1
0
mirror of https://github.com/PDP-10/its.git synced 2026-03-21 08:48:51 +00:00
Files
PDP-10.its/src/mits_s/v80.4
2018-11-25 20:59:17 +01:00

835 lines
19 KiB
Groff
Executable File
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.
.lif z %defin
.title Versatec (V80) support
.sbttl Versatec (V80) support: Definitions, Macros and Code
v80vrs==%fnam2
;;; Plotter will be refered to as MATRIX (because printer and
;;; plotter both begin with "p"
.iif z %defin, .nlist ;don't list definitions and macros if not
;defining them
.if nz %defin ;only define symbols when we are supposed to
.if p1
.sbttl -- Definitions
;;; prefixes used in this module
;;; ;;; V8. Hardware interface offsets and bits
;;; ;;; $VS Versated scan line structure offsets
;;; ;;; $VH Hardware device object offsets
;;; ;;; VA V80 hardware routines
;;; ;;; V80 V80 support routines (random things)
;;; ;;; V8S V80 scan line routines
;;; ;;; V8% V80 scan line commands
;;; ;;; V8N V80 network routines
;;; ;;; V8C V80 constants
;;; ;;; V8V V80 variables
;;; ;;; V8T V80 tables
;;; ;;; V8$ V80 strings
;;; ;;; typical register usage:
;;; ;;; r0/ chaos connection
;;; ;;; r1/ chaos packet
;;; ;;; r2/ V80 hardware/interface object (v80 connection?)
;;; ;;; r3/ V80 scan line (V80 packet?)
;;; ;;; r5/ device base address = $vaadr(r2)
;; V80 definitions
;; offsets to the device registers (relative to printer status)
v8.mbc==00 ;matrix byte count
v8.ext==02 ;dma data buffer address extension bits
v8.pbc==04 ;printer byte count
v8.dma==06 ;dma data buffer address
v8.mcs==10 ;matrix control and status
v8.mdb==12 ;matrix data buffer
v8.pcs==14 ;printer control and status
v8.pdb==16 ;printer data buffer
;;; Control and Status Register bits
v8.err==bit.15 ;error
v8.dtc==bit.14 ;data transmission complete interrupt enable
v8.bsy==bit.13 ;DMA busy
v8.swp==bit.09 ;swap bytes on DMA transfer
v8.ers==bit.08 ;DMA erase after read
v8.rdy==bit.07 ;ready
v8.ien==bit.06 ;interrupt enable
v8.lnt==bit.05 ;remote line terminate
v8.frm==bit.04 ;remote form feed
v8.eot==bit.03 ;remote end of transmission
v8.clb==bit.02 ;clear buffer
v8.rst==bit.01 ;remote reset
v8.spp==bit.00 ;enable SPP
.endc p1
.sbttl -- Macros
v8cnv8==0 ;start with no V80s
.macro v8 pvec,mvec,csr,nos,chwin
.if p2
%%==.
.=v8tpvc+<2*v8cnv8>
.word pvec
.=v8tmvc+<2*v8cnv8>
.word mvec
.=v8tcsr+<2*v8cnv8>
.word csr
.=%%
.endc p2
v8cnos==nos
v8cchw==chwin
v8cnv8==v8cnv8+1
.endm
chnsrv ^"VERSATEC",cxversatec ;define the new server
.endc %defin
.iif z %defin, .list ;start listing again
.iif nz %defin, .nlist ;don't list code if only doing definitions
.if z %defin ;only do code if not defining symbols
.sbttl -- Code
.sbttl VA.... Interface definitions and tables
;;
;;;;;; a V80 hardware object
;;
dsect < ;;interface/hardware object
$vasta:: .blkw 1 ;device available flag
%vsava==100000 ;available flag (must be high bit)
%vsprn==000001 ;state is printing
%vsplt==000002 ;state is plotting
$vaadd:: .blkw 1 ;address of this interface
$vaxqu:: .blkw 1 ;transmission queue
$vaxqe:: .blkw 1 ;pointer to end of transmission queue
$vanvs:: .blkw 1 ;number of items on transmission queue
$vanos:: .blkw 1 ;number of output slots on queue
$vapks:: .blkw 1 ;chaos packets (print) that should be freed
$vacur:: .blkw 1 ;current scan line being worked on
$vaprv:: .blkw 1 ;previous scan line (for XORing)
$vaeof:: .blkw 1 ;consecutive CHAOS EOF count
$vawid:: .blkw 1 ;width of usable line in bytes
$varem:: .blkw 1 ;number of bytes remaning in line
$valft:: .blkw 1 ;offset to left of scan line
$vaxor:: .blkw 1 ;xor flag
$vacon:: .blkw 1 ;current command continuation (0 for top level)
$vacom:: .blkw 1 ;last command (in case continuation needs it)
$vanar:: .blkw 1 ;number of args needed for current command
$vaarp:: .blkw 1 ;pointer to place to deposit next arg
$vaarg:: .blkb 64. ;max of 64 bytes of args (plot n)
;; if you add things, be sure to update VAINI and V80DWN
>,l$vaobj
;;
;;;;;; Tables
;;
.wvector v8tobj,v8cnv8 ;table of the objects
v8tpvc: .blkw v8cnv8 ;print vector
v8tmvc: .blkw v8cnv8 ;matrix vector
v8tcsr: .blkw v8cnv8 ;control and status register
;;
;;;;;; Interrupt vectors point here
;;
v8tbrk:
.rept v8cnv8
.lif z .rpcnt
v8tpbr::
jsr r2,@#vaintp
.word v8tobj+<2*.rpcnt>
.lif z .rpcnt
v8tmbr::
jsr r2,@#vaintm
.word v8tobj+<2*.rpcnt>
.endr
lv8tbrk==<.-v8tbrk>/v8cnv8
v8tvap: ;vector address, print
.rept v8cnv8
.word v8tpbr+<.rpcnt*lv8tbrk>
.endr
v8tvam: ;vector address, matrix
.rept v8cnv8
.word v8tmbr+<.rpcnt*lv8tbrk>
.endr
;;; Init the Versatec hardware(s)
v8ini:
vaini: clr r0 ;start at v80 index 0
loop <
call 100$ ;really init the beast
add #2,r0
cmp r0,#v8cnv8*2
rptl lo
>
call v8sini ;init the scan line routines
return
100$: ;do the work
mov v8tcsr(r0),r3
call nxmcat ;catch bad interface
vanxm
mov #v8.clb,v8.pcs(r3) ;clear buffer (to print CSR)
mov #v8.clb,v8.mcs(r3) ;clear buffer (to matrix CSR)
clr v8.dma(r3) ;clear DMA address
clr v8.ext(r3) ;and DMA address extension bits
call nxmclr ;safe, interface is alive
mov v8tpvc(r0),r2 ;get print vector
mov v8tvap(r0),(r2)+ ;set vector address
mov #pr5,(r2)+ ;and priority
mov v8tmvc(r0),r2 ;get matrix vector
mov v8tvam(r0),(r2)+ ;set vector address
mov #pr5,(r2)+ ;and priority
push #l$vaobj
call fsmall
call fsmclr
pop r2
if eq,<bpt> ;oops, out of memory at initialization
mov r2,v8tobj(r0)
mov #%vsava,$vasta(r2) ;device is available
mov r3,$vaadd(r2) ;set it's CSR address
jcall v80dwn ;shut down this versatec
vanxm: clr v8tobj(r0) ;declare no hardware object
return
v80dwn: tst sysup ;is the system up yet
if ne,< ;yup
push r1,r3
mov $vaxqu(r2),r3 ;get the Xmit queue
if ne,<call v8sfrl> ;free it if exists
mov $vacur(r2),r3 ;get current scan line
if ne,<call v8sfre> ;free it if exists
mov $vaprv(r2),r3 ;get previous scan line
if ne,<call v8sfre> ;free it if exists
mov $vapks(r2),r1 ;get list of chaos packets to free
if ne,<call cpkfrl> ;free them if exists
call v8sfls ;flush all scan lines
pop r3,r1
>
push r2
add #$vaxqu,r2 ;want to auto-inc
clr (r2)+ ;nothing on the Xmit queue
mov r2,(r2) ;set up end pointer
sub #2,(r2)+ ;...
clr (r2)+ ;no scan lines on the Xmit list
mov #v8cnos,(r2)+ ;all output slots available
clr (r2)+ ;no chaos packets to free
clr (r2)+ ;no current scan line
clr (r2)+ ;no previous scan line
clr (r2)+ ;no chaos eofs
clr (r2)+ ;no width
clr (r2)+ ;no bytes remaining
clr (r2)+ ;no left margin info yet
clr (r2)+ ;don't do XOR
clr (r2)+ ;no current command continuation
add #3*2,r2 ;last command, # needed args, arg ptr have
;no meaning without command continuation
pop r2
return
vaintp: ;printer support
mov @(r2),r2 ;get the hardware object
push r1,r5
mov $vaadd(r2),r5 ;get device address
loop <
mov $vaxqu(r2),r1 ;get a packet off the list
if eq,<
bic #v8.ien,v8.pcs(r5) ;turn off interrupts
mov r2,$vaxqe(r2) ;set up end pointer
add #$vaxqu,$vaxqe(r2) ;...
exitl
>
tst $cpknb(r1) ;did we already use it?
if mi,< ;yup
mov (r1),$vaxqu(r2) ;unlink it
dec $vanvs(r2) ;one less scan line
inc $vanos(r2) ;one more output slot
mov $vapks(r2),(r1) ;link the chaos packets into this one
mov r1,$vapks(r2) ;and make this one the list
rptl ;and try again
>
push r1
add #$cpkdt,(sp) ;point to the data region
pop v8.dma(r5) ;put it in the DMA register
push $cpknb(r1) ;number of bytes
neg (sp) ;V80 wants 2's complement
pop v8.pbc(r5) ;this is the printer byte count
bis #bit.15,$cpknb(r1) ;flag this packet as printed
>
pop r5,r1,r2 ;pop all regs
rti
vaintm: mov @(r2),r2 ;get the hardware object
push r3,r5 ;for scan line and device address
mov $vaadd(r2),r5 ;get the address of the interface
loop < ;loop over the transmission queue
mov $vaxqu(r2),r3 ;get the scan line on the front
if eq,<
bic #v8.ien,v8.mcs(r5) ;turn off interrupts
mov r2,$vaxqe(r2) ;set up the end of the queue
add #$vaxqu,$vaxqe(r2) ;...
exitl
>
tst $vsskb(r3) ;skip before?
if ne,< ;yup
dec $vsskb(r3)
bis #v8.lnt,v8.mcs(r5) ;terminate line
exitl
>
tst $vsnum(r3) ;print this line?
if ne,< ;yup
dec $vsnum(r3)
push r3
add #$vsdat,(sp) ;point to data
pop v8.dma(r5) ;set the DMA address
mov #-%vsnby,v8.mbc(r5) ;neg byte count
exitl
>
tst $vsska(r3) ;skip after?
if ne,< ;yup
dec $vsska(r3)
bis #v8.lnt,v8.mcs(r5) ;terminate line
exitl
>
tst $vsflg(r3)
if ne,<
bis #v8.frm,v8.mcs(r5) ;remote form feed
clr $vsflg(r3)
exitl
>
mov $vslnk(r3),$vaxqu(r2) ;unlink this scan line
dec $vanvs(r2) ;one less scan line
inc $vanos(r2) ;another output slot
mov #-1,$vslnk(r3) ;no longer on a transmit list
cmp r3,$vaprv(r2) ;is this the previous packet
if ne,<call v8sfre> ;free the scan line
rptl ;and try again
>
pop r5,r3,r2
rti
.sbttl V80... V80 random support routines
v80wto: ;wait for an output slot
loop <
tst $vanos(r2)
exitl gt
push r0,r1,r2
add #$vanos,r2
.regs #hng.ne,#zero
.hang
pop r2,r1,r0
rptl
>
return
v80frc: loop <
tst $vanvs(r2)
exitl eq
push r0,r1,r2
add #$vanvs,r2
.regs #hng.eq,#zero
.hang
pop r2,r1,r0
>
return
v80vso: call v80wto
lock 5
clr (r3)
mov r3,@$vaxqe(r2)
mov r3,$vaxqe(r2)
inc $vanvs(r2)
dec $vanos(r2)
add $vaadd(r2),r5
bis #v8.ien,(r5)
unlock
return
.sbttl V8S... V80 scan line (de)allocation routines
;;; Versatec scan line structure
%vsnby==2112./8. ;number of bytes in a scan line
dsect <
$vslnk:: .blkw 1 ;transmit link, for packet linking
$vsskb:: .blkw 1 ;scan lines to skip before this line
$vsnum:: .blkw 1 ;number of times to do this scan line
$vsska:: .blkw 1 ;scan lines to skip after this line
$vsflg:: .blkw 1 ;flags
;; be sure to update v8sall if you change this
$vsdat:: .blkb %vsnby ;actual scan data
.even
>,l$vs
.wscalar v8vfrl ;free scan line list
.wscalar v8vnfr ;number on the freelist
v8sini: ;initialize scan lines
clr v8vfrl ;clear the head of the list
clr v8vnfr ;and nothing on it
return
;;; Free the scan line in r3
v8sfre: cmp v8vnfr,#v8cnos+2 ;should we free it?
if ge,< push r3 ;give it back to free storage
call fsmfre ;must be CALLED
inc r3 ;cause error on word reference
return>
lock 5 ;no interrupts from versatec
mov v8vfrl,(r3) ;shove the freelist into the scan
mov r3,v8vfrl ;and make it the freelist
inc v8vnfr ;one more scan line on the freelist
unlock
inc r3 ;cuase error on word reference
return
v8sfrl: push r5 ;to hold the list
mov r3,r5 ;put the list in r5
loop <
mov r5,r3 ;get the scan line
exitl eq ;finished if no packet
mov (r3),r5 ;cdr on down
call v8sfre ;free the one scan line
rptl ;and loop around
>
pop r5
return
;;; Flush the current list of available packets
v8sfls: lock 5
mov v8vfrl,r5
clr v8vfrl
clr v8vnfr
unlock
loop <
push r5
exitl eq
mov (r5),r5
call fsmfre
rptl
>
pop *
return
;;; Allocate a scan line. Return in r3 (or 0 if none)
v8sall: lock 5 ;don't allow versatec to confuse the freelist
mov v8vfrl,r3 ;get the top of the freelist
if ne,< mov (r3),v8vfrl ;unlink it
dec v8vnfr ;one less on the freelist
unlock>
else < unlock ;it is indeed safe
push #l$vs ;length of a scan line structure
call fsmall
pop r3>
push r3
if ne,<
mov #-1,(r3)+ ;not linked on any list
clr (r3)+ ;0 skip before count
clr (r3)+ ;0 times to print this one
clr (r3)+ ;0 skip after count
clr (r3)+ ;no flags
>
pop r3 ;set Z flag in the process if zero
return
.sbttl V8%... Chaos packet discombobulating
%v8eop==0
%v8rpt==000
%v8skp==100
%v8plt==200
%v8eol==300
%v8rpl==300
%v8xor==337
%v8mar==340
%v8ma1==350
;;; Conventions:
;;; r0: Number of bytes left in CHAOS packet
;;; r1: Byte pointer into CHAOS packet
;;; r2: Hardware object
;;; r3: byte pointer into current scan line
;;; r4: available
;;; r5: available
;;; push <number of args needed>
;;; call va%gar
;;; looks like it returns when all args accumulated
;;; must save r4 and r5 if you want to keep them. Do not save them on
;;; the stack
va%gar: pop $vacon(r2) ;save return address as continuation
pop $vanar(r2) ;number of args we need
mov r2,$vaarp(r2) ;setup pointer to place ...
add #$vaarg,$vaarp(r2) ;... to deposit next args
va%ga2: ;;; packet processor reenters here
mov $vanar(r2),r4 ;number of args still needed
tst r4
if ne,<
tst r0
if ne,<
cmp r0,r4
if lt,<mov r0,r4> ;take min with chaos bytes
sub r4,r0 ;number of packet bytes when finished
sub r4,$vanar(r2) ;discount it from number we need
mov $vaarp(r2),r5 ;get pointer to next place for args
loop <
movb (r1)+,(r5)+
sorl r4
>
mov r5,$vaarp(r2) ;save new value
>
>
tst $vanar(r2) ;test possible new value
if ne,<return> ;need more, return to packet processor
push $vacon(r2) ;restore return address
clr $vacon(r2) ;no continuation for next time
return ;and return to command processor
v8%eop: call v8%lfn ;finish current line
mov $vacur(r2),r3
mov #-1,$vsflg(r3)
v8%out: lock 5
mov $vaprv(r2),r3 ;get previous
if ne,<
cmp (r3),#-1 ;is it on a transmit list?
if eq,<call v8sfre> ;free it if not
>
mov $vacur(r2),r3 ;get current
mov r3,$vaprv(r2) ;new previous
unlock
mov #v8.mcs,r5 ;address offset
call v80vso
v8%new: loop <
call v8sall ;get a new one
exitl ne
push r0,r1
.regs #1,#0
.sleep
pop r1,r0
rptl
>
mov r3,$vacur(r2)
add $valft(r2),r3
mov $vawid(r2),$varem(r2)
jcall v8%clr ;clear the scan line
v8%rpt: mov r5,$vacom(r2) ;save command
push #1 ;one arg
call va%gar ;get it
mov $vacom(r2),r5 ;get command back
bic #mask6,r5
inc r5
sub r5,$varem(r2)
movb $vaarg(r2),r4 ;get the arg
loop <
movb r4,(r3)+
sorl r5
>
return
v8%skp: mov r5,$vacom(r2) ;save command
push #1 ;one arg
call va%gar ;get it
mov $vacom(r2),r5 ;get command back
bic #mask6,r5
inc r5
sub r5,$varem(r2)
add r5,r3
movb $vaarg(r2),(r3)+ ;set the byte
dec $varem(r2)
return
v8%plt: bic #mask6,r5
inc r5
mov r5,$vacom(r2) ;save nbytes as command
push r5 ;number of args needed
call va%gar
mov $vacom(r2),r5 ;get number of bytes back
sub r5,$varem(r2)
mov r2,r4
add #$vaarg,r4 ;get pointer to args
loop <
movb (r4)+,(r3)+
sorl r5
>
return
v8%eol: jcall v8%lad
v8%rpl: bic #mask5,r5
push r5
call v8%lfn
pop r5
push r3
mov $vaprv(r2),r3
lock 5
add r5,$vsnum(r3)
cmp (r3),#-1 ;is it on a transmit list
if eq,< mov #v8.mcs,r5 ;address offset
call v80vso> ;if not, put it back on
unlock
pop r3
return
v8%xor: call v8%lfn
mov #-1,$vaxor(r2)
return
v8%mar: mov r5,$vacom(r2) ;save command
push #3 ;need 3 args
call va%gar ;get them
mov $vacom(r2),r5 ;get command back
bic #mask3,r5
movb $vaarg+0(r2),r4
bic #mask8,r4
ash #3,r4
add r5,r4
dec r4 ;convert one based to zero based
mov $vacur(r2),r5 ;get current scan line
mov r4,$vsskb(r5) ;tell it to skip before the top margin
;before printing
pushb $vaarg+1(r2) ;get second arg
bic #mask8,(sp)
movb $vaarg+2(r2),r4 ;get third arg
bic #mask8,r4
v8%ma.: sub (sp),r4
inc r4
mov r4,$vawid(r2)
mov r4,$varem(r2)
mov #$vsdat-1,r3 ;point to data with conversion from one
;based to zero based.
add (sp)+,r3
mov r3,$valft(r2)
add $vacur(r2),r3
return
v8%ma1: push #4
call va%gar ;get 4 args
push $vaarg+0(r2) ;get first 2
swab (sp) ;PDP-10 to PDP-11 style
push $vaarg+2(r2) ;get second 2
swab (sp) ;pdp-10 to pdp-11 style
pop r4
br v8%ma.
v8%lfn: cmp $varem(r2),$vawid(r2)
if eq,<return>
loop <
tst $vaxor(r2)
if ne,< call v8%dxr
clr $vaxor(r2)>
exitl
v8%lad: cmp $varem(r2),$vawid(r2)
rptl ne
>
mov $vacur(r2),r3
mov #1,$vsnum(r3)
jcall v8%out
v8%clr: mov $vacur(r2),r4
add #$vsdat,r4
mov #<%vsnby+1>/2,r5
loop <
clr (r4)+
sorl r5
>
return
v8%dxr: mov $vacur(r2),r5
mov $vaprv(r2),r4
add #$vsdat,r5
add #$vsdat,r4
push r2,r3
mov #<%vsnby+1>/2,r3
loop <
mov (r4)+,r2
xor r2,(r5)+
sorl r3
>
pop r3,r2
return
.sbttl V8N... Versatec network handler
cxversatec::
v8nchaos:
cx$srv v8nopn,40,240_8,<>
v8nopn: call cpkpki ;get the RFC
if cs,<
110$: call ccnfre
.logout
>
mov #v8cnv8,r5 ;number of V80 configured
mov #v8tobj,r4 ;pointer to devices
loop <
mov (r4)+,r2 ;set the hardware object
if ne,< ;if there is something there
tst $vasta(r2) ;is it available?
exitl mi ;yup, so use it
>
sorl r5 ;else try for the next
mov (pc)+,r2
.string <All VERSATECs at this site are in use.>
120$: clr $cpknb(r1)
call cpkaz1 ;stuff message into one packet
movb #%cocls,$cpkop(r1) ;make it a close packet
call cpkpko ;output it
br 110$
>
clr $vasta(r2) ;no longer available, no status
mov $vaadd(r2),r5
mov #v8.clb,v8.pcs(r5) ;clear buffer command
mov #v8cchw,$cpkpn(r1) ;window size
movb #%coopn,$cpkop(r1) ;open packet
call cpkpko ;output packet
call v80dwn ;shut it down for good measure
clr $vaeof(r2) ;no eof packets seen yet.
loop <
lock 5
mov $vapks(r2),r1 ;get packets that may need freeing
if eq,<unlock>
else <
clr $vapks(r2)
unlock
call cpkfrl
>
call cpkpki ;get a packet
if cs,<
200$: call v80frc ;force all scans out
call v80dwn ;shut down the versatec
mov $vaadd(r2),r3
bis #v8.frm,v8.pcs(r3) ;issue form feed
mov #%vsava,$vasta(r2) ;make it available
br 110$
>
if eq,<
call cpkwti ;wait for an input packet
rptl
>
tstb $cpkop(r1) ;is it data?
if pl,<
pushb $cpkop(r1)
call cpkfre
cmpb (sp)+,#%coeof
if eq,<
inc $vaeof(r2)
cmp $vaeof(r2),#2
bge 200$
> >
else <clr $vaeof(r2)
call v8npkt> ;go process the packet
rptl
>
;;; Process the packet
v8npkt: bitb #1,$cpkop(r1) ;print or plot
if eq,< ;print
cmpb $vasta(r2),#%vsprn ;already in print?
if ne,<call v80frc> ;finish current set of commands
movb #%vsprn,$vasta(r2)
mov r1,r3
mov #v8.pcs,r5
jcall v80vso ;output the "scan line"
>
cmpb $vasta(r2),#%vsplt ;else plot packet
if ne,<call v80frc>
movb #%vsplt,$vasta(r2)
push r0,r1
tst $vacur(r2) ;is there already a scan line?
if eq,<call v8%new> ;try and get a new scan line
mov $cpknb(r1),r0 ;get byte count
add #$cpkdt,r1 ;point to data
loop < ;real loop
tst r0 ;any more packet data?
exitl le ;get out if not
loop < ;exit mechanism
tst $vacon(r2) ;is there a continuation?
if ne,< ;yup
call va%ga2 ;continue argument collection
exitl ;maybe finish command
>
dec r0 ;going to grab a byte from packet
movb (r1)+,r5
if eq,<call v8%eop
exitl>
if pl,<bit #100,r5
if eq,<call v8%rpt
exitl>
call v8%skp
exitl>
bit #100,r5
if eq,<call v8%plt
exitl>
cmpb r5,#%v8eol
if eq,<call v8%eol
exitl>
cmpb r5,#%v8xor
if lo,<call v8%rpl
exitl>
if eq,<call v8%xor
exitl>
cmpb r5,#%v8ma1
if lo,<call v8%mar
exitl>
if eq,<call v8%ma1>
>
tst $varem(r2)
if le,<call v8%lfn>
rptl
>
pop r1,r0
jcall cpkfre
****
.endc %defin
.iif nz %defin, .list ;start listing as usual
;; local modes:
;; mode:midas
;; auto fill mode:
;; fill column:75
;; comment column:32
;; compile command: :xfile dcp;\swit compil M
;; end: