Subttl -Firmware Lo-Level Disk Driver Routines (15_Aug_84) ; ; Copyright 1983, 1984 ; Morrow Designs, Inc. ; San Leandro, Ca. ; John Zalabak, Howard Fullmer ; .z80 ;Switch set to assemble z80 nemonics Include HD22DEF.MAC ;Include Global Equates ASeg Org O_Dsk2 ;See the hd*def.mac module for definition ; Index: Lo Level Disk Drivers ;----------------------------- ; ; Verify Verify track info by reading a header ; rdio Read a Sector ; wrio Write a Sector ; hdrio Read a Header ; fmtio Format a Track ; Smudge Destroy the Current Sector ; ; IIRQ Initialize Interrupt Vectors for Normal Operations ; IDB Initialize Disk Buffer Area for Normal Operation ; IFB Initialize Disk Buffer Area for Formatting ; ; HDhdr Setup Hard Disk Header Image ; HDhdrF Setup Hard Disk Header Image for Formatting ; FDhdr Setup Floppy Disk Header Image ; ; FIndex Floppy Disk Index/Time-out Interrupt Routine ; FMatch Floppy Disk Match Interrupt Routine ; HIndex Hard Disk Index/Time-out Interrupt Routine ; HMatch Hard Disk Match Interrupt Routine ; FFirq Floppy Disk Format Index/Time-out Interrupt Routine ; HFirq Hard Disk Format Index/Time-out Interrupt Routine ; GMatch Get the error code for a match interrupt ; ; CHS Compare a Header Address String in Single Density ; CHD Compare a Header Address String in Double Density ; CH Compare a Header ; ; RDS Read Data Address String in Single Density ; RDD Read Data Address String in Double Density ; RD Read a Data Field ; ; WDS Write a Data Address String in Single Density ; WDD Write a Data Address String in Double Density ; WD Write a Data Field ; ; RHS Read Header Address String in Single Density ; RHD Read Header Address String in Double Density ; RH Read a Header Field page 64 ;---------------------------------------------------------------------- ; Linkage Definitions (28_Nov_83) ;-------------------------------- ; public Verify ;Verify track info by reading a header public Rdio ;read data from the disk controller public hdrio ;Read a Header public Wrio ;write data to floppy disk controller public Fmtio ;Format a Track public Smudge ;Destroy the Current Sector public IIRQ ;Init IRQ Vectors for Normal Operations public IDB ;Init Disk Buffer for Normal Operation ; In the Hi-Level Disk Module (dsk1) external clrlat ;Clear the control strobe latch ; In the Main Module external Hdone ;Vector to the Hard disk return code external Xfrdat ;Move default IX, IY and MTABs into ram ; In the I/O Module external Mesg ;Print message pointed to by the DE external CinIY ;Console Input external CoutIY ;Console Output external outbyt ;Output accm as 2 digits of hex ; In the Bios Module external Rdhst ;Read a sector external Gdsk ;Set HL pointing to start current MTAB ;---------------------------------------------------------------------- ; Local Equates ;-------------- ; ;Hard Disk Command Masks for the Mode register (mode) $CMDRD equ 0 ;Read a Sector $CMDWRT equ 40h ;Write a Sector $CMDRDH equ 80h ;Read a Header $CMDFMT equ 0C0h ;Format a Track page ;====================================================================== ; Verify - Verify a Sector Header (12_Dec_83) ;============================================ ; 1) This routine reads a header and then verifies that the track head ; (and size if its a floppy) match the desired values. ; 2) If there was a seek error then the cylinder found is returned in ; the DE register pair. ; 3) Register Usage: ; A -> General Purpose/Returned status (0=no_error) ; DE -> Cylinder found on seek errors ; HL -> Current Cylinder (entry value not altered) ; Verify: bit @HRDDSK,(ix+dskdef0) ;If (Floppy disk) then jr z,VRFsk3 ; skip to next segment ; Test a hard disk header against the image in the IY area ;--------------------------------------------------------- ; ld a,0FFh ld (header+3),a ;Set the Head Number to 0FFh call hdrio ;Do a Read Headers Command or a ;If (error eq true) jr z,VRFsk0 ld a,(header+3) ; If (header wasn't written) cp 0FFh ld a,Eha ; (Error:= header Addr.) ret z ; Return ld a,Ehc ; Else (Error:= Header CRC) ret ; Return ;Check the track number VRFsk0: ld a,(header+1) ;If (track ne same) cp (iy+phytrk) jr nz,VRFe1 ld a,(header+2) cp (iy+phytrk+1) jr z,VRFsk1 VRFe1: ld a,(header+1) ld e,a ld a,(header+2) ld d,a ; DE:= Track found ld a,Esk ; Error:= seek error ret ; Return ;Check the Head Number VRFsk1: ld a,(header+3) ;Else If (Head number ne same) cp (iy+phyhd) jr z,VRFsk2 ld a,Ehn ; Error:= Head mismatch ret ; Return VRFsk2: ld a,0 ;Else Error:= NONE ret ; Return page ; Test a floppy disk header against the image in the IY area ;----------------------------------------------------------- ; VRFsk3: ld a,0FFh ld (header+3),a ;Set the Sector Size to 0FFh call hdrio ;Do a Read Headers Command or a ;If (error eq true) jr z,VRFsk4 ; Return ld a,(header+3) ; If (header wasn't written) cp 0FFh ld a,Eha ; (Error:= Header Addr ret z ; Return ld a,Ehc ; Else (Error:= Header CRC) ret ; Return ;Check the track number VRFsk4: ld a,(header) ;If (track ne same) cp (iy+phytrk) jr z,VRFsk5 ld a,(header) ld e,a ld d,0 ; DE:= Track Number Read ld a,Esk ; Error:= seek error ret ; Return ;Check the head number VRFsk5: ld a,(header+1) ;Else If (Head number ne same) cp (iy+phyhd) jr z,VRFsk6 ld a,Ehn ; Error:= Head Mismatch ret ; Return ;Check the sector size code VRFsk6: push bc ;Else ld a,(header+3) ; (skip the sector) ld b,a ; If (size mask doesn't match) ld a,(ix+dskdef1) and $SIZMSK xor b pop bc ret z ; (note: accm = 0) ld a,Ess ; Error:= Size mismatch ret ; Return page ;====================================================================== ; RDIO - Read a Sector ;===================== ; Rdio: ld a,0 ld (error),a ;Reset the error register bit @HRDDSK,(ix+dskdef0) jp z,Rsk2 ;If (Drive is Hard_Disk) ; Read a Sector from a Hard Sectored Disk (22_Dec_83) ;---------------------------------------------------- ; call HDhdr ; Setup Normal hard disk image ld a,(cpymod) and $PRECMP ;(remove all but pre-compensation bit) or $MFM or $STD or $CMDRD out (mode),a ;Initialize the mode register ld a,(iy+cpybnk) or $AUTOE out (bnkstb),a ;Set Auto_Enable ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $RAM out (ctlstb),a ;Initialize the control strobe (latch) ld hl,hngloc ;HL:= PCHL hang location ld b,3 ;B:= # of revs before failure ld c,20h ;C:= # of 32 byte blocks push IX push IY ld IX,dskbuf ; IX:= Start of Data Buffer ld IY,Rreent ; IY:= Re:entry Vector ei jp prebuf ; read the sector Rreent: di ; (vectored from loc 40h) pop IY pop IX ld a,b ; If (revs count ne 0) or a jr z,RdskH1 ; (error set by IRQ) ld a,0 ld (error),a ; Reset error location RdskH1: call clrlat ; Clear Auto_Enable ld a,(postbuf) ld (postbuf-2),a ; Move last two bytes into buffer ld a,(postbuf+1) ld (postbuf-1),a ld a,(error) ; A:= Error Status ret ; Return page ; Read a Sector from a floppy disk (20_Dec_83) ;--------------------------------------------- ; Rsk2: call FDhdr ;Else Setup for floppy transfer push ix ; Save the IX register ld ix,Rint ; Set IX for interrupts ld a,3 ld (revs),a ; Initialize revs Rint: ld hl,header ; HL:= Start of the header image ld a,(cpymod) out (mode),a ; Set the mode byte and $MFM ; If (drive is DOUBLE DENSITY) jr z,RskS1 call CHD ; Compare Header D.D or a ; If (error eq false) jr nz,Rdon ld b,0D9h Rlp1: djnz Rlp1 ; wait @ 700us ld hl,dskbuf ; HL:= Dskbuf call RDD ; Read Data jr Rdon ; Return RskS1: call CHS ; Else Compare Header S.D. or a ; If (error eq false) jr nz,Rdon ld b,0D9h Rlp2: djnz Rlp2 ; wait @ 700us ld hl,dskbuf ; HL:= Dskbuf call RDS ; Read Data Rdon: pop ix push af call clrlat ; Reset the control latch pop af ret page ;====================================================================== ; WRIO - Write a Sector ;====================== ; Wrio: ld a,0 ld (error),a ;Reset the error register bit @HRDDSK,(ix+dskdef0) jp z,Wsk2 ;If (Drive is Hard_Disk) ; Write to the Hard Disk (22_Dec_83) ;----------------------------------- ; call HDhdr ; Setup Normal hard disk image ld a,(postbuf-1) ld (postbuf),a ; last byte to end of buffer ld a,(cpymod) and $PRECMP ;(remove all but pre-compensation bit) or $MFM or $STD or $CMDWRT out (mode),a ;Initialize the mode register ld a,(iy+cpybnk) or $AUTOE out (bnkstb),a ; Set Auto_Enable ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $RAM out (ctlstb),a ; Initialize control strobe (latch) ld hl,hngloc ; HL:= PCHL hang location ld b,3 ; B:= # of revs before failure ld c,20h ; C:= # of 32 byte blocks push IY ld IY,Wreent ; IY:= Re:entry Vector ei jp prebuf ; Write the sector Wreent: di ; (Vectored from location 40h) pop IY ld a,b ; If (the revs count is non-zero) or a jr z,WrskH1 ; (error set by IRQ) ld a,0 ld (error),a ; Reset error location WrskH1: call clrlat ; Clear Auto_Enable in a,(drvsts) ; If (Write_Fault eq true) and $FAULT ld a,Ewf ; Error:= Write fault jr nz,WskH2 ld a,(error) ; Else Error:= returned error WskH2: ret ; Return page ; Write to a floppy disk (30_Dec_83) ;----------------------------------- ; Wsk2: in a,(drvsts) and $WPROT ;If (Write Protect eq true) ld a,Ewp ; (Error:= Write Protect) ret nz ; (Return) call FDhdr ;Else (setup for floppy transfer) push ix ; Save the IX register ld ix,Wint ; Set IX for interrupts ld a,3 ld (revs),a ; Initialize revs Wint: ld hl,header ; HL:= Header ld a,(cpymod) out (mode),a ; Set the mode byte and $MFM ; If (drive is DOUBLE DENSITY) jr z,WskF2 call CHD ; Compare Header or a ; If (error eq false) ld hl,dskbuf ; HL:= Dskbuf call z,WDD ; Write Data jr Wdon ; Return WskF2: call CHS ; Else Compare Header or a ; If (error eq false) ld hl,dskbuf ; HL:= Dskbuf call z,WDS ; Write Data Wdon: pop ix push af call clrlat ; Reset the control latch pop af ret page ;====================================================================== ; HDRIO - Read a Header ;====================== ; Hdrio: ld a,0 ld (error),a ;Reset the error register bit @HRDDSK,(ix+dskdef0) jp z,Hdsk1 ;If (Drive is Hard_Disk) ; Read a Header from a Hard Sectored Disk (22_Dec_83) ;---------------------------------------------------- ; ld a,(cpymod) and $PRECMP ;(remove all but pre-compensation bit) or $MFM or $STD or $CMDRDH out (mode),a ;Initialize the mode register ld a,(iy+cpybnk) or $AUTOE out (bnkstb),a ;Set Auto_Enable ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $RAM out (ctlstb),a ;Initialize the control strobe (latch) ld hl,hngloc ;HL:= PCHL hang location ld b,3 ;B:= # of revs before failure push IY ld IY,HdentH ; IY:= Re:entry Vector ei jp prebuf ; read the sector HdentH: di ; (vectored from loc 40h) pop IY ld a,b ; If (the revs count is non-zero) or a jr z,HdskH1 ; (error set by IRQ) ld a,0 ld (error),a ; Reset error location HdskH1: call clrlat ; Clear Auto_Enable ld a,(error) ret ; Return page ; Floppy Disk Read Header Routine (20_Dec_83) ;-------------------------------------------- ; Hdsk1: push ix ; Save the IX register ld ix,Hint ; Set IX for interrupts ld a,3 ld (revs),a ; Initialize revs Hint: ld hl,header ; HL:= Header ld a,(cpymod) out (mode),a ; Set the mode byte and $MFM ; If (drive is DOUBLE DENSITY) jr z,HskS1 call RHD ; Read Header (double density) jr Hdon HskS1: call RHS ; Else Read Header (single density) Hdon: pop ix push af call clrlat ; Reset the control latch pop af ret page ;====================================================================== ; FMTIO - Format a Track ;======================= ; 1) This routine formats one track ; Fmtio: ld a,0 ld (error),a ;Reset the error register bit @HRDDSK,(ix+dskdef0) jp z,Fmsk2 ;If (Drive is Hard_Disk) ; Format a Hard Disk (22_Dec_83) ;------------------------------- ; call IFB ; Setup pre/post buffer area call HDhdrF ; Setup Format hard disk image ld a,(cpymod) and $PRECMP ;(remove all but pre-compensation bit) or $MFM or $STD or $CMDFMT out (mode),a ;Initialize the mode register ld a,(iy+cpybnk) or $AUTOE out (bnkstb),a ;Set Auto_Enable ld a,$WRITE or $INTE or $RAM out (ctlstb),a ;Initialize the control strobe (latch) ld hl,HFirq1 ld (HDIvct),hl ; Set Index Interrupt Vector to Format push IY ld IY,Fmeent ; IY:= Re:entry Vector ld a,(gap3) ld h,a ; H:= Gap-3 size ld l,20h ; L:= Sector Size/32 ld c,9 ; C:= Number of sectors ld b,2 ; B:= Revs ei jp prebuf ; Write the sector Fmeent: di ; (Vectored from location 40h) pop IY call clrlat ; clear the state latch call IIRQ ; Restore the interrupt vectors call IDB ; Restore the pre/post Buffer area ld a,(error) ; Flag:= No Error ret page ; Floppy Disk Format (21_Jan_84) ;------------------------------- ; Fmsk2: in a,(drvsts) and $WPROT ;If (Write Protect eq true) ld a,Ewp ; (Error:= Write Protect) ret nz ; (Return) call FDhdr ;Else (setup for floppy disk format) ld a,2 ld (revs),a ; Initialize revs ld hl,FFirq ld (FDIvct),hl ; Set Index Interrupt Vector ld hl,FDstbl ld e,(iy+physpt) ; E:= Sectors/Track ld d,0 add hl,de ; HL:= top of sector skew table ld (savehl),hl ; (Save the HL register pair) ld a,(ix+dskdef1) and $SIZMSK ld c,a ; C:= Sector Size ld a,(cpymod) out (mode),a ; Set the mode byte ; and $MFM ; (No Single Density for Now) push ix ; Save the IX register ld ix,FFgo ; Set IX for interrupts call FDD ; Format a track in double density pop ix push af ; (Save the error code) call clrlat ; Reset the control latch call IIRQ ; Reset Floppy Index Interrupt pop af ret page ;====================================================================== ; SMUDGE - Destroy the current cylinder (16_Dec_83) ;================================================== ; 1) This routine sumdges (i.e. destroys) the current sector by ; Re:Writing the first 32 bytes into the middle of the sector. ; 2) Notice that the Floppy disk index interrupt is used instead of ; the hard disk interrupt as you would expect. Unless Auto is ; enabled all interrupts go through the floppy vectors. ; 3) All timing is done from the physical index hole. Make the ; assumptions: ; Sector Size 1024 bytes ; Sector overhead 44 bytes ; Gap 3 64 bytes ; Sectors/track 9 ; Speed tolerance 2% (+/-) ; Then: ; Jitter per Sector 23 bytes (+/-) ; Jitter 9 Sectors 207 bytes (+/-) ; Worst case offset 414 bytes (formatted 2% fast; read 2% slow) ; 3) Register Usage: ; A -> General Purpose ; B -> Number of sectors to delay ; DE -> Save Location for the Index IRQ Vector and Offsets ; HL -> Pointer and Delay Count ; ;Setup to Find the sector in the skew table Smudge: ld hl,HDstbl ;HL:= Pointer to base of skew table ld e,(iy+physpt) ld d,0 ;DE:= Length of table add hl,de ;HL:= Top of table + 1 ld b,e ;B:= Number of physical sectors/track ld a,(iy+physec) ;A:= current sector ;Find the sector in the skew table smglp1: dec hl ;Loop Pointer:= Pointer - 1 cp (hl) ; If (sector eq table entry) jr z,smgsk1 ; break djnz smglp1 ; If (sector isn't in the table) ld a,Esn ; Error:= Sector number ret ; Return ;Setup to Sync on the Index smgsk1: ld de,(FDIvct) ;DE:= Original Interrupt Vector ld hl,SmgE1 ld (FDIvct),hl ;Index_IRQ:= smudge Re:Entry 1 ld a,$INTE out (ctlstb),a ;Set the Enable Interrupt line ld a,(cpydrv) out (drvstb),a ;Select the drive ;Sync on the Index ei ;Enable Interrupts ld hl,0A10h ;Counter:= 16.7ms smglp2: dec hl ;Repeat ld a,h ; Counter:= Counter - 1 or l jr nz,smglp2 ;Until (counter eq 0) page ;Index NOT Found (return time-out Error) di ;Disable Interrupts ld (FDIvct),de ;Restore index interrupt vector ld a,0 out (drvstb),a ;DeSelect the drive call clrlat ;Clear the control latch ld a,Enr ;Error:= Not Ready ret ;Return ;Interrupt Vector Entry SmgE1: di ;Disable Interrupts pop af ;Pull the interrupt address in a,(clrint) ;Clear any pending interrupts ld (FDIvct),de ;Restore index interrupt vector in a,(cstat) ;If (this was a motor time-out) and $MTR ld a,Eto ; Error:= Motor Time-Out ret z ; Return ;Delay until the middle of the sector (adjust for setup overhead) ld hl,7Eh ;Counter:= 512 bytes smglp3: dec hl ;Repeat ld a,h ; Counter:= Counter - 1 or l jr nz,smglp3 ;Until (counter eq 0) ;Delay N Sectors ld a,(iy+physpt) ;A:= Physical Sector/Track sub b ;B:= Sectors until the end of the track jr z,Smgsk2 ;If (this isn't the desired sector) ld b,a ; B:= Sectors from the index Smglp4: ld hl,116h ; Repeat Cnt:= 1132 bytes smglp5: dec hl ; Repeat ld a,h ; Cnt:=Cnt - 1 or l jr nz,smglp5 ; Until (Cnt eq 0) djnz Smglp4 ; Until (counter eq 0) ;Smudge the Sector smgsk2: ld a,(cpymod) and $PRECMP ;(remove all but pre-compensation bit) or $MFM or $STD or $CMDWRT out (mode),a ;Initialize the mode register ld a,(iy+cpybnk) or $AUTOE out (bnkstb),a ; Set Auto_Enable ld a,$WRITE or $RAM or $_CRC or $INTE out (ctlstb),a ;Reset the control strobe ld hl,hngloc ; HL:= PCHL hang location ld b,3 ; B:= # of revs before failure ld c,1 ;Blocks:= 1 (write 32 bytes) push iy ld iy,SmgE2 ;IY:= Re:Entry Point ei ;Enable Interrupts jp dskbuf ;Smudge the sector SmgE2: di ;Disable interrupts pop iy call clrlat ;Clear Auto-Enable ld a,0 ;A:= No Error ret ;Return page ;====================================================================== ; IIRQ - Initialize Interrupt Vectors for Normal Operations (25_Oct_83) ;====================================================================== ; IIRQ: im 2 ;Set interrupt mode 2 ld a,HIGH IRQbase ld i,a ;Put interrupt vectors at top of memory ld hl,FIndex ld (FDIvct),hl ;Floppy Disk Index Interrupt Vector ld hl,FMatch ld (FDMvct),hl ;Floppy Disk Match Interrupt Vector ld hl,HIndex ld (HDIvct),hl ;Hard Disk Index Interrupt Vector ld hl,HMatch ld (HDMvct),hl ;Hard Disk Match Interrupt Vector ret ;====================================================================== ; IDB - Initialize Disk Buffer Area for Normal Operation (7_Sept_83) ;=================================================================== ; ; Initialize Disk Pre-Buffer Area (dskbuf-20h->dskbuf-1) IDB: ld hl,prebuf ;HL:= Pointer to start of area ld b,20h ;B:= Max_Count IDBlp1: ld (hl),0 ;Repeat Buffer:= 0 inc hl ; Pointer:= Pointer + 1 djnz IDBlp1 ;Until (Count eq 0) ;Move Sync byte strings (A1,FE & A1,F8) into Disk Pre-Buffer Area ld hl,0FEA1h ld (hdID1),hl ;Init Header Sync byte and ID byte ld hl,0F8A1h ld (hdID2),hl ;Init Data Sync byte and ID byte ld (hdID3),hl ;Init Data Sync byte and ID byte ; Initialize Disk Post-Buffer Area and Scratch Area (postbuf->postbuf+30) ld hl,postbuf ;HL:= Pointer to start of area ld b,30h ;B:= Max_Count IDBlp2: ld (hl),0 ;Repeat Buffer:= 0 inc hl ; Pointer:= Pointer + 1 djnz IDBlp2 ;Until (Count eq 0) ret page ;---------------------------------------------------------------------- ; IFB - Initialize Disk Buffer Area for Formatting (7_Sept_83) ;------------------------------------------------------------- ; ; Initialize Disk Pre-Buffer Area & Data Field (dskbuf-20h->dskbuf+1Fh) IFB: ld hl,prebuf ;HL:= Pointer to start of area ld b,40h ;B:= Max_Count IFBlp1: ld (hl),0 ;Repeat Buffer:= 0 inc hl ; Pointer:= Pointer + 1 djnz IFBlp1 ;Until (Count eq 0) ;Move the Sync byte strings (A1,FE & A1,F8) into the pre-buffer area ld hl,0FEA1h ld (prebuf+15h),hl ;Init Header Sync byte and ID byte ld hl,0F8A1h ld (dskbuf+1),hl ;Init Data Sync byte and ID byte ld hl,prebuf+9h ;Pre-Buffer 4E fill ld b,4 IFBlp2: ld (hl),4Eh inc hl djnz IFBlp2 ld hl,dskbuf+3 ;Data Field Fill ld b,16h IFBlp4: ld (hl),0E5h inc hl djnz IFBlp4 ;Initialize Disk Post-Buffer Area & Scratch Area (postbuf->postbuf+20h) ld hl,postbuf ;HL:= Pointer to start of area ld b,20h ;B:= Max_Count IFBlp3: ld (hl),0 ;Repeat Buffer:= 0 inc hl ; Pointer:= Pointer + 1 djnz IFBlp3 ;Until (Count eq 0) ;Initialize the Sector Table ld de,postbuf+1 ;DE:= Start Format sector table ld hl,HDstbl ;HL:= Start system hard disk skew table ld bc,9 ;BC:= Sectors Per track ldir ;Move the sector table into place ld hl,postbuf+12h ;Post Buffer 4E fill ld b,0Bh IFBlp5: ld (hl),4Eh inc hl djnz IFBlp5 ret page ;---------------------------------------------------------------------- ; HDHDR - Setup Hard Disk Header Image (13_Oct_83) ;------------------------------------------------- ; 1) This routine places the track and head number in the proper ; place for a Normal Read/Write operation ; HDhdr: ld a,(iy+PHYTRK) ld (header),a ld a,(iy+PHYTRK+1) ld (header+1),a ;Install the Cylinder ld a,(iy+PHYHD) ld (header+2),a ;Install the Head Number ld a,(iy+PHYSEC) ld (header+3),a ;Install the Sector Number ret ;---------------------------------------------------------------------- ; HDHDRF - Setup Hard Disk Header Image for Formatting (13_Oct_83) ;----------------------------------------------------------------- ; 1) This routine places the track and head number in the proper ; place for a format operation ; HDhdrF: ld a,(iy+PHYTRK) ld (header+13h),a ld a,(iy+PHYTRK+1) ld (header+14h),a ;Install the Cylinder ld a,(iy+PHYHD) ld (header+15h),a ;Install the Head Number ret ;---------------------------------------------------------------------- ; FDHDR - Setup Floppy Disk Header Image (13_Oct_83) ;--------------------------------------------------- ; FDhdr: ; Setup the Sector Header Image ld a,(iy+PHYTRK) ;Install the Cylinder ld (header),a ld a,(iy+PHYHD) ld (header+1),a ;Install the Head Number ld a,(iy+PHYSEC) ld (header+2),a ;Install the Sector Number ld a,(ix+dskdef1) ;A:= dskdef1 and $SIZMSK ld (header+3),a ;Install the sector length code ret page ;---------------------------------------------------------------------- ; FINDEX - Floppy Disk Index/Time-out Interrupt Routine (20_Dec_83) ;------------------------------------------------------------------ ; 1) This routine is entered due to any floppy disk Index or Motor ; Time-Out Interrupt. ; 2) If either the revolution count has been exhausted or a motor time- ; out is detected then and error return is made. ; 3) If revs has been decremented to zero then the value of (error) is ; checked. If (error) is non-zero then an unreadable media error (Eum) ; is returned. ; FIndex: pop de ;Pull the IRQ address from the stack call clrlat ;Reset latch and Clear any pending interrupts in a,(cstat) ;If (the motor has timed out) and $MTR ld a,Eto ; load motor-time-out failure jr z,FIsk2 ; GOTO Error Return ld a,(revs) ;Else dec a ; Rev-counter:= Rev-counter - 1 ld (revs),a ; If (revs counter NE 0) jr z,FIsk1 pop de ; Pull subroutine call from stack jp (ix) ; Restart at main line rdio/wrio FIsk1: ld a,(error) ;If (the error code hasn't been set yet) or a jr nz,FIsk2 ld a,Eum ; Error:= Unreadable Media FIsk2: ret ;Return to the calling routine ;---------------------------------------------------------------------- ; FMATCH - Floppy Disk Match Interrupt Routine (7_Nov_83) ;-------------------------------------------------------- ; 1) This routine is entered due to any floppy disk match interrupt. ; The control strobe is reset and pending interrupts are cleared ; (by clrlat routine). Then the source of the match interrupt is ; roughly determined in GMatch. Finally, the interrupt and initial ; subroutine return address are removed from the stack before ; returning to the register setup routine in rdio/wrio/hdrio. ; FMatch: call clrlat ;Reset latch and Clear any pending interrupts ex de,hl ;Move the pointer into the de pair call GMatch ;Determine the cause of the failure pop de ;Pull the interrupt address off of the stack pop de ;Pull the subroutine call off of the stack jp (ix) ;return to the interrupted routine page ;---------------------------------------------------------------------- ; HINDEX - Hard Disk Index/Time-out Interrupt Routine (8_Jun_84) ;--------------------------------------------------------------- ; HIndex: pop de ;Pull the return address off of the stack in a,(clrint) ;Clear the Interrupts in a,(cstat) ;If (the motor has timed out) and $MTR ld a,Eto ; load motor-time-out failure jr z,HIFsk2 ; GOTO Error Return ;Enter Here if the Match IRQ detected an index hole HImtch: res @Index,b ;Else Clear the Index Not Processed Bit dec b ; Revs_Count:= Revs_Count - 1 jp z,HIFsk1 ; If (the revs count is NOT zero) ld c,20h ; C:= Number 32 byte blocks/sector ld hl,hngloc ; HL:= reset to hang location ei ; Re:enable the interrupts jp prebuf ; Try Again HIFsk1: ld a,(error) ;If (error code hasn't been setup) or a jr nz,HIFsk2 ld a,Eum ; Error:= Unreadable Media HIFsk2: ld (error),a ;Update the error count ld b,0 ;Set Revs Counter to zero for error handeling jp Hdone ;Goto return location ;---------------------------------------------------------------------- ; HMATCH - Hard Disk Match Interrupt Routine (8_Jun_84) ;------------------------------------------------------ ; HMatch: pop de ;Pull the IRQ address from the stack in a,(ClrInt) ;Clear the Interrupts in a,(DrvSts) bit @Index,a ;If (Index Pulse is active) jr z,HMsk1 bit @Index,b ; If (the Index has Not been Processed) jr nz,HImtch ; Goto HINDEX (-> HImtch entry) jp c,PreBuf ; If (header not found yet) Goto PreBuf jr HMsk2 HMsk1: set @Index,b ;Else Set the Index Not Processed bit jp c,PreBuf ; If (header not found yet) Goto PreBuf HMsk2: call GMatch ;determine the error ld c,20h ;C:= Number of 32 byte blocks to load ld hl,HngLoc ;HL:= reset to the hang location jp PreBuf ;Go try again page ;---------------------------------------------------------------------- ; FFIRQ - Floppy Disk Format Index/Time-out IRQ Routine (16_Feb_84) ;------------------------------------------------------------------ ; 1) Notice that the read of cstat also clears any pending ; interrupts. ; FFirq: inc sp inc sp ;Pull the IRQ address from the stack in a,(clrint) ;Clear pending interrupt in a,(cstat) ;If (the motor has timed out) and $MTR ld a,Eto ; Error:= Motor Time Out jr z,FFdon ; GOTO Error Return ld a,(revs) ;Else dec a ; Rev-counter:= Rev-counter - 1 ld (revs),a ; If (rev-counter NE 0) jr z,FFdon ei ; Enable interrupts jp (ix) ; Start formatting FFdon: push af ;(Save the Returned Error Code) call clrlat ;Reset the latch pop af ret ;Return to the calling routine ;---------------------------------------------------------------------- ; HFIRQ - Hard Disk Format Index/Time-out Interrupt Routine (15_Aug_84) ;---------------------------------------------------------------------- ; HFirq1: inc sp inc sp ;Pull the return address off of the stack in a,(clrint) ;Clear the Interrupts in a,(cstat) ;If (the motor has timed out) and $MTR ld a,Eto ; load motor-time-out failure jr z,HFsk1 HFsk1: dec b ;Else Revs_Count:= Revs_Count - 1 jr z,HFsk3 ; If (the revs count is NOT zero) push hl ld hl,HFirq2 ld (HDIvct),hl ; Index_Irq_Vect:= Format entry 2 pop hl ei ; Re:enable the interrupts jp prebuf ; Wait for Second Interrupt HFsk2: ld (error),a ;Update the error code Hfsk3: jp Hdone ;Goto return location HFirq2: in a,(clrint) ;Clear the Interrupts ei ;Enable Interrupts jp nz,PreBuf+7 ;If (1st Entry Here) Begin Formatting pop de ;Pull 1st Irq Return from stack pop de ; " 2nd " " " " jp Hdone ;Return to calling routine page ;---------------------------------------------------------------------- ; GMatch - Get the source of a Match Error (15_Feb_84) ;----------------------------------------------------- ; 1) This routine is used by both the hard and floppy disk match ; interrupt routines to identify the source of a match interrupt ; error as being a data-crc, data-address or header error. ; 2) The DE register pair should point to the location in the buffer ; at which the match error occured. ; GMatch: ld a,HIGH prebuf ;If (error is in the pre-buffer) cp d jr c,GMsk1 ld a,e ; If (error is in header) cp LOW prebuf+0Ah ld a,Ehd ; Error:= Header jr c,GMsk3 ld a,Eda ; Else Error:= Data Address jr GMsk3 GMsk1: ld a,HIGH dskbuf ;Else If (Error is in start of dskbuf) cp d jr nz,GMsk2 ld a,e ; If (Error eq start of dskbuf) cp LOW dskbuf+0Ah ld a,Eda ; Error:= Data Address jr nc,GMsk3 GMsk2: ld a,Edc ; Else Error:= Data CRC GMsk3: ld (error),a ret page ;---------------------------------------------------------------------- ; CHS - Compare a Header Address String in Single Density (18_Jan_84) ;-------------------------------------------------------------------- ; 1) Register Usage ; A -> General purpose ; DE -> Time_Out Limit ; CHS: ld de,56CEh ;Time_Out:= 300ms in a,(rdshfH) ;find a byte boundry ld a,$READ or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,0FEh out (wrtshf),a ;Data:= initial value to compare ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $RAM out (ctlstb),a ;Set Latch ei CHSlp1: in a,(drvsts) ;Repeat and $CRCSET ; If (Read Sync Attained) jp z,CH ; Goto Compare a header dec de ; Counter:= Counter - 1 ld a,e or d jr nz,CHSlp1 ;Until (Counter eq 0) di ;Disable Interrupts ld a,Enf ;Error:= Not Found ret page ;---------------------------------------------------------------------- ; CHD - Compare a Header Address String in Double Density (18_Jan_84) ;-------------------------------------------------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Time_Out Limit Lo Byte ; C -> Time_Out Limit Hi Byte ; D -> Mask for Sync Attained Bit ; CHD: ld b,0 ld c,72h ;BC:= Time_Out Limit @300ms ld d,$CRCSET ;D:= Mask for Sync Attained bit in a,(rdshfH) ;Dummy read to sync ld a,$READ or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,0A1h out (wrtshf),a ;Data:= initial value to compare ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $RAM out (ctlstb),a ;Set Latch ei CHDlp1: in a,(Drvsts) ;Loop If (Read Sync Attained) and d jp z,CHDsk1 ; Break djnz CHDlp1 ; If (Time_Out Lo Byte eq 0) in a,(Drvsts) ; If (Read Sync Attained) and d jp z,CHDsk1 ; Break dec e ; Else If (Time_Out Hi Byte eq 0) jr z,CHDerr ; Goto Error in a,(Drvsts) ; If (Read Sync Attained) and d jr nz,CHDlp1 ; Break CHDsk1: ld a,0A1h out (wrtshf),a ;Compare second A1 ld a,0A1h out (wrtshf),a ;Compare the third A1 ld a,$READ or $CMPR or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,0FEh out (wrtshf),a ;Compare the ID byte jp CH CHDerr: di ;Disable Interrupts ld a,Enf ;Error:= Not Found ret ;Return page ;---------------------------------------------------------------------- ; CH - Compare a Header (20_Dec_83) ;---------------------------------- ; 1) This segment reads and compares a floppy disk header consisting ; of track, sector, side, size, CRC, CRC. ; 2) Notice that the HL pair is initially pointer to the start of the ; header image - 1. This makes it possible to tell the difference ; between an ID address mark failure and a track value failure. ; 3) Register Usage: ; A -> General Purpose ; B -> Counter (3 = number of bytes to compare in header - 1) ; C -> Pointer to Write-and-hang I/O Port ; HL -> Pointer to start of Header Image ; CH: ld a,$READ or $CMPR or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch ld b,3 ;B:= Number of bytes to compare ld c,wrtshf ;C:= Write Shift Register port ;Compare the Track, side, Sector and Size CHlp1: outi ;While (byte-count ne 0) nop ; (Pad for Refresh) nop ; (Pad for Refresh) jr nz,CHlp1 ld a,$READ or $CMPR or $_CRC or $INTE or $CRC out (ctlstb),a ;Set Latch for CRC bytes ld a,(hl) out (c),a ;Compare last byte (size) of the header nop nop ;Compare the CRC bytes out (c),a ;Check the first CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$READ or $CMPR or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch setup the latch for the last read out (c),a ;Check the second CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$READ or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch in a,(rdshfH) ;Do one last read ld a,0 out (ctlstb),a ;Latch:= Clear ret page ;---------------------------------------------------------------------- ; RDS - Read Data Sync String in Single Density (18_Jan_84) ;---------------------------------------------------------- ; 1) Register Usage: ; A -> General Purpose ; DE -> Time_Out Limit ; RDS: ld de,56CEh ;Time_Out:= 300ms in a,(rdshfH) ;Dummy read to sync ld a,$READ or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,0FBh out (wrtshf),a ;Data:= initial value to compare ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $SR out (ctlstb),a ;Set Latch ei RDSlp1: in a,(drvsts) ;Repeat and $CRCSET ; If (Read Sync Attained) jp z,RD ; Goto Read a Data Field dec de ; Counter:= Counter - 1 ld a,e or d jr nz,RDSlp1 ;Until (Counter eq 0) di ;Disable Interrupts ld a,Enf ;Error:= Not Found ret page ;---------------------------------------------------------------------- ; RDD - Read Data Sync String in Double Density (18_Jan_84) ;---------------------------------------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Time_Out Limit Lo Byte ; C -> Time_Out Limit Hi Byte ; D -> Mask for Sync Attained Bit ; RDD: ld b,0 ld c,72h ;BC:= Time_Out Limit @300ms ld d,$CRCSET ;D:= Mask for Sync Attained bit in a,(rdshfH) ;Dummy read to sync ld a,$READ or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,0A1h out (wrtshf),a ;Data:= initial value to compare ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $RAM out (ctlstb),a ;Set Latch ei RDDlp1: in a,(Drvsts) ;Loop If (Read Sync Attained) and d jp z,RDDsk1 ; Break djnz RDDlp1 ; If (Time_Out Lo Byte eq 0) in a,(Drvsts) ; If (Read Sync Attained) and d jp z,RDDsk1 ; Break dec e ; Else If (Time_Out Hi Byte eq 0) jr z,RDDerr ; Goto Error in a,(Drvsts) ; If (Read Sync Attained) and d jr nz,RDDlp1 ; Break RDDsk1: ld a,0A1h out (wrtshf),a ;Compare second A1 ld a,0A1h out (wrtshf),a ;Compare the third A1 ld a,$READ or $CMPR or $_CRC or $INTE or $SR out (ctlstb),a ;Set Latch ld a,0FBh out (wrtshf),a ;Compare the ID byte jp RD RDDerr: di ;Disable Interrupts ld a,Enf ;Error:= Not Found ret ;Return page ds ($ and 1) + 2,0 ; Make sure this falls on even byte boundry ;---------------------------------------------------------------------- ; RD - Read a Data Field (20_Dec_83) ;----------------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Counter - Number of bytes in one block ; C -> Pointer to Read-and-Hang I/O Port ; D -> Number of Blocks per sector - 1 ; HL -> Pointer to the start of the data buffer - 1 ; RD: ld a,$READ or $_CRC or $INTE or $SR out (ctlstb),a ;Set Latch ld b,31 ;B:= Number of bytes/block - 1 ld c,rdshfH ;C:= Read and Hang I/O Port ld a,(blocks) ld d,a ;D:= Number of blocks/sector - 1 in a,(rdshfH) ;Do a dummy read to clear the shift register ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] nop RDlp1: ini ;Repeat read a byte ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] jr nz,RDlp1 ; If (not the last byte of the block) ld b,32 ; Else 32-byte-counter:= reset nop ini ;Repeat read a byte ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] dec d ; block_count:= block_count - 1 jr nz,RDlp1 ;Until (block count eq 0) dec b ;Count:= last block minus 2 nop ; [for fixing read sync] RDlp2: ini ;Repeat read a byte ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] jr nz,RDlp2 ; If (not the last byte of the block) ld a,$READ or $_CRC or $INTE or $CRC out (ctlstb),a ;Set Latch for CRC generation nop ini ;Read the Second to the last byte of the sector ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] ld a,$READ or $CMPR or $_CRC or $INTE or $CRC out (ctlstb),a ;Set Latch for final read nop ini ;Read the last byte of the sector ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] ld a,$READ or $CMPR or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch for final read out (c),a ;Check the first CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$READ or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch for final read out (c),a ;Check the second CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$RAM out (ctlstb),a ;Latch:= Clear in a,(c) ;Do one last read di ld a,0 ;Load No_Error Returned status ret page ;---------------------------------------------------------------------- ; WDS - Write a Data Field Sync String in Single Density (20_Dec_83) ;------------------------------------------------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Counter for number of zeros to write ; WDS: ld b,9 ;B:= Counter (Gap2 length - 2) ld c,RdshfH ;C:= Read and Hang I/O Port WDSlp1: in a,(c) ;Repeat nop nop djnz WDSlp1 ;Until (all of gap2 has been read) ld a,$INTE or $RAM out (ctlstb),a ;Set latch for writing (use crystal clock) in a,(c) ;Read the last fill byte nop nop ; (pad for refresh) ld a,$WRITE or $RAM or $INTE out (ctlstb),a ;Set Latch for writing Zero fill ld a,0 ld b,6 ;Counter:= number of zeros to write WDSlp2: out (c),a ;Repeat nop nop djnz WDSlp2 ;Until (all zeros have been written) ld a,$WRITE or $MARK or $_CRC or $RAM or $INTE out (ctlstb),a ;Set latch (ready to Write) ld a,0FBh out (wrtshf),a ;Write the Data Address Mark ld a,$WRITE or $_CRC or $RAM or $INTE out (ctlstb),a ;Set Latch to Start CRC generation jp WD ;GOTO Write a Data Field page ;---------------------------------------------------------------------- ; WDD - Write a Data Field Sync String in Double Density (20_Dec_83) ;------------------------------------------------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Counter for number of Zeros to write ; WDD: ld b,20 ;Counter:= Gap2 length - 2 ld c,RdshfH ;C:= Read and Hang I/O Port WDDlp1: in a,(c) ;Repeat nop nop djnz WDDlp1 ;Until (all of gap2 has been read) ld a,$INTE or $RAM out (ctlstb),a ;Set latch for writing in a,(c) ;Read the last fill byte ld a,$WRITE or $INTE or $RAM out (ctlstb),a ;Set Latch for writing zero fill ld a,0 ld b,12 ;Counter:= number of zeros to write WDDlp2: out (c),a ;Repeat nop nop djnz WDDlp2 ;Until (all zeros have been written) ld a,$WRITE or $MARK or $_CRC or $INTE or $RAM out (ctlstb),a ;Set latch (ready to Write) ld a,0A1h out (wrtshf),a ;Write the First Sync Byte ld a,0A1h out (wrtshf),a ;Write the Second Sync Byte ld a,0A1h out (wrtshf),a ;Write the Third Sync Byte ld a,$WRITE or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch to remove mark byte generation ld a,0FBh out (wrtshf),a ;Write the Data ID byte jp WD ;GOTO Write a Data Field page ;---------------------------------------------------------------------- ; WD - Write a Data Field (20_Dec_83) ;------------------------------------ ; 1) Register Usage: ; A -> General Purpose ; B -> Counter - Number of bytes in one block ; C -> Pointer to Read-and-Hang I/O Port ; D -> Number of Blocks per sector - 1 ; HL -> Pointer to the start of the data buffer - 1 ; WD: ld b,32 ;B:= Counter (number of bytes/block) ld c,Wrtshf ;C:= Write Shift Register I/O Port ld a,(blocks) ld d,a ;D:= Number of blocks/sector - 1 WDlp0: outi ;Repeat write a byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) jr nz,WDlp0 ; If (not the last byte of the block) ld b,32 ; Else 32-byte-counter:= reset dec d ; block_count:= block_count - 1 jr nz,WDlp0 ;Until (block count eq 0) dec b ;Count:= last block minus 1 WDlp1: outi ;Repeat write a byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) jr nz,WDlp1 ; If (not the last byte of the block) ld a,$WRITE or $_CRC or $INTE or $CRC out (ctlstb),a ;Set Latch for CRC generation ld a,(hl) out (c),a ;Write the last byte of sector nop ld a,$WRITE or $_CRC or $INTE or $CRC out (ctlstb),a ;Set the Latch for second crc byte in a,(c) ;Write the First CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$WRITE or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch for fill bytes in a,(c) ;Write the Second CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$WRITE or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,(filchr) ;A:= Fill character out (c),a ;Repeat ld a,$RAM out (ctlstb),a ;Latch:= Clear di ld a,0 ;Returned Error Status:= No Error ret page ;---------------------------------------------------------------------- ; RHS - Read Header Address String in Single Density (18_Jan_84) ;--------------------------------------------------------------- ; 1) Register Usage ; A -> General purpose ; DE -> Time_Out Limit ; RHS: ld de,56CEh ;Time_Out:= 300ms in a,(rdshfH) ;find a byte boundry ld a,$READ or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,0FEh out (wrtshf),a ;Data:= initial value to compare ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $SR out (ctlstb),a ;Set Latch ei RHSlp1: in a,(drvsts) ;Repeat and $CRCSET ; If (Read Sync Attained) jp z,RH ; Goto Compare a header dec de ; Counter:= Counter - 1 ld a,e or d jr nz,RHSlp1 ;Until (Counter eq 0) di ;Disable Interrupts ld a,Enf ;Error:= Not Found ret page ;---------------------------------------------------------------------- ; RHD - Read Header Address String in Double Density (18_Jan_84) ;--------------------------------------------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Time_Out Limit Lo Byte ; C -> Time_Out Limit Hi Byte ; D -> Mask for Sync Attained Bit ; RHD: ld b,0 ld c,72h ;BC:= Time_Out Limit @300ms ld d,$CRCSET ;D:= Mask for Sync Attained bit in a,(rdshfH) ;Dummy read to sync ld a,$READ or $INTE or $RAM out (ctlstb),a ;Set Latch ld a,0A1h out (wrtshf),a ;Data:= initial value to compare ld a,$READ or $CMPR or $_CRC or $MARK or $INTE or $RAM out (ctlstb),a ;Set Latch ei RHDlp1: in a,(Drvsts) ;Loop If (Read Sync Attained) and d jp z,RHDsk1 ; Break djnz RHDlp1 ; If (Time_Out Lo Byte eq 0) in a,(Drvsts) ; If (Read Sync Attained) and d jp z,RHDsk1 ; Break dec e ; Else If (Time_Out Hi Byte eq 0) jr z,RHDerr ; Goto Error in a,(Drvsts) ; If (Read Sync Attained) and d jr nz,RHDlp1 ; Break RHDsk1: ld a,0A1h out (wrtshf),a ;Compare second A1 ld a,0A1h out (wrtshf),a ;Compare the third A1 ld a,$READ or $CMPR or $_CRC or $INTE or $SR out (ctlstb),a ;Set Latch ld a,0FEh out (wrtshf),a ;Compare the ID byte jp RH RHDerr: di ;Disable Interrupts ld a,Enf ;Error:= Not Found ret ;Return page ds ($ and 1) + 2,0 ; Make sure this falls on even byte boundry ;---------------------------------------------------------------------- ; RH - Read a Header Field (20_Dec_83) ;------------------------------------- ; 1) This segment reads a floppy disk header consisting of track, ; sector, side, size, CRC, CRC into the normal header area. ; 2) Notice that the HL pair is initially pointer to the start of the ; header image - 1. This makes it possible to tell the difference ; between an ID address mark failure and a track value failure. ; 3) Register Usage: ; A -> General Purpose ; C -> Read and Hand I/O Port ; HL -> Pointer to the start of the header ; RH: ld a,$READ or $_CRC or $INTE or $SR out (ctlstb),a ;Set Latch ld c,RdshfH ;C:= Read and Hang I/O Port in a,(rdshfH) ;Do a dummy read to clear the shift register ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] nop ini ;Repeat read the track number ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] nop ini ;Repeat read the head number ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] ld a,$READ or $_CRC or $INTE or $CRC out (ctlstb),a ;Set Latch for CRC generation nop ini ;Read the Sector Number ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] ld a,$READ or $CMPR or $_CRC or $INTE or $CRC out (ctlstb),a ;Set Latch for final read nop ini ;Read the Sector size code ld a,(3A3Ah) nop ; [for fixing read sync] nop ; [for fixing read sync] ld a,$READ or $CMPR or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch for final read out (wrtshf),a ;Check the first CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$READ or $_CRC or $INTE or $RAM out (ctlstb),a ;Set Latch for final read out (wrtshf),a ;Check the second CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$RAM out (ctlstb),a ;Latch:= Clear in a,(c) ;Do one last read di ld a,0 ret page ;---------------------------------------------------------------------- ; FDD - Format a floppy disk Track in Double Density (16_Feb_84) ;--------------------------------------------------------------- ; ;Enable Interrupts and then wait for an index hole FDD: ld a,$RAM or $INTE or $WRITE out (ctlstb),a ;Set Latch for Normal write and enable IRQ ei ;Enable Interrupts ld hl,0B520h ;Counter:= 300ms FDDlp0: dec hl ;Repeat ld a,h ; Counter:= Counter - 1 or l jr nz,FDDlp0 ;Until (counter eq 0) di ;Disable Interrupts ld a,Enr ;Error:= Not Ready ret ;Return page ; Write Gap 5 (Pre-Address Mark) ;------------------------------- ; FFgo: ld a,(gap5) ;If (gap 5 specification is present) or a jp z,noidam ld b,a ; B:= Counter (gap 5 length) ld a,(filchr) ; A:= Fill character gap5lp: out (wrtshf),a ; Repeat Write pre-index fill character djnz gap5lp ; Until (count - 1 = 0) ; Write Index Address Mark Sync String ;------------------------------------- ; ld b,12 ; B:= Count ld a,0 ; A:= Fill character gdlp2: out (wrtshf),a ; Repeat Write fill character to the disk djnz gdlp2 ; Until (count - 1 = 0) ld a,$RAM or $INTE or $WRITE or $MARK out (ctlstb),a ; Set latch for missing clock write ld a,(cpymod) xor $ALT out (mode),a ; Reset the mode byte for Index Marks ld a,0C2h out (wrtshf),a ; Write the First Sync Byte ld a,0C2h out (wrtshf),a ; Write the Second Sync Byte ld a,0C2h out (wrtshf),a ; Write the Third Sync Byte ld a,$RAM or $INTE or $WRITE out (ctlstb),a ; Set Latch to remove mark byte generation ld a,(cpymod) out (mode),a ; Set mark character for Normal address marks ld a,0FCh out (wrtshf),a ; Write the Data ID byte page ; Write Gap 1 (Pre-Address Mark) ;------------------------------- ; noidam: ld a,(gap1) ld b,a ;B:= Gap 1 Length ld a,(filchr) ;A:= Fill character ld hl,(savehl) ;HL:= Pointer to the start of the sector table gap1lp: out (wrtshf),a ;Repeat Write post-index fill character djnz gap1lp ;Until (count - 1 = 0) ; Write the Header Sync String ;----------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Counter for number of Zeros to write ; ; Write the Zero Fill Preceeding the Index address mark nxtsec: ld b,12 ;B:= Count ld a,0 ;A:= Fill character gdlp4: out (wrtshf),a ;Repeat Write fill character to the disk djnz gdlp4 ;Until (count - 1 = 0) ld a,$RAM or $INTE or $WRITE or $MARK or $_CRC out (ctlstb),a ;Set latch (ready to Write) ld a,0A1h out (wrtshf),a ;Write the First Sync Byte ld a,0A1h out (wrtshf),a ;Write the Second Sync Byte ld a,0A1h out (wrtshf),a ;Write the Third Sync Byte ld a,$RAM or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set Latch to remove mark byte generation ld a,0FEh out (wrtshf),a ;Write the Data ID byte page ; Write a Header ;--------------- ; ld a,(iy+phytrk) out (wrtshf),a ;write a the track number nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,(iy+phyhd) out (wrtshf),a ;write a the head number nop ; (Pad for Refresh) nop ; (Pad for Refresh) dec hl ;Sector_Pointer:= Sector_Pointer - 1 ld a,(hl) ;Get the current sector number out (wrtshf),a ;write a the sector number nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$CRC or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set Latch for CRC generation ld a,c out (wrtshf),a ;Write the size byte nop ld a,$CRC or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set the Latch for second crc byte in a,(rdshfH) ;Write the First CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$RAM or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set Latch for fill bytes in a,(rdshfH) ;Write the Second CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$RAM or $INTE or $WRITE out (ctlstb),a ;Set Latch page ; Write Gap 2 (post header gap) ;------------------------------ ; ld a,(filchr) ld b,22 ;B:= Counter Gap2 length gap2lp: out (wrtshf),a ;Repeat nop nop djnz gap2lp ;Until (all of gap2 has been read) ; Write a Data Field Sync String in Double Density ;------------------------------------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Counter for number of Zeros to write ; ld a,0 ld b,12 ;Counter:= number of zeros to write FDlp2: out (wrtshf),a ;Repeat nop nop djnz FDlp2 ;Until (all zeros have been written) ld a,$RAM or $INTE or $WRITE or $MARK or $_CRC out (ctlstb),a ;Set latch (ready to Write) ld a,0A1h out (wrtshf),a ;Write the First Sync Byte ld a,0A1h out (wrtshf),a ;Write the Second Sync Byte ld a,0A1h out (wrtshf),a ;Write the Third Sync Byte ld a,$RAM or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set Latch to remove mark byte generation ld a,0FBh out (wrtshf),a ;Write the Data ID byte page ; Write a Data Field ;------------------- ; 1) Register Usage: ; A -> General Purpose ; B -> Counter - Number of bytes in one block ; C -> Pointer to Read-and-Hang I/O Port ; D -> Number of Blocks per sector - 1 ; E -> Fill Character for Gap 3 ; ld b,32 ;Counter:= 1_Block (32 bytes) ld a,(blocks) ld d,a ;D:= Number of 32 byte blocks to format ld a,0E5h ;A:= Data Field Fill Character FWDlp0: out (wrtshf),a ;Repeat write a byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) djnz FWDlp0 ; If (not the last byte of the block) ld b,32 ; Else 32-byte-counter:= reset dec d ; block_count:= block_count - 1 jr nz,FWDlp0 ;Until (block count eq 0) dec b ;Count:= last block minus 1 FWDlp1: out (wrtshf),a ;Repeat write a byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) djnz FWDlp1 ; If (not the last byte of the block) ld a,$CRC or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set Latch for CRC generation ld a,0E5h ;A:= Fill character out (wrtshf),a ;Write the last byte of sector nop ld a,$CRC or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set the Latch for second crc byte in a,(rdshfH) ;Write the First CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$RAM or $INTE or $WRITE or $_CRC out (ctlstb),a ;Set Latch for fill bytes in a,(rdshfH) ;Write the Second CRC byte nop ; (Pad for Refresh) nop ; (Pad for Refresh) ld a,$RAM or $INTE or $WRITE out (ctlstb),a ;Set Latch page ; Write gap 3 (post sector gap) ;------------------------------ ; ld a,(gap3) ld b,a ;B:= Counter (gap 3 length) ld a,(filchr) ;A:= Fill character gap3lp: out (wrtshf),a ;Repeat Write pre-index fill character djnz gap3lp ;Until (count - 1 = 0) ;Check if we'er done dec e ;If (there are more sectors to format) jp nz,nxtsec ; Goto beginning of format loop ; Write gap 4 (final gap) ;------------------------ ; ld a,(filchr) ;A:= Fill character gap4lp: out (wrtshf),a ;Repeat Write fill character jr gap4lp ;Until (count - 1 = 0) ;Note: The index interrupt routine will ; Return control to the calling routine If ($ lt O_Test - 1) ;If (we haven't overwritten hd*test) E_Dsk2: ds (O_Test - $) - 1, 0FFh ; Fill to the test module Else ;Else If2 ; print an error message on pass2 .printx "The dsk2 module has overflowed into the test module" EndIf EndIf end