;*** Z207 DEVICE DRIVER ; NOLIST ; ; RESTRICTED RIGHTS LEGEND ; ------------------------ ; ; "Use, duplication, or disclosure by the ; government is subject to restrictions as set forth ; in paragraph (b) (3) (B) of the Rights in Technical ; Data and Computer Software clause in DAR ; 7-104.9(a). Contractor/manufacturer is Zenith ; Data Systems Corporation of Hilltop Road, St. ; Joseph, Michigan 49085. ; LIST WAIT EQU TRUE ;USE WAIT STATE I/O Z207MRC EQU 12 ;MAX # RETRIES Z207HUDV EQU 35/TINTRVL+1 ;HEAD UNLOAD DELAY (~35mS) Z207DSELV EQU 2000/TINTRVL ;DESELECT VALUE (~2000mS) ;** DRIVER ENTRY JUMP VECTORS ; DRVR207: JMP SEL207 ;SELECT JMP RDT207 ;READ TRACK JMP WRT207 ;WRITE TRACK JMP MNT207 ;MOUNT JMP FMT207 ;FORMAT JMP WPC207 ;WRITE PROTECT CHECK ;** INITIALIZE DRIVE TABLES ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL ; IN207: ;* RESTORE THE HEAD ON EACH DRIVE TO DETERMINE IF IT EXISTS MOV CX,4 ;# OF Z207 DRIVES LEA BP,DPEBASE ;START ADDRESS OF Z207 DPE'S OR DSKOP,DSKOPI ;INDICATE INIT IN PROGRESS IN2071: PUSH CX CALL DS207 ;SELECT DRIVE CALL RST207 ;RESTORE HEAD TEST AL,FDSTK0 ;Q. TRACK 0 INDICATION JNZ IN2073 ; BR IF YES OR DPEFLG2[BP],DPEIMG ;FLAG DRIVE AS IMAGINARY IN2073: TEST DPEUNIT[BP],CONDS8 ;Q. 8" DRIVE JNZ IN2074 ; BR IF YES IN AL,FDAS ;DETERMINE IF 5 1/4" DRIVE IS TEST AL,AS96T ; 48 OR 96 TPI AND INDICATE THIS JZ IN2074 ; IN TABLE OR DPEFLAG[BP],DPE96T IN2074: ADD BP,DPEL ;BUMP TO NEXT DRIVE TABLE POP CX LOOP IN2071 ;LOOP AND CHECK ALL DRIVES AND DSKOP,NOT DSKOPI ;INDICATE INIT DONE CALL DONE207 ;TURN OFF DRIVES ;* DO DRIVE MAPPING & REAL/IMAGINARY TABLE INITIALIZATION XOR AX,AX MOV ES,AX MOV ES,ES: .MTRDSEG ;GET ADDRESS OF MONITOR DATA AREA MOV CL,ES: MTRBU ;GET BOOT DEVICE UNIT # MOV AL,ES: MTRBI ;GET BOOT DEVICE INDEX # CMP AL,1 ;Q. BOOT DEVICE WAS 8" DRIVE JE IN2076 ; BR IF YES ; BOOT DEVICE WAS 5 1/4" DRIVE; BUILD 5 1/4" TABLES THEN 8" TABLES MOV CH,2 ;# DRIVE TABLES MOV DH,0 ;START OF 5 1/4" TABLES CALL CBTFIL ;FILL IN TABLES MOV CL,0 ;UNIT # MOV CH,2 ;# DRIVE TABLES MOV DH,2 ;START OF 8" TABLES CALL CBTFIL ;FILL IN TABLES RET ; BOOT DEVICE WAS 8" DRIVE; BUILD 8" TABLES THEN 5 1/4" TABLES IN2076: MOV CH,2 ;# DRIVE TABLES MOV DH,2 ;START OF 8" TABLES CALL CBTFIL ;FILL IN TABLES MOV CL,0 ;UNIT # MOV CH,2 ;# DRIVE TABLES MOV DH,0 ;START OF 5 1/4" TABLES CALL CBTFIL ;FILL IN TABLES RET ;** SELECT DRIVE FOR 1ST LOGIN ; ; ENTRY: 'PHYDPE'=ADDRESS OF DPE FOR DRIVE ; (BX)=POINTER TO BUFFER HEADER INFO ; 'XLATES'=ADDRESS OF XLATE TABLE ADDRESSES ; EXIT: 'PHYDPE'=STATUS ; 0=ERROR , OTHERWISE SAME AS ON ENTRY ; USES: AX,CX,BP,SI,DI ; SEL207: OR DSKOP,DSKOPS ;INDICATE SELECT OPERATION IN PROGRESS MOV BP,BUFDPE[BX] MOV DPETRK[BP],DPEUNK ;INDICATE DRIVE HEAD POSITION UNKNOWN TEST DPEUNIT[BP],CONDS8 ;Q. 8" DRIVE JZ $+5 JMP SEL2075 ; BR IF 8" DRIVE ;* SELECT ROUTINE FOR 5 1/4" DRIVES ; READ LABEL MOV PHYTRK,0 ;LABEL IS ON TRACK 0 MOV PHYSID,0 ; SIDE 0 MOV PHYSEC,0 ; 1ST SECTOR CALL RDY2070 ;READY CHECK CMP BUFERR[BX],0 ;Q. DRIVE NOT READY ; JE SEL2079 ; BR IF NOT READY JNE $+5 JMP SEL2079 MOV BUFERR[BX],0 ;CLEAR ERROR FLAG CALL DS207 ;SELECT DRIVE CALL RST207 ;RESTORE HEAD MOV COUNT,1024 ;MAXIMUM SECTOR LENGTH LES DI,DWORD PTR BUFBUF[BX] ;USE HOST BUFFER CALL RDS207 ;TRY READING LABEL AT DENSITY TEST AL,AL ; CURRENTLY INDICATED IN TABLES JZ SEL2072 ; BR IF ABLE TO READ LABEL SECTOR XOR DEVCTL,CONSD ;UNABLE TO READ LABEL SECTOR MOV AL,DEVCTL ; CHANGE TO OTHER DENSITY OUT FDCON,AL LES DI,DWORD PTR BUFBUF[BX] ;TRY TO READ LABEL SECTOR AGAIN CALL RDS207 TEST AL,AL ; JNZ SEL2079 ; BR IF ERROR JZ $+5 JMP SEL2079 SEL2072: LES SI,DWORD PTR BUFBUF[BX] ;CHECK CHECKSUM OF LABEL ADD SI,LABEL CALL CHKLAB JZ SEL2072A ; BR IF NO ERROR TEST DPEFLAG[BP],DPEDD ;Q. DOUBLE DENSITY DISK ; JZ SEL2079 ; BR IF NOT JNZ $+5 JMP SEL2079 MOV CX,LABCS-LABEL ;ASSUME NOT ZDS CP/M DISK BUT SET UP LEA SI,DL207 ; DEFAULT LABEL AS IF IBM PC CP/M DISK LES DI,DWORD PTR BUFBUF[BX] ; DOUBLE DENSITY/SINGLE SIDED/48 TPI LEA DI,LABEL[DI] CLD REP MOVSB ; MOVE LABEL INFO TO DPE'S HEATH EXTENSIONS SEL2072A: LES SI,DWORD PTR BUFBUF[BX] AND DPEFLAG[BP],DPETYPE+DPE96T MOV AL,ES: LABHTH+(OFFSET DPEFLAG)-(OFFSET DPEHTH) [SI] AND AL,DPEDD+DPE2S OR DPEFLAG[BP],AL ;FLAG BYTE #1 MOV AL,ES: LABHTH+(OFFSET DPERPS)-(OFFSET DPEHTH) [SI] MOV DPERPS[BP],AL ;CP/M RECORDS PER PHYSICAL SECTOR MOV AL,ES: LABHTH+(OFFSET DPERPAB)-(OFFSET DPEHTH) [SI] MOV DPERPAB[BP],AL ;CP/M RECORDS PER ALLOCATION BLOCK AND DPEFLG2[BP],NOT DPE96TM MOV AL,ES: LABHTH+(OFFSET DPEFLG2)-(OFFSET DPEHTH) [SI] AND AL,DPE96TM OR DPEFLG2[BP],AL ;FLAG BYTE #2 ; IF LABEL INDICATES THAT THE MEDIA IS DOUBLE SIDED, THEN ; CHECK OUT THE DRIVE FOR DOUBLE SIDED CAPABILITY TEST DPEFLAG[BP],DPE2S ;Q. DOUBLE SIDED MEDIA JZ SEL2073 ; BR IF NOT MOV PHYSID,FDFSS1 ;TRY TO READ A SECTOR HEADER LEA DI,RDABUF ; ON 2ND SIDE CALL RDA207 TEST AL,AL ; JNZ SEL2079 ; BR IF ERROR JZ $+5 JMP SEL2079 CMP RDABUF+FDRASID,1 ;CHECK SIDE INFO ; JNE SEL2079 ; BR IF NOT 2ND SIDE JE $+5 JMP SEL2079 ; STEP IN 2 TRACKS, READ ADDRESS, AND STEP BACK OUT 2 TRACKS. ; IF READ ADDRESS FINDS TRACK 1 INSTEAD OF TRACK 2, ; THEN ASSUME 48 TPI MEDIA GENERATED ; ON A 48 TPI DRIVE WAS INSERTED INTO THE 96 TPI DRIVE; THEREFOR, ; USE AS A R/O DISK WITH DOUBLE STEPPING. ; ; THERE ARE TWO 48 TPI MEDIA FORMATS THAT ARE SUPPORTED ON ; A 96 TPI DRIVE. ; 1) MEDIA WAS FORMATTED ON A 96 TPI DRIVE AND ONLY USES ; THE FIRST HALF OF THE DISK SURFACE. (E.G. A 48 TPI MEDIA ; IS DUPLICATED ONTO MEDIA IN A 96 TPI DRIVE) ; 2) MEDIA WAS FORMATTED ON A 48 TPI DRIVE. THE HARDWARE ; GROUP HAS INFORMED ME THAT THE 96 TPI DRIVE CAN RELIABLY ; READ SUCH MEDIA BUT CANNOT WRITE ON IT. TO GO BETWEEN ; TRACKS IT IS NECESSARY TO DOUBLE THE NUMBER OF STEPS. ; ; THE FOLLOWING ARE THE POSSIBLE OUTCOMES OF THE READ ADDRESS ; MEDIA DRIVE DRIVE OUTCOME ; FORMAT GENERATED ON INSERTED IN TRACK ; ------ ------------ ----------- ------- ; 48 TPI 48 TPI 48 TPI 2 ; 48 TPI 48 TPI 96 TPI 1 ; 48 TPI 96 TPI 48 TPI ERROR ; 48 TPI 96 TPI 96 TPI 2 ; 96 TPI 96 TPI 48 TPI ERROR ; 96 TPI 96 TPI 96 TPI 2 ; SEL2073: MOV PHYTRK,2 ;STEP IN TWO TRACKS CALL SDT207 MOV PHYSID,0 ;DO READ ADDRESS LEA DI,RDABUF CALL RDA207 TEST AL,AL ; JNZ SEL2079 ; BR IF ERROR JZ $+5 JMP SEL2079 CMP RDABUF+FDRATRK,2 ;CHECK IF TRACK 2 JE SEL2073A ; BR IF YES ; 1) 48 TPI MEDIA GENERATED ON 48 TPI ; DRIVE INSERTED INTO 48 TPI DRIVE ; 2) 48 TPI MEDIA GENERATED ON 96 TPI ; DRIVE INSERTED INTO 96 TPI DRIVE ; 3) 96 TPI MEDIA INSERTED IN 96 TPI CMP RDABUF+FDRATRK,1 ;CHECK IF TRACK 1 ; JNE SEL2079 ; BR IF NOT (ERROR) JE $+5 JMP SEL2079 OR DPEFLAG[BP],DPE48RO ;SET FLAG TO INDICATE 48 TPI MEDIA ; GENERATED ON 48 TPI DRIVE INSERTED ; INTO 96 TPI DRIVE. THE MEDIA ; IS TREATED AS R/O SEL2073A: CALL RST207 ;STEP OUT TWO TRACKS BY DOING RESTORE ; MOVE LABEL INFO TO DISK PARAMETER BLOCK LES SI,DWORD PTR BUFBUF[BX] ADD SI,LABDPB MOV DI,DPEDPB[BP] MOV CX,DPBL CLD CALL EXDSES REP MOVSB CALL EXDSES JMP SEL2078 ;* SELECT FOR 8" DRIVE SEL2075: MOV PHYTRK,2 ;ATTEMPT TO READ ADDRESS HEADER MOV PHYSID,0 ; ON PHYSICAL TRACK #2 SIDE 0 CALL DS207 ; AT THE CURRENT DENSITY IN CALL RST207 ; THE DRIVE'S DPE CALL SDT207 LEA DI,RDABUF CALL RDA207 TEST AL,AL JZ SEL2075A ;BR IF ABLE TO READ XOR DPEFLAG[BP],DPEDD ;CHANGE TO OTHER DENSITY XOR DEVCTL,CONSD MOV AL,DEVCTL OUT FDCON,AL LEA DI,RDABUF ;ATTEMPT TO READ ADDRESS HEADER CALL RDA207 ; AT OTHER DENSITY TEST AL,AL JNZ SEL2079 ;BR IF ERROR SEL2075A: AND DPEFLAG[BP],NOT DPET0SD ;ASSUME TRACK 0 IS SAME DENSITY TEST DPEFLAG[BP],DPEDD ;Q. DISK IS DOUBLE DENSITY JZ SEL2076 ; BR IF NOT MOV PHYTRK,0 ;CHECK IF TRACK 0 IS SINGLE DENSITY CALL SDT207 ; BY TRYING TO READ ADDRESS HEADER LEA DI,RDABUF2 ; AT DOUBLE DENSITY CALL RDA207 TEST AL,AL ;Q. ERROR JZ SEL2076 ; BR IF NOT -- TRACK 0 IS ALSO DOUBLE OR DPEFLAG[BP],DPET0SD ; OTHERWISE ASSUME TRACK 0 IS SINGLE ; UPDATE REST OF DPE SEL2076: AND DPEFLAG[BP],NOT DPE2S ;# OF SIDES IN AL,FDAS ;ASK DRIVE HOW MANY SIDES TEST AL,AS2S JZ SEL2076A OR DPEFLAG[BP],DPE2S SEL2076A: MOV SI,DPEDD+DPE2S ;COMPUTE ADDRESS OF TABLE CONTAINING AND SI,WORD PTR DPEFLAG[BP] ; INFO FOR UPDATE IF (DPEDD NE 2) OR (DPE2S NE 1) %: DPEDD MUST BE 2 AND DPE2S MUST BE 1 ENDIF SHL SI,1 SHL SI,1 XOR AH,AH MOV AL,RDABUF+FDRASL ADD SI,AX SHL SI,1 MOV SI,TBL207[SI] ;GET ADDRESS OF UPDATE INFO TEST SI,SI ;CHECK FOR NOT SUPPORTED FORMAT JZ SEL2079 ; BR IF NOT SUPPORTED CLD LODSW ;XLATE TABLE ADDRESS MOV DPEXLT[BP],AX LODSB ;CP/M RECORDS PER PHYSICAL SECTOR MOV DPERPS[BP],AL LODSB ;CP/M RECORDS PER ALLOCATION BLOCK MOV DPERPAB[BP],AL MOV DI,DPEDPB[BP] ;DPB MOV CX,DPBL CLD MOV AX,DS MOV ES,AX REP MOVSB ;* DONE WITH SELECT OPERATION SEL2078: AND DSKOP,NOT DSKOPS ;INDICATE DONE WITH SELECT OPERATION JMP DONE207 ;RETURN VIA 'DONE207' ;* ERROR OCCURRED SEL2079: MOV PHYDPE,0 ;INDICATE ERROR JMPS SEL2078 ;** READ TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=NO ERROR , 1=ERROR ; USES: AX,DI ; RDT207: CALL SET207 ;SETUP CALL SDT207 ;SEEK DESIRED TRACK CALL S1S207 ;SET 1ST SECTOR TO READ LES DI,DWORD PTR BUFBUF[BX] ;BUFFER ADDRESS ADD DI,AX RDT2071: CMP PREREAD,0 ;Q. DOING PREREAD JNE RDT2072 ; BR IF YES CMP BUFERR[BX],0 ;Q. ABORT JNE RDT2073 ; BR IF YES RDT2072: CALL RDS207 ;READ NEXT SECTOR RDT2073: ADD DI,COUNT ;BUMP BUFFER POINTER INC PHYSEC ;BUMP PHYSICAL SECTOR # MOV AL,BYTE PTR PHYSEC ;CHECK IF SECTOR # WRAPAROUND CMP AL,SECCNT JB RDT2074 ; BR IF NOT XOR AX,AX ; OTHERWISE START AT BEGINNING MOV PHYSEC,AX MOV DI,BUFBUF[BX] RDT2074: CMP AL,SEC1ST ;CHECK IF ALL OF TRACK READ JNE RDT2071 ; BR IF NOT JMP DONE207 ;RETURN THRU 'DONE207' ;** WRITE TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=NO ERROR , 1=ERROR ; USES: AX,SI,DI ; WRT207: CALL SET207 ;SETUP CALL SDT207 ;SEEK DESIRED TRACK CALL S1S207 ;SET 1ST SECTOR TO WRITE LES SI,DWORD PTR BUFBUF[BX] ;BUFFER ADDRESS ADD SI,AX WRT2071: MOV DI,BUFSECF[BX] ;CHECK IF PHYSICAL SECTOR IS DIRTY ADD DI,PHYSEC TEST BYTE PTR [DI],1 JZ WRT2073 ; BR IF IT IS NOT MOV BYTE PTR [DI],0 ;CLEAR DIRTY SECTOR FLAG CMP BUFERR[BX],0 ;Q. ABORT JNE WRT2073 ; BR IF YES -- SKIP PHYSICAL WRITE CALL WRS207 ;WRITE SECTOR WRT2073: ADD SI,COUNT ;SKIP BUFFER POINTER TO NEXT SECTOR INC PHYSEC ;BUMP PHYSICAL SECTOR # MOV AL,BYTE PTR PHYSEC ;CHECK IF SECTOR # WRAPAROUND CMP AL,SECCNT JB WRT2074 ; BR IF NOT XOR AX,AX ; OTHERWISE SET TO START MOV PHYSEC,AX MOV SI,BUFBUF[BX] WRT2074: CMP AL,SEC1ST ;CHECK IF ALL OF TRACK WRITTEN JNE WRT2071 ; BR IF NOT CALL WBS207 ;WAIT FOR WRITE GATE TURN OFF JMP DONE207 ;RETURN THRU 'DONE207' ;** MOUNT ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: NONE ; USES: DI ; MNT207: MOV DI,BUFDPE[BX] ;SET TRACK POSITION TO UNKNOWN MOV DPETRK[DI],DPEUNK RET ;** FORMAT TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; 'FVFLG'=VERIFY FLAG ; 'DMAPTR'=ADDRESS OF TRACK IMAGE (OFFSET) ; 'DMASEG'=ADDRESS OF TRACK IMAGE (SEGMENT) ; EXIT: 'ERROR'=ERROR STATUS ; USES: AX,CX,DX,SI ; FMT207: CALL SET207 ;SETUP CALL SDT207 ;SEEK DESIRED TRACK OR DSKOP,DSKOPF ;INDICATE FORMAT OPERATION IN PROGRESS CALL SRC207 ;SET RETRY COUNTER TEST DPEUNIT[BP],CONDS8 ;Q. TIME FOR SPECIAL CHECK JZ FMT2071 ; IF 8" DRIVE CMP PHYTRK,0 ; TRACK 0 JNE FMT2071 ; CMP PHYSID,FDFSS1 ; SIDE 1 JNE FMT2071 ; BR IF NOT IN AL,FDAS ;Q. IS DOUBLE SIDED DISKETTE INSERTED TEST AL,AS2S JNZ FMT2071 ; BR IF YES MOV AL,FDSNRD ; ELSE -- FLAGS AS NOT READY ERROR JMPS FMT2072 FMT2071: MOV AL,PHYSID ;GET SIDE SELECT FLAG OR AL,FDCWRT ; OR IN COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FLAG FOR NEXT I/O LES SI,DWORD PTR DMAPTR ;GET ADDRESS OF TRACK IMAGE MOV CX,12000 ;USE LARGE COUNT CALL WR207 ;USE LOW LEVEL WRITE ROUTINE TEST AL,AL ;Q. ERROR JZ FMT2073 ; BR IF NOT CALL WBS207 ;WAIT BEFORE STEPPING FMT2072: CALL ERR207 ;Q. SHOULD I RETRY JNC FMT2071 ; BR IF YES AND DSKOP,NOT DSKOPF ; OTHERWISE EXIT JMP FMT2074 FMT2073: AND DSKOP,NOT DSKOPF ;INDICATE FORMAT OPERATION OVER CMP FVFLG,0 ;Q. SHOULD I VERIFY JZ FMT2074 ; BR IF NOT MOV PREREAD,0 CALL RDT207 ;TRY READING TRACK FMT2074: JMP DONE207 ;** WRITE PROTECT CHECK ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=R/W , 1=R/O ; USES: AL,BP ; WPC207: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE OR DSKOP,DSKOPWP ;INDICATE WRITE PROTECT OPERATION CALL DS207 ;SELECT DRIVE MOV AL,FDCFI+FDFINI ;FORCE TYPE 1 STATUS OUT FDCMD,AL PUSH AX MOV AX,(60+3)/4 CALL WDLY POP AX WPC2071: IN AL,FDSTA ;WAIT FOR CONTROLLER NOT BUSY TEST AL,FDSBSY JNZ WPC2071 AND AL,FDSWPV ;ISOLATE WRITE PROTECT BIT MOV AL,0 ;ASSUME R/W JZ WPC2072 ; BR IF R/W MOV AL,1 ;INDICATE R/O WPC2072: MOV BUFERR[BX],AL ;RETURN VALUE AND DSKOP,NOT DSKOPWP ;INDICATE WRITE PROTECT OP DONE JMP DONE207 ;RET VIA 'DONE207' ;** READY CHECK ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER ; EXIT: 'BUFERR[BX]'=STATUS (0=NOT READY , 1=READY) ; USES: AL,DX,BP ; RDY207: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE CALL RDY2070 JMP DONE207 RDY2070: MOV BUFERR[BX],0 ;ASSUME NOT READY OR DSKOP,DSKOPRD ;INDICATE READY CHECK IN PROGRESS CALL DS207 ;SELECT DRIVE MOV DX,5000/TINTRVL+1 ;COMPUTE TIMEOUT COUNT (5 SEC) ADD DX,TICCNT MOV AL,FDCFI+FDFII2 ;WAIT FOR INDEX HOLE TRANSITION OUT FDCMD,AL PUSH AX MOV AX,(60+3)/4 CALL WDLY POP AX RDY2071: CMP DX,TICCNT ;Q. TIMEOUT JE RDY2073 ; BR IF YES IN AL,FDAS ;Q. INDEX HOLE FOUND TEST AL,ASIRQ JZ RDY2071 ; BR IF NOT RDY2072: IN AL,FDSTA ;WAIT FOR 1797 TO GO NOT BUSY TEST AL,FDSBSY JNZ RDY2072 MOV BUFERR[BX],1 ;INDICATE DRIVE READY RDY2073: AND DSKOP,NOT DSKOPRD ;INDICATE READY CHECK DONE RET ;* READ SECTOR ; ; ENTRY: 'PHYSEC'=SECTOR # ; (DI),(ES)=BUFFER POINTER ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL,CX ; RDS207: OR DSKOP,DSKOPR ;INDICATE READ OPERATION IN PROGRESS CALL SRC207 ;SET RETRY COUNTER MOV HSTPTR,DI ;SAVE BUFFER POINTER MOV HSTPTR+2,ES MOV AL,BYTE PTR PHYSEC ;GET SECTOR # INC AL ;PUT INTO RANGE 1 TO SPT OUT FDSEC,AL ;TELL CONTROLLER RDS2071: MOV AL,PHYSID ;GET SIDE SELECT VALUE OR AL,FDCRDS+FDFSLF ;FORM COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FOR NEXT I/O MOV CX,COUNT ;GET COUNT LES DI,DWORD PTR HSTPTR ;GET BUFFER POINTER CALL RD207 ;USE LOW LEVEL READ ROUTINE AND AL,NOT FDSRTE ;MASK ERROR CODE TEST AL,AL ;CHECK FOR ERROR JZ RDS2073 ; BR IF NO ERROR CALL ERR207 ;CHECK IF I SHOULD DO RETRY JNC RDS2071 ; BR IF YES CMP PREREAD,0 ;Q. IS THIS A PREREAD OPERATION JNE RDS2074 ; BR IF YES CALL ABTIGN ;HANDLE ABORT/IGNORE RDS2074: MOV AL,ERRTYP ;RESTORE ERROR CODE RDS2073: LES DI,DWORD PTR HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPR ;INDICATE READ OPERATION DONE RET ;* LOW LEVEL READ ROUTINE ; ; ENTRY: (AL)=COMMAND ; (DI),(ES)=BUFFER POINTER ; (CX)=COUNT ; EXIT: (AL)=CONTROLLER STATUS ; USES: AX,CX,DI ; RD207: MOV AH,AL ;SAVE COMMAND IN AL,FDDAT ;CLEAR ANY PENDING DRQ IF WAIT MOV AL,DEVCTL ;ENABLE WAIT STATE I/O OR AL,CONWE OUT FDCON,AL ENDIF CLD ;FORWARD DIRECTION PUSHF ;DISABLE INTERRUPTS CLI MOV AL,AH ;RESTORE COMMAND OUT FDCMD,AL ;ISSUE COMMAND RD2071: IF NOT WAIT IN AL,FDAS ;WAIT FOR DRQ OR IRQ TEST AL,ASDRQ+ASIRQ JZ RD2071 ENDIF IN AL,FDDAT ;GET DATA STOSB ;STORE IN BUFFER LOOP RD2071 ;LOOP AND READ POPF ;RESTORE INTERRUPT STATUS CALL WAIT2071 ;WAIT FOR COMMAND COMPLETION IF WAIT MOV AH,AL ;SAVE CONTROLLER STATUS MOV AL,DEVCTL ;DISABLE WAIT STATE I/O OUT FDCON,AL MOV AL,AH ;RESTORE CONTROLLER STATUS ENDIF RET ;* RDA207 - READ ADDRESS ; ; ENTRY: (DI)=BUFFER ADDRESS OFFSET ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL,CX,DI ; RDA207: OR DSKOP,DSKOPRA ;SHOW READ ADDR OP IN PROGRESS MOV HSTPTR,DI ;SAVE BUFFER POINTER MOV HSTPTR+2,DS RDA2071: MOV AL,PHYSID ;GET SIDE FLAG VALUE OR AL,FDCRDA ; OR IN COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FOR NEXT I/O MOV CX,FDRAL ;COUNT LES DI,DWORD PTR HSTPTR ;GET BUFFER POINTER CALL RD207 ;USE LOW LEVEL READ ROUTINE AND DSKOP,NOT DSKOPRA ;INDICATE READ ADDRESS OP DONE RET ;* S1S - SET 1ST SECTOR ; ; ENTRY: NONE ; EXIT: (AX)=BUFFER DISPLACEMENT ; 'PHYSEC','SEC1ST'=1ST SECTOR # ; USES: AX,DI ; S1S207: LEA DI,RDABUF ;USE READ ADDRESS BUFFER CALL RDA207 ; TO DO READ ADDRESS OPERATION LEA DI,RDABUF ;GET ADDR OF READ ADDRESS INFO TEST AL,AL ;CHECK IF READ ADDRESS RETURN ERROR JZ S1S2071 ; BR IF NO ERROR MOV BYTE PTR FDRASEC[DI],0 ; OTHERWISE 0 S1S2071: MOV AL,FDRASEC[DI] ;GET SECTOR # CMP AL,SECCNT ;CHECK IF LAST SECTOR ON TRACK JB S1S2072 ; BR IF NOT XOR AL,AL ; OTHERWISE 0 S1S2072: MOV SEC1ST,AL ;SAVE AS 1ST SECTOR # CBW ;SET 'PHYSEC' MOV PHYSEC,AX MUL COUNT ;COMPUTE DISPLACEMENT RET ;* WRS207 - WRITE SECTOR ; ; ENTRY: 'PHYSEC'=SECTOR # ; (SI),(ES)=BUFFER POINTER ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL,CX,DX ; WRS207: OR DSKOP,DSKOPW ;INDICATE WRITE OPERATION IN PROGRESS CALL SRC207 ;SET RETRY COUNTER MOV HSTPTR,SI ;SAVE BUFFER POINTER MOV HSTPTR+2,ES MOV AL,BYTE PTR PHYSEC ;GET SECTOR # INC AL ;PUT INTO RANGE 1 TO SPT OUT FDSEC,AL ;TELL CONTROLLER WRS2071: MOV AL,PHYSID ;GET SIDE SELECT VALUE OR AL,FDCWRS+FDFSLF ;FORM COMMAND OR AL,HLDDLYF ; OR IN DELAY FLAG MOV HLDDLYF,0 ;ZERO DELAY FOR NEXT I/O MOV CX,COUNT ;GET COUNT LES SI,DWORD PTR HSTPTR ;GET BUFFER POINTER CALL WR207 ;USE LOW LEVEL WRITE ROUTINE TEST AL,AL ;CHECK FOR ERROR JZ WRS2073 ; BR IF NO ERROR CALL WBS207 ;WAIT FOR WRITE GATE TURN OFF CALL ERR207 ;CHECK IF I SHOULD DO RETRY JNC WRS2071 ; BR IF YES CALL ABTIGN ;ASK ABOUT ABORTING MOV AL,ERRTYP ;RESTORE ERROR CODE WRS2073: LES SI,DWORD PTR HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPW ;INDICATE WRITE OP DONE RET ;* WR207 - LOW LEVEL WRITE ROUTINE ; ; ENTRY: (AL)=COMMAND ; (SI)=BUFFER POINTER (OFFSET) ; (ES)=BUFFER POINTER (SEGMENT) ; (CX)=COUNT ; EXIT: (AL)=CONTROLLER STATUS ; USES: AX,CX,SI ; WR207: MOV AH,AL ;SAVE COMMAND MOV AL,FDSWPV ;ASSUME WRITE PROTECT VIOLATION TEST DPEFLAG[BP],DPE48RO ;CHECK FOR 48 TPI R/O DISK JNZ WR2072 ; BR IF IT IS IN AL,FDDAT ;CLEAR ANY PENDING DRQ IF WAIT MOV AL,DEVCTL ;ENABLE WAIT STATE I/O OR AL,CONWE OUT FDCON,AL ENDIF PUSHF ;DISABLE INTERRUPTS CLI CLD ;FORWARD DIRECTION CALL EXDSES ;GET DATA SEGMENT MOV AL,AH OUT FDCMD,AL ;ISSUE COMMAND WR2071: IF NOT WAIT IN AL,FDAS ;WAIT FOR DRQ OR IRQ TEST AL,ASDRQ+ASIRQ JZ WR2071 ENDIF LODSB ;GET DATA OUT FDDAT,AL ;SEND TO DISK LOOP WR2071 ;LOAD AND WRITE CALL EXDSES ;RESTORE DATA SEGMENT POPF ;RESTORE INTERRUPT STATUS CALL WAIT2071 ;WAIT FOR COMMAND COMPLETION IF WAIT MOV AH,AL ;SAVE CONTROLLER STATUS MOV AL,DEVCTL ;DISABLE WAIT STATE I/O OUT FDCON,AL MOV AL,AH ;RESTORE CONTROLLER STATUS ENDIF WR2072: RET ;* DONE WITH 207 ; ; ENTRY: NONE ; EXIT: NONE ; USES: AL ; DONE207: MOV AL,PHYSID ;SAVE SIDE SELECT VALUE CMP BUFERR[BX],0 ;Q. DID ERROR OCCUR JZ DONE2071 ; BR IF NOT MOV AL,FDFSS1 DONE2071: MOV SIDE207,AL MOV Z207DSEL,Z207DSELV ;SET DESELECT VALUE RET ;* SET UP DEVICE ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: (BP)=ADDRESS OF DPE ; 'PHYTRK'=PHYSICAL TRACK # ; 'PHYSID'=PHYSICAL SIDE # ; 'SECCNT'=# SECTORS PER TRACK ; 'COUNT'=# BYTES PER SECTOR ; DRIVE IS SELECTED ; USES: AX,BP,SI ; SET207: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE ; COMPUTE PHYSICAL TRACK AND SIDE VALUES MOV AL,BYTE PTR BUFTRK[BX] ;GET CP/M TRACK # MOV PHYSID,0 ;ASSUME SIDE 0 MOV PHYSIDN,0 TEST DPEFLAG[BP],DPE2S JZ SET2071A ;BR IF NOT DOUBLE SIDED MEDIA SHR AL,1 ;DIVIDE TRACK # BY 2 JNC SET2071A ;EVEN TRACKS ON SIDE 0 MOV PHYSID,FDFSS1 ; ODD TRACKS ON SIDE 1 MOV PHYSIDN,1 SET2071A: MOV PHYTRK,0 ;INSURE HIGH ORDER BYTE IS 0 MOV BYTE PTR PHYTRK,AL ;SAVE PHYSICAL TRACK # ; CHECK FOR SPECIAL CASE OF 8" DRIVE, TRACK 0, SIDE 0 CMP BYTE PTR PHYTRK,0 ;CHECK IF TRACK 0 JNE SET2072 ; BR IF NOT CMP PHYSID,0 ;CHECK IF SIDE 0 JNE SET2072 ; BR IF NOT TEST DPEFLAG[BP],DPET0SD ;CHECK IF TRACK 0 SINGLE DENSITY JZ SET2072 ; BR IF NOT MOV SECCNT,26 ;26 PHYSICAL SECTORS PER TRACK MOV COUNT,128 ;128 BYTES PER PHYSICAL SECTOR JMPS SET2073 ; COMPUTE NUMBER OF SECTORS PER TRACK SET2072: MOV SI,DPEDPB[BP] MOV AX,DPBSPT[SI] DIV DPERPS[BP] MOV SECCNT,AL ; COMPUTE NUMBER OF BYTES PER SECTOR MOV AL,128 MUL DPERPS[BP] MOV COUNT,AX ; SET2073: CALL DS207 ;SELECT DRIVE ; SET TRACK REGISTER IN CONTROLLER MOV AL,DPETRK[BP] ;GET TRACK POSITION OUT FDTRK,AL ;SET TRACK REGISTER TEST AL,DPEUNK ;CHECK IF UNKNOWN JZ SET2074 ; BR IF KNOWN CALL RST207 ;RESTORE HEAD ; SET2074: RET ;* SET I/O RETRY COUNTER ; ; ENTRY: NONE ; EXIT: 'RETRIES' SET ; USES: NONE ; SRC207: MOV RETRIES,Z207MRC ;ASSUME MAX # TEST DSKOP,DSKOPRA+DSKOPS ;CHECK IF SPECIAL CASE JZ SRC2071 ; BR IF NOT MOV RETRIES,4 ;ALLOW ONLY 4 RETRIES SRC2071: RET ;* DRIVE SELECT ; ; ENTRY: NONE ; EXIT: DRIVE SELECTED AND UP TO SPEED ; USES: AX,CX ; DS207: MOV HLDDLYF,0 ;ASSUME ZERO DELAY MOV Z207DSEL,0 ;ZERO DESELECT TIMER ; FORM CONTROL WORD MOV AL,DPEUNIT[BP] ;GET UNIT SELECT FROM DPE OR AL,CONDSEN ;DRIVE SELECT ENABLE TEST DPEFLAG[BP],DPEDD ;Q. DOUBLE DENSITY JZ DS2070 ; BR IF NOT CMP BYTE PTR PHYTRK,0 ;CHECK FOR SPECIAL CASE JNE DS2071 ; WHERE TRACK 0 SIDE 0 CMP PHYSID,0 ; SINGLE DENSITY WHILE THE JNE DS2071 ; REST IS DOUBLE DENSITY TEST DPEFLAG[BP],DPET0SD JZ DS2071 ;BR IF NOT SPECIAL CASE DS2070: OR AL,CONSD ;SET FOR SINGLE DENSITY ; DS2071: MOV AH,AL ;(AH)=NEW CONTROL WORD TEST DPEFLG2[BP],DPEHLS ;Q. DRIVE HAS HEAD LOAD SELONOID JZ DS2071A ; BR IF NOT AND AL,CONDSEN+CONDS8+CONDS ;ISOLATE DRIVE SELECT BITS IN NEW MOV CL,DEVCTL ;ISOLATE DRIVE SELECT AND CL,CONDSEN+CONDS8+CONDS ; BITS IN OLD CONTROL WORD CMP AL,CL ;Q. SAME DRIVE STILL SELECTED JE DS2071A ; BR IF YES IN AL,FDTRK ;NEW DRIVE SELECTED - CAUSE 1797 OUT FDDAT,AL ; TO RESET HEAD LOAD DELAY TIMER MOV AL,FDCSEK ; BY DOING ZERO LENGTH SEEK WITH CALL WAIT207 ; HEAD UNLOADED MOV HLDDLYF,FDFDLF ;USE DELAY FOR NEXT I/O MOV Z207HUD,Z207HUDV DS2071A: TEST DPEFLG2[BP],DPEHLS ;Q. DRIVE HAS HEAD LOAD SELENOID JZ DS2071C ; BR IF NOT DS2071B: CMP Z207HUD,0 ; WAIT FOR HEAD UNLOAD DELAY TIME JNE DS2071B DS2071C: TEST AH,CONDS8 ;CHECK IF SELECTING 8" DRIVE JNZ DS2075 ; BR IF 8" ; SELECT 5 1/4" DRIVE AND AH,NOT CONPC ;ASSUME PRE-COMP TEST DPEFLAG[BP],DPE96T ;Q. 96 TPI DRIVE JNZ DS2072 ; BR IF YES CMP BYTE PTR PHYTRK,23 ;Q. TRACK >= 23 ON 48 TPI DRIVE JAE DS2072 ; BR IF YES OR AH,CONPC ;DON'T USE PRE-COMP DS2072: MOV AL,AH ;SELECT DRIVE OUT FDCON,AL ; HANDLE MOTOR START UP DELAY FOR 5 1/4" DRIVE TEST DSKOP,DSKOPWP+DSKOPI ;Q. WAIT FOR MOTOR UP TO SPEED ; JNZ DS2079 ; BR IF NO JZ $+5 JMP DS2079 MOV AL,DEVCTL ;CHECK IF A 5 1/4" DRIVE AND AL,CONDSEN+CONDS8 ; IS ALREADY SELECTED CMP AL,CONDSEN ; JE DS2079 ; BR IF YES JNE $+5 JMP DS2079 IN AL,FDAS ;SEE IF MOTOR STILL RUNNING TEST AL,ASMO ; JNZ DS2079 ; BR IF IT IS JZ $+5 JMP DS2079 MOV CX,250/TINTRVL+1 ;WAIT FOR 250 mS TEST DPESEK[BP],DPEMO ;CHECK IF FAST MOTOR UP TO SPEED JNZ DS2073 ; BR IF YES MOV CX,1000/TINTRVL+1 ;WAIT FOR 1 SEC DS2073: ADD CX,TICCNT DS2073A: CMP CX,TICCNT JNE DS2073A JMP DS2079 ; SELECT 8" DRIVE ; ; SINCE THE 1797 CHECKS THE DRIVE READY STATUS LINE BEFORE PLACING ; THE VALUE OF THE SIDE SELECT ON ITS OUTPUT PIN, IT MAY BE NECESSARY ; TO FORCE THE 1797 TO PLACE A SIDE SELECT VALUE ACCEPTABLE TO THE ; DRIVE BEFORE PRECEDING. THIS SITUATION ARISES WHEN ; 1. A PREVIOUS 1797 COMMAND SELECTED SIDE 1 ; 2. THE MEDIA IS NOT DOUBLE SIDED ; WHAT HAPPENS IS SOME DRIVES INDICATE DRIVE READY AS ; 1. MEDIA INSERTED ; 2. DOOR CLOSED ; 3. SIDE SELECTED IS AVAILABLE DS2075: MOV AL,AH ;SELECT DRIVE OUT FDCON,AL TEST DSKOP,DSKOPWP+DSKOPI+DSKOPRD ;Q. SKIP JNZ DS2079 ; BR IF YES CMP PHYSID,FDFSS1 ;Q. WISH TO USE SIDE 1 JE DS2078 IN AL,FDAS ;CHECK IF DOUBLE SIDED MEDIA TEST AL,AS2S JNZ DS2078 ; BR IF DOUBLE SIDED MEDIA CMP SIDE207,FDFSS1 ;CHECK IF SIDE 1 SELECTED PREVIOUSLY JNE DS2078 ; BR IF NOT XOR AL,AL ;DESELECT DRIVE OUT FDCON,AL PUSH AX MOV AL,FDCRDA+FDFDLF ;USE READ ADDRESS COMMAND OUT FDCMD,AL ; TO FORCE SIDE 0 SELECT MOV AX,(60+3)/4 ;DELAY TO GIVE STATUS A CHANCE CALL WDLY DS2076: IN AL,FDSTA ;WAIT UNTIL 1797 GOES BUSY TEST AL,FDSBSY JZ DS2076 MOV AL,FDCFI+FDFINI ;TERMINATE COMMAND OUT FDCMD,AL MOV AX,(60+3)/4 ;DELAY TO GIVE STATUS A CHANCE CALL WDLY DS2077: IN AL,FDSTA ;WAIT UNTIL 1797 GOES NOT BUSY TEST AL,FDSBSY JNZ DS2077 IN AL,FDDAT ;FLUSH ANY DATA IN 1797 POP AX TEST DPEFLG2[BP],DPEHLS ;Q. DRIVE HAS HEAD LOAD SELENOID JZ DS2077B ; BR IF NOT MOV Z207HUD,Z207HUDV ; WAIT FOR HEAD UNLOAD SETTLE TIME DS2077A: CMP Z207HUD,0 JNE DS2077A DS2077B: MOV AL,AH ;RESELECT DRIVE OUT FDCON,AL ; WAIT FOR MOTOR UP TO SPEED. DRIVE WILL INDICATE READY WHEN ; UP TO SPEED. THIS IS DONE TO ACCOMODATE DRIVES WITH DC MOTORS. DS2078: PUSH AX MOV AL,FDCFI+FDFINI ;FORCE TYPE 1 STATUS OUT FDCMD,AL MOV AX,(60+3)/4 ;DELAY TO GIVE STATUS A CHANCE CALL WDLY DS2078A: IN AL,FDSTA ;WAIT UNITL 1797 GOES NOT BUSY TEST AL,FDSBSY JNZ DS2078A MOV CX,1000/TINTRVL+1 ;WAIT 1 SEC MAX ADD CX,TICCNT DS2078B: CMP CX,TICCNT ;Q. TIME UP JE DS2078C ; BR IF YES IN AL,FDSTA TEST AL,FDSNRD ;Q. DRIVE READY JNZ DS2078B ; BR IF NOT DS2078C: POP AX ; DS2079: MOV DEVCTL,AH ;SAVE CONTROL REGISTER IMAGE RET ;* WWD207 - ISSUE COMMAND, WAIT FOR I/O COMPLETION, AND ; WAIT FOR MECHANICAL DELAY AFTER STEPPING ; ; ENTRY: (AL)=COMMAND ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL ; WWD207: CALL WAIT207 ;DO I/O PUSH AX ;WAIT FOR MECHANICAL DELAY MOV AX,18*250 CALL WDLY TEST DPEUNIT[BP],CONDS8 ;WAIT A WHILE FOR DRIVE TO BE READY JZ WWD2073 ; THIS IS DONE FOR ZENITH PUSH CX ; 8" DRIVES MOV CX,200/TINTRVL+1 ADD CX,TICCNT WWD2071: CMP CX,TICCNT JE WWD2072 IN AL,FDSTA TEST AL,FDSNRD JNZ WWD2071 WWD2072: POP CX WWD2073: POP AX RET ;* WAIT207 - ISSUE COMMAND AND WAIT FOR I/O COMPLETION ; ; ENTRY: (AL)=COMMAND ; EXIT: (AL)=CONTROLLER STATUS ; USES: AL ; WAIT207: OUT FDCMD,AL ;ISSUE COMMAND PUSH AX ;WAIT AT LEAST 60uS MOV AX,(60+3)/4 ; BEFORE CHECKING STATUS CALL WDLY POP AX WAIT2071: IN AL,FDAS ;WAIT FOR IRQ TEST AL,ASIRQ JZ WAIT2071 WAIT2073: IN AL,FDSTA ;GET CONTROLLER STATUS TEST AL,FDSBSY ;WAIT FOR NOT BUSY JNZ WAIT2073 RET ;* CHECK IF TO DO RETRIES ; ; ENTRY: (AL)=CONTROLLER STATUS ; 'RETRIES'=RETRY COUNTER ; EXIT: PSW/C=RETRY STATUS (0=RETRY , 1=NO RETRY) ; USES: AL,CX,DI ; ; I/O RECOVERY PROCEDURE: ; 1) RETRY I/O OPERATION ; 2) STEP HEAD IN/OUT 1 TRACK, THEN RETRY I/O OPERATION ; 3) RETRY I/O OPERATION ; 4) STEP HEAD OUT/IN 1 TRACK, THEN RETRY I/O OPERATION ; 5) RETRY I/O OPERATION ; 6) RESTORE HEAD/RE-SEEK, THEN RETRY I/O OPERATION ; 7) RETRY I/O OPERATION ; 8) STEP HEAD IN/OUT 1 TRACK, THEN RETRY I/O OPERATION ; 9) RETRY I/O OPERATION ; 10) STEP HEAD OUT/IN 1 TRACK, THEN RETRY I/O OPERATION ; 11) RETRY I/O OPERATION ; 12) FLAG AS HARD ERROR ; ERR207: MOV ERRTYP,AL ;SAVE CONTROLLER STATUS AS ERROR TYPE TEST AL,FDSNRD+FDSWPV ;CHECK FOR NOT READY OR WRITE PROTECT ; JNZ ERR2079 ; BR IF YES - NO RETRIES JZ $+5 JMP ERR2079 TEST DSKOP,DSKOPR+DSKOPW ;Q. READ/WRITE OPERATION JZ ERR2070 ; BR IF NOT TEST AL,FDSRNF ;Q. RNF ERROR JZ ERR2070 ; BR IF NOT CMP RETRIES,Z207MRC ;Q. 1ST TRY JNE ERR2070 ; BR IF NOT PUSH HSTPTR ;TRY READING HEADER AT OTHER DENSITY PUSH HSTPTR+2 XOR DEVCTL,CONSD MOV AL,DEVCTL OUT FDCON,AL LEA DI,RDABUF CALL RDA207 POP HSTPTR+2 POP HSTPTR PUSH AX XOR DEVCTL,CONSD MOV AL,DEVCTL OUT FDCON,AL POP AX TEST AL,FDSRNF ;Q. RNF ERROR JZ ERR2079 ; BR IF NOT -- SOMEONE PROBABLY SWAPPED ; DISK THAT IS DIFFERENT DENSITY ERR2070: TEST DSKOP,DSKOPS ;IF NOT DOING A SELECT OPERATION JNZ ERR2071 INC SECNT ; BUMP SOFT ERROR COUNTER ERR2071: DEC RETRIES ;UPDATE RETRY COUNTER JZ ERR2079 ; BR IF EXHAUSTED RETRIES MOV AL,RETRIES CMP AL,6 JA ERR2072 SUB AL,6 ERR2072: JNZ ERR2073 ;BR IF NOT TIME TO DO RESTORE HEAD CALL RST207 ;RESTORE HEAD BEFORE TRYING AGAIN JMPS ERR2077 ERR2073: CMP AL,4 ;CHECK IF TIME TO STEP OUT JNE ERR2074 ; BR IF NOT DEC BYTE PTR PHYTRK ;DECREMENT TO NEXT TRACK JS ERR2073A ; BR IF BEFORE TRACK 0 CALL SDT207 ; OTHERWISE STEP OUT ERR2073A: INC BYTE PTR PHYTRK ;RESTORE DESIRED TRACK JMPS ERR2077 ERR2074: CMP AL,2 ;CHECK IF TIME TO STEP IN JNE ERR2078 ; BR IF NOT MOV AL,NTRK837-1 ;GET MAXIMUM TRACK # TEST DPEUNIT[BP],CONDS8 JNZ ERR2074A MOV AL,NTRKD37-1 TEST DPEFLAG[BP],DPE96T JNZ ERR2074A MOV AL,NTRKS37-1 ERR2074A: INC BYTE PTR PHYTRK ;INCREMENT TO NEXT TRACK CMP AL,BYTE PTR PHYTRK ;CHECK IF MAX TRACK # >= NEXT TRACK JB ERR2074B ; BR IF IT IS CALL SDT207 ; OTHERWISE STEP IN ERR2074B: DEC BYTE PTR PHYTRK ;RESTORE DESIRED TRACK ERR2077: CALL SDT207 ;SEEK DESIRED TRACK ERR2078: CLC ;INDICATE TRY AGAIN RET ERR2079: MOV BUFERR[BX],1 ;SET ERROR FLAG MOV AL,ERRTYP ;RECOVER CONTROLLER STATUS TEST DSKOP,DSKOPR+DSKOPW ;IF DOING READ OR WRITE OPERATION JZ ERR2079B MOV DI,BUFERRF[BX] ; PLACE IN ERROR ARRAY ADD DI,PHYSEC MOV [DI],AL JMPS ERR2079D ERR2079B: TEST DSKOP,DSKOPF ;Q. FORMAT OPERATION JZ ERR2079C ; BR IF NO TEST DEVCTL,CONDS8 ;Q. 8" DRIVE JZ ERR2079C ; BR IF NOT CMP PHYTRK,0 ;Q. TRACK 0 JNE ERR2079C ; BR IF NOT CMP PHYSID,FDFSS1 ;Q. SIDE 1 JNE ERR2079C ; BR IF NOT CMP ERRTYP,FDSNRD ;Q. NOT READY ERROR JE ERR2079E ; BR IF YES ERR2079C: CALL ERRRPT ; OTHERWISE REPORT ERROR IMMEDIATELY ERR2079D: TEST DSKOP,DSKOPS ;IF NOT DOING A SELECT OPERATION JNZ ERR2079E INC HECNT ; COUNT HARD ERROR ERR2079E: STC ;INDICATE DON'T TRY AGAIN RET ;* RESTORE HEAD ; ; ENTRY: NONE ; EXIT: (AL)=CONTROLLER STATUS ; USES: AX ; RST207: MOV DPETRK[BP],0 ;INDICATE TRACK # 0 TEST DPESEK[BP],DPEFS ;Q. CAN DRIVE FAST STEP JZ RST2071 ; BR IF NOT MOV AL,DEVCTL ;SET UP FAST STEP OR AL,CON5FS OUT FDCON,AL RST2071: MOV AL,DPESEK[BP] ;GET STEP RATE AND AL,FDFSRM OR AL,FDCRST ;RESTORE HEAD COMMAND CALL WWD207 ;DO RESTORE TEST DPEFLG2[BP],DPEHLS ;Q. DRIVE HAS HEAD LOAD SELENOID JZ RST2071B ; BR IF NOT MOV Z207HUD,Z207HUDV ; WAIT FOR HEAD UNLOAD DELAY RST2071A: CMP Z207HUD,0 JNE RST2071A RST2071B: TEST DSKOP,DSKOPI ;Q. INIT OPERATION JZ RST2072 ; BR IF NOT TEST AL,FDSTK0 ;Q. AT TRACK 0 JZ RST2073 ; BR IF NOT RST2072: MOV AL,4 ;STEP IN 4 TRACKS TEST DSKOP,DSKOPI ;Q. INIT OPERATION JZ RST2072A ; BR IF NOT MOV AL,10 ; STEP IN 10 TRACKS RST2072A: CALL SDT2077 MOV AL,FDCRST+FDFHLB+FDFS30 ;RESTORE HEAD COMMAND CALL WWD207 ;DO RESTORE RST2073: MOV AH,AL ;SAVE CONTROLLER STATUS MOV AL,DEVCTL ;TURN OFF FAST STEP OUT FDCON,AL MOV AL,AH ;RESTORE CONTROLLER STATUS MOV HLDDLYF,FDFDLF ;USE DELAY FOR NEXT I/O RET ;* SEEK DESIRED TRACK ; ; ENTRY: 'PHYTRK'=TRACK # ; EXIT: NONE ; USES: AL ; SDT207: MOV AL,DPETRK[BP] ;GET CURRENT TRACK CMP AL,BYTE PTR PHYTRK ;CHECK AGAINST DESIRED TRACK JE SDT2072 ;ALREADY AT DESIRED TRACK TEST DPESEK[BP],DPEFS ;CHECK FOR FAST STEP JZ SDT2070 ; BR IF NOT MOV AL,DEVCTL ;ENABLE FAST STEP OR AL,CON5FS OUT FDCON,AL SDT2070: CALL SDT2076 ;DO SEEK TEST DPEFLAG[BP],DPE48RO ;CHECK IF 48TPI R/O MEDIA JZ SDT2071 ; BR IF NOT -- NO NEED TO DOUBLE STEP MOV AL,DPETRK[BP] ;GO THROUGH SEEK PROCEDURE AGAIN A SECOND TIME OUT FDTRK,AL ;RESET CONTROLLER'S TRACK REG CALL SDT2076 ;DO 2ND SEEK SDT2071: MOV AL,BYTE PTR PHYTRK ;OUTPUT DESIRED TRACK TO TRACK REG OUT FDTRK,AL ; THIS IS DONE IN CASE SEEK ABORTED ; WHEN IT TRIED TO STEP TO NEGATIVE ; TRACK LEAVING TRACK REGISTER ; CONTAINING 0 MOV DPETRK[BP],AL ;UPDATE IN MEMORY TRACK VALUE MOV AL,DEVCTL ;RESTORE CONTROL REGISTER OUT FDCON,AL ; INCASE I WAS FAST STEPPING SDT2072: MOV HLDDLYF,FDFDLF ;USE DELAY FOR NEXT I/O RET ; DO SEEK SDT2076: MOV AL,BYTE PTR PHYTRK ;TELL CONTROLLER DESIRED TRACK SDT2077: OUT FDDAT,AL MOV AL,DPESEK[BP] ;GET STEP RATE AND AL,FDFSRM OR AL,FDCSEK+FDFHLB ; OR IN COMMAND JMP WWD207 ;DO I/O + MECHANICAL DELAY ; RET VIA WDD207 ;* WAIT ~1.5 mS BEFORE STEPPING ; ; ENTRY: NONE ; EXIT: NONE ; USES: NONE ; WBS207: PUSH AX MOV AX,250*3/2+1 CALL WDLY POP AX RET X207 EQU OFFSET $ DSEG ORG X207 Z207DSEL DW 0 ;DRIVE DESELECT TIMER SLOT Z207HUD DW 0 ;HEAD UNLOAD DELAY TIMER SLOT DL207 RB 0 ;DEFAULT LABEL FOR 5 1/4" DB 0,DPEDD,0,4,8,0,0,0,0 DW 32 DB 3,7,0 DW 155,63,00C0H,16,1 IF (OFFSET $ - OFFSET DL207) NE (LABCS-LABEL) %: 5 1/4" DEFAULT LABEL IS NOT CORRECT LENGTH ENDIF X2071 EQU OFFSET $ CSEG ORG X2071