1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-22 18:42:15 +00:00

952 lines
30 KiB
Plaintext
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.

;;; -*- Mode:MIDAS -*-
;;; Copyright (c) 1999 Massachusetts Institute of Technology
;;; See the COPYING file at the top-level directory of this project.
IMPVRS==.IFNM2 ; Version of IMP code
IFN NCPP,.FATAL IMP Code doesn't support NCP any more!
IFE KSIMP\SSIMP,.FATAL Wrong IMP driver file included!
OVHMTR IMP ;Charge all this stuff to the IMP
$INSRT LHDH
; IMP 1822 PROTOCOL INFORMATION (EXTENDED-LEADER VERSION)
; The IMP leader is 96 bits long, usually organized as 3 words of 32 bits.
; For further details, these documents are available from the Network
; Information Center:
; IMP-HOST protocol: BBN Report No. 1822
; NCP protocol: NIC 8246, Host-to-Host Protocol for the ARPANET
; IP, TCP: Internet Protocol Transition Workbook, and
; Internet Protocol Implementor's Guide
;
; Here is the leader format used by the IMP code. This format uses
; no IMP padding, assumes IP only, and expects all IMP<->HOST data
; transfers in 32-bit mode.
;
; Previous versions of this code which supported NCP used a much more
; complicated leader formatting scheme based on 36 bit transfers and
; IMP padding. That scheme is dead, see SYSTEM;IMPOLD WTHNCP for details.
;
; All data from the IMP interface ends up in the -10 as left-justified
; 32-bit words. Objects of less than 32 bits length, such as IP octets,
; are stored in PDP10 ILDB byte order.
;
;------------------------------------------------------------------------
;1: 4.9-4.6 not used (0)
; 4.5-4.2 all 1's for new format, else old msg type (4=old nop)
; 4.1-3.3 network number (0)
; 3.2-2.8 not used (0)
; 2.7 trace (ignored)
; 2.6-2.4 leader flags (2.6 is to be ignored, 2.5-2.4 are not used!)
; 2.3-1.5 message type
;
;2: 4.9-4.2 Handling type (7 for big buffers, 4 for small buffers,
; 0 for the control link)
; 4.1-3.3 Host number on IMP
; 3.2-1.5 IMP number
;
;3: 4.9-4.2 Link Number (High 8 bits of Message ID)
; 4.1-3.7 Low 4 bits of Message ID (0)
; 3.6-3.3 Sub-type
; 3.2-1.5 Message length
;------------------------------------------------------------------------
;4: 4.9-1.5 First word of IP datagram
; ....
;------------------------------------------------------------------------
;
;In message types 2 and 6, the going-down status 16-bit word is
;in word 3 bits 4.9-3.3.
;3.6-3.3 of word 3 are the padding count for type 4 (nop) from host.
;This is currently 0 (none). Padding is only put on type-0 messages.
IMPLDS==3 ;IMP local leader size
;Byte pointers to fields of input leader
IMOTBP: 340400,,IMPILB+0 ;Message format type
IMTBP: 041000,,IMPILB+0 ;Message type field
IMSABP: 043000,,IMPILB+1 ;Source address field (host+IMP)
IMSHBP: 241000,,IMPILB+1 ;Source host field
IMSIBP: 042000,,IMPILB+1 ;Source IMP field
IMLNBP: 341000,,IMPILB+2 ;Link number field
IMSTBP: 240400,,IMPILB+2 ;Subtype field
IMMLBP: 042000,,IMPILB+2 ;Message length field
SUBTTL ARPANET VARIABLES AND TABLES
EBLK
%IMXLN==:<<8159.-96.>+31.>/32. ; Max # of 32-bit words in IMP regular msg,
; exclusive of leader and leader padding. = 252.
%IMMTU==:251.*4 ; Used by IP/TCP. Driver currently rounds to PDP10 words,
; forcing this to be 1004 instead of 1007.
; ACTIVE HOST TABLE. Entries herein are allocated as needed, using garbage
; collection. Most "host number" fields are really indices into this table.
;
LIMPHT==<XBL+10.> ; TCP conns plus a few extra
IMPHTF: -1 ;Host table free list, threaded through IMPHTB, end with -1
IMPHTS: ;Start of table area
IMPHTN: BLOCK LIMPHT ; Host number. 1.1-1.8 HOST, 2.1-3.7 IMP
IMPHTB: BLOCK LIMPHT ;Bits:
;4.9 UNUSED
;4.8 GC MARK BIT
;4.7-4.3 UNUSED
;4.2-4.1 STATUS OF HOST 0 DOWN, 1 RST SENT, 2 UP
;3.9-3.1 UNUSED
.SEE IMPHDS ;RH Last message from IMP about "host dead status"
IMPHTC: BLOCK LIMPHT ; # active messages outstanding for host (8 max)
IMPHTT: BLOCK LIMPHT ; Time of last RFNM received
IMPHTE==.-1 ;Last location in table
;Status variables
;
IMPUP: -1 ;0 => IMP up ;-1 => down ;-2 => coming up, PI still off
;1 => down for good, until next time IMP ready line changes
IMPTCU: 0 ;0 IMP up/down status not changing
;>0 Trying to reinitialize, SYSJOB hasn't done so yet
;-1 Has been reinitialized, haven't exchanged NOPs yet
IMPUCT: 0 ;IMP coming up timeout, if 4 NOPs don't go through promptly.
IMPDWN: BLOCK 3 ;Last message from IMP that it is going down
;WD0: "Reason" claimed by IMP (see ch 3 of BBN report 1822)
;WD1: Time when expected down
;WD2: Time when expected up (SYS time=1/30 sec since up)
IMERCN: -1 ;CONI into here when net goes down
BBLK
EBLK
;Input side variables
;
IMPILB: BLOCK IMPLDS ;Input leader buffer
IMPCSH: -1 ;Current source host (IMPHTB index). -1 when idle.
IMPCLN: 0 ;Current link number
IMIFLS: 0 ;Flushing output at interrupt handler
IMPIEC: 0 ;Count of input errors while down.
IMPIBC: 0 ;Count of words available in DMA input buffer
IMPIBP: 0 ;Pointer into DMA input buffer
;Output side variables
;
;Output leader buffer
IMOLDR: <17_10.>,,0 ;Regular new-format message
IMOLAD: 0 ;Filled in with destination IMP address
<233_10.>,,0 ;IP link field
IMNOPC: 0 ;< 0 => Send NOPs
IMPOAC: -1 ;>= 0 => Output active, don't restart
IMPBZY: 0 ;-1 == Waiting for output interrupt
IMPODP: 0 ;Pointer to IP datagram being output at PI level
IMPOS: 0 ;Output state
%ISODL==:0 ; Not expecting output done (i.e. between messages)
%ISONP==:1 ; Sending NOP
%ISOID==:2 ; Sending IP Datagram
;Meters
;IP meters
IMNIPI: 0 ; # of IP datagrams input (rcvd)
IMNIPF: 0 ; # of IP datagrams flushed (input threw away)
IMNIPO: 0 ; # of IP datagrams output (sent)
IMNIPR: 0 ; # of IP RFNMs received
IMNIP7: 0 ; # of IP Type 7 (Dest Host Dead) messages received
IMNIP8: 0 ; # of IP Type 8 (Error) msgs rcvd
IMNIP9: 0 ; # of IP Type 9 (Incomplete Transmission) msgs rcvd
IMNWIG: 0 ; # words ignored by "Ignore" state (%ISIGN)
IMNWIF: 0 ; # words flushed by IMPRM5
;IMP meters
IMNSRF: 0 ;Number of spurious RFNMs on non-IP links
IMNBLK: 0 ;Number of times blockage avoided (output held up by ITS)
IMPMSR: BLOCK 20;Count of IMP messages rcvd
IMPM1S: BLOCK 4 ; # Type 1 (Error in Leader) subtype msgs
IMPM9S: BLOCK 2 ; # Type 9 (Incomplete Transmission) subtype msgs
IMPMSS: BLOCK 1 ;Count of IMP msg sent (we only send regular msgs)
IMCT1: 0 ;# Unvectored interrupts
IMCT2: 0 ;# Valid input interrupts
IMCT3: 0 ;# Valid output interrupts
BBLK
SUBTTL ARPANET MAIN-PROGRAM LEVEL
;IMPIBF, IMPOBF defined as low-memory buffer page in ITS
IF2,IFN IMPIBF&777,.FATAL IMPIBF not on DEC page boundary
;(Re)Start IMP. Called from SYSJOB to start IMP, or on error or
; user requested cycle through LOCK
;
IMPINI: SETOM IMPUP ;Not up yet,
SETOM IMPTCU ; but thinking about it.
MOVEI A,IMPIBF_-9. ;DEC page # of IMP buffer page
TRO A,%UQ16B\%UQVAL ;Valid mapping, 16 bit device
IOWRI A,UBAPAG+IUIMPG_1 ;Set up 1 DEC page of UBA mapping. Note that
; the second half of IUIMPG isn't mapped at all
CONO PI,NETOFF ;Freeze things while IMP bashing occurs
MOVEI A,%LHRST
IOWRI A,%LHOCS ;Reset output side
IOWRI A,%LHICS ;Reset Input side
;IMP now shut down. Reset variables
SKIPE A,IMPODP ;Have an output datagram ?
PUSHJ P,IPIODN ;Yep, release it.
SETZM IMPODP ;No output datagram
SETZM IMPOS ;Output idle
SETOM IMPOAC ;Output interrupt level inactive
SETZM IMPBZY ;No pending output interrupt
SETZM IMPIBC ;No input available
SETZM IMPIEC ;No input errors yet
SETZM IMIFLS ;Not flushing input at interrupt level
SETOM IMPCSH ;No current host table index
SETOM IMPDWN+1 ;Time for IMP to go down, not known
CONO PI,NETON ;Allow interrupts again
;Wait one sec for IMP to notice rdy line drop
MOVE T,TIME
ADDI T,30.
CAMLE T,TIME
PUSHJ P,UFLS
MOVNI A,30. ;Allow 15 seconds to come up
MOVEM A,IMPUCT
MOVE T,TIME ;Note when we last started IMP
MOVEM T,LNETIM
PUSHJ P,IMPHRS ;Set host ready
PUSHJ P,IMPIST ;Start input
MOVE T,TIME
ADDI T,15. ;Wait 1/2 sec before we try to output
CAMLE T,TIME
PUSHJ P,UFLS
MOVNI A,4
MOVEM A,IMNOPC ;Send 4 NOPs to start
;Falls through to start output
;Start IMP output
;
IMPOST:
IMPIOS: CONO PI,PIOFF ;Freeze.
AOSE IMPOAC ;Do nothing if output already active.
JRST PIONJ
SETOM IMPBZY ;Note we want an IMP interrupt
CONO PI,NETRQ ;Force nonvectored IMP interrupt
JRST PIONJ
;Check if IMP ready line is set
; Called from SYSJOB.
; Return +1 if IMP not ready, +2 if so
;
IMPCKR: IORDI A,%LHICS ;Get input CSR
TRNN A,%LHINR ;Skip if IMP not ready
AOS (P) ;Return +2 if ready
POPJ P, ;That's all
;Set HOST READY. From SYS job only, please, loops waiting.
;
IMPHRS: IORDI T,%LHICS
TRNN T,%LHRDY ;Can we mung?
BUG
IORI T,%LHHRC\%LHSE ;Turn on HR. SE prevents dropping messages
IOWRI T,%LHICS
MOVEI A,777777 ;I don't know why this takes so long.
IMPHR1: IORDI T,%LHICS ;Get the bits back
TRNE T,%LHHR ;LHDH thinks host ready is ready
RET ;HR line set
SOJG A,IMPHR1 ;Timed out yet?
BUG CHECK,[IMP: Timed out setting Host Ready]
RET
SUBTTL HOST-TABLE MANAGEMENT
;IMPHTI - Initialize host table
; Performed whenever IMP announces that it has been reset
;
IMPHTI: SETOM IMPHTF ;Force GC of IMPHTB on first reference
SETZM IMPHTS ;Clear table of old information
MOVE A,[IMPHTS,,IMPHTS+1]
BLT A,IMPHTE
POPJ P,
; FNDHST - Look up host-table index for a given IMP host address.
; Call with NETOFF or NETCHN PI in progress.
; T/ IMP host address (maybe someday other nets?)
; Returns .+1 if failed (no room in table)
; Returns .+2
; H/ host-table index
; Smashes W.
FNDHST: MOVEI H,LIMPHT-1 ;Search for an entry for this host
CAME T,IMPHTN(H)
SOJGE H,.-1
JUMPGE H,POPJ1 ;Found
SKIPGE H,IMPHTF ;Not found, cons one off free list
JRST FNDHS1 ;Oops, must garbage collect
MOVE W,IMPHTB(H)
CAIGE H,LIMPHT ;Make sure H is valid idx
CAIL W,LIMPHT ;ditto W
BUG HALT,[NET: FNDHST idx clobbered!!!]
MOVEM W,IMPHTF
MOVEM T,IMPHTN(H)
SETZM IMPHTB(H) ;Nothing is known about this host
SETZM IMPHTC(H) ;Assume no RFNMs outstanding
SETZM IMPHTT(H) ;Clear out time of last RFNM.
JRST POPJ1
; Host-Table full, attempt to GC it and flush unused entries, by
; scanning all possible pointers into table.
; IMP pointers are IMPCSH and IMPHTC(H)
; TCP pointers are XBNADR(I)
; GC mark phase - mark entries in use
FNDHS1: PUSH P,I
MOVSI W,200000 ;Mark bit
MOVEI H,LIMPHT-1 ;Clear all mark bits
ANDCAM W,IMPHTB(H)
SOJGE H,.-1
SKIPL H,IMPCSH ;Mark from IMPCSH
IORM W,IMPHTB(H)
IFN TCPP,[
MOVEI I,XBL-1
SKIPL H,XBNADR(I) ; See if TCP conn has a net addr specified
IORM W,IMPHTB(H) ; Yes, set the mark bit.
SOJGE I,.-2
] ;IFN TCPP
; GC sweep phase - free all unmarked entries
SETO I, ;Free pointer
MOVEI H,LIMPHT-1
MOVSI W,601000 ;Protect if RFNM-WAIT, RST-WAIT, or marked
FNDHS4:
SKIPG IMPHTC(H) ;Also protect if any outstanding RFNMs
TDNE W,IMPHTB(H)
SOJGE H,FNDHS4
JUMPL H,FNDHS5
SETZM IMPHTN(H) ;Don't belong to any host
MOVEM I,IMPHTB(H) ;Cons onto free list
MOVE I,H
SOJGE H,FNDHS4
FNDHS5: MOVEM I,IMPHTF ;Free list
POP P,I
SKIPGE IMPHTF
POPJ P, ;GC-overflow
JRST FNDHST ;Try again, should win
;See if IMP code is willing to handle a particular datagram right now.
; A/ IP DGM pointer
; C/ Immediate destination address
; Returns +1, can't send right now, +2, OK to send
;
IMPCTS:
IFE SSIMP,[
MOVE T,C ;Set up for FNDHST
AND T,[<377_16.>+377] ;Mask out all but host and IMP field
CALL FNDHST ;Get host index in H
POPJ P, ;No host entry, don't send
JSP T,IMPBLI ;See if OK to send
POPJ P, ;IMP wants to block, no send
] ; IFE SSIMP
JRST POPJ1 ;Skip return if OK to send.
IFE SSIMP,[ ; Not needed with Simple IMP!
;;; IMP Blockage avoidance
; The current IMP software will not accept more than 8 active
; messages to a single host; attempting to send a 9th message will block
; ALL output to the interface, until the first message has been ack'd
; by means of one of the following message types:
; Type 5, RFNM - Message delivered OK
; Type 7, Host dead - transmit failed ("permanent")
; Type 8, Error in data - interface spazzed
; Type 9, Incomplete Transmission - temporary failure
; If for some reason the first message simply becomes lost, the IMP timeout
; (and blockage) can last for up to 30-45 seconds.
; More details in BBN Report 1822.
; ITS attempts to fix this by keeping a count of active un-ACKed
; messages for each host it is communicating with. A timeout is also
; associated with each host; if output to a given host is blocked by ITS
; because there are 8 active messages, trying to send a 9th message
; will check the last-RFNM-received time and if this was more than
; 30 or so seconds then the IMP is probably not giving us what it should
; and we should reset things for that host.
%IMPMA==:8. ; # of maximum active IMP messages allowed
; IMPBLI, IMPBLD - routines to hack active-message counts, called via JSP T,
; IMPBLD decrements count.
; IMPBLI increments count and skips if successful (else failed,
; and must NOT output another message to this host!)
; Also clobbers Q.
;
IMPBLI: AOS Q,IMPHTC(H)
CAIGE Q,%IMPMA ;Trying to send max or more messages?
JRST 1(T) ;No, can return safely.
CAIG Q,%IMPMA ;Is this the maximum # allowed?
JRST [ MOVE Q,TIME ;Yes, set up blockage timeout
ADDI Q,60.*30. ; for one minute.
MOVEM Q,IMPHTT(H)
JRST 1(T)] ;And allow this one to be sent
; Trying to send too many messages, block it (check for timeout though)
SOS IMPHTC(H) ;Restore original count
AOS IMNBLK ;Increment # of times softwarily blocked.
MOVE Q,IMPHTT(H)
CAML Q,TIME ;See if timeout still in the future
JRST (T) ;Yes, just take failure-return to block.
BUG INFO,[IMP: RFNM-wait timeout! Hst=],OCT,IMPHTN(H)
SETZM IMPHTC(H) ;This may be dangerous... oh well.
SETZM IMPHTT(H)
JRST (T) ;Block one last time, next try will win.
] ; IFE SSIMP
;Decrement block count on receipt of any kind of ACK
;
IMPBLD: SOSL Q,IMPHTC(H)
JRST IMPBL2
BUG INFO,[IMP: negative RFNM-wait cnt, Hst=],OCT,IMPHTN(H)
SETZB Q,IMPHTC(H)
IMPBL2:
IFE SSIMP,[
CAIL Q,%IMPMA-1 ;If we were blocking on this host,
PUSHJ P,IMPIOS ;Ensure IMP output started up so blocked stuff
]
JRST (T) ; gets sent promptly.
SUBTTL ARPANET INPUT INTERRUPT LEVEL
;First level interrupt handling for input side. Here from UBA vector hardware.
IFN NETCHN-UTCCHN,.ERR NETCHN assumed == UTCCHN at IMPIBK
EBLK
IMPIBK: 0
BBLK
JSR UTCSAV ;Save AC's, get a stack
AOS IMCT2 ;Count input interrupts
IORDI TT,%LHICS ;Get CS register
TRNE TT,%LHERR\%LHNXM
JRST IMPRST ;Try resetting the IMP
TRNE TT,%LHMRE ;Ready line flapped
JRST IMPIER ;Go directly to error routine
TRNN TT,%LHRDY ;Device ready for new operation?
JRST IMPRST ;Try resetting.
TRNN TT,%LHEOM ;Saw EOM from IMP?
JRST IMPIB1 ;No, word count ran out before message
SKIPGE IMIFLS ;Flushing output?
JRST [ SETZM IMIFLS ;Not any more!
JRST IMPIRT ] ;But flush last piece by queueing new request
IORDI A,%LHIWC ;End of message. Get remaining UB word count
SKIPE A ;This would be a surprise, really
TDO A,[-1,,600000] ;36bit number of UBA words remaining in bfr
IDIVI A,2 ;Number of PDP10 words (cleverly rounded)
ADDI A,IMPBFS ;Number of PDP10 words of message
MOVEM A,IMPIBC ;Set current count of available data words
MOVEI A,IMPIBF
MOVEM A,IMPIBP ;Set pointer to available data words
JRST IMPLDD ;Go process input message
;Here when finished processing current message.
IMPIRT: SETOM IMPCSH ;Note no current host
PUSHJ P,IMPIST ;Restart input listener
JRST IMPEX
;Message didn't fit in input buffer. Shouldn't ever get here, but
;might if messages concatenated due to ready line randomness
;
IMPIB1: BUG INFO,[IMP: Huge message]
SETOM IMIFLS ;Say we are flushing output
JRST IMPIRT ;And go queue up another read
;Here if error during IMP message transfer
; Currently the only error handled is the IMP going non-ready
IMPIER: SKIPE IMPUP ;Is the IMP supposed to be up?
JRST IMPIE1 ;No, handle errors differently
BUG INFO,[IMP: Input Ready Error]
JRST IMPRST ;Ready line flapped while up, cycle interface
IMPIE1: AOS T,IMPIEC
CAIG T,10. ;Huge number of errors while down?
JRST IMPIRT ;No, just ignore this input and start another
SETZM IMPIEC ;Reset
BUG INFO,[IMP: Excessive input errors while down]
JRST IMPRST ;Cycle the interface
IMPRST: IORDI T,%LHICS ;Record IMP status for sysjob
HRLZM T,IMERCN
IORDI T,%LHOCS
HRRM T,IMERCN
MOVEI A,%LHRST ;Avoid randomness by resetting HW now.
IOWRI A,%LHOCS ;Reset output side
IOWRI A,%LHICS ;Reset Input side
SETOM IMPUP ;IMP is down
MOVEI T,1
MOVEM T,IMPTCU ;But trying to come up (sysjob poked)
MOVSI J,SCLNET ;Ask SYSJOB to cycle the IMP
IORM J,SUPCOR
JRST IMPEX
SUBTTL IMP leader dispatch handling
IMPLDD: SKIPG B,IMPIBC ;Get count of available data
POPJ P, ;None, nothing to do.
CAILE B,IMPLDS ;More than a leader worth?
MOVEI B,IMPLDS ;Yep, only want leader now
MOVS A,IMPIBP ;Copy and reformat leader to IMPILB
HRRI A,IMPILB
IFE SSIMP,BLTUB A,IMPILB-1(B)
IFN SSIMP,BLT A,IMPILB-1(B) ; No reformatting needed for SSIMP
ADDM B,IMPIBP ;Increment buffer pointer,
MOVN C,B
ADDM C,IMPIBC ; and decrement count
LDB T,IMOTBP ;Examine new-format flag bits of leader
CAIL B,IMPLDS ;Large enough to be a valid leader?
CAIE T,17 ;Verify that leader is "new" 96-bit fmt.
JRST IMPLDE ;Go process error in leader
LDB T,IMLNBP ;Extract link number (high 8 bits of msg-id)
MOVEM T,IMPCLN ;Save link message arrived on
LDB T,IMSABP ;Get arpanet address (source host+imp)
IFN 0,[
LDB T,IMSHBP ;Source host
LDB A,IMSIBP ;Source imp
DPB A,[112000,,T] ;Form host address
];IFN 0
PUSHJ P,FNDHST ;H gets host table index
JRST IMPLHE ;Host table full
MOVEM H,IMPCSH ;Save current host
LDB A,IMTBP ;Get message type in A
CAIL A,IMTDTS
JRST IMPUN ;Unknown type?
AOS IMPMSR(A) ;Count IMP msgs rcvd
JRST @IMTDT(A) ;Dispatch
IMTDT: IMPRM ; 0 Regular Message
IMPBE1 ; 1 Error in Leader (no msg-id)
IMPGD ; 2 IMP Going Down
IMPUN ; 3 -
IMPIN ; 4 NOP
IMPRFN ; 5 RFNM - Ready For Next Message (transmit succeeded)
IMPHDS ; 6 Host Dead Status (general info)
IMPDHD ; 7 Destination Host Dead (transmit failed)
IMPBE8 ; 8 Error in Data (has msg-id)
IMPINC ; 9 Incomplete Transmission (transmit failed temporarily)
IMPIRS ;10 Interface Reset - IMP dropped its ready line
IMTDTS==.-IMTDT
IMPLHE: BUG INFO,[IMP: Message discarded due to host table full],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2
JRST IMPIRT
;Here if leader is too short or of wrong format.
; B/ Leader length
IMPLDE: SKIPE IMPUP ;If IMP is not up, we'll take anything.
JRST IMPIRT
CAIGE B,IMPLDS ;Announce short leader if so.
BUG INFO,[IMP: Short leader, ],DEC,B,[wds. WD1=],OCT,IMPILB,[WD2=],OCT,IMPILB+1
LDB A,IMOTBP ;Get message format type
CAIN A,4 ;Old-type NOP?
JRST IMPIRT ; Just ignore it.
IFN 0,[ ;;For the moment this is a problem because the IMP is marked
;;up too soon, before all incoming NOPS are received.
CAIN A,16 ;Is it 1822L format?
BUG INFO,[IMP: 1822L leader],OCT,IMPILB
CAIE A,17 ;Is it not the long-leader format?
BUG INFO,[IMP: Old-type leader],OCT,IMPILB
]
JRST IMPIRT ;Ignore rest of message, if any
;;; IMP->Host Type X (e.g. 3, 11-255) - bad type
IMPUN: BUG INFO,[IMP: Unknown msg type ],OCT,A,[ leader ],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2
JRST IMPIRT
;;; IMP->Host Type 1 - Error in leader (msg-id not given)
;;; IMP->Host Type 8 - Error in data (msg-id given)
IMPBE1: LDB T,IMSTBP ;Get subtype (4 bits)
ANDI T,3 ;Only 2 bits should be used
AOS IMPM1S(T) ;Increment count of Type 1 subtype messages
IMPBE8: SKIPN IMPUP ;Ignore error during initial syncronization
BUG INFO,[IMP: Type ],DEC,A,[err msg, leader],OCT,IMPILB,OCT,IMPILB+1,OCT,IMPILB+2
MOVE B,IMPCLN ;Get link msg came in on
CAIN B,233 ;Internet link?
AOS IMNIP8 ;Yes, count IP meter
CAIN A,8. ;Error identified with a particular message?
JSP T,IMPBLD ;Decrement count of active messages
JRST IMPIRT
;;; IMP->Host Type 2 - IMP going down
IMPGD: LDB B,[420200,,IMPILB+2] ;Reason (see 1822)
MOVEM B,IMPDWN
LDB B,[360400,,IMPILB+2] ;How soon going down * 5 mins
MOVE H,B
IMULI B,5*60.*30. ;Ticks in 5 mins
ADD B,TIME
MOVEM B,IMPDWN+1
LDB C,[241200,,IMPILB+2] ;How long to be down * 5 minutes
MOVE Q,C
IMULI C,5*60.*30. ;Downtime in ticks
ADD C,B ;Add to time down
MOVEM C,IMPDWN+2 ;Store time when will be up
IMULI H,5 ;Minutes
IMULI Q,5
BUG INFO,[IMP: Going down in ],DEC,H,[mins for ],DEC,Q,[mins, reason],DEC,IMPDWN
JRST IMPIRT
;;; IMP->Host Type 4 - NOP
IMPIN: JRST IMPIRT ;One more NOP from IMP
;;; IMP->Host Type 5 - RFNM (Ready For Next Message)
IMPRFN: JSP T,IMPBLD ;Decrement outstanding message count for host
MOVE A,IMPCLN ;Get link #
CAIE A,233 ;IP link number?
JRST IMRFNX ;No, skip IP code
AOS IMNIPR ;Bump count of IP RFNMs received
JRST IMPIRT ; and do nothing else about it, ugh.
IMRFNX: BUG INFO,[IMP: Spurious RFNM from ],OCT,IMPHTN(H),[link],OCT,IMPCLN
AOS IMNSRF
JRST IMPIRT
;;; IMP->Host Type 6 - Host Down Status
; H/ host index
IMPHDS: LDB A,[301400,,IMPILB+2];Bits 65-76 of leader, 4.9-3.7 3rd word
HRRM A,IMPHTB(H) ;Store, hope user read RFC 611
JRST IMPIRT
;;; IMP->Host Type 7 - Destination Host Dead
IMPDHD: MOVEI E,%NCDED
JRST IMPHNR
;;; IMP->Host Type 9 - Incomplete Transmission
IMPINC: LDB T,IMSTBP ;Get subtype field (4 bit reason for failure)
AOS IMPM9S(T) ;Bump count of subtypes
MOVEI E,%NCINC ;This is an incomplete msg response
IMPHNR: JSP T,IMPBLD ;Decrement active IMP msg count for this host
MOVE A,IMPCLN ;Link for this message?
CAIE A,233 ;IP Link?
JRST IMPHN1
CAIN E,%NCINC ;Yes, count IP meters
AOS IMNIP9
CAIN E,%NCDED
AOS IMNIP7
JRST IMPIRT
IMPHN1: BUG INFO,[IMP: DHD or IT msg rcvd on non-IP link]
JRST IMPIRT
;;; IMP->Host Type 10 - Interface Reset
IMPIRS: PUSHJ P,IMPHTI ;Initialize host table
BUG INFO,[IMP: Interface reset]
JRST IMPIRT
;;; IMP->Host Type 0 - Regular Host-Host message
; Unless the source host screwed up and sent a dataless message,
; there is at least one word waiting to be read in the buffer.
;
IMPRM: SKIPG A,IMPIBC ;Get available input word count
JRST IMPIRT ;None left, just ignore message
MOVE B,IMPCLN ;Is link number the magic cookie for IP?
CAIE B,233
JRST IMPIRT ;No, ignore it
;IP datagram. Copy into IP buffer and pass it up.
;
AOS IMNIPI ;Bump count of IP datagrams received
PUSHJ P,IPGIPT ;Ask IP for buffer of size (A)
JRST [ AOS IMNIPF ;Punted, bump cnt of datagrams lost
JRST IMPIRT ] ;Flush this message (err msg already printed)
MOVE B,PK.BUF(A) ;Destination
HRL B,IMPIBP ;Source
MOVE C,IMPIBC ;Input words available
ADDI C,-1(B) ;Last destination address
IFE SSIMP,BLTUB B,(C) ;Copy and reformat data to IP buffer
IFN SSIMP,BLT B,(C) ; No reformatting needed for SSIMP
MOVE B,IMPIBC ;Get word count back to B
SETZB C,IMPIBC ;Say zero offset to IP header, and clear count.
MOVE J,IMPCSH ;Set idx to host-table entry dgm received from.
PUSHJ P,IPRDGM ;Hand off rcvd datagram to IP
JRST IMPIRT ;Return from PI level, setting up for next msg
;Start listening for new input from IMP
;
IMPIST: HRREI T,-IMPBFS*2
IOWRI T,%LHIWC ;Read up to a buffer full of data
MOVEI T,<IUIMPG_12.>+<4*<IMPIBF&777>>
IOWRI T,%LHICA ;Read data to here
MOVEI T,%LHIE\%LHHRC\%LHSE\%LHGO ;Interrupt, store data, go
IOWRI T,%LHICS ;Start read
RET
SUBTTL ARPANET OUTPUT INTERRUPT LEVEL
;Here on unvectored interrupt caused by call to IMPIOS
IMPINT: AOS IMCT1 ;Count unvectored interrupts
JRST IMPOBZ ;Go try to start output
;Returns directly to interrupt dispatcher
;First-level interrupt handling, from hardware dispatch.
; Crash on severe interface errors
; Restart IMP on ready line flappage.
; Else, go look for more output to send.
IFN NETCHN-UTCCHN,.ERR NETCHN assumed == UTCCHN at IMPOBK
EBLK
IMPOBK: 0
BBLK
JSR UTCSAV ;Save AC's, get a stack
AOS IMCT3 ;Count output interrupts
IORDI TT,%LHOCS ;Get CS register
TRNE TT,%LHERR\%LHNXM ;Interface lost?
JRST IMPOEC ;Try cycling
TRNE TT,%LHMRE ;Somebody bounce a ready line?
JRST IMPOER
IMPOBE: TRNN TT,%LHRDY ;Device ready for new operation?
JRST IMPOEC ;Try cycling
PUSHJ P,IMPOBZ ;No IMP error. Perform planned action.
JRST IMPEX ;Dismiss interrupt.
;Error while outputting datagram. Currently, just means ready line flapped.
; If IMP was up, finish up IP output if necessary to free buffer, then
; cycle the interface.
; If trying to send NOPS to come up, just send a few more to resynch.
;
IMPOER: SKIPE IMPUP ;IMP up?
JRST IMPOE1 ;Not running normally, maybe OK.
BUG INFO,[IMP: Output RDY error]
IMPOEC: SKIPE A,IMPODP ;Have an output datagram ?
PUSHJ P,IPIODN ;Yep, release it.
SETZM IMPOS ;Doing nothing useful
JRST IMPRST ;Go poke SYSJOB to cycle the IMP
;Here if interface wasn't fully up.
IMPOE1: MOVE T,IMPOS
CAIE T,%ISONP ;Were we sending a NOP?
BUG CHECK,[IMP: Confusing output error]
SOS IMNOPC ;Add another NOP to make up for this one
SETZM IMPOS ;NOt doing anything anymore
JRST IMPOBE ;Go continue processing.
;IMPOBZ - Toplevel output processing routing.
; Called from output done interrupt handler or from MP/CLOCK level with
; NETOFF to start output.
IMPOBZ: SKIPL B,IMPOS
CAIL B,IMPODL
BUG HALT,[IMP: Bad output state]
JRST @IMPODT(B)
IMPODT: OFFSET -.
%ISODL:: IMPOB0 ; 0 Idle, look for something to send
%ISONP:: IMPOB1 ; 1 Finished NOP
%ISOID:: IMPOB2 ; 2 Finished IP datagram messge
IMPODL::OFFSET 0
;Here when interrupt has finished processing a complete message.
; Attempt to find something else to do.
;
IMORET:
;JRST IMPOB0 ;Fall through to try for more
; Idle - Look for output to send. First ensure we can send stuff,
; then try things in the order:
; (1) Send NOP if net coming up
; (2) Check IP datagram queue
;
IMPOB0: HRRZ T,IMPUP ;Get current IMP state.
CAIE T,-2 ;Don't say it's up when it's still going down
CAIN T,1 ;or when it is broken
JRST IMPOBN
; First check to see if NOP needs to be sent.
AOSG IMNOPC ;Check to see if sending NOPs
JRST IMONOP ;Output a NOP
SETZM IMPUP ;Say IMP is up
SETZM IMPTCU ;Say no longer trying to come up
; Now see if there is any real traffic to send
PUSHJ P,IPGIOQ ;Check IP. Get IP IMP output queue entry if any
JRST IMPOBN ;Nothing there, we're done.
; Returns A/ ptr to IP dgm struct
; B/ BLKO pointer to 32-bit words (unused)
; C/ Arpanet address
;
;Build an IMP-format datagram at IMPOBF.
; Set correct address in prototype leader.
; BLT and reformat leader to IMPOBF.
; BLT and reformat datagram to IMPOBF + leader size.
MOVEM A,IMPODP ;Save ptr to datagram being output
AOS IMNIPO ;# of IP datagrams sent
;Put together the IMP leader in IMOLDR.
IFN 0,[ ;First and third word initialized at assembly time
MOVE B,[17_10.,,0] ;Regular message
MOVEM B,IMOLDR
MOVSI B,233_10. ;IP link # in left 8 bits
MOVEM B,IMOLDR+2 ;Set up third word
]
IFE SSIMP, AND C,[<377_16.>+377] ;Mask out all but host and IMP field
LSH C,4. ;Move net address to correct field
MOVEM C,IMOLAD ;set up second word of leader
;Copy leader and datagram to IMPOBF
MOVE B,[IMOLDR,,IMPOBF]
IFE SSIMP,BLTBU B,IMPOBF+IMPLDS-1 ;Move IMP leader into place
IFN SSIMP,BLT B,IMPOBF+IMPLDS-1 ; No reformatting needed for SSIMP
MOVS B,PK.BUF(A) ;SOURCE,,COUNT
MOVEI A,IMPLDS(B) ;Size including leader to A
HRRI B,IMPOBF+IMPLDS ;Put d'gram immediately after leader.
IFE SSIMP,BLTBU B,IMPOBF-1(A)
IFN SSIMP,BLT B,IMPOBF-1(A) ; No reformatting needed for SSIMP
PUSHJ P,IMPSOH ;Go start hardware
MOVEI C,%ISOID ;Remember we are outputting IP leader
MOVEM C,IMPOS
POPJ P,
;Here if nothing to output.
; Flag output inactive and disable interface
;
IMPOBN: SETOM IMPOAC ;No more output
IORDI TT,%LHOCS
TRZ TT,%LHIE\%LHGO ;Deactivate interface for a bit
IOWRI TT,%LHOCS
POPJ P,
;IMONOP - Send a NOP, here from IMPOBZ only.
;
IMONOP: MOVEI A,IMPNOS ;Length of NOP message
MOVE B,[IMPNOP,,IMPOBF] ;BLT (and reformat) NOP to output buffer
IFE SSIMP,BLTBU B,IMPOBF-1(A)
IFN SSIMP,BLT B,IMPOBF-1(A) ; No reformatting needed for SSIMP
PUSHJ P,IMPSOH ;Start output of (A) words from IMPOBF to IMP
MOVEI C,%ISONP ;Set correct output FSM state
MOVEM C,IMPOS
POPJ P,
;Prefabricated NOP Host-IMP leader
IMPNOP: 17_10.,,4_4 ;New format, type 4 = NOP
0
0 ;No padding required on regular messages
IMPNOS==.-IMPNOP
;Finished sending NOP, from IMPOBZ
;
IMPOB1: SETZM IMPOS ;Reset state
JRST IMORET ;Go look for something else to do.
;Was sending IP datagram, from IMPOBZ
;
IMPOB2: SETZB A,IMPOS ;Reset output state.
EXCH A,IMPODP ;Get active datagram and reset pointer
PUSHJ P,IPIODN ;Tell IP level that datagram was output
JRST IMORET ;Go see if there is anything else to do.
;Start output hardware.
; A/ Count of PDP10 words to write to net.
; Data to output in IMPOBF.
; Must be NETOFF or at NETCHN interrupt level. Bashes A only.
IMPSOH: ASH A,1 ;Convert PDP10 word count to...
MOVNS A ; negative unibus word count.
IOWRI A,%LHOWC ;Tell the interface
MOVEI A,<IUIMPG_12.>+<4*<IMPOBF&777>>
IOWRI A,%LHOCA ;Unibus address of output buffer
MOVEI A,%LHIE\%LHELB\%LHGO ;Enable interrupts, send EOM, GO
IOWRI A,%LHOCS ;Start DMA transfer
POPJ P, ;And forget it.
SUBTTL ARPANET CLOCK LEVEL
IMRSTO: RET ;Nothing to do any more?
OVHMTR UUO
;NETHST (HOST INFO)
; ARG 1 - HOST => VAL 1 - STATUS, VAL 2 - HOST NUMBER
; ARG 1 - -1 => VAL 1 - (STATUS), VAL 2 - OUR HOST NUMBER
;NOT CURRENTLY IMPLEMENTED- ARG 1 - -1, ARG 2 - OUR GOING-DOWN REASON
;
ANETHST:HRRE T,A ;Let immediate -1 win (777777 not a valid host)
AOJE T,ANETH2 ;Jump if want local status and host number
MOVE T,A
JSP J,STDHST ;Standardize and error-check host number
MOVE B,T ;Return new format
TLO B,(NW%ARP)
MOVEI H,LIMPHT-1
CONO PI,NETOFF ;Do we have status for this host?
CAME T,IMPHTN(H) ;Scan table
SOJGE H,.-1
JUMPGE H,ANETH1 ;Yes, return it
CONO PI,NETON ;No, have to go get it
MOVEM T,SRN3(U)
POPJ P, ;Oh, too bad
;Here to return status of foreign ARPAnet host
ANETH1: MOVE A,IMPHTB(H) ;Get status
CONO PI,NETON
EXCH A,B
CALL CVH2NA ;Convert to HOSTS2 for compat
EXCH A,B
JRST LSWCJ1 ;Return IMSOC, NETLST if not done already
;Here to return our status, host
ANETH2:
REPEAT 0,[
CAIL W,2 ;(This is a crock)
MOVEM B,NTHDSW ;If 2 args, set our reason for going down.
]
SKIPE IMPUP ;Fake up our status
TDZA A,A ;We're down
MOVSI A,2000 ;We are up
;; KLH: "fixed" 11/1/99
;; MOVEI B,IMPUS ;And our host umber
MOVE B,NIFIPA ;And our host number
JRST POPJ1
;NETIMP (REASON,TIMEDOWN,TIMEUP) READ/SET
;
ANETIM: JUMPLE W,ANETM1 ;No args, return current data
CAIGE W,3 ;Must have 3 args if any
JRST OPNL30
MOVEM A,IMPDWN ;Set data
MOVEM B,IMPDWN+1
MOVEM C,IMPDWN+2
JRST POPJ1
ANETM1: MOVE A,IMPDWN ;Get data to return
MOVE B,IMPDWN+1
MOVE C,IMPDWN+2
SKIPE IMPUP ;Note current condition of IMP, too
TLO A,400000
JRST POPJ1