TITLE DISK CONTROLLER MODULE (DCM) LIST NOCOND ;*************************************************************************** ; ; The Disk Controller Module contains the firmware for the Jade ; Double D Disk controller board. ; ;*************************************************************************** ; ; The disk controller module (DCM) resides internal to the Jade Double D ; Disk Controller board. This program provides a facility to read/write ; diskette sectors & format diskette tracks (in single & double density). ; This module sets the parameters for each drive during the "LOG-ON" ; operation. The FORMAT program (not in this module) writes an ident- ; ification sector (T0,S1) which provides the needed information. If this ; identity sector is not present on the diskette, it is assumed to be a ; standard 8" IBM 3740 format. This program contains a 6 word timing block ; which should be patched to match the user's disk drives. This has normally ; been set for Shugart SA800/801 drives. ; ;*************************************************************************** ; ; REVISION STATUS: ; ; 1.0 - 1 AUG 82 GRH ; Initial release ; ; 1.1 - GRH ; Fix bug causing code to crash after predictable number of warm boots. ; A CALL was being made without a return in the login function. ; ; 1.2 - 1 AUG 82 GRH ; ADDED RECAL FEATURE TO RECOVER FROM THE INSTANCE WHERE THE ; HEAD IS OUTSIDE TRACK 0 BUT THE SENSOR IS STILL GIVING ; THE TRACK 0 SIGNAL. IF TRK 0 SENSE IS TRUE ON ENTRY, THE ; HEAD IS STEPPED IN SEVERAL TRACKS, THEN A TRK 0 SEEK IS ; PERFORMED. ; ; 1.3 - 31 AUG 83 GRH ; Add sector de-blocking algorithms for 256 byte sectors. Remove unused ; code & vars. Optimize code. ; ; 1.4 - 30 OCT 85 GRH ; Revise objects for improved include file. Add hooks for double sided ; drives. Change logon to return boolean reflecting a valid descriptor ; sector. ; VERSN EQU '14' ; ;************************************************************* SUBTTL FIRMWARE DEFINITIONS FALSE EQU 0 TRUE EQU NOT FALSE ; ;*INCLUDE JDDLOC.DEF ;*INCLUDE JDDDISK.DEF ;*INCLUDE JDDCONT.DEF ;*MACLIB ASMBTOOL.MLB ; LIST OFF *INCLUDE JDDLOC.DEF *INCLUDE JDDDISK.DEF *INCLUDE JDDCONT.DEF *MACLIB ASMBTOOL.MLB LIST ON ; SECSIZ EQU 128 ;SIZE OF LOGICAL SECTORS IDFLD: EQU 00000000B ;3740 FLAGS DFDFL EQU 0 ;DEFAULT DISK FLAGS SUBTTL MAIN FIRMWARE ;********************************************************** ; ; REGISTER USAGE: ; A, B= SCRATCH ; C= 179X INVERSION CONSTANT ; DE= USED FOR FLAG, SECTOR BY R/W SECTOR SUBR ; HL= PTR TO DATA XFER BY R/W SECTOR SUBR ; IX= DISK PARAMETER BLOCK PTR ; IY= 179X NMI RETURN ADDRESS ; AF'= R/W FLAGS ; BC', DE', HL'= NOT USED ; ;********************************************************** ;-------------------------------------------------------------------- ; ; THE FOLLOWING AREA IS THE INITIAL START JUMP TABLE. ; THE 1ST JUMP IS EXECUTED WHEN THE ONBOARD Z80 IS RESET. ; THE SECOND JUMP IS THE DCM ENTRY FROM A BOOTSTRAP LOADER. ; THIS ENTRY ASSUMES DCM HAS BEEN LOADED INTO DD BANK 1 BY THE ; LOADER ROUTINE. ; ;-------------------------------------------------------------------- ORG 0 JP CLEAR ;RESET & RE-INITIALIZE Z-80 REGS JP INITB + BANKL ;INIT - BOOTSTRAPPED ;******************************************************************** ; ; THIS SUBROUTINE IS THE ENTRY POINT FOR THE DISK CONTROLLER ; TIMING MODULE. THIS MODULE PROVIDES DELAYS WHICH ARE ; MULTIPLES OF 100 us. THE CONTENTS OF DE DETERMINES THE TOTAL ; PERIOD. (DELAY= DE * 100 us). ; ENTRY- DE= 100 MICROSECOND MULTIPLIER (0= 65,536) ; EXIT - DE= A= B= 0 ; ;******************************************************************** ORG 8 ;POSITION FOR RESTART 8 VECTOR ; ; USE SMALLER TIME TO OFFSET CALLING TIME ; LD B,TMRFC ;SET CONSTANT DJNZ $ JP TICKE ;GOTO TICK ENTRY ; ; DELAY FOR 100 us ; TICKR: LD B,TMRNC ;SET NORMAL CONSTANT DJNZ $ ; ; IF MULTIPLIER NOT EXHAUSTED THEN REPEAT TIME ; TICKE: DEC DE ;COUNT -1 LD A,D OR E ;IF COUNT NOT 0 THEN REPEAT NOP NOP JR NZ,TICKR ; ; DONE ; RET ;------------------------------------------------ ; ; INITIALIZATION FROM RESET VECTOR ; ;------------------------------------------------ CLEAR: LD SP,STACK CALL INIT JR SLEEP ;-------------------------------------- ; ; ENTRY VECTOR TO READ SECTOR ; USES RST 40 VECTOR ; ;-------------------------------------- ORG 40 ;POSITION CODE FOR RESTART 40D VECTOR JP RDSEC ;************************************** ; ; TEMPORARY INIT USED ONLY ONCE ; ;************************************** IF $ > (56 - 8) ?OVRLAP RST 56,$-56-8 ENDIF DS (56 - 8) - $ ;POSITION CODE RST38A: CALL INIT ; ; MODIFY CALL VECTOR TO NOT CALL THIS CODE ANY MORE ; LD A,XCUTE ;MODIFY CALL VECTOR LD (HRVEC + 1),A ;-------------------------------------------------------------------- ; ; MASKABLE HOST INTERRUPT ROUTINE - EXECUTED WHEN RESTARTING THE ; LOCAL PROCESSOR FROM A HALT IN ORDER TO PROCESS A COMMAND. ; ;-------------------------------------------------------------------- ORG 56 ;POSITION CODE FOR RESTART 56 VECTOR ; ; CLEAR THE HOST INTERRUPT FLOP ; IN A,(XPIRR) ; ; RESTORE THE STACK ; LD SP,STACK ; ; FIRST TIME, CALL THE INITIALIZATION CODE. FROM THEN ON CALL THE ; COMMAND EXECUTION SUBROUTINE. ; HRVEC: CALL RST38A ;MODIFIED BY RST38A TO CALL XCUTE ; ;-------------------------------------------------------------------- ; ; COMMANDS RETURN HERE. ; THE LOCAL PROCESSOR ENABLES INTERRUPTS & HALTS. DURING THIS TIME, ; THE HOST SYSTEM CAN ACCESS THE CONTROLLER MEMORY AND GET THE COMMAND ; STATUS AND SECTOR DATA. ; ;-------------------------------------------------------------------- SLEEP: EI ;SET ALARM HALT ;GO TO SLEEP ;-------------------------------------- ; ; IDLE COMMAND (NOT IMPLEMENTED) ; ;-------------------------------------- IDLE: ; IN A,(BLSTS) ;IF NO HOST INTERRUPT THEN WAIT ; AND BSINT ; JR Z,IDLE ; ; IN A,(XPIRR) ;ELSE RESET INTERRUPT REQUEST & EXIT ; RET ;------------------------------------------- ; ; READ ADDRESS COMMAND (NOT IMPLEMENTED) ; ;------------------------------------------- ADDR: ;------------------ ; ; SPARE COMMAND ; ;------------------ SPAR: LD HL,CMDBLK + DDMODO ;SET COMMAND ERROR LD (HL),CMDERR RET ;******************************************************************** ; ; THIS IS THE NON-MASKABLE INTERRUPT ROUTINE USED BY THE FDC ; UPON COMMAND TERMINATION. THE STATUS PORT IS INTERROGATED & SAVED (SVSTS). ; ENTRY- IY= INTERRUPT RETURN ADDRESS ; EXIT - (COMMAND BLOCK STATUS)= A= FDC STATUS ; IY= INTERRUPTED ADDRESS ; ;******************************************************************** IF $ > 66H ?OVRLAP NMI VECTOR,$-66H ENDIF ORG 66H ;POSITION CODE FOR NMI VECTOR LOCATION ; ; GET FDC STATUS & PUT INTO COMMAND BLOCK FOR HOST INTERPRETATION ; IN A,(WDSTS) ;CLEARS INTERRUPT TOO XOR C LD (CMDBLK + DDSTSO),A ; ; PUT RETURN ADDRESS ON STACK & RETURN TO IT. ; EX (SP),IY RETN ;******************************************************************** ; ; COMMAND SELECTOR SUBR GETS CONTROL AFTER THE DISK CONTROLLER IS ; INTERRUPTED FROM THE HALT CONDITION. IT BRANCHES TO THE INDIVIDUAL ; COMMAND ROUTINES. ; ;******************************************************************** XCUTE: ; ; ASSUME NO ERROR ; XOR A,A LD (CMDBLK + DDMODO),A LD (CMDBLK + DDSTSO),A ; ; GET FDC'S ATTENTION FOR COMMANDS ; CALL EXSTS ;GET 179X'S ATTENTION FOR CMDS ; ; FETCH COMMAND FROM COMMUNICATION BLOCK ; LD A,(CMDBLK + DDCMDO) ;GET HOST CMD ; ; IF ILLEGAL COMMAND THEN RETURN COMMAND ERROR ; CP NCMDS ;LIMIT OPTIONS JR NC,SPAR ; ; COMPUTE COMMAND TABLE POINTER ; LD D,0 LD E,A ;SET UP OFFSET LD HL,CMDT ;SET TABLE PTR ADD HL,DE ; ; FETCH COMMAND OFFSET FROM TABLE ; LD L,(HL) ;GET ADDRESS LD H,0 ; ; EXECUTE COMMAND. ALL COMMANDS RETURN TO INTERRUPTED WAIT LOOP ; JP (HL) ;GOTO COMMAND ; ; COMMAND TABLE ; CMDT: DB LGON ;LOG-ON DRIVE DB READ ;READ SECTOR DB WRITV ;WRITE SECTOR DB FORM ;FORMAT TRACK DB ADDR ;READ ADDRESS DB SPAR ;SPARES DB SPAR DB IDLE ;BACKGROUND NCMDS EQU $ - CMDT ;COMMAND COUNT WRITV: JP WRIT ;---------------------------- ; ; FORMAT TRACK COMMAND ; ;---------------------------- FORM: ; ; SELECT DRIVE 1ST ; CALL SELECT RET NZ ;IF ERROR THEN RETURN ; ; SET DISK FLAGS TO DATA IN SECTOR BYTE OF COMMAND BLOCK ; LD A,(CMDBLK + DDSECO) ;GET FORMAT FLAGS LD (IX + DVFLG),A ;RESET DRIVE FLAGS ; ; SEEK TRACK FROM COMMAND BLOCK ; CALL SEEK ; ; SET UP FOR COMMAND COMPLETION ; LD IY,NMIWT ;SET RETURN ADDR ; ; OUTPUT FORMAT TRACK COMMAND TO FDC ; LD A,DCWRT ;OUTPUT WRITE TRACK COMMAND TO 1791 XOR C OUT (WDCMD),A EX (SP),HL ;WAIT FOR 1791 EX (SP),HL EX (SP),HL EX (SP),HL ; ; EXECUTE CODE IN BUFFER ; JP FMTPS ; ; COMMAND DONE, RETURN FORMAT STATUS ; NMIWT: ; ; RETURN LAST GAP BYTE COUNT ; LD (CMDBLK + DDADRO),HL ; ; MASK APPLICABLE ERRORS ; AND DMFER ;SET ANY ERRORS ; ; RETURN ERROR STATUS IN COMMUNICATION BLOCK ; RETERR: OR A,A ;IF NO ERROR THEN QUIT NOW RET Z ; LD (CMDBLK + DDSTSO),A LD A,FDCERR RETFER: LD (CMDBLK + DDMODO),A RET ;-------------------------------------------------------------------- ; ; DRIVE LOG-ON COMMAND READS THE IDENTITY SECTOR FROM THE ; DISKETTE AND MAKES THE NEEDED ENTRYS INTO THE DRIVE TABLE. ; THE SECTOR DATA IS ALSO LEFT IN THE SECTOR BUFFER FOR BIOS ; TO FINISH THE LOG-ON OPERATION. ; ;-------------------------------------------------------------------- LGON: ; ; SELECT DRIVE 1ST ; CALL SELECT RET NZ ;IF DRIVE ERROR THEN RETURN ; ; SET UP TO READ DESCRIPTOR SECTOR ; XOR A ;SET TRACK=0 LD (CMDBLK + DDTRKO),A ; INC A ;SET SECTOR =1 LD (CMDBLK + DDSECO),A ; ; SEEK TRACK ; CALL SEEK ; ; READ DESCRIPTOR SECTOR INTO BUFFER ; LD HL,XBUF LD E,1 CALL RDSEC ;READ ID SECTOR ; ; CHECK FOR DESCRIPTOR ID TEXT ; LD DE,JADEID ;SET STRING PTR LD HL,XBUF + IDLBLO ;SET SECTOR BUFFER PTR TO COMPARE LD B,IDSZE ;SET ID LENGTH ; CKJI: LD A,(DE) ;IF ID NOT=JADE THEN 3740 CP (HL) JR NZ,I3740 ; INC HL ;ELSE INC PTRS INC DE DJNZ CKJI ;IF NOT DONE THEN REPEAT ; ; VALID DESCRIPTOR SECTOR FOUND, FETCH DISK PARAMETERS ; LD A,(XBUF + IDFLGO) ;SET SIDES & DENSITIES LD (IX + DVFLG),A ; ; RETURN VALID DESCRIPTOR SECTOR FLAG TO HOST ; LD A,-1 SETFFG: LD (CMDBLK + DDFFGO),A RET ; ; ASSUME 3740 FORMAT ; I3740: ; ; SET DISK PARAMETERS TO SINGLE SIDED, SINGLE DENSITY ; LD A,IDFLD ;SIDE & DENSITIES FLAGS=0 LD (IX+DVFLG),A ; ; RETURN INVALID DESCRIPTOR SECTOR TO HOST ; XOR A,A JR SETFFG ;---------------------------- ; ; READ SECTOR COMMAND ; ;---------------------------- READ: LD A,-1 ;FLAG := READ OR A JR OPCONT ;---------------------------- ; ; WRITE SECTOR COMMAND ; ;---------------------------- WRIT: XOR A ;FLAG := WRITE OPCONT: ; ; SAVE OPERATION FLAGS ; EX AF,AF' ;SAVE OP IN ALT REGS ; ; SELECT DRIVE 1ST ; CALL SELECT ;SELECT DRIVE ; ; IF NO ERRORS THEN SEEK TRACK ; CALL Z,SEEK ;SEEK TRACK ; ; IF SELECT OR SEEK ERROR THEN RETURN ; RET NZ ; ; DEFAULT READ PTR IS UNBLOCKED ; LD HL,XBUF ;DEFAULT TO UNBLOCKED ; ; FETCH SECTOR DATA ; LD A,(CMDBLK + DDSECO) LD E,A ; ; CHECK FOR DEBLOCKING ; LD A,(IX + DVFLG) ;IF SECTOR SIZE == 128 THEN SKIP BLOCKING AND 11000000B JP Z,RWSECA ; ; DEBLOCKING REQUIRED ; CALL DOBUFR ;SET UP PHYSICAL SECTOR BUFFER RET NZ ; ; IF READ THEN DOBUFR DID IT ALL ; EX AF,AF' ;IF READ THEN ALREADY IN XBUF RET NZ ; ; ELSE WRITE IT OUT ; LD D,A EX AF,AF' LD HL,SBUFR ;USE PHYSICAL SECTOR BUFFER LD A,(BSECT) LD E,A JP RWSECT SUBTTL SUBROUTINES ;************************************** ; ; INITIALIZE REGS & VARS SUBR ; ;************************************** INIT: ; ; SINGLE INTERRUPT MODE ; IM 1 ;SINGLE INTERRUPT MODE TO RST 56 ; ; TEST FOR INVERTED BUS FDC OPTION ; LD C,0 ;DEFAULT TO NON-INVERTED DATA IN A,(BLSTS) AND BSUS0 JR NZ,STOP ; ; IF INVERTED THEN SET REGISTER TO XOR DATA WITH 0FFH ; DEC C ; ; SET DRIVE TABLE POINTER TO DUMMY ; STOP: LD IX,DTDED ;SET DRIVE TABLE PTR ; ; INITIALIZE DEBLOCKING BUFFER TO INSURE 1ST READ ; XOR A ;BLOCKED BUFFER := EMPTY LD (BSECT),A LD (SVDRV),A ;BASE BLCTL BITS ; ; DONE ; RET ;******************************************************************** ; ; THIS SUBROUTINE IS RESPONSIBLE FOR SELECTING THE COMMAND ; REQUESTED DRIVE #. BEFORE DRIVE SELECTION, THE DRIVE MOTOR ; STATE IS TESTED AND IF NEEDED, THEY ARE TURNED ON. ; EXIT - IX= NEW DRIVE TABLE ; A= 0: OK, /0: ERR ; ;******************************************************************** SELECT: ; ; IF MOTOR OFF THEN START MOTOR ; IN A,(BLSTS) ;GET BOARD LEVEL STATUS AND BSMOF ;IF MOTOR ON THEN CHECK DRIVE JR Z,CKDV ; IN A,(XPMTX) ;ELSE ISSUE MOTOR START LD DE,TMMTO ;WAIT FOR A WHILE RST 8 ; ; RETRIGGER MOTOR OFF DELAY ; CKDV: IN A,(XPMTX) ;EXTEND MOTOR TIME ; ; ENABLE DRIVE SELECT ; LD A,(SVDRV) OR BCDSE OUT (BLCTL),A ; ; IF REQUESTED DRIVE = CURRENT DRIVE THEN OK AS IS ; LD A,(CMDBLK + DDDRVO) SUB (IX + DVNBR) RET Z ; ; UNLOAD HEAD ON CURRENT DRIVE ; LD E,DCHDU CALL EXHEAD ; ; DESELECT CURRENT DRIVE ; LD A,(SVDRV) ;DESELECT CURRENT DRIVE, AND [NOT BCDSE] OUT (BLCTL),A ; ; IF REQUESTED DRIVE NOT LEGAL THEN RETURN ERROR ; LD A,(CMDBLK + DDDRVO) ;FETCH REQUESTED DRIVE CP 4 JR C,SELCT1 ; LD A,SELERR JP RETFER ; ; NOW SELECT REQUESTED DRIVE ; SELCT1: OUT (BLCTL),A OR BCDSE OUT (BLCTL),A LD (SVDRV),A ; ; SELECT NEW DRIVE TABLE ; AND BCDSN LD IX,DVTBL LD DE,DVDES ;DRIVE TABLE ARRAY SIZE ; NEXT: DEC A ;IF DRIVE = 0 THEN EXIT WITH POINTER SET JP M,SLED ; ADD IX,DE ;ELSE POINT TO NEXT ARRAY & REPEAT JR NEXT ; ; IX NOW HAS DRIVE TABLE PTR ; SLED: ; ; FETCH DRIVE READY STATUS FROM FDC ; CALL EXSTS ;SET FLAGS PER DRIVE READY AND DMDNR JP RETERR ;******************************************************************** ; ; HOMED SUBROUTINE STEPS THE DISK DRIVE HEAD OUTWARD UNTIL ; TRACK 0 FLAG IS TRUE OR 255 STEPS HAVE BEEN ISSUED ; EXIT - A= 0: OK, -1: TRK 0 NOT FOUND ; ;******************************************************************** HOMED: ; ; IF NOT ALREADY ON TRACK 0 THEN SKIP RECALIBRATE ; CALL EXSTS ;IF NOT TRK 0 THEN NO RECAL AND DMTK0 JR Z,HOME1 ; ; STEP IN 10 TRACKS TO INSURE INSIDE TRACK 0 ; LD L,10 ;ELSE STEP IN BEYOND TRK 0 LD A,(SVDRV) ;SELECT 'IN' OR BCDAS OUT (BLCTL),A ; ; STEP ONCE ; RECAL1: IN A,(XPSTP) LD DE,TMSTPC RST 8 ; ; IF NOT 10 TRACKS THEN REPEAT ; DEC L JR NZ,RECAL1 ; ; NOW STEP OUT UNTIL TRACK 0 FOUND ; LD A,(SVDRV) ;RESTORE DIRECTION OUT (BLCTL),A HOME1: ; ; SET MAX TRACKS TO 255 ; LD L,255D ;SET MAX COUNT ; ; IF ON TRACK 0 THEN DONE ; STEP: CALL EXSTS ;IF ON TRACK 0 THEN EXIT AND DMTK0 JR NZ,EXIT ; ; IF > 255 TRACKS THEN RECAL ERROR ; DEC L ;IF STEPS = 255 THEN ERROR JR Z,EROR ; ; STEP ONCE ; IN A,(XPSTP) ;ISSUE STEP PULSE LD DE,TMSTPC ;SET DELAY RST 8 JR STEP ; ; DRIVE IS RESTORED, WAIT FOR SETTLING TIME ; EXIT: LD DE,TMALS ;WAIT A BIT AFTER LAST STEP RST 8 ; ; CURRENT TRACK = 0 ; LD A,0 ;SET COMPLETE FLAG LD (IX+DVTRK),A ;SET TRACK VALUE ; ; RETURN NO ERROR ; AND A ;SET RETURN FLAGS RET ; ; TRACK 0 NOT FOUND ; EROR: LD A,SEEKERR ;SET FAILURE FLAG JP RETFER ;************************************************ ; ; TRACK SEEK SUBROUTINE ; EXIT - DENSITY & PRE-COMP CONTROLS SET ; ZF= OK, NZ= ERROR ; ;************************************************ SEEK: ; ; IF HEAD NOT LOADED THEN LOAD HEAD ; CALL EXSTS ;IF HEAD ALREADY LOADED THE BYPASS AND DMHDL JR NZ,HLDD ; LD E,DCHDL CALL EXHEAD ; ; WAIT FOR HEAD SETTLING TIME ; LD DE,TMHLD RST 8 ; ; IF CURRENT TRACK = REQUESTED TRACK THEN NO SEEK REQUIRED ; HLDD: LD A,(CMDBLK + DDTRKO) SUB (IX + DVTRK) JR NZ,DSET ; ; RETURN PREVIOUS CONTROLS ; LD A,(IX + DVCTL) JR EXITS ; ; SET DIRECTION & STEP COUNT ; DSET: ; ; SAVE TRACK DIFFERENCE ; PUSH AF ; ; DELAY FOR STEP AFTER WRITE REQUIREMENT ; LD DE,TMSAW ;DELAY FOR STEP AFTER WRITE RST 8 ; ; RESTORE TRACK DIFFERENCE ; POP AF ; ; IF REQUESTED < CURRENT TRACK THEN STEP OUT ; JR C,SOUT ;CARRY=STEP OUT ; ; ELSE STEP IN ; SIN: LD L,A LD A,(SVDRV) OR BCDAS OUT (BLCTL),A JR STEPS ; ; STEP OUT REQUIRED ; SOUT: ; ; COMPUTE TRACK COUNT ; NEG ;COMPLEMENT OFFSET ; ; IF COUNT > 127 THEN HOME, MUST BE ERROR ; JP M,HOME ; ; SET UP TO STEP OUT ; LD L,A LD A,(SVDRV) OUT (BLCTL),A ; ; STEP ONCE ; STEPS: IN A,(XPSTP) LD DE,TMSTPC RST 8 ; ; IF COUNT NOT EXHAUSTED THEN REPEAT ; DEC L ;IF STEPS-1 NOT 0 THEN STEP AGAIN JR NZ,STEPS ; ; WAIT FOR SETTLING TIME ; LD DE,TMALS ;ELSE EXTEND LAST PULSE RST 8 ; ; SET UP TRACK DENSITY & PRECOMPENSATION LEVEL ACCORDING TO TRACK NUMBER ; LD E,BCSDS + BCPCL ;USE SD, PRECOMP LOW AS DEFAULTS ; ; IF TRACK 0 THEN USE DEFAULTS ; LD A,(CMDBLK + DDTRKO) ;IF TRACK 0 THEN USE DEFAULTS CP 1 JR C,CTLS ; ; IF TRACK 1 THEN DO TRACK 1 ; JR Z,TRK1 ; ; IF TRACK < 26 THEN DO OUTER VALUES ; CP 26 JR C,OUTS ; ; IF {26 < TRACK < 52} THEN DO MIDDLE VALUES ; CP 52 JR C,MIDS ; ; ELSE DO INNER VALUES ; JR INSD ; ; TRACK 1 ; TRK1: BIT DFT1DB,(IX + DVFLG) ;IF SD THEN USE DEFAULTS JR Z,CTLS ; ; USE DOUBLE DENSITY, LOW PRECOMP ; T1DD: LD E,BCDDS + BCPCL JR CTLS ; ; OUTSIDE TRACKS ; OUTS: BIT DFDTDB,(IX + DVFLG) ;IF SD THEN USE DEFAULTS JR Z,CTLS ; JR T1DD ;ELSE USE SAME AS TRACK 1 ; ; MIDDLE TRACKS ; MIDS: BIT DFDTDB,(IX + DVFLG) ;IF SD THEN USE DEFAULTS JR Z,CTLS ; ; USE DOUBLE DENSITY, MEDIUM PRECOMP ; LD E,BCDDS + BCPCM ;USE DD, MEDIUM PRECOMP JR CTLS ; ; INSIDE TRACKS ; INSD: BIT DFDTDB,(IX + DVFLG) ;IF SD THEN USE DEFAULTS JR Z,CTLS ; ; USE DOUBLE DENSITY, HIGH PRECOMP ; LD E,BCDDS + BCPCH ;SET DD, HIGH PRECOMP ; ; SET CONTROLS ; CTLS: LD A,(SVDRV) ;ADD DENSITY, PRECOMP BITS TO CONTROL BITS OR E LD (IX + DVCTL),A ; ; SET CONTROLS ; EXITS: OUT (BLCTL),A ; ; SET CURRENT TRACK ; LD A,(CMDBLK + DDTRKO) ;SET REQUESTED TRACK LD (IX + DVTRK),A XOR C OUT (WDTRK),A ;SET TRACK REGISTER ; ; RETURN NO ERRORS ; XOR A ;SET Z FLAG RET ; ; CALIBRATE TRACK # ; HOME: CALL HOMED ;HOME SELECTED DRIVE JP HLDD ;NOW SEEK TRACK ;************************************** ; ; HEAD LOAD/UNLOAD SUBROUTINES ; ENTRY - E= HEAD COMMAND ; ;************************************** EXHEAD: ; ; USE RETURN ADDRESS FOR INTERRUPT RETURN ; POP IY ;IY=RETURN ADDR ; ; PUT TRACK # INTO DATA REGISTER ; IN A,(WDTRK) ;PERFORM SEEK TO CURRENT TRACK WITH HEAD LOAD OUT (WDDTA),A ; ; OUTPUT PASSED COMMAND TO FDC ; LD A,E ;OUTPUT PASSED COMMAND XOR C OUT (WDCMD),A ; ; WAIT FOR FDC INTERRUPT ; JR $ ;WAIT FOR INTERRUPT ;************************************** ; ; GET STATUS SUBROUTINE ; EXIT - A= 1791 STATUS ; ;************************************** EXSTS: ; ; ISSUE TERMINATE FDC OPERATION & READ FDC STATUS COMMAND ; LD A,DCSTS ;OUTPUT SET STATUS COMMAND TO 1791 XOR C OUT (WDCMD),A EX (SP),HL ;PAUSE EX (SP),HL EX (SP),HL EX (SP),HL ; ; RETURN FDC STATUS ; IN A,(WDSTS) XOR C RET ;************************************************ ; ; READ SECTOR SUBR PRESETS RWOP TO READ ; ;************************************************ RDSEC: LD D,-1 JR RWSECT ;************************************** ; ; READ/WRITE SECTOR SUBR ; ENTRY- A'= 0: WRITE, /0: READ ; HL= XFER PTR ; E= SECTOR ; EXIT - NZ= ERROR ; A,HL,B= ? ; ;************************************** RWSECA: EX AF,AF' LD D,A EX AF,AF' ;******************************************************************** ; ; READ/WRITE SECTOR SUBROUTINE INITIATES DISK XFER, SEVICES THE ; CONTROLLER CHIP DURING DATA XFER, & TERMINATES OPERATION ; WHEN FINISHED. ERROR DETECTION IS IMPLEMENTED & RETRIES ARE ; EXECUTED IF DATA ERRORS ARE DETECTED. ; ENTRY - D= 0: WRITE, /0: READ ; HL= XFER PTR ; E= PHYSICAL SECTOR # (1..26) ; EXIT - NZ= ERROR ; HL, A, B= ? ; ;******************************************************************** RWSECT: XOR A ;0 ERROR COUNT LD (ERRCT),A ; ; SET FDC SECTOR REGISTER ; LD A,E XOR C OUT (WDSEC),A ; ; SET FDC INTERRUPT RETURN VECTOR ; RWRTRY: LD IY,RWNMI ;SET NMI VECTOR FOR RETURN ; ; DEFAULT TO READ COMMAND ; LD B,DCRDS ; ; IF WRITE OPERATION THEN SET WRITE COMMAND ; LD A,D ;SELECT OPERATION OR A JR NZ,OPOK ; LD B,DCWRS ;WRITE OP ; ; OUTPUT COMMAND TO FDC ; OPOK: LD A,B ;OUTPUT READ SECTOR COMMAND XOR C OUT (WDCMD),A ; ; WAIT FOR FDC TO CATCH UP ; EX (SP),HL EX (SP),HL ;WAIT FOR 1791 EX (SP),HL EX (SP),HL ; ; SELECT DIRECTION ; LD A,D ;IF WRITE OP THEN GO DO IT OR A JR Z,WROP ; ; READ DIRECTION ; RDREPT: ; ; OUTPUTTING TO THIS PORT GENERATES A CPU 'WAIT' UNTIL FDC READY ; IN A,(XPDSH) ; ; FDC READY, XFER DATA ; IN A,(WDDTA) XOR C LD (HL),A INC HL ;PTR +1 JR RDREPT ; ; OPERATION DONE, CHECK STATUS ; RWNMI: ; ; ASSUME READ ERROR MASK ; LD B,DMRER ;IF NO ERRORS THEN RETURN PUSH AF ;SAVE 179X STATUS ; ; IF WRITE OPERATION THEN USE WRITE ERROR MASK ; LD A,D ;IF WRITE OP THEN OR A JR NZ,RWMSK ; LD B,DMWER ;USE WRITE ERR MASK ; ; RETURN OPERATION STATUS ; RWMSK: POP AF ;179X STATUS AND B RET Z ; ; SAVE THIS ERROR IN CASE RETRYS EXHAUSTED ; LD B,A PUSH BC ; ; SAVE FLAG, SECTOR ; PUSH DE ;SAVE FLAG, SECTOR ; ; IF RETRYS NOT EXHAUSTED THEN RETRY ; CALL CHKRT POP DE POP BC JR Z,RWRTRY ; ; RESTORE ERROR & RETURN IT ; LD A,B JP RETERR ; ; EXECUTION OF NEXT INSTRUCTION GENERATES A WAIT CONDITION UNTIL FDC READY ; WROP: REPTW: IN A,(XPDSH) ;HOLD FOR DATA REQ ; ; OUTPUT DATA TO FDC ; LD A,(HL) XOR C OUT (WDDTA),A ; ; POINT TO NEXT DATA ; INC HL JR REPTW ;************************************** ; ; CHECK FOR RETRYS SUBROUTINE ; EXIT - A= 0: OK, /0: ERROR ; ;************************************** CHKRT: ; ; IF ERROR IS DRIVE NOT READY THEN HARD ERROR ; AND DMDNR RET NZ ; ; IF NO RETRYS ALLOWED THEN RETURN HARD ERROR ; LD A,(CMDBLK + DDFFGO) AND DDNRT RET NZ ; ; KICK MOTOR ON IN THE PANTS AGAIN ; IN A,(XPMTX) ; ; BUMP ERROR COUNT ; LD A,(ERRCT) INC A LD (ERRCT),A ; ; IF HALF OF RETRYS EXHAUSTED THEN TRY RECALIBRATE ; CP RTYSK JR NZ,CKLS ; CALL HOMED ;HOME SELECTED DRIVE CALL Z,SEEK ;RE-SEEK DESIRED TRACK RET NZ ;IF ERROR THEN EXIT ; ; IF RETRYS EXHAUSTED THEN RETURN ERROR ; CKLS: CP RTYLS JR Z,STNZ ; ; DELAY A WHILE & RETURN WITH NO ERRORS ; LD DE,TMPLD ;ELSE WAIT & RETURN WITH NO ERRORS RST 8 ; XOR A RET ; ; RETURN RETRYS EXHAUSTED (NZ) ; STNZ: INC A RET ;************************************************ ; ; DEBLOCKING BUFFER HANDLER ; ENTRY- AF'= ZF: WRITE OP, NZ: READ OP ; EXIT - NZ= ERROR ; HL, DE= ? ; ;************************************************ DOBUFR: ; ; SET UP SECTOR BUFFER ; CALL BUFOK RET NZ ; ; SET UP FOR TRANSFER ; PUSH BC LD BC,SECSIZ ;SET UP XFER LD DE,XBUF LD HL,SBUFR ;DEFAULT TO LO HALF ; ; COMPUTE LOGICAL SECTOR (0: LOW 128 BYTES, 1: HIGH 128 BYTES) ; LD A,(CMDBLK + DDSECO) DEC A ;MAKE 1..N INTO 0..N-1 SECTOR NUMBER BIT 0,A JR Z,XOK ; LD HL,SBUFR + SECSIZ ;XFER HI HALF ; ; IF READ THEN BUFFER OK ; XOK: EX AF,AF' JR NZ,NOTWRT ; ; ELSE REVERSE DIRECTION ; EX DE,HL ; ; MOVE DATA TO/FROM BUFFER ; NOTWRT: EX AF,AF' ;RESTORE FLAG LDIR ; ; RETURN NO ERROR ; POP BC XOR A RET ;************************************** ; ; CHECK FOR BUFFER OK SUBR ; EXIT - NZ= ERROR ; HL,DE,A= ? ;************************************** BUFOK: ; ; COMPUTE PHYSICAL SECTOR FROM LOGICAL SECTOR REQUESTED ; PS = ((LS - 1) / 2) + 1 ; LD A,(CMDBLK + DDSECO) DEC A SRA A INC A ; ; IF REQUESTED SECTOR IS CURRENT SECTOR THEN RETURN ; LD E,A ;SAVE FOR LATER LD A,(BSECT) CP E JR NZ,NOTSAME ; LD A,(BDISK) ;IF BUFFER NOT SAME THEN READ BUFR CP (IX + DVNBR) JR NZ,NOTSAME ; LD A,(BTRACK) CP (IX + DVTRK) RET Z ;SAME, JUST RETURN ; ; ELSE READ PROPER SECTOR INTO BUFFER ; NOTSAME: LD HL,SBUFR ;SET PTR PUSH DE ;SAVE PHYSICAL SECTOR # CALL RDSEC POP DE JR Z,BRDOK ;IF ERROR THEN CLEAR BUFFER ; ; IF READ ERROR THEN SET BUFFER CORRUPTED (SECTOR = 0 (ILLEGAL)) ; LD E,0 ; ; SET BUFFER POINTERS ; BRDOK: LD HL,BSECT LD (HL),E ;CURRENT SECTOR INC HL ;CURRENT TRACK LD A,(IX + DVTRK) LD (HL),A INC HL ;CURRENT DRIVE LD A,(IX + DVNBR) LD (HL),A RET SUBTTL DATA AREAS ;---------------------------- ; ; DISKETTE FORMAT LABEL ; ;---------------------------- JADEID: DB 'Jade DD ' ;DISKETTE ID LABLE IDSZE: EQU $-JADEID ;LABEL LENGTH ;-------------------------------------- ; ; DRIVE TABLE OFFSETS ; ;-------------------------------------- STRUCT 0 DVNBR DS 1 ;CURRENT PHYSICAL DRIVE # DVTRK DS 1 ;CURRENT PHYSICAL TRACK # DVSEC DS 1 ;CURRENT PHYSICAL SECTOR # DVFLG DS 1 ;DISK FORMAT FLAGS DVCTL DS 1 ;LAST CONTROLS USED OFFSET DVSPT0 DS 1 ;SECTORS PER TRACK 0 DVSPT1 DS 1 ;SECTORS PER TRACK 1 DVSPTD DS 1 ;SECTORS PER DATA TRACKS DVSIZE DS 0 ENDM ; ; ; DRIVE TABLES ; DVTBL: IRP #DRIVE,0,1,2,3 DB #DRIVE,255,0,DFDFL,0C4H + #DRIVE,26,48,48 ENDM ; DTDED: DB 4,255,0,0,0,0,0,0 ;DUMMY DVDES EQU DVSIZE ;-------------------------------------- ; ; COMMAND BLOCK ; THIS IS THE HOST COMMUNICATION AREA ; ;-------------------------------------- IF $ > (BANK0 + DDCBO) ?OVRLAP COMMAND BLOCK,$-BANK0+DDCBO ENDIF ORG BANK0 + DDCBO ;POSITION BLOCK CMDBLK: DB 0 ;CONTROL COMMAND DB 0 ;DRIVE # DB 0 ;TRACK # DB 0 ;SECTOR # DB 0 ;FORMAT FLAGS DB 0 ;UNASSIGNED DB 0 ;MODE SELECTS DB 0 ;CONTROLLER STATUS DW 0 ;LOAD ADDR DW 0 ;LOAD LENGTH ; SVSTS DB 0 ;1791 RAW STATUS IF $ > (BANK0 + DDBUFO) ?OVRLAP XFER BUFFER,$-BANK0+DDBUFO ENDIF ORG (BANK0 + DDBUFO) XBUF EQU $ ;DATA XFER BUFFER START SUBTTL INITIALIZATION ROUTINE ;--------------------------------------------------------------------------- ; ; THIS CODE IS ENTERED BY THE BOOT INJECTION MODULE (BIM) FROM ENTRY ; VECTOR AT DCM ADDRESS 0003H (ACTUALLY AT 0403H WHEN EXECUTED). ; IT RELOCATES THE ENTIRE DCM CURRENTLY IN BANK 1 TO BANK 0, THEN TRANSFERS ; CONTROL TO IT'S BANK 0 IMAGE WHICH THEN PROCEEDS TO INITIALIZE THE FIRMWARE ; AND LOAD THE BIOS LOADER INTO THIS BUFFER. ; ;--------------------------------------------------------------------------- INITB: ; ; WHEN BOOTED IN, THIS CODE IS IN BANK 1 SO MOVE TO BANK 0 ; LD BC,BANKL ;SET BYTE COUNT TO MOVE LD DE,BANK0 LD HL,BANK1 LDIR ;XFER DCM TO BANK 0 FROM LOAD ; ; EXECUTING THIS JUMP STARTS EXECUTING THE SAME POINT IN THE BANK 0 IMAGE ; JP DOWN ;TRANSFER TO FOLLOWING CODE NOW IN BANK 0 ALSO ; ; NOW IN BANK 0 ; DOWN: ; ; SET UP HARDWARE ; LD SP,STACK CALL INIT ; ; LOAD IN BIOS LOADER SECTOR, PUT BIOS LOADER ENTRY ON STACK SO READ WILL ;RETURN & EXECUTE IT INSTEAD OF THIS CODE. ; LD E,2 ;LOAD IN BIOS LOADER SECTOR IN A,(XPMTX) LD HL,BANK0 + DDBUFO ;SET RETURN TO EXECUTE BLT PUSH HL JP RDSEC ; IF $ > BANK1 ?OVRLAP PAST BANK 0,$-BANK0+1024 ENDIF SUBTTL UNINITIALIZED VARIABLES ORG BANK1 ;################################################ ; ; PHYSICAL SECTOR LOCATIONS FOR DEBLOCKING ; ;################################################ SBUFR DS 256 ;PHYSICAL SECTOR BUFFER ; ; ;######################################################################### ; ; NOTE: THE FOLLOWING 3 BYTES MUST APPEAR IN THIS ORDER, THEY ARE ; INDEXED BY A POINTER IN BUFOK SUBR. ; ;######################################################################### BSECT DS 1 ;CURRENT SECTOR # BTRACK DS 1 ;CURRENT SECTOR TRACK # BDISK DS 1 ;CURRENT SECTOR DISK # ; SVDRV DS 1 ;BLCTL DRIVE BITS ERRCT DS 1 ;RETRY COUNT ; DS 32 ;STACK SIZE STACK EQU $ IF $ > (BANK1 + 1024) ?OVRLAP PAST BANK 1,$-BANK1+1024 ENDIF END