TITLE 'CP/M VER 2.2 BIOS FOR SCSI HOST ADAPTOR' ; NAME ('BIOS22') ; DATE 20-JUN-83 ; BY DAVID WAGSTAFF ; COPYRIGHT 1983 BY GRIFFIN TECH. ALL RIGHTS RESERVED ; ; MACLIB Z80 ; Z-80 CODING IS USED ASEG ; ABSOLUTE ADDRESSING IS NEEDED ; ; ; ; THIS MODULE CONTAINS THE BASIC INPUT/OUTPUT SYSTEM FOR ; VERSION 2.2 OF THE CP/M OPERATING SYSTEM. ; PORTIONS OF THE SERIAL PORT I/O HAVE NOT BEENED CODED FOR OVIOUS REASONS ; THEREFORE, THIS TASK IS LEFT TO THE CUSTOMER OF THIS PRODUCT. ; THE EQUATE 'SCSI$BASE' HAS BE EQUATED TO THE BASE ADDRESS FOR THE SCSI ; INTERFACE BOARD, THE CURRENT VALUE IS 050H. ; THE EQUATE 'MSIZE' SHOULD BE SET TO THE SIZE OF THE OPERATING SYSTEM ; TO BE GEN'ED, TYPICALY THIS SHOULD BE ABOUT 60K. ; ; ; ; ** >> EDITING HISTORY << ** ; ; VER. DATE MODIFICATION ; ---- -------- ---------------------------------------- ; 00 06/20/83 1) CREATED. ; ; ; MDBE MACRO VALUE,SP ; MACRO TO PRINT VERSION OR DATE DB (VALUE SHR 12)+'0' DB ((VALUE SHR 8) AND 0FH)+'0' DB SP DB ((VALUE SHR 4) AND 0FH)+'0' DB (VALUE AND 0FH) +'0' ENDM ;*** DEBUG MACRO MESG,VALUES ; MACRO TO DEBUGGING BIOS LOCAL DM,DR,SPACE,SKIP ; 'MESG' IS A ASCII STRING LOCAL HLX,DEX,BCX,AFX,ARD ; TO BE PRINTD, 'VALUES' IS LOCAL CRLF ; A LIST OF MEMORY LOCATION JMP ARD ; TO DUMP TO THE TERMINAL. HLX: DW 00 ; A REGISTER DUMP WILL ALSO BCX: DW 00 ; BE PRINTED ON THE CONSOLE. DEX: DW 00 AFX: DW 00 ARD: STA AFX SHLD HLX SDED DEX SBCD BCX PUSH PSW PUSH H PUSH B PUSH D IFNB IRP VAL, LHLD VAL CALL ?PDEC LXI H,SPACE CALL ?PRTMSG ENDM ENDIF LXI H,DM CALL ?PRTMSG LXI H,SKIP CALL ?PRTMSG IRP VAL, LHLD VAL CALL ?PDEC LXI H,SPACE CALL ?PRTMSG ENDM LXI H,CRLF CALL ?PRTMSG POP D POP B POP H POP PSW JMP DR DM: DB MESG DB CR,LF,EOM SPACE: DB " ",EOM SKIP: DB "REGISTER DUMP AF, HL, DE, BC" CRLF: DB CR,LF,EOM DR: ENDM ; ; ; ; PAGE ; ; *** ASCII CONSTANTS AND USER OPTIONS *** ; ASEG BELL EQU 0007H ; SOUND CONSOLE BELL CR EQU 000DH ; CARIAGE RETURN LF EQU 000AH ; LINEFEED FFD EQU 000CH ; FORMFEED XON EQU 0011H ; ^Q XOFF EQU 0013H ; ^S EOM EQU 0000H ; END OF MESSAGE MARKER FALSE EQU 0000H ; TRUE EQU NOT FALSE ; RETRY EQU 0010 ; RETRYS BEFORE HARD-ERROR MSIZE EQU 0060 ; 60K SYSTEM. ; ; ; *** PORT ASSIGNMENTS *** ; SCSI$BASE EQU 0050H ; SCSI INTERFACE BOARD BASE QUAD$EIA EQU 0010H ; BASE PORT FOR QUAD. EIA BOARD CRTSTATUS EQU QUAD$EIA+4 ; STATUS PORT FOR CONSOLE CRTDATA EQU QUAD$EIA+5 ; DATA PORT FOR CONSOLE ; TXRDY EQU 0001H ; TX. READY BIT IN 8251 USART RXRDY EQU 0002H ; RX. READY BIT IN 8251 USART ; ; *** SCSI PORT ASSIGNMENTS *** ; ; * BIT,BYTE AND PORT ASSIGMENTS FOR * ; * SCSI HOST INTERFACE ADAPTOR * ; DATAI EQU SCSI$BASE ; DATA IN REGISTER DATAO EQU SCSI$BASE+2 ; DATA OUT REGISTER BSTAT EQU SCSI$BASE+1 ; BUS STATUS SELPORT EQU SCSI$BASE ; SELECT PORT ADR. CLRINT EQU SCSI$BASE+1 ; CLR. INTRRUPT PORT DMAPORT EQU SCSI$BASE+3 ; DMA ADDRESS PORT CPARITY EQU SCSI$BASE+4 ; CLEAR PARITY PORT BUSY EQU 80H ; CONTROLER BUSY BIT CD EQU 40H ; COMMAND/DATA BIT DIREC EQU 20H ; DIRECTON BIT REQ EQU 10H ; REQUEST BIT MSG EQU 08H ; END MESSAGE BIT PERR EQU 04H ; PERR ERROR BIT BDACK EQU 02H ; BOARD ACK. SIGNAL LINT EQU 01H ; INTERUPTE BIT ; ; *** CARTRIAGE STORAGE INFORMATION FOR IOMEGA SYSTEM *** ; OFFSET EQU 0001 ; TRACK OFFSET FOR SYSTEM TRACK NCYN EQU 306 ; # TRACK/DRIVE NSCYN EQU 64 ; # SECTORS/TRACK ?NBSCT EQU 2 ; # BLOCKS/SECTOR NBBLK EQU 256 ; # BYTES/BLOCK NBREC EQU 128 ; CP/M RECORD SIZE BLS EQU 2048 ; CP/M BLOCK SIZE DRM EQU 512-1 ; # DIR. ENTRYS -1 BYSCT EQU NBBLK*?NBSCT ; # BYTES/SECTOR NBCYN EQU NSCYN*BYSCT ; # BYTES/TRACK NRSCT EQU BYSCT/NBREC ; # RECS/SECTOR NRCYN EQU NSCYN*NRSCT ; # RECS/TRACK NRECBLS EQU BLS/NBREC ; # RECS/BLS NBLSCYN EQU NRCYN/NRECBLS ; # BLS/TRACK DSMA EQU NBLSCYN*(NCYN/2); SIZE OF AN LOGCAL DRIVE A: DSMB EQU NBLSCYN*((NCYN/2)-OFFSET) ; SIZE OF B: ; ; * IOMEGA COMMAND SET * ; FMTZTRK EQU 10000B ; FORMAT Z-TRACK FLGSCT EQU 10010B ; FLAG SECTOR FLGTRK EQU 10100B ; FLAG TRACK C?SEEK EQU 00110B ; SEEK TRACK C?HOME EQU 01000B ; ?HOME DRIVE REQST EQU 01010B ; REQEST STATUS REQES EQU 01100B ; REQEST EXTENDED STATUS CTEST EQU 01110B ; TEST CONTRL. STATUS RDDATA EQU 00001B ; READ DATA RDID EQU 10101B ; READ ID RDDTOF EQU 11001B ; READ DATA WITH OFFSET RDDIAG EQU 10001B ; READ DIAGNOSTIC WRTDATA EQU 00011B ; WRITE DATA WRTID EQU 00111B ; WRITE ID WRTDIAG EQU 10011B ; WRITE DIAGNOSITC ; ; ; ; *** CP/M ENVIROMENT CONSTANTS *** ; TPA EQU 0100H ; ADDRESS OF START OF TPA BIAS EQU (MSIZE-20)*1024 ; CCP EQU 3400H+BIAS ; BASE OF CCP BDOS EQU CCP+0806H ; BASE OF BDOS BIOS EQU CCP+1600H ; BASE OF THIS BIOS IOBYTE EQU 0003H ; ADDRESS OF IOBYTE CDRIVE EQU 0004H ; CURRENT DISK INDICATOR NSECTS EQU (BIOS-CCP)/128 ; # OF SECTORS/ CCP ; ; ; *** IOMEGA BLOCKING SIZE EQUATES *** ; BUFSZ EQU 2048 ; DATA BLOCKING SIZE MGABLKS EQU BUFSZ/256 ; # OF IOMEGA BLOCKS CPMBLKS EQU BUFSZ/NBREC ; # OF CP/M RECORDS MASK EQU 07H ; SEE FOLLOWING TABLE ; ; ******************************************** ; * THE VALUE OF "MASK" DETERMINES THE BLOCK * ; * BUFFER SIZE OF THE DEBLOCKING ROUTINES. * ; * THE VALUE OF "MASK" ARE: * ; * BUFSZ MASK * ; * ----- ---- * ; * 2048 07H * ; * 4096 0FH * ; * 8192 1FH * ; * 16384 3FH * ; ******************************************** ; ; ; ; ORG BIOS ; START AT BIOS CSEG ; ; PAGE ; JMP ?BOOT ; COLD START JMP ?WBOOT ; WARM BOOT JMP ?CONST ; CONSOLE STATUS JMP ?CONIN ; CONSOLE INPUT JMP ?CONOUT ; CONSOLE OUTPUT JMP ?LIST ; PRINTER OUTPUT JMP ?PUNCH ; AUX: OUTPUT ROUTINE JMP ?READER ; AUX: INPUT ROUTINE JMP ?HOME ; RECALIBRATE DRIVE JMP ?SELDSK ; SELECT DRIVE JMP ?SETTRK ; SET TRACK NUMBER JMP ?SETSEC ; SET SECTOR NUMBER JMP ?SETDMA ; SET DMA ADDRESS JMP ?READ ; READ A SECTOR JMP ?WRITE ; WRITE A SECTOR JMP ?LISTST ; RETURN PRINTER STATUS JMP ?SECTRAN ; SECTOR TRANSLATOR ROUTINE ; PAGE ; ; *** >>> COMMON DATA STORAGE DEFINITION AREA <<< *** ; ; *** DISK PARAMETER BLOCK DEFINITIONS *** ; DPABLK: DW NRCYN ; DRIVE A: TYPE DB 4,15 DB 0 DW DSMA DW DRM DW 0FF00H DW (DRM/4)+1 DW 1 ;**** DPBBLK: DW NRCYN ; DRIVE B: TYPE DB 4,15 DB 0 DW DSMB DW DRM DW 0FF00H ; DEBUG = 0FFFFH DW (DRM/4)+1 DW 9AH ;**** ; ; ; *** >>> DISK PARAMETER HEADER TABLES <<< *** ; DPBASE: ; DW 0000,0000 ; DRIVE A: DW 0000,0000 ; DW DIRBF,DPABLK ; DW CHKA,ALLA ; ; DW 0000,0000 ; DRIVE B: DW 0000,0000 ; DW DIRBF,DPBBLK ; DW CHKB,ALLB ; ; PAGE ; ; ; *** >>> START OF BOOT AND WARM BOOT ROUTINES <<< *** ; ?BOOT: ;-OP: HANDLE MISC. INITILIZATION AND SIGNON MESSAGE PRINTING ;-PP: NONE ;-RC: NONE ;- XRA A ; CLEAR IOBYTE STA IOBYTE ; STA CDRIVE ; AND CURRENT DISK LXI H,SIGNON ; GO PRINT SIGN-ON MESSAGE CALL ?PRTMSG ; ?GOCPM: MVI A,0C3H ; A = OP. CODE FOR 'JP' STA 0000H ; VECTOR @ 0000H STA 0005H ;& VECTOR @ 0005H LXI H,BIOS+3 ; LOCATION OF WBOOT ROUTINE SHLD 0001H ; SAVE IT LXI H,BDOS ; LOCATION OF BDOS SHLD 0006H ; SAVE TO SYSTEM VECTOR LDA CDRIVE ; GET THE CURRENT DISK MOV C,A ; TO REGISTER C JMP CCP ; AND PASS CONTROL TO THE CCP ;* ;** ;* SIGNON: DB CR,LF,LF,LF DB 'BIOS220 --- CP/M VER. 2.2 BIOS 20-JUN-83',CR,LF CRLF: DB CR,LF,EOM ;* ;** ;* PAGE ;+ ?WBOOT: ;-OP: WARM BOOT CP/M SYSTEM. ;-PP: SYSTEM TRACKS OF DRIVE A: HAS A VALID SYSTEM ON IT. ;-RC: CCP IS RELOADED INTO CORE FROM SYSTEM TRACKS ;- LXI SP,0080H ; SET-UP THE STACK TO FREE AREA CALL ?FLUSH ; FLUSH DISK CACHE LXI H,-1 ; FORCE NEW READS SHLD @RBLK ; MVI A,'W' ; MARK AS WARM BOOT STA @WRTACT ; MVI C,0 ; SELECT DRIVE A: CALL ?SELDSK ; CALL ?HOME ; RECALIBRATE DRIVE ; ;* AT THIS POINT WE MUST RELOAD IN EVERYTHING BUT THE BIOS * ; LDA CDRIVE ; A= CURRENT DISK NUMBER WBT1: PUSH PSW ; SAVE CURRENT DISK LXI H,0001 ; SET TO READY BLOCK 1 SHLD @ACTSCT ; LXI H,CCP ; HL @ BASE OF CCP WBT2: SHLD @RPNTR ; SAVE LOAD ADR. TO DMA POINTER MVI A,8 ; GO READ IN 8 BLOCKS (8*256) BYTES CALL ?RDBLK ; GO DO IT JRNZ WBTERR ; BRIF ERROR LHLD @RPNTR ; UP-DATE DMA POINTER LXI D,NBBLK*8 ; DE = TRANSFER SIZE DAD D ; LDA @ACTSCT ; POINT NEXT DATA BLOCK ADI 08 ; STA @ACTSCT ; CPI 11H ; SEE IF THE END HAS BEEN REACHED JRNZ WBT2 ; BRIF NOT DONE MVI A,FALSE ; MARK AS NOT WRITE ACTIVE STA @WRTACT ; POP PSW ; RECOVER CURRENT DISK NUMBER STA CDRIVE ; JMP ?GOCPM ; AN PASS CONTROL TO CCP ;* WBTERR: MVI A,'W' ; A = CODE FOR WARM BOOT ERROR CALL ?DSKERR ; GO PRINT THE MESSAGE POP PSW ; RECOVER ALL OLD NUMBER JMP WBT1 ; AND TRY AGAIN ;* ;** ;* PAGE ; ; *** >>> START OF CHARACTER I/O ROUTINES *** ; ?CONST: ;-OP: SEE IF CONSOLE HAS CHARACTER READY ;-PP: NONE ;-RC: A = 00 : NO CHARACTER READY ;- FF : CHARACTER READY ;- ; >>> SUPPLY CODE HERE FOR YOUR HARDWARE CONFIGURATION <<< ; SAMPLE CODE IS PROVIDED FOR A 8251 TYPE USART ; IN CRTSTATUS ; GET STATUS CMA ; OUR HARDWARE COMPLEMENTS STATUS REGISTER ANI RXRDY ; RZ ; EXIT IF NOT READY ORI 0FFH ; ELSE WITH WITH TRUE RET ;* ;** ;* ;+ ?CONIN: ;-OP: GET CHARACTER FROM THE CONSOLE ;-PP: NONE ;-RC: A = CHARACTER (PARITY BIT STRIPED, I.E. ONLY 7-BITS PRESENT) ;- CALL ?CONST ; WAIT FOR CHARACTER READY ORA A ; JRZ ?CONIN ; ; ; >>> SUPPLY CODE HERE FOR YOUR HARDWARE CONFIGURATION <<< ; >>> REGISTER A WILL RECEIVE CHARACTER, PORT HAS CHARACTER READY <<< ; SAMPLE CODE IS PROVIDED FOR A 8251 TYPE USART. ; IN CRTDATA ; GRAB THE DATA BYTE CMA ; OUR HARDWARE COMPLEMENTS THE DATA REGISTER RET ; AND THEN EXIT ;* ;** ;* ;+ ?CONOUT: ;-OP: SEND CHARACTER TO CONSOLE ;-PP: C = CHARACTER ;-RC: NONE ;- ; >>> SUPPLY CODE HERE FOR YOUR HARDWARE CONFIGURATION <<< ; SAMPLE CODE IS PROVIDED FOR A 8251 TYPE USART IN CRTSTATUS ; WAIT FOR TX. READY ANI TXRDY ; JRNZ ?CONOUT ; REMEMBER OUR HARDWARE MOV A,C ; A = CHARACTER TO SEND OUT CRTDATA ; EJECT THE CHARACTER RET ; AND THEN EXIT ;* ;** ;* ;+ ?LIST: ?PUNCH: ;-OP: HANDLE OUTPUT TO LIST AND PUNCH DEVICES ;-PP: C = CHARACTER TO SEND ;-RC: NONE ;- ; >>> SUPPLY CODE HERE FOR YOUR HARDWARE CONFIGURATION <<< RET ; THIS JUST ACTS AS A BIT-BUCKET ;* ;** ;* ;+ ?LISTST: ;-OP: RETURN STATUS OF PRINTER READY ;-PP: NONE ;-RC: A = 00 : PRINTER NOT READY ;- FF : PRINTER IS READY ;- ; >>> SUPPLY CODE HERE FOR YOUR HARDWARE CONFIGURATION <<< ; MVI A,TRUE ; THIS IS JUST A DEFAULT RET ; AND THEN EXIT ;* ;** ;* ;+ ?READER: ;-OP: HANDLE INPUT FROM A SECONDARY INPUT DEVICE ;-PP: NONE ;-RC: A = INPUTED CHARACTER. ;- ; >>> SUPPLY CODE HERE FOR YOUR HARDWARE CONFIGURATION <<< MVI A,'Z' AND 3FH ; THIS JUST RETURNS EOF RET ; ;* ;** ;* ; ; PAGE ; *** >>> DISK SUPPORT ROUTINES <<< *** ; ;+ ?HOME: ;-OP: THIS FUNCTION PERFORMS NO-OPERATION IN ;- THIS SYSTEM. ;- RET ; JUST EXIT ;* ;** ;* ;+ ?SELDSK: ;-OP: SELECT A DRIVE FOR FURTHER OPERATIONS ;-PP: C = DRIVE TO SELECT ;-RC: HL @ DPH FOR DRIVE ELSE 0000 IF BAD DRIVE ;- LXI H,0000 ; READY FOR ERROR EXIT MOV A,C ; A = DRIVE CODE CPI 2 ; RNC ; EXIT IF BAD SELECT CODE STA CDRIVE ; SAVE NEW CURRENT DISK MOV L,A ; HL = DRIVE CODE REPT 4 DAD H ; HL = HL * 16 ENDM LXI D,DPBASE ; DE = BASE OF TABLE DAD D ; PERFORM THE INDEX OPERATION RET ; AND THEN EXIT ;* ;** ;* ;+ ?SETTRK: ;-OP: SET-UP TRACK POINTER ;-PP: BC = TRACK FOR NEXT OPERATION ;-RC: NONE ;- SBCD @TRK ; SAVE CURRENT TRACK RET ; AND EXIT ;* ;** ;* ;+ ?SETSEC: ;-OP: SET-UP SECTOR POINTER ;-PP: BC = SECTOR FOR NEXT OPERATION ;-RC: NONE ;- SBCD @SECT ; SAVE CURRENT SECTOR RET ; AND THEN EXIT ;* ;** ;* ;+ ?SETDMA: ;-OP: SET-UP DMA ADDRESS POINTER ;-PP: BC = ADDRESS OF DMA AREA ;-RC: NONE ;- SBCD @DMA ; SAVE CURRENT DMA ADDRESS RET ; AND THEN EXIT ;* ;** ;* ;+ ?READ: ;-OP: READ A SECTOR ;-PP: DISK READ PARMATERS SET (I.E. TRACK, SECTOR AND DRIVE) ;-RC: A = 0 : NO ERRORS OCCURED ;- = 0FFH : ERRORS DETECTED ;- LXI H,RDBUF ; POINT TO READ BUFFER SHLD @RPNTR CALL COMPUTE ; GET LOG. BLOCK # (HL =) XCHG ; IS BLOCK LOADED?? LHLD @WBLK ; IS SECTOR WRT. ACTIVE?? ORA A ; DSBC DE ; JRZ RD4 ; BRIF SO LHLD @RBLK ; IS BLOCK ALREADY LOADED?? ORA A ; (IN READ BUFFER THAT IS) DSBC DE ; JRZ RD1 ; BRIF IF LOADED JR RD2 ; BRIF NOT ;* RD4: LXI H,WRTBUF ; INDEX INTO WRT. BUFF. JMP RD3 ; GO DO IT RD1: LXI H,RDBUF ; INDEX INTO RD. BUFF. RD3: DAD B ; BC = INDEX, HL @ SECTOR DAT LDED @DMA ; DE = ADDRESS DMA LXI B,NBREC ; BC = SIZE OF CP/M RECORD LDIR ; PERFORM THE TRANSFER XRA A ; EXIT WITH NO ERRORS RET ; AND EXIT ;* RD2: SDED @ACTSCT ; SET-UP FOR READ SDED @RBLK ; SET POINTER LDA @WRTACT ; SEE IF WARM BOOT ACTIVE CPI 'W' ; JRZ RD20 ; BRIF SO RES 0,L ; CLEAR UNIT FLAG RD20: MVI A,MGABLKS ; XXX BLOCKS ONLY CALL ?RDBLK ; GO DO IT RNZ ; RETURN ON ERROR JMP RD1 ; GO INDEX INTO TABLE ;* ;** ;* PAGE ;+ ?WRITE: ;-OP: WRITE A SECTOR ;-PP: DISK PERAMETERS ARE SET (I.E. TRACK, SECTOR AND DRIVE) ;- REG C HAS WRITE TYPE 0,1,2 ;-RC: A = 0 : NO ERRORS DETECTED ;- = 0FFH : ERRORS DETECTED ;- MOV A,C ; A= WRITE TYPE STA @WRTYPE ; SAVE FOR LATER CALL COMPUTE ; GO COMPUTE MGA BLOCK WT03: XCHG ; DE = BLOCK LHLD @WBLK ; SEE IF THE SAME AS LOADED ORI A ; CLEAR CARRY DSBC DE ; TEST JRZ WT02 ; BRIF SO PUSH D ; SAVE GOAL BLK# CALL ?FLUSH ; FLUSH OUT OLD BLOCK NUMBER POP H ; HL= NEW BLOCK # SHLD @ACTSCT ; UP-DATE POINTERS SHLD @WBLK ; LXI H,WRTBUF ; DMA TO WRITE BUFFER SHLD @RPNTR ; ; IF BUFSZ-2048 MVI A,MGABLKS ; READ IN A BLOCK CALL ?RDBLK ; GO READ IT IN ELSE ; BLOCK SIZE = 2048 LDA @WRTYPE ; SEE IF WRITE TYPE IS TYPE 2 CPI 2 ; MVI A,MGABLKS ; READY FOR PRE-READ IF NECESSARY CNZ ?RDBLK ; BRIF SO ENDIF ; RNZ ; RETURN ON ERROR WT02: LXI H,WRTBUF ; HL @ SECTOR BUFFER DAD B ; ADD IN THE OFFSET XCHG ; DE @ SECTOR LHLD @DMA ; HL @ DATA LXI B,NBREC ; BC = # BYTES/CP/M RECORD LDIR ; DO THE TRNSFR ; MVI A,TRUE ; SET WRITE ACTIVE TO TRUE STA @WRTACT ; LDA @WRTYPE ; GET BACK WRITE TYPE DCR A ; CHECK FOR DIRECTORY MVI A,0 ; FOR SAFTY CZ ?FLUSH ; GO FLUSH DATA IF SO ORA A ; SET FLAGS RET ; AND EXIT ;* ;** ;* PAGE ;+ COMPUTE: ;-OP: COMPUTE PHYS. BLOCK NUMBER ;-PP: TRACK AND SECTOR ARE SET ;-RC: HL = PHYS. BLOCK NUMBER ;- BC = INDEX INTO BLOCK (0..BUFSZ) ;- ; LXI H,@TRK ; HL @ TRACK # MVI E,0 ; CLEAR LOW DE MOV D,M ; LOAD LOW TRACK INX H ; POINT HI TRACK MOV A,M ; A= HI TRACK RRA ; DIVIDE BY TWO RARR D ; RARR E ; XCHG ; HL= TRACK*128 LDA @SECT ; A = SECTOR NUMBER SRLR A ; DIVIDE BY 2 MVI C,0 ; C= 0 OR 80H RARR C ; ADD L ; MOV B,A ; ANI NOT MASK ; MOV L,A ; MOV A,B ; ANI MASK ; MOV B,A ; SBCD @OFS ; SAVE OFFSET LDA CDRIVE ; FOR SELECTION ORA A ; CHECK FOR UNIT 0 RZ ; RETURN IF SO SETB 0,L ; ELSE SET UNIT 1 FLAG RET ; AND EXIT ;* ;** ;* ;+ ?FLUSH: ;-OP: FLUSH WRITE BUFFER IF NEEDED ;-PP: @WBLK IS SET AND VALID ;- IF @WRTACT FLAG IS SET TO TRUE ;- ; LXI H,WRTBUF ; SET DMA TO WRITE BUFFER SHLD @RPNTR ; LDA @WRTACT ; CPI FALSE ; BUFFER WRITE ACTIVE?? RZ ; RETURN IF NOT LHLD @WBLK ; SHLD @ACTSCT ; ACTSEC = WBLKN MVI A,MGABLKS ; WRITE ONLY XX BLOCK CALL WRTBLK ; GO WRITE IT MVI A,FALSE ; BUFFER NOT WRITE ACTIVE STA @WRTACT ; LHLD @RBLK ; IS READ/WRITE TO SAME LDED @WBLK » ORA A ; DSBC DE ; JRNZ FLSH1 ; BRIF NOT LXI H,-1 ; FORCE READ SHLD @RBLK ; FLSH1: XRA A ; RECORD NO ERROR RET ; AND EXIT ;* ;** ;* ; ; PAGE ; ; *** >>> SACI HOST INTERFACE ADAPTOR SUPPORT ROUTINES <<< *** ; ;+ ?RDBLK: ;-OP: READ IN X SECTORS ;-PP: A = NUMBER OF BLOCKS TO READ ;- @ACTSCT IS VALID ;- MVI E,RDDATA ; E = READ DATA COMMAND JR PRECMD ; GO PREPARE FOR IT ;* ;** ;* ;+ WRTBLK: ;-OP: WRITE OUT X BLOCKS ;-PP: A = NUMBER OF BLOCKS TO WRITE ;- @ACTSCT IS VALID ;- MVI E,WRTDATA ; E = WRITE DATA CMD. ;+ PRECMD: ;-OP: CREATE COMMAND BLOCK ;-PP: A = NUMBER OF BLOCK INVOLVED ;- E = FIRST COMMAND BYTE ;- PUSH D ; SAVE COMMAND LXI H,CMDTBL ; HL @ COMMAND BLOCK MOV M,E ; STORE COMMAND BYTE INX H ; POINT NEXT LDED @ACTSCT ; DE = LOG. BLOCK NUMBER PUSH PSW ; SAVE BLOCK COUNT LDA @WRTACT ; SEE IF IN WARM BOOT CPI 'W' ; JRZ PC10 ; BRIF SO MOV A,E ; MASK OUT GARBAGE ANI NOT MASK ; MOV E,A ; PC10: POP PSW ; RECOVER BLOCK COUNT MOV M,D ; SAVE IT INX H ; MOV M,E ; INX H ; MVI M,0 ; ALWAYS < 256 LOG. BLOCKS INX H MOV M,A ; SAVE # BLOCKS TO TRNSFR INX H MVI M,0 ; CLEAR EXTRA BYTE LXI H,CMDTBL ; HL @ CMD. BLOCK CALL ?DOCMD ; GO DO IT POP D ; RECOVER COMMAND RZ ; RETURN IF OK CALL SCSI$ERROR ;GO PRINT DISK ERROR MVI A,0FFH ;MARK THE ERROR ORA A ; RET ;AND EXIT ;* ;** ;* ;+ SCSI$ERROR: ;-OP: HANDLE SCSI DISK ERRORS ;- MVI A,'D' ; CODE FOR DATA ERROR CALL ?DSKERR ; DO THE DISK ERROR RET ; AND THEN EXIT ;* ;** ;* ; PAGE ; ;* START OF PROTOCAL HANDLING ROUTNES * ; ;+ ?DOCMD: ;-OP: ISSUE COMMAND TO SCSI HOST ADAPTOR ;-PP: HL @ COMMAND BYTES TO SEND ;- @ACTSEC & @RPNTR ARE VALID ;-RC: NO - ZERO : ERROR IN COMMAND (A = ERROR BITS) ;- ZERO : COMMAND WAS EXECUTED SUCCESSFULLY ;- SHLD LCMD@ ; SAVE COMMAND @ MVI A,RETRY ; GET RETRY COUNT STA TRYCNTR ; RESET COUNTER OUT CPARITY ; RESET PARITY ERROR DCMD1: PUSH B ; SAVE COUNTER CALL ?PUTDMA ; SET DMA ADDRESS CALL ?SELECT ; GO SELECT CONTROLER POP B ; RECOVER BC ; WAIT: ; ;* HERE WE MUST WAIT FOR EXECUTION * ; IN BSTAT ; A <--- BUSS STATUS ANI CD+REQ ; CHECK FOR DATA JRNZ WAIT ; BRIF STILL DATA IN DATAI ; A <-- COMPLETION STATUS PUSH PSW ; SAVE ENDING STATUS WAIT1: IN BSTAT ; WAIT FOR REQ. AND MSG. ANI REQ+MSG ; JRNZ WAIT1 ; IN DATAI ; GET BYTE OF ZERO POP PSW ; RECOVER STATUS ANI 00011111B ; MASK OUT ERRORS JRNZ WAIT4 ; BRIF NOT OK IN BSTAT ; CHECK FOR PARITY ANI PERR ; OUT CLRINT ; CLEAR INTERRUPT MVI A,0FFH ; JRNZ WAIT4 ; BRIF ERROR XRA A ; EXIT WITH ZERO RET ; AND EXIT ;* ;* WAIT7: POP PSW ; CLEAR OUT STACK WAIT4: BIT 2,A ; HARDWARE BUSY?? JRZ WAIT6 ; BRIF NOT MVI A,'R' ; CODE FOR READY ERROR CALL ?DSKERR ; JR WAIT5 ; AND CONTINUE ;* WAIT6: LXI H,TRYCNTR ; SEE IF RETRY UP DCR M ; JRZ WAIT2 ; BRIF RETRY IS UP WAIT5: LHLD LCMD@ ; RECOVER LAST COMMAND JMP DCMD1 ; AND TRY AGAIN ;* WAIT2: OUT CLRINT ; CLEAR INTERRUPT ORA A ; EXIT WITH NON-ZERO RET ; AND EXIT ;* ;** ;* ;+ ?PUTDMA: ;-OP: SEND DMA ADDRESS TO HOST ADAPTER ;-PP: RPNTR HAS DMA ADDRESS ;- LDA HIDMA ; SET HI-BYTE OUT DMAPORT ; HIGH BYTE ALWAYS ZERO LDED @RPNTR ; DE @ DMA ADDRESS MOV A,D OUT DMAPORT ; SEND BYTE 1 MOV A,E OUT DMAPORT ; SEND BYTE 2 RET ; AND EXIT ;* ;** ;* ;+ ?SELECT: ;-OP: SELECT CONTROLER ;- IN BSTAT ; IS CONTROLER BUSY?? ANI BUSY ; WAIT FOR NOT BUSY JRZ ?SELECT ; WAIT IF SO SEL2: MVI A,01H ; SELECT CONTROLER #1 OUT DATAO ; OUT SELPORT ; AND SELECT CONTROLER SEL1: IN BSTAT ; WAIT FOR REQ ANI REQ ; JRNZ SEL1 ; MOV D,A ; D=0, MARK FIRST COMMAND ; ;* NOW FALL ON THRU TO OUTPUT COMMAND BYTES * ; ;+ ?OUTCMD: ;-OP: ISSUE COMMAND BYTES TO HOST ADAPTOR ;-PP: HL @ COMMAND BYTES ;- IN BSTAT ; GRAB BUSS STATUS MOV C,A ; SAVE STATUS ANI CD ; SEE IF DATA RNZ ; EXIT IF DATA MOV A,C ; CHECK FOR DIREC ANI DIREC ; RZ ; EXIT IF INPUT MVI A,REQ+BDACK ; BIT 0,D ; SEE IF FIRST CMD. JRNZ ?OC5 ; BRIF NOT MVI A,REQ ; ELSE JUST CHECK FOR REQ. ?OC5: ANA C ; CHECK FOR READY JRNZ ?OUTCMD ; BRIF NOT (1.75/1.17) ?OC1: MOV A,M ; GET COMMAND BYTE (1.75/1.17) OUT DATAO ; SEND TO CONTROLER (2.75/1.83) INX H ; POINT NEXT (1.5/1.0) MVI D,1 ; MARK NOT FIRST COMMAND JR ?OUTCMD ; AND DO IT AGAIN! ;* ;** ;* ; PAGE ; ; *** MISC. ROUTINES AND FUNCTIONS *** ; ; ;+ ?SECTRAN: ;-OP: PERFORM SECTOR TRANSLATION ;-PP: DE @ TRAN. TABLE ;- BC = SECTOR NUMBER ;- HL = TRAN. SECTOR NUMBER ;- MOV H,B ; SIMPLE 1 TO 1 TRANSLATION MOV L,C ; RET ; ADD EXIT ;* ;** ;* ; ;+ ?PRTMSG: ;-OP: PRINT MESSAGE STRING AT HL ;-PP: HL @ MESSAGE STRING TERMINATED WITH A ZERO BYTE. ;-RC: NONE ;- MOV A,M ; CHECK FOR EOS ORA A ; RZ ; EXIT IF SO MOV C,A ; C = CHARACTER INX H ; POINT NEXT CHARACTER PUSH H ; AND SAVE CALL ?CONOUT ; AND ISSUE TO TERMINAL HANDLER POP H ; RECOVER POINTER JR ?PRTMSG ; AND CONTINUE ;* ;** ;* ;+ ?DSKERR: ;-OP: DISK ERROR HANDLER ;-PP: A = ERROR CODE LETTER ;-RC: NONE ;- PUSH PSW ; SAVE ERROR LETTER ON STACK LXI H,DEM ; HL @ DISK ERROR MESSAGE CALL ?PRTMSG ; GO PRINT MESSAGE HEADER POP PSW ; C = ERROR CODE LETTRE MOV C,A ; CALL ?CONOUT ; AND PRINT IT RET ; AND EXIT ;* DEM: DB CR,LF,LF DB 'DISK I/O ERROR :',0 ;* ;** ;* ; PAGE ; ; *** >>> BIOS DATA STORAGE AREA <<< *** ; ; @RPNTR: DW 00 ; ADDRESS OF INTERNAL DEBLOCKING BUFFER @WBLK: DW 00 ; CURRENT WRITE BLOCK NUMBER @RBLK: DW 00 ; CURRENT READ BLOCK NUMBER @ACTSCT: DW 00 ; BLOCK NUMBER TO READ/WRITE @WRTACT: DB FALSE ; TRUE IF BLOCK IS WRITE ACTIVE LCMD@: DW 00 ; ADDRESS OF LAST IOMEGA COMMAND TRYCNTR: DB 00 ; RETRY COUNTER FOR IOMEGA I/O OP.S HIDMA: DB 00H ; PAGE ADDRESS OF IOMEGA BUFFER AREA @DMA: DW 00 ; CURRENT DMA ADDESS @TRK: DW 00 ; CURRENT TRACK NUMBER @SECT: DW 00 ; CURRENT SECTOR NUMBER CMDTBL: DS 11 ; IOMEGA COMMAND TABLE STORAGE @WRTYPE: DB 00H ; CURRENT WRITE TYPE @OFS: DW 00 ; CURRENT DISK CACHE INDEX DIRBF: DS 128 ; DIRECTORY BUFFER CHKA: DS (DRM/4)+1 ; DIRECTORY CHECKSUM FOR DRIVE A: CHKB: DS (DRM/4)+1 ; DIRECTORY CHECKSUM FOR DRIVE B: ALLA: DW (DSMA/8)+1 ; ALLOCATION MAP FOR DRIVE A: ALLB: DW (DSMB/8)+1 ; ALLOCATION MAP FOR DRIVE B: RDBUF: DW BUFSZ ; ADDRESS OF READ DATA BUFFER WRTBUF: DS BUFSZ ; ADDRESS OF WRITE DATA BUFFER @EXTRA: DB 00 ; EXTRA BYTE ; END END