📄 nicevbend.c
字号:
** This routine can be called in two modes. If it is called with an empty but* allocated string, it places the name of this device (that is, "ln") into * the <initString> and returns 0.** If the string is allocated and not empty, the routine attempts to load* the driver using the values specified in the string.** RETURNS: An END object pointer, or NULL on error, or 0 and the name of the* device if the <initString> was NULL.*/END_OBJ* nicEvbEndLoad ( char* initString /* string to be parse by the driver */ ) { NICEVB_END_DEVICE *pDrvCtrl; DRV_LOG (DRV_DEBUG_LOAD, "Loading nic...\n", 1, 2, 3, 4, 5, 6); if (initString == NULL) return (NULL); if (initString[0] == NULL) { bcopy((char *)NIC_EVB_DEV_NAME, initString, NIC_EVB_DEV_NAME_LEN); return (0); } /* allocate the device structure */ pDrvCtrl = (NICEVB_END_DEVICE *)calloc (sizeof (NICEVB_END_DEVICE), 1); if (pDrvCtrl == NULL) goto errorExit; /* init device object */ pDrvCtrl->pRxCluster = NULL; pDrvCtrl->flags = 0x00; /* parse the init string, filling in the device structure */ if (nicEvbInitParse (pDrvCtrl, initString) == ERROR) goto errorExit; /* Have the BSP hand us our address. */ SYS_ENET_ADDR_GET(pDrvCtrl,(char*)&(pDrvCtrl->enetAddr)); /* initialize the END and MIB2 parts of the structure */ if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, NIC_EVB_DEV_NAME, pDrvCtrl->unit, &nicEvbFuncTable, "ST-NIC Enhanced Network Driver") == ERROR || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], NIC_EVB_EADR_LEN, ETHERMTU, NIC_EVB_SPEED) == ERROR) goto errorExit; /* Perform memory allocation */ if (nicEvbInitMem (pDrvCtrl) == ERROR) goto errorExit; /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->end, IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST); DRV_LOG (DRV_DEBUG_LOAD, "Done loading nicEvb...\n", 1, 2, 3, 4, 5, 6); return (&pDrvCtrl->end); errorExit: { nicEvbUnload (pDrvCtrl); return NULL; } }/********************************************************************************* nicEvbInitParse - parse the initialization string** Parse the input string. Fill in values in the driver control structure.* The initialization string format is:* <unit>:<base_adrs>:<vecnum>:<intLvl>** .IP <unit>* Device unit number, a small integer.* .IP <base_adrs>* Base address for NIC device* .IP <vecNum>* Interrupt vector number (used with sysIntConnect() ).* .IP <intLvl>* Interrupt level.** RETURNS: OK, or ERROR if any arguments are invalid.*/STATUS nicEvbInitParse ( NICEVB_END_DEVICE * pDrvCtrl, char * initString ) { char * tok; char * pHolder = NULL; long address; /* Parse the initString */ /* Unit number. */ tok = strtok_r (initString, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi (tok); /* NIC address. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; address = strtoul (tok, NULL, 16); pDrvCtrl->pNic = (NIC_DEVICE* )address; /* Interrupt vector. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ivec = atoi (tok); /* Interrupt level. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ilevel = atoi (tok); DRV_LOG (DRV_DEBUG_LOAD, "Processed all arugments\n", 1, 2, 3, 4, 5, 6); DRV_LOG (DRV_DEBUG_LOAD, "Address %p Level %u ivec %d\n", pDrvCtrl->pNic, pDrvCtrl->ilevel, pDrvCtrl->ivec, 4, 5, 6); return OK; }/********************************************************************************* nicEvbInitMem - initialize memory for Lance chip** Using data in the control structure, setup and initialize the memory* areas needed. If the memory address is not already specified, then allocate* cache safe memory.** RETURNS: OK or ERROR.*/LOCAL STATUS nicEvbInitMem ( NICEVB_END_DEVICE * pDrvCtrl /* device to be initialized */ ) { M_CL_CONFIG mclBlkConfig; CL_DESC clDesc; /* cluster description */ pDrvCtrl->rringSize = NIC_RBR_LEN; /* size of the whole ring */ pDrvCtrl->rringLen = pDrvCtrl->rringSize * NIC_BUF_SZ; /* rec ring len */ pDrvCtrl->rmdIndex = 0; /* init recv buf index */ pDrvCtrl->nextPkt = CURR; /* reset to initial value */ /* for remote DMA access */ pDrvCtrl->dmaSem = semMCreate (SEM_Q_PRIORITY); /* * Allocate receive buffers from our own private pool. */ /* Initialize net buffer pool for tx/rx buffers */ bzero ((char *)&mclBlkConfig, sizeof(mclBlkConfig)); bzero ((char *)&clDesc, sizeof(clDesc)); if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); mclBlkConfig.mBlkNum = pDrvCtrl->rringSize * 8; clDesc.clNum = pDrvCtrl->rringSize * 8; mclBlkConfig.clBlkNum = clDesc.clNum; mclBlkConfig.memSize = (mclBlkConfig.mBlkNum * (MSIZE + sizeof (long))) + (mclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof(long))); if ((mclBlkConfig.memArea = (char *) memalign (sizeof(long), mclBlkConfig.memSize)) == NULL) return (ERROR); clDesc.clSize = NIC_BUF_SZ; clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 4)) + 4); clDesc.memArea = memalign (sizeof(long), clDesc.memSize); pDrvCtrl->pRxCluster = (NIC_CLUSTER)clDesc.memArea; if (clDesc.memArea == NULL) { DRV_LOG (DRV_DEBUG_LOAD, "system memory unavailable\n", 1, 2, 3, 4, 5, 6); return (ERROR); } /* Initialize the net buffer pool with transmit buffers */ if (netPoolInit(pDrvCtrl->end.pNetPool, &mclBlkConfig, &clDesc, 1, NULL) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); return (ERROR); } #ifdef DRV_DEBUG nicNetPool = *pDrvCtrl->end.pNetPool;#endif /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool, NIC_BUF_SZ, FALSE); /* Setup the receive ring */ return OK; }/********************************************************************************* nicEvbStart - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS nicEvbStart ( NICEVB_END_DEVICE *pDrvCtrl ) { STATUS result; pDrvCtrl->txCleaning = FALSE; pDrvCtrl->txBlocked = FALSE; SYS_INT_CONNECT (pDrvCtrl, nicEvbInt, (int)pDrvCtrl, &result); if (result == ERROR) return ERROR; DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6); /* reset the device */ nicEvbReset (pDrvCtrl); nicEvbConfig (pDrvCtrl); /* device config */ /* mark the interface -- up */ END_FLAGS_SET (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); SYS_INT_ENABLE (pDrvCtrl->ivec); DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* nicEvbConfig - configure the NIC chip and program address** This routine follows the algorythm in the ST-NIC manual for enabling* a NIC device on an active network. Essentially, this routine initializes* the NIC device.** RETURNS: N/A.*/LOCAL void nicEvbConfig ( NICEVB_END_DEVICE * pDrvCtrl /* device to be configured */ ) { NIC_DEVICE* pNic = pDrvCtrl->pNic; UCHAR* pEnetAddr = pDrvCtrl->enetAddr; nicEvbWriteCr (pNic, RPAGE0 | STP | ABORT); nicEvbResetDelay (); nicEvbWriteReg (pNic, &pNic->Dcr, NOTLS | FIFO8, RPAGE0); /* clear remote DMA byte count registers */ nicEvbWriteReg (pNic, &pNic->Rbcr0, 0, RPAGE0); nicEvbWriteReg (pNic, &pNic->Rbcr1, 0, RPAGE0); /* accept broadcast and multicast, but not runt */ /* MULTI */ nicEvbWriteReg (pNic, &pNic->Rcr, AB, RPAGE0); nicEvbWriteReg (pNic, &pNic->Rcr, (AB | AM), RPAGE0); nicEvbWriteReg (pNic, &pNic->Tcr, MODE1, RPAGE0); /* int loopback mode */ nicEvbWriteReg (pNic, &pNic->Pstart, PSTART, RPAGE0); nicEvbWriteReg (pNic, &pNic->Pstop, PSTOP, RPAGE0); nicEvbWriteReg (pNic, &pNic->Bnry, BNRY, RPAGE0); nicEvbWriteReg (pNic, &pNic->Isr, 0xff, RPAGE0); /* clr pending ints */ nicEvbWriteReg (pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* enable int */ /* set up page 1 registers */ nicEvbWriteReg (pNic, &pNic->Par0, pEnetAddr [0], RPAGE1); nicEvbWriteReg (pNic, &pNic->Par1, pEnetAddr [1], RPAGE1); nicEvbWriteReg (pNic, &pNic->Par2, pEnetAddr [2], RPAGE1); nicEvbWriteReg (pNic, &pNic->Par3, pEnetAddr [3], RPAGE1); nicEvbWriteReg (pNic, &pNic->Par4, pEnetAddr [4], RPAGE1); nicEvbWriteReg (pNic, &pNic->Par5, pEnetAddr [5], RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar0, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar1, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar2, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar3, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar4, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar5, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar6, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->nic_pg1.mar7, 0x00, RPAGE1); nicEvbWriteReg (pNic, &pNic->Curr, CURR, RPAGE1); nicEvbWriteCr (pNic, RPAGE0 | ABORT | STA); /* back to page 0 */ nicEvbWriteReg (pNic, &pNic->Tcr, MODE0, RPAGE0); /* Tx normal mode */ }/********************************************************************************* nicEvbResetDelay - performs the delay required before resetting the chip ** This routine performs a 1.6 ms delay for PowerPC architecture if * using the internal PPC time base (the number of time base increment to* count for 1.6 msec is defined by the value nicRestartDelay which must * be set in the BSP), or waits for one system clock tick otherwise.** RETURNS: N/A.*/ LOCAL void nicEvbResetDelay (void) {#ifdef NIC_USE_PPCTIMEBASE UINT32 tbu1, tbu2; UINT32 tbl1, tbl2;#endif#ifdef NIC_USE_PPCTIMEBASE vxTimeBaseGet (&tbu1, &tbl1); while (1) { vxTimeBaseGet (&tbu2, &tbl2); if ((tbu2-tbu1) != 0) vxTimeBaseGet (&tbu1, &tbl1); else if ((tbl2 - tbl1) > nicEvbRestartDelay) break; }#else taskDelay (1); /* wait at least 1.6 mSec */#endif }/********************************************************************************* nicEvbWriteCr - write to the NIC command register** RETURNS: N/A.*/LOCAL void nicEvbWriteCr ( NIC_DEVICE *pNic, UINT8 value ) { int level = intLock (); do { pNic->Cr = value; } while (!((*(volatile UINT8 *)NIC_DMA) & ACC_MASK)); intUnlock (level); }/********************************************************************************* nicEvbWriteReg - write to a NIC register** RETURNS: N/A.*/LOCAL void nicEvbWriteReg ( NIC_DEVICE * pNic, volatile UINT8 * pReg, UINT8 value, UINT8 page ) { volatile UINT8 * nicDma = (volatile UINT8 *) NIC_DMA; UINT8 cr; int level = intLock (); do { cr = pNic->Cr; } while (!((*nicDma) & ACC_MASK)); if ((cr & PBMASK) != page) do { pNic->Cr = (cr & 0x3f) | page; } while (!((*nicDma) & ACC_MASK)); do { *pReg = value; } while (!((*nicDma) & ACC_MASK)); intUnlock (level); }/********************************************************************************* nicReadReg - read from a NIC register** RETURNS: the register value.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -