📄 ns8390x.c
字号:
register long dev_num;
/*---------------------------------------------------------------------*/
/* Set up the device number from the packet structure */
/*---------------------------------------------------------------------*/
dev_num = rcvHdrPtr->dev_num;
/*---------------------------------------------------------------------*/
/* Determine the # of bytes from this buff to the end of the ring */
/*---------------------------------------------------------------------*/
numBytes = ((LAN_RXSTOP - rcvHdrPtr->pageNum) * sizeof(STNIC_RING_BUFF));
/*---------------------------------------------------------------------*/
/* If the # of bytes >= length the data is in contiguous addresses */
/*---------------------------------------------------------------------*/
if (numBytes >= (rcvHdrPtr->dataLen + sizeof(RCV_BUFF_STAT)))
{
remDmaSetup(dev_num, ((rcvHdrPtr->pageNum) << 8) + sizeof(RCV_BUFF_STAT),
(ULONG)rcvHdrPtr->dataLen, REMOTE_READ);
remDmaDo(dev_num, ((UCHAR *) &(rcvHdrPtr->daddr)),
(ULONG)rcvHdrPtr->dataLen, REMOTE_READ);
}
else
{
numBytes -= sizeof(RCV_BUFF_STAT);
remDmaSetup(dev_num, ((rcvHdrPtr->pageNum) << 8) + sizeof(RCV_BUFF_STAT),
numBytes, REMOTE_READ);
remDmaDo(dev_num, ((UCHAR *) &(rcvHdrPtr->daddr)), numBytes, REMOTE_READ);
remDmaSetup(dev_num, (LAN_RXSTART << 8) + 0,
rcvHdrPtr->dataLen - numBytes, REMOTE_READ);
remDmaDo(dev_num, (UCHAR *) (((ULONG) &(rcvHdrPtr->daddr)) + numBytes),
rcvHdrPtr->dataLen - numBytes, REMOTE_READ);
}
}
/***********************************************************************/
/* remDmaSetup: Set up The remote DMA channel for Reading or Writing */
/* the specified number of bytes remote DMA channel */
/* */
/* INPUTS: long dev_num = Device number */
/* ULONG PageNum = Ring buffer page # + offset in page */
/* ULONG len = Number of bytes to read/write */
/* ULONG Op = Remote READ or Remote WRITE */
/* OUTPUTS: None */
/* */
/***********************************************************************/
STATIC void remDmaSetup(long dev_num, ULONG Pg, ULONG len, ULONG Op)
{
if (len & 0x1)
len++;
/*---------------------------------------------------------------------*/
/* For remote writes setup Xfr as read first. !?! - The manual says so */
/*---------------------------------------------------------------------*/
wrStNicCR(dev_num, LAN_PG0_CR_RD2+LAN_PAGE0+LAN_PG0_CR_STA);
/*---------------------------------------------------------------------*/
/* Set up the remote DMA channel - Byte count & Page address */
/*---------------------------------------------------------------------*/
wrStNicReg(dev_num, LAN_PG0_RBCR0, (UCHAR)(len & 0xFF), LAN_PAGE0);
wrStNicReg(dev_num, LAN_PG0_RBCR1, (UCHAR)((len >> 8) & 0xFF), LAN_PAGE0);
wrStNicReg(dev_num, LAN_PG0_RSAR0, (UCHAR)(Pg & 0xFF), LAN_PAGE0);
wrStNicReg(dev_num, LAN_PG0_RSAR1, (UCHAR)((Pg >> 8) & 0xFF), LAN_PAGE0);
/*---------------------------------------------------------------------*/
/* Set up requested transfer type */
/*---------------------------------------------------------------------*/
if (Op == REMOTE_READ)
wrStNicCR(dev_num, LAN_PG0_CR_RD0|LAN_PG0_CR_STA);
else
wrStNicCR(dev_num, LAN_PG0_CR_RD1);
}
/***********************************************************************/
/* remDmaDo: Perform the transfer of the specified number of bytes */
/* */
/* INPUTS: long dev_num = Device number */
/* UCHAR *bufPtr = Address of transfer buffer */
/* ULONG len = Number of bytes to read/write */
/* ULONG Op = Remote READ or Remote WRITE */
/* OUTPUTS: None */
/* */
/* NOTES: Optimized in assembly in asm.s */
/* */
/***********************************************************************/
STATIC void remDmaDo(long dev_num, UCHAR *bufPtr, ULONG len, ULONG Op)
{
USHORT svar, *bptr = (USHORT *)bufPtr;
int count;
count = len >> 1;
if (Op == REMOTE_READ)
{
while (count-- != 0)
{
*bptr = inw(portPtr[dev_num]);
bptr++;
}
if (len & 0x1)
{
svar = inw(portPtr[dev_num]);
*((char *) bptr) = (char) svar;
}
}
else
{
/* REMOTE_WRITE always called with even length (len) */
while (count-- != 0)
{
outw(portPtr[dev_num], *bptr);
bptr++;
}
}
}
/***********************************************************************/
/* TxCpyData: Copy data to Transmit buffers from a transmit header */
/* */
/* INPUTS: curtxPtr: Current transmit header */
/* pageNum: Trasmit page number */
/* OUTPUTS: None */
/* */
/***********************************************************************/
STATIC void TxCpyData(LAN_TX_HDR *curtxPtr, ULONG pageNum)
{
mblk_t *msgBlk;
ULONG i, length, frameLen, write_flag=0;
long dev_num;
unsigned short prev_word=0;
/*---------------------------------------------------------------------*/
/* Set up the device number from the packet structure */
/*---------------------------------------------------------------------*/
dev_num = curtxPtr->dev_num;
/*---------------------------------------------------------------------*/
/* Update min transmit count if required */
/*---------------------------------------------------------------------*/
if (curtxPtr->numBytes < 64)
curtxPtr->numBytes = 64;
/*---------------------------------------------------------------------*/
/* Copy transmit header info into remote buffer area */
/*---------------------------------------------------------------------*/
remDmaSetup(dev_num, (pageNum << 8) + 0, curtxPtr->numBytes, REMOTE_WRITE);
remDmaDo(dev_num, (UCHAR *) &(curtxPtr->daddr), 0x06, REMOTE_WRITE);
remDmaDo(dev_num, (UCHAR *) &(curtxPtr->saddr), 0x06, REMOTE_WRITE);
remDmaDo(dev_num, (UCHAR *) &(curtxPtr->type), 0x02, REMOTE_WRITE);
/*---------------------------------------------------------------------*/
/* Now copy the buffers pointed to by the message block triplet in. */
/*---------------------------------------------------------------------*/
frameLen = 14;
msgBlk = curtxPtr->msg_ptr;
while (msgBlk)
{
length = msgBlk->b_wptr - msgBlk->b_rptr;
/*---------------------------------------------------------------*/
/* Combine last byte of previous mblk with first byte of current */
/* Note length > 0, since zero blocks are freed initially */
/*---------------------------------------------------------------*/
if (write_flag)
{
prev_word = prev_word | ((USHORT)(msgBlk->b_rptr[0]) << 8);
frameLen += 2;
remDmaDo(dev_num, (UCHAR *) &prev_word, 2, REMOTE_WRITE);
length--;
msgBlk->b_rptr++;
write_flag = 0;
}
/*---------------------------------------------------------------*/
/* Copy the last byte. Send it out in next DmaDo */
/*---------------------------------------------------------------*/
if (length & 0x1)
{
write_flag = 1;
prev_word = msgBlk->b_wptr[-1];
length--;
}
frameLen += length;
/*---------------------------------------------------------------*/
/* Copy the message block data */
/*---------------------------------------------------------------*/
remDmaDo(dev_num, (UCHAR *) msgBlk->b_rptr, length, REMOTE_WRITE);
msgBlk = msgBlk->b_cont;
}
/*---------------------------------------------------------------------*/
/* Last byte left in the last mblk. Pad it to 2 bytes and send it out */
/*---------------------------------------------------------------------*/
if (write_flag)
{
prev_word = prev_word | 0;
frameLen += 2;
remDmaDo(dev_num, (UCHAR *) &prev_word, 2, REMOTE_WRITE);
}
/*---------------------------------------------------------------------*/
/* If the frame length is less than 64 pad till 64 */
/*---------------------------------------------------------------------*/
if (frameLen < 64)
{
length = 64 - frameLen;
/* Note length is always even, since frameLen is even */
for (i = 0; i < (length >> 1); i++)
{
outw(portPtr[dev_num], 0x0000);
}
}
}
/***********************************************************************/
/* TxFillBuffs_isr: Called from isr on trasmit completion */
/* Move outgoing packets from the outgoing queue to the */
/* transmit buffers ring, if possible. */
/* */
/* INPUTS: long dev_num */
/* OUTPUTS: None */
/* */
/***********************************************************************/
STATIC void TxFillBuffs_isr(long dev_num)
{
if (TxCurrHdrPtr[dev_num][0] == (struct TxHdr *) -1)
{
if (TxAbortpageNum[dev_num] == LAN_TXSTART)
{
TxAbortpageNum[dev_num] = -1;
ns8390_trigger_send(dev_num, LAN_TXSTART,
(ULONG)TxAbortnumBytes[dev_num]);
}
else
TxCurrHdrPtr[dev_num][0] = NULL;
}
if (TxCurrHdrPtr[dev_num][1] == (struct TxHdr *) -1)
{
if (TxAbortpageNum[dev_num] == (LAN_TXSTART + 6))
{
TxAbortpageNum[dev_num] = -1;
ns8390_trigger_send(dev_num, LAN_TXSTART + 6,
(ULONG)TxAbortnumBytes[dev_num]);
}
else
TxCurrHdrPtr[dev_num][1] = NULL;
}
TxFillBuffs(dev_num);
}
/***********************************************************************/
/* TxFillBuffs: Move outgoing packets from the outgoing queue to the */
/* transmit buffers ring, if possible. */
/* */
/* INPUTS: long dev_num = Device number */
/* OUTPUTS: TxUsedPtr is updated */
/* */
/***********************************************************************/
STATIC void TxFillBuffs(long dev_num)
{
ULONG i, iLevel;
ULONG pageNum;
LAN_TX_HDR **currtxpptr;
ULONG numBytes;
for (;;)
{
/*-----------------------------------------------------------------*/
/* Disable Interrupts for critical processing */
/*----------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -