Beispiel #1
0
/*---------------------------------------------------------------------------*
 *	L0 -> L1 data from hardware
 *---------------------------------------------------------------------------*/
int
i4b_l1_ph_data_ind(int drv_unit, struct mbuf *data)
{
	int *tab;

	if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)	
		panic("i4b_l1_ph_data_ind: unknown driver type %d\n", L0DRVR(drv_unit));

#if 0
	NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
#endif

	return(PH_Data_Ind(tab[L0UNIT(drv_unit)], data));
}
Beispiel #2
0
/*---------------------------------------------------------------------------*
 *	L2 -> L1 command to hardware
 *---------------------------------------------------------------------------*/
int
i4b_l1_mph_command_req(int unit, int command, void * parm)
{
	int drv_unit = L0DRVR(l1drvunittab[unit]);
	int ch_unit = L0UNIT(l1drvunittab[unit]);
 
	NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);

	if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
	    || l1mux_func[drv_unit]->mph_command_req == NULL)
		panic("i4b_l1_mph_command_req: unknown driver type %d\n", drv_unit);
 
	return(l1mux_func[drv_unit]->mph_command_req(ch_unit, command, parm));
}
Beispiel #3
0
/*---------------------------------------------------------------------------*
 *	L0 -> L1 trace information to trace driver
 *---------------------------------------------------------------------------*/
int
i4b_l1_trace_ind(i4b_trace_hdr_t *hdr, int len, u_char *data)
{
	int *tab;
	
	if((tab = getl1tab(L0DRVR(hdr->unit))) == NULL)
		panic("i4b_l1_trace_ind: unknown driver type %d\n", L0DRVR(hdr->unit));

	NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d", L0DRVR(hdr->unit), L0UNIT(hdr->unit), tab[L0UNIT(hdr->unit)]);
	
	hdr->unit = tab[L0UNIT(hdr->unit)];

	return(MPH_Trace_Ind(hdr, len, data));
}
Beispiel #4
0
/*---------------------------------------------------------------------------*
 *	wait for HSCX transmit FIFO write enable
 *---------------------------------------------------------------------------*/
void
isic_hscx_waitxfw(struct isic_softc *sc, int h_chan)
{
#define WAITVAL 50
#define WAITTO	200

	int timeout = WAITTO;

	while((!(((HSCX_READ(h_chan, H_STAR)) &
		(HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout)
	{
		DELAY(WAITVAL);
		timeout--;
	}

	if(timeout == 0)
	{
		NDBGL1(L1_H_ERR, "HSCX wait for XFW timeout!");
	}
	else if (timeout != WAITTO)
	{
		NDBGL1(L1_H_XFRERR, "HSCX wait for XFW time: %d uS", (WAITTO-timeout)*50);
	}
}
Beispiel #5
0
/*---------------------------------------------------------------------------*
 *	L2 -> L1 data to be transmitted to hardware
 *---------------------------------------------------------------------------*/
int
i4b_l1_ph_data_req(int unit, struct mbuf *data, int flag)
{
	int drv_unit = L0DRVR(l1drvunittab[unit]);
	int ch_unit = L0UNIT(l1drvunittab[unit]);

#if 0
	NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);
#endif
	
	if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
	    || l1mux_func[drv_unit]->ph_data_req == NULL)
		panic("i4b_l1_ph_data_req: unknown driver type %d\n", drv_unit);

	return(l1mux_func[drv_unit]->ph_data_req(ch_unit, data, flag));
}
Beispiel #6
0
/*---------------------------------------------------------------------------*
 *	set the ISDN driver linktab
 *---------------------------------------------------------------------------*/
void
i4b_l1_set_linktab(int unit, int channel, drvr_link_t *dlt)
{
	int drv_unit, ch_unit;
 
	drv_unit = L0DRVR(l1drvunittab[unit]);
	ch_unit = L0UNIT(l1drvunittab[unit]);
 
	NDBGL1(L1_PRIM, "unit %d -> drv %d / drvunit %d", unit, drv_unit, ch_unit);

	if (drv_unit >= MAXL1DRVR || l1mux_func[drv_unit] == NULL
	    || l1mux_func[drv_unit]->set_linktab == NULL)
		panic("i4b_l1_set_linktab: unknown driver type %d\n", drv_unit);

	l1mux_func[drv_unit]->set_linktab(ch_unit, channel, dlt);
}
Beispiel #7
0
/*---------------------------------------------------------------------------*
 *	FSM function: received INFO2
 *---------------------------------------------------------------------------*/
static void
F_I2(struct isic_softc *sc)
{
	NDBGL1(L1_F_MSG, "FSM function F_I2 executing");

	if(sc->sc_trace & TRACE_I)
	{
		i4b_trace_hdr hdr;
		char info = INFO2;

		hdr.type = TRC_CH_I;
		hdr.dir = FROM_NT;
		hdr.count = 0;
		isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
	}
}
Beispiel #8
0
/*---------------------------------------------------------------------------*
 *	write command to HSCX command register
 *---------------------------------------------------------------------------*/
void
isic_hscx_cmd(struct isic_softc *sc, int h_chan, unsigned char cmd)
{
	int timeout = 20;

	while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout)
	{
		DELAY(10);
		timeout--;
	}

	if(timeout == 0)
	{
		NDBGL1(L1_H_ERR, "HSCX wait for CEC timeout!");
	}

	HSCX_WRITE(h_chan, H_CMDR, cmd);
}
Beispiel #9
0
/*---------------------------------------------------------------------------*
 *	FSM function: received INFO 0 in states F3 .. F5
 *---------------------------------------------------------------------------*/	
static void
F_I01(struct l1_softc *sc)
{
	NDBGL1(L1_F_MSG, "FSM function F_I01 executing");

	if(sc->sc_trace & TRACE_I)
	{
		i4b_trace_hdr_t hdr;
		char info = INFO0;
		
		hdr.unit = L0IFPNPUNIT(sc->sc_unit);
		hdr.type = TRC_CH_I;
		hdr.dir = FROM_NT;
		hdr.count = 0;
		MICROTIME(hdr.time);
		i4b_l1_trace_ind(&hdr, 1, &info);
	}
}
/*---------------------------------------------------------------------------*
 *	initalize / deinitialize B-channel hardware
 *---------------------------------------------------------------------------*/
static void
iwic_bchan_init(struct iwic_softc *sc, int chan_no, int activate)
{
	struct iwic_bchan *bchan = &sc->sc_bchan[chan_no];

	NDBGL1(L1_BCHAN, "chan %d, activate %d", chan_no, activate);

	if(activate)
	{
		if(bchan->bprot == BPROT_NONE)
		{
			/* Extended transparent mode */
			IWIC_WRITE(sc, bchan->offset + B_MODE, B_MODE_MMS);
		}
		else
		{
			/* Transparent mode */
			IWIC_WRITE(sc, bchan->offset + B_MODE, 0);
			/* disable address comparation */
			IWIC_WRITE (sc, bchan->offset+B_ADM1, 0xff);
			IWIC_WRITE (sc, bchan->offset+B_ADM2, 0xff);
		}

		/* reset & start receiver */
		IWIC_WRITE(sc, bchan->offset + B_CMDR, B_CMDR_RRST|B_CMDR_RACT);

		/* clear irq mask */
		IWIC_WRITE(sc, bchan->offset + B_EXIM, 0);
	}
	else
	{
		/* mask all irqs */		
		IWIC_WRITE(sc, bchan->offset + B_EXIM, 0xff);

		/* reset mode */
		IWIC_WRITE(sc, bchan->offset + B_MODE, 0);
		
		/* Bring interface down */
		IWIC_WRITE(sc, bchan->offset + B_CMDR, B_CMDR_RRST | B_CMDR_XRST);

		/* Flush pending interrupts */
		IWIC_READ(sc, bchan->offset + B_EXIR);
	}
}
Beispiel #11
0
/*---------------------------------------------------------------------------*
 *	FSM function: received INFO 0 in state F6
 *---------------------------------------------------------------------------*/
static void
F_I02(struct isic_softc *sc)
{
	NDBGL1(L1_F_MSG, "FSM function F_I02 executing");

	if(((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S)
		isdn_layer2_activate_ind(&sc->sc_l2, sc->sc_l3token, 0);

	if(sc->sc_trace & TRACE_I)
	{
		i4b_trace_hdr hdr;
		char info = INFO0;

		hdr.type = TRC_CH_I;
		hdr.dir = FROM_NT;
		hdr.count = 0;
		isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, 1, &info);
	}
}
Beispiel #12
0
/*---------------------------------------------------------------------------*
 *	FSM function: received INFO 0 in state F6
 *---------------------------------------------------------------------------*/	
static void
F_I02(struct l1_softc *sc)
{
	NDBGL1(L1_F_MSG, "FSM function F_I02 executing");

	if(ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S)
		i4b_l1_ph_deactivate_ind(L0IFPNPUNIT(sc->sc_unit));

	if(sc->sc_trace & TRACE_I)
	{
		i4b_trace_hdr_t hdr;
		char info = INFO0;
		
		hdr.unit = L0IFPNPUNIT(sc->sc_unit);
		hdr.type = TRC_CH_I;
		hdr.dir = FROM_NT;
		hdr.count = 0;
		MICROTIME(hdr.time);
		i4b_l1_trace_ind(&hdr, 1, &info);
	}
}
Beispiel #13
0
/*---------------------------------------------------------------------------*
 *	FSM function: activate request
 *---------------------------------------------------------------------------*/	
static void
F_AR(struct l1_softc *sc)
{
	NDBGL1(L1_F_MSG, "FSM function F_AR executing");

	if(sc->sc_trace & TRACE_I)
	{
		i4b_trace_hdr_t hdr;
		char info = INFO1_8;
		
		hdr.unit = L0IFPNPUNIT(sc->sc_unit);
		hdr.type = TRC_CH_I;
		hdr.dir = FROM_TE;
		hdr.count = 0;
		MICROTIME(hdr.time);
		i4b_l1_trace_ind(&hdr, 1, &info);
	}

	ifpnp_isac_l1_cmd(sc, CMD_AR8);

	T3_start(sc);
}
/*---------------------------------------------------------------------------*
 *	ISAC interrupt service routine
 *---------------------------------------------------------------------------*/
void
ifpnp_isac_irq(struct l1_softc *sc, int ista)
{
	u_char c = 0;
	NDBGL1(L1_F_MSG, "unit %d: ista = 0x%02x", sc->sc_unit, ista);

	if(ista & ISAC_ISTA_EXI)	/* extended interrupt */
	{
		c |= ifpnp_isac_exir_hdlr(sc, ISAC_READ(I_EXIR));
	}
	
	if(ista & ISAC_ISTA_RME)	/* receive message end */
	{
		int rest;
		u_char rsta;

		/* get rx status register */
		
		rsta = ISAC_READ(I_RSTA);

		if((rsta & ISAC_RSTA_MASK) != 0x20)
		{
			int error = 0;
			
			if(!(rsta & ISAC_RSTA_CRC))	/* CRC error */
			{
				error++;
				NDBGL1(L1_I_ERR, "unit %d: CRC error", sc->sc_unit);
			}
	
			if(rsta & ISAC_RSTA_RDO)	/* ReceiveDataOverflow */
			{
				error++;
				NDBGL1(L1_I_ERR, "unit %d: Data Overrun error", sc->sc_unit);
			}
	
			if(rsta & ISAC_RSTA_RAB)	/* ReceiveABorted */
			{
				error++;
				NDBGL1(L1_I_ERR, "unit %d: Receive Aborted error", sc->sc_unit);
			}

			if(error == 0)			
				NDBGL1(L1_I_ERR, "unit %d: RME unknown error, RSTA = 0x%02x!", sc->sc_unit, rsta);

			i4b_Dfreembuf(sc->sc_ibuf);

			c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;

			sc->sc_ibuf = NULL;
			sc->sc_ib = NULL;
			sc->sc_ilen = 0;

			ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
			ISACCMDRWRDELAY();

			return;
		}

		rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));

		if(rest == 0)
			rest = ISAC_FIFO_LEN;

		if(sc->sc_ibuf == NULL)
		{
			if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
				sc->sc_ib = sc->sc_ibuf->m_data;
			else
				panic("ifpnp_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n");
			sc->sc_ilen = 0;
		}

		if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
		{
			ISAC_RDFIFO(sc->sc_ib, rest);
			sc->sc_ilen += rest;
			
			sc->sc_ibuf->m_pkthdr.len =
				sc->sc_ibuf->m_len = sc->sc_ilen;

			if(sc->sc_trace & TRACE_D_RX)
			{
				i4b_trace_hdr_t hdr;
				hdr.unit = L0IFPNPUNIT(sc->sc_unit);
				hdr.type = TRC_CH_D;
				hdr.dir = FROM_NT;
				hdr.count = ++sc->sc_trace_dcount;
				MICROTIME(hdr.time);
				i4b_l1_trace_ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
			}

			c |= ISAC_CMDR_RMC;

			if(sc->sc_enabled &&
			   (ctrl_desc[sc->sc_unit].protocol != PROTOCOL_D64S))
			{
				i4b_l1_ph_data_ind(L0IFPNPUNIT(sc->sc_unit), sc->sc_ibuf);
			}
			else
			{
				i4b_Dfreembuf(sc->sc_ibuf);
			}
		}
		else
		{
			NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
			i4b_Dfreembuf(sc->sc_ibuf);
			c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
		}

		sc->sc_ibuf = NULL;
		sc->sc_ib = NULL;
		sc->sc_ilen = 0;
	}

	if(ista & ISAC_ISTA_RPF)	/* receive fifo full */
	{
		if(sc->sc_ibuf == NULL)
		{
			if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
				sc->sc_ib= sc->sc_ibuf->m_data;
			else
				panic("ifpnp_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
			sc->sc_ilen = 0;
		}

		if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
		{
			ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
			sc->sc_ilen += ISAC_FIFO_LEN;			
			sc->sc_ib += ISAC_FIFO_LEN;
			c |= ISAC_CMDR_RMC;
		}
		else
		{
			NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
			i4b_Dfreembuf(sc->sc_ibuf);
			sc->sc_ibuf = NULL;
			sc->sc_ib = NULL;
			sc->sc_ilen = 0;
			c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;			
		}
	}

	if(ista & ISAC_ISTA_XPR)	/* transmit fifo empty (XPR bit set) */
	{
		if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
		{
			sc->sc_freeflag = sc->sc_freeflag2;
			sc->sc_obuf = sc->sc_obuf2;
			sc->sc_op = sc->sc_obuf->m_data;
			sc->sc_ol = sc->sc_obuf->m_len;
			sc->sc_obuf2 = NULL;
#ifdef NOTDEF			
			kprintf("ob2=%x, op=%x, ol=%d, f=%d #",
				sc->sc_obuf,
				sc->sc_op,
				sc->sc_ol,
				sc->sc_state);
#endif				
		}
		else
		{
#ifdef NOTDEF
			kprintf("ob=%x, op=%x, ol=%d, f=%d #",
				sc->sc_obuf,
				sc->sc_op,
				sc->sc_ol,
				sc->sc_state);
#endif
		}			
		
		if(sc->sc_obuf)
		{			
			ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));
	
			if(sc->sc_ol > ISAC_FIFO_LEN)	/* length > 32 ? */
			{
				sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
				sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
				c |= ISAC_CMDR_XTF;	    /* set XTF bit */
			}
			else
			{
				if(sc->sc_freeflag)
				{
					i4b_Dfreembuf(sc->sc_obuf);
					sc->sc_freeflag = 0;
				}
				sc->sc_obuf = NULL;
				sc->sc_op = NULL;
				sc->sc_ol = 0;
	
				c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
			}
		}
		else
		{
			sc->sc_state &= ~ISAC_TX_ACTIVE;
		}
	}
	
	if(ista & ISAC_ISTA_CISQ)	/* channel status change CISQ */
	{
		u_char ci;
	
		/* get command/indication rx register*/
	
		ci = ISAC_READ(I_CIRR);

		/* if S/Q IRQ, read SQC reg to clr SQC IRQ */
	
		if(ci & ISAC_CIRR_SQC)
			ISAC_READ(I_SQRR);

		/* C/I code change IRQ (flag already cleared by CIRR read) */
	
		if(ci & ISAC_CIRR_CIC0)
			ifpnp_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
	}
Beispiel #15
0
/*---------------------------------------------------------------------------*
 *	HSCX IRQ Handler
 *---------------------------------------------------------------------------*/
void
isic_hscx_irq(register struct isic_softc *sc, u_char ista, int h_chan, u_char ex_irq)
{
	register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
	u_char exir = 0;
	int activity = -1;
	u_char cmd = 0;

	NDBGL1(L1_H_IRQ, "%#x", ista);

	if(ex_irq)
	{
		/* get channel extended irq reg */

		exir = HSCX_READ(h_chan, H_EXIR);

		if(exir & HSCX_EXIR_RFO)
		{
			chan->stat_RFO++;
			NDBGL1(L1_H_XFRERR, "ex_irq: receive data overflow");
		}

		if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
		{
			chan->stat_XDU++;
			NDBGL1(L1_H_XFRERR, "ex_irq: xmit data underrun");
			isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES);

			if (chan->out_mbuf_head != NULL)  /* don't continue to transmit this buffer */
			{
				i4b_Bfreembuf(chan->out_mbuf_head);
				chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
			}
		}

	}

	/* rx message end, end of frame */

	if(ista & HSCX_ISTA_RME)
	{
		register int fifo_data_len;
		u_char rsta;
		int error = 0;

		rsta = HSCX_READ(h_chan, H_RSTA);

		if((rsta & 0xf0) != 0xa0)
		{
			if((rsta & HSCX_RSTA_VFR) == 0)
			{
				chan->stat_VFR++;
				cmd |= (HSCX_CMDR_RHR);
				NDBGL1(L1_H_XFRERR, "received invalid Frame");
				error++;
			}

			if(rsta & HSCX_RSTA_RDO)
			{
				chan->stat_RDO++;
				NDBGL1(L1_H_XFRERR, "receive data overflow");
				error++;
			}

			if((rsta & HSCX_RSTA_CRC) == 0)
			{
				chan->stat_CRC++;
				cmd |= (HSCX_CMDR_RHR);
				NDBGL1(L1_H_XFRERR, "CRC check failed");
				error++;
			}

			if(rsta & HSCX_RSTA_RAB)
			{
				chan->stat_RAB++;
				NDBGL1(L1_H_XFRERR, "Receive message aborted");
				error++;
			}
		}

		fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) &
						((sc->sc_bfifolen)-1));

		if(fifo_data_len == 0)
			fifo_data_len = sc->sc_bfifolen;

		/* all error conditions checked, now decide and take action */

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

			fifo_data_len -= 1; /* last byte in fifo is RSTA ! */

			if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
			{
				/* read data from HSCX fifo */

				HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len);

				cmd |= (HSCX_CMDR_RMC);
				isic_hscx_cmd(sc, h_chan, 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 hdr;
					hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
					hdr.dir = FROM_NT;
					hdr.count = ++sc->sc_trace_bcount;
					isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
				}

				(*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);

				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 |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC);
			}
		}
		else
		{
			if (chan->in_mbuf != NULL)
			{
				i4b_Bfreembuf(chan->in_mbuf);
				chan->in_mbuf = NULL;
				chan->in_cbptr = NULL;
				chan->in_len = 0;
			}
			cmd |= (HSCX_CMDR_RMC);
		}
	}

	/* rx fifo full */

	if(ista & HSCX_ISTA_RPF)
	{
		if(chan->in_mbuf == NULL)
		{
			if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
				panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!");
			chan->in_cbptr = chan->in_mbuf->m_data;
			chan->in_len = 0;
		}

		chan->rxcount += sc->sc_bfifolen;

		if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN)
		{
			/* read data from HSCX fifo */

			HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);

			chan->in_cbptr += sc->sc_bfifolen;
	                chan->in_len += sc->sc_bfifolen;
		}
		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 hdr;
					hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
					hdr.dir = FROM_NT;
					hdr.count = ++sc->sc_trace_bcount;
					isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr,chan->in_mbuf->m_len, chan->in_mbuf->m_data);
				}

				/* silence detection */

				if(!(isdn_bchan_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->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);

				/* alloc new buffer */

				if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
					panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!");

				/* setup new data ptr */

				chan->in_cbptr = chan->in_mbuf->m_data;

				/* read data from HSCX fifo */

				HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen);

				chan->in_cbptr += sc->sc_bfifolen;
				chan->in_len = sc->sc_bfifolen;

				chan->rxcount += sc->sc_bfifolen;
			}
			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 |= (HSCX_CMDR_RHR);
			}
		}

		/* command to release fifo space */

		cmd |= HSCX_CMDR_RMC;
	}

	/* transmit fifo empty, new data can be written to fifo */

	if(ista & HSCX_ISTA_XPR)
	{
		/*
		 * for a description what is going on here, please have
		 * a look at isic_bchannel_start() in i4b_bchan.c !
		 */

		int len;
		int nextlen;

		NDBGL1(L1_H_IRQ, "%s, chan %d - XPR, Tx Fifo Empty!", device_xname(sc->sc_dev), h_chan);

		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 &= ~HSCX_TX_ACTIVE;
				(*chan->l4_driver->bch_tx_queue_empty)(chan->l4_driver_softc);
			}
			else
			{
				chan->state |= HSCX_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 hdr;
					hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
					hdr.dir = FROM_TE;
					hdr.count = ++sc->sc_trace_bcount;
					isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
				}

				if(chan->bprot == BPROT_NONE)
				{
					if(!(isdn_bchan_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 != sc->sc_bfifolen)
		{
			nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);

#ifdef NOTDEF
			printf("i: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

			isic_hscx_waitxfw(sc, h_chan);	/* necessary !!! */

			HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen);
			cmd |= HSCX_CMDR_XTF;

			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 hdr;
						hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
						hdr.dir = FROM_TE;
						hdr.count = ++sc->sc_trace_bcount;
						isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
					}
				}
				else
				{
					if (chan->bprot != BPROT_NONE)
						cmd |= HSCX_CMDR_XME;
					i4b_Bfreembuf(chan->out_mbuf_head);
					chan->out_mbuf_head = NULL;
				}

			}
		}
	}

	if(cmd)		/* is there a command for the HSCX ? */
	{
		isic_hscx_cmd(sc, h_chan, cmd);	/* yes, to HSCX */
	}

	/* call timeout handling routine */

	if(activity == ACT_RX || activity == ACT_TX)
		(*chan->l4_driver->bch_activity)(chan->l4_driver_softc, activity);
}
Beispiel #16
0
/*---------------------------------------------------------------------------*
 *
 *	L2 -> L1: PH-DATA-REQUEST
 *	=========================
 *
 *	parms:
 *		unit		physical interface unit number
 *		m		mbuf containing L2 frame to be sent out
 *		freeflag	MBUF_FREE: free mbuf here after having sent
 *						it out
 *				MBUF_DONTFREE: mbuf is freed by Layer 2
 *	returns:
 *		==0	fail, nothing sent out
 *		!=0	ok, frame sent out
 *
 *---------------------------------------------------------------------------*/
int
ifpi_ph_data_req(int unit, struct mbuf *m, int freeflag)
{
	u_char cmd;
	struct l1_softc *sc = ifpi_scp[unit];

#ifdef NOTDEF
	NDBGL1(L1_PRIM, "PH-DATA-REQ, unit %d, freeflag=%d", unit, freeflag);
#endif

	if(m == NULL)			/* failsafe */
		return (0);

	crit_enter();

	if(sc->sc_I430state == ST_F3)	/* layer 1 not running ? */
	{
		NDBGL1(L1_I_ERR, "still in state F3!");
		ifpi_ph_activate_req(unit);
	}

	if(sc->sc_state & ISAC_TX_ACTIVE)
	{
		if(sc->sc_obuf2 == NULL)
		{
			sc->sc_obuf2 = m;		/* save mbuf ptr */

			if(freeflag)
				sc->sc_freeflag2 = 1;	/* IRQ must mfree */
			else
				sc->sc_freeflag2 = 0;	/* IRQ must not mfree */

			NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", ifpi_printstate(sc));

			if(sc->sc_trace & TRACE_D_TX)
			{
				i4b_trace_hdr_t hdr;
				hdr.unit = L0IFPIUNIT(unit);
				hdr.type = TRC_CH_D;
				hdr.dir = FROM_TE;
				hdr.count = ++sc->sc_trace_dcount;
				MICROTIME(hdr.time);
				i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
			}
			crit_exit();
			return(1);
		}

		NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", ifpi_printstate(sc));
	
		if(freeflag == MBUF_FREE)
			i4b_Dfreembuf(m);			
	
		crit_exit();
		return (0);
	}

	if(sc->sc_trace & TRACE_D_TX)
	{
		i4b_trace_hdr_t hdr;
		hdr.unit = L0IFPIUNIT(unit);
		hdr.type = TRC_CH_D;
		hdr.dir = FROM_TE;
		hdr.count = ++sc->sc_trace_dcount;
		MICROTIME(hdr.time);
		i4b_l1_trace_ind(&hdr, m->m_len, m->m_data);
	}
	
	sc->sc_state |= ISAC_TX_ACTIVE;	/* set transmitter busy flag */

	NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set");

	sc->sc_freeflag = 0;		/* IRQ must NOT mfree */
	
	ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */

	if(m->m_len > ISAC_FIFO_LEN)	/* message > 32 bytes ? */
	{
		sc->sc_obuf = m;	/* save mbuf ptr */
		sc->sc_op = m->m_data + ISAC_FIFO_LEN; 	/* ptr for irq hdl */
		sc->sc_ol = m->m_len - ISAC_FIFO_LEN;	/* length for irq hdl */

		if(freeflag)
			sc->sc_freeflag = 1;	/* IRQ must mfree */
		
		cmd = ISAC_CMDR_XTF;
	}
	else
	{
		sc->sc_obuf = NULL;
		sc->sc_op = NULL;
		sc->sc_ol = 0;

		if(freeflag)
			i4b_Dfreembuf(m);

		cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
  	}

	ISAC_WRITE(I_CMDR, cmd);
	ISACCMDRWRDELAY();

	crit_exit();
	
	return(1);
}
Beispiel #17
0
/*---------------------------------------------------------------------------*
 *	L0 -> L1 status indication from hardware
 *---------------------------------------------------------------------------*/
int
i4b_l1_mph_status_ind(int drv_unit, int status, int parm, struct i4b_l1mux_func *l1mux_func_p)
{
	int *tab;
	
	/*
	 * in case the status STI_ATTACH is sent from the hardware, the
	 * driver has just attached itself and we need to initialize
	 * the tables and assorted variables.
	 */

	if(status == STI_ATTACH)
	{
		if (l1mux_func_p == NULL)
			panic("i4b_l1_mph_status_ind: i4b_l1mux_func pointer is NULL\n");

		if(numl1units < MAXL1UNITS)
		{
			if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)
				panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));
			
			tab[L0UNIT(drv_unit)] = numl1units;

			l1drvunittab[numl1units] = drv_unit;

			l1mux_func[L0DRVR(drv_unit)] = l1mux_func_p;

			switch(L0DRVR(drv_unit))
			{
#if NISIC > 0
				case L1DRVR_ISIC:
					kprintf("isic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
					break;
#endif
#if NIWIC > 0
				case L1DRVR_IWIC:
					kprintf("iwic%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
					break;
#endif
#if NIFPI > 0
				case L1DRVR_IFPI:
					kprintf("ifpi%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
					break;
#endif
#if NIFPI2 > 0
				case L1DRVR_IFPI2:
					kprintf("ifpi2-%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
					break;
#endif
#if NIFPNP > 0
				case L1DRVR_IFPNP:
					kprintf("ifpnp%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
					break;
#endif
#if NIHFC > 0
				case L1DRVR_IHFC:
					kprintf("ihfc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
					break;
#endif
#if NITJC > 0
				case L1DRVR_ITJC:
					kprintf("itjc%d: passive stack unit %d\n", L0UNIT(drv_unit), numl1units);
					break;
#endif
			}
			
			NDBGL1(L1_PRIM, "ATTACH drv %d, drvunit %d -> unit %d", L0DRVR(drv_unit), L0UNIT(drv_unit), numl1units);

			numl1units++;			
		}
	}

	if((tab = getl1tab(L0DRVR(drv_unit))) == NULL)	
		panic("i4b_l1_mph_status_ind: unknown driver type %d\n", L0DRVR(drv_unit));

	NDBGL1(L1_PRIM, "(drv %d / drvunit %d) -> unit %d\n", L0DRVR(drv_unit), L0UNIT(drv_unit), tab[L0UNIT(drv_unit)]);
	
	return(MPH_Status_Ind(tab[L0UNIT(drv_unit)], status, parm));
}
/*---------------------------------------------------------------------------*
 *	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();
}
/*---------------------------------------------------------------------------*
 *	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);
	}
}
Beispiel #20
0
/*---------------------------------------------------------------------------*
 *
 *	L2 -> L1: PH-DATA-REQUEST
 *	=========================
 *
 *	parms:
 *		token		softc of physical driver
 *		m		mbuf containing L2 frame to be sent out
 *		freeflag	MBUF_FREE: free mbuf here after having sent
 *						it out
 *				MBUF_DONTFREE: mbuf is freed by Layer 2
 *	returns:
 *		==0	fail, nothing sent out
 *		!=0	ok, frame sent out
 *
 *---------------------------------------------------------------------------*/
static int
isic_std_ph_data_req(isdn_layer1token token, struct mbuf *m, int freeflag)
{
	struct isic_softc *sc = (struct isic_softc*)token;
	u_char cmd;
	int s;

	if (m == NULL)			/* failsafe */
		return (0);

	s = splnet();

	if(sc->sc_I430state == ST_F3)	/* layer 1 not running ? */
	{
		NDBGL1(L1_I_ERR, "still in state F3!");
		isic_std_ph_activate_req(token);
	}

	if(sc->sc_state & ISAC_TX_ACTIVE)
	{
		if(sc->sc_obuf2 == NULL)
		{
			sc->sc_obuf2 = m;		/* save mbuf ptr */

			if(freeflag)
				sc->sc_freeflag2 = 1;	/* IRQ must mfree */
			else
				sc->sc_freeflag2 = 0;	/* IRQ must not mfree */

			NDBGL1(L1_I_MSG, "using 2nd ISAC TX buffer, state = %s", isic_printstate(sc));

			if(sc->sc_trace & TRACE_D_TX)
			{
				i4b_trace_hdr hdr;
				hdr.type = TRC_CH_D;
				hdr.dir = FROM_TE;
				hdr.count = ++sc->sc_trace_dcount;
				isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, m->m_len, m->m_data);
			}
			splx(s);
			return(1);
		}

		NDBGL1(L1_I_ERR, "No Space in TX FIFO, state = %s", isic_printstate(sc));

		if(freeflag == MBUF_FREE)
			i4b_Dfreembuf(m);

		splx(s);
		return (0);
	}

	if(sc->sc_trace & TRACE_D_TX)
	{
		i4b_trace_hdr hdr;
		hdr.type = TRC_CH_D;
		hdr.dir = FROM_TE;
		hdr.count = ++sc->sc_trace_dcount;
		isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, m->m_len, m->m_data);
	}

	sc->sc_state |= ISAC_TX_ACTIVE;	/* set transmitter busy flag */

	NDBGL1(L1_I_MSG, "ISAC_TX_ACTIVE set");

	sc->sc_freeflag = 0;		/* IRQ must NOT mfree */

	ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */

	if(m->m_len > ISAC_FIFO_LEN)	/* message > 32 bytes ? */
	{
		sc->sc_obuf = m;	/* save mbuf ptr */
		sc->sc_op = m->m_data + ISAC_FIFO_LEN; 	/* ptr for irq hdl */
		sc->sc_ol = m->m_len - ISAC_FIFO_LEN;	/* length for irq hdl */

		if(freeflag)
			sc->sc_freeflag = 1;	/* IRQ must mfree */

		cmd = ISAC_CMDR_XTF;
	}
	else
	{
		sc->sc_obuf = NULL;
		sc->sc_op = NULL;
		sc->sc_ol = 0;

		if(freeflag)
			i4b_Dfreembuf(m);

		cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
  	}

	ISAC_WRITE(I_CMDR, cmd);
	ISACCMDRWRDELAY();

	splx(s);

	return(1);
}
Beispiel #21
0
/*---------------------------------------------------------------------------*
 *	ISAC interrupt service routine
 *---------------------------------------------------------------------------*/
void
isic_isac_irq(struct isic_softc *sc, int ista)
{
	register u_char c = 0;
	NDBGL1(L1_F_MSG, "%s: ista = 0x%02x", device_xname(&sc->sc_dev), ista);

	if(ista & ISAC_ISTA_EXI)	/* extended interrupt */
	{
		u_int8_t exirstat = ISAC_READ(I_EXIR);
		if (sc->sc_intr_valid == ISIC_INTR_VALID)
			c |= isic_isac_exir_hdlr(sc, exirstat);
	}

	if(ista & ISAC_ISTA_RME)	/* receive message end */
	{
		register int rest;
		u_char rsta;

		/* get rx status register */

		rsta = ISAC_READ(I_RSTA);

		if((rsta & ISAC_RSTA_MASK) != 0x20)
		{
			int error = 0;

			if(!(rsta & ISAC_RSTA_CRC))	/* CRC error */
			{
				error++;
				NDBGL1(L1_I_ERR, "%s: CRC error", device_xname(&sc->sc_dev));
			}

			if(rsta & ISAC_RSTA_RDO)	/* ReceiveDataOverflow */
			{
				error++;
				NDBGL1(L1_I_ERR, "%s: Data Overrun error", device_xname(&sc->sc_dev));
			}

			if(rsta & ISAC_RSTA_RAB)	/* ReceiveABorted */
			{
				error++;
				NDBGL1(L1_I_ERR, "%s: Receive Aborted error", device_xname(&sc->sc_dev));
			}

			if(error == 0)
			{
				NDBGL1(L1_I_ERR, "%s: RME unknown error, RSTA = 0x%02x!", device_xname(&sc->sc_dev), rsta);
			}

			i4b_Dfreembuf(sc->sc_ibuf);

			c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;

			sc->sc_ibuf = NULL;
			sc->sc_ib = NULL;
			sc->sc_ilen = 0;

			ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES);
			ISACCMDRWRDELAY();

			return;
		}

		rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1));

		if(rest == 0)
			rest = ISAC_FIFO_LEN;

		if(sc->sc_ibuf == NULL)
		{
			if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
				sc->sc_ib = sc->sc_ibuf->m_data;
			else
				panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!");
			sc->sc_ilen = 0;
		}

		if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
		{
			ISAC_RDFIFO(sc->sc_ib, rest);
			sc->sc_ilen += rest;

			sc->sc_ibuf->m_pkthdr.len =
				sc->sc_ibuf->m_len = sc->sc_ilen;

			if(sc->sc_trace & TRACE_D_RX)
			{
				i4b_trace_hdr hdr;
				memset(&hdr, 0, sizeof hdr);
				hdr.type = TRC_CH_D;
				hdr.dir = FROM_NT;
				hdr.count = ++sc->sc_trace_dcount;
				isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
			}

			c |= ISAC_CMDR_RMC;

			if(sc->sc_intr_valid == ISIC_INTR_VALID &&
			   (((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S))
			{
				isdn_layer2_data_ind(&sc->sc_l2, sc->sc_l3token, sc->sc_ibuf);
			}
			else
			{
				i4b_Dfreembuf(sc->sc_ibuf);
			}
		}
		else
		{
			NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
			i4b_Dfreembuf(sc->sc_ibuf);
			c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
		}

		sc->sc_ibuf = NULL;
		sc->sc_ib = NULL;
		sc->sc_ilen = 0;
	}

	if(ista & ISAC_ISTA_RPF)	/* receive fifo full */
	{
		if(sc->sc_ibuf == NULL)
		{
			if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
				sc->sc_ib= sc->sc_ibuf->m_data;
			else
				panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!");
			sc->sc_ilen = 0;
		}

		if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN))
		{
			ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN);
			sc->sc_ilen += ISAC_FIFO_LEN;
			sc->sc_ib += ISAC_FIFO_LEN;
			c |= ISAC_CMDR_RMC;
		}
		else
		{
			NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
			i4b_Dfreembuf(sc->sc_ibuf);
			sc->sc_ibuf = NULL;
			sc->sc_ib = NULL;
			sc->sc_ilen = 0;
			c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES;
		}
	}

	if(ista & ISAC_ISTA_XPR)	/* transmit fifo empty (XPR bit set) */
	{
		if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
		{
			sc->sc_freeflag = sc->sc_freeflag2;
			sc->sc_obuf = sc->sc_obuf2;
			sc->sc_op = sc->sc_obuf->m_data;
			sc->sc_ol = sc->sc_obuf->m_len;
			sc->sc_obuf2 = NULL;
#ifdef NOTDEF
			printf("ob2=%x, op=%x, ol=%d, f=%d #",
				sc->sc_obuf,
				sc->sc_op,
				sc->sc_ol,
				sc->sc_state);
#endif
		}
		else
		{
#ifdef NOTDEF
			printf("ob=%x, op=%x, ol=%d, f=%d #",
				sc->sc_obuf,
				sc->sc_op,
				sc->sc_ol,
				sc->sc_state);
#endif
		}

		if(sc->sc_obuf)
		{
			ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN));

			if(sc->sc_ol > ISAC_FIFO_LEN)	/* length > 32 ? */
			{
				sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */
				sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */
				c |= ISAC_CMDR_XTF;	    /* set XTF bit */
			}
			else
			{
				if(sc->sc_freeflag)
				{
					i4b_Dfreembuf(sc->sc_obuf);
					sc->sc_freeflag = 0;
				}
				sc->sc_obuf = NULL;
				sc->sc_op = NULL;
				sc->sc_ol = 0;

				c |= ISAC_CMDR_XTF | ISAC_CMDR_XME;
			}
		}
		else
		{
			sc->sc_state &= ~ISAC_TX_ACTIVE;
		}
	}

	if(ista & ISAC_ISTA_CISQ)	/* channel status change CISQ */
	{
		register u_char ci;

		/* get command/indication rx register*/

		ci = ISAC_READ(I_CIRR);

		/* if S/Q IRQ, read SQC reg to clr SQC IRQ */

		if(ci & ISAC_CIRR_SQC)
			(void) ISAC_READ(I_SQRR);

		/* C/I code change IRQ (flag already cleared by CIRR read) */

		if(ci & ISAC_CIRR_CIC0)
			isic_isac_ind_hdlr(sc, (ci >> 2) & 0xf);
	}

	if(c)
	{
		ISAC_WRITE(I_CMDR, c);
		ISACCMDRWRDELAY();
	}
}
Beispiel #22
0
/*---------------------------------------------------------------------------*
 *	illegal state default action
 *---------------------------------------------------------------------------*/	
static void
F_ill(struct l1_softc *sc)
{
	NDBGL1(L1_F_ERR, "FSM function F_ill executing");
}
Beispiel #23
0
/*---------------------------------------------------------------------------*
 *	ISACSX interrupt service routine
 *---------------------------------------------------------------------------*/
void
isic_isacsx_irq(struct isic_softc *sc, int ista)
{
	register u_char c = 0;
	register u_char istad = 0;

	NDBGL1(L1_F_MSG, "%s: ista = 0x%02x", device_xname(&sc->sc_dev), ista);

	/* was it an HDLC interrupt ? */
	if (ista & ISACSX_ISTA_ICD)
	{
		istad = ISAC_READ(I_ISTAD);
		NDBGL1(L1_F_MSG, "%s: istad = 0x%02x", device_xname(&sc->sc_dev), istad);

		if(istad & (ISACSX_ISTAD_RFO|ISACSX_ISTAD_XMR|ISACSX_ISTAD_XDU))
		{
			/* not really EXIR, but very similar */
			c |= isic_isacsx_exir_hdlr(sc, istad);
		}
	}

	if(istad & ISACSX_ISTAD_RME)	/* receive message end */
	{
		register int rest;
		u_char rsta;

		/* get rx status register */

		rsta = ISAC_READ(I_RSTAD);

		/* Check for Frame and CRC valid */
		if((rsta & ISACSX_RSTAD_MASK) != (ISACSX_RSTAD_VFR|ISACSX_RSTAD_CRC))
		{
			int error = 0;

			if(!(rsta & ISACSX_RSTAD_VFR))	/* VFR error */
			{
				error++;
				NDBGL1(L1_I_ERR, "%s: Frame not valid error", device_xname(&sc->sc_dev));
			}

			if(!(rsta & ISACSX_RSTAD_CRC))	/* CRC error */
			{
				error++;
				NDBGL1(L1_I_ERR, "%s: CRC error", device_xname(&sc->sc_dev));
			}

			if(rsta & ISACSX_RSTAD_RDO)	/* ReceiveDataOverflow */
			{
				error++;
				NDBGL1(L1_I_ERR, "%s: Data Overrun error", device_xname(&sc->sc_dev));
			}

			if(rsta & ISACSX_RSTAD_RAB)	/* ReceiveABorted */
			{
				error++;
				NDBGL1(L1_I_ERR, "%s: Receive Aborted error", device_xname(&sc->sc_dev));
			}

			if(error == 0)
				NDBGL1(L1_I_ERR, "%s: RME unknown error, RSTAD = 0x%02x!", device_xname(&sc->sc_dev), rsta);

			i4b_Dfreembuf(sc->sc_ibuf);

			c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES;

			sc->sc_ibuf = NULL;
			sc->sc_ib = NULL;
			sc->sc_ilen = 0;

			ISAC_WRITE(I_CMDRD, ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES);

			return;
		}

		rest = (ISAC_READ(I_RBCLD) & (ISACSX_FIFO_LEN-1));

		if(rest == 0)
			rest = ISACSX_FIFO_LEN;

		if(sc->sc_ibuf == NULL)
		{
			if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL)
				sc->sc_ib = sc->sc_ibuf->m_data;
			else
				panic("isic_isacsx_irq: RME, i4b_Dgetmbuf returns NULL!\n");
			sc->sc_ilen = 0;
		}

		if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest))
		{
			ISAC_RDFIFO(sc->sc_ib, rest);
			 /* the  last byte contains status, strip it */
			sc->sc_ilen += rest - 1;

			sc->sc_ibuf->m_pkthdr.len =
				sc->sc_ibuf->m_len = sc->sc_ilen;

			if(sc->sc_trace & TRACE_D_RX)
			{
				i4b_trace_hdr hdr;

				memset(&hdr, 0, sizeof hdr);
				hdr.type = TRC_CH_D;
				hdr.dir = FROM_NT;
				hdr.count = ++sc->sc_trace_dcount;
				isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data);
			}

			c |= ISACSX_CMDRD_RMC;

			if(sc->sc_intr_valid == ISIC_INTR_VALID &&
			   (((struct isdn_l3_driver*)sc->sc_l3token)->protocol != PROTOCOL_D64S))
			{
				isdn_layer2_data_ind(&sc->sc_l2, sc->sc_l3token, sc->sc_ibuf);
			}
			else
			{
				i4b_Dfreembuf(sc->sc_ibuf);
			}
		}
		else
		{
			NDBGL1(L1_I_ERR, "RME, input buffer overflow!");
			i4b_Dfreembuf(sc->sc_ibuf);
			c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES;
		}

		sc->sc_ibuf = NULL;
		sc->sc_ib = NULL;
		sc->sc_ilen = 0;
	}

	if(istad & ISACSX_ISTAD_RPF)	/* receive fifo full */
	{
		if(sc->sc_ibuf == NULL)
		{
			if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL)
				sc->sc_ib= sc->sc_ibuf->m_data;
			else
				panic("isic_isacsx_irq: RPF, i4b_Dgetmbuf returns NULL!\n");
			sc->sc_ilen = 0;
		}

		if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISACSX_FIFO_LEN))
		{
			ISAC_RDFIFO(sc->sc_ib, ISACSX_FIFO_LEN);
			sc->sc_ilen += ISACSX_FIFO_LEN;
			sc->sc_ib += ISACSX_FIFO_LEN;
			c |= ISACSX_CMDRD_RMC;
		}
		else
		{
			NDBGL1(L1_I_ERR, "RPF, input buffer overflow!");
			i4b_Dfreembuf(sc->sc_ibuf);
			sc->sc_ibuf = NULL;
			sc->sc_ib = NULL;
			sc->sc_ilen = 0;
			c |= ISACSX_CMDRD_RMC|ISACSX_CMDRD_RRES;
		}
	}

	if(istad & ISACSX_ISTAD_XPR)	/* transmit fifo empty (XPR bit set) */
	{
		if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL))
		{
			sc->sc_freeflag = sc->sc_freeflag2;
			sc->sc_obuf = sc->sc_obuf2;
			sc->sc_op = sc->sc_obuf->m_data;
			sc->sc_ol = sc->sc_obuf->m_len;
			sc->sc_obuf2 = NULL;
#ifdef NOTDEF
			printf("ob2=%x, op=%x, ol=%d, f=%d #",
				sc->sc_obuf,
				sc->sc_op,
				sc->sc_ol,
				sc->sc_state);
#endif
		}
		else
		{
#ifdef NOTDEF
			printf("ob=%x, op=%x, ol=%d, f=%d #",
				sc->sc_obuf,
				sc->sc_op,
				sc->sc_ol,
				sc->sc_state);
#endif
		}

		if(sc->sc_obuf)
		{
			ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISACSX_FIFO_LEN));

			if(sc->sc_ol > ISACSX_FIFO_LEN)	/* length > 32 ? */
			{
				sc->sc_op += ISACSX_FIFO_LEN; /* bufferptr+32 */
				sc->sc_ol -= ISACSX_FIFO_LEN; /* length - 32 */
				c |= ISACSX_CMDRD_XTF;	    /* set XTF bit */
			}
			else
			{
				if(sc->sc_freeflag)
				{
					i4b_Dfreembuf(sc->sc_obuf);
					sc->sc_freeflag = 0;
				}
				sc->sc_obuf = NULL;
				sc->sc_op = NULL;
				sc->sc_ol = 0;

				c |= ISACSX_CMDRD_XTF | ISACSX_CMDRD_XME;
			}
		}
		else
		{
			sc->sc_state &= ~ISAC_TX_ACTIVE;
		}
	}

	if(ista & ISACSX_ISTA_CIC)	/* channel status change CISQ */
	{
		register u_char ci;

		/* get command/indication rx register*/

		ci = ISAC_READ(I_CIR0);

		/* C/I code change IRQ (flag already cleared by CIR0 read) */

		if(ci & ISACSX_CIR0_CIC0)
			isic_isacsx_ind_hdlr(sc, (ci >> 4) & 0xf);
	}

	if(c)
	{
		ISAC_WRITE(I_CMDRD, c);
	}
}
Beispiel #24
0
/*---------------------------------------------------------------------------*
 *	ISACSX L1 Indication handler
 *---------------------------------------------------------------------------*/
static void
isic_isacsx_ind_hdlr(register struct isic_softc *sc, int ind)
{
	register int event;

	switch(ind)
	{
		case ISACSX_CIR0_IAI8:
			NDBGL1(L1_I_CICO, "rx AI8 in state %s", isic_printstate(sc));
			if(sc->sc_bustyp == BUS_TYPE_IOM2)
				isic_isacsx_l1_cmd(sc, CMD_AR8);
			event = EV_INFO48;
			isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
			break;

		case ISACSX_CIR0_IAI10:
			NDBGL1(L1_I_CICO, "rx AI10 in state %s", isic_printstate(sc));
			if(sc->sc_bustyp == BUS_TYPE_IOM2)
				isic_isacsx_l1_cmd(sc, CMD_AR10);
			event = EV_INFO410;
			isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
			break;

		case ISACSX_CIR0_IRSY:
			NDBGL1(L1_I_CICO, "rx RSY in state %s", isic_printstate(sc));
			event = EV_RSY;
			break;

		case ISACSX_CIR0_IPU:
			NDBGL1(L1_I_CICO, "rx PU in state %s", isic_printstate(sc));
			event = EV_PU;
			break;

		case ISACSX_CIR0_IDR:
			NDBGL1(L1_I_CICO, "rx DR in state %s", isic_printstate(sc));
			isic_isacsx_l1_cmd(sc, CMD_DIU);
			event = EV_DR;
			break;

		case ISACSX_CIR0_IDID:
			NDBGL1(L1_I_CICO, "rx DID in state %s", isic_printstate(sc));
			event = EV_INFO0;
			isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_IDLE);
			break;

		case ISACSX_CIR0_IDIS:
			NDBGL1(L1_I_CICO, "rx DIS in state %s", isic_printstate(sc));
			event = EV_DIS;
			break;

		case ISACSX_CIR0_IEI:
			NDBGL1(L1_I_CICO, "rx EI in state %s", isic_printstate(sc));
			isic_isacsx_l1_cmd(sc, CMD_DIU);
			event = EV_EI;
			break;

		case ISACSX_CIR0_IARD:
			NDBGL1(L1_I_CICO, "rx ARD in state %s", isic_printstate(sc));
			event = EV_INFO2;
			break;

		case ISACSX_CIR0_ITI:
			NDBGL1(L1_I_CICO, "rx TI in state %s", isic_printstate(sc));
			event = EV_INFO0;
			break;

		case ISACSX_CIR0_IATI:
			NDBGL1(L1_I_CICO, "rx ATI in state %s", isic_printstate(sc));
			event = EV_INFO0;
			break;

		case ISACSX_CIR0_ISD:
			NDBGL1(L1_I_CICO, "rx SD in state %s", isic_printstate(sc));
			event = EV_INFO0;
			break;

		default:
			NDBGL1(L1_I_ERR, "UNKNOWN Indication 0x%x in state %s", ind, isic_printstate(sc));
			event = EV_INFO0;
			break;
	}
	isic_next_state(sc, event);
}
Beispiel #25
0
/*---------------------------------------------------------------------------*
 *	No action
 *---------------------------------------------------------------------------*/	
static void
F_NULL(struct l1_softc *sc)
{
	NDBGL1(L1_F_MSG, "FSM function F_NULL executing");
}
Beispiel #26
0
/*---------------------------------------------------------------------------*
 *	L1 ISAC initialization
 *---------------------------------------------------------------------------*/
int
isic_isac_init(struct isic_softc *sc)
{
	ISAC_IMASK = 0xff;		/* disable all irqs */

	ISAC_WRITE(I_MASK, ISAC_IMASK);

	if(sc->sc_bustyp != BUS_TYPE_IOM2)
	{
		NDBGL1(L1_I_SETUP, "configuring for IOM-1 mode");

		/* ADF2: Select mode IOM-1 */
		ISAC_WRITE(I_ADF2, 0x00);

		/* SPCR: serial port control register:
		 *	SPU - software power up = 0
		 *	SAC - SIP port high Z
		 *	SPM - timing mode 0
		 *	TLP - test loop = 0
		 *	C1C, C2C - B1 and B2 switched to/from SPa
		 */
		ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1);

		/* SQXR: S/Q channel xmit register:
                 *	SQIE - S/Q IRQ enable = 0
		 *	SQX1-4 - Fa bits = 1
		 */
		ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);

		/* ADF1: additional feature reg 1:
		 *	WTC - watchdog = 0
		 *	TEM - test mode = 0
		 *	PFS - pre-filter = 0
		 *	CFS - IOM clock/frame always active
		 *	FSC1/2 - polarity of 8kHz strobe
		 *	ITF - interframe fill = idle
		 */
		ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2);	/* ADF1 */

		/* STCR: sync transfer control reg:
		 *	TSF - terminal secific functions = 0
		 *	TBA - TIC bus address = 7
		 *	STx/SCx = 0
		 */
		ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
	}
	else
	{
		NDBGL1(L1_I_SETUP, "configuring for IOM-2 mode");

		/* ADF2: Select mode IOM-2 */
		ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS);

		/* SPCR: serial port control register:
		 *	SPU - software power up = 0
		 *	SPM - timing mode 0
		 *	TLP - test loop = 0
		 *	C1C, C2C - B1 + C1 and B2 + IC2 monitoring
		 */
		ISAC_WRITE(I_SPCR, 0x00);

		/* SQXR: S/Q channel xmit register:
		 *	IDC  - IOM direction = 0 (master)
		 *	CFS  - Config Select = 0 (clock always active)
		 *	CI1E - C/I channel 1 IRQ enable = 0
                 *	SQIE - S/Q IRQ enable = 0
		 *	SQX1-4 - Fa bits = 1
		 */
		ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4);

		/* ADF1: additional feature reg 1:
		 *	WTC - watchdog = 0
		 *	TEM - test mode = 0
		 *	PFS - pre-filter = 0
		 *	IOF - IOM i/f off = 0
		 *	ITF - interframe fill = idle
		 */
		ISAC_WRITE(I_ADF1, 0x00);

		/* STCR: sync transfer control reg:
		 *	TSF - terminal secific functions = 0
		 *	TBA - TIC bus address = 7
		 *	STx/SCx = 0
		 */
		ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0);
	}


	/* MODE: Mode Register:
	 *	MDSx - transparent mode 2
	 *	TMD  - timer mode = external
	 *	RAC  - Receiver enabled
	 *	DIMx - digital i/f mode
	 */
	ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0);

	/* enabled interrupts:
	 * ===================
	 * RME  - receive message end
	 * RPF  - receive pool full
	 * XPR  - transmit pool ready
	 * CISQ - CI or S/Q channel change
	 * EXI  - extended interrupt
	 */

	ISAC_IMASK = ISAC_MASK_RSC |	/* auto mode only	*/
		     ISAC_MASK_TIN | 	/* timer irq		*/
		     ISAC_MASK_SIN;	/* sync xfer irq	*/

	ISAC_WRITE(I_MASK, ISAC_IMASK);

	ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES);
	ISACCMDRWRDELAY();

	return(0);
}
Beispiel #27
0
/*---------------------------------------------------------------------------*
 *	execute a layer 1 command
 *---------------------------------------------------------------------------*/
void
isic_isacsx_l1_cmd(struct isic_softc *sc, int command)
{
	u_char cmd;

#ifdef I4B_SMP_WORKAROUND

	/* XXXXXXXXXXXXXXXXXXX */

	/*
	 * patch from Wolfgang Helbig:
	 *
	 * Here is a patch that makes i4b work on an SMP:
	 * The card (TELES 16.3) didn't interrupt on an SMP machine.
	 * This is a gross workaround, but anyway it works *and* provides
	 * some information as how to finally fix this problem.
	 */

	HSCX_WRITE(0, H_MASK, 0xff);
	HSCX_WRITE(1, H_MASK, 0xff);
	ISAC_WRITE(I_MASKD, 0xff);
	ISAC_WRITE(I_MASK, 0xff);
	DELAY(100);
	HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
	HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
	ISAC_WRITE(I_MASKD, isacsx_imaskd);
	ISAC_WRITE(I_MASK, isacsx_imask);

	/* XXXXXXXXXXXXXXXXXXX */

#endif /* I4B_SMP_WORKAROUND */

	if(command < 0 || command > CMD_ILL)
	{
		NDBGL1(L1_I_ERR, "illegal cmd 0x%x in state %s", command, isic_printstate(sc));
		return;
	}

	cmd = ISACSX_CIX0_LOW;

	switch(command)
	{
		case CMD_TIM:
			NDBGL1(L1_I_CICO, "tx TIM in state %s", isic_printstate(sc));
			cmd |= (ISACSX_CIX0_CTIM << 4);
			break;

		case CMD_RS:
			NDBGL1(L1_I_CICO, "tx RS in state %s", isic_printstate(sc));
			cmd |= (ISACSX_CIX0_CRS << 4);
			break;

		case CMD_AR8:
			NDBGL1(L1_I_CICO, "tx AR8 in state %s", isic_printstate(sc));
			cmd |= (ISACSX_CIX0_CAR8 << 4);
			break;

		case CMD_AR10:
			NDBGL1(L1_I_CICO, "tx AR10 in state %s", isic_printstate(sc));
			cmd |= (ISACSX_CIX0_CAR10 << 4);
			break;

		case CMD_DIU:
			NDBGL1(L1_I_CICO, "tx DIU in state %s", isic_printstate(sc));
			cmd |= (ISACSX_CIX0_CDIU << 4);
			break;
	}
	ISAC_WRITE(I_CIX0, cmd);
}
Beispiel #28
0
/*---------------------------------------------------------------------------*
 *	isic_recovery - try to recover from irq lockup
 *---------------------------------------------------------------------------*/
void
isic_recover(struct isic_softc *sc)
{
	u_char byte;

	/* get hscx irq status from hscx b ista */

	byte = HSCX_READ(HSCX_CH_B, H_ISTA);

	NDBGL1(L1_ERROR, "HSCX B: ISTA = 0x%x", byte);

	if(byte & HSCX_ISTA_ICA)
		NDBGL1(L1_ERROR, "HSCX A: ISTA = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA));

	if(byte & HSCX_ISTA_EXB)
		NDBGL1(L1_ERROR, "HSCX B: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR));

	if(byte & HSCX_ISTA_EXA)
		NDBGL1(L1_ERROR, "HSCX A: EXIR = 0x%x", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR));

	/* get isac irq status */

	byte = ISAC_READ(I_ISTA);

	NDBGL1(L1_ERROR, "  ISAC: ISTA = 0x%x", byte);

	if(byte & ISAC_ISTA_EXI)
		NDBGL1(L1_ERROR, "  ISAC: EXIR = 0x%x", (u_char)ISAC_READ(I_EXIR));

	if(byte & ISAC_ISTA_CISQ)
	{
		byte = ISAC_READ(I_CIRR);

		NDBGL1(L1_ERROR, "  ISAC: CISQ = 0x%x", byte);

		if(byte & ISAC_CIRR_SQC)
			NDBGL1(L1_ERROR, "  ISAC: SQRR = 0x%x", (u_char)ISAC_READ(I_SQRR));
	}

	NDBGL1(L1_ERROR, "HSCX B: IMASK = 0x%x", HSCX_B_IMASK);
	NDBGL1(L1_ERROR, "HSCX A: IMASK = 0x%x", HSCX_A_IMASK);

	HSCX_WRITE(0, H_MASK, 0xff);
	HSCX_WRITE(1, H_MASK, 0xff);
	DELAY(100);
	HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
	HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
	DELAY(100);

	NDBGL1(L1_ERROR, "  ISAC: IMASK = 0x%x", ISAC_IMASK);

	ISAC_WRITE(I_MASK, 0xff);
	DELAY(100);
	ISAC_WRITE(I_MASK, ISAC_IMASK);
}
Beispiel #29
0
/*---------------------------------------------------------------------------*
 *	initialize one B channels rx/tx data structures and init/deinit HSCX
 *---------------------------------------------------------------------------*/
void
isic_bchannel_setup(int unit, int h_chan, int bprot, int activate)
{
	struct l1_softc *sc = &l1_sc[unit];
	l1_bchan_state_t *chan = &sc->sc_chan[h_chan];

	crit_enter();
	
	if(activate == 0)
	{
		/* deactivation */
		isic_hscx_init(sc, h_chan, activate);
	}
		
	NDBGL1(L1_BCHAN, "unit=%d, channel=%d, %s",
		sc->sc_unit, h_chan, activate ? "activate" : "deactivate");

	/* general part */

	chan->unit = sc->sc_unit;	/* unit number */
	chan->channel = h_chan;	/* B channel */
	chan->bprot = bprot;		/* B channel protocol */
	chan->state = HSCX_IDLE;	/* B channel state */

	/* receiver part */

	chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;

	i4b_Bcleanifq(&chan->rx_queue);	/* clean rx queue */

	chan->rxcount = 0;		/* reset rx counter */
	
	i4b_Bfreembuf(chan->in_mbuf);	/* clean rx mbuf */

	chan->in_mbuf = NULL;		/* reset mbuf ptr */
	chan->in_cbptr = NULL;		/* reset mbuf curr ptr */
	chan->in_len = 0;		/* reset mbuf data len */
	
	/* transmitter part */

	chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;

	i4b_Bcleanifq(&chan->tx_queue);	/* clean tx queue */

	chan->txcount = 0;		/* reset tx counter */
	
	i4b_Bfreembuf(chan->out_mbuf_head);	/* clean tx mbuf */

	chan->out_mbuf_head = NULL;	/* reset head mbuf ptr */
	chan->out_mbuf_cur = NULL;	/* reset current mbuf ptr */	
	chan->out_mbuf_cur_ptr = NULL;	/* reset current mbuf data ptr */
	chan->out_mbuf_cur_len = 0;	/* reset current mbuf data cnt */
	
	if(activate != 0)
	{
		/* activation */
		isic_hscx_init(sc, h_chan, activate);
	}

	crit_exit();
}
Beispiel #30
0
/*---------------------------------------------------------------------------*
 *	initialize one B channels rx/tx data structures
 *---------------------------------------------------------------------------*/
void
iwic_bchannel_setup(int unit, int chan_no, int bprot, int activate)
{
	struct iwic_softc *sc = &iwic_sc[unit];
	struct iwic_bchan *chan = &sc->sc_bchan[chan_no];

	int s = SPLI4B();
	
	NDBGL1(L1_BCHAN, "unit %d, chan %d, bprot %d, activate %d", unit, chan_no, bprot, activate);

	/* general part */

	chan->bprot = bprot;		/* B channel protocol */
	chan->state = ST_IDLE;		/* B channel state */

	if(activate == 0)
	{
		/* deactivation */
		iwic_bchan_init(sc, chan_no, activate);
	}
		
	/* receiver part */

	chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;

#if defined (__FreeBSD__) && __FreeBSD__ > 4
	mtx_init(&chan->rx_queue.ifq_mtx, "i4b_iwic_rx", MTX_DEF);
#endif

	i4b_Bcleanifq(&chan->rx_queue);	/* clean rx queue */

	chan->rxcount = 0;		/* reset rx counter */
	
	i4b_Bfreembuf(chan->in_mbuf);	/* clean rx mbuf */

	chan->in_mbuf = NULL;		/* reset mbuf ptr */
	chan->in_cbptr = NULL;		/* reset mbuf curr ptr */
	chan->in_len = 0;		/* reset mbuf data len */
	
	/* transmitter part */

	chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;

#if defined (__FreeBSD__) && __FreeBSD__ > 4	
	mtx_init(&chan->tx_queue.ifq_mtx, "i4b_iwic_tx", MTX_DEF);
#endif

	i4b_Bcleanifq(&chan->tx_queue);	/* clean tx queue */
	
	chan->txcount = 0;		/* reset tx counter */
	
	i4b_Bfreembuf(chan->out_mbuf_head);	/* clean tx mbuf */

	chan->out_mbuf_head = NULL;	/* reset head mbuf ptr */
	chan->out_mbuf_cur = NULL;	/* reset current mbuf ptr */	
	chan->out_mbuf_cur_ptr = NULL;	/* reset current mbuf data ptr */
	chan->out_mbuf_cur_len = 0;	/* reset current mbuf data cnt */
	
	if(activate != 0)
	{
		/* activation */
		iwic_bchan_init(sc, chan_no, activate);
	}

	splx(s);
}