Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_3_19910112
-
mit/monitor/nfephy.mac
There are no other files named nfephy.mac in the archive.
;<BBN-4-MONITOR>CNTPHY.MAC.17, 10-Apr-82 13:55:10, Edit by TAPPAN
; Add NFEVEC -- Hardware dependent dispatch vector
; Change name to NFEPHY (General network front end)
;<TAPPAN.4>CNTPHY.MAC.2, 28-Feb-82 19:21:39, Edit by TAPPAN
; rescind the previous edit, since we can't call
; NETHSH at interrupt level (should fix that)
;<BBN-4-MONITOR>CNTPHY.MAC.16, 23-Feb-82 20:15:17, Edit by TAPPAN
; Call INTUP and INTDWN when interface goes up or down
;<BBN-4-MONITOR>CNTPHY.MAC.14, 8-Feb-82 12:08:35, Edit by TAPPAN
; Change inefficent code at CNOSRT
;<BBN-4-MONITOR>CNTPHY.MAC.13, 9-Dec-81 13:07:08, Edit by TAPPAN
; Increase maximum packet size we can send to 1024.
;<BBN-4-MONITOR>CNTPHY.MAC.11, 28-Aug-81 16:05:38, Edit by TAPPAN
;103: Keep PI's off while hacking output Q's to preserve integrity
;<BBN-4-MONITOR>CNTPHY.MAC.3, 20-Jul-81 18:40:29, Edit by TAPPAN
; use LGTAD (resident) instead of GTAD% (swappable) to find time
;<MULTINET-MONITOR>CNTPHY.MAC.50, 8-Jun-81 19:59:40, Edit by TAPPAN
; Allow 8 or 16 byte transfers across the DTE under MODE16 conditional
SEARCH PROLOG,PROKL,MONSYM,MACSYM,INPAR,MNTPAR,IMPPAR
TTITLE NFEPHY,,<Driver for Network front-end DTE on Multinet>
;;; Dan Tappan
ASCIZ /
NFEPHY
COPYRIGHT (C) 1981,1982 BOLT BERANEK and NEWMAN INC.
/
;;;
;;; This impliments a device driver suitable for sending Internet packets
;;; out over a DTE to a front-end 11 (hooked up to Cheapnet or otherwise)
;;; that is compatable with Multinet conventions
;;;
;;;
;;; 10<->11 protocal used
;;;
;;; When one of the machines restarts, it clears the up bit in it's
;;; status word, and rings the other's doorbell, when the other recieves
;;; this, it reinitializes whatever is necessary, and sets it's
;;; ACK bit, and rings back. When the first recieves this it sets it's up bit
;;; clears the other's ACK bit, and allows I/O
;;;
;;; If one machine has a packet to send to the other, then it sets the REQOT
;;; bit in it's status word, and the size of the packet in bytes in the
;;; low eight bits, and rings the other's doorbell, this does what is
;;; necessary to receive, interrupting both on completion
;;;
;;; Definitions
MODE16==1 ; Non-zero if 16 bit transfers across the DTE
DEFSTR PKSIZ,,35,12 ; Size of packet to transfer
DEFSTR REQOT,,20,1 ; Output request bit
DEFSTR UPBIT,,21,1 ; Machine is up
DEFSTR AKBIT,,22,1 ; Restart acknowledge
MAXPKL==^D1024 ; Maximum packet length (bytes) we allow
BYTSIZ==^D8 ; Size of transfers across the DTE
WRDDIV==4 ; Divisor, #bytes -> #words(PDP10)
IFN MODE16,<
MAXPKL==MAXPKL/2
BYTSIZ==BYTSIZ*2
WRDDIV==2
> ; If word mode
SIZMSK==7777 ; 12 bits of packet size
;;; Address's of DTE block
;;; DTEINT and DTEEPW are globals
;;; DTEINT==:KIEPT+142 ; Interrupt location
;;; DTEEPW==:KIEPT+144 ; Examin protection word
;;; DTEERW==:KIEPT+145 ; Examine relocation word
;;; DTEDPW==:KIEPT+146 ; Deposit protection word
;;; DTEDRW==:KIEPT+147 ; Deposit relocatiopn word
;;; DTEEBP==:KIEPT+140 ; To 11 byte pointer
;;; DTETBP==:KIEPT+141 ; To 10 byte pointer
;;; CONO STUFF
;;; (Some of these bit definitions are in PROKL)
;;;
LDTEPI==DTEPI0+DTEPIE+IMPCHN ; Enable all interrupt
CLTO10==40 ; Clear input done bits
CLTO11==100 ; clear output done bits
RSTDTE==DTETDB+CLTO10+CLTO11 ; Reset relevant bits
;;;
;;; Header -- First word is link/size,
;;; the second word describes the type of packet.
;;; if > 2^24 then packet is an internet packet, header word is the
;;; internet address of the interface it was received on (11 -> 10)
;;; or the Internet address of the immediate destination (10->11)
;;;
;;; if the first byte if 0 then the next byte encodes the packet type
;;; further as:
;;; 0 -- NOP
;;; 1 -- Raw network packet, third byte is the interface number.
;;; 2 -- Interface reset. Byte 3 is the interface number,
;;; byte 4 is the network type code. If this command is sent
;;; from the 11 to the 10 then the packet data is the local address
;;; of the interface (size depends on the network type).
;;; If sent from the 10 to the 11 the first 32 bits of data are
;;; the internet address to be used on that front-end.
;;; 3 -- Address error (Interface unreachable). Probably only
;;; 11 -> 10. If the 3rd byte is 255 then the first 32 bits of data
;;; are the Internet address that can't be reached, otherwise
;;; it is the interface number that is not-usable
;;;
;;; Command codes
C%NOP==0
C%RPKT==1
C%IRST==2
C%AERR==3
.NFEDH==1 ; Destination host word
.NFEHL==2 ; length of header
DEFSTR PKTNET,.NFEDH,7,8 ; Non-zero if internet address
DEFSTR PKTCMD,.NFEDH,15,8 ; Command byte in word
DEFSTR PKTINN,.NFEDH,23,8 ; Interface number
DEFSTR PKTITY,.NFEDH,31,8 ; Network type
;;;
;;; Driver routines
RESCD
;;; Protocal vector
NFEVEC::
NCTVEC(NFEVEC,RSKP,NTPKIL) ; Protocal specific kill function
NCTVEC(NFEVEC,R,NTPERR) ; Protocal specific error handler
NCTVEC(NFEVEC,NFEEIN,NTIDUN) ; Done with input
NCTVEC(NFEVEC,INTODN,NTODUN) ; Done with input
NCTVEC(NFEVEC,INTFBF,NTRBUF) ; Flush a buffer
NCTVEC(NFEVEC,RSKP,NTOTOK) ; Output allowed check
NCTVEC(NFEVEC,NFEHDR,NTLLDR) ; Local leader routine
NCTVEC(NFEVEC,ININFE,NTPINI) ; protocal initialization
;;; Functions from the above
;;;
;;; Protocal specific initialization
;;;
ININFE: MOVEI T1,.NFEHL ; Size of "local leader
MOVEM T1,NTHDRL(P1) ; set it
RET ; and return
;;;
;;; NFEHDR -- Network front-end header.
;;; Called
;;; T1 -- Local destination address
;;; T2 -- buffer
;;;
NFEHDR:
IFN MAXLDR-.NFEHL,<
MOVEI T3,.NFEHL ; Size of our header
CALL FIXLDR ; Fix the leader size
>
LSH T1,4 ; left justify
MOVEM T1,.NFEDH(T2) ; Save the local destination
RET
;;;
;;; NFEEIN -- End of input handler
;;; Called P1 -- pointer to physical NCT
;;; NTIB(P1) completed buffer
;;;
NFEEIN:
MOVE T2,NTIB(P1) ; Get input buffer
JE PKTNET,(T2),NFEEI1 ; If Internet packet
MOVNI T3,.NFEHL ; Size to correct by
CALL FIXLDR ; ...
MOVEM T2,NTIB(P1) ; Set new address
CALLRET INTEIN ; Give packet to the internet
;;; Here if packet contains a function
NFEEI1: LOAD T1,PKTCMD,(T2) ; Get command
CAIL T1,MAXFCN ; Good?
MNTBUG(HLT,NFEBFN,<Bad function code from network FE>,<<T2,CODE>,<P1,NCT>>)
CALL @FCNTAB(T1) ; Dispatch
MOVE T2,NTIB(P1) ; get buffer
CALL INTFBF ; release it
SETZM NTIB(P1) ; CLear
CALLRET NFISRT ; Start input again if possible
;;; Function table
FCNTAB: IFIW!R ; NOP
IFIW!R ; Raw network packet
IFIW!NFEIUP ; Interface up
IFIW!NFENXI ; Interface non-existant
MAXFCN==.-FCNTAB
;;;
;;; Handle an "Interface up" message
;;; packet contains the type and address of the interface
;;;
;;; This should probably check the given address
;;; against the NCT's, and complain if different.
;;; Also if type is Ethernet, then should reply with
;;; a "set interface address" with the correct
;;; internet address.
NFEIUP: RET ; Nothing for now
;;;
;;; Handle a "Net unreachable" message
;;;
NFENXI: MOVE T3,.NFEHL(T2) ; get the address
LSH T2,-4 ; right justify
NETNUM T2,T3 ; and it's network number
XMOVEI T1,[ LOAD T1,NTNET,(P1) ; Get net
CAME T1,T2 ; Same?
RET ; no
SETZM NETON(P1) ; Mark the network down
CALL MNTWAK ; Wake up hardware fork
RET] ; and return
CALL VNCTFN ; Apply to the NCT's
RET
;;;
;;; Hardware vector
DTEVEC::
NCTVEC(DTEVEC,NFEKIL,NTHKIL) ; Hardware kill
NCTVEC(DTEVEC,NFEINI,NTHINI) ; Initialization
NCTVEC(DTEVEC,NFERSS,NTRSRT) ; Hardware restart
NCTVEC(DTEVEC,NFISRT,NTISRT) ; Input start
NCTVEC(DTEVEC,NFOSRT,NTOSRT) ; Output start
NCTVEC(DTEVEC,NFESCK,NTSCHK) ; Status check
SWAPCD
;;; NFEINI - Initialize an interface
NFEINI: XMOVEI T1,NFEINT ; Get our interrupt locaion
MOVEM T1,NTIDSP(P1) ; Set dispatch address
MOVE T1,NTCONO(P1) ; Get an I/O instruction
LSH T1,-^D23 ; Sift over to get
ANDI T1,170 ; Ofset into DTE area
MOVEM T1,NTDTEN(P1) ; Save it here
MOVEI T2,NT10ST(P1) ; Point to 10's status word
MOVEM T2,DTEERW(T1) ; Set examine relocation
MOVEI T2,NT11ST(P1) ; Point to 10's status word
MOVEM T2,DTEDRW(T1) ; Set deposit relocation
MOVEI T2,2 ; Size of region
MOVEM T2,DTEDPW(T1) ; Set for deposit region
MOVEI T2,1
MOVEM T2,DTEEPW(T1) ; And examine
MOVE T2,NTIINT(P1) ; Get interrupt instruction
MOVEM T2,DTEINT(T1) ; Store in DTE block
MOVE T1,[XWD .RESP3,MAXPKL/WRDDIV+2] ; Priority,, Size of buffer
MOVX T2,.RESGP ; From general pool
CALL ASGRES ; Assign it
JSP CX,NOBUFF ; No buffer
HRLI T1,(<POINT BYTSIZ,0>) ; Make into a byte pointer
MOVEM T1,NTINP(P1) ; Save
MOVE T2,NTDTEN(P1) ; ge back DTE index
MOVEM T1,DTETBP(T2) ; Set in block
MOVE T1,[XWD .RESP3,MAXPKL/WRDDIV+2] ; Again for output side
MOVX T2,.RESGP
CALL ASGRES
JSP CX,NOBUFF
HRLI T1,(<POINT BYTSIZ,0>)
MOVEM T1,NTOUP(P1) ; And save it for later also
MOVE T2,NTDTEN(P1)
MOVEM T1,DTEEBP(T2) ; ...
SETZM NTIB(P1) ; Clear buffers
SETZM NTOB(P1) ; ...
JRST NFERSS
;;; Here if insufficent storage for I/O buffers
NOBUFF: MNTBUG(HLT,NFENBF,<No storage for Fibernet buffers>,<<CX,D>>)
RESCD
;;; Here when restarting
NFERSS: SETZM NT10ST(P1) ; Clear status word
SETZM NT11ST(P1) ; And init the 11 side also
NFERS1: CALL CLROB ; Flush any output buffer
CALL CLRIB ; and input
SETZM NTORDY(P1) ; Output not allowed yet
MOVX T1,RSTDTE ; Get initializing bits
MNTXCT NTCONO ; And CONO them
MOVX T1,LDTEPI ; And PI bits also
MNTXCT NTCONO ; And CONO Them also
CALLRET RNGBEL ; And ring the 11's doorbel
;;;
;;; NFISRT - Start input routine
;;;
NFISRT: JE REQOT,<+NT11ST(P1)>,R ; Return if no input
SKIPE NTIB(P1) ; anything going?
RET ; yes, null also
SOSGE INTNFI ; Any input buffers?
AOSA INTNFI ; no
CAIA ;
JRST NFEINB ; error, defer processing
PIOFF ; Turn interrupts off
SKIPN T1,INTFRI ; Get next buffer
MNTBUG(HLT,NFBDIB,<Internet input queue fouled>)
LOAD T2,NBQUE,(T1) ; get next buffer
SKIPE T2
SETSEC T2,INTSEC ;Put inproper section if exists
MOVEM T2,INTFRI ; Put queue back
PION ; Allow inetrrupts again
SETZRO NBQUE,(T1) ; clear the queue word
IFN MAXLDR-.NFEHL,<
MOVE T2,T1 ; Point to the packet
CAML T2,[XWD INTSEC,1000] ; Valid buffer?
CAMLE T2,[XWD INTSEC,-1] ; ?
MNTBUG(HLT,INTGBB,<Got bad Internet buffer>)
MOVEI T3,.NFEHL ; Get header length
CALL FIXLDR ; Correct for it
>
EXCH T2,NTIB(P1) ; Save final buffer
JUMPN T2,CLROB1 ; If something else snuck in, free buffer
SETZRO REQOT,<+NT11ST(P1)> ; Clear request bit
MOVE T1,NTDTEN(P1) ; Get DTE block offset
MOVE T2,NTINP(P1) ; And input byte pointer
MOVEM T2,DTETBP(T1) ; Set in block
LOAD T1,PKSIZ,<+NT11ST(P1)> ; Get input size in bytes
CAILE T1,MAXPKL ; Valid size?
JRST NFEDE2 ; No, error
MOVNS T1 ; Get negative
ANDI T1,SIZMSK ; Round to 12 bits
TXO T1,1B23 ; Interrupt both on completion
MNTXCT NTDATO ; Do DATAO
RET ; Return
NFEINB: AOS INTFLG ; make gateway get more buffers
CALL MNTWAK ; Wake up hardware fork
RET
NFEDE2: MNTBUG(CHK,NFEIBG,<Input packet too big>)
CALLRET NFERSS ; Re-sync us
;;;
;;; NFOSRT - Start output routine
;;;
NFOSRT: PIOFF ; No interrupts
SKIPN NTOB(P1) ; Anything going now?
JRST NFOSR1
PION ; Allow interrupts again
SKIPN T1,NTTOUT(P1) ; get timeout
RET ; None set
SUB T1,TODCLK ; subtract "now"
JUMPL T1,NFERSS ; hung
RET ; return
NFOSR1:
SKIPE T2,NTIOBO(P1) ; Anything waiting?
JRST NFOSR2 ; Yes
PION ; 103: nothing waiting
SETZM NTOB(P1) ; Nothing waiting
RET
NFOSR2: LOAD T1,NBQUE,(T2) ; Get next in list
JUMPN T1,NFOSR3 ; Something there
SETZM NTIOBI(P1) ; clear input list also
CAIA
NFOSR3: SETSEC T1,INTSEC ; Put pointer in right section
MOVEM T1,NTIOBO(P1) ; Save pointer to next buffer
MOVEM T2,NTOB(P1) ; Save current output pointer
PION ; 103: Q's safe now, give back machine
SETZRO NBQUE,(T2) ; clear the link
LOAD T1,NBBSZ,(T2) ; Get number of words in buffer
SOS T1 ; Minus the link word
CAILE T1,MAXPKL/WRDDIV+1 ; Valid size?
MNTBUG(CHK,NFBGOT,<Output buffer too big>)
MOVE T3,T1 ; Save count
ASH T1,WRDDIV/2 ; Convert to number of bytes
STOR T1,PKSIZ,<+NT10ST(P1)> ; Set count
MOVE T1,T3 ; get size again
XMOVEI T2,.NFEDH(T2) ; point to the actual message
HRRZ T3,NTOUP(P1) ; Get dest ponter
CALL XBLTA ; Transfer down to section 0
MOVE T2,NTOUP(P1) ; Get pointer
MOVE T1,NTDTEN(P1) ; Get DTE offset
MOVEM T2,DTEEBP(T1) ; Set as byte pointer
MOVE T1,TODCLK ; get clock now
ADDI T1,^D1000 ; Set one second timeout
MOVEM T1,NTTOUT(P1) ; In NCT
SETONE REQOT,<+NT10ST(P1)> ; Request output
CALLRET RNGBEL ; Ring the bell
;;;
;;; NFEINT - Interrupt handler routine, Called from NCT with all AC's saved
;;;
NFEINT: MOVX T1,DTETDN!DTETER ; Input done?
MNTXCT NTCNSZ ; ?
JRST NFEIDN ; yes
MOVX T1,DTEEDN ; To 11 done?
MNTXCT NTCNSZ ; ?
JRST NFEODN ; Output done
MOVX T1,DTEEER ; To 11 error?
MNTXCT NTCNSZ ; ?
JRST NFERTX ; Yes, resend packet
MOVX T1,DTETDB ; Check doorbell
MNTXCT NTCNSZ ; ?
JRST NFETDB ; Yes, check it out
MNTBUG(HLT,NFEBDI,<Bad interrupt>)
;;; Here on to 11 done
NFEODN:
SKIPN NTOB(P1) ; really doing output?
JRST NFEOD1 ; no
MNTCALL NTODUN ; Do output done
NFEOD1: MOVX T1,CLTO11 ; Clear to 11 done bits
MNTXCT NTCONO
JRST NFOSRT ; Keep output moving
;;; Here on to 10 done
NFEIDN: SKIPN T3,NTIB(P1) ; Were we doing input?
JRST [ MNTBUG(CHK,NFEBII,<Bad Input Interrupt>)
JRST NFEIDX] ; Exit routine
MOVX T1,DTETER ; To 10 error?
MNTXCT NTCNSZ ; ?
JRST NFEID1 ; Yes, ignore it
MOVE T2,NTDTEN(P1) ; Get DTE offset
HRRZ T1,DTETBP(T2) ; Get final pointer
HRRZ T2,NTINP(P1) ; Get original
SUBI T1,-1(T2) ; Get packet size (in words)
PUSH P,T1 ; Save size
PUSH P,T3 ; And address
XMOVEI T3,1(T3) ; point one past the header
CALL XBLTA ; Transfer packet up to section 6
POP P,T3 ; Restore address
POP P,T1 ; And size
MOVEM T1,(T3) ; Set buffer size
MNTCALL NTIDUN ; Input done processing
NFEIDX: MOVX T1,CLTO10 ; Clear input bits
MNTXCT NTCONO ; With the appropriate CONO
CALLRET NFISRT ; In case there's another waiting
;;; Here on input error
NFEID1: MNTXCT NTCONI ; get the error bits
MNTBUG(INF,NFEIER,<Network front end input error>,<<T1,BITS>,<P1,NCT>>)
CALL CLRIB ; Clear input buffer
JRST NFEIDX ; And exit
;;;
;;; NFETDB - 10 doorbell handler
;;;
NFETDB: JN UPBIT,<+NT11ST(P1)>,NFEDB0 ; Up bit set?
SETONE <AKBIT,UPBIT>,<+NT10ST(P1)> ; Set our ack bit
CALL NFERS1 ; reset all
CALL LGTAD ; Get time of date
MOVEM T1,NTXUPT(P1) ; as when he came up
SETOM NTRDY(P1) ; Hardware is working
AOS NTSTCH(P1) ; Log a change of state
CALL MNTWAK ; Wake up hardware fork
JRST DBELLX ; Exit routine
;;; Here on response to ACK
NFEDB0: JN UPBIT,<+NT10ST(P1)>,NFEDB1 ; Has our upness been acked?
JE AKBIT,<+NT11ST(P1)>,NFEDBE ; He's not acking, error
SETZRO AKBIT,<+NT11ST(P1)> ; Zero ACK bit
SETONE UPBIT,<+NT10ST(P1)> ; Set our upbit
SETOM NTORDY(P1) ; And allow output
SETOM NTRDY(P1) ; Flag hardware working
CALL LGTAD ; Get time of date
MOVEM T1,NTXUPT(P1) ; as when he came up
AOS NTSTCH(P1) ; indicate change in state
CALL MNTWAK ; signal hardware fork
SKIPA ; Skip error
NFEDBE: MNTBUG(CHK,NFENAK,<Input before Ack>)
CALL RNGBEL ; Bong on him again
JRST DBELLX ; And exit
NFEDB1: SETOM NTORDY(P1) ; Output is allowed at this point
CALL NFOSRT ; Do output if possible
JE REQOT,<+NT11ST(P1)>,DBELLX ; Does he want to start output?
SKIPN NTIB(P1) ; Was input happening?
IFSKP.
MNTBUG(CHK,NFEMIN,<Input request while input in progress>)
CALL NFERSS ; Reset and resync
ELSE.
CALL NFISRT ; start it coming
ENDIF.
DBELLX: MOVX T1,DTETDB ; Clear the doorbell
MNTXCT NTCONO ; With cono
RET
;;;
;;; CLROB - Free up output buffer
;;;
CLROB: SKIPN T2,NTOB(P1) ; Get output buffer
RET ; Return now if nothing there
SETZM NTOB(P1) ; Flush buffer
SETZM NTTOUT(P1) ; Clear the timeout
CLROB1: CALLRET INTFBF ; free the buffer
;;; CLRIB - Free input buffer
CLRIB: SKIPN T2,NTIB(P1) ; Anything there?
RET ; no
SETZM NTIB(P1) ; zero flag
JRST CLROB1 ; free it
;;;
;;; NFERTX - Here on a to 11 error, clear error and try again
;;;
NFERTX: MNTXCT NTCONI
MNTBUG(INF,NFEOER,<Network FE Output error>,<<T1,BITS>,<P1,NCT>>)
MOVE T1,NTDTEN(P1) ; Get offset
MOVE T2,NTOUP(P1) ; Get pointer
MOVEM T2,DTETBP(T1) ; reset pointer
SETONE REQOT,<+NT10ST(P1)> ; Reset request bit
MOVX T1,DTEEER!DTEEDN ; Clear to 11 error
MNTXCT NTCONO ; ....
CALLRET RNGBEL ; Ring bell again
;;;
;;; RNGBEL - Ring 11's doorbel
;;;
RNGBEL: MOVX T1,DTEEDB ; Proper bit
MNTXCT NTCONO ; Zap it
RET ; and return
;;;
;;; NFESCK - Status check routine,
;;; skips if interface is alright
;;;
;;; Called with P1 - Pointer to NCT
NFESCK: JE UPBIT,<+NT11ST(P1)>,R ; If 11 is not up
JE UPBIT,<+NT10ST(P1)>,R ; Or hasn't seen us come up
JN AKBIT,<+NT10ST(P1)>,R ; Or hasn't seen our ack yet
MOVX T1,DTEEER!DTETER ; Or if an error has occured
MNTXCT NTCNSZ
RET ; Return bad
RETSKP ; else success
;;;
;;; NFEKIL - Turn off the hardware on a Fibernet DTE
;;;
NFEKIL: SKIPE NETON(P1) ; Network supposed to be on?
JRST NFEKL1 ; Yes, don't disable interrupts
; (so 11 can tell us when it comes back)
MOVX T1,DTEPIE ; Get Bits to
MNTXCT NTCONO ; Turn PI's off
NFEKL1: SETZM NTORDY(P1) ; Turn off output
CALL INTDWN ; Interface is down
RET ; And return
TNXEND
END ; Of NFEPHY