(FILECREATED "26-OCT-83 16:41:01" {PHYLUM}<LISPCORE>SOURCES>10MBDRIVER.;14 45778  

      changes to:  (FNS \10MBWATCHER \10MB.INPUT.INTERRUPT)

      previous date: " 4-OCT-83 11:13:17" {PHYLUM}<LISPCORE>SOURCES>10MBDRIVER.;13)


(* Copyright (c) 1982, 1983 by Xerox Corporation)

(PRETTYCOMPRINT 10MBDRIVERCOMS)

(RPAQQ 10MBDRIVERCOMS ((DECLARE: DONTCOPY (RECORDS 10MBENCAPSULATION)
				 (CONSTANTS \10MBENCAPSULATION.WORDS))
	(COMS (* Implementation of raw packet interface)
	      (FNS \10MBGETPACKET \10MBSENDPACKET \10MBENCAPSULATE \10MB.BROADCASTP \10MBWATCHER))
	(COMS (* Managing ether traffic above the head level)
	      (FNS \10MB.STARTDRIVER \10MB.CREATENDB \10MB.INPUT.INTERRUPT \10MB.OUTPUT.INTERRUPT 
		   \10MB.NOTESTAT))
	(COMS (* Buffer management)
	      (FNS \10MB.LOADINPUTQ \RELEASE.IOCB \GET.IOCB \INIT.ETHER.BUFFER.POOL)
	      (INITVARS (\10MBPACKETLENGTH 448))
	      (CONSTANTS (\MAXLLBUFFERPAGES 2)
			 (\MINLLBUFFERPAGES 1)
			 (\MAXIOCBS 64)
			 (\10MB.MAX.INPUT.LENGTH 20)))
	(COMS (* Dolphin/Dlion head)
	      (FNS \10MB.GETPACKETLENGTH \10MB.GETPACKETSTATUS \QUEUE.INPUT.IOCB \QUEUE.OUTPUT.IOCB 
		   \10MB.TURNOFFETHER \10MB.TURNONETHER)
	      (DECLARE: EVAL@COMPILE DONTCOPY (MACROS \D0.CONTROLLERBITS \D0.TURNOFFETHER 
						      \DL.TURNOFFETHER)
			(RECORDS D0ETHERCSB D0ETHERIOCB DLETHERCSB DLETHERIOCB)
			(CONSTANTS (\D0.ENABLE.10MBINPUT 49152)
				   (\D0.ENABLE.10MBOUTPUT 192)
				   (\D0.RESET.10MBCONTROLLER 512)
				   (\D0.INPUTSTATE 1)
				   (\D0.OUTPUTSTATE 2)
				   (\CSB.LENGTH 16)
				   (\IOCB.LENGTH 8)
				   (\MIN2PAGEBUFLENGTH 232)
				   (\10MB.MINPACKETLENGTH 30))
			(CONSTANTS * DLIONETHERCONSTANTS)
			(CONSTANTS * ETHERSTATUSCONSTANTS)
			(CONSTANTS * D0ETHERSTATUSCONSTANTS)
			(CONSTANTS * DLETHERSTATUSCONSTANTS)
			(GLOBALVARS \IOCB.INPUT.ALLOC \IOCB.INPUT.TOTAL \IOCB.OUTPUT.ALLOC 
				    \IOCB.OUTPUT.TOTAL \IOCBTOTAL \10MB.GETGARBAGE \10MB.RAWPACKETQ 
				    \10MB.IDEAL.INPUT.LENGTH \10MB.COLLECTSTATS \MACHINETYPE 
				    \10MBPACKETLENGTH \IOCBFREELIST)))
	(COMS (* Misc)
	      (FNS \NOMACHINETYPE)
	      (FNS IOCBQLENGTH))
	(INITVARS \10MB.GETGARBAGE \10MB.COLLECTSTATS)
	[COMS (* 3 to 10 kludges)
	      (FNS \HANDLE.RAW.3TO10 \TRANSLATE.3TO10 PRINT3TO10 \NOTE.3TO10)
	      (CONSTANTS \10MBTYPE.3TO10 \EPT.3TO10)
	      (ADDVARS (\PACKET.PRINTERS (513 . PRINT3TO10]
	(DECLARE: EVAL@COMPILE DONTCOPY (FILES (LOADCOMP)
					       LLETHER LLNS))))
(DECLARE: DONTCOPY 
[DECLARE: EVAL@COMPILE 

(ACCESSFNS 10MBENCAPSULATION [(10MBBASE (LOCF (fetch (ETHERPACKET EPENCAPSULATION) of DATUM]
			     [BLOCKRECORD 10MBBASE ((10MBLENGTH WORD)
                                                             (* Length of packet in words, starting at the next word.
							     Not part of the actual packet;
							     it is here for convenience)
					   (10MBDESTHOST0 3 WORD)
                                                             (* Immediate destination host)
					   (10MBSOURCEHOST0 3 WORD)
                                                             (* Us)
					   (10MBTYPE WORD)   (* Type of packet -- PUP, NS)
					   )
					  [ACCESSFNS 10MBDESTHOST0 ((10MBDESTHOST
							(\LOADNSHOSTNUMBER (LOCF DATUM))
							(\STORENSHOSTNUMBER (LOCF DATUM)
									    NEWVALUE))
						      (10MBPACKETBASE (LOCF DATUM))
						      (10MBDESTHOSTBASE (LOCF DATUM]
					  (ACCESSFNS 10MBSOURCEHOST0 ((10MBSOURCEHOST
							(\LOADNSHOSTNUMBER (LOCF DATUM))
							(\STORENSHOSTNUMBER (LOCF DATUM)
									    NEWVALUE))
						      (10MBSOURCEHOSTBASE (LOCF DATUM]
			     (TYPE? (type? ETHERPACKET DATUM)))
]

(DECLARE: EVAL@COMPILE 

(RPAQQ \10MBENCAPSULATION.WORDS 7)

(CONSTANTS \10MBENCAPSULATION.WORDS)
)
)



(* Implementation of raw packet interface)

(DEFINEQ

(\10MBGETPACKET
  [LAMBDA NIL                                                (* bvm: "28-FEB-83 11:39")
    (PROG (PACKET)
          (RETURN (COND
		    ((SETQ PACKET (\DEQUEUE \10MB.RAWPACKETQ))
		      [COND
			(\RAWTRACING (\MAYBEPRINTPACKET PACKET (QUOTE RAWGET]
		      PACKET])

(\10MBSENDPACKET
  [LAMBDA (NDB PACKET)                                       (* bvm: "10-JUN-83 14:47")
    (PROG ([DROPIT (AND \ETHERLIGHTNING (EQ 0 (RAND 0 \ETHERLIGHTNING]
	   IOCB BUFLENGTH)
          [COND
	    (\RAWTRACING (\MAYBEPRINTPACKET PACKET (QUOTE RAWPUT]
          (UNINTERRUPTABLY
              (replace EPTRANSMITTING of PACKET with T)
	      (COND
		([OR DROPIT (NULL (SETQ IOCB (\GET.IOCB (QUOTE OUTPUT]
                                                             (* Fake transmission)
		  (replace EPNETWORK of PACKET with NIL))
		(T (replace EPNETWORK of PACKET with IOCB)
		   (SETQ BUFLENGTH (IMAX (fetch 10MBLENGTH of PACKET)
					 \10MB.MINPACKETLENGTH))
		   (\TEMPLOCKPAGES PACKET (COND
				     ((IGEQ BUFLENGTH \MIN2PAGEBUFLENGTH)
				       2)
				     (T 1)))                 (* Put on microcode queue)
		   (\QUEUE.OUTPUT.IOCB NDB IOCB (fetch 10MBPACKETBASE of PACKET)
				       BUFLENGTH)
		   T))
	      (\ENQUEUE (fetch NDBTQ of NDB)
			PACKET)                              (* Put on driver's queue to pick up after microcode 
							     finishes with it)
	      )
          (RETURN (AND IOCB T])

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

(\10MB.BROADCASTP
  [LAMBDA (PACKET)                                           (* bvm: "19-JUL-83 10:53")
    (EQ (fetch 10MBDESTHOST0 of PACKET)
	65535])

(\10MBWATCHER
  [LAMBDA (NDB)                                              (* bvm: "26-OCT-83 15:23")
                                                             (* Process that watches the 10mb net and pulls packets 
							     in. Decodes the type and passes packet to interested 
							     party)
    (PROG ((CNTR 0)
	   PACKET)
      LP  (UNINTERRUPTABLY
              (\10MB.INPUT.INTERRUPT NDB)
	      (\10MB.OUTPUT.INTERRUPT NDB))
          [COND
	    ((SETQ PACKET (\10MBGETPACKET))                  (* 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])
)



(* Managing ether traffic above the head level)

(DEFINEQ

(\10MB.STARTDRIVER
  [LAMBDA (NDB RESTARTFLG MYNSNUMBER)                        (* bvm: " 8-JUL-83 18:38")
    (\10MB.TURNOFFETHER NDB)
    (OR (\INIT.ETHER.BUFFER.POOL)
	(ERROR "Unable to create buffer pool"))
    (replace NDBTQ of NDB with (create SYSQUEUE))
    (SETQ \10MB.RAWPACKETQ (create SYSQUEUE))
    (\10MB.TURNONETHER NDB NIL NIL (OR MYNSNUMBER T)
		       0 0)
    (PROG ((LEN 0)
	   (IQ (fetch NDBIQ of NDB)))
          [COND
	    [IQ (SETQ LEN (\10MB.LOADINPUTQ NDB (fetch SYSQUEUEHEAD of IQ]
	    (T (replace NDBIQ of NDB with (SETQ IQ (create SYSQUEUE]
          (bind IOCB PACKET to (IDIFFERENCE \10MB.IDEAL.INPUT.LENGTH LEN)
	     while (SETQ IOCB (\GET.IOCB (QUOTE INPUT)))
	     do (SETQ PACKET (\ALLOCATE.ETHERPACKET))
		(\TEMPLOCKPAGES PACKET 2)
		(replace EPNETWORK of PACKET with IOCB)
		(\QUEUE.INPUT.IOCB NDB IOCB (fetch 10MBPACKETBASE of PACKET)
				   \10MBPACKETLENGTH)        (* Add IOCB to microcode's queue)
		(\ENQUEUE IQ PACKET)                         (* and to driver's queue, so it can process it after 
							     arrival)
		(add LEN 1))
          (replace NDBIQLENGTH of NDB with LEN)
          (replace NDBWATCHER of NDB with (ADD.PROCESS (LIST (QUOTE \10MBWATCHER)
							     (KWOTE NDB))
						       (QUOTE RESTARTABLE)
						       (QUOTE SYSTEM)
						       (QUOTE AFTEREXIT)
						       (QUOTE DELETE)))
          (RETURN NDB])

(\10MB.CREATENDB
  [LAMBDA (ETHERTASK#)                                       (* bvm: " 8-JUL-83 18:20")
    (\10MB.STARTDRIVER (create NDB
			       NDBNSNET# ← 0
			       NDBPUPNET# ← 0
			       NETTYPE ← 10
			       NDBTRANSMITTER ←(FUNCTION \10MBSENDPACKET)
			       NDBENCAPSULATOR ←(FUNCTION \10MBENCAPSULATE)
			       NDBBROADCASTP ←(FUNCTION \10MB.BROADCASTP)
			       NDBTASK# ← ETHERTASK#
			       NDBETHERFLUSHER ←(FUNCTION \10MB.TURNOFFETHER])

(\10MB.INPUT.INTERRUPT
  [LAMBDA (NDB)                                              (* bvm: "26-OCT-83 15:24")

          (* This routine gets called when 10MB input signals an interrupt. See if the head of the input queue has indeed 
	  been processed, and if so, take care of it)


    (PROG ((PACKET (fetch SYSQUEUEHEAD of (fetch NDBIQ of NDB)))
	   STATUS ACCEPTPACKET IOCB)
          (COND
	    ((AND PACKET (NEQ [SETQ STATUS (\10MB.GETPACKETSTATUS (SETQ IOCB (fetch EPNETWORK
										of PACKET]
			      \ES.PENDING))                  (* Yes, something is there, and microcode is finished 
							     with it)
	      (\DEQUEUE (fetch NDBIQ of NDB))
	      [COND
		(\10MB.COLLECTSTATS (\10MB.NOTESTAT STATUS PACKET (QUOTE INPUT]
	      [COND
		((SETQ ACCEPTPACKET (OR (EQ STATUS \ES.GOOD.PACKET)
					\10MB.GETGARBAGE))
		  (PROG ((LENGTH (\10MB.GETPACKETLENGTH IOCB)))
                                                             (* Accept the packet)
		        (replace 10MBLENGTH of PACKET with LENGTH)
		        (\RCLK (LOCF (fetch EPTIMESTAMP of PACKET)))
		        (replace EPNETWORK of PACKET with NDB)
		        (replace EPTYPE of PACKET with (fetch 10MBTYPE of PACKET))
		        (COND
			  ((AND (EQ \MACHINETYPE \DANDELION)
				(IGREATERP LENGTH \MIN2PAGEBUFLENGTH))

          (* Dandelion ether uCode doesn't set the dirty bit on pages of PACKET, so make sure the second page gets marked 
	  dirty if it needs to be. The first page has been implicitly marked dirty by the replaces above)


			    (\PUTBASE PACKET (SUB1 (ITIMES WORDSPERPAGE 2))
				      0)))
		        (\TEMPUNLOCKPAGES PACKET 2)
		        (\ENQUEUE \10MB.RAWPACKETQ PACKET))
		  (PROGN                                     (* Now stuff a new buffer on queue)
			 (SETQ PACKET (\ALLOCATE.ETHERPACKET))
			 (\TEMPLOCKPAGES PACKET 2)
			 (replace EPNETWORK of PACKET with IOCB]
                                                             (* Now stuff a buffer back on the input)
	      (\QUEUE.INPUT.IOCB NDB IOCB (fetch 10MBPACKETBASE of PACKET)
				 \10MBPACKETLENGTH)
	      (\ENQUEUE (fetch NDBIQ of NDB)
			PACKET)))
          (RETURN ACCEPTPACKET])

(\10MB.OUTPUT.INTERRUPT
  [LAMBDA (NDB)                                              (* bvm: "10-JUN-83 14:56")

          (* This routine gets called when 10MB output signals an interrupt. Remove the head of the output queue and put it 
	  on the done queue)


    (PROG ((NEXTPACKET (fetch SYSQUEUEHEAD of (fetch NDBTQ of NDB)))
	   STATUS IOCB)
          (RETURN (COND
		    ((AND NEXTPACKET (OR (NULL (SETQ IOCB (fetch EPNETWORK of NEXTPACKET)))
					 (NEQ (SETQ STATUS (\10MB.GETPACKETSTATUS IOCB))
					      \ES.PENDING)))
                                                             (* Yes, microcode has finished processing this buffer)
		      (\DEQUEUE (fetch NDBTQ of NDB))
		      (replace EPTRANSMITTING of NEXTPACKET with NIL)
		      (replace EPNETWORK of NEXTPACKET with NIL)
		      (\REQUEUE.ETHERPACKET NEXTPACKET)
		      [COND
			(IOCB (\RELEASE.IOCB IOCB (QUOTE OUTPUT))
			      (\TEMPUNLOCKPAGES NEXTPACKET 2)
			      (COND
				(\10MB.COLLECTSTATS (\10MB.NOTESTAT STATUS NEXTPACKET (QUOTE OUTPUT]
		      T])

(\10MB.NOTESTAT
  [LAMBDA (STATUS BUF USE)                                   (* bvm: "15-JUL-82 14:43")
                                                             (* Increment counter associated with this status)
    NIL])
)



(* Buffer management)

(DEFINEQ

(\10MB.LOADINPUTQ
  [LAMBDA (NDB PACKETS)                                      (* bvm: "28-FEB-83 17:36")

          (* PACKETS points at the first of several buffers of NDB's IQ. We load them into the microcode's chain.
	  Value returned is the number of buffers)


    (bind (CNT ← 0) while PACKETS
       do (\TEMPLOCKPAGES PACKETS 2)
	  (\QUEUE.INPUT.IOCB NDB (fetch EPNETWORK of PACKETS)
			     (fetch 10MBPACKETBASE of PACKETS)
			     \10MBPACKETLENGTH)
	  (SETQ PACKETS (fetch EPLINK of PACKETS))
	  (add CNT 1)
       finally (RETURN CNT])

(\RELEASE.IOCB
  [LAMBDA (IOCB USE)                                         (* bvm: " 3-MAR-83 16:17")
                                                             (* Returns an IOCB to the free pool.
							     USE is INPUT or OUTPUT, according to which side should 
							     be credited. Must be called uninterruptably)
    (COND
      ((NOT (AND IOCB (EMADDRESSP IOCB)))
	(ERROR "ARG NOT IOCB" IOCB))
      (T (SELECTQ USE
		  (INPUT (add \IOCB.INPUT.ALLOC 1))
		  (OUTPUT (add \IOCB.OUTPUT.ALLOC 1))
		  (\ILLEGAL.ARG USE))
	 (replace D0NEXTIOCB of IOCB with (\LOLOC \IOCBFREELIST))
                                                             (* (\LOLOC NIL) = 0 works also)
	 (SETQ \IOCBFREELIST IOCB)
	 NIL])

(\GET.IOCB
  [LAMBDA (USE)                                              (* bvm: " 3-MAR-83 14:32")

          (* returns a IOCB for INPUT or OUTPUT use, or NIL if none is available. This must be called uninterruptably, since
	  we don't have any easy way of GCing these guys)


    (COND
      ((AND \IOCBFREELIST (IGREATERP (SELECTQ USE
					      (INPUT \IOCB.INPUT.ALLOC)
					      (OUTPUT \IOCB.OUTPUT.ALLOC)
					      (\ILLEGAL.ARG USE))
				     0))
	(SELECTQ USE
		 (INPUT (add \IOCB.INPUT.ALLOC -1))
		 (add \IOCB.OUTPUT.ALLOC -1))
	(PROG1 \IOCBFREELIST (SETQ \IOCBFREELIST (OR (EMPOINTER (fetch D0NEXTIOCB of \IOCBFREELIST))
						     (HELP "IOCB free list going NIL")))
                                                             (* Note that (EMPOINTER 0) = NIL, so this works even 
							     when free list runs out)
	       ])

(\INIT.ETHER.BUFFER.POOL
  [LAMBDA NIL                                                (* bvm: "17-JUL-83 16:00")

          (* Divides up the zone bcpl reserved for us into IOCB's used for sending/receiving ether packets.
	  The IOCB's must be quad-aligned. When an ether packet is to be sent, or prepared for receiving, an IOCB is 
	  assigned to it. The IOCB contains length and status info and a pointer to the ether packet buffer in Lisp space.
	  The IOCB's are chained for the microcode, and the packets are chained independently in Lisp space so that we can 
	  keep track of them after the microcode finishes. \IOCBFREELIST points at the first IOCB; there are a total of 
	  \IOCBTOTAL of them.)


    (PROG (LASTBUF BUFFER ZONE ZONELENGTH)
          (COND
	    ((ZEROP (SETQ ZONELENGTH (fetch (IFPAGE MDSZoneLength) of \InterfacePage)))
                                                             (* Bcpl was unable to allocate any space for us)
	      (SETQ \IOCBFREELIST NIL)
	      (SETQ \IOCBTOTAL 0)
	      (RETURN))
	    (T (SETQ ZONE (fetch (IFPAGE MDSZone) of \InterfacePage))
	       [SETQ ZONELENGTH (IDIFFERENCE ZONELENGTH (IDIFFERENCE ZONE (SETQ ZONE
								       (CEIL ZONE (ITIMES 2 
										     WORDSPERQUAD]
                                                             (* 8-align the zone, in case the microcode cares, and 
							     adjust the length downward if necessary)
	       (SETQ ZONE (EMPOINTER ZONE))                  (* Make an actual pointer)
	       ))
          (SETQ \IOCBTOTAL (IMIN (IQUOTIENT (IDIFFERENCE ZONELENGTH 3)
					    \IOCB.LENGTH)
				 \MAXIOCBS))
          (SETQ \IOCBFREELIST ZONE)
          (to \IOCBTOTAL
	     do                                              (* Link the idle IOCB's together using short addresses)
		[replace D0NEXTIOCB of ZONE with (\LOLOC (SETQ ZONE (\ADDBASE ZONE \IOCB.LENGTH]
	     finally (replace D0NEXTIOCB of ZONE with 0))
          [SETQ \TELERAIDIOCB (PROG1 \IOCBFREELIST (SETQ \IOCBFREELIST (EMPOINTER (fetch D0NEXTIOCB
										     of \IOCBFREELIST]
                                                             (* Pop one off for TeleRaid)
          (add \IOCBTOTAL -1)
          [SETQ \IOCB.INPUT.ALLOC (SETQ \IOCB.INPUT.TOTAL (SETQ \IOCB.OUTPUT.ALLOC
		(SETQ \IOCB.OUTPUT.TOTAL (IQUOTIENT (ITIMES \IOCBTOTAL 2)
						    3]
          (SETQ \10MB.IDEAL.INPUT.LENGTH (IMIN \10MB.MAX.INPUT.LENGTH (IQUOTIENT \IOCBTOTAL 2)))
          (RETURN \IOCBTOTAL])
)

(RPAQ? \10MBPACKETLENGTH 448)
(DECLARE: EVAL@COMPILE 

(RPAQQ \MAXLLBUFFERPAGES 2)

(RPAQQ \MINLLBUFFERPAGES 1)

(RPAQQ \MAXIOCBS 64)

(RPAQQ \10MB.MAX.INPUT.LENGTH 20)

(CONSTANTS (\MAXLLBUFFERPAGES 2)
	   (\MINLLBUFFERPAGES 1)
	   (\MAXIOCBS 64)
	   (\10MB.MAX.INPUT.LENGTH 20))
)



(* Dolphin/Dlion head)

(DEFINEQ

(\10MB.GETPACKETLENGTH
  [LAMBDA (IOCB)                                             (* bvm: "24-JUL-82 17:45")
    (SELECTC \MACHINETYPE
	     (\DOLPHIN (FOLDLO (fetch D0IOCBBYTESUSED of IOCB)
			       BYTESPERWORD))
	     (\DANDELION (fetch DLIOCBBYTESUSED of IOCB))
	     (\NOMACHINETYPE])

(\10MB.GETPACKETSTATUS
  [LAMBDA (IOCB)                                             (* bvm: "25-JUL-82 16:08")

          (* * Translate device bits to device-independent constants)


    (SELECTC \MACHINETYPE
	     [\DOLPHIN (PROG ((STATUS (fetch D0IOCBSTATUS of IOCB)))
			     (RETURN (SELECTC STATUS
					      (0 \ES.PENDING)
					      (\D0.GOOD.PACKET (COND
								 ((EVENP (fetch D0IOCBBYTESUSED
									    of IOCB))
								   \ES.GOOD.PACKET)
								 (T \ES.BAD.ALIGNMENT)))
					      (\D0.LATE.COLLISION \ES.LATE.COLLISION)
					      (\D0.TOO.MANY.COLLISIONS \ES.TOO.MANY.COLLISIONS)
					      (\D0.PACKET.TOO.LONG \ES.PACKET.TOO.LONG)
					      (\D0.BAD.ALIGNMENT \ES.BAD.ALIGNMENT)
					      (\D0.INPUT.BAD.CRC \ES.BAD.CRC)
					      ((LOGOR \D0.BAD.ALIGNMENT \D0.INPUT.BAD.CRC)
						\ES.BAD.CRC&ALIGNMENT)
					      (COND
						((NOT (ZEROP (LOGAND STATUS \D0.INPUT.OVERRUN)))
						  \ES.OVERRUN)
						((NOT (ZEROP (LOGAND STATUS \D0.OUTPUT.UNDERRUN)))
						  \ES.UNDERRUN)
						(T \ES.OTHER.ERROR]
	     [\DANDELION (PROG ((STATUS (fetch DLIOCBSTATUS of IOCB)))
			       (RETURN (COND
					 ((ZEROP STATUS)
					   \ES.PENDING)
					 [(ZEROP (fetch DLFOROUTPUTUSE of IOCB))
                                                             (* Input errors)
					   (COND
					     ((EQ (fetch DLIOCBLENGTH of IOCB)
						  177777Q)
					       \ES.PACKET.TOO.LONG)
					     (T (COND
						  ([ZEROP (SETQ STATUS
							    (LOGAND STATUS
								    (LOGOR \DL.BAD.ALIGNMENT 
									   \DL.OVERRUN \DL.BAD.CRC 
									   \DL.ODDLENGTH]
						    \ES.GOOD.PACKET)
						  ((NOT (ZEROP (LOGAND STATUS \DL.OVERRUN)))
						    \ES.OVERRUN)
						  ((NOT (ZEROP (LOGAND STATUS \DL.BAD.CRC)))
						    (COND
						      ((ZEROP (LOGAND STATUS (LOGOR \DL.BAD.ALIGNMENT 
										    \DL.ODDLENGTH)))
							\ES.BAD.CRC)
						      (T \ES.BAD.CRC&ALIGNMENT)))
						  ((NOT (ZEROP (LOGAND STATUS \DL.BAD.ALIGNMENT)))
						    \ES.BAD.ALIGNMENT)
						  (T \ES.OTHER.ERROR]
					 (T                  (* Output errors)
					    (COND
					      ((EQ (fetch DLRETRANSMISSIONMASK of IOCB)
						   17777Q)
						\ES.TOO.MANY.COLLISIONS)
					      (T (COND
						   ((ZEROP (LOGAND STATUS (LOGOR \DL.COLLISION 
										 \DL.UNDERRUN)))
						     \ES.GOOD.PACKET)
						   (T \ES.UNDERRUN]
	     (\NOMACHINETYPE])

(\QUEUE.INPUT.IOCB
  [LAMBDA (NDB IOCB BUFFER LENGTH)                           (* bvm: "16-FEB-83 17:14")

          (* Add IOCB to the end of the microcode input queue, with BUFFER of LENGTH words as its buffer.
	  I.e., this is a buffer that packets will be read into)


    (PROG ((CSB (fetch NDBCSB of NDB)))
          (SELECTC \MACHINETYPE
		   (\DOLPHIN (replace D0NEXTIOCB of IOCB with 0)
			     (replace D0RETRANSMISSIONMASK of IOCB with 0)
			     (replace D0IOCBSTATUS of IOCB with \ES.PENDING)
			     (replace D0IOCBLENGTH of IOCB with (UNFOLD LENGTH BYTESPERWORD))
			     (replace D0IOCBBUFFER of IOCB with BUFFER)
			     [COND
			       ((NEQ (fetch D0FIRSTICB of CSB)
				     0)                      (* There are some packets there, so add this to end)
				 (replace D0NEXTIOCB of (OR (EMPOINTER (fetch D0LASTICB of CSB))
							    (RAID "Garbage last ICB"))
				    with (\LOLOC IOCB]
			     [COND
			       ((AND (ZEROP (fetch D0FIRSTICB of CSB))
				     (EQ (fetch D0IOCBSTATUS of IOCB)
					 \ES.PENDING))

          (* No buffers left, so queue this as the only one. While we were in the last clause, microcode could have eaten up
	  its last buffer, which is why we test twice)


				 (replace D0FIRSTICB of CSB with (\LOLOC IOCB]
			     (replace D0LASTICB of CSB with (\LOLOC IOCB)))
		   (\DANDELION (replace DLFOROUTPUTUSE of IOCB with 0)
                                                             (* So that \10MB.GETPACKETSTATUS can tell which way 
							     packet is going)
			       (replace DLNEXTIOCB of IOCB with 0)
			       (replace DLRETRANSMISSIONMASK of IOCB with 0)
			       (replace DLIOCBSTATUS of IOCB with \ES.PENDING)
			       (replace DLIOCBLENGTH of IOCB with LENGTH)
			       (replace DLIOCBBUFFER of IOCB with BUFFER)
			       [COND
				 ((NEQ (fetch DLFIRSTICB of CSB)
				       0)                    (* There are some packets there, so add this to end)
				   (replace DLNEXTIOCB of (OR (EMPOINTER (fetch DLLASTICB
									    of CSB))
							      (RAID "Garbage last ICB"))
				      with (\LOLOC IOCB]
			       [COND
				 ((AND (ZEROP (fetch DLFIRSTICB of CSB))
				       (EQ (fetch DLIOCBSTATUS of IOCB)
					   \ES.PENDING))

          (* No buffers left, so queue this as the only one. While we were in the last clause, microcode could have eaten up
	  its last buffer, which is why we test twice)


				   (replace DLFIRSTICB of CSB with (\LOLOC IOCB]
			       (replace DLLASTICB of CSB with (\LOLOC IOCB)))
		   (\NOMACHINETYPE])

(\QUEUE.OUTPUT.IOCB
  [LAMBDA (NDB IOCB BUFFER LENGTH)                           (* bvm: "18-FEB-83 18:12")
                                                             (* Queue up IOCB for transmission.
							     LENGTH is length of BUFFER in words)
    (PROG ((CSB (fetch NDBCSB of NDB)))
          (SELECTC \MACHINETYPE
		   (\DOLPHIN (replace D0IOCBLENGTH of IOCB with (UNFOLD LENGTH BYTESPERWORD))
			     (replace D0NEXTIOCB of IOCB with 0)
			     (replace D0RETRANSMISSIONMASK of IOCB with 0)
			     (replace D0IOCBSTATUS of IOCB with \ES.PENDING)
			     (replace D0IOCBBUFFER of IOCB with BUFFER)
			     [COND
			       ((NEQ (fetch D0FIRSTOCB of CSB)
				     0)                      (* Hardware active, add to end of chain)
				 (replace D0NEXTIOCB of (OR (EMPOINTER (fetch D0LASTOCB of CSB))
							    (RAID "Garbage Last OCB"))
				    with (\LOLOC IOCB]
			     [COND
			       ((AND (ZEROP (fetch D0FIRSTOCB of CSB))
				     (EQ (fetch D0IOCBSTATUS of IOCB)
					 \ES.PENDING))       (* Separate check, as the hardware could have just gone 
							     idle since we last checked)
				 (replace D0FIRSTOCB of CSB with (\LOLOC IOCB))
				 (\DEVICE.OUTPUT \D0.ENABLE.10MBOUTPUT (\D0.CONTROLLERBITS NDB 
										  \D0.OUTPUTSTATE]
			     (replace D0LASTOCB of CSB with (\LOLOC IOCB)))
		   (\DANDELION (replace DLFOROUTPUTUSE of IOCB with 1)
                                                             (* So that \10MB.GETPACKETSTATUS can tell which way 
							     packet is going)
			       (replace DLIOCBLENGTH of IOCB with LENGTH)
			       (replace DLNEXTIOCB of IOCB with 0)
			       (replace DLRETRANSMISSIONMASK of IOCB with 0)
			       (replace DLIOCBSTATUS of IOCB with \ES.PENDING)
			       (replace DLIOCBBUFFER of IOCB with BUFFER)
			       [COND
				 ((NEQ (fetch DLFIRSTOCB of CSB)
				       0)                    (* Hardware active, add to end of chain)
				   (replace DLNEXTIOCB of (OR (EMPOINTER (fetch DLLASTOCB
									    of CSB))
							      (RAID "Garbage Last OCB"))
				      with (\LOLOC IOCB]
			       (COND
				 ((AND (ZEROP (fetch DLFIRSTOCB of CSB))
				       (EQ (fetch DLIOCBSTATUS of IOCB)
					   \ES.PENDING))     (* Separate check, as the hardware could have just gone 
							     idle since we last checked)
				   (replace DLFIRSTOCB of CSB with (\LOLOC IOCB))
				   (\DEVICE.OUTPUT \DL.ENABLE.OUTPUT \DL.ETHEROUTPUTREG)))
			       (replace DLLASTOCB of CSB with (\LOLOC IOCB)))
		   (\NOMACHINETYPE])

(\10MB.TURNOFFETHER
  [LAMBDA (NDB)                                              (* bvm: "16-MAR-83 12:49")
    (SELECTC \MACHINETYPE
	     (\DOLPHIN (\D0.TURNOFFETHER NDB))
	     (\DANDELION (\DL.TURNOFFETHER))
	     (\NOMACHINETYPE])

(\10MB.TURNONETHER
  [LAMBDA (NDB SMASHSTATE NEWSTATE NSHOSTNUMBER ININTERRUPT OUTINTERRUPT)
                                                             (* bvm: "17-MAR-83 00:06")

          (* * Reset and activate ether associated with NDB. If SMASHSTATE is given, it is a CSB-length block into which 
	  state is saved for later restoration by passing as the NEWSTATE arg. If NEWSTATE is NIL, then the remaining 
	  non-NIL args give parameters for this activation: the host number for microcode to watch for, T meaning my own 
	  number; and interrupt masks for when a packet arrives or finishes transmitting)


    (PROG ((CSB (fetch NDBCSB of NDB)))
          (SELECTC \MACHINETYPE
		   (\DOLPHIN (\D0.TURNOFFETHER NDB))
		   (\DANDELION (\DL.TURNOFFETHER))
		   (\NOMACHINETYPE))
          [COND
	    (SMASHSTATE (COND
			  (CSB (\BLT SMASHSTATE CSB \CSB.LENGTH))
			  (T                                 (* Arcane way of indicating ether is off.
							     May have to revisit)
			     (\PUTBASE CSB 4 177777Q]
          [COND
	    (NEWSTATE                                        (* Smash old state into CSB)
		      (COND
			((EQ (\GETBASE NEWSTATE 4)
			     177777Q)                        (* Leave ether off)
			  (RETURN)))
		      (\BLT CSB NEWSTATE \CSB.LENGTH))
	    (T (SELECTC \MACHINETYPE
			(\DOLPHIN [OR CSB (replace NDBCSB of NDB
					     with (SETQ CSB
						    (EMPOINTER (IPLUS 177400Q
								      (LLSH (fetch NDBTASK#
									       of NDB)
									    4]
                                                             (* Initialize the Ether CSB according to args.
							     No buffers initially)
				  (replace D0FIRSTOCB of CSB with 0)
				  (replace D0FIRSTICB of CSB with 0)
				  [AND NSHOSTNUMBER (COND
					 ((EQ NSHOSTNUMBER T)
					   (\BLT (LOCF (fetch D0LOCALHOST0 of CSB))
						 (LOCF (fetch (IFPAGE NSHost0) of \InterfacePage))
						 \#WDS.NSHOSTNUMBER))
					 (T (\STORENSHOSTNUMBER (LOCF (fetch D0LOCALHOST0
									 of CSB))
								NSHOSTNUMBER]
				  (AND OUTINTERRUPT (replace D0OUTPUTMASK of CSB with OUTINTERRUPT))
				  (AND ININTERRUPT (replace D0INPUTMASK of CSB with ININTERRUPT))
				  (replace D0LASTICB of CSB with 0)
				  (replace D0LASTOCB of CSB with 0)
				  (\DEVICE.OUTPUT \D0.ENABLE.10MBINPUT (\D0.CONTROLLERBITS NDB 
										   \D0.INPUTSTATE)))
			(PROGN                               (* Dandelion)
			       [OR CSB (replace NDBCSB of NDB with (SETQ CSB
								     (LOCF (fetch DLETHERNET
									      of \IOPAGE]
			       (COND
				 (NEWSTATE                   (* Smash old state into CSB)
					   (COND
					     ((EQ (\GETBASE NEWSTATE 4)
						  177777Q)   (* Leave ether off)
					       (RETURN)))
					   (\BLT CSB NEWSTATE \CSB.LENGTH))
				 (T                          (* Initialize the Ether CSB according to args.
							     No buffers initially)
				    (replace DLFIRSTOCB of CSB with 0)
				    (replace DLFIRSTICB of CSB with 0)
				    [AND NSHOSTNUMBER (COND
					   ((EQ NSHOSTNUMBER T)
					     (\BLT (LOCF (fetch DLLOCALHOST0 of CSB))
						   (LOCF (fetch (IFPAGE NSHost0) of \InterfacePage))
						   \#WDS.NSHOSTNUMBER))
					   (T (\STORENSHOSTNUMBER (LOCF (fetch DLLOCALHOST0
									   of CSB))
								  NSHOSTNUMBER]
				    (AND OUTINTERRUPT (replace DLOUTPUTMASK of CSB with OUTINTERRUPT))
				    (AND ININTERRUPT (replace DLINPUTMASK of CSB with ININTERRUPT))
				    (replace DLMISSEDPACKETS of CSB with 0)
				    (replace DLLASTICB of CSB with 0)
				    (replace DLLASTOCB of CSB with 0)))
			       (\DEVICE.OUTPUT \DL.ENABLE.INPUT \DL.ETHERINPUTREG]
          (SELECTC \MACHINETYPE
		   (\DOLPHIN (\DEVICE.OUTPUT \D0.ENABLE.10MBINPUT (\D0.CONTROLLERBITS NDB 
										   \D0.INPUTSTATE)))
		   (\DEVICE.OUTPUT \DL.ENABLE.INPUT \DL.ETHERINPUTREG))
          (RETURN NDB])
)
(DECLARE: EVAL@COMPILE DONTCOPY 
(DECLARE: EVAL@COMPILE 

(PUTPROPS \D0.CONTROLLERBITS MACRO ((NDB STATE)

          (* Returns a TASKREG argument for use with \DEVICE.INPUT / OUTPUT for controller's STATE reg, 0 <= STATE < 15;
	  \D0.ETHERTASKNUMBER is a global set in initialization)


				    (LOGOR (LLSH (fetch NDBTASK# of NDB)
						 4)
					   STATE)))

(PUTPROPS \D0.TURNOFFETHER MACRO (OPENLAMBDA (NDB)
					     (\D0.STARTIO \D0.RESET.10MBCONTROLLER)))

(PUTPROPS \DL.TURNOFFETHER MACRO [NIL (PROGN (\DEVICE.OUTPUT \DL.TURNOFFETHER \DL.ETHERINPUTREG)
					     (to 3 repeatuntil (ZEROP (LOGAND (\DEVICE.INPUT 
									       \DL.ETHERSTATUSREG)
									      (LOGOR 
										\DL.INPUT.ENABLED 
									       \DL.OUTPUT.ENABLED])
)

[DECLARE: EVAL@COMPILE 

(BLOCKRECORD D0ETHERCSB ((D0FIRSTOCB WORD)                   (* Short pointer to first OCB)
			 (D0OUTPUTMASK WORD)                 (* Bit mask for output interrupt)
			 (D0INPUTMASK WORD)                  (* Bit mask for input interrupt)
			 (D0MISSEDPACKETS WORD)              (* Count of missed packets (for debugging))
			 (D0FIRSTICB WORD)                   (* Short pointer to first ICB)
			 (D0LOCALHOST0 WORD)                 (* Address we are listening for, 48d bits)
			 (D0LOCALHOST1 WORD)
			 (D0LOCALHOST2 WORD)
			 (D0UCODESCRATCH 4 WORD)             (* Scratch buffer for microcode)
			 (D0LASTICB WORD)                    (* Short pointer to last ICB if D0FIRSTICB non-null;
							     not used by microcode)
			 (D0LASTOCB WORD)                    (* last OCB if D0FIRSTOCB non-null)
			 (D0CSBSPARE 2 WORD)))

(BLOCKRECORD D0ETHERIOCB ((D0NEXTIOCB WORD)                  (* Short pointer to next one)
			  (D0RETRANSMISSIONMASK WORD)        (* Retransmission mask, output only)
			  (NIL WORD)
			  (D0IOCBSTATUS WORD)                (* Completion code, filled in by microcode task)
			  (D0IOCBBYTESUSED WORD)             (* Number of bytes received)
			  (D0IOCBLENGTH WORD)                (* Length of buffer in bytes)
			  (D0IOCBBUFFERLO WORD)              (* Long pointer to buffer. Must be locked and quad-1 
							     aligned)
			  (D0IOCBBUFFERHI WORD))
			 [ACCESSFNS D0ETHERIOCB ((D0IOCBBUFFER (\VAG2 (fetch D0IOCBBUFFERHI
									 of DATUM)
								      (fetch D0IOCBBUFFERLO
									 of DATUM))
							       (PROGN (replace D0IOCBBUFFERHI
									 of DATUM
									 with (\HILOC NEWVALUE))
								      (replace D0IOCBBUFFERLO
									 of DATUM
									 with (\LOLOC NEWVALUE])

(BLOCKRECORD DLETHERCSB ((DLLOCALHOST0 WORD)                 (* Address we are listening for, 48d bits)
			 (DLLOCALHOST1 WORD)
			 (DLLOCALHOST2 WORD)
			 (DLFIRSTICB WORD)                   (* Short pointer to first ICB)
			 (DLINPUTMASK WORD)                  (* Bit mask for input interrupt)
			 (DLFIRSTOCB WORD)                   (* Short pointer to first OCB)
			 (DLOUTPUTMASK WORD)                 (* Bit mask for output interrupt)
			 (DLMISSEDPACKETS WORD)              (* Count of missed packets (for debugging))
			 (DLLASTICB WORD)                    (* Short pointer to last ICB if DLFIRSTICB non-null;
							     not used by microcode)
			 (DLLASTOCB WORD)                    (* last OCB if DLFIRSTOCB non-null)
			 ))

(BLOCKRECORD DLETHERIOCB ((DLIOCBLENGTH WORD)                (* Length of buffer in bytes)
			  (DLIOCBBUFFERLO WORD)              (* Long pointer to buffer. Must be locked and quad-1 
							     aligned)
			  (DLIOCBBUFFERHI WORD)
			  (DLRETRANSMISSIONMASK WORD)        (* Retransmission mask, output only)
			  (DLIOCBBYTESUSED WORD)             (* Number of bytes received)
			  (DLIOCBSTATUS WORD)                (* Completion code, filled in by microcode task)
			  (DLNEXTIOCB WORD)                  (* Short pointer to next one)
			  (DLFOROUTPUTUSE WORD)              (* Not used by microcode)
			  )
			 [ACCESSFNS DLETHERIOCB ((DLIOCBBUFFER (\VAG2 (fetch DLIOCBBUFFERHI
									 of DATUM)
								      (fetch DLIOCBBUFFERLO
									 of DATUM))
							       (PROGN (replace DLIOCBBUFFERHI
									 of DATUM
									 with (\HILOC NEWVALUE))
								      (replace DLIOCBBUFFERLO
									 of DATUM
									 with (\LOLOC NEWVALUE])
]

(DECLARE: EVAL@COMPILE 

(RPAQQ \D0.ENABLE.10MBINPUT 49152)

(RPAQQ \D0.ENABLE.10MBOUTPUT 192)

(RPAQQ \D0.RESET.10MBCONTROLLER 512)

(RPAQQ \D0.INPUTSTATE 1)

(RPAQQ \D0.OUTPUTSTATE 2)

(RPAQQ \CSB.LENGTH 16)

(RPAQQ \IOCB.LENGTH 8)

(RPAQQ \MIN2PAGEBUFLENGTH 232)

(RPAQQ \10MB.MINPACKETLENGTH 30)

(CONSTANTS (\D0.ENABLE.10MBINPUT 49152)
	   (\D0.ENABLE.10MBOUTPUT 192)
	   (\D0.RESET.10MBCONTROLLER 512)
	   (\D0.INPUTSTATE 1)
	   (\D0.OUTPUTSTATE 2)
	   (\CSB.LENGTH 16)
	   (\IOCB.LENGTH 8)
	   (\MIN2PAGEBUFLENGTH 232)
	   (\10MB.MINPACKETLENGTH 30))
)


(RPAQQ DLIONETHERCONSTANTS ((\DL.ETHERINPUTREG 5)
			    (\DL.ETHEROUTPUTREG 12)
			    (\DL.ETHERSTATUSREG 1)
			    (\DL.TURNOFFETHER 2)
			    (\DL.ENABLE.OUTPUT 1)
			    (\DL.ENABLE.INPUT 1)
			    (\DL.INPUT.ENABLED 1024)
			    (\DL.OUTPUT.ENABLED 256)))
(DECLARE: EVAL@COMPILE 

(RPAQQ \DL.ETHERINPUTREG 5)

(RPAQQ \DL.ETHEROUTPUTREG 12)

(RPAQQ \DL.ETHERSTATUSREG 1)

(RPAQQ \DL.TURNOFFETHER 2)

(RPAQQ \DL.ENABLE.OUTPUT 1)

(RPAQQ \DL.ENABLE.INPUT 1)

(RPAQQ \DL.INPUT.ENABLED 1024)

(RPAQQ \DL.OUTPUT.ENABLED 256)

(CONSTANTS (\DL.ETHERINPUTREG 5)
	   (\DL.ETHEROUTPUTREG 12)
	   (\DL.ETHERSTATUSREG 1)
	   (\DL.TURNOFFETHER 2)
	   (\DL.ENABLE.OUTPUT 1)
	   (\DL.ENABLE.INPUT 1)
	   (\DL.INPUT.ENABLED 1024)
	   (\DL.OUTPUT.ENABLED 256))
)


(RPAQQ ETHERSTATUSCONSTANTS ((\ES.PENDING 0)
			     (\ES.GOOD.PACKET 1)
			     (\ES.PACKET.TOO.LONG 2)
			     (\ES.BAD.CRC 3)
			     (\ES.BAD.CRC&ALIGNMENT 4)
			     (\ES.BAD.ALIGNMENT 5)
			     (\ES.OVERRUN 6)
			     (\ES.TOO.MANY.COLLISIONS 7)
			     (\ES.UNDERRUN 8)
			     (\ES.LATE.COLLISION 9)
			     (\ES.OTHER.ERROR 10)))
(DECLARE: EVAL@COMPILE 

(RPAQQ \ES.PENDING 0)

(RPAQQ \ES.GOOD.PACKET 1)

(RPAQQ \ES.PACKET.TOO.LONG 2)

(RPAQQ \ES.BAD.CRC 3)

(RPAQQ \ES.BAD.CRC&ALIGNMENT 4)

(RPAQQ \ES.BAD.ALIGNMENT 5)

(RPAQQ \ES.OVERRUN 6)

(RPAQQ \ES.TOO.MANY.COLLISIONS 7)

(RPAQQ \ES.UNDERRUN 8)

(RPAQQ \ES.LATE.COLLISION 9)

(RPAQQ \ES.OTHER.ERROR 10)

(CONSTANTS (\ES.PENDING 0)
	   (\ES.GOOD.PACKET 1)
	   (\ES.PACKET.TOO.LONG 2)
	   (\ES.BAD.CRC 3)
	   (\ES.BAD.CRC&ALIGNMENT 4)
	   (\ES.BAD.ALIGNMENT 5)
	   (\ES.OVERRUN 6)
	   (\ES.TOO.MANY.COLLISIONS 7)
	   (\ES.UNDERRUN 8)
	   (\ES.LATE.COLLISION 9)
	   (\ES.OTHER.ERROR 10))
)


(RPAQQ D0ETHERSTATUSCONSTANTS ((\D0.BAD.ALIGNMENT 2048)
			       (\D0.INPUT.OVERRUN 1024)
			       (\D0.INPUT.BAD.PACKET 512)
			       (\D0.INPUT.BAD.CRC 256)
			       (\D0.OUTPUT.UNDERRUN 64)
			       (\D0.COLLISION 32)
			       (\D0.OUTPUT.BAD.PARITY 128)
			       (\D0.OUTPUT.FAULT 16)
			       (\D0.GOOD.PACKET 16384)
			       (\D0.PACKET.TOO.LONG 25088)
			       (\D0.TOO.MANY.COLLISIONS 25600)
			       (\D0.LATE.COLLISION 26112)
			       (\D0.BUFFER.TOO.SHORT 26624)))
(DECLARE: EVAL@COMPILE 

(RPAQQ \D0.BAD.ALIGNMENT 2048)

(RPAQQ \D0.INPUT.OVERRUN 1024)

(RPAQQ \D0.INPUT.BAD.PACKET 512)

(RPAQQ \D0.INPUT.BAD.CRC 256)

(RPAQQ \D0.OUTPUT.UNDERRUN 64)

(RPAQQ \D0.COLLISION 32)

(RPAQQ \D0.OUTPUT.BAD.PARITY 128)

(RPAQQ \D0.OUTPUT.FAULT 16)

(RPAQQ \D0.GOOD.PACKET 16384)

(RPAQQ \D0.PACKET.TOO.LONG 25088)

(RPAQQ \D0.TOO.MANY.COLLISIONS 25600)

(RPAQQ \D0.LATE.COLLISION 26112)

(RPAQQ \D0.BUFFER.TOO.SHORT 26624)

(CONSTANTS (\D0.BAD.ALIGNMENT 2048)
	   (\D0.INPUT.OVERRUN 1024)
	   (\D0.INPUT.BAD.PACKET 512)
	   (\D0.INPUT.BAD.CRC 256)
	   (\D0.OUTPUT.UNDERRUN 64)
	   (\D0.COLLISION 32)
	   (\D0.OUTPUT.BAD.PARITY 128)
	   (\D0.OUTPUT.FAULT 16)
	   (\D0.GOOD.PACKET 16384)
	   (\D0.PACKET.TOO.LONG 25088)
	   (\D0.TOO.MANY.COLLISIONS 25600)
	   (\D0.LATE.COLLISION 26112)
	   (\D0.BUFFER.TOO.SHORT 26624))
)


(RPAQQ DLETHERSTATUSCONSTANTS ((\DL.COLLISION 64)
			       (\DL.UNDERRUN 32)
			       (\DL.BAD.ALIGNMENT 16)
			       (\DL.OVERRUN 8)
			       (\DL.BAD.CRC 4)
			       (\DL.ODDLENGTH 2)))
(DECLARE: EVAL@COMPILE 

(RPAQQ \DL.COLLISION 64)

(RPAQQ \DL.UNDERRUN 32)

(RPAQQ \DL.BAD.ALIGNMENT 16)

(RPAQQ \DL.OVERRUN 8)

(RPAQQ \DL.BAD.CRC 4)

(RPAQQ \DL.ODDLENGTH 2)

(CONSTANTS (\DL.COLLISION 64)
	   (\DL.UNDERRUN 32)
	   (\DL.BAD.ALIGNMENT 16)
	   (\DL.OVERRUN 8)
	   (\DL.BAD.CRC 4)
	   (\DL.ODDLENGTH 2))
)

(DECLARE: DOEVAL@COMPILE DONTCOPY

(ADDTOVAR GLOBALVARS \IOCB.INPUT.ALLOC \IOCB.INPUT.TOTAL \IOCB.OUTPUT.ALLOC \IOCB.OUTPUT.TOTAL 
	  \IOCBTOTAL \10MB.GETGARBAGE \10MB.RAWPACKETQ \10MB.IDEAL.INPUT.LENGTH \10MB.COLLECTSTATS 
	  \MACHINETYPE \10MBPACKETLENGTH \IOCBFREELIST)
)
)



(* Misc)

(DEFINEQ

(\NOMACHINETYPE
  [LAMBDA NIL                                                (* bvm: "24-JUL-82 17:47")
    (RAID "Operation not implemented on this machine"])
)
(DEFINEQ

(IOCBQLENGTH
  [LAMBDA (FIRSTIOCB)                                        (* bvm: " 2-MAR-83 17:52")
    (OR FIRSTIOCB (SETQ FIRSTIOCB \IOCBFREELIST))
    (while FIRSTIOCB sum (PROGN (SETQ FIRSTIOCB (EMPOINTER (fetch D0NEXTIOCB of FIRSTIOCB)))
				1])
)

(RPAQ? \10MB.GETGARBAGE NIL)

(RPAQ? \10MB.COLLECTSTATS NIL)



(* 3 to 10 kludges)

(DEFINEQ

(\HANDLE.RAW.3TO10
  [LAMBDA (PACKET TYPE)                                      (* bvm: "10-JUN-83 12:40")

          (* 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.3TO10)
	(PROG ((NDB (fetch EPNETWORK of PACKET)))
	      (AND XIPTRACEFLG (\MAYBEPRINTPACKET PACKET (QUOTE GET)))
	      [SELECTC (fetch TRANSOPERATION of PACKET)
		       [\TRANS.OP.REQUEST (COND
					    ((EQ (fetch TRANSPUPHOST of PACKET)
						 (fetch NDBPUPHOST# of NDB))
                                                             (* It's for us)
					      (COND
						((IGEQ (fetch 10MBLENGTH of PACKET)
						       (IPLUS \10MBENCAPSULATION.WORDS
							      (FOLDHI \TRANS.DATALENGTH BYTESPERWORD))
						       )     (* Add sender's address to cache)
						  (\NOTE.3TO10 (fetch TRANSSENDERNSHOST of PACKET)
							       (fetch TRANSSENDERPUPHOST
								  of PACKET)
							       NDB)))
					      (replace TRANSNSHOST of PACKET with (\LOCALNSHOSTNUMBER)
						       )     (* Add in the information he wants)
					      (replace TRANSOPERATION of PACKET with 
									       \TRANS.OP.RESPONSE)
					      (ENCAPSULATE.ETHERPACKET NDB PACKET
								       (fetch TRANSSENDERNSHOST
									  of PACKET)
								       \TRANS.DATALENGTH \EPT.3TO10)
                                                             (* Send back the response)
					      (AND XIPTRACEFLG (NOT (MEMB (QUOTE TRANS)
									  XIPIGNORETYPES))
						   (PRINT3TO10 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.3TO10 (fetch TRANSNSHOST of PACKET)
							(fetch TRANSPUPHOST of PACKET)
							NDB))
		       (COND
			 (XIPTRACEFLG (ERROR "Bad 3:10 operation" PACKET]
	      (\RELEASE.ETHERPACKET PACKET))
	T])

(\TRANSLATE.3TO10
  [LAMBDA (PUPHOSTNUMBER NDB)                                (* bvm: "10-JUN-83 12:40")

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


    (OR [CADR (ASSOC PUPHOSTNUMBER (ffetch NDBTRANSLATIONS of (\DTEST NDB (QUOTE NDB]
	(PROG ((MYPUPHOSTNUMBER (ffetch NDBPUPHOST# of NDB))
	       PACKET)
	      (COND
		((ZEROP MYPUPHOSTNUMBER)                     (* We don't know who we are yet)
		  (RETURN)))
	      (SETQ PACKET (\ALLOCATE.ETHERPACKET))
	      (replace EPTYPE of PACKET with \EPT.3TO10)
	      (freplace TRANSOPERATION of PACKET with \TRANS.OP.REQUEST)
	      (freplace TRANSPUPHOST of PACKET with PUPHOSTNUMBER)
	      (freplace TRANSSENDERNSHOST of PACKET with (\LOCALNSHOSTNUMBER))
	      (freplace TRANSSENDERPUPHOST of PACKET with MYPUPHOSTNUMBER)
	      (ENCAPSULATE.ETHERPACKET NDB PACKET BROADCASTNSHOSTNUMBER \TRANS.DATALENGTH \EPT.3TO10)
	      (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])

(PRINT3TO10
  [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 " 3:10 trans request for "
					      (fetch TRANSPUPHOST of EPKT)
					      " from "
					      (fetch TRANSSENDERPUPHOST of EPKT)
					      " = ")
				    (PRINTNSHOSTNUMBER (fetch TRANSSENDERNSHOST of EPKT)
						       FILE))
		 (\TRANS.OP.RESPONSE (printout FILE CALLER " 3:10 trans response: "
					       (fetch TRANSPUPHOST of EPKT)
					       " = ")
				     (PRINTNSHOSTNUMBER (fetch TRANSNSHOST of EPKT)
							FILE))
		 (printout FILE CALLER " unknown 10 to 3 translation operation "
			   (fetch TRANSOPERATION of EPKT)))
	(TERPRI FILE])

(\NOTE.3TO10
  [LAMBDA (NSHOST PUPHOST NDB)                               (* bvm: "26-MAR-83 15:03")
                                                             (* Update cache to include this pairing)
    (PROG [(A (ASSOC PUPHOST (ffetch NDBTRANSLATIONS of (\DTEST NDB (QUOTE NDB]
          (COND
	    (A (RPLACA (CDR A)
		       NSHOST))
	    (T (push (ffetch NDBTRANSLATIONS of NDB)
		     (LIST PUPHOST NSHOST (CLOCK 0])
)
(DECLARE: EVAL@COMPILE 

(RPAQQ \10MBTYPE.3TO10 513)

(RPAQQ \EPT.3TO10 513)

(CONSTANTS \10MBTYPE.3TO10 \EPT.3TO10)
)

(ADDTOVAR \PACKET.PRINTERS (513 . PRINT3TO10))
(DECLARE: EVAL@COMPILE DONTCOPY 
(FILESLOAD (LOADCOMP)
	   LLETHER LLNS)
)
(PUTPROPS 10MBDRIVER COPYRIGHT ("Xerox Corporation" 1982 1983))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (3803 6885 (\10MBGETPACKET 3813 . 4104) (\10MBSENDPACKET 4106 . 5333) (\10MBENCAPSULATE 
5335 . 5875) (\10MB.BROADCASTP 5877 . 6047) (\10MBWATCHER 6049 . 6883)) (6942 12649 (\10MB.STARTDRIVER
 6952 . 8490) (\10MB.CREATENDB 8492 . 8970) (\10MB.INPUT.INTERRUPT 8972 . 11285) (
\10MB.OUTPUT.INTERRUPT 11287 . 12409) (\10MB.NOTESTAT 12411 . 12647)) (12680 17531 (\10MB.LOADINPUTQ 
12690 . 13303) (\RELEASE.IOCB 13305 . 14068) (\GET.IOCB 14070 . 14955) (\INIT.ETHER.BUFFER.POOL 14957
 . 17529)) (17867 30633 (\10MB.GETPACKETLENGTH 17877 . 18197) (\10MB.GETPACKETSTATUS 18199 . 20611) (
\QUEUE.INPUT.IOCB 20613 . 23449) (\QUEUE.OUTPUT.IOCB 23451 . 26260) (\10MB.TURNOFFETHER 26262 . 26509)
 (\10MB.TURNONETHER 26511 . 30631)) (39707 39886 (\NOMACHINETYPE 39717 . 39884)) (39887 40174 (
IOCBQLENGTH 39897 . 40172)) (40273 45438 (\HANDLE.RAW.3TO10 40283 . 42582) (\TRANSLATE.3TO10 42584 . 
43941) (PRINT3TO10 43943 . 44977) (\NOTE.3TO10 44979 . 45436)))))
STOP