⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_eihk.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define DRV_CTRL_SIZ  sizeof(DRV_CTRL)#define EI_RX_TIMEOUT 3         /* # watchdog runs for receive timeout */#define EI_TX_TIMEOUT 2         /* # watchdog runs for transmit timeout *//***** GLOBALS *****//* Function declarations not in any header files */IMPORT void   sysSpareInt1 (int arg);			/* hkv3500 specific */IMPORT STATUS sysEnetAddrGet (int unit, char addr[]);IMPORT STATUS sys596Init (int unit, SCB *pScb);IMPORT STATUS sys596IntAck (int unit);IMPORT STATUS sys596IntEnable (int unit);IMPORT void   sys596IntDisable (int unit);IMPORT void   sys596Port (int unit, int cmd, UINT32 addr);IMPORT void   sys596ChanAtn (int unit);/***** LOCALS *****//* The array of driver control structs */LOCAL DRV_CTRL drvCtrl [MAX_UNITS];/* forward function declarations */static STATUS eiInit (int unit);static void eiReset (int unit);static int eiIoctl (IDR *pIDR, int cmd, caddr_t data);#ifdef BSD43_DRIVERstatic int eiOutput (IDR *pIDR, MBUF *pMbuf, SOCK *pDestAddr);static void eiTxStartup (int unit);#elsestatic void eiTxStartup (DRV_CTRL *pDrvCtrl);#endifvoid eiInt (DRV_CTRL *pDrvCtrl);static void eiTxCleanQ (DRV_CTRL *pDrvCtrl);static void eiHandleRecvInt (DRV_CTRL *pDrvCtrl);static STATUS eiReceive (DRV_CTRL *pDrvCtrl, RFD *pRfd);static void eiLoanFree (DRV_CTRL *pDrvCtrl, RFD *pRfd);static void eiDiag (int unit);static void eiConfig (int unit);static void eiIASetup (int unit);static void eiRxStartup (DRV_CTRL *pDrvCtrl);static void eiAction (int unit, UINT16 action);static STATUS eiCommand (DRV_CTRL *pDrvCtrl, UINT16 cmd);static void eiTxQPut (DRV_CTRL *pDrvCtrl, TFD *pTfd);static void eiTxQFlush (DRV_CTRL *pDrvCtrl);static void eiRxQPut (DRV_CTRL *pDrvCtrl, RFD *pRfd);static RFD *eiRxQGet (DRV_CTRL *pDrvCtrl);static BOOL eiRxQFull (DRV_CTRL *pDrvCtrl);static void eiQInit (EI_LIST *pHead);static EI_NODE *eiQGet (EI_LIST *pQueue);static void eiQPut (int unit, EI_LIST *pQueue, EI_NODE *pNode);static STATUS eiDeviceStart (int unit);static void eiWatchDog(int unit);/********************************************************************************* eihkattach - publish the `ei' network interface and initialize the driver and device** This routine publishes the `ei' interface by filling in a network interface* record and adding this record to the system list.  This routine also* initializes the driver and the device to the operational state.** The 82596 shares a region of memory with the driver.  The caller of this* routine can specify the address of this memory region, or can specify that* the driver must obtain this memory region from the system resources.** The <sysbus> parameter accepts values as described in the Intel manual* for the 82596.  A default number of transmit/receive frames of 32 can be* selected by passing zero in the parameters <nTfds> and <nRfds>.* In other cases, the number of frames selected should be greater than two.** The <memBase> parameter is used to inform the driver about the shared* memory region.  If this parameter is set to the constant "NONE," then this* routine will attempt to allocate the shared memory from the system.  Any* other value for this parameter is interpreted by this routine as the address* of the shared memory region to be used.** If the caller provides the shared memory region, then the driver assumes* that this region does not require cache coherency operations, nor does it* require conversions between virtual and physical addresses.** If the caller indicates that this routine must allocate the shared memory* region, then this routine will use cacheDmaMalloc() to obtain* some  non-cacheable memory.  The attributes of this memory will be checked,* and if the memory is not both read and write coherent, this routine will* abort and return ERROR.** RETURNS: OK or ERROR.** SEE ALSO: ifLib,* .I "Intel 82596 User's Manual"*/STATUS eihkattach    (    int         unit,       /* unit number */    int         ivec,       /* interrupt vector number */    UINT8       sysbus,     /* sysbus field of SCP */    char *      memBase,    /* address of memory pool or NONE */    int         nTfds,      /* no. of transmit frames (0 = default) */    int         nRfds       /* no. of receive frames (0 = default) */    )    {    DRV_CTRL    *pDrvCtrl;    UINT        size;                           /* temporary size holder */    UINT        sizeScp;    UINT        sizeIscp;    UINT        sizeScb;    UINT        sizeCfd;    RFD *       pRfd;                   /* pointer to RFD's */    int         ix;    static char *errMsg1 = "\neihkattach: could not obtain memory\n";    static char *errMsg2 = "\neihkattach: shared memory not cache coherent\n";    sizeScp  = MEM_ROUND_UP (sizeof (SCP));    sizeIscp = MEM_ROUND_UP (sizeof (ISCP));    sizeScb  = MEM_ROUND_UP (sizeof (SCB));    sizeCfd  = MEM_ROUND_UP (sizeof (CFD));    /* Sanity check the unit number */    if (unit < 0 || unit >= MAX_UNITS)        return (ERROR);    /* Ensure single invocation per system life */    pDrvCtrl = & drvCtrl [unit];    if (pDrvCtrl->attached)        return (OK);    /* Determine number of Tx and Rx descriptors to use */    pDrvCtrl->nTFDs = nTfds ? nTfds : DEF_NUM_TFDS;    pDrvCtrl->nRFDs = nRfds ? nRfds : DEF_NUM_RFDS;    /* Publish the interface record */#ifdef BSD43_DRIVER    ether_attach ( (IFNET *)&pDrvCtrl->idr, unit, "ei", (FUNCPTR)NULL,                   (FUNCPTR) eiIoctl, (FUNCPTR) eiOutput, (FUNCPTR) eiReset);#else    ether_attach (                  &pDrvCtrl->idr.ac_if,                  unit,                  "ei",                  (FUNCPTR) NULL,                 (FUNCPTR) eiIoctl,                  (FUNCPTR) ether_output,                  (FUNCPTR) eiReset                 );    pDrvCtrl->idr.ac_if.if_start = (FUNCPTR)eiTxStartup;#endif    /* calculate the total size of 82596 memory pool */    size =            16 +                                /* allow for alignment */            sizeScp +            sizeIscp +            sizeScb +            sizeCfd +                           /* synch'ed command frame */            (sizeof (RFD) * pDrvCtrl->nRFDs) +  /* pool of receive frames */            (sizeof (TFD) * pDrvCtrl->nTFDs);   /* pool of transmit frames */    /* Establish the memory area that we will share with the device.  If     * the caller has provided an area, then we assume it is non-cacheable     * and will not require the use of the special cache routines.     * If the caller did not provide an area, then we must obtain it from     * the system, using the cache savvy allocation routine.     */    switch ((int) memBase)        {        case NONE :                            /* we must obtain it */            /* this driver can't handle incoherent caches */            if (!CACHE_DMA_IS_WRITE_COHERENT () ||                !CACHE_DMA_IS_READ_COHERENT ())                {                printf (errMsg2);                goto error;                }            pDrvCtrl->memBase = cacheDmaMalloc (size);            if (pDrvCtrl->memBase == NULL)    /* no memory available */                {                printf (errMsg1);                goto error;                }            pDrvCtrl->cacheFuncs = cacheDmaFuncs;            break;        default :                               /* the user provided an area */            pDrvCtrl->memBase = memBase;        /* use the provided address */            pDrvCtrl->cacheFuncs = cacheNullFuncs;            break;        }    /* Save other passed-in parameters */    pDrvCtrl->sysbus = sysbus;                  /* remember sysbus value */    pDrvCtrl->ivec = ivec;                      /* interrupt vector */    /* Carve up the shared memory region into the specific sections */    bzero ((char *) pDrvCtrl->memBase, size);    pDrvCtrl->pScp  = (SCP *)                /* align to first 16 byte page */                      ( ((u_long) pDrvCtrl->memBase + 0xf) & ~0xf );    pDrvCtrl->pIscp = (ISCP *)((int)pDrvCtrl->pScp   + sizeScp);    pDrvCtrl->pScb  = (SCB *) ((int)pDrvCtrl->pIscp  + sizeIscp);    pDrvCtrl->pCfd  = (CFD *) ((int)pDrvCtrl->pScb   + sizeScb);    pDrvCtrl->rfdPool   = (RFD *) ((int)pDrvCtrl->pCfd   + sizeCfd);    pDrvCtrl->tfdPool = (TFD *)            ((int)pDrvCtrl->rfdPool+ (sizeof (RFD) * pDrvCtrl->nRFDs));    for (ix = 0, pRfd = pDrvCtrl->rfdPool; ix < DEF_NUM_RFDS; ix++, pRfd++)        {        pRfd->refCnt	= 0;                    /* initialize ref cnt */        }    /* Init the watchdog that will patrol for device lockups */     pDrvCtrl->transLocks = 0;    pDrvCtrl->recvLocks = 0;    pDrvCtrl->wid = wdCreate ();                      /* create watchdog */    if (pDrvCtrl->wid == NULL)                        /* no resource */        goto error;    pDrvCtrl->wdInterval = sysClkRateGet() >> 1;    /* get our enet addr */    if (sysEnetAddrGet (unit, (char *)pDrvCtrl->idr.ac_enaddr) == ERROR)	{	errnoSet (S_iosLib_INVALID_ETHERNET_ADDRESS);        goto error;	}    /* initialize the unit */    if (eiInit (unit) == ERROR)        goto error;    /* Set our flag */    pDrvCtrl->attached = TRUE;    /* Set status flags in IDR */    pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);    /* Successful return */    return (OK);    /***** Handle error cases *****/    error:        {        /* Release system memory */        if (((int) memBase == NONE) && ((int) pDrvCtrl->memBase != NULL))            cacheDmaFree (pDrvCtrl->memBase);        /* Release watchdog */        if (pDrvCtrl->wid != NULL)            wdDelete (pDrvCtrl->wid);        return (ERROR);        }    }/********************************************************************************* eiInit - Initialize the interface.** Initialization of interface; clear recorded pending operations.* Called at boot time and by eiWatchDog() if a reset is required.** RETURNS: OK or ERROR*/static STATUS eiInit     (    int unit			/* unit number */    )    {    DRV_CTRL    *pDrvCtrl = & drvCtrl [unit];    pDrvCtrl->rcvHandling   = FALSE;  /* netTask not running our receive job */    pDrvCtrl->txCleaning    = FALSE;  /* netTask not running our clean job */    pDrvCtrl->txIdle        = TRUE;         /* transmitter idle */    eiQInit ((EI_LIST *)&pDrvCtrl->rxQueue);    /* to be received queue */    eiQInit ((EI_LIST *)&pDrvCtrl->txQueue);    /* to be sent queue */    eiQInit ((EI_LIST *)&pDrvCtrl->tfdQueue);   /* free tfds to add to send q */    eiQInit ((EI_LIST *)&pDrvCtrl->cblQueue);   /* actively sending queue */    eiQInit ((EI_LIST *)&pDrvCtrl->cleanQueue); /* queue of TFDs to clean */    pDrvCtrl->wdTxTimeout = 0;    pDrvCtrl->wdRxTimeout = 0;    { /***** Perform device initialization *****/    /* Block local variables */    int ix;    sys596IntDisable (unit);            /* disable device interrupts */    (void) sys596Init (unit, pDrvCtrl->pScb);  /* do board specific init */    /* Connect the interrupt handler */    /* Note: hkv3500 BSP demultiplexes interrupt in sysSpareInt1() */    if (intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),		    sysSpareInt1, (int)pDrvCtrl) == ERROR)        return (ERROR);    /* Start the device */    if ( eiDeviceStart (unit) == ERROR )        return (ERROR);    eiDiag (unit);                             /* run diagnostics */    eiConfig (unit);                           /* configure chip */    eiIASetup (unit);                          /* setup address */    for (ix = 0; ix < pDrvCtrl->nTFDs; ix ++)  /* tank up the free tfd queue */        {        eiQPut  (                unit,                (EI_LIST *) & pDrvCtrl->tfdQueue,                (EI_NODE *) & pDrvCtrl->tfdPool [ix]                );        }    pDrvCtrl->pFreeRfd  = NULL;                  /* first free RFD */    pDrvCtrl->nLoanRfds = MAX_RFDS_LOANED;       /* number of loanable RFD's */    for (ix = 0; ix < pDrvCtrl->nRFDs; ix ++)   /* tank up the receive queue */	{	if (pDrvCtrl->rfdPool[ix].refCnt == 0)	        eiRxQPut (pDrvCtrl, & pDrvCtrl->rfdPool [ix]);	}    sys596IntAck (unit);                     /* clear any pended dev ints */    sys596IntEnable (unit);                  /* enable interrupts at system */    } /* End block */    wdCancel(pDrvCtrl->wid);                  /* in case re-initializing */    wdStart(pDrvCtrl->wid, 	    (int) pDrvCtrl->wdInterval, 	    (FUNCPTR) eiWatchDog, 	    pDrvCtrl->idr.ac_if.if_unit

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -