;******************************************************** ;* * ;* DISK INPUT/OUTPUT DRIVER SUBROUTINE PACKAGE * ;* FOR WESTERN DIGITAL 1771 DISK CONTROLLER * ;* * ;* bullet-proof error recovery added 12-APR-80 * ;* * ;******************************************************** ; ; ; EQUATES FOR DISK CONTROLLER PORTS AND COMMAND CODES ; STSREG EQU WD1771+0 ;STATUS REGISTER CMDREG EQU WD1771+0 ;COMMAND REGISTER TRKREG EQU WD1771+1 ;TRACK REGISTER SECREG EQU WD1771+2 ;SECTOR REGISTER DATREG EQU WD1771+3 ;DATA REGISTER ; RDCMD EQU 10001000B ;READ COMMAND WRTCMD EQU 10101000B ;WRITE COMMAND SKCMD EQU 00011100B ;SEEK COMMAND FINCMD EQU 11010000B ;FORCE INTR COMMAND RSTCMD EQU 00001100B ;RESTORE COMMAND HLOAD EQU 00000100B ;RD/WRT HEAD LOAD ENABLE ; RET EQU 0C9H ;SUBROUTINE RETURN INSTR OPCODE NMIVEC EQU 0066H ;THE NON-MASKABLE INTERRUPT IS ;USED FOR DATA SYNCRONIZATION BETWEEN ;THE Z-80 AND 1771 DISK CONTROLLER ; ; ; SELECT: LD A,C ;GET UNIT# PASSED IN C AND CP 4 ; CHECK FOR MAXIMUM VALID# RET NC ;ERROR IF NUMBER > 3 CALL TURNON ;MAKE SURE DISKS ARE TURNED ON IN A,(BITDAT) LD B,A ;SAVE CURRENT DRIVE SELECT DATA AND 11111000B ;MERGE IN NEW DRIVE UNIT# IN C OR C ; IN PLACE OF THE CURRENT ONE OUT (BITDAT),A ; TO SELECT THE NEW DISK DRIVE CALL FORCE ;TEST NEW DRIVE'S READY STATUS JR Z,SEL2-$ ; AND CONTINUE IF ITS READY LD A,B OUT (BITDAT),A ;ELSE PUT BACK OLD DRIVE SELECT DATA LD A,10000000B ; AND RETURN DRIVE-NOT-READY STATUS RET SEL2: LD HL,UNIT ;POINT HL TO DRIVE SELECT DATA LD A,(HL) ;LOAD A WITH CURRENT UNIT# LD (HL),C ; AND STORE NEW UNIT# FROM C CP 255 ;TEST IF NO DRIVE HAS BEEN SELECTED JR Z,SEL3-$ ; YET AND SKIP NEXT SEGMENT IF SO INC HL ;POINT TO HEAD POSITION TABLE ADD A,L ; AND ADD IN NEW UNIT# AS INDEX LD L,A IN A,(TRKREG) ;GET CURRENT HEAD POSITION LD (HL),A ; AND STORE IN TABLE @ HL SEL3: LD HL,TRKTAB LD A,L ADD A,C ;INDEX INTO TABLE TO GET LD L,A ; HEAD POSITION OF NEW DRIVE LD A,(HL) CP 255 ;TEST IF NEW DRIVE HAS EVER BEEN JR Z,HOME-$ ; SELECTED AND DO A HOME IF NOT OUT (TRKREG),A ;OUTPUT THE DRIVE'S CURRENT HEAD XOR A ; POSITION TO THE TRACK REGISTER RET ; ; ; HOME: CALL READY ;CLEAR DISK CONTROLLER RET NZ ;EXIT IF DRIVE NOT READY XOR A LD (TRACK),A ;SET TRACK# IN MEM TO ZERO RESTOR: LD B,RSTCMD ;LOAD B WITH A RESTORE COMMAND CALL STEP ;EXECUTE HEAD MOVING OPERATION XOR 00000100B ;GET TRUE TRACK 0 STATUS AND 10011100B ;MASK TO ERROR BITS RET ;RETURN 1771 STATUS IN A ; ; ; SEEK: CALL READY ;CLEAR DISK CONTROLLER RET NZ ;EXIT IF DRIVE NOT READY LD A,C ;GET TRACK# DATA FROM C AND CP 77 ; CHECK FOR MAXIMUM VALID# RET NC ;FORGET IT IF TRACK# > 76 LD (TRACK),A ; ELSE STORE TRACK# FOR SEEK OUT (DATREG),A ;OUTPUT TRACK # TO 1771 LD B,SKCMD ;LOAD B WITH A SEEK COMMAND AND CALL STEP ; GO SEEK WITH PROPER STEP RATE AND 10011000B ;MASK TO READY,SEEK AND CRC ERROR RET Z ; BITS AND RETURN IF ALL GOOD CALL RESTOR ;ELSE TRY TO RE-CAILBRATE HEAD RET NZ ;ERROR IF WE CAN'T FIND TRACK 0 LD A,C OUT (DATREG),A ;OUTPUT TRACK# TO 1771 LD B,SKCMD CALL STEP ;TRY TO SEEK THE TRACK AGAIN AND 10011000B RET ;RETURN FINAL SEEK STATUS IN A ; ; ; WRITE: CALL READY ;CLEAR THE DISK CONTROLLER RET NZ ;EXIT IF DRIVE NOT READY BIT 6,A RET NZ ;EXIT IF DISK IS WRITE-PROTECTED LD B,WRTCMD JR RDWRT-$ READ: CALL READY ;CLEAR DISK CONTROLLER RET NZ ;EXIT IF DRIVE NOT READY LD B,RDCMD RDWRT: LD (IOPTR),HL ;STORE DISK I/O DATA POINTER LD HL,SECTOR LD (HL),C ;STORE SECTOR# FOR READ/WRITE INC HL LD (HL),B ;SAVE READ/WRITE COMMAND BYTE INC HL LD (HL),2 ;SET DISK OPERATION RE-TRY COUNT RW1: DI ;NO INTERRUPTS DURING DISK I/O LD HL,NMIVEC ;SAVE BYTE AT NMI VECTOR LOCATION LD D,(HL) ; IN D FOR DURATION OF READ/WRITE LD (HL),RET ; LOOP AND REPLACE IT WITH A RET LD HL,RECLEN LD B,(HL) ;B=NUMBER OF BYTES/SECTOR LD C,DATREG ;C=1771 DATA REGISTER PORT# LD HL,(IOPTR) ;HL=DISK READ/WRITE DATA POINTER LD A,(SECTOR) ;GET SECTOR NUMBER OUT (SECREG),A ;OUTPUT SECTOR# TO 1771 CALL FORCE ;ISSUE A FORCE INTERRUPT COMMAND BIT 5,A ; TO TEST CURRENT HEAD LOAD STATUS LD A,(CMDTYP) ;GET READ OR WRITE COMMAND BYTE JR NZ,RW2-$ ;JUMP IF HEAD IS ALREADY LOADED OR HLOAD ; ELSE MERGE IN HLD BIT RW2: CALL CMDOUT ;START THE 1771 DOING IT'S THING BIT 5,A ;TEST IF COMMAND IS A READ OR WRITE JR NZ,WLOOP-$ ; AND JUMP TO THE CORRECT LOOP RLOOP: HALT INI JP NZ,RLOOP CALL BUSY ;LOOP UNTIL 1771 COMES UN-BUSY AND 10011100B ;MASK OFF TO READY, NOT FOUND, CRC JR RW3-$ ; AND LOST DATA STATUS BITS WLOOP: HALT OUTI JP NZ,WLOOP CALL BUSY AND 10111100B ;MASK OFF AS ABOVE PLUS WRITE FAULT RW3: LD HL,NMIVEC LD (HL),D ;RESTORE BYTE @ NMI VECTOR EI RET Z ;RETURN IF NO DISK I/O ERRORS LD HL,RETRY DEC (HL) ;DECREMENT RE-TRY COUNT AND JR NZ,RW4-$ ; EXECUTE COMAND AGAIN IF NOT=0 OR A RET ;ELSE RETURN 1771 ERROR STATUS RW4: LD HL,TRACK LD C,(HL) ;GET TRACK# FOR CURRENT OPERATION CALL SEEK ;TRY TO RE-CAILBRATE THE HEAD JR RW1-$ ; BEFORE READING OR WRITING AGAIN ; ; ; STEP: LD A,(SPEED) ;GET STEP SPEED VARIABLE AND 00000011B OR B ;MERGE WITH SEEK/HOME COMMAND IN B CALL CMDOUT ;OUTPUT COMMAND AND DELAY BUSY: IN A,(STSREG) BIT 0,A ;TEST BUSY BIT FROM JR NZ,BUSY-$ ; 1771 AND LOOP TILL=0 RET ; ; ; CMDOUT: OUT (CMDREG),A ;OUTPUT A COMMAND TO THE 1771 CALL PAUSE ;WASTE 44 MICROSECONDS PAUSE: EX (SP),HL EX (SP),HL RET ; ; ; READY: CALL TURNON ;KEEP THOSE DISKS SPINING FOLKS FORCE: LD A,FINCMD ;ISSUE A FORCE INTERRUPT COMMAND CALL CMDOUT IN A,(STSREG) ;READ STATUS REGISTER CONTENTS BIT 7,A ;TEST DRIVE NOT READY BIT RET ; ; ; TURNON: LD A,30 LD (MOTOR),A ;RE-LOAD THE MOTOR TURN-OFF TIMER CALL PAUSE IN A,(BITDAT) BIT 2,A ;TEST IF MOTORS HAVE BEEN STOPPED RET Z ; AND EXIT IF STILL TURNED ON AND 10111011B ;ELSE RE-ENABLE THE DRIVE SELECTS OUT (BITDAT),A ; AND ACTIVATE THE MOTOR RELAY PUSH BC LD B,0 ;SET READY LOOP MAX TIMEOUT TURN2: CALL WAIT ;WAIT 1/93 SECOND AND TEST READY JR Z,TURN3-$ ;EXIT LOOP IF DRIVE READY DJNZ TURN2-$ ; ELSE TRY AGAIN UP TO 256 TIMES TURN3: LD B,9 TURN4: CALL WAIT ;GIVE ABOUT 1/10 SECOND MORE DELAY DJNZ TURN4-$ POP BC RET ; ; WAIT: IN A,(CTC3) ;GET CURRENT CTC3 COUNT VALUE LD C,A WAIT2: IN A,(CTC3) CP C ;TEST IF CTC3 HAS CHANGED BY 1 COUNT JR Z,WAIT2-$ ; AND LOOP UNTIL IT CHANGES JR FORCE-$ ; THEN GO TEST DRIVE READY STATUS ; ; ; ;