📄 rtl81x9.c
字号:
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 (RTL_DRV_DEBUG_LOAD, "flags : 0x%X ...\n", pDrvCtrl->flags,
2, 3, 4, 5, 6);
return OK;
}
/*******************************************************************************
*
* rtl81x9InitMem - initialize memory for the device
*
* 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 rtl81x9InitMem
(
RTL81X9END_DEVICE * pDrvCtrl /* device to be initialized */
)
{
UINT sz = 0; /* temporary size holder */
/***** Establish size of shared memory region we require *****/
DRV_LOG (RTL_DRV_DEBUG_LOAD, "rtl81x9InitMem\n", 0, 0, 0, 0, 0, 0);
if ((int) pDrvCtrl->memAdrs != NONE) /* specified memory pool */
{
/*
* With a specified memory pool we want to maximize
* rtlRsize and rtlTsize
*/
DRV_LOG (RTL_DRV_DEBUG_LOAD, "No memAdrs supplied\n", 0, 0, 0, 0, 0, 0);
sz = (pDrvCtrl->memSize - (RMD_SIZ + sizeof (rtl_ib)))
/ ((2 * RTL_BUFSIZ) + RMD_SIZ);
sz >>= 1; /* adjust for roundoff */
for (rtlRsize = 0; sz != 0; rtlRsize++, sz >>= 1)
;
}
/* limit ring sizes to reasonable values */
rtlRsize = max (rtlRsize, 2); /* 4 Rx buffers is reasonable min */
rtlRsize = min (rtlRsize, 7); /* 128 Rx buffers is max for chip */
/* Add it all up */
sz = (((1 << rtlRsize) + 1) * RMD_SIZ) + IB_SIZ + 24;
DRV_LOG (RTL_DRV_DEBUG_LOAD, "sx - %d\n",sz, 0, 0, 0, 0, 0);
/***** 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 (RTL_DRV_DEBUG_LOAD, "rtl81x9: not enough memory provided need %ul got %d\n",
pDrvCtrl->memSize, sz, 0, 0, 0, 0);
return (NULL);
}
/* set the beginning of pool */
pDrvCtrl->pShMem = pDrvCtrl->memAdrs;
/* assume pool is cache coherent, copy null structure */
pDrvCtrl->cacheFuncs = cacheNullFuncs;
DRV_LOG (RTL_DRV_DEBUG_LOAD, "Memory checks out\n",0, 0, 0, 0, 0, 0);
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.
*/
if (!CACHE_DMA_IS_WRITE_COHERENT ())
{
DRV_LOG (RTL_DRV_DEBUG_LOAD, "rtl: device requires cache coherent memory\n", 0, 0, 0, 0, 0, 0);
return (ERROR);
}
pDrvCtrl->pShMem = (char *) cacheDmaMalloc (sz);
if ((int)pDrvCtrl->pShMem == NULL)
{
DRV_LOG (RTL_DRV_DEBUG_LOAD, "rtl: system memory unavailable\n", 0, 0, 0, 0, 0, 0);
return (ERROR);
}
/* copy the DMA structure */
pDrvCtrl->cacheFuncs = cacheDmaFuncs;
break;
}
/* Turkey Carving
* --------------
*
* LOW MEMORY
*
* |----------------------------------------|
* | The initialization block |
* | (sizeof (rtl_ib)) |
* |----------------------------------------|
* | The Rx descriptors |
* | ((1 << rtlRsize) + 1)*sizeof (RTL_RMD) |
* |----------------------------------------|
*/
/* align */
pDrvCtrl->pShMem = (char *) ( ( (int)pDrvCtrl->pShMem + 3) & ~3);
/* Save some things */
pDrvCtrl->memBase = (char *)((ULONG)pDrvCtrl->pShMem & 0xff000000);
if ((int) pDrvCtrl->memAdrs == NONE)
pDrvCtrl->flags |= RTL_FLG_MEM_ALLOC_FLAG;
/* first let's clear memory */
bzero ((char *) pDrvCtrl->pShMem, (int) sz);
/* setup Rx memory pointers */
pDrvCtrl->pRring = (RTL_RMD *) ((int)pDrvCtrl->pShMem + IB_SIZ);
pDrvCtrl->rringLen = rtlRsize;
pDrvCtrl->rringSize = 1 << rtlRsize;
/* Allocate a chunk of memory for the Chip to place the Rx Buffers in */
pDrvCtrl->ptrRxBufSpace = malloc (RTL_RXBUFLEN + 64);
pDrvCtrl->ptrRxBufSpace += 4;
if (pDrvCtrl->ptrRxBufSpace == NULL)
{
DRV_LOG (RTL_DRV_DEBUG_LOAD, "ptrRxBufSpace == NULL\n", 0, 0, 0, 0, 0, 0);
return (ERROR);
}
pDrvCtrl->rmdNext = 0;
/*
* Allocate receive buffers from our own private pool.
*/
if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
return (ERROR);
rtlMclConfig.mBlkNum = pDrvCtrl->rringSize * 2;
rtlClDesc[0].clNum = pDrvCtrl->rringSize *2;
rtlMclConfig.clBlkNum = rtlClDesc[0].clNum;
rtlMclConfig.memSize = (rtlMclConfig.mBlkNum * (MSIZE + sizeof (long))) +
(rtlMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long)));
if ((rtlMclConfig.memArea = (char *) memalign (sizeof(long),
rtlMclConfig.memSize))
== NULL)
return (ERROR);
rtlClDesc[0].clNum = pDrvCtrl->rringSize *2;
rtlClDesc[0].memSize = (rtlClDesc[0].clNum * (RTL_BUFSIZ + 8))
+ sizeof(int);
if ((int) pDrvCtrl->memAdrs != NONE) /* Do we hand over our own memory? */
{
rtlClDesc[0].memArea =
(char *)(pDrvCtrl->pRring + (((1 << rtlRsize) + 1) * RMD_SIZ));
}
else
{
rtlClDesc[0].memArea =
(char *) cacheDmaMalloc (rtlClDesc[0].memSize);
if ((int)rtlClDesc[0].memArea == NULL)
{
DRV_LOG(RTL_DRV_DEBUG_LOAD,
"system memory unavailable\n", 1, 2, 3, 4, 5, 6);
return (ERROR);
}
}
if (netPoolInit(pDrvCtrl->end.pNetPool, &rtlMclConfig,
&rtlClDesc[0], rtlClDescNumEnt, NULL) == ERROR)
{
DRV_LOG (RTL_DRV_DEBUG_LOAD, "Could not init buffering\n",0, 0, 0, 0, 0, 0);
return (ERROR);
}
/* Store the cluster pool id as others need it later. */
pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool,
RTL_BUFSIZ, FALSE);
return OK;
}
/*******************************************************************************
*
* rtl81x9Start - start the device
*
* This function initializes the device and calls BSP functions to connect
* interrupts and start the device running in interrupt mode.
*
* The complement of this routine is rtl81x9Stop. Once a unit is reset by
* rtl81x9Stop, it may be re-initialized to a running state by this routine.
*
* RETURNS: OK if successful, otherwise ERROR
*/
LOCAL STATUS rtl81x9Start
(
RTL81X9END_DEVICE * pDrvCtrl
)
{
STATUS result;
int rxcfg;
pDrvCtrl->txBlocked = FALSE;
SYS_INT_CONNECT (pDrvCtrl, rtl81x9Int, (int)pDrvCtrl, &result);
if (result == ERROR)
return ERROR;
SYS_INT_ENABLE (pDrvCtrl);
/* Init the RX buffer pointer register. */
rtl81x9CsrWriteLong(pDrvCtrl, RTL_REGS_RX_BUF, (ULONG) pDrvCtrl->ptrRxBufSpace, RTL_WIN_0);
/* Enable Tx and RX */
rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RX_ENB + RTL_CMD_TX_ENB, RTL_WIN_0);
/*
* Set the initial TX and RX configuration.
* Set the buffer size and set the wrap register
*/
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_TX_CONFIG, RTL_TXCFG_CONFIG, RTL_WIN_0);
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, RTL_RXCFG_CONFIG, RTL_WIN_0);
rxcfg = rtl81x9CsrReadLong(pDrvCtrl, RTL_REGS_RX_CONFIG, RTL_WIN_0);
/* Set the Early Threshold bits depending on flags read */
/* from initialisation string */
rxcfg |= ((pDrvCtrl->flags >> 16) << 24);
/* Set the individual bit to receive frames for this host only. */
rxcfg |= RTL_RXCG_APM;
/* If we want promiscuous mode, set the allframes bit. */
if (pDrvCtrl->ib->rtlIBMode == 0x8000)
{
rxcfg |= RTL_RXCG_AAP;
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0);
}
else
{
rxcfg &= ~RTL_RXCG_AAP;
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0);
}
/*
* Set capture broadcast bit to capture broadcast frames.
*/
rxcfg |= RTL_RXCG_AB;
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_CONFIG, rxcfg, RTL_WIN_0);
/* We now need to update the Multicast Registers */
/* These values need to be finalised and written */
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_MAR0, 0xffff, RTL_WIN_0);
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_MAR0 + 4, 0xffff, RTL_WIN_0);
/* Enable Controller Interrupts */
rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
/* Start RX/TX process. */
rtl81x9CsrWriteLong (pDrvCtrl, RTL_REGS_RX_MISSED, 0, RTL_WIN_0);
/* Enable Tx and RX */
rtl81x9CsrWriteByte(pDrvCtrl, RTL_REGS_CHIP_CMD, RTL_CMD_RX_ENB + RTL_CMD_TX_ENB, RTL_WIN_0);
return (OK);
}
/*******************************************************************************
*
* rtl81x9Int - handle controller interrupt
*
* This routine is called at interrupt level in response to an interrupt from
* the controller.
*
* RETURNS: N/A.
*/
LOCAL void rtl81x9Int
(
RTL81X9END_DEVICE *pDrvCtrl
)
{
u_short stat;
/* Disable controller interrupts. */
rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, 0x00, NONE);
for (;;)
{
/* Read the interrupt status register */
stat = rtl81x9CsrReadWord (pDrvCtrl, RTL_REGS_INTR_STATUS, NONE);
/* clear interrupts, */
if (stat)
rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_STATUS, stat, NONE);
/* Mask off bits not needed */
stat &= (~(RTL_ALL_INTERRUPTS - RTL_VALID_INTERRUPTS));
/* Check if a valid Interrupt has been set */
if ((stat & RTL_VALID_INTERRUPTS) == 0)
break;
if (stat & RTL_IPT_PCI_ERR)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_PCI_ERR - Reset and Re initialise\n", 0,0,0,0,0,0);
rtl81x9Reset (pDrvCtrl);
rtl81x9Restart (pDrvCtrl);
}
if (stat & RTL_IPT_PCS_TIMEOUT)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_PCS_TIMEOUT\n", 0, 0, 0, 0, 0, 0);
}
if (stat & RTL_IPT_CABLE_LEN_CHG)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_CABLE_LEN_CHG\n", 0, 0, 0, 0, 0, 0);
}
if (stat & RTL_IPT_RX_FIFO_OVER)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_RX_FIFO_OVER\n", 0, 0, 0, 0, 0, 0);
}
if (stat & RTL_IPT_RX_UNDERUN)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_RX_UNDERUN\n", 0, 0, 0, 0, 0, 0);
}
if (stat & RTL_IPT_RX_OVERFLOW)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_RX_OVERFLOW\n", 0, 0, 0, 0, 0, 0);
}
if (stat & RTL_IPT_TX_ERR)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_TX_ERR\n", 0, 0, 0, 0, 0, 0);
rtl81x9HandleTxInt (pDrvCtrl);
}
if (stat & RTL_IPT_RX_ERR)
{
DRV_LOG (RTL_DRV_DEBUG_INT, "RTL_IPT_RX_ERR\n", 0, 0, 0, 0, 0, 0);
if (netJobAdd ((FUNCPTR)rtl81x9HandleRecvInt, (int) pDrvCtrl,
0, 0, 0, 0) != OK)
DRV_LOG (RTL_DRV_DEBUG_INT, "xl: netJobAdd (rtl81x9HandleRecvInt) failed\n", 0, 0, 0, 0, 0, 0);
}
/* Check for transmit Interrupt */
if (stat & RTL_IPT_TX_OK)
{
rtl81x9HandleTxInt (pDrvCtrl);
}
if (stat & RTL_IPT_RX_OK)
{
if (netJobAdd ((FUNCPTR)rtl81x9HandleRecvInt, (int) pDrvCtrl,
0, 0, 0, 0) != OK)
DRV_LOG (RTL_DRV_DEBUG_INT, "xl: netJobAdd (rtl81x9HandleRecvInt) failed\n", 0, 0, 0, 0, 0, 0);
}
}
rtl81x9CsrWriteWord (pDrvCtrl, RTL_REGS_INTR_MASK, RTL_VALID_INTERRUPTS, NONE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -