if_sn.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:54k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* if_sn.c - National Semiconductor DP83932B SONIC Ethernet network driver */
  2. /* Copyright 1984-1999 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /* Copyright 1991 Ironics Inc. */
  5. /*
  6. modification history
  7. --------------------
  8. 01w,16mar99,elg  add unsupported features in documentation (SPR 9145).
  9. 01v,15jul97,map  added code to pullup highly fragmented mbufs [SPR# 20843]
  10. 01u,15jul97,spm  added ARP request to SIOCSIFADDR ioctl handler
  11. 01t,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.4
  12. 01s,23apr96,wkm  allow extra space for Sonic buffer overrun, zero sequence cnt
  13. o1r,16jan96,kkk  increase number of TX desc and TX frags.
  14. o1q,13feb95,jdi  doc cleanup.
  15. o1p,18oct93,cd   fixed virtual/physical address confusion, added extra
  16.  debug options, corrected comments.
  17.            +caf  made new snClkEnable() and snClkDisable() routines NOMANUAL.
  18. 01q,11aug93,jmm  Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h
  19. 01p,19feb93,jdi  documentation cleanup.
  20. 01o,06feb93,rfs  Fixed SPR #1990.
  21. 01n,05feb93,rfs  Fixed SPR #1984.
  22. 01m,13oct92,rfs  Added documentation.
  23. 01l,02oct92,rfs  Made multiple attach calls per unit return OK.
  24.                  Adapted to new convention for driver control structure.
  25. 01k,09sep92,gae  documentation tweaks.
  26. 01j,30jul92,dnw  Changed to new cacheLib.
  27.                  Removed cache flushes (except of mbufs) since this driver
  28.                  requires write coherent dma caches.
  29. 01i,16jul92,rfs  Consolidated init() into attach().
  30. 01h,15jul92,rfs  Enabled input hook mechanism.
  31. 01g,14jul92,rfs  Sync'ed up to cache library changes.  Required rewriting of
  32.                  method used to obtain shared memory and aligining it to
  33.                  meet the requirements of the device.
  34. 01f,29jun92,jwt  added RFS changes to support copy-back caches.
  35.     18jun92,jwt  prototyped 5.1 cache library with SPARC targets.
  36.     13apr92,rfs  Needed to subtract FCS from len of Rx packets.
  37.     17mar92,rfs  Verified cache scheme. Dealt with Tx FIFO underrun.
  38.     10mar92,rfs  Reworked cache coherency scheme and misc sanitizing.
  39.     20feb92,rfs  Receive side was hogging the spl semaphore.  It is now
  40.                  given up, and only taken when needed.
  41. 01e,26may92,rrr  the tree shuffle
  42.                  -changed includes to have absolute path from h/
  43. 01d,30jan92,rfs  unANSIized for 5.0.x support.
  44.                  Eliminated many routines and re-ordered routines into
  45.                  logical sections.
  46. 01c,05nov91,rfs  WRSized, genericized, sanitized, revitalized, ANSIized
  47. 01b,29jul91,kjl  clean up in anticipation of beta release
  48. 01a,25mar91,kjl  adapted from WRS if_ln.c 01s,20sep90,dab
  49. */
  50. /*
  51. DESCRIPTION
  52. This module implements the National Semiconductor DP83932 SONIC Ethernet 
  53. network interface driver.
  54. This driver is designed to be moderately generic, operating unmodified
  55. across the range of architectures and targets supported by VxWorks.  
  56. To achieve this, the driver must be given several target-specific
  57. parameters, and some external support routines must be provided.  These
  58. parameters, and the mechanisms used to communicate them to the driver, are
  59. detailed below.  If any of the assumptions stated below are not true for
  60. your particular hardware, this driver will probably not function correctly
  61. with it.  This driver supports up to four individual units per CPU.
  62. BOARD LAYOUT
  63. This device is on-board.  No jumpering diagram is necessary.
  64. EXTERNAL INTERFACE
  65. This driver provides the standard external interface with the following
  66. exceptions.  All initialization is performed within the attach routine;
  67. there is no separate initialization routine.  Therefore, in the global interface
  68. structure, the function pointer to the initialization routine is NULL.
  69. There is one user-callable routine, snattach();
  70. for details, see the manual entry for this routine.
  71. TARGET-SPECIFIC PARAMETERS
  72. .iP "device I/O address"
  73. This parameter is passed to the driver by snattach().
  74. It specifies the base address of the device's I/O register
  75. set.
  76. .iP "interrupt vector"
  77. This parameter is passed to the driver by snattach().
  78. It specifies the interrupt vector to be used by the driver
  79. to service an interrupt from the SONIC device.  The driver will connect
  80. the interrupt handler to this vector by calling intConnect().
  81. .iP "Ethernet address"
  82. This parameter is obtained by calling an external support routine.
  83. It specifies the unique, six-byte address assigned to the VxWorks target
  84. on the Ethernet.
  85. .LP
  86. EXTERNAL SUPPORT REQUIREMENTS
  87. This driver requires five external support functions:
  88. .iP "void sysEnetInit (int unit)" "" 9 -1
  89. This routine performs any target-specific
  90. operations that must be executed before the SONIC
  91. device is initialized.  The driver calls this routine, once per unit, 
  92. from snattach().
  93. .iP "STATUS sysEnetAddrGet (int unit, char *pCopy)"
  94. This routine provides the six-byte Ethernet address used by <unit>.  It
  95. must copy the six-byte address to the space provided by <pCopy>.  This
  96. routine returns OK, or ERROR if it fails.  The driver calls this routine, 
  97. once per unit, from snattach().
  98. .iP "void sysEnetIntEnable (int unit), void sysEnetIntDisable (int unit)"
  99. These routines enable or disable the interrupt from
  100. the SONIC device for the specified <unit>.  Typically,
  101. this involves interrupt controller hardware,
  102. either internal or external to the CPU.  The driver calls these routines 
  103. only during initialization, from snattach().
  104. .iP "void sysEnetIntAck (int unit)"
  105. This routine performs any interrupt acknowledgement or
  106. clearing that may be required.  This typically
  107. involves an operation to some interrupt control
  108. hardware.  The driver calls this routine from the
  109. interrupt handler.
  110. .LP
  111. DEVICE CONFIGURATION
  112. Two global variables, `snDcr' and `snDcr2', are used to set the SONIC
  113. device configuration registers.  By default, the device is programmed in
  114. 32-bit mode with zero wait states.  If these values are not suitable,
  115. the `snDcr' and `snDcr2' variables should be modified before calling
  116. snattach().  See the SONIC manual to change these parameters.
  117. SYSTEM RESOURCE USAGE
  118. When implemented, this driver requires the following system resources:
  119.     
  120.     - one interrupt vector
  121.     - 0 bytes in the initialized data section (data)
  122.     - 696 bytes in the uninitialized data section (BSS)
  123. The above data and BSS requirements are for the MC68020 architecture 
  124. and may vary for other architectures.  Code size (text) varies greatly between
  125. architectures and is therefore not quoted here.
  126. This driver uses cacheDmaMalloc() to allocate the memory to be shared with the
  127. SONIC device.  The size requested is 117,188 bytes.
  128. The SONIC device can only be operated if the shared memory region is
  129. write-coherent with the data cache.  The driver cannot maintain cache
  130. coherency for the device for data that is written by the driver
  131. because fields within the shared structures are asynchronously modified by
  132. the driver and the device, and these fields may share the same cache
  133. line.
  134. NOTE 1
  135. The previous transmit descriptor does not exist until the transmitter
  136. has been asked to send at least one packet.  Unfortunately the test
  137. for this condition must be done every time a new descriptor is to be added,
  138. even though the condition is only true the first time.  However, it
  139. is a valuable test, since we should not use the fragment count field
  140. as an index if it is 0.
  141. NOTE 2
  142. There are some things unsupported in this version:
  143.     a) buffer loaning on receive
  144.     b) output hooks
  145.     c) trailer protocol
  146.     d) promiscuous mode
  147. Also, the receive setup needs work so that the number of RRA descriptors
  148. is not fixed at four.  It would be a nice addition to allow all the
  149. sizes of the shared memory structures to be specified by the runtime
  150. functions that call our init routines.
  151. SEE ALSO: ifLib
  152. */
  153. /*
  154. INTERNAL
  155. This driver contains the conditional compilation switch SN_DEBUG.
  156. If defined, the debug output routines are included.  Output is further
  157. selectable at run-time via the snDebug global variable.
  158. See also the NOTES section at the end of this file.
  159. */
  160. #include "vxWorks.h"
  161. #include "sys/types.h"
  162. #include "taskLib.h"
  163. #include "iv.h"
  164. #include "memLib.h"
  165. #include "sys/ioctl.h"
  166. #include "etherLib.h"
  167. #include "net/mbuf.h"
  168. #include "net/protosw.h"
  169. #include "sys/socket.h"
  170. #include "errno.h"
  171. #include "net/if.h"
  172. #include "net/route.h"
  173. #include "netinet/in.h"
  174. #include "netinet/in_systm.h"
  175. #include "netinet/in_var.h"
  176. #include "netinet/ip.h"
  177. #include "netinet/if_ether.h"
  178. #include "net/if_subr.h"
  179. #include "cacheLib.h"
  180. #include "stdio.h"
  181. #include "intLib.h"
  182. #include "logLib.h"
  183. #include "netLib.h"
  184. /* Tunables needed by device header file */
  185. #define NUM_RRA_DESC  (4)             /* number of RRA descriptors */
  186. #define NUM_RX_DESC   (512)           /* number of Rx descriptors */
  187. #define NUM_TX_DESC   (64)            /* num of Tx desc, must be power of 2 */
  188. #define MAX_TX_FRAGS  (64)            /* max transmit frags to support */
  189. #include "drv/netif/if_sn.h"          /* device description */
  190. /* CONDITIONAL SWITCHES */
  191. /* LOCAL DEFINITIONS */
  192. #define MAX_UNITS   4                   /* max number of units to support */
  193. #define RX_BUF_SIZE (0x2000)            /* size of one receive buffer */
  194.                                         /* total size of receive buffer area */
  195. #define RX_BUF_EXTRA (0x200) /* Extra space needed to accomodate */
  196. /* Sonic buffer overrun in Rev. C */
  197. /* parts - found by Algorithmics  */
  198. #define RBA_SIZE    ((RX_BUF_SIZE + RX_BUF_EXTRA) * NUM_RRA_DESC)
  199. /* Typedefs for external structures that are not typedef'd in their .h files */
  200. typedef struct mbuf MBUF;
  201. typedef struct arpcom IDR;                  /* Interface Data Record wrapper */
  202. typedef struct ifnet IFNET;                 /* real Interface Data Record */
  203. typedef struct sockaddr SOCK;
  204. /* Driver control structure.  One per unit supported. */
  205. typedef struct drv_ctrl
  206.     {
  207.     IDR sn_ac;                          /* Ethernet common part */
  208.     SONIC *pDev;                        /* ptr to the device registers */
  209.     BOOL attached;                      /* indicates unit is attached */
  210.     char *pMem;                         /* ptr to allocated chunk */
  211.     char *pShMem;                       /* ptr to area shared with device */
  212.     unsigned long shMemSize;            /* size of the shared area */
  213.     unsigned long RSA;                  /* Start of Resource Area */
  214.     unsigned long REA;                  /* End of Resource Area */
  215.     unsigned long RBA1;                 /* Start of Receive Buffer Area */
  216.     unsigned long RBA2;                 /* Start of Receive Buffer Area */
  217.     unsigned long RBA3;                 /* Start of Receive Buffer Area */
  218.     unsigned long RBA4;                 /* Start of Receive Buffer Area */
  219.     unsigned long RDA;                  /* Start of Receive Desc Area */
  220.     unsigned long CDA;                  /* Start of CAM Desc Area */
  221.     TX_DESC *pTDA;                      /* Start of Transmit Desc Area */
  222.     TX_DESC *pTXDFree;                  /* ptr to next free TXD */
  223.     TX_DESC *pTXDReclaim;               /* ptr to next reclaimable TXD */
  224.     RX_DESC *pRXDNext;                  /* Next Receive descriptor */
  225.     RX_DESC *pRXDLast;                  /* Last one in link */
  226.     int TxErrs;                         /* transmitter errors */
  227.     FUNCPTR timerIntHandler;
  228.     int  ticks;
  229.     unsigned int imr;
  230.     } DRV_CTRL;
  231. #define DRV_CTRL_SIZ    sizeof(DRV_CTRL)
  232. /* shorthand for some struct members */
  233. #define sn_if       sn_ac.ac_if             /* network-visible interface */
  234. #define sn_enaddr   sn_ac.ac_enaddr         /* hardware Ethernet address */
  235. /* GLOBALS */
  236. unsigned long snDcr = WAIT0 | DW_32;
  237. unsigned long snDcr2 = 0;
  238. #define SN_DEBUG
  239. #ifdef SN_DEBUG
  240. int snDebug;
  241. #define SN_DEBUG_INIT      (snDebug & 0x01)
  242. #define SN_DEBUG_TX        (snDebug & 0x02)
  243. #define SN_DEBUG_RX        (snDebug & 0x04)
  244. #define SN_DEBUG_EVENT     (snDebug & 0x08)
  245. #define SN_DEBUG_VERBOSE   (snDebug & 0x10)
  246. #define SN_DEBUG_TRACE     (snDebug & 0x20)
  247. #endif
  248. /* External function prototypes not defined in any header files.
  249.  * Some of these are the functions required of the BSP modules.
  250.  */
  251. IMPORT STATUS sysEnetAddrGet ();
  252. IMPORT STATUS sysEnetInit ();
  253. IMPORT STATUS sysEnetIntEnable ();
  254. IMPORT STATUS sysEnetIntDisable ();
  255. IMPORT STATUS sysEnetIntAck ();
  256. extern int    splnet ();
  257. extern int    splimp ();
  258. extern void   splx (int x);
  259. /* LOCALS */
  260. /* an array of driver control struct ptrs, one per unit */
  261. LOCAL DRV_CTRL  drvCtrl [MAX_UNITS];
  262. LOCAL void      snIntr ();
  263. LOCAL void      snTxReclaim ();
  264. LOCAL void      snEventHandler ();
  265. LOCAL BOOL      snRxPktReady ();
  266. LOCAL STATUS    snRxPktProcess ();
  267. #ifdef BSD43_DRIVER
  268. LOCAL int       snOutput ();
  269. #endif
  270. LOCAL int       snIoctl ();
  271. LOCAL void      snReset ();
  272. #ifdef BSD43_DRIVER
  273. LOCAL void      snStartOutput ();
  274. #else
  275. LOCAL void  snStartOutput (DRV_CTRL *);
  276. #endif    /* BSD43_DRIVER */
  277. LOCAL void      snChipReset ();
  278. LOCAL void      snChipInit ();
  279. LOCAL void      snCamInit ();
  280. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  281.  * SECTION: Special routines; attach, ioctl, etc.
  282.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  283. /*******************************************************************************
  284. *
  285. * snattach - publish the `sn' network interface and initialize the driver and device
  286. *
  287. * This routine publishes the `sn' interface by filling in a network interface
  288. * record and adding this record to the system list.  It also
  289. * initializes the driver and the device to the operational state.
  290. *
  291. * RETURNS: OK or ERROR.
  292. */
  293. STATUS snattach
  294.     (
  295.     int    unit,       /* unit number */
  296.     char * pDevRegs,   /* addr of device's regs */
  297.     int    ivec        /* vector number */
  298.     )
  299.     {
  300.     u_long   temp;
  301.     DRV_CTRL *pDrvCtrl;
  302. #ifdef SN_DEBUG
  303.     if (SN_DEBUG_INIT)
  304.         logMsg ("snattach: unit=%d, addr=0x%x, vector=0x%xn",
  305.                 unit, (int)pDevRegs, ivec, 0, 0, 0);
  306. #endif /* SN_DEBUG */
  307.     /* Sanity check the unit number */
  308.     if (unit < 0 || unit >= MAX_UNITS)
  309.         return (ERROR);
  310.     /* Ensure single invocation per system life */
  311.     pDrvCtrl = & drvCtrl [unit];
  312.     if (pDrvCtrl->attached)
  313.         return (OK);
  314.     /* Publish driver existance */
  315. #ifdef BSD43_DRIVER
  316.     ether_attach (&pDrvCtrl->sn_if, unit, "sn", (FUNCPTR) NULL, 
  317.                   (FUNCPTR) snIoctl, (FUNCPTR) snOutput, (FUNCPTR) snReset);
  318. #else
  319.     ether_attach ( 
  320.                  &pDrvCtrl->sn_if,
  321.                  unit,
  322.                  "sn",
  323.                  (FUNCPTR) NULL,
  324.                  (FUNCPTR) snIoctl,
  325.                  (FUNCPTR) ether_output,  /* generic output for Ethernet */
  326.                  (FUNCPTR) snReset
  327.                  );
  328.     pDrvCtrl->sn_if.if_start = (FUNCPTR) snStartOutput;
  329. #endif
  330.     pDrvCtrl->pDev = (SONIC *) pDevRegs;             /* save the device ptr */
  331.     /* get an Ethernet addr in a board specific manner */
  332.     if (sysEnetAddrGet (unit, pDrvCtrl->sn_enaddr) == ERROR)
  333.         return (ERROR);
  334.     {   /***** Establish shared memory region *****/
  335.     /* The driver and the device share areas of memory.  Each area has a
  336.      * specific use.  The device imposes a nasty restriction, in that
  337.      * an area's bounds must lie in the same 64k page.  The entire amount of
  338.      * shared memory that is needed is much less than 64k.  Therefore, we
  339.      * will group all the individual areas into one area, and attempt to
  340.      * ensure that this total area lies in a single 64k page.
  341.      *
  342.      * We must also consider data cache coherency of this shared memory.
  343.      * We therefore use the special system functions that allow us to
  344.      * obtain cache-safe memory, or at least allow us to maintain the
  345.      * coherency of this memory ourselves.
  346.      *
  347.      * The first step is to calculate the size of this shared region.
  348.      */
  349.     pDrvCtrl->shMemSize =
  350.                     CAM_SIZE +      /* the area used for Ethernet addrs */
  351.                     RRA_SIZE +      /* the area that describes Rx buffers */
  352.                     RDA_SIZE +      /* the area that holds Rx descriptors */
  353.                     TDA_SIZE +      /* the area that holds Tx descriptors */
  354.                     RBA_SIZE;       /* the area that holds all Rx buffers */
  355.     /* That was easy.  Now we request some memory from the system.
  356.      * For now, we are taking a simple approach.  We simply request one
  357.      * big region, large enough to ensure that we can position our shared
  358.      * area in a single 64k page.  This approach will waste memory, but
  359.      * blame the board designers who picked the SONIC without realizing
  360.      * that the device has this weird restriction.
  361.      */
  362.     if (!CACHE_DMA_IS_WRITE_COHERENT ())
  363.         return (ERROR);
  364.     pDrvCtrl->pMem = cacheDmaMalloc (pDrvCtrl->shMemSize + 0x00010000);
  365.     if (pDrvCtrl->pMem == NULL)                 /* no memory, so abort */
  366.         return (ERROR);
  367.     /* Find start of 64k page in the region.  This becomes start of our
  368.      * region.
  369.      */
  370.     pDrvCtrl->pShMem = (char *)
  371.                        (((u_long)pDrvCtrl->pMem & 0xffff0000) + 0x00010000);
  372.     } /* Block end */
  373.     { /***** Carve up the shared area into specific areas *****/
  374.     /* Block local variables */
  375.     char *pCur;
  376.     pCur = pDrvCtrl->pShMem;                /* start of shared area */
  377.     pDrvCtrl->CDA = (u_long) pCur;          /* CAM area */
  378.     pCur += CAM_SIZE;                       /* advance the pointer */
  379.     pDrvCtrl->RSA = (u_long) pCur;          /* receive resource table */
  380.     pCur += RRA_SIZE;                       /* advance the pointer */
  381.     pDrvCtrl->REA = (u_long) pCur;          /* save end pointer */
  382.     pDrvCtrl->RDA = (u_long) pCur;          /* receive descriptor area */
  383.     pCur += RDA_SIZE;                       /* advance the pointer */
  384.     pDrvCtrl->pTDA = (TX_DESC *)pCur;       /* transmit descriptor area */
  385.     pCur += TDA_SIZE;                       /* advance the pointer */
  386.     pDrvCtrl->RBA1 = (u_long) pCur;         /* Receive Buffer 1 */
  387.     pCur += RX_BUF_SIZE + RX_BUF_EXTRA;     /* advance the pointer */
  388.     pDrvCtrl->RBA2 = (u_long) pCur;         /* Receive Buffer 2 */
  389.     pCur += RX_BUF_SIZE + RX_BUF_EXTRA;     /* advance the pointer */
  390.     pDrvCtrl->RBA3 = (u_long) pCur;         /* Receive Buffer 3 */
  391.     pCur += RX_BUF_SIZE + RX_BUF_EXTRA;     /* advance the pointer */
  392.     pDrvCtrl->RBA4 = (u_long) pCur;         /* Receive Buffer 4 */
  393.     } /* Block end */
  394. #ifdef SN_DEBUG
  395.     if (SN_DEBUG_INIT)
  396.         {
  397.         /* Dump all the resultant region pointers */
  398.         logMsg ("snattach: pDrvCtrl=%x RRA=%x RDA=%x TDA=%xn",
  399.                 (int)pDrvCtrl, pDrvCtrl->RSA,
  400.                 pDrvCtrl->RDA, (int)pDrvCtrl->pTDA, 0, 0);
  401.         logMsg ("snattach: RBA1=%x RBA2=%x RBA3=%x RBA4=%xn",
  402.                 pDrvCtrl->RBA1, pDrvCtrl->RBA2,
  403. pDrvCtrl->RBA3, pDrvCtrl->RBA4, 0, 0);
  404.         }
  405. #endif /* SN_DEBUG */
  406.     { /***** Perform device initialization *****/
  407.     snChipReset (pDrvCtrl);                 /* reset device */
  408.     sysEnetInit (unit);                     /* do any board specific set up */
  409.     sysEnetIntDisable (unit);               /* board specific int disable */
  410.                                             /* connect interrupt */
  411.     (void) intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC(ivec),snIntr,unit);
  412.     {  /* init the Tx descriptors */
  413.     int loopy;
  414.     TX_DESC *pTXD;
  415.     pTXD = pDrvCtrl->pTDA;                      /* get initial ptr */
  416.     bzero ((char *)pTXD, TDA_SIZE);             /* zero the whole enchilada */
  417.     loopy = NUM_TX_DESC;
  418.     while (loopy--)                             /* loop thru each */
  419.         {
  420.         pTXD->pLink = pTXD + 1;                 /* link to next */
  421.         pTXD++;                                 /* bump to next */
  422.         }
  423.     /* The link field of the last desc is special; it needs to point
  424.      * back to the first desc.  So, we fix it here.
  425.      */
  426.     (--pTXD)->pLink = pDrvCtrl->pTDA;
  427.     pDrvCtrl->pTXDFree = pDrvCtrl->pTDA;              /* initial value */
  428.     pDrvCtrl->pTXDReclaim = pDrvCtrl->pTDA;           /* initial value */
  429.     }
  430.     {  /* init the Rx buffer descriptors */
  431.     RRA_DESC *pRRAD;                            /* RRA working descriptor */
  432.     /* Build the RRA */
  433.     pRRAD = (RRA_DESC *)pDrvCtrl->RSA;           /* get ptr to first entry */
  434.     /* Stuff buffer ptr; least significant 16 bits, then most significant 16 */
  435.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->RBA1);
  436.     pRRAD->buff_ptr0 = temp & UMASK;
  437.     pRRAD->buff_ptr1 = temp >> 16;
  438.     /* Stuff word count; least significant 16 bits, then most significant 16 */
  439.     pRRAD->buff_wc0 = RX_BUF_SIZE >> 1 & UMASK;
  440.     pRRAD->buff_wc1 = RX_BUF_SIZE >> 1 >> 16;
  441.     pRRAD++;                                    /* bump to next entry */
  442.     /* Stuff buffer ptr; least significant 16 bits, then most significant 16 */
  443.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->RBA2);
  444.     pRRAD->buff_ptr0 = (u_long) temp & UMASK;
  445.     pRRAD->buff_ptr1 = (u_long) temp >> 16;
  446.     /* Stuff word count; least significant 16 bits, then most significant 16 */
  447.     pRRAD->buff_wc0 = RX_BUF_SIZE >> 1 & UMASK;
  448.     pRRAD->buff_wc1 = RX_BUF_SIZE >> 1 >> 16;
  449.     pRRAD++;                                    /* bump to next entry */
  450.     /* Stuff buffer ptr; least significant 16 bits, then most significant 16 */
  451.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->RBA3);
  452.     pRRAD->buff_ptr0 = (u_long) temp & UMASK;
  453.     pRRAD->buff_ptr1 = (u_long) temp >> 16;
  454.     /* Stuff word count; least significant 16 bits, then most significant 16 */
  455.     pRRAD->buff_wc0 = RX_BUF_SIZE >> 1 & UMASK;
  456.     pRRAD->buff_wc1 = RX_BUF_SIZE >> 1 >> 16;
  457.     pRRAD++;                                    /* bump to next entry */
  458.     /* Stuff buffer ptr; least significant 16 bits, then most significant 16 */
  459.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->RBA4);
  460.     pRRAD->buff_ptr0 = (u_long) temp & UMASK;
  461.     pRRAD->buff_ptr1 = (u_long) temp >> 16;
  462.     /* Stuff word count; least significant 16 bits, then most significant 16 */
  463.     pRRAD->buff_wc0 = RX_BUF_SIZE >> 1 & UMASK;
  464.     pRRAD->buff_wc1 = RX_BUF_SIZE >> 1 >> 16;
  465.     }
  466.     { /* Setup the Rx frame descriptors */
  467.     RX_DESC *pRXD;                              /* Rx working descriptor */
  468.     pRXD = (RX_DESC *) pDrvCtrl->RDA;           /* get initial ptr */
  469.     bzero ((char *)pRXD, RDA_SIZE);             /* zero the whole tomato */
  470.     pDrvCtrl->pRXDNext = pRXD;                  /* start from the start! */
  471.     pDrvCtrl->pRXDLast =                        /* stuff ptr to last */
  472.                     (RX_DESC *) ((u_long)pRXD + RDA_SIZE - RX_DESC_SIZ);
  473.     while (pRXD <= pDrvCtrl->pRXDLast)          /* loop thru each */
  474.         {
  475.         pRXD->in_use = NOT_IN_USE;              /* set NOT_IN_USE */
  476.         pRXD->link =                            /* set link */
  477.             (RX_DESC *) CACHE_DMA_VIRT_TO_PHYS (pRXD + 1);
  478.         pRXD++;                                 /* bump to next */
  479.         }
  480.     /* The link field of the last desc is special; it points nowhere,
  481.      * but must mark the end-of-list.  So, we fix it here.
  482.      */
  483.     pDrvCtrl->pRXDLast->link = RX_EOL;
  484.     }
  485.     /* Enable device interrupts at system level */
  486.     sysEnetIntEnable (unit);
  487.     /* Bring up the device */
  488.     snChipInit (pDrvCtrl);
  489.     } /* Block end */
  490.     /* Set flags */
  491.     pDrvCtrl->attached = TRUE;
  492.     pDrvCtrl->sn_ac.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);
  493.     return (OK);
  494.     } /* End of snattach() */
  495. /*******************************************************************************
  496. *
  497. * snReset - reset the interface
  498. *
  499. * Mark interface as inactive & reset the chip
  500. * This is one of the routines that can be called from "outside" via
  501. * the interface structure.
  502. * Cannot be called before the attach, since DRV_CTRL ptr would be NULL.
  503. */
  504. LOCAL void snReset (unit)
  505.     int unit;
  506.     {
  507.     DRV_CTRL *pDrvCtrl;
  508. #ifdef SN_DEBUG
  509.     if (SN_DEBUG_INIT)
  510.         logMsg ("sn: Reset: unit=%dn", unit, 0, 0, 0, 0, 0);
  511. #endif /* SN_DEBUG */
  512.     pDrvCtrl = & drvCtrl [unit];
  513.     pDrvCtrl->sn_if.if_flags = 0;
  514.     snChipReset (pDrvCtrl);                            /* reset device */
  515.     }
  516. /*******************************************************************************
  517. *
  518. * snChipReset - Place chip in Reset mode
  519. */
  520. LOCAL void snChipReset (pDrvCtrl)
  521.     DRV_CTRL *pDrvCtrl;
  522.     {
  523.     pDrvCtrl->pDev->cr = RST;
  524.     pDrvCtrl->pDev->rsc = 0;  /* set the sequence counter to zero */
  525.     }
  526. /*******************************************************************************
  527. *
  528. * snChipInit - hardware init of chip (init & start it)
  529. */
  530. LOCAL void snChipInit (pDrvCtrl)
  531.     DRV_CTRL *pDrvCtrl;
  532.     {
  533.     SONIC *pDev;                            /* ptr to the device regs */
  534.     u_long temp;
  535.     pDev = pDrvCtrl->pDev;
  536. #ifdef SN_DEBUG
  537.     if (SN_DEBUG_INIT)
  538.         logMsg ("sn: Chip init: pDrvCtrl=0x%Xn", (int)pDrvCtrl, 0, 0, 0, 0, 0);
  539. #endif /* SN_DEBUG */
  540.     pDev->cr = RST;                     /* Turn ON RESET */
  541.                                         /* Data Control */
  542.     pDev->dcr = snDcr;
  543.     if (snDcr2)
  544. pDev->dcr2 = snDcr2;
  545.     pDev->imr = 0;                      /* All Interrupts off */
  546.     pDev->isr = 0x7fff;                 /* Clear ISR */
  547.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->RSA);
  548.     pDev->urra = temp >> 16;            /* Upper RSA */
  549.     pDev->rsa = temp & UMASK;           /* Lower RSA */
  550.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->REA);
  551.     pDev->rea = temp & UMASK;           /* Lower REA */
  552.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->RSA);
  553.     pDev->rrp = temp & UMASK;           /* point to first desc */
  554.     pDev->rwp = temp & UMASK;           /* point to first desc */
  555.     pDev->rsc = 0;
  556.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->RDA);
  557.     pDev->urda = temp >> 16;            /* Upper RDA */
  558.     pDev->crda = temp & UMASK;          /* Lower RDA */
  559.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->pTDA);
  560.     pDev->utda = temp >> 16;            /* first TXD */
  561.     pDev->ctda = temp & UMASK;
  562.     pDev->cr = RST_OFF;                 /* Turn OFF RESET */
  563.     pDev->cr = RRRA;                    /* prime with RRA read */
  564.     snCamInit (pDrvCtrl);               /* Initialize the CAM */
  565.     pDev->rcr = BRD;
  566.     if (pDev->imr & TCEN)
  567. {
  568. pDev->wt0 = pDrvCtrl->ticks & 0xffff;
  569. pDev->wt1 = pDrvCtrl->ticks >> 16;
  570. pDev->cr = ST;
  571. }
  572.     pDev->imr = (pDrvCtrl->imr |= PRXEN); /* Enable these IRQ's */
  573.     pDev->cr = RXEN;                    /* Turn on Receiver */
  574.     }
  575. /*******************************************************************************
  576. *
  577. * snCamInit - put the local Ethernet address in the CAM
  578. *
  579. * First we set up a data area with the enet addr, then we tell the device
  580. * where it is and command the device to read it.  When the device is done,
  581. * it will interrupt us.  We wait for this interrupt with a semaphore that
  582. * will be given by the interrupt handler.
  583. */
  584. LOCAL void snCamInit (pDrvCtrl)
  585.     DRV_CTRL *pDrvCtrl;
  586.     {
  587.     SONIC *pDev;                         /* ptr to the device regs */
  588.     int jj;
  589.     u_long *CamData;
  590.     CamData = (unsigned long *) pDrvCtrl->CDA;
  591.     pDev = pDrvCtrl->pDev;
  592.     jj = 0;
  593.     CamData [jj++] = 0;                            /* Entry 0 */
  594.     CamData [jj++] = pDrvCtrl->sn_enaddr [1] << 8 | pDrvCtrl->sn_enaddr [0];
  595.     CamData [jj++] = pDrvCtrl->sn_enaddr [3] << 8 | pDrvCtrl->sn_enaddr [2];
  596.     CamData [jj++] = pDrvCtrl->sn_enaddr [5] << 8 | pDrvCtrl->sn_enaddr [4];
  597.     CamData [jj]   = 0x1;                          /* Enable entry 0 */
  598.     pDev->cdc = 1;                                 /* One entry */
  599.     pDev->cdp = (u_long) CACHE_DMA_VIRT_TO_PHYS (pDrvCtrl->CDA) & UMASK;
  600.     pDev->cr = LCAM;                               /* issue "load CAM" cmd */
  601.     /* Wait for operation to complete.  A "dead time" loop here is deemed
  602.      * OK, since we are in initialization phase, and will only do this
  603.      * once.
  604.      */
  605.     while (!(pDev->isr & LCD))
  606.         ;
  607.     pDev->isr = LCD;                        /* clear the event flag */
  608.     }
  609. /*******************************************************************************
  610. *
  611. * snIoctl - the driver I/O control function
  612. *
  613. * Process an ioctl request.
  614. * This is one of the routines that can be called from "outside" via
  615. * the interface structure.
  616. * Cannot be called before the attach, since DRV_CTRL ptr would be NULL.
  617. */
  618. LOCAL int snIoctl (IDR *pIDR, int cmd, caddr_t data)
  619.     {
  620.     int error;
  621.     error = 0;
  622. #ifdef SN_DEBUG
  623.     if (SN_DEBUG_INIT)
  624. logMsg ("sn: Ioctl: pIDR=0x%x, cmd=0x%x, data=0x%xn",
  625.                (int)pIDR, (int)cmd, (int)data, 0, 0, 0);
  626. #endif /* SN_DEBUG */
  627.     switch (cmd)
  628.         {
  629.         case SIOCSIFADDR:
  630.             ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr;
  631.             arpwhohas (pIDR, &IA_SIN (data)->sin_addr);
  632.             break;
  633.         case SIOCSIFFLAGS:
  634.             /* Flags are set outside this module. No additional work to do. */
  635.             break;
  636.         default:
  637.             error = EINVAL;
  638.         }
  639.     return (error);
  640.     }
  641. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  642.  * SECTION: Transmit related routines
  643.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  644. #ifdef BSD43_DRIVER
  645. /*******************************************************************************
  646. *
  647. * snOutput - adds new output to the driver's queue and calls output routine
  648. *
  649. * This is the driver output rotuine.  This is one of the routines that is
  650. * called from "outside" via the interface structure, ifnet.
  651. */
  652. LOCAL int snOutput (pIfnet, pMbuf, pDest)
  653.     IFNET *pIfnet;
  654.     MBUF *pMbuf;
  655.     SOCK *pDest;
  656.     {
  657.     DRV_CTRL *pDrvCtrl;
  658.     int spl;
  659.     pDrvCtrl = & drvCtrl [pIfnet->if_unit];
  660.     spl = splnet ();
  661.     if (IF_QFULL (&pIfnet->if_snd))                /* If the queue is full */
  662.         snStartOutput (pIfnet->if_unit);
  663.     splx (spl);
  664.     return (ether_output (pIfnet, pMbuf, pDest, (FUNCPTR) snStartOutput,
  665.               &pDrvCtrl->sn_ac));
  666.     }
  667. /*******************************************************************************
  668. *
  669. * snStartOutput - start pending output
  670. *
  671. * This routine removes mbuf chains from the driver queue and attempts to
  672. * set up a SONIC transmit descriptor for each chain.  The transmit descriptors
  673. * are fed to the SONIC and subsequently transmitted onto the media.
  674. */
  675. LOCAL void snStartOutput (unit)
  676.     int unit;
  677.     {
  678.     DRV_CTRL       *pDrvCtrl;
  679.     MBUF           *pMbuf;
  680.     MBUF           *pMbufTemp;
  681.     TX_DESC        *pTXD;
  682.     int            len;
  683.     int            adj_len;
  684.     int            fragIndex;
  685.     int            nUseableFrags;
  686.     char           *m_data;
  687.     u_long    temp;
  688.     pDrvCtrl = & drvCtrl [unit];
  689.     /* Loop as long as our incoming queue is not empty */
  690.     while (pDrvCtrl->sn_if.if_snd.ifq_head != NULL)
  691.         {
  692.         IF_DEQUEUE (&pDrvCtrl->sn_if.if_snd, pMbuf);
  693.         /* call output hook if any */
  694.         /* etherOutputHookRtn not supported.
  695.          * This would require copying mbufs to contiguous buf.
  696.          *  if ((etherOutputHookRtn != NULL) &&
  697.          *      (* etherOutputHookRtn) (&pDrvCtrl->sn_if, buf, len))
  698.          *      continue;
  699.          */
  700.         /* Calculate length  & number of fragments */
  701. #ifdef SN_DEBUG
  702. if (SN_DEBUG_TRACE)
  703.     {
  704.     static char buf[ETHERMTU];
  705.     struct ether_header *pPktHdr;        /* ptr to packet header */
  706.     FAST char *p = buf;
  707.     FAST struct mbuf *m = pMbuf;
  708.     for (; m != NULL; p += m->m_len, m = m->m_next)
  709. bcopy (mtod (m, char *), p, m->m_len);
  710.     pPktHdr = (struct ether_header *)&buf;
  711.     logMsg ("sn: Tx: packet type 0x%x from %s",
  712.     pPktHdr->ether_type,
  713.     (int)ether_sprintf (&pPktHdr->ether_shost), 0, 0, 0, 0);
  714.     logMsg (" to %sn", (int)ether_sprintf (&pPktHdr->ether_dhost), 0, 0, 0, 0, 0);
  715.     }
  716. #endif
  717.         pMbufTemp     = pMbuf;
  718.         len           =
  719.         nUseableFrags = 0;
  720.         while (pMbufTemp != NULL)            /* while valid pointer */
  721.             {
  722.             if (pMbufTemp->m_len)        /* only count non-zero length frags */
  723.                 {
  724.                 len += pMbufTemp->m_len;     /* add length of this fragment */
  725.                 nUseableFrags++;             /* bump fragment counter */
  726.                 }
  727.             pMbufTemp = pMbufTemp->m_next;   /* advance to next mbuf fragment */
  728.             }
  729.         /* Bail out if too many frags */
  730.         if (nUseableFrags >= MAX_TX_FRAGS)
  731.             {
  732.             logMsg ("sn: Tx: too many mbuf fragmentsn",0,0,0,0,0,0);
  733.             m_freem (pMbuf);                      /* packet is thrown away */
  734.             pDrvCtrl->sn_if.if_opackets--;        /* correct the stats */
  735.             pDrvCtrl->sn_if.if_oerrors++;
  736.             continue;
  737.             }
  738.         /* See if next transmit descriptor is available */
  739.         pTXD = pDrvCtrl->pTXDFree;
  740.         if (pTXD->flag)                           /* still in use */
  741.             {
  742.             m_freem (pMbuf);                      /* packet is thrown away */
  743.             pDrvCtrl->sn_if.if_opackets--;        /* correct the stats */
  744.             pDrvCtrl->sn_if.if_oerrors++;
  745. #ifdef SN_DEBUG
  746.             if (SN_DEBUG_TX)
  747.                 logMsg ("sn: Tx, no descriptors", 0, 0, 0, 0, 0, 0);
  748. #endif /* SN_DEBUG */
  749.             break;
  750.             }
  751.         /* Mark this descriptor as "in use" */
  752.         pTXD->flag   = TRUE;
  753.         pTXD->status = 0;
  754. /* remember the mbuf associated with this packet */
  755. pTXD->pMbuf = pMbuf;
  756.         /* Ensure we send a minimum sized packet */
  757.         adj_len = max (ETHERSMALL, len);
  758.         /* Build a transmit descriptor.
  759.          * Loop thru each fragment in the mbuf chain and stuff our info.
  760.          */
  761.         for (
  762.             fragIndex = 0, pMbufTemp = pMbuf;
  763.             pMbufTemp != NULL;                  /* while valid mbuf pointer */
  764.             pMbufTemp = pMbufTemp->m_next       /* advance to next mbuf frag */
  765.             )
  766.             {
  767.             /* ignore zero-length mbufs */
  768.             if ( pMbufTemp->m_len == 0 )
  769.                 continue;
  770.             m_data = mtod(pMbufTemp, char *);   /* get pointer to mbuf data */
  771.             /* ensure data is flushed */
  772.             CACHE_USER_FLUSH (m_data, pMbufTemp->m_len);
  773. #ifdef notdef
  774.     /* This is what we should be able to do... */
  775.     temp = (u_long) CACHE_DRV_VIRT_TO_PHYS (&cacheUserFuncs, m_data);
  776. #else
  777.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (m_data);
  778. #endif
  779.             pTXD->frag [fragIndex].frag_ptr0 = (u_long) temp & UMASK;
  780.             pTXD->frag [fragIndex].frag_ptr1 = (u_long) temp >> 16;
  781.             pTXD->frag [fragIndex].frag_size = pMbufTemp->m_len;
  782.             fragIndex++;
  783.             }
  784.         pTXD->pkt_size   = adj_len;                    /* set packet length */
  785.         pTXD->frag_count = fragIndex;                  /* set fragment count */
  786.         if (adj_len != len)                            /* pad pkt size to min */
  787.             pTXD->frag [fragIndex-1].frag_size += (adj_len-len);
  788.         /* copy link field to where device will expect it */
  789.         pTXD->frag [fragIndex].frag_ptr0 =
  790.             (u_long) CACHE_DMA_VIRT_TO_PHYS (pTXD->pLink) | TX_EOL;
  791. #ifdef SN_DEBUG
  792.         if (SN_DEBUG_TX && SN_DEBUG_VERBOSE)
  793.             logMsg ("sn: Tx: pTXD=%xn", (int)pTXD, 0, 0, 0, 0, 0);
  794. #endif /* SN_DEBUG */
  795.         /* Find previous desc in chain. (see NOTE #1)
  796.          * If prev desc has been used, then get a ptr to the actual
  797.          * link field within the desc, and clear the EOL bit.
  798.          */
  799.         {
  800.         TX_DESC *pPrevTXD;
  801.         u_long *pLink;
  802.         if (pTXD == pDrvCtrl->pTDA)
  803.             pPrevTXD = ((TX_DESC *)((char *)pDrvCtrl->pTDA + TDA_SIZE)) - 1;
  804.         else
  805.             pPrevTXD = pTXD - 1;
  806.         if (pPrevTXD->frag_count)
  807.             {
  808.             pLink = & pPrevTXD->frag [pPrevTXD->frag_count].frag_ptr0;
  809.             *pLink &= ~TX_EOL;
  810.             }
  811.         }
  812.         
  813.         /* start the transmitter */
  814.         pDrvCtrl->pDev->cr = TXP;
  815.         /* And finally, adjust pointer to next TXD. */
  816.         pDrvCtrl->pTXDFree = pTXD->pLink;
  817.         }
  818.     }
  819. #else
  820. /*******************************************************************************
  821. *
  822. * snStartOutput - start pending output
  823. *
  824. * This routine removes mbuf chains from the driver queue and attempts to
  825. * set up a SONIC transmit descriptor for each chain.  The transmit descriptors
  826. * are fed to the SONIC and subsequently transmitted onto the media.
  827. */
  828. LOCAL void snStartOutput 
  829.     (
  830.     DRV_CTRL *  pDrvCtrl
  831.     )
  832.     {
  833.     MBUF           *pMbuf;
  834.     MBUF           *pMbufTemp;
  835.     TX_DESC        *pTXD;
  836.     int            len;
  837.     int            adj_len;
  838.     int            fragIndex;
  839.     int            nUseableFrags;
  840.     char           *mbuf_data;
  841.     u_long    temp;
  842.     /* Loop as long as our incoming queue is not empty */
  843.     while (pDrvCtrl->sn_ac.ac_if.if_snd.ifq_head != NULL)
  844.         {
  845.         IF_DEQUEUE (&pDrvCtrl->sn_if.if_snd, pMbuf);
  846.         /* call output hook if any */
  847.         /* etherOutputHookRtn not supported.
  848.          * This would require copying mbufs to contiguous buf.
  849.          *  if ((etherOutputHookRtn != NULL) &&
  850.          *      (* etherOutputHookRtn) (&pDrvCtrl->sn_if, buf, len))
  851.          *      continue;
  852.          */
  853.         /* Calculate length  & number of fragments */
  854. #ifdef SN_DEBUG
  855. if (SN_DEBUG_TRACE)
  856.     {
  857.     static char buf[ETHERMTU];
  858.     struct ether_header *pPktHdr;        /* ptr to packet header */
  859.     FAST char *p = buf;
  860.     FAST struct mbuf *m = pMbuf;
  861.     for (; m != NULL; p += m->m_len, m = m->m_next)
  862. bcopy (mtod (m, char *), p, m->m_len);
  863.     pPktHdr = (struct ether_header *)&buf;
  864.     logMsg ("sn: Tx: packet type 0x%x from %s",
  865.     pPktHdr->ether_type,
  866.     (int)ether_sprintf (&pPktHdr->ether_shost), 0, 0, 0, 0);
  867.     logMsg (" to %sn", (int)ether_sprintf (&pPktHdr->ether_dhost), 0, 0, 0, 0, 0);
  868.     }
  869. #endif
  870.         pMbufTemp     = pMbuf;
  871.         len           =
  872.         nUseableFrags = 0;
  873.         while (pMbufTemp != NULL)            /* while valid pointer */
  874.             {
  875.             if (pMbufTemp->m_len)        /* only count non-zero length frags */
  876.                 {
  877.                 len += pMbufTemp->m_len;     /* add length of this fragment */
  878.                 nUseableFrags++;             /* bump fragment counter */
  879.                 }
  880.             pMbufTemp = pMbufTemp->m_next;   /* advance to next mbuf fragment */
  881.             }
  882.         /* Pull up the mbuf, if too many frags */
  883.         if (nUseableFrags >= MAX_TX_FRAGS)
  884.             {
  885.              pMbufTemp = pMbuf;
  886.              pMbuf = m_pullup (pMbufTemp, len);
  887.              m_freem (pMbufTemp);
  888.              if (pMbuf == NULL)
  889.                  continue;
  890.             }
  891.         /* See if next transmit descriptor is available */
  892.         pTXD = pDrvCtrl->pTXDFree;
  893.         if (pTXD->flag)                           /* still in use */
  894.             {
  895.             m_freem (pMbuf);                      /* packet is thrown away */
  896.             pDrvCtrl->sn_if.if_oerrors++;
  897. #ifdef SN_DEBUG
  898.             if (SN_DEBUG_TX)
  899.                 logMsg ("sn: Tx, no descriptors", 0, 0, 0, 0, 0, 0);
  900. #endif /* SN_DEBUG */
  901.             break;
  902.             }
  903.         /* Mark this descriptor as "in use" */
  904.         pTXD->flag   = TRUE;
  905.         pTXD->status = 0;
  906. /* remember the mbuf associated with this packet */
  907. pTXD->pMbuf = pMbuf;
  908.         /* Ensure we send a minimum sized packet */
  909.         adj_len = max (ETHERSMALL, len);
  910.         /* Build a transmit descriptor.
  911.          * Loop thru each fragment in the mbuf chain and stuff our info.
  912.          */
  913.         fragIndex = 0;
  914.         for (pMbufTemp = pMbuf; pMbufTemp != NULL; 
  915.              pMbufTemp = pMbufTemp->m_next)
  916.             {
  917.             /* ignore zero-length mbufs */
  918.             if ( pMbufTemp->m_len == 0 )
  919.                 continue;
  920.             mbuf_data = mtod(pMbufTemp, char *); /* get pointer to mbuf data */
  921.             /* ensure data is flushed */
  922.             CACHE_USER_FLUSH (mbuf_data, pMbufTemp->m_len);
  923. #ifdef notdef
  924.     /* This is what we should be able to do... */
  925.     temp = (u_long) CACHE_DRV_VIRT_TO_PHYS (&cacheUserFuncs, mbuf_data);
  926. #else
  927.     temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (mbuf_data);
  928. #endif
  929.             pTXD->frag [fragIndex].frag_ptr0 = (u_long) temp & UMASK;
  930.             pTXD->frag [fragIndex].frag_ptr1 = (u_long) temp >> 16;
  931.             pTXD->frag [fragIndex].frag_size = pMbufTemp->m_len;
  932.             fragIndex++;
  933.             }
  934.         pTXD->pkt_size   = adj_len;                    /* set packet length */
  935.         pTXD->frag_count = fragIndex;                  /* set fragment count */
  936.         if (adj_len != len)                            /* pad pkt size to min */
  937.             pTXD->frag [fragIndex-1].frag_size += (adj_len-len);
  938.         /* copy link field to where device will expect it */
  939.         pTXD->frag [fragIndex].frag_ptr0 =
  940.             (u_long) CACHE_DMA_VIRT_TO_PHYS (pTXD->pLink) | TX_EOL;
  941. #ifdef SN_DEBUG
  942.         if (SN_DEBUG_TX && SN_DEBUG_VERBOSE)
  943.             logMsg ("sn: Tx: pTXD=%xn", (int)pTXD, 0, 0, 0, 0, 0);
  944. #endif /* SN_DEBUG */
  945.         /* Find previous desc in chain. (see NOTE #1)
  946.          * If prev desc has been used, then get a ptr to the actual
  947.          * link field within the desc, and clear the EOL bit.
  948.          */
  949.         {
  950.         TX_DESC *pPrevTXD;
  951.         u_long *pLink;
  952.         if (pTXD == pDrvCtrl->pTDA)
  953.             pPrevTXD = ((TX_DESC *)((char *)pDrvCtrl->pTDA + TDA_SIZE)) - 1;
  954.         else
  955.             pPrevTXD = pTXD - 1;
  956.         if (pPrevTXD->frag_count)
  957.             {
  958.             pLink = & pPrevTXD->frag [pPrevTXD->frag_count].frag_ptr0;
  959.             *pLink &= ~TX_EOL;
  960.             }
  961.         }
  962.         pDrvCtrl->sn_if.if_opackets++;        /* bump the statistic */
  963.         /* start the transmitter */
  964.         pDrvCtrl->pDev->cr = TXP;
  965.         /* And finally, adjust pointer to next TXD. */
  966.         pDrvCtrl->pTXDFree = pTXD->pLink;
  967.         }
  968.     }
  969. #endif    /* BSD43_DRIVER */
  970. /*******************************************************************************
  971. *
  972. * snTxReclaim - reclaims transmit descriptors that the device has serviced
  973. *
  974. */
  975. LOCAL void snTxReclaim (pDrvCtrl)
  976.     DRV_CTRL *pDrvCtrl;
  977.     {
  978.     TX_DESC *pTXD;
  979.     int unit;
  980.     unit = pDrvCtrl->sn_if.if_unit;                /* get our unit number */
  981.     pTXD = pDrvCtrl->pTXDReclaim;                  /* get ptr to desc */
  982.     CACHE_DMA_INVALIDATE (&pTXD->status, sizeof (u_long));
  983.     /* The device is deemed to be done with the descriptor if the
  984.      * the descriptor had been flagged as "given" to the device,
  985.      * and the descriptor status field is set.
  986.      */
  987.     while (pTXD->flag && pTXD->status)
  988.         {
  989.         if ( pTXD->status & PTX )
  990.             {
  991.             /* Packet was transmitted successfully.  Extract mbuf ptr and
  992.              * free the mbufs.
  993.              */
  994.             m_freem (pTXD->pMbuf);
  995.             /* done with the desc, so clean it up */
  996.             pTXD->flag    = FALSE;
  997.             pTXD->status  = 0;
  998. #ifdef SN_DEBUG
  999.             if (SN_DEBUG_TX && SN_DEBUG_VERBOSE)
  1000.                 logMsg ("sn: Tx: reclaimed TXD=%xn", (int)pTXD, 0, 0, 0, 0, 0);
  1001. #endif /* SN_DEBUG */
  1002.             }
  1003.         else                                    /* ERROR! */
  1004.             {
  1005.             pDrvCtrl->TxErrs++;                 /* bump our counter */
  1006.             pDrvCtrl->pDev->cr = TXP;           /* restart transmitter */
  1007.             break;
  1008.             }
  1009.         /* Advance to the next TXD. */
  1010.         pTXD = pTXD->pLink;
  1011.         /* Update the reclaim pointer for next time. */
  1012.         pDrvCtrl->pTXDReclaim = pTXD;
  1013.         /* invalidate the cache for this TXD */
  1014.         CACHE_DMA_INVALIDATE (&pTXD->status, sizeof (pTXD->status));
  1015.         }
  1016.     }
  1017. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1018.  * SECTION: Receive related routines
  1019.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1020. /****************************************************************************
  1021. *
  1022. * snRxPktReady - indicates a received packet is ready for processing
  1023. */
  1024. LOCAL BOOL snRxPktReady (pDrvCtrl)
  1025.     DRV_CTRL *pDrvCtrl;
  1026.     {
  1027.     RX_DESC *pRXD;
  1028.     pRXD = pDrvCtrl->pRXDNext;
  1029.     CACHE_DMA_INVALIDATE (pRXD, RX_DESC_SIZ);
  1030.     if (pRXD->in_use == NOT_IN_USE)              /* if not yet filled */
  1031.         return (FALSE);
  1032.     return (TRUE);
  1033.     }
  1034. /*******************************************************************************
  1035. *
  1036. * snRxPktProcess - process one received packet
  1037. *
  1038. */
  1039. LOCAL STATUS snRxPktProcess (pDrvCtrl)
  1040.     DRV_CTRL *pDrvCtrl;
  1041.     {
  1042.     RX_DESC *pRXD;                       /* ptr to a packet descriptor */
  1043.     struct ether_header *pPktHdr;        /* ptr to packet header */
  1044.     u_char *pData;                       /* ptr to packet data */
  1045.     MBUF *pMbuf;                         /* ptr to mbuf structs */
  1046.     SONIC *pDev;                         /* ptr to the device regs */
  1047.     int len;
  1048.     int ndx;                                  /* index into RRA desc array */
  1049.     int status;                               /* return status */
  1050.     u_short ether_type;                       /* safe copy of packet type */
  1051.     int spl;
  1052.     /* The current RX_DESC will already have been made cache coherent
  1053.      * by the snRxPktReady() routine.  There is no need to do it here.
  1054.      */
  1055.     pRXD    = pDrvCtrl->pRXDNext;               /* get ptr to the desc */
  1056.     len     = (pRXD->byte_count & UMASK) - 4;   /* get pkt length - FCS */
  1057.     pPktHdr = (struct ether_header *)           /* get ptr to pkt header */
  1058.                 (((pRXD->pkt_ptr1 & UMASK) << 16) | (pRXD->pkt_ptr0 & UMASK));
  1059.     pPktHdr = (struct ether_header *) CACHE_DMA_PHYS_TO_VIRT (pPktHdr);
  1060.     /* Do some sanity checks on the RXD info */
  1061.     if  (
  1062.         (len < 60)                      ||
  1063.         (len > 1514)                    ||
  1064.         (pPktHdr == NULL)               ||
  1065.         (!(pRXD->status & PRX))         ||
  1066.         (pRXD->link == RX_EOL)          ||
  1067.         (pRXD->link == NULL)
  1068.         )
  1069.         {
  1070.         logMsg ("sn: Fatal error.  Receive structures invalid.n",0,0,0,0,0,0);
  1071.         taskSuspend (0);
  1072.         return (ERROR);
  1073.         }
  1074.     pDrvCtrl->sn_if.if_ipackets++;          /* bump statistic */
  1075.                                             /* advance our mgmt variable */
  1076.     pDrvCtrl->pRXDNext = (RX_DESC *) CACHE_DMA_PHYS_TO_VIRT (pRXD->link);
  1077. #ifdef SN_DEBUG
  1078.     if (SN_DEBUG_RX && SN_DEBUG_VERBOSE)
  1079.         logMsg ("sn: Rx: packet addr=0x%x, len=0x%x, pRXD=0x%xn",
  1080.                 (int)pPktHdr, len, (int)pRXD, 0, 0, 0);
  1081.     if (SN_DEBUG_TRACE)
  1082. {
  1083.         logMsg ("sn: Rx: packet type 0x%x from %s",
  1084. pPktHdr->ether_type, (int)ether_sprintf (&pPktHdr->ether_shost),
  1085. 0, 0, 0, 0);
  1086.         logMsg (" to %sn", (int) ether_sprintf (&pPktHdr->ether_dhost),
  1087. 0, 0, 0, 0, 0);
  1088. }
  1089. #endif /* SN_DEBUG */
  1090.     CACHE_DMA_INVALIDATE (pPktHdr, len);
  1091.     /* call input hook if any */
  1092.     if (etherInputHookRtn != NULL)
  1093.         {
  1094.         if ((* etherInputHookRtn) (&pDrvCtrl->sn_if, (char *)pPktHdr, len))
  1095.             return (OK);
  1096.         }
  1097.     /* Subtract size of enet header from packet length. */
  1098.     len -= 14;
  1099.     /* Set pData to begining of packet data. */
  1100.     pData = (u_char *)pPktHdr;
  1101.     pData += 14;
  1102.     /* save the packet type, since build_cluster modifies the packet header */
  1103.     ether_type = pPktHdr->ether_type;
  1104.     /* convert packet data into mbufs */
  1105.     spl = splnet ();
  1106.     pMbuf = copy_to_mbufs (pData, len, 0, (IFNET *) &pDrvCtrl->sn_if);
  1107.     splx (spl);
  1108.     /* We are now done with the packet descriptor and the packet data.
  1109.      * First we manage the packet buffer mechanisms, then we manage
  1110.      * the packet descriptor mechanisms.
  1111.      */
  1112.     { /* done with packet buffer */
  1113.     if (pRXD->status & LPKT)                 /* if last pkt in this buffer */
  1114.         {
  1115.         /* form index to RRA descriptor this packet associates with */
  1116.         ndx = (((pRXD->seq_no & 0x0000ff00) >> 8) + 1) % NUM_RRA_DESC;
  1117.         pDev = pDrvCtrl->pDev;
  1118.         pDev->rwp = (unsigned long)(&((RRA_DESC *)pDrvCtrl->RSA)[ndx]) & UMASK;
  1119.         if (pDev->isr & RBE)                /* deal with RBE condition */
  1120.             pDev->isr = RBE;                /* clear the RBE condition */
  1121.         }
  1122.     }
  1123.     {  /* done with the desc */
  1124.     pRXD->in_use = NOT_IN_USE;                     /* Set NOT_IN_USE */
  1125.     pRXD->link = RX_EOL;                           /* Last one */
  1126.     /* Link into list */
  1127.     pDrvCtrl->pRXDLast->link = (RX_DESC *) CACHE_DMA_VIRT_TO_PHYS (pRXD);
  1128.     pDrvCtrl->pRXDLast = pRXD;                /* update our mgmt variable */
  1129.     }
  1130.     if (pMbuf == NULL)
  1131.         {
  1132.         logMsg ("sn: out of mbufsn",0,0,0,0,0,0);
  1133.         pDrvCtrl->sn_if.if_ierrors++;           /* bump error statistic */
  1134.         status = ERROR;
  1135.         }
  1136.     else
  1137.         { /* give the packet to the appropriate protocol */
  1138.         spl = splnet ();
  1139. #ifdef BSD43_DRIVER
  1140.         do_protocol_with_type (ether_type, pMbuf, &pDrvCtrl->sn_ac, len);
  1141. #else
  1142.         do_protocol (pPktHdr, pMbuf, &pDrvCtrl->sn_ac, len);
  1143. #endif
  1144.         splx (spl);
  1145.         status = OK;
  1146.         }
  1147.     return (status);
  1148.     }
  1149. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1150.  * SECTION: Interrupt driven routines, and primary event handler
  1151.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1152. /*******************************************************************************
  1153. *
  1154. * snIntr - device interrupt handler
  1155. *
  1156. * This routine is called at interrupt level in response to an interrupt from
  1157. * the device.
  1158. *
  1159. * Only the "received packet" interrupt event is acknowledged and serviced
  1160. * in this routine.  Some of the exception conditions are handled elsewhere.
  1161. */
  1162. LOCAL void snIntr (int unit)
  1163.     {
  1164.     DRV_CTRL *pDrvCtrl;                  /* ptr to driver ctrl struct */
  1165.     SONIC *pDev;                         /* ptr to the device regs */
  1166.     pDrvCtrl = & drvCtrl [unit];
  1167.     pDev = pDrvCtrl->pDev;
  1168.     if ((pDev->isr & pDev->imr) & TCEN)
  1169. {
  1170. if (pDrvCtrl->timerIntHandler)
  1171.     {
  1172.     pDev->cr = STP;
  1173.     pDev->isr = TCEN;
  1174.     (*pDrvCtrl->timerIntHandler)();
  1175.     pDev->wt0 = pDrvCtrl->ticks & 0xffff;
  1176.     pDev->wt1 = pDrvCtrl->ticks >> 16;
  1177.     pDev->cr = ST;
  1178.     }
  1179. }
  1180.     if ((pDev->isr & pDev->imr) & (PKTRX | TXDN | TXER))
  1181. {
  1182.         /* disable further interrupts (except timer and bus retry enable). */
  1183. pDev->imr = (pDrvCtrl->imr &= BREN | TCEN);
  1184.         (void) netJobAdd (                   /* queue netTask job */
  1185.                          (FUNCPTR)snEventHandler,
  1186.                          unit,
  1187.                          0,0,0,0
  1188.                          );
  1189. }
  1190.     /* Handle bus retry interrupt. */
  1191.     if (pDev->isr & BR)
  1192.         pDev->isr = BR;
  1193.     sysEnetIntAck (unit);                /* do system int ack */
  1194.     }
  1195. /*******************************************************************************
  1196. *
  1197. * snEventHandler - device event handler, a netTask job
  1198. */
  1199. LOCAL void snEventHandler (int unit)
  1200.     {
  1201.     DRV_CTRL *pDrvCtrl;
  1202.     SONIC *pDev;                         /* ptr to the device regs */
  1203.     int loops;
  1204. #ifdef SN_DEBUG
  1205.     if (SN_DEBUG_EVENT)
  1206.         logMsg ("sn: event handler entern", 0, 0, 0, 0, 0, 0);
  1207. #endif /* SN_DEBUG */
  1208.     /* Give up the spl semaphore. We don't need it yet, even though the
  1209.      * netTask thinks we do.
  1210.      */
  1211.     splx (0);
  1212.     pDrvCtrl = & drvCtrl [unit];
  1213.     pDev = pDrvCtrl->pDev;
  1214.     loops = 0;
  1215.     /* Loop, processing events */
  1216.     while ( pDev->isr & (PKTRX | TXDN | TXER) )
  1217.         {
  1218.         /* Process received packets */
  1219.         if (pDev->isr & PKTRX)
  1220.             {
  1221.             while (snRxPktReady (pDrvCtrl))             /* packets ready? */
  1222.                 {
  1223.                 pDev->isr = PKTRX;                /* clear this interrupt */
  1224.                 snRxPktProcess (pDrvCtrl);
  1225.                 }
  1226.             }
  1227.         /* Process transmitter events */
  1228.         if ( pDev->isr & (TXDN | TXER) )
  1229.             {
  1230.             pDev->isr = (TXDN | TXER);            /* clear these interrupts */
  1231.             snTxReclaim (pDrvCtrl);
  1232.             }
  1233.  
  1234.         loops++;
  1235.         }
  1236.     /* Take the spl semaphore before we return to the main loop of the
  1237.      * netTask.  This is done because the spl semaphore is assumed to be
  1238.      * owned by netTask after this routine returns.
  1239.      */
  1240.     (void) splnet ();
  1241.     /* Enable the interrupts */
  1242.     pDev->imr = (pDrvCtrl->imr |= PKTRX | TXDN | TXER);
  1243. #ifdef SN_DEBUG
  1244.     if (SN_DEBUG_EVENT)
  1245.         logMsg ("sn: event handler exit %dn", loops, 0, 0, 0, 0, 0);
  1246. #endif /* SN_DEBUG */
  1247.     }
  1248. /*******************************************************************************
  1249. *
  1250. * snClkEnable - enable the SONIC timer interrupt
  1251. *
  1252. * This routine enables the SONIC timer to give a periodic interrupt.
  1253. * The <unit> parameter selects the SONIC device.  The <ticksPerSecond>
  1254. * parameter specifies the number of interrupts to generate per second.
  1255. * When an interrupt occurs, the function in <intHandler> is called.
  1256. *
  1257. * NOTE:
  1258. * The SONIC clock interrupt is dependent on the SONIC interface being
  1259. * configured and enabled.  For this reason, this interrupt is unsuitable
  1260. * for use as the main system clock.  It is suitable for use as an auxiliary
  1261. * clock source for boards that have no other source of clock.
  1262. *
  1263. * RETURNS: N/A
  1264. *
  1265. * SEE ALSO: snClkDisable()
  1266. *
  1267. * NOMANUAL
  1268. */
  1269. void snClkEnable
  1270.     (
  1271.     int unit, /* unit number */
  1272.     int ticksPerSecond, /* interrupt frequency */
  1273.     FUNCPTR intHandler /* interrupt handler */
  1274.     )
  1275.     {
  1276.     DRV_CTRL *pDrvCtrl;
  1277.     SONIC *pDev;
  1278.     int key;
  1279.     pDrvCtrl = & drvCtrl [ unit ];
  1280.     pDev = pDrvCtrl->pDev;
  1281.     key = intLock ();
  1282.     pDrvCtrl->timerIntHandler = intHandler;
  1283.     pDrvCtrl->ticks = 5000000 / ticksPerSecond;
  1284.     pDrvCtrl->imr |= TCEN;
  1285.     if (pDev)
  1286. {
  1287. pDev->cr = STP;
  1288. pDev->wt0 = pDrvCtrl->ticks & 0xffff;
  1289. pDev->wt1 = pDrvCtrl->ticks >> 16;
  1290. pDev->imr = pDrvCtrl->imr;
  1291. pDev->cr = ST;
  1292. }
  1293.     intUnlock (key);
  1294.     }
  1295. /*******************************************************************************
  1296. *
  1297. * snClkDisable - disable the SONIC timer interrupt
  1298. *
  1299. * This routine disables the SONIC timer interrupt.  The <unit> parameter
  1300. * selects the SONIC device.
  1301. *
  1302. * RETURNS: N/A
  1303. *
  1304. * SEE ALSO: snClkEnable()
  1305. *
  1306. * NOMANUAL
  1307. */
  1308. void snClkDisable
  1309.     (
  1310.     int unit /* unit number */
  1311.     )
  1312.     {
  1313.     DRV_CTRL *pDrvCtrl;
  1314.     SONIC *pDev;
  1315.     int key;
  1316.     pDrvCtrl = & drvCtrl [ unit ];
  1317.     pDev = pDrvCtrl->pDev;
  1318.     if (pDev)
  1319. {
  1320. key = intLock ();
  1321. pDev->imr = (pDrvCtrl->imr &= ~TCEN);
  1322. pDev->cr = STP;
  1323. intUnlock (key);
  1324. }
  1325.     }
  1326. /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1327.  * SECTION: NOTES
  1328.  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
  1329. /* END OF FILE */