1
0
mirror of https://github.com/PDP-10/its.git synced 2026-03-24 01:27:33 +00:00
Files
PDP-10.its/src/mits_s/dh11.10
2018-11-25 20:59:17 +01:00

456 lines
11 KiB
Plaintext
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 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: