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

VxWorks

开发平台:

C/C++

  1. /* mb86960End.c - END-style Fujitsu MB86960 Ethernet network interface driver */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01h,14jan02,dat  Removing warnings from Diab compiler
  8. 01g,20sep01,dat  Removing ANSI errors for diab compiler
  9. 01f,28aug00,stv  corrected the handling of EIOCSFLAGS ioctl (SPR# 29423).
  10. 01e,02aug00,stv  removed netMblkClChainFree() in Pollsend routine (SPR# 32885).
  11. 01d,27jan00,dat  fixed use of NULL
  12. 01c,01dec99,stv  freed mBlk chain before returning ERROR (SPR #28492).
  13. 01b,28mar99,jdi  doc: added missing module title and fixed other format
  14.                  errors (SPR 26119).
  15. 01a,27feb99,db  written from templateEnd.c and target/src/drv/netif/if_fn.c
  16. */
  17. /*
  18. DESCRIPTION
  19. This module implements the Fujitsu MB86960 NICE Ethernet network interface
  20. driver.
  21. This driver is non-generic and has only been run on the Fujitsu SPARClite
  22. Evaluation Board.  It currently supports only unit number zero.
  23. The driver must be given several target-specific parameters, and some external
  24. support routines must be provided.  These parameters, and the mechanisms used
  25. to communicate them to the driver, are detailed below.
  26. BOARD LAYOUT
  27. This device is on-board.  No jumpering diagram is necessary.
  28. The MB86960 Network Interface Controller with Encoder/Decoder (NICE) chip is
  29. a highly integrated monolithic device which incorporates both network
  30. controller, complete with buffer management and Manchester encoder/decoder.
  31. TARGET-SPECIFIC PARAMETERS
  32. The format of the parameter string is:
  33.     <unit>:<devBaseAddr>:<ivec>
  34. .IP <unit>
  35. A convenient holdover from the former model.  It is only used in the
  36. string name for the driver.
  37. .IP <devBaseAddr>
  38. The base Address of the chip registers.
  39. .IP <ivec>
  40. This is the interrupt vector number of the hardware interrupt generated by
  41. this ethernet device.  The driver uses intConnect() to attach an interrupt
  42. handler to this interrupt.
  43. EXTERNAL SUPPORT REQUIREMENTS
  44. This driver requires seven external support functions:
  45. .IP sys86960IntEnable()
  46. .CS
  47.     void sysEnetIntEnable (int unit)
  48. .CE
  49. This routine provides a target-specific interface to enable Ethernet device
  50. interrupts for a given device unit. For this driver, value of unit must be 0.
  51. .IP sys86960IntDisable()
  52. .CS
  53.     void sysEnetIntDisable (int unit)
  54. .CE
  55. This routine provides a target-specific interface to disable Ethernet device
  56. interrupts for a given device unit. For this driver, value of unit must be 0.
  57. .IP sysEnetAddrGet()
  58. .CS
  59.     STATUS sysEnetAddrGet (int unit, char *enetAdrs)
  60. .CE
  61. This routine provides a target-specific interface to access a device Ethernet
  62. address. This routine should provide a six-byte Ethernet address in  
  63. the <enetAdrs> parameter and return OK or ERROR.
  64. In this driver the macros SYS_OUT_SHORT and SYS_IN_SHORT which call
  65. bsp-specific functions to access the chip register.
  66. INCLUDES:
  67. end.h endLib.h etherMultiLib.h
  68. SEE ALSO: muxLib, endLib
  69. .I "Writing and Enhanced Network Driver"
  70. */
  71. /* includes */
  72. #include "vxWorks.h"
  73. #include "iv.h"
  74. #include "memLib.h"
  75. #include "intLib.h"
  76. #include "stdio.h"
  77. #include "stdlib.h"
  78. #include "netLib.h"
  79. #include "drv/end/mb86960End.h" /* Common defines. */
  80. #include "etherMultiLib.h" /* multicast stuff. */
  81. #include "end.h" /* Common END structures. */
  82. #include "endLib.h"
  83. #include "lstLib.h" /* Needed to maintain protocol list. */
  84. #include "logLib.h"
  85. #include "net/protosw.h"
  86. #include "sys/socket.h"
  87. #include "errno.h"
  88. #include "net/if.h"
  89. #include "net/route.h"
  90. #include "netinet/in.h"
  91. #include "netinet/in_systm.h"
  92. #include "netinet/in_var.h"
  93. #include "netinet/ip.h"
  94. #include "netinet/if_ether.h"
  95. #include "net/if_subr.h"
  96. #include "m2Lib.h"
  97. /* Endian safe macro - MB86960_SWAP_SHORT */
  98. #if (_BYTE_ORDER == _BIG_ENDIAN)
  99. #   define MB86960_SWAP_SHORT(x) (MSB(x) | LSB(x) << 8)
  100. #else
  101. #   define MB86960_SWAP_SHORT(x) (x)
  102. #endif 
  103. /*
  104.  * Default macro definitions for BSP interface.
  105.  * These macros can be redefined in a wrapper file, to generate
  106.  * a new module with an optimized interface.
  107.  */
  108. /* Macro to connect interrupt handler to vector */
  109. #ifndef SYS_INT_CONNECT
  110. #   define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) 
  111. IMPORT STATUS sysIntConnect(); 
  112. *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->vector), 
  113.      rtn, (int)arg); 
  114. }
  115. #endif
  116. /* Macro to disconnect interrupt handler from vector */
  117. #ifndef SYS_INT_DISCONNECT
  118. #   define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) 
  119. *pResult = OK; /* HELP: need a real routine */ 
  120. }
  121. #endif
  122. /* Macro to enable the appropriate interrupt level */
  123. #ifndef SYS_INT_ENABLE
  124. #   define SYS_INT_ENABLE(pDrvCtrl) 
  125. IMPORT STATUS sysEnetIntEnable(int); 
  126. sysEnetIntEnable (pDrvCtrl->unit); 
  127. }
  128. #endif
  129. #ifndef SYS_INT_DISABLE
  130. #   define SYS_INT_DISABLE(pDrvCtrl) 
  131. IMPORT STATUS sysEnetIntDisable(int); 
  132. sysEnetIntDisable (pDrvCtrl->unit); 
  133. }
  134. #endif
  135. /* Macro to get the ethernet address from the BSP */
  136. #ifndef SYS_ENET_ADDR_GET
  137. #   define SYS_ENET_ADDR_GET(pDrvCtrl, pRetCode) 
  138. IMPORT STATUS sysEnetAddrGet(); 
  139.         *pRetCode = sysEnetAddrGet (pDrvCtrl->unit, (char *) &pDrvCtrl->enetAddr); 
  140. }
  141. #endif
  142. /*
  143.  * Macros to do a short (UINT16) access to the chip. Default
  144.  * assumes a normal memory mapped device.
  145.  */
  146. #ifndef SYS_OUT_SHORT
  147. #   define SYS_OUT_SHORT(addr,value) 
  148. IMPORT void sysAsiSeth (); 
  149.         sysAsiSeth (addr, value); 
  150. }
  151. #endif
  152. #ifndef SYS_IN_SHORT
  153. #   define SYS_IN_SHORT(addr, var) 
  154. IMPORT u_short sysAsiGeth (); 
  155.         var = sysAsiGeth (addr); 
  156. }
  157. #endif
  158. /* A shortcut for getting the hardware address from the MIB II stuff. */
  159. #define END_HADDR(pEnd)
  160. ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
  161. #define END_HADDR_LEN(pEnd) 
  162. ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
  163. /*
  164.  * This will only work if there is only a single unit, for multiple
  165.  * unit device drivers these should be integrated into the MB86960_END_CTRL
  166.  * structure.
  167.  */
  168. M_CL_CONFIG fnMclBlkCfg =  /* network mbuf configuration table */
  169.     {
  170.     /* 
  171.     no. mBlks no. clBlks memArea memSize
  172.     ----------- ---------- ------- -------
  173.     */
  174.     0,  0,  NULL,  0
  175.     };
  176. CL_DESC fnClDescTbl [] =  /* network cluster pool configuration table */
  177.     {
  178.     /* 
  179.     clusterSize num memArea memSize
  180.     ----------- ---- ------- -------
  181.     */
  182.     {MB86960_BUFSIZ, 0, NULL, 0}  
  183.     }; 
  184. int fnClDescTblNumEnt = (NELEMENTS(fnClDescTbl));
  185. /* Definitions for the flags field */
  186. #define LS_PROMISCUOUS_FLAG     0x1
  187. #define LS_MEM_ALLOC_FLAG       0x2
  188. #define LS_PAD_USED_FLAG        0x4
  189. #define LS_RCV_HANDLING_FLAG    0x8
  190. #define LS_POLLING              0x20
  191. /***** DEBUG MACROS *****/
  192. #define DRV_DEBUG
  193. #ifdef DRV_DEBUG
  194. #define DRV_DEBUG_OFF 0x0000
  195. #define DRV_DEBUG_RX 0x0001
  196. #define DRV_DEBUG_TX 0x0002
  197. #define DRV_DEBUG_INT 0x0004
  198. #define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
  199. #define DRV_DEBUG_POLL_RX 0x0008
  200. #define DRV_DEBUG_POLL_TX 0x0010
  201. #define DRV_DEBUG_LOAD 0x0020
  202. #define DRV_DEBUG_IOCTL 0x0040
  203. #define DRV_DEBUG_POLL_REDIR 0x10000
  204. #define DRV_DEBUG_LOG_NVRAM 0x20000
  205. #ifdef LOCAL
  206. #undef LOCAL
  207. #endif /* LOCAL */
  208. #define LOCAL
  209. int  mb86960Debug = DRV_DEBUG_OFF;
  210. NET_POOL mb86960NetPool;
  211. #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)  
  212.         if (mb86960Debug & FLG)                   
  213.            logMsg(X0, X1, X2, X3, X4, X5, X6);
  214. #define DRV_PRINT(FLG,X)                          
  215. if (mb86960Debug & FLG) printf X;
  216. #else /*DRV_DEBUG*/
  217. #define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
  218. #define DRV_PRINT(DBG_SW,X)
  219. #endif /*DRV_DEBUG*/
  220. #define MB86960_BUFS  100    /* Needs some work */
  221. /* forward static functions */
  222. LOCAL void mb86960Reset (MB86960_END_CTRL * pDrvCtrl);
  223. LOCAL void mb86960Int (MB86960_END_CTRL * pDrvCtrl);
  224. LOCAL void mb86960HandleRcvInt   (MB86960_END_CTRL * pDrvCtrl);
  225. LOCAL STATUS mb86960Recv (MB86960_END_CTRL * pDrvCtrl, 
  226.  MB86960_RX_FRAME * pRxFrame);
  227. LOCAL BOOL      mb86960RxMore  (MB86960_END_CTRL * pDrvCtrl);
  228. LOCAL void mb86960Config (MB86960_END_CTRL * pDrvCtrl);
  229. /* END Specific interfaces. */
  230. /* This is the only externally visible interface. */
  231. END_OBJ *  mb86960EndLoad  (char * initString);
  232. LOCAL STATUS mb86960Start (MB86960_END_CTRL * pDrvCtrl);
  233. LOCAL STATUS mb86960Stop (MB86960_END_CTRL * pDrvCtrl);
  234. LOCAL STATUS mb86960Unload   ();
  235. LOCAL int mb86960Ioctl (MB86960_END_CTRL * pDrvCtrl, int cmd,
  236.  caddr_t data);
  237. LOCAL STATUS mb86960Send (MB86960_END_CTRL * pDrvCtrl, 
  238.  M_BLK_ID pBuf);
  239. LOCAL STATUS    mb89680Transmit (MB86960_END_CTRL * pDrvCtrl, 
  240.  M_BLK_ID pMblk);
  241. LOCAL STATUS    mb86960PacketGet (MB86960_END_CTRL  * pDrvCtrl, 
  242.   MB86960_RX_FRAME * pRxFrame);
  243. LOCAL BOOL      mb89680RxMore   (MB86960_END_CTRL * pDrvCtrl);
  244.   
  245. LOCAL void  mb86960AddrFilterSet (MB86960_END_CTRL* pDrvCtrl, char * pAddr, 
  246.       BOOL bSet);
  247. LOCAL STATUS mb86960MCastAddrAdd (MB86960_END_CTRL * pDrvCtrl, 
  248.      char* pAddress);
  249. LOCAL STATUS mb86960MCastAddrDel (MB86960_END_CTRL * pDrvCtrl, 
  250.      char* pAddress);
  251. LOCAL STATUS mb86960MCastAddrGet (MB86960_END_CTRL * pDrvCtrl, 
  252.      MULTI_TABLE* pTable);
  253. LOCAL STATUS mb86960PollSend (MB86960_END_CTRL * pDrvCtrl, M_BLK_ID pBuf);
  254. LOCAL STATUS mb86960PollRcv  (MB86960_END_CTRL * pDrvCtrl, M_BLK_ID pBuf);
  255. LOCAL STATUS mb86960PollStart (MB86960_END_CTRL * pDrvCtrl);
  256. LOCAL STATUS mb86960PollStop (MB86960_END_CTRL * pDrvCtrl);
  257. LOCAL STATUS mb86960InitParse (MB86960_END_CTRL *, char *);
  258. LOCAL STATUS mb86960MemInit ();
  259. LOCAL int  mb86960HashIndex (char * pEnAddr);
  260. LOCAL STATUS    mb86960HdrShow (struct ether_header * pHdr, char * msg);
  261. /*
  262.  * Declare our function table.  This is static across all driver
  263.  * instances.
  264.  */
  265. LOCAL NET_FUNCS mb86960FuncTable =
  266.     {
  267.     (FUNCPTR) mb86960Start, /* Function to start the device. */
  268.     (FUNCPTR) mb86960Stop, /* Function to stop the device. */
  269.     (FUNCPTR) mb86960Unload, /* Unloading function for the driver. */
  270.     (FUNCPTR) mb86960Ioctl, /* Ioctl function for the driver. */
  271.     (FUNCPTR) mb86960Send, /* Send function for the driver. */
  272.     (FUNCPTR) mb86960MCastAddrAdd, /* Multicast address add func. */
  273.     (FUNCPTR) mb86960MCastAddrDel, /* Multicast address delete func. */
  274.     (FUNCPTR) mb86960MCastAddrGet, /* Multicast table retrieve func. */
  275.     (FUNCPTR) mb86960PollSend, /* Polling send function. */
  276.     (FUNCPTR) mb86960PollRcv, /* Polling receive function. */
  277.     endEtherAddressForm,        /* Put address info into a packet. */
  278.     endEtherPacketDataGet,      /* Get a pointer to packet data. */
  279.     endEtherPacketAddrGet       /* Get packet addresses. */
  280.     };
  281. int overFlowCnt; 
  282. int dropCnt; 
  283. /*******************************************************************************
  284. *
  285. * mb86960EndLoad - initialize the driver and device
  286. *
  287. * This routine initializes the driver and puts the device to an operational 
  288. * state.
  289. * All of the device specific parameters are passed in via the initString, which
  290. * expects a string of the following format:
  291. *
  292. * <unit>:<base_addr>:<int_vector>:<int_level>
  293. *
  294. * This routine can be called in two modes. If it is called with an empty but
  295. * allocated string, it places the name of this device (that is, "fn") into
  296. * the <initString> and returns 0.
  297. *
  298. * If the string is allocated and not empty, the routine attempts to load
  299. * the driver using the values specified in the string.
  300. *
  301. * RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
  302. * device if the <initString> was NULL.
  303. *
  304. */
  305. END_OBJ * mb86960EndLoad
  306.     (
  307.     char * pInitString /* String to be parsed by the driver. */
  308.     )
  309.     {
  310.     MB86960_END_CTRL * pDrvCtrl;
  311.     STATUS retCode;
  312.     
  313.     DRV_LOG (DRV_DEBUG_LOAD, "Loading nice...n", 1, 2, 3, 4, 5, 6);
  314.     if (pInitString == NULL)
  315.         return (NULL);
  316.     if (pInitString[0] == EOS)
  317.         {
  318.         bcopy((char *)FN_DEV_NAME, pInitString, FN_DEV_NAME_LEN);
  319.         return (0);
  320.         }
  321.     
  322.     /* allocate the device structure */
  323.     pDrvCtrl = (MB86960_END_CTRL *) calloc (sizeof(MB86960_END_CTRL), 1);
  324.     if (pDrvCtrl == NULL)
  325. goto errorExit;
  326.     /* parse the init string, filling in the device structure */
  327.     if (mb86960InitParse (pDrvCtrl, pInitString) == ERROR)
  328. goto errorExit;
  329.     /* Ask the BSP to provide the ethernet address. */
  330.     SYS_ENET_ADDR_GET(pDrvCtrl, &retCode);
  331.     if (retCode == ERROR)
  332. goto errorExit;
  333.     /* 
  334.      * initialize the END and MIB2 parts of the structure
  335.      * The M2 element must come from m2Lib.h 
  336.      * This template is set up for a DIX type ethernet device.
  337.      */
  338.     if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, FN_DEV_NAME,
  339.                pDrvCtrl->unit, &mb86960FuncTable,
  340.       "Fujitsu MB86960 Ethernet Enhanced Network Driver") 
  341.       == ERROR || 
  342.       END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
  343.   &pDrvCtrl->enetAddr[0], ENET_ADDR_LEN, ETHERMTU,
  344.   MB86960_SPEED) == ERROR)
  345.         goto errorExit;
  346.     /* Perform memory allocation/distribution */
  347.     if (mb86960MemInit (pDrvCtrl) == ERROR)
  348.         goto errorExit;
  349.     /* (re)initialize and configure the device */
  350.     mb86960Reset (pDrvCtrl);
  351.     mb86960Config (pDrvCtrl);
  352.     /* set the flags to indicate readiness */
  353.     END_OBJ_READY (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS
  354.     | IFF_BROADCAST | IFF_MULTICAST));
  355.     DRV_LOG (DRV_DEBUG_LOAD, "Done loading end...n", 1, 2, 3, 4, 5, 6);
  356.     return (&pDrvCtrl->end);
  357. errorExit:
  358.     mb86960Unload (pDrvCtrl);
  359.     return (NULL);
  360.     }
  361. /*******************************************************************************
  362. *
  363. * mb86960InitParse - parse the initialization string
  364. *
  365. * This routine parses the input string, filling in values in the
  366. * driver control structure.
  367. *
  368. * The initialization string format is:   <unit>:<baseAddr>:<ivec>
  369. * .IP <unit>
  370. * Device unit number, a small integer.  Must always be 0.
  371. * .IP <devBaseAddr>
  372. * Base address of the device register set.
  373. * .IP <ivec>
  374. * Interrupt vector number, used with sysIntConnect().
  375. *
  376. * RETURNS: OK or ERROR for invalid arguments.
  377. */
  378. STATUS mb86960InitParse
  379.     (
  380.     MB86960_END_CTRL * pDrvCtrl, /* device pointer */
  381.     char * pInitString /* information string */
  382.     )
  383.     {
  384.     char * tok;
  385.     char *      pHolder = NULL; 
  386.     
  387.     /* Parse the initString */
  388.     /* Unit number. */
  389.     tok = strtok_r (pInitString, ":", &pHolder);
  390.     if (tok == NULL) 
  391. return ERROR;
  392.     if ((pDrvCtrl->unit = atoi (tok)) != 0) 
  393. return ERROR;
  394.     /* Device Base Address. */
  395.     tok = strtok_r (NULL, ":", &pHolder);
  396.     if (tok == NULL) 
  397. return ERROR;
  398.     pDrvCtrl->devBaseAddr = (char *)strtoul (tok, NULL, 16);
  399.     /* Interrupt vector. */
  400.     
  401.     tok = strtok_r (NULL, ":", &pHolder);
  402.     if (tok == NULL) 
  403. return ERROR;
  404.     pDrvCtrl->vector = atoi (tok);
  405.     DRV_LOG (DRV_DEBUG_LOAD, "Processed all arugmentsn", 1, 2, 3, 4, 5, 6);
  406.     DRV_LOG (DRV_DEBUG_LOAD, "Address %p ivec %dn",
  407.        (int ) pDrvCtrl->devBaseAddr, (int ) pDrvCtrl->vector, 
  408.        3, 4, 5, 6);
  409.     return OK;
  410.     }
  411. /*******************************************************************************
  412. *
  413. * mb86960MemInit - initialize memory for the chip
  414. *
  415. * This routine is highly specific to the device.  
  416. *
  417. * RETURNS: OK or ERROR.
  418. */
  419. STATUS mb86960MemInit
  420.     (
  421.     MB86960_END_CTRL * pDrvCtrl /* device to be initialized */
  422.     )
  423.     {
  424.     /*
  425.      * This is how we would set up and END netPool using netBufLib(1).
  426.      * This code is pretty generic.
  427.      */
  428.     
  429.     if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
  430.         return (ERROR);
  431.     fnMclBlkCfg.mBlkNum = MB86960_BUFS; 
  432.     fnClDescTbl[0].clNum = MB86960_BUFS;
  433.     fnMclBlkCfg.clBlkNum = fnClDescTbl[0].clNum;
  434.     /* Calculate the total memory for all the M-Blks and CL-Blks. */
  435.     fnMclBlkCfg.memSize = (fnMclBlkCfg.mBlkNum * (MSIZE + sizeof (long))) +
  436.                           (fnMclBlkCfg.clBlkNum * (CL_BLK_SZ + sizeof(long)));
  437.     if ((fnMclBlkCfg.memArea = (char *) memalign (sizeof(long),
  438.                                                   fnMclBlkCfg.memSize))
  439.         == NULL)
  440.         return (ERROR);
  441.     /* Calculate the memory size of all the clusters. */
  442.     fnClDescTbl[0].memSize = (fnClDescTbl[0].clNum * (MB86960_BUFSIZ + 8))
  443.         + sizeof(int);
  444.     /* Allocate the memory for the clusters from cache safe memory. */
  445.     fnClDescTbl[0].memArea =
  446.         (char *) memalign (sizeof(long), fnClDescTbl[0].memSize);
  447.     if (fnClDescTbl[0].memArea == NULL)
  448.         {
  449.         DRV_LOG(DRV_DEBUG_LOAD,
  450.                 "system memory unavailablen", 1, 2, 3, 4, 5, 6);
  451.         return (ERROR);
  452.         }
  453.     
  454.     /* Initialize the memory pool. */
  455.     if (netPoolInit(pDrvCtrl->end.pNetPool, &fnMclBlkCfg,
  456.                     &fnClDescTbl[0], fnClDescTblNumEnt, NULL) == ERROR)
  457.         {
  458.         DRV_LOG (DRV_DEBUG_LOAD, "Could not init bufferingn",
  459.                  1, 2, 3, 4, 5, 6);
  460.         return (ERROR);
  461.         }
  462. #ifdef DRV_DEBUG
  463.     mb86960NetPool = *pDrvCtrl->end.pNetPool;
  464. #endif
  465.     /* Store the cluster pool id as others need it later. */
  466.     
  467.     pDrvCtrl->pClPoolId = clPoolIdGet (pDrvCtrl->end.pNetPool, 
  468.       sizeof(struct rx_frame), FALSE);
  469.     DRV_LOG (DRV_DEBUG_LOAD, "Memory setup completen", 1, 2, 3, 4, 5, 6);
  470.     return OK;
  471.     }
  472. /*******************************************************************************
  473. *
  474. * mb86960Start - start the device
  475. *
  476. * This function calls BSP functions to connect interrupts and start the
  477. * device running in interrupt mode.
  478. *
  479. * RETURNS: OK or ERROR if ISR is not connected.
  480. *
  481. */
  482. LOCAL STATUS mb86960Start
  483.     (
  484.     MB86960_END_CTRL * pDrvCtrl /* device to be started */
  485.     )
  486.     {
  487.     STATUS result;
  488.     SYS_INT_CONNECT (pDrvCtrl, mb86960Int, (int)pDrvCtrl, &result);
  489.     if (result == ERROR) 
  490. return ERROR;
  491.     DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.n", 1, 2, 3, 4, 5, 6);
  492.     
  493.     /* Enable specific interrupts. */
  494.     SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NORM_INTRMASK);
  495.     
  496.     /* mark the interface -- up */
  497.     
  498.     END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
  499.     SYS_INT_ENABLE (pDrvCtrl);
  500.     DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.n", 1, 2, 3, 4, 5, 6);
  501.     return (OK);
  502.     }
  503. /*******************************************************************************
  504. *
  505. * mb86960Int - handle controller interrupt
  506. *
  507. * This routine is called at interrupt level in response to an interrupt from
  508. * the controller.
  509. *
  510. * RETURNS: N/A.
  511. */
  512. LOCAL void mb86960Int
  513.     (
  514.     MB86960_END_CTRL  * pDrvCtrl  /* interrupting device */
  515.     )
  516.     {
  517.     char * pDev; /* ptr to the device regs */
  518.     u_short event;
  519.     u_short reg;
  520.     pDev    = pDrvCtrl->devBaseAddr;    
  521.     
  522.     SYS_IN_SHORT((pDev + NICE_STATUS), event);
  523.     SYS_IN_SHORT((pDev + NICE_INTRMASK), reg);
  524.     
  525.     DRV_LOG (DRV_DEBUG_INT, "i=0x%x:n", event, 2, 3, 4, 5, 6);
  526.     /* Handle receiver overflow event. */
  527.     if (event & DLCR1_OVR_FLO)
  528. {
  529. overFlowCnt++;  /* bump the counter */
  530.   SYS_OUT_SHORT ((pDev + NICE_STATUS), DLCR1_OVR_FLO);
  531.   return; 
  532.     /* Handle the receiver event, only if it was enabled. */
  533.     if ((reg & DLCR3_RX_PKT) && (event & DLCR1_RX_PKT))
  534.         {
  535.         SYS_OUT_SHORT ((pDev + NICE_INTRMASK), NO_RX_INTRMASK);  /* disable */
  536.         netJobAdd ((FUNCPTR)mb86960HandleRcvInt, (int)pDrvCtrl, 0,0,0,0);
  537.         }
  538.     /* ACK the interrupts */
  539.     SYS_OUT_SHORT ((pDev + NICE_STATUS), event);
  540.     }
  541. /*******************************************************************************
  542. *
  543. * mb86960HandleRcvInt - task level interrupt service for input packets
  544. *
  545. * This routine is called at task level indirectly by the interrupt
  546. * service routine to do any message received processing.
  547. *
  548. * RETURNS: N/A.
  549. */
  550. LOCAL void mb86960HandleRcvInt
  551.     (
  552.     MB86960_END_CTRL * pDrvCtrl /* interrupting device */
  553.     )
  554.     {
  555.     char * pDev = pDrvCtrl->devBaseAddr;
  556.     MB86960_RX_FRAME * pCluster;
  557.     MB86960_RX_FRAME  temp;
  558.     STATUS retCode;
  559.     pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;
  560.     while (mb86960RxMore (pDrvCtrl))
  561.         {
  562.         /*
  563.          * We implicitly are loaning here, if copying is necessary this
  564.          * step may be skipped, but the data must be copied before being
  565.          * passed up to the protocols.
  566.          */
  567.     
  568.         pCluster = (MB86960_RX_FRAME *) netClusterGet(pDrvCtrl->end.pNetPool, 
  569. pDrvCtrl->pClPoolId);
  570.         if (pCluster == NULL)
  571.             {
  572.     dropCnt++;
  573.     DRV_LOG (DRV_DEBUG_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
  574.     mb86960PacketGet (pDrvCtrl, &temp);
  575.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  576.             }
  577.         else
  578.     {
  579.     retCode = mb86960PacketGet (pDrvCtrl, pCluster);
  580.     if (retCode != ERROR)
  581. {
  582.                 (void) mb86960Recv (pDrvCtrl, pCluster);
  583. }
  584.     else
  585. {
  586. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  587. break;
  588. }
  589.             }
  590.         }
  591.     pDrvCtrl->flags &= ~LS_RCV_HANDLING_FLAG;
  592.     
  593.     /* Turn the receive interrupts on again. */
  594.     SYS_OUT_SHORT ((pDev + NICE_INTRMASK), NORM_INTRMASK);
  595.     }
  596. /*******************************************************************************
  597. *
  598. * mb86960RxMore - indicates more packets in the buffer
  599. *
  600. * This routine indicates that there are more packets left in the buffer
  601. *
  602. * RETURNS: TRUE or FALSE
  603. */
  604. LOCAL BOOL mb86960RxMore 
  605.     (
  606.     MB86960_END_CTRL * pDrvCtrl /* interrupting device */
  607.     )
  608.     {
  609.     u_short  mode;
  610.     char * pDev; /* ptr to the device regs */
  611.     pDev = pDrvCtrl->devBaseAddr; /* get ptr to device */
  612.     SYS_IN_SHORT ((pDev + NICE_MODE), mode);
  613.     if (mode & DLCR5_BUF_EMPTY)
  614.         return (FALSE);
  615.     else
  616.         return (TRUE);
  617.     } 
  618. /*******************************************************************************
  619. *
  620. * mb86960PacketGet - get next received message
  621. *
  622. * Get next received message.  Returns NULL if none are ready.
  623. *
  624. * RETURNS: OK or ERROR.
  625. */
  626. LOCAL STATUS mb86960PacketGet
  627.     (
  628.     MB86960_END_CTRL  * pDrvCtrl, /* device structure */
  629.     MB86960_RX_FRAME *  pRxFrame /* pointer to an rx frame struct */
  630.     )
  631.     {
  632.     int loopy; /* loop counter */
  633.     char * pDev; /* ptr to the device regs */
  634.     u_short * pDest; /* ptr to destination */
  635.     pDev = pDrvCtrl->devBaseAddr;            /* get ptr to device */
  636.     /* Fill our local copy of the Rx header from the device's buffer. */
  637.     SYS_IN_SHORT((pDev + NICE_PORT), pRxFrame->rxHdr.status);
  638.     SYS_IN_SHORT((pDev + NICE_PORT), pRxFrame->rxHdr.len);
  639.     
  640.     /* swap bytes if needed */
  641.     pRxFrame->rxHdr.len = MB86960_SWAP_SHORT(pRxFrame->rxHdr.len);
  642.     /* Clear the status bit for packet ready. */
  643.     SYS_OUT_SHORT ((pDev + NICE_STATUS), DLCR1_RX_PKT);
  644.     /* Sanity check the packet info. */
  645.     if  ((!(pRxFrame->rxHdr.status & RX_HDR_STAT_GOOD))  ||
  646.          (pRxFrame->rxHdr.len < ETHERSMALL) || 
  647.  (pRxFrame->rxHdr.len > (ETHERMTU + SIZEOF_ETHERHEADER)))
  648.         {
  649.        /*  END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));   */
  650.         return (ERROR);
  651.         }
  652.     
  653.     /* Fill our frame buffer from the device's buffer. */
  654.     pDest = (u_short *) &pRxFrame->enetHdr;     /* stuff ptr */
  655.     for (loopy = pRxFrame->rxHdr.len; loopy > 0; loopy -= sizeof (u_short))
  656. {
  657.         SYS_IN_SHORT((pDev + NICE_PORT), *pDest++);
  658.         }
  659.     return (OK);
  660.     }
  661. /*******************************************************************************
  662. *
  663. * mb86960Recv - process the next incoming packet
  664. *
  665. * Handle one incoming packet.  The packet is checked for errors.
  666. *
  667. * RETURNS: OK  
  668. */
  669. LOCAL STATUS mb86960Recv
  670.     (
  671.     MB86960_END_CTRL * pDrvCtrl, /* device structure */
  672.     MB86960_RX_FRAME * pCluster /* pointer to header structure */
  673.     )
  674.     {
  675.     int         len;
  676.     M_BLK_ID  pMblk;
  677.     CL_BLK_ID pClBlk;
  678.     
  679.     len = pCluster->rxHdr.len;       /* obtain data length */
  680.     /* Grab a cluster block to marry to the cluster we received. */
  681.     if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL)
  682.         {
  683.         netClFree (pDrvCtrl->end.pNetPool, (UINT8 *) pCluster);
  684. DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!n", 1, 2, 3, 4, 5, 6);
  685. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  686. goto cleanRXD;
  687.         }
  688.     
  689.     /*
  690.      * OK we've got a spare, let's get an M_BLK_ID and marry it to the
  691.      * one in the ring.
  692.      */
  693.     if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL)
  694.         {
  695.         netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); 
  696.         netClFree (pDrvCtrl->end.pNetPool, (UINT8 *) pCluster);
  697. DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!n", 1, 2, 3, 4, 5, 6);
  698. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  699. goto cleanRXD;
  700.         }
  701.     
  702.     /* Add one to our unicast data. */
  703.     END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  704.     /* Join the cluster to the MBlock */
  705.     netClBlkJoin (pClBlk, (char *) pCluster, len, NULL, 0, 0, 0);
  706.     netMblkClJoin (pMblk, pClBlk);
  707.     pMblk->mBlkHdr.mData =  (char *)MB86960_FRAME_DATA_ADDR_GET(pCluster);
  708.     pMblk->mBlkHdr.mLen  = len;
  709.     pMblk->mBlkHdr.mFlags |= M_PKTHDR;
  710.     pMblk->mBlkPktHdr.len = len;
  711.     DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!n", 1, 2, 3, 4, 5, 6);
  712.     /* Call the upper layer's receive routine. */
  713.     END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);
  714. cleanRXD:
  715.     return (OK);
  716.     }
  717. /*******************************************************************************
  718. *
  719. * mb86960Send - the driver send routine
  720. *
  721. * This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
  722. * The buffer must already have the addressing information properly installed
  723. * in it.  This is done by a higher layer.  The last arguments are a free
  724. * routine to be called when the device is done with the buffer and a pointer
  725. * to the argument to pass to the free routine.  
  726. *
  727. * RETURNS: OK or ERROR.
  728. */
  729. LOCAL STATUS mb86960Send
  730.     (
  731.     MB86960_END_CTRL * pDrvCtrl, /* device ptr */
  732.     M_BLK_ID  pMblk /* data to send */
  733.     )
  734.     {
  735.     int   oldLevel = 0;
  736.     STATUS  status;
  737.     DRV_LOG(DRV_DEBUG_TX, "Begin mb86960Send pDrvCtrl %p pMblk %pn", 
  738.     (int ) pDrvCtrl, (int ) pMblk, 0, 0, 0, 0);
  739.     if ((END_FLAGS_GET(&pDrvCtrl->end) & (IFF_UP | IFF_RUNNING)) !=
  740.         (IFF_UP | IFF_RUNNING))
  741.         {
  742.         DRV_LOG(DRV_DEBUG_TX, "Device is NOT UP and RUNNINGn", 0, 0,
  743.                 0, 0, 0, 0);
  744. if (!(pDrvCtrl->flags & LS_POLLING))
  745.     netMblkClChainFree (pMblk); /* free the given mBlk chain */
  746.         errno = EINVAL;
  747.         return (ERROR);
  748.         }
  749.     /*
  750.      * Obtain exclusive access to transmitter.  This is necessary because
  751.      * we might have more than one stack transmitting at once.
  752.      */
  753.     if (!(pDrvCtrl->flags & LS_POLLING))
  754. semTake (pDrvCtrl->txSem, WAIT_FOREVER);
  755.     /* place a transmit request */
  756.     if (!(pDrvCtrl->flags & LS_POLLING))
  757.         oldLevel = intLock ();   /* now mb86960Int won't get confused */
  758.     
  759.       /* send packet out over interface */
  760.     if ((status = mb89680Transmit (pDrvCtrl, pMblk)) == ERROR)
  761.         {
  762.         DRV_LOG(DRV_DEBUG_TX, "FAILED mb89680Transmitn", 1, 2, 3, 4, 5, 6);
  763.         /* update statistics */
  764.         END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_ERRS, +1);
  765.         if (!(pDrvCtrl->flags & LS_POLLING))
  766.     {
  767.             intUnlock (oldLevel);   /* now mb86960Int won't get confused */
  768.     semGive (pDrvCtrl->txSem);
  769.             netMblkClChainFree (pMblk);
  770.     }
  771.         
  772. return (ERROR);
  773.         }
  774.     
  775.     if (!(pDrvCtrl->flags & LS_POLLING))
  776.         intUnlock (oldLevel);   /* now mb86960Int won't get confused */
  777.     
  778.     /* Advance our management index */
  779.     if (!(pDrvCtrl->flags & LS_POLLING))
  780. semGive (pDrvCtrl->txSem);
  781.     
  782.     /* Bump the statistic counter. */
  783.     END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
  784.     /*
  785.      * Cleanup.  The driver must either free the packet now or
  786.      * set up a structure so it can be freed later after a transmit
  787.      * interrupt occurs.
  788.      */
  789.     if (!(pDrvCtrl->flags & LS_POLLING))
  790. netMblkClChainFree (pMblk);
  791.     return (OK);
  792.     }
  793. /*******************************************************************************
  794. *
  795. * mb89680Transmit - kick start the transmitter after generic ether_output
  796. *
  797. * This routine is responsible for tranmitting packets over physical media.
  798. * The data to be sent out is held in a chain of mbufs. The data in each mbuf 
  799. * fragment must be copied to the device's packet buffer.
  800. *
  801. * RETURNS: OK, or ERROR
  802. */
  803. LOCAL STATUS mb89680Transmit
  804.     (
  805.     MB86960_END_CTRL * pDrvCtrl, /* pointer to driver control struct */
  806.     M_BLK_ID pMblk /* pointer to am Mblk */
  807.     )
  808.     {
  809.     int pktLen; /* total length of packet */
  810.     int dataLen; /* real length of data portion */
  811.     int loopy; /* loop counter */
  812.     char * nicePort; /* ptr to the nice buffer port */
  813.     u_short * pSource; /* ptr to source of data byte */
  814.     u_short     temp;
  815.     static char privateBuf [ETHERMTU];
  816.     /* get ptr to the buffer port */
  817.     nicePort = pDrvCtrl->devBaseAddr + NICE_PORT;
  818.     /*
  819.      * This driver maintains transmit resources internally. The 
  820.      * CPU cannot retrieve or examine them.
  821.      */
  822.      
  823.     dataLen = netMblkToBufCopy (pMblk, privateBuf, NULL);
  824.     /* Ensure we send a legal size frame. */
  825.     pktLen = max (ETHERSMALL, dataLen);
  826.     /* taking care of short packets, pad with 0s */
  827.     if (dataLen < ETHERSMALL)
  828.         for (loopy = dataLen; loopy < pktLen; loopy++)
  829.             privateBuf [loopy] = 0;
  830.     /* Tell the device the length; in little endian order */
  831.     
  832.     SYS_OUT_SHORT  (nicePort, MB86960_SWAP_SHORT(pktLen));
  833.     pSource = (u_short *)privateBuf;
  834.     for (loopy = pktLen; loopy > 0 ; loopy -= sizeof (u_short))
  835.         {
  836.         SYS_OUT_SHORT (nicePort, *pSource);
  837.         pSource++; 
  838.         }
  839.     if (pktLen % sizeof (u_short)) /* packet size is odd */
  840.         {
  841.         unsigned short lastByte;
  842.         lastByte = 0;
  843.         ( (char *) (&lastByte))[0] = ((char *) (pSource))[0];
  844.         SYS_OUT_SHORT (nicePort, lastByte);
  845.         }
  846.     /* See if transmitter is free and start it orelse  wait.  */
  847.     FOREVER 
  848.         {
  849.         SYS_IN_SHORT((pDrvCtrl->devBaseAddr + NICE_TRANSMIT), temp);
  850. if ((temp & (0x7f << 8)) == 0)
  851.     break;
  852.         }
  853.     SYS_OUT_SHORT((pDrvCtrl->devBaseAddr + NICE_TRANSMIT), KICK_TRANSMIT);
  854.     return (OK);
  855.     }
  856. /*******************************************************************************
  857. *
  858. * mb86960Ioctl - the driver I/O control routine
  859. *
  860. * Process an ioctl request.
  861. *
  862. * RETURNS: A command specific response, usually OK or ERROR.
  863. */
  864. LOCAL int mb86960Ioctl
  865.     (
  866.     MB86960_END_CTRL * pDrvCtrl, /* device receiving command */
  867.     int cmd, /* ioctl command code */
  868.     caddr_t data /* command argument */
  869.     )
  870.     {
  871.     int error = 0;
  872.     long value;
  873.     switch ((UINT)cmd)
  874.         {
  875.         case EIOCSADDR:
  876.     if (data == NULL)
  877. return (EINVAL);
  878.             bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
  879.    END_HADDR_LEN(&pDrvCtrl->end));
  880.             break;
  881.         case EIOCGADDR:
  882.     if (data == NULL)
  883. return (EINVAL);
  884.             bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
  885.     END_HADDR_LEN(&pDrvCtrl->end));
  886.             break;
  887.         case EIOCSFLAGS:
  888.     value = (long)data;
  889.     if (value < 0)
  890. {
  891. value = -value;
  892. value--;
  893. END_FLAGS_CLR (&pDrvCtrl->end, value);
  894. }
  895.     else
  896. {
  897. END_FLAGS_SET (&pDrvCtrl->end, value);
  898. }
  899.     mb86960Config (pDrvCtrl);
  900.             break;
  901.         case EIOCGFLAGS:
  902.     *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
  903.             break;
  904. case EIOCPOLLSTART:
  905.     mb86960PollStart (pDrvCtrl);
  906.     break;
  907. case EIOCPOLLSTOP:
  908.     mb86960PollStop (pDrvCtrl);
  909.     break;
  910.         case EIOCMULTIADD:               
  911.             error = mb86960MCastAddrAdd (pDrvCtrl, (char *)data);
  912.             break;
  913.         case EIOCMULTIDEL:              
  914.             error = mb86960MCastAddrDel (pDrvCtrl, (char *)data);
  915.             break;
  916.         case EIOCMULTIGET:            
  917.             error = mb86960MCastAddrGet (pDrvCtrl, (MULTI_TABLE *)data);
  918.             break;
  919.         case EIOCGMIB2:
  920.             if (data == NULL)
  921.                 return (EINVAL);
  922.             bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
  923.                   sizeof(pDrvCtrl->end.mib2Tbl));
  924.             break;
  925. #if 0
  926.         case EIOCGFBUF:
  927.             if (data == NULL)
  928.                 return (EINVAL);
  929.             *(int *)data = END_MIN_FBUF;
  930.             break;
  931. #endif
  932.         default:
  933.             error = EINVAL;
  934.         }
  935.     return (error);
  936.     }
  937. /******************************************************************************
  938. *
  939. * mb86960Reset - reset state initialization for the device
  940. *
  941. * This routine initializes the MB86960 device after a reset / reboot. 
  942. * of addresses (added with the endAddrAdd() routine) and sets the
  943. * device's filter correctly.
  944. *
  945. * RETURNS: N/A.
  946. */
  947. LOCAL void mb86960Reset
  948.     (
  949.     MB86960_END_CTRL *pDrvCtrl /* device to be re-configured */
  950.     )
  951.     {
  952.     /* Set promiscuous mode if it's asked for. */
  953. #if 0
  954.     if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
  955. {
  956. DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!n", 
  957.  1, 2, 3, 4, 5, 6);
  958. }
  959.     else
  960. {
  961. DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!n", 
  962.  1, 2, 3, 4, 5, 6);
  963. }
  964.     /* Set up address filter for multicasting. */
  965.     if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0)
  966. {
  967. mb86960AddrFilterSet (pDrvCtrl);
  968. }
  969. #endif
  970.     /* shutdown device completely */
  971.     SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), 0);
  972.     SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_STATUS), 0xffff);
  973.     return;
  974.     }
  975. /******************************************************************************
  976. *
  977. * mb86960Config - reconfigure the interface under us.
  978. *
  979. * Reconfigure the interface setting promiscuous mode, and changing the
  980. * multicast interface list.
  981. *
  982. * RETURNS: N/A.
  983. */
  984. LOCAL void mb86960Config
  985.     (
  986.     MB86960_END_CTRL * pDrvCtrl
  987.     )
  988.     {
  989.     u_short temp;          /* scratch pad */
  990.     char * pDev = pDrvCtrl->devBaseAddr;
  991.     /* initial setup of config register 1 */
  992.     temp = (DLCR6_DISABLE_DLC   |        /* resets things */
  993.     DLCR6_BIT_6         |        /* just do it */
  994.     DLCR6_SYS_BUS_16    |        /* use 16 bits */
  995.     DLCR6_BUF_BUS_16    |        /* use 16 bits */
  996.     DLCR6_TBS_4KB       |        /* Tx buf is 4kb */
  997.     DLCR6_BS_16KB       |        /* total buf is 16k */
  998.     DLCR7_CNF_NICE      |        /* normal NICE mode */
  999.     DLCR7_PWRDN_OFF     |        /* normal power mode */
  1000.     DLCR7_BIT_4         |        /* just do it */
  1001.     DLCR7_REG_BNK_DLC   |         /* map node ID regs */
  1002.             DLCR7_ENDIAN_LITTLE
  1003.    );
  1004.     
  1005.     SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
  1006.     /* Mask off all interrupts and clear all event flags. */
  1007.     SYS_OUT_SHORT ((pDev + NICE_INTRMASK), 0);
  1008.     SYS_OUT_SHORT ((pDev + NICE_STATUS), 0xffff);
  1009.     /* Disable device interrupt at system level and clear any pended. */
  1010.     SYS_INT_DISABLE (pDrvCtrl);
  1011.     /* The secondary DLC register group is mapped in.  Set the node ID. */
  1012.     SYS_OUT_SHORT ((pDev + NICE_ADDR1), (((u_short *) pDrvCtrl->enetAddr)[0])); 
  1013.     SYS_OUT_SHORT ((pDev + NICE_ADDR2), (((u_short *) pDrvCtrl->enetAddr)[1]));
  1014.     SYS_OUT_SHORT ((pDev + NICE_ADDR3), (((u_short *) pDrvCtrl->enetAddr)[2]));
  1015.     /* Change register map. Select buffer memory register group. */
  1016.     SYS_IN_SHORT ((pDev + NICE_CONFIG), temp);
  1017.     temp &= ~DLCR7_REG_BNK; /* clear bank select bits */
  1018.     temp |= DLCR7_REG_BNK_HASH;         /* add desired bits */
  1019.     SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
  1020.     /* clear all bits in hash table array */
  1021.     SYS_OUT_SHORT ((pDev + NICE_HASH1), 0);
  1022.     SYS_OUT_SHORT ((pDev + NICE_HASH2), 0);
  1023.     SYS_OUT_SHORT ((pDev + NICE_HASH3), 0);
  1024.     SYS_OUT_SHORT ((pDev + NICE_HASH4), 0);
  1025.     temp &= ~DLCR7_REG_BNK; /* clear bank select bits */
  1026.     temp |= DLCR7_REG_BNK_BMR; /* add desired bits */
  1027.     SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
  1028.     /* 
  1029.      * Setup the receiver and transmitter modes. Note that in
  1030.      * order to enable multicast + hash table, the bit 
  1031.      * DLCR5_AF1 must be set. The documentation for the
  1032.      * MB86960 says otherwise but is not correct
  1033.      */
  1034.     SYS_OUT_SHORT ((pDev + NICE_MODE), (DLCR4_LBC | DLCR5_BIT_2 | DLCR5_AF1));
  1035.     /* Enable the DLC. */
  1036.     SYS_IN_SHORT ((pDev + NICE_CONFIG), temp);     /* get config reg */
  1037.     temp &= ~DLCR6_DISABLE_DLC;                 /* clear the disable bit */
  1038.     SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);      /* update config reg */
  1039.     /* set collision control drop packet after 16 collisions */
  1040.     SYS_OUT_SHORT ((pDev + NICE_TRANSMIT), (BMR11_MASK16 | BMR11_RST_TX16
  1041.        | BMR11_OPT_16_COLL));
  1042.     }
  1043. /*******************************************************************************
  1044. *
  1045. * mb86960PollRcv - routine to receive a packet in polled mode.
  1046. *
  1047. * This routine is called by a user to try and get a packet from the
  1048. * device.
  1049. *
  1050. * RETURNS: OK upon success.  EAGAIN is returned when no packet is available.
  1051. */
  1052. LOCAL STATUS mb86960PollRcv
  1053.     (
  1054.     MB86960_END_CTRL * pDrvCtrl, /* device to be polled */
  1055.     M_BLK_ID pMblk /* ptr to buffer */
  1056.     )
  1057.     {
  1058.     STATUS retCode = OK;
  1059.     MB86960_RX_FRAME *  pCluster;
  1060.     int len;
  1061.     if (mb86960RxMore (pDrvCtrl) == FALSE)
  1062. return (EAGAIN);
  1063.     
  1064.     pCluster = (MB86960_RX_FRAME *) netClusterGet (pDrvCtrl->end.pNetPool, 
  1065.    pDrvCtrl->pClPoolId);
  1066.     if (pCluster == NULL)
  1067.         {
  1068.         DRV_LOG (DRV_DEBUG_POLL_RX, "Cannot loan!n", 1, 2, 3, 4, 5, 6);
  1069. END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);
  1070. return (EAGAIN); 
  1071.         }
  1072.     
  1073.     retCode = mb86960PacketGet (pDrvCtrl, pCluster);
  1074.     if (retCode == OK)
  1075. {
  1076.         len = pCluster->rxHdr.len;
  1077.         pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */
  1078.         pMblk->mBlkHdr.mLen = len;    /* set the data len */
  1079.         pMblk->mBlkPktHdr.len = len;    /* set the total len */
  1080.         bcopy ((char *)(char *)  &pCluster->enetHdr, 
  1081.        (char *)pMblk->mBlkHdr.mData, len);
  1082.         netClFree (pDrvCtrl->end.pNetPool, (UINT8 *)pCluster);
  1083.         END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
  1084.         }        
  1085.     else
  1086. retCode = EAGAIN;
  1087.     
  1088.     DRV_LOG (DRV_DEBUG_POLL_RX, "Received packetn", 1, 2, 3, 4, 5, 6);
  1089.     return (retCode);
  1090.     }
  1091. /*******************************************************************************
  1092. *
  1093. * mb86960PollSend - routine to send a packet in polled mode.
  1094. *
  1095. * This routine is called by a user to try and send a packet on the
  1096. * device.
  1097. *
  1098. * RETURNS: OK upon success.  EAGAIN if device is busy.
  1099. */
  1100. LOCAL STATUS mb86960PollSend
  1101.     (
  1102.     MB86960_END_CTRL* pDrvCtrl, /* device to be polled */
  1103.     M_BLK_ID pMblk /* packet to send */
  1104.     )
  1105.     {
  1106.     return (mb86960Send (pDrvCtrl, pMblk));
  1107.     }
  1108. /*****************************************************************************
  1109. *
  1110. * mb86960MCastAddrAdd - add a multicast address for the device
  1111. *
  1112. * This routine adds a multicast address to whatever the driver
  1113. * is already listening for.  It then resets the address filter.
  1114. *
  1115. * RETURNS: OK or ERROR.
  1116. */
  1117. LOCAL STATUS mb86960MCastAddrAdd
  1118.     (
  1119.     MB86960_END_CTRL * pDrvCtrl, /* device pointer */
  1120.     char * pAddress /* new address to add */
  1121.     )
  1122.     {
  1123.     int error;
  1124.     if ((error = etherMultiAdd (&pDrvCtrl->end.multiList,
  1125. pAddress)) == ENETRESET)
  1126. mb86960AddrFilterSet (pDrvCtrl, pAddress, TRUE);
  1127.     return (OK);
  1128.     }
  1129. /*****************************************************************************
  1130. *
  1131. * mb86960MCastAddrDel - delete a multicast address for the device
  1132. *
  1133. * This routine removes a multicast address from whatever the driver
  1134. * is listening for.  It then resets the address filter.
  1135. *
  1136. * RETURNS: OK or ERROR.
  1137. */
  1138. LOCAL STATUS mb86960MCastAddrDel
  1139.     (
  1140.     MB86960_END_CTRL * pDrvCtrl, /* device pointer */
  1141.     char * pAddress /* address to be deleted */
  1142.     )
  1143.     {
  1144.     int error;
  1145.     if ((error = etherMultiDel (&pDrvCtrl->end.multiList,
  1146.      (char *)pAddress)) == ENETRESET)
  1147. mb86960AddrFilterSet (pDrvCtrl, pAddress, FALSE);
  1148.     return (OK);
  1149.     }
  1150. /*****************************************************************************
  1151. *
  1152. * mb86960MCastAddrGet - get the multicast address list for the device
  1153. *
  1154. * This routine gets the multicast list of whatever the driver
  1155. * is already listening for.
  1156. *
  1157. * RETURNS: OK or ERROR.
  1158. */
  1159. LOCAL STATUS mb86960MCastAddrGet
  1160.     (
  1161.     MB86960_END_CTRL* pDrvCtrl, /* device pointer */
  1162.     MULTI_TABLE* pTable /* address table to be filled in */
  1163.     )
  1164.     {
  1165.     return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
  1166.     }
  1167. /******************************************************************************
  1168. *
  1169. * mb86960AddrFilterSet - set the address filter for multicast addresses
  1170. *
  1171. * This routine goes through all of the multicast addresses on the list
  1172. * of addresses (added with the MCastAddrAdd() routine) and sets the
  1173. * device's filter correctly.
  1174. *
  1175. * NOMANUAL
  1176. */
  1177. LOCAL void mb86960AddrFilterSet
  1178.     (
  1179.     MB86960_END_CTRL* pDrvCtrl, /* device pointer */
  1180.     char * pAddr,
  1181.     BOOL bSet
  1182.     )
  1183.     {
  1184.     UINT16 nRegOffset;
  1185.     UINT16 nBitPosition;
  1186.     UINT16 nBitMask = 0x01;
  1187.     UINT16 index;
  1188.     char * pReg;
  1189.     UINT16 temp;
  1190.     char *      pDev = pDrvCtrl->devBaseAddr;
  1191.     UINT16 saveConfig;
  1192.     /* get hash index for the address */
  1193.     index = mb86960HashIndex (pAddr);
  1194.     nRegOffset = index;
  1195.     nBitPosition= index;
  1196.     /* Find register and bit position */
  1197.     nBitPosition = nBitPosition & 0x0f;  /* 4 LSB bits */
  1198.     nRegOffset >>= 4;
  1199.     nBitMask <<= nBitPosition;
  1200.     
  1201.     /* Change register map. Select hash memory register group. */
  1202.     SYS_IN_SHORT ((pDev + NICE_CONFIG), temp);
  1203.     saveConfig = temp;
  1204.     temp &= ~DLCR7_REG_BNK; /* clear bank select bits */
  1205.     temp |= DLCR7_REG_BNK_HASH;        /* select hash table regs */
  1206.     temp |= DLCR6_DISABLE_DLC;
  1207.     SYS_OUT_SHORT ((pDev + NICE_CONFIG), temp);
  1208.     pReg = pDrvCtrl->devBaseAddr + NICE_HASH1 + nRegOffset*4;
  1209.     /* set the bit in bit array */
  1210.     nBitMask = MB86960_SWAP_SHORT(nBitMask);
  1211.     SYS_IN_SHORT(pReg, temp);
  1212.     if (bSet == TRUE)
  1213.         {
  1214.         temp |= nBitMask; /* set */
  1215.         }
  1216.     else
  1217.         {
  1218.         nBitMask = ~nBitMask; /* reset */
  1219.         temp &= nBitMask;        
  1220.         }
  1221.     SYS_OUT_SHORT (pReg, temp);
  1222.     
  1223.     /* restore the configuration register */
  1224.     SYS_OUT_SHORT ((pDev + NICE_CONFIG), saveConfig);
  1225.     }
  1226. /*******************************************************************************
  1227. *
  1228. * mb86960HashIndex - compute the hash index for an ethernet address
  1229. *
  1230. * RETURNS: hash index for an ethernet address.
  1231. */
  1232. LOCAL int mb86960HashIndex
  1233.     (
  1234.     char * pCp  /* pointer to an ethernet address */
  1235.     )
  1236.     {
  1237.     char c;
  1238.     u_long crc;
  1239.     int len;
  1240.     int count;
  1241.     crc = 0xffffffff;
  1242.     for (len = 6; --len >= 0;)
  1243.         {
  1244.         c = *pCp++;
  1245.         for (count = 0; count < 8; count++)
  1246.     {
  1247.     if ((c & 0x01) ^ (crc & 0x01))
  1248.         {
  1249.         crc >>= 1;
  1250. crc = crc ^ MB86960_CRC_POLY;
  1251. }
  1252.     else
  1253.         {
  1254.         crc >>= 1;
  1255.         }
  1256. c >>= 1;
  1257.     }
  1258. }
  1259.     /* Just want the 6 most significant bits. */
  1260.     crc = crc >> 26;
  1261.     return (crc);
  1262.     }
  1263. /*******************************************************************************
  1264. *
  1265. * mb86960Stop - stop the device
  1266. *
  1267. * This function calls BSP functions to disconnect interrupts and stop
  1268. * the device from operating in interrupt mode.
  1269. *
  1270. * RETURNS: OK or ERROR.
  1271. */
  1272. LOCAL STATUS mb86960Stop
  1273.     (
  1274.     MB86960_END_CTRL * pDrvCtrl  /* device to be stopped */
  1275.     )
  1276.     {
  1277.     STATUS result = OK;
  1278.     /* stop/disable the device. */
  1279.     SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NO_RX_INTRMASK);
  1280.     SYS_INT_DISCONNECT (pDrvCtrl, mb86960Int, (int)pDrvCtrl, &result);
  1281.     
  1282.     if (result == ERROR)
  1283. {
  1284. DRV_LOG (DRV_DEBUG_LOAD, "Could not diconnect interrupt!n", 
  1285.  1, 2, 3, 4, 5, 6);
  1286. }
  1287.     else
  1288. {
  1289.         END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
  1290. }
  1291.     return (result);
  1292.     }
  1293. /******************************************************************************
  1294. *
  1295. * mb86960Unload - unload a driver from the system
  1296. *
  1297. * This function first brings down the device, and then frees any
  1298. * stuff that was allocated by the driver in the load function.
  1299. *
  1300. * RETURNS: OK or ERROR.
  1301. */
  1302. LOCAL STATUS mb86960Unload
  1303.     (
  1304.     MB86960_END_CTRL * pDrvCtrl /* device to be unloaded */
  1305.     )
  1306.     {
  1307.     END_OBJECT_UNLOAD (&pDrvCtrl->end);
  1308.     return (OK);
  1309.     }
  1310. /*******************************************************************************
  1311. *
  1312. * mb86960PollStart - start polled mode operations
  1313. *
  1314. * RETURNS: OK or ERROR.
  1315. */
  1316. LOCAL STATUS mb86960PollStart
  1317.     (
  1318.     MB86960_END_CTRL * pDrvCtrl /* device to be polled */
  1319.     )
  1320.     {
  1321.     int         oldLevel;
  1322.     
  1323.     oldLevel = intLock ();          /* disable ints during update */
  1324.     /* turn off interrupts */
  1325.     SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), 0);
  1326.     
  1327.     intUnlock (oldLevel);   /* now mb86960Int won't get confused */
  1328.     
  1329.     pDrvCtrl->flags |= LS_POLLING;
  1330.     DRV_LOG (DRV_DEBUG_POLL, "STARTEDn", 1, 2, 3, 4, 5, 6);
  1331.     return (OK);
  1332.     }
  1333. /*******************************************************************************
  1334. *
  1335. * mb86960PollStop - stop polled mode operations
  1336. *
  1337. * This function terminates polled mode operation.  The device returns to
  1338. * interrupt mode.
  1339. *
  1340. * The device interrupts are enabled, the current mode flag is switched
  1341. * to indicate interrupt mode and the device is then reconfigured for
  1342. * interrupt operation.
  1343. *
  1344. * RETURNS: OK or ERROR.
  1345. */
  1346. LOCAL STATUS mb86960PollStop
  1347.     (
  1348.     MB86960_END_CTRL * pDrvCtrl /* device to be changed */
  1349.     )
  1350.     {
  1351.     int         oldLevel;
  1352.     oldLevel = intLock (); /* disable ints during register updates */
  1353.     /* Turn the receive interrupts on again. */
  1354.     SYS_OUT_SHORT ((pDrvCtrl->devBaseAddr + NICE_INTRMASK), NORM_INTRMASK);
  1355.     intUnlock (oldLevel);
  1356.     pDrvCtrl->flags &= ~LS_POLLING;
  1357.     DRV_LOG (DRV_DEBUG_POLL, "STOPPEDn", 1, 2, 3, 4, 5, 6);
  1358.     return (OK);
  1359.     }