home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
S
/
ZEN2.LBR
/
Z207DRVR.LIB
< prev
next >
Wrap
Text File
|
2000-06-30
|
32KB
|
1,475 lines
;*** Z207 DEVICE DRIVER
;
;** 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
ADD BP,BBIOS
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
PUSH ES
MOV ES,.MTRDSEG ;GET ADDRESS OF MONITOR DATA AREA
MOV CL,ES: MTRBU ;GET BOOT DEVICE UNIT #
MOV AL,ES: MTRBI ;GET BOOT DEVICE INDEX #
POP ES
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
MOV DI,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
MOV DI,BUFBUF[BX] ;TRY TO READ LABEL SECTOR AGAIN
CALL RDS207
TEST AL,AL
; JNZ SEL2079 ; BR IF ERROR
JZ $+5
JMP SEL2079
SEL2072:
MOV SI,BUFBUF[BX] ;CHECK CHECKSUM OF LABEL
ADD SI,LABEL
CALL CHKLAB
; JNZ SEL2079 ; BR IF ERROR
JZ $+5
JMP SEL2079
; MOVE LABEL INFO TO DPE'S HEATH EXTENSIONS
MOV SI,BUFBUF[BX]
AND DPEFLAG[BP],DPETYPE+DPE96T
MOV AL,LABHTH+(OFFSET DPEFLAG)-(OFFSET DPEHTH) [SI]
AND AL,DPEDD+DPE2S
OR DPEFLAG[BP],AL ;FLAG BYTE #1
MOV AL,LABHTH+(OFFSET DPERPS)-(OFFSET DPEHTH) [SI]
MOV DPERPS[BP],AL ;CP/M RECORDS PER PHYSICAL SECTOR
MOV AL,LABHTH+(OFFSET DPERPAB)-(OFFSET DPEHTH) [SI]
MOV DPERPAB[BP],AL ;CP/M RECORDS PER ALLOCATION BLOCK
AND DPEFLG2[BP],NOT DPE96TM
MOV AL,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
MOV SI,BUFBUF[BX]
ADD SI,LABDPB
MOV DI,DPEDPB[BP]
MOV CX,DPBL
CLD
REP MOVSB
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 SEL2076 ;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
; UPDATE REST OF DPE
SEL2076:
AND DPEFLAG[BP],0FFH-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
XOR AH,AH ;XLATE TABLE ADDRESS
LODSB
SHL AX,1
MOV DI,XLATES
ADD DI,AX
MOV AX,ES:[DI]
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
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
MOV DI,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
MOV SI,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
; 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
MOV SI,DMAPTR ;GET ADDRESS OF TRACK IMAGE
MOV CX,12000 ;USE LARGE COUNT
MOV DX,ES ;DATA SEGMENT TO USE
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)=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 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
MOV DI,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:
MOV DI,HSTPTR ;RESTORE BUFFER POINTER
AND DSKOP,NOT DSKOPR ;INDICATE READ OPERATION DONE
RET
;* LOW LEVEL READ ROUTINE
;
; ENTRY: (AL)=COMMAND
; (DI)=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
CALL EXDSES ;NEED ES: TO POINT TO MY BANK
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 EXDSES ;RESTORE DS: AND ES:
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
; EXIT: (AL)=CONTROLLER STATUS
; USES: AL,CX,DI
;
RDA207:
OR DSKOP,DSKOPRA ;SHOW READ ADDR OP IN PROGRESS
MOV HSTPTR,DI ;SAVE BUFFER POINTER
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
MOV DI,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)=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 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
MOV SI,HSTPTR ;GET BUFFER POINTER
MOV DX,DS ;DATA SEGMENT
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:
MOV SI,HSTPTR ;RESTORE BUFFER POINTER
AND DSKOP,NOT DSKOPW ;INDICATE WRITE OP DONE
RET
;* WR207 - LOW LEVEL WRITE ROUTINE
;
; ENTRY: (AL)=COMMAND
; (SI)=BUFFER POINTER
; (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
PUSH DS ;GET DATA SEGMENT
MOV DS,DX
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
POP DS ;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
XOR AL,AL ;DESELECT DRIVE
OUT FDCON,AL
MOV DEVCTL,AL
TEST DPEFLG2[BP],DPEHLS ;Q. DRIVE HAS HEAD LOAD SELONOID
JZ DONE2072 ; BR IF NOT
PUSH AX
MOV AX,35*250 ;WAIT DRIVE DESELECT TIME
CALL WDLY
POP AX
DONE2072:
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,12 ;ASSUME 12
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
; 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
DS2071A:
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
JMPS 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
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
;* 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,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
TEST DSKOP,DSKOPS ;IF NOT DOING A SELECT OPERATION
JNZ ERR2071
MOV DI,BBIOS ; BUMP SOFT ERROR COUNTER
INC SECNT[DI]
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
MOV DI,BBIOS ; COUNT HARD ERROR
INC HECNT[DI]
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 WAIT207 ;DO RESTORE
PUSH AX ;WAIT FOR MECHANICAL DELAY
MOV AX,15*250
CALL WDLY
POP AX
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,10 ;STEP IN 10 TRACKS
CALL SDT2077
MOV AL,FDCRST+FDFHLB+FDFS30 ;RESTORE HEAD COMMAND
CALL WAIT207 ;DO RESTORE
PUSH AX ;WAIT FOR MECHANICAL DELAY
MOV AX,15*250
CALL WDLY
POP AX
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
CALL WAIT207 ;DO I/O
PUSH AX ;WAIT FOR MECHANICAL DELAY
MOV AX,15*250
CALL WDLY
POP AX
RET
;* 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