mirror of
https://github.com/PDP-10/its.git
synced 2026-03-24 01:27:33 +00:00
456 lines
11 KiB
Plaintext
Executable File
456 lines
11 KiB
Plaintext
Executable File
|
||
.lif z %defin
|
||
.title DH11 (Able DH/DM) support
|
||
.sbttl DH11 support: Definitions, Macros and Code
|
||
|
||
;;; some qbus DHs look like unibus DHs (Emulex). Some don't (Canadian).
|
||
.iif z qbus, dhubus==-1
|
||
.iif nz qbus, .iif ndf dhubus, dhubus==0 ;qbus default to qbus (Canadian)
|
||
|
||
;;; ;;; General info:
|
||
;;; ;;; DH11 16 line DMA output async terminal driver. Also works for the
|
||
;;; ;;; qbus DHK-11
|
||
;;; ;;; Usage:
|
||
;;; ;;; defdev dh,dh11,<
|
||
;;; ;;; ;;; dh vec,csr ,<lines>
|
||
;;; ;;; ;;; dhl typ,baud.,P,stp,nbts,where
|
||
;;; ;;; dh 340,160020,<
|
||
;;; ;;; dhl v52,9600.,n,002,8,<EECS hardware lab x3-2737 (DH01-CH0)>
|
||
;;; ;;; >
|
||
;;; ;;; >
|
||
;;; ;;; Known bugs:
|
||
;;; ;;; Ignores all tty info, except typ and location. Assumes 9600. baud,
|
||
;;; ;;; no parity, 2 stop bits, 8 bits per character.
|
||
;;; ;;; Misfeatures:
|
||
;;; ;;; No modem control.
|
||
|
||
.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
|
||
|
||
;; DH11 definitions
|
||
|
||
;; offsets to device registers
|
||
dh.scr==0 ;(MIX W/B) System Control Register
|
||
dh.nxt==2 ;(R/ Wrd) Next Received Character Register
|
||
dh.lpr==4 ;(R/W Wrd) Line Parameter Register (Group)
|
||
dh.car==6 ;(R/W Wrd) Current Address Register
|
||
dh.bcr==10 ;(R/W Wrd) Byte Count Register (Group)
|
||
dh.bar==12 ;(R/W Wrd) Buffer Active Register
|
||
dh.brk==14 ;(R/W Wrd) Break Control Register
|
||
dh.ssr==16 ;(MIX W/B) Silo Status Register
|
||
|
||
;; System Control Register bits (dh.scr) [Mixed, Word/byte]
|
||
dh.xin==bit.15 ;(r/w) Transmitter Interrupt
|
||
dh.sin==bit.14 ;(r/ ) Storage Interrupt
|
||
dh.xie==bit.13 ;(r/w) Transmit and NXM Interrupt Enable
|
||
dh.sie==bit.12 ;(r/w) Storage Interrupt Enable
|
||
dh.mcl==bit.11 ;(r/w) Master Clear
|
||
dh.nin==bit.10 ;(r/ ) NXM Interrupt
|
||
dh.mnt==bit.09 ;(r/w) Maintenance
|
||
dh.cni==bit.08 ;( /w) Clear NXM Interrupt
|
||
dh.rin==bit.07 ;(r/ ) Receiver Interrupt
|
||
dh.rie==bit.06 ;(r/w) Receiver Interrupt Enable
|
||
dh.lin==mask4 ;(r/w) Line selection for setting LPR,CAR,BCR
|
||
|
||
;; Next Received Character Register bits (dh.nxt) [read only, word only]
|
||
dh.vdp==bit.15 ;Valid Data Present
|
||
dh.dov==bit.14 ;Data Overrun
|
||
dh.frm==bit.13 ;Framing Error
|
||
dh.par==bit.12 ;Parity Error
|
||
dh.rln==mask4 ;Line Number mask after SWAB'ing
|
||
dh.rch==mask8 ;Character Data Byte
|
||
|
||
;; Line Parameter Register bits (dh.lpr) [read/write, word only]
|
||
dh.aee==bit.15 ;Auto-Echo-Enable
|
||
dh.fdx==bit.14 ;(cleared =) Full Duplex
|
||
dh.tsp==10. ;ash for transmitter speed
|
||
dh.rsp==06. ;ash for receiver speed
|
||
dh.odd==bit.05 ;odd parity
|
||
dh.pen==bit.04 ;parity enable
|
||
dh.tsb==bit.02 ;two stop bits
|
||
dh.5bt==0 ;5 bits
|
||
dh.6bt==1 ;6 bits
|
||
dh.7bt==2 ;7 bits
|
||
dh.8bt==3 ;8 bits
|
||
|
||
;; Silo Status Register bits (dh.ssr)
|
||
dh.smn==bit.15 ;Silo Maintenence
|
||
dh.sfl==mask13&mask8 ;Silo Fill Level
|
||
dh.rxm==mask7&mask6 ;Read Extended Memory (A17 and A16)
|
||
dh.sal==mask5 ;Silo Alarm Level
|
||
|
||
|
||
.sbttl -- Macros
|
||
****
|
||
|
||
.macro dh vec,csr,dmvec,dmcsr,lines
|
||
ndhl==0
|
||
lines
|
||
.if p2
|
||
%%==.
|
||
.=dh$vec+<2*ndh>
|
||
.word vec
|
||
.=dh$csr+<2*ndh>
|
||
.word csr
|
||
.=dm$csr+<2*ndh>
|
||
.word dmcsr
|
||
.=dh$tty+<2*ndh>
|
||
.word 2*<ntty-ndhl>
|
||
.=dh$nlines+<2*ndh>
|
||
.word ndhl
|
||
.=%%
|
||
.endc
|
||
ndh==ndh+1
|
||
.endm
|
||
|
||
.macro dhl ttytyp,baud,par,nstop,nbits,where
|
||
.if p1
|
||
%%==.
|
||
.=0
|
||
.string <where>
|
||
.=%%
|
||
.iff
|
||
%%==.
|
||
.=ttyityp+<2*ntty>
|
||
.word t.'ttytyp
|
||
.=ttyispd+<2*ntty>
|
||
.word baud
|
||
.=ttyilo+<2*ntty>
|
||
.string <where>
|
||
.=%%
|
||
.endc
|
||
ntty==ntty+1
|
||
ndhl==ndhl+1
|
||
.endm
|
||
|
||
.endc p1
|
||
|
||
ndh==0 ;no DHs to start with
|
||
|
||
.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
|
||
dsect < ;;; a DH11 receiver structure
|
||
.blkb l$tti ;basically an input tty with....
|
||
>,l$dhr
|
||
|
||
dsect < ;;; a DH11 transmitter structure
|
||
.blkb l$tto ;basically an output tty with...
|
||
$dhxnum:: .blkw 1 ;a DH device index
|
||
$dhsel:: .blkw 1 ;select value to put in dh.scr (with int enables)
|
||
$dhbit:: .blkw 1 ;enable bit (lsh 1 line_number)
|
||
$dhqnb:: .blkw 1 ;number of bytes in last xmit
|
||
>,l$dhx
|
||
|
||
;;; DH11s are PDP11 interfaces to 16 serial lines. Each line is supported
|
||
;;; by one source object, and the transmitter by one destination object.
|
||
|
||
dh$vec: .blkw ndh ;interrupt vector location
|
||
dh$csr: .blkw ndh ;csr device register base address
|
||
dm$csr: .blkw ndh ;one DM per DH
|
||
dh$tty: .blkw ndh ;base tty number of this dh
|
||
dh$nli: .blkw ndh ;number of lines on the DHs
|
||
.wvector dh$oac,ndh ;old active control register
|
||
|
||
dh%bit: .rept 16.
|
||
.word 1_.rpcnt
|
||
.endr
|
||
|
||
dh$brk:
|
||
.rept ndh
|
||
.lif z .rpcnt
|
||
dh$rbk::
|
||
jsr r0,@#dhrint
|
||
.rpcnt*2
|
||
.lif z .rpcnt
|
||
dh$xbk::
|
||
jsr r0,@#dhxint
|
||
.rpcnt*2
|
||
.endr
|
||
ldh$brk==<.-dh$brk>/ndh
|
||
|
||
dh$var: ;vector address, receive
|
||
.rept ndh
|
||
.word dh$rbk+<.rpcnt*ldh$brk>
|
||
.endr
|
||
|
||
dh$vax: ;vector address, xmit
|
||
.rept ndh
|
||
.word dh$xbk+<.rpcnt*ldh$brk>
|
||
.endr
|
||
|
||
|
||
|
||
;;; DH11 receiver interrupt handler. Interrupt vector points in DH$BRK, which
|
||
;;; contains a JSR R0,@#DHRINT. This saves r0 on the stack, and the DH index
|
||
;;; can be picked up with MOV (R0),R0.
|
||
|
||
;;; r0: device index
|
||
;;; r1: character
|
||
;;; r4: tty device
|
||
;;; r5: csr
|
||
|
||
dhrint: mov (r0),r0 ;get DH index
|
||
push r1,r4,r5 ;save some more regs
|
||
mov dh$csr(r0),r5 ;get the csr
|
||
loop <
|
||
mov dh.nxt(r5),r1 ;get the next character
|
||
exitl pl ;nothing there, so exit
|
||
mov r1,r4
|
||
swab r4
|
||
bic #dh.rln,r4 ;get line number
|
||
cmp r4,dh$nlines(r0) ;make sure it is known
|
||
if lt,<
|
||
asl r4 ;indexable
|
||
add dh$tty(r0),r4 ;tty index
|
||
mov ttyrdv(r4),r4 ;get the receive device
|
||
bic #dh.rch,r1 ;get character bits only
|
||
call @$dvlpt(r4) ;put the character in the device
|
||
>
|
||
rptl ;try for more characters
|
||
>
|
||
pop r5,r4,r1,r0
|
||
rti
|
||
|
||
;;; DH11 Transmitter interrupt handler. Interrupt vector points in DH$BRK,
|
||
;;; which contains a JSR R0,@#DHXINT. this saves r0 on the stack and the DH
|
||
;;; index can be picked up with MOV (R0),R0.
|
||
|
||
;;; r0: DH index
|
||
;;; r3: Scratch
|
||
;;; r4: TTY output device
|
||
;;; r5: DH CSR
|
||
|
||
dhxint: mov (r0),r0 ;get index
|
||
push r5,r4,r3 ;save some more regs
|
||
mov dh$csr(r0),r5
|
||
bit #dh.nin,dh.scr(r5) ;NXM interrupt?
|
||
if ne,<bpt> ;GARP
|
||
bic #dh.xin,dh.scr(r5) ;turn interrupts back on (kludge...)
|
||
|
||
push dh$oac(r0) ;get old DH.BAR
|
||
bic dh.bar(r5),(sp) ;now has bits that went inactive
|
||
bic (sp),dh$oac(r0)
|
||
|
||
clr r3 ;start at DH line 0
|
||
loop <
|
||
mov r3,r4 ;get line number
|
||
asl r4 ;index
|
||
add dh$tty(r0),r4 ;now tty index
|
||
mov ttyxdv(r4),r4 ;get the tty xmit device
|
||
bit $dhbit(r4),(sp) ;was it active
|
||
if ne,< ;yup, but isn't now
|
||
add $dhqnb(r4),$dvfpt(r4) ;up the pointer
|
||
cmp $dvfpt(r4),$dvlim(r4) ;hit the top?
|
||
if his,<sub $dvqsz(r4),$dvfpt(r4)> ;chop it down
|
||
sub $dhqnb(r4),$dvhmn(r4) ;discount number of characters in
|
||
;last xmit
|
||
if eq,<bis $dvebx(r4),@$dvepx(r4)> ;allow more user transmission
|
||
else <call dhsout> ;start output to tty if still more
|
||
>
|
||
inc r3 ;go on to the next one
|
||
cmp r3,dh$nlines(r0) ;at the end yet
|
||
rptl lo
|
||
>
|
||
pop *,r3,r4,r5,r0
|
||
rti
|
||
|
||
;;; Start DH output
|
||
;;; r0: dh index
|
||
;;; r4: tty output device
|
||
;;; r5: dh csr
|
||
|
||
dhsout: bic $dhbit(r4),dh.bar(r5) ;make sure it isn't transmitting
|
||
mov $dhsel(r4),dh.scr(r5) ;select the line
|
||
mov $dvfpt(r4),dh.car(r5) ;current address register
|
||
push $dvlim(r4) ;upper limit of ring buffer
|
||
sub $dvfpt(r4),(sp) ;max number we should transmit
|
||
cmp $dvhmn(r4),(sp) ;does it wrap?
|
||
if lt,<mov $dvhmn(r4),(sp)> ;output the min
|
||
mov (sp),$dhqnb(r4) ;save queued nbytes for later updating
|
||
neg (sp) ;hardware wants neg count
|
||
pop dh.bcr(r5) ;byte count register
|
||
bis $dhbit(r4),dh.bar(r5) ;start it transmitting in hardware
|
||
bis $dhbit(r4),dh$oac(r0) ;and software
|
||
return
|
||
|
||
;;; Power-up and Initialization code
|
||
|
||
dhpwu::
|
||
dhini: clr r0
|
||
loop <
|
||
call dhinit ;initialize this DH11 (16 lines)
|
||
add #2,r0
|
||
cmp r0,#2*ndh ;done all yet??
|
||
rptl lt
|
||
>
|
||
return
|
||
|
||
;;; Initialize a 16-line DH11. Called with R0 as DH11 index.
|
||
|
||
dhinit: push r5,r4 ;save regs
|
||
mov dh$csr(r0),r5 ;get the CSR for this DH11
|
||
call nxmcat ;is it really there??
|
||
dhnxm
|
||
mov #dh.mcl,dh.scr(r5) ;do a master clear
|
||
clr dh.brk(r5) ;nobody doing breaks
|
||
clr dh.ssr(r5) ;zero limit, zero alarm limit for silo
|
||
mov #dh.xie+dh.rie,dh.scr(r5) ;enable interrupts
|
||
call nxmclr ;looks good, clear nxm catch
|
||
clr dh$oac(r0) ;no old active lines
|
||
|
||
mov dh$vec(r0),r4 ;interrupt vector
|
||
mov dh$var(r0),(r4)+ ;setup receive interrupt routine
|
||
mov #pr5,(r4)+ ;and priority
|
||
mov dh$vax(r0),(r4)+ ;setup xmit interrupt routine
|
||
mov #pr5,(r4)+ ;and priority
|
||
|
||
push r2,r1
|
||
mov dh$csr(r0),r5 ;get CSR back
|
||
mov dh$nlines(r0),r4 ;number of lines
|
||
loop <
|
||
mov dh$nlines(r0),r1
|
||
sub r4,r1 ;which line
|
||
mov r1,dh.scr(r5) ;select the line
|
||
|
||
mov r1,r3 ;set speed
|
||
asl r3
|
||
add dh$tty(r0),r3 ;tty index
|
||
mov ttyisp(r3),r3 ;get speed
|
||
mov #dhstbl,r2 ;get speed table
|
||
loop <
|
||
tst (r2)
|
||
if eq,<bpt>
|
||
cmp (r2)+,r3
|
||
exitl eq
|
||
tst (r2)+
|
||
rptl
|
||
>
|
||
mov (r2),r2 ;get the speed bits
|
||
bis #dh.8bt,r2 ;turn on 8bit mode
|
||
mov r2,dh.lpr(r5)
|
||
|
||
.if z qbus
|
||
mov dm$csr(r0),r2
|
||
if ne,<
|
||
call nxmcat
|
||
.word 10$
|
||
mov r1,(r2) ;set the line number
|
||
mov #2,2(r2) ;turn on DTR
|
||
call nxmclr
|
||
10$:
|
||
>
|
||
.endc
|
||
push r1
|
||
asl (sp)
|
||
add dh$tty(r0),(sp) ;tty index
|
||
push #l$dhr,#l$dhx ;size of xmit and recv devices
|
||
call ttygood
|
||
if cs,<bpt>
|
||
|
||
pop r2 ;get xmit device
|
||
mov #dhpput,$dvppt(r2) ;set physical put
|
||
mov r0,$dhxnum(r2)
|
||
mov r1,$dhsel(r2)
|
||
bis #dh.xie+dh.rie,$dhsel(r2) ;select is line with enable bits
|
||
asl r1 ;don't use r1 below here
|
||
mov dh%bit(r1),$dhbit(r2) ;enable bit
|
||
clr $dhqnb(r2)
|
||
|
||
pop r2 ;get receive device
|
||
mov #dhpget,$dvpgt(r2) ;set physical get routine
|
||
|
||
pop * ;punt tty index
|
||
|
||
dec r4
|
||
rptl ne ;too far for SOB
|
||
>
|
||
mov #dh.xie+dh.rie,dh.scr(r5) ;enable interrupts
|
||
pop r1,r2
|
||
|
||
pop r4,r5
|
||
return
|
||
|
||
.macro ..dhs speed,ubusval,qbusval
|
||
.if nz dhubus
|
||
.if ge ubusval
|
||
.word speed,ubusval*<<1_dh.tsp>+<1_dh.rsp>>
|
||
.endc
|
||
.iff
|
||
.if ge qbusval
|
||
.word speed,qbusval*<<1_dh.tsp>+<1_dh.rsp>>
|
||
.endc
|
||
.endc
|
||
.endm
|
||
|
||
dhstbl: ;dh speed table
|
||
..dhs 19200.,16,17
|
||
..dhs 9600.,15,16
|
||
..dhs 7200.,-1,15 ;only on qbus version
|
||
..dhs 4800.,14,14
|
||
..dhs 3600.,-1,13
|
||
..dhs 2400.,13,12
|
||
..dhs 2000.,-1,11
|
||
..dhs 1800.,12,10
|
||
..dhs 1200.,11,07
|
||
..dhs 600.,10,06
|
||
..dhs 300.,07,05
|
||
.word 0
|
||
|
||
dhnxm: push r0
|
||
mov dh$nlines(r0),r5
|
||
mov dh$tty(r0),r0
|
||
loop <
|
||
call ttybad
|
||
tst (r0)+
|
||
sorl r5
|
||
>
|
||
pop r0,r4,r5
|
||
return
|
||
|
||
dhpput: lock 6
|
||
call chnput
|
||
if cc,<
|
||
push r0
|
||
mov $dhxnum(r4),r0 ;get DH index
|
||
bit $dhbit(r4),dh$oac(r0) ;was it idle
|
||
if eq,<
|
||
push r5
|
||
mov dh$csr(r0),r5
|
||
call dhsout
|
||
pop r5
|
||
>
|
||
pop r0
|
||
>
|
||
unlock
|
||
return
|
||
|
||
dhpget: ;physical get
|
||
lock 6
|
||
call chnget
|
||
unlock
|
||
return
|
||
|
||
.endc %defin
|
||
|
||
.iif nz %defin, .list ;start listing as usual
|
||
|
||
|
||
;; local modes:
|
||
;; mode:midas
|
||
;; auto fill mode:
|
||
;; fill column:75
|
||
;; comment column:32
|
||
;; end:
|