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

VxWorks

开发平台:

C/C++

  1. /* if_mbc.c - Motorola 68EN302 network-interface driver */
  2. /* Copyright 1996-1997 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01h,15jul97,spm  removed driver initialization from ioctl support (SPR #8831)
  8. 01g,07apr97,spm  code cleanup, corrected statistics, and upgraded to BSD 4.4
  9. 01h,06jun97,map  renamed mbcRestartTx to mbcDeviceRestart,
  10.                  code to retart device on rx FIFO overflow problem [SPR# 8670]
  11. 01g,07may97,map  corrected rx buffer initialization loop [SPR# 8481]
  12. 01f,06nov96,dgp  doc: final formatting
  13. 01e,20aug96,map  doc updates
  14. 01d,12aug96,map  made mbcIntr global
  15. 01c,09aug96,map  clean compiler warnings in mbcattach()
  16. 01b,08aug96,map  modified for en302 ethernet
  17. 01a,09may96,dzb  derived from v01a of src/drv/netif/if_cpm.c.
  18. */
  19. /*
  20. DESCRIPTION
  21. This is a driver for the Ethernet controller on the 68EN302 chip.  The device
  22. supports a 16-bit interface, data rates up to 10 Mbps, a dual-ported RAM, and
  23. transparent DMA.  The dual-ported RAM is used for a 64-entry CAM table, and a
  24. 128-entry buffer descriptor table.  The CAM table is used to set the Ethernet
  25. address of the Ethernet device or to program multicast addresses.  The buffer
  26. descriptor table is partitioned into fixed-size transmit and receive tables.
  27. The DMA operation is transparent and transfers data between the internal FIFOs
  28. and external buffers pointed to by the receive- and transmit-buffer descriptors
  29. during transmits and receives.
  30. The driver currently supports one Ethernet module controller, but it can be
  31. extended to support multiple controllers when needed. An Ethernet module
  32. is initialized by calling mbcattach().
  33. The driver supports buffer loaning for performance and input/output hook
  34. routines.  It does not support multicast addresses.
  35. The driver requires that the memory used for transmit and receive buffers be
  36. allocated in cache-safe RAM area.  
  37. A glitch in the EN302 Rev 0.1 device causes the Ethernet transmitter to
  38. lock up from time to time. The driver uses a watchdog timer to reset the
  39. Ethernet device when the device runs out of transmit buffers and cannot
  40. recover within 20 clock ticks.
  41. BOARD LAYOUT
  42. This device is on-chip.  No jumpering diagram is necessary.  
  43. EXTERNAL INTERFACE
  44. This driver presents the standard WRS network driver API: first the device
  45. unit must be attached with the mbcattach() routine, then it must be
  46. initialized with the mbcInit() routine.
  47. The only user-callable routine is mbcattach(), which publishes the `mbc'
  48. interface and initializes the driver structures.
  49. TARGET-SPECIFIC PARAMETERS
  50. .iP "Ethernet module base address"
  51. This parameter is passed to the driver via mbcattach().
  52. This parameter is the base address of the Ethernet module. The driver
  53. addresses all other Ethernet device registers as offsets from this address.
  54. .iP "interrupt vector number"
  55. This parameter is passed to the driver via mbcattach().
  56. The driver configures the Ethernet device to use this parameter while
  57. generating interrupt ack cycles.  The interrupt service routine mbcIntr() is
  58. expected to be attached to the corresponding interrupt vector externally,
  59. typically in sysHwInit2().
  60. .iP "number of transmit and receive buffer descriptors"
  61. These parameters are passed to the driver via mbcattach().
  62. The number of transmit and receive buffer descriptors (BDs) used is
  63. configurable by the user while attaching the driver.  Each BD is 8 bytes in
  64. size and resides in the chip's dual-ported memory, while its associated
  65. buffer, 1520 bytes in size, resides in cache-safe conventional RAM. A minimum
  66. of 2 receive and 2 transmit BDs should be allocated.  If this parameter is
  67. NULL, a default of 32 BDs will be used.  The maximum number of BDs depends on
  68. how the dual-ported BD RAM is partitioned.  The 128 BDs in the dual-ported BD
  69. RAM can partitioned into transmit and receive BD regions with 8, 16, 32, or 64
  70. transmit BDs and corresponding 120, 112, 96, or 64 receive BDs.
  71. .iP "Ethernet DMA parameters"
  72. This parameter is passed  to the driver via mbcattach().
  73. This parameter is used to specify the settings of burst limit, water-mark, and
  74. transmit early, which control the Ethernet DMA, and is used to set the EDMA
  75. register.
  76. .iP "base address of the buffer pool"
  77. This parameter is passed to the driver via mbcattach().
  78. This parameter is used to notify the driver that space for the transmit and
  79. receive buffers need not be allocated, but should be taken from a
  80. cache-coherent private memory space provided by the user at the given address.
  81. The user should be aware that memory used for buffers must be 4-byte aligned
  82. and non-cacheable.  All the buffers must fit in the given memory space; no
  83. checking will be performed.  This includes all transmit and receive buffers
  84. (see above) and an additional 16 receive loaner buffers, unless the number of
  85. receive BDs is less than 16, in which case that number of loaner buffers will
  86. be used.  Each buffer is 1520 bytes.  If this parameter is "NONE", space for
  87. buffers will be obtained by calling cacheDmaMalloc() in cpmattach().
  88. .LP
  89. EXTERNAL SUPPORT REQUIREMENTS
  90. The driver requires the following support functions:
  91. .iP "STATUS sysEnetAddrGet (int unit, UINT8 * addr)" "" 9 -1
  92. The driver expects this routine to provide the six-byte Ethernet hardware
  93. address that will be used by <unit>.  This routine must copy the six-byte
  94. address to the space provided by <addr>.  This routine is expected to return
  95. OK on success, or ERROR.  The driver calls this routine, during device
  96. initialization, from the cpmInit() routine.
  97. .LP
  98. SYSTEM RESOURCE USAGE
  99. The driver requires the following system resource:
  100.     - one mutual exclusion semaphore
  101.     - one interrupt vector
  102.     - one watchdog timer
  103.     - 0 bytes in the initialized data section (data)
  104.     - 296 bytes in the uninitialized data section (bss)
  105. The data and BSS sections are quoted for the CPU32 architecture.
  106. If the driver allocates the memory shared with the Ethernet device unit,
  107. it does so by calling the cacheDmaMalloc() routine.  For the default case
  108. of 32 transmit buffers, 32 receive buffers, and 16 loaner buffers, the total
  109. size requested is 121,600 bytes.  If a non-cacheable memory region is provided
  110. by the user, the size of this region should be this amount, unless the
  111. user has specified a different number of transmit or receive BDs.
  112. This driver can only operate if the shared memory region is non-cacheable,
  113. or if the hardware implements bus snooping.  The driver cannot maintain
  114. cache coherency for the device because the buffers are asynchronously
  115. modified by both the driver and the device, and these fields may share the
  116. same cache line.  Additionally, the chip's dual-ported RAM must be
  117. declared as non-cacheable memory where applicable.
  118. SEE ALSO: ifLib,
  119. .I "Motorola MC68EN302 User's Manual",
  120. .I "Motorola MC68EN302 Device Errata, May 30, 1996"
  121. */
  122. /* includes */
  123. #include "vxWorks.h"
  124. #include "iv.h"
  125. #include "taskLib.h"
  126. #include "memLib.h"
  127. #include "ioctl.h"
  128. #include "etherLib.h"
  129. #include "net/mbuf.h"
  130. #include "net/protosw.h"
  131. #include "socket.h"
  132. #include "errno.h"
  133. #include "net/if.h"
  134. #include "net/unixLib.h"
  135. #include "net/route.h"
  136. #include "netinet/in.h"
  137. #include "netinet/in_systm.h"
  138. #include "netinet/in_var.h"
  139. #include "netinet/ip.h"
  140. #include "netinet/if_ether.h"
  141. #include "net/if_subr.h"
  142. #include "cacheLib.h"
  143. #include "stdio.h"
  144. #include "intLib.h"
  145. #include "netLib.h"
  146. #include "drv/netif/netifDev.h"
  147. #include "drv/netif/if_mbc.h"
  148. #include "wdLib.h"
  149. /* defines */
  150. #define MAX_UNITS 1 /* max ethernet units */
  151. #define ENET_ADDR_SIZE 0x6 /* size of ethernet src/dest addresses */
  152. #define TX_BD_MIN 2 /* minimum number of Tx buffer descriptors */
  153. #define RX_BD_MIN 2 /* minimum number of Rx buffer descriptors */
  154. #define TX_BD_DEFAULT 0x20 /* default number of Tx buffer descriptors */
  155. #define RX_BD_DEFAULT 0x20 /* default number of Rx buffer descriptors */
  156. #define FRAME_MAX 0x05ee /* maximum frame size */
  157. #define TX_BUF_SIZE FRAME_MAX /* size of a transmit buffer */
  158. #define RX_BUF_SIZE FRAME_MAX /* size of a receive buffer */
  159. #define FRAME_MIN 0x0040 /* minimum frame size */
  160. #define L_POOL 0x10 /* number of Rx loaner buffers in pool */
  161. #define WD_TIMEOUT 20      /* number of clock ticks for reset timeout*/
  162. /* register access macros */
  163. #ifndef MBC_REG_READ
  164. #   define MBC_REG_READ(b, r) (*(UINT16 *)((b) + (r)))
  165. #endif /* MBC_REG_READ */
  166. #ifndef MBC_REG_WRITE
  167. #   define MBC_REG_WRITE(b, r, v) (*(UINT16 *)((b) + (r)) = (v))
  168. #endif /* MBC_REG_WRITE */
  169. #define MBC_REG_UPDATE(b, r, v) MBC_REG_WRITE((b), (r),      
  170.                                               MBC_REG_READ((b), (r)) |(v))
  171. #define MBC_REG_RESET(b, r, v) MBC_REG_WRITE((b), (r),             
  172.                                               MBC_REG_READ((b), (r)) & ~(v))
  173. #define MBC_IEVNT_READ(b) MBC_REG_READ((b), MBC_IEVNT)
  174. #define MBC_IMASK_READ(b) MBC_REG_READ((b), MBC_IMASK)
  175. #define MBC_ECNTL_READ(b) MBC_REG_READ((b), MBC_ECNTL)
  176. #define MBC_INTR_ACK(b, v) MBC_REG_WRITE((b), MBC_IEVNT, (v))
  177. #define MBC_INTR_DISABLE(b, v) MBC_REG_RESET((b), MBC_IMASK, (v))
  178. #define MBC_INTR_ENABLE(b, v) MBC_REG_UPDATE((b), MBC_IMASK, (v))
  179.                                          
  180. /* typedefs */
  181. typedef struct mbuf MBUF;
  182. typedef struct arpcom IDR; /* Interface Data Record */
  183. typedef struct ifnet IFNET;
  184. typedef struct ifreq IFREQ;
  185. typedef struct sockaddr SOCK;
  186. typedef struct drv_ctrl /* DRV_CTRL */
  187.     {
  188.     IDR idr;            /* mbc interface data record */
  189.     BOOL initialized;    /* inidicates that the unit is initialized */
  190.     int nLoan;          /* number of buffers in the loaner pool */
  191.     UINT8 * lPool[L_POOL];  /* loaner pool */
  192.     UINT8  refCnt[L_POOL]; /* loaner buffer reference counters */
  193.     UINT8 * pRefCnt[L_POOL];/* pointer to the reference counters */
  194.     MBC_DEV ether;          /* mbc device */
  195.     UINT16 resetCounter; /* number of times the device was reset */
  196.     WDOG_ID wdId;           /* watchdog id */
  197.     UINT16 inum; /* interrupt number */
  198.     UINT16 dmaParms; /* DMA parameters */
  199.     } DRV_CTRL;
  200. /* globals */
  201. IMPORT STATUS sysEnetAddrGet (int unit, UINT8 * addr);
  202. IMPORT void sysMbcDmaParmGet (int unit, UINT16 * pParm);
  203. /* locals */
  204. LOCAL DRV_CTRL drvCtrl[MAX_UNITS]; 
  205. /* forward declarations */
  206. LOCAL STATUS mbcInit (int uint);
  207. LOCAL int mbcIoctl (IFNET * pIfNet, int cmd, caddr_t data);
  208. #ifdef BSD43_DRIVER
  209. LOCAL int mbcOutput (IFNET * pIfNet, MBUF * pMbuf, SOCK * pSock);
  210. #endif
  211. LOCAL void mbcReset (int uint);
  212. #ifdef BSD43_DRIVER
  213. LOCAL void mbcStartOutput (int unit);
  214. #else
  215. LOCAL void mbcStartOutput (DRV_CTRL *pDrvCtrl);
  216. #endif
  217. LOCAL void      mbcHandleInt (DRV_CTRL * pDrvCtrl);
  218. LOCAL void mbcDeviceRestart (int unit);
  219. LOCAL void mbcRecv (DRV_CTRL * pDrvCtrl, MBC_BD * pRxBd);
  220. LOCAL void mbcLoanFree (DRV_CTRL * pDrvCtrl, UINT8 * pRxBuf,
  221.                              UINT8 * pRefCnt);
  222. void mbcIntr (int unit);
  223. /*******************************************************************************
  224. *
  225. * mbcattach - publish the `mbc' network interface and initialize the driver
  226. *
  227. * The routine publishes the `mbc' interface by adding an `mbc' Interface Data
  228. * Record (IDR) to the global network interface list.
  229. *
  230. * The Ethernet controller uses buffer descriptors from an on-chip dual-ported
  231. * RAM region, while the buffers are allocated in RAM external to the
  232. * controller. The buffer memory pool can be allocated in a non-cacheable RAM
  233. * region and passed as parameter <bufBase>.  Otherwise <bufBase> is NULL and
  234. * the buffer memory pool is allocated by the routine using cacheDmaMalloc().
  235. * The driver uses this buffer pool to allocate the specified number of
  236. * 1518-byte buffers for transmit, receive, and loaner pools.
  237. *
  238. * The parameters <txBdNum> and <rxBdNum> specify the number of buffers
  239. * to allocate for transmit and receive. If either of these parameters
  240. * is NULL, the default value of 2 is used. The number of loaner buffers
  241. * allocated is the lesser of <rxBdNum> and 16.
  242. *
  243. * The on-chip dual ported RAM can only be partitioned so that the maximum
  244. * receive and maximum transmit BDs are:
  245. * .iP
  246. * Transmit BDs:  8, Receive BDs: 120
  247. * .iP
  248. * Transmit BDs: 16, Receive BDs: 112
  249. * .iP
  250. * Transmit BDs: 32, Receive BDs:  96
  251. * .iP
  252. * Transmit BDs: 64, Receive BDs:  64
  253. * .LP
  254. *
  255. * RETURNS: ERROR, if <unit> is out of range> or non-cacheable memory cannot be 
  256. * allocated; otherwise TRUE.
  257. *
  258. * SEE ALSO: ifLib,
  259. * .I "Motorola MC68EN302 User's Manual"
  260. */
  261. STATUS mbcattach
  262.     (
  263.     int unit,           /* unit number */
  264.     void * pEmBase,        /* ethernet module base address */
  265.     int inum,           /* interrupt vector number */
  266.     int txBdNum,        /* number of transmit buffer descriptors */
  267.     int rxBdNum,        /* number of receive buffer descriptors */
  268.     int dmaParms, /* DMA parameters */
  269.     UINT8 * bufBase         /* address of memory pool; NONE = malloc it */
  270.     )
  271.     {
  272.     DRV_CTRL * pDrvCtrl;
  273.     MBC_BD * pBd;
  274.     UINT8 bdSize;
  275.     UINT8 txBdMax;
  276.     UINT8 rxBdMax;
  277.     UINT8 nLoan;
  278.     UINT8 * txBuf;
  279.     UINT8 * rxBuf;
  280.     UINT8 * loanBuf;
  281.     int counter;
  282.     
  283.     /* sanity check - unit number */
  284.     if (unit < 0 || unit >= MAX_UNITS)
  285.         return (ERROR);
  286.     pDrvCtrl = & drvCtrl[unit];
  287.     pDrvCtrl->initialized = FALSE;
  288.     /* Use default values if the parameters are NULL */
  289.     if (txBdNum == NULL)
  290.         txBdNum = TX_BD_DEFAULT;
  291.     if (rxBdNum == NULL)
  292.         rxBdNum = RX_BD_DEFAULT;
  293.     /* Use the default minimum value if the given value is smaller */
  294.     txBdNum = max (TX_BD_MIN, txBdNum);
  295.     rxBdNum = max (RX_BD_MIN, rxBdNum);
  296.     
  297.     /* Ensure that txBdNum, and rxBdNum are within range */
  298.     
  299.     if (txBdNum > 64)
  300.         txBdNum = 64;
  301.     for (bdSize = MBC_EDMA_BDS_8; bdSize <= MBC_EDMA_BDS_64; bdSize++) 
  302.        {
  303.         txBdMax = 1 << (bdSize + 3);   /* set txBdMax to (8, 16, 32, 64) */
  304.         rxBdMax = MBC_BD_MAX - txBdMax;
  305.         
  306.         if (txBdNum <= txBdMax)
  307.             {
  308.             if (rxBdNum > rxBdMax)
  309.                 rxBdNum = rxBdMax;
  310.             break;
  311.             }
  312.         }
  313.     /* set the number of receive loaner buffers */
  314.     nLoan  = min (rxBdNum, L_POOL);
  315.     /* fill in the driver control parameters */
  316.     
  317.     pDrvCtrl->nLoan = nLoan;
  318.     pDrvCtrl->ether.mbcNum = unit;
  319.     pDrvCtrl->ether.bdSize = bdSize;
  320.     pDrvCtrl->ether.txBdNum = txBdNum;
  321.     pDrvCtrl->ether.rxBdNum = rxBdNum;
  322.     pDrvCtrl->ether.txBdBase = (MBC_BD *) ((int) pEmBase + MBC_EBD);
  323.     pDrvCtrl->ether.rxBdBase = (MBC_BD *) ((int) pEmBase + MBC_EBD +
  324.                                    sizeof (MBC_BD) * (1 << (bdSize + 3)));
  325.     pDrvCtrl->ether.txBdNext = 0;
  326.     pDrvCtrl->ether.rxBdNext = 0;
  327.     pDrvCtrl->ether.pDevBase = pEmBase;
  328.     pDrvCtrl->resetCounter = 0;
  329.     pDrvCtrl->inum = inum;
  330.     pDrvCtrl->dmaParms = dmaParms & (MBC_EDMA_BLIM_MSK |
  331.                                               MBC_EDMA_WMRK_MSK |
  332.                                               MBC_EDMA_TSRLY);
  333.     /* create a watchdog timer */
  334.     pDrvCtrl->wdId = wdCreate();
  335.     if (pDrvCtrl->wdId == NULL)
  336.         return (ERROR);
  337.     /* set up the transmit and receive buffers */
  338.     if (bufBase == (UINT8 *) NONE)
  339.         {
  340.         /* allocate the memory pool */
  341.         txBuf = cacheDmaMalloc (txBdNum * TX_BUF_SIZE);
  342.         if (txBuf == NULL)
  343.             {
  344.             wdDelete (pDrvCtrl->wdId);
  345.             return (ERROR);
  346.             }
  347.         rxBuf = cacheDmaMalloc (rxBdNum * RX_BUF_SIZE);
  348.         if (rxBuf == NULL)
  349.             {
  350.             wdDelete (pDrvCtrl->wdId);
  351.             cacheDmaFree (txBuf);
  352.             return (ERROR);
  353.             }
  354.         loanBuf = cacheDmaMalloc (nLoan * RX_BUF_SIZE);
  355.         if (loanBuf == NULL)
  356.             pDrvCtrl->nLoan = nLoan = 0;
  357.         }
  358.     else
  359.         {
  360.         /* partition memory pool for transmit/receive/loaner buffers */
  361.         txBuf = bufBase;
  362.         rxBuf = txBuf + (txBdNum * TX_BUF_SIZE);
  363.         loanBuf = rxBuf + (rxBdNum * RX_BUF_SIZE);
  364.         }
  365.     /* take the device out of reset state */
  366.     MBC_REG_WRITE ((int)pEmBase, MBC_ECNTL, MBC_ECNTL_RES_OFF);
  367.     /* Associate a buffer with each buffer descriptor */
  368.     pBd = pDrvCtrl->ether.txBdBase;
  369.     
  370.     for (counter = 0; counter < txBdNum; counter++, pBd++)
  371.         pBd->dataPointer = txBuf + (counter * TX_BUF_SIZE);
  372.     pBd = pDrvCtrl->ether.rxBdBase;
  373.     for (counter = 0; counter < rxBdNum; counter++, pBd++)
  374.         pBd->dataPointer = rxBuf + (counter * RX_BUF_SIZE);
  375.     /* Initialize the loaner buffer pool */
  376.     
  377.     for (counter = 0; counter < nLoan; counter++)
  378.         {
  379.         pDrvCtrl->lPool[counter] = loanBuf + (counter * RX_BUF_SIZE);
  380.         pDrvCtrl->refCnt[counter] = 0;
  381.         pDrvCtrl->pRefCnt[counter] = & pDrvCtrl->refCnt[counter];
  382.         }
  383.     /* reset the chip */
  384.     
  385.     mbcReset (unit);
  386.     /* publish the Interface Data Record */
  387. #ifdef BSD43_DRIVER    
  388.     ether_attach (& pDrvCtrl->idr.ac_if, unit, MBC_IFNAME,
  389.                   (FUNCPTR) mbcInit, (FUNCPTR) mbcIoctl,
  390.                   (FUNCPTR) mbcOutput, (FUNCPTR) mbcReset);
  391. #else
  392.     ether_attach (
  393.                  &pDrvCtrl->idr.ac_if, 
  394.                  unit,
  395.                  MBC_IFNAME,
  396.                  (FUNCPTR) mbcInit, 
  397.                  (FUNCPTR) mbcIoctl,
  398.                  (FUNCPTR) ether_output, 
  399.                  (FUNCPTR) mbcReset
  400.                  );
  401.     pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)mbcStartOutput;
  402. #endif
  403.     mbcInit (unit);
  404.     return (OK);
  405.     }
  406. /*******************************************************************************
  407. *
  408. * mbcInit - initialize the MBC network device
  409. *
  410. * This routine marks the interface as down, then configures and initializes
  411. * the chip.  It sets up the transmit and receive buffer descriptor (BD)
  412. * rings, initializes registers, and enables interrupts.  Finally, it marks
  413. * the interface as up and running.  It does not touch the receive loaner
  414. * buffer stack.
  415. *
  416. * This routine is called from the driver attach routine.
  417. *
  418. * The complement of this routine is mbcReset().  Once a unit is reset by
  419. * mbcReset(), it may be re-initialized to a running state by this routine.
  420. *
  421. * RETURNS: OK if successful, otherwise ERROR.
  422. *
  423. * SEE ALSO: mbcIoctl(), mbcReset()
  424. *
  425. */
  426. LOCAL STATUS mbcInit
  427.     (
  428.     int unit           /* unit number */
  429.     )
  430.     {
  431.     DRV_CTRL * pDrvCtrl;
  432.     MBC_BD * pBd;
  433.     volatile char * pDevBase;
  434.     UINT8 enetAddr[ENET_ADDR_SIZE];
  435.     UINT16 regValue;
  436.     int counter;
  437.     
  438.     /* sanity check the unit number */
  439.     
  440.     if (unit < 0 || unit >= MAX_UNITS)
  441.         return (ERROR);
  442.     pDrvCtrl = & drvCtrl[unit];
  443.     /* ensure single invocation */
  444.     
  445.     if (pDrvCtrl->initialized)
  446.         return (OK);
  447.     pDevBase = pDrvCtrl->ether.pDevBase;
  448.     /* mark the device as down */
  449.     pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  450.     /* take the device out of reset state */
  451.     MBC_REG_WRITE (pDevBase, MBC_ECNTL, MBC_ECNTL_RES_OFF);
  452.     /* set up transmit buffer descriptors */
  453.     
  454.     pDrvCtrl->ether.txBdNext = 0;
  455.     pBd = pDrvCtrl->ether.txBdBase;
  456.     for (counter = pDrvCtrl->ether.txBdNum; counter; counter--, pBd++)
  457.         pBd->statusMode = (MBC_TXBD_I | MBC_TXBD_L | MBC_TXBD_TC);
  458.     /* turn on the `wrap' bit on the last buffer descriptor */
  459.     pBd--;
  460.     pBd->statusMode |= MBC_TXBD_W;
  461.     /* set up the receive buffer descriptors */
  462.     pDrvCtrl->ether.rxBdNext = 0;
  463.     pBd = pDrvCtrl->ether.rxBdBase;
  464.     for (counter = pDrvCtrl->ether.rxBdNum; counter; counter--, pBd++)
  465.         pBd->statusMode = (MBC_RXBD_E | MBC_RXBD_I);
  466.     /* turn on the `wrap' bit on the last buffer descriptor */
  467.     
  468.     pBd--;
  469.     pBd->statusMode |= MBC_RXBD_W;
  470.     /* set the interrupt vector number */
  471.     MBC_REG_WRITE (pDevBase, MBC_IVEC, pDrvCtrl->inum);
  472.     /* set BD size and other DMA parameters */
  473.     regValue = pDrvCtrl->dmaParms;
  474.     regValue |= (pDrvCtrl->ether.bdSize << MBC_EDMA_BDS_SHFT);
  475.     MBC_REG_WRITE (pDevBase, MBC_EDMA, regValue);
  476.     /*
  477.      * set the operating mode to, no internal loopback, no full duplex, and
  478.      * no hearbeat control.
  479.      */
  480.     
  481.     MBC_REG_WRITE (pDevBase, MBC_ECFG, 0);
  482.     /*
  483.      * set address control to, no hash enable, no index enable, no multicast,
  484.      * no physical address rejection, and promiscuous mode, if needed.
  485.      */
  486.     
  487.     regValue = 0;
  488.     if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC)
  489.         regValue |= MBC_AR_PROM;
  490.     
  491.     MBC_REG_WRITE (pDevBase, MBC_AR, regValue);
  492.     /* set max receive frame size */
  493.     MBC_REG_WRITE (pDevBase, MBC_EMRBLR, FRAME_MAX);
  494.         
  495.     /* get ethernet address for this device */
  496.     
  497.     if (sysEnetAddrGet (unit, (UINT8 *) enetAddr) == ERROR)
  498.         return (ERROR);
  499.     /* copy in correct byte sequence */
  500.     
  501.     for (counter=0; counter < ENET_ADDR_SIZE; counter++)
  502.         pDrvCtrl->idr.ac_enaddr[ENET_ADDR_SIZE - counter - 1] =
  503.             enetAddr[counter];
  504.     /* install the ethernet address */
  505.     
  506.     bcopy ((char *) pDrvCtrl->idr.ac_enaddr,
  507.            (char *) (pDrvCtrl->ether.pDevBase + MBC_ARTAB),
  508.            ENET_ADDR_SIZE);
  509.     
  510.     /* set rest of the AR entries to broadcast address */
  511.     regValue=0xffff;
  512.     for (counter = 1; counter < MBC_ARTAB_SIZE; counter++)
  513.         {
  514.         MBC_REG_WRITE (pDevBase, MBC_ARTAB + (counter * 8), regValue);
  515.         MBC_REG_WRITE (pDevBase, MBC_ARTAB + (counter * 8) + 2, regValue);
  516.         MBC_REG_WRITE (pDevBase, MBC_ARTAB + (counter * 8) + 4, regValue);
  517.         }
  518.     
  519.     /* enable interrupts - clear events and set mask */
  520.     MBC_REG_WRITE (pDevBase, MBC_IEVNT, 0xffff);
  521.     MBC_REG_WRITE (pDevBase, MBC_IMASK, MBC_IMASK_RXF | MBC_IMASK_EBE);
  522.     /* set interface flags - mark device as `up' */
  523.     pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;
  524.     
  525.     /* mark device as initialized */
  526.     pDrvCtrl->initialized = TRUE;
  527.     /* enable the device */
  528.     MBC_REG_UPDATE (pDevBase, MBC_ECNTL, MBC_ECNTL_ENBL);
  529.     
  530.     /* start sending enqueued packets */
  531. #ifdef BSD43_DRIVER
  532.     (void) netJobAdd ((FUNCPTR) mbcStartOutput, unit, 0, 0, 0, 0); 
  533. #else
  534.     (void) netJobAdd ((FUNCPTR) mbcStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); 
  535. #endif
  536.     return (OK);
  537.     }
  538. #ifdef BSD43_DRIVER
  539. /*******************************************************************************
  540. *
  541. * mbcOutput - network interface output routine
  542. *
  543. * This routine simply calls ether_output(). ether_output() resolves 
  544. * the hardware addresses and calls mbcStartOutput() with the unit number
  545. * passed as an argument.
  546. *
  547. * RETURNS: OK if successful, otherwise errno.
  548. */
  549. LOCAL int mbcOutput
  550.     (
  551.     IFNET * pIfNet, /* pointer to IFNET structure */
  552.     MBUF * pMbuf, /* mbuf chain for output */
  553.     SOCK * pSock /* sock ptr for destination */  
  554.     )
  555.     {
  556.     DRV_CTRL * pDrvCtrl = & drvCtrl[pIfNet->if_unit];
  557.     return (ether_output (pIfNet, pMbuf, pSock, (FUNCPTR) mbcStartOutput,
  558.     & pDrvCtrl->idr));
  559.     }
  560. #endif
  561. /*******************************************************************************
  562. *
  563. * mbcStartOutput - output packet to network interface device
  564. *
  565. * mbcStartOutput() takes a packet from the network interface output queue,
  566. * copies the mbuf chain into an interface buffer, and sends the packet over
  567. * the interface.  etherOutputHookRtns are supported.
  568. *
  569. * Collision stats are collected in this routine from previously sent BDs.
  570. * These BDs will not be examined until after the transmitter has cycled the
  571. * ring, coming upon the BD after it has been sent. Thus, collision stat
  572. * collection will be delayed a full cycle through the Tx ring.
  573. *
  574. * This routine is called under several possible scenarios.  Each one will be
  575. * described below.
  576. *
  577. * The first, and most common, is when a user task requests the transmission of
  578. * data. Under BSD 4.3, this results in a call to mbcOutput(), which in turn
  579. * calls ether_output(). The routine, ether_output(), will make a call to
  580. * mbcStartOutput() if our interface output queue is not full, otherwise, the
  581. * outgoing data is discarded. BSD 4.4 uses a slightly different model, in
  582. * which the generic ether_output() routine is called directly, followed by
  583. * a call to this routine.
  584. *
  585. * The second scenario is when this routine, while executing runs out of free
  586. * Tx BDs, turns on transmit interrupts and exits.  When the next BD is
  587. * transmitted, an interrupt occurs and the ISR does a netJobAdd of the routine
  588. * which executes in the context of netTask() and continues sending packets
  589. * from the interface output queue.  
  590. *
  591. * The third scenario is when the device is reset, typically when the 
  592. * promiscuous mode is altered; which results in a call to mbcInit().  This 
  593. * resets the device, does a netJobAdd() of this routine to enable transmitting 
  594. * queued packets.
  595. *
  596. * RETURNS: N/A
  597. */
  598. #ifdef BSD43_DRIVER
  599. LOCAL void mbcStartOutput
  600.     (
  601.     int unit /* unit number */
  602.     )
  603.     {
  604.     DRV_CTRL * pDrvCtrl = & drvCtrl[unit];
  605. #else
  606. LOCAL void mbcStartOutput
  607.     (
  608.     DRV_CTRL *  pDrvCtrl  /* driver control structure */
  609.     )
  610.     {
  611.     int unit = pDrvCtrl->idr.ac_if.if_unit;
  612. #endif
  613.     volatile char * pDevBase = pDrvCtrl->ether.pDevBase;
  614.     MBUF * pMbuf; /* mbuf pointer */
  615.     int length;
  616.     MBC_BD * pTxBd;
  617.     UINT8 * pad;
  618.     UINT8 txBdMax = pDrvCtrl->ether.txBdNum - 2;
  619.     if (txBdMax == 0)
  620.         txBdMax++;
  621.     /*
  622.      * Loop until:
  623.      *     a) there are no more packets ready to send
  624.      *     b) we have insufficient resources left to send another one
  625.      *     c) txBdMax packets have been sent, so that the
  626.      *        transmitter on the rev 0.1 chip is not choked.
  627.      */
  628.     while (pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL)
  629.         {
  630. pTxBd = & pDrvCtrl->ether.txBdBase[pDrvCtrl->ether.txBdNext];
  631.         
  632. /* check if a transmit buffer descriptor is available */
  633.         
  634.         if ((pTxBd->statusMode & MBC_TXBD_R) || (txBdMax == 0))
  635.     {
  636.     /* if no BD available, enable interrupt to see when one is free */
  637.             wdStart (pDrvCtrl->wdId, WD_TIMEOUT, (FUNCPTR) mbcDeviceRestart,
  638.                      unit);
  639.             MBC_INTR_ENABLE (pDevBase, MBC_IEVNT_TXF);
  640.     break;
  641.     }
  642.         IF_DEQUEUE (& pDrvCtrl->idr.ac_if.if_snd, pMbuf); 
  643.         copy_from_mbufs (pTxBd->dataPointer, pMbuf, length);
  644.         /* initial hardware version does not support padding */
  645.         if (length < FRAME_MIN)
  646.             {
  647.             pad = pTxBd->dataPointer + length;
  648.             for (; length != FRAME_MIN; length++, pad++)
  649.                 *pad = 0x88;
  650.             }
  651.         /* call hook if one is connected */
  652.         if ((etherOutputHookRtn == NULL) || ((* etherOutputHookRtn)
  653.     (& pDrvCtrl->idr.ac_if, pTxBd->dataPointer, length) == 0))
  654.             {
  655.     /* add in collision stats from previously sent BDs */
  656.             pDrvCtrl->idr.ac_if.if_collisions += ((pTxBd->statusMode &
  657.                                                    MBC_TXBD_RC) >>
  658.                                                   MBC_TXBD_RC_SHFT);
  659.             /* add in transmission failures */
  660.             
  661.             if (pTxBd->statusMode & MBC_TXBD_ERRS)
  662.                 {
  663.                 pDrvCtrl->idr.ac_if.if_oerrors++;
  664.                 pDrvCtrl->idr.ac_if.if_opackets--;
  665.                 }
  666.     /* since hook did not grab the frame, send packet */
  667.             pTxBd->dataLength = length;
  668.             pTxBd->statusMode &= ~(MBC_TXBD_ERRS|MBC_TXBD_RC);
  669.             pTxBd->statusMode |= MBC_TXBD_R;
  670.             /* incr BD count */
  671.     pDrvCtrl->ether.txBdNext = (pDrvCtrl->ether.txBdNext + 1) %
  672.         pDrvCtrl->ether.txBdNum;
  673. #ifndef BSD43_DRIVER    /* BSD 4.4 ether_output() doesn't bump statistic. */
  674.             pDrvCtrl->idr.ac_if.if_opackets++;
  675. #endif
  676.             }
  677.         txBdMax --;
  678.         }
  679.     }
  680. /*******************************************************************************
  681. *
  682. * mbcIoctl - network interface control routine
  683. *
  684. * This routine implements the network interface control functions.
  685. * It handles SIOCSIFADDR and SIOCSIFFLAGS commands.
  686. *
  687. * RETURNS: OK if successful, otherwise EINVAL.
  688. */
  689. LOCAL int mbcIoctl
  690.     (
  691.     IFNET * pIfNet, /* pointer to IFNET structure */
  692.     int cmd, /* command to process */
  693.     caddr_t data /* pointer to data */ 
  694.     )
  695.     {
  696.     DRV_CTRL * pDrvCtrl = & drvCtrl[pIfNet->if_unit];
  697.     int         error   = 0;            /* error value */
  698.     int         s       = splimp ();    /* sem not taken in calling routines */
  699.     BOOL promiscReq; /* requested promisc state */
  700.     BOOL promiscCur;      /* current promisc state */
  701.     switch (cmd)
  702.         {
  703.         case SIOCSIFADDR:       /* set interface address */
  704.             ((struct arpcom *)pIfNet)->ac_ipaddr = IA_SIN (data)->sin_addr;
  705.             arpwhohas (pIfNet, &IA_SIN (data)->sin_addr);
  706.             break;
  707.     
  708.         case SIOCSIFFLAGS:
  709.             /* process request, if promisc mode needs change */
  710.             promiscReq = ((pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC) ?
  711.                           TRUE : FALSE);
  712.             promiscCur = ((MBC_REG_READ (pDrvCtrl->ether.pDevBase, MBC_AR) &
  713.                            MBC_AR_PROM) ? TRUE : FALSE);
  714.             if ((promiscReq && (!promiscCur)) || ((!promiscReq) && promiscCur))
  715.                 {
  716.                 mbcDeviceRestart (pIfNet->if_unit);
  717.                 }
  718.             break;
  719.         default:
  720.             error = EINVAL;
  721.         }
  722.     splx (s);
  723.     return (error);
  724.     }
  725. /*******************************************************************************
  726. *
  727. * mbcReset - network interface reset routine
  728. *
  729. * This routine marks the interface as down and resets the device.  This
  730. * includes disabling interrupts, stopping the transmitter and receiver.
  731. *
  732. * The complement of this rotuine is mbcInit().  Once a unit is reset by this
  733. * routine, it can be re-initialized to a  running state by mbcInit().
  734. *
  735. * RETURNS: N/A
  736. */
  737. LOCAL void mbcReset
  738.     (
  739.     int unit /* unit number */
  740.     )
  741.     {
  742.     DRV_CTRL * pDrvCtrl;
  743.     int counter = 0xffff;
  744.     if (unit < 0 || unit >= MAX_UNITS) /* sanity check the unit number */
  745.         return;
  746.   
  747.     pDrvCtrl = & drvCtrl[unit];
  748.     /* Disable interrupts */
  749.     
  750.     MBC_REG_WRITE (pDrvCtrl->ether.pDevBase, MBC_IMASK, 0x0);
  751.     /* clear pending `graceful stop complete' event, and start one */
  752.     MBC_REG_WRITE (pDrvCtrl->ether.pDevBase, MBC_IEVNT, MBC_IEVNT_GRA);
  753.     MBC_REG_UPDATE (pDrvCtrl->ether.pDevBase, MBC_ECNTL, MBC_ECNTL_GTS);
  754.     /* wait for graceful stop to register */
  755.     
  756.     while ((counter--) &&
  757.            (! (MBC_IEVNT_READ (pDrvCtrl->ether.pDevBase) & MBC_IEVNT_GRA)));
  758.     /* disable the receiver and transmitter. */
  759.     MBC_REG_RESET (pDrvCtrl->ether.pDevBase, MBC_ECNTL, MBC_ECNTL_ENBL);
  760.     /* mark the driver as down */
  761.     pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);
  762.     /* mark the driver as no longer initialized */
  763.     pDrvCtrl->initialized = FALSE;
  764.     pDrvCtrl->resetCounter++;
  765.     
  766.     }
  767. /*******************************************************************************
  768. *
  769. * mbcIntr - network interface interrupt handler
  770. *
  771. * This routine is called at interrupt level. It handles work that 
  772. * requires minimal processing. Interrupt processing that is more 
  773. * extensive gets handled at task level. The network task, netTask(), is 
  774. * provided for this function. Routines get added to the netTask() work 
  775. * queue via the netJobAdd() command.
  776. *
  777. * RETURNS: N/A
  778. */
  779. void mbcIntr
  780.     (
  781.     int unit /* unit number */
  782.     )
  783.     {
  784.     DRV_CTRL *  pDrvCtrl = & drvCtrl[unit];
  785.     volatile char * pDevBase = pDrvCtrl->ether.pDevBase;
  786.     int  events;
  787.     /* identify and acknowledge all interrupt events */
  788.     events = (MBC_IEVNT_READ (pDevBase) &
  789.               (MBC_IMASK_READ (pDevBase) | MBC_IMASK_BSY));
  790.     
  791.     MBC_INTR_ACK (pDevBase, events);
  792.     /* check for spurious interrupt -> driver initialized ? */
  793.     if (! pDrvCtrl->initialized)
  794. {
  795. MBC_INTR_ACK (pDevBase, 0xffff);
  796. return;
  797. }
  798.     /* handle receive events */
  799.     if (events & MBC_IEVNT_RXF)
  800. {
  801.         (void) netJobAdd ((FUNCPTR) mbcHandleInt, (int) pDrvCtrl, 0,0,0,0); 
  802. /* turn off receive interrupts - mbcHandleInt turns back on */
  803. MBC_INTR_DISABLE (pDevBase, MBC_IEVNT_RXF);
  804.         }
  805.     /* handle transmitter events - BD full condition -> ever happen ? */
  806.     if (events & MBC_IEVNT_TXF)
  807. {
  808.         wdCancel (pDrvCtrl->wdId);
  809. #ifdef BSD43_DRIVER        
  810.         (void) netJobAdd ((FUNCPTR) mbcStartOutput, unit, 0, 0, 0, 0); 
  811. #else
  812.         (void) netJobAdd ((FUNCPTR) mbcStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); 
  813. #endif
  814. MBC_INTR_DISABLE (pDevBase, MBC_IEVNT_TXF);
  815. }
  816.     /*
  817.      * check for input busy condition, we don't enable this interrupt
  818.      * but we check for it with each interrupt.
  819.      */
  820.     if (events & MBC_IEVNT_BSY)
  821. {
  822.         /* count discarded frames as errors */
  823.         pDrvCtrl->idr.ac_if.if_ierrors += 1;
  824. }
  825.     /* restart the transmitter on a ethernet bus error */
  826.     
  827.     if (events & MBC_IEVNT_EBE)
  828.         {
  829.         (void) netJobAdd ((FUNCPTR) mbcDeviceRestart, unit, 0,0,0,0);
  830.         
  831.         
  832.         MBC_INTR_ACK (pDevBase, MBC_IEVNT_EBE);
  833.         }
  834.     /* ignore and reset all other events */
  835.     MBC_INTR_ACK (pDevBase, ~(MBC_IMASK_READ(pDevBase)));
  836.     return;
  837.     }
  838. /*******************************************************************************
  839. *
  840. * mbcHandleInt - task-level interrupt handler
  841. *
  842. * This is the task-level interrupt handler, which is called from 
  843. * netTask(). mbcHandleInt() gets input frames from the device and then calls 
  844. * mbcRecv() to process each frame.  mbcRecv() only gets called if no error
  845. * stats were reported in the buffer descriptor.  Data chaining is not
  846. * supported.
  847. *
  848. * This routine should be called with MBC receive interrupts masked so that
  849. * more netJobAdds of this routine are not performed by mbcIntr().
  850. * Receive interrupts are turned back on by this routine before exiting.
  851. *
  852. * RETURNS: N/A
  853. */
  854. LOCAL void mbcHandleInt
  855.     (
  856.     DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */
  857.     )
  858.     {
  859.     volatile char *  pDevBase = pDrvCtrl->ether.pDevBase;
  860.     MBC_BD *      pRxBd;
  861.     pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext];
  862.     
  863.     while (!(pRxBd->statusMode & MBC_RXBD_E))
  864.         {
  865.         /* data chaining is not supported - check all error conditions */
  866.         if (((pRxBd->statusMode & (MBC_RXBD_F  | MBC_RXBD_L))
  867.                        == (MBC_RXBD_F  | MBC_RXBD_L)) &&
  868.             !(pRxBd->statusMode & (MBC_RXBD_CL | MBC_RXBD_OV |
  869.                                    MBC_RXBD_CR | MBC_RXBD_SH |
  870.                                    MBC_RXBD_NO | MBC_RXBD_LG)))
  871.             mbcRecv (pDrvCtrl, pRxBd);
  872.         else
  873.             {
  874.             pDrvCtrl->idr.ac_if.if_ierrors++;
  875.             /*
  876.              * Fix for errata #9 -- Device Errata, Feb 20, 1997.
  877.              * Ethernet frames may be incorrectly received after a rx FIFO
  878.              * overflow.
  879.              */
  880.             
  881.             if ((pRxBd->statusMode & MBC_RXBD_L) &&
  882.                 ! (pRxBd->statusMode & MBC_RXBD_F))
  883.                 {
  884.                 mbcDeviceRestart (pDrvCtrl->ether.mbcNum);
  885.                 return;
  886.                 }
  887.             }
  888.         /* reset buffer descriptor as empty */
  889.         pRxBd->statusMode |= MBC_RXBD_E;
  890.         
  891.         /* incr BD count */
  892.         pDrvCtrl->ether.rxBdNext = (pDrvCtrl->ether.rxBdNext + 1) %
  893.     pDrvCtrl->ether.rxBdNum;
  894.         pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext];
  895.         /* clear Rx events */
  896. MBC_INTR_ACK (pDevBase, MBC_IEVNT_RXF);
  897.         }
  898.     /* re-enable Rx interrupts */
  899.     MBC_INTR_ENABLE (pDevBase, MBC_IEVNT_RXF);
  900.     }
  901. /*******************************************************************************
  902. *
  903. * mbcRecv - process an input frame
  904. *
  905. * This routine processes an input frame, then passes it up to the higher 
  906. * level in a form it expects.  Buffer loaning, promiscuous mode, and
  907. * etherInputHookRtns are all supported.  Trailer protocols is not supported.
  908. *
  909. * RETURNS: N/A
  910. */
  911. LOCAL void mbcRecv
  912.     (
  913.     DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */
  914.     MBC_BD * pRxBd /* receive buffer descriptor */
  915.     )
  916.     { 
  917.     MBUF * pMbuf = NULL; /* MBUF pointer */
  918.     UINT8 * pData;
  919.     int length;
  920. #ifdef BSD43_DRIVER
  921.     UINT16 type;
  922. #else
  923.     struct ether_header *  pEh;
  924. #endif
  925.     /* bump input packet counter */
  926.     pDrvCtrl->idr.ac_if.if_ipackets++;
  927.     /* call hook if one is connected */
  928.     if ((etherInputHookRtn != NULL) && ((*etherInputHookRtn)
  929. (& pDrvCtrl->idr.ac_if, pRxBd->dataPointer, pRxBd->dataLength) != 0))
  930.         return; 
  931.     /* check the M bit, to filter frames not destined for this station. */
  932.     if (pRxBd->statusMode & MBC_RXBD_M)
  933.         return;
  934.     /* adjust length to data only */
  935.     length = pRxBd->dataLength - SIZEOF_ETHERHEADER;
  936.     if (length <= 0)
  937.         pDrvCtrl->idr.ac_if.if_ierrors++;
  938. return;
  939. }
  940.     /* point to data */
  941.     pData = pRxBd->dataPointer + SIZEOF_ETHERHEADER;
  942. #ifdef BSD43_DRIVER
  943.     /* save type - build_cluster trashes the type field */
  944.     type = ((ETH_HDR *) pRxBd->dataPointer)->ether_type;
  945. #else
  946.     /* BSD 4.4 uses Ethernet header */
  947.    
  948.     pEh = (struct ether_header *) pRxBd->dataPointer;
  949. #endif
  950.     /* OK to loan out buffer ? -> build a mbuf cluster */
  951.     if ((pDrvCtrl->nLoan > 0) && (USE_CLUSTER (length)))
  952. pMbuf = build_cluster (pData, length, & pDrvCtrl->idr, MC_MBC,
  953.     pDrvCtrl->pRefCnt[(pDrvCtrl->nLoan - 1)], mbcLoanFree,
  954.     (int) pDrvCtrl, (int) pRxBd->dataPointer,
  955.     (int) pDrvCtrl->pRefCnt[(pDrvCtrl->nLoan - 1)]);
  956.     /* if buffer was successfully turned into mbuf cluster */
  957.     if (pMbuf != NULL)
  958. pRxBd->dataPointer = pDrvCtrl->lPool[--pDrvCtrl->nLoan];
  959.     else
  960.         {
  961. /* else do same ol' copy to mbuf */
  962.         pMbuf = copy_to_mbufs (pData, length, 0, & pDrvCtrl->idr.ac_if);
  963.         if (pMbuf == NULL)
  964.     {
  965.             pDrvCtrl->idr.ac_if.if_ierrors++;
  966.             return;
  967.     }
  968.         }
  969.     /* send up to protocol */
  970. #ifdef BSD43_DRIVER
  971.     do_protocol_with_type (type, pMbuf, & pDrvCtrl->idr, length);
  972. #else
  973.     do_protocol (pEh, pMbuf, & pDrvCtrl->idr, length);
  974. #endif
  975.     }
  976. /*******************************************************************************
  977. *
  978. * mbcDeviceRestart - restart transmits
  979. *
  980. * This routine re-resets the Ethernet device.  It is called by the watchdog
  981. * timer which expires when transmit BDs are all full, and a transmit frame
  982. * interrupt does not occur with in 20 clock ticks.  Since on a transmit lock
  983. * up, the transmitter can be restarted only by resetting the device, this
  984. * routine resets, and reinitializes the device.  The device reset counter will
  985. * be updated on each reset, and can be examined with mbcShow().
  986. *
  987. * RETURNS: N/A
  988. *
  989. * SEE ALSO: mbcIntr(), mbcShow(), mbcStartOutput()
  990. */
  991. LOCAL void mbcDeviceRestart
  992.     (
  993.     int  unit
  994.     )
  995.     {
  996.     mbcReset (unit);
  997.     mbcInit (unit);
  998.     }
  999. /*******************************************************************************
  1000. *
  1001. * mbcLoanFree - return the given buffer to loaner pool
  1002. *
  1003. * This routine returns <pRxBuf> to the pool of available loaner buffers.
  1004. * It also returns <pRef> to the pool of available loaner reference counters,
  1005. * then zeroes the reference count.
  1006. *
  1007. * RETURNS: N/A
  1008. */
  1009. LOCAL void mbcLoanFree
  1010.     (
  1011.     DRV_CTRL * pDrvCtrl,
  1012.     UINT8 * pRxBuf,
  1013.     UINT8 * pRefCnt
  1014.     )
  1015.     {
  1016.     /* return loaned buffer to pool */
  1017.     pDrvCtrl->lPool[pDrvCtrl->nLoan] = pRxBuf;
  1018.     /* return loaned reference count to pool */
  1019.     pDrvCtrl->pRefCnt[pDrvCtrl->nLoan++] = pRefCnt;
  1020.     /* reset reference count - should have been done from above, but... */
  1021.     *pRefCnt = 0;
  1022.     }
  1023. /*******************************************************************************
  1024. *
  1025. * mbcShow - displays the internal state of an Ethernet unit
  1026. *
  1027. * This routine prints the following information about the device unit,
  1028. * .iP
  1029. * - txBdNum, the number of transmit buffer descriptors 
  1030. * .iP
  1031. * - rxBdNum, the number of receive buffer descriptors
  1032. * .iP
  1033. * - txBdNext, the next transmit buffer descriptor index
  1034. * .iP
  1035. * - rxBdNext, the next receive buffer descriptor index
  1036. * .iP
  1037. * - all the Ethernet configuration registers
  1038. * .LP
  1039. *
  1040. * RETURNS: N/A.
  1041. *
  1042. * NOMANUAL
  1043. */
  1044. void mbcShow
  1045.     (
  1046.     int unit                    /* unit number */
  1047.     )
  1048.     {
  1049.     DRV_CTRL * pDrvCtrl;
  1050.     volatile char * pDevBase;
  1051.  
  1052.     
  1053.     if (unit < 0 || unit >= MAX_UNITS)
  1054.         return;
  1055.     pDrvCtrl = & drvCtrl[unit];
  1056.     pDevBase = pDrvCtrl->ether.pDevBase;
  1057.     printf ("mbc (unit %d):n", unit);
  1058.     printf ("    0x%x Resetsn",
  1059.             pDrvCtrl->resetCounter);
  1060.     
  1061.     printf ("    %d transmit BDs, %d receive BDs, %d loaner buffersn",
  1062.             pDrvCtrl->ether.txBdNum, pDrvCtrl->ether.rxBdNum,
  1063.             pDrvCtrl->nLoan);
  1064.     printf ("    Next transmit BD is %d,  Next receive BD is %dn",
  1065.             pDrvCtrl->ether.txBdNext, pDrvCtrl->ether.rxBdNext);
  1066.     printf ("    Registers: ectrl (0x%x), edma (0x%x), mrbl (0x%x)n",
  1067.             MBC_REG_READ (pDevBase, MBC_ECNTL),
  1068.             MBC_REG_READ (pDevBase, MBC_EDMA),
  1069.             MBC_REG_READ (pDevBase, MBC_EMRBLR));
  1070.     
  1071.     printf ("               ivec (0x%x), ievent (0x%x), imask (0x%x)n",
  1072.             MBC_REG_READ (pDevBase, MBC_IVEC),
  1073.             MBC_REG_READ (pDevBase, MBC_IEVNT),
  1074.             MBC_REG_READ (pDevBase, MBC_IMASK));
  1075.                 
  1076.     printf ("               ecnfg (0x%x), etest (0x%x), ar(0x%x)n",
  1077.             MBC_REG_READ (pDevBase, MBC_ECFG),
  1078.             MBC_REG_READ (pDevBase, MBC_TEST),
  1079.             MBC_REG_READ (pDevBase, MBC_AR));
  1080.     }
  1081. /*******************************************************************************
  1082. *
  1083. * mbcBdShow - display buffer descriptors
  1084. *
  1085. * This routine displays the flags, len, and the buffer pointer fields of each
  1086. * buffer descriptor in the requested range. The parameter <start> is the
  1087. * beginning buffer descriptor, and <count> is number of buffer descriptors to
  1088. * display.
  1089. *
  1090. * RETURNS: N/A.
  1091. *
  1092. * NOMANUAL
  1093. */
  1094. void mbcBdShow
  1095.     (
  1096.     int unit,                   /* unit number */
  1097.     int start,                  /* starting BD */
  1098.     int count                   /* number of BDs */
  1099.     )
  1100.     {
  1101.     DRV_CTRL * pDrvCtrl;
  1102.     volatile MBC_BD * pBd;    /* buffer descriptor pointer */
  1103.     
  1104.     
  1105.     if (unit < 0 || unit >= MAX_UNITS)
  1106.         return;
  1107.     pDrvCtrl = & drvCtrl[unit];
  1108.     pBd      = pDrvCtrl->ether.txBdBase;
  1109.     while (start < 128 && count)
  1110.         {
  1111.         printf ("BD %d: flags=0x%x, len=0x%x, pBuf=0x%xn",
  1112.                 start, pBd[start].statusMode,
  1113.                 pBd[start].dataLength,
  1114.                 (UINT32) pBd[start].dataPointer);
  1115.  
  1116.         start++;
  1117.         count--;
  1118.         }
  1119.     }