home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
A
/
BIOS2RSX.LZH
/
BIOS2RSX.ASM
next >
Wrap
Assembly Source File
|
1991-01-16
|
12KB
|
540 lines
;
title 'CP/M 2.2 BIOS RSX'
;
; 18Jan84 By Mike Griswold
;
; This RSX will provide CP/M 2.2 compatible BIOS support
; for CP/M 3.x. Primarily it performs logical sector
; blocking and deblocking needed for some programs.
; All actual I/O is done by the CP/M 3.0 BIOS.
;
; Typed in from the Dr. Dobb's Journal article in the July 84
; issue. mabry
;
; Modified 9 July 1984 to run on an 8085 rather than just a Z80 !
; Also added trap for BDOS call 12 (version number) and returns
; the indication that the calling program is running under
; version 2.2 of CP/M. This is necessary for programs that
; are written to trap a CP/M Plus environment but not able to
; handle the physical sector I/O of a CP/M Plus BIOS.
; mabry
;
cseg
;
; This equate is the only hardware dependent value.
; It should be set to the largest sector size that
; will be used.
;
max$sector$size: equ 256
cr equ 0dh
lf equ 0ah
;
;
; RSX prefix structure
;
db 0,0,0,0,0,0
entry: jmp boot
next: db jmp ; jump
dw 0 ; next module in line
prev: dw 0 ; previous module
remove: db 0ffh ; remove flag
nonbmk: db 0
db 'BIOS2.21'
db 0,0,0
;
; The CP/M 3.0 BIOS jump table is copied here
; to allow easy access to 1st routines. The disk
; I/O routines are potentially in banked memory
; so they cannot be called directly.
;
xwboot: jmp 0 ; warm boot
xconst: jmp 0
xconin: jmp 0
xconout:jmp 0
xlist: jmp 0
xauxout:jmp 0
xauxin: jmp 0
jmp 0
jmp 0
jmp 0
jmp 0
jmp 0
jmp 0
jmp 0
xlistst:jmp 0
;
; Signon message
;
signon: db cr,lf,'BIOS ver 2.21 ACTIVE',cr,lf,0
;
; Cold boot
;
boot: push psw ; a BDOS call is in progress, save cpu state
push h ; so save cpu state
push d
push b
lda first ; is this the first time through ?
ora a
jz boot10 ; jump if no
xra a ; reset first time through flag
sta first
call init ; initialize BIOS variables
lhld 1 ; save the CP/M 3.0 BIOS jump
shld old$addr ; at location 0
lxi d,xwboot ; set up to move jump table
lxi b,15*3 ; byte count
; ldir
boot05:
mov a,m
stax d
inx h
inx d
dcr c ; This is cheating, but 15*3 < 256
jnz boot05
lxi h,wbt ; substitute new jump address
shld 1
lxi h,signon ; sound off
call prmsg
;
; We check to see if CP/M version number is requested via BDOS
; function 12. If so, return 2.2.
;
boot10:
mov a,c ; BDOS function number
cpi 12 ; version call ?
jnz boot15 ; if no, then continue
pop b
pop d
pop h
pop psw
lxi h,0022h ; flag CP/M and version 2.2
ret
boot15:
pop b ; restore BDOS call state
pop d
pop h
pop psw
jmp next ; carry on
;
; Warm boot
;
wboot: lhld old$addr
shld 1 ; restore normal BIOS address
jmp 0 ; jump to CP/M 3.0 warm boot
;
; Initialize BIOS internal variables for cold boot
;
init: xra a
sta hstwrt ; host buffer written
sta hstact ; host buffer inactive
lxi h,80h
shld dmaadr
ret
;
; Routine to call banked BIOS routines via BDOS
; function 50. All disk I.O calls are made through
; here.
;
xbios: sta biospb ; set BIOS function
mvi c,50 ; direct BIOS call function
lxi d,biospb ; BIOS parameter block
jmp next ; jump to BDOS
;
biospb: db 0 ; BIOS function
areg: db 0 ; A register
bcreg: dw 0 ; BC register
dereg: dw 0 ; DE register
hlreg: dw 0 ; HL register
;
; Home disk.
;
home: lda hstwrt ; check if pending write
ora a
cnz writehst ; dump buffer to disk
xra a
sta hstwrt ; buffer written
sta hstact ; buffer inactive
sta unacnt ; zero alloc count
sta sektrk ; zero track count
sta sektrk+1
ret
;
; Set track.
;
settrk:;sbcd sektrk
mov l,c ; track number to HL
mov h,b
shld sektrk
ret
;
; Align jump table on next page boundary. This is needed
; for programs that cheat when getting the addresses of
; BIOS jump table entries.
;
ds 16
;
; BIOS Jump Table
;
cbt: jmp wboot ; cold boot entry
wbt: jmp wboot ; warm boot entry
jmp xconst ; console status
jmp xconin ; console input
jmp xconout ; console output
jmp xlist ; list output
jmp xauxout ; aux device output
jmp xauxin ; aux device input
jmp home ; home disk head
jmp seldsk ; select drive
jmp settrk ; select track
jmp setsec ; select sector
jmp setdma ; set dma address
jmp read ; read a sector
jmp write ; write a sector
jmp xlistst ; list status
jmp sectran ; sector translation
;
; Select disk. Create a fake DPH for programs
; that might use it.
;
seldsk: mov a,c ; requested drive number
sta sekdsk
sta bcreg ; set C reg in BIOSPB
mvi a,9 ; BIOS function number
call xbios ; CP/M 3.0 select
mov a,h
ora l ; check for HL=0
rz ; select error
mov e,m ; get address of xlat table
inx h
mov d,m
xchg
shld xlat ; save xlat address
lxi h,11 ; offset to dpb address
dad d
mov e,m ; fetch address of dpb
inx h
mov d,m
xchg
shld dpb ; address of dpb
mov a,m ; cpm sectors per track
sta spt
inx h
inx h ; point to block shift mask
inx h
mov a,m
sta bsm ; save block shift mask
lxi d,12 ; offset to psh
dad d
mov a,m
sta psh ; save physical shift factor
lxi h,dph ; return DPH address
ret
;
; This fake DPH holds the adresses of the actual
; DPB. The CP/M 3.0 DPH is *not* understood
; by CP/M 2.2 programs.
;
dph: equ $
dw 0 ; no translation
ds 6 ; scratch words
ds 2 ; directory buffer
dpb: ds 2 ; DPB
ds 2 ; CSV
ds 2 ; ALV
;
; Set dma.
;
setdma:;sbcd dmaadr
mov l,c ; dma number to HL
mov h,b
shld dmaadr
ret
;
; Translate sectors. Sectors are not translated yet.
; Wait until we know the physical sector number.
; This works fine as long as the program trusts
; the BIOS to do the translation. Some programs
; access the XLAT table directly to do their own
; translation. These programs will get the wrong
; idea about the disk skew but it should cause no
; harm.
;
sectran:mov l,c ; return sector in HL
mov h,b
ret
;
; Set sector number.
;
setsec: mov a,c
sta seksec
ret
;
; Read the selected CP/M sector.
;
read: mvi a,1
sta readop ; read operation
inr a ; a=2 (wrual)
sta wrtype ; treat as unalloc
jmp alloc ; perform read
;
; Write the selected CP/M sector.
;
write: xra a
sta readop ; not a read operation
mov a,c
sta wrtype ; save write type
cpi 2 ; unalloc block?
jnz chkuna
;
; Write to first sector of unallocated block.
;
lda bsm ; get block shift mask
inr a ; adjust value
sta unacnt ; unalloc record count
lda sekdsk ; set up values for
sta unadsk ; writing to an unallocated
lda sektrk ; block
sta unatrk
lda seksec
sta unasec
;
chkuna: lda unacnt ; any unalloc sectors
ora a ; in this block?
jz alloc ; skip if not
dcr a ; unacnt = unacnt - 1
sta unacnt
lda sekdsk
lxi h,unadsk
cmp m ; sekdsk = unadsk ?
jnz alloc ; skip if not
lda sektrk
lxi h,unatrk
cmp m ; sektrk = unatrk ?
jnz alloc ; skip if not
lda seksec
lxi h,unasec
cmp m ; seksec = unasec ?
jnz alloc ; skip if not
inr m ; move to next sector
mov a,m
lxi h,spt ; addr of spt
cmp m ; sector > spt ?
jc noovf ; skip if no overflow
lhld unatrk
inx h
shld unatrk ; bump rack
xra a
sta unasec ; reset sector count
noovf: xra a
sta rsflag ; don't pre-read
jmp rwoper ; perform write
;
alloc: xra a ; requires pre-read
sta unacnt
inr a
sta rsflag ; force pre-read
;
rwoper: xra a
sta erflag ; no errors yet
lda psh ; get physical shift factor
ora a ; set flags
mov b,a
lda seksec ; logical sector
lxi h,hstbuf ; addr of buffer
lxi d,128
jz noblk ; no blocking
xchg ; shuffle registers
shift: xchg
rrc
jnc sh1
dad d ; bump buffer address
sh1: xchg
dad h ; double offset
ani 07fh ; zero high bit
; djnz shift
dcr b
jnz shift
xchg ; HL=buffer addr
noblk: sta sekhst
shld sekbuf
lxi h,hstact ; buffer active flag
mov a,m
mvi m,1 ; set buffer active
ora a ; was it already?
jz filhst ; fill buffer if not
lda sekdsk
lxi h,hstdsk ; same disk ?
cmp m
jnz nomatch
lda sektrk
lxi h,hsttrk ; same track ?
cmp m
jnz nomatch
lda sekhst ; same buffer ?
lxi h,hstsec
cmp m
jz match
;
nomatch:
lda hstwrt ; buffer changed?
ora a
cnz writehst ; clear buffer
filhst: lda sekdsk
sta hstdsk
lhld sektrk
shld hsttrk
lda sekhst
sta hstsec
lda rsflag ; need to read ?
ora a
cnz readhst ; yes
xra a
sta hstwrt ; no pending write
;
match: lhld dmaadr
xchg
lhld sekbuf
lda readop ; which way to move ?
ora a
jnz rwmove ; skip if read
mvi a,1
sta hstwrt ; mark buffer changed
xchg ; hl=dma de=buffer
;
rwmove: lxi b,128 ; byte count
; ldir ; block move
rwmv05:
mov a,m
stax d
inx h
inx d
dcr c ; This is cheating, but 128 < 256
jnz rwmv05
lda wrtype ; write type
cpi 1 ; to directory ?
jnz exit ; done
lda erflag ; check for errors
ora a
jnz exit ; don't write dir if so
xra a
sta hstwrt ; show buffer written
call writehst ; write buffer
exit: lda erflag
ret
;
; Disk read. Call CP/M 3.0 BIOS to fill the buffer
; with one physical sector.
;
readhst:
call rw$init ; init CP/M 3.0 BIOS
mvi a,13 ; read function number
call xbios ; read sector
sta erflag
ret
;
; Disk write. Call CP/M 3.0 BIOS to write one
; physical sector from buffer.
;
writehst:
call rw$init ; init CP/M 3.0 BIOS
mvi a,14 ; write function number
call xbios ; write sector
sta erflag
ret
;
; Translate sector. Set CP/M 3.0 track, sector,
; DMA buffer and DMA bank.
;
rw$init:
lda hstsec ; physical sector number
mov l,a
mvi h,0
shld bcreg ; sector number in BC
lhld xlat ; address of xlat table
shld dereg ; xlat address in DE
mvi a,16 ; sectrn function number
call xbios ; get skewed sector number
mov a,l
sta actsec ; actual sector
shld bcreg ; sector number in BC
mvi a,11 ; setsec function number
call xbios ; set CP/M 3.0 sector
lhld hsttrk ; physical track number
shld bcreg ; track number in BC
mvi a,10 ; settrk function number
call xbios
lxi h,hstbuf ; sector buffer
shld bcreg ; buffer address in BC
mvi a,12 ; setdma function number
call xbios
mvi a,1 ; DMA bank number
sta areg ; bank number in A
mvi a,28 ; setbnk function number
call xbios ; set DMA bank
ret
;
; Print message at HL until null.
;
prmsg: mov a,m
ora a
rz
mov c,m
push h
call xconout
pop h
inx h
jmp prmsg
;
; disk i/o buffer
;
hstbuf: ds max$sector$size
;
; variable storage area
;
sekdsk: ds 1 ; logical disk number
sektrk: ds 2 ; logical track number
seksec: ds 1 ; logical sector number
;
hstdsk: ds 1 ; physical disk number
hsttrk: ds 2 ; physical track number
hstsec: ds 1 ; physical sector number
;
actsec: ds 1 ; skewed physical sector
sekhst: ds 1 ; temp physical sector
hstact: ds 1 ; buffer ative flag
hstwrt: ds 1 ; buffer changed flag
;
unacnt: ds 1 ; unallocated sector cunt
unadsk: ds 1 ; unalloc disk number
unatrk: ds 2 ; unalloc track number
unasec: ds 1 ; unalloc sector number
sekbuf: ds 2 ; logical sector address in buffer
;
spt: ds 1 ; cpm sectors per track
xlat: ds 2 ; xlat address
bsm: ds 1 ; block shift mask
psh: ds 1 ; physical shift factor
;
erflag: ds 1 ; error reporting
rsflag: ds 1 ; force sector read
readop: ds 1 ; 1 if read operation
rwflag: ds 1 ; physical read flag
wrtype: ds 1 ; write operation type
dmaadr: ds 2 ; last dma address
oldaddr:ds 2 ; address of old BIOS
;
first: db 0ffh ; first time through flag, set on load
end