Browse Source

CPM3 Loader Using New HBIOS SLICE Function

pull/439/head
Mark Pruden 1 year ago
parent
commit
221b1b408c
  1. 158
      Source/CPM3/biosldr.z80
  2. 90
      Source/CPM3/hbios.z80

158
Source/CPM3/biosldr.z80

@ -4,11 +4,13 @@
maclib cpm3.lib maclib cpm3.lib
cseg cseg
extrn phex16, phex8 extrn phex16, phex8
extrn cin, cout extrn cin, cout
extrn crlf, crlf2 extrn crlf, crlf2
include hbios.z80
debug equ false debug equ false
; BIOS Jump vector. ; BIOS Jump vector.
@ -65,7 +67,7 @@ boot:
; this routine to avoid issues. ; this routine to avoid issues.
ld (stksav),sp ld (stksav),sp
ld sp,stack ld sp,stack
; Do the real work ; Do the real work
call boot0 call boot0
@ -78,6 +80,10 @@ boot0:
if cmdline if cmdline
boot1: 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 ; Get disk unit from user
ld de,msgunit ; disk unit prompt ld de,msgunit ; disk unit prompt
call writestr ; display on console call writestr ; display on console
@ -88,7 +94,7 @@ boot1:
sub '0' ; convert to binary sub '0' ; convert to binary
ld (unit),a ; save it ld (unit),a ; save it
jr c,selerr ; loop if below 0 entered 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 call 0FFF0h ; do it, E := disk unit count
ld a,(unit) ; get unit num back ld a,(unit) ; get unit num back
cp e ; compare to entry cp e ; compare to entry
@ -118,7 +124,7 @@ selerr:
boot2: boot2:
; Record unit & slice w/ HBIOS ; 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 a,(unit) ; get unit
ld d,a ; put in D ld d,a ; put in D
ld a,(slice) ; get slice ld a,(slice) ; get slice
@ -128,8 +134,13 @@ boot2:
else 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 ; 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 call 0FFF0h ; do it, D := boot unit, E: := slice
ld a,d ; move unit to A ld a,d ; move unit to A
ld (unit),a ; save it ld (unit),a ; save it
@ -138,103 +149,27 @@ boot2:
endif 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 ; Sense media to determine media format
ld a,(unit) ; Get boot unit 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 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: boot8:
ld (lba),hl ; save new lba, low word ld (lba),hl ; save new lba, low word
ld (lba+2),de ; save new lba, high word ld (lba+2),de ; save new lba, high word
@ -277,7 +212,7 @@ conin:
conout: conout:
ld e,c ; output character in E ld e,c ; output character in E
ld bc,0180h ; unit 80h (console), func 1 = COUT ld bc,0180h ; unit 80h (console), func 1 = COUT
jp 0FFF0h
jp 0FFF0h
list: list:
ld a,85H ld a,85H
halt halt
@ -311,7 +246,7 @@ setdma:
call crlf call crlf
call phex16 call phex16
pop hl pop hl
endif endif
ld (dma),bc ld (dma),bc
@ -337,18 +272,18 @@ read:
call phex16 call phex16
ld hl,(lba+0) ld hl,(lba+0)
call phex16 call phex16
endif endif
; Check device type ; Check device type
ld a,(unit) ; get unit ld a,(unit) ; get unit
ld c,a ; BIOS Disk Unit in C 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 rst 08 ; Do it, D=device type
ld a,d ; put in accum ld a,d ; put in accum
cp 01h ; floppy? cp 01h ; floppy?
jr nz,read2 ; if not, do LBA i/o jr nz,read2 ; if not, do LBA i/o
; Floppy I/O ; Floppy I/O
ld de,(sect) ; sector -> de, head(d) becomes zero ld de,(sect) ; sector -> de, head(d) becomes zero
ld hl,(trk) ; track -> hl (low bit has head) ld hl,(trk) ; track -> hl (low bit has head)
@ -356,7 +291,7 @@ read:
rr l ; ... and into carry rr l ; ... and into carry
rl d ; carry bit (head) into d rl d ; carry bit (head) into d
jr read3 ; do the disk i/o jr read3 ; do the disk i/o
; LBA I/O ; LBA I/O
read2: read2:
ld hl,(trk) ; get track ld hl,(trk) ; get track
@ -386,7 +321,7 @@ read3:
call phex16 call phex16
ex de,hl ex de,hl
call phex16 call phex16
endif endif
; DE:HL has sector address to read (LBA or CHS) ; DE:HL has sector address to read (LBA or CHS)
@ -401,14 +336,14 @@ diskread:
; Seek to requested sector in DE:HL ; Seek to requested sector in DE:HL
push bc ; save unit & count push bc ; save unit & count
ld b,012h ; HBIOS func: seek
ld b,BF_DIOSEEK ; HBIOS func: seek
call 0FFF0h ; do it call 0FFF0h ; do it
pop bc ; recover unit & count pop bc ; recover unit & count
jp nz,err_diskio ; handle error jp nz,err_diskio ; handle error
; Read sector(s) into buffer ; Read sector(s) into buffer
ld e,b ; transfer count 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 hl,(dma) ; read into info sec buffer
ld a,(0FFE0h) ; get current bank ld a,(0FFE0h) ; get current bank
ld d,a ; put in D ld d,a ; put in D
@ -477,7 +412,7 @@ xmove:
;cin: ;cin:
; ; Input character from console via HBIOS ; ; Input character from console via HBIOS
; ld c,080H ; console unit to C ; 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 ; call 0FFF0H ; HBIOS reads character
; ld a,e ; To A for return ; ld a,e ; To A for return
; ret ; done ; ret ; done
@ -486,7 +421,7 @@ xmove:
; ; Output character to console via HBIOS ; ; Output character to console via HBIOS
; ld e,a ; output char to E ; ld e,a ; output char to E
; ld c,080H ; console unit to C ; 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 ; jp 0FFF0H ; output & return
writestr: writestr:
@ -539,7 +474,7 @@ err:
str_err_prefix db "\r\n\r\n*** ","$" str_err_prefix db "\r\n\r\n*** ","$"
str_err_nodisk db "Disk unit not available","$" 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_diskio db "Disk I/O failure","$"
str_err_sig db "No system image on disk","$" str_err_sig db "No system image on disk","$"
str_err_api db "HBIOS API failure","$" str_err_api db "HBIOS API failure","$"
@ -728,7 +663,6 @@ dma ds 2 ; current DMA address
medid ds 1 ; media id medid ds 1 ; media id
lba ds 4 ; current lba lba ds 4 ; current lba
sps ds 2 ; sectors per slice
ds 64 ds 64
stack equ $ stack equ $

90
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
Loading…
Cancel
Save