1
0
mirror of https://github.com/PDP-10/its.git synced 2026-04-17 08:51:08 +00:00
Files
PDP-10.its/src/mits_s/ch11.14
2018-11-25 20:59:17 +01:00

446 lines
12 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 CHAOS-11 support
.sbttl CHAOS-11 support: Definitions, Macros and Code
.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
defnet c11 ;declare running with Chaos-11 hardware
.pkhrd < ;; needed packet fields for hardware
..word $c1hrd,1 ;hardware destination
>
.if p1
.sbttl -- Definitions
;;
;;;;;; hardware definitions for the chaos-11 hardware
;;
CH.CSR==0 ;OFFSET OF COMMAND STATE REG FROM THE BASE ADDRESS
%CATIE==1 ;0 FORMERLY XMT BUSY NOW QUAD TIMER INTERRUPT ENABLE (R/W)
%CALPBK==2 ;1 LOOP BACK MODE (DOESN'T USE CABLE WHEN ON) (R/W)
%CASPY==4 ;2 RECIEVE MSGS FOR ANY DESTINATION (R/W)
%CARCL==10 ;3 CLEAR THE RECEIVER. WRITING A 1 CLEARS RCV DONE
; AND ENABLES THE RECEIVER TO GOBBLE ANOTHER MESSAGE (WO)
%CAREN==20 ;4 RCV INT ENB (R/W)
%CATEN==40 ;5 XMT INT ENB (R/W)
%CATAB==100 ;6 TRANSMIT ABORTED BY ETHER CONFLICT (RO)
%CATDN==200 ;7 TRANSMIT DONE. SET WHEN TRANSMITTER IS DONE
%CATCL==400 ;8 CLEAR THE TRANSMITTER MAKING IT READY (WO)
;9-12 LOST COUNT (RO) [# MSGS RCVED WITH RCV BFR FULL]
; WHEN MSG IS WAITING IN BUFFER, THIS COUNTS
; THE MESSAGES THAT MATCHED OUR DESTINATION OR
; WERE BROADCAST, BUT COULDN'T BE RECIEVED.
; WHEN RECEIVER IS RE-ENABLED (WRITE 1 INTO %CARDN)
; THE COUNT IS THEN CLEARED.
; WHEN A MESSAGE IS LOST, RECEIVER ZAPS ETHER
; SO TRANSMITTER WILL ABORT (IF MESSAGE WAS DESTINED
; TO US.)
%CARST==20000 ;13 I/O RESET (WO)
%CAERR==40000 ;14 CRC ERROR (RO)
%CARDN==100000 ;15 RCV DONE.
CH.MYN==2 ;OFFSET OF MY # (READ ONLY)
;RETURNS THE [SOURCE] HOST# OF THIS INTERFACE.
CH.NET==3 ;OFFSET FOR READING SUBNET #
CH.WBF==2 ;OFFSET OF WRITE BUFFER (WRITE ONLY)
;FIRST WAIT FOR TDONE. (OR SET IT VIA CSR)
;FIRST WORD IN RESETS TRANSMITTER AND CLEARS TDONE.
;STORE INTO THIS REGISTER TO WRITE WORDS OF MESSAGE,
;LAST WORD IN IS DESTINATION ADDRESS, THEN READ CAIXMT.
;SOURCE ADDRESS AND CHECK WORD PUT IN BY HARDWARE.
CH.RBF==4 ;OFFSET OF READ BUFFER (READ ONLY)
;THE FIRST WORD READ WILL BE FILLED TO THE LEFT
;TO MAKE THE MESSAGE RECIEVED A MULTIPLE OF 16 BITS.
;IF THE NUMBER OF DATA BITS IN THE MESSAGE WAS A
;MULTIPLE OF 16, THIS WORD WILL BE THE FIRST WORD PUT
;INTO THE BUFFER BY THE TRANSMITTING HOST.
;THE LAST 3 WORDS READ ARE DESTINATION, SOURCE, CHECK.
CH.RBC==6 ;OFFSET OF RECEIVE BIT COUNTER (READ ONLY)
;WHEN A MESSAGE HAS BEEN RECEIVED THIS IS ONE LESS THAN
;THE NUMBER OF BITS IN THE MESSAGE (16 X THE
;NUMBER OF WORDS INCLUDING THE THREE OVERHEAD WORDS.)
;AFTER THE LAST WORD (THE CRC WORD) HAS BEEN READ, IT IS 7777
;BITS 10 AND 11 ARE THE HIGH ORDER BITS, AND IF THEY ARE ONE,
;THEN THERE WAS A BUFFER OVERFLOW
;NOTE: FOR THE Q-BUS VERSION OF THE INTERFACE (FOR LSI-11'S)
;WRITING CAIMYN INTO CAIRBC INITIATES TRANSMISSION.
CH.XMT==12 ;READING THIS OFFSET INITIATES TRANSMISSION (!!)
;THE VALUE READ IS ONE'S OWN HOST#.
;**** NOTE COMMENT ABOVE UNDER CAIRBF FOR LSI-11'S ****
CH.TMR==20 ;OFFSET OF INTERVAL TIMER
%c1max==16.+488. ;largest hardware packet size
.endc p1
****
.sbttl -- Macros
****
nch11==0 ;no CH11s to start with
.macro ch11 vec,csr,roudem,slow
.iif z nch11, c11net==nnet ;base net object of chaos-11 network objects
.if p2
%%==.
.=c1$vec+<2*nch11>
.word vec
.=c1$csr+<2*nch11>
.word csr
.=c1$cst+<2*nch11>
.word 11.+0'roudem
.=c1$slo+<2*nch11>
.word 0'slow
.=%%
.endc
nch11==nch11+1
nnet==nnet+1
.endm
.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
.iif z netc11, .error CHAOS-11 being included without support in PKTNCP
;;
;;;;;; Tables and pointers
;;
c1$vec: .blkw nch11 ;table of interrupt vectors
c1$csr: .blkw nch11 ;table of control/status registers
c1$cst: .blkw nch11 ;table of routing cost
c1$slo: .blkw nch11 ;is this a slow interface?
c1$brk:
.rept nch11
jsr r5,@#c1int
.word netobj+<2*c11net>+<2*.rpcnt>
.endr
lc1$brk==<.-c1$brk>/nch11
c1$vad: ;addresses at the vectors
.rept nch11
.word c1$brk+<.rpcnt*lc1$brk>
.endr
;;
;;;;;; A hardware object
;;
dsect <
.blkb l$nt ;length of a standard network object
$c1lok:: .blkw 1 ;device service lock
$c1run:: .blkw 1 ;keep the process running flag
$c1sup:: .blkw 1 ;bits that are "supposed" to be on
$c1xla:: .blkw 1 ;alst one sent (for aborts)
$c1xna:: .blkw 1 ;number of aborts for the current packet
$c1slo:: .blkw 1 ;is this a slow interface
>,l$c11
;;; The CHAOS-11 interrupt vector points to a JSR R5,@#C1INT. This
;;; pushes r5 on the stack and leaves r5 pointing to a pointer to the
;;; object. Therefore the object can be obtained by mov @(r5),r5.
;;; Note that this does not do anything with a packet; all packet
;;; frobing for this device is done at program level. The only thing
;;; this does is turn off interrupts and kick the service process.
c1int: mov @(r5),r5 ;pick up the object
push @$ntcsr(r5) ;get the CSR value on the stack
bic #-1-<%caten+%caren>,(sp) ;get only int enable bits
bis (sp)+,$c1sup(r5) ;and say we should restore those
bic #%caten+%caren,@$ntcsr(r5) ;turn off all interrupts
mov #1,$c1run(r5) ;tell the service routine to keep running
inc $c1lok(r5) ;try to grab the lock
if eq,<
mtps 4(sp) ;restore previous interrupt priority (under
;r5 and address)
.intstk < ;on the interrupt stack
call c1$int ;service this interface
> >
dec $c1lok(r5) ;release the lock
pop r5 ;restore reg
rti ;and conclude interrupt
;;; This is the routine that actually frobs the packets in and out of
;;; the CHAOS-11 hardware. All registers except r5 must be saved before
;;; using.
;;; registers:
;;; r5 base of hardware object
;;; r4 CSR address (not set up on entry)
c1$int: push r4,r3,r2,r1,r0 ;save entire register set (r5 known to be bashable)
mov $ntcsr(r5),r4 ;get CSR address
loop <
lock 7 ;don't lose a wakeup
tst $c1run(r5) ;keep running?
if eq,<
pop * ;about to return, throw away old priority.
;A valid priority will get set by the RTI
;of the person that called us.
bis #%caren,$c1sup(r5) ;always enable receiver interrupts
bis $c1sup(r5),(r4) ;turn on other bits that are supposed to be on
pop r0,r1,r2,r3,r4 ;restore register set
return
>
unlock
clr $c1run(r5)
bit #%cardn,(r4) ;receiver done
if ne,<
call c1rint ;simulate a receiver interrupt
inc $c1run(r5) ;keep the process running
>
bit #%caten,$c1sup(r5) ;waiting for interrupt?
if ne,< ;yup
bit #%catdn,(r4) ;transmitter ready?
if ne,<
call c1xint ;go transmit it
inc $c1run(r5) ;keep the process running
> >
rptl ;keep looping
>
c1rint:
clr r1 ;no packet to start with
loop < ;allow for easy exit on error conditions
bit #%caerr,(r4) ;CRC error?
if ne,< netmet cr
exitl>
mov ch.rbc(r4),r3 ;get the bit count
inc r3 ;hardware doesn't count one
bit #17,r3 ;better be multiple of 16 bits
if ne,< netmet bl ;bad length
exitl>
ash #-3,r3 ;convert to bytes
sub #2*3,r3 ;don't count 3 hardware words
cmp r3,#<pksiz.-$pktdt> ;minimum size of all packets
if lo,< netmet ot ;other reason for rejecting
exitl>
.iif le %c1max-<pksiz$-$pktdt>, %%==%c1max
.iif le <pksiz$-$pktdt>-%c1max, %%==<pksiz$-$pktdt>
cmp r3,#%% ;range check the high end
if hi,< netmet ot ;other reason for rejecting
exitl>
mov r3,r1
add #$pktdt,r1 ;size of packet needed
call pktall
if eq,< netmet ot ;lost for an "other" reason
exitl>
mov r1,r2 ;get pointer to packet
add #$pktdt,r2 ;go to the data portion
add #ch.rbf,r4 ;point to read buffer
neg r3 ;negative offset
call 100$(r3) ;get those bytes in a hurry
cmp (r4),(r4) ;skip destination and hardware source
tst (r4) ;skip CRC code
sub #ch.rbf,r4 ;go back to CSR
bit #%caerr,(r4) ;CRC error?
if ne,< ;yup, sigh
netmet c2
call pktfre
exitl
>
>
mov (r4),r2 ;get the CSR to get the lost count
swab r2
asr r2
bic #mask4,r2 ;finally have the lost count
netmet lo,r2 ;count them as lost
bis #%carcl,(r4) ;tell the hardware we are clear to receive
bis #%caren,$c1sup(r5) ;and tell the software to arm receive interrupts
tst r1
if eq,<return> ;if no packet, just return
bis #%pkt08,$pktfl(r1) ;declare packet safe for 8 bit
.if nz ncpchs
tstb $pktdt(r1) ;is it chaos protocol?
if eq,<jcall chsrcv> ;go receive the chaos packet
.endc
.if nz ncpip
.endc
netmet ot ;reject if not known protocol
jcall pktfre ;free the packet
.rept %c1max/2
mov (r4),(r2)+
.endr
100$: return
c1xint: mov $c1xla(r5),r1 ;get the last packet transmitted
if ne,< ;if there was one
clr $c1xla(r5)
bit #%catab,(r4) ;check for transmit abort
if ne,< ;yup, had an abort
netmet ab ;count another abort
inc $c1xna(r5) ;up the number of aborts for this packet
cmp $c1xna(r5),#8 ;allow 8 aborts
blt c1xtrn ;try and transmit it again
>
else <netmet ou> ;count the packet as successfully out
c1xin0: call pktngv ;free packet if not on user list
>
clr $c1xna(r5) ;no aborts yet
c1xin1: call ntremq ;remove a packet from the net device
if eq,<
c1xin2: bic #%caten,$c1sup(r5) ;disarm xmit interrupts
return
>
c1xtrn: cmp $pktul(r1),#+1 ;if user link +1, then we can throw it away
if eq,< call pktfre ;free it
br c1xin1 > ;go try another
bis #%catcl,(r4) ;clear the transmitter
mov $pktxs(r1),r3 ;get number of data bytes (rounded up to word)
cmp r3,#%c1max ;is it within range
bgt c1xin0 ;if too big, throw it away
mov r1,r2 ;get pointer to packet
add #$pktdt,r2 ;go up to the base of the packet
add #ch.wbf,r4 ;go to the write buffer
neg r3 ;negative address offset
call 10$(r3) ;push the packet in fast
mov $c1hrd(r1),(r4) ;hardware destination
sub #ch.wbf,r4 ;go back to the base
tst ch.xmt(r4) ;go Go GO!!
mov r1,$c1xla(r5) ;this was the last one transmitted
mov time,$pktxt(r1) ;remember the time for retransmission
tst $c1slo(r5) ;slow?
if ne,<bic #%caten,$c1sup(r5)> ;yes, wait until the clock ticks
return
.rept %c1max/2
mov (r2)+,(r4)
.endr
10$: return
.syclk c1cint
c1slon: .word 2
c1slct: .word 2
c1cint: dec c1slct
if le,<
mov c1slon,c1slct
push r0,r5
clr r0
loop <
tst c1$slo(r0)
if ne,<
mov netobj+<2*c11net>(r0),r5
tst $ntxqu(r5)
if ne,<bis #%caten,@$ntcsr(r5)>
>
add #2,r0
cmp r0,#nch11*2
rptl lo
>
pop r5,r0
>
return
c1ini: clr r0 ;index
loop <
call c1init
add #2,r0
cmp r0,#nch11*2
rptl lo
>
return
c1init: ;actually init one device
mov c1$csr(r0),r4 ;get the csr
call nxmcat
c1nxm
mov #%carst,(r4) ;reset the board
tst ch.myn(r4) ;get my hardware address
call nxmclr
mov c1$vec(r0),r2 ;get interrupt vector
mov c1$vad(r0),(r2)+ ;set vector address
mov #pr5,(r2)+
mov c1$vad(r0),(r2)+ ;and for interval timer??
mov #pr5,(r2)+
mov #l$c11,r5
call ntmake ;make the network object
if eq,<bpt> ;oops
mov r5,netobj+<2*c11net>(r0) ;save device in network table
mov r4,$ntcsr(r5) ;save CSR address
mov #-1,$c1lok(r5) ;preset the lock to free
mov c1$slo(r0),$c1slo(r5);slowness
.if nz ncpchs
mov #c1chgv,nt$chs(r5) ;routine to send chaos packets to interface
mov ch.myn(r4),nt.chs(r5) ;my address on chaos net
mov c1$cst(r0),$ctrcv(r5) ;routing cost for this interface
.endc
.if nz ncpip
.endc
mov #%carcl+%caren+%caten,(r4) ;clear receiver and allow
;interrupts
mov r0,r4 ;get chaos index into r4
add #<c11net*2>,r4 ;now network index
jcall ntmak1 ;finish making the object
c1nxm: clr netobj+<2*c11net>(r0) ;no network object
return
.if nz ncpchs
;;; call @nt$chs(r5)[r5:=object, r1:=packet, r2:=hardware_destination(if_needed)]
c1chgv: call cpks08 ;make packet safe for 8 bit hardware
mov r2,$c1hrd(r1) ;set the hardware destination
inc $pktxs(r1) ;round up to word boundary...
bic #1,$pktxs(r1) ;...
lock 6
call nt$ptq ;put it on the queue
tst $c1slo(r5) ;slow interface?
if eq,<bis #%caten,@$ntcsr(r5)> ;signal xmit interrupt
unlock
return
.endc
.endc %defin
.iif nz %defin, .list ;start listing as usual
;; local modes:
;; mode:midas
;; auto fill mode:
;; fill column:75
;; comment column:32
;; end: