Browse Source

CPM3 DiskIO routines now use HBIOS EXT_SLICE function during Drive Select

master
Mark Pruden 1 year ago
parent
commit
8e56b270c4
  1. 1
      Doc/ChangeLog.txt
  2. 255
      Source/CPM3/diskio.z80
  3. 2
      Source/ver.inc
  4. 2
      Source/ver.lib

1
Doc/ChangeLog.txt

@ -42,6 +42,7 @@ Version 3.5
- MAP: Added new HBIOS function EXT_SLICE (orginally SYSGET_DIOMED)
- MAP: ROMLDR now uses EXT_SLICE to get Slice Sector for boot
- MAP: CBIOS now uses EXT_SLICE during drive selection
- MAP: CPM3 Boot Loader, and BIOS (drive select) now use EXT_SLICE
- M?R: Added REBOOT application
Version 3.4

255
Source/CPM3/diskio.z80

@ -35,9 +35,9 @@
extrn ?pderr ; print BIOS disk error header
extrn ?conin,?cono ; con in and out
extrn ?const ; get console status
extrn ?bnkxlt
extrn phex16, phex8, cout, crlf, crlf2
@ -45,15 +45,18 @@
maclib cpm3.lib
; HBIOS related definitons
include hbios.z80
; common control characters
cr equ 13
lf equ 10
bell equ 7
; Extended Disk Parameter Headers (XDPHs)
; 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.
@ -186,7 +189,7 @@ dph15: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
cseg ; DPB must be resident
dpb$max:
dw 64 ; spt: sectors per track
db 5 ; bsh: block shift factor
@ -288,7 +291,7 @@ dpb_fd144: ; 3.5" DS/HD Floppy Drive (1.44M)
db 2 ; psh: 2 for 512 byte sectors
db 3 ; phm: (512 / 128) - 1
dpb_fd360: ; 5.25" DS/DD Floppy Drive (360K)
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
@ -370,7 +373,7 @@ dsk$init:
dsk$init1:
; Get bank count of RAM/ROM disk
ld b,0FAh ; HBIOS Peek Function
ld b,BF_SYSPEEK ; HBIOS Peek Function
ld a,(@hbbio) ; HBIOS bank id
ld d,a ; ... goes in D
rst 08 ; Call HBIOS, value in E
@ -399,9 +402,9 @@ dsk$init3:
dec hl ; subtract 1 for proper DSM value
ld (ix+5),l ; save updated
ld (ix+6),h ; ... DSM value
ret
;ld a,(@rdrv) ; unit being initialized
;ld hl,@bootdu
;cp (hl) ; compare to boot unit
@ -445,14 +448,13 @@ dsk$login:
;ret ; we have nothing to do in
; simple single density only environment.
;ld a,'L'
;call cout
ld (curdph),de ; save working DPH
ex de,hl ; DPH adr to HL
dec hl ; point to slice
dec hl ; point to slice
ld a,(hl) ; get slice
ld (slice),a ; save it
dec hl ; point to disk unit
@ -460,194 +462,38 @@ dsk$login:
ld (unit),a ; save it
inc a ; 0FFh -> 000h
jp z,err_ret ; bail out on no disk mapped here
;call media ; update DPH for media
;ret
media:
; Set retry address
ld hl,media
ld (retry$adr),hl
; Sense media to determine media format
ld a,(unit) ; get disk unit
ld c,a ; put in C
ld b,18h ; HBIOS Media function
ld e,1 ; Enable media check/discovery
ld b,BF_EXTSLICE ; HBIOS func: SLICE
ld a,(unit) ; passing boot unit
ld d,a
ld a,(slice) ; and slice
ld e,a
call 0FFF0H ; HBIOS call
jp nz,err_diskio ; handle error
ld a,e ; resultant media id to accum
ld (medid),a ; save media id
or a ; set flags, 0 is no media
jp z,err_nodisk ; handle no media error
; Initialize slice start LBA & sectors per slice
ld hl,0 ; assume slice starts
ld (lba),hl ; ... at LBA offset
set 7,h ; ... of zero
ld (lba+2),hl ; ... w/ LBA access
; Check device type
ld a,(unit) ; get disk unit
ld c,a ; put in C
ld b,17h ; HBIOS func: report device info
call 0FFF0h ; get unit info, device type in D
ld a,d ; device type -> A
cp 01h ; floppy?
jr nz,media1 ; if not, do LBA I/O
ld hl,lba+3 ; point to high order byte
res 7,(hl) ; switch from LBA -> CHS
media1:
ld hl,16640 ; assume legacy value for
ld (sps),hl ; ... sectors per slice
; If not hard disk, skip partition & slice stuff
ld a,(medid) ; get media id
cp 4 ; hard disk?
jp nz,media9 ; if not, jump ahead
; Read MBR
ld de,8000h ; LBA address zero
ld hl,0 ; ... to read first sector
ld bc,mbrsec ; read into MBR buffer
ld (dma),bc ; save
ld a,(0FFE0h) ; get current HBIOS bank
ld (bank),a ; set DMA bank
ld a,(unit) ; get bootunit
ld c,a ; put in C
ld b,013h ; HBIOS func: disk read
call dsk$io ; do it
ret nz ; abort on error
; Check signature
ld hl,(mbrsec+1FEh) ; get signature
ld a,l ; first byte
cp 055h ; should be $55
jr nz,media5 ; if not, no part table
ld a,h ; second byte
cp 0AAh ; should be $AA
jr nz,media5 ; if not, no part table
; Search part table for CP/M entry (type 0x2E)
ld b,4 ; four entries in part table
ld hl,mbrsec+1BEh+4 ; offset of first part type
media3:
ld a,(hl) ; get part type
cp 2Eh ; CP/M partition?
jr z,media4 ; cool, grab the LBA offset
ld de,16 ; part table entry size
add hl,de ; bump to next part type
djnz media3 ; loop thru table
jr media5 ; too bad, no CP/M partition
media4:
; Capture the starting LBA of the CP/M partition we found
ld de,4 ; LBA is 4 bytes after part type
add hl,de ; point to it
ld de,lba ; loc to store lba offset
ld bc,4 ; 4 bytes (32 bits)
ldir ; copy it
; Check that requested slice is "inside" partition.
; Slice size is exactly 16,384 sectors (8mb), so we can just
; right shift partition sector count by 14 bits
ld e,(hl) ; HL points to first byte
inc hl ; ... of 32 bit partition
ld d,(hl) ; ... sector count,
inc hl ; ... load sector count
push de ; ... into DE:HL
ld e,(hl) ; ...
inc hl ; ...
ld d,(hl) ; ...
pop hl ; ... DE:HL = part size in sectors
ld b,2 ; DE = DE:HL >> 2 (tricky!)
call rl32 ; DE = slicecnt
ex de,hl ; HL = slicecnt
ld a,(slice) ; get target slice
ld c,a ; put in C
ld b,0 ; BC := requested slice #
scf ; set carry!
sbc hl,bc ; max slices - slice - 1
jp c,err_noslice ; slice too high, error exit
; For now, it is implied that a slice within a partition
; table will be in the "new" disk format. So, we now
; adjust the sectors per slice and media id.
; Use new slice format sectors per slice value
ld hl,16384 ; new sectors per slice
ld (sps),hl ; save it
; Update media id for new hard disk format
ld a,10 ; new media id
ld (medid),a ; save it
media5:
; Adjust LBA offset based on target slice
ld a,(slice) ; get slice, A is loop cnt
ld hl,(lba) ; set DE:HL
ld de,(lba+2) ; ... to starting LBA
ld bc,(sps) ; sectors per slice
res 7,d ; clear lba mode bit
boot6:
or a ; set flags to check loop cntr
jr z,boot8 ; done if counter exhausted
add hl,bc ; add one slice to low word
jr nc,boot7 ; check for carry
inc de ; if so, bump high word
boot7:
dec a ; dec loop downcounter
jr boot6 ; and loop
boot8:
; LBA offset of desired slice is now in DE:HL.
; Need to check if the slice is beyond capacity of media.
; If lba_off + sps >= dsk_cap, error!
; Save lba_off
push de ; msw
push hl ; lsw
; Add sps to compute lba_req
ld bc,(sps) ; sectors per slice
add hl,bc ; add one slice to low word
jr nc,dsk_mbr9 ; check for carry
inc de ; if so, bump high word
dsk_mbr9:
; Save cap_req
ld (cap_req),hl ; lsw
ld (cap_req+2),de ; msw
; Get dsk_cap (de:hl)
ld b,1Ah ; hbios disk capacity func
ld a,(unit) ; disk unit number
ld c,a ; ... into c
rst 08 ; hbios call (de:hl = capacity)
; Save dsk_cap (de:hl)
push de ; save dsk_cap (msw)
push hl ; save dsk_cap (lsw)
; Check dsk_cap >= cap_req, cf set on overflow
; No need save actual result
or a ; clear carry for sbc
pop hl ; dsk_cap lsw
ld de,(cap_req) ; cap_req lsw
sbc hl,de ; dsk_cap - lba_req (lsw)
pop hl ; dsk_cap msw
ld de,(cap_req+2) ; cap_req msw
sbc hl,de ; dsk_cap - lba_req (msw)
; Restore lba_off
pop hl ; lsw
pop de ; msw
; Abort on overflow with error!
jp c,err_noslice ; slice too high, error exit
; Check errors from the Function
cp ERR_NOUNIT ; compare to no unit error
jp z,err_nodisk ; handle no disk err
cp ERR_NOMEDIA ; no media in the device
jp z,err_nodisk ; handle the error
cp ERR_RANGE ; slice is invalid
jp z,err_noslice ; bad slice, handle err
or a ; any other error
jp nz,err_diskio ; handle as general IO error
; Capture the Result
ld a,c ; resultant media id to accum
ld (medid),a ; save media id
; Finalize slice lba
BIT 7,B ; Is the floppy Disk Attribute Set
jr nz,media8 ; if it is Floppy; Skip Setting LBA
set 7,d ; set LBA access flag
media8:
ld (lba),hl ; save new lba, low word
ld (lba+2),de ; save new lba, high word
@ -698,23 +544,23 @@ media10:
; if necessary, then return an error code in <A>
dsk$read:
ld a,13h ; HBIOS disk read function
ld a,BF_DIOREAD ; HBIOS disk read function
ld (func),a ; save it
jr dsk$rw ; common disk read/write code
dsk$write:
ld a,14h ; HBIOS disk write function
ld a,BF_DIOWRITE ; HBIOS disk write function
ld (func),a ; save it
jr dsk$rw ; common disk read/write code
dsk$rw:
; Common disk read/write routine
; Assumes func is set to HBIOS read or write
; Set retry address
ld hl,dsk$rw$retry
ld (retry$adr),hl
; Save XDPH address
ld (curdph),de ; save to curdph
@ -743,12 +589,12 @@ dsk$rw$retry:
rr l ; ... and into carry
rl d ; carry bit (head) into d
jr dsk$rw9 ; do the disk I/O
dsk$rw2:
; LBA I/O
push de ; save hiword of LBA
push hl ; save loword of LBA
; Get track and shift into correct bits
ld hl,(@trk) ; get track
ld de,0 ; clear hiword
@ -767,7 +613,7 @@ dsk$rw2:
pop bc ; lba offset hiword
adc hl,bc ; add w/ carry to cur hiword
ex de,hl ; swap back
dsk$rw9:
; DE:HL has sector address to read (LBA or CHS)
ld bc,(@dma) ; get dma address
@ -791,7 +637,7 @@ dsk$io:
; Seek to requested sector in DE:HL
push bc ; save func & unit
ld b,012h ; HBIOS func: seek
ld b,BF_DIOSEEK ; HBIOS func: seek
call 0FFF0h ; do it
pop bc ; recover func & unit
jp nz,err_diskio ; handle error
@ -824,7 +670,7 @@ mult8_loop:
mult8_noadd:
djnz mult8_loop
ret
rl32:
; Left shift DE:HL by B bits (B > 0)
or a ; clear carry
@ -834,7 +680,7 @@ rl32:
rl d ; rotate D thru carry
djnz rl32 ; loop B times
ret ; done
cin$echo: ; get console input, echo it, and shift to upper case
call ?const ; check for char
or a ; set flags
@ -851,7 +697,7 @@ cin$echo1:
ret c ; done if carry
sub 'a' - 'A' ; make upper case
ret ; and done
; 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:
@ -872,7 +718,7 @@ err_perm:
call prt_err
jr err_ret
err_diskio:
cp -10 ; HBIOS read only error
cp ERR_READONLY ; HBIOS read only error
jr z,err_rdonly ; if so, handle special
ld a,(@ermde) ; get error mode
cp 0FFh ; FFh means suppress
@ -916,9 +762,6 @@ medid db 0 ; working media id value
unit db 0 ; working disk unit num
slice db 0 ; working slice num
lba dw 0,0 ; working lba
sps dw 0 ; sectors per slice
cap_req dw 0,0 ; lba cap required for slice
mbrsec ds 512 ; MBR sector buffer
dma dw 0 ; current DMA address
bank db 0 ; HBIOS DMA bank
func db 0 ; HBIOS function

2
Source/ver.inc

@ -2,7 +2,7 @@
#DEFINE RMN 5
#DEFINE RUP 0
#DEFINE RTP 0
#DEFINE BIOSVER "3.5.0-dev.92"
#DEFINE BIOSVER "3.5.0-dev.93"
#define rmj RMJ
#define rmn RMN
#define rup RUP

2
Source/ver.lib

@ -3,5 +3,5 @@ rmn equ 5
rup equ 0
rtp equ 0
biosver macro
db "3.5.0-dev.92"
db "3.5.0-dev.93"
endm

Loading…
Cancel
Save