Exemplo n.º 1
0
/*---------------------------------------------------------------------------*
 *	Data destinator switch for write channels - 0, 2 and 4
 *---------------------------------------------------------------------------*/
struct mbuf *
ihfc_getmbuf (ihfc_sc_t *sc, u_char chan)
{
	register struct mbuf  *m;
	i4b_trace_hdr_t hdr;

	if (chan < 2)
	{
		IF_DEQUEUE(&S_IFQUEUE, m);

		if((S_TRACE & TRACE_D_TX) && m)
		{
			hdr.count = ++S_DTRACECOUNT;
			hdr.dir   = FROM_TE;
			hdr.type  = TRC_CH_D;
			hdr.unit  = S_I4BUNIT;

			MICROTIME(hdr.time);

			i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
		}
	}
	else
	{
		IF_DEQUEUE(&S_IFQUEUE, m);

		if (!m)
		{
			S_BDRVLINK->bch_tx_queue_empty(S_BDRVLINK->unit);

			IF_DEQUEUE(&S_IFQUEUE, m);
		}
		if (m)
		{
		 	if(!i4b_l1_bchan_tel_silence(m->m_data, m->m_len))
			{
				S_BDRVLINK->bch_activity(S_BDRVLINK->unit, ACT_TX);
			}

			S_BYTES += m->m_len;

			if(S_TRACE & TRACE_B_TX)
			{
				hdr.count = ++S_BTRACECOUNT;
				hdr.dir   = FROM_TE;
				hdr.type  = (chan < 4) ? TRC_CH_B1 : TRC_CH_B2;
				hdr.unit  = S_I4BUNIT;

				MICROTIME(hdr.time);

				i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
			}
		}
	}

	return(m);
}
Exemplo n.º 2
0
/*---------------------------------------------------------------------------*
 *	start transmission on a b channel
 *---------------------------------------------------------------------------*/
static void
isic_bchannel_start(int unit, int h_chan)
{
	struct l1_softc *sc = &l1_sc[unit];
	l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
	int next_len;
	int len;
	int activity = -1;
	int cmd = 0;

	crit_enter();
	if(chan->state & HSCX_TX_ACTIVE)	/* already running ? */
	{
		crit_exit();
		return;				/* yes, leave */
	}

	/* get next mbuf from queue */
	
	IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
	
	if(chan->out_mbuf_head == NULL)		/* queue empty ? */
	{
		crit_exit();
		return;				/* yes, exit */
	}

	/* init current mbuf values */
	
	chan->out_mbuf_cur = chan->out_mbuf_head;
	chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
	chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;	
	
	/* activity indicator for timeout handling */

	if(chan->bprot == BPROT_NONE)
	{
		if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
			activity = ACT_TX;
	}
	else
	{
		activity = ACT_TX;
	}

	chan->state |= HSCX_TX_ACTIVE;		/* we start transmitting */
	
	if(sc->sc_trace & TRACE_B_TX)	/* if trace, send mbuf to trace dev */
	{
		i4b_trace_hdr_t hdr;
		hdr.unit = L0ISICUNIT(unit);
		hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
		hdr.dir = FROM_TE;
		hdr.count = ++sc->sc_trace_bcount;
		MICROTIME(hdr.time);
		i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
	}			

	len = 0;	/* # of chars put into HSCX tx fifo this time */

	/*
	 * fill the HSCX tx fifo with data from the current mbuf. if
	 * current mbuf holds less data than HSCX fifo length, try to
	 * get the next mbuf from (a possible) mbuf chain. if there is
	 * not enough data in a single mbuf or in a chain, then this
	 * is the last mbuf and we tell the HSCX that it has to send
	 * CRC and closing flag
	 */
	 
	while((len < sc->sc_bfifolen) && chan->out_mbuf_cur)
	{
		/*
		 * put as much data into the HSCX fifo as is
		 * available from the current mbuf
		 */
		 
		if((len + chan->out_mbuf_cur_len) >= sc->sc_bfifolen)
			next_len = sc->sc_bfifolen - len;
		else
			next_len = chan->out_mbuf_cur_len;

#ifdef NOTDEF		
		kprintf("b:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ",
			chan->out_mbuf_head,
			chan->out_mbuf_cur,			
			chan->out_mbuf_cur_ptr,
			chan->out_mbuf_cur_len,
			len,
			next_len);
#endif

		/* wait for tx fifo write enabled */

		isic_hscx_waitxfw(sc, h_chan);

		/* write what we have from current mbuf to HSCX fifo */

		HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, next_len);

		len += next_len;		/* update # of bytes written */
		chan->txcount += next_len;	/* statistics */
		chan->out_mbuf_cur_ptr += next_len;	/* data ptr */
		chan->out_mbuf_cur_len -= next_len;	/* data len */

		/*
		 * in case the current mbuf (of a possible chain) data
		 * has been put into the fifo, check if there is a next
		 * mbuf in the chain. If there is one, get ptr to it
		 * and update the data ptr and the length
		 */
		 
		if((chan->out_mbuf_cur_len <= 0)	&&
		  ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL))
		{
			chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
			chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;

			if(sc->sc_trace & TRACE_B_TX)
			{
				i4b_trace_hdr_t hdr;
				hdr.unit = L0ISICUNIT(unit);
				hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
				hdr.dir = FROM_TE;
				hdr.count = ++sc->sc_trace_bcount;
				MICROTIME(hdr.time);
				i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
			}			
		}
	}

	/*
	 * if there is either still data in the current mbuf and/or
	 * there is a successor on the chain available issue just
	 * a XTF (transmit) command to HSCX. if ther is no more
	 * data available from the current mbuf (-chain), issue
	 * an XTF and an XME (message end) command which will then
	 * send the CRC and the closing HDLC flag sequence
	 */
	 
	if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0))
	{
		/*
		 * more data available, send current fifo out.
		 * next xfer to HSCX tx fifo is done in the
		 * HSCX interrupt routine.
		 */
		 
		cmd |= HSCX_CMDR_XTF;
	}
	else
	{
		/* end of mbuf chain */
	
		if(chan->bprot == BPROT_NONE)
			cmd |= HSCX_CMDR_XTF;
		else
			cmd |= HSCX_CMDR_XTF | HSCX_CMDR_XME;
		
		i4b_Bfreembuf(chan->out_mbuf_head);	/* free mbuf chain */
		
		chan->out_mbuf_head = NULL;
		chan->out_mbuf_cur = NULL;			
		chan->out_mbuf_cur_ptr = NULL;
		chan->out_mbuf_cur_len = 0;
	}

	/* call timeout handling routine */
	
	if(activity == ACT_RX || activity == ACT_TX)
		(*chan->isic_drvr_linktab->bch_activity)(chan->isic_drvr_linktab->unit, activity);

	if(cmd)
		isic_hscx_cmd(sc, h_chan, cmd);
		
	crit_exit();
}
Exemplo n.º 3
0
/*---------------------------------------------------------------------------*
 *	B-channel interrupt handler
 *---------------------------------------------------------------------------*/
void
iwic_bchan_xirq(struct iwic_softc *sc, int chan_no)
{
	int irq_stat;
	struct iwic_bchan *chan;
	int cmd = 0;
	int activity = 0;

	chan = &sc->sc_bchan[chan_no];

	irq_stat = IWIC_READ(sc, chan->offset + B_EXIR);

	NDBGL1(L1_H_IRQ, "irq_stat = 0x%x", irq_stat);
	
	if((irq_stat & (B_EXIR_RMR | B_EXIR_RME | B_EXIR_RDOV | B_EXIR_XFR | B_EXIR_XDUN)) == 0)
	{
		NDBGL1(L1_H_XFRERR, "spurious IRQ!");
		return;
	}

	if (irq_stat & B_EXIR_RDOV)
	{
		NDBGL1(L1_H_XFRERR, "iwic%d: EXIR B-channel Receive Data Overflow", sc->sc_unit);
	}

	if (irq_stat & B_EXIR_XDUN)
	{
		NDBGL1(L1_H_XFRERR, "iwic%d: EXIR B-channel Transmit Data Underrun", sc->sc_unit);
		cmd |= (B_CMDR_XRST);	/*XXX must retransmit frame ! */
	}

/* RX message end interrupt */
	
	if(irq_stat & B_EXIR_RME)
	{
		int error;

		NDBGL1(L1_H_IRQ, "B_EXIR_RME");

		error = (IWIC_READ(sc,chan->offset+B_STAR) &
			 (B_STAR_RDOV | B_STAR_CRCE | B_STAR_RMB));

		if(error)
		{
			if(error & B_STAR_RDOV)
				NDBGL1(L1_H_XFRERR, "iwic%d: B-channel Receive Data Overflow", sc->sc_unit);
			if(error & B_STAR_CRCE)
				NDBGL1(L1_H_XFRERR, "iwic%d: B-channel CRC Error", sc->sc_unit);
			if(error & B_STAR_RMB)
				NDBGL1(L1_H_XFRERR, "iwic%d: B-channel Receive Message Aborted", sc->sc_unit);
		}

		/* all error conditions checked, now decide and take action */
		
		if(error == 0)
		{
			int fifo_data_len;
			fifo_data_len = ((IWIC_READ(sc,chan->offset+B_RBCL)) &
					((IWIC_BCHAN_FIFO_LEN)-1));
		
			if(fifo_data_len == 0)
				fifo_data_len = IWIC_BCHAN_FIFO_LEN;


			if(chan->in_mbuf == NULL)
			{
				if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
					panic("L1 iwic_bchan_irq: RME, cannot allocate mbuf!\n");
				chan->in_cbptr = chan->in_mbuf->m_data;
				chan->in_len = 0;
			}

			if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
			{
				/* read data from fifo */
	
				NDBGL1(L1_H_IRQ, "B_EXIR_RME, rd fifo, len = %d", fifo_data_len);

				IWIC_RDBFIFO(sc, chan, chan->in_cbptr, fifo_data_len);

				cmd |= (B_CMDR_RACK | B_CMDR_RACT);
				IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
				cmd = 0;
				
		                chan->in_len += fifo_data_len;
				chan->rxcount += fifo_data_len;

				/* setup mbuf data length */
					
				chan->in_mbuf->m_len = chan->in_len;
				chan->in_mbuf->m_pkthdr.len = chan->in_len;

				if(sc->sc_trace & TRACE_B_RX)
				{
					i4b_trace_hdr_t hdr;
					hdr.unit = L0IWICUNIT(sc->sc_unit);
					hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
					hdr.dir = FROM_NT;
					hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
					MICROTIME(hdr.time);
					i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
				}

				(*chan->iwic_drvr_linktab->bch_rx_data_ready)(chan->iwic_drvr_linktab->unit);

				activity = ACT_RX;
				
				/* mark buffer ptr as unused */
					
				chan->in_mbuf = NULL;
				chan->in_cbptr = NULL;
				chan->in_len = 0;
			}
			else
			{
				NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d", chan->in_len, fifo_data_len);
				chan->in_cbptr = chan->in_mbuf->m_data;
				chan->in_len = 0;
				cmd |= (B_CMDR_RRST | B_CMDR_RACK);
			}
		}
		else
		{
			if (chan->in_mbuf != NULL)
			{
				i4b_Bfreembuf(chan->in_mbuf);
				chan->in_mbuf = NULL;
				chan->in_cbptr = NULL;
				chan->in_len = 0;
			}
			cmd |= (B_CMDR_RRST | B_CMDR_RACK);
		}
	}

/* RX fifo full interrupt */

	if(irq_stat & B_EXIR_RMR)
	{
		NDBGL1(L1_H_IRQ, "B_EXIR_RMR");

		if(chan->in_mbuf == NULL)
		{
			if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
				panic("L1 iwic_bchan_irq: RMR, cannot allocate mbuf!\n");
			chan->in_cbptr = chan->in_mbuf->m_data;
			chan->in_len = 0;
		}

		chan->rxcount += IWIC_BCHAN_FIFO_LEN;
		
		if((chan->in_len + IWIC_BCHAN_FIFO_LEN) <= BCH_MAX_DATALEN)
		{
			/* read data from fifo */

			NDBGL1(L1_H_IRQ, "B_EXIR_RMR, rd fifo, len = max (64)");
			
			IWIC_RDBFIFO(sc, chan, chan->in_cbptr, IWIC_BCHAN_FIFO_LEN);

			chan->in_cbptr += IWIC_BCHAN_FIFO_LEN;
	                chan->in_len += IWIC_BCHAN_FIFO_LEN;
		}
		else
		{
			if(chan->bprot == BPROT_NONE)
			{
				/* setup mbuf data length */
				
				chan->in_mbuf->m_len = chan->in_len;
				chan->in_mbuf->m_pkthdr.len = chan->in_len;

				if(sc->sc_trace & TRACE_B_RX)
				{
					i4b_trace_hdr_t hdr;
					hdr.unit = L0IWICUNIT(sc->sc_unit);
					hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
					hdr.dir = FROM_NT;
					hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
					MICROTIME(hdr.time);
					i4b_l1_trace_ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
				}

				/* silence detection */
				
				if(!(i4b_l1_bchan_tel_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
					activity = ACT_RX;

				if(!(IF_QFULL(&chan->rx_queue)))
				{
					IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
				}
				else
				{
					i4b_Bfreembuf(chan->in_mbuf);
				}
				/* signal upper driver that data is available */

				(*chan->iwic_drvr_linktab->bch_rx_data_ready)(chan->iwic_drvr_linktab->unit);
				
				/* alloc new buffer */
				
				if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
					panic("L1 iwic_bchan_irq: RMR, cannot allocate new mbuf!\n");
	
				/* setup new data ptr */
				
				chan->in_cbptr = chan->in_mbuf->m_data;
	
				/* read data from fifo */
	
				NDBGL1(L1_H_IRQ, "B_EXIR_RMR, rd fifo1, len = max (64)");
				
				IWIC_RDBFIFO(sc, chan, chan->in_cbptr, IWIC_BCHAN_FIFO_LEN);

				chan->in_cbptr += IWIC_BCHAN_FIFO_LEN;
				chan->in_len = IWIC_BCHAN_FIFO_LEN;

				chan->rxcount += IWIC_BCHAN_FIFO_LEN;
			}
			else
			{
				NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
				chan->in_cbptr = chan->in_mbuf->m_data;
				chan->in_len = 0;
				cmd |= (B_CMDR_RRST | B_CMDR_RACK);
			}
		}
		
		/* command to release fifo space */
		
		cmd |= B_CMDR_RACK;
	}

/* TX interrupt */
	
	if (irq_stat & B_EXIR_XFR)
	{			
		/* transmit fifo empty, new data can be written to fifo */

		int activity = -1;
		int len;
		int nextlen;

		NDBGL1(L1_H_IRQ, "B_EXIR_XFR");
		
		if(chan->out_mbuf_cur == NULL) 	/* last frame is transmitted */
		{
			IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);

			if(chan->out_mbuf_head == NULL)
			{
				chan->state &= ~ST_TX_ACTIVE;
				(*chan->iwic_drvr_linktab->bch_tx_queue_empty)(chan->iwic_drvr_linktab->unit);
			}
			else
			{
				chan->state |= ST_TX_ACTIVE;
				chan->out_mbuf_cur = chan->out_mbuf_head;
				chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
				chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;

				if(sc->sc_trace & TRACE_B_TX)
				{
					i4b_trace_hdr_t hdr;
					hdr.unit = L0IWICUNIT(sc->sc_unit);
					hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
					hdr.dir = FROM_TE;
					hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
					MICROTIME(hdr.time);
					i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
				}

				if(chan->bprot == BPROT_NONE)
				{
					if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
						activity = ACT_TX;
				}
				else
				{
					activity = ACT_TX;
				}
			}
		}
			
		len = 0;

		while(chan->out_mbuf_cur && len != IWIC_BCHAN_FIFO_LEN)
		{
			nextlen = min(chan->out_mbuf_cur_len, IWIC_BCHAN_FIFO_LEN - len);

			NDBGL1(L1_H_IRQ, "B_EXIR_XFR, wr fifo, len = %d", nextlen);
			
			IWIC_WRBFIFO(sc, chan, chan->out_mbuf_cur_ptr, nextlen);

			cmd |= B_CMDR_XMS;
	
			len += nextlen;
			chan->txcount += nextlen;
	
			chan->out_mbuf_cur_ptr += nextlen;
			chan->out_mbuf_cur_len -= nextlen;
			
			if(chan->out_mbuf_cur_len == 0) 
			{
				if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
				{
					chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
					chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;

					if(sc->sc_trace & TRACE_B_TX)
					{
						i4b_trace_hdr_t hdr;
						hdr.unit = L0IWICUNIT(sc->sc_unit);
						hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
						hdr.dir = FROM_TE;
						hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
						MICROTIME(hdr.time);
						i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
					}
				}
				else
				{
					if (chan->bprot != BPROT_NONE)
						cmd |= B_CMDR_XME;
					i4b_Bfreembuf(chan->out_mbuf_head);
					chan->out_mbuf_head = NULL;
				}
			}
		}
	}
	if(cmd)
	{
		cmd |= B_CMDR_RACT;
		IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
	}
}
Exemplo n.º 4
0
/*---------------------------------------------------------------------------*
 *	start transmission on a b channel
 *---------------------------------------------------------------------------*/
static void
iwic_bchannel_start(int unit, int chan_no)
{
	struct iwic_softc *sc = &iwic_sc[unit];
	struct iwic_bchan *chan = &sc->sc_bchan[chan_no];
	int next_len;
	int len;
	int activity = -1;
	int cmd = 0;

	crit_enter();

	NDBGL1(L1_BCHAN, "unit %d, channel %d", unit, chan_no);

	if(chan->state & ST_TX_ACTIVE)		/* already running ? */
	{
		crit_exit();
		return;				/* yes, leave */
	}

	/* get next mbuf from queue */
	
	IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
	
	if(chan->out_mbuf_head == NULL)		/* queue empty ? */
	{
		crit_exit();
		return;				/* yes, exit */
	}

	/* init current mbuf values */
	
	chan->out_mbuf_cur = chan->out_mbuf_head;
	chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
	chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;	
	
	/* activity indicator for timeout handling */

	if(chan->bprot == BPROT_NONE)
	{
		if(!(i4b_l1_bchan_tel_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
			activity = ACT_TX;
	}
	else
	{
		activity = ACT_TX;
	}

	chan->state |= ST_TX_ACTIVE;		/* we start transmitting */

	if(sc->sc_trace & TRACE_B_TX)	/* if trace, send mbuf to trace dev */
	{
		i4b_trace_hdr_t hdr;
		hdr.unit = L0IWICUNIT(unit);
		hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
		hdr.dir = FROM_TE;
		hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
		MICROTIME(hdr.time);
		i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
	}			

	len = 0;	/* # of chars put into tx fifo this time */

	/*
	 * fill the tx fifo with data from the current mbuf. if
	 * current mbuf holds less data than fifo length, try to
	 * get the next mbuf from (a possible) mbuf chain. if there is
	 * not enough data in a single mbuf or in a chain, then this
	 * is the last mbuf and we tell the chip that it has to send
	 * CRC and closing flag
	 */
	 
	while((len < IWIC_BCHAN_FIFO_LEN) && chan->out_mbuf_cur)
	{
		/*
		 * put as much data into the fifo as is
		 * available from the current mbuf
		 */
		 
		if((len + chan->out_mbuf_cur_len) >= IWIC_BCHAN_FIFO_LEN)
			next_len = IWIC_BCHAN_FIFO_LEN - len;
		else
			next_len = chan->out_mbuf_cur_len;

		/* write what we have from current mbuf to fifo */

		IWIC_WRBFIFO(sc, chan, chan->out_mbuf_cur_ptr, next_len);
		
		len += next_len;		/* update # of bytes written */
		chan->txcount += next_len;	/* statistics */
		chan->out_mbuf_cur_ptr += next_len;	/* data ptr */
		chan->out_mbuf_cur_len -= next_len;	/* data len */

		/*
		 * in case the current mbuf (of a possible chain) data
		 * has been put into the fifo, check if there is a next
		 * mbuf in the chain. If there is one, get ptr to it
		 * and update the data ptr and the length
		 */
		 
		if((chan->out_mbuf_cur_len <= 0)	&&
		  ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL))
		{
			chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
			chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;

			if(sc->sc_trace & TRACE_B_TX)
			{
				i4b_trace_hdr_t hdr;
				hdr.unit = L0IWICUNIT(unit);
				hdr.type = (chan_no == IWIC_BCH_A ? TRC_CH_B1 : TRC_CH_B2);
				hdr.dir = FROM_TE;
				hdr.count = ++sc->sc_bchan[chan_no].sc_trace_bcount;
				MICROTIME(hdr.time);
				i4b_l1_trace_ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
			}
		}
	}

	/*
	 * if there is either still data in the current mbuf and/or
	 * there is a successor on the chain available issue just
	 * a XTF (transmit) command to the chip. if there is no more
	 * data available from the current mbuf (-chain), issue
	 * an XTF and an XME (message end) command which will then
	 * send the CRC and the closing HDLC flag sequence
	 */
	 
	if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0))
	{
		/*
		 * more data available, send current fifo out.
		 * next xfer to tx fifo is done in the
		 * interrupt routine.
		 */
		 
		cmd |= B_CMDR_XMS;
	}
	else
	{
		/* end of mbuf chain */
	
		if(chan->bprot == BPROT_NONE)
			cmd |= B_CMDR_XMS;
		else
			cmd |= (B_CMDR_XMS | B_CMDR_XME);
		
		i4b_Bfreembuf(chan->out_mbuf_head);	/* free mbuf chain */
		
		chan->out_mbuf_head = NULL;
		chan->out_mbuf_cur = NULL;			
		chan->out_mbuf_cur_ptr = NULL;
		chan->out_mbuf_cur_len = 0;
	}

	/* call timeout handling routine */
	
	if(activity == ACT_RX || activity == ACT_TX)
		(*chan->iwic_drvr_linktab->bch_activity)(chan->iwic_drvr_linktab->unit, activity);

	if(cmd)
	{
		cmd |= B_CMDR_RACT;
		IWIC_WRITE(sc, chan->offset + B_CMDR, cmd);
	}
		
	crit_exit();
}
Exemplo n.º 5
0
/*---------------------------------------------------------------------------*
 *	Data source switch for Read channels - 1, 3 and 5 (B and D-Channel)
 *---------------------------------------------------------------------------*/
void
ihfc_putmbuf (ihfc_sc_t *sc, u_char chan, struct mbuf *m)
{
	i4b_trace_hdr_t hdr;

	if (chan < 2)
	{
		if(S_TRACE & TRACE_D_RX)
		{
			hdr.count = ++S_DTRACECOUNT;
			hdr.dir   = FROM_NT;
			hdr.type  = TRC_CH_D;
			hdr.unit  = S_I4BUNIT;

			MICROTIME(hdr.time);

			i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
		}

		if (!S_ENABLED) { i4b_Dfreembuf(m); return; }

		m->m_pkthdr.len = m->m_len;
	
		i4b_l1_ph_data_ind(S_I4BUNIT, m);
	}
	else
	{
		if(S_TRACE & TRACE_B_RX)
		{
			hdr.count = ++S_BTRACECOUNT;
			hdr.dir   = FROM_NT;
			hdr.type  = (chan < 4) ? TRC_CH_B1 : TRC_CH_B2;
			hdr.unit  = S_I4BUNIT;

			MICROTIME(hdr.time);

			i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
		}

		if (!S_ENABLED) { i4b_Bfreembuf(m); return; }

		if (S_PROT == BPROT_NONE)
		{
			if(!i4b_l1_bchan_tel_silence(m->m_data, m->m_len))
			{
				S_BDRVLINK->bch_activity(S_BDRVLINK->unit, ACT_RX);
			}

			if (!_IF_QFULL(&S_IFQUEUE))
			{
				S_BYTES += m->m_len;
				IF_ENQUEUE(&S_IFQUEUE, m);
				S_BDRVLINK->bch_rx_data_ready(S_BDRVLINK->unit);
			}

			return;
		}

		if (S_PROT == BPROT_RHDLC)
		{
			S_MBUFDUMMY = m;
			S_BYTES    += m->m_pkthdr.len = m->m_len;
			S_BDRVLINK->bch_rx_data_ready(S_BDRVLINK->unit);
			S_MBUFDUMMY = NULL;

			return;
		}

		NDBGL1(L1_ERROR, "Unknown protocol: %d", S_PROT);
	}
}