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

1053 lines
25 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.

title 'Resident Portion of Banked BDOS'
;***************************************************************
;***************************************************************
;** **
;** B a s i c D i s k O p e r a t i n g S y s t e m **
;** **
;** R e s i d e n t P o r t i o n - B a n k e d B D O S **
;** **
;***************************************************************
;***************************************************************
;/*
; Copyright (C) 1978,1979,1980
; Digital Research
; P.O. Box 579
; Pacific Grove, CA 93950
;
; Revised:
; 11 Jan 80 by Thomas Rolander
;*/
on equ 0ffffh
off equ 00000h
;
org 0000h
base equ $
;
; XDOS jump table below BDOS origin
pdisp equ $-3
xdos equ pdisp-3
; equates for non graphic characters
ctlc equ 03h ;control c, abort
ctld equ 04h ;control d, detach
ctle equ 05h ;physical eol
ctlh equ 08h ;backspace
ctlp equ 10h ;prnt toggle
ctlq equ 11h ;prnt owner toggle
ctlr equ 12h ;repeat line
ctls equ 13h ;stop/start screen
ctlu equ 15h ;line delete
ctlx equ 18h ;=ctl-u
ctlz equ 1ah ;end of file
rubout equ 7fh ;char delete
tab equ 09h ;tab char
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
ctl equ 5eh ;up arrow
;
; BDOS call equates
dskinit equ 13
dskslct equ 14
dsksetDMA equ 26
setusercode equ 32
;
; XDOS call equates
poll equ 131
makeque equ 134
readque equ 137
condreadque equ 138
writeque equ 139
condwriteque equ 140
dispatch equ 142
terminate equ 143
attach equ 146
detach equ 147
sysdtadr equ 154
;
; Process Descriptor Offsets
pname equ 6
console equ 14
memseg equ 15
thread equ 18
disksetDMA equ 20
diskselect equ 22
diskparams equ 23
searcha equ 26
drvact equ 28
;
; System Data Page Offsets
userstackflag equ 3
brkvctr equ 48
usrstkregion equ 80
;
; MP/M Data Page Offsets
rlros equ 5
thrdrt equ 17
cnsatt equ 20
msegtbl equ 150
;
;*****
;
; enter here from the user's program with function number
; in c, and information address in d,e
jmp xbdos ;to xbdos handler
jmp bios ;to bios jump table base address
;
; bdos/xdos initialization code
syinit:
;HL = sysdat page address
shld sysdat
mvi l,7! lxi b,bnkbdos
mov a,m! mov e,a! stax b! inx b! inx h
mov a,m! mov d,a! stax b
xchg! inx h! inx h! inx h
shld bnkbdosinit
bnkbdosinit equ $+1
call $-$ ;initialize the banked bdos
jmp syinitcontd
extjmptbl:
jmp extreboot
jmp rlr
jmp getrlradr
jmp dsplynm
jmp xprint
jmp xcrlf
jmp conoutx
jmp getmemseg
jmp coninf
jmp homef
jmp seldskf
jmp settrkf
jmp setsecf
jmp setdmaf
jmp extreadf
jmp extwritef
jmp sectran
syinitcontd:
lhld sysdat! mov c,h
mvi l,252! mov a,m! inx h! mov h,m
mov l,a! lxi d,0005! dad d
shld rlradr! mov h,c
mvi l,userstackflag! mov a,m! sta usrstkflg
dcr l! mov l,m! mvi h,0 ;HL = RST #
mov c,l ;put RST # into C for use by SYSINITF
dad h! dad h! dad h ;HL = breakpoint address
mvi m,0C3h! inx h ;store jump to brkpt hndlr
lxi d,brkpt ;DE = brkpt entry address
mov m,e! inx h! mov m,d
;initialize jmp at 0000H to fake BIOS jump table
mvi a,0C3H! sta 0000H
lxi h,drctjmptbl! shld 0001H
;execute the XIOS SYSINIT function
call syinitf
ei ;in case it was not done in sysinit
;create disk mutual exclusion queue
mvi c,makeque! lxi d,diskcqcb! call xdos
mvi c,writeque! lxi d,MXDisk! call xdos
;create printer mutual exclusion queue
mvi c,makeque! lxi d,listcqcb! call xdos
mvi c,writeque! lxi d,MXList! call xdos
;get the directory buffer address
mvi c,0! call seldskf
lxi d,8! dad d! mov e,m! inx h! mov d,m
xchg! shld dirbufa
;initialize disk system
mvi c,dskinit! jmp bdos
;ret ;initialization is complete
;
CoNm:
db 'COPYRIGHT (C) 1980, '
db ' DIGITAL RESEARCH '
Serial:
db '654321'
lstack equ Serial+4
entsp equ lstack ;BDOS entry stack pointer
dtbl equ $
org ((dtbl-base)+0ffh) and 0ff00h
; *** this table is page aligned
; BIOS jump table for *.COM file support
jmp bootf
drctjmptbl:
jmp wbootf
jmp bconst
jmp bconin
jmp bconout
jmp blist
;
; Support for direct BIOS console & list device I/O
;
bconst: call setflg0
lxi h,console! dad d! mov d,m
jmp constf
bconin: call setflg0! mvi c,3! jmp xbdos
bconout:call setflg0! mov e,c! mvi c,4! jmp xbdos
blist: call setflg0! mov e,c! mvi c,5! jmp xbdos
setflg0:
lhld rlradr! mov e,m! inx h! mov d,m
lxi h,pname! dad d
mov a,m! ori 80h! mov m,a
ret
; Disk and List data structures
diskcqcb:
;disk mutual exclusion circular queue control block
dw $-$ ;link
db 'MXDisk ' ;name
dw 0 ;message length
dw 1 ;number of messages
dw $-$ ;dq process head
dw $-$ ;nq process head
dw $-$ ;msgin
dw $-$ ;msgout
dw $-$ ;msgcnt
dw $-$ ;owner Process descriptor adr
MXDisk:
;disk user queue control block
dw diskcqcb
listcqcb:
;list mutual exclusion circular queue control block
dw $-$ ;link
db 'MXList ' ;name
dw 0 ;message length
dw 1 ;number of messages
dw $-$ ;dq process head
dw $-$ ;nq process head
dw $-$ ;msgin
dw $-$ ;msgout
dw $-$ ;msgcnt
dw $-$ ;owner Process Descriptor adr
MXList:
;list user queue control block
dw listcqcb
xbdos: ;arrive here from user programs
mov a,c! ora c ; test function code
jz reboot ;zero terminates calling process
jp notXDOS ;jump if a BDOS call
call XDOS ;func >= 128 is a XDOS call
mov a,l ;XDOS returns address put low byte into A
ret
badfunc:
;invalid function code
lxi h,0ffffh! mov a,l! ret
brkpt: ;debugger breakpoint entry
di! shld svdhl! pop h! shld svdrt! push psw
;set HL = RLR
lhld rlradr! mov a,m! inx h! mov h,m! mov l,a
mvi a,memseg! add l! mov l,a
mvi a,0! adc h! mov h,a ;HL = .pd.memseg
mov a,m! add a! adi brkvctr
lhld sysdat! mov l,a ;HL = brkpt hndlr address
mov a,m! inx h! mov h,m! mov l,a
shld jmptobrk+1
pop psw! lhld svdrt! push h! lhld svdhl
jmptobrk:
jmp $-$
restore:
;restore user stack
xchg! pop h! sphl! xchg ;get user stack pointer
ret
notXDOS:
lda usrstkflg! ora a
jz BDOS ; if flag set then change stack
; get memory segment index
lhld rlradr! mov a,m! inx h
mov h,m! mov l,a
mvi a,memseg! add l! mov l,a
mvi a,0! adc h! mov h,a
mov a,m ; A = memory segment index
inr a! jz BDOS ;no stack change if system process call
dcr a! add a! adi usrstkregion
lhld sysdat! mov l,a
mov a,d! mov b,e ;save DE in AB
mov e,m! inx h! mov d,m
lxi h,0! dad sp
xchg! sphl! push d ;set & save user SP
lxi h,restore! push h ; setup return address to restore stack
mov d,a! mov e,b ;restore DE
BDOS:
mov a,c! cpi diskf! jc cnsfunc ;jump if not disk i/o
cpi nfuncs! jnc badfunc ;skip if invalid #
push d! push b ;save info & func
;test for 'live console' suppression, indicated by
; process name with high order bit of first char "on"
lhld rlradr! mov a,m! inx h! mov h,m! mov l,a
lxi b,pname! dad b! mov a,m! ani 80h
cz func11 ;simulate 'live console' with kbd status chk
;obtain entry by getting disk mutual exclusion message
mvi c,readque! lxi d,MXDisk! call XDOS
;setup & jump to banked bdos
pop b! pop d ;restore info & func
lxi h,0! dad sp! shld entsp
lxi sp,lstack
;perform the required buffer transfers from
; the user in common memory
mov a,c! cpi 17 ;search ?
jnz skipsrch
call rlr! push d! lxi d,searcha! dad d! pop d
mov m,e! inx h! mov m,d
jmp skipsrchnxt
skipsrch:
cpi 18 ;search next ?
jnz skipsrchnxt
call rlr! lxi d,searcha! dad d
mov e,m! inx h! mov d,m
skipsrchnxt:
mvi b,0! lxi h,dfctbl-12! dad b
mov a,m! push psw! push d
rar! jc cpydmain
rar! jc cpyfcbin
jmp nocpyin
cpydmain:
call rlr! lxi d,disksetdma! dad d
mov e,m! inx h! mov d,m
xchg! shld dmabufa! xchg
lhld dirbufa! mvi b,128
call move
pop d! push d
cpyfcbin:
lxi h,commonfcb! mvi b,36
call move
lxi d,commonfcb
nocpyin:
call getmemseg! sta usermemseg
mvi m,0 ;set memseg to 0 (memseg #0 must be bank zero)
push d! push b ;save info & func
mvi c,dispatch! call xdos
pop b! pop d
bnkbdos equ $+1
call $-$
shld aret
call getmemseg! lda usermemseg! mov m,a
mvi c,dispatch! call xdos
pop d! pop psw ;resore dfctbl byte & fcb address
ral! jc dmacpyout
ral! jnc nocpyout
fcbcpyout:
lxi h,commonfcb! xchg! mvi b,36
jmp cpyoutcmn
dmacpyout:
lhld dirbufa! xchg! lhld dmabufa! mvi b,128
cpyoutcmn:
call move
nocpyout:
lhld entsp! sphl ;user stack restored
lhld aret! push h
;release disk mutual exclusion message
mvi c,writeque! lxi d,MXDisk! call XDOS
;function done
pop h! mov a,l! mov b,h ;BA = HL = aret
ret
move:
;move data length of B from source DE to
;destination HL
inr b ;in case of length=0
move0:
dcr b! rz
ldax d! mov m,a
inx d! inx h
jmp move0
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,listf,func6,func7
dw cmnret,func9,func10,func11
diskf equ ($-functab)/2
nfuncs equ 40 ;must match with banked bdos # fns
;
func1:
;return console character with echo
call attcns! call conech
mov l,a! ret
;
func2:
;write console character with tab expansion
call attcns! jmp tabout
;
func3:
;return raw unattached console character
call testcnsatt
jmp dirinp
;
func4:
;write raw unattached console character
call testcnsatt
jmp conoutf
;
;func5:
;write list character
;write to list device
;jmp listf
;
func6:
;direct console i/o - read if 0ffh
call attcns
mov a,c! inr a! jz dirinp ;0ffh => 00h, means input mode
inr a! jz stsinp ;0feh => 00h, means status chk
;direct output function
jmp conoutf
dirinp:
;this differs from CP/M 2.0 which does const
;and returns zero if not ready
;character is ready, get it
lxi h,kbchar! call ofsthl
mov a,m! mvi m,0! ora a
cz coninf ;to A
mov l,a! ret
stsinp:
;direct console status input
call constf ;to A
mov l,a! ret
;
func7:
;return io byte
;*** Not implemented in MP/M 1.0 ***
xra a
mov l,a! ret
;
;func8:
;set i/o byte
;*** Not implemented in MP/M 1.0 ***
;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
;
getrlradr:
lhld rlradr! ret
rlr:
;set HL = contents of Ready List Root
lhld rlradr! mov a,m! inx h! mov h,m! mov l,a
ret
;
getmemseg:
;set A = memory segment #
call rlr ;HL = Ready List Root
mvi a,memseg! add l! mov l,a
mvi a,0! adc h! mov h,a ;HL = .pd.memseg
mov a,m! ret
;
testcnsatt:
;test to determine if console is attached
;Zero = attached, D = Console #
call rlr! xchg ;DE = Ready List Root
lxi h,console! dad d! mov a,m! push psw! push b
lhld rlradr! lxi b,cnsatt-rlros! dad b
add a! mov c,a! mvi b,0! dad b
mov a,m! cmp e! jnz testext
inx h! mov a,m! cmp d
testext:
pop b! pop d
mvi e,0 ;cns req'd flag false
ret
;
attcns:
;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! 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:
push d! call conoutf! pop d! ret
conin:
;read console character to A
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
call coninx ;to A
cpi ctlc! jz controlc ;ctlc implies re-boot
;not a reboot, act as if nothing has happened
xra a! ret ;with zero in accumulator
notcts:
;not a control s, control d?
cpi ctld! jnz notctd
;found ctld, detach console
push d! 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
;print console attach message
lxi b,atchmsg! call xprint
call rlr
dsplynm:
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
xcrlf:
;output crlf without CONBRK calls
mvi c,cr! call conoutx
mvi c,lf! call conoutx
xra a! ret ;with zero in A
notctd:
;not a control d, control c?
cpi ctlc! jnz conb0
controlc: ;entry point
;test to see if this is a user process
call getmemseg! inr a
rz ;ignore ^C if system process running
;print Abort (Y/N) ?
lxi b,abtmsg! call query
jz reboot
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! call coninx! 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 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 listf ;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! cpi '$'! 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
mvi a,01h! jmp ctlpqcmn
notp:
cpi ctlq! jnz notq ;skip if not ctlq
mvi a,80h
ctlpqcmn:
;list toggle - change parity
push h ;save next to fill - 1
push b! push d
lxi h,listcp! call ofsthl ;HL=.listcp flag
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,condwriteque! lxi d,MXList
call XDOS
pop h! jmp ctlpxit
prntron:
;test for ^p or ^q already "on"
cpi 81h! jz prntroff
;cond. read list mutex message
mvi c,condreadque
lxi d,MXList! call XDOS
mov a,l! ora a
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
notq:
;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,'$'
abtmsg:
db cr,lf,'Abort (Y/N) ?','$'
atchmsg:
db cr,lf,'Attach:$'
;
; 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
listcp: db 0 ;listing toggle
rept nmbcns-1
db 0
endm
kbchar: db 0 ;initial key char = 00
rept nmbcns-1
db 0
endm
;*********
;
; intercept bios boot, readf & writef to switch banks
extreboot:
call getmemseg! lda usermemseg! mov m,a
mvi c,dispatch! call xdos
lxi h,0ffffh! shld aret
lda usermemseg! inr a
jz nocpyout ;system process - release MXDisk & return
;
reboot:
;terminate the calling process
mvi c,terminate! lxi d,0
jmp xdos
extreadf:
call getmemseg! lda usermemseg! mov m,a
mvi c,dispatch! call xdos
call readf
jmp extcommon
extwritef:
call getmemseg! lda usermemseg! mov m,a
mvi c,dispatch! call xdos
call writef
extcommon:
push psw
call getmemseg! mvi m,0
mvi c,dispatch! call xdos
pop psw! ret
;
; Local Data Segment
rlradr: ds 2 ;address of Ready List Root
sysdat: ds 2 ;address of system data page
usrstkflg: ds 1 ;user stack flag, 0ffh=users stack
svdhl: ds 2 ;saved HL at breakpoint entry
svdrt: ds 2 ;saved return address at breakpoint entry
;
dirbufa: ds 2 ;directory buffer address
dmabufa: ds 2 ;dma buffer address
usermemseg: ds 1 ;saved user mem seg index
aret: ds 2 ;address value to return
commonfcb:
ds 36 ;fcb copy in common memory
;
; Disk Function Copy Table
;
dmain equ 00000001b ;dma copy on entry
fcbin equ 00000010b ;fcb copy on entry
dmaout equ 10000000b ;dma copy on exit
fcbout equ 01000000b ;fcb copy on exit
dfctbl:
db 0 ; 12=return version #
db 0 ; 13=reset disk system
db 0 ; 14=select disk
db fcbin+fcbout ; 15=open file
db fcbin ; 16=close file
db fcbin+dmain+dmaout ; 17=search first
db fcbin+dmain+dmaout ; 18=search next
db fcbin ; 19=delete file
db fcbin+fcbout ; 20=read sequential
db fcbin+fcbout ; 21=write sequential
db fcbin+fcbout ; 22=make file
db fcbin ; 23=rename file
db 0 ; 24=return login vector
db 0 ; 25=return current disk
db 0 ; 26=set DMA address
db 0 ; 27=get alloc address
db 0 ; 28=write protect disk
db 0 ; 29=get R/O vector
db fcbin ; 30=set file attributes
db 0 ; 31=get disk param addr
db 0 ; 32=get/set user code
db fcbin+fcbout ; 33=read random
db fcbin+fcbout ; 34=write random
db fcbin+fcbout ; 35=compute file size
db fcbin+fcbout ; 36=set random record
db 0 ; 37=drive reset
db 0 ; 38=access drive
db 0 ; 39=free drive
ds 6 ;reserve space for two jump instructions
;
; bios external jump table
last:
org (((last-base)+255) AND 0ff00h) - 6
jmp xbdos
jmp pdisp
;
; bios access 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