diff --git a/Doc/ChangeLog.txt b/Doc/ChangeLog.txt index d0e79583..d3d9df7b 100644 --- a/Doc/ChangeLog.txt +++ b/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 diff --git a/Source/CPM3/diskio.z80 b/Source/CPM3/diskio.z80 index c91caa4c..8705427e 100644 --- a/Source/CPM3/diskio.z80 +++ b/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 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 diff --git a/Source/ver.inc b/Source/ver.inc index 11b25f30..8623c78e 100644 --- a/Source/ver.inc +++ b/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 diff --git a/Source/ver.lib b/Source/ver.lib index 2a80f082..5427f545 100644 --- a/Source/ver.lib +++ b/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