Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
mit/monitor/impphy.mac
There are no other files named impphy.mac in the archive.
;<5.ISI.MONITOR>IMPPHY.MAC.5350 6-Jan-83 17:42:06 Edit by JGOLDBERGER
;#535 Add SKIPE to keep 0 instead of intsec,,0
;[BBNF]<CLYNN.NEW>IMPPHY.MAC.23, 17-Dec-82 17:48:09, Edit by: CLYNN
; Save T1 over IMOSRT in IMPSCK
;<5.ISI.MONITOR>IMPPHY.MAC.5010 22-Oct-82 08:39:46 Edit by JGOLDBERGER
;#501 Version 5 MultiNet
;[BBNF]<TAPPAN.NEW>IMPPHY.MAC.18, 8-Oct-82 12:20:55, Edit by: TAPPAN
; Fix handling of HSTGDM
;<TAPPAN.NEW>IMPPHY.MAC.2, 10-Apr-82 12:59:39, Edit by TAPPAN
; Remove NTBFFL (preparatory for No-NCP mods)
; Added IMPVEC -- Hardware routine vector
;<BBN-4-MONITOR>IMPPHY.MAC.4, 11-Mar-82 10:32:31, Edit by TAPPAN
; Modify IMISRT so IMSCHK is called with PION (so as not to hog
; the machine)
;<BBN-4-MONITOR>IMPPHY.MAC.3, 28-Aug-81 16:01:20, Edit by TAPPAN
; 103: keep PI's off when hacking output Q's to preserve integrity
;<TAPPAN.4>IMPPHY.MAC.3, 22-Aug-80 11:28:13, Edit by TAPPAN
; Removed TELENET
;<TAPPAN.4>IMPPHY.MAC.2, 1-Jul-80 16:11:30, Edit by TAPPAN
; Conversion to Multinet
;[BBNF]<TCP-BBN-4-MONITOR>IMPBBN.MAC.4011, 9-May-80 16:17:53, Ed: PLUMMER
; Make IMISRT call IMPRBF with arg in T2
;[BBNF]<TCP-BBN-4-MONITOR>IMPBBN.MAC.4010, 9-May-80 10:40:26, Ed: PLUMMER
; Merge with Internet version
;
; Various changes between here
;
;<CLEMENTS>IMPPHY.MAC.1, 19-Jul-76 16:18:47, EDIT BY CLEMENTS
;SEPARATED PHYSICAL IMP DRIVER FROM IMPDV.MAC
SEARCH PROLOG,IMPPAR
ND INETN,1
IFG INETN,<SEARCH INPAR>
SEARCH MNTPAR,MONSYM,MACSYM
ND MLCN,0
TTITLE (IMPPHY,IMPPHY,< - PHYSICAL IMP DRIVER FOR IMP10>)
ASCIZ /
IMPPHY
COPYRIGHT (C) 1980,1981,1982,1983 BOLT BERANEK and NEWMAN INC.
/
;;; DEVICE DEFINITION FOR BBN-STANDARD IMP10 INTERFACE
;;; Cono-coni bits
I.IRQ==1B32 ; Input word ready, CONI
I.ORQ==1B28 ; Ready for next output word, CONI
I.ERQ==1B24 ; End of input, CONI
I.NRD==1B22 ; IMP not ready line. CONI
I.ERR==1B21 ; The error flop, Imp has been down. CONI
I.DWN==1B20 ; Imp is now down. CONI
I.PWR==1B19 ; The interface is powered up. CONI
I.GEB==1B23 ; Clear eib, CONO
I.EOM==1B22 ; End of output message, CONO
I.STO==1B21 ; Stop output, CONO
I.NRL==1B20 ; Not Ready-line to IMP, CONO
I.CLR==1B19 ; Clear error flop, CONO
I.IOF==10B27+10 ; E of cono to clear input pi asmt
I.ION==<10+IMPCHN>B27+<10+IMPCHN> ; E of cono to set input pi asmt
I.OOF==10B31 ; E of cono to clear output assmnt
I.OON==<10+IMPCHN>B31 ; E of cono to set output pi asmt
;Device-dependent data for leaders
STY%NP==5 ;Number of Padding words, for H2I NOP
RESCD
;;;
;;; Hardware routine vector
IMPVEC::
NCTVEC(IMPVEC,IMPKIL,NTHKIL) ; Kill hardware
NCTVEC(IMPVEC,IMPINI,NTHINI) ; Init hardware
NCTVEC(IMPVEC,IMPRSS,NTRSRT) ; Restart hardware
NCTVEC(IMPVEC,IMISRT,NTISRT) ; Start input
NCTVEC(IMPVEC,IMOSRT,NTOSRT) ; Start output
NCTVEC(IMPVEC,IMPSCK,NTSCHK) ; Check interface status
;;; Pi dispatch
IMPSV:: PUSH P,P1 ; Save old AC
SKIPA P1,NCTVT ; Get first NCT
IMPSV0: LOAD P1,NTLNK,(P1) ; get next in list
JUMPE P1,IMPSV1 ; No more
LOAD T1,NTDEV,(P1) ; Get device type
CAIE T1,NT.BBN ; IMP10?
JRST IMPSV0 ; No, loop
CALL NTPOLL(P1) ; Check this one out
JRST IMPSV0 ; No this one
POP P,P1 ; Restore P1
UNBRK IMP ; Back from interrupt
;;; Here when no interrupt found
IMPSV1: POP P,P1 ; Restore
RET ; and return
;;; Start input
;;; called from process level when buffers made available and input is off
;;; and from endin processor if more buffers are available
IMISRT:
CALL IMPSCK ; Is the IMP up?
RET ; No, Can't do anything
PIOFF
SKIPE NTIB(P1) ;ALREADY DOING INPUT?
SOSA IMPNFI ;Yes, so don't start another
SOSGE IMPNFI ;IS THERE A BUFFER TO READ INTO?
JRST [AOSG IMPNFI ;IF NOT, CORRECT COUNT AND GIVE UP.
SETOM NOIBFS ; Flag (that failed) if no buffers
PION
RET]
MOVE T2,IMPFRI ;THERE ARE SOME, IT SAYS. GRAB ONE.
CALL CHKBUF ; CHECK OUT BUFFER
JSP CX,IMPFLB ; Free list bad
LOAD T1,NBQUE,(T2) ; Get next free
IFNKA < SKIPE T1 > ; If there's a successor,
SETSEC T1,ANBSEC ; Set section number
MOVEM T1,IMPFRI
SETZRO NBQUE,(T2) ; DeQueue it from any others
MOVEM T2,NTIB(P1)
SETZM NTIS32(P1) ; Flag reading in 36 bit mode
MOVEM T2,NTINP(P1) ; That's the 23-bit address
MOVNI T1,<.NBLD2+1> ; Read thru the IMP leader, and 1 pad word
MOVEM T1,NTIWC(P1) ; That's the count
XMOVEI T1,IMIN0 ; Prepare to accept first words from IMP
MOVEM T1,NTIDSP(P1) ; Here on PI level
PION
MOVEI T1,I.ION+I.CLR ; CLear error and start input
MNTXCT NTCONO ; ..
RET
;;; For subsequent interrupts, a field will steer the packing and counts.
;;; Values are named .IIxxx for Imp Interrupt dispatch. Store in NTITYP(NCT)
;;; and correspondingly in NTOTYP for output side.
.IINC6==0 ;This is a 36 bit NCP message
.IINC2==1 ;This is a 32 bit NCP message
.IITNT==2 ;Telenet link
.IISPQ==3 ;Special queue
.IIINT==4 ;Internet packing
.IIMLC==5 ;MLC (Ptip) format
.IISQ2==6 ;False start INT becomes SPQ later
;;; Pi service for input
;;; Dispatched at IMPSV to various routines via NTIDSP(NCT)
;;; IMPIND - handles 'end input' signal
IMIN0: CALL DOBLKI ; Do extended BLKI
JRST IMIN1 ; Leaders all read.
RETSKP ; More to read
;;; Here when all leader and one word of padding have been read.
IMIN1: MOVE T1,NTIB(P1) ; Get buffer location
LOAD T2,IHLNK,(T1) ; Get link and host numbers
LOAD T3,IHHST,(T1) ; for packing decisions
IFN MLCN,<
MOVEI T4,(T2) ; Half the link field
LSH T4,-1
CAMN T4,MLCHLF ; Match the MLC pair?
JRST IMI1ML ; Yes.
>
IFN INETN,<
CAIN T2,INTLNK ; Internet link?
JRST IMI1IN ; Yes.
>
CAIG T2,LLINK ; Normal NCP and host?
CAIL T2,FKHOST
JRST IMI1SQ ; No. pack in 32 bit mode
IMI1NC: MOVX T4,.IINC6 ; Seems to be an NCP message.
IMIN1A: XMOVEI T2,.NBLD2+1(T1) ; Get pointer to next word to read
MOVEM T2,NTINP(P1) ; For next BLKI pointer
HLRE T2,II1WCT(T4) ; Count, for this type of message
MOVEM T2,NTIWC(P1) ; That's the count for next group
HRRZ T2,II1WCT(T4) ; Build a zero or an AOBJN counter to
HRLS T2 ; see if we want to switch to 32 bit mode
SKIPE T2 ; ...
HRRI T2,^D8(T2) ; Counter. Set initial state.
MOVEM T2,NTIS32(P1) ; Save in core for further interrupts
XMOVEI T3,IMIN2 ; Where to go on next interrupt
MOVEM T3,NTIDSP(P1) ; Save for next int time
MOVEM T4,NTITYP(P1) ; Include type code
RETSKP ; Done this interrupt
IMI1SQ: MOVX T4,.IISPQ ;Special queues
JRST IMIN1A ;Join common code
IFN MLCN,<
IMI1ML: MOVX T4,.IIMLC ;MLC link
JRST IMIN1A ;Join common code
>
IFN INETN,<
IMI1IN: MOVX T4,.IIINT ;Internet link
JRST IMIN1A ;Join common code
>
II1WCT: XWD -2,0 ; TYPE NCP36
XWD -2,0 ; TYPE NCP32
XWD -2,0 ; TYPE TELENET (unused)
XWD -1,-^D8 ; TYPE SPECIAL Q, start 32 bit mode
XWD -5,-^D8 ; TYPE INTERNET, start 32 bit mode
XWD -2,0 ; TYPE MLC
XWD -1,-^D8 ; TYPE SQ2, start 32 bit mode
; Here for BLKI's in second group, after leader.
IMIN2: SKIPE NTIS32(P1) ; Reading 32 bit mode?
JRST [ CALL BLKI32 ; Yes, read and distribute 36 bits
JRST IMIN20 ; Finished
RETSKP] ; More to go
CALL DOBLKI ; Read another word in 36 bit mode
JRST IMIN20 ; Done.
RETSKP ; More to go.
IMIN20: MOVE T1,NTIB(P1) ; Point to buffer being read into
MOVE T4,NTITYP(P1) ; Get the type code for this msg
;;; Padding removal isn't needed if message isn't that long, but it's
;;; cheaper to always remove it than to test for needing to.
DMOVE T2,.NBLD2+2(T1) ; Crunch out the padding
STOR T2,IHPD1,(T1) ; Partial word in .NBLD2
MOVEM T3,.NBHHL(T1) ; and H-H leader to its rightful place
IFN INETN,<
CAIN T4,.IIINT ; Internet link?
CALL INETIN ; Yes. Special routine, may change T4,T1.
>
LOAD T2,NBBSZ,(T1) ; Set up BLKI pointer for rest of msg
MOVE T3,II2LDT(T4) ; Amount of buffer we have used so far
SUBI T2,(T3)
MOVNS T2 ; Negative for BLKI
MOVEM T2,NTIWC(P1) ; That's the next word count
MOVNI T2,2 ; The two fills just removed
ADDM T2,NTINP(P1) ; Subtract from read so far
CAIE T4,.IINC6 ; NCP message?
JRST IMIN2A ; No
LOAD T2,HHSIZ,(T1) ; Yes, see if packing 32 or 8
CAIN T2,^D36 ; Word mode?
JRST IMIN2A ; Yes, continue that way.
MOVEI T4,.IINC2 ; No, switch to 32 bit mode
MOVEM T4,NTITYP(P1) ; Update in core
MOVSI T3,-^D8 ; Start reading in 32 bit mode from here
MOVEM T3,NTIS32(P1)
IMIN2A: XMOVEI T3,IMIN3 ; Dispatch for next interrupts
MOVEM T3,NTIDSP(P1)
RETSKP
;Table of next word to read into at IMIN2 time, by message type
II2LDT: EXP .NBDW0 ;Type NCP36
EXP .NBDW0 ;Type NCP32
EXP .NBDW0 ;Type TELENET
EXP .NBHHL ;Type SPECIAL QUEUES
EXP .NBDW0+2 ;Type Internet
EXP .NBDW0 ;Type MLC
EXP .NBHHL+3 ;Type Special Q - false Internet
IFN INETN,<
; Called from IMIN2 when possible Internet message is coming in.
; This routine does the following:
; 1. Move the 2 remaining H-H words to the right place
; 2. Check for right message type and subtype
; 3. Check for Internet being on
; 4. Check for a Internet-supplied buffer being available
; If any of those conditions is lacking, input is resumed and the
; message is handled as a normal special queue message.
; If the message is really destined for the gateway (TCP, XNET, ...),
; it gets copied into a Internet-supplied buffer and input resumes.
; IMPEIN will then queue it for the gateway.
;T1/ Pointer to current NCP-supplied buffer
;T4/ .IIINT
; CALL INETIN
;Ret+1: Always. T4 set to .IIINT if I.N. msg to be completed, or .IISQ2
; if it will be given to a special Q
INETIN: DMOVE T2,.NBDW0+2(T1) ; Pick up the Internet header
DMOVEM T2,.NBDW0(T1) ; Stash in proper place
MOVE T2,.NBDW0+4(T1) ; And the twelve bits after it
MOVEM T2,.NBDW0+2(T1) ; Which have also been read
LOAD T2,IHFTY,(T1) ; ARPANET message format
LOAD T3,IHMTY,(T1) ; ARPANET message type
CAIN T3,.IHREG ; Regular msg?
CAIE T2,ITY%LL ; Long leader?
JRST INETIC ; No. Let normal code handle it.
LOAD T2,IHSTY,(T1) ; ARPANET subtype
LOAD T3,INPVR,(T1) ; Inet pkt version flag (part of 2.5 net)
CAIE T2,STY%FC ; Normal, flow-controlled?
CAIN T2,STY%UC ; or uncontrolled?
CAIE T3,.INTVR ; And right Internet version?
JRST INETIC ; No. Let normal code handle this.
SKIPG INTNFI ; And there is a Internet buffer around?
JRST INETIC ; No. Let normal special queue have it.
; All is OK for the switch to a Internet buffer. Do it, return the NCP buf.
SOSL INTNFI ; Count down number of free Internet bufs
SKIPN T2,INTFRI ; Get pointer to buffer to use
JSP CX,IMPNIT ; Buffer list fouled
IFN MAXLDR-.NBHHL,<
MOVEI T3,.NBHHL ; real header size
CALL FIXLDR ; correct it
>
PUSH P,T2 ; Save new pointer
XMOVEI T3,.NBLD0(T2) ; "To" -- into Internet buffer
XMOVEI T2,.NBLD0(T1) ; "From" pointer for BLT
HLRE T1,II1WCT(T4) ; Get size of second transfer
MOVNS T1
ADDI T1,.NBHHL-2 ; Compute count (-2 for fill crunch)
CALL XBLTA ; Copy ARPANET and Internet headers
MOVE T1,NTINP(P1) ; Pointer to last read into NCP buffer
SUB T1,NTIB(P1) ; Figure out how many words were read
ADD T1,INTFRI ; Pointer to correspoinding point in Inet pkt
MOVEM T1,NTINP(P1) ; Set new pointer
MOVE T2,INTFRI ; Get the Internet buffer again
LOAD T1,NBQUE,(T2) ; Next Internet free buffer
IFNKA < SKIPE T1 > ; SETSEC might not create an instruction
SETSEC T1,INTSEC
SETZRO NBQUE,(T2) ; Clear list pointer
EXCH T1,INTFRI ; Becomes head of list
POP P,T1 ; restore pointer
EXCH T1,NTIB(P1) ; Old head is now current input bfr
EXCH T1,IMPFRI ; Old input bfr goes to NCP free list
MOVE T2,IMPFRI ; Get copy for indexing
STOR T1,NBQUE,(T2) ; Old list is off of new head
AOS IMPNFI ; There is now another free input bfr
MOVE T1,NTIB(P1) ; Now think in terms of Internet buffer
RET
; Here when current input is to be continued. Fix to be spec. q. input.
INETIC:
;;; SETOM NTFLS(P1) ; Flush message when it gets in
MOVEI T2,.IISPQ ; Mark for special Queue dispatch
MOVEM T2,NTITYP(P1)
MOVEI T4,.IISQ2 ; Return this to caller
RET
> ;End cond on INETN
; Input body of message
IMIN3: SKIPE NTIS32(P1) ; Want 32 bit handling?
JRST IMIN32 ; Yes.
CALL DOBLKI ; No, read 36 more bits
JRST IMIMTL ; Overflowed buffer
RETSKP ; Mostly just wait for the end interrupt
IMIN32: SKIPL NTIWC(P1) ; Room for more?
JRST IM32TL ; Nope, too long. Clear interface
CALL BKI32B ; Read 36 bits into 32 format
JFCL ; Any more bits would be error.
RETSKP ; Ok, wait for more.
IM32TL: MNTXCT NTDATI ; Disgard the bits
IMIMTL: MOVE T4,NTITYP(P1) ; If Internet, this can happen legally
CAIE T4,.IIINT ; Because buffers are shorter.
MNTBUG(INF,IMPML2,<MSG TOO LONG>)
XMOVEI T1,IMIN00
MOVEM T1,NTIDSP(P1)
SETOM NTFLS(P1) ; Flag input overflow
RETSKP
;;; Here when message has been found to be a loser. Just throw it away
;;; until the end input interrupt comes along.
IMIN00: MNTXCT NTDATI ; Just disgard all wds until end input
RETSKP
;;; Routine to do a BLKI in extended address environment. We have two
;;; words, NTINP for the 23 bit address, and NTIWC as a negative count.
DOBLKI: MNTXCT NTDATI ; Get a word
AOS T2,NTINP(P1) ; Count the pointer
MOVEM T1,0(T2) ; Read the bits into core
AOSGE NTIWC(P1) ; Count up the count
AOS 0(P) ; Skip unless overflowed count
RET ; And return from DOBLKI
;;; Routine called if IMIS32 is non-zero. Pack 36 bits into
;;; two words, 32 bits in each.
;;; Two versions. BLKI32 for all but body of message, BKI32B for body.
;;; This is because body may go to last word of 1/2 page buffer, and
;;; in that case you can't do the MOVEM of the last partial word.
BKI32B: TDZA T4,T4 ; Remember entry point
BLKI32: SETO T4,0 ; Remember entry point
PUSH P,T4 ; Save on stack
MNTXCT NTDATI ; DATAI to T1
MOVE T3,NTIS32(P1) ; Get unpacking state word
AOS NTINP(P1) ; Step the data address
AOSGE T4,NTIWC(P1) ; And the word count
AOS -1(P) ; Do skip return if no overflow
TRNN T3,777777 ; Is this the zero'th state?
JRST [ AOS NTINP(P1) ; Yes, step pointers one more
AOS T4,NTIWC(P1)
JRST .+1]
IORM T4,0(P) ; Make stack negative unless overflowed.
MOVEI T2,0 ; Any pad bits should be zero
MOVE T4,NTINP(P1) ; Now point to the data
LSHC T1,@IMISHT(T3) ; Align input bytes with destination
DPB T1,IMIPT1(T3) ; High order byte for n-1st word
SKIPL 0(P) ; Don't overwrite if last word of body.
JRST [ SOS NTINP(P1) ; And don't make a 401 size!
SOS NTIWC(P1)
JRST BKI32C] ; Skip the MOVEM
MOVEM T2,0(T4) ; Low order byte for nth word
BKI32C: POP P,(P) ; Remove flag from stack
AOBJN T3,BKI32A ; Step state
MOVSI T3,-^D8 ; Reinit state word
BKI32A: MOVEM T3,NTIS32(P1) ; Save state
RET ; Return
;;; Tables for 36-32 bit conversion, indexed by state word
IMISHT: XX==4
REPEAT ^D8,<Z -XX
XX=XX+4>
IMIPT1: XX==^D32
REPEAT ^D8,<POINT XX,-1(T4),31
XX=XX-4>
;;; Here when end msg recd from imp
IMPIND::MOVEI T1,I.GEB!I.IOF ; We got the end bit, turn input off
MNTXCT NTCONO ; ...
AOS NTINP(P1) ; Incremnt pointer to 1 past last word read
MNTCALL NTIDUN ; Do Input done stuff
RETSKP ; Done successfully
;;; Routine to start msg going out. Called at PI
;;; level, and at main level if no output in progress
IMOSRT: PIOFF
SKIPN NTOB(P1) ; ANY OUTPUT IN PROGRESS?
JRST IMPXO1 ; NO
PION ; YES, TURN PI BACK ON
RET ; AND RETURN
IMPXO1: SETOM NTOB(P1) ; MARK OUTPUT IN PROGRESS
PION ; NOW IT'S OK TO TURN PI BACK ON
SKIPLE NTNOP(P1) ; Any nop's to send?
JRST IOUNOP ; Yes, go send them
CALL NCPUNQ ; Get next buffer to go out
JRST [ SKIPLE T2,HSTGDM(P1)
JRST IOUHGD ; Send the host going down msg
MOVEI T1,I.STO ; No turn off PI req
MNTXCT NTCONO ; ...
SETZM NTOB(P1)
RET]
MOVEM T1,NTOB(P1)
MOVMS HSTGDM(P1) ; may need another host going down message
SETZRO NBQUE,(T1) ; Remove from any queue
;;; SETZRO IHNET,(T1) ; And network number
;;; Now decide on packing via message type
LOAD T2,IHHST,(T1) ;Check host and link for NCP range
LOAD T3,IHLNK,(T1)
IFN MLCN,<
MOVEI T4,(T3) ;Get link
LSH T4,-1
CAMN T4,MLCHLF ;PTIP link?
JRST [ MOVEI T3,.IIMLC ;Yes. pack in 36 bit mode
JRST IMPIOD]
>
IFN INETN,<
CAIN T3,INTLNK ; Internet?
JRST [MOVEI T3,.IIINT ; Internet. Set packing mode
JRST IMPIOD]
>
CAIGE T2,FKHOST ;Special to-imp group?
CAILE T3,LLINK ;Or link out of range?
JRST [ MOVEI T3,.IISPQ ;Yes, special queue formatting.
JRST IMPIOD]
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
IMPIOD: MOVEM T1,NTOUP(P1)
MOVNI T1,<.NBLD2+1> ; Send up thru first fill wd in 36-bit
MOVEM T1,NTOWC(P1) ; Here's the count
XMOVEI T1,IMOLDR ; Where to go in out-done int level
MOVEM T1,NTODSP(P1) ; Setup dispatch
MOVEM T3,NTOTYP(P1) ; Here's the dispatch type
SETZM NTOS32(P1) ; Flag to send in 36 bit mode
MOVE T1,TODCLK ; Get time now
ADDI T1,^D60*^D1000 ; One minute timeout
MOVEM T1,NTTOUT(P1) ; Set it
CALL DOBLKO ; Send first word (always 36-bit)
JFCL
RET
;;; Pi service for output
IMOLDR: SKIPL NTOWC(P1) ; All done?
JRST IMOLD1 ; Yes, send some padding
IMO36B: CALL DOBLKO ; Send another word
JFCL
RETSKP
IMOLD1: MOVE T1,NTOB(P1) ; Point to buffer
XMOVEI T2,.NBHHL-1-1(T1) ; Get address of buffer, resend a word
; as padding
MOVE T4,NTOTYP(P1) ; Get the packing procedure
MOVEM T2,NTOUP(P1) ; Now send these words
HLRE T2,IO1WCT(T4) ; And select a word count for output
MOVEM T2,NTOWC(P1) ; This is the count
HRRZ T2,IO1WCT(T4) ; See if should switch to 32 bit mode
HRLS T2
SKIPE T2 ; Skip if staying in 36 bit mode
HRRI T2,^D8(T2) ; In 32 bits, make AOBJN counter
MOVEM T2,NTOS32(P1) ; Set packing state word
XMOVEI T2,IMOLD3 ; Here on next interrupt
MOVEM T2,NTODSP(P1)
JRST IMO362 ; Send the first one, 36 or 32 bits
IMOLD3: SKIPGE NTOWC(P1) ; Send all the second group?
JRST IMO362 ; No, send some more.
MOVE T1,NTOB(P1) ; Point to data buffer
MOVE T4,NTOTYP(P1) ; Get packing procedure
LOAD T2,NBBSZ,(T1) ; Set up BLKO pointer
MOVE T3,IOLDT(T4) ; How many sent already?
SUBI T2,(T3) ; Allow for sent words in count
MOVNM T2,NTOWC(P1) ; Count is negative for BLKO
MOVSI T3,-^D8 ; May need to set packing state
CAIN T4,.IINC2 ; If NCP 32 bit message,
MOVEM T3,NTOS32(P1) ; Switch to 32 bit mode here.
XMOVEI T3,IMOBDY ; For next interrupts, go here.
MOVEM T3,NTODSP(P1) ; Set in core dispatch
JRST IMO362 ; Now go send a word in 36 or 32 mode.
IO1WCT: XWD -2,0 ; TYPE NCP36
XWD -2,0 ; TYPE NCP32
XWD -2,0 ; TYPE TELENET
XWD -1,-^D8 ; TYPE SPECIAL Q, start 32 bit mode
XWD -1,-^D8 ; TYPE INTERNET, start 32 bit mode
XWD -2,0 ; TYPE MLC
XWD -1,-^D8 ; TYPE SQ2, start 32 bit mode
;Table of number of words already sent, at IMOLD3 time
IOLDT: EXP .NBDW0 ;Type NCP36
EXP .NBDW0 ;Type NCP32
EXP .NBDW0 ;Type TELENET
EXP .NBHHL ;Type SPECIAL QUEUES
EXP .NBHHL ;Type Internet
EXP .NBDW0 ;Type MLC
EXP .NBHHL ;Type SQ2
; Output body of message, in 32 or 36 bit mode
IMOBDY: SKIPL NTOWC(P1) ; Data left?
JRST IMODN1 ; No
TDZA T1,T1 ; Flag this is last part of buffer
IMO362: SETO T1,0 ; Flag this isn't last part of buffer
SKIPN T3,NTOS32(P1) ; In 32 bit mode?
JRST IMO36B ; No, send 36 bits.
IMO32: AOS T4,NTOUP(P1) ; Get pointer to data, step it
MOVE T3,NTOS32(P1) ; Get state word
AOSL NTOWC(P1) ; Count the count. Check end.
JRST [ MOVEI T2,0 ;Pad bits are zero, if from BDY
JUMPE T1,IMO32B ; If from BDY, don't load T2
JRST .+1] ; If in leaders, load T2
MOVE T2,1(T4) ; Get n+1th word
IMO32B: MOVE T1,0(T4) ; Get nth word
LSH T1,-4 ; Align high-order byte
LSHC T1,@IMOSHT(T3) ; Shift bytes into output word
MNTXCT NTDATO ; DATAO T1
AOBJN T3,IMO32A ; Step state
AOS NTOUP(P1) ; Extra inc of bfr each cycle
AOS NTOWC(P1) ; The count, too.
MOVSI T3,-^D8 ; Reinit state word
IMO32A: MOVEM T3,NTOS32(P1) ; Save state word
RETSKP
; Table for 32-36 bit conversion, indexed by state word
IMOSHT: XX==4
REPEAT ^D8,<Z XX
XX=XX+4>
IMODN1: MNTCALL NTODUN ; Do output done stuff
IMOIR2: MOVEI T1,I.EOM ; Tell IMP thats all
MNTXCT NTCONO ; Send it out
XMOVEI T1,IMODN2 ; Setup dispatch for final step
MOVEM T1,NTODSP(P1)
RETSKP
IMODN2: SETZM NTTOUT(P1) ; Clear output hung timeout
SETZM NTOB(P1)
CALL IMOSRT ; Start next msg if any
RETSKP
;
; Here to make a HOST GOING DOWN message
; HSTGDM is 0 if not going down, +N if needs to be sent
; -N if doesn't
IOUHGD: MOVEI T3,0 ; Set up 2 words of data
LSHC T2,-^D8 ; From down-time and reason
DMOVEM T2,IIMBUF+1 ; In a scratch buffer
MOVE T1,H2IHGD ; Proto Host-Going-Down msg
MOVEM T1,IIMBUF ; To the scratch buffer
XMOVEI T2,IIMBUF-1 ; Point to this msg
MOVNS HSTGDM(P1) ; down message sent
JRST IOUIRG ; And go send it.
IOUNOP: SOS NTNOP(P1) ; Decrement count of NOP's to send
XMOVEI T2,H2INOP-1 ; Prototype of a NOP/padding request
IOUIRG: MOVEM T2,NTOUP(P1) ; Set for further BLKO's
MOVNI T2,3 ; And the count for each
MOVEM T2,NTOWC(P1)
MOVE T1,TODCLK ; Get time
ADDI T1,^D1000 ; Timeout in one second
MOVEM T1,NTTOUT(P1) ; get timeout
XMOVEI T1,IMOIRG
MOVEM T1,NTODSP(P1)
CALL DOBLKO ; Now send first word of irreg msg
JFCL
RET ; and done
IMOIRG: SKIPL NTOWC(P1) ; Any more words?
JRST IMOIR2 ; No. Send end-of msg
JRST IMO36B ; Same as during leader. Send a word.
;;; Prototype Host-to-Imp NOP msg, with padding control.
H2INOP: BYTE (4)0,ITY%LL (16)0 (8).IHNOP (4)0
EXP 0
BYTE (4)0,STY%NP ; Desired padding amount
;;; Prototype Host-to-IMP Host-going-down message.
H2IHGD: BYTE (4)0,ITY%LL (16)0 (8).IHHGD (4)0 ;1-36
; BYTE (4)0 (24)0 (3)DAY-OF-WK (5)HOUR ;37-72
; BYTE (4)5MIN, REASON
;;; DOBLKO routine to do BLKO-ish stuff in multi-section environment
DOBLKO: PUSH P,T1 ; Save an AC
AOS T1,NTOUP(P1) ; Step the address pointer
MOVE T1,0(T1) ; Get word
MNTXCT NTDATO ; Send it out
AOSGE NTOWC(P1) ; Count the word count
AOS -1(P) ; Skip return if not overflowed
POP P,T1 ; Restore the AC
RET
;STATUS CHECK SUBROUTINES
IMPSCK: SKIPN NTRDY(P1) ; Hardware on?
RET ; no, error
PUSH P,T1 ; Save T1
MOVEI T1,I.PWR ; Power on?
MNTXCT NTCNSO ; ?
SETOM NTERRF(P1) ; No
MOVEI T1,<I.DWN+I.NRD+I.ERR> ;OK, IMP DOWN NOW OR RECENTLY?
MNTXCT NTCNSZ ; ?
SETOM NTERRF(P1) ; FLAG ERROR
SKIPL NTERRF(P1) ; DID ERROR HAPPEN NOW OR BEFORE?
JRST [ POP P,T1
RETSKP] ;NO, IT'S UP. SKIP RETURN
MOVNI T1,2
MOVEM T1,NTFLS(P1)
MOVEI T1,10
MOVEM T1,NTNOP(P1) ; Send some nops
MOVEI T1,I.CLR ; Clear error flop
MNTXCT NTCONO ; ...
CALL MNTWAK ; Wake up hardware fork
CALL IMOSRT ; Start NOP's going
POP P,T1
RET
;;; HERE FROM DOWN-SEQUENCE PROCESSING IN MAINTENANCE TO COMPLETELY
;;; SHUT OFF THE HARDWARE DEVICE
IMPKIL: MOVEI T1,I.STO!I.IOF!I.OOF!I.NRL
MNTXCT NTCONO ;STOP OUTPUT, TURN OFF INPUT AND
; OUTPUT SECTIONS, DROP READY LINE.
RET
;;; CALL HERE FROM IMPIN0 (ONLY FROM MAINTENANCE) AT INITIALIZATION OF
;;; BACKGROUND FORK - NOT ON EVERY RECYCLE OF READY LINE.
IMPINI: XMOVEI T1,IMIN00 ;RESET DISPATCHES
MOVEM T1,NTIDSP(P1) ;INPUT PI DISPATCH TO DISCARD DATA
XMOVEI T1,IMODN2 ;OUTPUT PI DISPATCH TO START NEW MSG
MOVEM T1,NTODSP(P1)
RET
;;; CALL HERE FROM MAINTENANCE, PROCESS LEVEL, WHEN IMP IS WANTED UP
;;; BUT NET IS CURRENTLY DOWN.
IMPRSS: SETZM NTTOUT(P1) ; Clear timout counter
MOVEI T1,I.PWR ; Power on?
MNTXCT NTCNSO ; ?
RET
MOVEI T1,I.NRD
MNTXCT NTCNSZ ; OK, IMP DOWN NOW OR RECENTLY?
RET ; No, stop here
MOVEI T1,I.CLR ; Clear
MNTXCT NTCONO
SETZM NTERRF(P1) ; And notices of errors
SETZM HSTGDM(P1) ; and down messages
HRRES NETON(P1) ; Forget any intervening down requests
MOVNI T1,2
MOVEM T1,NTFLS(P1) ; Init flush count
MOVEI T1,10
MOVEM T1,NTNOP(P1)
MOVEI T1,^D1000
DISMS ; Allow time for ready line to settle
AOS NTSTCH(P1) ; Cause change in state to be noted
CALL MNTWAK ; Wake up hardware fork
GTAD ; Yes
MOVEM 1,NTXUPT(P1) ; Save time whe it came up
MNTXCT NTDATI ; Helps to clear interface
MOVEI T1,I.STO+I.GEB
MNTXCT NTCONO
MOVEI T1,I.OON
MNTXCT NTCONO
SETOM NTRDY(P1)
SETOM NTORDY(P1) ; Allow output
CALL IMOSRT ; Start output if needed
CALLRET IMISRT ; And input
TNXEND
END ; OF IMPPHY