📄 ln97xend.c
字号:
#endif /*DRV_DEBUG*/
/* locals */
LOCAL int lnTsize = LN_TMD_TLEN; /* deflt xmit ring size as power of 2 */
LOCAL int lnRsize = LN_RMD_RLEN; /* deflt recv ring size as power of 2 */
LOCAL BOOL lnKickStartTx = LN_KICKSTART_TX;
/* forward static functions */
LOCAL int ln97xReset (LN_97X_DRV_CTRL * pDrvCtrl);
LOCAL void ln97xInt (LN_97X_DRV_CTRL * pDrvCtrl);
LOCAL void ln97xHandleRecvInt (LN_97X_DRV_CTRL * pDrvCtrl);
LOCAL STATUS ln97xRecv (LN_97X_DRV_CTRL * pDrvCtrl, LN_RMD *rmd);
LOCAL LN_RMD * ln97xFullRMDGet (LN_97X_DRV_CTRL * pDrvCtrl);
LOCAL void ln97xCsrWrite (LN_97X_DRV_CTRL * pDrvCtrl, int reg,
UINT32 value);
LOCAL void ln97xRestart (LN_97X_DRV_CTRL * pDrvCtrl);
LOCAL STATUS ln97xRestartSetup (LN_97X_DRV_CTRL * pDrvCtrl);
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -