(FILECREATED "14-Aug-85 17:36:32" {ERIS}<LISPCORE>SOURCES>10MBDRIVER.;9 50782  

      changes to:  (MACROS \D0.CONTROLLERBITS \D0.TURNOFFETHER \DL.TURNOFFETHER)
		   (VARS 10MBDRIVERCOMS 10MBDECLARATIONS \10MBENCAPSULATION.WORDS DLIONETHERCONSTANTS 
			 ETHERSTATUSCONSTANTS D0ETHERSTATUSCONSTANTS DLETHERSTATUSCONSTANTS)
		   (RECORDS 10MBENCAPSULATION D0ETHERCSB D0ETHERIOCB DLETHERCSB DLETHERIOCB)
		   (FNS \10MBGETPACKET \10MBSENDPACKET \10MBENCAPSULATE \10MB.BROADCASTP \10MBWATCHER 
			\10MB.STARTDRIVER \10MB.CREATENDB \10MB.INPUT.INTERRUPT 
			\10MB.OUTPUT.INTERRUPT \10MB.NOTESTAT \10MB.LOADINPUTQ \RELEASE.IOCB 
			\GET.IOCB \INIT.ETHER.BUFFER.POOL \10MB.GETPACKETLENGTH \10MB.GETPACKETSTATUS 
			\QUEUE.INPUT.IOCB \QUEUE.OUTPUT.IOCB \10MB.TURNOFFETHER \10MB.TURNONETHER 
			\NOMACHINETYPE IOCBQLENGTH \HANDLE.RAW.3TO10 \TRANSLATE.3TO10 PRINT3TO10 
			\NOTE.3TO10)

      previous date: "26-Jul-85 23:30:01" {ERIS}<LISPCORE>SOURCES>10MBDRIVER.;7)


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

(PRETTYCOMPRINT 10MBDRIVERCOMS)

(RPAQQ 10MBDRIVERCOMS ((COMS (* raw packet interface)
			     (FNS \10MBGETPACKET \10MBSENDPACKET \10MBENCAPSULATE \10MB.BROADCASTP 
				  \10MBWATCHER))
		       (COMS (* Machine independent part)
			     (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)))
		       (COMS (* Dolphin/Dlion head)
			     (FNS \10MB.GETPACKETLENGTH \10MB.GETPACKETSTATUS \QUEUE.INPUT.IOCB 
				  \QUEUE.OUTPUT.IOCB \10MB.TURNOFFETHER \10MB.TURNONETHER)
			     (DECLARE: EVAL@COMPILE DONTCOPY (COMS * 10MBDECLARATIONS)))
		       (COMS (* Misc)
			     (FNS \NOMACHINETYPE)
			     (FNS IOCBQLENGTH))
		       (INITVARS \10MB.GETGARBAGE \10MB.COLLECTSTATS)
		       [COMS (* PUP address resolution)
			     (FNS \HANDLE.RAW.3TO10 \TRANSLATE.3TO10 PRINT3TO10 \NOTE.3TO10)
			     (INITVARS (\10MBTYPE.PUP 512)
				       (\10MBTYPE.3TO10 513))
			     (GLOBALVARS \10MBTYPE.3TO10 \10MBTYPE.PUP)
			     (CONSTANTS \EPT.3TO10)
			     (ADDVARS (\PACKET.PRINTERS (513 . PRINT3TO10]
		       (DECLARE: EVAL@COMPILE DONTCOPY (FILES (LOADCOMP)
							      DOVEETHER LLETHER LLNS))))



(* 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: "26-Apr-84 09:30")
    (PROG ([DROPIT (AND \ETHERLIGHTNING (EQ 0 (RAND 0 \ETHERLIGHTNING]
	   IOCB BUFLENGTH)
          [COND
	    (\RAWTRACING (\MAYBEPRINTPACKET PACKET (QUOTE RAWPUT]
          [COND
	    ((AND (NOT (fetch NDBCANHEARSELF of NDB))
		  (OR (fetch 10MBMULTICASTP of PACKET)
		      (EQNSHOSTNUMBER (fetch 10MBDESTHOST of PACKET)
				      \MY.NSHOSTNUMBER)))    (* We would hear this packet if our hardware let us, so
							     fake receipt)
	      (PROG ((COPYPACKET (\ALLOCATE.ETHERPACKET)))
		    (\BLT (LOCF (fetch 10MBLENGTH of COPYPACKET))
			  (LOCF (fetch 10MBLENGTH of PACKET))
			  (ADD1 (fetch 10MBLENGTH of PACKET)))
                                                             (* Copy all data that would have been transmitted)
		    (replace EPTYPE of COPYPACKET with (fetch 10MBTYPE of PACKET))
		    (replace EPNETWORK of COPYPACKET with NDB)
		    (\ENQUEUE \10MB.RAWPACKETQ COPYPACKET]
          (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: "23-Apr-84 14:34")
    (fetch 10MBMULTICASTP of PACKET])

(\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])
)



(* Machine independent part)

(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: "15-Feb-85 22:18")
    (\10MB.STARTDRIVER (create NDB
			       NDBNSNET# ← 0
			       NDBPUPNET# ← 0
			       NETTYPE ← 10
			       NDBPUPTYPE ← \10MBTYPE.PUP
			       NDBTRANSMITTER ←(FUNCTION \10MBSENDPACKET)
			       NDBENCAPSULATOR ←(FUNCTION \10MBENCAPSULATE)
			       NDBBROADCASTP ←(FUNCTION \10MB.BROADCASTP)
			       NDBTASK# ← ETHERTASK#
			       NDBETHERFLUSHER ←(FUNCTION \10MB.TURNOFFETHER)
			       NDBCANHEARSELF ←(EQ \MACHINETYPE \DOLPHIN])

(\10MB.INPUT.INTERRUPT
  [LAMBDA (NDB)                                              (* ejs: "26-Jul-85 22:36")

          (* 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 (OR (EQ \MACHINETYPE \DANDELION)
				    (EQ \MACHINETYPE \DAYBREAK))
				(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)                                              (* edited: "14-Aug-85 16:46")

          (* 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)


    (DECLARE (GLOBALVARS \10MBLOCALNDB))
    (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))

          (* * I removed the call to HELP that used to be in here. If the IOCB freelist goes NIL, the packet is dropped on the
	  floor)


	(PROG1 \IOCBFREELIST (SETQ \IOCBFREELIST (EMPOINTER (fetch D0NEXTIOCB of \IOCBFREELIST)))
                                                             (* Note that (EMPOINTER 0) = NIL, so this works even 
							     when free list runs out)
	       ])

(\INIT.ETHER.BUFFER.POOL
  [LAMBDA NIL                                                (* ejs: "26-Jul-85 23:14")

          (* 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
	    ((EQ (SETQ ZONELENGTH (fetch (IFPAGE MDSZoneLength) of \InterfacePage))
		 0)                                          (* 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)
					    (SELECTC \MACHINETYPE
						     (\DAYBREAK \DoveEther.IOIOCBLength)
						     \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
									      (SELECTC \MACHINETYPE
										       (\DAYBREAK
											 
									  \DoveEther.IOIOCBLength)
										       \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)



(* Dolphin/Dlion head)

(DEFINEQ

(\10MB.GETPACKETLENGTH
  [LAMBDA (IOCB)                                             (* ejs: "26-Jul-85 22:38")
    (SELECTC \MACHINETYPE
	     (\DANDELION (fetch DLIOCBBYTESUSED of IOCB))
	     (\DAYBREAK (fetch (Dove.EtherIOCB Count) of IOCB))
	     (\DOLPHIN (FOLDLO (fetch D0IOCBBYTESUSED of IOCB)
			       BYTESPERWORD))
	     (\NOMACHINETYPE])

(\10MB.GETPACKETSTATUS
  [LAMBDA (IOCB)                                             (* ejs: "26-Jul-85 22:43")

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



          (* * Now allow odd-length packets to be received)


    (SELECTC \MACHINETYPE
	     [\DANDELION (PROG ((STATUS (fetch DLIOCBSTATUS of IOCB)))
			       (RETURN (COND
					 ((EQ STATUS 0)
					   \ES.PENDING)
					 [(EQ (fetch DLFOROUTPUTUSE of IOCB)
					      0)             (* Input errors)
					   (COND
					     ((EQ (fetch DLIOCBLENGTH of IOCB)
						  65535)
					       \ES.PACKET.TOO.LONG)
					     (T (COND
						  ((EQ (SETQ STATUS (LOGAND STATUS
									    (LOGOR \DL.BAD.ALIGNMENT 
										   \DL.OVERRUN 
										   \DL.BAD.CRC)))
						       0)
						    \ES.GOOD.PACKET)
						  ((NEQ (LOGAND STATUS \DL.OVERRUN)
							0)
						    \ES.OVERRUN)
						  ((NEQ (LOGAND STATUS \DL.BAD.CRC)
							0)
						    (COND
						      ((EQ (LOGAND STATUS (LOGOR \DL.BAD.ALIGNMENT 
										 \DL.ODDLENGTH))
							   0)
							\ES.BAD.CRC)
						      (T \ES.BAD.CRC&ALIGNMENT)))
						  ((NEQ (LOGAND STATUS \DL.BAD.ALIGNMENT)
							0)
						    \ES.BAD.ALIGNMENT)
						  (T \ES.OTHER.ERROR]
					 (T                  (* Output errors)
					    (COND
					      ((EQ (fetch DLRETRANSMISSIONMASK of IOCB)
						   8191)
						\ES.TOO.MANY.COLLISIONS)
					      (T (COND
						   ((EQ (LOGAND STATUS (LOGOR \DL.COLLISION 
									      \DL.UNDERRUN))
							0)
						     \ES.GOOD.PACKET)
						   (T \ES.UNDERRUN]
	     (\DAYBREAK (\DoveEther.GetPacketStatus IOCB))
	     [\DOLPHIN (PROG ((STATUS (fetch D0IOCBSTATUS of IOCB)))
			     (RETURN (SELECTC STATUS
					      (0 \ES.PENDING)
					      (\D0.GOOD.PACKET \ES.GOOD.PACKET)
					      (\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
						((NEQ (LOGAND STATUS \D0.INPUT.OVERRUN)
						      0)
						  \ES.OVERRUN)
						((NEQ (LOGAND STATUS \D0.OUTPUT.UNDERRUN)
						      0)
						  \ES.UNDERRUN)
						(T \ES.OTHER.ERROR]
	     (\NOMACHINETYPE])

(\QUEUE.INPUT.IOCB
  [LAMBDA (NDB IOCB BUFFER LENGTH)                           (* ejs: "26-Jul-85 23:29")

          (* 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
		   (\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 (EQ (fetch DLFIRSTICB of CSB)
					   0)
				       (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)))
		   (\DAYBREAK (\DoveEther.QueueInput IOCB BUFFER LENGTH))
		   (\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 (EQ (fetch D0FIRSTICB of CSB)
					 0)
				     (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)))
		   (\NOMACHINETYPE])

(\QUEUE.OUTPUT.IOCB
  [LAMBDA (NDB IOCB BUFFER LENGTH)                           (* ejs: "26-Jul-85 22:46")
                                                             (* Queue up IOCB for transmission.
							     LENGTH is length of BUFFER in words)
    (PROG ((CSB (fetch NDBCSB of NDB)))
          (SELECTC \MACHINETYPE
		   (\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 (EQ (fetch DLFIRSTOCB of CSB)
					   0)
				       (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)))
		   (\DAYBREAK (\DoveEther.QueueOutput IOCB BUFFER LENGTH))
		   (\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 (EQ (fetch D0FIRSTOCB of CSB)
					 0)
				     (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)))
		   (\NOMACHINETYPE])

(\10MB.TURNOFFETHER
  [LAMBDA (NDB)                                              (* ejs: "26-Jul-85 22:47")
    (SELECTC \MACHINETYPE
	     (\DANDELION (\DL.TURNOFFETHER))
	     (\DAYBREAK (\DoveEther.MakeSureOff))
	     (\DOLPHIN (\D0.TURNOFFETHER NDB))
	     (\NOMACHINETYPE])

(\10MB.TURNONETHER
  [LAMBDA (NDB SMASHSTATE NEWSTATE NSHOSTNUMBER ININTERRUPT OUTINTERRUPT)
                                                             (* ejs: "26-Jul-85 23:01")

          (* * 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)



          (* * For Daybreak, SMASHSTATE and NEWSTATE must be NIL)


    (PROG ((CSB (fetch NDBCSB of NDB)))
          (SELECTC \MACHINETYPE
		   (\DANDELION (\DL.TURNOFFETHER))
		   [\DAYBREAK (\DoveEther.MakeSureOff)
			      (COND
				((OR SMASHSTATE NEWSTATE)
				  (HELP 
			    "SMASHSTATE/NEWSTATE not supported on Daybreak ether initialization!"]
		   (\DOLPHIN (\D0.TURNOFFETHER NDB))
		   (\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 65535]
          [COND
	    (NEWSTATE                                        (* Smash old state into CSB)
		      (COND
			((EQ (\GETBASE NEWSTATE 4)
			     65535)                          (* Leave ether off)
			  (RETURN)))
		      (\BLT CSB NEWSTATE \CSB.LENGTH))
	    (T (SELECTC \MACHINETYPE
			(\DANDELION [OR CSB (replace NDBCSB of NDB
					       with (SETQ CSB (LOCF (fetch DLETHERNET of \IOPAGE]
				    (COND
				      (NEWSTATE              (* Smash old state into CSB)
                                                             (* I don't think you can get here! --ejs)
						(COND
						  ((EQ (\GETBASE NEWSTATE 4)
						       65535)
                                                             (* 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))
			(\DAYBREAK (\DoveEther.TurnOn))
			(\DOLPHIN [OR CSB (replace NDBCSB of NDB
					     with (SETQ CSB
						    (EMPOINTER (IPLUS 65280
								      (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)))
			(\NOMACHINETYPE]
          (SELECTC \MACHINETYPE
		   (\DANDELION (\DEVICE.OUTPUT \DL.ENABLE.INPUT \DL.ETHERINPUTREG))
		   (\DAYBREAK)
		   (\DOLPHIN (\DEVICE.OUTPUT \D0.ENABLE.10MBINPUT (\D0.CONTROLLERBITS NDB 
										   \D0.INPUTSTATE)))
		   (\NOMACHINETYPE))
          (RETURN NDB])
)
(DECLARE: EVAL@COMPILE DONTCOPY 

(RPAQQ 10MBDECLARATIONS ((COMS (RECORDS 10MBENCAPSULATION)
			       (CONSTANTS \10MBENCAPSULATION.WORDS))
			 (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)
			 (CONSTANTS (\MAXLLBUFFERPAGES 2)
				    (\MINLLBUFFERPAGES 1)
				    (\MAXIOCBS 64)
				    (\10MB.MAX.INPUT.LENGTH 20))
			 (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)))
[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)
					   )
					  (BLOCKRECORD 10MBBASE ((NIL WORD)
                                                             (* Length)
							(NIL BITS 7)
							(10MBMULTICASTP FLAG)
							(NIL BITS 8)
                                                             (* Lo bit of first destination byte is the multicast 
							     bit)
							))
					  [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)
)
(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: 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))
)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(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)



(* PUP address resolution)

(DEFINEQ

(\HANDLE.RAW.3TO10
  [LAMBDA (PACKET TYPE)                                      (* bvm: "15-Feb-85 21:11")

          (* 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 \10MBTYPE.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 
								       \10MBTYPE.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: "15-Feb-85 21:11")

          (* 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
		((EQ MYPUPHOSTNUMBER 0)                      (* 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 
				       \10MBTYPE.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: "14-Feb-85 21:21")
    (COND
      ((OR (NOT DOFILTER)
	   (NOT (MEMB (QUOTE TRANS)
		      XIPIGNORETYPES)))
	(OR FILE (SETQ FILE XIPTRACEFILE))
	(FRESHLINE 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])
)

(RPAQ? \10MBTYPE.PUP 512)

(RPAQ? \10MBTYPE.3TO10 513)
(DECLARE: DOEVAL@COMPILE DONTCOPY

(GLOBALVARS \10MBTYPE.3TO10 \10MBTYPE.PUP)
)
(DECLARE: EVAL@COMPILE 

(RPAQQ \EPT.3TO10 513)

(CONSTANTS \EPT.3TO10)
)

(ADDTOVAR \PACKET.PRINTERS (513 . PRINT3TO10))
(DECLARE: EVAL@COMPILE DONTCOPY 
(FILESLOAD (LOADCOMP)
	   DOVEETHER LLETHER LLNS)
)
(PUTPROPS 10MBDRIVER COPYRIGHT ("Xerox Corporation" 1982 1983 1984 1985))
(DECLARE: DONTCOPY
  (FILEMAP (NIL (2398 6489 (\10MBGETPACKET 2408 . 2731) (\10MBSENDPACKET 2733 . 4904) (\10MBENCAPSULATE 
4906 . 5450) (\10MB.BROADCASTP 5452 . 5611) (\10MBWATCHER 5613 . 6487)) (6527 12671 (\10MB.STARTDRIVER
 6537 . 8171) (\10MB.CREATENDB 8173 . 8761) (\10MB.INPUT.INTERRUPT 8763 . 11244) (
\10MB.OUTPUT.INTERRUPT 11246 . 12431) (\10MB.NOTESTAT 12433 . 12669)) (12702 18142 (\10MB.LOADINPUTQ 
12712 . 13337) (\RELEASE.IOCB 13339 . 14142) (\GET.IOCB 14144 . 15224) (\INIT.ETHER.BUFFER.POOL 15226
 . 18140)) (18209 32261 (\10MB.GETPACKETLENGTH 18219 . 18608) (\10MB.GETPACKETSTATUS 18610 . 21156) (
\QUEUE.INPUT.IOCB 21158 . 24168) (\QUEUE.OUTPUT.IOCB 24170 . 27154) (\10MB.TURNOFFETHER 27156 . 27454)
 (\10MB.TURNONETHER 27456 . 32259)) (44306 44489 (\NOMACHINETYPE 44316 . 44487)) (44490 44793 (
IOCBQLENGTH 44500 . 44791)) (44899 50327 (\HANDLE.RAW.3TO10 44909 . 47330) (\TRANSLATE.3TO10 47332 . 
48777) (PRINT3TO10 48779 . 49830) (\NOTE.3TO10 49832 . 50325)))))
STOP