You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

371 lines
8.2 KiB

;
;-----------------------------------------------------------------------
; p-System BIOS for RomWBW HBIOS
;
;-----------------------------------------------------------------------
;
; 3:46 PM 1/13/2023 - WBW - Initial release
;
; TODO:
;
; - Assign the HBIOS console device to the p-System console instead
; of just using a hard-coded reference to Serial Unit 0.
;
; - Implement Extended BIOS.
;
#include "../ver.inc"
;
#include "psys.inc"
;
#include "../HBIOS/hbios.inc"
;
; IORESULT values
;
ior_ok .equ 0 ; No error
ior_badblk .equ 1 ; Bad block, CRC error (parity)
ior_baddev .equ 2 ; Bad device number
ior_badio .equ 3 ; Illegal I/O request
ior_timout .equ 4 ; Data-com timeout
ior_offlin .equ 5 ; Volume is no longer on-line
ior_nofile .equ 6 ; File is no longer in directory
ior_filnamerr .equ 7 ; Illegal file name
ior_full .equ 8 ; No room; insufficient space on disk
ior_novol .equ 9 ; No such volume on-line
ior_notfnd .equ 10 ; No such file name in directory
ior_dupfil .equ 11 ; Duplicate file
ior_notclos .equ 12 ; Not closed: attempt to open an open file
ior_notopen .equ 13 ; Not open: attempt to access a closed file
ior_badfmt .equ 14 ; Bad format: error reading real or integer
ior_bufovr .equ 15 ; Ring buffer overflow
ior_diskwp .equ 16 ; Write attempt to protected disk
ior_blknumerr .equ 17 ; Illegal block number
ior_bufadrerr .equ 18 ; Illegal buffer address
ior_badsiz .equ 19 ; Bad text file size
;
;
;
.org bios_loc
;
; Simple BIOS vectors
jp sysinit ; 0: Initialize machine
jp syshalt ; 1: Exit UCSD Pascal
jp coninit ; 2: Console initialize
jp constat ; 3: Console status
jp conread ; 4: Console input
jp conwrit ; 5: Console output
jp setdisk ; 6: Set disk number
jp settrak ; 7: Set track number
jp setsect ; 8: Set sector number
jp setbufr ; 9: Set buffer address
jp dskread ; 10: Read sector from disk
jp dskwrit ; 11: Write sector to disk
jp dskinit ; 12: Reset disk
jp dskstrt ; 13: Activate disk
jp dskstop ; 14: De-activate disk
;
; Extended BIOS vectors
jp panic ; 15: Extended BIOS vector
jp panic ; 16: Extended BIOS vector
jp panic ; 17: Extended BIOS vector
jp panic ; 18: Extended BIOS vector
jp panic ; 19: Extended BIOS vector
jp panic ; 20: Extended BIOS vector
jp panic ; 21: Extended BIOS vector
jp panic ; 22: Extended BIOS vector
jp panic ; 23: Extended BIOS vector
jp panic ; 24: Extended BIOS vector
jp panic ; 25: Extended BIOS vector
jp panic ; 26: Extended BIOS vector
jp panic ; 27: Extended BIOS vector
;
;
;
sysinit:
;ld a,0
;jp panic
ld hl,str_banner
call prtstr
call conread
ld b,BF_SYSGET ; HBIOS SysGet function
ld c,BF_SYSGET_BOOTINFO ; BootInfo sub-function
rst 08 ; do it, boot disk device unit in
ld a,d ; boot unit id returned in D
ld (hb_dev),a ; save for disk I/O
; sysinit is being called twice during startup. Once from
; the bootstrap and then from the interpreter. So, we
; remap the vector here to avoid doing the above stuff
; multiple times.
ld hl,sysinit1 ; re-vector to sysinit1
ld (bios_loc+1),hl ; update the jump table
sysinit1:
xor a ; signal success
ret ; done
syshalt:
;ld a,1
;jp panic
; The syshalt vector does not seem be to invoked when
; selecting the Halt option from the p-System menu.
; I have no idea why.
ld b,BF_SYSRESET ; HBIOS reset function
ld c,BF_SYSRES_WARM ; warm reset is fine
rst 08 ; do it
; we should never get here
di ; interrupts off
halt ; ... and die
coninit:
;ld a,2
;jp panic
xor a ; signal success
ret ; done
constat:
;ld a,3
;jp panic
ld b,BF_CIOIST ; serial port status function
ld c,0 ; port 0
rst 08 ; call HBIOS
ld c,0 ; assume no chars pendin
jr z,constat1 ; if zero, no chars waiting
ld c,$FF ; signal char(s) pending
constat1:
xor a ; signal success
ret ; done
conread:
;ld a,4
;jp panic
ld b,BF_CIOIN ; serial port read function
ld c,0 ; port 0
rst 08 ; call HBIOS
ld c,e ; char to C
xor a ; signal success
ret ; done
conwrit:
;ld a,5
;jp panic
ld a,c
cp 27 ; escape?
jr nz,conwrit1 ; if not, handle normally
call conwrit1 ; else, send escape
ld c,'[' ; ... followed by '[' for ANSI
conwrit1:
ld e,c ; char to write to E
ld b,BF_CIOOUT ; serial port write function
ld c,0 ; port 0
rst 08 ; call HBIOS
xor a ; signal success
ret ; done
setdisk:
;ld a,6
;jp panic
ld a,c ; disk number to A
ld (curdisk),a ; save for later
xor a ; signal success
ret ; done
settrak:
;ld a,7
;jp panic
ld a,c ; track number to A
ld (curtrak),a ; save for later
xor a ; signal success
ret ; done
setsect:
;ld a,8
;jp panic
ld a,c ; sector number to A
dec a ; from 1 indexed to 0 indexed
ld (cursect),a ; save for later
xor a ; signal success
ret
setbufr:
;ld a,9
;jp panic
ld (curbufr),bc ; save buf adr for later
xor a ; signal success
ret ; done
dskread:
;ld a,10
;jp panic
;ld a,(curdisk)
;cp 0
;jr nz,dskinit1
call chkdisk
ret nz
call seek
ret nz
ld b,BF_DIOREAD ; HBIOS disk read function
ld a,(hb_dev) ; HBIOS disk unit
ld c,a ; ... goes in C
ld a,(HB_CURBNK) ; get current memory bank
ld d,a ; use as target bank for transfer
ld e,1 ; read 1 sector
ld hl,(curbufr) ; disk read buffer adr
rst 08 ; do it
ret z ; return if good read
ld a,ior_badblk ; else i/o error
ret ; done
dskwrit:
;ld a,11
;jp panic
call chkdisk
ret nz
call seek
ret nz
ld b,BF_DIOWRITE ; HBIOS disk read function
ld a,(hb_dev) ; HBIOS disk unit
ld c,a ; ... goes in C
ld a,(HB_CURBNK) ; get current memory bank
ld d,a ; use as target bank for transfer
ld e,1 ; read 1 sector
ld hl,(curbufr) ; disk read buffer adr
rst 08 ; do it
ret z ; return if good read
ld a,ior_badblk ; else i/o error
ret ; done
dskinit:
;ld a,12
;jp panic
call chkdisk
ret nz
xor a ; signal success
ret ; done
dskstrt:
;ld a,13
;jp panic
xor a ; signal success
ret ; done
dskstop:
;ld a,14
;jp panic
xor a ; signal success
ret ; done
chkdisk:
; Validate that curdisk is <= max supported
ld a,(curdisk) ; get current disk
cp disks ; compare to disk count
jr nc,chkdisk1 ; if too high, go to err
xor a ; signal success
ret ; done
chkdisk1:
ld a,ior_novol ; signal not online
or a
ret
seek:
; A single physical HBIOS disk device will contain p-System
; volume slices. Each slice will be 8MB. Start by computing
; a track offset using the p-System disk number as an
; index. <Track Offset> = 8MB * <Disk Number>
; A track contains 0x20000 bytes:
; 512 (bytes per sec) * 16 (sec per trk) * 16 (hds per cyl)
; So, 8MB / 0x20000 = 0x40 tracks
ld hl,0 ; starting unit track offset
ld de,$0040 ; per disk track offset
ld a,(curdisk) ; get current disk
or a ; set flags
jr z,seek2 ; disk 0 needs no offset
ld b,a ; into B for loop counter
seek1:
add hl,de ; add another offset
djnz seek1 ; and loop as needed
seek2:
push hl ; save total track offset
ld a,(curtrak) ; get current track value
push af ; save track value
and $0F ; head is low 4 bits of track
ld d,a ; save in D for head
pop af ; recover original track value
rra ; rotate to remove head bits
rra
rra
rra
and $0F ; mask off other bits
ld l,a ; save in low byte of HL
ld h,0 ; zero out high byte of HL
ld a,(cursect) ; get sector
ld e,a ; put in E
pop bc
add hl,bc ; add track offset
ld b,BF_DIOSEEK ; HBIOS seek function
ld a,(hb_dev) ; HBIOS disk unit
ld c,a ; ... goes in C
rst 08 ; do it
ret z ; if no error, done
ld a,ior_badblk ; signal I/O error
ret ; done
prtstr:
ld a,(hl)
or a
ret z
push hl
ld c,a
call conwrit
pop hl
inc hl
jr prtstr
panic:
di
halt
hb_dev .db 3 ; HBIOS disk device unit
;
curdisk .db 0 ; Current disk number
curtrak .db 0 ; Current track number
cursect .db 0 ; Current sector number
curbufr .dw 0 ; Current disk buffer address
;
str_banner .db 13,10,"RomWBW p-System BIOS v"
.db BIOSVER
.db 13,10,13,10
.db "Press any key...",0
;
;
;
.fill bios_end - $
;
.end