📄 smc8xx.c
字号:
/* mblk. */
/* The mblk pointer is then used to free the mblk (return it to */
/* the mblk pool of free mblks. */
/*-----------------------------------------------------------------*/
/* MUST CHANGE what happens if the ring is out of sync with */
/* the rx_queue ? Need some check! */
imask = splx(MAX_ILEV);
buffer = BufListRxRemove(&chan->rx_queue);
(void)splx(imask);
if(SCLOSENOFREE == 0)
(chan->freeb)(buffer);
/*-----------------------------------------------------------------*/
/* Update rx ring pointer, wrap if needed. */
/* rxrg_bottom contains a pointer to the ring bottom. If there */
/* set ring to top and continue. */
/*-----------------------------------------------------------------*/
_sync_io();
if (ring == chan->rxrg_bottom)
{
ring->status = SMC_TX_WRAP;
ring = chan->rxrg_top;
}
else
{
ring->status = 0;
ring++;
}
}
_sync_io();
/*
* update read pointer and clear unused receive descriptor counter
*/
chan->rxrg_rd = ring;
chan->unused_rx = 0;
}
/***********************************************************************/
/* flush_txring: */
/* This routine flushes the transmit descriptor ring */
/* by returning all buffers to the upper layer. */
/* The transmitter should be stopped before this */
/* routine is executed. */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
flush_txring(chan_control *chan)
{
BuffDescType *ring; /* pointer to tx descriptor ring */
mblk_t *buffer; /* upper layer buffer to be returned */
USHORT status; /* ring entry status */
ULONG imask; /* slpx saved level */
/*---------------------------------------------------------------------*/
/* Get current read pointer to descriptor ring. */
/*---------------------------------------------------------------------*/
ring = chan->txrg_rd;
/*---------------------------------------------------------------------*/
/* Delete everything from the transmit descriptor ring and */
/* Call the UDataCnf for each buffer in ring. */
/* Go through the ring until a null buffer pointer is found. */
/*---------------------------------------------------------------------*/
while (ring->address != (void *)0)
{
status = ring->status;
_sync_io();
/*-----------------------------------------------------------------*/
/* Instead of adjusting these counters once (at the end of */
/* the loop), we have to keep exact track of what is freed */
/* as the Data Link layer may provide more data to be queued */
/* within the Data Confirmation handler: BEWARE... */
/*-----------------------------------------------------------------*/
chan->unused_tx++;
chan->hard_queued -= ring->length;
/*-----------------------------------------------------------------*/
/* Clear the Buffer Descriptor data pointer and data length. */
/*-----------------------------------------------------------------*/
ring->length = 0;
ring->address = (void *)0;
/*-----------------------------------------------------------------*/
/* Update tx ring pointer, wrap if needed. */
/*-----------------------------------------------------------------*/
_sync_io();
if (ring == chan->txrg_bottom)
{
ring->status = SMC_TX_WRAP;
ring = chan->txrg_top;
}
else
{
ring->status = 0;
ring++;
}
/*-----------------------------------------------------------------*/
/* Check the Interrupt flag (TBD_INT always set if descriptor */
/* is valid). */
/*-----------------------------------------------------------------*/
if ((status & SMC_TX_INTR) != 0)
{
/*-------------------------------------------------------------*/
/* The tx_queue contains a list of actual mblk_t structures, */
/* it operates in parallel to the transmit ring. */
/* The macro BufListTxRemove will remove the first mblk_t */
/* structure from the transmit and return the pointer that */
/* mblk. */
/* The mblk pointer is then used to in the UDataCnf call. */
/* The UDataCnf function status is set to SIOCABORT so the */
/* upper layer code will know this buffer was not transmitted. */
/* NOTE: The upper layer is responsible for freeing the buffer.*/
/*-------------------------------------------------------------*/
imask = splx(MAX_ILEV);
buffer = BufListTxRemove(&chan->tx_queue);
(void)splx(imask);
chan->tx_count--;
DO_DATACNF(buffer, SIOCABORT);
_sync_io();
}
}
/*---------------------------------------------------------------------*/
/* Update read pointer. */
/*---------------------------------------------------------------------*/
chan->txrg_rd = ring;
}
/***********************************************************************/
/* service_queue: */
/* Services SMC software backup queue and keeps */
/* hardware queue full of data. */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
service_queue(chan_control *chan)
{
mblk_t *mblk=NULL; /* frame to be transmitted */
ULONG imask; /* splx saved level */
/*---------------------------------------------------------------------*/
/* Transmit entries out of software queue until empty */
/*---------------------------------------------------------------------*/
while (chan->backup_count > 0)
{
imask = splx(MAX_ILEV);
mblk = BufListTxRemove(&chan->backup_queue);
(void)splx(imask);
if (hardware_transmit(chan, mblk) != SIOCOK)
break;
chan->soft_queued -= BufSize(mblk);
chan->backup_count--;
}
/*---------------------------------------------------------------------*/
/* Requeue the buffer we could not send (at the front of the queue) */
/*---------------------------------------------------------------------*/
if (chan->backup_count != 0
&& mblk!=NULL /* added by just for restraining warning */
)
{
imask = splx(MAX_ILEV);
BufListPrepend(mblk, &chan->backup_queue);
(void)splx(imask);
}
}
/***********************************************************************/
/* flush_backup: */
/* Flush software queue and return all buffers */
/* to their data link layer (should only be called */
/* when the hardware queue is empty!) */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
flush_backup(chan_control *chan)
{
mblk_t *buffer; /* pointer to buffer to cancel */
ULONG imask; /* splx saved level */
while (chan->backup_count != 0)
{
imask = splx(MAX_ILEV);
buffer = BufListTxRemove(&chan->backup_queue);
(void)splx(imask);
chan->backup_count--;
/*----------------------------------------------------------------*/
/* Call the data confirmation function and tell it that this */
/* buffer has been aborted. */
/*----------------------------------------------------------------*/
DO_DATACNF(buffer, SIOCABORT);
}
/*---------------------------------------------------------------------*/
/* Nothing left on the software queue. Set the pointer to NULL. */
/*---------------------------------------------------------------------*/
chan->soft_queued = 0;
}
/***********************************************************************/
/* replenish_desc: */
/* This routine replenishes the receive descriptor */
/* ring with fresh buffers. Only the descriptors */
/* that were used are replenished. Replenish stops */
/* when either the ring is full or we run out of */
/* buffers (up to the maximum configured). */
/* */
/* INPUTS: */
/* chan pointer to the structure that contains channel */
/* information */
/* */
/***********************************************************************/
static void
replenish_desc(chan_control *chan)
{
BuffDescType *ring; /* pointer to receive descriptors */
BuffDescType *bottom; /* bottom of circular ring */
mblk_t *mblk; /* mblk from RxPool */
UINT count; /* count of descriptors ready for SMC */
UINT maxcount; /* max count of desc. for SMC at any time*/
int bufsize; /* individual segment size */
ULONG imask; /* slpx saved level */
maxcount = chan->MaxBuffers;
/*---------------------------------------------------------------------*/
/* Get current write pointer to receive descriptor ring */
/*---------------------------------------------------------------------*/
count = chan->unused_rx;
ring = chan->rxrg_wr;
bottom = chan->rxrg_bottom;
/*---------------------------------------------------------------------*/
/* Set size of individual mblk. */
/*---------------------------------------------------------------------*/
bufsize = chan->cfg.RBuffSize;
/*---------------------------------------------------------------------*/
/* Replenish all receive descriptors with new mblocks */
/* and set EMPTY bit */
/*---------------------------------------------------------------------*/
while (ring->address == (void *)0)
{
/*-----------------------------------------------------------------*/
/* Get a mblock with buffer attached by using the allocation */
/* function pointer for the channel supplied to the smc8xx_Open */
/* call. */
/*-----------------------------------------------------------------*/
mblk = (chan->allocb)(bufsize, BPRI_HI);
if (mblk == (mblk_t *)NULL)
{
chan->stats.no_mblks++;
break;
}
/*-----------------------------------------------------------------*/
/* Compensate for the allocation code not really allocating */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -