📄 ei82596end.c
字号:
IMPORT void sys596Port (int unit, int cmd, UINT32 addr);IMPORT void sys596ChanAtn (int unit);/* forward function declarations */LOCAL STATUS ei82596InitParse (END_CTRL *pDrvCtrl, char *initString);LOCAL STATUS ei82596InitMem (END_CTRL *pDrvCtrl);LOCAL STATUS ei82596Diag (END_CTRL *pDrvCtrl);LOCAL void ei82596Config (END_CTRL *pDrvCtrl);LOCAL STATUS ei82596MCastConfig (END_CTRL *pDrvCtrl);LOCAL void ei82596IASetup (END_CTRL *pDrvCtrl);LOCAL void ei82596RxStartup (END_CTRL *pDrvCtrl);LOCAL void ei82596Action (END_CTRL *pDrvCtrl, UINT16 action);LOCAL STATUS ei82596Command (END_CTRL *pDrvCtrl, UINT16 cmd);LOCAL void ei82596TxQPut (END_CTRL *pDrvCtrl, TFD *pTfd);LOCAL void ei82596RxQPut (END_CTRL *pDrvCtrl, RFD *pRfd);LOCAL void ei82596TxQFlush (END_CTRL *pDrvCtrl);LOCAL RFD * ei82596RxQGet (END_CTRL *pDrvCtrl);LOCAL BOOL ei82596RxQFull (END_CTRL *pDrvCtrl);LOCAL void ei82596QInit (volatile EI_LIST *pHead);LOCAL EI_NODE * ei82596QGet (volatile EI_LIST *pQueue);LOCAL void ei82596QPut (END_CTRL *pDrvCtrl, EI_LIST *pQueue, EI_NODE *pNode);LOCAL void ei82596QCat (volatile EI_LIST *pQDest, volatile EI_LIST *pQSrc);LOCAL STATUS ei82596DeviceStart (END_CTRL *pDrvCtrl);LOCAL void ei82596WatchDog (END_CTRL *pDrvCtrl);LOCAL void ei82596Recv (END_CTRL *pDrvCtrl, RFD *pRfd);LOCAL void ei82596TxCleanQ (END_CTRL *pDrvCtrl);LOCAL void ei82596RxIntHandle (END_CTRL *pDrvCtrl);LOCAL void ei82596Int (END_CTRL *pDrvCtrl);LOCAL void ei82596DeviceRestart(END_CTRL *pDrvCtrl);/* END Specific interfaces. */END_OBJ * ei82596EndLoad (char *initString);LOCAL STATUS ei82596Unload (END_CTRL *pDrvCtrl);LOCAL STATUS ei82596Start(END_CTRL *pDrvCtrl);LOCAL STATUS ei82596Stop(END_CTRL *pDrvCtrl);LOCAL int ei82596Ioctl (END_CTRL *pDrvCtrl, int cmd, caddr_t data);LOCAL STATUS ei82596Send (END_CTRL *pDrvCtrl, M_BLK_ID pMblk);LOCAL STATUS ei82596MCastAdrsAdd (END_CTRL *pDrvCtrl, char* pAddress);LOCAL STATUS ei82596MCastAdrsDel (END_CTRL *pDrvCtrl, char* pAddress);LOCAL STATUS ei82596MCastAdrsGet (END_CTRL *pDrvCtrl, MULTI_TABLE *pTable);LOCAL STATUS ei82596PollSend (END_CTRL *pDrvCtrl, M_BLK_ID pMblk);LOCAL STATUS ei82596PollReceive (END_CTRL *pDrvCtrl, M_BLK_ID pMblk);LOCAL STATUS ei82596PollStart (END_CTRL *pDrvCtrl);LOCAL STATUS ei82596PollStop (END_CTRL *pDrvCtrl);/* * Define the device function table. This is static across all driver * instances. */LOCAL NET_FUNCS netFuncs = { (FUNCPTR)ei82596Start, /* start func. */ (FUNCPTR)ei82596Stop, /* stop func. */ (FUNCPTR)ei82596Unload, /* unload func. */ (FUNCPTR)ei82596Ioctl, /* ioctl func. */ (FUNCPTR)ei82596Send, /* send func. */ (FUNCPTR)ei82596MCastAdrsAdd, /* multicast add func. */ (FUNCPTR)ei82596MCastAdrsDel, /* multicast delete func. */ (FUNCPTR)ei82596MCastAdrsGet, /* multicast get fun. */ (FUNCPTR)ei82596PollSend, /* polling send func. */ (FUNCPTR)ei82596PollReceive, /* polling receive func. */ endEtherAddressForm, /* put address info into a NET_BUFFER. */ endEtherPacketDataGet, /* get pointer to data in NET_BUFFER. */ endEtherPacketAddrGet /* Get packet addresses. */ }; /* network buffers configuration */M_CL_CONFIG eiMclBlkConfig = { 0, 0, NULL, 0};CL_DESC eiClDescTbl [] ={ /* clusterSize num memArea memSize ----------- ---- ------- ------- */ {ETHERMTU + EH_SIZE + 2, 0, NULL, 0}}; int eiClDescTblNumEnt = (NELEMENTS(eiClDescTbl));/********************************************************************************* ei82596EndLoad - initialize the driver and device** This routine initializes both driver and device to an operational state* using the device-specific values specified by <initString>.* The <initString> parameter expects an ordered list of colon-separated * values. * * The format of the <initString> is:* * <unit>:<ivec>:<sysbus>:<memBase>:<nTfds>:<nRfds>** .IP <unit>* Specifies the unit number for this device.* .IP <ivec>* This is the interrupt vector number of the hardware interrupt generated by* this Ethernet device. The driver uses intConnect() to attach an interrupt* handler for this interrupt.* .IP <sysbus> * Passes in 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.* .IP <memBase> * Informs the driver about the shared memory region. 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. If this parameter * is set to the constant "NONE", this routine tries 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, 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, this routine uses cacheDmaMalloc() to obtain some non-cacheable * memory. The attributes of this memory are checked, and, if the memory is * not both read- and write-coherent, this routine aborts.* .LP** RETURNS: An END object pointer or NULL.** SEE ALSO: ifLib,* .I "Intel 82596 User's Manual"*/END_OBJ *ei82596EndLoad ( char * initString /* parameter string */ ) { END_CTRL *pDrvCtrl; UCHAR eAdrs[EADDR_LEN]; /* ethernet address */ RFD *pRfd; int ix; if (initString == NULL) return (NULL); if (initString[0] == 0) { bcopy((char *)DRV_NAME, initString, DRV_NAME_LEN); return (0); } /* Allocate a control structure for this device */ pDrvCtrl = calloc (sizeof(END_CTRL), 1); if (pDrvCtrl == NULL) return (NULL); /* Parse InitString */ if (ei82596InitParse (pDrvCtrl, initString) == ERROR) return (NULL);#ifdef DRV_DEBUG pEndCtrl=pDrvCtrl;#endif /* DRV_DEBUG */ /* endObj initializations */ if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ*) pDrvCtrl, DRV_NAME, pDrvCtrl->unit, &netFuncs, "Intel 82596 Ethernet Enhanced Network Driver") == ERROR) return (NULL); /* memory initialization */ if (ei82596InitMem (pDrvCtrl) == ERROR) goto error; /* Initialize a watchdog for device lockups */ pDrvCtrl->txLockups = 0; pDrvCtrl->rxLockups = 0; pDrvCtrl->wid = wdCreate (); /* create watchdog */ if (pDrvCtrl->wid == NULL) /* no resource */ goto error; pDrvCtrl->wdInterval = sysClkRateGet() >> 1; /* Get our enet addr */ if (sysEnetAddrGet (pDrvCtrl->unit, eAdrs) == ERROR) { errnoSet (S_iosLib_INVALID_ETHERNET_ADDRESS); goto error; } /* Initialize MIB-II entries */ if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd, eAdrs, 6, ETHERMTU, EI_SPEED) == ERROR) goto error; pDrvCtrl->txIdle = TRUE; pDrvCtrl->rxHandling = FALSE; pDrvCtrl->txCleaning = FALSE; ei82596QInit (&pDrvCtrl->rxQueue); /* to be received queue */ ei82596QInit (&pDrvCtrl->txQueue); /* to be sent queue */ ei82596QInit (&pDrvCtrl->freeQueue); /* free tfds for the send q */ ei82596QInit (&pDrvCtrl->cblQueue); /* actively sending queue */ ei82596QInit (&pDrvCtrl->cleanQueue);/* queue of TFDs to clean */ pDrvCtrl->wdTxTimeout = 0; pDrvCtrl->wdRxTimeout = 0; for (ix = 0; ix < pDrvCtrl->nTFDs; ix ++) /* tank up the free tfd queue */ { ei82596QPut (pDrvCtrl, (EI_LIST *) & pDrvCtrl->freeQueue, (EI_NODE *) & pDrvCtrl->tfdPool [ix]); } for (ix = 0; ix < pDrvCtrl->nRFDs; ix ++) /* tank up the receive queue */ { static BOOL first = TRUE; pRfd = (RFD *) netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId); if (pRfd == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "Could not get an RFD buffer\n", 1, 2, 3, 4, 5, 6); goto error; } /* offset pRfd if needed */ pRfd = (RFD *) (((char *) pRfd) + pDrvCtrl->offset); pRfd->status = 0; pRfd->command = 0; if (first) { pDrvCtrl->pFreeRfd = pRfd; first = FALSE; } pRfd->bufSize = ETHERMTU + EH_SIZE; /* max packet size */ LINK_WR (& pRfd->lBufDesc, 0xffffffff); /* no RDB */ ei82596QPut (pDrvCtrl, (EI_LIST *) &pDrvCtrl->rxQueue, (EI_NODE *) pRfd); } pRfd = (RFD *) pDrvCtrl->rxQueue.tail; pRfd->command = CFD_C_EL; /* end of list */ /* Mark the device ready */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST); /* Successful return */ return (&pDrvCtrl->endObj); /***** Handle error cases *****/ error: { ei82596Unload (pDrvCtrl); return (NULL); } }/********************************************************************************* ei82596Unload - unload a driver from the system** This routine deallocates lists, and free allocated memory.** RETURNS: OK, always.*/LOCAL STATUS ei82596Unload ( END_CTRL *pDrvCtrl ) { DRV_LOG (DRV_DEBUG_LOAD, "eiUnload\n", 0, 0, 0, 0, 0, 0); /* deallocate lists */ END_OBJ_FREE (&pDrvCtrl->endObj); /* Free the allocated watchdog */ if (pDrvCtrl->wid != NULL) wdDelete (pDrvCtrl->wid); /* deallocate allocated shared memory */ if (DRV_FLAGS_ISSET (EI_MEMOWN) && pDrvCtrl->memBase) cacheDmaFree (pDrvCtrl->memBase); return (OK); }/********************************************************************************* ei82596InitParse - parse parameter values from initString** RETURNS: OK or ERROR.*/LOCAL STATUS ei82596InitParse ( END_CTRL *pDrvCtrl, char *initString ) { char * tok; /* an initString token */ char * holder=NULL; /* points to initString fragment beyond tok */ tok = strtok_r(initString, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi(tok); tok=strtok_r(NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->ivec = strtoul (tok, NULL, 16); tok=strtok_r(NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->sysbus = (UINT8) strtoul (tok, NULL, 16); tok=strtok_r(NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->memBase = (char *) strtoul (tok, NULL, 16); tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->nTFDs = atoi (tok); if (!pDrvCtrl->nTFDs || pDrvCtrl->nTFDs == -1) pDrvCtrl->nTFDs = DEF_NUM_TFDS; tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return ERROR; pDrvCtrl->nRFDs = atoi (tok); if (!pDrvCtrl->nRFDs || pDrvCtrl->nRFDs == -1) pDrvCtrl->nRFDs = DEF_NUM_RFDS; pDrvCtrl->offset = -1; tok = strtok_r (NULL, ":", &holder); if (tok != NULL) { pDrvCtrl->offset = atoi (tok); } if (pDrvCtrl->offset == -1) pDrvCtrl->offset = 0; DRV_LOG (DRV_DEBUG_LOAD, "eiEndLoad: unit=%d ivec=0x%x sysbus=0x%x membase=0x%x " "nTfds=%d nRfds=%d\n", pDrvCtrl->unit, pDrvCtrl->ivec, pDrvCtrl->sysbus, (int)pDrvCtrl->memBase, pDrvCtrl->nTFDs, pDrvCtrl->nRFDs); if (pDrvCtrl->offset) DRV_LOG (DRV_DEBUG_LOAD, "eiEndLoad: unit=%d offset=%d\n", pDrvCtrl->unit, pDrvCtrl->offset, 0, 0, 0, 0); return OK; }/********************************************************************************* ei82596InitMem - initialize memory** RETURNS: OK or ERROR*/LOCAL STATUS ei82596InitMem ( END_CTRL * pDrvCtrl ) { UINT size; UINT sizeScp; UINT sizeIscp; UINT sizeScb; UINT sizeCfd; static char *errMsg1 = "\nei82596EndLoad: could not obtain memory\n"; static char *errMsg2 = "\nei82596EndLoad: shared memory not cache" "coherent\n"; /* initialize the netPool */ if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); if (eiMclBlkConfig.mBlkNum == 0) /* pool of mblks */ eiMclBlkConfig.mBlkNum = pDrvCtrl->nRFDs * 4; if (eiClDescTbl [0].clNum == 0) {/* pool of receive frames */ eiClDescTbl[0].clNum = pDrvCtrl->nRFDs * 2; eiClDescTbl[0].clSize = MEM_ROUND_UP(sizeof (RFD) + pDrvCtrl->offset); } if (eiMclBlkConfig.clBlkNum == 0) /* pool of cluster blks */ eiMclBlkConfig.clBlkNum = eiClDescTbl[0].clNum; /* Force word (4-byte) alignment */ sizeScp = MEM_ROUND_UP (sizeof (SCP)); sizeIscp = MEM_ROUND_UP (sizeof (ISCP)); sizeScb = MEM_ROUND_UP (sizeof (SCB)); sizeCfd = MEM_ROUND_UP (sizeof (CFD)); /* calculate the total size of 82596 memory pool */ size = 16 + /* allow for alignment */ sizeScp + sizeIscp + sizeScb + sizeCfd + /* synch'ed command frame */ (((eiClDescTbl[0].clSize + 4) * eiClDescTbl[0].clNum) + 4) +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -