Files
Digital-Research-Source-Code/MPM OPERATING SYSTEMS/MPM II/MPM II SOURCE 2/bdos/conbdos.asm
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

674 lines
16 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;***************************************************************
;***************************************************************
;** **
;** B a s i c D i s k O p e r a t i n g S y s t e m **
;** **
;** C o n s o l e P o r t i o n **
;** **
;***************************************************************
;***************************************************************
cnsfunc:
mov a,c! mov c,e! mov b,d
lxi h,functab! mov e,a! mvi d,0 ;DE=func, HL=.functab
dad d! dad d! mov e,m! inx h! mov d,m ;DE=functab(func)
xchg! pchl ;dispatched
;
; dispatch table for functions
functab:
dw bootf,func1,func2,func3
dw func4,func5,func6,func7
dw cmnret,func9,func10,func11
diskf equ ($-functab)/2
nfuncs equ 41 ;must match with banked bdos # fns
;
func1:
;return console character with echo
call conech
mov l,a! ret
;
func2:
;write console character with tab expansion
call attcns! jmp tabout
;
func3:
;return raw unattached console character
call rawattcns
jmp dirinp
;
func4:
;write raw unattached console character
call rawattcns
jmp conoutf
;
func5:
;write list character
call testlstatt
;write to list device if already attached
jz listf
;else must attach list device first
push b! push d
mvi c,attlst! call xdos
pop d! pop b
jmp listf
;
func6:
;direct console i/o - 0ffh = read/status
; 0feh = status
; 0fdh = read
call rawattcns
mov a,c! inr a! jz stsdirinp
inr a! jz stsinp
inr a! jz dirinp
;direct output function
jmp conoutf
stsdirinp:
push d! call constf! pop d
ora a! jnz dirinp
mvi c,dispatch! call xdos
xra a! mov l,a! ret
stsinp:
;direct console status input
call constf ;to A
mov l,a! ret
dirinp:
lxi h,kbchar! call ofsthl
mov a,m! mvi m,0! ora a
cz coninf ;to A
mov l,a! ret
;
func7:
;return io byte
;*** Not implemented in MP/M ***
xra a
mov l,a! ret
;
;func8:
;set i/o byte
;*** Not implemented in MP/M ***
;ret
;
func9:
;write line until $ encountered
;BC = string address
call attcns! jmp print ;out to console
;
func10:
;read a buffered console line
call attcns! jmp read
;
func11:
;check console status
call testcnsatt
jz doconbrk
mvi c,dispatch! call xdos
xra a! mov l,a! ret
doconbrk:
call conbrk
mov l,a
;
cmnret:
ret
;
tstlivekbd:
;test for simulated 'live keyboard'
;pd.name(3)' = off
call rlr! lxi b,pname+3! dad b! mov a,m! ani 80h
ret
;
testlstatt:
;test to determine if list is attached
;Zero = attached, D = List #
di
call rlr! xchg ;DE = Ready List Root
lxi h,console! dad d! mov a,m! ani 0f0h
rrc! rrc! rrc! rrc! push psw! push b
lxi b,lstatt-rlros! jmp attcmn
;ret
;
testcnsatt:
;test to determine if console is attached
;Zero = attached, D = Console #
di
call rlr! xchg ;DE = Ready List Root
lxi h,console! dad d! mov a,m! ani 0fh
push psw! push b
lxi b,cnsatt-rlros
attcmn:
lhld rlradr! dad b
add a! mov c,a! mvi b,0! dad b
mov a,m! cmp e! inx h! jnz notatt
mov a,m! cmp d! jz testext
notatt:
mov a,m! dcx h! ora m! jnz testext
mov m,e! inx h! mov m,d! xra a ;attach ok
testext:
ei! pop b! pop d
mvi e,0 ;cns req'd flag false
ret
;
rawattcns:
push b! mvi b,80h! jmp attcns0
attcns:
push b! mvi b,0
attcns0:
call rlr
inx h! inx h! inx h! inx h! inx h! inx h
mov a,m! ani 7fh! ora b! mov m,a ;set/reset direct i/o
inx h! inx h! inx h
mov a,m! ani 7fh! ora b! mov m,a ;set/reset simul. live kbd
pop b
;attach console if req'd
call testcnsatt
mvi e,0ffh! rz ;cns req'd flag true
push b! push d!
mvi c,attach! call xdos
pop d! push d ;restore DE
call dsplyatchmsg
pop d! pop b
ret
;
ofsthl:
;offset HL by console # (in D)
push psw
mov a,d! add l! mov l,a
mvi a,0! adc h! mov h,a
pop psw
ret
;
; console handlers
constx:
push d! call constf! pop d! ret
coninx:
;returns char & cond code = NZ if raw input
push d! call rlr! lxi d,pname! dad d
pop d! push d! ;restore console #
mov a,m! ani 80h! push psw
call coninf
mov b,a! pop psw! mov a,b
pop d! ret
conoutx:
mov a,c! ani 7fh! mov c,a
push d! call conoutf! pop d! ret
conin:
;read console character to A
;attach console first
call attcns
lxi h,kbchar! call ofsthl
mov a,m! mvi m,0! ora a! rnz
;no previous keyboard character ready
call getchr ;get character externally and test it
jmp conin ;only exit is with kbchar <> 0
;ret
;
conech:
;read character with echo
call conin! call echoc! rc ;echo character?
;character must be echoed before return
push psw! mov c,a! call tabout! pop psw
ret ;with character in A
;
echoc:
;echo character if graphic
;cr, lf, tab, or backspace
cpi cr! rz ;carriage return?
cpi lf! rz ;line feed?
cpi tab! rz ;tab?
cpi ctlh! rz ;backspace?
cpi ' '! ret ;carry set if not graphic
;
conbrk: ;check for character ready
call constx! ani 1
lxi h,kbchar! call ofsthl
jnz pgetchr ;jump if char to be read in
mov a,m! ora a! rz ;return if no char in kbchar either
jmp conb1 ;active kbchar
pgetchr:
mvi m,0 ;clear kbchar to prepare for new char
;character ready, read it
getchr: ;entry point used by conin
call coninx ;to A
jnz conb0; skip char testing if pd.pname.f0 is "on"
cpi ctls! jnz notcts ;check stop screen function
;found ctls, read next character
getctlq:
call coninx ;to A
cpi ctlc! jz controlc ;ctlc implies re-boot
cpi ctlq! jz gotctlq
mvi c,7! call conoutx ;send bell character
jmp getctlq
gotctlq:
;resume after ^Q
xra a! ret ;with zero in accumulator
notcts:
;not a control s, control q?
cpi ctlq! jz gotctlq
;ignore control Q's
notctq:
;not a control s, control d?
cpi ctld! jnz notctd
;found ctld, detach console
;^D is ignored if submit in progress
lhld sysdat! mvi l,128! call ofsthl
mov a,m! ora a! mvi a,0! rnz
push d! lxi h,listcp! call ofsthl
;if ^D and ^P then detach list
mov a,m! ora a! jz notctlp
mvi c,detlst! call XDOS
notctlp:
mvi c,detach! call XDOS
;then attach console back
; unless cns not req'd
pop d! mov a,e! ora a
rz! push d ;return if cns not req'd
mvi c,attach! call XDOS! pop d
dsplyatchmsg:
;print console attach message
lxi b,atchmsg! call xprint
call rlr
dsplynm:
call pdsplynm
xcrlf:
;output crlf without CONBRK calls
mvi c,cr! call conoutx
mvi c,lf! call conoutx
xra a! ret ;with zero in A
pdsplynm:
lxi b,pname! dad b! mvi e,8
dsploop:
mov c,m! push h! push d! call conoutx
pop d! pop h! inx h! dcr e
jnz dsploop
inr e ;cns req'd set true
ret
notctd:
;not a control d, control c?
cpi ctlc! jnz conb0
controlc: ;entry point
lhld sysdat! mvi l,128! call ofsthl
mov a,m! ora a! jz ctlcnt
push h! lxi b,submsg! call query
pop h! jnz ctlcnt
mvi m,0
ctlcnt:
;test for suppress abort flag
call rlr! lxi b,(pname+7)! dad b
mov a,m! ani 80h! jz notctlcsupr
dcx h! mov a,m! ori 80h! mov m,a
xra a! ret
notctlcsupr:
;test to see if this is a user process
inx h! inx h
mov a,m! ora a! rz
inr a! rz ;ignore ^C if system process running
;print Abort (Y/N) ?
lxi b,abtmsg1! call xprint
call rlr! call pdsplynm
lxi b,abtmsg2! call query! jz xreboot
xra a! ret ;with zero in A
conb0:
;character in accum, save it
lxi h,kbchar! call ofsthl! mov m,a
conb1:
;return with true set in accumulator
mvi a,1! ret
;
query:
call xprint
eatctlc:
call coninx! ani 7fh
cpi ctlc! jz eatctlc! push psw
mov c,a! call conoutx
mvi c,cr! call conoutx
mvi c,lf! call conoutx
pop psw
ani 5fh! cpi 'Y'
ret
;
conout:
;compute character position/write console char from C
;compcol = true if computing column position
lxi h,compcol! call ofsthl
mov a,m! ora a! jnz compout
;write the character, then compute the column
;write console character from C
push b! call conoutx ;externally, to console
call tstlivekbd ;conbrk only if simulated 'live kbd'
cz conbrk ;check for screen stop function
pop b! push b! push d ;recall/save character & con #
;may be copying to the list device
lxi h,listcp! call ofsthl
mov a,m! ani 01h! cnz func5 ;to printer, if so
pop d! pop b ;recall the character & con #
compout:
mov a,c ;recall the character
;and compute column position
lxi h,column! call ofsthl ;A = char, HL = .column
cpi rubout! rz ;no column change if nulls
inr m ;column = column + 1
cpi ' '! rnc ;return if graphic
;not graphic, reset column position
dcr m ;column = column - 1
mov a,m! ora a! rz ;return if at zero
;not at zero, may be backspace or end line
mov a,c ;character back to A
cpi ctlh! jnz notbacksp
;backspace character
dcr m ;column = column - 1
ret
notbacksp:
;not a backspace character, eol?
cpi lf! rnz ;return if not
;end of line, column = 0
mvi m,0 ;column = 0
ret
;
ctlout:
;send C character with possible preceding up-arrow
mov a,c! call echoc ;cy if not graphic (or special case)
jnc tabout ;skip if graphic, tab, cr, lf, or ctlh
;send preceding up arrow
push psw! mvi c,ctl! call conout ;up arrow
pop psw! ori 40h ;becomes graphic letter
mov c,a ;ready to print
;(drop through to tabout)
;
tabout:
;expand tabs to console
mov a,c! cpi tab! jnz conout ;direct to conout if not
;tab encountered, move to next tab position
tab0:
mvi c,' '! call conout ;another blank
call ldacolumn! ani 111b ;column mod 8 = 0 ?
jnz tab0 ;back for another if not
ret
;
backup:
;back-up one screen position
call pctlh! mvi c,' '! call conoutx ;jmp pctlh
;
pctlh:
;send ctlh to console without affecting column count
mvi c,ctlh! jmp conoutx
;ret
;
crlfp:
;print #, cr, lf for ctlx, ctlu, ctlr functions
;then move to strtcol (starting column)
mvi c,'#'! call conout
call crlf
;column = 0, move to position strtcol
crlfp0:
call ldacolumn! lxi h,strtcol! call ofsthl
cmp m! rnc ;stop when column reaches strtcol
mvi c,' '! call conout ;print blank
jmp crlfp0
;;
;
crlf:
;carriage return line feed sequence
mvi c,cr! call conout! mvi c,lf! jmp conout
;ret
;
xprint:
;print routine which does not CONBRK
;BC = string address, string terminated with a '$'
ldax b! ORA A! rz
push b! mov c,a! call conoutx! pop b
inx b! jmp xprint
;
print:
;print message until M(BC) = '$'
ldax b! cpi '$'! rz ;stop on $
;more to print
inx b! push b! mov c,a ;char to C
call tabout ;another character printed
pop b! jmp print
;
pread: ;entry to read, restores buffer address
pop b
read: ;BC = address (max length, current length, buffer)
push b ;save buffer address for possible ^X or ^U
call ldacolumn
lxi h,strtcol! call ofsthl
mov m,a ;save start for ctl-x, ctl-h
mov h,b! mov l,c! mov c,m! inx h! push h! mvi b,0
;B = current buffer length,
;C = maximum buffer length,
;HL= next to fill - 1
readnx:
;read next character, BC, HL active
push b! push h ;blen, cmax, HL saved
readn0:
call conin ;next char in A
ani 7fh ;mask parity bit
pop h! pop b ;reactivate counters
cpi cr! jz readen ;end of line?
cpi lf! jz readen ;also end of line
cpi ctlh! jnz noth ;backspace?
;do we have any characters to back over?
mov a,b! ora a! jz readnx
;characters remain in buffer, backup one
dcr b ;remove one character
call ldacolumn
lxi h,compcol! call ofsthl
mov m,a ;col > 0
;compcol > 0 marks repeat as length compute
jmp linelen ;uses same code as repeat
noth:
;not a backspace
cpi rubout! jnz notrub ;rubout char?
;rubout encountered, rubout if possible
mov a,b! ora a! jz readnx ;skip if len=0
;buffer has characters, resend last char
mov a,m! dcr b! dcx h ;A = last char
;blen=blen-1, next to fill - 1 decremented
jmp rdech1 ;act like this is an echo
;
notrub:
;not a rubout character, check end line
cpi ctle! jnz note ;physical end line?
;yes, save active counters and force eol
push b! push h! call crlf
lxi h,strtcol! call ofsthl
xra a! mov m,a ;start position = 00
jmp readn0 ;for another character
note:
;not end of line, list toggle?
cpi ctlp! jnz notp ;skip if not ctlp
lda kbproc! ora a! jnz notp
;list toggle - change parity
push h ;save next to fill - 1
push b! push d
lxi h,listcp! call ofsthl ;HL=.listcp flag
mvi a,01h! xra m! mov m,a ;listcp=-listcp
push h ;save address of listcp
jnz prntron ; jump if printer to be turned on
prntroff:
;return list mutex queue message
mvi m,0! ;zero listcp(console)
mvi c,detlst! call XDOS
pop h! jmp ctlpxit
prntron:
call testlstatt
pop h! jz ctlpxit
;printer busy, could not ^p
mvi m,0! lxi b,pbsymsg
;D = console #
pop d! push d
call xprint
ctlpxit:
pop d! pop b
pop h! jmp readnx ;for another char
notp:
;not a ctlp, line delete?
cpi ctlx! jnz notx
pop h ;discard start position
;loop while column > strtcol
backx:
lxi h,strtcol! call ofsthl
mov a,m! lxi h,column! call ofsthl
cmp m! jnc pread ;start again
dcr m ;column = column - 1
call backup ;one position
jmp backx
notx:
;not a control x, control u?
cpi ctlu! jnz notu ;skip if not
;delete line (ctlu)
call crlfp ;physical eol
pop h ;discard starting position
jmp pread ;to start all over
notu:
;not line delete, repeat line?
cpi ctlr! jnz notr
linelen:
;repeat line, or compute line len (ctlh)
;if compcol > 0
push b! call crlfp ;save line length
pop b! pop h! push h! push b
;bcur, cmax active, beginning buff at HL
rep0:
mov a,b! ora a! jz rep1 ;count len to 00
inx h! mov c,m ;next to print
dcr b! push b! push h ;count length down
call ctlout ;character echoed
pop h! pop b ;recall remaining count
jmp rep0 ;for the next character
rep1:
;end of repeat, recall lengths
;original BC still remains pushed
push h ;save next to fill
lxi h,compcol! call ofsthl
mov a,m! ora a ;>0 if computing length
jz readn0 ;for another char if so
;column position computed for ctlh
lxi h,column! call ofsthl! sub m ;diff > 0
lxi h,compcol! call ofsthl
mov m,a ;count down below
;move back compcol-column spaces
backsp:
;move back one more space
call backup ;one space
lxi h,compcol! call ofsthl! dcr m
jnz backsp
jmp readn0 ;for next character
notr:
;not a ctlr, place into buffer
rdecho:
inx h! mov m,a ;character filled to mem
inr b ;blen = blen + 1
rdech1:
;look for a random control character
push b! push h ;active values saved
mov c,a ;ready to print
call ctlout ;may be up-arrow C
pop h! pop b! mov a,b ;len to A
;are we at end of buffer?
cmp c! jc readnx ;go for another if not
readen:
;end of read operation, store blen
pop h! mov m,b ;M(current len) = B
pop h ;discard buffer address
mvi c,cr! jmp conout ;return carriage
;ret
;
ldacolumn:
lxi h,column! call ofsthl! mov a,m! ret
pbsymsg:
db cr,lf,'Printer Busy.',cr,lf,0
abtmsg1:
db cr,lf,'Abort ',0
abtmsg2:
db ' (Y/N) ?',0
atchmsg:
db cr,lf,'Attach:',0
submsg:
db cr,lf,'Terminate Submit ?',0
;
; data areas
;
nmbcns equ 16
compcol:db 0 ;true if computing column position
rept nmbcns-1
db 0
endm
strtcol:db 0 ;starting column position after read
rept nmbcns-1
db 0
endm
column: db 0 ;column position
rept nmbcns-1
db 0
endm
kbchar: db 0 ;initial key char = 00
rept nmbcns-1
db 0
endm
listcp: db 0 ;listing toggle
rept nmbcns-1
db 0
endm
kbproc: db 0 ;kb proc resident flag
;
patch$size equ 80
ds patch$size
patch:
org (((patch-base)+255) AND 0ff00h)-patch$size
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
;
; bios external jump table
;
bios equ $ ;base of the bios jump table
bootf equ bios ;cold boot function
wbootf equ bootf+3 ;warm boot function
constf equ wbootf+3 ;console status function
coninf equ constf+3 ;console input function
conoutf equ coninf+3 ;console output function
listf equ conoutf+3 ;list output function
punchf equ listf+3 ;punch output function
readerf equ punchf+3 ;reader input function
homef equ readerf+3 ;disk home function
seldskf equ homef+3 ;select disk function
settrkf equ seldskf+3 ;set track function
setsecf equ settrkf+3 ;set sector function
setdmaf equ setsecf+3 ;set dma function
readf equ setdmaf+3 ;read disk function
writef equ readf+3 ;write disk function
liststf equ writef+3 ;list status function
sectran equ liststf+3 ;sector translate
;
; xios access table
xiosms equ sectran+3 ;memory select / protect
xiospl equ xiosms+3 ;device poll
strclk equ xiospl+3 ;start clock
stpclk equ strclk+3 ;stop clock
exitr equ stpclk+3 ;exit critical region
maxcns equ exitr+3 ;max console #
syinitf equ maxcns+3 ;MP/M system initialization
;
end