(FILECREATED "17-Aug-84 12:39:12" {ERIS}<LISPCORE>SOURCES>LLETHER.;2 67191  

      changes to:  (VARS LLETHERCOMS)
		   (FNS \ETHEREVENTFN)

      previous date: "24-Apr-84 12:13:26" {ERIS}<LISPCORE>SOURCES>LLETHER.;1)


(* Copyright (c) 1982, 1983, 1984 by Xerox Corporation. All rights reserved.)

(PRETTYCOMPRINT LLETHERCOMS)

(RPAQQ LLETHERCOMS [[COMS (* Stuff which should be somwhere else!)
			  (INITVARS (ERRORMESSAGESTREAM T)
				    (PROMPTWINDOW T))
			  (GLOBALVARS ERRORMESSAGESTREAM PROMPTWINDOW)
			  (COMS (* Queue management for data which can be chain-linked through the 
				   first cell)
				(DECLARE: DONTCOPY (EXPORT (RECORDS SYSQUEUE QABLEITEM)
							   (MACROS \QUEUEHEAD)))
				(INITRECORDS SYSQUEUE)
				(SYSRECORDS SYSQUEUE)
				(FNS \ENQUEUE \DEQUEUE \QUEUELENGTH \ONQUEUE \UNQUEUE)
				(* Queue management constructed by TCONC)
				(EXPORT (MACROS \DETCONC \ENTCONC \PEEKTCONC]
		    (COMS (* General packet management)
			  (DECLARE: DONTCOPY (* * Skeletal ether packet. Other users define with 
						respect to)
				    (EXPORT (RECORDS ETHERPACKET ETHERAUX)
					    (CONSTANTS \EPT.PUP \3MBTYPE.PUP \10MBTYPE.PUP \EPT.XIP 
						       \3MBTYPE.XIP \10MBTYPE.XIP \EPT.10TO3 
						       \3MBTYPE.10TO3 \EPT.UNKNOWN))
				    (GLOBALVARS \FREE.PACKET.QUEUE))
			  (INITRECORDS ETHERPACKET)
			  (SYSRECORDS ETHERPACKET)
			  (FNS \ALLOCATE.ETHERPACKET \RELEASE.ETHERPACKET RELEASE.PUP 
			       \FLUSH.PACKET.QUEUE \REQUEUE.ETHERPACKET \EP.PUT.AUX)
			  (INITVARS (\FREE.PACKET.QUEUE (NCREATE (QUOTE SYSQUEUE)))
				    (\NEWPACKETCOUNTER 5)))
		    [COMS (INITRECORDS NSADDRESS)
			  (INITVARS (\MY.NSHOSTNUMBER NIL)
				    (\MY.NSNETNUMBER NIL)
				    (\MY.NSADDRESS NIL))
			  (VARS BROADCASTNSHOSTNUMBER)
			  (FNS \SETLOCALNSNUMBERS \LOADNSADDRESS \STORENSADDRESS \PRINTNSADDRESS 
			       \NSADDRESS.DEFPRINT \LOADNSHOSTNUMBER \STORENSHOSTNUMBER 
			       PRINTNSHOSTNUMBER)
			  (DECLARE: EVAL@COMPILE DONTCOPY (COMS * NSADDRESSCOMS))
			  (DECLARE: DONTEVAL@LOAD DOCOPY (P (DEFPRINT (QUOTE NSADDRESS)
								      (QUOTE \NSADDRESS.DEFPRINT]
		    [COMS (* Assorted Level 0)
			  (FNS \ETHERINIT \ETHEREVENTFN \SETETHERFLAGS \FLUSHNDBS \FLUSH.NDB.QUEUE)
			  (FNS \CHECKSUM \HANDLE.RAW.OTHER \HANDLE.RAW.PACKET \ADD.PACKET.FILTER 
			       \DEL.PACKET.FILTER)
			  (DECLARE: DONTCOPY (EXPORT (CONSTANTS (\NULLCHECKSUM 65535)))
				    (GLOBALVARS \PACKET.FILTERS \ETHERLIGHTNING))
			  (INITVARS (\PACKET.FILTERS NIL)
				    (\ETHERLIGHTNING))
			  (DECLARE: DONTEVAL@LOAD DOCOPY (P (\ETHERINIT)
							    (MOVD? (QUOTE NILL)
								   (QUOTE BLOCK))
							    (MOVD? (QUOTE NILL)
								   (QUOTE \STASH.PASSWORDS]
		    (COMS (* Assorted routing stuff)
			  (DECLARE: DONTCOPY (EXPORT (RECORDS NDB ROUTING))
				    (CONSTANTS \RT.INFINITY)
				    (MACROS ENCAPSULATE.ETHERPACKET TRANSMIT.ETHERPACKET BROADCASTP 
					    .RTLOOKUP.)
				    (GLOBALVARS \RT.TIMEOUTINTERVAL \RT.AGEINTERVAL \RT.PURGEFLG 
						\GATEWAYFLG)
				    (GLOBALVARS \3MBFLG \10MBFLG \3MBLOCALNDB \10MBLOCALNDB 
						\LOCALNDBS \NSFLG \NS.ROUTING.TABLE 
						\PUP.ROUTING.TABLE))
			  (INITRECORDS NDB)
			  (SYSRECORDS NDB)
			  (FNS \AGE.ROUTING.TABLE \FLUSH.ROUTING.TABLE PRINTROUTINGTABLE 
			       \MAP.ROUTING.TABLE)
			  (FNS ENCAPSULATE.ETHERPACKET TRANSMIT.ETHERPACKET)
			  (INITVARS (\RT.TIMEOUTINTERVAL 90000)
				    (\RT.AGEINTERVAL 30000)
				    (\RT.PURGEFLG T)
				    (\GATEWAYFLG))
			  (INITVARS (\3MBFLG T)
				    (\10MBFLG)
				    (\3MBLOCALNDB)
				    (\10MBLOCALNDB)
				    (\LOCALNDBS)
				    (\NSFLG)))
		    (COMS (* 10 to 3 translation ugliness)
			  (FNS \TRANSLATE.10TO3 \NOTE.10TO3 \HANDLE.RAW.10TO3)
			  (DECLARE: DONTCOPY (RECORDS ETHERTRANS)
				    (CONSTANTS \TRANS.OP.REQUEST \TRANS.OP.RESPONSE \TRANS.DATALENGTH)
				    (* The \TRANS.DATALENGTH includes the space for 10TO3OPERATION 
				       and two 3-word/1-word translation pairs.)))
		    (COMS (* Printing routines for packets)
			  (FNS PRINTPACKET \MAYBEPRINTPACKET PRINT10TO3 PRINTPACKETDATA 
			       PRINTPACKETQUEUE TIME.SINCE.PACKET)
			  (INITVARS (\RAWTRACING))
			  (ADDVARS (\PACKET.PRINTERS (512 . PRINTPUP)
						     (1537 . PRINT10TO3)))
			  (GLOBALVARS \RAWTRACING \PACKET.PRINTERS PUPTRACEFILE XIPTRACEFILE))
		    (COMS (* 3MB stuff, which is not needed in DandeLion)
			  (FNS \3MBGETPACKET \3MB.CREATENDB \3MBSENDPACKET \3MBWATCHER 
			       \3MBENCAPSULATE \3MB.BROADCASTP \3MBFLUSH)
			  (INITVARS (\MAXWATCHERGETS 5))
			  (DECLARE: DONTCOPY (RECORDS 3MBENCAPSULATION PBI)
				    (EXPORT (MACROS \SERIALNUMBER))
				    (CONSTANTS \3MBENCAPSULATION.WORDS)
				    (GLOBALVARS \MAXWATCHERGETS)))
		    [COMS (* Debugging)
			  (FNS ASSURE.ETHER.ON INITPUPLEVEL1 TURN.ON.ETHER RESTART.ETHER 
			       TURN.OFF.ETHER PRINTWORDS)
			  (VARS ROUTINGINFOMACRO ETHERFILES)
			  (DECLARE: EVAL@COMPILE DONTCOPY (P (CLISPDEC (QUOTE FETCHFIELD))
							     (* Slow, checking version for debugging]
		    (COMS (* Opcodes)
			  (FNS \DEVICE.INPUT \DEVICE.OUTPUT \D0.STARTIO)
			  (DECLARE: DONTCOPY (CONSTANTS * D0DEVICES)
				    (EXPORT (PROP DOPVAL \DEVICE.INPUT \DEVICE.OUTPUT \D0.STARTIO])



(* Stuff which should be somwhere else!)


(RPAQ? ERRORMESSAGESTREAM T)

(RPAQ? PROMPTWINDOW T)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS ERRORMESSAGESTREAM PROMPTWINDOW)
)



(* Queue management for data which can be chain-linked through the first cell)

(DECLARE: DONTCOPY 
(* FOLLOWING DEFINITIONS EXPORTED)


[DECLARE: EVAL@COMPILE 

(DATATYPE SYSQUEUE ((NIL BYTE)
		    (SYSQUEUEHEAD POINTER)
		    (NIL BYTE)
		    (SYSQUEUETAIL POINTER)))

(BLOCKRECORD QABLEITEM ((NIL BYTE)
			(QLINK POINTER)                      (* Link to next thing in queue always in first pointer 
							     of datum, independent of what the datum is)
			)
		       (BLOCKRECORD QABLEITEM ((NIL BYTE)
				     (LINK POINTER)          (* Let's also be able to call it a LINK)
				     )))
]
(/DECLAREDATATYPE (QUOTE SYSQUEUE)
		  (QUOTE (BYTE POINTER BYTE POINTER)))
(DECLARE: EVAL@COMPILE 

(PUTPROPS \QUEUEHEAD MACRO ((Q)
			    (fetch (SYSQUEUE SYSQUEUEHEAD) of Q)))
)


(* END EXPORTED DEFINITIONS)

)
(/DECLAREDATATYPE (QUOTE SYSQUEUE)
		  (QUOTE (BYTE POINTER BYTE POINTER)))
[ADDTOVAR SYSTEMRECLST

(DATATYPE SYSQUEUE ((NIL BYTE)
		    (SYSQUEUEHEAD POINTER)
		    (NIL BYTE)
		    (SYSQUEUETAIL POINTER)))
]
(DEFINEQ

(\ENQUEUE
  [LAMBDA (Q ITEM)                                           (* bvm: " 2-MAR-83 11:49")
                                                             (* Adds ITEM to tail of Q, which must be a SYSQUEUE 
							     datatype. ITEM must be describable by QABLEITEM.)
    (SETQ Q (\DTEST Q (QUOTE SYSQUEUE)))                     (* Do this \DTEST first, even though the fetch will also
							     do it, so that no error occurs underneath the 
							     UNINTERRUPTABLY)
    (freplace QLINK of ITEM with NIL)                        (* Just for safety -- who knows what garbage may have 
							     creeped into the LINK slot of ITEM)
    (UNINTERRUPTABLY
        [COND
	  ((NULL (ffetch SYSQUEUEHEAD of Q))                 (* Empty queue)
	    (freplace SYSQUEUEHEAD of Q with ITEM))
	  (T (PROG ((TAILEND (ffetch SYSQUEUETAIL of Q)))
	           (OR (NULL (fetch QLINK of TAILEND))
		       (ERROR "Tail of queue not consistent with queue's contents" Q))
	           (freplace QLINK of TAILEND with ITEM]
	(freplace SYSQUEUETAIL of Q with ITEM)               (* ITEM is now last thing on the queue)
	)
    ITEM])

(\DEQUEUE
  [LAMBDA (Q)                                                (* bvm: " 4-FEB-83 13:05")
                                                             (* Removes and returns the top item on Q, which should 
							     be a SYSQUEUE datatype. Returns NIL if queue is empty.)
    (SETQ Q (\DTEST Q (QUOTE SYSQUEUE)))                     (* Do this \DTEST first, even though the fetch will also
							     do it, so that no error occurs underneath the 
							     UNINTERRUPTABLY)
    (UNINTERRUPTABLY
        (PROG ((ITEM (fetch SYSQUEUEHEAD of Q)))
	      (if ITEM
		  then                                       (* First, "cdr" the link in the queue head)
		       (if (NULL (replace SYSQUEUEHEAD of Q with (fetch QLINK of ITEM)))
			   then                              (* Exhausted queue)
				(replace SYSQUEUETAIL of Q with NIL))
		       (replace QLINK of ITEM with NIL)      (* Break the connection that ITEM had with the queue.)
		  )
	      (RETURN ITEM)))])

(\QUEUELENGTH
  [LAMBDA (Q)                                                (* bvm: " 4-FEB-83 13:05")
    (PROG ((X (fetch SYSQUEUEHEAD of Q))
	   (CNT 0))
      LP  (OR X (RETURN CNT))
          (SETQ X (fetch QLINK of X))
          (add CNT 1)
          (GO LP])

(\ONQUEUE
  [LAMBDA (ITEM Q)                                           (* bvm: " 4-FEB-83 13:04")
    (for (X ←(fetch (SYSQUEUE SYSQUEUEHEAD) of Q)) by (fetch QLINK of X) while X do (RETURN ITEM)
       when (EQ X ITEM])

(\UNQUEUE
  [LAMBDA (QUEUE ITEM NOERRORFLG)                            (* bvm: " 6-FEB-83 18:27")

          (* * Removes ITEM from QUEUE, wherever it may be. Is error if ITEM not in QUEUE unless NOERRORFLG is true)


    (COND
      [(UNINTERRUPTABLY
           [bind (NEXT ←(fetch SYSQUEUEHEAD of QUEUE))
		 PREV while NEXT do (COND
				      ((EQ NEXT ITEM)
					(COND
					  [(NULL PREV)       (* removing head of queue)
					    (COND
					      ((NULL (replace SYSQUEUEHEAD of QUEUE
							with (fetch QLINK of ITEM)))
                                                             (* Exhausted queue)
						(replace SYSQUEUETAIL of QUEUE with NIL]
					  ((NULL (replace QLINK of PREV with (fetch QLINK
										of ITEM)))
                                                             (* Removing last item)
					    (replace SYSQUEUETAIL of QUEUE with PREV)))
					(replace QLINK of ITEM with NIL)
					(RETURN ITEM))
				      (T (SETQ NEXT (fetch QLINK of (SETQ PREV NEXT])]
      ((NOT NOERRORFLG)
	(ERROR (LIST ITEM (QUOTE not)
		     (QUOTE on)
		     QUEUE])
)



(* Queue management constructed by TCONC)

(* FOLLOWING DEFINITIONS EXPORTED)


(DECLARE: EVAL@COMPILE 

(PUTPROPS \DETCONC MACRO [OPENLAMBDA (TQ)
				     (PROG1 (\PEEKTCONC TQ)
					    (if [NULL (CAR (RPLACA TQ (CDAR TQ]
						then (RPLACD TQ])

(PUTPROPS \ENTCONC MACRO (= . TCONC))

(PUTPROPS \PEEKTCONC MACRO (= . CAAR))
)


(* END EXPORTED DEFINITIONS)




(* General packet management)

(DECLARE: DONTCOPY 
(* * Skeletal ether packet. Other users define with respect to)


(* FOLLOWING DEFINITIONS EXPORTED)


[DECLARE: EVAL@COMPILE 

(DATATYPE ETHERPACKET ((NIL BYTE)
		       (EPLINK POINTER)                      (* For queue maintenence)
		       (EPFLAGS BYTE)                        (* optional flags for some applications)
		       (EPUSERFIELD POINTER)                 (* Arbitrary pointer for applications)
		       (NIL BYTE)
		       (EPPLIST POINTER)                     (* Extra field for use as an A-list for properties)
		       (EPTRANSMITTING FLAG)                 (* True while packet is being transmitted and hence 
							     cannot be reused)
		       (NIL BITS 7)
		       (EPREQUEUE POINTER)                   (* Where to requeue this packet after transmission)
		       (NIL BYTE)
		       (EPSOCKET POINTER)
		       (NIL BYTE)
		       (EPNETWORK POINTER)
		       (EPTYPE WORD)                         (* Type of packet to be encapsulated 
							     (PUP or XIP or 10TO3))
		       (NIL WORD)
		       (EPTIMESTAMP FIXP)                    (* Gets RCLK value when transmitted/received)
		       (EPREQUEUEFN POINTER)                 (* FN to perform requeueing)
		       (NIL 4 WORD)                          (* Space for expansion)
                                                             (* Note: This next field wants to be quad+2 aligned so 
							     that the 10mb packet is quad+3 aligned)
		       (EPENCAPSULATION 8 WORD)              (* 10mb encapsulation, or 3mb encapsulation with 
							     padding)
		       (EPBODY 289 WORD)                     (* Body of packet, header up to 16 words plus data up to
							     546 bytes)
		       ))

(ACCESSFNS ETHERAUX ((AUXPTR (CDR (ASSOC (QUOTE AUXPTR)
					 (fetch EPPLIST of DATUM)))
			     (\EP.PUT.AUX DATUM (QUOTE AUXPTR)
					  NEWVALUE))
		     (AUXWORD (OR (CDR (ASSOC (QUOTE AUXWORD)
					      (fetch EPPLIST of DATUM)))
				  0)
			      (\EP.PUT.AUX DATUM (QUOTE AUXWORD)
					   NEWVALUE))
		     (AUXBYTE (OR (CDR (ASSOC (QUOTE AUXBYTE)
					      (fetch EPPLIST of DATUM)))
				  0)
			      (\EP.PUT.AUX DATUM (QUOTE AUXBYTE)
					   NEWVALUE))))
]
(/DECLAREDATATYPE (QUOTE ETHERPACKET)
		  (QUOTE (BYTE POINTER BYTE POINTER BYTE POINTER FLAG (BITS 7)
			       POINTER BYTE POINTER BYTE POINTER WORD WORD FIXP POINTER WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD)))
(DECLARE: EVAL@COMPILE 

(RPAQQ \EPT.PUP 512)

(RPAQQ \3MBTYPE.PUP 512)

(RPAQQ \10MBTYPE.PUP 512)

(RPAQQ \EPT.XIP 1536)

(RPAQQ \3MBTYPE.XIP 1536)

(RPAQQ \10MBTYPE.XIP 1536)

(RPAQQ \EPT.10TO3 1537)

(RPAQQ \3MBTYPE.10TO3 1537)

(RPAQQ \EPT.UNKNOWN 255)

(CONSTANTS \EPT.PUP \3MBTYPE.PUP \10MBTYPE.PUP \EPT.XIP \3MBTYPE.XIP \10MBTYPE.XIP \EPT.10TO3 
	   \3MBTYPE.10TO3 \EPT.UNKNOWN)
)


(* END EXPORTED DEFINITIONS)


(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \FREE.PACKET.QUEUE)
)
)
(/DECLAREDATATYPE (QUOTE ETHERPACKET)
		  (QUOTE (BYTE POINTER BYTE POINTER BYTE POINTER FLAG (BITS 7)
			       POINTER BYTE POINTER BYTE POINTER WORD WORD FIXP POINTER WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD WORD 
			       WORD WORD WORD WORD WORD)))
[ADDTOVAR SYSTEMRECLST

(DATATYPE ETHERPACKET ((NIL BYTE)
		       (EPLINK POINTER)
		       (EPFLAGS BYTE)
		       (EPUSERFIELD POINTER)
		       (NIL BYTE)
		       (EPPLIST POINTER)
		       (EPTRANSMITTING FLAG)
		       (NIL BITS 7)
		       (EPREQUEUE POINTER)
		       (NIL BYTE)
		       (EPSOCKET POINTER)
		       (NIL BYTE)
		       (EPNETWORK POINTER)
		       (EPTYPE WORD)
		       (NIL WORD)
		       (EPTIMESTAMP FIXP)
		       (EPREQUEUEFN POINTER)
		       (NIL 4 WORD)
		       (EPENCAPSULATION 8 WORD)
		       (EPBODY 289 WORD)))
]
(DEFINEQ

(\ALLOCATE.ETHERPACKET
  [LAMBDA NIL                                                (* bvm: "12-FEB-83 17:35")
    (PROG ((PACKET (\DEQUEUE \FREE.PACKET.QUEUE)))
          (RETURN (COND
		    (PACKET (\ZEROWORDS (fetch XIPBASE of PACKET)
					(LOCF (fetch XIPFIRSTDATAWORD of PACKET)))
                                                             (* Clear the header. XIP header is the larger, so this 
							     clears for ether pups or xips)
			    PACKET)
		    (T (COND
			 ((ILESSP (SETQ \NEWPACKETCOUNTER (SUB1 \NEWPACKETCOUNTER))
				  0)                         (* GC doesn't happen often enough, so too many packets 
							     tend to get created)
			   (RECLAIM)
			   (SETQ \NEWPACKETCOUNTER 5)))
		       (create ETHERPACKET])

(\RELEASE.ETHERPACKET
  [LAMBDA (EPKT)                                             (* bvm: " 3-MAR-83 15:14")
                                                             (* Free a ETHERPACKET -- might want to let GC do it, but
							     GC doesn't happen often enough)
    (\DTEST EPKT (QUOTE ETHERPACKET))
    (COND
      ([NOT (AND (ffetch EPTRANSMITTING of EPKT)
		 (PROGN (freplace EPREQUEUE of EPKT with (QUOTE FREE))
			(ffetch EPTRANSMITTING of EPKT]      (* Don't free it yet if it's still being transmitted.
							     Test twice in case it finished while we were setting 
							     EPREQUEUE)
	[freplace EPREQUEUE of EPKT with (freplace EPUSERFIELD of EPKT
					    with (freplace EPNETWORK of EPKT
						    with (freplace EPPLIST of EPKT
							    with (freplace EPSOCKET of EPKT
								    with NIL]
	(\ENQUEUE \FREE.PACKET.QUEUE EPKT)))
    NIL])

(RELEASE.PUP
  [LAMBDA (PUP)                                              (* bvm: " 3-MAR-83 16:14")
    (\RELEASE.ETHERPACKET PUP])

(\FLUSH.PACKET.QUEUE
  [LAMBDA (QUEUE)                                            (* bvm: " 4-FEB-83 14:37")

          (* * Releases all packets in QUEUE and returns how many were flushed)


    (bind PACKET (CNT ← 0) while (SETQ PACKET (\DEQUEUE QUEUE))
       do (\RELEASE.ETHERPACKET PACKET)
	  (add CNT 1])

(\REQUEUE.ETHERPACKET
  [LAMBDA (PACKET)                                           (* bvm: " 3-MAR-83 15:14")
    (PROG ((REQUEUE (fetch EPREQUEUE of PACKET)))
          (SELECTQ REQUEUE
		   ((NIL T))
		   (FREE (\RELEASE.ETHERPACKET PACKET))
		   (UNINTERRUPTABLY
                       (COND
			 ((type? SYSQUEUE REQUEUE)
			   (\ENQUEUE REQUEUE PACKET)))
		       (replace EPREQUEUE of PACKET with NIL))])

(\EP.PUT.AUX
  [LAMBDA (PKT KEY VAL)                                      (* JonL " 8-JUL-82 21:45")
    (PROG ((PLIST (fetch EPPLIST of PKT))
	   A)
          [COND
	    ((NULL (SETQ A (ASSOC KEY PLIST)))
	      [COND
		((NEQ KEY (QUOTE AUXPTR))
		  ([LAMBDA (CELL)
		      (PutUnboxed CELL VAL)
		      (SETQ VAL CELL]
		    (CREATECELL \FIXP]
	      (push (fetch EPPLIST of PKT)
		    (CONS KEY VAL)))
	    ((EQ KEY (QUOTE AUXPTR))
	      (RPLACD A VAL))
	    (T (PutUnboxed (CDR A)
			   VAL)
	       (SETQ VAL (CDR A]
          (RETURN VAL])
)

(RPAQ? \FREE.PACKET.QUEUE (NCREATE (QUOTE SYSQUEUE)))

(RPAQ? \NEWPACKETCOUNTER 5)
(/DECLAREDATATYPE (QUOTE NSADDRESS)
		  (QUOTE (FIXP WORD WORD WORD WORD)))

(RPAQ? \MY.NSHOSTNUMBER NIL)

(RPAQ? \MY.NSNETNUMBER NIL)

(RPAQ? \MY.NSADDRESS NIL)

(RPAQQ BROADCASTNSHOSTNUMBER (NSHOSTNUMBER 65535 65535 65535))
(DEFINEQ

(\SETLOCALNSNUMBERS
  [LAMBDA (TYPE)                                             (* bvm: "19-MAR-83 14:53")
    [SETQ \MY.NSHOSTNUMBER (COND
	([NOT (ZEROP (LOGOR (fetch (IFPAGE NSHost0) of \InterfacePage)
			    (fetch (IFPAGE NSHost1) of \InterfacePage)
			    (fetch (IFPAGE NSHost2) of \InterfacePage]
	  (create NSHOSTNUMBER
		  NSHOST0 ←(fetch (IFPAGE NSHost0) of \InterfacePage)
		  NSHOST1 ←(fetch (IFPAGE NSHost1) of \InterfacePage)
		  NSHOST2 ←(fetch (IFPAGE NSHost2) of \InterfacePage)))
	(T (create NSHOSTNUMBER
		   NSHOST0 ← 0
		   NSHOST1 ← 12345Q
		   NSHOST2 ←(\SERIALNUMBER]
    (SETQ \MY.NSNETNUMBER 0)
    (SETQ \MY.NSADDRESS (create NSADDRESS
				NSHNM0 ←(fetch NSHOST0 of \MY.NSHOSTNUMBER)
				NSHNM1 ←(fetch NSHOST1 of \MY.NSHOSTNUMBER)
				NSHNM2 ←(fetch NSHOST2 of \MY.NSHOSTNUMBER])

(\LOADNSADDRESS
  [LAMBDA (BASE A)                                           (* JonL " 2-AUG-82 00:09")
    (PROG [(A (if (type? NSADDRESS A)
		  then A
		else (create NSADDRESS]
          (\MOVENSADDRESSES BASE A)
          (RETURN A])

(\STORENSADDRESS
  [LAMBDA (BASE A)                                           (* JonL " 2-AUG-82 00:11")
    (\MOVENSADDRESSES (\DTEST A (QUOTE NSADDRESS))
		      BASE)
    A])

(\PRINTNSADDRESS
  [LAMBDA (BASE FILE)                                        (* bvm: " 1-FEB-83 15:51")
    (if (ILESSP (IDIFFERENCE (LINELENGTH NIL FILE)
			     (POSITION FILE))
		(IPLUS 24Q (IQUOTIENT (IPLUS 2 (INTEGERLENGTH (\GETBASE BASE 5)))
				      3)))
	then                                                 (* Find how many octal digits in the socket number.)
	     (TERPRI FILE))
    (printout FILE .I0.-8 (\MAKENUMBER (\GETBASE BASE 0)
				       (\GETBASE BASE 1))
	      "#" .I0.-8 (\GETBASE BASE 2)
	      "." .I0.-8 (\GETBASE BASE 3)
	      "." .I0.-8 (\GETBASE BASE 4)
	      "#" .I0.-8 (\GETBASE BASE 5))
    ""])

(\NSADDRESS.DEFPRINT
  [LAMBDA (BASE)                                             (* bvm: " 1-FEB-83 15:51")
    (LIST (CONCAT (OCTALSTRING (\MAKENUMBER (\GETBASE BASE 0)
					    (\GETBASE BASE 1)))
		  "#"
		  (OCTALSTRING (\GETBASE BASE 2))
		  "."
		  (OCTALSTRING (\GETBASE BASE 3))
		  "."
		  (OCTALSTRING (\GETBASE BASE 4))
		  "#"
		  (OCTALSTRING (\GETBASE BASE 5])

(\LOADNSHOSTNUMBER
  [LAMBDA (BASE OLDBOX)                                      (* bvm: "17-FEB-83 17:07")
    (COND
      ((NULL OLDBOX)
	(create NSHOSTNUMBER
		NSHOST0 ←(\GETBASE BASE 0)
		NSHOST1 ←(\GETBASE BASE 1)
		NSHOST2 ←(\GETBASE BASE 2)))
      ((type? NSHOSTNUMBER OLDBOX)
	(replace NSHOST0 of OLDBOX with (\GETBASE BASE 0))
	(replace NSHOST1 of OLDBOX with (\GETBASE BASE 1))
	(replace NSHOST2 of OLDBOX with (\GETBASE BASE 2))
	OLDBOX)
      (T (ERROR "ARG NOT NSHOSTNUMBER" OLDBOX])

(\STORENSHOSTNUMBER
  [LAMBDA (BASE NSHNM)                                       (* bvm: "17-FEB-83 17:07")
    (COND
      ((type? NSHOSTNUMBER NSHNM)
	(\PUTBASE BASE 0 (fetch NSHOST0 of NSHNM))
	(\PUTBASE BASE 1 (fetch NSHOST1 of NSHNM))
	(\PUTBASE BASE 2 (fetch NSHOST2 of NSHNM)))
      (T (ERROR "ARG NOT NSHOSTNUMBER" NSHNM)))
    NSHNM])

(PRINTNSHOSTNUMBER
  [LAMBDA (NSHOSTNUMBER FILE)                                (* bvm: " 5-AUG-83 15:12")
    (RESETFORM (RADIX 10Q)
	       (printout FILE (fetch NSHOST0 of NSHOSTNUMBER)
			 "."
			 (fetch NSHOST1 of NSHOSTNUMBER)
			 "."
			 (fetch NSHOST2 of NSHOSTNUMBER])
)
(DECLARE: EVAL@COMPILE DONTCOPY 

(RPAQQ NSADDRESSCOMS ((EXPORT (RECORDS NSADDRESS NSHOSTNUMBER)
			      (MACROS LOADNSHOSTNUMBER STORENSHOSTNUMBER \MOVENSADDRESSES 
				      \SWAPNSADDRESSES)
			      (CONSTANTS (\#WDS.NSADDRESS 6)
					 (\#WDS.NSHOSTNUMBER 3))
			      (MACROS \LOCALNSHOSTNUMBER \LOCALNSNETNUMBER \LOCALNSADDRESS 
				      \BLTLOCALHOSTNUMBER)
			      (GLOBALVARS BROADCASTNSHOSTNUMBER \MY.NSADDRESS \MY.NSHOSTNUMBER 
					  \MY.NSNETNUMBER))
		      (MACROS EQNSHOSTNUMBER EQBROADCASTBASE EQNSHOSTBASE)
		      (FNS TRANSLATE.NSH)
		      (ADDVARS (DONTCOMPILEFNS TRANSLATE.NSH))))
(* FOLLOWING DEFINITIONS EXPORTED)


[DECLARE: EVAL@COMPILE 

(DATATYPE NSADDRESS ((NSNET FIXP)
		     (NSHNM0 WORD)
		     (NSHNM1 WORD)
		     (NSHNM2 WORD)
		     (NSSOCKET WORD))
		    (ACCESSFNS (NSHOSTNUMBER (LOADNSHOSTNUMBER (LOCF (fetch NSHNM0 of DATUM)))
					     (STORENSHOSTNUMBER (LOCF (fetch NSHNM0 of DATUM))
								NEWVALUE)))
		    (BLOCKRECORD NSADDRESS ((NSNETHI WORD)
				  (NSNETLO WORD))))

(TYPERECORD NSHOSTNUMBER (NSHOST0 NSHOST1 NSHOST2))
]
(/DECLAREDATATYPE (QUOTE NSADDRESS)
		  (QUOTE (FIXP WORD WORD WORD WORD)))
(DECLARE: EVAL@COMPILE 

(PUTPROPS LOADNSHOSTNUMBER MACRO (= . \LOADNSHOSTNUMBER))

(PUTPROPS STORENSHOSTNUMBER MACRO (= . \STORENSHOSTNUMBER))

(PUTPROPS \MOVENSADDRESSES MACRO ((BASE1 BASE2)
				  (\BLT BASE2 BASE1 \#WDS.NSADDRESS)))

(PUTPROPS \SWAPNSADDRESSES MACRO [OPENLAMBDA (BASE1 BASE2)
					     (for I from 0 to (SUB1 \#WDS.NSADDRESS)
						do (\PUTBASE BASE1 I
							     (PROG1 (\GETBASE BASE2 I)
								    (\PUTBASE BASE2 I
									      (PROGN (\GETBASE BASE1 
											       I])
)
(DECLARE: EVAL@COMPILE 

(RPAQQ \#WDS.NSADDRESS 6)

(RPAQQ \#WDS.NSHOSTNUMBER 3)

(CONSTANTS (\#WDS.NSADDRESS 6)
	   (\#WDS.NSHOSTNUMBER 3))
)
(DECLARE: EVAL@COMPILE 

(PUTPROPS \LOCALNSHOSTNUMBER MACRO (NIL \MY.NSHOSTNUMBER))

(PUTPROPS \LOCALNSNETNUMBER MACRO (NIL \MY.NSNETNUMBER))

(PUTPROPS \LOCALNSADDRESS MACRO (NIL \MY.NSADDRESS))

(PUTPROPS \BLTLOCALHOSTNUMBER MACRO ((BASE)
				     (\BLT BASE (LOCF (fetch (IFPAGE NSHost0) of \InterfacePage))
					   3)))
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS BROADCASTNSHOSTNUMBER \MY.NSADDRESS \MY.NSHOSTNUMBER \MY.NSNETNUMBER)
)


(* END EXPORTED DEFINITIONS)

(DECLARE: EVAL@COMPILE 

(PUTPROPS EQNSHOSTNUMBER MACRO (X (TRANSLATE.NSH X)))

(PUTPROPS EQBROADCASTBASE MACRO (OPENLAMBDA (X)
					    (EQ (LOGAND (\GETBASE X 0)
							(\GETBASE X 1)
							(\GETBASE X 2))
						65535)))

(PUTPROPS EQNSHOSTBASE MACRO [OPENLAMBDA (X Y)
					 (AND (type? NSHOSTNUMBER Y)
					      (EQ (\GETBASE X 2)
						  (fetch (NSHOSTNUMBER NSHOST2) of Y))
					      (EQ (\GETBASE X 1)
						  (fetch (NSHOSTNUMBER NSHOST1) of Y))
					      (EQ (\GETBASE X 0)
						  (fetch (NSHOSTNUMBER NSHOST0) of Y])
)
(DEFINEQ

(TRANSLATE.NSH
  [LAMBDA (ARGS)                                             (* bvm: "28-Nov-83 17:32")
    (SETQ ARGS (CDR (DWIMIFY (CONS (QUOTE PROGN)
				   ARGS)
			     T)))
    (PROG ((ARG1 (CAR ARGS))
	   (ARG2 (CADR ARGS)))
          (RETURN (COND
		    ((OR (NLISTP ARG1)
			 (SELECTQ (CAR (SETQ ARG1 (OR (GETHASH ARG1 CLISPARRAY)
						      ARG1)))
				  ((LOADNSHOSTNUMBER \LOADNSHOSTNUMBER)
				    NIL)
				  T))
		      (LIST (QUOTE EQUAL)
			    ARG1 ARG2))
		    ((EQ ARG2 (QUOTE BROADCASTNSHOSTNUMBER))
		      (LIST (QUOTE EQBROADCASTBASE)
			    (CADR ARG1)))
		    (T (LIST (QUOTE EQNSHOSTBASE)
			     (CADR ARG1)
			     ARG2])
)

(ADDTOVAR DONTCOMPILEFNS TRANSLATE.NSH)
)
(DECLARE: DONTEVAL@LOAD DOCOPY 
(DEFPRINT (QUOTE NSADDRESS)
	  (QUOTE \NSADDRESS.DEFPRINT))
)



(* Assorted Level 0)

(DEFINEQ

(\ETHERINIT
  [LAMBDA NIL                                                (* bvm: "14-MAR-83 11:47")

          (* * This gets us EVENT action to take care of pup stuff around LOGOUT, etc.)


    (MOVD (QUOTE \RELEASE.ETHERPACKET)
	  (QUOTE RELEASE.PUP))
    (MOVD (QUOTE \ALLOCATE.ETHERPACKET)
	  (QUOTE ALLOCATE.PUP))
    (\DEFINEDEVICE NIL (create FDEV
			       DEVICENAME ←(QUOTE ETHER)
			       EVENTFN ←(FUNCTION \ETHEREVENTFN)
			       DIRECTORYNAMEP ←(QUOTE NILL)
			       HOSTNAMEP ←(QUOTE NILL])

(\ETHEREVENTFN
  [LAMBDA (DEV EVENT)                                        (* bvm: "17-Aug-84 12:34")
    (SELECTQ EVENT
	     ((NIL AFTERLOGOUT AFTERSYSOUT AFTERMAKESYS AFTERSAVEVM RESTART)
	       (PROG (NDB TURNOFFNS TIMESET)
		     (SETQ \PUP.READY (SETQ \NS.READY))
		     (\SETETHERFLAGS)
		     (\SETLOCALNSNUMBERS)
		     (\FLUSHNDBS EVENT)
		     [SETQ \3MBLOCALNDB (COND
			 (\3MBFLG (SETQ \LOCALNDBS (\3MB.CREATENDB \3MBFLG]
		     (SETQ \10MBLOCALNDB (COND
			 (\10MBFLG (SETQ NDB (\10MB.CREATENDB \10MBFLG))
				   (COND
				     (\LOCALNDBS (replace NDBNEXT of \LOCALNDBS with NDB))
				     (T (SETQ \LOCALNDBS NDB)))
				   NDB)))
		     [for (DB ← \LOCALNDBS) by (fetch NDBNEXT of DB) while DB
			do (\LOCKWORDS DB (fetch DTDSIZE of (\GETDTD (NTYPX DB]
		     [COND
		       ((OR \NSFLG (SETQ TURNOFFNS \10MBFLG))
                                                             (* Start NS before Pup so that when on 10 we can find 
							     out our pup number, which is done via NS protocol)
			 (\NSINIT EVENT)
			 (SETQ TIMESET (\NS.SETTIME]
		     (\STARTPUP EVENT)
		     (OR TIMESET (AND (EQ \PUP.READY T)
				      (\PUP.SETTIME))
			 [SELECTC \MACHINETYPE
				  (\DANDELION (NEQ 0 (fetch DLTODVALID of \IOPAGE)))
				  (IGREATERP (IDATE)
					     (CONSTANT (IDATE " 1-JAN-84 12:00"]
			 (printout PROMPTWINDOW T "[Time not set]"))
		     (COND
		       (TURNOFFNS (STOPNS)))
		     (COND
		       (\GATEWAYFLG (\INIT.GATEWAY)))
		 T))
	     ((BEFOREMAKESYS BEFORELOGOUT BEFORESYSOUT BEFORESAVEVM)
	       (COND
		 ((EQ EVENT (QUOTE BEFORESAVEVM))            (* Save passwords in place outside vmem to avoid having 
							     to reenter them later)
		   (\STASH.PASSWORDS))
		 (T                                          (* No need to flush this before SAVEVM)
		    (CLRHASH \ETHERPORTS)))
	       (CLRHASH LOGINPASSWORDS))
	     NIL])

(\SETETHERFLAGS
  [LAMBDA NIL                                                (* bvm: " 5-MAY-83 23:46")
    (SELECTC \MACHINETYPE
	     (\DANDELION (SETQ \10MBFLG 0)
			 (SETQ \3MBFLG NIL))
	     [\DOLPHIN (COND
			 [(ILESSP (\SERIALNUMBER)
				  255)
			   (SETQ \3MBFLG T)
			   (SETQ \10MBFLG (COND
			       ((EQ (LRSH (\DEVICE.INPUT (LLSH 5 4))
					  8)
				    \DEVICE.10MBETHER)
				 5]
			 (T (SETQ \3MBFLG NIL)
			    (SETQ \10MBFLG (COND
				((EQ (LRSH (\DEVICE.INPUT (LLSH 7 4))
					   8)
				     \DEVICE.10MBETHER)
				  7]
	     (\DORADO (SETQ \3MBFLG T)
		      (SETQ \10MBFLG NIL))
	     (SHOULDNT])

(\FLUSHNDBS
  [LAMBDA (EVENT)                                            (* bvm: " 4-AUG-83 22:51")
    [bind NDB QUEUE while (SETQ NDB \LOCALNDBS)
       do (SETQ \LOCALNDBS (fetch NDBNEXT of NDB))
	  (replace NDBNEXT of NDB with NIL)
	  (COND
	    ((EQ EVENT (QUOTE RESTART))
	      (APPLY* (fetch NDBETHERFLUSHER of NDB)
		      NDB)))
	  (DEL.PROCESS (fetch NDBWATCHER of NDB))
	  (replace NDBWATCHER of NDB with (replace NDBTRANSLATIONS of NDB with NIL))
	  [COND
	    ((SETQ QUEUE (fetch NDBTQ of NDB))
	      (\FLUSH.NDB.QUEUE QUEUE EVENT (QUOTE OUTPUT))
                                                             (* Don't do this just yet, because of possible race in 
							     \PUPGATELISTENER -
							     (replace NDBTQ of NDB with NIL))
	      ]
	  (COND
	    ((SETQ QUEUE (fetch NDBIQ of NDB))
	      (\FLUSH.NDB.QUEUE QUEUE EVENT (QUOTE INPUT))
	      (replace NDBIQ of NDB with NIL]
    (SETQ \PUP.ROUTING.TABLE (CONS))
    (SETQ \NS.ROUTING.TABLE (CONS])

(\FLUSH.NDB.QUEUE
  [LAMBDA (QUEUE EVENT USE)                                  (* bvm: " 8-JUL-83 18:10")

          (* * Release any packets on this QUEUE, and their IOCB's for USE if EVENT is RESTART)


    (bind PACKET IOCB while (SETQ PACKET (\DEQUEUE QUEUE))
       do (COND
	    ((AND (EQ EVENT (QUOTE RESTART))
		  (SETQ IOCB (fetch EPNETWORK of PACKET)))
	      (\RELEASE.IOCB IOCB USE)))
	  (\RELEASE.ETHERPACKET PACKET])
)
(DEFINEQ

(\CHECKSUM
  [LAMBDA (BASE NWORDS INITSUM)                              (* bvm: " 7-FEB-83 12:05")
    (PROG ((CHECKSUM (COND
		       (INITSUM (LOGAND INITSUM MASKWORD1'S))
		       (T 0)))
	   (ADDR BASE)
	   (CNT NWORDS)
	   DIF DATA)
          (while (IGREATERP CNT 0)
	     do 

          (* * Algorithm: Do 1's complement add of next base word, then rotate sum left one. If result is all ones, then 
	  make it zero)


		[SETQ CHECKSUM (COND
		    ([ILEQ CHECKSUM (SETQ DIF (IDIFFERENCE MAX.SMALL.INTEGER (SETQ DATA
							     (\GETBASE ADDR 0]
                                                             (* No carry)
		      (IPLUS CHECKSUM DATA))
		    (T                                       (* Carry, so add the carry into the result.
							     This is actually "CHECKSUM+DATA-(177777Q+1)+1" = 
							     "CHECKSUM-(177777Q-DATA)")
		       (IDIFFERENCE CHECKSUM DIF]
		[SETQ CHECKSUM (COND
		    ((IGREATERP CHECKSUM 77777Q)
		      (LOGOR 1 (LLSH (LOGAND CHECKSUM 77777Q)
				     1)))
		    (T (LLSH CHECKSUM 1]                     (* ROT)
		(SETQ ADDR (\ADDBASE ADDR 1))
		(SETQ CNT (SUB1 CNT)))
          (RETURN (COND
		    ((EQ CHECKSUM MASKWORD1'S)
		      0)
		    (T CHECKSUM])

(\HANDLE.RAW.OTHER
  [LAMBDA (PACKET RAWTYPE)                                   (* bvm: "15-FEB-83 18:30")
    [COND
      (XIPTRACEFLG (printout XIPTRACEFILE "Dropping packet of unknown encapsulation type: ")
		   (COND
		     (RAWTYPE (printout XIPTRACEFILE "[ = #" .I0.-8 RAWTYPE "]"]
    (\RELEASE.ETHERPACKET PACKET])

(\HANDLE.RAW.PACKET
  [LAMBDA (PACKET)                                           (* bvm: " 8-JUN-83 16:56")
    (OR (AND (OR (NOT \ETHERLIGHTNING)
		 (NEQ (RAND 0 \ETHERLIGHTNING)
		      0))
	     (find FILTER in \PACKET.FILTERS bind (TYPE ←(fetch EPTYPE of PACKET))
		suchthat (APPLY* FILTER PACKET TYPE)))
	(\RELEASE.ETHERPACKET PACKET])

(\ADD.PACKET.FILTER
  [LAMBDA (FILTER)                                           (* bvm: "17-FEB-83 15:17")
    (OR (FMEMB FILTER \PACKET.FILTERS)
	(SETQ \PACKET.FILTERS (NCONC1 \PACKET.FILTERS FILTER)))
    FILTER])

(\DEL.PACKET.FILTER
  [LAMBDA (FILTER)                                           (* bvm: "17-FEB-83 15:18")
    (COND
      ((FMEMB FILTER \PACKET.FILTERS)
	(SETQ \PACKET.FILTERS (DREMOVE FILTER \PACKET.FILTERS))
	T])
)
(DECLARE: DONTCOPY 
(* FOLLOWING DEFINITIONS EXPORTED)


(DECLARE: EVAL@COMPILE 

(RPAQQ \NULLCHECKSUM 65535)

(CONSTANTS (\NULLCHECKSUM 65535))
)


(* END EXPORTED DEFINITIONS)


(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \PACKET.FILTERS \ETHERLIGHTNING)
)
)

(RPAQ? \PACKET.FILTERS NIL)

(RPAQ? \ETHERLIGHTNING )
(DECLARE: DONTEVAL@LOAD DOCOPY 
(\ETHERINIT)
(MOVD? (QUOTE NILL)
       (QUOTE BLOCK))
(MOVD? (QUOTE NILL)
       (QUOTE \STASH.PASSWORDS))
)



(* Assorted routing stuff)

(DECLARE: DONTCOPY 
(* FOLLOWING DEFINITIONS EXPORTED)


[DECLARE: EVAL@COMPILE 

(DATATYPE NDB ((NETTYPE BYTE)                                (* 10 or 3 for now)
	       (NDBNEXT POINTER)                             (* Link to next NDB)
	       (NDBPUPNET# BYTE)                             (* Pup number of this net. May be different from NS net 
							     number, though not in Xerox world)
	       (NDBNSNET# POINTER)                           (* Can be 32-bits, so might as well leave its box 
							     around)
	       (NDBTASK# BYTE)                               (* Task # of this network)
	       (NDBBROADCASTP POINTER)                       (* Function that returns true if packet is of broadcast 
							     type)
	       (NDBPUPHOST# BYTE)                            (* My pup address on this net.
							     NS address is global to all nets, so not needed here)
	       (NDBTRANSMITTER POINTER)                      (* Routine to send a raw packet on this net -
							     args NDB PACKET returns NIL on failure)
	       (NIL BYTE)
	       (NDBENCAPSULATOR POINTER)                     (* Routine to encapsulate and send a higher-level packet
							     on this net -
							     args NDB PACKET HOST LENGTH TYPE)
	       (NDBCSB POINTER)                              (* Pointer to CSB for this network)
	       (NDBIQLENGTH BYTE)
	       (NDBIQ POINTER)                               (* Queue of empty packets for receiver)
	       (NDBTQ POINTER)                               (* Queue of packets to transmit)
	       (NDBTRANSLATIONS POINTER)                     (* Cache of translations, 3:10 or 10:3 according to 
							     network)
	       (NDBETHERFLUSHER POINTER)                     (* Turns off this ether. Args NDB)
	       (NDBWATCHER POINTER)
	       (NDBCANHEARSELF POINTER)                      (* True if receiver can hear packets sent by 
							     transmitter)
	       (NIL POINTER)
	       (NIL POINTER)                                 (* Spares)
	       ))

(RECORD ROUTING (RTNET# RTHOPCOUNT RTGATEWAY# RTNDB RTTIMER RTRECENT))
]
(/DECLAREDATATYPE (QUOTE NDB)
		  (QUOTE (BYTE POINTER BYTE POINTER BYTE POINTER BYTE POINTER BYTE POINTER POINTER 
			       BYTE POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER)))


(* END EXPORTED DEFINITIONS)


(DECLARE: EVAL@COMPILE 

(RPAQQ \RT.INFINITY 16)

(CONSTANTS \RT.INFINITY)
)

(DECLARE: EVAL@COMPILE 

(PUTPROPS ENCAPSULATE.ETHERPACKET MACRO ((NDB PACKET HOST LENGTH TYPE)
					 (SPREADAPPLY* (fetch NDBENCAPSULATOR of NDB)
						       NDB PACKET HOST LENGTH TYPE)))

(PUTPROPS TRANSMIT.ETHERPACKET MACRO ((NDB PACKET)
				      (SPREADAPPLY* (fetch NDBTRANSMITTER of NDB)
						    NDB PACKET)))

(PUTPROPS BROADCASTP MACRO ((PACKET)
			    ([LAMBDA (NDB)
				(AND NDB (APPLY* (fetch NDBBROADCASTP of NDB)
						 PACKET NDB]
			      (fetch EPNETWORK of PACKET))))

(PUTPROPS .RTLOOKUP. MACRO ((NET TABLE)                      (* Net numbers are currently smallp's so this is okay)
			    (ASSOC NET (CDR TABLE))))
)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \RT.TIMEOUTINTERVAL \RT.AGEINTERVAL \RT.PURGEFLG \GATEWAYFLG)
)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \3MBFLG \10MBFLG \3MBLOCALNDB \10MBLOCALNDB \LOCALNDBS \NSFLG \NS.ROUTING.TABLE 
	  \PUP.ROUTING.TABLE)
)
)
(/DECLAREDATATYPE (QUOTE NDB)
		  (QUOTE (BYTE POINTER BYTE POINTER BYTE POINTER BYTE POINTER BYTE POINTER POINTER 
			       BYTE POINTER POINTER POINTER POINTER POINTER POINTER POINTER POINTER)))
[ADDTOVAR SYSTEMRECLST

(DATATYPE NDB ((NETTYPE BYTE)
	       (NDBNEXT POINTER)
	       (NDBPUPNET# BYTE)
	       (NDBNSNET# POINTER)
	       (NDBTASK# BYTE)
	       (NDBBROADCASTP POINTER)
	       (NDBPUPHOST# BYTE)
	       (NDBTRANSMITTER POINTER)
	       (NIL BYTE)
	       (NDBENCAPSULATOR POINTER)
	       (NDBCSB POINTER)
	       (NDBIQLENGTH BYTE)
	       (NDBIQ POINTER)
	       (NDBTQ POINTER)
	       (NDBTRANSLATIONS POINTER)
	       (NDBETHERFLUSHER POINTER)
	       (NDBWATCHER POINTER)
	       (NDBCANHEARSELF POINTER)
	       (NIL POINTER)
	       (NIL POINTER)))
]
(DEFINEQ

(\AGE.ROUTING.TABLE
  [LAMBDA (TABLE)                                            (* bvm: "14-FEB-83 14:18")
    (for (TAIL ←(CDR TABLE))
	 (PREV ← TABLE) while TAIL bind ENTRY do (COND
						   [[COND
						       ((AND (NEQ (fetch RTHOPCOUNT
								     of (SETQ ENTRY (CAR TAIL)))
								  0)
							     (TIMEREXPIRED? (fetch RTTIMER
									       of ENTRY)))
                                                             (* Entry has timed out)
							 (COND
							   ((fetch RTRECENT of ENTRY)
                                                             (* New entry, make it old)
							     (replace RTRECENT of ENTRY with NIL)
							     (SETUPTIMER \RT.TIMEOUTINTERVAL
									 (fetch RTTIMER of ENTRY))
							     NIL)
							   (T \RT.PURGEFLG]
						     (RPLACD PREV (SETQ TAIL (CDR TAIL]
						   (T (SETQ TAIL (CDR (SETQ PREV TAIL])

(\FLUSH.ROUTING.TABLE
  [LAMBDA (TABLE)                                            (* bvm: "14-FEB-83 14:32")
    (FRPLACD TABLE (for X in (CDR TABLE) collect X when (ZEROP (fetch RTHOPCOUNT of X])

(PRINTROUTINGTABLE
  [LAMBDA (TABLE SORT FILE)                                  (* bvm: " 3-MAR-83 16:19")
    (SELECTQ TABLE
	     (NS (SETQ TABLE \NS.ROUTING.TABLE))
	     ((NIL PUP)
	       (SETQ TABLE \PUP.ROUTING.TABLE))
	     NIL)
    (RESETFORM (RADIX 10Q)
	       (printout FILE "Net#   Gateway     #Hops   Recent?" T)
	       (for ENTRY in (COND
			       (SORT (SORT (APPEND (CDR TABLE))
					   T))
			       (T (CDR TABLE)))
		  bind GATE
		  do (printout FILE .I4.8 (fetch RTNET# of ENTRY))
		     (COND
		       ((NOT (SETQ GATE (fetch RTGATEWAY# of ENTRY)))
			 (PRIN1 "      ---  " FILE))
		       ((FIXP GATE)
			 (printout FILE .I9.8 GATE))
		       (T (SPACES 2 FILE)
			  (PRINTNSHOSTNUMBER GATE FILE)))
		     (printout FILE 25Q .I2 (fetch RTHOPCOUNT of ENTRY)
			       (COND
				 ((fetch RTRECENT of ENTRY)
				   "     Yes")
				 ((TIMEREXPIRED? (fetch RTTIMER of ENTRY))
				   "  timed out")
				 (T "     No"))
			       T))
	       (TERPRI FILE])

(\MAP.ROUTING.TABLE
  [LAMBDA (TABLE MAPFN)                                      (* bvm: "22-SEP-83 14:21")
    (for ENTRY in (APPEND (CDR (OR TABLE \PUP.ROUTING.TABLE))) do (APPLY* MAPFN ENTRY])
)
(DEFINEQ

(ENCAPSULATE.ETHERPACKET
  [LAMBDA (NDB PACKET PDH NBYTES ETYPE)                      (* bvm: "10-JUN-83 12:11")
    (APPLY* (ffetch NDBENCAPSULATOR of (\DTEST NDB (QUOTE NDB)))
	    NDB
	    (\DTEST PACKET (QUOTE ETHERPACKET))
	    PDH NBYTES ETYPE])

(TRANSMIT.ETHERPACKET
  [LAMBDA (NDB PACKET)                                       (* bvm: "10-JUN-83 12:15")
    (APPLY* (ffetch NDBTRANSMITTER of (\DTEST NDB (QUOTE NDB)))
	    NDB
	    (\DTEST PACKET (QUOTE ETHERPACKET])
)

(RPAQ? \RT.TIMEOUTINTERVAL 90000)

(RPAQ? \RT.AGEINTERVAL 30000)

(RPAQ? \RT.PURGEFLG T)

(RPAQ? \GATEWAYFLG )

(RPAQ? \3MBFLG T)

(RPAQ? \10MBFLG )

(RPAQ? \3MBLOCALNDB )

(RPAQ? \10MBLOCALNDB )

(RPAQ? \LOCALNDBS )

(RPAQ? \NSFLG )



(* 10 to 3 translation ugliness)

(DEFINEQ

(\TRANSLATE.10TO3
  [LAMBDA (NSHOSTNUMBER NDB)                                 (* bvm: "10-JUN-83 12:29")

          (* Translate from an NSHOSTNUMBER to a PUP host number for the indicated network. If we don't have the 
	  translation, we initiate a probe for it and return NIL)


    (OR [CADR (SASSOC NSHOSTNUMBER (ffetch NDBTRANSLATIONS of (\DTEST NDB (QUOTE NDB]
	(PROG ((PACKET (\ALLOCATE.ETHERPACKET)))
	      (replace EPTYPE of PACKET with \EPT.10TO3)
	      (freplace TRANSOPERATION of PACKET with \TRANS.OP.REQUEST)
	      (freplace TRANSNSHOST of PACKET with NSHOSTNUMBER)
	      (freplace TRANSSENDERNSHOST of PACKET with (\LOCALNSHOSTNUMBER))
	      (freplace TRANSSENDERPUPHOST of PACKET with (ffetch NDBPUPHOST# of NDB))
	      (ENCAPSULATE.ETHERPACKET NDB PACKET 0 \TRANS.DATALENGTH \EPT.10TO3)
	      (AND XIPTRACEFLG (\MAYBEPRINTPACKET PACKET (QUOTE PUT)))
	      (freplace EPREQUEUE of PACKET with (QUOTE FREE))
	      (TRANSMIT.ETHERPACKET NDB PACKET)              (* We didn't find out this time, but we will later on)
	      (RETURN])

(\NOTE.10TO3
  [LAMBDA (NSHOST PUPADDRESS NDB)                            (* bvm: "26-MAR-83 15:02")
                                                             (* Update cache to include this pairing)
    (PROG ([A (SASSOC NSHOST (ffetch NDBTRANSLATIONS of (\DTEST NDB (QUOTE NDB]
	   (HOST (fetch PUPHOST# of PUPADDRESS)))
          (COND
	    (A (RPLACA (CDR A)
		       HOST))
	    (T (push (ffetch NDBTRANSLATIONS of NDB)
		     (LIST NSHOST HOST (CLOCK 0])

(\HANDLE.RAW.10TO3
  [LAMBDA (PACKET TYPE)                                      (* bvm: "10-JUN-83 12:31")

          (* Called when a TRANSLATION packet is received. This is either a packet requesting a 10-to-3 translation, in 
	  which case we respond if it is asking about us; or it is a response to a request of ours, in which case we store 
	  the info in the cache)


    (COND
      ((EQ TYPE \EPT.10TO3)
	(PROG ((NDB (fetch EPNETWORK of PACKET)))
	      (AND XIPTRACEFLG (\MAYBEPRINTPACKET PACKET (QUOTE GET)))
	      [SELECTC (fetch TRANSOPERATION of PACKET)
		       [\TRANS.OP.REQUEST (COND
					    ((EQNSHOSTNUMBER (fetch TRANSNSHOST of PACKET)
							     (\LOCALNSHOSTNUMBER))
                                                             (* It's for us)
					      (COND
						((IGEQ (fetch 3MBLENGTH of PACKET)
						       (IPLUS \3MBENCAPSULATION.WORDS
							      (FOLDHI \TRANS.DATALENGTH BYTESPERWORD))
						       )     (* Add sender's address to cache)
						  (\NOTE.10TO3 (fetch TRANSSENDERNSHOST of PACKET)
							       (fetch TRANSSENDERPUPHOST
								  of PACKET)
							       NDB)))
					      (replace TRANSPUPHOST of PACKET
						 with (fetch NDBPUPHOST# of NDB))
                                                             (* Add in the information he wants)
					      (replace TRANSOPERATION of PACKET with 
									       \TRANS.OP.RESPONSE)
					      (ENCAPSULATE.ETHERPACKET NDB PACKET
								       (fetch TRANSSENDERPUPHOST
									  of PACKET)
								       \TRANS.DATALENGTH \EPT.10TO3)
                                                             (* Send back the response)
					      (AND XIPTRACEFLG (NOT (MEMB (QUOTE TRANS)
									  XIPIGNORETYPES))
						   (PRINT10TO3 PACKET (QUOTE PUT)
							       XIPTRACEFILE))
					      (replace EPREQUEUE of PACKET with (QUOTE FREE))
					      (TRANSMIT.ETHERPACKET NDB PACKET)
					      (RETURN]
		       (\TRANS.OP.RESPONSE                   (* Add the information to the cache)
					   (\NOTE.10TO3 (fetch TRANSNSHOST of PACKET)
							(fetch TRANSPUPHOST of PACKET)
							NDB))
		       (COND
			 (XIPTRACEFLG (printout XIPTRACEFILE "Bad 10:3 operation: "
						(fetch TRANSOPERATION of PACKET)
						T]
	      (\RELEASE.ETHERPACKET PACKET))
	T])
)
(DECLARE: DONTCOPY 
[DECLARE: EVAL@COMPILE 

(ACCESSFNS ETHERTRANS [(TRANSBODY (LOCF (fetch (ETHERPACKET EPBODY) of DATUM]
		      [BLOCKRECORD TRANSBODY ((TRANSOPERATION WORD)
                                                             (* Request or response)
				    (BASETRANSNSHOST 3 WORD)
                                                             (* Known or desired NS address)
				    (TRANSPUPHOST BYTE)      (* Known or desired PUP address)
				    (NIL BYTE)               (* Padding)
				    (BASETRANSSENDERNSHOST 3 WORD)
                                                             (* Sender's info)
				    (TRANSSENDERPUPHOST BYTE)
				    (NIL BYTE))
				   [ACCESSFNS BASETRANSNSHOST ((TRANSCONTENTS (LOCF DATUM]
				   [ACCESSFNS BASETRANSNSHOST ((TRANSNSHOST (\LOADNSHOSTNUMBER
									      (LOCF DATUM))
									    (\STORENSHOSTNUMBER
									      (LOCF DATUM)
									      NEWVALUE]
				   (ACCESSFNS BASETRANSSENDERNSHOST ((TRANSSENDERNSHOST
						 (\LOADNSHOSTNUMBER (LOCF DATUM))
						 (\STORENSHOSTNUMBER (LOCF DATUM)
								     NEWVALUE]
		      (TYPE? (type? ETHERPACKET DATUM)))
]

(DECLARE: EVAL@COMPILE 

(RPAQQ \TRANS.OP.REQUEST 4161)

(RPAQQ \TRANS.OP.RESPONSE 3640)

(RPAQQ \TRANS.DATALENGTH 18)

(CONSTANTS \TRANS.OP.REQUEST \TRANS.OP.RESPONSE \TRANS.DATALENGTH)
)




(* The \TRANS.DATALENGTH includes the space for 10TO3OPERATION and two 3-word/1-word 
translation pairs.)

)



(* Printing routines for packets)

(DEFINEQ

(PRINTPACKET
  [LAMBDA (PACKET CALLER FILE PRE.NOTE DOFILTER)             (* bvm: "18-FEB-83 15:25")
    (PROG ((TYPE (fetch EPTYPE of PACKET))
	   FN)
          [COND
	    ((SETQ FN (CDR (FASSOC TYPE \PACKET.PRINTERS)))
	      (RETURN (APPLY* FN PACKET CALLER FILE PRE.NOTE DOFILTER]
          (OR FILE (SETQ FILE XIPTRACEFILE))
          (AND PRE.NOTE (printout FILE T PRE.NOTE))
          (AND CALLER (printout FILE CALLER ": "))
          (printout FILE "Unknown ether packet type: " TYPE T)
          (RETURN PACKET])

(\MAYBEPRINTPACKET
  [LAMBDA (PACKET CALLER FILE PRE.NOTE)                      (* bvm: "18-JUN-83 20:57")
    (PROG ((TYPE (fetch EPTYPE of PACKET))
	   NDB)
          (SELECTQ (SELECTC TYPE
			    (\EPT.PUP PUPTRACEFLG)
			    XIPTRACEFLG)
		   (NIL)
		   [PEEK (PRIN1 (SELECTQ CALLER
					 [(GET RAWGET)
					   (COND
					     ((BROADCASTP PACKET)
					       (QUOTE *))
					     (T (QUOTE +]
					 [(PUT RAWPUT)
					   (COND
					     ((BROADCASTP PACKET)
					       (QUOTE ↑))
					     (T (QUOTE !]
					 (QUOTE ?))
				(OR FILE (SELECTC TYPE
						  (\EPT.PUP PUPTRACEFILE)
						  XIPTRACEFILE]
		   [RAW (SELECTQ CALLER
				 ((RAWGET RAWPUT)
				   (PRINTPACKET PACKET CALLER FILE PRE.NOTE T))
				 (PRIN1 (SELECTQ CALLER
						 (GET (QUOTE #))
						 (PUT (QUOTE ↑))
						 (QUOTE ?))
					(OR FILE (SELECTC TYPE
							  (\EPT.PUP PUPTRACEFILE)
							  XIPTRACEFILE]
		   (PRINTPACKET PACKET CALLER FILE PRE.NOTE T])

(PRINT10TO3
  [LAMBDA (EPKT CALLER FILE PRE.NOTE DOFILTER)               (* bvm: " 3-MAR-83 16:16")
    (COND
      ((OR (NOT DOFILTER)
	   (NOT (MEMB (QUOTE TRANS)
		      XIPIGNORETYPES)))
	(OR FILE (SETQ FILE XIPTRACEFILE))
	(OR (ZEROP (POSITION FILE))
	    (TERPRI FILE))
	(COND
	  (PRE.NOTE (PRIN1 PRE.NOTE FILE)))
	(SELECTC (fetch TRANSOPERATION of EPKT)
		 (\TRANS.OP.REQUEST (printout FILE CALLER " 10:3 trans request for ")
				    (PRINTNSHOSTNUMBER (fetch TRANSNSHOST of EPKT)
						       FILE)
				    (printout FILE " from ")
				    (PRINTNSHOSTNUMBER (fetch TRANSSENDERNSHOST of EPKT)
						       FILE)
				    (printout FILE " = " (fetch TRANSSENDERPUPHOST of EPKT)
					      T))
		 (\TRANS.OP.RESPONSE (printout FILE CALLER " 10:3 trans response: ")
				     (PRINTNSHOSTNUMBER (fetch TRANSNSHOST of EPKT)
							FILE)
				     (printout FILE " = " (fetch TRANSPUPHOST of EPKT)
					       T))
		 (printout FILE CALLER " unknown 10 to 3 translation operation "
			   (fetch TRANSOPERATION of EPKT)
			   T])

(PRINTPACKETDATA
  [LAMBDA (BASE OFFSET MACRO LENGTH FILE)                    (* bvm: "26-MAY-83 12:27")

          (* * Prints to FILE the data portion of a packet starting at byte OFFSET (default zero) of BASE for LENGTH bytes 
	  according to MACRO. MACRO contains elements describing what format the data is in -
	  WORDS, BYTES, CHARS: print as words, numeric bytes or ascii characters -
	  IFSSTRING: data is a string whose length is in the first two bytes -
	  <positive number>: subsequent commands apply starting at this byte offset -
	  <negative number>: commands apply for the next {magnitude} bytes -
	  ...: print "..." and quit if you still have data at this point -
	  REPEAT: rest of macro should be applied repeatedly until data exhausted -
	  T: end of line -
	  SEPR: separate items (other than CHARS) with next token -
	  FINALLY: print next token when you get to the end)


    (OR OFFSET (SETQ OFFSET 0))
    (bind CHAR TMP FINALPRINT REPEATMACRO (SEPR ← ", ")
	  (TILOFFSET ← 0)
	  (DATATYPE ←(QUOTE WORDS))
	  (STREAM ←(GETSTREAM FILE (QUOTE OUTPUT))) while (ILESSP OFFSET LENGTH)
       do (while (AND (OR MACRO (SETQ MACRO REPEATMACRO))
		      (IGEQ OFFSET TILOFFSET))
	     do [SELECTQ (CAR MACRO)
			 ((WORDS BYTES CHARS INTEGERS)
			   (SETQ DATATYPE (CAR MACRO)))
			 [(WORD BYTE CHAR INTEGER)
			   (SETQ DATATYPE (PACK* (CAR MACRO)
						 (QUOTE S]
			 [IFSSTRING                          (* Hack. Data is assumed to be a string whose first word
							     is its length)
				    (SETQ TMP (\GETBASE BASE (FOLDLO OFFSET BYTESPERWORD)))
				    (printout STREAM (QUOTE {)
					      .P2 TMP (QUOTE }))
				    (add OFFSET 2)
				    (SETQ TILOFFSET (CEIL (IPLUS OFFSET TMP)
							  BYTESPERWORD))
				    (COND
				      ((NEQ DATATYPE (QUOTE BYTES))
					(SETQ DATATYPE (QUOTE CHARS]
			 (... (PRIN1 (QUOTE ...)
				     STREAM)
			      (SETQ DATATYPE (SETQ MACRO)))
			 (REPEAT (SETQ REPEATMACRO (CDR MACRO)))
			 (SEPR (SETQ SEPR (CADR MACRO))
			       (SETQ MACRO (CDR MACRO)))
			 [FINALLY (SETQ FINALPRINT (CAR (SETQ MACRO (CDR MACRO]
			 (T (TERPRI STREAM))
			 (COND
			   [(FIXP (CAR MACRO))
			     (SETQ TILOFFSET (COND
				 ((IGEQ (CAR MACRO)
					0)
				   (CAR MACRO))
				 (T                          (* Relative)
				    (IDIFFERENCE OFFSET (CAR MACRO]
			   (T (PRIN1 (CAR MACRO)
				     STREAM]
		(SETQ MACRO (CDR MACRO)))
	  (SELECTQ DATATYPE
		   [WORDS (PRIN2 (\GETBASE BASE (FOLDLO OFFSET BYTESPERWORD))
				 STREAM)
			  (add OFFSET 2)
			  (COND
			    ((AND SEPR (ILESSP OFFSET LENGTH))
			      (PRIN1 SEPR STREAM]
		   [INTEGERS (PRIN2 (\MAKENUMBER (\GETBASE BASE (SETQ TMP (FOLDLO OFFSET BYTESPERWORD)
							     ))
						 (\GETBASE BASE (ADD1 TMP)))
				    STREAM)
			     (add OFFSET 4)
			     (COND
			       ((AND SEPR (ILESSP OFFSET LENGTH))
				 (PRIN1 SEPR STREAM]
		   (CHARS [COND
			    ((AND (IGEQ (SETQ CHAR (\GETBASEBYTE BASE OFFSET))
					(CHARCODE SPACE))
				  (ILESSP CHAR 177Q))
			      (\OUTCHAR STREAM CHAR))
			    ((AND (EQ CHAR (CHARCODE CR))
				  (IGREATERP LENGTH (ADD1 OFFSET))
				  (EQ (\GETBASEBYTE BASE (ADD1 OFFSET))
				      (CHARCODE LF)))
			      (PRIN1 "[crlf]" STREAM)
			      (add OFFSET 1))
			    (T (printout STREAM (QUOTE %[)
					 CHAR
					 (QUOTE %]]
			  (add OFFSET 1))
		   (BYTES (printout STREAM (QUOTE %[)
				    (\GETBASEBYTE BASE OFFSET)
				    (QUOTE %]))
			  (add OFFSET 1))
		   (RETURN))
       finally (AND FINALPRINT (PRIN1 FINALPRINT STREAM)))
    (TERPRI FILE])

(PRINTPACKETQUEUE
  [LAMBDA (QUEUE CALLER FILE)                                (* bvm: "21-APR-83 23:51")
    (for [PACKET ←(COND
		   ((type? SYSQUEUE QUEUE)
		     (fetch SYSQUEUEHEAD of QUEUE))
		   (T (\DTEST QUEUE (QUOTE ETHERPACKET]
       by (fetch EPLINK of PACKET) while PACKET do (PRINTPACKET PACKET CALLER FILE])

(TIME.SINCE.PACKET
  [LAMBDA (PACKET)                                           (* bvm: "26-OCT-83 15:46")
                                                             (* Returns time in milliseconds since PACKET's 
							     EPTIMESTAMP was last set)
    (PROG ((CLK1 (\RCLK (\CREATECELL \FIXP)))
	   (CLK0 (\CREATECELL \FIXP)))
          (\BLT CLK0 (LOCF (fetch EPTIMESTAMP of PACKET))
		WORDSPERCELL)
          (RETURN (IQUOTIENT (\BOXIDIFFERENCE CLK1 CLK0)
			     \RCLKMILLISECOND])
)

(RPAQ? \RAWTRACING )

(ADDTOVAR \PACKET.PRINTERS (512 . PRINTPUP)
			   (1537 . PRINT10TO3))
(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \RAWTRACING \PACKET.PRINTERS PUPTRACEFILE XIPTRACEFILE)
)



(* 3MB stuff, which is not needed in DandeLion)

(DEFINEQ

(\3MBGETPACKET
  [LAMBDA NIL                                                (* bvm: "26-OCT-83 15:16")
    (PROG (PACKET)
          (RETURN (COND
		    ((UNINTERRUPTABLY
                         (PROG ((PBI (\READRAWPBI)))
			       [COND
				 (PBI (SETQ PACKET (\ALLOCATE.ETHERPACKET))
				      (\BLT (fetch 3MBBASE of PACKET)
					    (fetch PBIRAWSTART of PBI)
					    (ADD1 (fetch PBILENGTH of PBI)))
				      (COND
					((NEQ (fetch PBISOCKET of PBI)
					      0)
					  (HELP "PBI has a socket" PBI]
			       (RETURN PBI)))
		      (\BOXIPLUS (LOCF (fetch NETIOOPS of \MISCSTATS))
				 1)
		      (\RCLK (LOCF (fetch EPTIMESTAMP of PACKET)))
		      (replace EPNETWORK of PACKET with \3MBLOCALNDB)
		      (replace EPTYPE of PACKET with (fetch 3MBTYPE of PACKET))
		      [COND
			(\RAWTRACING (\MAYBEPRINTPACKET PACKET (QUOTE RAWGET]
		      PACKET])

(\3MB.CREATENDB
  [LAMBDA NIL                                                (* bvm: " 8-JUL-83 18:15")
    (create NDB
	    NDBPUPHOST# ←(\SERIALNUMBER)
	    NDBPUPNET# ← 0
	    NDBNSNET# ← 0
	    NETTYPE ← 3
	    NDBTRANSMITTER ←(FUNCTION \3MBSENDPACKET)
	    NDBENCAPSULATOR ←(FUNCTION \3MBENCAPSULATE)
	    NDBBROADCASTP ←(FUNCTION \3MB.BROADCASTP)
	    NDBETHERFLUSHER ←(FUNCTION NILL)
	    NDBWATCHER ←(ADD.PROCESS (QUOTE (\3MBWATCHER))
				     (QUOTE RESTARTABLE)
				     (QUOTE SYSTEM)
				     (QUOTE AFTEREXIT)
				     (QUOTE DELETE])

(\3MBSENDPACKET
  [LAMBDA (NDB PACKET)                                       (* bvm: " 8-JUN-83 16:59")
                                                             (* Sends raw seething etherpacket on the 3mb net denoted
							     by NDB)
    (SETQ PACKET (\DTEST PACKET (QUOTE ETHERPACKET)))
    (PROG NIL
          (AND \RAWTRACING (\MAYBEPRINTPACKET PACKET (QUOTE RAWPUT)))
          [COND
	    ((OR (NULL \ETHERLIGHTNING)
		 (NEQ (RAND 0 \ETHERLIGHTNING)
		      0))
	      (UNINTERRUPTABLY
                  (PROG ((PBI (\GETPACKETBUFFER)))
		        [OR PBI (RETURN (COND
					  (\RAWTRACING (PRIN1 (QUOTE x)
							      (SELECTC (fetch EPTYPE of PACKET)
								       (\EPT.PUP PUPTRACEFILE)
								       XIPTRACEFILE]
		        (\BLT (fetch PBIRAWSTART of PBI)
			      (fetch 3MBBASE of PACKET)
			      (ADD1 (fetch 3MBLENGTH of PACKET)))
		        (\WRITERAWPBI PBI)
		        (\BOXIPLUS (LOCF (fetch NETIOOPS of \MISCSTATS))
				   1)))]
          (\REQUEUE.ETHERPACKET PACKET)
          (RETURN T])

(\3MBWATCHER
  [LAMBDA NIL                                                (* bvm: "26-OCT-83 15:21")

          (* * Process that watches the 3mb net and pulls packets in, passing them to the raw packet handler)


    (PROG ((CNTR 0)
	   PACKET)
      LP  [COND
	    ((SETQ PACKET (\3MBGETPACKET))                   (* Got something)
	      (\HANDLE.RAW.PACKET PACKET)
	      (COND
		((ILESSP (add CNTR 1)
			 \MAXWATCHERGETS)                    (* Hack to get better ether service in lieu of 
							     preemption)
		  (GO LP]
          (BLOCK)
          (SETQ CNTR 0)
          (GO LP])

(\3MBENCAPSULATE
  [LAMBDA (NDB PACKET PDH LENGTH TYPE)                       (* bvm: " 7-MAR-83 12:44")
                                                             (* Encapsulates packets for 3mb net)
    (replace 3MBDESTHOST of PACKET with PDH)
    (replace 3MBSOURCEHOST of PACKET with (fetch NDBPUPHOST# of NDB))
    (replace 3MBLENGTH of PACKET with (IPLUS (FOLDHI LENGTH BYTESPERWORD)
					     \3MBENCAPSULATION.WORDS))
    (replace 3MBTYPE of PACKET with TYPE)
    PACKET])

(\3MB.BROADCASTP
  [LAMBDA (PACKET)                                           (* bvm: "18-JUN-83 20:53")
    (ZEROP (fetch 3MBDESTHOST of PACKET])

(\3MBFLUSH
  [LAMBDA (ASPROC)                                           (* bvm: "18-FEB-83 17:10")
    (PROG NIL
      LP  (RETURN (PROG1 (while (\READRAWPBI) sum 1)
			 (COND
			   (ASPROC (BLOCK 11610Q)
				   (GO LP])
)

(RPAQ? \MAXWATCHERGETS 5)
(DECLARE: DONTCOPY 
[DECLARE: EVAL@COMPILE 

(ACCESSFNS 3MBENCAPSULATION [(3MBENCAPSTART (LOCF (fetch (ETHERPACKET EPENCAPSULATION) of DATUM]
			    (BLOCKRECORD 3MBENCAPSTART ((NIL 5 WORD)
                                                             (* waste space)
					  (3MBLENGTH WORD)   (* Length of packet in words, starting at the next word)
					  (3MBDESTHOST BYTE)
                                                             (* Immediate destination host)
					  (3MBSOURCEHOST BYTE)
                                                             (* Us)
					  (3MBTYPE WORD)     (* Type of packet -- PUP or XIP or 10TO3)
					  )
					 [ACCESSFNS 3MBLENGTH ((3MBBASE (LOCF DATUM]
                                                             (* What to hand to BCPL)
					 )
			    (TYPE? (type? ETHERPACKET DATUM)))

(BLOCKRECORD PBI ((PBILINK WORD)
		  (PBIQUEUE WORD)
		  (PBISOCKET WORD)
		  (PBINDB WORD)
		  (PBIINPUTP FLAG)
		  (PBIALLNETSP FLAG)
		  (PBINOZEROP FLAG)
		  (NIL BITS 13)
		  (PBITIMER WORD)
		  (PBILENGTH WORD)
		  (PBIENCAPSULATION 2 WORD)
		  (PBIFIRSTPUPWORD 10 WORD)
		  (PBIFIRSTPUPDATAWORD WORD))
		 [ACCESSFNS PBI ((PBIPUPSTART (LOCF (fetch PBIFIRSTPUPWORD of DATUM)))
			     (PBIPUPDATASTART (LOCF (fetch PBIFIRSTPUPDATAWORD of DATUM)))
			     (PBIRAWSTART (LOCF (fetch PBILENGTH of DATUM])
]

(* FOLLOWING DEFINITIONS EXPORTED)


(DECLARE: EVAL@COMPILE 

(PUTPROPS \SERIALNUMBER MACRO (NIL (fetch (IFPAGE SerialNumber) of \InterfacePage)))
)


(* END EXPORTED DEFINITIONS)


(DECLARE: EVAL@COMPILE 

(RPAQQ \3MBENCAPSULATION.WORDS 2)

(CONSTANTS \3MBENCAPSULATION.WORDS)
)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \MAXWATCHERGETS)
)
)



(* Debugging)

(DEFINEQ

(ASSURE.ETHER.ON
  [LAMBDA (USENS)                                            (* bvm: " 8-JUL-83 18:31")
    (OR (THIS.PROCESS)
	(ERROR "Processes not on!" "" T))
    (COND
      ((NOT \LOCALNDBS)
	(AND USENS (SETQ \NSFLG T))
	(\ETHEREVENTFN))
      ((AND USENS (NOT \NSFLG))
	(\NSINIT])

(INITPUPLEVEL1
  [LAMBDA (FLG)                                              (* bvm: " 5-MAY-83 23:49")
    (TURN.OFF.ETHER)
    (DEL.PROCESS (QUOTE \3MBFLUSH))
    (SELECTC \MACHINETYPE
	     (\DANDELION)
	     (\PUPLEVEL1STATE NIL))
    (ASSURE.ETHER.ON)
    (COND
      (FLG                                                   (* This hack used for Bootstrapping: we got called from 
							     \PUPINIT in the evaluation of PUP's coms)
	   (HARDRESET])

(TURN.ON.ETHER
  [LAMBDA NIL                                                (* bvm: "26-MAR-83 15:55")
    (ASSURE.ETHER.ON \NSFLG])

(RESTART.ETHER
  [LAMBDA NIL                                                (* bvm: "22-SEP-83 14:20")
    (PROG (PROC)
          (AND (SETQ PROC (FIND.PROCESS (QUOTE \PUPGATELISTENER)))
	       (SUSPEND.PROCESS PROC))
          (AND (SETQ PROC (FIND.PROCESS (QUOTE \NSGATELISTENER)))
	       (SUSPEND.PROCESS PROC)))
    (\ETHEREVENTFN NIL (QUOTE RESTART])

(TURN.OFF.ETHER
  [LAMBDA NIL                                                (* bvm: "12-JUL-83 14:03")
    (BREAKCONNECTION T)
    (DEL.PROCESS (QUOTE \PUPGATELISTENER))
    (DEL.PROCESS (QUOTE \NSGATELISTENER))
    (CLOSEPUPSOCKET T)
    (AND (GETD (QUOTE CLOSENSOCKET))
	 (CLOSENSOCKET T))
    (\FLUSHNDBS (QUOTE RESTART])

(PRINTWORDS
  [LAMBDA (BASE NWORDS)                                      (* bvm: "25-MAY-82 21:26")
    (for I from 0 to (SUB1 NWORDS) do (printout NIL .P2 I ": " .P2 (\GETBASE BASE I)
						T])
)

(RPAQQ ROUTINGINFOMACRO (1 "Operation = " WORDS 2 "Info: " REPEAT "(" SEPR ", " INTEGER -4 WORDS SEPR 
			   ") "
			   -2 FINALLY ")"))

(RPAQQ ETHERFILES (LLETHER LLNS 10MBDRIVER PUP LEAF BSP CHAT SPP))
(DECLARE: EVAL@COMPILE DONTCOPY 
(CLISPDEC (QUOTE FETCHFIELD))
(* Slow, checking version for debugging)
)



(* Opcodes)

(DEFINEQ

(\DEVICE.INPUT
  [LAMBDA (TASKREG)                                          (* bvm: "12-JUL-82 13:29")
    ((OPCODES MISC1 1)
     (\DTEST TASKREG (QUOTE SMALLP])

(\DEVICE.OUTPUT
  [LAMBDA (VALUE TASKREG)                                    (* bvm: "12-JUL-82 13:29")
    ((OPCODES MISC2 2)
     (\DTEST VALUE (QUOTE SMALLP))
     (\DTEST TASKREG (QUOTE SMALLP])

(\D0.STARTIO
  [LAMBDA (BITS)                                             (* bvm: "12-JUL-82 13:28")
    ((OPCODES MISC1 0)
     (\DTEST BITS (QUOTE SMALLP])
)
(DECLARE: DONTCOPY 

(RPAQQ D0DEVICES ((\DEVICE.3MBETHERIN 7)
		  (\DEVICE.3MBETHEROUT 6)
		  (\DEVICE.10MBETHER 21)
		  (\DEVICE.SA4000 3)
		  (\DEVICE.DISPLAY 2)))
(DECLARE: EVAL@COMPILE 

(RPAQQ \DEVICE.3MBETHERIN 7)

(RPAQQ \DEVICE.3MBETHEROUT 6)

(RPAQQ \DEVICE.10MBETHER 21)

(RPAQQ \DEVICE.SA4000 3)

(RPAQQ \DEVICE.DISPLAY 2)

(CONSTANTS (\DEVICE.3MBETHERIN 7)
	   (\DEVICE.3MBETHEROUT 6)
	   (\DEVICE.10MBETHER 21)
	   (\DEVICE.SA4000 3)
	   (\DEVICE.DISPLAY 2))
)

(* FOLLOWING DEFINITIONS EXPORTED)



(PUTPROPS \DEVICE.INPUT DOPVAL (1 MISC1 1))

(PUTPROPS \DEVICE.OUTPUT DOPVAL (2 MISC2 2))

(PUTPROPS \D0.STARTIO DOPVAL (1 MISC1 0))


(* END EXPORTED DEFINITIONS)

)
(PUTPROPS LLETHER COPYRIGHT ("Xerox Corporation" 1982 1983 1984))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (6429 10525 (\ENQUEUE 6439 . 7678) (\DEQUEUE 7680 . 8763) (\QUEUELENGTH 8765 . 9057) (
\ONQUEUE 9059 . 9323) (\UNQUEUE 9325 . 10523)) (18168 21482 (\ALLOCATE.ETHERPACKET 18178 . 18968) (
\RELEASE.ETHERPACKET 18970 . 19958) (RELEASE.PUP 19960 . 20104) (\FLUSH.PACKET.QUEUE 20106 . 20453) (
\REQUEUE.ETHERPACKET 20455 . 20904) (\EP.PUT.AUX 20906 . 21480)) (21817 25472 (\SETLOCALNSNUMBERS 
21827 . 22727) (\LOADNSADDRESS 22729 . 22993) (\STORENSADDRESS 22995 . 23180) (\PRINTNSADDRESS 23182
 . 23838) (\NSADDRESS.DEFPRINT 23840 . 24223) (\LOADNSHOSTNUMBER 24225 . 24773) (\STORENSHOSTNUMBER 
24775 . 25155) (PRINTNSHOSTNUMBER 25157 . 25470)) (28422 29095 (TRANSLATE.NSH 28432 . 29093)) (29266 
33981 (\ETHERINIT 29276 . 29800) (\ETHEREVENTFN 29802 . 31766) (\SETETHERFLAGS 31768 . 32401) (
\FLUSHNDBS 32403 . 33507) (\FLUSH.NDB.QUEUE 33509 . 33979)) (33982 36417 (\CHECKSUM 33992 . 35240) (
\HANDLE.RAW.OTHER 35242 . 35584) (\HANDLE.RAW.PACKET 35586 . 35962) (\ADD.PACKET.FILTER 35964 . 36188)
 (\DEL.PACKET.FILTER 36190 . 36415)) (41196 43643 (\AGE.ROUTING.TABLE 41206 . 42137) (
\FLUSH.ROUTING.TABLE 42139 . 42368) (PRINTROUTINGTABLE 42370 . 43424) (\MAP.ROUTING.TABLE 43426 . 
43641)) (43644 44164 (ENCAPSULATE.ETHERPACKET 43654 . 43921) (TRANSMIT.ETHERPACKET 43923 . 44162)) (
44481 48631 (\TRANSLATE.10TO3 44491 . 45671) (\NOTE.10TO3 45673 . 46176) (\HANDLE.RAW.10TO3 46178 . 
48629)) (50157 57306 (PRINTPACKET 50167 . 50717) (\MAYBEPRINTPACKET 50719 . 51675) (PRINT10TO3 51677
 . 52792) (PRINTPACKETDATA 52794 . 56416) (PRINTPACKETQUEUE 56418 . 56789) (TIME.SINCE.PACKET 56791 . 
57304)) (57579 61780 (\3MBGETPACKET 57589 . 58547) (\3MB.CREATENDB 58549 . 59112) (\3MBSENDPACKET 
59114 . 60196) (\3MBWATCHER 60198 . 60824) (\3MBENCAPSULATE 60826 . 61376) (\3MB.BROADCASTP 61378 . 
61540) (\3MBFLUSH 61542 . 61778)) (63618 65489 (ASSURE.ETHER.ON 63628 . 63927) (INITPUPLEVEL1 63929 . 
64407) (TURN.ON.ETHER 64409 . 64553) (RESTART.ETHER 64555 . 64924) (TURN.OFF.ETHER 64926 . 65263) (
PRINTWORDS 65265 . 65487)) (65830 66387 (\DEVICE.INPUT 65840 . 66010) (\DEVICE.OUTPUT 66012 . 66218) (
\D0.STARTIO 66220 . 66385)))))
STOP