You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

781 lines
22 KiB

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 @<HL> up to 00, saves <BC> & <DE>
extrn ?pdec ; print binary number in <A> 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 <DE>
;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 <DE>
; they transfer the appropriate data, perform retries
; if necessary, then return an error code in <A>
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, <operation> <type>, 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 "<BEL>, 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 <B>
; 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 <B>
; 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