📄 lan91c111end.c
字号:
*
* RETURNS: N/A.
*/
void lan91c111HandleRcvInt
(
LAN91C111END_DEVICE *pDrvCtrl /* interrupting device */
)
{
UINT receiveReady;
int loopCount=0;
pDrvCtrl->rxHandling = TRUE;
do {
lan91c111Recv (pDrvCtrl);
receiveReady = pDrvCtrl->pRxReadIndex->pData ? 1 : 0;
loopCount++;
} while ((receiveReady != 0) && (loopCount <= 30));
pDrvCtrl->rxHandling = FALSE;
return;
}
#endif
#define CLCHAIN_DBG 1
#if CLCHAIN_DBG
M_BLK_ID myMblk;
#endif
/******************************************************************************
* lan91c111Send - end send routine
*
* This routine will be called by the network stack whenever the upper layer want
* to send the datagram. It takes a pointer to mbuf. It extacts the data from the
* mbuf and writes in chip.
*
* RETURNS: status of the write operation
*/
STATUS lan91c111Send(END_OBJ *pEnd,M_BLK_ID pMblk)
{
LAN91C111END_DEVICE *pDrvCtrl = (LAN91C111END_DEVICE *)pEnd;
BOOLEAN status;
M_BLK_ID curMblk;
int currentKey;
DRV_LOG (DRV_DEBUG_TX, "lan91c111Send: called \n",1, 2, 3, 4, 5, 6);
/* This Block is to put the packet sent by the upper layers in a ring Buffer.Here
we are using ReadIndex and WriteIndex instead of allocpending and writepending Queues*/
/* He is not checking for null since he is sending null in the TX Int case...
I think we have to check for null ..ask kumar about this.. */
if(pMblk ==(M_BLK_ID) 1)
{
currentKey = intLock();
pDrvCtrl->AllocPending =FALSE;
curMblk = pDrvCtrl->pTxReadIndex->pMblk;
END_TX_SEM_TAKE (&pDrvCtrl->endObj,WAIT_FOREVER);
pDrvCtrl->sendDatalen = netMblkToBufCopy(curMblk,pDrvCtrl->sendBuf,NULL);
pDrvCtrl->sendDatalen = (ETHER_ZLEN < pDrvCtrl->sendDatalen) ? pDrvCtrl->sendDatalen : ETHER_ZLEN;
pDrvCtrl->pTxReadIndex->pMblk = NULL;
netMblkClChainFree(curMblk);
if ( pDrvCtrl->pTxReadIndex < pDrvCtrl->pTxBase + TX_PACKETS - 2)
pDrvCtrl->pTxReadIndex++;
else
pDrvCtrl->pTxReadIndex = pDrvCtrl->pTxBase;
lan91c111WriteToChip(pDrvCtrl);
intUnlock(currentKey);
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
return OK;
}
else if(pMblk) /* put in ring buffer */
{
if(pDrvCtrl->pTxWriteIndex->pMblk)
{
/* TX fifo full, drop packet */
netMblkClChainFree(pMblk);
}
else
{
/* TX fifo not full, queue packet */
pDrvCtrl->pTxWriteIndex->pMblk = pMblk;
/*
DRV_LOG(DRV_DEBUG_TX,"TxWriteIndex : %d\n",pDrvCtrl->pTxWriteIndex,2,3,4,5,6);
*/
if(pDrvCtrl->pTxWriteIndex < (pDrvCtrl->pTxBase + TX_PACKETS - 2))
pDrvCtrl->pTxWriteIndex++;
else
pDrvCtrl->pTxWriteIndex = pDrvCtrl->pTxBase;
}
}
/* This Block calls two Functions one allocates the memory
from the MMU and other copies the stuff from clusters to the chip*/
curMblk = pDrvCtrl->pTxReadIndex->pMblk;
if(!curMblk)
{
DRV_LOG (DRV_DEBUG_ERR, "lan91c111Send: Current MBlk is NULL \n",1, 2, 3, 4, 5, 6);
return OK;
}
status = DoAllocate(pDrvCtrl);
if(status)
{
DRV_LOG(DRV_DEBUG_TX, "lan91c111Send : Got Access to MMU\n",1,2,3,4,5,6);
END_TX_SEM_TAKE (&pDrvCtrl->endObj,WAIT_FOREVER);
currentKey = intLock();
pDrvCtrl->sendDatalen = netMblkToBufCopy(curMblk,pDrvCtrl->sendBuf,NULL);
pDrvCtrl->sendDatalen = (ETHER_ZLEN < pDrvCtrl->sendDatalen) ? pDrvCtrl->sendDatalen : ETHER_ZLEN;
pDrvCtrl->pTxReadIndex->pMblk = NULL;
netMblkClChainFree(curMblk);
if ( pDrvCtrl->pTxReadIndex < pDrvCtrl->pTxBase + TX_PACKETS - 2)
pDrvCtrl->pTxReadIndex++;
else
pDrvCtrl->pTxReadIndex = pDrvCtrl->pTxBase;
lan91c111WriteToChip(pDrvCtrl);
intUnlock(currentKey);
}
else
{
USHORT OldMask;
int key;
key = intLock();
pDrvCtrl->AllocPending = TRUE;
SYS_IN_SHORT(pDrvCtrl->IOBase + BANK2_INT_STS, (PUSHORT)&OldMask);
SYS_OUT_SHORT(pDrvCtrl->IOBase + BANK2_INT_STS, 0);
OldMask |= ( INT_ALLOC << 8 );
OldMask &= 0xFF00; /* Do not ACK interrupts */
SYS_OUT_SHORT(pDrvCtrl->IOBase + BANK2_INT_STS, OldMask);
intUnlock(key);
DRV_LOG(DRV_DEBUG_TX, "lan91c111Send : Set Alloc Int bit\n",1,2,3,4,5,6);
}
END_TX_SEM_GIVE (&pDrvCtrl->endObj);
return OK;
}
/*****************************************************************************
* DoAllocate - allocates the memory for write operation
*
* This routine makes a request MMU for 2k bytes of memory for packet
* transmition.
*
* RETIRNS: status of the request
*/
BOOLEAN DoAllocate(LAN91C111END_DEVICE *pDrvCtrl)
{
UINT AllocateOk; /* Delay loop control */
UINT IOBase;
USHORT AllocSts;
IOBase = pDrvCtrl->IOBase;
SYS_OUT_SHORT(IOBase + BANK_SELECT, 2);
SYS_OUT_SHORT(IOBase + BANK2_MMU_CMD,(USHORT)((((pDrvCtrl->sendDatalen + FRAME_OVERHEAD) & 0xfffe) >> 8)|CMD_ALLOC));
AllocateOk = MMU_WAIT;
while(AllocateOk)
{
SYS_IN_SHORT(IOBase + BANK2_INT_STS,(PUSHORT) &AllocSts);
if(AllocSts & INT_ALLOC)
break;
AllocateOk--;
}
/* Check whether the allocation result is a pass or fail */
return((BOOLEAN) (AllocSts & INT_ALLOC));
}
/***********************************************************************
* writeToChip - write data to the chip
*
* This routine will writes the data to the chip and the transmission for
* transmition.
*
* RETURNS: N/A
*/
void lan91c111WriteToChip(LAN91C111END_DEVICE *pDrvCtrl)
{
UINT IOBase;
UINT DataPort;
USHORT TempWord;
BYTE TempByte;
USHORT length = pDrvCtrl->sendDatalen ;
char *p = pDrvCtrl->sendBuf ;
int key;
#if PING_DEBUG
if(length <= 100)
memcpy((void *)TxBuff, (void *)p, length);
#endif
/*-----------------3/13/01 2:38PM-------------------
* For faster data access
* --------------------------------------------------*/
if(pDrvCtrl->EarlyTransmit == TRUE)
{
EarlyTransmit(pDrvCtrl);
}
else
{
IOBase = pDrvCtrl->IOBase;
DataPort = IOBase + BANK2_DATA1;
key = intLock();
SYS_OUT_SHORT(IOBase + BANK_SELECT, 2);
/*-----------------3/13/01 2:35PM-------------------
* The next 3 lines of code reads the Alloc Result register
* and writes into the packet Number Register
* --------------------------------------------------*/
SYS_IN_SHORT( IOBase + BANK2_PNR,(PUSHORT) &TempWord );
TempByte = HIBYTE(TempWord);
SYS_OUT_SHORT(IOBase + BANK2_PNR,TempByte);
/*-----------------3/13/01 2:38PM-------------------
* From here we are writing the packet into the Chip
* --------------------------------------------------*/
SYS_OUT_SHORT(IOBase + BANK2_PTR,(USHORT) PTR_AUTO);
SYS_OUT_SHORT(DataPort,(USHORT) 0);
/* force byte count even 3/25/96 NW */
SYS_OUT_SHORT((DataPort), (USHORT) (0xfffe & (length + FRAME_OVERHEAD )) );
while(length > 3)
{
SYS_OUT_LONG((DataPort),(*((PULONG) p)));
length -= sizeof(ULONG);
p += sizeof(ULONG);
}
if(length > 1)
{
SYS_OUT_SHORT((DataPort),(*((PUSHORT) p)));
length -= sizeof(USHORT);
p += sizeof(USHORT);
}
if(length)
{
sysOutByte((DataPort),(*p));lan91c111Delay();
sysOutByte((DataPort),(UCHAR)( CTL_BYTE_ODD | CTL_BYTE_CRC));lan91c111Delay();
}
else
{
SYS_OUT_SHORT((DataPort),((USHORT)CTL_BYTE_CRC<<8));
}
SYS_OUT_SHORT(( IOBase + BANK2_MMU_CMD),(USHORT) CMD_ENQ_TX );
intUnlock(key);
}
DRV_LOG (DRV_DEBUG_TX, "lan91c111Send : Out of Write Function \n",1, 2, 3, 4, 5, 6);
}
/*******************************************************************************
*
* ln7990HandleError - handle controller interrupt errors
*
* This routine is called to process controller errors at a task level that
* were detecected in interrupt context.
*
* RETURNS: N/A.
*/
void lan91c111HandleError(LAN91C111END_DEVICE *pDrvCtrl, USHORT PacketStatus)
{
pDrvCtrl->errorHandling = FALSE;
pDrvCtrl->lastError.errCode = END_ERR_WARN;
if(PacketStatus & TFS_UNDERRUN)
{
pDrvCtrl->lastError.pMesg = "Tx UnderRuns";
}
if(PacketStatus & TFS_CARRIER)
{
pDrvCtrl->lastError.pMesg = "Lost Carrier Sense";
}
if(PacketStatus & TFS_LATE)
{
pDrvCtrl->lastError.pMesg = "Late Collisions";
}
if(PacketStatus & TFS_16COL)
{
pDrvCtrl->lastError.pMesg = "16 Collisions";
}
if(PacketStatus & TFS_SQET)
{
pDrvCtrl->lastError.pMesg = "SQET Error";
}
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);
END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1);
muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError);
return;
}
/*******************************************************************************
*
* lan91c111Ioctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS: A command specific response, usually OK or ERROR.
*/
int lan91c111Ioctl
(
END_OBJ * pEnd, /* device receiving command */
int cmd, /* ioctl command code */
caddr_t data /* command argument */
)
{
int error = 0;
long value;
LAN91C111END_DEVICE *pDrvCtrl = (LAN91C111END_DEVICE *)pEnd;
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);
END_FLAGS_CLR (&pDrvCtrl->endObj, value);
}
else
{
END_FLAGS_SET (&pDrvCtrl->endObj, value);
}
lan91c111Config (pDrvCtrl);
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);
break;
case EIOCPOLLSTART: /* Begin polled operation */
lan91c111PollStart (pDrvCtrl);
break;
case EIOCPOLLSTOP: /* End polled operation */
lan91c111PollStop (pDrvCtrl);
break;
case EIOCGMIB2: /* return MIB information */
if (data == NULL)
return (EINVAL);
bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,
sizeof(pDrvCtrl->endObj.mib2Tbl));
break;
case EIOCGFBUF: /* return minimum First Buffer for chaining */
if (data == NULL)
return (EINVAL);
*(int *)data = LAN91C111_MIN_FBUF;
break;
case EIOCGHDRLEN:
if (data == NULL)
return (EINVAL);
*(int *)data = EH_SIZE;
break;
default:
error = EINVAL;
}
return (error);
}
/************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -