📄 ln97xend.c
字号:
else
return ((LN_RMD *) NULL);
}
/*******************************************************************************
*
* ln97xRecv - process the next incoming packet
*
* RETURNS: OK/ERROR
*/
LOCAL STATUS ln97xRecv
(
LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */
LN_RMD * pRmd
)
{
int len;
M_BLK_ID pMblk;
char * pCluster;
char * pNewCluster;
char * pTemp;
CL_BLK_ID pClBlk;
UINT32 rmd1Tmp;
/* Packet must be checked for errors, Read rmd1 once only */
rmd1Tmp = PCI_SWAP (pRmd->rBufRmd1);
DRV_LOG (DRV_DEBUG_TX, "Recv : rmd1 = %X index = %d\n", rmd1Tmp,
pDrvCtrl->rmdIndex, 3, 4, 5, 6);
/* If error flag OR if packet is not completely in one buffer */
if ((rmd1Tmp & RMD1_ERR) ||
(rmd1Tmp & (RMD1_STP | RMD1_ENP)) != (RMD1_STP | RMD1_ENP))
{
DRV_LOG (DRV_DEBUG_RX, "RMD error!\n", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
goto cleanRXD; /* skip to clean up */
}
/* If we cannot get a buffer to loan then bail out. */
pNewCluster = netClusterGet (pDrvCtrl->endObj.pNetPool,
pDrvCtrl->pClPoolId);
if (pNewCluster == NULL)
{
DRV_LOG (DRV_DEBUG_RX, "Cannot loan!\n", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL)
{
netClFree (pDrvCtrl->endObj.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
/*
* OK we've got a spare, let's get an M_BLK_ID and marry it to the
* one in the ring.
*/
if ((pMblk = mBlkGet(pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA))
== NULL)
{
netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk);
netClFree (pDrvCtrl->endObj.pNetPool, pNewCluster);
DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
goto cleanRXD;
}
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);
len = LN_PKT_LEN_GET (pRmd); /* get packet length */
LN_RMD_TO_ADDR (pRmd, pCluster); /* Get pointer to packet */
pCluster -= pDrvCtrl->offset;
DRV_LOG (DRV_DEBUG_RX, "Packet @ 0x%X for %d bytes!\n", pCluster,
len, 3, 4, 5, 6);
/* Join the cluster to the MBlock */
netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);
netMblkClJoin (pMblk, pClBlk);
/* make the packet data coherent */
LN_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);
pMblk->mBlkHdr.mData += pDrvCtrl->offset;
pMblk->mBlkHdr.mLen = len;
pMblk->mBlkHdr.mFlags |= M_PKTHDR;
pMblk->mBlkPktHdr.len = len;
DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!\n", 1, 2, 3, 4, 5, 6);
/* Deal with memory alignment. */
pNewCluster += pDrvCtrl->offset;
/* Give receiver a new buffer */
LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pNewCluster);
/* Call the upper layer's receive routine. */
END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk);
cleanRXD:
/* clear status bits */
LN_CLEAN_RXD (pRmd);
/* Flush the write pipe */
CACHE_PIPE_FLUSH ();
/* Advance our management index */
pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1);
return (OK);
}
/*******************************************************************************
*
* lnSend - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it. This is done by a higher layer. The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS ln97xSend
(
LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */
M_BLK_ID pMblk /* data to send */
)
{
LN_TMD * pTmd;
UINT32 ltmd1;
void * pTemp;
char * pBuf;
char * pOrig;
int level;
int len = 0;
/*
* Obtain exclusive access to transmitter. This is necessary because
* we might have more than one stack transmitting at once.
*/
if (!(pDrvCtrl->flags & LS_POLLING))
END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex;
DRV_LOG (DRV_DEBUG_TX, "Send : index %d tmd = 0x%X\n",
pDrvCtrl->tmdIndex, (int)pTmd, 3, 4, 5, 6);
LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);
ltmd1 = PCI_SWAP (pTmd->tBufTmd1);
if ((ltmd1 & TMD1_OWN) ||
(((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1))
== pDrvCtrl->tmdIndexC))
{
if (!(pDrvCtrl->flags & LS_POLLING))
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
/* Are we still on the first chunk? */
DRV_LOG (DRV_DEBUG_TX, "Out of TMDs!\n", 1, 2, 3, 4, 5, 6);
level = intLock ();
pDrvCtrl->txBlocked = TRUE;
intUnlock (level);
return (END_ERR_BLOCK);
}
DRV_LOG (DRV_DEBUG_TX, "before cluster get %d %d\n",
pDrvCtrl->endObj.pNetPool,
pDrvCtrl->pClPoolId, 3, 4, 5, 6);
pOrig = pBuf = netClusterGet (pDrvCtrl->endObj.pNetPool,
pDrvCtrl->pClPoolId);
DRV_LOG (DRV_DEBUG_TX, "after cluster get pBuf = 0x%X\n",
(int)pBuf, 2, 3, 4, 5, 6);
if (pBuf == NULL)
{
netMblkClChainFree(pMblk);
return (ERROR);
}
pBuf += pDrvCtrl->offset; /* take care of the alignment */
len = netMblkToBufCopy (pMblk, pBuf, NULL);
netMblkClChainFree(pMblk);
LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pBuf);
len = max (len, ETHERSMALL);
pTmd->tBufTmd2 = 0; /* clear buffer error status */
ltmd1 = TMD1_STP | TMD1_ENP | TMD1_CNST;
ltmd1 |= (TMD1_BCNT_MSK & -len);
pTmd->tBufTmd1 = PCI_SWAP (ltmd1);
CACHE_PIPE_FLUSH ();
LN_CACHE_INVALIDATE (pTmd, TMD_SIZ);
ltmd1 |= TMD1_OWN;
DRV_LOG (DRV_DEBUG_TX, "TMD1 = 0x%X\n", ltmd1, 2, 3, 4, 5, 6);
/* write to actual register */
pTmd->tBufTmd1 = PCI_SWAP (ltmd1);
pDrvCtrl->freeRtn [pDrvCtrl->tmdIndex] = (FUNCPTR)netClFree;
pDrvCtrl->freeData [pDrvCtrl->tmdIndex].arg1 = pDrvCtrl->endObj.pNetPool;
pDrvCtrl->freeData [pDrvCtrl->tmdIndex].arg2 = pOrig;
/* Advance our management index */
pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);
/* Flush the write pipe */
CACHE_PIPE_FLUSH ();
if (lnKickStartTx)
{
if (!(pDrvCtrl->flags & LS_POLLING))
ln97xCsrWrite (pDrvCtrl, 0, (CSR0_INTMASK | CSR0_TDMD));
else
ln97xCsrWrite (pDrvCtrl, 0, CSR0_TDMD);
}
if (!(pDrvCtrl->flags & LS_POLLING))
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);
return (OK);
}
/*******************************************************************************
*
* ln97xIoctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS OK or ERROR value
*/
LOCAL int ln97xIoctl
(
LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */
int cmd, /* ioctl command to execute */
caddr_t data /* date to get or set */
)
{
long value;
int error = 0;
switch (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--; /* HELP: WHY ??? */
END_FLAGS_CLR (&pDrvCtrl->endObj, value);
}
else
{
END_FLAGS_SET (&pDrvCtrl->endObj, value);
}
ln97xConfig (pDrvCtrl);
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET (&pDrvCtrl->endObj);
break;
case EIOCPOLLSTART:
error = ln97xPollStart (pDrvCtrl);
break;
case EIOCPOLLSTOP:
error = ln97xPollStop (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);
*(int *)data = LN_MIN_FBUF;
break;
case EIOCGMWIDTH:
if (data == NULL)
return (EINVAL);
*(int *)data = pDrvCtrl->memWidth;
break;
case EIOCGHDRLEN:
if (data == NULL)
return (EINVAL);
*(int *)data = 14;
break;
default:
error = EINVAL;
}
return (error);
}
/*******************************************************************************
*
* ln97xReset - hardware reset of chip (stop it)
*
* This routine is responsible for resetting the device and switching into
* 32 bit mode.
*
* RETURNS: OK/ERROR
*/
LOCAL int ln97xReset
(
LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */
)
{
UINT32 resetTmp;
/* Enable 32 bit access by doing a 32 bit write */
SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRdp, 0);
ln97xCsrWrite (pDrvCtrl, CSR(0), CSR0_STOP);
/* Generate a soft-reset of the controller */
SYS_IN_LONG(pDrvCtrl, pDrvCtrl->pReset, resetTmp);
/* This isn't a real test - it just stops the compiler ignoring the read */
if (resetTmp == 0x12345678)
return (ERROR);
ln97xBcrWrite (pDrvCtrl, BCR(20), BCR20_SWSTYLE_PCNET);
/* autoselect port tye - 10BT or AUI */
ln97xBcrWrite (pDrvCtrl, BCR(2), BCR2_AUTO_SELECT);
/* read BCR */
resetTmp = ln97xBcrRead (pDrvCtrl, BCR(20));
return (OK);
}
/*******************************************************************************
*
* ln97xCsrWrite - select and write a CSR register
*
* This routine selects a register to write, through the RAP register and
* then writes the CSR value to the RDP register.
*
* RETURNS: N/A
*/
LOCAL void ln97xCsrWrite
(
LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */
int reg, /* CSR register to select */
UINT32 value /* CSR value to write */
)
{
int level;
level = intLock ();
/* select CSR */
reg &= 0xff;
SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRap, PCI_SWAP (reg));
CACHE_PIPE_FLUSH ();
value &=0xffff;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -