diff --git a/Source/CPM3/biosldr.z80 b/Source/CPM3/biosldr.z80 index 58e57cf0..9eacd755 100644 --- a/Source/CPM3/biosldr.z80 +++ b/Source/CPM3/biosldr.z80 @@ -4,11 +4,13 @@ maclib cpm3.lib cseg - + extrn phex16, phex8 extrn cin, cout extrn crlf, crlf2 - + + include hbios.z80 + debug equ false ; BIOS Jump vector. @@ -65,7 +67,7 @@ boot: ; this routine to avoid issues. ld (stksav),sp ld sp,stack - + ; Do the real work call boot0 @@ -78,6 +80,10 @@ boot0: if cmdline boot1: + ; + ; The following Code is the Entry Point for the Loader when + ; it is built as a COM file. Typically CPMLDR.COM or ZPMLDR.COM + ; ; Get disk unit from user ld de,msgunit ; disk unit prompt call writestr ; display on console @@ -88,7 +94,7 @@ boot1: sub '0' ; convert to binary ld (unit),a ; save it jr c,selerr ; loop if below 0 entered - ld bc,0F810h ; HBIOS, get disk unit count + ld bc,BC_SYSGET_DIOCNT ; HBIOS, get disk unit count call 0FFF0h ; do it, E := disk unit count ld a,(unit) ; get unit num back cp e ; compare to entry @@ -118,7 +124,7 @@ selerr: boot2: ; Record unit & slice w/ HBIOS - ld bc,0F9E0h ; HBIOS func: set boot info + ld bc,BC_SYSSET_BOOTINFO ; HBIOS func: set boot info ld a,(unit) ; get unit ld d,a ; put in D ld a,(slice) ; get slice @@ -128,8 +134,13 @@ boot2: else + ; + ; The following Code is the Entry Point for the Loader when + ; it is built as a SYS file, and run from the System Track + ; + ; Get unit & slice from HBIOS - ld bc,0F8E0h ; HBIOS func: get boot info + ld bc,BC_SYSGET_BOOTINFO ; HBIOS func: get boot info call 0FFF0h ; do it, D := boot unit, E: := slice ld a,d ; move unit to A ld (unit),a ; save it @@ -138,103 +149,27 @@ boot2: endif - ; Check that drive actually exists - ld bc,0F810h ; HBIOS func: get disk count - call 0FFF0h ; do it, E=disk count - ld a,(unit) ; get boot disk unit - cp e ; compare to count - jp nc,err_nodisk ; handle no disk err - ; Sense media to determine media format ld a,(unit) ; Get boot unit - ld c,a ; put in C - ld b,18h ; HBIOS Media function - ld e,1 ; Enable media check/discovery + ld d,a ; put in D + ld a,(slice) ; get boot slice + ld e,a ; put in E + ld b,BF_EXTSLICE ; HBIOS FUNC: SLICE 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_diskio ; handle no media error - - ; Initialize slice start LBA & sectors per slice - ld hl,0 ; assume slice starts - ld (lba),hl ; ... at LBA offset - ld (lba+2),hl ; ... of zero - 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? - jr nz,boot9 ; 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 b,1 ; one sector - ld a,(unit) ; get bootunit - ld c,a ; put in C - call diskread ; do it, no return on err - - ; Check signature - ld hl,(mbrsec+1FEh) ; get signature - ld a,l ; first byte - cp 055h ; should be $55 - jr nz,boot5 ; if not, no part table - ld a,h ; second byte - cp 0AAh ; should be $AA - jr nz,boot5 ; 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 -boot3: - ld a,(hl) ; get part type - cp 2Eh ; CP/M partition? - jr z,boot4 ; cool, grab the LBA offset - ld de,16 ; part table entry size - add hl,de ; bump to next part type - djnz boot3 ; loop thru table - jr boot5 ; too bad, no CP/M partition - -boot4: - ; 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 - - ; 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 - -boot5: - ; Adjust LBA offset based on target slice - ld a,(slice) ; get boot slice, A is loop cnt - ld hl,(lba) ; set DE:HL - ld de,(lba+2) ; ... to starting LBA - ld bc,(sps) ; sectors per slice -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 + ; 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 + + ; Initialize slice start LBA and Media ID + ld a,c + ld (medid),a ; save media id boot8: ld (lba),hl ; save new lba, low word ld (lba+2),de ; save new lba, high word @@ -277,7 +212,7 @@ conin: conout: ld e,c ; output character in E ld bc,0180h ; unit 80h (console), func 1 = COUT - jp 0FFF0h + jp 0FFF0h list: ld a,85H halt @@ -311,7 +246,7 @@ setdma: call crlf call phex16 pop hl - + endif ld (dma),bc @@ -337,18 +272,18 @@ read: call phex16 ld hl,(lba+0) call phex16 - + endif ; Check device type ld a,(unit) ; get unit ld c,a ; BIOS Disk Unit in C - ld b,17h ; HBIOS DEVICE function + ld b,BF_DIODEVICE ; HBIOS DEVICE function rst 08 ; Do it, D=device type ld a,d ; put in accum cp 01h ; floppy? jr nz,read2 ; if not, do LBA i/o - + ; Floppy I/O ld de,(sect) ; sector -> de, head(d) becomes zero ld hl,(trk) ; track -> hl (low bit has head) @@ -356,7 +291,7 @@ read: rr l ; ... and into carry rl d ; carry bit (head) into d jr read3 ; do the disk i/o - + ; LBA I/O read2: ld hl,(trk) ; get track @@ -386,7 +321,7 @@ read3: call phex16 ex de,hl call phex16 - + endif ; DE:HL has sector address to read (LBA or CHS) @@ -401,14 +336,14 @@ diskread: ; Seek to requested sector in DE:HL push bc ; save unit & count - ld b,012h ; HBIOS func: seek + ld b,BF_DIOSEEK ; HBIOS func: seek call 0FFF0h ; do it pop bc ; recover unit & count jp nz,err_diskio ; handle error ; Read sector(s) into buffer ld e,b ; transfer count - ld b,013h ; HBIOS func: disk read + ld b,BF_DIOREAD ; HBIOS func: disk read ld hl,(dma) ; read into info sec buffer ld a,(0FFE0h) ; get current bank ld d,a ; put in D @@ -477,7 +412,7 @@ xmove: ;cin: ; ; Input character from console via HBIOS ; ld c,080H ; console unit to C -; ld b,00H ; HBIOS func: input char +; ld b,BF_CIOIN ; HBIOS func: input char ; call 0FFF0H ; HBIOS reads character ; ld a,e ; To A for return ; ret ; done @@ -486,7 +421,7 @@ xmove: ; ; Output character to console via HBIOS ; ld e,a ; output char to E ; ld c,080H ; console unit to C -; ld b,01H ; HBIOS func: output char +; ld b,BF_CIOOUT ; HBIOS func: output char ; jp 0FFF0H ; output & return writestr: @@ -539,7 +474,7 @@ err: str_err_prefix db "\r\n\r\n*** ","$" str_err_nodisk db "Disk unit not available","$" -str_err_noslice db "Disk unit does not support slices","$" +str_err_noslice db "Slice not supported","$" str_err_diskio db "Disk I/O failure","$" str_err_sig db "No system image on disk","$" str_err_api db "HBIOS API failure","$" @@ -728,7 +663,6 @@ dma ds 2 ; current DMA address medid ds 1 ; media id lba ds 4 ; current lba -sps ds 2 ; sectors per slice ds 64 stack equ $ diff --git a/Source/CPM3/hbios.z80 b/Source/CPM3/hbios.z80 new file mode 100644 index 00000000..36b6c683 --- /dev/null +++ b/Source/CPM3/hbios.z80 @@ -0,0 +1,90 @@ + +; +BF_CIO EQU 000h +BF_CIOIN EQU BF_CIO + 0 ; CHARACTER INPUT +BF_CIOOUT EQU BF_CIO + 1 ; CHARACTER OUTPUT +BF_CIOIST EQU BF_CIO + 2 ; CHARACTER INPUT STATUS +BF_CIOOST EQU BF_CIO + 3 ; CHARACTER OUTPUT STATUS +BF_CIOINIT EQU BF_CIO + 4 ; INIT/RESET DEVICE/LINE CONFIG +BF_CIOQUERY EQU BF_CIO + 5 ; REPORT DEVICE/LINE CONFIG +BF_CIODEVICE EQU BF_CIO + 6 ; REPORT DEVICE INFO +; +; +BF_DIO EQU 010h +BF_DIOSTATUS EQU BF_DIO + 0 ; DISK STATUS +BF_DIORESET EQU BF_DIO + 1 ; DISK RESET +BF_DIOSEEK EQU BF_DIO + 2 ; DISK SEEK +BF_DIOREAD EQU BF_DIO + 3 ; DISK READ SECTORS +BF_DIOWRITE EQU BF_DIO + 4 ; DISK WRITE SECTORS +BF_DIOVERIFY EQU BF_DIO + 5 ; DISK VERIFY SECTORS +BF_DIOFORMAT EQU BF_DIO + 6 ; DISK FORMAT TRACK +BF_DIODEVICE EQU BF_DIO + 7 ; DISK DEVICE INFO REPORT +BF_DIOMEDIA EQU BF_DIO + 8 ; DISK MEDIA REPORT +BF_DIODEFMED EQU BF_DIO + 9 ; DEFINE DISK MEDIA +BF_DIOCAP EQU BF_DIO + 10 ; DISK CAPACITY REPORT +BF_DIOGEOM EQU BF_DIO + 11 ; DISK GEOMETRY REPORT +; +BF_EXT EQU 0E0h +BF_EXTSLICE EQU BF_EXT + 0 ; SLICE CALCULATION (WAS BF_SYSGET_DIOMED) +; +BF_SYS EQU 0F0h +BF_SYSRESET EQU BF_SYS + 0 ; SOFT RESET HBIOS +BF_SYSVER EQU BF_SYS + 1 ; GET HBIOS VERSION +BF_SYSSETBNK EQU BF_SYS + 2 ; SET CURRENT BANK +BF_SYSGETBNK EQU BF_SYS + 3 ; GET CURRENT BANK +BF_SYSSETCPY EQU BF_SYS + 4 ; BANK MEMORY COPY SETUP +BF_SYSBNKCPY EQU BF_SYS + 5 ; BANK MEMORY COPY +BF_SYSALLOC EQU BF_SYS + 6 ; ALLOC HBIOS HEAP MEMORY +BF_SYSFREE EQU BF_SYS + 7 ; FREE HBIOS HEAP MEMORY +BF_SYSGET EQU BF_SYS + 8 ; GET HBIOS INFO +BF_SYSSET EQU BF_SYS + 9 ; SET HBIOS PARAMETERS +BF_SYSPEEK EQU BF_SYS + 10 ; GET A BYTE VALUE FROM ALT BANK +BF_SYSPOKE EQU BF_SYS + 11 ; SET A BYTE VALUE IN ALT BANK +BF_SYSINT EQU BF_SYS + 12 ; MANAGE INTERRUPT VECTORS +; +; 2 BYTE FUNCTION/SUBFUNCTION : BC_ => BIOS CALL -> LOAD TO BC REGISTER +; +BC_SYSGET_CIOCNT EQU 0F800h ; GET CHAR UNIT COUNT +BC_SYSGET_CIOFN EQU 0F801h ; GET CIO UNIT FN/DATA ADR +BC_SYSGET_DIOCNT EQU 0F810h ; GET DISK UNIT COUNT +BC_SYSGET_DIOFN EQU 0F811h ; GET DIO UNIT FN/DATA ADR +BC_SYSGET_RTCCNT EQU 0F820h ; GET RTC UNIT COUNT +BC_SYSGET_DSKYCNT EQU 0F830h ; GET DSKY UNIT COUNT +BC_SYSGET_VDACNT EQU 0F840h ; GET VDA UNIT COUNT +BC_SYSGET_VDAFN EQU 0F841h ; GET VDA UNIT FN/DATA ADR +BC_SYSGET_SNDCNT EQU 0F850h ; GET VDA UNIT COUNT +BC_SYSGET_SNDFN EQU 0F851h ; GET SND UNIT FN/DATA ADR +BC_SYSGET_TIMER EQU 0F8D0h ; GET CURRENT TIMER VALUE +BC_SYSGET_SECS EQU 0F8D1h ; GET CURRENT SECONDS VALUE +BC_SYSGET_BOOTINFO EQU 0F8E0h ; GET BOOT INFORMATION +BC_SYSGET_CPUINFO EQU 0F8F0h ; GET CPU INFORMATION +BC_SYSGET_MEMINFO EQU 0F8F1h ; GET MEMORY CAPACTITY INFO +BC_SYSGET_BNKINFO EQU 0F8F2h ; GET BANK ASSIGNMENT INFO +BC_SYSGET_CPUSPD EQU 0F8F3h ; GET CLOCK SPEED & WAIT STATES +BC_SYSGET_PANEL EQU 0F8F4h ; GET FRONT PANEL SWITCHES VAL +BC_SYSGET_APPBNKS EQU 0F8F5h ; GET APP BANK INFORMATION +; +BC_SYSSET_TIMER EQU 0F9D0h ; SET TIMER VALUE +BC_SYSSET_SECS EQU 0F9D1h ; SET SECONDS VALUE +BC_SYSSET_BOOTINFO EQU 0F9E0h ; SET BOOT INFORMATION +BC_SYSSET_CPUSPD EQU 0F9F3h ; SET CLOCK SPEED & WAIT STATES +BC_SYSSET_PANEL EQU 0F9F4h ; SET FRONT PANEL LEDS +; +; +; +ERR_NONE EQU 0 ; SUCCESS +; +ERR_UNDEF EQU -1 ; UNDEFINED ERROR +ERR_NOTIMPL EQU -2 ; FUNCTION NOT IMPLEMENTED +ERR_NOFUNC EQU -3 ; INVALID FUNCTION +ERR_NOUNIT EQU -4 ; INVALID UNIT NUMBER +ERR_NOMEM EQU -5 ; OUT OF MEMORY +ERR_RANGE EQU -6 ; PARAMETER OUT OF RANGE +ERR_NOMEDIA EQU -7 ; MEDIA NOT PRESENT +ERR_NOHW EQU -8 ; HARDWARE NOT PRESENT +ERR_IO EQU -9 ; I/O ERROR +ERR_READONLY EQU -10 ; WRITE REQUEST TO READ-ONLY MEDIA +ERR_TIMEOUT EQU -11 ; DEVICE TIMEOUT +ERR_BADCFG EQU -12 ; INVALID CONFIGURATION +ERR_INTERNAL EQU -13 ; INTERNAL ERROR +