; HDWD5A - This one for RADIO SHACK - LDOS 5.1 - 06/10/84 ; Change Log ;Log in drive if possible 04/26/83 ;Store total head count for drive 04/29/83 ;Padded to 399 bytes 06/10/83 ;Added precomp reg init 07/07/83 ;Handle WD1010 controller 12/12/83 ; TITLE '' SUBTTL '' ORG 6000H ;*=*=* ; Version equates ;*=*=* LF EQU 10 CR EQU 13 MINTRK EQU 3 MAXTRK EQU 404 *GET VERSION *LIST OFF IF MOD1 *GET MOD1/EQU ENDIF IF MOD3 *GET MOD3/EQU ENDIF *LIST ON ;DVRWD/ASM - LDOS 5.1 - 01/13/83 - RS/CJ/LM ;*=*=* ;*=*=* ; Calling Sequence ; B => disk command ; C => logical drive number ; D => logical cylinder number ; E => logical sector number ; HL => sector I/O buffer address ; IY => drive code table address ;*=*=* ; bit 2 => wait enable ; bit 3 => device enable ; bit 4 => software reset HARDWP EQU 0C0H HDCONT EQU 0C1H ;*=*=* DATA EQU 0C8H ;Data transfer port ERROR EQU DATA+1 ;Error code port WRP EQU DATA+1 ;Write precompensation port SECNT EQU DATA+2 ;Sector count SECNO EQU DATA+3 ;Sector number port CYLLO EQU DATA+4 ;Cylinder lo CYLHI EQU DATA+5 ;Cylinder hi SDH EQU DATA+6 ;Size/Drive/Head port STATUS EQU DATA+7 ;Status port COMMAND EQU DATA+7 ;Command port ;*=*=* ; Western Digital Controller OP codes ; ; 0001rrrr - Restore drive ; 0111rrrr - Seek sector/head/cyl ; 0010d000 - Read sector ; 00110000 - Write sector ; 01010000 - Format track ; ; rrrr = step rate ; d = 0=programmed I/O, 1=DMA ;*=*=* ; Winchester drive code tables ;*=*=* DCTAB EQU $ DB 0,0,0 ;Push to correct posn TYPQTY EQU 1 DRVSEL EQU 3 ;DCT pos for select ;*=*=* ; Defaults for ST-506 ;*=*=* DB 8!4 ;5" fixed hard drive DB 10H ;Alien, starting head = 0 DB 0 ;Unused here DB 153-1 ;Max cylinder DB 3<5+31 ;4 heads & 32 sectors/tk DB 0<5+15 ;Y "grans/tk" 16 sec/gran DB 76 ;Directory cyl ;*=*=* ; start of driver ;*=*=* DISK JR START ;Branch around linkage DW $-$ ;Last byte used DB 5,'TRSH1' ;Progname ; RETRYR LD HL,'DH' LD (3C00H+62),HL ;Init done by ICONFG IFDEF HDCONT INIT LD A,10H OUT (HDCONT),A LD B,40H CALL @PAUSE LD A,0CH OUT (HDCONT),A EX (SP),HL EX (SP),HL IN A,(STATUS) AND 80H JR NZ,RETRYR ;*=*=* ; Restore the WDC to set the step rate ;*=*=* ELSE INIT XOR A ENDIF ; OUT (SDH),A ; set the step rate LD A,16H ;* set 3ms-restore STP1 EQU $-1 ;+set by user entry if >3 OUT (COMMAND),A ;* execute command CALL DWR1 ;Wait until not busy R1 EQU $-2 XOR A OUT (CYLHI),A OUT (CYLLO),A ;Set for WD1010 LD A,1<4!0 ;Restore w/step rate STP2 EQU $-1 ;+set by user entry OUT (COMMAND),A LD B,50 ;Delay about .32 sec. CALL @PAUSE LD HL,' ' LD (3C00H+62),HL CALL DWR2 ;Wait for completion R2 EQU $-2 JR NZ,RETRYR ;Retry if error PCPTRK LD A,$-$ OUT (WRP),A ;Set precomp trk#/4 LINK RET ;End call before install DB 'WD' ;2 more bytes for @ICNFG ; ;*=*=* ; Driver start ;*=*=* START BIT 3,B JR NZ,DIO ;Jump if I/O request IFDEF HARDWP TSTBSY LD A,(IY+3) ;P/u drive address AND 3 ; & remove other junk LD C,A ;Save for counter IN A,(HARDWP) ;P/u the front panel WP DB 0DCH ;Ignore next 2 by CALL C, ALIGN RLCA ;Align hard WP bit to b7 DEC C ; according to drive JR NZ,ALIGN ; address OR (IY+3) ;Merge software WP ELSE ; TSTBSY LD A,(IY+3) ;Just dct bit ENDIF ; AND 80H ;Write protected ??? SLA A ;WP to carry RET NC ;W/0 in A LD A,01000000B ;Show floppy type WP RET ;W Z,C set ;*=*=* ; Disk I/O requested ;*=*=* DIO PUSH HL PUSH DE BIT 2,B ;Test input or output JR Z,INPUT ;Go if read/verify CALL TSTBSY ;If Write, check first R3 EQU $-2 LD A,15 ;Write prot error JR C,POP2 ;Ret w/error LD A,B ;Get fcn SUB 13 ;WRSEC? JR Z,WRSEC DEC A ;Or WRSYS JR Z,WRSEC ;Go on output LD A,8 ;Not available..for format JR POP2 ;Set NZ/ret w/error ;*=*=* ; Sector read routine ;*=*=* INPUT PUSH BC ;Save fcn # CALL SETUP ;Establish drive R6 EQU $-2 LD A,20H ;Set controller OP code OUT (COMMAND),A ; & send to WDC CALL DWR1 ;Delay/wait for completion R7 EQU $-2 POP DE ;Fcn to D PUSH AF ;Save status fm disk BIT 1,D ;Sector verify? JR Z,READ ;Go if read VRLP IN E,(C) DJNZ VRLP DB 11H ;Skip next via LD DE, READ INIR ;Get data POP AF ;Recover completion status LD HL,RDTBL ;Error xlate R8 EQU $-2 JR NZ,ENDERR ;Go on error POP DE ;Adjust read error LD A,D ; code if system CP (IY+9) ; sector was read LD A,6 JR Z,POP1 ;Go if system XOR A JR POP1 ;*=*=* ; sector WRITE routine ;*=*=* ; WRSEC CALL SETUP ;Establish drive linkage R9 EQU $-2 ;*=*=* ; Routine to pass WRITE Command to WDC & do it ;*=*=* LD A,30H ;Init write command OUT (COMMAND),A ; & pass to WDC OTIR ;Output the data LD HL,WRTBL ;Point to error xlate R10 EQU $-2 CALL DWR1 ;Wait for completion R11 EQU $-2 JR Z,EXIT ; ENDERR CALL WD1010 ;Clear controller R12 EQU $-2 IN A,(ERROR) ;Grab error code ERR1 RLCA ;Find error TYPE INC HL ;Bump counter JR NC,ERR1 ;Loop for error byte LD A,(HL) ;P/u error code ; EXIT EQU $ ;Restore registers POP2 POP DE POP1 POP HL OR A ;Set flag ;This is to take care of the WD1010 controller CIP bit WD1010 PUSH AF IN A,(STATUS) ; AND 00000010B ;Bit 1 is CIP for 1010 JR Z,CLEAN ;All OK LD A,10H ;Do a software reset OUT (HDCONT),A LD A,0CH ;Then re-enable OUT (HDCONT),A CLEAN POP AF ;Continue RET ;*=*=* ; LDOS error conversion table ; Bit Error RD WR ; 7 Bad block detect 7 14 ; 6 CRC - Data field 4 12 ; 5 CRC - ID field 1 9 ; 4 ID not found 5 13 ; 3 Not used 127 127 ; 2 Aborted command 8 8 ; 1 TR000 error 2 10 ; 0 DAM not found 3 11 ;*=*=* RDTBL EQU $-1 DB 7,4,1,5,127,8,2,3 WRTBL EQU $-1 DB 14,12,9,13,127,8,10,11 ; DWR1 EX (SP),HL ;Delay time to settle EX (SP),HL ; the controller ; DWR2 IN A,(STATUS) ;Wait until controller RLCA ; is no longer busy JR C,DWR2 IN A,(STATUS) ;Get status again AND 00000001B ;NZ=error RET ;*=*=* ; SETUP disk ; IY= DCT ; D = Cylinder # (0-202) ; E = Sector # (0-255) ;*=*=* SETUP EQU $ ;Wait until not busy ;*=*=* ; Select routine ;*=*=* PUSH HL ;Save buffer pointer ;*=*=* ; Recalc cyl, sector to head, sector, cyl ;*=*=* RECALC LD L,D ;Xfer cylinder LD H,0 ; BIT 5,(IY+4) ;Double track? JR Z,$+3 ;Go if not ADD HL,HL ;Cyl * 2 ;***** ; Check on track advance ;***** LD A,(IY+7) ;P/u sectors/track PUSH DE LD D,A ;Hang on to value AND 1FH ;Strip off other data LD E,A INC E ;Adj for zero offset LD C,E ;Keep sec per track XOR D ;Get # of heads RLCA ;Shift heads to 0-2 RLCA RLCA INC A ;Adjust for zero offset CALL MULTEA@ DEC A ;Adjust for compare POP DE ;Rcvr sector CP E ;Is sector on this track? JR NC,REC1 ;Bypass if yes CPL ;Else subtract off a ADD A,E ; track's # of sectors LD E,A ;Reset sector # INC HL ; and bump cyl # REC1 LD A,C ;Sector#/sectors per head CALL DIVEA@ LD D,A ;Xfer head # needed LD A,(IY+4) ;P/u starting head AND 0FH ;Strip off other data ADD A,D ;Add in relative head LD D,A ;Point to physical head ;***** ; Xfer head, sector, & cylinder data to WDC ;***** LD A,(IY+3) ;Grab the drive select AND 3 RLCA ;Shift to bits 3-4 RLCA RLCA OR D ;Merge in head select OUT (SDH),A ;Transfer to WDC LD A,E OUT (SECNO),A LD A,L OUT (CYLLO),A LD A,H OUT (CYLHI),A POP HL ;Rcvr buffer pointer LD BC,0<8!DATA ;Set buflen & xfer port RET HOWBIG EQU $-DISK DC 399-HOWBIG,0 ;Pad out to 400 bytes DISKEND EQU $ ;*=*=* ; some patch space - INSTALL must be patched also to load ;*=*=* DW 0,0,0,0,0,0,0,0,0,0 DW 0,0,0,0,0,0,0,0,0,0 DW 0,0,0,0,0,0,0,0,0,0 DW 0,0,0,0,0,0,0,0,0,0 RELTAB DW R1,R2,R3,R6,R7 DW R8,R9,R10,R11,R12 TABLEN EQU $-RELTAB/2 DW 0,0,0,0 ;Patch addresses ; ; end of actual I/O driver ; PAGE