📄 ln97xend.c
字号:
LOCAL void ln97xAddrFilterSet (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL UINT32 ln97xCsrRead (LN_97X_DRV_CTRL * pDrvCtrl, int reg);LOCAL void ln97xBcrWrite (LN_97X_DRV_CTRL * pDrvCtrl, int reg, UINT32 value);LOCAL void ln97xTRingScrub (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL void ln97xConfig (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL STATUS ln97xMemInit (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL UINT32 ln97xBcrRead (LN_97X_DRV_CTRL * pDrvCtrl, int reg);/* END Specific interfaces. */LOCAL STATUS ln97xStart (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL STATUS ln97xStop (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL STATUS ln97xUnload (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL int ln97xIoctl (LN_97X_DRV_CTRL * pDrvCtrl, int cmd, caddr_t data);LOCAL STATUS ln97xSend (LN_97X_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS ln97xMCastAddrAdd (LN_97X_DRV_CTRL* pDrvCtrl, char * pAddress);LOCAL STATUS ln97xMCastAddrDel (LN_97X_DRV_CTRL * pDrvCtrl, char * pAddress);LOCAL STATUS ln97xMCastAddrGet (LN_97X_DRV_CTRL * pDrvCtrl, MULTI_TABLE * pTable);LOCAL STATUS ln97xPollSend (LN_97X_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS ln97xPollReceive (LN_97X_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS ln97xPollStart (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL STATUS ln97xPollStop (LN_97X_DRV_CTRL * pDrvCtrl);/* * Declare our function table. This is static across all driver * instances. */LOCAL NET_FUNCS ln97xFuncTable = { (FUNCPTR) ln97xStart, /* Function to start the device. */ (FUNCPTR) ln97xStop, /* Function to stop the device. */ (FUNCPTR) ln97xUnload, /* Unloading function for the driver. */ (FUNCPTR) ln97xIoctl, /* Ioctl function for the driver. */ (FUNCPTR) ln97xSend, /* Send function for the driver. */ (FUNCPTR) ln97xMCastAddrAdd, /* Multicast address add */ (FUNCPTR) ln97xMCastAddrDel, /* Multicast address delete */ (FUNCPTR) ln97xMCastAddrGet, /* Multicast table retrieve */ (FUNCPTR) ln97xPollSend, /* Polling send function */ (FUNCPTR) ln97xPollReceive, /* Polling receive function */ endEtherAddressForm, /* Put address info into a packet. */ endEtherPacketDataGet, /* Get a pointer to packet data. */ endEtherPacketAddrGet /* Get packet addresses. */ };/******************************************************************************** ln97xEndLoad - initialize the driver and device** This routine initializes the driver and the device to the operational state.* All of the device-specific parameters are passed in <initString>, which* expects a string of the following format:** <unit>:<devMemAddr>:<devIoAddr>:<pciMemBase:<vecnum>:<intLvl>:<memAdrs>* :<memSize>:<memWidth>:<csr3b>:<offset>:<flags>** 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, "lnPci") 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 * ln97xEndLoad ( char * initString /* string to be parse by the driver */ ) { LN_97X_DRV_CTRL * pDrvCtrl; DRV_LOG (DRV_DEBUG_LOAD, "Loading ln97x...debug @ 0X%X\n", (int)&ln97xDebug, 2, 3, 4, 5, 6); if (initString == NULL) return (NULL); if (initString [0] == NULL) { bcopy ((char *)LN_97X_DEV_NAME, initString, LN_97X_DEV_NAME_LEN); DRV_LOG (DRV_DEBUG_LOAD, "Returning string...\n", 1, 2, 3, 4, 5, 6); return ((END_OBJ *)OK); } DRV_LOG (DRV_DEBUG_LOAD, "lnstring: [%s]\n", (int)initString, 2, 3, 4, 5, 6); /* allocate the device structure */ pDrvCtrl = (LN_97X_DRV_CTRL *)calloc (sizeof (LN_97X_DRV_CTRL), 1); if (pDrvCtrl == NULL) goto errorExit; DRV_LOG (DRV_DEBUG_LOAD, "DrvControl : 0x%X\n", (int)pDrvCtrl, 2, 3, 4, 5, 6); /* parse the init string, filling in the device structure */ if (ln97xInitParse (pDrvCtrl, initString) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Parse failed ...\n", 1, 2, 3, 4, 5, 6); goto errorExit; } /* Have the BSP hand us our address. */ SYS_ENET_ADDR_GET (pDrvCtrl, &(pDrvCtrl->enetAddr [0])); /* initialize the END and MIB2 parts of the structure */ if (END_OBJ_INIT (&pDrvCtrl->endObj, (DEV_OBJ *)pDrvCtrl, LN_97X_DEV_NAME, pDrvCtrl->unit, &ln97xFuncTable, "AMD 79C970 Lance PCI Enhanced Network Driver") == ERROR || END_MIB_INIT (&pDrvCtrl->endObj, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], 6, ETHERMTU, LN_SPEED) == ERROR) goto errorExit; DRV_LOG (DRV_DEBUG_LOAD, "END init done ...\n", 1, 2, 3, 4, 5, 6); /* Perform memory allocation */ if (ln97xMemInit (pDrvCtrl) == ERROR) goto errorExit; DRV_LOG (DRV_DEBUG_LOAD, "Malloc done ...\n", 1, 2, 3, 4, 5, 6); /* Perform memory distribution and reset and reconfigure the device */ if (ln97xRestartSetup (pDrvCtrl) == ERROR) goto errorExit; DRV_LOG (DRV_DEBUG_LOAD, "Restart setup done ...\n", 1, 2, 3, 4, 5, 6); /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX); DRV_LOG (DRV_DEBUG_LOAD, "Done loading ln97x...\n", 1, 2, 3, 4, 5, 6); return (&pDrvCtrl->endObj);errorExit: if (pDrvCtrl != NULL) free ((char *)pDrvCtrl); return ((END_OBJ *)NULL); }/********************************************************************************* ln97xInitParse - parse the initialization string** Parse the input string. This routine is called from ln97xEndLoad() which* intializes some values in the driver control structure with the values* passed in the intialization string.** The initialization string format is:* <unit>:<devMemAddr>:<devIoAddr>:<pciMemBase:<vecNum>:<intLvl>:<memAdrs>* :<memSize>:<memWidth>:<csr3b>:<offset>:<flags>** .IP <unit>* Device unit number, a small integer.* .IP <devMemAddr>* Device register base memory address* .IP <devIoAddr>* Device register base IO address* .IP <pciMemBase>* Base address of PCI memory space* .IP <vecNum>* Interrupt vector number.* .IP <intLvl>* Interrupt level.* .IP <memAdrs>* Memory pool address or NONE.* .IP <memSize>* Memory pool size or zero.* .IP <memWidth>* Memory system size, 1, 2, or 4 bytes (optional).* .IP <CSR3>* Value of CSR3 (for endian-ness mainly)* .IP <offset>* Offset of starting of data in the device buffers.* .IP <flags>* Device specific flags, for future use.** RETURNS: OK, or ERROR if any arguments are invalid.*/STATUS ln97xInitParse ( LN_97X_DRV_CTRL * pDrvCtrl, /* pointer to the control structure */ char * initString /* initialization string */ ) { char* tok; char** holder = NULL; UINT32 devMemAddr; UINT32 devIoAddr; DRV_LOG (DRV_DEBUG_LOAD, "Parse starting ...\n", 1, 2, 3, 4, 5, 6); /* Parse the initString */ /* Unit number. */ tok = strtok_r (initString, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi (tok); DRV_LOG (DRV_DEBUG_LOAD, "Unit : %d ...\n", pDrvCtrl->unit, 2, 3, 4, 5, 6); /* devAdrs address. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; devMemAddr = (UINT32) strtoul (tok, NULL, 16); DRV_LOG (DRV_DEBUG_LOAD, "devMemAddr : 0x%X ...\n", devMemAddr, 2, 3, 4, 5, 6); /* devIoAddrs address */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; devIoAddr = (UINT32) strtoul (tok, NULL, 16); DRV_LOG (DRV_DEBUG_LOAD, "devIoAddr : 0x%X ...\n", devIoAddr, 2, 3, 4, 5, 6); /* always use memory mapped IO if provided, else use io map */ if ((devMemAddr == NONE) && (devIoAddr == NONE)) { DRV_LOG (DRV_DEBUG_LOAD, "No memory or IO base specified ...\n", 1, 2, 3, 4, 5, 6); return (ERROR); } else if (devMemAddr != NONE) { pDrvCtrl->devAdrs = devMemAddr; pDrvCtrl->flags |= LS_MODE_MEM_IO_MAP; } else pDrvCtrl->devAdrs = devIoAddr; /* PCI memory base address as seen from the CPU */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->pciMemBase = strtoul (tok, NULL, 16); DRV_LOG (DRV_DEBUG_LOAD, "Pci : 0x%X ...\n", pDrvCtrl->pciMemBase, 2, 3, 4, 5, 6); /* Interrupt vector. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->ivec = atoi (tok); DRV_LOG (DRV_DEBUG_LOAD, "ivec : 0x%X ...\n", pDrvCtrl->ivec, 2, 3, 4, 5, 6); /* Interrupt level. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->ilevel = atoi (tok); DRV_LOG (DRV_DEBUG_LOAD, "ilevel : 0x%X ...\n", pDrvCtrl->ilevel, 2, 3, 4, 5, 6); /* Caller supplied memory address. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->memAdrs = (char *)strtoul (tok, NULL, 16); DRV_LOG (DRV_DEBUG_LOAD, "memAdrs : 0x%X ...\n", (int)pDrvCtrl->memAdrs, 2, 3, 4, 5, 6); /* Caller supplied memory size. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->memSize = strtoul (tok, NULL, 16); DRV_LOG (DRV_DEBUG_LOAD, "memSize : 0x%X ...\n", pDrvCtrl->memSize, 2, 3, 4, 5, 6); /* Caller supplied memory width. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->memWidth = atoi (tok); DRV_LOG (DRV_DEBUG_LOAD, "memWidth : 0x%X ...\n", pDrvCtrl->memWidth, 2, 3, 4, 5, 6); /* CSR3B value */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->csr3B = strtoul (tok, NULL, 16); DRV_LOG (DRV_DEBUG_LOAD, "CSR3b : 0x%X ...\n", pDrvCtrl->csr3B, 2, 3, 4, 5, 6); /* Caller supplied alignment offset. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->offset = atoi (tok); DRV_LOG (DRV_DEBUG_LOAD, "Offset : 0x%X ...\n", pDrvCtrl->offset, 2, 3, 4, 5, 6); /* caller supplied flags */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->flags |= strtoul (tok, NULL, 16); DRV_LOG (DRV_DEBUG_LOAD, "flags : 0x%X ...\n", pDrvCtrl->flags, 2, 3, 4, 5, 6); return OK; }/********************************************************************************* ln97xMemInit - 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 ln97xMemInit ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { UINT32 sz; /* temporary size holder */ int ix; LN_RMD * pRmd; void * pTemp; char * pTempBuf; /* Remember register addresses */ pDrvCtrl->pRdp = LN_97X_RDP; pDrvCtrl->pRap = LN_97X_RAP; pDrvCtrl->pReset = LN_97X_RST; pDrvCtrl->pBdp = LN_97X_BDP; /***** Establish size of shared memory region we require *****/ if ((int) pDrvCtrl->memAdrs != NONE) /* specified memory pool */ { /* * With a specified memory pool we want to maximize * lnRsize and lnTsize */ sz = (pDrvCtrl->memSize - (RMD_SIZ + TMD_SIZ + sizeof (LN_IB))) / ((2 * LN_BUFSIZ) + RMD_SIZ + TMD_SIZ); sz >>= 1; /* adjust for roundoff */ for (lnRsize = 0; sz != 0; lnRsize++, sz >>= 1) ; lnTsize = lnRsize; /* lnTsize = lnRsize for convenience */ } /* limit ring sizes to reasonable values */ lnRsize = max (lnRsize, LN_RMD_MIN); /* 4 Rx buffers is reasonable min */ lnRsize = min (lnRsize, LN_RMD_MAX); /* 128 Rx buffers is max for chip */ lnTsize = max (lnTsize, LN_TMD_MIN); /* 4 Tx buffers is reasonable min */ lnTsize = min (lnTsize, LN_TMD_MAX); /* 128 Tx buffers is max for chip */ /* Add it all up */ sz = (((1 << lnRsize) + 1) * RMD_SIZ) + (((1 << lnTsize) + 1) * TMD_SIZ) + IB_SIZ + 0x10; /***** Establish a region of shared memory *****/ /* OK. We now know how much shared memory we need. If the caller * provides a specific memory region, we check to see if the provided * region is large enough for our needs. If the caller did not * provide a specific region, then we attempt to allocate the memory * from the system, using the cache aware allocation system call. */ switch ((int) pDrvCtrl->memAdrs) { default : /* caller provided memory */ if (pDrvCtrl->memSize < sz) /* not enough space */ { DRV_LOG (DRV_DEBUG_LOAD, "ln97x: not enough memory provided\n" "ln97x: need %ul got %d\n", sz, pDrvCtrl->memSize, 3, 4, 5, 6); return (NULL); } /* set the beginning of pool */ pDrvCtrl->pShMem = pDrvCtrl->memAdrs; /* assume pool is cache coherent, copy null structure */ pDrvCtrl->cacheFuncs = cacheNullFuncs; DRV_LOG (DRV_DEBUG_LOAD, "Memory checks out\n", 1, 2, 3, 4, 5, 6); break; case NONE : /* get our own memory */ /* Because the structures that are shared between the device * and the driver may share cache lines, the possibility exists * that the driver could flush a cache line for a structure and * wipe out an asynchronous change by the device to a neighboring * structure. Therefore, this driver cannot operate with memory * that is not write coherent. We check for the availability of * such memory here, and abort if the system did not give us what * we need. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -