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

VxWorks

开发平台:

C/C++

  1. /* mbcEnd.c - Motorola 68302fads END network interface driver */
  2. /* Copyright 1996-2000 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01e,11jun00,ham  removed reference to etherLib.
  8. 01d,27jan00,dat  fixed use of NULL
  9. 01c,29mar99,dat  SPR 26119, documentation, usage of .bS/.bE
  10. 01b,13mar99,db   suppressed warnings. integrated driver(SPR #25386)
  11. 01a,28jan99,dra  written.
  12. */
  13. /*
  14. DESCRIPTION
  15. This is a driver for the Ethernet controller on the 68EN302 chip.  The device
  16. supports a 16-bit interface, data rates up to 10 Mbps, a dual-ported RAM, and
  17. transparent DMA.  The dual-ported RAM is used for a 64-entry CAM table, and a
  18. 128-entry buffer descriptor table.  The CAM table is used to set the Ethernet
  19. address of the Ethernet device or to program multicast addresses.  The buffer
  20. descriptor table is partitioned into fixed-size transmit and receive tables.
  21. The DMA operation is transparent and transfers data between the internal FIFOs
  22. and external buffers pointed to by the receive and transmit-buffer descriptors
  23. during transmits and receives.
  24. The driver requires that the memory used for transmit and receive buffers be
  25. allocated in cache-safe RAM area.  
  26. Up to 61 multicast addresses are supported.  Multicast addresses are
  27. supported by adding the multicast ethernet addresses to the address
  28. table in the ethernet part.  If more than 61 multicast addresses are
  29. desired, address hashing must be used (the address table holds 62
  30. entries at most). However, address hashing does not appear to work in
  31. this ethernet part.
  32. A glitch in the EN302 Rev 0.1 device causes the Ethernet transmitter to
  33. lock up from time to time. The driver uses a watchdog timer to reset the
  34. Ethernet device when the device runs out of transmit buffers and cannot
  35. recover within 20 clock ticks.
  36. BOARD LAYOUT
  37. This device is on-chip.  No jumpering diagram is necessary.  
  38. EXTERNAL INTERFACE
  39. The only external interface is the mbcEndLoad() routine, which expects
  40. the <initString> parameter as input.  This parameter passes in a 
  41. colon-delimited string of the format:
  42. unit:memAddr:ivec:txBdNum:rxBdNum:dmaParms:bufBase:offset
  43. TARGET-SPECIFIC PARAMETERS
  44. .IP <unit>
  45. A convenient holdover from the former model.  This parameter is used only
  46. in the string name for the driver.
  47. .IP <memAddr>
  48. This parameter is the base address of the Ethernet module. The driver
  49. addresses all other Ethernet device registers as offsets from this address.
  50. .IP <ivec>
  51. The interrupt vector to be used in connecting the interrupt handler.
  52. .IP <txBdNum>
  53. The number of transmit buffer descriptors to use.
  54. .IP <rxBdNum>
  55. The number of receive buffer descriptors to use.
  56. The number of transmit and receive buffer descriptors (BDs) used is
  57. configurable by the user while attaching the driver.  Each BD is 8
  58. bytes in size and resides in the chip's dual-ported memory, while its
  59. associated buffer, 1520 bytes in size, resides in cache-safe
  60. conventional RAM. A minimum of 2 receive and 2 transmit BDs should be
  61. allocated.  If this parameter is 0, a default of 32 BDs will be used.
  62. The maximum number of BDs depends on how the dual-ported BD RAM is
  63. partitioned.  The 128 BDs in the dual-ported BD RAM can partitioned
  64. into transmit and receive BD regions with 8, 16, 32, or 64 transmit
  65. BDs and corresponding 120, 112, 96, or 64 receive BDs.
  66. .IP <dmaParms>
  67. Ethernet DMA parameters.
  68. This parameter is used to specify the settings of burst limit, water-mark, and
  69. transmit early, which control the Ethernet DMA, and is used to set the EDMA
  70. register.
  71. .IP <bufBase>
  72. Base address of the buffer pool.
  73. This parameter is used to notify the driver that space for the
  74. transmit and receive buffers need not be allocated, but should be
  75. taken from a cache-coherent private memory space provided by the user
  76. at the given address.  The user should be aware that memory used for
  77. buffers must be 4-byte aligned and non-cacheable.  All the buffers
  78. must fit in the given memory space; no checking will be performed.
  79. Each buffer is 1520 bytes.  If this parameter is "NULL", space for
  80. buffers will be obtained by calling cacheDmaMalloc() in mbcMemInit().
  81. .IP <offset>
  82. Specifies the memory alignment offset.
  83. .LP
  84. EXTERNAL SUPPORT REQUIREMENTS
  85. This driver requires several external support functions, defined as macros:
  86. .CS
  87.     SYS_INT_CONNECT(pDrvCtrl, routine, arg)
  88.     SYS_INT_DISCONNECT (pDrvCtrl, routine, arg)
  89.     SYS_INT_ENABLE(pDrvCtrl)
  90.     SYS_OUT_SHORT(pDrvCtrl, reg, data)
  91.     SYS_IN_SHORT(pDrvCtrl, reg, pData)
  92. .CE
  93. There are default values in the source code for these macros.  They presume
  94. memory-mapped accesses to the device registers and the normal intConnect(),
  95. and intEnable() BSP functions.  The first argument to each is the device
  96. controller structure. Thus, each has access back to all the device-specific
  97. information.  Having the pointer in the macro facilitates the addition 
  98. of new features to this driver.
  99. SYSTEM RESOURCE USAGE
  100. The driver requires the following system resources:
  101.     - one watchdog timer
  102.     - one interrupt vector
  103.     - 52 bytes in the initialized data section (data)
  104.     - 0 bytes in the uninitialized data section (bss)
  105. The above data and BSS requirements are for the MC68000 architecture
  106. and can vary for other architectures.  Code size (text) varies greatly 
  107. between architectures and is therefore not quoted here.
  108. If the driver allocates the memory shared with the Ethernet device
  109. unit, it does so by calling the cacheDmaMalloc() routine.  For the
  110. default case of 32 transmit buffers, 32 receive buffers, the total
  111. size requested is roughly 100,000 bytes.  If a memory region is
  112. provided to the driver, the size of this region is adjustable to suit
  113. user needs.
  114. This driver can only operate if the shared memory region is non-cacheable,
  115. or if the hardware implements bus snooping.  The driver cannot maintain
  116. cache coherency for the device because the buffers are asynchronously
  117. modified by both the driver and the device, and these fields may share the
  118. same cache line.  Additionally, the chip's dual-ported RAM must be
  119. declared as non-cacheable memory where applicable.
  120. INCLUDES:
  121. end.h endLib.h etherMultiLib.h
  122. SEE ALSO: muxLib, endLib
  123. .I "Writing and Enhanced Network Driver"
  124. */
  125. /* includes */
  126. #include "vxWorks.h"
  127. #include "stdlib.h"
  128. #include "cacheLib.h"
  129. #include "intLib.h"
  130. #include "end.h" /* Common END structures. */
  131. #include "endLib.h"
  132. #include "lstLib.h" /* Needed to maintain protocol list. */
  133. #include "wdLib.h"
  134. #include "iv.h"
  135. #include "semLib.h"
  136. #include "logLib.h"
  137. #include "netLib.h"
  138. #include "stdio.h"
  139. #include "sysLib.h"
  140. #include "errno.h"
  141. #include "errnoLib.h"
  142. #include "memLib.h"
  143. #include "iosLib.h"
  144. #undef ETHER_MAP_IP_MULTICAST
  145. #include "etherMultiLib.h" /* multicast stuff. */
  146. #include "net/mbuf.h"
  147. #include "net/unixLib.h"
  148. #include "net/protosw.h"
  149. #include "net/systm.h"
  150. #include "net/if_subr.h"
  151. #include "net/route.h"
  152. #include "sys/socket.h"
  153. #include "sys/ioctl.h"
  154. #include "sys/times.h"
  155. #include "drv/end/mbcEnd.h"
  156. /* defines */
  157. #define FRAME_MAX 1518 /* maximum frame size */
  158. #define FRAME_MIN 64 /* minimum frame size */
  159. #define ENET_ADDR_SIZE 6 /* size of ethernet src/dst addresses */
  160. #define TX_BD_MIN 2 /* minimum number of Tx buffer descriptors */
  161. #define RX_BD_MIN 2 /* minimum number of Rx buffer descriptors */
  162. #define TX_BD_DEFAULT 0x20 /* default number of Tx buffer descriptors */
  163. #define RX_BD_DEFAULT 0x20 /* default number of Rx buffer descriptors */
  164. #define WD_TIMEOUT 20 /* number of clock ticks for reset timeout */
  165. #define MBC_BUFSIZ      (1520)
  166. #define MBC_MIN_FBUF (1520) /* min first buffer size */
  167. #define EH_SIZE (14)
  168. #define MBC_SPEED_10M 10000000 /* 10Mbs */
  169. #define MBC_SPEED MBC_SPEED_10M
  170. /* Cache macros */
  171. #define MBC_CACHE_INVALIDATE(address, len) 
  172.         CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))
  173. #define MBC_CACHE_PHYS_TO_VIRT(address) 
  174.         CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
  175. #define MBC_CACHE_VIRT_TO_PHYS(address) 
  176.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  177. /*
  178.  * Default macro definitions for BSP interface.
  179.  * These macros can be redefined in a wrapper file, to generate
  180.  * a new module with an optimized interface.
  181.  */
  182. /* Macro to connect interrupt handler to vector */
  183. #ifndef SYS_INT_CONNECT
  184. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) 
  185.     { 
  186.     IMPORT STATUS sysIntConnect(); 
  187.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC ((pDrvCtrl)->ivec), 
  188.    rtn, (int)(arg)); 
  189.     }
  190. #endif
  191. /* Macro to disconnect interrupt handler from vector */
  192. LOCAL void dummyIsr (void) { };
  193. #ifndef SYS_INT_DISCONNECT
  194. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) 
  195.     { 
  196.     IMPORT STATUS intConnect(); 
  197.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC ((pDrvCtrl)->ivec), 
  198.     dummyIsr, (int)(arg)); 
  199.     }
  200. #endif
  201. /* Macro to get the ethernet address from the BSP */
  202. #ifndef SYS_ENET_ADDR_GET
  203. #define SYS_ENET_ADDR_GET(pAddress) 
  204.     { 
  205.     sysEnetAddrGet (pDrvCtrl->unit, (char *) (pAddress)); 
  206.     }
  207. #endif /* SYS_ENET_ADDR_GET */
  208. /*
  209.  * Macros to do a short (UINT16) access to the chip. Default
  210.  * assumes a normal memory mapped device.
  211.  */
  212. #ifndef SYS_OUT_SHORT
  213. #define SYS_OUT_SHORT(pDrvCtrl, addr, value) 
  214. (*(volatile UINT16 *)((pDrvCtrl)->memAddr + (addr)) = (value))
  215. #endif
  216. #ifndef SYS_IN_SHORT
  217. #define SYS_IN_SHORT(pDrvCtrl, addr, pData) 
  218. (*(pData) = (*(volatile UINT16 *)((pDrvCtrl)->memAddr + (addr))))
  219. #endif
  220. #ifndef SYS_UPDATE_SHORT
  221. #define SYS_UPDATE_SHORT(pDrvCtrl, addr, val) 
  222. ((*(volatile UINT16 *)((pDrvCtrl)->memAddr + (addr))) |= (val))
  223. #endif
  224. #ifndef SYS_RESET_SHORT
  225. #define SYS_RESET_SHORT(pDrvCtrl, addr, val) 
  226. ((*(volatile UINT16 *)((pDrvCtrl)->memAddr + (addr))) &= ~(val))
  227. #endif
  228.     
  229. /* A shortcut for getting the hardware address from the MIB II stuff. */
  230. #define END_HADDR(pEnd)
  231. ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  232. #define END_HADDR_LEN(pEnd) 
  233. ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  234. /* Definitions for the flags field */
  235. #define MBC_POLLING 0x1
  236. #define MBC_MEM_ALLOC_FLAG      0x2
  237. /* DEBUG MACROS */
  238. #undef DRV_DEBUG
  239. #ifdef DRV_DEBUG
  240. #define DRV_DEBUG_OFF 0x0000
  241. #define DRV_DEBUG_RX 0x0001
  242. #define DRV_DEBUG_TX 0x0002
  243. #define DRV_DEBUG_INT 0x0004
  244. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  245. #define DRV_DEBUG_POLL_RX 0x0008
  246. #define DRV_DEBUG_POLL_TX 0x0010
  247. #define DRV_DEBUG_LOAD 0x0020
  248. #define DRV_DEBUG_IOCTL 0x0040
  249. #define DRV_DEBUG_MULTI 0x0080
  250. #define DRV_DEBUG_ERROR 0x0100
  251. int mbcDebug = DRV_DEBUG_ERROR;
  252. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)
  253.     do
  254.         {
  255. if (mbcDebug & (FLG))
  256.     logMsg (X0, X1, X2, X3, X4, X5, X6);
  257. }
  258.     while (0)
  259. #define DRV_PRINT(FLG, X)
  260.     do
  261.         {
  262. if (mbcDebug & (FLG))
  263.     printf X;
  264. }
  265.     while (0)
  266. #else /* DRV_DEBUG */
  267.     
  268. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) do {} while (0)
  269. #define DRV_PRINT(FLG, X) do {} while (0)
  270.     
  271. #endif /* DRV_DEBUG */
  272. /* typedefs */
  273. typedef struct free_args
  274.     {
  275.     void * arg1;
  276.     void * arg2;
  277.     } FREE_ARGS;
  278.         
  279. /* The definition of the driver control structure */
  280. typedef struct MBC_DEVICE
  281.     {
  282.     END_OBJ     end; /* The class we inherit from. */
  283.     int unit; /* unit number */
  284.     int         ivec;                   /* interrupt vector */
  285.     WDOG_ID wdId; /* watchdog id */
  286.     UCHAR * memAddr; /* address of mbc's shared memory */
  287.     int txBdNum; /* number of tx buffer descriptors */
  288.     int rxBdNum; /* number of rx buffer descriptors */
  289.     int dmaParms; /* DMA parameters */
  290.     int         offset; /* packet data offset */
  291.     UCHAR enetAddr[6]; /* ethernet address */    
  292.     ULONG flags; /* Our local flags. */
  293.     BOOL txBlocked; /* TX is blocked */
  294.     BOOL txCleaning; /* TX is being cleaned */
  295.     BOOL rxHandling; /* rcv task is scheduled */
  296.     char * bufBase; /* address of memory pool; */
  297.     int bdSize; /* buffer descriptor size */
  298.     MBC_BD * txBdBase; /* transmit BD array address */
  299.     MBC_BD * rxBdBase; /* receive BD array address */
  300.     int txBdNext; /* next transmit BD to fill */
  301.     int txClNext; /* next transmit BD to clean */
  302.     int rxBdNext; /* next receive BD to read */
  303.     int resetCounter; /* number of times the device reset */
  304.     CACHE_FUNCS cacheFuncs;             /* cache function pointers */
  305.     UCHAR mcastFilter[8]; /* multicast address mask */
  306.     FUNCPTR     freeRtn[128];           /* Array of free routines. */
  307.     struct free_args    freeData[128];  /* Array of free arguments */
  308.                                         /* to the free routines. */
  309.     CL_POOL_ID pClPoolId; /* cluster pool */
  310.     } MBC_DEVICE;
  311. /* globals */
  312. IMPORT STATUS sysEnetAddrGet (int unit, char * addr);
  313. IMPORT int endMultiLstCnt (END_OBJ * pEnd);
  314. /* locals */
  315. /* forward static functions */
  316. LOCAL void mbcReset (MBC_DEVICE * pDrvCtrl);
  317. LOCAL void mbcInt (MBC_DEVICE * pDrvCtrl);
  318. LOCAL void mbcHandleRcvInt (MBC_DEVICE * pDrvCtrl);
  319. LOCAL STATUS mbcRecv (MBC_DEVICE * pDrvCtrl, char * pData);
  320. LOCAL void mbcConfig (MBC_DEVICE * pDrvCtrl);
  321. LOCAL STATUS mbcInit (MBC_DEVICE * pDrvCtrl);
  322. LOCAL void mbcAddrFilterSet(MBC_DEVICE * pDrvCtrl);
  323. LOCAL void mbcScrubTRing (MBC_DEVICE * pDrvCtrl);
  324. LOCAL STATUS mbcPollStart (MBC_DEVICE * pDrvCtrl);
  325. LOCAL STATUS mbcPollStop (MBC_DEVICE * pDrvCtrl);
  326. LOCAL void mbcDeviceRestart(MBC_DEVICE * pDrvCtrl);
  327. LOCAL STATUS mbcParse (MBC_DEVICE * pDrvCtrl, char * initString);
  328. LOCAL STATUS mbcMemInit (MBC_DEVICE * pDrvCtrl);
  329. /* END Specific interfaces. */
  330. /* This is the only externally visible interface. */
  331. END_OBJ *  mbcEndLoad (char * initString);
  332. LOCAL STATUS mbcStart (void * pDrvCtrl);
  333. LOCAL STATUS mbcStop (void * pDrvCtrl);
  334. LOCAL STATUS mbcUnload (void * pDrvCtrl);
  335. LOCAL int mbcIoctl (void * pDrvCtrl, int cmd, caddr_t data);
  336. LOCAL STATUS mbcSend (void * pDrvCtrl, M_BLK_ID pBuf);
  337. LOCAL STATUS mbcMCastAdd (void * pDrvCtrl, char * pAddress);
  338. LOCAL STATUS mbcMCastDel (void * pDrvCtrl, char * pAddress);
  339. LOCAL STATUS mbcMCastGet (void * pDrvCtrl, MULTI_TABLE * pTable);
  340. LOCAL STATUS mbcPollSend (void * pDrvCtrl, M_BLK_ID pBuf);
  341. LOCAL STATUS mbcPollRcv (void * pDrvCtrl, M_BLK_ID pBuf);
  342. /*
  343.  * Declare our function table.  This is static across all driver
  344.  * instances.
  345.  */
  346. LOCAL NET_FUNCS mbcFuncTable =
  347.     {
  348.     (FUNCPTR) mbcStart,    /* Function to start the device. */
  349.     (FUNCPTR) mbcStop,    /* Function to stop the device. */
  350.     (FUNCPTR) mbcUnload,   /* Unloading function for the driver. */
  351.     (FUNCPTR) mbcIoctl,    /* Ioctl function for the driver. */
  352.     (FUNCPTR) mbcSend,    /* Send function for the driver. */
  353.     (FUNCPTR) mbcMCastAdd, /* Multicast add function for the  driver*/
  354.     (FUNCPTR) mbcMCastDel, /* Multicast delete function for driver */
  355.     (FUNCPTR) mbcMCastGet, /* Multicast retrieve function for driver*/
  356.     (FUNCPTR) mbcPollSend, /* Polling send function */
  357.     (FUNCPTR) mbcPollRcv,  /* Polling receive function */
  358.     endEtherAddressForm,   /* put address info into a NET_BUFFER */
  359.     endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
  360.     endEtherPacketAddrGet  /* Get packet addresses. */
  361.     };
  362. /******************************************************************************
  363. *
  364. * mbcEndLoad - initialize the driver and device
  365. *
  366. * This routine initializes the driver and the device to the operational state.
  367. * All of the device specific parameters are passed in the initString.
  368. *
  369. * The string contains the target specific parameters like this:
  370. *
  371. * "unit:memAddr:ivec:txBdNum:rxBdNum:dmaParms:bufBase:offset"
  372. * RETURNS: An END object pointer or NULL on error.
  373. */
  374. END_OBJ* mbcEndLoad
  375.     (
  376.     char * initString /* String to be parsed by the driver. */
  377.     )
  378.     {
  379.     MBC_DEVICE * pDrvCtrl;
  380.       
  381.     if (initString == NULL)
  382.         return (NULL);
  383.     
  384.     if (initString[0] == 0)
  385.         {
  386.         bcopy ((char *)DEV_NAME, initString, DEV_NAME_LEN);
  387.         return (NULL);
  388.         }
  389.  
  390.     DRV_LOG (DRV_DEBUG_LOAD, "Loading mbc...n", 1, 2, 3, 4, 5, 6);
  391.    
  392.     /* allocate the device structure */
  393.     pDrvCtrl = (MBC_DEVICE *) calloc (sizeof (MBC_DEVICE), 1);
  394.     if (pDrvCtrl == NULL)
  395. goto errorExit;
  396.           
  397.     /* parse the init string, filling in the device structure */
  398.     if (mbcParse (pDrvCtrl, initString) == ERROR)
  399. goto errorExit;
  400.     /* Ask the BSP to provide the ethernet address. */
  401.     
  402.     SYS_ENET_ADDR_GET (&pDrvCtrl->enetAddr);
  403.    
  404.     /* Allocate a watchdog timer */
  405.     pDrvCtrl->wdId = wdCreate ();
  406.     if (pDrvCtrl->wdId == NULL)
  407. goto errorExit;
  408.     /* initialize the END and MIB2 parts of the structure */
  409.     /*
  410.      * The M2 element must come from m2Lib.h 
  411.      * This mbcis set up for a DIX type ethernet device.
  412.      */
  413.     
  414.     if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, DEV_NAME,
  415.                       pDrvCtrl->unit, &mbcFuncTable,
  416.                       "END mbcDriver.") == ERROR)
  417. goto errorExit;
  418.     if (END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
  419.                       &pDrvCtrl->enetAddr[0], 6, ETHERMTU,
  420.                       MBC_SPEED) == ERROR)
  421. goto errorExit;
  422.     /* Perform memory allocation/distribution */
  423.     if (mbcMemInit (pDrvCtrl) == ERROR)
  424. goto errorExit;
  425.     /* reset and reconfigure the device */
  426.     mbcReset (pDrvCtrl);
  427.     mbcInit (pDrvCtrl);
  428.     mbcConfig (pDrvCtrl);
  429.     /* set the flags to indicate readiness */
  430.     END_OBJ_READY (&pDrvCtrl->end,
  431.    IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
  432.    | IFF_MULTICAST);
  433.     DRV_LOG (DRV_DEBUG_RX, "%s%d: mbcEndLoad: offset=%dn",
  434.      (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->offset, 0, 0, 0);
  435.     return (&pDrvCtrl->end);
  436. errorExit:
  437.     if (pDrvCtrl != NULL)
  438. {
  439. if (pDrvCtrl->wdId)
  440.     wdDelete (pDrvCtrl->wdId);
  441. free ((char *)pDrvCtrl);
  442. }
  443.     return (NULL);
  444.     }
  445. /******************************************************************************
  446. *
  447. * mbcParse - parse the init string
  448. *
  449. * Parse the input string.  Fill in values in the driver control structure.
  450. *
  451. * The initialization string format is:
  452. * .CS
  453. *    "unit:memAddr:ivec:txBdNum:rxBdNum:dmaParms:bufBase:offset"
  454. * .CE
  455. *
  456. * .IP <unit>
  457. * Device unit number, a small integer.
  458. * .IP <memAddr>
  459. * ethernet module base address.
  460. * .IP <ivec>
  461. * Interrupt vector number (used with sysIntConnect)
  462. * .IP <txBdNum>
  463. * transmit buffer descriptor
  464. * .IP <rxBdNum>
  465. * receive buffer descriptor
  466. * .IP <dmaParms>
  467. * dma parameters
  468. * .IP <bufBase>
  469. * address of memory pool
  470. * .IP <offset>
  471. * packet data offset 
  472. * .LP
  473. *
  474. * RETURNS: OK or ERROR for invalid arguments.
  475. */
  476. STATUS mbcParse
  477.     (
  478.     MBC_DEVICE * pDrvCtrl, /* device pointer */
  479.     char * initString /* information string */
  480.     )
  481.     {
  482.     char * tok;
  483.     char * pHolder = NULL;
  484.     
  485.     /* Parse the initString */
  486.     /* Unit number. */
  487.     tok = strtok_r (initString, ":", &pHolder);
  488.     if (tok == NULL)
  489. return (ERROR);
  490.     pDrvCtrl->unit = strtoul (tok, NULL, 16);
  491.     /* ethernet module base address */
  492.     tok = strtok_r (NULL, ":", &pHolder);
  493.     if (tok == NULL)
  494. return (ERROR);
  495.     pDrvCtrl->memAddr = (void *) strtoul (tok, NULL, 16);
  496.     
  497.     /* Interrupt vector. */
  498.     tok = strtok_r (NULL, ":", &pHolder);
  499.     if (tok == NULL)
  500. return (ERROR);
  501.     pDrvCtrl->ivec = strtoul (tok, NULL, 16);
  502.     /* number of transmit buffer descriptors */
  503.     tok = strtok_r (NULL, ":", &pHolder);
  504.     if (tok == NULL)
  505. return (ERROR);
  506.     pDrvCtrl->txBdNum = strtoul (tok, NULL, 16);
  507.     /* number of receive buffer descriptors */
  508.     tok = strtok_r (NULL, ":", &pHolder);
  509.     if (tok == NULL)
  510. return (ERROR);
  511.     pDrvCtrl->rxBdNum = strtoul (tok, NULL, 16);
  512.     /* DMA parameters */
  513.     tok = strtok_r (NULL, ":", &pHolder);
  514.     if (tok == NULL)
  515. return (ERROR);
  516.     pDrvCtrl->dmaParms = strtoul (tok, NULL, 16);
  517.     /* address of memory pool; NONE = malloc it */
  518.     tok = strtok_r (NULL, ":", &pHolder);
  519.     if (tok == NULL)
  520. return (ERROR);
  521.     pDrvCtrl->bufBase = (void *) strtoul (tok, NULL, 16);
  522.     /* packet data offset */
  523.     tok = strtok_r (NULL, ":", &pHolder);
  524.     if (tok == NULL)
  525. return (ERROR);
  526.     pDrvCtrl->offset = strtoul (tok, NULL, 16);
  527.     return (OK);
  528.     }
  529. /******************************************************************************
  530. *
  531. * mbcMemInit - initialize memory for the chip
  532. *
  533. * Allocates and initializes the memory pools for the mbc device.
  534. *
  535. * RETURNS: OK or ERROR.
  536. */
  537. STATUS mbcMemInit
  538.     (
  539.     MBC_DEVICE * pDrvCtrl /* device to be initialized */
  540.     )
  541.     {
  542.     MBC_BD * pBd;
  543.     int counter;
  544.     int bdSize;
  545.     int txBdMax;
  546.     int rxBdMax;
  547.     M_CL_CONFIG mbcMclBlkConfig;
  548.     CL_DESC mbcClDesc;
  549.     /* Setup the netPool */
  550.     
  551.     if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  552.         return (ERROR);
  553.     /* Use default values if the parameters are NULL */
  554.     if (pDrvCtrl->txBdNum == 0)
  555.         pDrvCtrl->txBdNum = TX_BD_DEFAULT;
  556.     if (pDrvCtrl->rxBdNum == 0)
  557.         pDrvCtrl->rxBdNum = RX_BD_DEFAULT;
  558.     /* Use the default minimum value if the given value is smaller */
  559.     pDrvCtrl->txBdNum = max (TX_BD_MIN, pDrvCtrl->txBdNum);
  560.     pDrvCtrl->rxBdNum = max (RX_BD_MIN, pDrvCtrl->rxBdNum);
  561.     
  562.     /* Ensure that txBdNum, and rxBdNum are within range */
  563.     
  564.     if (pDrvCtrl->txBdNum > 64)
  565.         pDrvCtrl->txBdNum = 64;
  566.     for (bdSize = MBC_EDMA_BDS_8; bdSize <= MBC_EDMA_BDS_64; bdSize++) 
  567. {
  568. txBdMax = 1 << (bdSize + 3);   /* set txBdMax to (8, 16, 32, 64) */
  569.         rxBdMax = MBC_BD_MAX - txBdMax;
  570.         
  571.         if (pDrvCtrl->txBdNum <= txBdMax)
  572.             {
  573.             if (pDrvCtrl->rxBdNum > rxBdMax)
  574.                 pDrvCtrl->rxBdNum = rxBdMax;
  575.             break;
  576.             }
  577.         }
  578.     /* fill in the driver control parameters */
  579.     
  580.     pDrvCtrl->bdSize = bdSize;
  581.     pDrvCtrl->txBdBase = (MBC_BD *) ((int) pDrvCtrl->memAddr + MBC_EBD);
  582.     pDrvCtrl->rxBdBase = (MBC_BD *) ((int) pDrvCtrl->memAddr + MBC_EBD
  583.      + sizeof (MBC_BD) * (1 << (bdSize + 3)));
  584.     pDrvCtrl->txBdNext = 0;
  585.     pDrvCtrl->rxBdNext = 0;
  586.     pDrvCtrl->resetCounter = 0;
  587.     DRV_LOG (DRV_DEBUG_LOAD,
  588.      "%s%d: rxBdNum=%d txBdNum=%d rxBdBase=%x txBdBase=%xn",
  589.      (int) DEV_NAME, pDrvCtrl->unit,
  590.      pDrvCtrl->rxBdNum, pDrvCtrl->txBdNum,
  591.      (int) pDrvCtrl->rxBdBase, (int) pDrvCtrl->txBdBase);
  592.     mbcClDesc.clNum = 4 * (pDrvCtrl->rxBdNum + pDrvCtrl->txBdNum);
  593.     mbcClDesc.clSize = MEM_ROUND_UP (MBC_BUFSIZ + pDrvCtrl->offset);
  594.     mbcClDesc.memSize = (mbcClDesc.clNum * (mbcClDesc.clSize + 4)) + 4;
  595.     /* Calculate the total memory for all the M-Blks and CL-Blks. */
  596.     mbcMclBlkConfig.mBlkNum = mbcClDesc.clNum;
  597.     mbcMclBlkConfig.clBlkNum = mbcClDesc.clNum;
  598.     mbcMclBlkConfig.memSize =
  599.       (mbcMclBlkConfig.mBlkNum * (MSIZE + sizeof (long)))
  600.       + (mbcMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
  601.     mbcMclBlkConfig.memArea = (char *) memalign (sizeof(long),
  602.  mbcMclBlkConfig.memSize);
  603.     if (mbcMclBlkConfig.memArea == NULL)
  604. {
  605. free (pDrvCtrl->end.pNetPool);
  606. return (ERROR);
  607. }
  608.     
  609.     /* Allocate the memory for the clusters from cache safe memory. */
  610.     
  611.     if (pDrvCtrl->bufBase == NULL)
  612. {
  613. /* Get our own memory */
  614. pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  615. pDrvCtrl->bufBase = (char *) cacheDmaMalloc (mbcClDesc.memSize);
  616. pDrvCtrl->flags |= MBC_MEM_ALLOC_FLAG;
  617. if (pDrvCtrl->bufBase == NULL)
  618.             {
  619.     DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_ERROR,
  620.      "%s%d: system memory unavailable (%d bytes)n",
  621.      (int) DEV_NAME, pDrvCtrl->unit, mbcClDesc.memSize,
  622.      4, 5, 6);
  623.     free (pDrvCtrl->end.pNetPool);
  624.     free (mbcMclBlkConfig.memArea);
  625.     return (ERROR);
  626.     }
  627. }
  628.     else
  629. {
  630. /* Caller provided memory */
  631. pDrvCtrl->cacheFuncs = cacheNullFuncs;
  632. }
  633.    
  634.     mbcClDesc.memArea = pDrvCtrl->bufBase;
  635.     
  636.     /* Initialize the memory pool. */
  637.     if (netPoolInit(pDrvCtrl->end.pNetPool, &mbcMclBlkConfig,
  638.                     &mbcClDesc, 1, NULL) == ERROR)
  639.         {
  640.         DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_ERROR,
  641.  "Could not init bufferingn",
  642.  1, 2, 3, 4, 5, 6);
  643. free (pDrvCtrl->end.pNetPool);
  644. free (mbcMclBlkConfig.memArea);
  645. if (pDrvCtrl->flags & MBC_MEM_ALLOC_FLAG)
  646.     cacheDmaFree (pDrvCtrl->bufBase);
  647. return (ERROR);
  648.         }
  649.     /*
  650.      * If you need clusters to store received packets into then get them
  651.      * here ahead of time.
  652.      */
  653.     pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool,
  654.   MBC_BUFSIZ, FALSE);
  655.     if (pDrvCtrl->pClPoolId == NULL)
  656. {
  657. free (pDrvCtrl->end.pNetPool);
  658. free (mbcMclBlkConfig.memArea);
  659. if (pDrvCtrl->flags & MBC_MEM_ALLOC_FLAG)
  660.     cacheDmaFree (pDrvCtrl->bufBase);
  661. return (ERROR);
  662. }
  663.     
  664.     /* take the device out of reset state */
  665.     SYS_OUT_SHORT (pDrvCtrl, MBC_ECNTL, MBC_ECNTL_RES_OFF);
  666.     /* set up transmit buffer descriptors, setting 'wrap' bit on last */
  667.     
  668.     pDrvCtrl->txBdNext = 0;
  669.     pDrvCtrl->txClNext = 0;
  670.     pBd = pDrvCtrl->txBdBase;
  671.     for (counter = pDrvCtrl->txBdNum; counter; counter--, pBd++)
  672. {
  673.         pBd->statusMode = (MBC_TXBD_I | MBC_TXBD_L | MBC_TXBD_TC);
  674. pBd->dataPointer = NULL;
  675. }
  676.     pBd--;
  677.     pBd->statusMode |= MBC_TXBD_W;
  678.     /* set up the receive buffer descriptors, setting 'wrap' bit on last */
  679.     pDrvCtrl->rxBdNext = 0;
  680.     pBd = pDrvCtrl->rxBdBase;
  681.     for (counter = pDrvCtrl->rxBdNum; counter; counter--, pBd++)
  682. {
  683.         pBd->statusMode = MBC_RXBD_I;
  684. pBd->dataPointer = NULL;
  685. }
  686.     pBd--;
  687.     pBd->statusMode |= MBC_RXBD_W;
  688.     DRV_LOG (DRV_DEBUG_LOAD, "%s%d: Memory setup completen",
  689.      (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  690.       
  691.     return (OK);
  692.     }
  693. /******************************************************************************
  694. *
  695. * mbcInit - initialize the MBC network device
  696. * Mbc initializes registers, and enables interrupts.
  697. *
  698. * The complement of this routine is mbcReset().  Once a unit is reset by
  699. * mbcReset(), it may be re-initialized to a running state by this routine.
  700. *
  701. * RETURNS: OK or ERROR.
  702. *
  703. * SEE ALSO: mbcIoctl(), mbcReset()
  704. *
  705. */
  706. LOCAL STATUS mbcInit
  707.     (
  708.     MBC_DEVICE * pDrvCtrl
  709.     )
  710.     {
  711.     UINT16 regValue;
  712.     MBC_BD * pBd;
  713.     int counter;
  714.     DRV_LOG (DRV_DEBUG_LOAD, "%s%d: mbcInitn",
  715.      (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  716.     /* take the device out of reset state */
  717.     SYS_OUT_SHORT (pDrvCtrl, MBC_ECNTL, MBC_ECNTL_RES_OFF);
  718.     /*
  719.      * set up transmit buffer descriptors, setting 'wrap' bit on last.
  720.      * clean up any transmit buffers left behind.
  721.      */
  722.     
  723.     pDrvCtrl->txBdNext = 0;
  724.     pDrvCtrl->txClNext = 0;
  725.     pBd = pDrvCtrl->txBdBase;
  726.     for (counter = pDrvCtrl->txBdNum; counter; counter--, pBd++)
  727. {
  728. if ((pBd->dataPointer != NULL) && (pDrvCtrl->freeRtn[counter] != NULL))
  729.     pDrvCtrl->freeRtn[counter] (pDrvCtrl->freeData[counter].arg1,
  730. pDrvCtrl->freeData[counter].arg2); 
  731. pDrvCtrl->freeRtn[counter] = NULL;
  732. pDrvCtrl->freeData[counter].arg1 = NULL; 
  733. pDrvCtrl->freeData[counter].arg2 = NULL; 
  734. pBd->dataPointer = NULL;
  735.         pBd->statusMode = (MBC_TXBD_I | MBC_TXBD_L | MBC_TXBD_TC);
  736. }
  737.     pBd--;
  738.     pBd->statusMode |= MBC_TXBD_W;
  739.     /*
  740.      * set up the receive buffer descriptors, setting 'wrap' bit on last.
  741.      * Free up any old receive clusters left behind.
  742.      */
  743.     pDrvCtrl->rxBdNext = 0;
  744.     pBd = pDrvCtrl->rxBdBase;
  745.     for (counter = pDrvCtrl->rxBdNum; counter; counter--, pBd++)
  746. {
  747. char * pBuf;
  748. if (pBd->dataPointer != NULL)
  749.     netClFree (pDrvCtrl->end.pNetPool,
  750.        (pBd->dataPointer - pDrvCtrl->offset));
  751. pBuf = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  752. if (pBuf == NULL)
  753.     {
  754.             DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_ERROR,
  755.      "Could not get a buffern", 1, 2, 3, 4, 5, 6);
  756.             return (ERROR);
  757.     }
  758.         pBd->statusMode = (MBC_RXBD_E | MBC_RXBD_I);
  759. pBd->dataPointer = pBuf + pDrvCtrl->offset;
  760. }
  761.     pBd--;
  762.     pBd->statusMode |= MBC_RXBD_W;
  763.     /* set the interrupt vector number */
  764.     SYS_OUT_SHORT (pDrvCtrl, MBC_IVEC, pDrvCtrl->ivec);
  765.     /* set BD size and other DMA parameters */
  766.     regValue = pDrvCtrl->dmaParms | (pDrvCtrl->bdSize << MBC_EDMA_BDS_SHFT);
  767.     SYS_OUT_SHORT (pDrvCtrl, MBC_EDMA, regValue);
  768.     /*
  769.      * set the operating mode to, no internal loopback, no full duplex, and
  770.      * no hearbeat control.
  771.      */
  772.     
  773.     SYS_OUT_SHORT (pDrvCtrl, MBC_ECFG, 0);
  774.     /*
  775.      * set address control to, no hash enable, no index enable, no multicast,
  776.      * no physical address rejection.
  777.      */
  778.     
  779.     SYS_OUT_SHORT (pDrvCtrl, MBC_AR, 0x00);
  780.     /* set max receive frame size */
  781.     SYS_OUT_SHORT (pDrvCtrl, MBC_EMRBLR, FRAME_MAX);
  782.         
  783.     return (OK);
  784.     }
  785. /******************************************************************************
  786. *
  787. * mbcDeviceRestart - restart transmits
  788. *
  789. * This routine re-resets the Ethernet device. Since on a transmit lock
  790. * up, the transmitter can be restarted only by resetting the device, this
  791. * routine resets, and reinitializes the device.  The device reset counter will
  792. * be updated on each reset.
  793. *
  794. * RETURNS: N/A
  795. *
  796. * SEE ALSO: mbcInt(), mbcSend(), mbcPacketGet()
  797. *
  798. * NOMANUAL
  799. */
  800. LOCAL void mbcDeviceRestart
  801.     (
  802.     MBC_DEVICE * pDrvCtrl
  803.     )
  804.     {
  805.     mbcReset (pDrvCtrl);
  806.     mbcInit (pDrvCtrl);
  807.     }
  808. /******************************************************************************
  809. *
  810. * mbcConfig - reconfigure the interface under us.
  811. *
  812. * Reconfigure the interface setting promiscuous mode, and changing the
  813. * multicast interface list.
  814. *
  815. * RETURNS: N/A.
  816. *
  817. * NOMANUAL
  818. */
  819. LOCAL void mbcConfig
  820.     (
  821.     MBC_DEVICE * pDrvCtrl /* device to be re-configured */
  822.     )
  823.     {
  824.     int i;
  825.     int numMulti; /* Number of multicast addresses */
  826.     UINT16 regValue;
  827.     /* Determine the number of multicast addresses */
  828.     numMulti = END_MULTI_LST_CNT (&pDrvCtrl->end);
  829.     DRV_LOG (DRV_DEBUG_LOAD, "%s%d: mbcConfig: %d multicast addressesn",
  830.      (int) DEV_NAME, pDrvCtrl->unit, numMulti, 4, 5, 6);
  831.     /* install the ethernet address */
  832.     
  833.     bcopy ((char *) pDrvCtrl->enetAddr,
  834.            (char *) (pDrvCtrl->memAddr + MBC_ARTAB),
  835.            ENET_ADDR_SIZE);
  836.     
  837.     /*
  838.      * Setup address control w/o multicasting enabled, and write
  839.      * the entire address arrray.
  840.      */
  841.     
  842.     regValue = MBC_AR_MULTI_00;
  843.     if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
  844.         regValue |= MBC_AR_PROM;
  845.     SYS_OUT_SHORT (pDrvCtrl, MBC_AR, regValue);
  846.     for (i = 1; i < MBC_ARTAB_SIZE; i++)
  847.         {
  848.         SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + (i * 8), ~0);
  849.         SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + (i * 8) + 2, ~0);
  850.         SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + (i * 8) + 4, ~0);
  851.         }
  852.     
  853.     /* Now install the multicast addresses or filter */
  854.     if ((numMulti > 0) && (numMulti <= MBC_ARTAB_SIZE-1))
  855. {
  856. ETHER_MULTI * pCurr;
  857. /* Install the multicast addresses directly in the table */
  858. for (i = 1, pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
  859.      pCurr != NULL;
  860.      pCurr = END_MULTI_LST_NEXT(pCurr), ++i)
  861.     {
  862.     bcopy ((char *) &pCurr->addr,
  863.    (char *) (pDrvCtrl->memAddr + MBC_ARTAB + i*8),
  864.    ENET_ADDR_SIZE);
  865.     }
  866. }
  867.     else if (numMulti > MBC_ARTAB_SIZE-1)
  868. {
  869. /* Setup the multicast filter */
  870. mbcAddrFilterSet (pDrvCtrl);
  871. DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_MULTI,
  872.  "Multicast Filter 0-3 %02x:%02x:%02x:%02xn",
  873.  pDrvCtrl->mcastFilter[0], pDrvCtrl->mcastFilter[1],
  874.  pDrvCtrl->mcastFilter[2], pDrvCtrl->mcastFilter[3], 0, 0);
  875. DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_MULTI,
  876.  "Multicast Filter 4-7 %02x:%02x:%02x:%02xn",
  877.  pDrvCtrl->mcastFilter[4], pDrvCtrl->mcastFilter[5],
  878.  pDrvCtrl->mcastFilter[6], pDrvCtrl->mcastFilter[7], 0, 0);
  879. /* Write out multicast filter */
  880.         SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01f0,
  881.        (pDrvCtrl->mcastFilter[0] << 8)
  882.        | pDrvCtrl->mcastFilter[1]);
  883.         SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01f2,
  884.        (pDrvCtrl->mcastFilter[2] << 8)
  885.        | pDrvCtrl->mcastFilter[3]);
  886.         SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01f8,
  887.        (pDrvCtrl->mcastFilter[4] << 8)
  888.        | pDrvCtrl->mcastFilter[5]);
  889.         SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01fa,
  890.        (pDrvCtrl->mcastFilter[6] << 8)
  891.        | pDrvCtrl->mcastFilter[7]);
  892. /* Now enable multicast addressing */
  893. SYS_IN_SHORT (pDrvCtrl, MBC_AR, &regValue);
  894. regValue |= MBC_AR_HASH;
  895. SYS_OUT_SHORT (pDrvCtrl, MBC_AR, regValue);
  896. }
  897.     }
  898. /******************************************************************************
  899. *
  900. * mbcStart - start the device
  901. *
  902. * This function calls BSP functions to connect interrupts and start the
  903. * device running in interrupt mode.
  904. *
  905. * RETURNS: OK or ERROR
  906. *
  907. * NOMANUAL
  908. */
  909. LOCAL STATUS mbcStart
  910.     (
  911.     void * pObj /* device ID */
  912.     )
  913.     {
  914.     STATUS  result;
  915.     MBC_DEVICE * pDrvCtrl = pObj; /* device to be started */
  916.     DRV_LOG (DRV_DEBUG_LOAD, "%s%d: mbcStartn",
  917.      (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  918.     SYS_INT_CONNECT (pDrvCtrl, mbcInt, (int)pDrvCtrl, &result);
  919.     if (result == ERROR)
  920. return (ERROR);
  921.     DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
  922.     /* enable interrupts - clear events and set mask */
  923.     SYS_OUT_SHORT (pDrvCtrl, MBC_IEVNT, 0xffff);
  924.     SYS_OUT_SHORT (pDrvCtrl, MBC_IMASK, MBC_IMASK_RXF | MBC_IMASK_EBE);
  925.     /* enable the device */
  926.     SYS_UPDATE_SHORT (pDrvCtrl, MBC_ECNTL, MBC_ECNTL_ENBL);
  927.     
  928.     DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
  929.     return (OK);
  930.     }
  931. /******************************************************************************
  932. *
  933. * mbcInt - handle controller interrupt
  934. *
  935. * This routine is called at interrupt level in response to an interrupt from
  936. * the controller.
  937. *
  938. * RETURNS: N/A.
  939. */
  940. LOCAL void mbcInt
  941.     (
  942.     MBC_DEVICE * pDrvCtrl /* interrupting device */
  943.     )
  944.     {
  945.     UINT16  mask;
  946.     UINT16  events;
  947.     /* identify and acknowledge all interrupt events */
  948.     SYS_IN_SHORT (pDrvCtrl, MBC_IEVNT, &events);
  949.     SYS_IN_SHORT (pDrvCtrl, MBC_IMASK, &mask);
  950.     events = (events & (mask | MBC_IMASK_BSY));
  951.     SYS_OUT_SHORT (pDrvCtrl, MBC_IEVNT, events);
  952.     DRV_LOG (DRV_DEBUG_INT,
  953.      "%s%d: mbcInt events=%04x mask=%04xn",
  954.      (int) DEV_NAME, pDrvCtrl->unit, events, mask, 0, 0);
  955.     /* handle receive events */
  956.     if (events & MBC_IEVNT_RXF)
  957. {
  958.         if (pDrvCtrl->rxHandling == FALSE)
  959.             {
  960.     pDrvCtrl->rxHandling = TRUE;
  961.             netJobAdd ((FUNCPTR)mbcHandleRcvInt, (int)pDrvCtrl, 0, 0, 0, 0);
  962.     }
  963.         }
  964.     /* handle transmitter events - BD full condition -> ever happen ? */
  965.     if (events & MBC_IEVNT_TXF)
  966. {
  967. DRV_LOG (DRV_DEBUG_INT | DRV_DEBUG_ERROR,
  968.  "%s%d: mbcInt: transmit fulln",
  969.  (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  970.      
  971.         wdCancel (pDrvCtrl->wdId);
  972. if (pDrvCtrl->txBlocked) /* cause a restart */
  973.     {
  974.     netJobAdd ((FUNCPTR)muxTxRestart, (int) &pDrvCtrl->end,
  975.        0, 0, 0, 0);
  976.     pDrvCtrl->txBlocked = FALSE;
  977.     }
  978. SYS_RESET_SHORT (pDrvCtrl, MBC_IMASK, MBC_IEVNT_TXF);
  979. }
  980.     /*
  981.      * check for input busy condition, we don't enable this interrupt
  982.      * but we check for it with each interrupt.
  983.      */
  984.     if (events & MBC_IEVNT_BSY)
  985. {
  986. DRV_LOG (DRV_DEBUG_INT | DRV_DEBUG_ERROR,
  987.  "%s%d: mbcInt: input busyn",
  988.  (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  989.         /* count discarded frames as errors */
  990. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  991. }
  992.     /* restart the transmitter on a ethernet bus error */
  993.     if (events & MBC_IEVNT_EBE)
  994.         {
  995. DRV_LOG (DRV_DEBUG_INT | DRV_DEBUG_ERROR,
  996.  "%s%d: mbcInt: ethernet bus errorn",
  997.  (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0);
  998. netJobAdd ((FUNCPTR)mbcDeviceRestart, (int) pDrvCtrl, 0, 0, 0, 0);
  999. }
  1000.     if (!pDrvCtrl->txCleaning)
  1001.         {
  1002.         pDrvCtrl->txCleaning = TRUE;
  1003.         netJobAdd ((FUNCPTR)mbcScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0);
  1004.         }
  1005.     /* ignore and reset all other events */
  1006.     SYS_OUT_SHORT (pDrvCtrl, MBC_IEVNT, ~mask);
  1007.     }
  1008. /******************************************************************************
  1009. *
  1010. * mbcScrubTRing - clean the transmit ring
  1011. *
  1012. * Cleans the transmit ring.
  1013. *
  1014. * RETURNS: N/A
  1015. *
  1016. * NOMANUAL
  1017. */
  1018. LOCAL void mbcScrubTRing
  1019.     (
  1020.     MBC_DEVICE * pDrvCtrl
  1021.     )
  1022.     {
  1023.     int oldLevel;
  1024.     volatile MBC_BD * pTxBd;
  1025.     
  1026.     pDrvCtrl->txCleaning = TRUE;
  1027.     pTxBd = &pDrvCtrl->txBdBase [pDrvCtrl->txClNext];
  1028.     while (pTxBd->dataPointer != NULL)
  1029.         {
  1030.         /* If the buffer is still owned by MBC, don't touch it */
  1031. if (pTxBd->statusMode & MBC_TXBD_R)
  1032.     break;
  1033.         oldLevel = intLock ();
  1034.         if (pDrvCtrl->freeRtn[pDrvCtrl->txClNext] != NULL)
  1035.             {
  1036.             pDrvCtrl->freeRtn[pDrvCtrl->txClNext]
  1037.       (pDrvCtrl->freeData[pDrvCtrl->txClNext].arg1,
  1038.        pDrvCtrl->freeData[pDrvCtrl->txClNext].arg2); 
  1039.             pDrvCtrl->freeRtn[pDrvCtrl->txClNext] = NULL;
  1040.             pDrvCtrl->freeData[pDrvCtrl->txClNext].arg1 = NULL; 
  1041.             pDrvCtrl->freeData[pDrvCtrl->txClNext].arg2 = NULL; 
  1042.             }
  1043.         
  1044. pTxBd->dataPointer = NULL;
  1045. pTxBd->statusMode &= ~MBC_TXBD_ERRS;
  1046.         /* now bump the disposal index pointer around the ring */
  1047. pDrvCtrl->txClNext = (pDrvCtrl->txClNext + 1) % pDrvCtrl->txBdNum;
  1048. pTxBd = &pDrvCtrl->txBdBase [pDrvCtrl->txClNext];
  1049.         intUnlock (oldLevel);
  1050.         }
  1051.     pDrvCtrl->txCleaning = FALSE;
  1052.     }
  1053. /******************************************************************************
  1054. *
  1055. * mbcSend - the driver send routine
  1056. *
  1057. * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
  1058. * The buffer must already have the addressing information properly installed
  1059. * in it.  This is done by a higher layer.
  1060. *
  1061. * RETURNS: OK or ERROR.
  1062. */
  1063. LOCAL STATUS mbcSend
  1064.     (
  1065.     void * pObj, /* device ptr */
  1066.     M_BLK_ID pMblk /* data to send */
  1067.     )
  1068.     {
  1069.     int len;
  1070.     char * pBuf;
  1071.     char * pOrig;
  1072.     int oldLevel;
  1073.     MBC_DEVICE * pDrvCtrl = pObj;
  1074.     volatile MBC_BD * pTxBd;
  1075.     
  1076.     DRV_LOG (DRV_DEBUG_TX,
  1077.      "%s%d: mbcSend txBlocked=%d txCleaning=%dn",
  1078.      (int) DEV_NAME, pDrvCtrl->unit,
  1079.      pDrvCtrl->txBlocked, pDrvCtrl->txCleaning, 5, 6);
  1080.     /*
  1081.      * Obtain exclusive access to transmitter.  This is necessary because
  1082.      * we might have more than one stack transmitting at once.
  1083.      */
  1084.     if (!(pDrvCtrl->flags & MBC_POLLING))
  1085. END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);
  1086.     /* check if a transmit buffer descriptor is available */
  1087.     pTxBd = &pDrvCtrl->txBdBase [pDrvCtrl->txBdNext];
  1088.     if (pTxBd->statusMode & MBC_TXBD_R)
  1089. {
  1090. DRV_LOG (DRV_DEBUG_TX | DRV_DEBUG_ERROR,
  1091.  "%s%d: mbcSend: #%d still readyn",
  1092.  (int) DEV_NAME, pDrvCtrl->unit,
  1093.  pDrvCtrl->txBdNext, 4, 5, 6);
  1094. wdStart (pDrvCtrl->wdId, WD_TIMEOUT, (FUNCPTR) mbcDeviceRestart,
  1095.  (int) pDrvCtrl);
  1096. pDrvCtrl->txBlocked = TRUE;
  1097. SYS_UPDATE_SHORT (pDrvCtrl, MBC_IMASK, MBC_IEVNT_TXF);
  1098. if (!(pDrvCtrl->flags & MBC_POLLING))
  1099.     END_TX_SEM_GIVE (&pDrvCtrl->end);
  1100. return (END_ERR_BLOCK);
  1101. }
  1102.     if (pTxBd->dataPointer)
  1103. {
  1104. /* cleaning still needed, queue cleaning task */
  1105. DRV_LOG (DRV_DEBUG_TX | DRV_DEBUG_ERROR,
  1106.  "%s%d: mbcSend: #%d needs cleaning (cleaning=%d)n",
  1107.  (int) DEV_NAME, pDrvCtrl->unit,
  1108.   pDrvCtrl->txBdNext, pDrvCtrl->txCleaning, 5, 6);
  1109. pDrvCtrl->txBlocked = TRUE;
  1110. if (pDrvCtrl->txCleaning == FALSE)
  1111.     {
  1112.     pDrvCtrl->txCleaning = TRUE;
  1113.     netJobAdd ((FUNCPTR)mbcScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0);
  1114.     }
  1115. if (!(pDrvCtrl->flags & MBC_POLLING))
  1116.     END_TX_SEM_GIVE (&pDrvCtrl->end);
  1117.         return (END_ERR_BLOCK);
  1118. }
  1119.     pOrig = pBuf = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  1120.     if (pBuf == NULL)
  1121.         {
  1122. DRV_LOG (DRV_DEBUG_TX | DRV_DEBUG_ERROR,
  1123.  "%s%d: mbcSend: out of clustersn",
  1124.  (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1125. if (!(pDrvCtrl->flags & MBC_POLLING))
  1126.     END_TX_SEM_GIVE (&pDrvCtrl->end);
  1127.         netMblkClChainFree (pMblk);
  1128.         return (ERROR);
  1129.         }
  1130.     pBuf += pDrvCtrl->offset;
  1131.     len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1132.     netMblkClChainFree (pMblk); 
  1133.     len = max (len, ETHERSMALL);
  1134.     /* place a transmit request */
  1135.     if (!(pDrvCtrl->flags & MBC_POLLING))
  1136.         oldLevel = intLock ();
  1137.     
  1138.     pTxBd->dataPointer = pBuf;
  1139.     pTxBd->dataLength = len;
  1140.     pTxBd->statusMode &= ~(MBC_TXBD_ERRS|MBC_TXBD_RC);
  1141.     pTxBd->statusMode |= MBC_TXBD_R;
  1142.     /* Advance our management index, and register for cleaning */
  1143.     pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum;
  1144.     pDrvCtrl->freeRtn [pDrvCtrl->txBdNext] = (FUNCPTR) netClFree;
  1145.     pDrvCtrl->freeData [pDrvCtrl->txBdNext].arg1 = pDrvCtrl->end.pNetPool;
  1146.     pDrvCtrl->freeData [pDrvCtrl->txBdNext].arg2 = pOrig;
  1147.     if (!(pDrvCtrl->flags & MBC_POLLING))
  1148. {
  1149.         intUnlock (oldLevel);
  1150. END_TX_SEM_GIVE (&pDrvCtrl->end);
  1151. }
  1152.     
  1153.     /* Bump the statistic counter. */
  1154.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  1155.     return (OK);
  1156.     }
  1157. /******************************************************************************
  1158. *
  1159. * mbcPacketGet - get next received message
  1160. *
  1161. * Get next received message.  Returns NULL if none are
  1162. * ready.
  1163. *
  1164. * RETURNS: ptr to next packet, or NULL if none ready.
  1165. *
  1166. * NOMANUAL
  1167. */
  1168. char* mbcPacketGet
  1169.     (
  1170.     MBC_DEVICE * pDrvCtrl /* device structure */
  1171.     )
  1172.     {
  1173.     volatile MBC_BD * pRxBd;
  1174.     
  1175.     pRxBd = &pDrvCtrl->rxBdBase [pDrvCtrl->rxBdNext];
  1176.     
  1177.     while (!(pRxBd->statusMode & MBC_RXBD_E))
  1178.         {
  1179.         /* data chaining is not supported - check all error conditions */
  1180.         if (((pRxBd->statusMode & (MBC_RXBD_F  | MBC_RXBD_L))
  1181.                        == (MBC_RXBD_F  | MBC_RXBD_L)) &&
  1182.             !(pRxBd->statusMode & (MBC_RXBD_CL | MBC_RXBD_OV |
  1183.                                    MBC_RXBD_CR | MBC_RXBD_SH |
  1184.                                    MBC_RXBD_NO | MBC_RXBD_LG)))
  1185.     {
  1186.     return (pRxBd->dataPointer);
  1187.     }
  1188. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1189. /*
  1190.  * Fix for errata #9 -- Device Errata, Feb 20, 1997.
  1191.  * Ethernet frames may be incorrectly received after a rx FIFO
  1192.  * overflow.
  1193.  */
  1194. if ((pRxBd->statusMode & MBC_RXBD_L)
  1195.     && !(pRxBd->statusMode & MBC_RXBD_F))
  1196.     {
  1197.     mbcDeviceRestart (pDrvCtrl);
  1198.     return (NULL);
  1199.     }
  1200.         /* reset buffer descriptor as empty */
  1201.         pRxBd->statusMode |= MBC_RXBD_E;
  1202.         
  1203.         /* Advance our management index */
  1204.         pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;
  1205.         pRxBd = &pDrvCtrl->rxBdBase [pDrvCtrl->rxBdNext];
  1206.         }
  1207.     return (NULL);
  1208.     }
  1209. /******************************************************************************
  1210. *
  1211. * mbcRecv - process the next incoming packet
  1212. *
  1213. * Handles one incoming packet.  The packet is checked for errors.
  1214. *
  1215. * RETURNS: OK.
  1216. *
  1217. * NOMANUAL
  1218. *
  1219. */
  1220. LOCAL STATUS mbcRecv
  1221.     (
  1222.     MBC_DEVICE * pDrvCtrl, /* device structure */
  1223.     char * pData /* packet to process */
  1224.     )
  1225.     {
  1226.     int len;
  1227.     M_BLK_ID pMblk;
  1228.     char * pNewCluster;
  1229.     char * pCluster;
  1230.     CL_BLK_ID pClBlk;
  1231.     volatile MBC_BD * pRxBd;
  1232.     pRxBd = &pDrvCtrl->rxBdBase [pDrvCtrl->rxBdNext];
  1233.     /*
  1234.      * We implicitly are loaning here, if copying is necessary this
  1235.      * step may be skipped, but the data must be copied before being
  1236.      * passed up to the protocols.
  1237.      */
  1238.     
  1239.     pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  1240.     if (pNewCluster == NULL)
  1241.         {
  1242. DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERROR,
  1243.  "%s%d: mbcRecv: out of clustersn",
  1244.  (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1245. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1246. goto cleanRXD;
  1247.         }
  1248.     /* Grab a cluster block to marry to the cluster we received. */
  1249.     pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT);
  1250.     if (pClBlk == NULL)
  1251.         {
  1252. DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERROR,
  1253.  "%s%d: mbcRecv: out of cluster blocksn",
  1254.  (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1255.         netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
  1256. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1257. goto cleanRXD;
  1258.         }
  1259.     
  1260.     /*
  1261.      * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  1262.      * one in the ring.
  1263.      */
  1264.     pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA);
  1265.     if (pMblk == NULL)
  1266.         {
  1267. DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERROR,
  1268.  "%s%d: mbcRecv: out of M blocksn",
  1269.  (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1270.         netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); 
  1271.         netClFree (pDrvCtrl->end.pNetPool, pNewCluster);
  1272. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1273. goto cleanRXD;
  1274.         }
  1275.     DRV_LOG (DRV_DEBUG_RX,
  1276.      "%s%d: mbcRecv %d: dataLength=%d dataPointer=%x data=%xn",
  1277.      (int) DEV_NAME, pDrvCtrl->unit,
  1278.      pDrvCtrl->rxBdNext, pRxBd->dataLength,
  1279.      (int) pRxBd->dataPointer, (int) pData);
  1280.     /* Add one to our unicast data. */
  1281.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1282.     len = pRxBd->dataLength;
  1283.     pCluster = pRxBd->dataPointer - pDrvCtrl->offset;
  1284.     /* Join the cluster to the MBlock */
  1285.     netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);
  1286.     netMblkClJoin (pMblk, pClBlk);
  1287.     pMblk->mBlkHdr.mData += pDrvCtrl->offset;
  1288.     pMblk->mBlkHdr.mLen = len;
  1289.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1290.     pMblk->mBlkPktHdr.len = len;
  1291.     /* make the packet data coherent */
  1292.     MBC_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);
  1293.     /* Installed (adjusted) new cluster, and reset descriptor */
  1294.     pRxBd->dataPointer = pNewCluster + pDrvCtrl->offset;
  1295.     pRxBd->statusMode |= MBC_RXBD_E;
  1296.     /* Advance our management index */
  1297.     pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;
  1298. #ifdef DRV_DEBUG
  1299.     {
  1300.     char *pAddress = pCluster + pDrvCtrl->offset;
  1301.     if (pAddress[0] & 0x01)
  1302. DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_MULTI,
  1303.  "Recv Multicast %02x:%02x:%02x:%02x:%02x:%02xn",
  1304.  pAddress[0]&0xff, pAddress[1]&0xff, pAddress[2]&0xff,
  1305.  pAddress[3]&0xff, pAddress[4]&0xff, pAddress[5]&0xff);
  1306.     }
  1307. #endif
  1308.     /* Call the upper layer's receive routine. */
  1309.     END_RCV_RTN_CALL (&pDrvCtrl->end, pMblk);
  1310.     return (OK);
  1311. cleanRXD:
  1312.     /* Reset descriptor and advance management index */
  1313.     pRxBd->statusMode |= MBC_RXBD_E;
  1314.     pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;
  1315.     return (OK);
  1316.     }
  1317. /******************************************************************************
  1318. *
  1319. * mbcHandleRcvInt - task level interrupt service for input packets
  1320. *
  1321. * This routine is called at task level indirectly by the interrupt
  1322. * service routine to do any message received processing.
  1323. *
  1324. * The double loop is to protect against a race condition where the interrupt
  1325. * code see rxHandling as TRUE, but it is then turned off by task code.
  1326. * This race is not fatal, but does cause occassional delays until a second
  1327. * packet is received and then triggers the netTask to call this routine again.
  1328. *
  1329. * RETURNS: N/A.
  1330. */
  1331. LOCAL void mbcHandleRcvInt
  1332.     (
  1333.     MBC_DEVICE * pDrvCtrl /* interrupting device */
  1334.     )
  1335.     {
  1336.     char * pData;
  1337.     do
  1338.         {
  1339.         pDrvCtrl->rxHandling = TRUE;
  1340.         while ((pData = mbcPacketGet (pDrvCtrl)) != NULL)
  1341.             mbcRecv (pDrvCtrl, pData);
  1342.         pDrvCtrl->rxHandling = FALSE;
  1343.         }
  1344.     while (mbcPacketGet (pDrvCtrl) != NULL);
  1345.     }
  1346. /******************************************************************************
  1347. *
  1348. * mbcIoctl - the driver I/O control routine
  1349. *
  1350. * Process an ioctl request.
  1351. *
  1352. * RETURNS: A command specific response, usually OK or ERROR.
  1353. */
  1354. LOCAL int mbcIoctl
  1355.     (
  1356.     void * pObj, /* device receiving command */
  1357.     int cmd, /* ioctl command code */
  1358.     caddr_t data /* command argument */
  1359.     )
  1360.     {
  1361.     MBC_DEVICE * pDrvCtrl = pObj; /* device receiving command */
  1362.     int error = 0;
  1363.     long value;
  1364.     switch (cmd)
  1365.             {
  1366.         case EIOCSADDR:
  1367.     if (data == NULL)
  1368. return (EINVAL);
  1369.             bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
  1370.    END_HADDR_LEN(&pDrvCtrl->end));
  1371.             break;
  1372.         case EIOCGADDR:
  1373.     if (data == NULL)
  1374. return (EINVAL);
  1375.             bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *) data,
  1376.    END_HADDR_LEN(&pDrvCtrl->end));
  1377.             break;
  1378.         case EIOCSFLAGS:
  1379.     value = (long)data;
  1380.     if (value < 0)
  1381. {
  1382. value = -(value - 1);
  1383. END_FLAGS_CLR (&pDrvCtrl->end, value);
  1384. }
  1385.     else
  1386. {
  1387. END_FLAGS_SET (&pDrvCtrl->end, value);
  1388. }
  1389.     mbcConfig (pDrvCtrl);
  1390.             break;
  1391.         case EIOCGFLAGS:
  1392.     *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
  1393.             break;
  1394. case EIOCPOLLSTART: /* Begin polled operation */
  1395.     mbcPollStart (pDrvCtrl);
  1396.     break;
  1397. case EIOCPOLLSTOP: /* End polled operation */
  1398.     mbcPollStop (pDrvCtrl);
  1399.     break;
  1400.         case EIOCGMIB2: /* return MIB information */
  1401.             if (data == NULL)
  1402.                 return (EINVAL);
  1403.             bcopy ((char *)&pDrvCtrl->end.mib2Tbl, (char *) data,
  1404.    sizeof(pDrvCtrl->end.mib2Tbl));
  1405.             break;
  1406.     
  1407.         case EIOCGFBUF: /* return minimum First Buffer for chaining */
  1408.             if (data == NULL)
  1409.                 return (EINVAL);
  1410.             *(int *) data = MBC_MIN_FBUF;
  1411.             break;
  1412.     
  1413.         default:
  1414.             error = EINVAL;
  1415.         }
  1416.     return (error);
  1417.     }
  1418. /******************************************************************************
  1419. *
  1420. * mbcAddrFilterSet - set the address filter for multicast addresses
  1421. *
  1422. * This routine goes through all of the multicast addresses on the list
  1423. * of addresses (added with the endAddrAdd() routine) and sets the
  1424. * device's filter correctly.
  1425. *
  1426. * RETURNS: N/A.
  1427. */
  1428. void mbcAddrFilterSet
  1429.     (
  1430.     MBC_DEVICE * pDrvCtrl /* device to be updated */
  1431.     )
  1432.     {
  1433.     int len;
  1434.     int count;
  1435.     u_char c;
  1436.     u_char * pCp;
  1437.     u_long crc;
  1438.     ETHER_MULTI * pCurr;
  1439.     
  1440.     pDrvCtrl->mcastFilter[0] = 0x00;
  1441.     pDrvCtrl->mcastFilter[1] = 0x00;
  1442.     pDrvCtrl->mcastFilter[2] = 0x00;
  1443.     pDrvCtrl->mcastFilter[3] = 0x00;
  1444.     pDrvCtrl->mcastFilter[4] = 0x00;
  1445.     pDrvCtrl->mcastFilter[5] = 0x00;
  1446.     pDrvCtrl->mcastFilter[6] = 0x00;
  1447.     pDrvCtrl->mcastFilter[7] = 0x00;
  1448.     for (pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
  1449.  pCurr != NULL;
  1450.  pCurr = END_MULTI_LST_NEXT(pCurr))
  1451. {
  1452. /*
  1453.  * AUTODIN-II, adapted for ethernet (bit reversed),
  1454.  * taken from the ln7990End.c driver
  1455.  */
  1456. pCp = (unsigned char *)&pCurr->addr;
  1457. crc = 0xffffffff;
  1458. for (len = 6; --len >= 0;)
  1459.     {
  1460.     c = *pCp++;
  1461.     for (count = 0; count < 8; count++)
  1462. {
  1463. if ((c & 0x01) ^ (crc & 0x01))
  1464.     {
  1465.     crc >>= 1;
  1466.     crc = crc ^ 0xedb88320;
  1467.     }
  1468. else
  1469.     {
  1470.     crc >>= 1;
  1471.     }
  1472. c >>= 1;
  1473. }
  1474.     }
  1475. /* Just want the 6 most significant bits. */
  1476. crc = crc >> 26;
  1477. /* Turn on the corresponding bit in the filter. */
  1478. pDrvCtrl->mcastFilter [crc >> 3] |= (1 << (crc & 0x07));
  1479. }
  1480.     }
  1481. /******************************************************************************
  1482. *
  1483. * mbcPollRcv - routine to receive a packet in polled mode.
  1484. *
  1485. * This routine is called by a user to try and get a packet from the
  1486. * device.
  1487. *
  1488. * RETURNS: OK upon success.  EAGAIN is returned when no packet is available.
  1489. */
  1490. LOCAL STATUS mbcPollRcv
  1491.     (
  1492.     void *  pObj, /* device to be polled */
  1493.     M_BLK_ID pMblk /* ptr to buffer */
  1494.     )
  1495.     {
  1496.     int len;
  1497.     MBC_DEVICE * pDrvCtrl = pObj; /* device to be polled */
  1498.     volatile MBC_BD * pRxBd;
  1499.     pRxBd = &pDrvCtrl->rxBdBase [pDrvCtrl->rxBdNext];
  1500.     len = pRxBd->dataLength;
  1501.     /* If no packet is available return immediately */
  1502.     if (pRxBd->statusMode & MBC_RXBD_E)
  1503.         return (EAGAIN);
  1504.     /* Upper layer must provide a valid buffer. */
  1505.     if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
  1506. {
  1507. DRV_LOG (DRV_DEBUG_POLL_RX, "%s%d: mbcPollRcv: rxBdNext=%d bad mblkn",
  1508.  (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->rxBdNext, 4, 5, 6);
  1509. return (EAGAIN);
  1510. }
  1511.     /* Check packet and device for errors */
  1512.     if (((pRxBd->statusMode & (MBC_RXBD_F | MBC_RXBD_L))
  1513.  != (MBC_RXBD_F | MBC_RXBD_L))
  1514. || (pRxBd->statusMode & (MBC_RXBD_CL | MBC_RXBD_OV |
  1515.  MBC_RXBD_CR | MBC_RXBD_SH |
  1516.  MBC_RXBD_NO | MBC_RXBD_LG)))
  1517. {
  1518. /* packet has an error */
  1519. DRV_LOG (DRV_DEBUG_POLL_RX | DRV_DEBUG_ERROR,
  1520.  "%s%d: mbcPollRcv: rxBdNext=%d bad packet stat=%xn",
  1521.  (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->rxBdNext,
  1522.  pRxBd->statusMode, 5, 6);
  1523. pRxBd->statusMode |= MBC_RXBD_E;
  1524. pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;
  1525.         return (EAGAIN);
  1526. }
  1527.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1528.     pMblk->mBlkHdr.mData += pDrvCtrl->offset;
  1529.     bcopy (pRxBd->dataPointer, pMblk->mBlkHdr.mData, len);
  1530.     pMblk->mBlkHdr.mLen = len;
  1531.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1532.     pMblk->mBlkPktHdr.len = len;
  1533.     /* Done with packet, clean up and give it to the device. */
  1534.     pRxBd->statusMode |= MBC_RXBD_E;
  1535.     pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;
  1536.         
  1537.     DRV_LOG (DRV_DEBUG_POLL_RX,
  1538.      "%s%d: mbcPollRcv: rxBdNext=%d good packet len=%dn",
  1539.      (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->rxBdNext,
  1540.      len, 5, 6);
  1541.     return (OK);
  1542.     }
  1543. /******************************************************************************
  1544. *
  1545. * mbcPollSend - routine to send a packet in polled mode.
  1546. *
  1547. * This routine is called by a user to try to send a packet on the
  1548. * device.
  1549. *
  1550. * RETURNS: OK upon success.  EAGAIN if device is busy.
  1551. */
  1552. LOCAL STATUS mbcPollSend
  1553.     (
  1554.     void *  pObj, /* device to be polled */
  1555.     M_BLK_ID    pMblk /* packet to send */
  1556.     )
  1557.     {
  1558.     char * pBuf = NULL;
  1559.     int len;
  1560.     int oldLevel;
  1561.     MBC_DEVICE * pDrvCtrl = pObj; /* device to be polled */
  1562.     volatile MBC_BD * pTxBd;
  1563.     
  1564.     /* test to see if TX is busy */
  1565.     
  1566.     pTxBd = &pDrvCtrl->txBdBase [pDrvCtrl->txBdNext];
  1567.     if (pTxBd->statusMode & MBC_TXBD_R)
  1568. {
  1569. DRV_LOG (DRV_DEBUG_POLL_TX | DRV_DEBUG_ERROR,
  1570.  "%s%d: mbcPollSend: no Tx desc. txBdNext=%dn",
  1571.  (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->txBdNext, 4, 5, 6);
  1572. return (EAGAIN);
  1573. }
  1574.     /* Check if descriptor is clean */
  1575.     if (pTxBd->dataPointer)
  1576. {
  1577. DRV_LOG (DRV_DEBUG_POLL_TX | DRV_DEBUG_ERROR,
  1578.  "%s%d: mbcPollSend: needs cleaningn",
  1579.  (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1580. if (!pDrvCtrl->txCleaning == TRUE);
  1581.     netJobAdd ((FUNCPTR)mbcScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0);
  1582. return (EAGAIN);
  1583. }
  1584.     /*
  1585.      * If packet is in a single block, we can transmit
  1586.      * directly from the M_BLK, otherwise we have to copy.
  1587.      */
  1588.     
  1589. #if 0 /* XXX */
  1590.     if (pMblk->mBlkHdr.mNext == NULL)
  1591.         {
  1592.         len = max (ETHERSMALL, pMblk->m_len);
  1593. pTxBd->dataPointer = pMblk->m_data;
  1594.         }
  1595.     else
  1596. #endif  /* 0 */
  1597.         {
  1598.         pBuf = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
  1599.         if (pBuf == NULL)
  1600.     {
  1601.     DRV_LOG (DRV_DEBUG_POLL_TX | DRV_DEBUG_ERROR,
  1602.      "%s%d: mbcPollSend: no clustersn",
  1603.      (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1604.             return (EAGAIN);
  1605.     }
  1606.         len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1607. pTxBd->dataPointer = pBuf;
  1608.         }
  1609.     
  1610.     DRV_LOG (DRV_DEBUG_POLL_TX, "%s%d: mbcPollSend: txBdNext=%d len=%dn",
  1611.      (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->txBdNext, len, 5, 6);
  1612.     CACHE_PIPE_FLUSH ();
  1613.     /* Bump the statistic counter. */
  1614.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  1615.   
  1616.     /* Start transmission */
  1617.     oldLevel = intLock ();
  1618.     pTxBd->dataLength = len;
  1619.     pTxBd->statusMode &= ~(MBC_TXBD_ERRS|MBC_TXBD_RC);
  1620.     pTxBd->statusMode |= MBC_TXBD_R;
  1621.     intUnlock (oldLevel);
  1622.     /* Advance our management index. */
  1623.     pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum;
  1624.     /* Spin until packet has been sent. */
  1625.     while (pTxBd->statusMode & MBC_TXBD_R)
  1626. ;
  1627.     /* Manually clean descriptor. */
  1628.     pTxBd->dataPointer = NULL;
  1629.     pTxBd->statusMode &= ~MBC_TXBD_ERRS;
  1630.     /* Free allocated cluster (if any), and clean tx ring (if needed) */
  1631.     if (pBuf != NULL)
  1632.         netClFree (pDrvCtrl->end.pNetPool, pBuf);
  1633.     if (!pDrvCtrl->txCleaning)
  1634.         {
  1635.         pDrvCtrl->txCleaning = TRUE;
  1636.         mbcScrubTRing (pDrvCtrl);
  1637.         }
  1638.     
  1639.     return (OK);
  1640.     }
  1641. /******************************************************************************
  1642. *
  1643. * mbcMCastAdd - add a multicast address for the device
  1644. *
  1645. * This routine adds a multicast address to whatever the driver
  1646. * is already listening for.  It then resets the address filter.
  1647. *
  1648. * RETURNS: OK or ERROR.
  1649. */
  1650. LOCAL STATUS mbcMCastAdd
  1651.     (
  1652.     void * pObj, /* device pointer */
  1653.     char * pAddress /* new address to add */
  1654.     )
  1655.     {
  1656.     int error;
  1657.     MBC_DEVICE * pDrvCtrl = pObj; /* device pointer */
  1658.     DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_MULTI,
  1659.      "mbcMCastAdd %02x:%02x:%02x:%02x:%02x:%02xn",
  1660.      pAddress[0]&0xff, pAddress[1]&0xff, pAddress[2]&0xff,
  1661.      pAddress[3]&0xff, pAddress[4]&0xff, pAddress[5]&0xff);
  1662.     error = etherMultiAdd (&pDrvCtrl->end.multiList, pAddress);
  1663.     if (error == ENETRESET)
  1664. mbcConfig (pDrvCtrl);
  1665.     return (OK);
  1666.     }
  1667. /******************************************************************************
  1668. *
  1669. * mbcMCastDel - delete a multicast address for the device
  1670. *
  1671. * This routine removes a multicast address from whatever the driver
  1672. * is listening for.  It then resets the address filter.
  1673. *
  1674. * RETURNS: OK or ERROR.
  1675. */
  1676. LOCAL STATUS mbcMCastDel
  1677.     (
  1678.     void * pObj, /* device pointer */
  1679.     char * pAddress /* address to be deleted */
  1680.     )
  1681.     {
  1682.     int  error;
  1683.     MBC_DEVICE * pDrvCtrl = pObj; /* device pointer */
  1684.     DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_MULTI,
  1685.      "mbcMCastDel %02x:%02x:%02x:%02x:%02x:%02xn",
  1686.      pAddress[0]&0xff, pAddress[1]&0xff, pAddress[2]&0xff,
  1687.      pAddress[3]&0xff, pAddress[4]&0xff, pAddress[5]&0xff);
  1688.     error = etherMultiDel (&pDrvCtrl->end.multiList, pAddress);
  1689.     if (error == ENETRESET)
  1690. mbcConfig (pDrvCtrl);
  1691.     return (OK);
  1692.     }
  1693. /******************************************************************************
  1694. *
  1695. * mbcMCastGet - get the multicast address list for the device
  1696. *
  1697. * This routine gets the multicast list of whatever the driver
  1698. * is already listening for.
  1699. *
  1700. * RETURNS: OK or ERROR.
  1701. */
  1702. LOCAL STATUS mbcMCastGet
  1703.     (
  1704.     void * pObj, /* device pointer */
  1705.     MULTI_TABLE * pTable /* address table to be filled in */
  1706.     )
  1707.     {
  1708.     MBC_DEVICE * pDrvCtrl = pObj; /* device pointer */
  1709.     return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
  1710.     }
  1711. /******************************************************************************
  1712. *
  1713. * mbcStop - stop the device
  1714. *
  1715. * This function calls BSP functions to disconnect interrupts and stop
  1716. * the device from operating in interrupt mode.
  1717. *
  1718. * RETURNS: OK or ERROR.
  1719. */
  1720. LOCAL STATUS mbcStop
  1721.     (
  1722.     void * pObj /* device to be stopped */
  1723.     )
  1724.     {
  1725.     MBC_DEVICE * pDrvCtrl = pObj; /* device to be stopped */
  1726.     STATUS result = OK;
  1727.     /* stop/disable the device. */
  1728.     
  1729.     mbcReset (pDrvCtrl);
  1730.     
  1731.     SYS_INT_DISCONNECT (pDrvCtrl, mbcInt, (int)pDrvCtrl, &result);
  1732. #ifdef DRV_DEBUG
  1733.     if (result == ERROR)
  1734. {
  1735. DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_ERROR,
  1736.  "Could not disconnect interrupt!n",
  1737.  1, 2, 3, 4, 5, 6);
  1738. }
  1739. #endif /* DRV_DEBUG */
  1740.     return (result);
  1741.     }
  1742. /******************************************************************************
  1743. *
  1744. * mbcUnload - unload a driver from the system
  1745. *
  1746. * This function first brings down the device, and then frees any
  1747. * stuff that was allocated by the driver in the load function.
  1748. *
  1749. * RETURNS: OK.
  1750. */
  1751. LOCAL STATUS mbcUnload
  1752.     (
  1753.     void * pObj /* device to be unloaded */
  1754.     )
  1755.     {
  1756.     MBC_DEVICE * pDrvCtrl = pObj; /* device to be unloaded */
  1757.     END_OBJECT_UNLOAD (&pDrvCtrl->end);
  1758.     
  1759.     /* Free the shared DMA memory. */
  1760.     if (pDrvCtrl->flags & MBC_MEM_ALLOC_FLAG)
  1761. cacheDmaFree (pDrvCtrl->bufBase);
  1762.     
  1763.     return (OK);
  1764.     }
  1765. /******************************************************************************
  1766. *
  1767. * mbcPollStart - start polled mode operations
  1768. *
  1769. * RETURNS: OK.
  1770. */
  1771. LOCAL STATUS mbcPollStart
  1772.     (
  1773.     MBC_DEVICE * pDrvCtrl /* device to be polled */
  1774.     )
  1775.     {
  1776.     int oldLevel;
  1777.     DRV_LOG (DRV_DEBUG_POLL, "%s%d: ultraPollStartn",
  1778.      (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1779.      
  1780.     oldLevel = intLock (); /* disable ints during update */
  1781.     SYS_OUT_SHORT (pDrvCtrl, MBC_IMASK, 0x00);
  1782.     pDrvCtrl->flags |= MBC_POLLING;
  1783.     intUnlock (oldLevel); /* now mbcInt won't get confused */
  1784.     return (OK);
  1785.     }
  1786. /******************************************************************************
  1787. *
  1788. * mbcPollStop - stop polled mode operations
  1789. *
  1790. * This function terminates polled mode operation.  The device returns to
  1791. * interrupt mode.
  1792. *
  1793. * The device interrupts are enabled, the current mode flag is switched
  1794. * to indicate interrupt mode and the device is then reconfigured for
  1795. * interrupt operation.
  1796. *
  1797. * RETURNS: OK or ERROR.
  1798. */
  1799. LOCAL STATUS mbcPollStop
  1800.     (
  1801.     MBC_DEVICE * pDrvCtrl /* device to be polled */
  1802.     )
  1803.     {
  1804.     int oldLevel;
  1805.     DRV_LOG (DRV_DEBUG_POLL, "%s%d: ultraPollStopn",
  1806.      (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);
  1807.      
  1808.     /* re-enable interrupts */
  1809.       
  1810.     oldLevel = intLock (); /* disable ints during register updates */
  1811.     SYS_OUT_SHORT (pDrvCtrl, MBC_IMASK, MBC_IMASK_RXF | MBC_IMASK_EBE);
  1812.     pDrvCtrl->flags &= ~MBC_POLLING;
  1813.     intUnlock (oldLevel);
  1814.     return (OK);
  1815.     }
  1816. /******************************************************************************
  1817. *
  1818. * mbcReset - reset device
  1819. *
  1820. * RETURNS: N/A.
  1821. *
  1822. * NOMANUAL
  1823. */
  1824. LOCAL void mbcReset
  1825.     (
  1826.     MBC_DEVICE * pDrvCtrl /* interrupting device */
  1827.     )
  1828.     {
  1829.     int counter = 0xffff;
  1830.     
  1831.     /* Disable interrupts */
  1832.     
  1833.     SYS_OUT_SHORT (pDrvCtrl, MBC_IMASK, 0x00);
  1834.     /* clear pending `graceful stop complete' event, and start one */
  1835.     SYS_OUT_SHORT (pDrvCtrl, MBC_IEVNT, MBC_IEVNT_GRA);
  1836.     SYS_OUT_SHORT (pDrvCtrl, MBC_ECNTL, MBC_ECNTL_GTS);
  1837.     /* wait for graceful stop to register */
  1838.     while (counter--)
  1839. {
  1840. USHORT event;
  1841. SYS_IN_SHORT (pDrvCtrl, MBC_IEVNT, &event);
  1842. if (event & MBC_IEVNT_GRA)
  1843.     break;
  1844. }
  1845.     /* disable the receiver and transmitter. */
  1846.     SYS_RESET_SHORT (pDrvCtrl, MBC_ECNTL, MBC_ECNTL_ENBL);
  1847.     
  1848.     pDrvCtrl->resetCounter++;
  1849.     }