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

578 lines
14 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 ('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