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

VxWorks

开发平台:

C/C++

  1. /* auEnd.c - END style Au MAC Ethernet driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc., and Cetia Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * This file has been developed or significantly modified by the
  6.  * MIPS Center of Excellence Dedicated Engineering Staff.
  7.  * This notice is as per the MIPS Center of Excellence Master Partner
  8.  * Agreement, do not remove this notice without checking first with
  9.  * WR/Platforms MIPS Center of Excellence engineering management.
  10.  */
  11. /*
  12. modification history
  13. --------------------
  14. 01k,24jun02,zmm  Removed kernel calls from polling routines, Fix SPR 75773.
  15. 01j,14may02,zmm  Global au1000 name changes. SPR 77333.
  16. 01i,18apr02,zmm  Add muxError calls, if mBlkGet, netClBlkGet, or netClusterGet
  17.                  fails. Fix SPR 73756.
  18. 01h,04apr02,zmm  Move enabling the receiver from Reset to Config routine.
  19.                  Fix SPR 75126.
  20. 01g,15nov01,zmm  Supported auto-negotiation and cache coherency, 
  21.                  plus general cleanups. SPR 71884.
  22. 01f,11oct01,tlc  Change register names according to new revision of Au1000
  23.                  Databook.  General cleanup.
  24. 01e,21sep01,agf  add cluster alloc and MAC enable address to LOAD string
  25.                  generalize driver to work on MAC 0 or 1
  26. 01d,20sep01,agf  increase pCluster allocation, check Done bit prior to Tx load
  27. 01c,19jul01,zmm  Supported polling driver mode, and few interrupt mode fixes.
  28. 01b,19jun01,zmm  Fix race condition and Tx handling.
  29. 01a,17may01,mem  written.
  30. */
  31. /*
  32. DESCRIPTION  
  33. This module implements the Alchemey Semiconductor au on-chip
  34. ethernet MACs.
  35. The software interface to the driver is divided into three parts.
  36. The first part is the interrupt registers and their setup. This part
  37. is done at the BSP level in the various BSPs which use this driver. 
  38. The second and third part are addressed in the driver. The second part of
  39. the interface comprises of the I/O control registers and their
  40. programming. The third part of the interface comprises of the descriptors
  41. and the buffers. 
  42. This driver is designed to be moderately generic. Though it currently is
  43. implemented on one processor, in the future it may be added to other
  44. Alchemey product offerings. Thus, it would be desirable to use the same
  45. driver with no source level changes. To achieve this, the driver must be
  46. given several target-specific parameters, and some external support
  47. routines must be provided. These target-specific values and the external
  48. support routines are described below.
  49. This driver supports multiple units per CPU.  The driver can be
  50. configured to support big-endian or little-endian architectures.
  51. BOARD LAYOUT
  52. This device is on-board.  No jumpering diagram is necessary.
  53. EXTERNAL INTERFACE
  54. The only external interface is the auEndLoad() routine, which expects
  55. the <initString> parameter as input.  This parameter passes in a 
  56. colon-delimited string of the format:
  57. <unit>:<devMemAddr>:<devIoAddr>:<enableAddr>:<vecNum>:<intLvl>:<offset>
  58. :<qtyCluster>:<flags>
  59. The auEndLoad() function uses strtok() to parse the string.
  60. TARGET-SPECIFIC PARAMETERS
  61. .IP <unit>
  62. A convenient holdover from the former model.  This parameter is used only
  63. in the string name for the driver.
  64. .IP <devAddr>
  65. This parameter is the memory base address of the device registers in the
  66. memory map of the CPU. It indicates to the driver where to find the
  67. base MAC register.
  68. .IP <devIoAddr>
  69. This parameter in the base address of the device registers for the
  70. dedicated DMA channel for the MAC device.  It indicates to the driver
  71. where to find the DMA registers. 
  72. .IP <enableAddr>
  73. This parameter is the address MAC enable register. It is necessary to 
  74. specify selection between MAC 0 and MAC 1.
  75. .IP <vecNum>
  76. This parameter is the vector associated with the device interrupt.
  77. This driver configures the MAC device to generate hardware interrupts
  78. for various events within the device; thus it contains an interrupt handler
  79. routine.  The driver calls intConnect() via the macro SYS_INT_CONNECT()
  80. to connect its interrupt handler to the interrupt vector generated as a
  81. result of the MAC interrupt.
  82. .IP <intLvl>
  83. Some targets use additional interrupt controller devices to help organize
  84. and service the various interrupt sources.  This driver avoids all board-
  85. specific knowledge of such devices.  During the driver's initialization,
  86. the external routine sysLanAuIntEnable() is called to perform any
  87. board-specific operations required to allow the servicing of an interrupt.
  88. For a description of sysLanAuIntEnable(), see "External Support
  89. Requirements" below.
  90. .IP <offset>
  91. This parameter specifies the offset from which the packet has to be
  92. loaded from the begining of the device buffer. Normally this parameter is
  93. zero except for architectures which access long words only on aligned
  94. addresses. For these architectures the value of this offset should be 2.
  95. .IP <qtyCluster>
  96. This parameter is used to explicitly allocate the number of clusters that
  97. will be allocated. This allows the user to suit the stack to the amount of
  98. physical memory on the board.
  99. .IP <flags>
  100. This is parameter is reserved for future use. Its value should be zero.
  101. EXTERNAL SUPPORT REQUIREMENTS
  102. This driver requires several external support functions, defined as macros:
  103. .CS
  104.     SYS_INT_CONNECT(pDrvCtrl, routine, arg)
  105.     SYS_INT_DISCONNECT (pDrvCtrl, routine, arg)
  106.     SYS_INT_ENABLE(pDrvCtrl)
  107.     SYS_INT_DISABLE(pDrvCtrl)
  108.     SYS_OUT_BYTE(pDrvCtrl, reg, data)
  109.     SYS_IN_BYTE(pDrvCtrl, reg, data)
  110.     SYS_OUT_WORD(pDrvCtrl, reg, data)
  111.     SYS_IN_WORD(pDrvCtrl, reg, data)
  112.     SYS_OUT_LONG(pDrvCtrl, reg, data)
  113.     SYS_IN_LONG(pDrvCtrl, reg, data)
  114.     SYS_ENET_ADDR_GET(pDrvCtrl, pAddress)    
  115.     sysLanAuIntEnable(pDrvCtrl->intLevel) 
  116.     sysLanAuIntDisable(pDrvCtrl->intLevel) 
  117.     sysLanAuEnetAddrGet(pDrvCtrl, enetAdrs)
  118. .CE
  119. There are default values in the source code for these macros.  They presume
  120. memory mapped accesses to the device registers and the intConnect(), and
  121. intEnable() BSP functions.  The first argument to each is the device
  122. controller structure. Thus, each has access back to all the device-specific
  123. information.  Having the pointer in the macro facilitates the addition of new
  124. features to this driver.
  125. The macros SYS_INT_CONNECT, SYS_INT_DISCONNECT, SYS_INT_ENABLE and
  126. SYS_INT_DISABLE allow the driver to be customized for BSPs that use special
  127. versions of these routines.
  128. The macro SYS_INT_CONNECT is used to connect the interrupt handler to
  129. the appropriate vector.  By default it is the routine intConnect().
  130. The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler prior
  131. to unloading the module.  By default this routine is not implemented.
  132. The macro SYS_INT_ENABLE is used to enable the interrupt level for the
  133. end device.  It is called once during initialization.  It calls an
  134. external board level routine sysLanAuIntEnable(). 
  135. The macro SYS_INT_DISABLE is used to disable the interrupt level for the
  136. end device.  It is called during stop.  It calls an
  137. external board level routine sysLanAuIntDisable(). 
  138. The macro SYS_ENET_ADDR_GET is used get the ethernet hardware of the
  139. chip. This macro calls an external board level routine namely
  140. sysLanAuEnetAddrGet() to get the ethernet address.
  141. SYSTEM RESOURCE USAGE
  142. When implemented, this driver requires the following system resources:
  143.     - one mutual exclusion semaphore
  144.     - one interrupt vector
  145.     - 64 bytes in the initialized data section (data)
  146.     - 0 bytes in the uninitialized data section (BSS)
  147. The driver allocates clusters of size 1520 bytes for receive frames and
  148. and transmit frames.
  149. INCLUDES:
  150. end.h endLib.h etherMultiLib.h auEnd.h
  151. SEE ALSO: muxLib, endLib, netBufLib
  152. .I "Writing and Enhanced Network Driver"
  153. */
  154. #include "vxWorks.h"
  155. #include "wdLib.h"
  156. #include "stdlib.h"
  157. #include "taskLib.h"
  158. #include "logLib.h"
  159. #include "intLib.h"
  160. #include "netLib.h"
  161. #include "stdio.h"
  162. #include "stdlib.h"
  163. #include "sysLib.h"
  164. #include "iv.h"
  165. #include "memLib.h"
  166. #include "semLib.h"
  167. #include "cacheLib.h"
  168. #include "sys/ioctl.h"
  169. #ifndef DOC             /* don't include when building documentation */
  170. #include "net/mbuf.h"
  171. #endif  /* DOC */
  172. #include "net/protosw.h"
  173. #include "sys/socket.h"
  174. #include "errno.h"
  175. #include "net/if.h"
  176. #include "net/route.h"
  177. #include "netinet/in.h"
  178. #include "netinet/in_systm.h"
  179. #include "netinet/in_var.h"
  180. #include "netinet/ip.h"
  181. #include "netinet/if_ether.h"
  182. #include "net/if_subr.h"
  183. #include "m2Lib.h"
  184. #include "miiLib.h"
  185. #include "etherMultiLib.h"              /* multicast stuff. */
  186. #include "end.h"                        /* Common END structures. */
  187. #include "netBufLib.h"
  188. #include "muxLib.h"
  189. #undef END_MACROS
  190. #include "endLib.h"
  191. #include "lstLib.h"                     /* Needed to maintain protocol list. */
  192. #include "logLib.h"
  193. #include "drv/end/auEnd.h"
  194. #include "drv/multi/auLib.h"
  195. /* local defines */
  196. #define DRV_DEBUG /* temporary should be taken out */
  197. #undef DRV_DEBUG
  198. /* define the various levels of debugging if the DRV_DEBUG is defined */    
  199. #ifdef DRV_DEBUG
  200. #define DRV_DEBUG_OFF 0x0000
  201. #define DRV_DEBUG_RX 0x0001
  202. #define DRV_DEBUG_TX 0x0002
  203. #define DRV_DEBUG_INT 0x0004
  204. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  205. #define DRV_DEBUG_POLL_RX 0x0008
  206. #define DRV_DEBUG_POLL_TX 0x0010
  207. #define DRV_DEBUG_LOAD 0x0020
  208. #define DRV_DEBUG_LOAD2 0x0040
  209. #define DRV_DEBUG_IOCTL 0x0080
  210. #define DRV_DEBUG_RESET 0x0100
  211. #define DRV_DEBUG_MCAST 0x0200
  212. #define DRV_DEBUG_CSR 0x0400
  213. #define DRV_DEBUG_RX_PKT        0x0800
  214. #define DRV_DEBUG_POLL_REDIR 0x10000
  215. #define DRV_DEBUG_LOG_NVRAM 0x20000
  216. #define DRV_DEBUG_MII 0x40000
  217. #define DRV_DEBUG_ALL           0xfffff
  218. #endif /* DRV_DEBUG */
  219. /* MII macro */
  220. #define DRV_PHY_FLAGS_ISSET(setBits)                                    
  221.         (pDrvCtrl->miiPhyFlags & (setBits))
  222. /* Cache macros */
  223. #define AU_CACHE_VIRT_TO_PHYS(address) 
  224.         CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
  225. #define AU_CACHE_PHYS_TO_VIRT(address) 
  226.         CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
  227. /*
  228.  * Default macro definitions for BSP interface.
  229.  * These macros can be redefined in a wrapper file, to generate
  230.  * a new module with an optimized interface.
  231.  */
  232. #ifndef SYS_INT_CONNECT
  233. #define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult)                       
  234.     {                                                                   
  235.     IMPORT STATUS intConnect();                                      
  236.     *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),
  237.                              (rtn), (int)(arg));                        
  238.     }
  239. #endif /*SYS_INT_CONNECT*/
  240. #ifndef SYS_INT_DISCONNECT
  241. #define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult)                    
  242.     {                                                                   
  243.     }
  244. #endif /*SYS_INT_DISCONNECT*/
  245. #ifndef SYS_INT_ENABLE
  246. #define SYS_INT_ENABLE(pDrvCtrl) 
  247.     { 
  248.     IMPORT STATUS sysLanAuIntEnable(); 
  249.     sysLanAuIntEnable (pDrvCtrl->ilevel); 
  250.     }
  251. #endif /* SYS_INT_ENABLE*/
  252. /* Macro to disable the appropriate interrupt level */
  253. #ifndef SYS_INT_DISABLE
  254. #define SYS_INT_DISABLE(pDrvCtrl) 
  255.     { 
  256.     IMPORT STATUS sysLanAuIntDisable (); 
  257.     sysLanAuIntDisable (pDrvCtrl->ilevel); 
  258.     }
  259. #endif /* SYS_INT_DISABLE */
  260. #ifndef SYS_ENET_ADDR_GET
  261. #define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress) 
  262.     { 
  263.     IMPORT STATUS sysLanAuEnetAddrGet (AU_DRV_CTRL *pDrvCtrl, 
  264.                                      char * enetAdrs); 
  265.     sysLanAuEnetAddrGet (pDrvCtrl, pAddress); 
  266.     }
  267. #endif /* SYS_ENET_ADDR_GET */
  268. #ifndef SYS_WB_FLUSH
  269. #define SYS_WB_FLUSH() 
  270.     { 
  271.     IMPORT void sysWbFlush (void); 
  272.     sysWbFlush(); 
  273.     }
  274. #endif/* SYS_WB_FLUSH */
  275. /* A shortcut for getting the hardware address from the MIB II stuff. */
  276. #define END_HADDR(pEnd) 
  277.                 ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  278. #define END_HADDR_LEN(pEnd) 
  279.                 ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  280. #define END_FLAGS_ISSET(pEnd, setBits) 
  281.             ((pEnd)->flags & (setBits))
  282. /* externs */
  283. IMPORT int endMultiLstCnt (END_OBJ *);
  284. #ifdef DRV_DEBUG /* if debugging driver */
  285. int         auDebug = (DRV_DEBUG_LOAD | DRV_DEBUG_TX | DRV_DEBUG_RX
  286.    | DRV_DEBUG_MII | DRV_DEBUG_INT);
  287. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) 
  288.         if (auDebug & FLG) 
  289.             logMsg((char *)X0, (int)X1, (int)X2, (int)X3, (int)X4, 
  290.     (int)X5, (int)X6);
  291. #define DRV_PRINT(FLG,X) 
  292.         if (auDebug & FLG) printf X;
  293. #else /*DRV_DEBUG*/
  294. #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
  295. #define DRV_PRINT(DBG_SW,X)
  296. #endif /*DRV_DEBUG*/
  297. /* locals */
  298. #ifdef DRV_DEBUG
  299. AU_DRV_CTRL *  dbgDrvCtrl[2];
  300. #endif
  301. /* forward static functions */
  302. LOCAL int  auReset (AU_DRV_CTRL * pDrvCtrl);
  303. LOCAL void  auInt (AU_DRV_CTRL * pDrvCtrl);
  304. LOCAL void  auHandleInt (AU_DRV_CTRL * pDrvCtrl);
  305. LOCAL STATUS  auRecv (AU_DRV_CTRL * pDrvCtrl);
  306. LOCAL void  auRestart (AU_DRV_CTRL * pDrvCtrl);
  307. LOCAL STATUS  auRestartSetup (AU_DRV_CTRL * pDrvCtrl);
  308. LOCAL void  auAddrFilterSet (AU_DRV_CTRL * pDrvCtrl);
  309. LOCAL void auConfig (AU_DRV_CTRL * pDrvCtrl);
  310. LOCAL STATUS  auMemInit (AU_DRV_CTRL * pDrvCtrl);
  311. LOCAL void auTRingScrub (AU_DRV_CTRL * pDrvCtrl);
  312. LOCAL STATUS  auPhyPreInit  (AU_DRV_CTRL *pDrvCtrl);
  313. LOCAL STATUS  auMiiInit  (AU_DRV_CTRL *pDrvCtrl);
  314. LOCAL STATUS auMiiRead (AU_DRV_CTRL *pDrvCtrl, UINT8 phyAdrs,
  315.        UINT8 phyReg, UINT16 *pRetVal);
  316. LOCAL STATUS auMiiWrite (AU_DRV_CTRL *pDrvCtrl, UINT8 phyAdrs,
  317. UINT8 phyReg, USHORT data);
  318. LOCAL UINT8 auPhyFind (AU_DRV_CTRL *pDrvCtrl);
  319. /* END Specific interfaces. */
  320. LOCAL STATUS    auStart (AU_DRV_CTRL * pDrvCtrl);
  321. LOCAL STATUS    auStop (AU_DRV_CTRL * pDrvCtrl);
  322. LOCAL STATUS    auUnload (AU_DRV_CTRL * pDrvCtrl);
  323. LOCAL int       auIoctl (AU_DRV_CTRL * pDrvCtrl, int cmd, caddr_t data);
  324. LOCAL STATUS    auSend (AU_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);
  325. LOCAL STATUS    auMCastAddrAdd (AU_DRV_CTRL* pDrvCtrl, char * pAddress);
  326. LOCAL STATUS    auMCastAddrDel (AU_DRV_CTRL * pDrvCtrl,
  327.                                    char * pAddress);
  328. LOCAL STATUS    auMCastAddrGet (AU_DRV_CTRL * pDrvCtrl,
  329.                                     MULTI_TABLE * pTable);
  330. LOCAL STATUS    auPollSend (AU_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);
  331. LOCAL STATUS    auPollReceive (AU_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);
  332. LOCAL STATUS    auPollStart (AU_DRV_CTRL * pDrvCtrl);
  333. LOCAL STATUS    auPollStop (AU_DRV_CTRL * pDrvCtrl);
  334. /*
  335.  * Declare our function table.  This is static across all driver
  336.  * instances.
  337.  */
  338. LOCAL NET_FUNCS auFuncTable =
  339.     {
  340.     (FUNCPTR) auStart,               /* Function to start the device.      */
  341.     (FUNCPTR) auStop,                /* Function to stop the device.       */
  342.     (FUNCPTR) auUnload,  /* Unloading function for the driver. */
  343.     (FUNCPTR) auIoctl,               /* Ioctl function for the driver.     */
  344.     (FUNCPTR) auSend,                /* Send function for the driver.      */
  345.     (FUNCPTR) auMCastAddrAdd,        /* Multicast address add              */
  346.     (FUNCPTR) auMCastAddrDel,  /* Multicast address delete           */
  347.     (FUNCPTR) auMCastAddrGet,  /* Multicast table retrieve           */
  348.     (FUNCPTR) auPollSend,            /* Polling send function              */
  349.     (FUNCPTR) auPollReceive,  /* Polling receive function           */
  350.     endEtherAddressForm,         /* Put address info into a packet.    */
  351.     endEtherPacketDataGet,       /* Get a pointer to packet data.      */
  352.     endEtherPacketAddrGet        /* Get packet addresses.              */
  353.     };
  354. /******************************************************************************
  355. *
  356. * auEndLoad - initialize the driver and device
  357. *
  358. * This routine initializes the driver and the device to the operational state.
  359. * All of the device-specific parameters are passed in <initString>, which
  360. * expects a string of the following format:
  361. *
  362. * <unit>:<devMemAddr>:<devIoAddr>:<enableAddr>:<vecNum>:<intLvl>:<offset>
  363. * :<qtyCluster>:<flags>
  364. *
  365. * This routine can be called in two modes. If it is called with an empty but
  366. * allocated string, it places the name of this device (that is, "au") into 
  367. * the <initString> and returns 0.
  368. *
  369. * If the string is allocated and not empty, the routine attempts to load
  370. * the driver using the values specified in the string.
  371. *
  372. * RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
  373. * device if the <initString> was NULL.
  374. */
  375. END_OBJ * auEndLoad
  376.     (
  377.     char * initString            /* string to be parse by the driver */
  378.     )
  379.     {
  380.     AU_DRV_CTRL * pDrvCtrl;
  381.     DRV_LOG (DRV_DEBUG_LOAD, "Loading au...debug @ 0X%Xn",
  382.              (int)&auDebug, 2, 3, 4, 5, 6);
  383.     if (initString == NULL)
  384.         return (NULL);
  385.     if (initString [0] == 0)
  386.         {
  387.         bcopy ((char *)AU_DEV_NAME, initString, AU_DEV_NAME_LEN);
  388. DRV_LOG (DRV_DEBUG_LOAD, "Returning string...n", 1, 2, 3, 4, 5, 6);
  389.         return ((END_OBJ *)OK);
  390.         }
  391.     DRV_LOG (DRV_DEBUG_LOAD, "austring: [%s]n",
  392.     (int)initString, 2, 3, 4, 5, 6);
  393.     /* allocate the device structure */
  394.     pDrvCtrl = (AU_DRV_CTRL *)calloc (sizeof (AU_DRV_CTRL), 1);
  395.     if (pDrvCtrl == NULL)
  396.         goto errorExit;
  397.     DRV_LOG (DRV_DEBUG_LOAD, "DrvControl : 0x%Xn", (int)pDrvCtrl,
  398.              2, 3, 4, 5, 6);
  399.     /* parse the init string, filling in the device structure */
  400.     if (auInitParse (pDrvCtrl, initString) == ERROR)
  401. {
  402. DRV_LOG (DRV_DEBUG_LOAD, "Parse failed ...n", 1, 2, 3, 4, 5, 6);
  403.         goto errorExit;
  404. }
  405.     DRV_LOG (DRV_DEBUG_LOAD, "mac   addr %08x %08xn",
  406.      AU_MAC_ADDRESS_HIGH,
  407.      AU_MAC_ADDRESS_LOW, 0, 0, 0, 0);
  408.     DRV_LOG (DRV_DEBUG_LOAD, "multi addr %08x %08xn",
  409.      AU_MULTICAST_HASH_ADDRESS_HIGH,
  410.      AU_MULTICAST_HASH_ADDRESS_LOW, 0, 0, 0, 0);
  411.     /* Have the BSP hand us our address. */
  412.     SYS_ENET_ADDR_GET (pDrvCtrl, &(pDrvCtrl->enetAddr [0]));
  413.     /* initialize the END and MIB2 parts of the structure */
  414.     if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, AU_DEV_NAME,
  415.                       pDrvCtrl->unit, &auFuncTable,
  416.                       "Au MAC Enhanced Network Driver") == ERROR
  417.      || END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd,
  418.                       &pDrvCtrl->enetAddr[0], 6, ETHERMTU,
  419.                       AU_SPEED)
  420.                     == ERROR)
  421.         goto errorExit;
  422.     DRV_LOG (DRV_DEBUG_LOAD, "END init done ...n", 1, 2, 3, 4, 5, 6);
  423.     /* Allocate PHY structure */
  424.     /* Perform memory allocation */
  425.     if (auMemInit (pDrvCtrl) == ERROR)
  426.         goto errorExit;
  427.     DRV_LOG (DRV_DEBUG_LOAD, "Malloc done ...n", 1, 2, 3, 4, 5, 6);
  428.     /* Perform memory distribution and reset and reconfigure the device */
  429.     if (auRestartSetup (pDrvCtrl) == ERROR)
  430.         goto errorExit;
  431.     DRV_LOG (DRV_DEBUG_LOAD, "Restart setup done ...n", 1, 2, 3, 4, 5, 6);
  432.     /* set the flags to indicate readiness */
  433.     END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_BROADCAST |
  434.                        IFF_MULTICAST | IFF_SIMPLEX);
  435.     DRV_LOG (DRV_DEBUG_LOAD, "Done loading au...n", 1, 2, 3, 4, 5, 6);
  436. #ifdef DRV_DEBUG
  437.     dbgDrvCtrl[pDrvCtrl->unit] = pDrvCtrl;
  438. #endif
  439.     
  440.     return (&pDrvCtrl->endObj);
  441. errorExit:
  442.     if (pDrvCtrl != NULL)
  443.         free ((char *)pDrvCtrl);
  444.     return ((END_OBJ *)NULL);
  445.     }
  446. /*******************************************************************************
  447. *
  448. * auInitParse - parse the initialization string
  449. *
  450. * Parse the input string. This routine is called from auEndLoad() which
  451. * intializes some values in the driver control structure with the values
  452. * passed in the intialization string.
  453. *
  454. * The initialization string format is:
  455. * <unit>:<devMemAddr>:<devIoAddr>:<vecNum>:<intLvl>:<offset>:<flags>
  456. *
  457. * .IP <unit>
  458. * Device unit number, a small integer.
  459. * .IP <devMemAddr>
  460. * Device register base memory address
  461. * .IP <devIoAddr>
  462. * I/O register base memory address
  463. * .IP <enableAddr>
  464. * Address of MAC enable register
  465. * .IP <vecNum>
  466. * Interrupt vector number.
  467. * .IP <intLvl>
  468. * Interrupt level.
  469. * .IP <offset>
  470. * Offset of starting of data in the device buffers.
  471. * .IP <qtyCluster>
  472. * Number of clusters to allocate
  473. * .IP <flags>
  474. * Device specific flags, for future use.
  475. *
  476. * RETURNS: OK, or ERROR if any arguments are invalid.
  477. */
  478. STATUS auInitParse
  479.     (
  480.     AU_DRV_CTRL * pDrvCtrl, /* pointer to the control structure */
  481.     char *  initString /* initialization string */
  482.     )
  483.     {
  484.     char*       tok;
  485.     char*       holder = NULL;
  486.     DRV_LOG (DRV_DEBUG_LOAD, "Parse starting ...n", 1, 2, 3, 4, 5, 6);
  487.     /* Parse the initString */
  488.     /* Unit number. */
  489.     tok = strtok_r (initString, ":", &holder);
  490.     if (tok == NULL)
  491.         return ERROR;
  492.     pDrvCtrl->unit = atoi (tok);
  493.     DRV_LOG (DRV_DEBUG_LOAD, "Unit : %d ...n", pDrvCtrl->unit, 2, 3, 4, 5, 6);
  494.     /* devAdrs address. */
  495.     tok = strtok_r (NULL, ":", &holder);
  496.     if (tok == NULL)
  497.         return ERROR;
  498.     pDrvCtrl->devAdrs = (UINT32) strtoul (tok, NULL, 16);
  499.     DRV_LOG (DRV_DEBUG_LOAD, "devAdrs : 0x%X ...n", pDrvCtrl->devAdrs,
  500.              2, 3, 4, 5, 6);
  501.     /* dmaAdrs address. */
  502.     tok = strtok_r (NULL, ":", &holder);
  503.     if (tok == NULL)
  504.         return ERROR;
  505.     pDrvCtrl->dmaAdrs = (UINT32) strtoul (tok, NULL, 16);
  506.     DRV_LOG (DRV_DEBUG_LOAD, "dmaAdrs : 0x%X ...n", pDrvCtrl->dmaAdrs,
  507.              2, 3, 4, 5, 6);
  508.     /* enableAdrs address. */
  509.     tok = strtok_r (NULL, ":", &holder);
  510.     if (tok == NULL)
  511.         return ERROR;
  512.     pDrvCtrl->enableAdrs = (UINT32) strtoul (tok, NULL, 16);
  513.     DRV_LOG (DRV_DEBUG_LOAD, "enableAdrs : 0x%X ...n", pDrvCtrl->enableAdrs,
  514.              2, 3, 4, 5, 6);
  515.     /* Interrupt vector. */
  516.     tok = strtok_r (NULL, ":", &holder);
  517.     if (tok == NULL)
  518.         return ERROR;
  519.     pDrvCtrl->ivec = atoi (tok);
  520.     DRV_LOG (DRV_DEBUG_LOAD, "ivec : 0x%X ...n", pDrvCtrl->ivec,
  521.              2, 3, 4, 5, 6);
  522.     /* Interrupt level. */
  523.     tok = strtok_r (NULL, ":", &holder);
  524.     if (tok == NULL)
  525.         return ERROR;
  526.     pDrvCtrl->ilevel = atoi (tok);
  527.     DRV_LOG (DRV_DEBUG_LOAD, "ilevel : 0x%X ...n", pDrvCtrl->ilevel,
  528.              2, 3, 4, 5, 6);
  529.     /* Caller supplied alignment offset. */
  530.     tok = strtok_r (NULL, ":", &holder);
  531.     if (tok == NULL)
  532. return ERROR;
  533.     pDrvCtrl->offset = atoi (tok);
  534.     DRV_LOG (DRV_DEBUG_LOAD, "Offset : 0x%X ...n", pDrvCtrl->offset,
  535.              2, 3, 4, 5, 6);
  536.     /* Caller supplied cluster qty */
  537.     tok = strtok_r (NULL, ":", &holder);
  538.     if (tok == NULL)
  539. return ERROR;
  540.     pDrvCtrl->clDesc.clNum    = atoi (tok);
  541.     DRV_LOG (DRV_DEBUG_LOAD, "Cluster Qty : 0x%X ...n", pDrvCtrl->clDesc.clNum,
  542.              2, 3, 4, 5, 6);
  543.     /* caller supplied flags */
  544.     tok = strtok_r (NULL, ":", &holder);
  545.     if (tok == NULL)
  546.         return ERROR;
  547.     pDrvCtrl->flags |= strtoul (tok, NULL, 16);
  548.     DRV_LOG (DRV_DEBUG_LOAD, "flags : 0x%X ...n", pDrvCtrl->flags,
  549.              2, 3, 4, 5, 6);
  550.     return (OK);
  551.     }
  552. /*******************************************************************************
  553. *
  554. * auMemInit - initialize memory.
  555. *
  556. * Using data in the control structure, setup and initialize the memory
  557. * areas needed.  If the memory address is not already specified, then allocate
  558. * cache safe memory.
  559. *
  560. * RETURNS: OK or ERROR.
  561. */
  562. LOCAL STATUS auMemInit
  563.     (
  564.     AU_DRV_CTRL * pDrvCtrl /* device to be initialized */
  565.     )
  566.     {
  567.     int         i;
  568.     char * pRxMem;
  569.     char * pTxMem;
  570.     UINT32      rxSize;
  571.     UINT32      txSize;
  572.     UINT32      bufPtr;
  573.     pDrvCtrl->rringSize = AU_N_RX_BUF;
  574.     pDrvCtrl->tringSize = AU_N_TX_BUF;
  575.     
  576.     rxSize = pDrvCtrl->rringSize * ROUND_UP(AU_DMA_BUFSIZ, 32) + 32;
  577.     pRxMem = (char *) cacheDmaMalloc (rxSize);
  578.     txSize = pDrvCtrl->tringSize * ROUND_UP(AU_DMA_BUFSIZ, 32) + 32;
  579.     pTxMem = (char *) cacheDmaMalloc (txSize);
  580.     if ((pRxMem == NULL) || (pTxMem == NULL))
  581. {
  582. printf ("au: system memory unavailablen");
  583. return (ERROR);
  584. }
  585.     pDrvCtrl->pRxMemBase = pRxMem;
  586.     pDrvCtrl->pTxMemBase = pTxMem;
  587.     /* copy the DMA structure */
  588.     pDrvCtrl->cacheFuncs = cacheDmaFuncs;
  589.     bufPtr = (UINT32)pRxMem;
  590.     for (i = 0; i < pDrvCtrl->rringSize; ++i)
  591. {
  592. pDrvCtrl->pRxMem[i] = (char *)ROUND_UP(bufPtr, 32);
  593. bufPtr += AU_DMA_BUFSIZ;
  594. }
  595.     bufPtr = (UINT32)pTxMem;
  596.     for (i = 0; i < pDrvCtrl->tringSize; ++i)
  597. {
  598. pDrvCtrl->pTxMem[i] = (char *)ROUND_UP(bufPtr, 32);
  599. bufPtr += AU_DMA_BUFSIZ;
  600. }
  601.     /* allocate pool structure for mblks, clBlk, and clusters */
  602.     if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  603. return (ERROR);
  604.     /* number of clusters is passed in by the endLoadString 
  605.      * pDrvCtrl->clDesc.clNum    = pDrvCtrl->rringSize * 2;
  606.      */
  607.     pDrvCtrl->mClCfg.clBlkNum = pDrvCtrl->clDesc.clNum;
  608.     pDrvCtrl->mClCfg.mBlkNum  = pDrvCtrl->mClCfg.clBlkNum * 2;
  609.     /* total memory size for mBlks and clBlks */
  610.     
  611.     pDrvCtrl->mClCfg.memSize =
  612.         (pDrvCtrl->mClCfg.mBlkNum  *  (MSIZE + sizeof (long))) +
  613.         (pDrvCtrl->mClCfg.clBlkNum * (CL_BLK_SZ + sizeof (long)));
  614.     /* total memory for mBlks and clBlks */
  615.     if ((pDrvCtrl->mClCfg.memArea =
  616.          (char *) memalign (sizeof(long), pDrvCtrl->mClCfg.memSize)) == NULL)
  617.         return (ERROR);
  618.     /* total memory size for all clusters */
  619.     pDrvCtrl->clDesc.clSize  = AU_BUFSIZ;
  620.     pDrvCtrl->clDesc.memSize =
  621.         (pDrvCtrl->clDesc.clNum * (pDrvCtrl->clDesc.clSize + 8)) + sizeof(int);
  622.     /* Allocate cluster memory */
  623.     pDrvCtrl->clDesc.memArea = malloc (pDrvCtrl->clDesc.memSize);
  624.     if (pDrvCtrl->clDesc.memArea == NULL)
  625. {
  626. DRV_LOG(DRV_DEBUG_LOAD,
  627. "system memory unavailablen", 1, 2, 3, 4, 5, 6);
  628. return (ERROR);
  629. }
  630.     /* initialize the device net pool */
  631.     
  632.     if (netPoolInit (pDrvCtrl->endObj.pNetPool, &pDrvCtrl->mClCfg,
  633.                      &pDrvCtrl->clDesc, 1, NULL) == ERROR)
  634.         {
  635.         DRV_LOG (DRV_DEBUG_LOAD, "Could not init bufferingn",
  636.                  1, 2, 3, 4, 5, 6);
  637.         return (ERROR);
  638.         }
  639.     
  640.     /* Store the cluster pool id as others need it later. */
  641.     pDrvCtrl->pClPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool,
  642.                                        AU_BUFSIZ, FALSE);
  643.     return (OK);
  644.     }
  645. /***************************************************************************
  646. *
  647. * auMiiInit - initialize the chip to use the MII interface
  648. *
  649. * This routine initializes the chip to use the MII interface.
  650. *
  651. * RETURNS: OK, or ERROR
  652. */
  653.  
  654. LOCAL STATUS auMiiInit
  655.     (
  656.     AU_DRV_CTRL *  pDrvCtrl       /* pointer to DRV_CTRL structure */
  657.     )
  658.     {
  659.     DRV_LOG (DRV_DEBUG_MII, "auMiiInitn",
  660.              0, 0, 0, 0, 0, 0);
  661.     /* initialize some fields in the PHY info structure */
  662.     if (auPhyPreInit (pDrvCtrl) != OK)
  663. {
  664. DRV_LOG (DRV_DEBUG_LOAD, ("Failed to pre-initialize PHYn"),
  665.   0, 0, 0, 0, 0, 0);
  666. return (ERROR);
  667. }
  668.     DRV_LOG (DRV_DEBUG_MII, "miiPhyInitn",
  669.              0, 0, 0, 0, 0, 0);
  670.     if (miiPhyInit (pDrvCtrl->pPhyInfo) != OK)
  671.         {
  672. DRV_LOG (DRV_DEBUG_LOAD, "Failed to initialise PHYn", 0,0,0,0,0,0);
  673. return (ERROR);
  674.         }
  675.     /* deal with full duplex mode and speed */
  676.     if (pDrvCtrl->pPhyInfo->phyFlags & MII_PHY_FD)
  677. {
  678.         AU_MAC_CONTROL |= AU_MAC_CONTROL_F;
  679. SYS_WB_FLUSH();
  680. DRV_LOG (DRV_DEBUG_LOAD, "In full duplex moden", 0,0,0,0,0,0);
  681. }
  682.     else
  683. {
  684. DRV_LOG (DRV_DEBUG_LOAD, "In half duplex moden", 0,0,0,0,0,0);
  685. }
  686.     if (pDrvCtrl->pPhyInfo->phyFlags & MII_PHY_100)
  687. {
  688. DRV_LOG (DRV_DEBUG_LOAD, "In 100Mbps moden", 0,0,0,0,0,0);
  689. }
  690.     else
  691. {
  692. DRV_LOG (DRV_DEBUG_LOAD, "In 10Mbps moden", 0,0,0,0,0,0);
  693. }
  694.     return (OK);
  695.     }
  696. /***************************************************************************
  697. *
  698. * auPhyPreInit - initialize some fields in the phy info structure
  699. *
  700. * This routine initializes some fields in the phy info structure,
  701. * for use of the phyInit() routine.
  702. *
  703. * RETURNS: OK, or ERROR if could not obtain memory.
  704. */
  705.  
  706. LOCAL STATUS auPhyPreInit
  707.     (
  708.     AU_DRV_CTRL *  pDrvCtrl /* pointer to DRV_CTRL structure */
  709.     )
  710.     {
  711.     PHY_INFO * pPhyInfo = NULL;
  712.     
  713.     DRV_LOG (DRV_DEBUG_MII, "auMiiPhyPreInitn",
  714.              0, 0, 0, 0, 0, 0);
  715.     /* set MII defaults */
  716.     pDrvCtrl->pMiiPhyTbl = NULL;
  717.     pDrvCtrl->miiPhyFlags = (AU_USR_MII_10MB | AU_USR_MII_HD |
  718.                             AU_USR_MII_100MB | AU_USR_MII_FD);
  719.     /* get memory for the phyInfo structure */
  720.  
  721.     if ((pDrvCtrl->pPhyInfo = calloc (sizeof (PHY_INFO), 1)) == NULL)
  722. return (ERROR);
  723.     pPhyInfo = pDrvCtrl->pPhyInfo;
  724.     /* set some default values */
  725.  
  726.     pDrvCtrl->pPhyInfo->pDrvCtrl = (void *) pDrvCtrl;
  727.  
  728.     pDrvCtrl->pPhyInfo->phyAnOrderTbl = pDrvCtrl->pMiiPhyTbl;
  729.     pDrvCtrl->pPhyInfo->phyAddr = auPhyFind (pDrvCtrl);
  730.     /* 
  731.      * in case of link failure, set a default mode for the PHY 
  732.      * if we intend to use a different media, this flag should 
  733.      * be cleared
  734.      */
  735.  
  736.     pDrvCtrl->pPhyInfo->phyFlags |= MII_PHY_DEF_SET;
  737.     pDrvCtrl->pPhyInfo->phyWriteRtn = (FUNCPTR) auMiiWrite;
  738.     pDrvCtrl->pPhyInfo->phyReadRtn = (FUNCPTR) auMiiRead;
  739.     pDrvCtrl->pPhyInfo->phyDelayRtn = (FUNCPTR) taskDelay;
  740.     pDrvCtrl->pPhyInfo->phyMaxDelay = MII_PHY_DEF_DELAY;
  741.     pDrvCtrl->pPhyInfo->phyDelayParm = 1;
  742.     /* in case the cable is not there, leave the PHY ready to auto-negotiate */
  743.     pDrvCtrl->pPhyInfo->phyDefMode = PHY_AN_ENABLE;
  744.     /* handle some user-to-physical flags */
  745.     if (!(DRV_PHY_FLAGS_ISSET (AU_USR_MII_NO_AN)))
  746.         MII_PHY_FLAGS_SET (MII_PHY_AUTO);
  747.     else
  748.         MII_PHY_FLAGS_CLEAR (MII_PHY_AUTO);
  749.     if (DRV_PHY_FLAGS_ISSET (AU_USR_MII_AN_TBL))
  750.         MII_PHY_FLAGS_SET (MII_PHY_TBL);
  751.     else
  752.         MII_PHY_FLAGS_CLEAR (MII_PHY_TBL);
  753.     if (DRV_PHY_FLAGS_ISSET (AU_USR_MII_100MB))
  754.         MII_PHY_FLAGS_SET (MII_PHY_100);
  755.     else
  756.         MII_PHY_FLAGS_CLEAR (MII_PHY_100);
  757.     if (DRV_PHY_FLAGS_ISSET (AU_USR_MII_FD))
  758.         MII_PHY_FLAGS_SET (MII_PHY_FD);
  759.     else
  760.         MII_PHY_FLAGS_CLEAR (MII_PHY_FD);
  761.     if (DRV_PHY_FLAGS_ISSET (AU_USR_MII_10MB))
  762.         MII_PHY_FLAGS_SET (MII_PHY_10);
  763.     else
  764.         MII_PHY_FLAGS_CLEAR (MII_PHY_10);
  765.     if (DRV_PHY_FLAGS_ISSET (AU_USR_MII_HD))
  766.         MII_PHY_FLAGS_SET (MII_PHY_HD);
  767.     else
  768.         MII_PHY_FLAGS_CLEAR (MII_PHY_HD);
  769.     if (DRV_PHY_FLAGS_ISSET (AU_USR_MII_BUS_MON))
  770.         MII_PHY_FLAGS_SET (MII_PHY_MONITOR);
  771.     else
  772.         MII_PHY_FLAGS_CLEAR (MII_PHY_MONITOR);
  773.     MII_PHY_FLAGS_SET (MII_PHY_PRE_INIT);
  774.  
  775.     DRV_LOG (DRV_DEBUG_LOAD, ("auPhyPreInit pPhyInfo = 0x%x read=0x%x
  776.        write=0x%x tbl=0x%x addr=0x%x
  777.        flags=0x%x n"),
  778.        (int) pDrvCtrl->pPhyInfo,
  779.        (int) pDrvCtrl->pPhyInfo->phyReadRtn,
  780.        (int) pDrvCtrl->pPhyInfo->phyWriteRtn,
  781.        (int) pDrvCtrl->pPhyInfo->phyAnOrderTbl,
  782.        (int) pDrvCtrl->pPhyInfo->phyAddr,
  783.        (int) pDrvCtrl->pPhyInfo->phyFlags);
  784.  
  785.     return (OK);
  786.     }
  787. /***************************************************************************
  788. * auMiiRead - read a PHY device register via MII
  789. * RETURNS: the contents of a PHY device register in retVal arg, OK always
  790. */
  791. LOCAL STATUS auMiiRead
  792.     (
  793.     AU_DRV_CTRL * pDrvCtrl,
  794.     UINT8 phyAdrs, /* PHY address to access */
  795.     UINT8 phyReg, /* PHY register to read */
  796.     UINT16 * pRetVal
  797.     )
  798.     {
  799.     int timeout;
  800.     
  801.     AU_MII_CONTROL = (phyAdrs << 11) | (phyReg << 6);
  802.     timeout = 20;
  803.     while (AU_MII_CONTROL & AU_MII_CONTROL_BUSY)
  804. {
  805. taskDelay (1);
  806. if (--timeout == 0)
  807.     {
  808.     DRV_LOG (DRV_DEBUG_MII, "PHY access timeoutn",
  809.      0, 0, 0, 0, 0, 0);
  810.     return (ERROR);
  811.     }
  812. }
  813.     *pRetVal = AU_MII_DATA;
  814.     DRV_LOG (DRV_DEBUG_MII, "auMiiRead adr=%02x reg=%02x data=%04xn",
  815.              phyAdrs, phyReg, *pRetVal, 0, 0, 0);
  816.     return (OK);
  817.     }
  818. /***************************************************************************
  819. *
  820. * auMiiWrite - write to a PHY device register via MII
  821. *
  822. * RETURNS: OK or ERROR
  823. */
  824. LOCAL STATUS auMiiWrite
  825.     (
  826.     AU_DRV_CTRL * pDrvCtrl,
  827.     UINT8 phyAdrs, /* PHY address to access */
  828.     UINT8 phyReg, /* PHY register to write */
  829.     UINT16 data /* Data to write */
  830.     )
  831.     {
  832.     int timeout;
  833.     
  834.     DRV_LOG (DRV_DEBUG_MII, "auMiiWrite adr=%02x reg=%02x data=%04xn",
  835.              phyAdrs, phyReg, data, 0, 0, 0);
  836.     timeout = 20;
  837.     while (AU_MII_CONTROL & AU_MII_CONTROL_BUSY)
  838. {
  839. taskDelay (1);
  840. if (--timeout == 0)
  841.     {
  842.     DRV_LOG (DRV_DEBUG_MII, "PHY access timeoutn",
  843.      0, 0, 0, 0, 0, 0);
  844.     return (ERROR);
  845.     }
  846. }
  847.     AU_MII_DATA = data;
  848.     AU_MII_CONTROL = ((phyAdrs << 11) | (phyReg << 6)
  849.   | AU_MII_CONTROL_WRITE);
  850.     timeout = 20;
  851.     while (AU_MII_CONTROL & AU_MII_CONTROL_BUSY)
  852. {
  853. taskDelay (1);
  854. if (--timeout == 0)
  855.     {
  856.     DRV_LOG (DRV_DEBUG_MII, "PHY access timeoutn",
  857.      0, 0, 0, 0, 0, 0);
  858.     return (ERROR);
  859.     }
  860. }
  861.     return (OK);
  862.     }
  863. /***************************************************************************
  864. *
  865. * auPhyFind - Find the first PHY.
  866. *
  867. * RETURNS: Address of PHY or 0xFF if not found.
  868. */
  869. LOCAL UINT8 auPhyFind
  870.     (
  871.     AU_DRV_CTRL *pDrvCtrl
  872.     )
  873.     {
  874.     UINT16  miiData;
  875.     UINT8   phyAddr;
  876.     DRV_LOG (DRV_DEBUG_MII, "auMiiPhyFindn",
  877.              0, 0, 0, 0, 0, 0);
  878.     for (phyAddr = 0; phyAddr < (UINT8)AU_MAX_PHY; phyAddr++) 
  879.         {
  880.          auMiiRead (pDrvCtrl, phyAddr, MII_PHY_ID0, &miiData);
  881.         /* Verify PHY address read */
  882.         if ((miiData != 0xFFFF) && (miiData != 0)) /* Found PHY */
  883.             {
  884.     DRV_LOG (DRV_DEBUG_MII, "PHY @ %xn", phyAddr, 0,0,0,0,0);
  885.             return (phyAddr);
  886.             }
  887.         }
  888.     DRV_LOG (DRV_DEBUG_LOAD, "No PHY foundn", 0,0,0,0,0,0);
  889.     return (0xFF);
  890.     }
  891. /*******************************************************************************
  892. *
  893. * auStart - start the device
  894. *
  895. * This function calls BSP functions to connect interrupts and start the
  896. * device running in interrupt mode.
  897. *
  898. * RETURNS: OK or ERROR
  899. */
  900. LOCAL STATUS auStart
  901.     (
  902.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  903.     )
  904.     {
  905.     STATUS  result;
  906.     pDrvCtrl->txCleaning = FALSE;
  907.     pDrvCtrl->txBlocked  = FALSE;
  908.     if (auMiiInit (pDrvCtrl) == ERROR)
  909. return (ERROR);
  910.     SYS_INT_CONNECT (pDrvCtrl, auInt, (int)pDrvCtrl, &result);
  911.     if (result == ERROR)
  912.         return ERROR;
  913.     /* mark the interface as up */
  914.     END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  915.     DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
  916.     SYS_INT_ENABLE (pDrvCtrl);
  917.     DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
  918.     return (OK);
  919.     }
  920. /*******************************************************************************
  921. *
  922. * auInt - handle controller interrupt
  923. *
  924. * This routine is called at interrupt level in response to an interrupt from
  925. * the controller.
  926. */
  927. LOCAL void auInt
  928.     (
  929.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  930.     )
  931.     {
  932.     int i;
  933.     int txDone = FALSE;
  934.     int rxDone = FALSE;
  935.     DRV_LOG (DRV_DEBUG_INT, "auInt control=%08x rising=%08x, req0 %08xn",
  936.      AU_MAC_CONTROL, AU_INTC_RISING_EDGE_CLEAR(0),
  937.      AU_INTC_REQUEST0_INT(0), 0, 0, 0);
  938.     /* Acknowledge interrupt */
  939.     SYS_INT_DISABLE(pDrvCtrl);
  940.     SYS_WB_FLUSH();
  941.     /* Examine receive buffers */
  942.     for (i = 0; i < pDrvCtrl->rringSize; ++i)
  943. {
  944. if (AU_RX_ADDRESS(i) & (1 << 1))
  945.     rxDone = TRUE;
  946. }
  947.     /* Examine transmit buffers */
  948.     for (i = 0; i < pDrvCtrl->tringSize; ++i)
  949. {
  950. if (AU_TX_ADDRESS(i) & (1 << 1))
  951.     txDone = TRUE;
  952. }
  953.     /* Have netTask handle all packets */
  954.     if (rxDone || txDone)
  955. {
  956.         netJobAdd ((FUNCPTR)auHandleInt,(int)pDrvCtrl, 0, 0, 0, 0);
  957. }
  958.     if (pDrvCtrl->txBlocked)
  959.         {
  960.         pDrvCtrl->txBlocked = FALSE;
  961.         netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj, 0, 0, 0, 0);
  962.         }
  963.     }
  964. /*******************************************************************************
  965. *
  966. * auHandleInt - task level interrupt service for all packets
  967. *
  968. * This routine is called at task level indirectly by the interrupt
  969. * service routine to do any message received processing.
  970. */
  971. LOCAL void auHandleInt
  972.     (
  973.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  974.     )
  975.     {
  976. /*
  977.  * Handle zero or more previously transmitted frames
  978.  */
  979. while (AU_TX_ADDRESS(pDrvCtrl->tmdLastIndex) & (1<<1))
  980. {
  981. AU_TX_ADDRESS(pDrvCtrl->tmdLastIndex) = 0;
  982.      pDrvCtrl->tmdLastIndex = (pDrvCtrl->tmdLastIndex + 1) &
  983.  (pDrvCtrl->tringSize - 1);
  984. }
  985. SYS_WB_FLUSH();
  986. /*
  987.  * Handle zero or more newly received frames
  988.  */
  989. while (AU_RX_ADDRESS(pDrvCtrl->rmdIndex) & (1<<1)) auRecv (pDrvCtrl);
  990. /* 
  991.  * Re-enable interrupts 
  992.  */
  993. SYS_INT_ENABLE(pDrvCtrl);
  994. SYS_WB_FLUSH();
  995.     }
  996. /*******************************************************************************
  997. *
  998. * auRecv - process the next incoming packet
  999. *
  1000. * RETURNS: OK/ERROR
  1001. */
  1002. LOCAL STATUS auRecv
  1003.     (
  1004.     AU_DRV_CTRL * pDrvCtrl /* device to be initialized */
  1005.     )
  1006.     {
  1007.     int len;
  1008.     M_BLK_ID pMblk;
  1009.     char * pCluster;
  1010.     char * pBuf;
  1011.     CL_BLK_ID pClBlk;
  1012.     UINT32 status;
  1013.     int rmdIndex;
  1014.     /* Extract packet particulators */
  1015. rmdIndex = pDrvCtrl->rmdIndex;
  1016.     status = AU_RX_STATUS(rmdIndex);
  1017.     len = AU_RX_STATUS (rmdIndex) & 0x3fff; /* get packet length */
  1018.     pBuf = pDrvCtrl->pRxMem[rmdIndex];
  1019.     DRV_LOG (DRV_DEBUG_RX, "auRecv index = %d status = %08x len=%dn",
  1020.      rmdIndex, status, len, 0, 0, 0);
  1021.     DRV_LOG (DRV_DEBUG_RX, "auRecv dst=%02x:%02x:%02x:%02x:%02x:%02xn",
  1022.      pBuf[0]&0xff, pBuf[1]&0xff, pBuf[2]&0xff,
  1023.      pBuf[3]&0xff, pBuf[4]&0xff, pBuf[5]&0xff);
  1024.     DRV_LOG (DRV_DEBUG_RX, "auRecv src=%02x:%02x:%02x:%02x:%02x:%02xn",
  1025.      pBuf[6]&0xff, pBuf[7]&0xff, pBuf[8]&0xff,
  1026.      pBuf[9]&0xff, pBuf[10]&0xff, pBuf[11]&0xff);
  1027.     /* If error flag OR if packet is not completely in one buffer */
  1028.     if (!len)
  1029. {
  1030. DRV_LOG (DRV_DEBUG_RX, "RMD error!n", 1, 2, 3, 4, 5, 6);
  1031. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1032. goto cleanRXD; /* skip to clean up */
  1033. }
  1034.     /* If we cannot get a buffer to loan then bail out. */
  1035.     pCluster = netClusterGet (pDrvCtrl->endObj.pNetPool,
  1036.       pDrvCtrl->pClPoolId);
  1037.     if (pCluster == NULL)
  1038. {
  1039. DRV_LOG (DRV_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
  1040. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1041.         pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1042.         muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError);
  1043. goto cleanRXD;
  1044. }
  1045.     if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL)
  1046. {
  1047. netClFree (pDrvCtrl->endObj.pNetPool, pCluster);
  1048. DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
  1049. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1050.         pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1051.         muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError);
  1052. goto cleanRXD;
  1053. }
  1054.     /*
  1055.      * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  1056.      * one in the ring.
  1057.      */
  1058.     if ((pMblk = mBlkGet(pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA))
  1059. == NULL)
  1060. {
  1061. netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk);
  1062. netClFree (pDrvCtrl->endObj.pNetPool, pCluster);
  1063. DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
  1064. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1065.         pDrvCtrl->lastError.errCode = END_ERR_NO_BUF;
  1066.         muxError(&pDrvCtrl->endObj, &pDrvCtrl->lastError);
  1067. goto cleanRXD;
  1068. }
  1069.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1070.     bcopy (pBuf, pCluster + pDrvCtrl->offset, len);
  1071.     /* Join the cluster to the MBlock */
  1072.     netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);
  1073.     netMblkClJoin (pMblk, pClBlk);
  1074.     pMblk->mBlkHdr.mData  += pDrvCtrl->offset;
  1075.     pMblk->mBlkHdr.mLen   = len;
  1076.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1077.     pMblk->mBlkPktHdr.len = len;
  1078.     AU_RX_STATUS(rmdIndex) = 0;
  1079.     AU_RX_ADDRESS(rmdIndex)
  1080.       = ((UINT32) AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pRxMem[rmdIndex])) | 1;
  1081. SYS_WB_FLUSH();
  1082.     /* Advance our management index */
  1083.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  1084.     DRV_LOG (DRV_DEBUG_RX, "auRecv clean index %d %08xn",
  1085.      rmdIndex, AU_RX_ADDRESS(rmdIndex) & 0x1f, 0, 0, 0, 0);
  1086.     /* Call the upper layer's receive routine. */
  1087.     END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk);
  1088.     return (OK);
  1089. cleanRXD:
  1090.     /* Restore the receiver buffer */
  1091.     AU_RX_STATUS(rmdIndex) = 0;
  1092.     AU_RX_ADDRESS(rmdIndex)
  1093.       = ((UINT32) AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pRxMem[rmdIndex])) | 1;
  1094. SYS_WB_FLUSH();
  1095.     DRV_LOG (DRV_DEBUG_RX, "auRecv clean index %d %08xn",
  1096.      rmdIndex, AU_RX_ADDRESS(rmdIndex) & 0x1f, 0, 0, 0, 0);
  1097.     /* Advance our management index */
  1098.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  1099.     return (OK);
  1100.     }
  1101. /*******************************************************************************
  1102. *
  1103. * auSend - the driver send routine
  1104. *
  1105. * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
  1106. * The buffer must already have the addressing information properly installed
  1107. * in it.  This is done by a higher layer.  The last arguments are a free
  1108. * routine to be called when the device is done with the buffer and a pointer
  1109. * to the argument to pass to the free routine.  
  1110. *
  1111. * RETURNS: OK or ERROR.
  1112. */
  1113. LOCAL STATUS auSend
  1114.     (
  1115.     AU_DRV_CTRL *  pDrvCtrl,  /* device to be initialized */
  1116.     M_BLK_ID  pMblk      /* data to send */
  1117.     )
  1118.     {
  1119.     char *        pBuf;
  1120.     int index;
  1121.     int          len = 0;
  1122. UINT32 addr;
  1123.     DRV_LOG (DRV_DEBUG_TX, "auSendn", 1, 2, 3, 4, 5, 6);
  1124.     /* check device mode */
  1125.     if (pDrvCtrl->flags & AU_POLLING)
  1126.         {
  1127.         netMblkClChainFree (pMblk);
  1128.         errno = EINVAL;
  1129.         return (ERROR);
  1130.         }
  1131.     /*
  1132.      * Obtain exclusive access to transmitter.  This is necessary because
  1133.      * we might have more than one stack transmitting at once.
  1134.      */
  1135.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  1136.     /* Advance our management index (first) */
  1137.     index = pDrvCtrl->tmdIndex;
  1138.     if (AU_TX_ADDRESS(index) & 0x03)
  1139. {
  1140.         /* Are we still on the first chunk? */
  1141.         DRV_LOG (DRV_DEBUG_TX, "Out of TMDs! addr=%08x astat=%08x stat=%08xn",
  1142.  AU_TX_ADDRESS(index) & ~0x1f,
  1143.  AU_TX_ADDRESS(index) & 0x1f,
  1144.  AU_TX_STATUS(index), 4, 5, 6);
  1145. #ifdef DRV_DEBUG
  1146. auDump (pDrvCtrl->unit);
  1147. #endif
  1148.         pDrvCtrl->txBlocked = TRUE;
  1149.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1150.         return (END_ERR_BLOCK);
  1151.         }
  1152.     pBuf = pDrvCtrl->pTxMem[index];
  1153.     DRV_LOG (DRV_DEBUG_TX, "pBuf = 0x%Xn", (int)pBuf, 2, 3, 4, 5, 6);
  1154.     if (pBuf == NULL)
  1155.         {
  1156.         pDrvCtrl->txBlocked = TRUE;
  1157.         END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1158.         return (END_ERR_BLOCK);
  1159.         }
  1160.     /* copy and release the packet */
  1161.     
  1162.     len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1163.     netMblkClChainFree (pMblk);
  1164.     if (len < ETHERSMALL)
  1165. {
  1166. /* Pad to ETHERSMALL with zeros, required by H/W */
  1167. bzero (&pBuf[len], ETHERSMALL - len);
  1168. len = ETHERSMALL;
  1169. }
  1170.     addr  = ((UINT32)AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pTxMem[index]) | 1);
  1171. AU_TX_LENGTH(index) = len;
  1172. AU_TX_STATUS(index) = 0;
  1173.     AU_TX_ADDRESS(index) = addr;
  1174. SYS_WB_FLUSH();
  1175.     DRV_LOG (DRV_DEBUG_TX, "auSend: index %d len %dn",
  1176.              index, len, 3, 4, 5, 6);
  1177.     DRV_LOG (DRV_DEBUG_TX, "auSend dst=%02x:%02x:%02x:%02x:%02x:%02xn",
  1178.      pBuf[0]&0xff, pBuf[1]&0xff, pBuf[2]&0xff,
  1179.      pBuf[3]&0xff, pBuf[4]&0xff, pBuf[5]&0xff);
  1180.     DRV_LOG (DRV_DEBUG_TX, "auSend src=%02x:%02x:%02x:%02x:%02x:%02xn",
  1181.      pBuf[6]&0xff, pBuf[7]&0xff, pBuf[8]&0xff,
  1182.      pBuf[9]&0xff, pBuf[10]&0xff, pBuf[11]&0xff);
  1183.     
  1184.     /* Advance our management index */
  1185.     index = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
  1186.     pDrvCtrl->tmdIndex = index;
  1187.     /* Bump the statistic counter. */
  1188.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1189.     END_TX_SEM_GIVE (&pDrvCtrl->endObj);
  1190.     DRV_LOG (DRV_DEBUG_TX, "auSend Donen", 1, 2, 3, 4, 5, 6);
  1191.     return (OK);
  1192.     }
  1193. /*******************************************************************************
  1194. *
  1195. * auIoctl - the driver I/O control routine
  1196. *
  1197. * Process an ioctl request.
  1198. *
  1199. * RETURNS OK or ERROR value
  1200. */
  1201. LOCAL int auIoctl
  1202.     (
  1203.     AU_DRV_CTRL *  pDrvCtrl, /* device to be initialized */
  1204.     int  cmd,   /* ioctl command to execute */
  1205.     caddr_t  data   /* data to get or set       */
  1206.     )
  1207.     {
  1208.     long  value;
  1209.     int  error = 0;
  1210.     switch (cmd)
  1211.         {
  1212.         case EIOCSADDR:
  1213.     if (data == NULL)
  1214. return (EINVAL);
  1215.             bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),
  1216.    END_HADDR_LEN (&pDrvCtrl->endObj));
  1217.             break;
  1218.         case EIOCGADDR:
  1219.     if (data == NULL)
  1220. return (EINVAL);
  1221.             bcopy ((char *)END_HADDR (&pDrvCtrl->endObj), (char *)data,
  1222.     END_HADDR_LEN (&pDrvCtrl->endObj));
  1223.             break;
  1224.         case EIOCSFLAGS:
  1225.     value = (long)data;
  1226.             
  1227.     if (value < 0)
  1228. {
  1229. value = -value;
  1230. value--; /* HELP: WHY ??? */
  1231. END_FLAGS_CLR (&pDrvCtrl->endObj, value);
  1232. }
  1233.     else
  1234. {
  1235. END_FLAGS_SET (&pDrvCtrl->endObj, value);
  1236. }
  1237.     auConfig (pDrvCtrl);
  1238.             break;
  1239.         case EIOCGFLAGS:
  1240.     *(int *)data = END_FLAGS_GET (&pDrvCtrl->endObj);
  1241.             break;
  1242.         case EIOCMULTIADD:
  1243.             error = auMCastAddrAdd (pDrvCtrl, (char *) data);
  1244.             break;
  1245.         case EIOCMULTIDEL:
  1246.             error = auMCastAddrDel (pDrvCtrl, (char *) data);
  1247.             break;
  1248.         case EIOCMULTIGET:
  1249.             error = auMCastAddrGet (pDrvCtrl, (MULTI_TABLE *) data);
  1250.             break;
  1251. case EIOCPOLLSTART:
  1252.     error = auPollStart (pDrvCtrl);
  1253.     break;
  1254. case EIOCPOLLSTOP:
  1255.     error = auPollStop (pDrvCtrl);
  1256.     break;
  1257.         case EIOCGMIB2:
  1258.             if (data == NULL)
  1259.                 return (EINVAL);
  1260.             bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
  1261.                   sizeof(pDrvCtrl->endObj.mib2Tbl));
  1262.             break;
  1263.         case EIOCGFBUF:
  1264.             if (data == NULL)
  1265.                 return (EINVAL);
  1266.             *(int *)data = AU_MIN_FBUF;
  1267.             break;
  1268.         case EIOCGMWIDTH:
  1269.             if (data == NULL)
  1270.                 return (EINVAL);
  1271.             *(int *)data = 4;
  1272.             break;
  1273.         case EIOCGHDRLEN:
  1274.             if (data == NULL)
  1275.                 return (EINVAL);
  1276.             *(int *)data = 14;
  1277.             break;
  1278.         default:
  1279.             error = EINVAL;
  1280.         }
  1281.     return (error);
  1282.     }
  1283. /*******************************************************************************
  1284. *
  1285. * auReset - hardware reset of chip (stop it)
  1286. *
  1287. * This routine is responsible for resetting the device and switching into
  1288. * 32 bit mode.
  1289. *
  1290. * RETURNS: OK/ERROR
  1291. */
  1292. LOCAL int auReset
  1293.     (
  1294.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1295.     )
  1296.     {
  1297.     int i;
  1298.     DRV_LOG (DRV_DEBUG_LOAD, "auResetn", 1, 2, 3, 4, 5, 6);
  1299.     /* Reset MAC & DMA units */
  1300.     AU_MAC_ENABLE = 0;
  1301.     /* setup Rx memory pointers */
  1302.     pDrvCtrl->rmdIndex = 0;
  1303.     for (i = 0; i < pDrvCtrl->rringSize; ++i)
  1304.         {
  1305.         AU_RX_STATUS(i) = 0;
  1306.         AU_RX_ADDRESS(i) = 0;
  1307. }
  1308.     /* setup Tx memory pointers */
  1309.     pDrvCtrl->tmdIndex = 0;
  1310.     pDrvCtrl->tmdLastIndex = 0;
  1311.     for (i = 0; i < pDrvCtrl->tringSize; ++i)
  1312. {
  1313. AU_TX_STATUS(i) = 0;
  1314. AU_TX_LENGTH(i) = 0;
  1315. AU_TX_ADDRESS(i) = 0;
  1316. }
  1317. SYS_WB_FLUSH();
  1318.     return (OK);
  1319.     }
  1320. /*******************************************************************************
  1321. *
  1322. * auRestartSetup - setup memory descriptors and turn on chip
  1323. *
  1324. * This routine initializes all the shared memory structures and turns on
  1325. * the chip.
  1326. *
  1327. * RETURNS OK/ERROR
  1328. */
  1329. LOCAL STATUS auRestartSetup
  1330.     (
  1331.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1332.     )
  1333.     {  
  1334.     DRV_LOG (DRV_DEBUG_LOAD, "auRestartSetupn", 1, 2, 3, 4, 5, 6);
  1335.     /* reset the device */
  1336.     auReset (pDrvCtrl);
  1337.     DRV_LOG (DRV_DEBUG_LOAD, "Memory setup completen", 1, 2, 3, 4, 5, 6);
  1338.     /* reconfigure the device */
  1339.     auConfig (pDrvCtrl);
  1340.     return (OK);
  1341.     }
  1342. /*******************************************************************************
  1343. *
  1344. * auRestart - restart the device after a fatal error
  1345. *
  1346. * This routine takes care of all the messy details of a restart.  The device
  1347. * is reset and re-initialized.  The driver state is re-synchronized.
  1348. *
  1349. * RETURNS: N/A
  1350. */
  1351. LOCAL void auRestart
  1352.     (
  1353.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1354.     )
  1355.     {
  1356.     auRestartSetup (pDrvCtrl);
  1357.     /* set the flags to indicate readiness */
  1358.     END_OBJ_READY (&pDrvCtrl->endObj,
  1359.                     IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST
  1360.                     | IFF_MULTICAST);
  1361.     }
  1362. /******************************************************************************
  1363. *
  1364. * auConfig - reconfigure the interface under us.
  1365. *
  1366. * Reconfigure the interface setting promiscuous mode, and changing the
  1367. * multicast interface list.
  1368. *
  1369. * RETURNS: N/A
  1370. */
  1371. LOCAL void auConfig
  1372.     (
  1373.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1374.     )
  1375.     {
  1376.     UCHAR * enetAddr;
  1377.     int i;
  1378.     DRV_LOG (DRV_DEBUG_LOAD, "auConfign", 1, 2, 3, 4, 5, 6);
  1379.     /* Set promiscuous mode if it's asked for. */
  1380.     if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_PROMISC)
  1381.         {
  1382.         DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!n",
  1383.                  1, 2, 3, 4, 5, 6);
  1384.         /* chip will be in promiscuous mode */
  1385.         pDrvCtrl->flags |= AU_PROMISCUOUS_FLAG; 
  1386.         }
  1387.     else
  1388.         {
  1389.         DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!n",
  1390.                  1, 2, 3, 4, 5, 6);
  1391.         pDrvCtrl->flags &= ~AU_PROMISCUOUS_FLAG; 
  1392.         }
  1393.     /* Set up address filter for multicasting. */
  1394.     if (END_MULTI_LST_CNT (&pDrvCtrl->endObj) > 0)
  1395.         {
  1396.         auAddrFilterSet (pDrvCtrl);
  1397.         }
  1398.     /* Enable the MAC */
  1399.     AU_MAC_ENABLE = AU_MAC_ENABLE_CLOCKS_ONLY;
  1400.     SYS_WB_FLUSH();
  1401.     AU_MAC_ENABLE = AU_MAC_ENABLE_NORMAL & ~AU_MAC_ENABLE_TS;
  1402.     SYS_WB_FLUSH();
  1403.     /* Configure the MAC */
  1404. #if (_BYTE_ORDER == _BIG_ENDIAN)
  1405.     AU_MAC_CONTROL = AU_MAC_CONTROL_EM_BIG | AU_MAC_CONTROL_DO;
  1406. #else
  1407.     AU_MAC_CONTROL = AU_MAC_CONTROL_DO;
  1408. #endif
  1409.     enetAddr = pDrvCtrl->enetAddr;
  1410.     AU_MAC_ADDRESS_HIGH = (enetAddr[5] << 8) | enetAddr[4];
  1411.     AU_MAC_ADDRESS_LOW = ((enetAddr[3] << 24)
  1412.       | (enetAddr[2] << 16)
  1413.       | (enetAddr[1] << 8)
  1414.       | (enetAddr[0] << 0));
  1415.     DRV_LOG (DRV_DEBUG_LOAD, "mac   addr %08x %08xn",
  1416.      AU_MAC_ADDRESS_HIGH,
  1417.      AU_MAC_ADDRESS_LOW, 0, 0, 0, 0);
  1418.     DRV_LOG (DRV_DEBUG_LOAD, "multi addr %08x %08xn",
  1419.      AU_MULTICAST_HASH_ADDRESS_HIGH,
  1420.      AU_MULTICAST_HASH_ADDRESS_LOW, 0, 0, 0, 0);
  1421.     /* Configure MII */
  1422.     /* Setup RxD and TxD pointers */
  1423.     pDrvCtrl->rmdIndex = (AU_RX_ADDRESS(0) >> 2) & 0x03;
  1424.     pDrvCtrl->tmdIndex = (AU_TX_ADDRESS(0) >> 2) & 0x03;
  1425.     pDrvCtrl->tmdLastIndex = pDrvCtrl->tmdIndex;
  1426. #ifdef AU_PROMISCUOS_MODE
  1427.     /* Handle promiscuous mode */
  1428.     if (pDrvCtrl->flags & AU_PROMISCUOUS_FLAG)
  1429. AU_MAC_CONTROL |= AU_MAC_CONTROL_PR;
  1430. #endif
  1431.     for (i = 0; i < pDrvCtrl->rringSize; ++i)
  1432.         AU_RX_ADDRESS(i) 
  1433.           = ((UINT32) AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pRxMem[i])) | 1;
  1434.     /* Enable transmit and receive */
  1435.     AU_MAC_CONTROL |= AU_MAC_CONTROL_TE | AU_MAC_CONTROL_RE;
  1436.     SYS_WB_FLUSH();
  1437.     }
  1438. /******************************************************************************
  1439. *
  1440. * auAddrFilterSet - set the address filter for multicast addresses
  1441. *
  1442. * This routine goes through all of the multicast addresses on the list
  1443. * of addresses (added with the auAddrAdd() routine) and sets the
  1444. * device's filter correctly.
  1445. *
  1446. * RETURNS: N/A
  1447. */
  1448. LOCAL void auAddrFilterSet
  1449.     (
  1450.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1451.     )
  1452.     {
  1453.     ETHER_MULTI *  pCurr;
  1454.     UINT8 * pCp;
  1455.     UINT8  byte;
  1456.     UINT32  crc;
  1457.     int  len;
  1458.     int  count;
  1459.     pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
  1460.     while (pCurr != NULL)
  1461. {
  1462. pCp = (UINT8 *)&pCurr->addr;
  1463. crc = 0xffffffff;
  1464. for (len = AU_LA_LEN; --len >= 0;)
  1465.     {
  1466.     byte = *pCp++;
  1467.             for (count = 0; count < AU_LAF_LEN; count++)
  1468. {
  1469. if ((byte & 0x01) ^ (crc & 0x01))
  1470.     {
  1471.     crc >>= 1;
  1472.     crc = crc ^ AU_CRC_POLYNOMIAL;
  1473.     }
  1474. else
  1475.     {
  1476.     crc >>= 1;
  1477.     }
  1478. byte >>= 1;
  1479. }
  1480.     }
  1481. /* Just want the 6 most significant bits. */
  1482. crc = AU_CRC_TO_LAF_IX (crc);
  1483. pCurr = END_MULTI_LST_NEXT(pCurr);
  1484. }
  1485.     }
  1486. /*******************************************************************************
  1487. *
  1488. * auPollReceive - routine to receive a packet in polled mode.
  1489. *
  1490. * This routine is called by a user to try and get a packet from the
  1491. * device. This routine return OK if it is successful in getting the packet
  1492. *
  1493. * RETURNS: OK or EAGAIN.
  1494. */
  1495. LOCAL STATUS auPollReceive
  1496.     (
  1497.     AU_DRV_CTRL *  pDrvCtrl, /* device to be initialized */
  1498.     M_BLK_ID  pMblk
  1499.     )
  1500.     {
  1501.     int                 len;
  1502.     char *              pBuf;
  1503.     UINT32              status, ERROR_MASK=0x812bc000;
  1504.     int                 rmdIndex,oldLevel;
  1505.     DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bn", 1, 2, 3, 4, 5, 6);
  1506.  /*
  1507.   * Handle zero or more newly received frames
  1508.   */
  1509. if (!(AU_RX_ADDRESS(pDrvCtrl->rmdIndex) & (1<<1)))
  1510.     {
  1511.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  1512.     /* goto cleanRx; */
  1513.     return (EAGAIN);
  1514.     }
  1515.     /* Extract packet particulators */
  1516.     rmdIndex = pDrvCtrl->rmdIndex;
  1517.     /* Read the device status register */
  1518.     status = AU_RX_STATUS(rmdIndex);
  1519.     len = AU_RX_STATUS (rmdIndex) & 0x3fff; /* get packet length */
  1520.     pBuf = pDrvCtrl->pRxMem[rmdIndex];
  1521.     if (status & (ERROR_MASK & ~0x0))
  1522.         {
  1523.         DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad errorn", 1, 2, 3, 4, 5, 6);
  1524. END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1525.         /* restart chip on fatal error */
  1526.         if (status & ERROR_MASK & 0x0)        /* memory error */
  1527.             {
  1528.     END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); 
  1529.             DRV_LOG (DRV_DEBUG_POLL_RX, "PRX restartn", 1, 2, 3, 4, 5, 6);
  1530.             auRestart (pDrvCtrl);
  1531.             return (EAGAIN);
  1532.             }
  1533.         /* goto cleanRx;  */
  1534.         goto cleanRx;
  1535.         }
  1536.     if (!len)
  1537.         {
  1538.         DRV_LOG (DRV_DEBUG_RX, "RMD error!n", 1, 2, 3, 4, 5, 6);
  1539.         END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
  1540.         goto cleanRx;                          /* skip to clean up */
  1541.         }
  1542.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
  1543.     /* Upper layer provides the buffer. */
  1544.     if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
  1545. {
  1546.         DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad mblk len:%d flags:%dn",
  1547.                  pMblk->mBlkHdr.mLen, pMblk->mBlkHdr.mFlags, 3, 4, 5, 6);
  1548. return (EAGAIN);
  1549. }
  1550.     pMblk->mBlkHdr.mData  += pDrvCtrl->offset;
  1551.     bcopy (pBuf, pMblk->mBlkHdr.mData, len);
  1552.     pMblk->mBlkHdr.mLen = len;
  1553.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  1554.     pMblk->mBlkPktHdr.len = len;
  1555. cleanRx:
  1556.     /* Restore the receiver buffer */
  1557.     AU_RX_STATUS(rmdIndex) = 0;
  1558.     AU_RX_ADDRESS(rmdIndex)
  1559.       = ((UINT32) AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pRxMem[rmdIndex])) | 1;
  1560.     SYS_WB_FLUSH();
  1561.     DRV_LOG (DRV_DEBUG_RX, "auPollReceive clean index %d %08xn",
  1562.              rmdIndex, AU_RX_ADDRESS(rmdIndex) & 0x1f, 0, 0, 0, 0);
  1563.     /* Advance our management index */
  1564.     pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
  1565.     DRV_LOG (DRV_DEBUG_POLL_RX, "PRX okn", 1, 2, 3, 4, 5, 6);
  1566.     return (OK);
  1567.     }
  1568. /*******************************************************************************
  1569. *
  1570. * auPollSend - routine to send a packet in polled mode.
  1571. *
  1572. * This routine is called by a user to try and send a packet on the
  1573. * device.
  1574. *
  1575. * RETURNS: OK or EAGAIN.
  1576. */
  1577. LOCAL STATUS auPollSend
  1578.     (
  1579.     AU_DRV_CTRL *  pDrvCtrl, /* device to be initialized */
  1580.     M_BLK_ID  pMblk
  1581.     )
  1582.     {
  1583.     char *        pBuf;
  1584.     int index;
  1585.     int          len = 0;
  1586.     int          oldLevel;
  1587.     UINT32 addr;
  1588.     DRV_LOG (DRV_DEBUG_POLL_TX, "PTX bn", 1, 2, 3, 4, 5, 6);
  1589.     /* Advance our management index (first) */
  1590.     index = pDrvCtrl->tmdIndex;
  1591.     if (AU_TX_ADDRESS(index) & 0x01) 
  1592.         {
  1593.         DRV_LOG (DRV_DEBUG_POLL_TX, "Out of tmds.n", 1, 2, 3, 4, 5, 6);
  1594.         
  1595.         if (!pDrvCtrl->txCleaning) 
  1596.     auTRingScrub (pDrvCtrl);
  1597. return (EAGAIN);
  1598.         }
  1599.     pBuf = pDrvCtrl->pTxMem[index];
  1600.     
  1601.     if (pBuf == NULL)
  1602.          return (EAGAIN);
  1603.     /* copy and release the packet */
  1604.     len = netMblkToBufCopy (pMblk, pBuf, NULL);
  1605.     if (len < ETHERSMALL)
  1606. {
  1607. /* Pad to ETHERSMALL with zeros, required by H/W */
  1608. bzero (&pBuf[len], ETHERSMALL - len);
  1609. len = ETHERSMALL;
  1610. }
  1611.     addr  = ((UINT32)AU_CACHE_VIRT_TO_PHYS(pDrvCtrl->pTxMem[index]) | 1);
  1612.     AU_TX_LENGTH(index) = len;
  1613.     AU_TX_STATUS(index) = 0;
  1614.     AU_TX_ADDRESS(index) = addr;
  1615.     SYS_WB_FLUSH();
  1616.     /* Bump the statistic counter. */
  1617.     END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
  1618.     /* Spin until we think we've sent it.  */
  1619.     
  1620.     while (!(AU_TX_ADDRESS(index) & (1<<1)));
  1621.     AU_TX_ADDRESS(index) = 0;
  1622.     AU_TX_STATUS(index) = 0;
  1623.     AU_TX_LENGTH(index) = 0;
  1624.     SYS_WB_FLUSH();
  1625.     
  1626.     index = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
  1627.     pDrvCtrl->tmdIndex = index;
  1628.     pDrvCtrl->tmdLastIndex = (pDrvCtrl->tmdLastIndex + 1) &
  1629.                               (pDrvCtrl->tringSize - 1);
  1630.     DRV_LOG (DRV_DEBUG_POLL_TX, "PTX en", 1, 2, 3, 4, 5, 6);
  1631.     return (OK);
  1632.     }
  1633. /*****************************************************************************
  1634. *
  1635. * auMCastAddrAdd - add a multicast address for the device
  1636. *
  1637. * This routine adds a multicast address to whatever the driver
  1638. * is already listening for.  It then resets the address filter.
  1639. *
  1640. * RETURNS: OK
  1641. */
  1642. LOCAL STATUS auMCastAddrAdd
  1643.     (
  1644.     AU_DRV_CTRL *  pDrvCtrl, /* device to be initialized */
  1645.     char *  pAddress
  1646.     )
  1647.     {
  1648. #ifdef AU_END_MULTICAST
  1649.     int  error;
  1650.     if ((error = etherMultiAdd (&pDrvCtrl->endObj.multiList,
  1651. pAddress)) == ENETRESET)
  1652.     auConfig (pDrvCtrl);
  1653. #endif
  1654.     return (OK);
  1655.     }
  1656. /*****************************************************************************
  1657. *
  1658. * auMCastAddrDel - delete a multicast address for the device
  1659. *
  1660. * This routine removes a multicast address from whatever the driver
  1661. * is listening for.  It then resets the address filter.
  1662. *
  1663. * RETURNS: OK.
  1664. */
  1665. LOCAL STATUS auMCastAddrDel
  1666.     (
  1667.     AU_DRV_CTRL *  pDrvCtrl, /* device to be initialized */
  1668.     char *  pAddress
  1669.     )
  1670.     {
  1671. #if AU_END_MULTICAST
  1672.     int  error;
  1673.     if ((error = etherMultiDel (&pDrvCtrl->endObj.multiList,
  1674.      (char *)pAddress)) == ENETRESET)
  1675.     auConfig (pDrvCtrl);
  1676. #endif
  1677.     return (OK);
  1678.     }
  1679. /*****************************************************************************
  1680. *
  1681. * auMCastAddrGet - get the multicast address list for the device
  1682. *
  1683. * This routine gets the multicast list of whatever the driver
  1684. * is already listening for.
  1685. *
  1686. * RETURNS: OK/ERROR
  1687. */
  1688. LOCAL STATUS auMCastAddrGet
  1689.     (
  1690.     AU_DRV_CTRL *  pDrvCtrl, /* device to be initialized */
  1691.     MULTI_TABLE *  pTable
  1692.     )
  1693.     {
  1694.     int  error;
  1695.     error = etherMultiGet (&pDrvCtrl->endObj.multiList, pTable);
  1696.     return (error);
  1697.     }
  1698. /*******************************************************************************
  1699. *
  1700. * auStop - stop the device
  1701. *
  1702. * This function calls BSP functions to disconnect interrupts and stop
  1703. * the device from operating in interrupt mode.
  1704. *
  1705. * RETURNS: OK or ERROR
  1706. */
  1707. LOCAL STATUS auStop
  1708.     (
  1709.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1710.     )
  1711.     {
  1712.     STATUS  result = OK;
  1713.     /* Stop the device. */
  1714.     auReset (pDrvCtrl);
  1715.     SYS_INT_DISABLE (pDrvCtrl);
  1716.     /* mark the interface as down */
  1717.     END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING));
  1718.     /* disconnect the interrupt handler */
  1719.     SYS_INT_DISCONNECT (pDrvCtrl, auInt, (int)pDrvCtrl, &result);
  1720.     if (result == ERROR)
  1721. {
  1722. DRV_LOG (DRV_DEBUG_LOAD, "Could not disconnect interrupt!n",
  1723.                  1, 2, 3, 4, 5, 6);
  1724. }
  1725.     return (result);
  1726.     }
  1727. /******************************************************************************
  1728. *
  1729. * auUnload - unload a driver from the system
  1730. *
  1731. * This function first brings down the device, and then frees any
  1732. * stuff that was allocated by the driver in the load function. The controller
  1733. * structure should be free by who ever is calling this function.
  1734. *
  1735. * RETURNS: OK
  1736. */
  1737. LOCAL STATUS auUnload
  1738.     (
  1739.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1740.     )
  1741.     {
  1742.     END_OBJECT_UNLOAD (&pDrvCtrl->endObj);
  1743.     /* Free the shared DMA memory. */
  1744.     if (pDrvCtrl->pRxMem)
  1745. {
  1746. cacheDmaFree (pDrvCtrl->pRxMemBase);
  1747. pDrvCtrl->pRxMemBase = NULL;
  1748. }
  1749.     
  1750.     if (pDrvCtrl->pTxMem)
  1751. {
  1752. cacheDmaFree (pDrvCtrl->pTxMemBase);
  1753. pDrvCtrl->pTxMemBase = NULL;
  1754. }
  1755.     /* Free the shared DMA memory allocated for clusters */
  1756.     
  1757.     if (pDrvCtrl->flags & AU_MEM_ALLOC_FLAG)
  1758.         cacheDmaFree (pDrvCtrl->clDesc.memArea);
  1759.     /* Free the memory allocated for mBlks and clBlks */
  1760.     
  1761.     if (pDrvCtrl->mClCfg.memArea != NULL)
  1762.         free (pDrvCtrl->mClCfg.memArea);
  1763.     /* Free the memory allocated for driver pool structure */
  1764.     if (pDrvCtrl->endObj.pNetPool != NULL)
  1765.         free (pDrvCtrl->endObj.pNetPool);
  1766.     return (OK);
  1767.     }
  1768. /*******************************************************************************
  1769. *
  1770. * auPollStart - start polled mode operations
  1771. *
  1772. * RETURNS: OK or ERROR.
  1773. */
  1774. LOCAL STATUS auPollStart
  1775.     (
  1776.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1777.     )
  1778.     {
  1779.     SYS_INT_DISABLE(pDrvCtrl);
  1780.     pDrvCtrl->flags |= AU_POLLING;
  1781.     DRV_LOG (DRV_DEBUG_POLL, "POLL STARTEDn", 1, 2, 3, 4, 5, 6);
  1782.     return (OK);
  1783.     }
  1784. /*******************************************************************************
  1785. *
  1786. * auPollStop - stop polled mode operations
  1787. *
  1788. * RETURNS: OK or ERROR.
  1789. */
  1790. LOCAL STATUS auPollStop
  1791.     (
  1792.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1793.     )
  1794.     {
  1795.     SYS_INT_ENABLE(pDrvCtrl);
  1796.     pDrvCtrl->flags &= ~AU_POLLING;
  1797.     DRV_LOG (DRV_DEBUG_POLL, "STOPPEDn", 1, 2, 3, 4, 5, 6);
  1798.     return (OK);
  1799.     }
  1800. /******************************************************************************
  1801. *
  1802. * auTRingScrub - clean the transmit ring
  1803. *
  1804. * RETURNS: N/A
  1805. *
  1806. */
  1807. LOCAL void auTRingScrub
  1808.     (
  1809.     AU_DRV_CTRL *  pDrvCtrl /* device to be initialized */
  1810.     )
  1811.     {
  1812.     
  1813.     pDrvCtrl->txCleaning = TRUE;
  1814.     
  1815.     do
  1816.         {
  1817.         /* if the buffer is still owned by the MAC, don't touch it */
  1818. if (AU_TX_ADDRESS(pDrvCtrl->tmdLastIndex) & (1 << 1))
  1819.     break;
  1820. /* Clear the TX entry */
  1821.         DRV_LOG (DRV_DEBUG_TX, "auTRingScrub %dn",
  1822.  pDrvCtrl->tmdLastIndex, 0, 0, 0, 0, 0);
  1823. AU_TX_STATUS(pDrvCtrl->tmdLastIndex) = 0;
  1824. AU_TX_LENGTH(pDrvCtrl->tmdLastIndex) = 0;
  1825. AU_TX_ADDRESS(pDrvCtrl->tmdLastIndex) = 0;
  1826.         /* Increment the tmd disposal index pointer around the ring */
  1827.         pDrvCtrl->tmdLastIndex = (pDrvCtrl->tmdLastIndex + 1) &
  1828.       (pDrvCtrl->tringSize - 1);
  1829.         }
  1830.     while (pDrvCtrl->tmdLastIndex != pDrvCtrl->tmdIndex);
  1831.     pDrvCtrl->txCleaning = FALSE;
  1832.     }
  1833. /******************************************************************************
  1834. *
  1835. * auDump - display device status
  1836. *
  1837. */
  1838. void auDump
  1839.     (
  1840.     int unit
  1841.     )
  1842.     {
  1843. #ifdef DRV_DEBUG
  1844.     int i;
  1845.     AU_DRV_CTRL *  pDrvCtrl = dbgDrvCtrl[unit];
  1846.     /* Examine receive buffers */
  1847.     printf ("Rx index %d (rmdIndex=%d)n",
  1848.     (AU_RX_ADDRESS(0) >> 2) & 0x03,
  1849.     pDrvCtrl->rmdIndex);
  1850.     for (i = 0; i < pDrvCtrl->rringSize; ++i)
  1851. {
  1852. printf ("rx%d addr=%08x astat=%02x stat=%08x len=%dn", i,
  1853. AU_RX_ADDRESS(i) & ~0x1f,
  1854. AU_RX_ADDRESS(i) & 0x1f,
  1855. AU_RX_STATUS(i) & 0xffffc000,
  1856. AU_RX_STATUS(i) & 0x00003fff);
  1857.     printf ("receive %d donen", AU_RX_ADDRESS(i) & (1 << 1) ? 1 : 0);
  1858. }
  1859.     /* Examine transmit buffers */
  1860.     printf ("Tx index %dn",
  1861.     (AU_TX_ADDRESS(0) >> 2) & 0x03);
  1862.     for (i = 0; i < pDrvCtrl->tringSize; ++i)
  1863. {
  1864. printf ("tx%d addr=%08x astat=%02x stat=%08x len=%dn", i,
  1865. AU_TX_ADDRESS(i) & ~0x1f,
  1866. AU_TX_ADDRESS(i) & 0x1f,
  1867. AU_TX_STATUS(i),
  1868. AU_TX_LENGTH(i));
  1869.     printf ("transmit %d donen", AU_TX_ADDRESS(i) & (1 << 1) ? 1 : 0);
  1870. }
  1871. #endif
  1872.     }