Ejemplo n.º 1
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);
}
Ejemplo n.º 2
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);
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
/*---------------------------------------------------------------------------*
 *	HSCX initialization
 *
 *	for telephony: extended transparent mode 1
 *	for raw hdlc:  transparent mode 0
 *---------------------------------------------------------------------------*/
void
isic_hscx_init(struct isic_softc *sc, int h_chan, int activate)
{
	l1_bchan_state_t *chan = &sc->sc_chan[h_chan];

	HSCX_WRITE(h_chan, H_MASK, 0xff);		/* mask irq's */

	if(sc->sc_ipac)
	{
		/* CCR1: Power Up, Clock Mode 5 */
		HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU  |	/* power up */
			      HSCX_CCR1_CM1);	/* IPAC clock mode 5 */
	}
	else
	{
		/* CCR1: Power Up, Clock Mode 5 */
		HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU  |	/* power up */
			      HSCX_CCR1_CM2 |	/* HSCX clock mode 5 */
			      HSCX_CCR1_CM0);
	}

	/* XAD1: Transmit Address Byte 1 */
	HSCX_WRITE(h_chan, H_XAD1, 0xff);

	/* XAD2: Transmit Address Byte 2 */
	HSCX_WRITE(h_chan, H_XAD2, 0xff);

	/* RAH2: Receive Address Byte High Reg. 2 */
	HSCX_WRITE(h_chan, H_RAH2, 0xff);

	/* XBCH: reset Transmit Byte Count High */
	HSCX_WRITE(h_chan, H_XBCH, 0x00);

	/* RLCR: reset Receive Length Check Register */
	HSCX_WRITE(h_chan, H_RLCR, 0x00);

	/* CCR2: set tx/rx clock shift bit 0	*/
	/*       disable CTS irq, disable RIE irq*/
	HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0);

	/* XCCR: tx bit count per time slot */
	HSCX_WRITE(h_chan, H_XCCR, 0x07);

	/* RCCR: rx bit count per time slot */
	HSCX_WRITE(h_chan, H_RCCR, 0x07);

	if(sc->sc_bustyp == BUS_TYPE_IOM2)
	{
		switch(h_chan)
		{
			case HSCX_CH_A:	/* Prepare HSCX channel A */
				/* TSAX: tx clock shift bits 1 & 2	*/
				/*       tx time slot number		*/
		        	HSCX_WRITE(h_chan, H_TSAX, 0x2f);

				/* TSAR: rx clock shift bits 1 & 2	*/
				/*       rx time slot number		*/
				HSCX_WRITE(h_chan, H_TSAR, 0x2f);
				break;

			case HSCX_CH_B: /* Prepare HSCX channel B */
				/* TSAX: tx clock shift bits 1 & 2	*/
				/*       tx time slot number		*/
				HSCX_WRITE(h_chan, H_TSAX, 0x03);

				/* TSAR: rx clock shift bits 1 & 2	*/
				/*       rx time slot number		*/
				HSCX_WRITE(h_chan, H_TSAR, 0x03);
				break;
		}
	}
	else	/* IOM 1 setup */
	{
		/* TSAX: tx clock shift bits 1 & 2	*/
		/*       tx time slot number		*/
		HSCX_WRITE(h_chan, H_TSAX, 0x07);

		/* TSAR: rx clock shift bits 1 & 2	*/
		/*       rx time slot number		*/
		HSCX_WRITE(h_chan, H_TSAR, 0x07);
	}

	if(activate)
	{
		if(chan->bprot == BPROT_RHDLC)
		{
		  /* HDLC Frames, transparent mode 0 */
		  HSCX_WRITE(h_chan, H_MODE,
		     HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS);
		}
		else
		{
		  /* Raw Telephony, extended transparent mode 1 */
		  HSCX_WRITE(h_chan, H_MODE,
		     HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
		}

		isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES);
	}
	else
	{
		/* TSAX: tx time slot */
		HSCX_WRITE(h_chan, H_TSAX, 0xff);

		/* TSAR: rx time slot */
		HSCX_WRITE(h_chan, H_TSAR, 0xff);

		/* Raw Telephony, extended transparent mode 1 */
		HSCX_WRITE(h_chan, H_MODE,
		   HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS);
	}

 	/* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */
	/* always disable RSC and TIN */

	chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN;

	if(activate)
	{
		/* enable */
		chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR);
	}
	else
	{
		/* disable */
		chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR;
	}

	/* handle ICA, EXA, and EXB via interrupt mask of channel b */

	if (h_chan == HSCX_CH_A)
	{
		if (activate)
			HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA);
		else
			HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA;
		HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK);
		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
	}
	else
	{
		if (activate)
			HSCX_B_IMASK &= ~HSCX_MASK_EXB;
		else
			HSCX_B_IMASK |= HSCX_MASK_EXB;
		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
	}

	/* clear spurious interrupts left over */

	if(h_chan == HSCX_CH_A)
	{
		HSCX_READ(h_chan, H_EXIR);
		HSCX_READ(h_chan, H_ISTA);
	}
	else  /* mask ICA, because it must not be cleared by reading ISTA */
	{
		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA);
		HSCX_READ(h_chan, H_EXIR);
		HSCX_READ(h_chan, H_ISTA);
		HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK);
	}
}
Ejemplo n.º 5
0
/*---------------------------------------------------------------------------*
 *	isic - device driver interrupt routine
 *---------------------------------------------------------------------------*/
void
isicintr(struct l1_softc *sc)
{
	if(sc->sc_ipac == 0)	/* HSCX/ISAC interupt routine */
	{
		u_char was_hscx_irq = 0;
		u_char was_isac_irq = 0;

		register u_char hscx_irq_stat;
		register u_char isac_irq_stat;

		for(;;)
		{
			/* get hscx irq status from hscx b ista */
			hscx_irq_stat =
	 	    	    HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
	
			/* get isac irq status */
			isac_irq_stat = ISAC_READ(I_ISTA);
	
			/* do as long as there are pending irqs in the chips */
			if(!hscx_irq_stat && !isac_irq_stat)
				break;
	
			if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
					    HSCX_ISTA_RSC | HSCX_ISTA_XPR |
					    HSCX_ISTA_TIN | HSCX_ISTA_EXB))
			{
				isic_hscx_irq(sc, hscx_irq_stat,
						HSCX_CH_B,
						hscx_irq_stat & HSCX_ISTA_EXB);
				was_hscx_irq = 1;			
			}
			
			if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
			{
				isic_hscx_irq(sc,
				    HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
				    HSCX_CH_A,
				    hscx_irq_stat & HSCX_ISTA_EXA);
				was_hscx_irq = 1;
			}
	
			if(isac_irq_stat)
			{
				isic_isac_irq(sc, isac_irq_stat); /* isac handler */
				was_isac_irq = 1;
			}
		}

		HSCX_WRITE(0, H_MASK, 0xff);
		ISAC_WRITE(I_MASK, 0xff);
		HSCX_WRITE(1, H_MASK, 0xff);
	
#ifdef ELSA_QS1ISA
		DELAY(80);
		
		if((sc->sc_cardtyp == CARD_TYPEP_ELSAQS1ISA) && (sc->clearirq))
		{
			sc->clearirq(sc);
		}
#else
		DELAY(100);
#endif	
	
		HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
		ISAC_WRITE(I_MASK, ISAC_IMASK);
		HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);
	}
	else	/* IPAC interrupt routine */
	{
		register u_char ipac_irq_stat;
		register u_char was_ipac_irq = 0;

		for(;;)
		{
			/* get global irq status */
			
			ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
			
			/* check hscx a */
			
			if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
			{
				/* HSCX A interrupt */
				isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
						HSCX_CH_A,
						ipac_irq_stat & IPAC_ISTA_EXA);
				was_ipac_irq = 1;			
			}
			if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
			{
				/* HSCX B interrupt */
				isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
						HSCX_CH_B,
						ipac_irq_stat & IPAC_ISTA_EXB);
				was_ipac_irq = 1;			
			}
			if(ipac_irq_stat & IPAC_ISTA_ICD)
			{
				/* ISAC interrupt */
				isic_isac_irq(sc, ISAC_READ(I_ISTA));
				was_ipac_irq = 1;
			}
			if(ipac_irq_stat & IPAC_ISTA_EXD)
			{
				/* force ISAC interrupt handling */
				isic_isac_irq(sc, ISAC_ISTA_EXI);
				was_ipac_irq = 1;
			}
	
			/* do as long as there are pending irqs in the chip */
			if(!ipac_irq_stat)
				break;
		}

		IPAC_WRITE(IPAC_MASK, 0xff);
		DELAY(50);
		IPAC_WRITE(IPAC_MASK, 0xc0);
	}		
}
Ejemplo n.º 6
0
Archivo: isic.c Proyecto: MarginC/kame
/*---------------------------------------------------------------------------*
 *	isic - device driver interrupt routine
 *---------------------------------------------------------------------------*/
int
isicintr(void *arg)
{
	struct isic_softc *sc = arg;

	/* could this be an interrupt for us? */
	if (sc->sc_intr_valid == ISIC_INTR_DYING)
		return 0;	/* do not touch removed hardware */

	if(sc->sc_ipac == 0)	/* HSCX/ISAC interupt routine */
	{
		u_char was_hscx_irq = 0;
		u_char was_isac_irq = 0;

		register u_char hscx_irq_stat;
		register u_char isac_irq_stat;

		for(;;)
		{
			/* get hscx irq status from hscx b ista */
			hscx_irq_stat =
	 	    	    HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK;
	
			/* get isac irq status */
			isac_irq_stat = ISAC_READ(I_ISTA);
	
			/* do as long as there are pending irqs in the chips */
			if(!hscx_irq_stat && !isac_irq_stat)
				break;
	
			if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF |
					    HSCX_ISTA_RSC | HSCX_ISTA_XPR |
					    HSCX_ISTA_TIN | HSCX_ISTA_EXB))
			{
				isic_hscx_irq(sc, hscx_irq_stat,
						HSCX_CH_B,
						hscx_irq_stat & HSCX_ISTA_EXB);
				was_hscx_irq = 1;			
			}
			
			if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA))
			{
				isic_hscx_irq(sc,
				    HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK,
				    HSCX_CH_A,
				    hscx_irq_stat & HSCX_ISTA_EXA);
				was_hscx_irq = 1;
			}
	
			if(isac_irq_stat)
			{
				/* isac handler */
				isic_isac_irq(sc, isac_irq_stat);
				was_isac_irq = 1;
			}
		}
	
		HSCX_WRITE(0, H_MASK, 0xff);
		ISAC_WRITE(I_MASK, 0xff);
		HSCX_WRITE(1, H_MASK, 0xff);
	
		if (sc->clearirq)
		{
			DELAY(80);
			sc->clearirq(sc);
		} else
			DELAY(100);
	
		HSCX_WRITE(0, H_MASK, HSCX_A_IMASK);
		ISAC_WRITE(I_MASK, ISAC_IMASK);
		HSCX_WRITE(1, H_MASK, HSCX_B_IMASK);

		return(was_hscx_irq || was_isac_irq);
	}
	else	/* IPAC interrupt routine */
	{
		register u_char ipac_irq_stat;
		register u_char was_ipac_irq = 0;

		for(;;)
		{
			/* get global irq status */
			
			ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f;
			
			/* check hscx a */
			
			if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA))
			{
				/* HSCX A interrupt */
				isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA),
						HSCX_CH_A,
						ipac_irq_stat & IPAC_ISTA_EXA);
				was_ipac_irq = 1;			
			}
			if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB))
			{
				/* HSCX B interrupt */
				isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA),
						HSCX_CH_B,
						ipac_irq_stat & IPAC_ISTA_EXB);
				was_ipac_irq = 1;			
			}
			if(ipac_irq_stat & IPAC_ISTA_ICD)
			{
				/* ISAC interrupt, Obey ISAC-IPAC differences */
				u_int8_t isac_ista = ISAC_READ(I_ISTA);
				if (isac_ista & 0xfe)
					isic_isac_irq(sc, isac_ista & 0xfe);
				if (isac_ista & 0x01) /* unexpected */
					printf("%s: unexpected ipac timer2 irq\n", 
					    sc->sc_dev.dv_xname);
				was_ipac_irq = 1;
			}
			if(ipac_irq_stat & IPAC_ISTA_EXD)
			{
				/* ISAC EXI interrupt */
				isic_isac_irq(sc, ISAC_ISTA_EXI);
				was_ipac_irq = 1;
			}
	
			/* do as long as there are pending irqs in the chip */
			if(!ipac_irq_stat)
				break;
		}

#if 0
		/*
		 * This seems not to be necessary on IPACs - no idea why
		 * it is here - but due to limit range of test cards, leave
		 * it in for now, in case we have to resurrect it.
		 */
		IPAC_WRITE(IPAC_MASK, 0xff);
		DELAY(50);
		IPAC_WRITE(IPAC_MASK, 0xc0);
#endif

		return(was_ipac_irq);
	}		
}