📄 ne2000end.c
字号:
void* pBSP /* for BSP group */ ) { NE2000END_DEVICE *pDrvCtrl; int level; UCHAR regVal;#ifdef DEBUG printf ("ne2000EndLoad(%s)\n", initString); printf ("\tinitString '%s'\n", initString ? initString : ""); printf ("\tpBSP '%s'\n", pBSP ? pBSP : "");#endif if (initString == NULL) return (NULL); if (initString[0] == '\0') { bcopy((char *)NE2000_DEV_NAME, initString, NE2000_DEV_NAME_LEN); return (NULL); } /* allocate the device structure */ pDrvCtrl = (NE2000END_DEVICE *) calloc (sizeof(NE2000END_DEVICE), 1); if (pDrvCtrl == NULL) goto errorExit; /* parse the init string, filling in the device structure */ if (ne2000Parse (pDrvCtrl, initString) == ERROR) goto errorExit; /* * If the optional load string parameters configRegA or configRegB * are passed in with the load string then load the passed in value * into the appropriate register. */ if (pDrvCtrl->configRegA != 0) { /* This must be an atomic transaction, so it must be intLocked */ level = intLock (); SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE0); SYS_IN_CHAR (pDrvCtrl, ENE_RBCR0, ®Val); SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, pDrvCtrl->configRegA); intUnlock (level); } if (pDrvCtrl->configRegB != 0) { /* This must be an atomic transaction, so it must be intLocked */ level = intLock (); SYS_IN_CHAR (pDrvCtrl, ENE_RBCR1, ®Val); SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, pDrvCtrl->configRegB); intUnlock (level); } /* stop device */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP); /* * HELP: * In the generic driver it always uses BUS16 here. I agree that this * code looks better, but if the device is inactive why are we doing this * here at all. Why not call ne2000Config from ne2000Start and let it set * up the chip when we actually start it ??? */ if (pDrvCtrl->byteAccess) SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS_8 | DCON_LOOPBK_OFF); else SYS_OUT_CHAR (pDrvCtrl, ENE_DCON, DCON_BSIZE1 | DCON_BUS16 | DCON_LOOPBK_OFF); /* Ask the BSP to provide the ethernet address. */ SYS_ENET_ADDR_GET (pDrvCtrl); /* initialize the END parts of the structure */ if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, NE2000_DEV_NAME, pDrvCtrl->unit, &ne2000FuncTable, "ne2000 Enhanced Network Driver") == ERROR) goto errorExit; /* initialize the MIB2 parts of the structure */ if (END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], 6, ETHERMTU, END_SPEED) == ERROR) goto errorExit; /* Perform memory allocation/distribution */ if (ne2000MemInit (pDrvCtrl) == ERROR) goto errorExit; /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_NOTRAILERS | IFF_MULTICAST | IFF_BROADCAST); return (&pDrvCtrl->endObj);errorExit: if (pDrvCtrl != NULL) free ((char *)pDrvCtrl); return (NULL); }/******************************************************************************** ne2000Parse - parse the init string** Parse the input string. Fill in values in the driver control structure.** The initialization string format is:* .CS* "unit:adrs:vecnum:intLvl:byteAccess:usePromEnetAddr:offset"* .CE** .IP <unit>* Device unit number, a small integer.* .IP <adrs>* Base address* .IP <vecNum>* Interrupt vector number (used with sysIntConnect)* .IP <intLvl>* Interrupt level (used with sysLanIntEnable)* .IP <byteAccess>* Use 8-bit access mode.* .IP <usePromEnetAddr>* get ethernet address from PROM.* .IP <offset>* offset for memory alignment* Set Configuration Register A. Defaults to reset value. * .IP <configRegA>* Set Configuration Register B. Defaults to reset value. * .IP <configRegB>* .LP** RETURNS: OK or ERROR for invalid arguments.*/LOCAL STATUS ne2000Parse ( NE2000END_DEVICE * pDrvCtrl, char * initString ) { char* tok; char* holder = NULL; /* Parse the initString */ /* Unit number. */ tok = strtok_r (initString, ":", &holder); if (tok == NULL) return (ERROR); pDrvCtrl->unit = atoi (tok); /* Base address. */ tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return (ERROR); pDrvCtrl->base = strtoul (tok, NULL, 16); /* Interrupt vector. */ tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return (ERROR); pDrvCtrl->ivec = strtoul (tok, NULL, 16); /* Interrupt level. */ tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return (ERROR); pDrvCtrl->ilevel = strtoul (tok, NULL, 16); /* 8-bit access. */ tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return (ERROR); pDrvCtrl->byteAccess = atoi (tok); /* ethernet address from PROM. */ tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return (ERROR); pDrvCtrl->usePromEnetAddr = atoi (tok); /* memory alignment offset */ tok = strtok_r (NULL, ":", &holder); if (tok == NULL) return (ERROR); pDrvCtrl->offset = strtoul (tok, NULL, 16); /* Set configuration register A - optional parameter */ pDrvCtrl->configRegA = 0; tok = strtok_r (NULL, ":", &holder); if (tok != NULL) pDrvCtrl->configRegA = strtoul (tok, NULL, 16); /* Set configuration register B - optional parameter */ pDrvCtrl->configRegB = 0; tok = strtok_r (NULL, ":", &holder); if (tok != NULL) pDrvCtrl->configRegB = strtoul (tok, NULL, 16); return (OK); }/********************************************************************************* ne2000MemInit - initialize memory for the chip** This routine is highly specific to the device.** RETURNS: OK or ERROR.*/LOCAL STATUS ne2000MemInit ( NE2000END_DEVICE * pDrvCtrl /* device to be initialized */ ) { M_CL_CONFIG eneMclBlkConfig; CL_DESC clDesc; /* cluster description */ bzero ((char *)&eneMclBlkConfig, sizeof(eneMclBlkConfig)); bzero ((char *)&clDesc, sizeof(clDesc)); clDesc.clNum = 32; clDesc.clSize = NE2000_BUFSIZ; /* allow for alignment */ clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 8)) + 4); eneMclBlkConfig.mBlkNum = 16 * 4; eneMclBlkConfig.clBlkNum = clDesc.clNum; /* * mBlk and cluster configuration memory size initialization * memory size adjusted to hold the netPool pointer at the head. */ eneMclBlkConfig.memSize = (eneMclBlkConfig.mBlkNum * (MSIZE + sizeof (long))) + (eneMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof (long))); eneMclBlkConfig.memArea = (char *) memalign(sizeof (long), eneMclBlkConfig.memSize); if (eneMclBlkConfig.memArea == NULL) return (ERROR); clDesc.memArea = (char *) malloc (clDesc.memSize); if (clDesc.memArea == NULL) return (ERROR); pDrvCtrl->endObj.pNetPool = (NET_POOL_ID) malloc (sizeof(NET_POOL)); if (pDrvCtrl->endObj.pNetPool == NULL) return (ERROR); /* Initialize the net buffer pool with transmit buffers */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &eneMclBlkConfig, &clDesc, 1, NULL) == ERROR) return (ERROR); /* Save the cluster pool id */ pDrvCtrl->clPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool, NE2000_BUFSIZ, FALSE); return (OK); }/********************************************************************************* ne2000Ioctl - the driver I/O control routine** Process an ioctl request.*/LOCAL int ne2000Ioctl ( void* pCookie, /* device ptr */ int cmd, caddr_t data ) { int error = 0; long value; NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie; switch ((UINT) cmd) { case EIOCSADDR: if (data == NULL) return (EINVAL); bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj), END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCGADDR: if (data == NULL) return (EINVAL); bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data, END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -value; value--; END_FLAGS_CLR (&pDrvCtrl->endObj, value); } else END_FLAGS_SET (&pDrvCtrl->endObj, value); ne2000Config (pDrvCtrl, TRUE); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj); break; case EIOCPOLLSTART: ne2000PollStart (pDrvCtrl); break; case EIOCPOLLSTOP: ne2000PollStop (pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) return (EINVAL); bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data, sizeof(pDrvCtrl->endObj.mib2Tbl)); break; case EIOCGFBUF: if (data == NULL) return (EINVAL);#if 0 /* XXX */ *(int *)data = END_MIN_FBUF;#endif break; default: error = EINVAL; } return (error); }/********************************************************************************* ne2000Start - 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 ne2000Start ( void* pCookie ) { STATUS result; NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie; ENDLOGMSG (("ne2000Start\n", 0, 0, 0, 0, 0, 0)); SYS_INT_CONNECT (pDrvCtrl, ne2000Int, (int)pDrvCtrl, &result); if (result == ERROR) return (ERROR); /* mark the interface as up (SPR #32034) */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* Enable interrupts */ pDrvCtrl->imask = (pDrvCtrl->flags & END_POLLING) ? 0 : NE2000_ALL_INTS; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); SYS_INT_ENABLE (pDrvCtrl); return (OK); }/******************************************************************************** ne2000Config - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** NOMANUAL*/LOCAL void ne2000Config ( NE2000END_DEVICE *pDrvCtrl, BOOL intEnable /* TRUE to enable interrupts */ ) { UCHAR rxFilter; /* receiver configuration */#ifdef DEBUG static buf [256];#endif ENDLOGMSG (("ne2000Config: enter (intEnable=%d)\n", intEnable, 0, 0, 0, 0, 0)); /* Disable device interrupts */ pDrvCtrl->imask = 0; SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask); /* Set up address filter for multicasting. */ if (END_MULTI_LST_CNT(&pDrvCtrl->endObj) > 0) ne2000AddrFilterSet (pDrvCtrl); /* preserve END_POLLING and OVERWRITE flags */ pDrvCtrl->flags &= (END_POLLING | END_OVERWRITE | END_OVERWRITE2); /* 1. program Command Register for page 0 and for no DMA */ SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_STOP); /* 2. initialize Data Configuration Register: * 16-bit bus, burst mode, 8-deep FIFO. * or * 8-bit bus, burst mode, 8-deep FIFO. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -