title 'HBIOS disk handler' ; CP/M-80 Version 3 -- Modular BIOS maclib options.lib dseg ; Disk drive dispatching tables for linked BIOS public dph0,dph1,dph2,dph3,dph4,dph5,dph6,dph7 public dph8,dph9,dph10,dph11,dph12,dph13,dph14,dph15 ; Linked BIOS variables public @sysdr extrn @bootdu ; Variables containing parameters passed by BDOS extrn @adrv,@rdrv extrn @dma,@trk,@sect extrn @dbnk ; System Control Block variables extrn @ermde ; BDOS error mode ; Utility routines in standard BIOS extrn ?wboot ; warm boot vector extrn ?pmsg ; print message @ up to 00, saves & extrn ?pdec ; print binary number in from 0 to 99. extrn ?pderr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status extrn ?bnkxlt ; CP/M 3 Disk definition macros maclib cpm3.lib ; common control characters cr equ 13 lf equ 10 bell equ 7 ; Extended Disk Parameter Headers (XPDHs) ; All DPH entries below are generic. They are updated during ; boot to point to available HBIOS disk unit/slices dynamically. dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph0: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph1: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph2: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph3: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph4: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph5: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph6: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph7: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph8: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph9: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph10: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph11: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph12: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph13: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph14: dph 0,dpb$max ; Real DPB filled in at disk login dw dsk$write dw dsk$read dw dsk$login dw dsk$init db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot) dph15: dph 0,dpb$max ; Real DPB filled in at disk login cseg ; DPB must be resident dpb$max: dw 64 ; spt: sectors per track db 5 ; bsh: block shift factor db 31 ; blm: block mask db 1 ; exm: extent mask dw 2047 ; dsm: total storage in blocks - 1 = (8mb / 4k bls) - 1 = 2047 dw 511 ; drm: dir entries - 1 = 512 - 1 = 511 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 64 ; cks: directory check vector size - 256 / 4 dw 0 ; off: reserved tracks = 16 trks * (16 trks * 16 heads * 16 secs * 512 bytes) = 128k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb$start: dpb$rom: ; 384K ROM Drive dw 64 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 1 ; exm: extent mask dw 192 - 1 ; dsm: total storage in blocks - 1 = (384kb / 2k bls) - 1 = 191 dw 256 - 1 ; drm: dir entries - 1 = 256 - 1 = 255 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 8000h ; cks: directory check vector size - permanent storage = 8000H dw 0 ; off: reserved tracks = 16 trks * (16 trks * 16 heads * 16 secs * 512 bytes) = 128k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb$sz equ $ - dpb$start dpb$ram: ; 256K RAM Drive dw 64 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 1 ; exm: extent mask dw 128 - 1 ; dsm: total storage in blocks - 1 = (256kb / 2k bls) - 1 = 127 dw 256 - 1 ; drm: dir entries - 1 = 256 - 1 = 255 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 8000h ; cks: directory check vector size - permanent storage = 8000H dw 0 ; off: reserved tracks = 16 trks * (16 trks * 16 heads * 16 secs * 512 bytes) = 128k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb$rf: ; 4MB RAM Floppy Drive dw 64 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 0 ; exm: extent mask dw 2047 ; dsm: total storage in blocks - 1 = (4mb / 2k bls) - 1 = 2047 dw 255 ; drm: dir entries - 1 = 256 - 1 = 255 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 8000h ; cks: directory check vector size - permanent storage = 8000H dw 0 ; off: reserved tracks = 0 trks db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb$hd: ; 8MB Hard Disk Drive dw 64 ; spt: sectors per track db 5 ; bsh: block shift factor db 31 ; blm: block mask db 1 ; exm: extent mask dw 2047 ; dsm: total storage in blocks - 1 = (8mb / 4k bls) - 1 = 2047 dw 511 ; drm: dir entries - 1 = 512 - 1 = 511 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 8000h ; cks: directory check vector size - permanent storage = 8000H dw 16 ; off: reserved tracks = 16 trks * (16 trks * 16 heads * 16 secs * 512 bytes) = 128k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb$fd720: ; 3.5" DS/DD Floppy Drive (720K) dw 36 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 0 ; exm: extent mask dw 350 ; dsm: total storage in blocks - 1 blk = ((720k - 18k off) / 2k bls) - 1 = 350 dw 127 ; drm: dir entries - 1 = 128 - 1 = 127 db 11000000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 32 ; cks: directory check vector size = 128 / 4 dw 4 ; off: reserved tracks = 4 trks * (512 b/sec * 36 sec/trk) = 18k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb_fd144: ; 3.5" DS/HD Floppy Drive (1.44M) dw 72 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 0 ; exm: extent mask dw 710 ; dsm: total storage in blocks - 1 blk = ((1,440k - 18k off) / 2k bls) - 1 = 710 dw 255 ; drm: dir entries - 1 = 256 - 1 = 255 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 64 ; cks: directory check vector size = 256 / 4 dw 2 ; off: reserved tracks = 2 trks * (512 b/sec * 72 sec/trk) = 18k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb_fd360: ; 5.25" DS/DD Floppy Drive (360K) dw 36 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 1 ; exm: extent mask dw 170 ; dsm: total storage in blocks - 1 blk = ((360k - 18k off) / 2k bls) - 1 = 170 dw 127 ; drm: dir entries - 1 = 128 - 1 = 127 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 32 ; cks: directory check vector size = 128 / 4 dw 4 ; off: reserved tracks = 4 trks * (512 b/sec * 36 sec/trk) = 18k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb_fd120: ; 5.25" DS/HD Floppy Drive (1.2M) dw 60 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 0 ; exm: extent mask dw 591 ; dsm: total storage in blocks - 1 blk = ((1,200k - 15k off) / 2k bls) - 1 = 591 dw 255 ; drm: dir entries - 1 = 256 - 1 = 255 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 64 ; cks: directory check vector size = 256 / 4 dw 2 ; off: reserved tracks = 2 trks * (512 b/sec * 60 sec/trk) = 15k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dpb_fd111: ; 8" DS/DD Floppy Drive (1.11M) dw 60 ; spt: sectors per track db 4 ; bsh: block shift factor db 15 ; blm: block mask db 0 ; exm: extent mask dw 569 ; dsm: total storage in blocks - 1 blk = ((1,155k - 15k off) / 2k bls) - 1 = 569 dw 255 ; drm: dir entries - 1 = 256 - 1 = 255 db 11110000b ; al0: dir blk bit map, first byte db 00000000b ; al1: dir blk bit map, second byte dw 64 ; cks: directory check vector size = 256 / 4 dw 2 ; off: reserved tracks = 2 trks * (512 b/sec * 60 sec/trk) = 15k db 2 ; psh: 2 for 512 byte sectors db 3 ; phm: (512 / 128) - 1 dseg ; rest is banked ; Disk I/O routines for standardized BIOS interface ; Initialization entry point. ; called for first time initialization. dsk$init: inc de ; point to slice in XDPH inc de inc de ld a,(de) ; get slice or a ; set flags ret nz ; done if not zero ld a,(@rdrv) ; unit being initialized ld hl,@bootdu cp (hl) ret nz ; done if no match ld a,(@adrv) ; get cp/m drive ld (@sysdr),a ; and save it ret ; lxi h,init$table ;fd$init$next: ; mov a,m ! ora a ! rz ; mov b,a ! inx h ! mov c,m ! inx h ; outir ; jmp fd$init$next ; ;fd$init1: ; all initialization done by drive 0 ; ret ;init$table db 4,p$zpio$1A ; db 11001111b, 11000010b, 00010111b,11111111b ; db 4,p$zpio$1B ; db 11001111b, 11011101b, 00010111b,11111111b ; db 0 dsk$login: ; This entry is called when a logical drive is about to ; be logged into for the purpose of density determination. ; It may adjust the parameters contained in the disk ; parameter header pointed at by ;ret ; we have nothing to do in ; simple single density only environment. push de ; save DPH ptr ; check media ld a,(@rdrv) ; get disk unit ;halt ld c,a ; put in C ld b,18h ; HBIOS Media function ld e,1 ; Enabled media check/discovery call 0FFF0H ; HBIOS call ld a,e ; Resultant media id to accum or a ; Set flags ;halt ; ; !!! Need to do something on error !!! ; ret z ; Bail out on error ld hl,dpb$start - dpb$sz ld de,dpb$sz ld b,a ; loop count dsk$login1: add hl,de ; next dpb djnz dsk$login1 ; loop as needed ; hl is ptr to desired dpb pop de ; restore DPH ptr ;halt ex de,hl ; de = DPB adr, hl = DPH adr push de ; save DPB adr ld de,12 ; offset of DPB in DPH add hl,de ; hl = adr of DPB field in DPH pop de ; recover DPB adr ld (hl),e ; update LSB inc hl ld (hl),d ; udpate MSB ret ; done ; disk READ and WRITE entry points. ; these entries are called with the following arguments: ; relative drive number in @rdrv (8 bits) ; absolute drive number in @adrv (8 bits) ; disk transfer address in @dma (16 bits) ; disk transfer bank in @dbnk (8 bits) ; disk track address in @trk (16 bits) ; disk sector address in @sect (16 bits) ; pointer to XDPH in ; they transfer the appropriate data, perform retries ; if necessary, then return an error code in dsk$read: ; ld ix,30H ; halt push de ; save XDPH pointer call dsk$seek ; disk seek pop hl ; restore pointer to HL ret nz ; abort on seek error ; dec hl ; point to unit field of XDPH dec hl ld c,(hl) ; BIOS Disk Unit in C ld b,13H ; HBIOS READ function ld hl,(@dma) ; Dest buffer adr if banked ld a,(@dbnk) ; destination bank call ?bnkxlt else ld a,(0FFE0H) ; get current bank endif ld d,a ; set desk bank ld e,1 ; 1 sector ;rst 08 ; do it call 0FFF0H ret ; return ; lxi h,read$msg ; point at " Read " ; mvi a,88h ! mvi b,01h ; 1797 read + Z80DMA direction ; jmp rw$common dsk$write: ;ld ix,32H ;halt push de ; save XDPH pointer call dsk$seek ; disk seek pop hl ; restore pointer to XDPH ret nz ; abort on seek error ; dec hl ; point to unit field of XDPH dec hl ld c,(hl) ; BIOS Disk Unit in C ld b,14H ; HBIOS WRITE function ld hl,(@dma) ; Dest buffer adr if banked ld a,(@dbnk) ; destination bank call ?bnkxlt else ld a,(0FFE0H) ; get current bank endif ld d,a ; set desk bank ld e,1 ; 1 sector ;rst 08 ; do it call 0FFF0H ret ; return ; lxi h,write$msg ; point at " Write " ; mvi a,0A8h ! mvi b,05h ; 1797 write + Z80DMA direction ; ; jmp wr$common dsk$seek: dec de ; point to unit field of XDPH dec de ld a,(de) ; get it ld c,a ; BIOS Disk Unit in C ld b,12H ; HBIOS SEEK function push bc ; save it inc de ; point to slice field of XDPH ld a,(de) ; get it ld e,a ; slice to E ld h,65 ; number of tracks per slice call mult8 ; HL now has track offset for slice push hl ; save it for now ld hl,(@trk) ; get track value ld a,l ; lsb of track to a and 0FH ; isolate head in low 4 bits ld d,a ; stuff it in d ld a,(@sect) ; get sector ld e,a ; stuff it in e ld b,4 ; prepare to shift out 4 bit head value seek1: srl h ; shift one bit out rr l ; ... of hl djnz seek1 ; do all 4 bits ex de,hl ; de=track, hl=head/sect ex (sp),hl ; save head/sect, hl = offset add hl,de ; hl has final track value pop de ; recover head/sect to de pop bc ; recover function & unit ;rst 08 ; perform seek call 0FFF0H ret ; ; multiply 8-bit values ; in: multiply h by e ; out: hl = result, e = 0, b = 0 ; mult8: ld d,0 ld l,d ld b,8 mult8_loop: add hl,hl jr nc,mult8_noadd add hl,de mult8_noadd: djnz mult8_loop ret ;rw$common: ; seek to correct track (if necessary), ; ; initialize DMA controller, ; ; and issue 1797 command. ; ; shld operation$name ; save message for errors ; sta disk$command ; save 1797 command ; mov a,b ! sta zdma$direction ; save Z80DMA direction code ; lhld @dma ! shld zdma$dma ; get and save DMA address ; lda @rdrv ! mov l,a ! mvi h,0 ; get controller-relative disk drive ; lxi d,select$table ! dad d ; point to select mask for drive ; mov a,m ! sta select$mask ; get select mask and save it ; out p$select ; select drive ;more$retries: ; mvi c,10 ; allow 10 retries ;retry$operation: ; push b ; save retry counter ; ; lda select$mask ! lxi h,old$select ! cmp m ; mov m,a ; jnz new$track ; if not same drive as last, seek ; ; lda @trk ! lxi h,old$track ! cmp m ; mov m,a ; jnz new$track ; if not same track, then seek ; ; in p$fdmisc ! ani 2 ! jnz same$track ; head still loaded, we are OK ; ;new$track: ; or drive or unloaded head means we should . . . ; call check$seek ; . . read address and seek if wrong track ; ; lxi b,16667 ; 100 ms / (24 t states*250 ns) ;spin$loop: ; wait for head/seek settling ; dcx b ; mov a,b ! ora c ; jnz spin$loop ; ;same$track: ; lda @trk ! out p$fdtrack ; give 1797 track ; lda @sect ! out p$fdsector ; and sector ; ; lxi h,dma$block ; point to dma command block ; lxi b,dmab$length*256 + p$zdma ; command block length and port address ; outir ; send commands to Z80 DMA ; ; in p$bankselect ; get old value of bank select port ; ani 3Fh ! mov b,a ; mask off DMA bank and save ; lda @dbnk ! rrc ! rrc ; get DMA bank to 2 hi-order bits ; ani 0C0h ! ora b ; merge with other bank stuff ; out p$bankselect ; and select the correct DMA bank ; ; lda disk$command ; get 1797 command ; call exec$command ; start it then wait for IREQ and read status ; sta disk$status ; save status for error messages ; ; pop b ; recover retry counter ; ora a ! rz ; check status and return to BDOS if no error ; ; ani 0001$0000b ; see if record not found error ; cnz check$seek ; if a record not found, we might need to seek ; ; dcr c ! jnz retry$operation ; ; ; suppress error message if BDOS is returning errors to application... ; ; lda @ermde ! cpi 0FFh ! jz hard$error ; ; ; Had permanent error, print message like: ; ; ; BIOS Err on d: T-nn, S-mm, , Retry ? ; ; call ?pderr ; print message header ; ; lhld operation$name ! call ?pmsg ; last function ; ; ; then, messages for all indicated error bits ; ; lda disk$status ; get status byte from last error ; lxi h,error$table ; point at table of message addresses ;errm1: ; mov e,m ! inx h ! mov d,m ! inx h ; get next message address ; add a ! push psw ; shift left and push residual bits with status ; xchg ! cc ?pmsg ! xchg ; print message, saving table pointer ; pop psw ! jnz errm1 ; if any more bits left, continue ; ; lxi h,error$msg ! call ?pmsg ; print ", Retry (Y/N) ? " ; call u$conin$echo ; get operator response ; cpi 'Y' ! jz more$retries ; Yes, then retry 10 more times ;hard$error: ; otherwise, ; mvi a,1 ! ret ; return hard error to BDOS ; ;cancel: ; here to abort job ; jmp ?wboot ; leap directly to warmstart vector ; ; ; ; subroutine to seek if on wrong track ; ; called both to set up new track or drive ; ;check$seek: ; push b ; save error counter ; call read$id ; try to read ID, put track in ; jz id$ok ; if OK, we're OK ; call step$out ; else step towards Trk 0 ; call read$id ; and try again ; jz id$ok ; if OK, we're OK ; call restore ; else, restore the drive ; mvi b,0 ; and make like we are at track 0 ;id$ok: ; mov a,b ! out p$fdtrack ; send current track to track port ; lda @trk ! cmp b ! pop b ! rz ; if its desired track, we are done ; out p$fddata ; else, desired track to data port ; mvi a,00011010b ; seek w/ 10 ms. steps ; jmp exec$command ; ; ; ;step$out: ; mvi a,01101010b ; step out once at 10 ms. ; jmp exec$command ; ;restore: ; mvi a,00001011b ; restore at 15 ms ; ; jmp exec$command ; ; ;exec$command: ; issue 1797 command, and wait for IREQ ; ; return status ; out p$fdcmnd ; send 1797 command ;wait$IREQ: ; spin til IREQ ; in p$fdint ! ani 40h ! jz wait$IREQ ; in p$fdstat ; get 1797 status and clear IREQ ; ret ; ;read$id: ; lxi h,read$id$block ; set up DMA controller ; lxi b,length$id$dmab*256 + p$zdma ; for READ ADDRESS operation ; outir ; mvi a,11000100b ; issue 1797 read address command ; call exec$command ; wait for IREQ and read status ; ani 10011101b ; mask status ; lxi h,id$buffer ! mov b,m ; get actual track number in ; ret ; and return with Z flag true for OK ; ; ;u$conin$echo: ; get console input, echo it, and shift to upper case ; call ?const ! ora a ! jz u$c1 ; see if any char already struck ; call ?conin ! jmp u$conin$echo ; yes, eat it and try again ;u$c1: ; call ?conin ! push psw ; mov c,a ! call ?cono ; pop psw ! cpi 'a' ! rc ; sui 'a'-'A' ; make upper case ; ret ; ; ;disk$command ds 1 ; current wd1797 command ;select$mask ds 1 ; current drive select code ;old$select ds 1 ; last drive selected ;old$track ds 1 ; last track seeked to ; ;disk$status ds 1 ; last error status code for messages ; ;select$table db 0001$0000b,0010$0000b ; for now use drives C and D ; ; ; ; error message components ; ;read$msg db ', Read',0 ;write$msg db ', Write',0 ; ;operation$name dw read$msg ; ; ; table of pointers to error message strings ; ; first entry is for bit 7 of 1797 status byte ; ;error$table dw b7$msg ; dw b6$msg ; dw b5$msg ; dw b4$msg ; dw b3$msg ; dw b2$msg ; dw b1$msg ; dw b0$msg ; ;b7$msg db ' Not ready,',0 ;b6$msg db ' Protect,',0 ;b5$msg db ' Fault,',0 ;b4$msg db ' Record not found,',0 ;b3$msg db ' CRC,',0 ;b2$msg db ' Lost data,',0 ;b1$msg db ' DREQ,',0 ;b0$msg db ' Busy,',0 ; ;error$msg db ' Retry (Y/N) ? ',0 ; ; ; ; ; command string for Z80DMA device for normal operation ; ;dma$block db 0C3h ; reset DMA channel ; db 14h ; channel A is incrementing memory ; db 28h ; channel B is fixed port address ; db 8Ah ; RDY is high, CE/ only, stop on EOB ; db 79h ; program all of ch. A, xfer B->A (temp) ;zdma$dma ds 2 ; starting DMA address ; dw 128-1 ; 128 byte sectors in SD ; db 85h ; xfer byte at a time, ch B is 8 bit address ; db p$fddata ; ch B port address (1797 data port) ; db 0CFh ; load B as source register ; db 05h ; xfer A->B ; db 0CFh ; load A as source register ;zdma$direction ds 1 ; either A->B or B->A ; db 0CFh ; load final source register ; db 87h ; enable DMA channel ;dmab$length equ $-dma$block ;read$id$block db 0C3h ; reset DMA channel ; db 14h ; channel A is incrementing memory ; db 28h ; channel B is fixed port address ; db 8Ah ; RDY is high, CE/ only, stop on EOB ; db 7Dh ; program all of ch. A, xfer A->B (temp) ; dw id$buffer ; starting DMA address ; dw 6-1 ; Read ID always xfers 6 bytes ; db 85h ; byte xfer, ch B is 8 bit address ; db p$fddata ; ch B port address (1797 data port) ; db 0CFh ; load dest (currently source) register ; db 01h ; xfer B->A ; db 0CFh ; load source register ; db 87h ; enable DMA channel ;length$id$dmab equ $-read$id$block cseg ; easier to put ID buffer in common ;id$buffer ds 6 ; buffer to hold ID field ; ; track ; ; side ; ; sector ; ; length ; ; CRC 1 ; ; CRC 2 cseg @sysdr db 0 ; system boot drive end