Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
mit/monitor/1822dv.mac
There are no other files named 1822dv.mac in the archive.
;<5.ISI.MONITOR>1822DV.MAC.5700, 10-Feb-83 16:49:27, Edit by CHASE
;#570 In IMPHDR, set up T4 before using it.
;<5.ISI.MONITOR>1822DV.MAC.5350 6-Jan-83 17:30:54 Edit by JGOLDBERGER
;#535 Clear NBQUE in packets returned by RFNOUT, in case...
; Restart input after calling INTFBF in IMPEI3
;<5.ISI.MONITOR>1822DV.MAC.5220, 21-Dec-82 13:32:22, Edit by BILKIS
;#522 Fix test at RFNOU2+1 to be JUMPG not JUMPL to make RFNTOTs go away
;<5.ISI.MONITOR>1822DV.MAC.5010 19-Nov-82 13:35:31 Edit by JGOLDBERGER
;#501 Version 5 MultiNet without MLC code
;<134>1822DV.MAC;5 10-DEC-82 15:59:13 EDIT BY TAFT
; Fix trouble at IMPEI3 which resulted in NTIB never being zeroed and input
; never being restarted.
;<134>1822DV.MAC;4 7-DEC-82 10:34:11 EDIT BY TAFT
; Remove search of MONSYM
; Remove defs of NCPF and MLCF
; Change MLCF to MLCN
; Fix unterminated conditional at IMPEI3
;[BBNF]<TAPPAN.NEW>1822DV.MAC.48, 2-Sep-82 11:18:50, Edit by: TAPPAN
; Send NOP's if the IMP starts sending us short leader messages
;[BBNF]<TAPPAN.NEW>1822DV.MAC.44, 23-Jul-82 08:48:41, Edit by: TAPPAN
; Add RFN8TO table maintainance, to protect against pathological case
; where RFNM's get lost and buffers gets locked on the output queues
;<TAPPAN.NEW>1822DV.MAC.29, 12-Jun-82 16:21:16, Edit by TAPPAN
; Added RFNM counting code (based on ISI's)
; Added NCPUNQ -- routine for deciding which buffer from
; which queue should go next
;
SEARCH PROLOG,MNTPAR,IMPPAR
ND MLCN,0
ND INETN,1
ND NCPF,0
ND ISIQ,0
IFG INETN,<SEARCH INPAR>
TTITLE 1822DV
ASCIZ /
1822DV
COPYRIGHT (C) 1982,1983 BOLT BERANEK and NEWMAN INC.
/
;;;
;;; Multinet interface routines common to 1822 networks
;;; These are the "Protocal" dependent routines (i.e. those
;;; that are hardware independent), Hardware dependent routines
;;; are in the driver module (IMPPHY, ANXPHY etc.).
;;;
;;; All routines expect an NCT pointer in P1
;;;
DEFSTR ADR23,0,35,23 ; 23 bit address
RESCD
;;;
;;; Protocal dispatch vector
;;;
NCPVEC::
NCTVEC(NCPVEC,NCPKIL,NTPKIL) ; Protocal specific interface kill
NCTVEC(NCPVEC,NCPERR,NTPERR) ; protocal specific error handler
NCTVEC(NCPVEC,IMPEIN,NTIDUN) ; Input done
NCTVEC(NCPVEC,IMODUN,NTODUN) ; Output done
NCTVEC(NCPVEC,NCPRBF,NTRBUF) ; Flush buffer chain
NCTVEC(NCPVEC,NCPOTT,NTOTOK) ; Output allowed check
NCTVEC(NCPVEC,IMPHDR,NTLLDR) ; Create local leader
NCTVEC(NCPVEC,NCPINI,NTPINI) ; Network up function
SWAPCD
;;;
;;; NCPINI -- Network up function
;;;
NCPINI: MOVEI T1,.NBHHL ; Local leader size
MOVEM T1,NTHDRL(P1) ; set it
RET ; and done
;;;
;;; NCPERR -- Protocal dependent function when an interface
;;; error occurs
;;;
NCPERR:
IFN NCPF,<
MOVEI T3,NHOSTS ; Size of host hash table
PUTSEC T4,MNTSEC ; right section
NCPER0: PUSH P,T3 ; Save
PUSH P,T4 ; ..
SKIPN T1,HSTHSH(T4) ; Slot empty?
JRST NCPER1 ; Yes
CALL NETCMP ; Same net?
JRST NCPER1 ; no
CALL CHKNWP ; "New NCP" host?
TRNA ; no
JRST NCPER1 ; Yes, can recover
SKIPGE HSTSTS(T4) ; Is it up?
CALL HSTDED ; Not any more
NCPER1: POP P,T4 ; Restore
POP P,T3 ; ...
AOS T4 ; increment
SOJG T3,NCPER0 ; Loop
>
RET
;;;
;;; NCPKIL -- Protocal dependent functions in taking down an interface
;;; returns +2 when function is complete
;;;
NCPKIL: MOVE T1,NTRDY(P1) ; Get status word
TRZN T1,1B18 ; First time through?
JRST NCPKL5 ; No
MOVEM T1,NTRDY(P1) ; Save modified flag
IFN NCPF,<
PUTSEC T1,MNTSEC
MOVEM T1,IMPCCH(P1) ; Send RST's to everyone
SETZM IMPTIM ; Now
CALL NETDWN ; Kill all connections
CALL NVTDWN ; And all NVT's
>
;;; Create a "Host going down" message
;;; Assumes "Unknown reason"
;;; HSYST4 contains time back up
REPEAT 0,<
CALL LGTAD ; Get time
CAMLE T1,HSYST4 ; IS TIME BACK UP LATER THAN NOW?
JRST [ MOVEI T1,177776 ; NO
JRST NCPKL3] ; TIME BACK UP NOT KNOWN
ADD T1,[6,,0]
CAMG T1,HSYST4 ; MORE THAN 6 DAYS AWAY?
JRST [ MOVEI T1,177777 ; YES
JRST NCPKL3]
MOVX T4,<IC%DSA!IC%UTZ> ; USE GMT STANDARD TIME
ODCNV ; SEPARATE INTO DAY, SECOND ETC
HRRZ T1,T3 ; DAY OF WEEK
HRRZ T2,T4 ; SECONDS SINCE MIDNIGHT
IDIVI T2,^D300 ; CONVERT SECONDS TO 5 MIN
IDIVI T2,^D12 ; SEPARATE INTO HOUR AND 5 MIN
LSH T1,5
IORI T1,(T2) ; INSERT HOUR OF DAY
LSH T1,4
IORI T1,(T3) ; AND 5 MIN PART OF HOUR
NCPKL3:
LSH T1,4 ; Room for REASON
; (Assume "reason unknown")
>
MOVX T1,177776B31 ; Assume "unknown reason", "unknown time up".
MOVEM T1,HSTGDM(P1) ; Save message
MOVEI T1,^D10000 ; When to give up
ADD T1,TODCLK ; ..
MOVEM T1,NTDCLK(P1) ; Save timer
NCPKL5: MOVE T1,NTDCLK(P1) ; Get timeout value
CAMLE T1,TODCLK ; Timeout happened?
SKIPG HSTGDM(P1) ; Wait for "Going down" message to go out
RETSKP ; Skip return when done
RET ; Not done yet
;;;
;;; NCPRBF -- Release a buffer (chain). Called when
;;; flushing the NCT's queues.
;;; T2 -- Buffer list
;;; (Buffers are NOT internet buffers)
;;;
NCPRBF:
NCPRB0:
TRNN T2,-1 ; Anything there?
RET ; No
IFE NCPF,<
MNTBUG(HLT,RBNNCP,<Releasing buffer but no NCP>)
>
IFN NCPF,<
MOVE T1,T2 ; get this buffer
LOAD T2,NBQUE,(T1) ; Get next in list
SETSEC T2,ANBSEC ; Point in the right section
PUSH P,T2 ; Save next
CALL NCPRB6 ; Clear RFNM count if appropriate
POP P,T2 ; ...
JRST NCPRB0 ; loop through the chain
;;; NCPRB6 - Clear RFNM count, re-xmit flag and buffer, then unlock.
;;; Buffer in T1
NCPRB6:
PUSH P,T2 ; Save some registers
PUSH P,T3
PUSH P,T1
CALL IMPGHL ; Get a LNKLUK arg
JRST NCPRB7 ; Non-NCP buffer
CALL LNKLUK ; Look up the connection
JRST NCPRB7 ; Not found. May be deleted.
PIOFF ; Grab machine for a moment
MOVX T2,RFNMCM!RXMTF ; Clear IMPLT knowledge of this buffer
ANDCAM T2,IMPLT2(T1) ; Both status bits,
HLLZS IMPLT3(T1) ; and address of buffer
PION ; done
NCPRB7: MOVE T2,0(P) ; Get address back
CALL IMPRBF ; Release the buffer
POP P,T1
POP P,T3 ; Restore the AC's
POP P,T2
RET
>
RESCD
;;;
;;; IMPEIN -- "End of input" processing for a buffer
;;; Here from device driver after device specific
;;; operations done, when a packet has been recieved.
;;; called with P1 pointing to NCT for device
;;;
IMPEIN::SKIPG T1,NTIB(P1) ; Bfr address
JRST IMPEI2 ; Wasn't one
MNTCALL NTSCHK ; Check status
JRST IMPEI3 ; error occured, drop it
AOSG NTFLS(P1) ; Flushing msgs?
JRST IMPEI3 ; Yes, return to free list
HRRZ T2,NTINP(P1) ; How much was read?
CAIGE T2,.NBLD2(T1) ; A full leader?
JRST IMPEI3 ; No, Discard it as useless
MOVE T2,NTNET(P1) ; get network number from NCT
STOR T2,IHNET,(T1) ; Stick it into buffer header
LOAD T3,IHFTY,(T1) ; Is this a long leader msg?
CAIE T3,ITY%LL ; ..
JRST IMPE3A ; No. Just throw it away. (But correct IMP)
LOAD T3,IHMTY,(T1) ; Get message type.
CAIGE T3,NRFNXS ; Possible RFNM counting ?
XCT RFNXCT(T3) ; Yes, act according to type.
CALL INTBCK ; Internet buffer?
JRST IMPE01 ; No
CAIE T3,.IHREG ; Regular?
CAIN T3,.IHUNC ; Uncontrolled?
CAIA ; One of the above
JRST IMPEI3 ; Not valid data
LOAD T3,NBBSZ,(T1) ; Get size of buffer
CAMLE T3,MAXWPM ; Check size field
MNTBUG(HLT,IMPIWW,<IMPEIN: Internet bfr word size wrong>)
IFN MAXLDR-.NBHHL,<
MOVE T2,T1
MOVNI T3,.NBHHL ; Ammount to correct leader by
CALL FIXLDR
>
MOVE T3,INTIBI ; Queue for Internet gateway
JUMPN T3,IMPE00
MOVEM T1,INTIBO
SKIPA
IMPE00: STOR T1,NBQUE,(T3)
MOVEM T1,INTIBI
AOS INTFLG ; Cause Internet process to notice it
JRST IMPE11 ; Avoid running NCP -- Internet buf used
IMPE01:
IFN NCPF,<
CAIE T3,.IHIGD ; One of the ones that has no msg ID?
CAIN T3,.IHDHS ; ..
JRST IMPEI4 ; Yes. Give it to NCP
CAIN T3,.IHNOP ; You also can't believe link on NOPs
JRST IMPEI4 ; Give them to NCP anyhow
LOAD T2,IHHST,(T1) ; See whether it's an NCP irreg msg
LOAD T4,IHLNK,(T1) ; Get host and link
CAIGE T2,FKHOST ; From IMP fake hosts?
CAILE T4,LLINK ; Or non-NCP Link?
TRNA ; Yes, not for NCP
JUMPN T3,IMPEI4 ; Give irreg msg to NCP
CAIN T4,INTLNK ; Internet?
JRST IMPEI3 ; Yes, just drop it on the floor
>
IFN MLCN,<
LSH T4,-1 ; Link field for MLC traffic?
CAMN T4,MLCHLF ; Is it the MLC link field?
JRST IMPEIP ; Yes do MLC queue
>
IFN NCPF,<
MOVE T3,IMPIBI ; Add to NCP fork's queue
JUMPN T3,IMPEIA ; Anything on it already?
MOVEM T1,IMPIBO ; No. This is it, then.
SKIPA ; Don't chain it
IMPEIA: STOR T1,NBQUE,(T3) ; Add buffer to input queue for NCPFRK
MOVEM T1,IMPIBI ; This is the last guy on queue
AOS IMPFLG ; Request job 0 service
IMPEI1: LOAD T3,NBBSZ,(T1) ; Make sure not a released buffer
CAMLE T3,MAXWPM ; by checking size field for a PC
JSP CX,IMPAFB ; Bughlt if so
>
IMPE11: LOAD T3,ADR23,+NTINP(P1) ; Get last loc with data +1
SUB T3,NTIB(P1) ; Less base of the buffer
STOR T3,NBBSZ,(T1) ; RECORD ACTUAL COUNT IN BUFFER HEADER
IMPEI2: SETZM NTIB(P1)
MNTCALL NTISRT ; Start new input
RET ; And done
IFN MLCN,<
IMPEIP: MOVE T3,MLCIBI ;ANYTHING ON PTIP INPUT QUEUE YET?
JUMPN T3,IMPEP2 ;JUMP IF SO
MOVEM T1,MLCIBO ;NO, SO THIS IS THE FIRST ONE OUT
SKIPA ;DON'T TRY TO LINK IT
IMPEP2: STOR T1,NBQUE,(T3) ;LINK TO PREVIOUS LAST-IN
MOVEM T1,MLCIBI ;THIS IS NEW LAST-IN
MOVE T3,IMPNIB ; GET INPUT BUFFER THRESHOLD
LSH T3,-1 ; HALVE
CAML T3,IMPNFI ; DO WE HAVE MORE THAN THAT ON TAP?
AOS IMPFLG ; NO, GOOSE THE NCP SO IT WILL NOTICE
JRST IMPEI1 ; THAT MLC STOLE AN INPUT BUFFER
>
IFN NCPF,<
IMPEI4: CALL IMP8XQ ; Put on irreg msg Q for NCP
AOS IMPFLG ; Awaken NCP
JRST IMPEI3 ; join below
>
;;; Here if we get a short leader message
;;; Message type in T3
;;; packet in T1
;;;
IMPE3A: CAIN T3,.IHNOP ; NOP?
JRST IMPEI3 ; ignore it (avoid resonance)
PUSH P,T1 ; save the packet
MOVEI T1,10 ; send some NOP's so the IMP knows what we want
MOVEM T1,NTNOP(P1)
MNTCALL NTOSRT ; Make sure output is going
POP P,T1 ; restore packet pointer
IMPEI3: MOVE T2,T1 ; Copy for indexing below
IFN NCPF,<
CALL INTBCK ;(T1) ; Internet buffer?
JRST .+3 ; No
> ;**** beware .+3 above
CALL INTFBF ;(T2,P1) ; Free an internet buffer
JRST IMPEI2
IFN NCPF,<
CALL IMPRBF ;(T2) ; Release buffer
JRST IMPEI2
>
; RFNXCT- Table of XCTs, do Rfnm counting if proper msg type
RFNXCT: JFCL ; not for normal msgs
CALL RFNIN ; count err in ldr as rfnm
REPEAT 3,<JFCL> ; Not for types 2-4
CALL RFNIN ; Of course for Rfnms
JFCL ; not for dead host status
CALL RFNIN ; but yes for dead host msgs
CALL RFNIN ; yes for err in data
CALL RFNIN ; yes for inc trx
JFCL ; and not for interface reset
NRFNXS==.-RFNXCT ;
IFN NCPF,<
;;; IMPGHL - Get Host-Link arg for LNKLUK from buffer in T1
;;; Puts host in T1, 32 bit form, and link in T2, with L1%SND on
;;; Skip if succeed, non-skip if non-NCP Host or link
IMPGHL::
LOAD T2,IHHST,(T1) ; Is this for a fake host?
CAIL T2,FKHOST ; ..
RET ; Yes. Won't be found by LNKLUK
LOAD T2,IHLNK,(T1) ; Is it for a non-NCP link?
CAILE T2,LLINK ; ..
RET ; Yes. Can't find this one either
TXO T2,L1%SND ; This is a send connection
PUSH P,T2 ; Save
LOAD T2,IHADR,(T1) ; Get 24 bit address
LOAD T1,IHNET,(T1) ; And 8 bit net
ASH T1,^D24 ; Shift to right position
IOR T1,T2 ; Stick in low part
POP P,T2 ; And restore Link arg
RETSKP ; Return LNKLUK args in T1,T2
>
;;;
;;; IMPODN -- End of output handler for 1822 nets.
;;;
;;; HERE ON PI LEVEL FROM DEVICE ROUTINE AFTER SENDING OUT
;;; LAST WORD OF A BUFFER. PUT IT ON RETRANSMISSION QUEUE IF
;;; REGULAR LINK, AND RFNM STILL OUTSTANDING. ELSE PUT IT
;;; ON FREE LIST.
;;;
;;; P1 - Contains pointer to NCT
;;;
IMODUN::
MNTCALL NTSCHK ; Keep ready line status up to date
JFCL ; ignore return
MOVE T1,NTOB(P1) ; Get buffer location
HRRZS (T1) ; Clear link field
IFN NCPF,<
CALL INTBCK ; Internet buffer?
CAIA ; No
JRST IMODN3 ; Yes
CALL IMPGHL ; Get Host-Link pair for LNKLUK in T1,T2
JRST IMODN4 ; Fake host or something non-NCP
CALL IMPPIL ; Get lt index for this
JRST IMODN6 ; Not there
MOVX T2,RFNMCM ; Be sure RFNM has not returned already
TDNN T2,IMPLT2(T1) ; which would be pretty fast service
JRST IMODN4 ; Well what do you know! It did!
HRRZ T2,IMPLT3(T1) ; Be sure nothing is on re-xmit Q already
JUMPN T2,IMODN6 ; Anomalous, but what can you do?
MOVE T2,NTOB(P1) ; Get buffer address
HRRM T2,IMPLT3(T1) ; Save for rexmission if RFNM times out
MOVE T1,T2 ; Put buffer address in right register
CALLRET MULKSP ; Unlock bfr
IMODN6: MOVE T4,NTOB(P1) ; Pick up buffer addr again
DMOVE T1,1(T4) ; Get most of leader for printing
DMOVE T3,3(T4)
MNTBUG(INF,IMPLEO,<Can't find LT entry for output message>,<<T1,D>,<T2,D>,<T3,D>,<T4,D>>)
IMODN4: MOVE T2,NTOB(P1) ; GET BUFFER ADDRESS
JRST IMPRBF ; RELEASE OR PUT ON FREE LIST
IMODN3:
>
;;; Here with an Internet buffer
MOVE T2,T1 ; Place in the right register
CALLRET INTFBF ; Free it
;;;
;;; IMPHDR - routine for creating an arpanet type local leader
;;; from an Internet V4 leader
;;;
;;; called with - T1 - Local address to send to
;;; T2 - Pointing MAXLDR (defined in INPAR) words above
;;; an Internet buffer,
;;; (Future mod -- T3 type of buffer (Internet, Chaos etc.)
;;; returns with T2 pointing to the local leader
;;; (actually the link,,size word just before it)
;;; Should be modified to allow Class B "Arpanet"'s
IMPHDR:
IFL MAXLDR-.NBHHL,<
PRINTX ?ERROR MAXLDR is less than the IMP header
>
IFN MAXLDR-.NBHHL,< ; If we aren't the maximimum leader
MOVEI T3,.NBHHL ; Amount to correct by
CALL FIXLDR ; Fix header size
>
SETZM .NBLD0(T2) ; Clear 1st word of leader
SETZM .NBLD1(T2) ; Clear other words
SETZM .NBLD2(T2) ; ..
TDZ T1,NTNLHM(P1) ; Clear logical host bits from destination
STOR T1,IHADR,(T2) ; Store address
LSH T1,-30 ; get the network number
STOR T1,IHNET,(T2) ; set it into the packet (used by RFNOUT)
;;; T1 now free
MOVX T3,INTLNK ; Get link
STOR T3,IHLNK,(T2) ; Set it in leader
MOVX T3,ITY%LL ; New format flag
STOR T3,IHFTY,(T2) ; Set it in leader
IFN <PIPRC-7B10>,<PRINTX ? Fix PIPRC mask>
MOVE T4,MAXLDR+.IPKVR(T2) ;#570 Get word with type of service
MOVX T3,<HTY%HP_<-4>> ; Bit in split word
TXNE T4,<4B10> ; High priority?
STOR T3,IHHT2,(T2) ; Yes, set bit
TXNE T4,<PILDY> ; Unless request "low delay"
TXNE T4,<PIHRL> ; and "low reliability"
TDZA T1,T1 ; Message sub-type 0
MOVX T1,3 ; If both, message sub-type 3
LOAD T3,NBBSZ,(T2) ; Get size, bytes
ASH T3,2+3 ; Make into bits
CAILE T3,^D991 ; Sub-type 3 must be <991 data bits
SETZ T1,
IDIVI T3,^D1008 ; Number of packets
STOR T3,IHHTY,(T2) ; Store it
STOR T1,IHSTY,(T2) ; Message sub-type
RET ; And return
;;;
;;; NCPOTT (OuTput Test)
;;; Test if can send an Internet buffer
;;;
NCPOTT==RSKP ; Return good always for now.
;;;
;;; RFNM counting code.
;;; These routines make sure that we do not flood the IMP
;;; with messages for a single host.
;;;
RFNCNT: -1 ; Non-zero to enable RFNM counting
;;;
;;; RFNIN -- Handle a received RFNM (or equivalent)
;;; T1/ Received Buffer address
;;;
RFNIN:
SAVEAC <T1,T2,T3> ; Save temp AC's
LOAD T2,IHADR,(T1) ; Get 24 bit address
LOAD T1,IHNET,(T1) ; And 8 bit net
LSH T1,^D24 ; Shift to right position
IOR T2,T1 ; Stick in low part
CALL RFNHSH ; Find entry for this host
JRST RFNIDN ; If not found we're done early
CAML T1,RFNMAX ; Were we at max?
AOS MNTFLG ; Make sure output is going
SKIPN T1 ; Were there any outstanding?
JRST RFNIDN ; no (?) then done
MOVX T1,-1B3 ; Decrementing value
ADDM T1,RFNTAB(T3) ; count down
RFNIDN: RET
;;;
;;; RFNOUT -- Count up outgoing packets to a host.
;;; Called
;;; T2/ Queue pointer
;;; 0(T2) -- Head, 1(T2) tail
;;; Returns
;;; +1 No packets on this queue can go out
;;; +2 Packet to send in T1, already dequeued.
;;; clobbers T2
;;;
RFNOUT: SKIPN 0(T2) ; if nothing on the queue
RET ; do nothing
SAVEAC <T3,T4,Q1>
MOVE Q1,T2 ; Save queue pointer
PIOFF ; protect Queues and RFNM tables
MOVE T1,0(Q1) ; Get first buffer
MOVE T4,T1 ; save as "previous" also
RFNOU1:
IFN MLCN,< ; Kludge for MLC traffic
LOAD T2,IHLNK,(T1) ; get link number
LSH T2,-1 ; over 2
CAMN T2,MLCHLF ; PTIP?
JRST RFNIC5 ; Yes, send it regardless
> ; end of PTIP kludge
LOAD T2,IHADR,(T1) ; Get host part
LOAD T3,IHNET,(T1) ; and net
LSH T3,^D24 ; CLass A
IOR T2,T3 ; merge it in
PUSH P,T1 ; Save buffer pointer
CALL RFNHSH ;
JRST RFNNEW ; not in table
SKIPE RFNCNT ; is counting enabled?
CAMGE T1,RFNMAX ; too many for this host?
JRST RFNINC ; no, use this buffer
;;; Check if packet has been on the queue too long
SKIPE T1,RFN8TO(T3) ; Has timeout been set?
JRST RFNOU2 ; yes
MOVE T1,TODCLK ; no
ADDI T1,^D30000 ; Wait 30 seconds max
MOVEM T1,RFN8TO(T3) ; save
RFNOU2: SUB T1,TODCLK ; Compare with current time
JUMPG T1,RFNOU3 ;#522 Timeout hasn't occured
Ife ISIQ,MNTBUG(INF,RFNTOT,<RFNM Table timeout>,<<T2,HOST>>)
Ifn ISIQ,AOS RFNTC ;#522 conditionally count instead of buginf
MOVX T1,-1B3 ; timeout!
ANDCAM T1,RFNTAB(T3) ; clear count
JRST RFNINC ; and output the packet
;;; Must try the next in the list
RFNOU3: POP P,T4 ; Save buffer as "previous"
LOAD T1,NBQUE,(T4) ; get next
JUMPE T1,RFNMEX ; End of list
HLL T1,T4 ; same section
JRST RFNOU1 ; onward to the next packet
;;; Here to increment packet count for this host, and
;;; D-Q the buffer
RFNINC: MOVX T1,1B3 ; Incrementor
ADDM T1,RFNTAB(T3) ; increment the count
SETZM RFN8TO(T3) ; Clear timeout
RFNIC0: POP P,T1 ; restore this buffer
;;; T1 contains this buffer
;;; T4 contains previous buffer
;;; Q1 contains queue pointer
RFNIC5: LOAD T2,NBQUE,(T1) ; Get next
STOR T2,NBQUE,(T4) ; remove from list
SKIPE T2 ; If nothing there, skip
HLL T2,T1 ; else place in same section
CAMN T1,0(Q1) ; Was this the queue head?
MOVEM T2,0(Q1) ; yes, set new head
CAME T1,1(Q1) ; was this the queue tail?
JRST RFNIC1 ; no
MOVEM T4,1(Q1) ; yes, set new tail
CAMN T1,T4 ; was it the head also?
SETZM 1(Q1) ; then empty the queue
RFNIC1: PION ; everything is safe now
SETZRO NBQUE,(T1) ; Not in a queue
RETSKP
;;; Here when no entry for this address
RFNNEW: JUMPL T3,[
;;; MNTBUG(INF,RFNFUL,<RFNM Table full>,<<T2,D>>)
; This is probably caused by
; the NCP sending RESETs to all
; all hosts at startup.
; rather than suffer along with
; a full hash table, the best alternative
; is to flush everything, and at worst
; suffer a short blockage.
SETZM RFNTAB
MOVE T1,[XWD RFNTAB,RFNTAB+1]
BLT T1,RFNTAB+RFNTSZ
POP P,T1
JRST RFNOU1] ; Try again with this buffer
MOVEM T2,RFNTAB(T3) ; set new entry in table
JRST RFNINC ; and increment the count
RFNMEX: PION ; Things are safe
RET ; return
;;;
;;; RFNHSH -- Look up an entry in the RFNM hash table
;;; Called
;;; T2/ host address
;;; Returns
;;; +1 No entry for this host
;;; T3/ index of free slot or -1 of table full
;;; +2 entry found
;;; T1/ RFNM count
;;; T3/ index
;;; Hash table format
;;; 0-3 Count of outstanding RFNM's for a host
;;; 4-35 Host address
RFNHSH: SAVEAC <T4> ; Save some ACs
LDB T3,[POINT 16,T2,19] ; Get high half of address
LDB T4,[POINT 16,T2,35] ; and low
XORB T3,T4 ; Mix them together
LSH T3,-^D8 ; and
XOR T3,T4 ; grind down to 8 bits
ANDI T3,RFNTSZ-1 ; fit within table size
MOVE T4,T3 ; save start
RFNHLP: SKIPN T1,RFNTAB(T3) ; Entry here?
RET ; No, free slot
XOR T1,T2 ; Compare with search object
TXNN T1,-1^!-1B3 ; But only the host bits
JRST [ LSH T1,-^D32 ; Got a match, return count
RETSKP] ; return success
CAIL T3,RFNTSZ-1 ; At end of table?
TDZA T3,T3 ; Yes, wraparound
AOS T3 ; Otherwise just bump index
CAME T3,T4 ; Are we back where we started?
JRST RFNHLP ; No, keep looking
SETO T3, ; Yes, indicate by T3=-1
RET ; and return bad
RFNMAX: EXP 7 ; maximum outstanding messages
;;;
;;; NCPUNQ -- Get next buffer to send on a NCP net.
;;; Called
;;; P1 -- NCT
;;; Returns
;;; +1 if no buffer can be sent
;;; +2 buffer to send in T1
;;;
NCPUNQ::
MOVEI T2,NTHOBO ; Point to
ADD T2,P1 ; queue head
CALL RFNOUT ; Get a buffer
CAIA ; Failed
JRST NCPUNX ; exit with buffer
SETZ T4, ; Assume no priority changes
SKIPN NTLOBO(P1) ; Anything on low priority Queue
JRST NCPUN2 ; no, Internet or nothing
SKIPN NTIOBO(P1) ; Anything on internet?
JRST NCPUN4 ; no, low or nothing
SKIPG T4,NTPRIO(P1) ; Who should we try first?
JRST NCPUN4 ; Low priority
;;; Here to try from Internet
NCPUN2: MOVEI T2,NTIOBO ; try from the internet queue
ADD T2,P1 ; ...
CALL RFNOUT ; try to get one
JRST [ SKIPG T4 ; Was there something on low?
RET ; no, total failure
JRST NCPUN4] ; get from low
HRRZ T2,TNPRIO ; Get NCP credit
SKIPE T4 ; was there anything on NCP?
SUB T4,T2 ; yes, give it credit
JRST NCPUN7 ; join below
;;; Here to try from low priority
NCPUN4: MOVEI T2,NTLOBO ; try the low priority queue
ADD T2,P1 ; ...
CALL RFNOUT ; get a buffer
JRST [ SKIPL T4 ; failed, anything on internet?
RET ; no, nothing anywhere
JRST NCPUN2] ; join above
HLRZ T2,TNPRIO ; get Internet credit
SKIPE T4 ; conflict?
ADD T4,T2 ; give internet credit
NCPUN7: MOVEM T4,NTPRIO(P1) ; set back new priority word
NCPUNX: MOVEI T2,377777 ; Flag that buffer passed to net
STOR T2,NBQUE,(T1) ; ...
RETSKP ; return success, buffer in T1
TNPRIO: 1,,1 ; constant for NCP/Internet favoritism
TNXEND ; End of module
END ; ...