idt32438End.c
上传用户:yingyi0918
上传日期:2022-06-26
资源大小:214k
文件大小:28k
源码类别:

VxWorks

开发平台:

C/C++

  1. /*  idt32438End.c - Ethernet END Driver for IDT RC32438 */
  2. /* Copyright 1984-2002 Wind River Systems, 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. 02a,16Dec02,krao Modified driver for IDT 79pmc438 board.
  15. 01b,25jul02,slk  SPR 80131 and also general code clean up
  16. 01b,11jul02,pgh  Significant re-write and clean up.
  17. 01a,19Jun02,d_c  Code from IDT modified to approach C of E standards.
  18. */
  19. /*
  20. DESCRIPTION
  21. This module implements the IDT RC32438 enhanced network driver.  This device 
  22. is an integrated communications processor, so the ethernet interface is part 
  23. of the processor.  The ethernet interface provides a 10/100 Mbit ISO/IEC 8802-3:
  24. 1996 compliant interface.  An external Ethernet physical device (PHY) 
  25. connects to the Ethernet interface through an IEEE Std 802.3u-1995 Media 
  26. Independent Interface (MII).  This allows the Ethernet interface to be used 
  27. with a multitude of physical layers such as: 10BASE-T, 100BASE-TX, and 
  28. 100BASE-FX.
  29. During boot configuration the RC32438 may be configured to operate in either
  30. big endian mode or little endian mode.  Although ethernet packet data is
  31. packed into words in FIFO's, packet data is referenced in bytes by the CPU
  32. and Ethernet MAC. Data is always stored in big endian format within FIFO data
  33. words, with endianness conversion taking place as data is transfered between
  34. the IP bus and the FIFO's. Thus data stored in the FIFOs always appears to the
  35. programmer in the endianness selected during boot configuration.
  36. This driver is designed specifically for the RC32438 ethernet interface. It can
  37. operate on any of the boards containing a RC32438 processor under vxWorks.
  38. EXTERNAL INTERFACE
  39. The driver provides one standard external interface, idt32438EndLoad ().  As
  40. input, this function expects a string of colon-separated parameters.
  41. The format of the parameter string is:
  42.  <intVec>:<regBase>:<nTFDs>:<nRFDs>:<userFlags>
  43. TARGET-SPECIFIC PARAMETERS
  44. .IP <unit>
  45. The unit number for this device.
  46. .IP <intVec>
  47. Vector number for the ethernet overrun error condition.
  48. .IP <regBase>
  49. Base address of the rc32438 registers.
  50. .IP <numTDRs>
  51. The number of transmit descriptors to use.  This controls how much data
  52. the device can absorb under load.  If this is specified as NONE (-1) or
  53. is less than the minimum number, the defined minimum number is used.
  54. .IP <numRDRs>
  55. The number of receive descriptors to use.  This controls how much data
  56. the device can absorb under load.  If this is specified as NONE (-1) or
  57. is less than the minimum number, the defined minimum number is used.
  58. .IP <userFlags>
  59. Always set to zero on startup.
  60. EXTERNAL SUPPORT REQUIREMENTS
  61. This driver requires the following external functions to operate.
  62. .IP sysDmaIntrVectorSet ()
  63. .CS
  64.     void     sysDmaIntrVectorSet (int, void (*fptr)(), void *)
  65. .CE
  66. This routine is used to set the interrupt vectors for ethernet
  67. Tx and Rx DMA channels 9 and 10.
  68. .IP sysDmaIntrVectorClr ()
  69. .CS
  70.     void     sysDmaIntrVectorClr (int)
  71. .CE
  72. This routine is used to clear the interrupt vectors for ethernet
  73. Tx and Rx DMA channels 9 and 10.
  74. .IP sysEnetAddrGet ()
  75. .CS
  76.     void     sysEnetAddrGet (int unit, UINT8 *)
  77. .CE
  78. This routine is used to get the ethernet address.
  79. .IP sysUSecTimoutStart ()
  80. .CS
  81.     UINT32   sysUSecTimoutStart (void)
  82. .CE
  83. This routine is used to get the start count of the microsecond
  84. timer.
  85. .IP sysUSecTimoutExpired ()
  86. .CS
  87.     BOOL    sysUSecTimoutExpired (UINT32, UINT32)
  88. .CE
  89. This routine is used to test if a desired timeout value has
  90. expired.
  91. */
  92. #define END_ERR_NO_BUF  1 /* ### HACK HACK HACK */
  93. /* includes */
  94. #include "vxWorks.h"
  95. #include "stdio.h"
  96. #include "stdlib.h"
  97. #include "logLib.h"
  98. #include "semLib.h"
  99. #include "intLib.h"
  100. #include "tickLib.h"
  101. #include "netLib.h"
  102. #include "netBufLib.h"
  103. #include "memLib.h"
  104. #include "etherLib.h"
  105. #include "etherMultiLib.h"      /* multicast stuff. */
  106. #include "endLib.h"
  107. #include "lstLib.h"             /* Needed to maintain protocol list. */
  108. #include "cacheLib.h"
  109. #include "sysLib.h"
  110. #include "taskLib.h"
  111. #include "iv.h"
  112. #include "rc32438.h"
  113. /* RFC1213 mode (define before idt32438End.h) */
  114. #define INCLUDE_RFC_1213
  115. #include "idt32438End.h"
  116. /* defines */
  117. /* Debug Flags */
  118. #ifdef  DRV_DEBUG
  119. UINT32 idt32438DebugFlags = 0x0 ;
  120. #endif  /* DRV_DEBUG */
  121. /* enable/disable dumpEthInfo and idt32438PhyRegsDump if IDT_DEBUG
  122.  * not zero
  123.  */
  124. #define IDT_DEBUG            1
  125. #define PHY_INIT             0
  126. #define TOKBASE              16            /* base of string input field */
  127. #define CRC_MASK             0x3F          /* mask off CRC bits */
  128. #define CRC_GEN              0x04C11DB7
  129. /* microsecond timeouts for hardware operations */
  130. #define ETH_TIMEOUT          50          /* ETH operation timeout */
  131. #define DMA_TIMEOUT          50          /* DMA operation timeout */
  132. #define PHY_RD_TIMEOUT       500         /* PHY operation timeout */
  133. #define PHY_WR_TIMEOUT       20000       /* PHY operation timeout */
  134. /* cluster buffer alignment compensation value */
  135. #define CLUST_BUF_OFFSET     2
  136. #if (IDT_DEBUG != 0)
  137. /* globals for counting the packets transmitted and received */
  138. static unsigned int ethTxCnt   = 0;  /* Ethernet transmit frame count */
  139. static unsigned int ethRxCnt   = 0;  /* Ethernet receive frame count */
  140. static unsigned int ethRxToss  = 0;  /* Ethernet receive frame counts dropped */
  141. static unsigned int ethRxInt   = 0;  /* Ethernet receive interrupts */
  142. static unsigned int ethTxInt   = 0;  /* Ethernet transmit interrupts */
  143. static unsigned int ethCRCErr  = 0;  /* Ethernet CRC Error frame count */
  144. static unsigned int ethLErr    = 0;  /* Ethernet Length Error frame count */
  145. #endif /* IDT_DEBUG */
  146.  
  147. /* forward declarations */
  148. void            dumpEthInfo (void);
  149. LOCAL STATUS    idt32438PhyRegRead (int, int, int *, DRV_CTRL *);
  150. LOCAL void      initializeTDRs (DRV_CTRL *);
  151. LOCAL void      initializeRDRs (DRV_CTRL *);
  152. LOCAL STATUS    idt32438EtherInit (DRV_CTRL *, UINT8 *);
  153. LOCAL STATUS    idt32438InitParse (DRV_CTRL *, char *);
  154. LOCAL STATUS    idt32438MemInit (DRV_CTRL *);
  155. LOCAL STATUS    idt32438Send (DRV_CTRL *, M_BLK_ID);
  156. LOCAL STATUS    idt32438PhyInit (DRV_CTRL *);
  157. LOCAL STATUS    idt32438Stop (DRV_CTRL *);
  158. LOCAL STATUS    idt32438Reset (DRV_CTRL *);
  159. LOCAL STATUS    idt32438Restart (DRV_CTRL *);
  160. LOCAL void      idt32438HandleRx (DRV_CTRL *);
  161. LOCAL void      idt32438IntOVR (DRV_CTRL * );
  162. LOCAL void      idt32438Int (int, DRV_CTRL *);
  163. END_OBJ *       idt32438EndLoad (char *);
  164. LOCAL STATUS    idt32438Start (DRV_CTRL *);
  165. LOCAL STATUS    idt32438Unload (DRV_CTRL *);
  166. LOCAL STATUS    idt32438Ioctl (DRV_CTRL *, unsigned int, caddr_t);
  167. LOCAL STATUS    idt32438MCastAddrAdd (DRV_CTRL *, char *);
  168. LOCAL STATUS    idt32438MCastAddrDel (DRV_CTRL *, char *);
  169. LOCAL STATUS    idt32438MCastAddrGet (DRV_CTRL *, MULTI_TABLE *);
  170. LOCAL STATUS    idt32438PollSend (DRV_CTRL *, M_BLK_ID);
  171. LOCAL STATUS    idt32438PollReceive (DRV_CTRL *, M_BLK_ID);
  172. LOCAL STATUS    idt32438PollStart (DRV_CTRL *);
  173. LOCAL STATUS    idt32438PollStop (DRV_CTRL *);
  174. LOCAL STATUS    idt32438ARCFlagsConfig (DRV_CTRL *);
  175. LOCAL STATUS    idt32438PhyRegWrite (int, int, int, DRV_CTRL *);
  176. LOCAL UINT32    idt32438ComputeCRC (UINT8 *);
  177. LOCAL void      idt32438HashBitErase (UINT8 *, DRV_CTRL *);
  178. LOCAL void      idt32438HashBitWrite (UINT8 *, DRV_CTRL *);
  179. LOCAL void      idt32438SetEthAddr (DRV_CTRL *, UINT8 *);
  180. LOCAL void      idt32438HandleTx (DRV_CTRL *);
  181. /* Console callable routines */
  182. void            idt32438PhyRegsDump (void);
  183. /* external function declarations */
  184. IMPORT void     sysDmaIntrVectorSet (int, void (*fptr)(), void *);
  185. IMPORT void     sysDmaIntrVectorClr (int);
  186. IMPORT void     sysEnetAddrGet (int unit, UINT8 *);
  187. IMPORT void     sysWbFlush ();
  188. IMPORT UINT32   sysUSecTimoutStart (void);
  189. IMPORT BOOL     sysUSecTimoutExpired (UINT32, UINT32);
  190. /*
  191.  * Define the device function table.  This is static across all driver
  192.  * instances.
  193.  */
  194. LOCAL NET_FUNCS netFuncs =
  195.     {
  196.     (FUNCPTR) idt32438Start,            /* start func. */
  197.     (FUNCPTR) idt32438Stop,             /* stop func.  */
  198.     (FUNCPTR) idt32438Unload,           /* unload func.*/
  199.     (FUNCPTR) idt32438Ioctl,            /* ioctl func. */
  200.     (FUNCPTR) idt32438Send,             /* send func.  */
  201.     (FUNCPTR) idt32438MCastAddrAdd,     /* multicast add func.    */
  202.     (FUNCPTR) idt32438MCastAddrDel,     /* multicast delete func. */
  203.     (FUNCPTR) idt32438MCastAddrGet,     /* multicast get fun.     */
  204.     (FUNCPTR) idt32438PollSend,         /* polling send func.     */
  205.     (FUNCPTR) idt32438PollReceive,      /* polling receive func. */
  206.     endEtherAddressForm,                /* put address info into a NET_BUFFER*/
  207.     (FUNCPTR) endEtherPacketDataGet,    /* get pointer to data in NET_BUFFER*/
  208.     (FUNCPTR) endEtherPacketAddrGet     /* Get packet addresses. */
  209.     };
  210.  BOOL      ETH_INIT_DN = FALSE ;       /* Global to mark mii initialization    */
  211.    
  212. /***************************************************************************
  213. *
  214. * idt32438EndLoad - initialize the driver and device
  215. *
  216. * This routine initializes both, driver and device to an operational state
  217. * using device specific parameters specified by <initString>.
  218. *
  219. * The parameter string, <initString>, is defined above in the section
  220. * titled TARGET-SPECIFIC PARAMETRERS.  
  221. *
  222. * A default number of transmit/receive frames of 20 can be selected by
  223. * passing zero in the parameters <numTDRs> and <numRDRs>.
  224. *
  225. * RETURNS: an END object pointer, NULL on error if initString pointer
  226. * is NULL or the name of the driver if the initString pointer isn't
  227. * NULL but initString [0] == NULL.
  228. *
  229. */
  230. END_OBJ * idt32438EndLoad
  231.     (
  232.     char *  initString  /* parameter string */
  233.     )
  234.     {
  235.     STATUS      rtv;
  236.     DRV_CTRL *  pDrvCtrl;   /* pointer to DRV_CTRL structure */
  237.     UINT32      speed;      /* Ethernet speed (100/10) */
  238.     UINT8       eAdrs[ENET_SIZE + 1] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00};
  239.    
  240.                             /*Default ethernet address */
  241.   
  242.     DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438EndLoad()n",
  243.              1, 2, 3, 4, 5, 6);
  244.              
  245.     /* Check for an allocated string. */
  246.     if (initString == (char *)NULL)
  247.         return ((END_OBJ *) NULL);
  248.     /* If a null string, then copy the device's name to the string. */
  249.     if (initString[0] == '')
  250.         {
  251.         bcopy ((char *)IDT438_DEV_NAME, initString, IDT438_DEV_NAME_LEN);
  252.         return ((END_OBJ *) NULL);
  253.         }
  254.     /* Allocate the device structure */
  255.     pDrvCtrl = (DRV_CTRL *) calloc (sizeof (DRV_CTRL), 1);
  256.     if (pDrvCtrl == (DRV_CTRL *) NULL)
  257.         return ((END_OBJ *) NULL);
  258.     /* Parse initString, filling in the device structure */
  259.     if (idt32438InitParse (pDrvCtrl, initString) == ERROR)
  260.         goto errorExit;
  261.     /* memory initialization */
  262.     if (idt32438MemInit (pDrvCtrl) == ERROR)
  263.         goto errorExit;
  264.     /* disable DMA and Ethernet Rx and Tx interrupts */
  265.     DMA_INT_DISABLE(pDrvCtrl);
  266.     ETH_DMA_RX_INT_DISABLE(pDrvCtrl);
  267.     ETH_DMA_TX_INT_DISABLE(pDrvCtrl);
  268.     /*
  269.      * Initialize the default parameter for the Physical medium
  270.      * layer control user has his chance to override in the BSP,
  271.      * just be CAREFUL
  272.      */
  273.     pDrvCtrl->board.phyAddr  = 0;
  274.     pDrvCtrl->board.phySpeed = PHY_AUTO_SPEED;
  275.     pDrvCtrl->board.phyDpx   = PHY_AUTO_DPX;
  276.     /* Ask the BSP to provide the ethernet address. */
  277.     
  278.     
  279.    sysEnetAddrGet (pDrvCtrl->unit, &eAdrs[0]);
  280.      
  281.     
  282.     /*
  283.      * initialize the ethernet and the phy
  284.      */
  285.     if (idt32438EtherInit (pDrvCtrl, &eAdrs[0]) != OK)
  286.         {
  287.         DRV_LOG (DRV_DEBUG_LOAD,
  288.                  "idt32438LoadEnd(): idt32438EtherInit() failed.n",
  289.                  1, 2, 3, 4, 5, 6);
  290.         goto errorExit;
  291.         }
  292.     /* save Phy speed per configuration */
  293.     if (pDrvCtrl->board.phySpeed == PHY_10MBS)
  294.         speed = PHY_SPEED_10;
  295.     else
  296.         speed = PHY_SPEED_100;
  297.     DRV_LOG (DRV_DEBUG_LOAD, "Speed = %d, Mode = %dn", speed,
  298.              (int) pDrvCtrl->board.phyDpx, 3, 4, 5, 6);
  299.     pDrvCtrl->attached = TRUE;
  300.     /* endObj initializations */
  301.     rtv = END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *) pDrvCtrl,
  302.                         IDT438_DEV_NAME, pDrvCtrl->unit, &netFuncs,
  303.                         "IDT RC32438 Ethernet Enhanced Network Driver");
  304.     if (rtv == ERROR)
  305.         {
  306.         DRV_LOG (DRV_DEBUG_LOAD, "idt32438LoadEnd(): END_OBJ_INIT() failed.n",
  307.                  1, 2, 3, 4, 5, 6);
  308.         goto errorExit;
  309.         }
  310. #ifdef INCLUDE_RFC_1213
  311.     /* Initialize the MIB-II structure */
  312.     rtv = END_MIB_INIT (&pDrvCtrl->endObj,
  313.                         M2_ifType_ethernet_csmacd,
  314.                         &eAdrs[0],
  315.                         ENET_SIZE,
  316.                         ETHERMTU,
  317.                         speed);
  318.     if (rtv == ERROR)
  319.         {
  320.         DRV_LOG (DRV_DEBUG_LOAD, "idt32438LoadEnd(): END_MIB_INIT() failed.n",
  321.                  1, 2, 3, 4, 5, 6);
  322.         goto errorExit;
  323.         }
  324.     /* Mark the device ready */
  325.     END_OBJ_READY (&pDrvCtrl->endObj,
  326.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
  327. #else /* INCLUDE_RFC_1213 */
  328.       /* Initialize MIB-II entries (for RFC 2233 ifXTable) */
  329.     pDrvCtrl->endObj.pMib2Tbl = m2IfAlloc(M2_ifType_ethernet_csmacd,
  330.                                           (UINT8*) &eAdrs[0], ENET_SIZE,
  331.                                           ETHERMTU, speed,
  332.                                           IDT32438_DEV_NAME, pDrvCtrl->unit);
  333.     if (pDrvCtrl->endObj.pMib2Tbl == NULL)
  334.         {
  335.         DRV_LOG (DRV_DEBUG_ERROR, "MIB-II initialization failedn",
  336.                 1, 2, 3, 4, 5, 6);
  337.         goto errorExit;
  338.         }
  339.     /*
  340.      * Set the RFC2233 flag bit in the END object flags field and
  341.      * install the counter update routines.
  342.      */
  343.     m2IfPktCountRtnInstall(pDrvCtrl->endObj.pMib2Tbl, m2If8023PacketCount);
  344.     /*
  345.      * Make a copy of the data in mib2Tbl struct as well. We do this
  346.      * mainly for backward compatibility issues. There might be some
  347.      * code that might be referencing the END pointer and might
  348.      * possibly do lookups on the mib2Tbl, which will cause all sorts
  349.      * of problems.
  350.      */
  351.     bcopy ((char *)&pDrvCtrl->endObj.pMib2Tbl->m2Data.mibIfTbl,
  352.                    (char *)&pDrvCtrl->endObj.mib2Tbl, sizeof (M2_INTERFACETBL));
  353.     /* Mark the device ready */
  354.     END_OBJ_READY (&pDrvCtrl->endObj,
  355.                    IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST |
  356.                    END_MIB_2233);
  357. #endif /* INCLUDE_RFC_1213 */
  358.     DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438EndLoad()n",
  359.              1, 2, 3, 4, 5, 6);
  360.     return (&pDrvCtrl->endObj);
  361. errorExit:
  362.     DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438EndLoad():errorn",
  363.              1, 2, 3, 4, 5, 6);
  364.     if (pDrvCtrl != (DRV_CTRL *) NULL)
  365.         {
  366.         idt32438Unload (pDrvCtrl);
  367.         free ((char *) pDrvCtrl);
  368.         }
  369.     return (END_OBJ *) NULL;
  370.     }
  371. /***************************************************************************
  372. *
  373. * idt32438InitParse - parse parameter values from initString
  374. *
  375. * This routine parses the initialization string which is specified
  376. * above in the section TARGET-SPECIFIC PARAMETERS
  377. *
  378. * RETURNS: OK or ERROR
  379. */
  380. LOCAL STATUS idt32438InitParse
  381.     (
  382.     DRV_CTRL *  pDrvCtrl,   /* pointer to DRV_CTRL structure */
  383.     char *      initString  /* parameter string */
  384.     )
  385.     {
  386.     char *  tok;                    /* an initString token */
  387.     char *  holder = (char *)NULL;  /* points to string fragment beyond tok */
  388.     UINT32  regBase;                /* rc32438 register base addr */
  389.     DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438InitParsen", 1, 2, 3, 4, 5, 6);
  390.  
  391.     /* get the unit number parameter */
  392.     tok = strtok_r (initString, ":", &holder);
  393.     if (tok == (char *)NULL)
  394.         return ERROR;
  395.     pDrvCtrl->unit = atoi (tok);
  396.      
  397.     
  398.     /* ethernet input overflow vector number */
  399.     tok = strtok_r ((char *)NULL, ":", &holder);
  400.     if (tok == (char *)NULL)
  401.         return ERROR;
  402.     pDrvCtrl->ivec = atoi (tok);
  403.    
  404.     
  405.     /* rc32438 register base address */
  406.     tok = strtok_r ((char *)NULL, ":", &holder);
  407.     if (tok == (char *)NULL)
  408.         return ERROR;
  409.     regBase = (UINT32) strtoul (tok, NULL, TOKBASE);
  410.      
  411.     
  412.     /* get the number of Transmit Frame Descriptors parameter */
  413.     tok = strtok_r ((char *)NULL, ":", &holder);
  414.     if (tok == (char *)NULL)
  415.         return ERROR;
  416.     pDrvCtrl->nTDRs = atoi (tok);
  417.     
  418.     
  419.     /* get the number of Receive Frame Descriptors parameter */
  420.     tok = strtok_r ((char *)NULL, ":", &holder);
  421.     if (tok == (char *)NULL)
  422.         return ERROR;
  423.     pDrvCtrl->nRDRs = atoi (tok);
  424.    
  425.    
  426.     
  427.     /* assign the correct base addresses for the DMA, Int Controller
  428.      * and Ethernet devices inside rc32438
  429.      */
  430.     
  431.     if(pDrvCtrl->unit == 1)
  432.         {
  433.     
  434.         pDrvCtrl->dmaRegBase = (UINT32)(regBase + IDT_DMA1_REG_OFFSET);
  435.         pDrvCtrl->intRegBase = (UINT32)(regBase + IDT_INTC_REG_OFFSET);
  436.         pDrvCtrl->ethRegBase = (UINT32)(regBase + IDT_ETH1_REG_OFFSET);
  437.          
  438.         }
  439.     else
  440.         {
  441.         pDrvCtrl->dmaRegBase = (UINT32)(regBase + IDT_DMA0_REG_OFFSET);
  442.         pDrvCtrl->intRegBase = (UINT32)(regBase + IDT_INTC_REG_OFFSET);
  443.         pDrvCtrl->ethRegBase = (UINT32)(regBase + IDT_ETH0_REG_OFFSET);
  444.        
  445.         }
  446.      
  447.     /* flags always set to zero on startup */ 
  448.     pDrvCtrl->flags = 0;
  449.     /* make sure there are enough TDRs */
  450.     if (pDrvCtrl->nTDRs < MIN_NUM_TDRS)
  451.         {
  452.         pDrvCtrl->nTDRs = MIN_NUM_TDRS;
  453.         }
  454.     /* make sure there are enough RDRs */
  455.     if (pDrvCtrl->nRDRs < MIN_NUM_RDRS)
  456.         {
  457.         pDrvCtrl->nRDRs = MIN_NUM_RDRS;
  458.         }
  459.     DRV_LOG (DRV_DEBUG_LOAD2, "idt32438InitParse %x %x %x %xn",
  460.              pDrvCtrl->unit, pDrvCtrl->nTDRs, pDrvCtrl->nRDRs,
  461.              (int)pDrvCtrl->flags, 5, 6);
  462.     DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438InitParsen",
  463.              1, 2, 3, 4, 5, 6);
  464.     return (OK);
  465.     }
  466. /******************************************************************************
  467. *
  468. * initializeTDRs - Initialize TDR Control Data Structures
  469. *
  470. *
  471. * Initializes the Transmit DMA Descriptor Register data structures.
  472. *
  473. * RETURNS: N/A
  474. */
  475. LOCAL void initializeTDRs
  476.     (
  477.     DRV_CTRL *  pDrvCtrl    /* pointer to DRV_CTRL structure */
  478.     )
  479.     {
  480.     DMA_DR *    pTDR;       /* pointer to CFDs */
  481.     DMA_DR *    pTDROld;
  482.     int         ix;         /* a counter */
  483.     /* First ready TDR pointer */
  484.     pTDR = (DMA_DR *) pDrvCtrl->pTDRmem;
  485.     pDrvCtrl->pTDRTail = pDrvCtrl->pTDRHead = pTDR;
  486.     pDrvCtrl->pTDRQStart = (DMA_DR *)NULL;
  487.     pDrvCtrl->cntTDRused = 0;
  488.     pTDROld = &pTDR[pDrvCtrl->nTDRs - 1];
  489.     /* initialize the TDR ring */
  490.     for (ix = 0; ix < pDrvCtrl->nTDRs; ix++)
  491.         {
  492.         /* Initialize DDT */
  493.         pTDR->control = (DMA_DR_CONTROL_IOD | DMA_DR_CONTROL_IOF);
  494.         pTDR->link = 0;
  495.         pTDR->devcs = 0;
  496.         pTDR->pClust = (char *)K0_TO_K1 ((UINT32)netClusterGet (
  497.                                      pDrvCtrl->endObj.pNetPool, 
  498.                                      pDrvCtrl->pClPoolId));
  499.         pTDR->flags = 0;
  500.         /* Tie the current TDR to the next one */
  501.         pTDR->next = pTDR + 1;
  502.         /* Previous TDR pointer */
  503.         pTDR->prev = pTDROld;
  504.         /* remember this TDR */
  505.         pTDROld = pTDR;
  506.         /* bump to the next TDR */
  507.         pTDR++;
  508.         }
  509.     /* tie the last TDR to the first one */
  510.     pTDR--;
  511.     pTDR->next = pDrvCtrl->pTDRHead;
  512.     DRV_LOG (DRV_DEBUG_MEM, "initializeTDRs: first=%x last=%xn",
  513.              (int)pDrvCtrl->pTDRHead, (int)pDrvCtrl->pTDRHead->prev, 
  514.              3, 4, 5, 6);
  515.     }
  516.  
  517. /*******************************************************************************
  518. *
  519. * initializeRDRs - Initialize RDR Control Data Structures
  520. *
  521. * Initializes Receive DMA Descriptor Register data structures.
  522. *
  523. * RETURNS: N/A
  524. */
  525.  
  526. LOCAL void initializeRDRs
  527.     (
  528.     DRV_CTRL *  pDrvCtrl    /* pointer to DRV_CTRL structure */
  529.     )
  530.     {
  531.     DMA_DR *    pRDR;       /* pointer to RDRs */
  532.     DMA_DR *    pRDROld;
  533.     int         ix;         /* a counter */
  534.     /* First ready RDR pointer */
  535.     pRDR = (DMA_DR *) pDrvCtrl->pRDRmem; /* point to frame descriptor memory */
  536.     pDrvCtrl->pRDR = pRDR;
  537.      
  538.     pRDROld = &pRDR[pDrvCtrl->nRDRs - 1];
  539.     
  540.     /* Note: RDRs are keep as a list and not as a ring.  this is
  541.      * because in stress situations on the rcv side where you can
  542.      * experience an input overflow, the end RDR in the list must
  543.      * have a link pointer equal to NULL.  this will stop the DMA
  544.      * from continuing around the ring.  this is important because
  545.      * a disable then enable of the ethernet and DMA is required
  546.      * on input overflow and the DMA behaviour isn't repeatable if
  547.      * the last RDR doesn't have a NULL pointer for the link.  the
  548.      * DMA will not always restart in a repeatable way.
  549.      */
  550.     /* initialize the RDR list */
  551.     for (ix = 0; ix < pDrvCtrl->nRDRs; ix++)
  552.         {
  553.         pRDR->control = RDR_CONTROL_VAL;
  554.         pRDR->link = K1_TO_PHYS ((UINT32)(pRDR + 1));
  555.         pRDR->devcs = 0;
  556.         pRDR->flags = 0;
  557.         
  558.         /* add offset to descriptor buffer so buffer is correctly aligned */
  559.         pRDR->pClust = (char *)K0_TO_K1((
  560.                                       netClusterGet (pDrvCtrl->endObj.pNetPool,
  561.                                       pDrvCtrl->pClPoolId)) + CLUST_BUF_OFFSET);
  562.         pRDR->ca = K1_TO_PHYS ((UINT32)pRDR->pClust);
  563.         /* Tie the previous RDR to the current one */
  564.         pRDR->next = pRDR + 1;
  565.         pRDR->prev = pRDROld;
  566.         /* remember this RDR */
  567.         pRDROld = pRDR;
  568.         /* bump to the next RDR */
  569.         pRDR++;
  570.         }
  571.     /* Tie the Last RDR link to NULL finishing the linked list */
  572.     pRDR--;
  573.      
  574.     pRDR->link = (UINT32)NULL;; 
  575.     pRDR->next = pDrvCtrl->pRDR;
  576.      
  577.      
  578.     
  579.     DRV_LOG (DRV_DEBUG_MEM, "initializeRDRs: first=%x last=%xn",
  580.              (int)pDrvCtrl->pRDR, (int)pDrvCtrl->pRDR->prev, 3, 4, 5, 6);
  581.     }
  582.   
  583.  
  584. /***************************************************************************
  585. *
  586. * idt32438MemInit - Initialize memory
  587. *
  588. * This routine initializes the transmit and receive descriptor lists
  589. *
  590. * RETURNS: OK or ERROR
  591. */
  592. LOCAL STATUS idt32438MemInit
  593.     (
  594.     DRV_CTRL *  pDrvCtrl        /* pointer to DRV_CTRL structure */
  595.     )
  596.     {
  597.     UINT32      nRDRLoan;
  598.     CL_DESC     clDesc;
  599.     M_CL_CONFIG mClBlkConfig;
  600.     int         memTDRsize;
  601.     int         memRDRsize;
  602.     DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438MemInit()n", 1, 2, 3, 4, 5, 6);
  603.     /* this driver can't handle write incoherent caches */
  604.     if (!CACHE_DMA_IS_WRITE_COHERENT ())
  605.         {
  606.         DRV_LOG (DRV_DEBUG_ERROR,
  607.                  "idt32438MemInit: shared memory not cache coherentn",
  608.                  1, 2, 3, 4, 5, 6);
  609.         return (ERROR);
  610.         }
  611.     /* allocate memory for transmit descriptor registers.  Get
  612.      * the memory from non-cached space
  613.      */
  614.     memTDRsize = pDrvCtrl->nTDRs * sizeof (DMA_DR);
  615.     pDrvCtrl->pTDRmem = cacheDmaMalloc (memTDRsize);
  616.     /* allocate memory for receive descriptor registers.  Get
  617.      * the memory from non-cached space
  618.      */
  619.     memRDRsize = pDrvCtrl->nRDRs * sizeof (DMA_DR);
  620.     pDrvCtrl->pRDRmem = cacheDmaMalloc (memRDRsize);
  621.     
  622.     if ((pDrvCtrl->pTDRmem == NULL) || (pDrvCtrl->pRDRmem == NULL))
  623.         {
  624.         DRV_LOG (DRV_DEBUG_ERROR, "idt32438MemInit: could not obtain memoryn",
  625.                  1, 2, 3, 4, 5, 6);
  626.         return (ERROR);
  627.         }
  628.     /* zero the descriptor memory */
  629.     memset (pDrvCtrl->pTDRmem, 0, memTDRsize);
  630.     memset (pDrvCtrl->pRDRmem, 0, memRDRsize);
  631.     /*
  632.      * Calculate the number of clusters, their size, and the memory size for
  633.      * all the clusters.  Then allocate memory for the clusters.
  634.      */
  635.     nRDRLoan = (pDrvCtrl->nRDRs * 4);
  636.     clDesc.clNum = pDrvCtrl->nRDRs +
  637.                    pDrvCtrl->nRDRs +
  638.                    nRDRLoan;
  639.     clDesc.clSize = IDT_BUFSIZ ;
  640.     clDesc.memSize = (clDesc.clNum * (clDesc.clSize + sizeof(long) )) + 
  641.                      sizeof (long);
  642.     clDesc.memArea = memalign (sizeof (long), clDesc.memSize); 
  643.     
  644.     pDrvCtrl->clBaseAddr = clDesc.memArea;
  645.     if (clDesc.memArea == (char *) NULL)
  646.         {
  647.         DRV_LOG (DRV_DEBUG_ERROR, "System memory unavaiablen",
  648.                  1, 2, 3, 4, 5, 6);
  649.         return (ERROR);
  650.         }
  651.     DRV_LOG (DRV_DEBUG_INFO, "Memory alignment clDesc.memArea:%xn",
  652.              (int)clDesc.memArea, 2, 3, 4, 5, 6);
  653.     /* Set 5 times as many mBlk's as clusters. */
  654.     mClBlkConfig.mBlkNum = clDesc.clNum * 2;
  655.     /* Set the number of clusters. */
  656.     mClBlkConfig.clBlkNum = clDesc.clNum;
  657.     /*
  658.      * total memory size for mBlks and clBlks
  659.      * get memory for mblks
  660.      * memory size adjusted to hold the netPool pointer at the head
  661.      */
  662.     mClBlkConfig.memSize = 
  663.         (mClBlkConfig.mBlkNum * (M_BLK_SZ + sizeof (long))) +
  664.         (mClBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof (long)));
  665.     mClBlkConfig.memArea = (char *) memalign (sizeof (long), 
  666.                                               mClBlkConfig.memSize);
  667.     if (mClBlkConfig.memArea == (char *) NULL)
  668.         {
  669.         DRV_LOG (DRV_DEBUG_ERROR, "Memory align (by %d) failed, memSize %xn",
  670.                  sizeof (long), (int) mClBlkConfig.memSize, 3, 4, 5, 6);
  671.         return (ERROR);
  672.         }
  673.     /* store the pointer to the cluster area */
  674.     pDrvCtrl->pMemArea = mClBlkConfig.memArea;
  675.     /* Allocate the network pool. */
  676.     pDrvCtrl->endObj.pNetPool = (NET_POOL_ID)malloc (sizeof (NET_POOL));
  677.     if (pDrvCtrl->endObj.pNetPool == (NET_POOL_ID)NULL)
  678.         {
  679.         DRV_LOG (DRV_DEBUG_ERROR, "pNetPool alloc failed for size %dn",
  680.                  sizeof (NET_POOL), 2, 3, 4, 5, 6);
  681.         return (ERROR);
  682.         }
  683.     /* init the mem pool */
  684.     if (netPoolInit (pDrvCtrl->endObj.pNetPool, &mClBlkConfig,
  685.                      &clDesc, 1, (POOL_FUNC *)NULL) == ERROR)
  686.         {
  687.         DRV_LOG (DRV_DEBUG_ERROR, "netPoolInit() failed.n",
  688.                  1, 2, 3, 4, 5, 6);
  689.         return (ERROR);
  690.         }
  691.     pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool, 
  692.                                           IDT_BUFSIZ, FALSE);
  693.     if (pDrvCtrl->pClPoolId == (CL_POOL_ID)NULL)
  694.         {
  695.         DRV_LOG (DRV_DEBUG_ERROR, "netClPoolIdGet() returned NULL pool ID.n",
  696.                  1, 2, 3, 4, 5, 6);
  697.         return (ERROR);
  698.         }
  699.     /* We are setting up the TDRs as a fixed ring   */
  700.     initializeTDRs (pDrvCtrl);
  701.     /* We are setting up the RDRs as a fixed ring   */
  702.     initializeRDRs (pDrvCtrl);
  703.     DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438MemInitn",
  704.             1, 2, 3, 4, 5, 6);
  705.     return (OK);
  706.     }
  707.  
  708. /***************************************************************************
  709. *
  710. * idt32438Send - send an Ethernet packet
  711. *
  712. * This routine() takes a M_BLK_ID and sends off the data in the M_BLK_ID.
  713. * The buffer must already have the addressing information properly installed
  714. * in it. This is done by a higher layer.
  715. *
  716. * muxSend() calls this routine each time it wants to send a packet.
  717. *
  718. * RETURNS: ERROR if not valid parameters or OK
  719. */
  720.  
  721. LOCAL STATUS idt32438Send
  722.     (
  723.     DRV_CTRL *  pDrvCtrl,   /* pointer to DRV_CTRL structure */
  724.     M_BLK_ID    pMblk       /* pointer to the mBlk/cluster pair */
  725.     )
  726.     {
  727.     M_BLK_ID    pMblkTmp;   /* pointer to pMblk for counting mNext segments */
  728.     int         mblks;      /* number of Mblks in packet */
  729.     int         len;
  730.     int         totalLen ;
  731.     DMA_DR *    pTDR;
  732.     DMA_DR *    pTDRFirst;
  733.     int         intKey;
  734.  
  735.      
  736.     DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438Send()n", 1, 2, 3, 4, 5, 6);
  737.     /* check device mode and validate mBlk pointer */
  738.  
  739.     if ((pDrvCtrl->flags & IDT_POLLING) != 0)
  740.         {
  741.         netMblkClChainFree (pMblk);
  742.         errno = EINVAL;
  743.         return (ERROR);
  744.         } 
  745.     else if (pMblk == (M_BLK_ID)NULL)
  746.         {
  747.         errno = EINVAL;
  748.         return (ERROR);
  749.         }
  750.     /* interlock with Interrupt ISR/DPC task */
  751.     END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
  752.     /* count the number of mblks in this packet */
  753.     for (mblks = 0, pMblkTmp = pMblk;pMblkTmp != (M_BLK_ID)NULL;
  754.          pMblkTmp = pMblkTmp->mBlkHdr.mNext, mblks++)
  755.             {
  756.           len = pMblkTmp->mBlkHdr.mLen;
  757.          (void)cacheFlush (DATA_CACHE, pMblkTmp->mBlkHdr.mData, len);
  758.   totalLen += len;
  759.         }
  760.        
  761.     /* stall if not enough TDR's available for this mBlk */
  762.     if (mblks > (pDrvCtrl->nTDRs - pDrvCtrl->cntTDRused))
  763.         {
  764.         DRV_LOG (DRV_DEBUG_ERROR,