idt32438End.c
资源名称:idt438.rar [点击查看]
上传用户:yingyi0918
上传日期:2022-06-26
资源大小:214k
文件大小:28k
源码类别:
VxWorks
开发平台:
C/C++
- /* idt32438End.c - Ethernet END Driver for IDT RC32438 */
- /* Copyright 1984-2002 Wind River Systems, Inc. */
- #include "copyright_wrs.h"
- /*
- * This file has been developed or significantly modified by the
- * MIPS Center of Excellence Dedicated Engineering Staff.
- * This notice is as per the MIPS Center of Excellence Master Partner
- * Agreement, do not remove this notice without checking first with
- * WR/Platforms MIPS Center of Excellence engineering management.
- */
- /*
- modification history
- --------------------
- 02a,16Dec02,krao Modified driver for IDT 79pmc438 board.
- 01b,25jul02,slk SPR 80131 and also general code clean up
- 01b,11jul02,pgh Significant re-write and clean up.
- 01a,19Jun02,d_c Code from IDT modified to approach C of E standards.
- */
- /*
- DESCRIPTION
- This module implements the IDT RC32438 enhanced network driver. This device
- is an integrated communications processor, so the ethernet interface is part
- of the processor. The ethernet interface provides a 10/100 Mbit ISO/IEC 8802-3:
- 1996 compliant interface. An external Ethernet physical device (PHY)
- connects to the Ethernet interface through an IEEE Std 802.3u-1995 Media
- Independent Interface (MII). This allows the Ethernet interface to be used
- with a multitude of physical layers such as: 10BASE-T, 100BASE-TX, and
- 100BASE-FX.
- During boot configuration the RC32438 may be configured to operate in either
- big endian mode or little endian mode. Although ethernet packet data is
- packed into words in FIFO's, packet data is referenced in bytes by the CPU
- and Ethernet MAC. Data is always stored in big endian format within FIFO data
- words, with endianness conversion taking place as data is transfered between
- the IP bus and the FIFO's. Thus data stored in the FIFOs always appears to the
- programmer in the endianness selected during boot configuration.
- This driver is designed specifically for the RC32438 ethernet interface. It can
- operate on any of the boards containing a RC32438 processor under vxWorks.
- EXTERNAL INTERFACE
- The driver provides one standard external interface, idt32438EndLoad (). As
- input, this function expects a string of colon-separated parameters.
- The format of the parameter string is:
- <intVec>:<regBase>:<nTFDs>:<nRFDs>:<userFlags>
- TARGET-SPECIFIC PARAMETERS
- .IP <unit>
- The unit number for this device.
- .IP <intVec>
- Vector number for the ethernet overrun error condition.
- .IP <regBase>
- Base address of the rc32438 registers.
- .IP <numTDRs>
- The number of transmit descriptors to use. This controls how much data
- the device can absorb under load. If this is specified as NONE (-1) or
- is less than the minimum number, the defined minimum number is used.
- .IP <numRDRs>
- The number of receive descriptors to use. This controls how much data
- the device can absorb under load. If this is specified as NONE (-1) or
- is less than the minimum number, the defined minimum number is used.
- .IP <userFlags>
- Always set to zero on startup.
- EXTERNAL SUPPORT REQUIREMENTS
- This driver requires the following external functions to operate.
- .IP sysDmaIntrVectorSet ()
- .CS
- void sysDmaIntrVectorSet (int, void (*fptr)(), void *)
- .CE
- This routine is used to set the interrupt vectors for ethernet
- Tx and Rx DMA channels 9 and 10.
- .IP sysDmaIntrVectorClr ()
- .CS
- void sysDmaIntrVectorClr (int)
- .CE
- This routine is used to clear the interrupt vectors for ethernet
- Tx and Rx DMA channels 9 and 10.
- .IP sysEnetAddrGet ()
- .CS
- void sysEnetAddrGet (int unit, UINT8 *)
- .CE
- This routine is used to get the ethernet address.
- .IP sysUSecTimoutStart ()
- .CS
- UINT32 sysUSecTimoutStart (void)
- .CE
- This routine is used to get the start count of the microsecond
- timer.
- .IP sysUSecTimoutExpired ()
- .CS
- BOOL sysUSecTimoutExpired (UINT32, UINT32)
- .CE
- This routine is used to test if a desired timeout value has
- expired.
- */
- #define END_ERR_NO_BUF 1 /* ### HACK HACK HACK */
- /* includes */
- #include "vxWorks.h"
- #include "stdio.h"
- #include "stdlib.h"
- #include "logLib.h"
- #include "semLib.h"
- #include "intLib.h"
- #include "tickLib.h"
- #include "netLib.h"
- #include "netBufLib.h"
- #include "memLib.h"
- #include "etherLib.h"
- #include "etherMultiLib.h" /* multicast stuff. */
- #include "endLib.h"
- #include "lstLib.h" /* Needed to maintain protocol list. */
- #include "cacheLib.h"
- #include "sysLib.h"
- #include "taskLib.h"
- #include "iv.h"
- #include "rc32438.h"
- /* RFC1213 mode (define before idt32438End.h) */
- #define INCLUDE_RFC_1213
- #include "idt32438End.h"
- /* defines */
- /* Debug Flags */
- #ifdef DRV_DEBUG
- UINT32 idt32438DebugFlags = 0x0 ;
- #endif /* DRV_DEBUG */
- /* enable/disable dumpEthInfo and idt32438PhyRegsDump if IDT_DEBUG
- * not zero
- */
- #define IDT_DEBUG 1
- #define PHY_INIT 0
- #define TOKBASE 16 /* base of string input field */
- #define CRC_MASK 0x3F /* mask off CRC bits */
- #define CRC_GEN 0x04C11DB7
- /* microsecond timeouts for hardware operations */
- #define ETH_TIMEOUT 50 /* ETH operation timeout */
- #define DMA_TIMEOUT 50 /* DMA operation timeout */
- #define PHY_RD_TIMEOUT 500 /* PHY operation timeout */
- #define PHY_WR_TIMEOUT 20000 /* PHY operation timeout */
- /* cluster buffer alignment compensation value */
- #define CLUST_BUF_OFFSET 2
- #if (IDT_DEBUG != 0)
- /* globals for counting the packets transmitted and received */
- static unsigned int ethTxCnt = 0; /* Ethernet transmit frame count */
- static unsigned int ethRxCnt = 0; /* Ethernet receive frame count */
- static unsigned int ethRxToss = 0; /* Ethernet receive frame counts dropped */
- static unsigned int ethRxInt = 0; /* Ethernet receive interrupts */
- static unsigned int ethTxInt = 0; /* Ethernet transmit interrupts */
- static unsigned int ethCRCErr = 0; /* Ethernet CRC Error frame count */
- static unsigned int ethLErr = 0; /* Ethernet Length Error frame count */
- #endif /* IDT_DEBUG */
- /* forward declarations */
- void dumpEthInfo (void);
- LOCAL STATUS idt32438PhyRegRead (int, int, int *, DRV_CTRL *);
- LOCAL void initializeTDRs (DRV_CTRL *);
- LOCAL void initializeRDRs (DRV_CTRL *);
- LOCAL STATUS idt32438EtherInit (DRV_CTRL *, UINT8 *);
- LOCAL STATUS idt32438InitParse (DRV_CTRL *, char *);
- LOCAL STATUS idt32438MemInit (DRV_CTRL *);
- LOCAL STATUS idt32438Send (DRV_CTRL *, M_BLK_ID);
- LOCAL STATUS idt32438PhyInit (DRV_CTRL *);
- LOCAL STATUS idt32438Stop (DRV_CTRL *);
- LOCAL STATUS idt32438Reset (DRV_CTRL *);
- LOCAL STATUS idt32438Restart (DRV_CTRL *);
- LOCAL void idt32438HandleRx (DRV_CTRL *);
- LOCAL void idt32438IntOVR (DRV_CTRL * );
- LOCAL void idt32438Int (int, DRV_CTRL *);
- END_OBJ * idt32438EndLoad (char *);
- LOCAL STATUS idt32438Start (DRV_CTRL *);
- LOCAL STATUS idt32438Unload (DRV_CTRL *);
- LOCAL STATUS idt32438Ioctl (DRV_CTRL *, unsigned int, caddr_t);
- LOCAL STATUS idt32438MCastAddrAdd (DRV_CTRL *, char *);
- LOCAL STATUS idt32438MCastAddrDel (DRV_CTRL *, char *);
- LOCAL STATUS idt32438MCastAddrGet (DRV_CTRL *, MULTI_TABLE *);
- LOCAL STATUS idt32438PollSend (DRV_CTRL *, M_BLK_ID);
- LOCAL STATUS idt32438PollReceive (DRV_CTRL *, M_BLK_ID);
- LOCAL STATUS idt32438PollStart (DRV_CTRL *);
- LOCAL STATUS idt32438PollStop (DRV_CTRL *);
- LOCAL STATUS idt32438ARCFlagsConfig (DRV_CTRL *);
- LOCAL STATUS idt32438PhyRegWrite (int, int, int, DRV_CTRL *);
- LOCAL UINT32 idt32438ComputeCRC (UINT8 *);
- LOCAL void idt32438HashBitErase (UINT8 *, DRV_CTRL *);
- LOCAL void idt32438HashBitWrite (UINT8 *, DRV_CTRL *);
- LOCAL void idt32438SetEthAddr (DRV_CTRL *, UINT8 *);
- LOCAL void idt32438HandleTx (DRV_CTRL *);
- /* Console callable routines */
- void idt32438PhyRegsDump (void);
- /* external function declarations */
- IMPORT void sysDmaIntrVectorSet (int, void (*fptr)(), void *);
- IMPORT void sysDmaIntrVectorClr (int);
- IMPORT void sysEnetAddrGet (int unit, UINT8 *);
- IMPORT void sysWbFlush ();
- IMPORT UINT32 sysUSecTimoutStart (void);
- IMPORT BOOL sysUSecTimoutExpired (UINT32, UINT32);
- /*
- * Define the device function table. This is static across all driver
- * instances.
- */
- LOCAL NET_FUNCS netFuncs =
- {
- (FUNCPTR) idt32438Start, /* start func. */
- (FUNCPTR) idt32438Stop, /* stop func. */
- (FUNCPTR) idt32438Unload, /* unload func.*/
- (FUNCPTR) idt32438Ioctl, /* ioctl func. */
- (FUNCPTR) idt32438Send, /* send func. */
- (FUNCPTR) idt32438MCastAddrAdd, /* multicast add func. */
- (FUNCPTR) idt32438MCastAddrDel, /* multicast delete func. */
- (FUNCPTR) idt32438MCastAddrGet, /* multicast get fun. */
- (FUNCPTR) idt32438PollSend, /* polling send func. */
- (FUNCPTR) idt32438PollReceive, /* polling receive func. */
- endEtherAddressForm, /* put address info into a NET_BUFFER*/
- (FUNCPTR) endEtherPacketDataGet, /* get pointer to data in NET_BUFFER*/
- (FUNCPTR) endEtherPacketAddrGet /* Get packet addresses. */
- };
- BOOL ETH_INIT_DN = FALSE ; /* Global to mark mii initialization */
- /***************************************************************************
- *
- * idt32438EndLoad - initialize the driver and device
- *
- * This routine initializes both, driver and device to an operational state
- * using device specific parameters specified by <initString>.
- *
- * The parameter string, <initString>, is defined above in the section
- * titled TARGET-SPECIFIC PARAMETRERS.
- *
- * A default number of transmit/receive frames of 20 can be selected by
- * passing zero in the parameters <numTDRs> and <numRDRs>.
- *
- * RETURNS: an END object pointer, NULL on error if initString pointer
- * is NULL or the name of the driver if the initString pointer isn't
- * NULL but initString [0] == NULL.
- *
- */
- END_OBJ * idt32438EndLoad
- (
- char * initString /* parameter string */
- )
- {
- STATUS rtv;
- DRV_CTRL * pDrvCtrl; /* pointer to DRV_CTRL structure */
- UINT32 speed; /* Ethernet speed (100/10) */
- UINT8 eAdrs[ENET_SIZE + 1] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00};
- /*Default ethernet address */
- DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438EndLoad()n",
- 1, 2, 3, 4, 5, 6);
- /* Check for an allocated string. */
- if (initString == (char *)NULL)
- return ((END_OBJ *) NULL);
- /* If a null string, then copy the device's name to the string. */
- if (initString[0] == ' ')
- {
- bcopy ((char *)IDT438_DEV_NAME, initString, IDT438_DEV_NAME_LEN);
- return ((END_OBJ *) NULL);
- }
- /* Allocate the device structure */
- pDrvCtrl = (DRV_CTRL *) calloc (sizeof (DRV_CTRL), 1);
- if (pDrvCtrl == (DRV_CTRL *) NULL)
- return ((END_OBJ *) NULL);
- /* Parse initString, filling in the device structure */
- if (idt32438InitParse (pDrvCtrl, initString) == ERROR)
- goto errorExit;
- /* memory initialization */
- if (idt32438MemInit (pDrvCtrl) == ERROR)
- goto errorExit;
- /* disable DMA and Ethernet Rx and Tx interrupts */
- DMA_INT_DISABLE(pDrvCtrl);
- ETH_DMA_RX_INT_DISABLE(pDrvCtrl);
- ETH_DMA_TX_INT_DISABLE(pDrvCtrl);
- /*
- * Initialize the default parameter for the Physical medium
- * layer control user has his chance to override in the BSP,
- * just be CAREFUL
- */
- pDrvCtrl->board.phyAddr = 0;
- pDrvCtrl->board.phySpeed = PHY_AUTO_SPEED;
- pDrvCtrl->board.phyDpx = PHY_AUTO_DPX;
- /* Ask the BSP to provide the ethernet address. */
- sysEnetAddrGet (pDrvCtrl->unit, &eAdrs[0]);
- /*
- * initialize the ethernet and the phy
- */
- if (idt32438EtherInit (pDrvCtrl, &eAdrs[0]) != OK)
- {
- DRV_LOG (DRV_DEBUG_LOAD,
- "idt32438LoadEnd(): idt32438EtherInit() failed.n",
- 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- /* save Phy speed per configuration */
- if (pDrvCtrl->board.phySpeed == PHY_10MBS)
- speed = PHY_SPEED_10;
- else
- speed = PHY_SPEED_100;
- DRV_LOG (DRV_DEBUG_LOAD, "Speed = %d, Mode = %dn", speed,
- (int) pDrvCtrl->board.phyDpx, 3, 4, 5, 6);
- pDrvCtrl->attached = TRUE;
- /* endObj initializations */
- rtv = END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *) pDrvCtrl,
- IDT438_DEV_NAME, pDrvCtrl->unit, &netFuncs,
- "IDT RC32438 Ethernet Enhanced Network Driver");
- if (rtv == ERROR)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "idt32438LoadEnd(): END_OBJ_INIT() failed.n",
- 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- #ifdef INCLUDE_RFC_1213
- /* Initialize the MIB-II structure */
- rtv = END_MIB_INIT (&pDrvCtrl->endObj,
- M2_ifType_ethernet_csmacd,
- &eAdrs[0],
- ENET_SIZE,
- ETHERMTU,
- speed);
- if (rtv == ERROR)
- {
- DRV_LOG (DRV_DEBUG_LOAD, "idt32438LoadEnd(): END_MIB_INIT() failed.n",
- 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- /* Mark the device ready */
- END_OBJ_READY (&pDrvCtrl->endObj,
- IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST);
- #else /* INCLUDE_RFC_1213 */
- /* Initialize MIB-II entries (for RFC 2233 ifXTable) */
- pDrvCtrl->endObj.pMib2Tbl = m2IfAlloc(M2_ifType_ethernet_csmacd,
- (UINT8*) &eAdrs[0], ENET_SIZE,
- ETHERMTU, speed,
- IDT32438_DEV_NAME, pDrvCtrl->unit);
- if (pDrvCtrl->endObj.pMib2Tbl == NULL)
- {
- DRV_LOG (DRV_DEBUG_ERROR, "MIB-II initialization failedn",
- 1, 2, 3, 4, 5, 6);
- goto errorExit;
- }
- /*
- * Set the RFC2233 flag bit in the END object flags field and
- * install the counter update routines.
- */
- m2IfPktCountRtnInstall(pDrvCtrl->endObj.pMib2Tbl, m2If8023PacketCount);
- /*
- * Make a copy of the data in mib2Tbl struct as well. We do this
- * mainly for backward compatibility issues. There might be some
- * code that might be referencing the END pointer and might
- * possibly do lookups on the mib2Tbl, which will cause all sorts
- * of problems.
- */
- bcopy ((char *)&pDrvCtrl->endObj.pMib2Tbl->m2Data.mibIfTbl,
- (char *)&pDrvCtrl->endObj.mib2Tbl, sizeof (M2_INTERFACETBL));
- /* Mark the device ready */
- END_OBJ_READY (&pDrvCtrl->endObj,
- IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST |
- END_MIB_2233);
- #endif /* INCLUDE_RFC_1213 */
- DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438EndLoad()n",
- 1, 2, 3, 4, 5, 6);
- return (&pDrvCtrl->endObj);
- errorExit:
- DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438EndLoad():errorn",
- 1, 2, 3, 4, 5, 6);
- if (pDrvCtrl != (DRV_CTRL *) NULL)
- {
- idt32438Unload (pDrvCtrl);
- free ((char *) pDrvCtrl);
- }
- return (END_OBJ *) NULL;
- }
- /***************************************************************************
- *
- * idt32438InitParse - parse parameter values from initString
- *
- * This routine parses the initialization string which is specified
- * above in the section TARGET-SPECIFIC PARAMETERS
- *
- * RETURNS: OK or ERROR
- */
- LOCAL STATUS idt32438InitParse
- (
- DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */
- char * initString /* parameter string */
- )
- {
- char * tok; /* an initString token */
- char * holder = (char *)NULL; /* points to string fragment beyond tok */
- UINT32 regBase; /* rc32438 register base addr */
- DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438InitParsen", 1, 2, 3, 4, 5, 6);
- /* get the unit number parameter */
- tok = strtok_r (initString, ":", &holder);
- if (tok == (char *)NULL)
- return ERROR;
- pDrvCtrl->unit = atoi (tok);
- /* ethernet input overflow vector number */
- tok = strtok_r ((char *)NULL, ":", &holder);
- if (tok == (char *)NULL)
- return ERROR;
- pDrvCtrl->ivec = atoi (tok);
- /* rc32438 register base address */
- tok = strtok_r ((char *)NULL, ":", &holder);
- if (tok == (char *)NULL)
- return ERROR;
- regBase = (UINT32) strtoul (tok, NULL, TOKBASE);
- /* get the number of Transmit Frame Descriptors parameter */
- tok = strtok_r ((char *)NULL, ":", &holder);
- if (tok == (char *)NULL)
- return ERROR;
- pDrvCtrl->nTDRs = atoi (tok);
- /* get the number of Receive Frame Descriptors parameter */
- tok = strtok_r ((char *)NULL, ":", &holder);
- if (tok == (char *)NULL)
- return ERROR;
- pDrvCtrl->nRDRs = atoi (tok);
- /* assign the correct base addresses for the DMA, Int Controller
- * and Ethernet devices inside rc32438
- */
- if(pDrvCtrl->unit == 1)
- {
- pDrvCtrl->dmaRegBase = (UINT32)(regBase + IDT_DMA1_REG_OFFSET);
- pDrvCtrl->intRegBase = (UINT32)(regBase + IDT_INTC_REG_OFFSET);
- pDrvCtrl->ethRegBase = (UINT32)(regBase + IDT_ETH1_REG_OFFSET);
- }
- else
- {
- pDrvCtrl->dmaRegBase = (UINT32)(regBase + IDT_DMA0_REG_OFFSET);
- pDrvCtrl->intRegBase = (UINT32)(regBase + IDT_INTC_REG_OFFSET);
- pDrvCtrl->ethRegBase = (UINT32)(regBase + IDT_ETH0_REG_OFFSET);
- }
- /* flags always set to zero on startup */
- pDrvCtrl->flags = 0;
- /* make sure there are enough TDRs */
- if (pDrvCtrl->nTDRs < MIN_NUM_TDRS)
- {
- pDrvCtrl->nTDRs = MIN_NUM_TDRS;
- }
- /* make sure there are enough RDRs */
- if (pDrvCtrl->nRDRs < MIN_NUM_RDRS)
- {
- pDrvCtrl->nRDRs = MIN_NUM_RDRS;
- }
- DRV_LOG (DRV_DEBUG_LOAD2, "idt32438InitParse %x %x %x %xn",
- pDrvCtrl->unit, pDrvCtrl->nTDRs, pDrvCtrl->nRDRs,
- (int)pDrvCtrl->flags, 5, 6);
- DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438InitParsen",
- 1, 2, 3, 4, 5, 6);
- return (OK);
- }
- /******************************************************************************
- *
- * initializeTDRs - Initialize TDR Control Data Structures
- *
- *
- * Initializes the Transmit DMA Descriptor Register data structures.
- *
- * RETURNS: N/A
- */
- LOCAL void initializeTDRs
- (
- DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */
- )
- {
- DMA_DR * pTDR; /* pointer to CFDs */
- DMA_DR * pTDROld;
- int ix; /* a counter */
- /* First ready TDR pointer */
- pTDR = (DMA_DR *) pDrvCtrl->pTDRmem;
- pDrvCtrl->pTDRTail = pDrvCtrl->pTDRHead = pTDR;
- pDrvCtrl->pTDRQStart = (DMA_DR *)NULL;
- pDrvCtrl->cntTDRused = 0;
- pTDROld = &pTDR[pDrvCtrl->nTDRs - 1];
- /* initialize the TDR ring */
- for (ix = 0; ix < pDrvCtrl->nTDRs; ix++)
- {
- /* Initialize DDT */
- pTDR->control = (DMA_DR_CONTROL_IOD | DMA_DR_CONTROL_IOF);
- pTDR->link = 0;
- pTDR->devcs = 0;
- pTDR->pClust = (char *)K0_TO_K1 ((UINT32)netClusterGet (
- pDrvCtrl->endObj.pNetPool,
- pDrvCtrl->pClPoolId));
- pTDR->flags = 0;
- /* Tie the current TDR to the next one */
- pTDR->next = pTDR + 1;
- /* Previous TDR pointer */
- pTDR->prev = pTDROld;
- /* remember this TDR */
- pTDROld = pTDR;
- /* bump to the next TDR */
- pTDR++;
- }
- /* tie the last TDR to the first one */
- pTDR--;
- pTDR->next = pDrvCtrl->pTDRHead;
- DRV_LOG (DRV_DEBUG_MEM, "initializeTDRs: first=%x last=%xn",
- (int)pDrvCtrl->pTDRHead, (int)pDrvCtrl->pTDRHead->prev,
- 3, 4, 5, 6);
- }
- /*******************************************************************************
- *
- * initializeRDRs - Initialize RDR Control Data Structures
- *
- * Initializes Receive DMA Descriptor Register data structures.
- *
- * RETURNS: N/A
- */
- LOCAL void initializeRDRs
- (
- DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */
- )
- {
- DMA_DR * pRDR; /* pointer to RDRs */
- DMA_DR * pRDROld;
- int ix; /* a counter */
- /* First ready RDR pointer */
- pRDR = (DMA_DR *) pDrvCtrl->pRDRmem; /* point to frame descriptor memory */
- pDrvCtrl->pRDR = pRDR;
- pRDROld = &pRDR[pDrvCtrl->nRDRs - 1];
- /* Note: RDRs are keep as a list and not as a ring. this is
- * because in stress situations on the rcv side where you can
- * experience an input overflow, the end RDR in the list must
- * have a link pointer equal to NULL. this will stop the DMA
- * from continuing around the ring. this is important because
- * a disable then enable of the ethernet and DMA is required
- * on input overflow and the DMA behaviour isn't repeatable if
- * the last RDR doesn't have a NULL pointer for the link. the
- * DMA will not always restart in a repeatable way.
- */
- /* initialize the RDR list */
- for (ix = 0; ix < pDrvCtrl->nRDRs; ix++)
- {
- pRDR->control = RDR_CONTROL_VAL;
- pRDR->link = K1_TO_PHYS ((UINT32)(pRDR + 1));
- pRDR->devcs = 0;
- pRDR->flags = 0;
- /* add offset to descriptor buffer so buffer is correctly aligned */
- pRDR->pClust = (char *)K0_TO_K1((
- netClusterGet (pDrvCtrl->endObj.pNetPool,
- pDrvCtrl->pClPoolId)) + CLUST_BUF_OFFSET);
- pRDR->ca = K1_TO_PHYS ((UINT32)pRDR->pClust);
- /* Tie the previous RDR to the current one */
- pRDR->next = pRDR + 1;
- pRDR->prev = pRDROld;
- /* remember this RDR */
- pRDROld = pRDR;
- /* bump to the next RDR */
- pRDR++;
- }
- /* Tie the Last RDR link to NULL finishing the linked list */
- pRDR--;
- pRDR->link = (UINT32)NULL;;
- pRDR->next = pDrvCtrl->pRDR;
- DRV_LOG (DRV_DEBUG_MEM, "initializeRDRs: first=%x last=%xn",
- (int)pDrvCtrl->pRDR, (int)pDrvCtrl->pRDR->prev, 3, 4, 5, 6);
- }
- /***************************************************************************
- *
- * idt32438MemInit - Initialize memory
- *
- * This routine initializes the transmit and receive descriptor lists
- *
- * RETURNS: OK or ERROR
- */
- LOCAL STATUS idt32438MemInit
- (
- DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */
- )
- {
- UINT32 nRDRLoan;
- CL_DESC clDesc;
- M_CL_CONFIG mClBlkConfig;
- int memTDRsize;
- int memRDRsize;
- DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438MemInit()n", 1, 2, 3, 4, 5, 6);
- /* this driver can't handle write incoherent caches */
- if (!CACHE_DMA_IS_WRITE_COHERENT ())
- {
- DRV_LOG (DRV_DEBUG_ERROR,
- "idt32438MemInit: shared memory not cache coherentn",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* allocate memory for transmit descriptor registers. Get
- * the memory from non-cached space
- */
- memTDRsize = pDrvCtrl->nTDRs * sizeof (DMA_DR);
- pDrvCtrl->pTDRmem = cacheDmaMalloc (memTDRsize);
- /* allocate memory for receive descriptor registers. Get
- * the memory from non-cached space
- */
- memRDRsize = pDrvCtrl->nRDRs * sizeof (DMA_DR);
- pDrvCtrl->pRDRmem = cacheDmaMalloc (memRDRsize);
- if ((pDrvCtrl->pTDRmem == NULL) || (pDrvCtrl->pRDRmem == NULL))
- {
- DRV_LOG (DRV_DEBUG_ERROR, "idt32438MemInit: could not obtain memoryn",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* zero the descriptor memory */
- memset (pDrvCtrl->pTDRmem, 0, memTDRsize);
- memset (pDrvCtrl->pRDRmem, 0, memRDRsize);
- /*
- * Calculate the number of clusters, their size, and the memory size for
- * all the clusters. Then allocate memory for the clusters.
- */
- nRDRLoan = (pDrvCtrl->nRDRs * 4);
- clDesc.clNum = pDrvCtrl->nRDRs +
- pDrvCtrl->nRDRs +
- nRDRLoan;
- clDesc.clSize = IDT_BUFSIZ ;
- clDesc.memSize = (clDesc.clNum * (clDesc.clSize + sizeof(long) )) +
- sizeof (long);
- clDesc.memArea = memalign (sizeof (long), clDesc.memSize);
- pDrvCtrl->clBaseAddr = clDesc.memArea;
- if (clDesc.memArea == (char *) NULL)
- {
- DRV_LOG (DRV_DEBUG_ERROR, "System memory unavaiablen",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- DRV_LOG (DRV_DEBUG_INFO, "Memory alignment clDesc.memArea:%xn",
- (int)clDesc.memArea, 2, 3, 4, 5, 6);
- /* Set 5 times as many mBlk's as clusters. */
- mClBlkConfig.mBlkNum = clDesc.clNum * 2;
- /* Set the number of clusters. */
- mClBlkConfig.clBlkNum = clDesc.clNum;
- /*
- * total memory size for mBlks and clBlks
- * get memory for mblks
- * memory size adjusted to hold the netPool pointer at the head
- */
- mClBlkConfig.memSize =
- (mClBlkConfig.mBlkNum * (M_BLK_SZ + sizeof (long))) +
- (mClBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof (long)));
- mClBlkConfig.memArea = (char *) memalign (sizeof (long),
- mClBlkConfig.memSize);
- if (mClBlkConfig.memArea == (char *) NULL)
- {
- DRV_LOG (DRV_DEBUG_ERROR, "Memory align (by %d) failed, memSize %xn",
- sizeof (long), (int) mClBlkConfig.memSize, 3, 4, 5, 6);
- return (ERROR);
- }
- /* store the pointer to the cluster area */
- pDrvCtrl->pMemArea = mClBlkConfig.memArea;
- /* Allocate the network pool. */
- pDrvCtrl->endObj.pNetPool = (NET_POOL_ID)malloc (sizeof (NET_POOL));
- if (pDrvCtrl->endObj.pNetPool == (NET_POOL_ID)NULL)
- {
- DRV_LOG (DRV_DEBUG_ERROR, "pNetPool alloc failed for size %dn",
- sizeof (NET_POOL), 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* init the mem pool */
- if (netPoolInit (pDrvCtrl->endObj.pNetPool, &mClBlkConfig,
- &clDesc, 1, (POOL_FUNC *)NULL) == ERROR)
- {
- DRV_LOG (DRV_DEBUG_ERROR, "netPoolInit() failed.n",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->endObj.pNetPool,
- IDT_BUFSIZ, FALSE);
- if (pDrvCtrl->pClPoolId == (CL_POOL_ID)NULL)
- {
- DRV_LOG (DRV_DEBUG_ERROR, "netClPoolIdGet() returned NULL pool ID.n",
- 1, 2, 3, 4, 5, 6);
- return (ERROR);
- }
- /* We are setting up the TDRs as a fixed ring */
- initializeTDRs (pDrvCtrl);
- /* We are setting up the RDRs as a fixed ring */
- initializeRDRs (pDrvCtrl);
- DRV_LOG (DRV_DEBUG_ENTRY, "<== idt32438MemInitn",
- 1, 2, 3, 4, 5, 6);
- return (OK);
- }
- /***************************************************************************
- *
- * idt32438Send - send an Ethernet packet
- *
- * This routine() takes a M_BLK_ID and sends off the data in the M_BLK_ID.
- * The buffer must already have the addressing information properly installed
- * in it. This is done by a higher layer.
- *
- * muxSend() calls this routine each time it wants to send a packet.
- *
- * RETURNS: ERROR if not valid parameters or OK
- */
- LOCAL STATUS idt32438Send
- (
- DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */
- M_BLK_ID pMblk /* pointer to the mBlk/cluster pair */
- )
- {
- M_BLK_ID pMblkTmp; /* pointer to pMblk for counting mNext segments */
- int mblks; /* number of Mblks in packet */
- int len;
- int totalLen ;
- DMA_DR * pTDR;
- DMA_DR * pTDRFirst;
- int intKey;
- DRV_LOG (DRV_DEBUG_ENTRY, "==> idt32438Send()n", 1, 2, 3, 4, 5, 6);
- /* check device mode and validate mBlk pointer */
- if ((pDrvCtrl->flags & IDT_POLLING) != 0)
- {
- netMblkClChainFree (pMblk);
- errno = EINVAL;
- return (ERROR);
- }
- else if (pMblk == (M_BLK_ID)NULL)
- {
- errno = EINVAL;
- return (ERROR);
- }
- /* interlock with Interrupt ISR/DPC task */
- END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
- /* count the number of mblks in this packet */
- for (mblks = 0, pMblkTmp = pMblk;pMblkTmp != (M_BLK_ID)NULL;
- pMblkTmp = pMblkTmp->mBlkHdr.mNext, mblks++)
- {
- len = pMblkTmp->mBlkHdr.mLen;
- (void)cacheFlush (DATA_CACHE, pMblkTmp->mBlkHdr.mData, len);
- totalLen += len;
- }
- /* stall if not enough TDR's available for this mBlk */
- if (mblks > (pDrvCtrl->nTDRs - pDrvCtrl->cntTDRused))
- {
- DRV_LOG (DRV_DEBUG_ERROR,