📄 smc8xx.c
字号:
/* the room in the buffer (has to be done by the user!)... */
/*-----------------------------------------------------------------*/
mblk->b_wptr += bufsize;
/*-----------------------------------------------------------------*/
/* Insert the buffer into our pending list. */
/*-----------------------------------------------------------------*/
imask = splx(MAX_ILEV);
BufListAppend(mblk, &chan->rx_queue);
(void)splx(imask);
/*-----------------------------------------------------------------*/
/* Insert into the chip ring list: the data must be aligned */
/* on a multiple of 4 bytes boundary. */
/*-----------------------------------------------------------------*/
ring->address = (void *)BufSegAddr(mblk);
/*-----------------------------------------------------------------*/
/* Update rx ring pointer, wrap if needed. */
/*-----------------------------------------------------------------*/
_sync_io();
if (ring == bottom)
{
ring->status = SMC_RX_EMPTY | SMC_RX_WRAP | SMC_RX_INTR;
ring = chan->rxrg_top;
}
else
{
ring->status = SMC_RX_EMPTY | SMC_RX_INTR;
ring++;
}
if (++count >= maxcount)
break;
}
/*---------------------------------------------------------------------*/
/* Update descriptor write pointer and unused descriptor count. */
/*---------------------------------------------------------------------*/
chan->rxrg_wr = ring;
chan->unused_rx = count;
/*---------------------------------------------------------------------*/
/* Process flow control, if any. */
/*---------------------------------------------------------------------*/
#if 0
switch (chan->flowState)
{
case XOFF_STATE:
/*-----------------------------------------------------------------*/
/* Receiver is xoffed. Now that it has receive buffers send XON */
/* or set Request To Send. */
/*-----------------------------------------------------------------*/
/* MUST CHANGE if there is more then 1 receive buffer xon! */
if (chan->unused_rx >= (maxcount - 1))
{
chan->flowState = XON_STATE;
if (chan->cfg.Cfg.Uart.Flags & SWFC)
queue_toseq(chan, chan->cfg.Cfg.Uart.XOnCharacter);
}
break;
case XON_STATE:
/*-----------------------------------------------------------------*/
/* Receiver is xon. If there is only one receive buffer send Xoff */
/* or drop Request To Send. */
/*-----------------------------------------------------------------*/
if (chan->unused_rx <= 1)
{
chan->flowState = XOFF_STATE;
if (chan->cfg.Cfg.Uart.Flags & SWFC)
queue_toseq( chan, chan->cfg.Cfg.Uart.XOffCharacter);
}
break;
default:
break;
}
#endif
}
/***********************************************************************/
/* drop_buffer: */
/* This routine drops a frame from the receive ring. */
/* The buffer(s) dropped are returned to the receive pool.*/
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
drop_buffer(chan_control *chan)
{
BuffDescType *ring = chan->rxrg_rd;
mblk_t *mblk;
/* USHORT status; -- delete by szg , no used it */
ULONG imask; /* slpx saved level */
/*---------------------------------------------------------------------*/
/* Increment buffers dropped statistic. */
/*---------------------------------------------------------------------*/
++chan->stats.buffers_dropped;
while (1)
{
_sync_io();
/* status = ring->status; -- delete by szg , no used it */
/*-----------------------------------------------------------------*/
/* Get address of the buffer to be dropped and return it to */
/* free pool by call the free function pointed to by freeb set */
/* in smc8xx_Open */
/*-----------------------------------------------------------------*/
imask = splx(MAX_ILEV);
mblk = BufListRxRemove(&chan->rx_queue);
(void)splx(imask);
if(SCLOSENOFREE == 0)
(chan->freeb)(mblk);
/*-----------------------------------------------------------------*/
/* Null out the descriptor ring entry. */
/*-----------------------------------------------------------------*/
ring->address = (void *)0;
ring->length = 0;
/*-----------------------------------------------------------------*/
/* Update rx ring pointer, wrap if needed. */
/*-----------------------------------------------------------------*/
_sync_io();
if (ring == chan->rxrg_bottom)
{
ring->status = SMC_RX_WRAP;
ring = chan->rxrg_top;
}
else
{
ring->status = 0;
ring++;
}
chan->unused_rx--;
/*-----------------------------------------------------------------*/
/* Stop discarding buffers when a new beginning of frame is */
/* detected or no more descriptors are in use. */
/*-----------------------------------------------------------------*/
if ( ring->address == (void *)0 )
break;
}
/*---------------------------------------------------------------------*/
/* Update channel's pointers to point to the last descriptor checked. */
/*---------------------------------------------------------------------*/
chan->rxrg_rd = ring;
chan->rxrg_ep = ring;
}
/***********************************************************************/
/* frame_receive: */
/* This routine empties a frame from the receive */
/* descriptor ring when a frame has been completely */
/* received by retrieving the associated buffer */
/* descriptors from the receive list and building a */
/* logical buffer out of them. */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/* OUTPUTS: */
/* frameFlag status of frame */
/* */
/***********************************************************************/
static mblk_t *
frame_receive(chan_control *chan, UINT *frameFlag)
{
BuffDescType *ring; /* receive ring pointer */
USHORT rxstatus; /* frame receive status */
USHORT length; /* accumulated length of frame */
USHORT status; /* status of the current Rx BD */
mblk_t *mblk; /* individual receive buffer */
mblk_t *frame; /* the received frame */
ULONG imask; /* slpx saved level */
frame = (mblk_t *)NULL;
*frameFlag = 0;
rxstatus = 0;
/*---------------------------------------------------------------------*/
/* Poll EMPTY bit to see if a frame has been received (restart */
/* from where we last left off). */
/* chan->rxrg_ep is a pointer to a receive buffer descriptor in the */
/* channels ring of receive buffers. It is the next one in the ring */
/* from where the last receive buffer descriptor was taken. */
/*---------------------------------------------------------------------*/
_sync_io();
ring = chan->rxrg_ep;
status = ring->status;
/*---------------------------------------------------------------------*/
/* Scan descriptors for end of packet: */
/* Caution: some segments may have been received, without further */
/* buffers to complete the frame reception, the SMC is */
/* busy and stuck on this last BD (the next one has to be */
/* emptied before the SMC can proceed). */
/* If descriptor is not empty and the buffer pointer is not null */
/* process it. */
/* Check the RBD_EMPTY empty bit if it is not set then the descriptor */
/* should contain valid data. Also check to see if the data buffer */
/* does not point to NULL. */
/*---------------------------------------------------------------------*/
if ( ( (status & SMC_RX_EMPTY) != 0) || (ring->address == (void *)0) )
{
/*-----------------------------------------------------------------*/
/* No frames to process return NULL. */
/*-----------------------------------------------------------------*/
return(frame);
}
/*---------------------------------------------------------------------*/
/* Receive a complete frame: start the reassembly where we last left */
/* off. */
/* chan->rxrg_rd is the current rec ring read position. */
/*---------------------------------------------------------------------*/
ring = chan->rxrg_rd;
/* status = ring->status; -- deleted by szg , not used */
/*---------------------------------------------------------------------*/
/* Initialize length to 0. */
/*---------------------------------------------------------------------*/
/* length = 0; -- deleted by szg, not used */
/*---------------------------------------------------------------------*/
/* Attach the last mblock to the frame. */
/*---------------------------------------------------------------------*/
imask = splx(MAX_ILEV);
_sync_io();
mblk = BufListRxRemove(&chan->rx_queue);
(void)splx(imask);
frame = BufJoin(frame, mblk);
/*---------------------------------------------------------------------*/
/* Update the buffer total length: the last ring entry contains */
/* the length of the whole frame (including the CRC) */
/*---------------------------------------------------------------------*/
length = ring->length;
ring->address = (void *)0;
ring->length = 0;
/*---------------------------------------------------------------------*/
/* Get status to return. */
/*---------------------------------------------------------------------*/
status = ring->status;
/*---------------------------------------------------------------------*/
/* Update rx ring pointer, wrap if needed. */
/*---------------------------------------------------------------------*/
_sync_io();
if (ring == chan->rxrg_bottom)
{
ring->status = SMC_RX_WRAP;
ring = chan->rxrg_top;
}
else
{
ring->status = 0;
ring++;
}
/*---------------------------------------------------------------------*/
/* Decrement unused buffers counter. */
/*---------------------------------------------------------------------*/
--chan->unused_rx;
chan->rxrg_ep = chan->rxrg_rd = ring;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -