Trailing-Edge
-
PDP-10 Archives
-
BB-4170H-SM
-
sources/iman22.mac
There is 1 other file named iman22.mac in the archive. Click here to see a list.
;<4.MONITOR>IMAN22.MAC.71, 10-Jan-80 09:45:23, EDIT BY STOCKDALE
;ADD "AND T2,[-1,,177777] & AND T4,..." to ensure bits 18,19 are cleared - this
; fixes problem where UBA puts buffer address into buffer (18 bit address) on a
; left byte transfer which then messes up IMAN22 which expects to see only 16
; bit bytes.
;<4.MONITOR>IMAN22.MAC.70, 3-Jan-80 08:08:53, EDIT BY R.ACE
;UPDATE COPYRIGHT DATE
;[SRI-KL]<LCAMPBELL>IMAN22.MAC.72 7-Dec-79 09:27:30, Edit by LCAMPBELL
;[SRI-KL]<LCAMPBELL>IMAN22.MAC.71 6-Dec-79 09:59:54, Edit by LCAMPBELL
;[SRI-KL]<LCAMPBELL>IMAN22.MAC.70 5-Dec-79 10:04:27, Edit by LCAMPBELL
;[SRI-KL]<LCAMPBELL>IMAN22.MAC.69 4-Dec-79 12:14:17, Edit by LCAMPBELL
;[SRI-KL]<LCAMPBELL>IMAN22.MAC.68 28-Nov-79 17:47:16, Edit by LCAMPBELL
;[SRI-KL]<LCAMPBELL>IMAN22.MAC.67 15-Nov-79 19:58:27, Edit by LCAMPBELL
; Fix special queues
;<4.MONITOR>IMAN22.MAC.66, 17-Sep-79 12:26:35, Edit by LCAMPBELL
; Document BUGs
;<OSMAN.MON>IMAN22.MAC.1, 10-Sep-79 15:32:57, EDIT BY OSMAN
;TCO 4.2412 - Move definition of BUGHLTs, BUGCHKs, and BUGINFs to BUGS.MAC
;<4.MONITOR>IMAN22.MAC.64, 6-Sep-79 14:43:29, Edit by LCAMPBELL
; BUGHLT if input started without an input buffer available
;<4.MONITOR>IMAN22.MAC.63, 18-Jul-79 16:50:12, Edit by LCAMPBELL
; Fix byte count for 36-bit mode output and special queues output
;<4.MONITOR>IMAN22.MAC.62, 17-Jul-79 11:47:18, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.61, 17-Jul-79 10:41:05, Edit by LCAMPBELL
; Fix PK3236, it also wasn't quite right
;<4.MONITOR>IMAN22.MAC.60, 16-Jul-79 21:34:44, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.59, 16-Jul-79 20:01:10, Edit by LCAMPBELL
; Overhaul UP3632 -- it was only half right
;<4.MONITOR>IMAN22.MAC.58, 16-Jul-79 13:04:00, Edit by LCAMPBELL
; Type out address of caller of AN2BUG
;<4.MONITOR>IMAN22.MAC.57, 11-Jul-79 17:34:46, Edit by LCAMPBELL
; Pare down number of RDIOs and WRIOs for better performance
;<4.MONITOR>IMAN22.MAC.56, 11-Jul-79 16:52:55, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.55, 10-Jul-79 16:41:04, Edit by LCAMPBELL
; Random fixes
;<4.MONITOR>IMAN22.MAC.54, 5-Jul-79 17:48:52, Edit by LCAMPBELL
; Get packing decisions right at AN2RC7
;<4.MONITOR>IMAN22.MAC.53, 29-Jun-79 15:29:41, Edit by LCAMPBELL
; Invalidate cache before touching input buffer
;<4.MONITOR>IMAN22.MAC.52, 28-Jun-79 17:28:42, Edit by LCAMPBELL
; When starting input (AN2STI), insure no input in progress
;<4.MONITOR>IMAN22.MAC.51, 27-Jun-79 19:14:54, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.50, 27-Jun-79 16:32:55, Edit by LCAMPBELL
; Minor fixes
;<4.MONITOR>IMAN22.MAC.49, 22-Jun-79 00:17:10, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.48, 21-Jun-79 14:10:57, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.47, 19-Jun-79 13:58:35, Edit by LCAMPBELL
; Ignore leftover data available interrupts if input in progress
;<4.MONITOR>IMAN22.MAC.46, 18-Jun-79 14:55:08, Edit by LCAMPBELL
; Fix race in input service
;<4.MONITOR>IMAN22.MAC.45, 18-Jun-79 11:56:01, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.44, 18-Jun-79 11:53:26, Edit by LCAMPBELL
; Reboot AN22 when bringing net back up
;<4.MONITOR>IMAN22.MAC.43, 14-Jun-79 19:54:40, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.42, 13-Jun-79 11:52:05, Edit by LCAMPBELL
; Handle case of data arriving when handling input interrupt
; and no buffers are available (flag interrupt for later)
;<4.MONITOR>IMAN22.MAC.41, 12-Jun-79 12:34:37, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.40, 8-Jun-79 15:19:44, Edit by LCAMPBELL
; Save a RDIOB, they're damn expensive
;<4.MONITOR>IMAN22.MAC.39, 8-Jun-79 15:14:34, Edit by LCAMPBELL
; Keep history of recent commands in ring buffer for debugging
;<4.MONITOR>IMAN22.MAC.38, 6-Jun-79 14:50:09, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.37, 4-Jun-79 18:03:33, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.36, 4-Jun-79 18:00:18, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.35, 31-May-79 10:23:46, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.34, 28-May-79 16:04:58, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.33, 28-May-79 16:02:32, Edit by LCAMPBELL
; Make AN2BUG a BUGCHK, get word count right at AN2LDR
;<4.MONITOR>IMAN22.MAC.32, 25-May-79 13:41:08, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.31, 25-May-79 13:12:08, Edit by LCAMPBELL
; Bug fixes, code cleanup
;<4.MONITOR>IMAN22.MAC.30, 24-May-79 18:04:57, Edit by LCAMPBELL
; Check to see if xmit done at xmit interrupt routines
;<4.MONITOR>IMAN22.MAC.29, 23-May-79 11:42:47, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.28, 22-May-79 11:11:49, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.27, 20-May-79 18:56:15, Edit by LCAMPBELL
; Allocate buffers at link time, not runtime
;<4.MONITOR>IMAN22.MAC.26, 16-May-79 17:04:27, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.25, 15-May-79 14:24:02, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.24, 14-May-79 18:03:18, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.23, 14-May-79 14:43:24, Edit by LCAMPBELL
; Fix handling of buffer pointers
;<4.MONITOR>IMAN22.MAC.22, 14-May-79 10:51:08, Edit by LCAMPBELL
; Add code to verify microcode and follow std KMC conventions more closely
;<4.MONITOR>IMAN22.MAC.21, 14-May-79 10:12:01, Edit by LCAMPBELL
; Fix AC usage at call to packing routine
;<4.MONITOR>IMAN22.MAC.20, 11-May-79 17:26:04, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.19, 11-May-79 16:15:18, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.18, 11-May-79 16:10:07, Edit by LCAMPBELL
; Random bug fixes
;<4.MONITOR>IMAN22.MAC.17, 4-May-79 11:52:29, Edit by LCAMPBELL
; Fix AC usage at BUTKMC
;<4.MONITOR>IMAN22.MAC.16, 19-Apr-79 09:43:44, Edit by LCAMPBELL
; Set AN2XIE before telling AN22 to transmit
;<4.MONITOR>IMAN22.MAC.15, 18-Apr-79 15:49:00, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.14, 18-Apr-79 15:39:48, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.13, 18-Apr-79 13:58:23, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.12, 18-Apr-79 12:32:08, Edit by LCAMPBELL
; Minor code reordering and listing cleanup
;<4.MONITOR>IMAN22.MAC.11, 18-Apr-79 09:52:40, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.10, 17-Apr-79 15:32:40, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.9, 17-Apr-79 15:29:04, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.8, 17-Apr-79 15:26:07, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.7, 17-Apr-79 15:15:23, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.6, 17-Apr-79 15:13:47, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.5, 17-Apr-79 15:11:40, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.4, 17-Apr-79 15:10:47, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.3, 17-Apr-79 15:09:56, Edit by LCAMPBELL
;<4.MONITOR>IMAN22.MAC.2, 17-Apr-79 14:34:25, Edit by LCAMPBELL
; Fix random assembly errors
;<LCAMPBELL.ARPANET>IMAN22.MAC.62, 17-Apr-79 14:33:51, Edit by LCAMPBELL
; Creation
;This software is furnished under a license and may only be used
; or copied in accordance with the terms of such license.
;
;Copyright (C) 1979,1980 by Digital Equipment Corporation, Maynard, Mass.
SEARCH MACSYM,MONSYM,IMPPAR,PROKS,PROLOG
SALL
.DIRECTIVE FLBLST
TTITLE (IMPPHY,IMAN22,< - AN22 driver for 2020 - L. Campbell>)
;Nota bene:
; Although this driver was written for a 2020, care has been taken
; to write code that will run in nonzero sections, so that future
; machines with extended addressing can use this driver.
;
; All interrupt routines save T1-T4, CX, CSR, and P, and dismiss through
; common exit code.
;
; Unlike IMPANX, the word count stored in NBBSZ on a receive is computed
; from HHSIZ and HHCNT in the H-H leader. IMPANX computes it from the
; word count kept by the AN10. These should agree, but watch out...
; (Note: for special queues the word count supplied by the firmware
; in the AN22 is believed, because there is no H-H leader)
DEFAC (CSR,Q3) ; address of AN22 CSRs (control & status regs)
;Hardware definitions
AN2UBN==3 ; UBA number AN22 sits on
AN2ADR==AN2UBN,,760110 ; AN22 CSR address
AN2VEC==300 ; AN22 vector A address
SEL0==0
BSEL0==0 ; command handed to AN22
BSEL1==1 ; maintenance register
; contains microcode version number
KMCRUN==100000 ; KMC run flop
KMCCLR==040000 ; KMC master clear
SEL2==2 ; BSEL2 and BSEL3 are occasionally referenced as a word
BSEL2==2 ; bits
AN2PDP==1 ; PDP-11 mode (byte-swapping)
AN2RDA==2 ; receive data available
AN2RDN==4 ; receive done
AN2XDN==10 ; transmit done
AN2HRD==20 ; host ready
AN2IRD==40 ; IMP ready
AN2ILX==100 ; illegal command code
AN2IWD==200 ; IMP was down (ready line error)
BSEL3==3 ; more bits, and fields
AN2XIE==1 ; transmit interrupt enable
AN2RIE==2 ; receive interrupt enable
AN2XTC==34 ; transmit termination code
MSKSTR XMTTM,,AN2XTC
AN2RTC==340 ; receive termination code
MSKSTR RCVTM,,AN2RTC
TC.NEM==1 ; not end of message
TC.EOM==2 ; end of message
TC.NMP==3 ; NXM fetching buffer pointer
TC.NMB==4 ; NXM accessing buffer
TC.NNB==5 ; non-negative byte count
SEL4==4 ; SEL4 and SEL6 are addressed as words
SEL6==6
; AN22 command codes
C.NOOP==200 ; no-op
C.SHRD==201 ; set host ready (AN2HRD)
C.CHRD==202 ; clear host ready (AN2HRD)
C.SRIE==203 ; set receive interrupt enable (AN2RIE)
C.CRIE==204 ; clear receive interrupt enable (AN2RIE)
C.SXIE==205 ; set transmit interrupt enable (AN2XIE)
C.CXIE==206 ; clear transmit interrupt enable (AN2XIE)
C.XPAR==207 ; transmit partial message
C.XEOM==210 ; transmit end of message (set LHB when done)
C.RECV==211 ; start a receive
C.SPDP==212 ; set PDP-11 mode (don't reorder bytes)
C.CIWD==213 ; clear IMP was down (AN2IWD)
C.RSET==214 ; reset
; 215-220 ; reserved
; Random parameters
STY%NP==0 ; number of words of leader padding requested
AN2STN==30 ; size of interrupt stack
MXWPM==400 ; maximum words per message
CMRNGN==^D64 ; length of command ring buffer
; Storage
RS(AN2AC1,2) ; interrupt ACs
RS(AN2AC3,2) ; ..
RS(AN2CSR,1) ; ..
RS(AN2CX,2) ; also gets P
RS(AN2STK,AN2STN) ; interrupt stack
RS(AN2NMR,1) ; number of UBA mapping registers used
RS(INBUB,1) ; Unibus address of input buffer
RS(OUTBUB,1) ; Unibus address of output buffer
RS(AN2UBM,1) ; address of first UBA map register
RS(AN2XPC,10) ; XPCW block for vectored interrupts (2)
RS(AN2NRD,1) ; no. of times we had cmd ready but AN22 wasn't
RS(AN2BAD,1) ; no. of junk messages received
RS(INPON,1) ; input interrupts are enabled
RS(IOWDIU,1) ; Unibus address of input IOWD
RS(IOWDOU,1) ; Unibus address of output IOWD
RS(UBWADR,0) ;----start of area windowed into Unibus space
RS(IOWDI,1) ; input IOWD
RS(IOWDO,1) ; output IOWD
RS(AN2IBF,MXWPM) ; input buffer
RS(AN2OBF,MXWPM) ; output buffer
RS(UBWEND,0) ;----end of Unibus window
RS(CMRNGB,1) ; pointer to command ring buffer
RS(RING,CMRNGN) ; the ring buffer
RS(CMRNGE,0) ; end of ring buffer
UCDVER: EXP 215 ; microcode version we understand
; Boot the AN22, set up XPCW block, allocate buffers, etc.
IMPINI::MOVE T1,[AN2ADR] ; address of AN22
CALL UBGOOD ; check to see if installed
RET ; no AN22
XMOVEI T1,UBWADR ; address of first thing windowed to Unibus
LSH T1,-^D9 ; starting page of window
XMOVEI T2,UBWEND ; last page of window
LSH T2,-^D9 ; ending page of window
SUB T2,T1 ; pages needed
ADDI T2,1 ; ..
MOVEM T2,AN2NMR ; remember how many mapping regs used
MOVEI T1,AN2UBN ; UBA unit number
CALL ALUBWA ; get UBA mapping registers
BUG(AN2NUA)
MOVEM T1,AN2UBM ; save address of UBA mapping registers
XMOVEI T1,UBWADR ; get -10 address of buffer space
ANDI T1,777 ; word offset within page
LSH T1,2 ; byte offset within page
ADD T2,T1 ; compute Unibus address of buffer space
LSH T2,-2 ; form Unibus -10-word address
MOVEM T2,IOWDIU ; save Unibus addr of input IOWD
ADDI T2,1 ; next Unibus addr
MOVEM T2,IOWDOU ; is Unibus addr of output IOWD
ADDI T2,1 ; next is first buffer
MOVEM T2,INBUB ; save Unibus address of input buffer
ADDI T2,MXWPM ; plus length gives Unibus addr of next buffer
MOVEM T2,OUTBUB ; save its Unibus address
; ..
; ..
MOVE T1,AN2UBM ; addr of UBA mapping registers
MOVEI T2,AN2IBF ; get address of AN22 buffers
LSH T2,-^D9 ; convert to page number
IORI T2,UNBVBT ; flag valid
MOVE T3,AN2NMR ; no. of mapping registers
IMPIN1: WRIO T2,@T1 ; set mapping register
ADDI T2,1 ; next page
ADDI T1,1 ; next map register
SOJG T3,IMPIN1 ; loop for all pages in window
MOVSI T1,(<XPCW>) ; interrupt instruction
HRRI T1,AN2XPC ; XPCW addr for vector A (output) interrupts
SETZM 2(T1) ; clear interrupt flags
XMOVEI T3,AN2ERR ; right now, any interrupt would be an error
MOVEM T3,3(T1) ; set interrupt routine addr
MOVEI T2,AN2VEC/4 ; offset for vector
ADD T2,SMTEPT+AN2UBN ; get addr of vector table
MOVEM T1,(T2) ; set vector
ADDI T1,4 ; XPCW addr for vector B (input) interrupts
SETZM 2(T1) ; flags for vector B
XMOVEI T3,AN2ERR ; any interrupts now are garbage
MOVEM T3,3(T1) ; interrupt routine for vector B
MOVEM T1,1(T2) ; set vector B
MOVEI T1,RING-1 ; init command ring buffer pointer
MOVEM T1,CMRNGB ; ..
RET
; Boot KMC11 and start microcode
BUTKMC::ACVAR<JFN,CKS> ; JFN of ucode file, checksum
MOVE CSR,[AN2ADR] ; address of AN22 Unibus registers
MOVX T1,GJ%SHT
HRROI T2,[ASCIZ /PS:<SYSTEM>AN22.MICROCODE/]
GTJFN
ERJMP [MOVE T1,LSTERR
BUG(AN2CFM,<<T1,LSTERR>>)
RET]
MOVX T2,OF%RD+<070000,,0>
OPENF
ERJMP [MOVE T1,LSTERR
BUG(AN2COM,<<T1,LSTERR>>)
RET]
MOVE JFN,T1
BUTKM1: MOVE T1,JFN
BIN ; get another byte
JUMPE T2,[GTSTS ; see if EOF
TXNN T2,GS%EOF ; is it?
JRST BUTKM1 ; no, ignore embedded nulls
JRST BUTKM2] ; yes, finish up
CAIN T2,";" ; comment line?
JRST [ CALL SKPLIN ; yes, skip rest of line
JRST BUTKM1] ; and go for more
CAIN T2,"C" ; CRAM line?
JRST BTCRAM ; yes, handle it
CAIN T2,"D" ; DRAM line?
JRST BTDRAM ; yes
BUTKMX: BUG(AN2ULM)
CALL SKPLIN ; ignore the line
JRST BUTKM1
BUTKM2: MOVE T1,JFN ; finish up
CLOSF
JFCL
RETSKP ; give good return
; Skip a line of microcode
SKPLIN: MOVE T1,JFN
BIN
JUMPE T2,[GTSTS ; see if EOF
TXNN T2,GS%EOF ; is it?
JRST SKPLIN ; no, ignore imbedded nulls
JRST BUTKM2] ; yes, finish up
CAIE T2,12 ; LF?
JRST SKPLIN ; no, keep looking
RET
; Get a word of data from ASCIIized microcode file
GETWD: SETZ T4, ; init sum
MOVE T1,JFN
GETWD1: BIN ; get a character
JUMPE T2,[GTSTS ; see if EOF
TXNN T2,GS%EOF ; is it?
JRST GETWD1 ; no, ignore nulls
JRST BUTKM2] ; yes, finish up
CAIE T2,"," ; comma?
CAIN T2,15 ; or carriage return?
JRST [ MOVE T1,T4 ; yes, return what we've got
RET]
LSH T4,6
CAIL T2,100 ; do funny conversion
SUBI T2,100
ADD T4,T2
JRST GETWD1
; Boot a line of CRAM
BTCRAM: MOVE T1,JFN ; next byte
BIN
CAIE T2," " ; should be space
JRST BUTKMX ; catch-all error handler
CALL GETWD ; get word count
JUMPE T1,BTXFER ; zero means this is transfer block
MOVE P1,T1 ; save
MOVE CKS,T1 ; start running checksum
CALL GETWD ; get load address
MOVE P2,T1 ; save
ADD CKS,T1 ; compute checksum
BTCRM1: CALL GETWD ; next data word
ADD CKS,T1 ; keep running checksum
MOVEI T2,4 ; select CRAM
WRIOB T2,BSEL1(CSR) ; ..
WRIO P2,SEL4(CSR) ; address into which to load it
WRIO T1,SEL6(CSR) ; plug instruction into KMC register
MOVEI T2,40 ; toggle CRAM write
BSIOB T2,BSEL1(CSR) ; ..
SETZ T2, ; clear SEL0
WRIO T2,SEL0(CSR) ; ..
WRIO T2,SEL4(CSR) ; and 4 and 6
WRIO T2,SEL6(CSR) ; ..
MOVEI T2,4 ; set RAM O
WRIOB T2,BSEL1(CSR) ; ..
WRIO P2,SEL4(CSR) ; set PC to read
RDIO T2,SEL6(CSR) ; read the word
CAME T1,T2 ; does it match what we thought we loaded?
BUG(AN2MCV,<<T1,DESIRD>,<T2,ACTUAL>>)
SETZ T1,
WRIO T1,SEL0(CSR) ; clear bits
ADDI P2,1 ; bump load address
SOJG P1,BTCRM1 ; do for all words in this frame
CALL GETWD ; get line checksum
ANDI CKS,177777 ; keep only 16 bits of running checksum
ADD CKS,T1 ; see if checksum OK
TRNE CKS,177777 ; ?
BUG(AN2CKS)
CALL SKPLIN ; skip end of this line
JRST BUTKM1 ; go do next line
; Boot line of KMC11 DRAM
BTDRAM: BUG(AN2DNS)
CALL SKPLIN
JRST BUTKM1
; Transfer block
BTXFER: CALL GETWD ; get start address
MOVE P1,T1 ; save it
CALL GETWD ; get checksum
MOVE CKS,P1 ; see if it checks
ADD CKS,T1 ; ..
TRNE CKS,177777
BUG(AN2CEX)
MOVEI T1,KMCCLR ; KMC11 master clear
WRIO T1,SEL0(CSR) ; clear it
HRRZ T1,P1 ; get start address
ANDI T1,1400 ; get high order two bits
LSH T1,3 ; position for strange KMC architecture
HRRZ T2,P1 ; get address again
ANDI T2,377 ; low-order 8 bits
IOR T1,T2 ; form address in split (KMC) format
IORI T1,100400 ; make an unconditional branch instruction
WRIO T1,SEL6(CSR) ; (See KMC11 Programmer's Manual for
MOVEI T2,2 ; an explanation of this esoteric
WRIOB T2,BSEL1(CSR) ; procedure - page 2-13)
MOVEI T2,3 ; execute the instruction
BSIOB T2,BSEL1(CSR) ; ..
MOVEI T2,7 ; clear leftover bits
BCIOB T2,BSEL1(CSR) ; ..
MOVEI T1,KMCRUN ; KMC11 run flop
WRIO T1,SEL0(CSR) ; start the little bugger
CALL SKPLIN ; eat the line feed
JRST BUTKM1
; Clock level check routine
IMPCHK::MOVEI T1,^D1000 ; call this every second
MOVEM T1,IMPTM2
SKIPN IMPRDY ; net on?
RET ; no, quit now
CALL IMPRLQ ; IMP is or was down?
SKIPL IMPRDT ; and not already noticed?
RET ; no, no need to do anything
CALL IMIERR ; yes, get it noticed
AOS IMPFLG ; cause NCP fork to run
RET
; Start input
IMISRT::CALL IMPRLQ ; IMP up?
RET ; no, do nothing
SOSL IMPNFI ; get next free input buffer
SKIPN T1,IMPFRI ; ..
BUG(IMPNII)
LOAD T2,NBQUE,(T1) ; get address of next buffer
MOVEM T2,IMPFRI ; point head of list at it
SETZRO NBQUE,(T1) ; unlink this buffer
MOVEM T1,IMIB ; remember this one
SETZM IMPIOV ; clear overflow flag
XMOVEI T1,AN2RC1 ; interrupt dispatch address
MOVEM T1,AN2XPC+7 ; set it up
MOVE CSR,[AN2ADR] ; address of AN22 registers
RDIOB T1,BSEL2(CSR) ; see if data already available
TXNE T1,AN2RDA ; any there?
CALL AN2STI ; yes, start input already
SKIPE INPON ; input interrupts already enabled?
RET ; yes, save time
MOVEI T1,C.SRIE ; set receive interrupt enable
SETOM INPON ; and return
CALL AN2CMD ; ..
RET
; These magic numbers are stored in IMITYP and IMOTYP to steer packing
; and unpacking decisions for input and output, respectively
.IINC6==0 ; 36-bit NCP message
.IINC2==1 ; 32-bit NCP message
.IITNT==2 ; Telenet link
.IISPQ==3 ; special queue
.IIINT==4 ; Internet
.IIMLC==5 ; MLC (PTIP) format
; Routines to call to pack a buffer read from AN22 into a net buffer
PACK: IFIW!PK3236 ; 36-bit NCP
IFIW!PK3232 ; 32-bit NCP
IFIW!PAKBUG ; Telenet not supported by DEC
IFIW!PKSPQ ; special queue
IFIW!PAKBUG ; Internet not supported by DEC
IFIW!PAKBUG ; PTIP not supported by DEC
; Routines to call to unpack a buffer from net buffer into AN22 output buffer
UNPACK: IFIW!UP3632 ; 36-bit NCP
IFIW!UP3232 ; 32-bit NCP
IFIW!PAKBUG ; Telenet not supported by DEC
IFIW!UP3232 ; special queue
IFIW!PAKBUG ; Internet not supported by DEC
IFIW!PAKBUG ; PTIP not supported by DEC
PAKBUG: BUG(AN2BPK)
RET
;Input ready
AN2RC1: DMOVEM T1,AN2AC1 ; save ACs
DMOVEM T3,AN2AC3
DMOVEM CX,AN2CX
MOVEM CSR,AN2CSR
MOVE CSR,[AN2ADR] ; address of AN22
MOVE P,[-AN2STN,,AN2STK]
RDIOB T1,BSEL2(CSR) ; get byte with useful bits in it
TXNN T1,AN2ILX ; illegal command interrupt?
TXNN T1,AN2RDA ; or receive data available not set?
CALL AN2BUG ; yes, BUGCHK
CALL AN2STI ; start input
JRST AN2RCX ; restore regs and dismiss
; Here to actually start input
AN2STI: SKIPN IMIB ; make sure input buffer is ready
BUG(AN2BNR)
RDIOB T1,BSEL2(CSR) ; get status bits
TXNN T1,AN2RDN ; insure no input in progress
CALL AN2BUG ; there is, gripe
MOVSI T1,-^D17 ; read I-H leader and H-H leader (136 bits)
HRR T1,INBUB ; Unibus address of buffer
MOVEM T1,IOWDI ; store the IOWD
MOVE T1,IOWDIU ; Unibus addr of IOWD
WRIO T1,SEL4(CSR) ; point AN22 at IOWD
XMOVEI T1,AN2RC2 ; next interrupt dispatch
MOVEM T1,AN2XPC+7 ; set it
MOVEI T1,C.RECV ; receive command code
CALLRET AN2CMD ; whomp it in there
AN2ERR: DMOVEM T1,AN2AC1 ; funny interrupt
DMOVEM T3,AN2AC3
DMOVEM CX,AN2CX
MOVEM CSR,AN2CSR
MOVE P,[-AN2STN,,AN2STK]
MOVE CSR,[AN2ADR]
CALL AN2BUG ; report error
JRST AN2RCX ; restore regs and dismiss
; Here on random AN22 bugs
AN2BUG: RDIOB T1,BSEL0(CSR) ; get bad command code
RDIO T2,SEL2(CSR) ; and interesting bits
MOVE T3,0(P) ; and return address
BUG(AN2BG1,<<T1,BSEL0>,<T2,SEL2>,<T3,CALLER>>)
RET
; Here when I-H leader and H-H leader (if present) have been read
AN2RC2: DMOVEM T1,AN2AC1 ; save standard ACs
DMOVEM T3,AN2AC3
DMOVEM CX,AN2CX
MOVEM CSR,AN2CSR
MOVE P,[-AN2STN,,AN2STK]
MOVE CSR,[AN2ADR]
RDIOB T1,BSEL2(CSR) ; get byte with interesting bits
TXNE T1,AN2ILX ; illegal command interrupt?
CALL AN2BUG ; yes, complain
TXNN T1,AN2RDN ; receive done?
JRST AN2RCX ; no, probably leftover data available int
; posted while we were in interrupt service
TXNE T1,AN2IWD ; was IMP down?
CALL IMIERR ; yes, note that
MOVEI T1,AN2IBF ; physical address of AN22 input buffer
LSH T1,-^D9 ; page number
CALL MONCLR ; invalidate cache for that page
MOVEI T2,AN2IBF ; get address of buffer back
ADDI T2,MXWPM ; compute ending address
LSH T2,-^D9 ; compute ending page
EXCH T1,T2 ; in case call to MONCLR needed
CAME T1,T2 ; buffer crosses page boundary?
CALL MONCLR ; yes, invalidate second page
MOVEI T1,AN2IBF ; pack from
MOVE T2,IMIB ; to
ADDI T2,.NBLD0 ; first word of leader
MOVEI T3,5 ; 17 8-bit bytes fits in 5 32-bit words
CALL PK3236 ; pack the data
MOVE T1,IMIB ; address of newly packed data
LOAD T2,IHHST,(T1) ; get host and link
LOAD T3,IHLNK,(T1) ; ..
CAIGE T2,FKHOST ; outside NCP range?
CAILE T3,LLINK ; ..
JRST [ DMOVE T2,.NBLD2(T1) ; yes, no H-H leader then
LSHC T2,^D20 ; so get first 32 bits of data
LSH T2,^D4 ; justify
DMOVEM T2,.NBHHL(T1) ; save it and the next 8 bits
JRST AN2R2A]
DMOVE T2,.NBLD2(T1) ; get H-H leader (crosses word boundary)
LSHC T2,-^D8 ; position to where IMPDV expects it
STOR T2,IHPD1,(T1) ; high-order 4 bits here (.NBLD2)
MOVEM T3,.NBHHL(T1) ; and low 36 bits here
AN2R2A: RDIOB T1,BSEL3(CSR) ; get byte with termination codes
LOAD T1,RCVTM,T1 ; get receive termination code
CAIN T1,TC.EOM ; end of message?
JRST AN2EOM ; yes, handle it
CAIE T1,TC.NEM ; receive OK without EOM?
CALL AN2BUG ; no, complain
XMOVEI T1,AN2RC3 ; next interrupt dispatch
MOVEM T1,AN2XPC+7 ; set it up
MOVNI T1,MXWPM ; negative max word count
LSH T1,2+^D18 ; Unibus byte count in left half
HRR T1,INBUB ; Unibus address of input buffer
MOVEM T1,IOWDI ; save IOWD
MOVE T1,IOWDIU ; Unibus addr of IOWD
WRIO T1,SEL4(CSR) ; point AN22 at IOWD
MOVEI T1,C.RECV ; receive command code
CALL AN2CMD ; hand the command to the AN22
JRST AN2RCX ; restore ACs and dismiss
;Here when user data has been completely read
AN2RC3: DMOVEM T1,AN2AC1 ;save ACs
DMOVEM T3,AN2AC3
DMOVEM CX,AN2CX
MOVEM CSR,AN2CSR
MOVE P,[-AN2STN,,AN2STK]
MOVE CSR,[AN2ADR] ;address of AN22 registers
RDIOB T1,BSEL2(CSR) ;get byte with illegal command bit
TXNN T1,AN2ILX ;illegal command?
TXNN T1,AN2RDN ; or receive done not set?
CALL AN2BUG ;yes to either, die
RDIOB T1,BSEL3(CSR) ;get byte with rcv termination code
LOAD T1,RCVTM,T1 ;get termination code
CAIN T1,TC.NEM ;not end of message?
JRST [ AOS IMPIOV ;yes, flag overflow
MOVNI T1,MXWPM ; ..
LSH T1,2+^D18 ;Unibus byte count
HRR T1,INBUB ;Unibus addr of input buffer
MOVEM T1,IOWDI ; save IOWD
MOVE T1,IOWDIU ; Unibus addr of IOWD
WRIO T1,SEL4(CSR) ; ..
MOVEI T1,C.RECV ;receive command code
CALL AN2CMD ;hand it off
JRST AN2RCX] ;dismiss the interrupt
; JRST AN2EOM
AN2EOM: CAIE T1,TC.EOM ; bad termination code?
CALL AN2BUG ; yes, note the error
MOVEI T2,AN2IWD ; was IMP down?
TIOEB T2,BSEL2(CSR) ; ??
CALL IMIERR ; yes, note that
AOSG IMPFLS ; flushing messages?
JRST [ AOS AN2BAD ; yes, count bad messages
JRST AN2RC5] ; discard it
SKIPE IMPIOV ; overflow happened?
JRST [ BUG(AN2OVF)
AOS AN2BAD ; count discarded msgs
JRST AN2RC5] ; gobble that goop
MOVE T1,IMIB ; get buffer address
LOAD T3,IHFTY,(T1) ; new format flag
CAIE T3,ITY%LL ; long leader?
JRST [ AOS AN2BAD ; no, count discards
JRST AN2RC5] ; flush it
LOAD T3,IHMTY,(T1) ; get message type
CAIE T3,.IHIGD ; one without a message-id (link)?
CAIN T3,.IHDHS ; ..
JRST AN2IRM ; yes, give leader to NCP (no user data)
CAIN T3,.IHNOP ; link also meaningless on NOPs
JRST AN2IRM ; ..
MOVEI T2,.IINC6 ; assume NCP 36-bit packing
MOVEM T2,IMITYP ; ..
; ..
; ..
LOAD T2,IHHST,(T1) ; see whether NCP irregular message
LOAD T4,IHLNK,(T1) ; get host and link
CAIGE T2,FKHOST ; from a fake host?
CAILE T4,LLINK ; or non-NCP link?
JRST [ MOVEI T2,.IISPQ ; special queue formatting then
MOVEM T2,IMITYP ; remember it
JRST .+2] ; and place onto NCPFRK queue
JUMPN T3,AN2IRM ; non-zero message type is irregular
MOVEI T1,AN2IBF ; address of AN22 input buffer
LSH T1,-^D9 ; page number
CALL MONCLR ; invalidate cache for that page
MOVEI T2,AN2IBF ; get address of buffer back
ADDI T2,MXWPM ; compute ending address
LSH T2,-^D9 ; compute ending page
EXCH T1,T2 ; in case call to MONCLR needed
CAME T1,T2 ; buffer crosses page boundary?
CALL MONCLR ; yes, invalidate second page
MOVE T1,IMIB ; current net buffer for input
LOAD T2,HHSIZ,(T1) ; get connection byte size
MOVE T3,IMITYP ; special queues?
CAIN T3,.IISPQ ; ..
JRST AN2RC7 ; yes, don't change packing decision now
MOVEI T3,.IINC2 ; 32-bit NCP packing?
CAIE T2,^D36 ; (non-36-bit-bytes get 32-bit packing)
MOVEM T3,IMITYP ; yes, remember that
AN2RC7: HRRZ T3,IOWDI ; Get carcass of IOWD
HRRZ T2,INBUB ; Unibus addr of input buffer
SUBI T3,-1(T2) ; Compute no. of 32-bit words read
MOVEI T2,.NBDW0(T1) ; where to put the data
MOVEI T1,AN2IBF ; where raw input lives
MOVE T4,IMITYP ; get buffer type
CALL @PACK(T4) ; call appropriate packing routine
MOVE T1,IMIB ; get address of NCP buffer
MOVE T3,IMPIBI ; add to NCP fork's queue
JUMPN T3,AN2RC4 ; anything on it already?
MOVEM T1,IMPIBO ; no, this is only entry then
SKIPA ; don't chain it
AN2RC4: HRLM T1,0(T3) ; add buffer to input queue
MOVEM T1,IMPIBI
MOVE T3,IMITYP ; special queue?
CAIE T3,.IISPQ ; ..
JRST AN2RC8 ; no, believe H-H leader then
HRRZ T2,IOWDI ; yes, no H-H leader, so figure count
HRRZ T3,INBUB ; from hardware word count
SUBI T2,(T3) ; minus one because we put data into .NBHHL
JRST AN2RC9 ; pass this count on to NCP
AN2RC8: LOAD T3,HHSIZ,(T1) ; get connection byte size
LOAD T2,HHCNT,(T1) ; and byte count for this msg
IMULI T2,(T3) ; compute bits received
MOVEI T4,^D36 ; assume 36 bits per word
CAIE T3,^D36 ; is it really?
MOVEI T4,^D32 ; no, must be 32 then
ADDI T2,-1(T4) ; round up
IDIV T2,T4 ; compute words in buffer
AN2RC9: ADDI T2,.NBDW0+1 ; add length of leaders and count word
STOR T2,NBBSZ,(T1) ; save for IMPDV
AOS IMPFLG ; nudge job zero
; JRST AN2RC6
AN2RC6: SETZM IMIB ; no current input buffer for NCP
SKIPLE IMPNFI ; any more buffers available?
JRST [ CALL IMISRT ; yes, start input
JRST AN2RCX] ; and dismiss
SETZM INPON ; remember that input is off
MOVEI T1,C.CRIE ; clear receive interrupt enable
CALL AN2CMD ; ..
XMOVEI T1,AN2RCY ; while disabled, just flush interrupts
MOVEM T1,AN2XPC+7 ; (this is necessary because one might be
; pending now)
AN2RCX: DMOVE T1,AN2AC1
DMOVE T3,AN2AC3
DMOVE CX,AN2CX
MOVE CSR,AN2CSR
AN2RCY: XJEN AN2XPC+4
; Here with irregular message
AN2IRM: CALL IMP8XQ ; hand to the NCP
AOS IMPFLG ; poke job zero
; fall through
; Here to release buffer
AN2RC5: MOVE T1,IMIB ; get current net buffer's address
MOVE T2,T1 ; copy to T2
EXCH T1,IMPFRI ; cause to be first free
HRLM T1,0(T2) ; chain onto old first free
AOS IMPNFI ; count one more free buffer
JRST AN2RC6 ; start input and dismiss
; Here from PI level, or NCPFRK, to start output going out
; Call:
; JSP T4,IMPXOU
IMPXOU::PIOFF
SKIPN IMPOB ; any output in progress?
JRST AN2XO1 ; no
PION ; yes, quit
JRST 0(T4)
AN2XO1: SETOM IMPOB ; flag output in progress
PION
PUSH P,T4 ; put return addr on stack
AN2IOU: CALL IMPRLQ ; IMP up?
JRST [ SETZM IMPOB ; no, clear output-in-progress
RET] ; and quit
SKIPLE NOPCNT ; any NOP's still pending?
JRST IOUNOP ; yes, send one
MOVE T1,IMPHBO ; high priority message waiting?
JUMPE T1,AN2IOL ; no, check for low priority
HLRZ T2,0(T1) ; yes, does it have a successor?
JUMPN T2,AN2IO1 ; yes
SETZM IMPHBI ; no, flag queue empty
SKIPA ; keep IMPHBO zero
AN2IO1: HRLI T2,ANBSEC ; section buffers are in
MOVEM T2,IMPHBO ; dequeue this one
JRST AN2IOC ; send it
AN2IOL: SKIPN T1,IMPOBO ; any messages waiting?
JRST [ SKIPE T2,HSTGDM ; any host-going-down msgs?
JRST IOUHGD ; yes, send it
XMOVEI T1,AN2DN2 ; reset interrupt dispatch
MOVEM T1,AN2XPC+3 ; ..
SETZM IMPOB ; flag no output in progress
RET] ; return
HLRZ T2,0(T1) ; get successor
JUMPN T2,AN2IO2 ; is there one?
SETZM IMPOBI ; no, empty the queue
SKIPA ; keep tail ptr zero
AN2IO2: HRLI T2,ANBSEC ; set section number
MOVEM T2,IMPOBO ; dequeue this buffer
; ..
; ..
AN2IOC: MOVEM T1,IMPOB ; remember this buffer
SETZRO NBQUE,(T1) ; remove from old chain
LOAD T2,IHHST,(T1) ; Check host and link for NCP range
LOAD T3,IHLNK,(T1) ; ..
CAIGE T2,FKHOST ; Special to-imp group?
CAILE T3,LLINK ; Or link out of range?
JRST [ MOVEI T3,.IISPQ ; Yes, special queue formatting.
JRST AN2IOD]
LOAD T2,HHSIZ,(T1) ; NCP will have set up packing mode
CAIE T2,^D36 ; Is it 36 bit mode?
SKIPA T3,[.IINC2] ; No, it is 8 or 32.
MOVEI T3,.IINC6 ; Select 36 bit mode
AN2IOD: MOVEM T3,IMOTYP ; remember packing decision
MOVEI T1,1(T1) ; first word of I-H leader
MOVEI T2,AN2OBF ; addr of AN22 output buffer
MOVEI T3,^D3 ; just move I-H leader (3 36-bit words)
CALL UP3632 ; shuffle those bits!
MOVE T1,IMPOB ; recover net buffer address
MOVEI T2,AN2OBF ; and output buffer address
MOVE T3,.NBHHL(T1) ; get H-H leader (36 bits of it)
LSH T3,-^D6 ; position for output buffer
HLLM T3,3(T2) ; do first two bytes
LSH T3,-2 ; make the 2-bit gap
HRRM T3,3(T2) ; next two bytes
SETZM 4(T2) ; last byte is always zero
XMOVEI T1,AN2LDR ; where to go on next output interrupt
MOVEM T1,AN2XPC+3 ; set up interrupt dispatch
MOVE CSR,[AN2ADR] ; AN22 Unibus address
MOVSI T1,-^D17 ; byte count
MOVE T2,IMOTYP ; special queue?
CAIN T2,.IISPQ ; ..
MOVSI T1,-^D12 ; yes, no H-H leader to send, then
HRR T1,OUTBUB ; Unibus address of output buffer
MOVEM T1,IOWDO ; save it
MOVE T1,IOWDOU ; Unibus addr of same
WRIO T1,SEL6(CSR) ; hand off to AN22
MOVE T2,IMPOB ; addr of net buffer
LOAD T2,NBBSZ,(T2) ; get size of this message
MOVEI T1,C.XPAR ; transmit partial message
CAIG T2,.NBHHL ; unless this is a short one
MOVEI T1,C.XEOM ; in which case turn on EOM bit at end
CALL AN2CMD ; nudge the AN22 and return
RET ; (don't change to CALLRET)
; Here when both leaders have been sent
AN2LDR: DMOVEM T1,AN2AC1 ; save ACs
DMOVEM T3,AN2AC3
DMOVEM CX,AN2CX
MOVEM CSR,AN2CSR
MOVE CSR,[AN2ADR]
MOVE P,[-AN2STN,,AN2STK]
RDIOB T1,BSEL2(CSR) ; fetch useful bits
TXNN T1,AN2ILX ; illegal command?
TXNN T1,AN2XDN ; or transmit done not set?
CALL AN2BUG ; yes, go die
RDIOB T2,BSEL3(CSR) ; get byte with termination code
LOAD T2,XMTTM,T2 ; get termination code
CAIN T2,TC.EOM ; end of message (short message)?
JRST AN2DN1 ; yes, go finish up
CAIE T2,TC.NEM ; termination code OK?
CALL AN2BUG ; no, complain
MOVE T1,IMPOB ; addr of this net buffer
MOVEI T2,AN2OBF ; -10 addr of AN22 output buffer
LOAD T3,NBBSZ,(T1) ; get size of buffer
SUBI T3,.NBHHL ; account for leader already sent
XMOVEI T1,.NBDW0(T1) ; first word of user data
MOVE T4,IMOTYP ; get packing type index
CAIN T4,.IISPQ ; special queues?
JRST [ SUBI T1,<.NBDW0-.NBHHL> ; yes, data starts one word earlier
ADDI T3,<.NBDW0-.NBHHL> ; hence have one more to send
JRST .+1]
CALL @UNPACK(T4) ; shuffle those bits!
MOVE T1,IMPOB ; addr of net buffer
LOAD T2,NBBSZ,(T1) ; get word count
MOVE T4,IMOTYP ; special queue?
CAIN T4,.IISPQ ; ..
JRST AN2LD0 ; yes, no adjustments necessary
LOAD T3,HHSIZ,(T1) ; get byte size
CAIN T3,^D36 ; 36-bit mode?
JRST [ IMULI T2,^D36 ; yes, must adjust word count
IDIVI T2,^D32 ; because of 32-bit packing
JRST AN2LD0] ; ..
AN2LD0: LSH T2,2 ; make byte count
MOVN T2,T2 ; negate
ADDI T2,^D12 ; account for I/H leader already sent
CAIE T4,.IISPQ ; special queue? if so, no H-H leader
ADDI T2,^D5 ; no, account for H-H leader already sent
LSH T2,^D18 ; move to left half
HRR T2,OUTBUB ; Unibus addr of AN22 buffer
MOVEM T2,IOWDO ; save it
MOVE T2,IOWDOU ; Unibus addr of same
WRIO T2,SEL6(CSR) ; tell AN22 where to find IOWD
XMOVEI T1,AN2DN0 ; where to go when done with this output
MOVEM T1,AN2XPC+3 ; set up interrupt dispatch
MOVEI T1,C.XEOM ; transmit end of message
CALL AN2CMD ; ..
DMOVE T1,AN2AC1 ; restore ACs
DMOVE T3,AN2AC3
DMOVE CX,AN2CX
MOVE CSR,AN2CSR
XJEN AN2XPC ; dismiss interrupt
; Make a Host Going Down message
IOUHGD: MOVE T1,H2IHGD ; get template for msg
SETZ T3, ; build msg in T1-T3
LSHC T2,-^D32
LSH T2,2 ; waste bits, UBA-style
LSHC T2,^D16
LSH T3,-2 ; and again
JRST IOUIRG ; common irregular msg sender
; Here to send NOP to IMP
IOUNOP: SOS NOPCNT ; count NOPs
DMOVE T1,H2INOP ; get template NOP
MOVE T3,H2INOP+2 ; fall through
; Send irregular message, message in T1-T3 in AN22 format
IOUIRG: MOVEI T4,AN2OBF ; -10 addr of AN22 output buffer
DMOVEM T1,0(T4) ; build message
MOVEM T3,2(T4) ; ..
MOVE CSR,[AN2ADR] ; AN22 address
MOVSI T1,-^D12 ; 12 bytes in an irregular msg
HRR T1,OUTBUB ; Unibus addr of AN22 output buffer
MOVEM T1,IOWDO ; stuff it
MOVE T1,IOWDOU ; Unibus addr of IOWD
WRIO T1,SEL6(CSR) ; inform AN22 of this
XMOVEI T1,AN2DN2 ; output interrupt dispatch
MOVEM T1,AN2XPC+3 ; set it up
MOVEI T1,C.XEOM ; transmit end of message
CALL AN2CMD ; ..
RET ; and return (DON'T change to CALLRET)
;Templates of the only two Host-to-IMP irregular messages we ever send
H2INOP: ; the 2-bit fields are UBA-ignored bits
BYTE (2)0(4)0,ITY%LL (8)0(2)0(8)0(8).IHNOP
EXP 0
EXP 0 ; padding control is here, happens to be zero
H2IHGD: ; the 2-bit fields are UBA-ignored bits
BYTE (2)0(4)0,ITY%LL (8)0(2)0(8)0(8).IHHGD
; Here on output done interrupt for a real buffer (regular message)
AN2DN0: DMOVEM T1,AN2AC1 ; save interrupt ACs
DMOVEM T3,AN2AC3
DMOVEM CX,AN2CX
MOVEM CSR,AN2CSR
MOVE CSR,[AN2ADR]
MOVE P,[-AN2STN,,AN2STK]
RDIOB T1,BSEL2(CSR) ; get byte with "illegal command" bit
TXNN T1,AN2ILX ; was it one?
TXNN T1,AN2XDN ; or transmit done not set?
CALL AN2BUG ; yes, BUGCHK
RDIOB T2,BSEL3(CSR) ; get byte with termination code
LOAD T2,XMTTM,T2 ; get termination code
CAIE T2,TC.EOM ; OK?
CALL AN2BUG ; no, complain
TXNE T1,AN2IWD ; ready line error?
CALL IMIERR ; yes, note that
AN2DN1: CALL IMODUN ; post completion and free buffer
MOVE T1,IMPOB
CALL IMULKB ; unlock buffer
AN2UBO: SETZM IMPOB ; note no output in progress
CALL AN2IOU ; start output if any ready to go
DMOVE T1,AN2AC1 ; restore ACs
DMOVE T3,AN2AC3
DMOVE CX,AN2CX
MOVE CSR,AN2CSR
XJEN AN2XPC ; and dismiss
; Here on output done interrupt for irregular message (so no net buffer
; to be released)
AN2DN2: DMOVEM T1,AN2AC1
DMOVEM T3,AN2AC3
DMOVEM CX,AN2CX
MOVEM CSR,AN2CSR
MOVE P,[-AN2STN,,AN2STK]
MOVE CSR,[AN2ADR]
RDIOB T1,BSEL2(CSR) ; illegal command interrupt?
TXNN T1,AN2ILX ; ..
TXNN T1,AN2XDN ; or transmit done not set?
CALL AN2BUG ; yes, BUGCHK
TXNE T1,AN2IWD ; ready line error?
CALL IMIERR ; yes, complain
RDIOB T1,BSEL3(CSR) ; get byte with termination code
LOAD T1,XMTTM,T1 ; get termination code
CAIE T1,TC.EOM ; end of message?
CALL AN2BUG ; no, gripe
JRST AN2UBO ; go start output if possible and dismiss
;Pack data stored UBA-style into 36-bit words
; Note that the AN22 reverses the bytes before storing into -10
; memory, to save the -10 the byte-swapping time
;Call:
; T1/ source
; T2/ dest
; T3/ word count (32-bit words)
PK3236: SAVEP
DMOVE P1,T1 ; copy args
MOVE P3,T3
PK26B: MOVE T2,(P1) ; get 32 bits
AND T2,[-1,,177777] ; clear 2 high order bits which we expect
ADDI T2,(T2) ; cleared anyway
ADDI T2,(T2)
LSH T2,2 ; concatenate and left justify
MOVEM T2,(P2) ; store 32 bits
SOJLE P3,R ; count words fetched, quit if exhausted
MOVSI T4,-^D8 ; offset counter
PK26A: ADDI P1,1 ; next source word
MOVE T2,(P1) ; next 32 bits
AND T2,[-1,,177777] ; clear 2 high order bits which we expect
ADDI T2,(T2) ; cleared anyway
ADDI T2,(T2)
LSH T2,2 ; dump unused bits
SETZ T1, ; clear unused bits
LSHC T1,@SHIFT(T4) ; 4,8,12,16,20,24,28,32 bits
IORM T1,(P2) ; fill out righthand end of dest word
ADDI P2,1 ; next dest word
LSHC T1,^D36 ; left-justify remainder
MOVEM T1,(P2) ; save leftmost bits of next word
SOJLE P3,R ; if done, quit
AOBJN T4,PK26A ; do it 8 times
ADDI P1,1 ; next source word
JRST PK26B ; loop
SHIFT: EXP ^D4
EXP ^D8
EXP ^D12
EXP ^D16
EXP ^D20
EXP ^D24
EXP ^D28
EXP ^D32 ; amount to shift remainder of word
;Pack data stored UBA style into 32-bit words
; (i.e., concatenate and left-justify it)
;Call:
; T1/ source
; T2/ dest
; T3/ word count (32-bit words)
PK3232: MOVE T4,(T1) ;get source word
AND T4,[-1,,177777] ; clear 2 high order bits which we expect
ADDI T4,(T4) ; cleared anyway
ADDI T4,(T4) ;concatenate and left justify
LSH T4,2
MOVEM T4,(T2) ;store
ADDI T1,1 ;next source word
ADDI T2,1 ;next dest word
SOJG T3,PK3232
RET
;Pack input for special queues. First word (.NBDW0) already has
; one byte of data in it.
;
; Call:
; T1/ source
; T2/ dest
; T3/ word count (32-bit words)
PKSPQ: PUSH P,P1 ; need this
LSH T3,2 ; compute 8-bit-byte count
HRLI T2,(POINT 8,,7) ; net buffer already has one byte in it
MOVSI P1,-4 ; state counter
PKSPQ0: LDB T4,UBYTE(P1) ; get ptr to this byte in Unibus data
IDPB T4,T2 ; pick 'em up and put 'em down
SOJLE T3,PKSPQR ; count bytes
AOBJN P1,PKSPQ0 ; step state counter
MOVSI P1,-4 ; reset state counter
ADDI T1,1 ; and step to next word in Unibus buffer
JRST PKSPQ0 ; and keep going
PKSPQR: POP P,P1 ; return
RET
;Table of pointers to bytes in Unibus format (T1 points at word)
UBYTE: POINT 8,(T1),9
POINT 8,(T1),17
POINT 8,(T1),27
POINT 8,(T1),35
;Unpack 36-bit words into UBA-style format
; Note that the AN22 reverses the bytes for us, to save
; the -10 from having to swap bytes (a KS is slow enough already!)
;Call:
; T1/ source addr
; T2/ dest addr
; T3/ word count (36-bit words)
;Returns: +1 always
UP3632: SAVEP
DMOVE P1,T1 ; copy args
MOVE P3,T3
MOVE T2,(P1) ; get word of source
ADDI P1,1 ; next source
SETZ T1,
LSHC T1,^D16 ; form one -11 word
LSH T1,2 ; waste a couple of bits
LSHC T1,^D16 ; form next -11 word
MOVEM T1,(P2) ; stuff into UBA buffer
ADDI P2,1 ; next dest
; T2 now has 4 bits left in it, left-justified.
UP62A: MOVSI T3,-4 ; loop counter
UP62B: SETZ T1,
LSHC T1,@[EXP ^D4 ; get bits left in T2
EXP ^D8
EXP ^D12
EXP ^D16](T3)
MOVE T2,(P1) ; get more source
ADDI P1,1 ; next source addr
SKIPG P3 ; if source exhausted,
SETZ T2, ; then supply filler
LSHC T1,@[EXP ^D12 ; get bits needed to fill out a whole -11 word
EXP ^D8
EXP ^D4
EXP ^D0](T3)
LSH T1,2 ; make a gap
LSHC T1,^D16 ; another whole -11 word
MOVEM T1,(P2) ; stuff it
ADDI P2,1 ; next dest
SOJLE P3,R ; if source gone, we're done
AOBJN T3,UP62B ; do for all flavors of -11-word fragments
; at this point T2 has 20 bits left in it, left-justified
LSHC T1,^D16 ; get another PDP-11 word
LSH T1,2 ; make a gap
; T2 now has 4 bits left. T1 has 16 bits and a gap.
MOVSI T3,-4 ; loop and offset counter
UP62C: LSHC T1,@[EXP ^D4 ; get remaining bits
EXP ^D8
EXP ^D12
EXP ^D16](T3)
MOVE T2,(P1) ; get 36 more bits
ADDI P1,1 ; bump pointer to source
SKIPG P3 ; if source exhausted,
SETZ T2, ; fill with zeroes
LSHC T1,@[EXP ^D12 ; get bits to make another -11 word
EXP ^D8
EXP ^D4
EXP ^D0](T3)
MOVEM T1,(P2) ; store it
ADDI P2,1 ; next dest word
SOJLE P3,R ; if source exhausted, quit
LSHC T1,^D16 ; get next -11 word
LSH T1,2 ; make another gap
AOBJN T3,UP62C ; go round again
; T1 now has 16 bits and a gap. T2 has 20 bits.
LSHC T1,^D16 ; next -11 word
MOVEM T1,(P2) ; stuff it
ADDI P2,1 ; bump dst addr
JRST UP62A ; now T2 has 4 bits left -- reenter first loop
;Unpack 32-bit words left-justified into UBA-style buffer
;Call:
; T1/ source addr
; T2/ dest addr
; T3/ word count
;Returns: +1 always
UP3232: ACVAR<SRC> ; source pointer
MOVE SRC,T1
MOVE T4,T2 ; need T2 for scratch
UP22A: MOVE T2,(SRC) ; get some
SETZ T1, ; insure unused bits stay zero
LSHC T1,^D16 ; form one -11 word
LSH T1,2 ; and a gap
LSHC T1,^D16 ; next -11 word
MOVEM T1,(T4) ; stuff it
ADDI SRC,1 ; next source word
ADDI T4,1 ; next destination word
SOJG T3,UP22A ; loop
RET
;Here to give command to AN22. Call with command code in T1.
; Saves history of commands in ring buffer pointed to by CMRNGB.
AN2CMD: SKIPN DBUGSW ; debugging?
JRST AN2CM1 ; no, skip this expensive stuff
PIOFF ; interrupt routines use this, too
AOS T2,CMRNGB ; advance round command ring buffer
CAILE T2,CMRNGE-1 ; gone past end?
SUBI T2,CMRNGN ; yes, wrap around
HRLZ T3,T1 ; put command in left half
HRR T3,(P) ; and caller's address in right half
MOVEM T3,(T2) ; save it
MOVEM T2,CMRNGB ; and current pointer
PION
AN2CM1: MOVE T4,T1 ; preserve command code
JSP CX,AN2WAT ; wait for AN22 ready
WRIOB T4,BSEL0(CSR) ; give the command
PION ; interrupts back on
RET ; and return
; Wait for AN22 to be ready to accept a command
; Call: CSR/ address of AN22
; JSP CX,AN2WAT
; Return: +1 always, with PI's off
AN2WAT: MOVEI T3,^D5000 ; how patient to be
MOVEI T1,200 ; magic bit (see AN22 functional spec)
AN2WT1: PIOFF ; prevent confusion
TIONB T1,BSEL0(CSR) ; ready yet?
JRST 0(CX) ; yes, return
PION ; no, don't tie up machine
AOS AN2NRD ; count occurrences of this
SOJG T3,AN2WT1 ; keep trying for a while
RDIOB T1,BSEL0(CSR) ; get offending command code
BUG(AN2HNG,<<T1,BSEL0>>)
SETZM NETON ; shut down ARPANET
JRST 0(CX) ; and return
; Status check
IMPRLQ::SAVET
MOVE T1,[AN2ADR]
CALL UBGOOD ; AN22 exist?
RET ; no, return bad
MOVE CSR,[AN2ADR]
RDIOB T1,BSEL2(CSR) ; get byte with IMP READY bit
TXNN T1,AN2IRD ; is IMP ready?
RET ; no, fail
RETSKP ; yes, ok
; Here from NCPFRK to shut down our side of IMP/Host interface
IDVKIL::SAVET
MOVE CSR,[AN2ADR]
MOVEI T1,C.RSET ; reset command code
CALL AN2CMD ; (don't change to CALLRET, please)
RET
; Called here from IMPIN0 on initialization of NCPFRK
IMPRSD::XMOVEI T1,AN2ERR ; reset interrupt dispatches
MOVEM T1,AN2XPC+7 ; input interrupts will cause BUGCHK
XMOVEI T1,AN2DN2 ; output interrupts will attempt more output
MOVEM T1,AN2XPC+3 ; ..
RET
; Called here from NCPFRK whenever net is down and wanted up
IMPRSS::CALL BUTKMC ; boot the AN22
RET ; something fell over
RDIOB T1,BSEL1(CSR) ; get ucode version number
MOVE T2,UCDVER ; see if it's what we expect
CAME T1,T2 ; is it?
BUG(AN2UCV,<<T1,ACTUAL>,<T2,DESIRD>>)
CALL IMPRLQ ; IMP there?
RET ; no, do nothing
CALL IMPRSN ; reset variables
SETZM IMPRDL ; clear count of IMP ready line flaps
MOVE CSR,[AN2ADR] ; address of AN22
MOVEI T1,C.RSET ; reset it
CALL AN2CMD ; ..
MOVEI T1,C.SHRD ; set host ready
CALL AN2CMD ; ..
MOVEI T1,C.SXIE ; set xmit interrupt enable
CALL AN2CMD ; once now and forever
SETZM INPON ; flag input off
SETZM IMPDRQ ; forget any take-down requests
MOVNI T1,2 ; flush first 2 messages IMP sends
MOVEM T1,IMPFLS ; (they're NOPs, or should be)
MOVEI T1,3 ; send three NOPs
MOVEM T1,NOPCNT
MOVEI T1,^D500 ; allow time for ready line to settle
DISMS
AOS NETTCH ; note network change of state
AOS JB0FLG ; poke job zero
GTAD ; get current time and date
MOVEM T1,NCPUPT ; remember time net came up
SKIPLE IMPNFI ; if input buffers available,
CALL IMISRT ; then start input
SETOM IMPRDY ; note IMP ready
SETOM IMPORD ; allow output
MOVE T1,NLHOST ; send ourself an RRP
CALL IMPRRP ; ..
RET
; Here whenever IMP ready line flaps
IMIERR: SAVET
SETOM IMPRDL ; Be sure NCP notices this
MOVNI T1,2 ; flush NOPs from IMP
MOVEM T1,IMPFLS ; ..
MOVNM T1,NOPCNT ; and send some ourself
MOVE CSR,[AN2ADR] ; addr of AN22
RDIO T1,SEL2(CSR) ; get interesting bits
BUG(AN2IER,<<T1,SEL2>>)
MOVEI T1,C.CIWD ; clear ready line error
CALL AN2CMD ; (don't change to CALLRET, please)
RET
END