Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 3.X/CPM 3.0/3.0 PLM SOURCE/PUTF.ASM
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

578 lines
14 KiB
NASM

$title ('PUTF - CP/M 3.0 Output Redirection - August 1982')
;******************************************************************
;
; PUT 'Redirection Initializer' version 3.0
;
; 11/30/82 - Doug Huskey
;******************************************************************
;
;
; Copyright (c) 1982
; Digital Research
; P.O. Box 579
; Pacific Grove, Ca.
; 93950
;
;
; generation procedure
;
; seteof put.plm
; seteof getscan.dcl
; seteof putf.asm
; seteof getscan.plm
; seteof parse.asm
; is14
; asm80 putf.asm debug
; asm80 mcd80a.asm debug
; asm80 parse.asm debug
; plm80 put.plm pagewidth(100) debug optimize
; link mcd80a.obj,put.obj,parse.obj,putf.obj,plm80.lib to put.mod
; locate put.mod code(0100H) stacksize(100)
; era put.mod
; cpm
; objcpm put
; rmac putrsx
; link putrsx[op]
; era put.rsx
; ren put.rsx=putrsx.prl
; gencom put.com
; gencom put.com put.rsx
;
;
; This module is called as an external routine by the
; PL/M program PUT. The address of a the following
; structure is passed:
;
; declare putpb structure
; (output$type byte,
; echo$flag byte,
; filtered$flag byte,
; system$flag byte);
;
; output$type = 0 > console output (default)
; = 1 > auxiliary output
; = 2 > list output
; = 3 > console input
;
; echo = true > echo output to real device
; (default)
; = false > don't echo output (input is
; still echoed)
; filtered = true > convert control characters
; to a printable form
; preceeded by an ^
; = false > no character conversions
; program = true > continue until user uses
; PUT command to revert to
; console
; = false > active only until program
; termination
public putf
extrn mon1,fcb,memsiz
;
;
true equ 0ffffh
false equ 00000h
;
biosfunctions equ true ;intercept BIOS list or conout
;
;
; low memory locations
;
wboot equ 0000h
wboota equ wboot+1
;
; equates for non graphic characters
;
cr equ 0dh ; carriage return
lf equ 0ah ; line feed
;
; BDOS function equates
;
cinf equ 1 ;read character
coutf equ 2 ;output character
crawf equ 6 ;raw console I/O
creadf equ 10 ;read buffer
cstatf equ 11 ;status
lchrf equ 5 ;list character
pbuff equ 9 ;print buffer
resetf equ 13 ;disk reset
selectf equ 14 ;select disk
openf equ 15 ;open file
closef equ 16 ;close file
delf equ 19 ;delete file
dreadf equ 20 ;disk read
makef equ 22 ;make file
dmaf equ 26 ;set dma function
curdrv equ 25 ;get current drive
dpbf equ 31 ;get dpb address
userf equ 32 ;set/get user number
resdvf equ 37 ;reset drive
scbf equ 49 ;set/get system control block word
rsxf equ 60 ;RSX function call
resalvf equ 99 ;reset allocation vector
pblkf equ 111 ;print block to console
lblkf equ 112 ;print block to list device
ginitf equ 128 ;GET initialization sub-function no.
gkillf equ 129 ;GET delete sub-function no.
gfcbf equ 130 ;GET file display sub-function no.
pinitf equ 132 ;PUT initialization sub-funct no.
pckillf equ 133 ;PUT CON: delete sub-function no.
pcfcbf equ 134 ;return PUT CON: fcb address
plkillf equ 137 ;PUT LST: delete sub-function no.
plfcbf equ 138 ;return PUT LST:fcb address
jinitf equ 140 ;JOURNAL initialization sub-funct no.
jkillf equ 141 ;JOURNAL delete sub-function no.
jfcbf equ 142 ;return JOURNAL fcb address
skillf equ 144 ;SUBMIT delete sub-function no.
sfcbf equ 145 ;SUBMIT fcb address function
svkillf equ 160 ;SAVE delete sub-function no.
;
; System Control Block definitions
;
scba equ 03ah ;offset of scbadr from SCB base
ccpflg1 equ 0b3h ;offset of ccpflags word from page boundary
submit equ 040h ;mask for active submit or get test
errflg equ 0aah ;offset of error flag from page boundary
conmode equ 0cfh ;offset of console mode from page boundary
listcp equ 0d4h ;offset of ^P flag from page boundary
common equ 0f9h ;offset of common memory base from pg. bound
wbootfx equ 068h ;offset of warm boot jmp from page. bound
constfx equ 06eh ;offset of constat jmp from page. bound
coninfx equ 074h ;offset of conin jmp from page. bound
conoufx equ 07ah ;offset of conout jmp from page. bound
listfx equ 080h ;offset of list jmp from page. bound
cstjmp equ 003h ;offset of console status jmp from warm boot
cinjmp equ 006h ;offset of console input jmp from warm boot
coujmp equ 009h ;offset of console output jmp from warm boot
lstjmp equ 00ch ;offset of list output jmp from warm boot
;
; Restore mode equates (used with inr a, rz, rm, ret)
;
norestore equ 0ffh ;no BIOS interception
biosonly equ 07fh ;restore BIOS jump table only
everything equ 0 ;restore BIOS jump table and jmps in
;RESBDOS (default mode)
;
; Instructions
;
lxih equ 21h ;LXI H, instruction
jmpi equ 0c3h ;jump instruction
;
;******************************************************************
; START OF INITIALIZATION CODE
;******************************************************************
cseg
putf:
;get parameters
mov h,b
mov l,c ;HL = .(parameter block)
mov a,m ;output type 0=con:,1=aux:,2=lst:,3=conin:
cpi 1 ;is it aux?
jz notimp ;error if so
cpi 3 ;is it console input only
jnz setlst
sta input ;non-zero => console input
xra a
setlst: sta list ;non-zero => list device
inx h
mov a,m ;echo/noecho mode
sta echo
inx h
mov a,m ;cooked/raw mode
sta cooked
inx h
mov a,m ;system/program mode
sta program
;
;check if enough memory
;
lhld memsiz
mov a,h
cpi 20h
lxi d,memerr
jc error
;
;check if drive specified
lxi h,fcb
mov a,m ;drive code
dcr a ;drive specified?
jp movfcb ;jump if so
;
;set to current drive, if not
;
mvi c,curdrv
push h ;save .fcb
call mon1
pop h ;a=current drive, hl=.fcb
mov m,a ;set fcb to force drive select
inr m ;must be relative to 1
;
movfcb: ;copy default fcb up into data area for move to RSX
;
mov e,a
mvi c,selectf ;make sure drive is selected
push h ;save .fcb
call mon1 ;so we get the right DPB
pop h
lxi d,putfcb
lxi b,32 ;length of fcb
call ldir ;move it to putfcb
;
;initialize other variables to be moved to RSX
;
call getusr ;get current user number
sta putusr ;save for redirection file I/O
call getscbadr
shld scbadr ;System Control Block address
;
;initialize records per block (BLM)
;
mvi c,dpbf
call mon1 ;HL = .disk parameter block
inx h
inx h
inx h ;HL = .blm
mov a,m
sta blm
;
;initialize function table (functions to be intercepted)
;
lda list
ora a
lxi b,funcend-functbl ;count
lxi d,functbl ;destination
lxi h,pcfcbf*256+pckillf ;rsx function codes
jz ckinput
lxi h,listfunc ;list function table
call ldir
mvi a,lchrf
sta bdosfunc ;use list output for bios trap
mvi a,listfx
sta resoff ;offset of fixup for bios list
mvi a,lstjmp
sta biosoff ;offset of bios lst jmp
lxi h,plfcbf*256+plkillf
jmp getrsxadr
ckinput:
lda input
ora a
jz getrsxadr
lxi h,inputfunc
call ldir
mvi a,cinf
sta bdosfunc ;use console input
mvi a,coninfx
sta resoff ;offset of fixup for bios conin
mvi a,cinjmp
sta biosoff
sta echo ;must be non-zero for input
lhld scbadr
mvi l,ccpflg+1
mov a,m
ani submit ;SUBMIT or GET active?
lxi d,noget
jnz error ;error if so
lxi h,jfcbf*256+jkillf
;
;get address of initialization table in RSX
;
getrsxadr:
shld rsxfun
mvi c,rsxf ;PUT is not compatible with SAVE.RSX
lxi d,savkill ;as both SAVE & PUT trap warm starts
call mon1 ;eliminate SAVE.RSX if active
mvi c,rsxf
lxi d,rsxinit
call mon1 ;call PUT.RSX initialization routine
push h ;save address of destination for move
mov e,m
inx h
mov d,m ;DE = .kill flag
push d ;save for later set
;
if biosfunctions
;
inx h
inx h
inx h ;HL = .(.(bios entry in RSX))
push h ;save for getting RSX entry point
;later (in trap:)
;check if BIOS jump table looks valid (jmp in right places)
check: lhld biosoff
xchg
lhld wboota
mov a,m
cpi jmpi ;should be a jump
dad d ;HL = .(jmp address)
mov a,m
cpi jmpi ;should be a jump
jnz bioserr ;skip bios redirection if not
;
;fix up RESBDOS to do BIOS calls to intercepted functions
;
lhld scbadr
mvi l,common+1
mov a,m ;get high byte of common base
ora a
jnz fix0 ;high byte = zero if non-banked
mvi a,biosonly
sta biosmode
jmp trap ;skip code that fixes resbdos
;fix warmboot BIOS jmp in resbdos
fix0: mvi l,wbootfx ;HL = .warm boot fix in SCB
shld wmfix ;save for RSX restore at end
mov a,m
cpi jmpi ;is it a jump instruction?
jz fix1 ;jump if so
mvi a,biosonly ;whoops already traped
sta biosmode
fix1: mvi m,lxih ;change jump to an lxi h,
;fix list bios jmp in resbdos
lda resoff
mov l,a
shld biosfix
mov a,m
cpi jmpi ;is it a jump instruction?
jz biosck ;jump if so
mvi a,biosonly ;whoops already changed
sta biosmode ;restore jump table only
fix3: mvi m,lxih
;
;get address of list entry point
;
trap: pop h ;.(.(bios entry point in RSX))
mov c,m
inx h
mov b,m
push h
lhld biosoff
xchg
lhld wboota
dad d ;HL = .(jmp address)
inx h ;move past jmp instruction
shld biosjmp ;save for RSX restore at end
mov e,m
mov m,c
inx h
mov d,m ;DE = bios routine address
mov m,b ;BIOS jmp jumps to RSX
xchg
shld biosout ;save bios routine address
;get addresses of RSX bios trap
pop h
inx h
mov c,m ;HL = .(.(bios warm start in RSX))
inx h
mov b,m ;BC = .bios warmstart entry in RSX
;
;patch RSX wmboot entry into BIOS jump table
;save real wmboot address in RSX exit table
;
lhld wboota
inx h
shld wmjmp ;save for RSX restore at end
mov e,m
mov m,c
inx h
mov d,m
mov m,b
xchg
shld wmsta ;save real bios warm start routine
endif
;
;move data area to RSX
;
rsxmov:
pop h ;HL = .(kill flag = 0FFh)
inr m ;set to zero for redirection active
lxi h,movstart
pop d ;RSX data area address
lxi b,movend-movstart
call ldir
jmp wboot
;
; auxiliary redirection
;
notimp:
lxi d,notdone
error:
mvi c,pbuff
call mon1
mvi c,closef
lxi d,fcb
call mon1
mvi c,delf
lxi d,fcb
call mon1
jmp wboot
if biosfunctions
;
; check if warm boot was fixed up by someone
; and list or console output was not
;
biosck: lda biosmode
cpi biosonly
jnz fix3 ;warm boot not fixed up
;
; can't do BIOS redirection
;
bioserr:
lxi d,nobios
mvi c,pbuff
call mon1
lxi h,biosmode
mvi m,norestore
pop h ;throw away stacked bios entry
jmp rsxmov
endif
;
; get/set user number
;
getusr: mvi a,0ffh ;get current user number
setusr: mov e,a ;set current user number (in A)
mvi c,userf
jmp mon1
;
; get system control block address
; (BDOS function #49)
;
; exit: hl = system control block address
;
getscbadr:
mvi c,scbf
lxi d,data49
jmp mon1
;
data49: db scba,0 ;data structure for getscbadd
;
;
; copy memory bytes (emulates z80 ldir instruction)
;
ldir: mov a,m ;get byte
stax d ;store it at destination
inx h ;advance pointers
inx d
dcx b ;decrement byte count
mov a,c ;loop if non-zero
ora b
jnz ldir
ret
;
;******************************************************************
; DATA AREA
;******************************************************************
;
; equates function table
;
eot equ 0ffh ; end of function table
skipf equ 0feh ; skip this function
;
listfunc:
db lchrf, lblkf, coutf, cstatf, crawf
db pbuff, cinf, creadf, resetf, resdvf
db resalvf, pblkf, eot
; Note that the list routines precede the console
; routines so that the CKLIST: routine in PUTRSX
; can distinquish list functions from console
; functions.
inputfunc: ;preset for console input
db skipf, skipf, skipf, skipf, crawf
db skipf, cinf, creadf, resetf, resdvf
db resalvf, eot, skipf
;
savkill: db svkillf
rsxinit: db Pinitf
nobios: db cr,lf,'WARNING: Cannot redirect from BIOS',cr,lf,'$'
notdone:
db cr,lf
db 'ERROR: Auxiliary device redirection not implemented',cr,lf,'$'
memerr:
db cr,lf
db 'ERROR: Insufficient Memory',cr,lf,'$'
noget:
db cr,lf
db 'ERROR: You cannot PUT INPUT to a file',cr,lf
db ' when using GET or SUBMIT.',cr,lf,'$'
resoff: db conoufx
biosoff: dw coujmp
aux: db 0
;
;******************************************************************
; Following variables are initialized by PUT.COM
; and moved to the PUT RSX - Their order must not be changed
;******************************************************************
;
;
movstart:
inittable: ;addresses used by PUT.COM for
scbadr: dw 0 ;address of System Control Block
;
if biosfunctions ;PUT.RSX initialization
;
gobios: mov c,e
db jmpi
biosout:
dw 0 ;set to real BIOS routine
;
;restore only if changed when removed.
biosjmp:
dw 0 ;address of bios jmp initialized by COM
biosfix:
dw 0 ;address of jmp in resbdos to restore
db jmpi
wmsta: dw 0 ;address of real warm start routine
wmjmp: dw 0 ;address of jmp in bios to restore
wmfix: dw 0 ;address of jmp in resbdos to restore
bdosfunc:
db coutf
biosmode:
db 0 ;0FFh = no bios restore, 07fh = restore
;only bios jmp, 0 = restore bios jump and
;resbdos jmp when removed.
endif
functbl: ;preset for console output
db skipf, skipf, coutf, cstatf, crawf, pbuff
db cinf, creadf, resetf, resdvf, resalvf, pblkf, eot
funcend:
;
input: db 0 ;non-zero if putting input to a file
list: db 0 ;TRUE if list output redirection
echo: db 1 ;echo output to device
cooked: ;must be next after echo
db 0 ;TRUE if ctrl chars displayed with ^
rsxfun:
pkillf: db 255 ;put abort routine code
pfcbf: db 255 ;put FCB display function no.
; ********** remaining variables must be in this order
record: db 0 ;counts down records to block boundary
blm: db 0 ;block mask = records per block (rel 0)
program: ;This must be @ .putfcb-2
db 0
putusr: db 0 ;user number for redirection file
putfcb: db 1 ;a
db 'SYSOUT '
db '$$$'
db 0,0
putmod: db 0
putrc: db 0
ds 16 ;map
putcr: db 0
;
cbufp: db 0
movend:
;*******************************************************************
end