mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 17:04:19 +00:00
Upload
Digital Research
This commit is contained in:
653
CPM OPERATING SYSTEMS/CPM 3.X/CPM 3.0/SOURCE/bioskrnl.asm
Normal file
653
CPM OPERATING SYSTEMS/CPM 3.X/CPM 3.0/SOURCE/bioskrnl.asm
Normal file
@@ -0,0 +1,653 @@
|
||||
title 'Root module of relocatable BIOS for CP/M 3.0'
|
||||
|
||||
; version 1.0 15 Sept 82
|
||||
|
||||
true equ -1
|
||||
false equ not true
|
||||
|
||||
banked equ true
|
||||
|
||||
|
||||
; Copyright (C), 1982
|
||||
; Digital Research, Inc
|
||||
; P.O. Box 579
|
||||
; Pacific Grove, CA 93950
|
||||
|
||||
|
||||
; This is the invariant portion of the modular BIOS and is
|
||||
; distributed as source for informational purposes only.
|
||||
; All desired modifications should be performed by
|
||||
; adding or changing externally defined modules.
|
||||
; This allows producing "standard" I/O modules that
|
||||
; can be combined to support a particular system
|
||||
; configuration.
|
||||
|
||||
cr equ 13
|
||||
lf equ 10
|
||||
bell equ 7
|
||||
ctlQ equ 'Q'-'@'
|
||||
ctlS equ 'S'-'@'
|
||||
|
||||
ccp equ 0100h ; Console Command Processor gets loaded into the TPA
|
||||
|
||||
cseg ; GENCPM puts CSEG stuff in common memory
|
||||
|
||||
|
||||
; variables in system data page
|
||||
|
||||
extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors
|
||||
extrn @mxtpa ; addr of system entry point
|
||||
extrn @bnkbf ; 128 byte scratch buffer
|
||||
|
||||
; initialization
|
||||
|
||||
extrn ?init ; general initialization and signon
|
||||
extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT
|
||||
|
||||
; user defined character I/O routines
|
||||
|
||||
extrn ?ci,?co,?cist,?cost ; each take device in <B>
|
||||
extrn ?cinit ; (re)initialize device in <C>
|
||||
extrn @ctbl ; physical character device table
|
||||
|
||||
; disk communication data items
|
||||
|
||||
extrn @dtbl ; table of pointers to XDPHs
|
||||
public @adrv,@rdrv,@trk,@sect ; parameters for disk I/O
|
||||
public @dma,@dbnk,@cnt ; '' '' '' ''
|
||||
|
||||
; memory control
|
||||
|
||||
public @cbnk ; current bank
|
||||
extrn ?xmove,?move ; select move bank, and block move
|
||||
extrn ?bank ; select CPU bank
|
||||
|
||||
; clock support
|
||||
|
||||
extrn ?time ; signal time operation
|
||||
|
||||
; general utility routines
|
||||
|
||||
public ?pmsg,?pdec ; print message, print number from 0 to 65535
|
||||
public ?pderr ; print BIOS disk error message header
|
||||
|
||||
maclib modebaud ; define mode bits
|
||||
|
||||
|
||||
; External names for BIOS entry points
|
||||
|
||||
public ?boot,?wboot,?const,?conin,?cono,?list,?auxo,?auxi
|
||||
public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write
|
||||
public ?lists,?sctrn
|
||||
public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl
|
||||
public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov
|
||||
|
||||
|
||||
; BIOS Jump vector.
|
||||
|
||||
; All BIOS routines are invoked by calling these
|
||||
; entry points.
|
||||
|
||||
?boot: jmp boot ; initial entry on cold start
|
||||
?wboot: jmp wboot ; reentry on program exit, warm start
|
||||
|
||||
?const: jmp const ; return console input status
|
||||
?conin: jmp conin ; return console input character
|
||||
?cono: jmp conout ; send console output character
|
||||
?list: jmp list ; send list output character
|
||||
?auxo: jmp auxout ; send auxilliary output character
|
||||
?auxi: jmp auxin ; return auxilliary input character
|
||||
|
||||
?home: jmp home ; set disks to logical home
|
||||
?sldsk: jmp seldsk ; select disk drive, return disk parameter info
|
||||
?sttrk: jmp settrk ; set disk track
|
||||
?stsec: jmp setsec ; set disk sector
|
||||
?stdma: jmp setdma ; set disk I/O memory address
|
||||
?read: jmp read ; read physical block(s)
|
||||
?write: jmp write ; write physical block(s)
|
||||
|
||||
?lists: jmp listst ; return list device status
|
||||
?sctrn: jmp sectrn ; translate logical to physical sector
|
||||
|
||||
?conos: jmp conost ; return console output status
|
||||
?auxis: jmp auxist ; return aux input status
|
||||
?auxos: jmp auxost ; return aux output status
|
||||
?dvtbl: jmp devtbl ; return address of device def table
|
||||
?devin: jmp ?cinit ; change baud rate of device
|
||||
|
||||
?drtbl: jmp getdrv ; return address of disk drive table
|
||||
?mltio: jmp multio ; set multiple record count for disk I/O
|
||||
?flush: jmp flush ; flush BIOS maintained disk caching
|
||||
|
||||
?mov: jmp ?move ; block move memory to memory
|
||||
?tim: jmp ?time ; Signal Time and Date operation
|
||||
?bnksl: jmp bnksel ; select bank for code execution and default DMA
|
||||
?stbnk: jmp setbnk ; select different bank for disk I/O DMA operations.
|
||||
?xmov: jmp ?xmove ; set source and destination banks for one operation
|
||||
|
||||
jmp 0 ; reserved for future expansion
|
||||
jmp 0 ; reserved for future expansion
|
||||
jmp 0 ; reserved for future expansion
|
||||
|
||||
|
||||
; BOOT
|
||||
; Initial entry point for system startup.
|
||||
|
||||
dseg ; this part can be banked
|
||||
|
||||
boot:
|
||||
lxi sp,boot$stack
|
||||
mvi c,15 ; initialize all 16 character devices
|
||||
c$init$loop:
|
||||
push b ! call ?cinit ! pop b
|
||||
dcr c ! jp c$init$loop
|
||||
|
||||
call ?init ; perform any additional system initialization
|
||||
; and print signon message
|
||||
|
||||
lxi b,16*256+0 ! lxi h,@dtbl ; init all 16 logical disk drives
|
||||
d$init$loop:
|
||||
push b ; save remaining count and abs drive
|
||||
mov e,m ! inx h ! mov d,m ! inx h ; grab @drv entry
|
||||
mov a,e ! ora d ! jz d$init$next ; if null, no drive
|
||||
push h ; save @drv pointer
|
||||
xchg ; XDPH address in <HL>
|
||||
dcx h ! dcx h ! mov a,m ! sta @RDRV ; get relative drive code
|
||||
mov a,c ! sta @ADRV ; get absolute drive code
|
||||
dcx h ; point to init pointer
|
||||
mov d,m ! dcx h ! mov e,m ; get init pointer
|
||||
xchg ! call ipchl ; call init routine
|
||||
pop h ; recover @drv pointer
|
||||
d$init$next:
|
||||
pop b ; recover counter and drive #
|
||||
inr c ! dcr b ! jnz d$init$loop ; and loop for each drive
|
||||
jmp boot$1
|
||||
|
||||
cseg ; following in resident memory
|
||||
|
||||
boot$1:
|
||||
call set$jumps
|
||||
call ?ldccp ; fetch CCP for first time
|
||||
jmp ccp
|
||||
|
||||
|
||||
; WBOOT
|
||||
; Entry for system restarts.
|
||||
|
||||
wboot:
|
||||
lxi sp,boot$stack
|
||||
call set$jumps ; initialize page zero
|
||||
call ?rlccp ; reload CCP
|
||||
jmp ccp ; then reset jmp vectors and exit to ccp
|
||||
|
||||
|
||||
set$jumps:
|
||||
|
||||
if banked
|
||||
mvi a,1 ! call ?bnksl
|
||||
endif
|
||||
|
||||
mvi a,JMP
|
||||
sta 0 ! sta 5 ; set up jumps in page zero
|
||||
lxi h,?wboot ! shld 1 ; BIOS warm start entry
|
||||
lhld @MXTPA ! shld 6 ; BDOS system call entry
|
||||
ret
|
||||
|
||||
|
||||
ds 64
|
||||
boot$stack equ $
|
||||
|
||||
|
||||
; DEVTBL
|
||||
; Return address of character device table
|
||||
|
||||
devtbl:
|
||||
lxi h,@ctbl ! ret
|
||||
|
||||
|
||||
; GETDRV
|
||||
; Return address of drive table
|
||||
|
||||
getdrv:
|
||||
lxi h,@dtbl ! ret
|
||||
|
||||
|
||||
|
||||
; CONOUT
|
||||
; Console Output. Send character in <C>
|
||||
; to all selected devices
|
||||
|
||||
conout:
|
||||
|
||||
lhld @covec ; fetch console output bit vector
|
||||
jmp out$scan
|
||||
|
||||
|
||||
; AUXOUT
|
||||
; Auxiliary Output. Send character in <C>
|
||||
; to all selected devices
|
||||
|
||||
auxout:
|
||||
lhld @aovec ; fetch aux output bit vector
|
||||
jmp out$scan
|
||||
|
||||
|
||||
; LIST
|
||||
; List Output. Send character in <C>
|
||||
; to all selected devices.
|
||||
|
||||
list:
|
||||
lhld @lovec ; fetch list output bit vector
|
||||
|
||||
out$scan:
|
||||
mvi b,0 ; start with device 0
|
||||
co$next:
|
||||
dad h ; shift out next bit
|
||||
jnc not$out$device
|
||||
push h ; save the vector
|
||||
push b ; save the count and character
|
||||
not$out$ready:
|
||||
call coster ! ora a ! jz not$out$ready
|
||||
pop b ! push b ; restore and resave the character and device
|
||||
call ?co ; if device selected, print it
|
||||
pop b ; recover count and character
|
||||
pop h ; recover the rest of the vector
|
||||
not$out$device:
|
||||
inr b ; next device number
|
||||
mov a,h ! ora l ; see if any devices left
|
||||
jnz co$next ; and go find them...
|
||||
ret
|
||||
|
||||
|
||||
; CONOST
|
||||
; Console Output Status. Return true if
|
||||
; all selected console output devices
|
||||
; are ready.
|
||||
|
||||
conost:
|
||||
lhld @covec ; get console output bit vector
|
||||
jmp ost$scan
|
||||
|
||||
|
||||
; AUXOST
|
||||
; Auxiliary Output Status. Return true if
|
||||
; all selected auxiliary output devices
|
||||
; are ready.
|
||||
|
||||
auxost:
|
||||
lhld @aovec ; get aux output bit vector
|
||||
jmp ost$scan
|
||||
|
||||
|
||||
; LISTST
|
||||
; List Output Status. Return true if
|
||||
; all selected list output devices
|
||||
; are ready.
|
||||
|
||||
listst:
|
||||
lhld @lovec ; get list output bit vector
|
||||
|
||||
ost$scan:
|
||||
mvi b,0 ; start with device 0
|
||||
cos$next:
|
||||
dad h ; check next bit
|
||||
push h ; save the vector
|
||||
push b ; save the count
|
||||
mvi a,0FFh ; assume device ready
|
||||
cc coster ; check status for this device
|
||||
pop b ; recover count
|
||||
pop h ; recover bit vector
|
||||
ora a ; see if device ready
|
||||
rz ; if any not ready, return false
|
||||
inr b ; drop device number
|
||||
mov a,h ! ora l ; see if any more selected devices
|
||||
jnz cos$next
|
||||
ori 0FFh ; all selected were ready, return true
|
||||
ret
|
||||
|
||||
coster: ; check for output device ready, including optional
|
||||
; xon/xoff support
|
||||
mov l,b ! mvi h,0 ; make device code 16 bits
|
||||
push h ; save it in stack
|
||||
dad h ! dad h ! dad h ; create offset into device characteristics tbl
|
||||
lxi d,@ctbl+6 ! dad d ; make address of mode byte
|
||||
mov a,m ! ani mb$xonxoff
|
||||
pop h ; recover console number in <HL>
|
||||
jz ?cost ; not a xon device, go get output status direct
|
||||
lxi d,xofflist ! dad d ; make pointer to proper xon/xoff flag
|
||||
call cist1 ; see if this keyboard has character
|
||||
mov a,m ! cnz ci1 ; get flag or read key if any
|
||||
cpi ctlq ! jnz not$q ; if its a ctl-Q,
|
||||
mvi a,0FFh ; set the flag ready
|
||||
not$q:
|
||||
cpi ctls ! jnz not$s ; if its a ctl-S,
|
||||
mvi a,00h ; clear the flag
|
||||
not$s:
|
||||
mov m,a ; save the flag
|
||||
call cost1 ; get the actual output status,
|
||||
ana m ; and mask with ctl-Q/ctl-S flag
|
||||
ret ; return this as the status
|
||||
|
||||
cist1: ; get input status with <BC> and <HL> saved
|
||||
push b ! push h
|
||||
call ?cist
|
||||
pop h ! pop b
|
||||
ora a
|
||||
ret
|
||||
|
||||
cost1: ; get output status, saving <BC> & <HL>
|
||||
push b ! push h
|
||||
call ?cost
|
||||
pop h ! pop b
|
||||
ora a
|
||||
ret
|
||||
|
||||
ci1: ; get input, saving <BC> & <HL>
|
||||
push b ! push h
|
||||
call ?ci
|
||||
pop h ! pop b
|
||||
ret
|
||||
|
||||
|
||||
; CONST
|
||||
; Console Input Status. Return true if
|
||||
; any selected console input device
|
||||
; has an available character.
|
||||
|
||||
const:
|
||||
lhld @civec ; get console input bit vector
|
||||
jmp ist$scan
|
||||
|
||||
|
||||
; AUXIST
|
||||
; Auxiliary Input Status. Return true if
|
||||
; any selected auxiliary input device
|
||||
; has an available character.
|
||||
|
||||
auxist:
|
||||
lhld @aivec ; get aux input bit vector
|
||||
|
||||
ist$scan:
|
||||
mvi b,0 ; start with device 0
|
||||
cis$next:
|
||||
dad h ; check next bit
|
||||
mvi a,0 ; assume device not ready
|
||||
cc cist1 ; check status for this device
|
||||
ora a ! rnz ; if any ready, return true
|
||||
inr b ; drop device number
|
||||
mov a,h ! ora l ; see if any more selected devices
|
||||
jnz cis$next
|
||||
xra a ; all selected were not ready, return false
|
||||
ret
|
||||
|
||||
|
||||
; CONIN
|
||||
; Console Input. Return character from first
|
||||
; ready console input device.
|
||||
|
||||
conin:
|
||||
lhld @civec
|
||||
jmp in$scan
|
||||
|
||||
|
||||
; AUXIN
|
||||
; Auxiliary Input. Return character from first
|
||||
; ready auxiliary input device.
|
||||
|
||||
auxin:
|
||||
lhld @aivec
|
||||
|
||||
in$scan:
|
||||
push h ; save bit vector
|
||||
mvi b,0
|
||||
ci$next:
|
||||
dad h ; shift out next bit
|
||||
mvi a,0 ; insure zero a (nonexistant device not ready).
|
||||
cc cist1 ; see if the device has a character
|
||||
ora a
|
||||
jnz ci$rdy ; this device has a character
|
||||
inr b ; else, next device
|
||||
mov a,h ! ora l ; see if any more devices
|
||||
jnz ci$next ; go look at them
|
||||
pop h ; recover bit vector
|
||||
jmp in$scan ; loop til we find a character
|
||||
|
||||
ci$rdy:
|
||||
pop h ; discard extra stack
|
||||
jmp ?ci
|
||||
|
||||
|
||||
; Utility Subroutines
|
||||
|
||||
|
||||
ipchl: ; vectored CALL point
|
||||
pchl
|
||||
|
||||
|
||||
?pmsg: ; print message @<HL> up to a null
|
||||
; saves <BC> & <DE>
|
||||
push b
|
||||
push d
|
||||
pmsg$loop:
|
||||
mov a,m ! ora a ! jz pmsg$exit
|
||||
mov c,a ! push h
|
||||
call ?cono ! pop h
|
||||
inx h ! jmp pmsg$loop
|
||||
pmsg$exit:
|
||||
pop d
|
||||
pop b
|
||||
ret
|
||||
|
||||
?pdec: ; print binary number 0-65535 from <HL>
|
||||
lxi b,table10! lxi d,-10000
|
||||
next:
|
||||
mvi a,'0'-1
|
||||
pdecl:
|
||||
push h! inr a! dad d! jnc stoploop
|
||||
inx sp! inx sp! jmp pdecl
|
||||
stoploop:
|
||||
push d! push b
|
||||
mov c,a! call ?cono
|
||||
pop b! pop d
|
||||
nextdigit:
|
||||
pop h
|
||||
ldax b! mov e,a! inx b
|
||||
ldax b! mov d,a! inx b
|
||||
mov a,e! ora d! jnz next
|
||||
ret
|
||||
|
||||
table10:
|
||||
dw -1000,-100,-10,-1,0
|
||||
|
||||
?pderr:
|
||||
lxi h,drive$msg ! call ?pmsg ; error header
|
||||
lda @adrv ! adi 'A' ! mov c,a ! call ?cono ; drive code
|
||||
lxi h,track$msg ! call ?pmsg ; track header
|
||||
lhld @trk ! call ?pdec ; track number
|
||||
lxi h,sector$msg ! call ?pmsg ; sector header
|
||||
lhld @sect ! call ?pdec ; sector number
|
||||
ret
|
||||
|
||||
|
||||
; BNKSEL
|
||||
; Bank Select. Select CPU bank for further execution.
|
||||
|
||||
bnksel:
|
||||
sta @cbnk ; remember current bank
|
||||
jmp ?bank ; and go exit through users
|
||||
; physical bank select routine
|
||||
|
||||
|
||||
xofflist db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero
|
||||
db -1,-1,-1,-1,-1,-1,-1,-1
|
||||
|
||||
|
||||
|
||||
dseg ; following resides in banked memory
|
||||
|
||||
|
||||
|
||||
; Disk I/O interface routines
|
||||
|
||||
|
||||
; SELDSK
|
||||
; Select Disk Drive. Drive code in <C>.
|
||||
; Invoke login procedure for drive
|
||||
; if this is first select. Return
|
||||
; address of disk parameter header
|
||||
; in <HL>
|
||||
|
||||
seldsk:
|
||||
mov a,c ! sta @adrv ; save drive select code
|
||||
mov l,c ! mvi h,0 ! dad h ; create index from drive code
|
||||
lxi b,@dtbl ! dad b ; get pointer to dispatch table
|
||||
mov a,m ! inx h ! mov h,m ! mov l,a ; point at disk descriptor
|
||||
ora h ! rz ; if no entry in table, no disk
|
||||
mov a,e ! ani 1 ! jnz not$first$select ; examine login bit
|
||||
push h ! xchg ; put pointer in stack & <DE>
|
||||
lxi h,-2 ! dad d ! mov a,m ! sta @RDRV ; get relative drive
|
||||
lxi h,-6 ! dad d ; find LOGIN addr
|
||||
mov a,m ! inx h ! mov h,m ! mov l,a ; get address of LOGIN routine
|
||||
call ipchl ; call LOGIN
|
||||
pop h ; recover DPH pointer
|
||||
not$first$select:
|
||||
ret
|
||||
|
||||
|
||||
; HOME
|
||||
; Home selected drive. Treated as SETTRK(0).
|
||||
|
||||
home:
|
||||
lxi b,0 ; same as set track zero
|
||||
|
||||
|
||||
; SETTRK
|
||||
; Set Track. Saves track address from <BC>
|
||||
; in @TRK for further operations.
|
||||
|
||||
settrk:
|
||||
mov l,c ! mov h,b
|
||||
shld @trk
|
||||
ret
|
||||
|
||||
|
||||
; SETSEC
|
||||
; Set Sector. Saves sector number from <BC>
|
||||
; in @sect for further operations.
|
||||
|
||||
setsec:
|
||||
mov l,c ! mov h,b
|
||||
shld @sect
|
||||
ret
|
||||
|
||||
|
||||
; SETDMA
|
||||
; Set Disk Memory Address. Saves DMA address
|
||||
; from <BC> in @DMA and sets @DBNK to @CBNK
|
||||
; so that further disk operations take place
|
||||
; in current bank.
|
||||
|
||||
setdma:
|
||||
mov l,c ! mov h,b
|
||||
shld @dma
|
||||
|
||||
lda @cbnk ; default DMA bank is current bank
|
||||
; fall through to set DMA bank
|
||||
|
||||
; SETBNK
|
||||
; Set Disk Memory Bank. Saves bank number
|
||||
; in @DBNK for future disk data
|
||||
; transfers.
|
||||
|
||||
setbnk:
|
||||
sta @dbnk
|
||||
ret
|
||||
|
||||
|
||||
; SECTRN
|
||||
; Sector Translate. Indexes skew table in <DE>
|
||||
; with sector in <BC>. Returns physical sector
|
||||
; in <HL>. If no skew table (<DE>=0) then
|
||||
; returns physical=logical.
|
||||
|
||||
sectrn:
|
||||
mov l,c ! mov h,b
|
||||
mov a,d ! ora e ! rz
|
||||
xchg ! dad b ! mov l,m ! mvi h,0
|
||||
ret
|
||||
|
||||
|
||||
; READ
|
||||
; Read physical record from currently selected drive.
|
||||
; Finds address of proper read routine from
|
||||
; extended disk parameter header (XDPH).
|
||||
|
||||
read:
|
||||
lhld @adrv ! mvi h,0 ! dad h ; get drive code and double it
|
||||
lxi d,@dtbl ! dad d ; make address of table entry
|
||||
mov a,m ! inx h ! mov h,m ! mov l,a ; fetch table entry
|
||||
push h ; save address of table
|
||||
lxi d,-8 ! dad d ; point to read routine address
|
||||
jmp rw$common ; use common code
|
||||
|
||||
|
||||
; WRITE
|
||||
; Write physical sector from currently selected drive.
|
||||
; Finds address of proper write routine from
|
||||
; extended disk parameter header (XDPH).
|
||||
|
||||
write:
|
||||
lhld @adrv ! mvi h,0 ! dad h ; get drive code and double it
|
||||
lxi d,@dtbl ! dad d ; make address of table entry
|
||||
mov a,m ! inx h ! mov h,m ! mov l,a ; fetch table entry
|
||||
push h ; save address of table
|
||||
lxi d,-10 ! dad d ; point to write routine address
|
||||
|
||||
rw$common:
|
||||
mov a,m ! inx h ! mov h,m ! mov l,a ; get address of routine
|
||||
pop d ; recover address of table
|
||||
dcx d ! dcx d ; point to relative drive
|
||||
ldax d ! sta @rdrv ; get relative drive code and post it
|
||||
inx d ! inx d ; point to DPH again
|
||||
pchl ; leap to driver
|
||||
|
||||
|
||||
; MULTIO
|
||||
; Set multiple sector count. Saves passed count in
|
||||
; @CNT
|
||||
|
||||
multio:
|
||||
sta @cnt ! ret
|
||||
|
||||
|
||||
; FLUSH
|
||||
; BIOS deblocking buffer flush. Not implemented.
|
||||
|
||||
flush:
|
||||
xra a ! ret ; return with no error
|
||||
|
||||
|
||||
|
||||
; error message components
|
||||
drive$msg db cr,lf,bell,'BIOS Error on ',0
|
||||
track$msg db ': T-',0
|
||||
sector$msg db ', S-',0
|
||||
|
||||
|
||||
; disk communication data items
|
||||
|
||||
@adrv ds 1 ; currently selected disk drive
|
||||
@rdrv ds 1 ; controller relative disk drive
|
||||
@trk ds 2 ; current track number
|
||||
@sect ds 2 ; current sector number
|
||||
@dma ds 2 ; current DMA address
|
||||
@cnt db 0 ; record count for multisector transfer
|
||||
@dbnk db 0 ; bank for DMA operations
|
||||
|
||||
|
||||
cseg ; common memory
|
||||
|
||||
@cbnk db 0 ; bank for processor operations
|
||||
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user