;*** Z217 DEVICE DRIVER ; ; * * * N O T E * * * ; ; THIS DRIVE ASSUMES A CELL SIZE OF 512 BYTES WITH 18 SECTORS PER TRACK. ; ; ONLY UNIT 0 IS HANDLED. ; ; ALTHOUGH THE CONTROLLER PROVIDES FOR 21 BIT LOGICAL SECTOR NUMBERS, ; THIS DRIVER ONLY HANDLES 16 BIT LOGICAL SECTOR NUMBERS. THEREFORE, ; THE MAXIMUM SIZE OF DISK IS 65536 SECTORS (0-FFFFH). ; ;** DRIVER ENTRY JUMP VECTORS ; DRVR217: JMP SEL217 ;SELECT JMP RDT217 ;READ TRACK JMP WRT217 ;WRITE TRACK JMP MNT217 ;MOUNT JMP FMT217 ;FORMAT JMP WPC217 ;WRITE PROTECT CHECK ;** INITIALIZE DRIVE TABLES ; ; ENTRY: NONE ; EXIT: NONE ; USES: ALL ; IN217: ; FILL IN COMMAND BLOCK LEA DI,Z217BLK ;ADDRESS OF NEXT COMMAND CALL TMA217 MOV AL,Z217BLK+OFFSET WI01HT MOV Z217BLK+OFFSET WI01HN,AL MOV AL,Z217BLK+OFFSET WI01MT MOV Z217BLK+OFFSET WI01MN,AL MOV AL,Z217BLK+OFFSET WI01LT MOV Z217BLK+OFFSET WI01LN,AL ; CHECK IF CONTROLLER IS PRESENT LEA DI,Z217BLK ;ATTEMPT TO ISSUE SETUP COMMAND CALL SUP217 JC IN2174 ; BR IF ERROR ; READ SBC AND SET DRIVE PARAMETERS LEA DI,BUFFER ;GET BUFFER ADDRESS CALL TMA217 CALL WAIT2171 ;EXECUTE READ COMMAND TEST AL,WISERR ;Q. ERROR JNZ IN2174 ; BR IF ERROR LEA DI,BUFFER+OFFSET SBCSDP ;ADDRESS OF SET DRIVE CALL SUP217 ; PARAMETERS COMMAND JC IN2174 ; BR IF ERROR CALL WAIT2171 ;EXECUTE COMMAND TEST AL,WISERR ;Q. ERROR JNZ IN2174 ; BR IF ERROR LEA DI,Z217BLK ;ADDRESS FOR REST OF DRIVER CALL SUP217 JNC IN2175 ; BR IF NO ERROR ; MARK DRIVE AS IMAGINARY IN2174: MOV CX,2 ;# OF Z217 DRIVES LEA BP,DPEBASE+DPEL*4 ;START ADDRESS OF Z217 DPE'S ADD BP,BBIOS IN21741: OR DPEFLG2[BP],DPEIMG ;FLAG DRIVE AS IMAGINARY ADD BP,DPEL ;BUMP POINTER LOOP IN21741 ;LOOP AND MARK ALL DRIVES ; FILL IN DPE TABLES / DISK MAP TABLE IN2175: MOV CH,2 ;# DRIVES MOV CL,0 ;STARTING UNIT # MOV DH,4 ;STARTING DRIVE MAP # CALL CBTFIL ;DO FILL ; ASSIGN PARTITION IF BOOT UNIT PUSH ES MOV ES,.MTRDSEG ;GET ADDRESS OF MONITOR DATA AREA CMP ES: MTRBI,2 ;Q. Z217 BOOTED POP ES JNE IN2176 ; BR IF NOT LEA BP,DPEBASE+4*DPEL ;GET ADDRESS OF 1ST DPE FOR Z217 ADD BP,BBIOS OR DPEFLAG[BP],DPEASGN ;SHOW PARTITION ASSIGNED MOV AX,BBIOS-4 MOV WORD PTR DPETRK[BP],AX ;SET BEGINNING SECTOR OF PARTITION MOV AX,BBIOS-6 MOV WORD PTR DPEUPB[BP],AX ;SET LAST SECTOR # OF PARTITION IN2176: RET ;** SELECT DRIVE FOR 1ST LOGIN ; ; ENTRY: 'PHYDPE'=ADDRESS OF DPE FOR DRIVE ; (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'PHYDPE'=STATUS ; 0=ERROR , OTHERWISE SAME AS ON ENTRY ; USES: NONE ; SEL217: OR DSKOP,DSKOPS ;INDICATE SELECT OP IN PROGRESS MOV BUFTRK[BX],0 ;READ LABEL CALL SET217 MOV DI,BUFBUF[BX] CALL RDS217 CMP BUFERR[BX],0 ;Q. ERROR JNZ SET2179 ; BR IF YES MOV SI,BUFBUF[BX] ;CHECK CHECKSUM OF LABEL ADD SI,LABEL CALL CHKLAB JNZ SET2179 ; BR IF ERROR MOV SI,BUFBUF[BX] ;CHECK IF LABEL'S BEGINNING OF MOV DI,WORD PTR LABHTH+(OFFSET DPETRK)-(OFFSET DPEHTH) [SI] CMP DI,WORD PTR DPETRK[BP] ;PARTITION SECTOR # MATCHES DRIVE TABLE JNE SET2179 ; BR IF NOT MOV DI,WORD PTR LABHTH+(OFFSET DPEUPB)-(OFFSET DPEHTH) [SI] CMP DI,WORD PTR DPEUPB[BP] ;CHECK IF LABEL'S LAST SECTOR # OF ; PARTITION MATCHES DRIVE TABLE JNE SET2179 ; BR IF NOT MOV AL,LABHTH+(OFFSET DPERPAB)-(OFFSET DPEHTH) [SI] MOV DPERPAB[BP],AL ;CP/M RECORDS PER ALLOCATION BLOCK ADD SI,OFFSET LABDPB ;UPDATE DISK PARAMETER BLOCK VALUES MOV DI,DPEDPB[BP] MOV CX,DPBL CLD REP MOVSB SET2178: AND DSKOP,NOT DSKOPS ;INDICATE SELECT OP COMPLETE RET SET2179: MOV PHYDPE,0 ;INDICATE ERROR JMPS SET2178 ;** READ TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]=STATUS ; 0=NO ERROR , 1=ERROR ; USES: DI ; RDT217: CALL SET217 ;SETUP MOV DI,BUFBUF[BX] ;BUFFER ADDRESS RDT2171: CMP PREREAD,0 ;Q. DOING PREREAD JNE RDT2172 ; BR IF YES CMP BUFERR[BX],0 ;Q. ABORT JNE RDT2173 ; BR IF YES RDT2172: CALL RDS217 ;READ NEXT SECTOR RDT2173: ADD DI,WICSZ ;BUMP BUFFER POINTER INC PHYSEC ;BUMP 'PHYSEC' CMP PHYSEC,WINSPT ;Q. ALL SECTORS READ JNE RDT2171 ; BR IF NOT RET ;** WRITE TRACK ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=NO ERROR , 1=ERROR ; USES: AX,SI,DI ; WRT217: CALL SET217 ;SETUP MOV DI,BUFBUF[BX] ;BUFFER ADDRESS WRT2171: MOV SI,BUFSECF[BX] ;CHECK IF PHYSICAL SECTOR IS DIRTY ADD SI,PHYSEC TEST BYTE PTR [SI],1 JZ WRT2173 ; BR IF IT IS NOT MOV BYTE PTR [SI],0 ;CLEAR DIRTY SECTOR FLAG CMP BUFERR[BX],0 ;Q. ABORT JNE WRT2173 ; BR IF YES CALL WRS217 ;WRITE SECTOR WRT2173: ADD DI,WICSZ ;BUMP BUFFER POINTER TO NEXT SECTOR INC PHYSEC ;BUMP PHYSICAL SECTOR # CMP PHYSEC,WINSPT ;Q. ALL TRACK WRITTEN JNE WRT2171 ; BR IF NOT RET ;** MOUNT ; ; ENTRY: (BX)=POINTER TO BUFFER HEADER INFO ; EXIT: NONE ; USES: NONE ; MNT217: RET ;** FORMAT TRACK ; ; ENTRY: NONE ; EXIT: NONE ; USES: NONE ; FMT217: RET ;** WRITE PROTECT CHECK ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER INFO ; EXIT: 'BUFERR[BX]'=STATUS ; 0=R/W , 1=R/O ; USES: NONE ; WPC217: MOV BUFERR[BX],0 ;ALWAYS R/W RET ;* READ SECTOR ; ; ENTRY: 'PHYSEC'=PHYSICAL SECTOR # ; 'SEC217'=STARTING LOGICAL SECTOR # OF TRACK ; (DI)=BUFFER POINTER ; EXIT: NONE ; USES: AL ; RDS217: OR DSKOP,DSKOPR ;INDICATE READ OP IN PROGRESS MOV HSTPTR,DI ;SAVE BUFFER POINTER MOV Z217BLK+OFFSET WI01OP,WIRDL ;READ LOGICAL OP CODE CALL CLS217 ;CALCULATE LOGICAL SECTOR # JC RDS2172 ; BR IF ERROR CALL TMA217 ;CALCULATE DATA TMA ADDRESS CALL WAIT217 ;DO I/O TEST AL,WISERR ;Q. ERROR JZ RDS2173 ; BR IF NO ERROR RDS2172: CALL ERR217 ;REPORT ERROR CMP PREREAD,0 ;Q. IS THIS A PREREAD OPERATION JNE RDS2173 ; BR IF YES CALL ABTIGN ;HANDLE ABORT/IGNORE RDS2173: MOV DI,HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPR ;INDICATE READ OP DONE RET ;* WRITE SECTOR ; ; ENTRY: 'PHYSEC'=PHYSICAL SECTOR # ; 'SEC217'=STARTING LOGICAL SECTOR # OF TRACK ; (DI)=BUFFER POINTER ; EXIT: NONE ; USES: AL ; WRS217: OR DSKOP,DSKOPW ;INDICATE WRITE OP IN PROGRESS MOV HSTPTR,DI ;SAVE BUFFER POINTER MOV Z217BLK+OFFSET WI01OP,WIWRL ;WRITE LOGICAL OP CODE CALL CLS217 ;CALCULATE LOGICAL SECTOR # JC WRS2172 ; BR IF ERROR CALL TMA217 ;CALCULATE DATA TMA ADDRESS CALL WAIT217 ;DO I/O TEST AL,WISERR ;Q. ERROR JZ WRS2173 ; BR IF NO ERROR WRS2172: CALL ERR217 ;REPORT ERROR CALL ABTIGN ;HANDLE ABORT/IGNORE WRS2173: MOV DI,HSTPTR ;RESTORE BUFFER POINTER AND DSKOP,NOT DSKOPW ;INDICATE WRITE OP DONE RET ;* EXECUTE COMMAND AND WAIT FOR I/O COMPLETION ; ; ENTRY: 'Z217BLK'=COMMAND BLOCK ; EXIT: (AL)=CONTROLLER HARDWARE STATUS ; USES: AL ; WAIT217: TEST DPEFLAG[BP],DPEASGN ;Q. PARTITION ASSIGNED JNZ WAIT2171 ; BR IF YES TEST DPEFLAG[BP],DPELSIO ;Q. LOGICAL SECTOR I/O JNZ WAIT2171 ; BR IF YES MOV AL,WISERR ;INDICATE ERROR MOV Z217BLK+OFFSET WI01EEC,WIEPNA RET WAIT2171: MOV AL,WIEXEC ;ISSUE EXECUTE COMMAND OUT WIPCMD,AL WAIT2172: IN AL,WIPSTAT ;WAIT FOR CONTROLLER TO BE DONE TEST AL,WISDONE JZ WAIT2172 RET ;* CALCULATE LOGICAL SECTOR # AND PLACE IN COMMAND BLOCK ; ; ENTRY: 'PHYSEC'=PHYSICAL SECTOR # FOR TRACK ; 'PHYTRK'=LOGICAL SECTOR # OF 1ST SECTOR OF TRACK ; EXIT: 'Z217BLK'=COMMAND BLOCK CONTAINS LOGICAL SECTOR # ; 'C' = 0 NO ERROR , 1=ERROR ; USES: AX ; ; LOGICAL SECTOR # = 'PHYTRK' + 'PHYSEC' ; CLS217: MOV AX,PHYTRK ADD AX,PHYSEC TEST DPEFLAG[BP],DPELSIO ;Q. LOGICAL SECTOR I/O JNZ CLS2171 ; BR IF YES CMP AX,WORD PTR DPETRK[BP] ;Q. SECTOR # WITHIN PARTITION JB CLS2172 ; BR IF NOT CMP AX,WORD PTR DPEUPB[BP] JA CLS2172 ; BR IF NOT CLC CLS2171: MOV Z217BLK+OFFSET WI01LS,AL MOV Z217BLK+OFFSET WI01MS,AH RET CLS2172: STC ;INDICATE ERROR MOV Z217BLK+OFFSET WI01EEC,WIESNWP MOV Z217BLK+OFFSET WI01EMS,AH MOV Z217BLK+OFFSET WI01ELS,AL RET ;* CALCULATE DATA TMA ADDRESS ; ; ENTRY: (DS)=DATA SEGMENT ; (DI)=DATA OFFSET ; EXIT: 'Z217BLK'=COMMAND BLOCK CONTAINS DATA TMA ADDRESS ; USES: AX,DL ; ; DATA TMA ADDRESS = (DS)*16 + (DI) ; TMA217: MOV AX,DS XOR DL,DL SHL AX,1 RCL DL,1 SHL AX,1 RCL DL,1 SHL AX,1 RCL DL,1 SHL AX,1 RCL DL,1 ADD AX,DI ADC DL,0 MOV Z217BLK+OFFSET WI01HT,DL MOV Z217BLK+OFFSET WI01MT,AH MOV Z217BLK+OFFSET WI01LT,AL RET ;* COMMON SETUP ROUTINE ; ; ENTRY: (BX)=ADDRESS OF BUFFER HEADER INFO ; EXIT: 'PHYTRK'=LOGICAL SECTOR # OF 1ST SECTOR OF TRACK ; 'PHYSEC'=0 ; USES: AX,DX ; SET217: MOV BP,BUFDPE[BX] ;GET ADDRESS OF DPE MOV AX,BUFTRK[BX] ;CALCULATE LOGICAL SECTOR # MOV DX,WINSPT ; OF 1ST SECTOR ON TRACK MUL DX TEST DPEFLAG[BP],DPELSIO ;Q. LOGICAL SECTOR I/O JNZ SET2171 ; BR IF YES ADD AX,WORD PTR DPETRK[BP] ;ADJUST FOR BEGINING OF PARTITION SET2171: MOV PHYTRK,AX MOV PHYSEC,0 RET ;* ISSUE SETUP COMMAND TO CONTROLLER ; ; ENTRY: (DI)=COMMAND BLOCK ADDRESS ; EXIT: PSW/C 0=OK , 1=ERROR ; USES: AX ; SUP217: CALL TMA217 ;CONVERT ADDRESS TO 24 BITS MOV AX,10*250 ;SET MAXIMUM TIME FOR ALL TO HAPPEN CALL NWDLY ; TO 10 mS MOV AL,WISETUP ;ISSUE SETUP COMMAND OUT WIPCMD,AL SUP2172: CMP TIMEFLG,0 ;Q. TIME UP JNE SUP2174 ; BR IF YES IN AL,WIPSTAT ;INPUT HARDWARE STATUS TEST AL,WISBUSY ;Q. CONTROLLER BUSY JZ SUP2172 ; BR IF NOT MOV AL,Z217BLK+OFFSET WI01HT ;SEND HIGH ADDRESS BYTE OUT WIPCMD,AL MOV AL,Z217BLK+OFFSET WI01MT ;SEND MIDDLE ADDRESS BYTE OUT WIPCMD,AL MOV AL,Z217BLK+OFFSET WI01LT ;SEND LOW ADDRESS BYTE OUT WIPCMD,AL SUP2173: CMP TIMEFLG,0 ;Q. TIME UP JNE SUP2174 ; BR IF YES IN AL,WIPSTAT ;INPUT HARDWARE STATUS TEST AL,WISBUSY ;Q. STILL BUSY JNZ SUP2173 ; BR IF YES TEST AL,WISDONE ;Q. I/O DONE JZ SUP2173 ; BR IF NOT DONE ; RET ; SUP2174: STC ;INDICATE ERROR RET ;* ERROR REPORTING ; ; ENTRY: 'Z217BLK' CONTAINS ERROR INFORMATION ; EXIT: NONE ; USES: AL,CX,SI,DI ; ERR217: MOV BUFERR[BX],1 ;INDICATE ERROR MOV AL,Z217BLK+OFFSET WI01EEC ;GET ERROR CODE TEST DSKOP,DSKOPR+DSKOPW ;IF DOING READ OR WRITE OPERATION JZ ERR2177 MOV DI,BUFERRF[BX] ; PLACE IN ERROR ARRAY ADD DI,PHYSEC MOV [DI],AL JMPS ERR2178 ERR2177: CALL ERRRPT ; OTHERWISE REPORT ERROR IMMEDIATELY ERR2178: TEST DSKOP,DSKOPS ;Q. DOING 1ST TIME SELECT JNZ ERR2179 ; BR IF YES MOV DI,BBIOS ;COUNT HARD ERROR INC HECNT[DI] ERR2179: RET ;* LOCAL DATA AREA FOR DRIVER WIX1 EQU OFFSET $ DSEG ORG WIX1 Z217BLK RB 0 ;COMMAND BLOCK DB WIRDL ; OP CODE DB 0 ; UNIT SELECT DB 0,0 ; LOGICAL SECTOR # DB 1 ; SECTOR COUNT DB 0,0,0 ; TMA ADDRESS DB 0,0,0 ; NEXT COMMAND ADDRESS DB 0 ; FLAGS DB 0,0,0,0 ; ERROR RETURN INFO IF (OFFSET $ - OFFSET Z217BLK) NE WI01BKL %: Z217BLK IS NOT CORRECT LENGTH ENDIF ; WIX2 EQU OFFSET $ CSEG ORG WIX2