Browse Source

CPM3 Loader Using New HBIOS SLICE Function

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

140
Source/CPM3/biosldr.z80

@ -9,6 +9,8 @@
extrn cin, cout
extrn crlf, crlf2
include hbios.z80
debug equ false
; BIOS Jump vector.
@ -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
@ -343,7 +278,7 @@ read:
; 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?
@ -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 $

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