예제 #1
0
void isic_attach_Dyn(struct isic_softc *sc)
{
	/* setup access routines */
	sc->clearirq = NULL;
	sc->readreg = dynalink_read_reg;
	sc->writereg = dynalink_write_reg;
	sc->readfifo = dynalink_read_fifo;
	sc->writefifo = dynalink_write_fifo;

	/* setup card type */
	sc->sc_cardtyp = CARD_TYPEP_DYNALINK;

	/* setup IOM bus type */
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("%s: HSCX VSTR test failed for Dynalink PnP\n",
			device_xname(&sc->sc_dev));
		printf("%s: HSC0: VSTR: %#x\n",
			device_xname(&sc->sc_dev), HSCX_READ(0, H_VSTR));
		printf("%s: HSC1: VSTR: %#x\n",
			device_xname(&sc->sc_dev), HSCX_READ(1, H_VSTR));
		return;
	}

	bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, RESET);
	DELAY(SEC_DELAY / 10);
	bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, 0);
	DELAY(SEC_DELAY / 10);
}
예제 #2
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);
}
예제 #3
0
int
isic_attach_itkix1(struct isa_device *dev)
{
	struct isic_softc *sc = &l1_sc[dev->id_unit];
	u_int8_t hv1, hv2;

	sc->sc_irq = dev->id_irq;

	dev->id_msize = 0;
	
	/* check if we got an iobase */
	sc->sc_port = dev->id_iobase;

	/* setup access routines */
	sc->clearirq = NULL;
	sc->readreg = itkix1_read_reg;
	sc->writereg = itkix1_write_reg;
	sc->readfifo = itkix1_read_fifo;
	sc->writefifo = itkix1_write_fifo;

	/* setup card type */	
	sc->sc_cardtyp = CARD_TYPEP_ITKIX1;

	/* setup IOM bus type */
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* setup ISAC and HSCX base addr */
	ISAC_BASE = (caddr_t) sc->sc_port;
	HSCX_A_BASE = (caddr_t) sc->sc_port + 1;
	HSCX_B_BASE = (caddr_t) sc->sc_port + 2;

	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1) or 0x04 (V2.0). */
	hv1 = HSCX_READ(0, H_VSTR) & 0xf;
	hv2 = HSCX_READ(1, H_VSTR) & 0xf;
	if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04))
	{
		printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n",
			dev->id_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}                   

	outb((dev->id_iobase)+ITK_CONFIG, 1);
	DELAY(SEC_DELAY / 10);
	outb((dev->id_iobase)+ITK_CONFIG, 0);
	DELAY(SEC_DELAY / 10);
	return(1);
}
int
isic_attach_sws(struct isa_device *dev)
{
	struct isic_softc *sc = &l1_sc[dev->id_unit];

	/* fill in isic_softc structure */

	sc->readreg     = sws_read_reg;
	sc->writereg    = sws_write_reg;
	sc->readfifo    = sws_read_fifo;
	sc->writefifo   = sws_write_fifo;
	sc->clearirq    = NULL;
	sc->sc_unit     = dev->id_unit;
	sc->sc_irq      = dev->id_irq;
	sc->sc_port     = dev->id_iobase;
	sc->sc_cardtyp  = CARD_TYPEP_SWS;
	sc->sc_bustyp   = BUS_TYPE_IOM2;
	sc->sc_ipac     = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;
	dev->id_msize   = 0;

	ISAC_BASE   = (void *) (((u_int) sc->sc_port) + SWS_ISAC);
	HSCX_A_BASE = (void *) (((u_int) sc->sc_port) + SWS_HSCX0);
	HSCX_B_BASE = (void *) (((u_int) sc->sc_port) + SWS_HSCX1);

	/*
	 * Read HSCX A/B VSTR.  Expected value for the SWS PnP card is
	 * 0x05 ( = version 2.1 ) in the least significant bits.
	 */

	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
            ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("isic%d: HSCX VSTR test failed for SWS PnP\n",
			dev->id_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}

	/* reset card */

	outb( ((u_int) sc->sc_port) + SWS_RESON , 0x3);
	DELAY(SEC_DELAY / 5);
	outb( ((u_int) sc->sc_port) + SWS_RESOFF, 0);
	DELAY(SEC_DELAY / 5);

	return(1);
}
예제 #5
0
/*---------------------------------------------------------------------------*
 *	Eicon Diehl DIVA 2.0
 *---------------------------------------------------------------------------*/
int
isic_attach_diva(device_t dev)
{
	int unit = device_get_unit(dev);
	struct l1_softc *sc = &l1_sc[unit];	
	bus_space_tag_t    t = rman_get_bustag(sc->sc_resources.io_base[0]);
	bus_space_handle_t h = rman_get_bushandle(sc->sc_resources.io_base[0]);
	
	/* setup access routines */

	sc->clearirq = NULL;
	sc->readreg = diva_read_reg;
	sc->writereg = diva_write_reg;

	sc->readfifo = diva_read_fifo;
	sc->writefifo = diva_write_fifo;

	/* setup card type */
	
	sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA;

	/* setup IOM bus type */
	
	sc->sc_bustyp = BUS_TYPE_IOM2;

	/* setup chip type = ISAC/HSCX */

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */

	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || 
	    ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("isic%d: HSCX VSTR test failed for Eicon DIVA 2.0\n",
			sc->sc_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			sc->sc_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			sc->sc_unit, HSCX_READ(1, H_VSTR));
		return ENXIO;
	}
	/* reset on */
	bus_space_write_1(t,h,DIVA_CTRL_OFF,0);
	DELAY(100);
	/* reset off */
	bus_space_write_1(t,h,DIVA_CTRL_OFF,DIVA_CTRL_WRRST);
	return(0);
}
void
isic_attach_sws(struct isic_softc *sc)
{
	/* setup access routines */

	sc->readreg   = sws_read_reg;
	sc->writereg  = sws_write_reg;

	sc->readfifo  = sws_read_fifo;
	sc->writefifo = sws_write_fifo;

	/* setup card type */

	sc->sc_cardtyp = CARD_TYPEP_SWS;

	/* setup IOM bus type */

	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/*
	 * Read HSCX A/B VSTR.  Expected value for the SWS PnP card is
	 * 0x05 ( = version 2.1 ) in the least significant bits.
	 */

	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
            ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("%s: HSCX VSTR test failed for SWS PnP\n",
			device_xname(sc->sc_dev));
		printf("%s: HSC0: VSTR: %#x\n",
			device_xname(sc->sc_dev), HSCX_READ(0, H_VSTR));
		printf("%s: HSC1: VSTR: %#x\n",
			device_xname(sc->sc_dev), HSCX_READ(1, H_VSTR));
		return;
	}

	/* reset card */
        {
        	bus_space_tag_t t = sc->sc_maps[0].t;
        	bus_space_handle_t h = sc->sc_maps[0].h;
        	bus_space_write_1(t, h, SWS_RESON, 0x3);
		DELAY(SEC_DELAY / 5);
		bus_space_write_1(t, h, SWS_RESOFF, 0);
		DELAY(SEC_DELAY / 5);
	}
}
예제 #7
0
/* attach callback routine */
int
isic_attach_Dyn(device_t dev)
{
	int unit = device_get_unit(dev);	/* get unit */
	struct l1_softc *sc = &l1_sc[unit];		/* pointer to softc */

	struct i4b_info *  info = &(sc->sc_resources);
	bus_space_tag_t    t = rman_get_bustag(info->io_base[0]);
	bus_space_handle_t h = rman_get_bushandle(info->io_base[0]);

	/* fill in l1_softc structure */
	sc->readreg	= dynalink_read_reg;
	sc->writereg	= dynalink_write_reg;
	sc->readfifo	= dynalink_read_fifo;
	sc->writefifo	= dynalink_write_fifo;
	sc->clearirq	= NULL;
	sc->sc_cardtyp = CARD_TYPEP_DYNALINK;
	sc->sc_bustyp = BUS_TYPE_IOM2;
	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || 
	    ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		kprintf("isic%d: HSCX VSTR test failed for Dynalink\n",
			sc->sc_unit);
		kprintf("isic%d: HSC0: VSTR: %#x\n",
			sc->sc_unit, HSCX_READ(0, H_VSTR));
		kprintf("isic%d: HSC1: VSTR: %#x\n",
			sc->sc_unit, HSCX_READ(1, H_VSTR));
		return ENXIO;
	}

	/* reset card */
	bus_space_write_1(t,h,ADDR,RESET);
	DELAY(SEC_DELAY / 10);
	bus_space_write_1(t,h,ADDR,0);
	DELAY(SEC_DELAY / 10);

	return 0;                
}
예제 #8
0
int isic_attach_itkix1(struct isic_softc *sc)
{
	u_int8_t hv1, hv2;

	/* setup access routines */
	sc->clearirq = NULL;
	sc->readreg = itkix1_read_reg;
	sc->writereg = itkix1_write_reg;
	sc->readfifo = itkix1_read_fifo;
	sc->writefifo = itkix1_write_fifo;

	/* setup card type */	
	sc->sc_cardtyp = CARD_TYPEP_ITKIX1;

	/* setup IOM bus type */
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1) or 0x04 (V2.0). */
	hv1 = HSCX_READ(0, H_VSTR) & 0xf;
	hv2 = HSCX_READ(1, H_VSTR) & 0xf;
	if((hv1 != 0x05 && hv1 != 0x04) || (hv2 != 0x05 && hv2 != 0x04))
	{
		printf("%s: HSCX VSTR test failed for ITK ix1 micro\n",
			sc->sc_dev.dv_xname);
		printf("%s: HSC0: VSTR: %#x\n",
			sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR));
		printf("%s: HSC1: VSTR: %#x\n",
			sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR));
		return 0;
	}                   

	bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 1);
	DELAY(SEC_DELAY / 10);
	bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 0);
	DELAY(SEC_DELAY / 10);
	return 1;
}
예제 #9
0
int
isapnp_match_dynalink(struct device *parent, struct cfdata *cf,
		struct isa_attach_args *ia)
{
	struct isic_softc dummysc, *sc = &dummysc;
	pnp_resource_t res;
	char *ids[] = {"ASU1688", NULL};
	bzero(&res, sizeof res);
	res.res_irq[0].irq_level = ia->ia_irq;
	res.res_port[0].prt_base = ia->ia_iobase;
	res.res_port[0].prt_length = 4;

	if (!pnp_assigndev(ids, isiccd.cd_name, &res))
		return (0);

	ia->ia_irq = res.res_irq[0].irq_level;
	ia->ia_iobase = res.res_port[0].prt_base;
	ia->ia_iosize = res.res_port[0].prt_length;

	if (set_softc(sc, ia, cf->cf_unit) == 0)
		return 0;

	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
	    ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("isic%d: HSCX VSTR test failed for Dynalink\n",
			cf->cf_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			cf->cf_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			cf->cf_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}

	cf->cf_flags = FLAG_DYNALINK;
	return (1);
}
예제 #10
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);
}
예제 #11
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);
	}
}
예제 #12
0
int
isic_probe_Dyn(struct isa_device *dev, unsigned int iobase2)
{

	struct isic_softc *sc = &l1_sc[dev->id_unit];

	if(dev->id_unit >= ISIC_MAXUNIT)
	{
		printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dynalink IS64PH.\n",
				dev->id_unit, dev->id_unit);
		return(0);
	}
	sc->sc_unit = dev->id_unit;

	/* check IRQ validity */

	switch(ffs(dev->id_irq) - 1)
	{
		case 3:
		case 4:
		case 5:
		case 9:
		case 10:
		case 11:
		case 12:
		case 15:
			break;

		default:
			printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n",
				dev->id_unit, ffs(dev->id_irq)-1);
			return(0);
			break;
	}
	sc->sc_irq = dev->id_irq;

	/* check if memory addr specified */

	if(dev->id_maddr)
	{
		printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n",
			dev->id_unit, (u_long)dev->id_maddr);
		return (0);
	}
	dev->id_msize = 0;

	/* check if we got an iobase */
	if ( (dev->id_iobase < 0x100) ||
	     (dev->id_iobase > 0x3f8) ||
	     (dev->id_iobase & 3) )
	{
			printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", dev->id_unit, dev->id_iobase);
			return(0);
	}
	sc->sc_port = dev->id_iobase;

	/* setup access routines */
	sc->clearirq = NULL;
	sc->readreg = dynalink_read_reg;
	sc->writereg = dynalink_write_reg;
	sc->readfifo = dynalink_read_fifo;
	sc->writefifo = dynalink_write_fifo;

	/* setup card type */
	sc->sc_cardtyp = CARD_TYPEP_DYNALINK;

	/* setup IOM bus type */
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* setup ISAC and HSCX base addr */
	ISAC_BASE = (void *) sc->sc_port;
	HSCX_A_BASE = (void *) sc->sc_port + 1;
	HSCX_B_BASE = (void *) sc->sc_port + 1 + HSCXB_HACK;

	/* Read HSCX A/B VSTR.  Expected value is 0x05 (V2.1). */
	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
	    ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("isic%d: HSCX VSTR test failed for Dynalink\n",
			dev->id_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}

	return (1);
}
예제 #13
0
/*---------------------------------------------------------------------------*
 *	isic_probe_usrtai - probe for USR
 *---------------------------------------------------------------------------*/
int
isic_probe_usrtai(device_t dev)
{
	size_t unit = device_get_unit(dev);	/* get unit */
	struct l1_softc *sc = 0;	/* pointer to softc */
	void *ih = 0;			/* dummy */

	/* check max unit range */

	if(unit >= ISIC_MAXUNIT)
	{
		kprintf("isic%d: Error, unit %d >= ISIC_MAXUNIT for USR Sportster TA!\n",
				unit, unit);
		return(ENXIO);	
	}

	sc = &l1_sc[unit];			/* get pointer to softc */
	sc->sc_unit = unit;			/* set unit */

	/* see if an io base was supplied */
	
	if(!(sc->sc_resources.io_base[0] =
			bus_alloc_resource(dev, SYS_RES_IOPORT,
	                                   &sc->sc_resources.io_rid[0],
	                                   0ul, ~0ul, 1, RF_ACTIVE)))
	{
		kprintf("isic%d: Could not get iobase for USR Sportster TA!\n",
				unit);
		return(ENXIO);
	}

	/* set io base */

	sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
	
	/* release io base */
	
	bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
		sc->sc_resources.io_base[0]);


	/* check if we got an iobase */

	switch(sc->sc_port)
	{
		case 0x200:
		case 0x208:
		case 0x210:
		case 0x218:
		case 0x220:
		case 0x228:
		case 0x230:
		case 0x238:
		case 0x240:
		case 0x248:
		case 0x250:
		case 0x258:
		case 0x260:
		case 0x268:
		case 0x270:
		case 0x278:
			break;
			
		default:
			kprintf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n",
				unit, sc->sc_port);
			return(0);
			break;
	}

	/* allocate all the ports needed */

	if(usrtai_alloc_port(dev))
	{
		kprintf("isic%d: Could not get the ports for USR Sportster TA!\n", unit);
		isic_detach_common(dev);
		return(ENXIO);
	}

	/* get our irq */

	if(!(sc->sc_resources.irq =
		bus_alloc_resource(dev, SYS_RES_IRQ,
				   &sc->sc_resources.irq_rid,
				   0ul, ~0ul, 1, RF_ACTIVE)))
	{
		kprintf("isic%d: Could not get an irq for USR Sportster TA!\n",unit);
		isic_detach_common(dev);
		return ENXIO;
	}

	/* get the irq number */
	sc->sc_irq = rman_get_start(sc->sc_resources.irq);

	/* register interrupt routine */
	bus_setup_intr(dev, sc->sc_resources.irq, 0,
			(void(*)(void *))(isicintr), sc, &ih, NULL);

	/* check IRQ validity */

	if(intr_no[sc->sc_irq] == 0)
	{
		kprintf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
			unit, sc->sc_irq);
		return(1);
	}

	/* setup ISAC access routines */

	sc->clearirq = NULL;
	sc->readreg = usrtai_read_reg;
	sc->writereg = usrtai_write_reg;

	sc->readfifo = usrtai_read_fifo;
	sc->writefifo = usrtai_write_fifo;

	/* setup card type */

	sc->sc_cardtyp = CARD_TYPEP_USRTA;

	/* setup IOM bus type */
	
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;
	
	/* setup ISAC and HSCX base addr */
	
	ISAC_BASE   = (caddr_t)sc->sc_port + USR_ISAC_OFF;
	HSCX_A_BASE = (caddr_t)sc->sc_port + USR_HSCXA_OFF;
	HSCX_B_BASE = (caddr_t)sc->sc_port + USR_HSCXB_OFF;

	/* 
	 * Read HSCX A/B VSTR.  Expected value for USR Sportster TA based
	 * boards is 0x05 in the least significant bits.
	 */

	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
            ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		kprintf("isic%d: HSCX VSTR test failed for USR Sportster TA\n",
			unit);
		kprintf("isic%d: HSC0: VSTR: %#x\n",
			unit, HSCX_READ(0, H_VSTR));
		kprintf("isic%d: HSC1: VSTR: %#x\n",
			unit, HSCX_READ(1, H_VSTR));
		return (1);
	}                   
	
	return (0);
}
예제 #14
0
파일: isic.c 프로젝트: 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);
	}		
}
int
isic_probe_avma1_pcmcia(struct isa_device *dev)
{
	struct isic_softc *sc = &l1_sc[dev->id_unit];
	u_char byte;
	int i;
	u_int cardinfo;

	/* check max unit range */

	if(dev->id_unit > 1)
	{
		printf("isic%d: Error, unit %d > MAXUNIT for AVM PCMCIA Fritz!Card\n",
				dev->id_unit, dev->id_unit);
		return(0);
	}
	sc->sc_unit = dev->id_unit;

	/*
	 * we trust the IRQ we got from PCCARD service
	 */
	sc->sc_irq = dev->id_irq;

	/* check if we got an iobase */

	switch(dev->id_iobase)
	{
		case 0x140:
		case 0x300:
			break;
		default:
			printf("isic%d: Error, invalid iobase 0x%x specified for AVM PCMCIA Fritz!Card.\n",
				dev->id_unit, dev->id_iobase);
			return(0);
			break;
	}
	sc->sc_port = dev->id_iobase;

	/* ResetController */

	outb(dev->id_iobase + STAT0_OFFSET, 0x00);
	DELAY(SEC_DELAY / 20);
	outb(dev->id_iobase + STAT0_OFFSET, 0x01);
	DELAY(SEC_DELAY / 20);
	outb(dev->id_iobase + STAT0_OFFSET, 0x00);

	/*
	 * CheckController
	 * The logic to check for the PCMCIA was adapted as
	 * described by AVM.
	 */

	outb(dev->id_iobase + ADDR_REG_OFFSET, 0x21);	/* ISAC STAR */
	if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
	{
		printf("isic%d: Error, ISAC STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
				dev->id_unit, byte);
		return(0);
	}

	outb(dev->id_iobase + ADDR_REG_OFFSET, 0xa1);	/* HSCX STAR */
	if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 )
	{
		printf("isic%d: Error, HSCX STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n",
				dev->id_unit, byte);
		return(0);
	}

	byte = ASL_TESTBIT;
	for (i=0; i<256; i++)	{
		byte = byte ? 0 : ASL_TESTBIT;
		outb(dev->id_iobase + STAT0_OFFSET, byte);
		if ((inb(dev->id_iobase+STAT0_OFFSET)&ASL_TESTBIT)!=byte)   {
			printf("isic%d: Error during toggle of AVM PCMCIA Status Latch0\n",
				dev->id_unit);
			return(0);
		}
	}

	sc->clearirq = NULL;
	sc->readreg   = avma1_pcmcia_read_reg;
	sc->writereg  = avma1_pcmcia_write_reg;

	sc->readfifo  = avma1_pcmcia_read_fifo;
	sc->writefifo = avma1_pcmcia_write_fifo;

	/* setup IOM bus type */

	sc->sc_bustyp = BUS_TYPE_IOM2; 			/* ap: XXX ??? */

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* setup ISAC and HSCX base addr */
	/*
	 * NOTE: for PCMCIA these are no real addrs; they are
	 * offsets to be written into the base+ADDR_REG_OFFSET register
	 * to pick up the values of the bytes fro base+DATA_REG_OFFSET
	 *
	 * see also the logic in the avma1_pcmcia_* routines;
	 * therefore we also must have the base addr in some static
	 * space or struct; XXX better solution?
	 */

	PCMCIA_IO_BASE = dev->id_iobase;
	ISAC_BASE      = (void *)0x20;

	HSCX_A_BASE    = (void *)0xA0;
	HSCX_B_BASE    = (void *)0xE0;

	/*
	 * Read HSCX A/B VSTR.
	 * Expected value for AVM A1 is 0x04 or 0x05 and for the
	 * AVM Fritz!Card is 0x05 in the least significant bits.
	 */

	if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4))	||
            (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
	{
		printf("isic%d: HSCX VSTR test failed for AVM PCMCIA Fritz!Card\n",
			dev->id_unit);
		printf("isic%d: HSC0: VSTR: 0x%0x\n",
			dev->id_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: 0x%0x\n",
			dev->id_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}

	/*
	 * seems we really have an AVM PCMCIA Fritz!Card controller
	 */
	cardinfo = inb(dev->id_iobase + VERREG_OFFSET)<<8 | inb(dev->id_iobase + MODREG_OFFSET);
	printf("isic%d: successfully detect AVM PCMCIA cardinfo = 0x%0x\n",
		dev->id_unit, cardinfo);
	dev->id_flags = FLAG_AVM_A1_PCMCIA;
	return (1);
}
예제 #16
0
int
isic_probe_s0163(struct isa_device *dev)
{
    struct isic_softc *sc = &l1_sc[dev->id_unit];
    u_char byte;

    /* check max unit range */

    if(dev->id_unit >= ISIC_MAXUNIT)
    {
        printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3!\n",
               dev->id_unit, dev->id_unit);
        return(0);
    }
    sc->sc_unit = dev->id_unit;

    /* check IRQ validity */

    if((intr_no[ffs(dev->id_irq) - 1]) == 1)
    {
        printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
               dev->id_unit, ffs(dev->id_irq)-1);
        return(0);
    }
    sc->sc_irq = dev->id_irq;

    /* check if memory addr specified */

    if(dev->id_maddr)
    {
        printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!\n",
               dev->id_unit, (u_long)dev->id_maddr);
        return(0);
    }

    dev->id_msize = 0;

    /* check if we got an iobase */

    switch(dev->id_iobase)
    {
    case 0xd80:
    case 0xe80:
    case 0xf80:
        break;

    default:
        printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n",
               dev->id_unit, dev->id_iobase);
        return(0);
        break;
    }
    sc->sc_port = dev->id_iobase;

    if(((byte = inb(sc->sc_port)) != 0x51) && (byte != 0x10))
    {
        printf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!\n",
               dev->id_unit, byte);
        return(0);
    }

    if((byte = inb(sc->sc_port + 1)) != 0x93)
    {
        printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n",
               dev->id_unit, byte);
        return(0);
    }

    if(((byte = inb(sc->sc_port + 2)) != 0x1c) && (byte != 0x1f))
    {
        printf("isic%d: Error, signature 3 0x%x != (0x1c||0x1f) for Teles S0/16.3!\n",
               dev->id_unit, byte);
        return(0);
    }

    /* setup access routines */

    sc->clearirq = NULL;
    sc->readreg = tels0163_read_reg;
    sc->writereg = tels0163_write_reg;

    sc->readfifo = tels0163_read_fifo;
    sc->writefifo = tels0163_write_fifo;

    /* setup card type */

    sc->sc_cardtyp= CARD_TYPEP_16_3;

    /* setup IOM bus type */

    sc->sc_bustyp = BUS_TYPE_IOM2;

    sc->sc_ipac = 0;
    sc->sc_bfifolen = HSCX_FIFO_LEN;

    /* setup ISAC and HSCX base addr */

    switch(dev->id_iobase)
    {
    case 0xd80:
        ISAC_BASE = (void *) 0x960;
        HSCX_A_BASE = (void *) 0x160;
        HSCX_B_BASE = (void *) 0x560;
        break;

    case 0xe80:
        ISAC_BASE = (void *) 0xa60;
        HSCX_A_BASE = (void *) 0x260;
        HSCX_B_BASE = (void *) 0x660;
        break;

    case 0xf80:
        ISAC_BASE = (void *) 0xb60;
        HSCX_A_BASE = (void *) 0x360;
        HSCX_B_BASE = (void *) 0x760;
        break;
    }

    /*
     * Read HSCX A/B VSTR.  Expected value for the S0/16.3 card is
     * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
     */

    if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
            ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4))	||
            (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
    {
        printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
               dev->id_unit);
        printf("isic%d: HSC0: VSTR: %#x\n",
               dev->id_unit, HSCX_READ(0, H_VSTR));
        printf("isic%d: HSC1: VSTR: %#x\n",
               dev->id_unit, HSCX_READ(1, H_VSTR));
        return (0);
    }

    return (1);
}
예제 #17
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);
}
예제 #18
0
int
isic_probe_s0163(struct device *dev, struct cfdata *cf,
                 struct isa_attach_args *ia)
{
    u_char byte;
    struct isic_softc dummysc, *sc = &dummysc;

    if((intr_no[ffs(ia->ia_irq) - 1]) == 1)
    {
        printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
               cf->cf_unit, ffs(ia->ia_irq)-1);
        return(0);
    }

    /* check if memory addr specified */

    if(ia->ia_maddr)
    {
        printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!\n",
               cf->cf_unit, (u_long)ia->ia_maddr);
        return 0;
    }

    /* Set up a temporary softc for the probe */

    if (set_softc(sc, ia, cf->cf_unit) == 0)
        return 0;

    if((byte = inb(sc->sc_port)) != 0x51)
    {
        printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16.3!\n",
               cf->cf_unit, byte);
        return(0);
    }

    if((byte = inb(sc->sc_port + 1)) != 0x93)
    {
        printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n",
               cf->cf_unit, byte);
        return(0);
    }

    if(((byte = inb(sc->sc_port + 2)) != 0x1c) && (byte != 0x1f))
    {
        printf("isic%d: Error, signature 3 0x%x != (0x1c||0x1f) for Teles S0/16.3!\n",
               cf->cf_unit, byte);
        return(0);
    }

    /*
     * Read HSCX A/B VSTR.  Expected value for the S0/16.3 card is
     * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
     */

    if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
            ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4))	||
            (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
             ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )
    {
        printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
               cf->cf_unit);
        printf("isic%d: HSC0: VSTR: %#x\n",
               cf->cf_unit, HSCX_READ(0, H_VSTR));
        printf("isic%d: HSC1: VSTR: %#x\n",
               cf->cf_unit, HSCX_READ(1, H_VSTR));
        return (0);
    }

    return (1);
}
예제 #19
0
/*---------------------------------------------------------------------------*
 *	isic_attach_common - common attach routine for all busses
 *---------------------------------------------------------------------------*/
int
isic_attach_common(device_t dev)
{
	char *drvid = NULL;
	int unit = device_get_unit(dev);
	struct l1_softc *sc = &l1_sc[unit];
	
	sc->sc_unit = unit;
	
	sc->sc_isac_version = 0;
	sc->sc_hscx_version = 0;

	if(sc->sc_ipac)
	{
		sc->sc_ipac_version = IPAC_READ(IPAC_ID);

		switch(sc->sc_ipac_version)
  		{
			case IPAC_V11:
			case IPAC_V12:
  				break;

  			default:
  				printf("isic%d: Error, IPAC version %d unknown!\n",
  					unit, sc->sc_ipac_version);
  				return(0);
  				break;
		}
	}
	else
	{
		sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;
	
		switch(sc->sc_isac_version)
		{
			case ISAC_VA:
			case ISAC_VB1:
			case ISAC_VB2:
			case ISAC_VB3:
				break;
	
			default:
				printf("isic%d: Error, ISAC version %d unknown!\n",
					unit, sc->sc_isac_version);
				return ENXIO;
				break;
		}

		sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;

		switch(sc->sc_hscx_version)
		{
			case HSCX_VA1:
			case HSCX_VA2:
			case HSCX_VA3:
			case HSCX_V21:
				break;
				
			default:
				printf("isic%d: Error, HSCX version %d unknown!\n",
					unit, sc->sc_hscx_version);
				return ENXIO;
				break;
		}
	}
	
	isic_isac_init(sc);		/* ISAC setup */

	/* HSCX setup */

	isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
	
	isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);

	isic_init_linktab(sc);		/* setup linktab */

	sc->sc_trace = TRACE_OFF;	/* set trace level */

	sc->sc_state = ISAC_IDLE;	/* set state */

	sc->sc_ibuf = NULL;		/* input buffering */
	sc->sc_ib = NULL;
	sc->sc_ilen = 0;

	sc->sc_obuf = NULL;		/* output buffering */
	sc->sc_op = NULL;
	sc->sc_ol = 0;
	sc->sc_freeflag = 0;

	sc->sc_obuf2 = NULL;		/* second output buffer */
	sc->sc_freeflag2 = 0;

	/* timer setup */
	
	callout_handle_init(&sc->sc_T3_callout);
	callout_handle_init(&sc->sc_T4_callout);	
	
	/* init higher protocol layers */
	
	i4b_l1_mph_status_ind(L0ISICUNIT(sc->sc_unit), STI_ATTACH, sc->sc_cardtyp, &isic_l1mux_func);

	/* announce manufacturer and card type for ISA cards */
	
	switch(sc->sc_cardtyp)
	{
		case CARD_TYPEP_8:
			drvid = "Teles S0/8 (or compatible)";
			break;

		case CARD_TYPEP_16:
			drvid = "Teles S0/16 (or compatible)";
			break;

		case CARD_TYPEP_16_3:
			drvid = "Teles S0/16.3";
			break;

		case CARD_TYPEP_AVMA1:
			drvid = "AVM A1 or Fritz!Card Classic";
			break;

		case CARD_TYPEP_PCFRITZ:
			drvid = "AVM Fritz!Card PCMCIA";
			break;

		case CARD_TYPEP_USRTA:
			drvid = "USRobotics Sportster ISDN TA intern";
			break;

		case CARD_TYPEP_ITKIX1:
			drvid = "ITK ix1 micro";
			break;

		case CARD_TYPEP_PCC16:
			drvid = "ELSA MicroLink ISDN/PCC-16";
			break;

		default:
			drvid = NULL;	/* pnp/pci cards announce themselves */
			break;
	}

	if(drvid)
		printf("isic%d: %s\n", unit, drvid);
	
	if(bootverbose)
	{
		/* announce chip versions */
		
		if(sc->sc_ipac)
		{
			if(sc->sc_ipac_version == IPAC_V11)
				printf("isic%d: IPAC PSB2115 Version 1.1\n", unit);
			else
				printf("isic%d: IPAC PSB2115 Version 1.2\n", unit);
		}
		else
		{
			printf("isic%d: ISAC %s (IOM-%c)\n",
				unit,
				ISACversion[sc->sc_isac_version],
				sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');

			printf("isic%d: HSCX %s\n",
				unit,
				HSCXversion[sc->sc_hscx_version]);
		}
	}
	return 0;
}
예제 #20
0
/*---------------------------------------------------------------------------*
 *	isic_probe_Cs0P - probe for Creatix ISDN-S0 P&P and compatibles
 *---------------------------------------------------------------------------*/
int
isic_probe_Cs0P(struct isa_device *dev, unsigned int iobase2)
{
	struct isic_softc *sc = &l1_sc[dev->id_unit];
	
	/* check max unit range */
	
	if(dev->id_unit >= ISIC_MAXUNIT)
	{
		printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Creatix ISDN-S0 P&P!\n",
				dev->id_unit, dev->id_unit);
		return(0);	
	}	
	sc->sc_unit = dev->id_unit;

	/* check IRQ validity */

	switch(ffs(dev->id_irq) - 1)
	{
		case 3:
		case 5:
		case 7:
		case 10:
		case 11:
		case 12:
			break;
			
		default:
			printf("isic%d: Error, invalid IRQ [%d] specified for Creatix ISDN-S0 P&P!\n",
				dev->id_unit, ffs(dev->id_irq)-1);
			return(0);
			break;
	}
	sc->sc_irq = dev->id_irq;

	/* check if memory addr specified */

	if(dev->id_maddr)
	{
		printf("isic%d: Error, mem addr 0x%lx specified for Creatix ISDN-S0 P&P!\n",
			dev->id_unit, (u_long)dev->id_maddr);
		return(0);
	}
	dev->id_msize = 0;
	
	if(iobase2 == 0)
	{
		printf("isic%d: Error, iobase2 is 0 for Creatix ISDN-S0 P&P!\n",
			dev->id_unit);
		return(0);
	}

	/* check if we got an iobase */

	switch(dev->id_iobase)
	{
		case 0x120:
		case 0x180:
/*XXX*/			break;
			
		default:
			printf("isic%d: Error, invalid iobase 0x%x specified for Creatix ISDN-S0 P&P!\n",
				dev->id_unit, dev->id_iobase);
			return(0);
			break;
	}
	sc->sc_port = dev->id_iobase;

	/* setup access routines */

	sc->clearirq = NULL;
	sc->readreg = ctxs0P_read_reg;
	sc->writereg = ctxs0P_write_reg;

	sc->readfifo = ctxs0P_read_fifo;
	sc->writefifo = ctxs0P_write_fifo;

	/* setup card type */
	
	sc->sc_cardtyp = CARD_TYPEP_CS0P;

	/* setup IOM bus type */
	
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;
	
	/* setup ISAC and HSCX base addr */
	
	ISAC_BASE   = (caddr_t) dev->id_iobase - 0x20;
	HSCX_A_BASE = (caddr_t) iobase2 - 0x20;
	HSCX_B_BASE = (caddr_t) iobase2;

	/* 
	 * Read HSCX A/B VSTR.  Expected value for the Creatix PnP card is
	 * 0x05 ( = version 2.1 ) in the least significant bits.
	 */

	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
            ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("isic%d: HSCX VSTR test failed for Creatix PnP\n",
			dev->id_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}                   

	return (1);
}
예제 #21
0
static int
isicattach(int flags, struct isic_softc *sc)
{
	int ret = 0;
	const char *drvid;

#ifdef __FreeBSD__

	struct isic_softc *sc = &l1_sc[dev->id_unit];
#define	PARM	dev
#define	PARM2	dev, iobase2
#define	FLAGS	dev->id_flags

#elif defined(__bsdi__)

	struct isic_softc *sc = device_private(self);
#define	PARM	parent, self, ia
#define	PARM2	parent, self, ia
#define	FLAGS	sc->sc_flags

#else

#define PARM	sc
#define PARM2	sc
#define	FLAGS	flags

#endif /* __FreeBSD__ */

  	static const char *ISACversion[] = {
  		"2085 Version A1/A2 or 2086/2186 Version 1.1",
		"2085 Version B1",
		"2085 Version B2",
		"2085 Version V2.3 (B3)",
		"Unknown Version"
	};

	static const char *HSCXversion[] = {
		"82525 Version A1",
		"Unknown (0x01)",
		"82525 Version A2",
		"Unknown (0x03)",
		"82525 Version A3",
		"82525 or 21525 Version 2.1",
		"Unknown Version"
	};

	/* card dependent setup */
	switch(FLAGS)
	{
#ifdef ISICISA_DYNALINK
#if defined(__bsdi__) || defined(__FreeBSD__)
		case FLAG_DYNALINK:
			ret = isic_attach_Dyn(PARM2);
			break;
#endif
#endif

#ifdef ISICISA_TEL_S0_8
		case FLAG_TELES_S0_8:
			ret = isic_attach_s08(PARM);
			break;
#endif

#ifdef ISICISA_TEL_S0_16
		case FLAG_TELES_S0_16:
			ret = isic_attach_s016(PARM);
			break;
#endif

#ifdef ISICISA_TEL_S0_16_3
		case FLAG_TELES_S0_163:
			ret = isic_attach_s0163(PARM);
			break;
#endif

#ifdef ISICISA_AVM_A1
		case FLAG_AVM_A1:
			ret = isic_attach_avma1(PARM);
			break;
#endif

#ifdef ISICISA_USR_STI
		case FLAG_USR_ISDN_TA_INT:
			ret = isic_attach_usrtai(PARM);
			break;
#endif

#ifdef ISICISA_ITKIX1
		case FLAG_ITK_IX1:
			ret = isic_attach_itkix1(PARM);
			break;
#endif

#ifdef ISICISA_ELSA_PCC16
		case FLAG_ELSA_PCC16:
			ret = isic_attach_Eqs1pi(dev, 0);
			break;
#endif

#ifdef amiga
		case FLAG_BLMASTER:
			ret = 1; /* full detection was done in caller */
			break;
#endif

/* ======================================================================
 * Only P&P cards follow below!!!
 */

#ifdef __FreeBSD__		/* we've already splitted all non-ISA stuff
				   out of this ISA specific part for the other
				   OS */

#ifdef AVM_A1_PCMCIA
		case FLAG_AVM_A1_PCMCIA:
                      ret = isic_attach_fritzpcmcia(PARM);
			break;
#endif

#ifdef TEL_S0_16_3_P
		case FLAG_TELES_S0_163_PnP:
			ret = isic_attach_s0163P(PARM2);
			break;
#endif

#ifdef CRTX_S0_P
		case FLAG_CREATIX_S0_PnP:
			ret = isic_attach_Cs0P(PARM2);
			break;
#endif

#ifdef DRN_NGO
		case FLAG_DRN_NGO:
			ret = isic_attach_drnngo(PARM2);
			break;
#endif

#ifdef SEDLBAUER
		case FLAG_SWS:
			ret = isic_attach_sws(PARM);
			break;
#endif

#ifdef ELSA_QS1ISA
		case FLAG_ELSA_QS1P_ISA:
			ret = isic_attach_Eqs1pi(PARM2);
			break;
#endif

#ifdef AVM_PNP
		case FLAG_AVM_PNP:
			ret = isic_attach_avm_pnp(PARM2);
			ret = 0;
			break;
#endif

#ifdef SIEMENS_ISURF2
		case FLAG_SIEMENS_ISURF2:
			ret = isic_attach_siemens_isurf(PARM2);
			break;
#endif

#ifdef ASUSCOM_IPAC
		case FLAG_ASUSCOM_IPAC:
			ret = isic_attach_asi(PARM2);
			break;
#endif

#endif /* __FreeBSD__ / P&P specific part */

		default:
			break;
	}

	if(ret == 0)
		return(0);

	if(sc->sc_ipac)
	{
		sc->sc_ipac_version = IPAC_READ(IPAC_ID);

		switch(sc->sc_ipac_version)
		{
			case IPAC_V11:
			case IPAC_V12:
				break;

			default:
				aprint_error_dev(sc->sc_dev, "Error, IPAC version %d unknown!\n", ret);
				return(0);
				break;
		}
	}
	else
	{
		sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;

		switch(sc->sc_isac_version)
		{
			case ISAC_VA:
			case ISAC_VB1:
			case ISAC_VB2:
			case ISAC_VB3:
				break;

			default:
				printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
				ISIC_PARM, sc->sc_isac_version);
				return(0);
				break;
		}

		sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;

		switch(sc->sc_hscx_version)
		{
			case HSCX_VA1:
			case HSCX_VA2:
			case HSCX_VA3:
			case HSCX_V21:
				break;

			default:
				printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
					ISIC_PARM, sc->sc_hscx_version);
				return(0);
				break;
		}
	}

        sc->sc_intr_valid = ISIC_INTR_DISABLED;

	/* HSCX setup */

	isic_bchannel_setup(sc, HSCX_CH_A, BPROT_NONE, 0);

	isic_bchannel_setup(sc, HSCX_CH_B, BPROT_NONE, 0);

	/* setup linktab */

	isic_init_linktab(sc);

	/* set trace level */

	sc->sc_trace = TRACE_OFF;

	sc->sc_state = ISAC_IDLE;

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

	sc->sc_obuf = NULL;
	sc->sc_op = NULL;
	sc->sc_ol = 0;
	sc->sc_freeflag = 0;

	sc->sc_obuf2 = NULL;
	sc->sc_freeflag2 = 0;

#if defined(__FreeBSD__) && __FreeBSD__ >=3
	callout_handle_init(&sc->sc_T3_callout);
	callout_handle_init(&sc->sc_T4_callout);
#endif

#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
	callout_init(&sc->sc_T3_callout, 0);
	callout_init(&sc->sc_T4_callout, 0);
#endif

	/* announce manufacturer and card type */

	switch(FLAGS)
	{
		case FLAG_TELES_S0_8:
			drvid = "Teles S0/8 or Niccy 1008";
			break;

		case FLAG_TELES_S0_16:
			drvid = "Teles S0/16, Creatix ISDN S0-16 or Niccy 1016";
			break;

		case FLAG_TELES_S0_163:
			drvid = "Teles S0/16.3";
			break;

		case FLAG_AVM_A1:
			drvid = "AVM A1 or AVM Fritz!Card";
			break;

		case FLAG_AVM_A1_PCMCIA:
			drvid = "AVM PCMCIA Fritz!Card";
			break;

		case FLAG_TELES_S0_163_PnP:
			drvid = "Teles S0/PnP";
			break;

		case FLAG_CREATIX_S0_PnP:
			drvid = "Creatix ISDN S0-16 P&P";
			break;

		case FLAG_USR_ISDN_TA_INT:
			drvid = "USRobotics Sportster ISDN TA intern";
			break;

		case FLAG_DRN_NGO:
			drvid = "Dr. Neuhaus NICCY Go@";
			break;

		case FLAG_DYNALINK:
			drvid = "Dynalink IS64PH";
			break;

		case FLAG_SWS:
			drvid = "Sedlbauer WinSpeed";
			break;

		case FLAG_BLMASTER:
			/* board announcement was done by caller */
			drvid = (char *)0;
			break;

		case FLAG_ELSA_QS1P_ISA:
			drvid = "ELSA QuickStep 1000pro (ISA)";
			break;

		case FLAG_ITK_IX1:
			drvid = "ITK ix1 micro";
			break;

		case FLAG_ELSA_PCC16:
			drvid = "ELSA PCC-16";
			break;

		case FLAG_ASUSCOM_IPAC:
			drvid = "Asuscom ISDNlink 128K PnP";
			break;

		case FLAG_SIEMENS_ISURF2:
			drvid = "Siemens I-Surf 2.0";
			break;

		default:
			drvid = "ERROR, unknown flag used";
			break;
	}
#ifndef __FreeBSD__
	printf("\n");
#endif
	if (drvid)
		printf(ISIC_FMT "%s\n", ISIC_PARM, drvid);

	/* announce chip versions */

	if(sc->sc_ipac)
	{
		if(sc->sc_ipac_version == IPAC_V11)
			printf(ISIC_FMT "IPAC PSB2115 Version 1.1\n", ISIC_PARM);
		else
			printf(ISIC_FMT "IPAC PSB2115 Version 1.2\n", ISIC_PARM);
	}
	else
	{
		if(sc->sc_isac_version >= ISAC_UNKN)
		{
			printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
					ISIC_PARM,
					sc->sc_isac_version);
			sc->sc_isac_version = ISAC_UNKN;
		}
		else
		{
			printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
					ISIC_PARM,
					ISACversion[sc->sc_isac_version],
					sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
		}

#ifdef __FreeBSD__
		printf("(Addr=0x%lx)\n", (u_long)ISAC_BASE);
#endif

		if(sc->sc_hscx_version >= HSCX_UNKN)
		{
			printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
					ISIC_PARM,
					sc->sc_hscx_version);
			sc->sc_hscx_version = HSCX_UNKN;
		}
		else
		{
			printf(ISIC_FMT "HSCX %s" TERMFMT,
					ISIC_PARM,
					HSCXversion[sc->sc_hscx_version]);
		}

#ifdef __FreeBSD__
		printf("(AddrA=0x%lx, AddrB=0x%lx)\n", (u_long)HSCX_A_BASE, (u_long)HSCX_B_BASE);

#endif /* __FreeBSD__ */
	}

#ifdef __FreeBSD__
	next_isic_unit++;

#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003

	/* set the interrupt handler - no need to change isa_device.h */
	dev->id_intr = (inthand2_t *)isicintr;

#endif

#endif /* __FreeBSD__ */

	/* init higher protocol layers */
	isic_attach_bri(sc, drvid, &isic_std_driver);

	return(1);
#undef PARM
#undef FLAGS
}
예제 #22
0
/*---------------------------------------------------------------------------*
 *	isic_probe_usrtai - probe for USR
 *---------------------------------------------------------------------------*/
int
isic_probe_usrtai(struct isa_device *dev)
{
	struct isic_softc *sc = &l1_sc[dev->id_unit];

	/* check max unit range */

	if(dev->id_unit >= ISIC_MAXUNIT)
	{
		printf("isic%d: Error, unit %d >= MAXUNIT for USR Sportster TA!\n",
				dev->id_unit, dev->id_unit);
		return(0);
	}
	sc->sc_unit = dev->id_unit;

	/* check IRQ validity */

	if((intr_no[ffs(dev->id_irq) - 1]) == 0)
	{
		printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n",
			dev->id_unit, (ffs(dev->id_irq))-1);
		return(0);
	}
	sc->sc_irq = dev->id_irq;

	/* check if memory addr specified */

	if(dev->id_maddr)
	{
		printf("isic%d: Error, mem addr 0x%lx specified for USR Sportster TA!\n",
			dev->id_unit, (u_long)dev->id_maddr);
		return(0);
	}
	dev->id_msize = 0;

	/* check if we got an iobase */

	switch(dev->id_iobase)
	{
		case 0x200:
		case 0x208:
		case 0x210:
		case 0x218:
		case 0x220:
		case 0x228:
		case 0x230:
		case 0x238:
		case 0x240:
		case 0x248:
		case 0x250:
		case 0x258:
		case 0x260:
		case 0x268:
		case 0x270:
		case 0x278:
			break;

		default:
			printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n",
				dev->id_unit, dev->id_iobase);
			return(0);
			break;
	}
	sc->sc_port = dev->id_iobase;

	/* setup ISAC access routines */

	sc->clearirq = NULL;
	sc->readreg = usrtai_read_reg;
	sc->writereg = usrtai_write_reg;

	sc->readfifo = usrtai_read_fifo;
	sc->writefifo = usrtai_write_fifo;

	/* setup card type */

	sc->sc_cardtyp = CARD_TYPEP_USRTA;

	/* setup IOM bus type */

	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* setup ISAC and HSCX base addr */

	ISAC_BASE   = (void *)dev->id_iobase + USR_ISAC_OFF;
	HSCX_A_BASE = (void *)dev->id_iobase + USR_HSCXA_OFF;
	HSCX_B_BASE = (void *)dev->id_iobase + USR_HSCXB_OFF;

	/*
	 * Read HSCX A/B VSTR.  Expected value for USR Sportster TA based
	 * boards is 0x05 in the least significant bits.
	 */

	if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) ||
            ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) )
	{
		printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n",
			dev->id_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}

	return (1);
}
예제 #23
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);
	}		
}
예제 #24
0
int
isicattach(int flags, struct isic_softc *sc)

#endif /* __FreeBSD__ */
{
	int ret = 0;
	char *drvid;

#ifdef __FreeBSD__
	struct isic_softc *sc = &isic_sc[dev->id_unit];
#define	PARM	dev
#define	PARM2	dev, iobase2
#define	FLAGS	dev->id_flags
#else
#define PARM	sc
#define PARM2	sc
#define	FLAGS	flags
#endif

  	static char *ISACversion[] = {
  		"2085 Version A1/A2 or 2086/2186 Version 1.1",
		"2085 Version B1",
		"2085 Version B2",
		"2085 Version V2.3 (B3)",
		"Unknown Version"
	};

	static char *HSCXversion[] = {
		"82525 Version A1",
		"Unknown (0x01)",
		"82525 Version A2",
		"Unknown (0x03)",
		"82525 Version A3",
		"82525 or 21525 Version 2.1",
		"Unknown Version"
	};

	/* done in bus specific attach code for other OS */

#ifdef __FreeBSD__
	if(dev->id_unit != next_isic_unit)
	{
		printf("isicattach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit);
		return(0);
	}

	sc->sc_unit = dev->id_unit;
#else
	isic_sc[sc->sc_unit] = sc;
#endif
	
	/* card dependent setup */
	switch(FLAGS)
	{
#ifdef DYNALINK
		case FLAG_DYNALINK:
			ret = isic_attach_Dyn(PARM2);
			break;
#endif

#ifdef TEL_S0_8
		case FLAG_TELES_S0_8:
			ret = isic_attach_s08(PARM);
			break;
#endif

#ifdef TEL_S0_16
		case FLAG_TELES_S0_16:
			ret = isic_attach_s016(PARM);
			break;
#endif

#ifdef TEL_S0_16_3
		case FLAG_TELES_S0_163:
			ret = isic_attach_s0163(PARM);		
			break;
#endif

#ifdef AVM_A1
		case FLAG_AVM_A1:
			ret = isic_attach_avma1(PARM);
			break;
#endif

#ifdef USR_STI
		case FLAG_USR_ISDN_TA_INT:
			ret = isic_attach_usrtai(PARM);		
			break;
#endif

#ifdef ITKIX1
		case FLAG_ITK_IX1:
			ret = isic_attach_itkix1(PARM);
			break;
#endif

/* ======================================================================
 * Only P&P cards follow below!!!
 */
#ifdef __FreeBSD__		/* we've already splitted all non-ISA stuff
				   out of this ISA specific part for the other
				   OS */

#ifdef AVM_PCMCIA
		case FLAG_AVM_A1_PCMCIA:
			ret = isic_attach_fritzpcmcia(PARM);
			break;
#endif

#ifndef __FreeBSD__
#ifdef TEL_S0_16_3_P
		case FLAG_TELES_S0_163_PnP:
			ret = isic_attach_s0163P(PARM2);
			break;
#endif
#endif

#ifdef CRTX_S0_P
		case FLAG_CREATIX_S0_PnP:
			ret = isic_attach_Cs0P(PARM2);		
			break;
#endif

#ifdef DRN_NGO
		case FLAG_DRN_NGO:
			ret = isic_attach_drnngo(PARM2);		
			break;
#endif

#ifdef SEDLBAUER
		case FLAG_SWS:
			ret = isic_attach_sws(PARM);
			break;
#endif

#ifdef ELSA_QS1ISA
		case FLAG_ELSA_QS1P_ISA:
			ret = isic_attach_Eqs1pi(PARM2);
			break;
#endif

#endif /* __FreeBSD__ / P&P specific part */

/* --- XXX - don't know how to handle this - should be removed!!!! ---- */
#ifdef amiga
		case FLAG_BLMASTER:
			ret = 1; /* full detection was done in caller */
			break;
#endif
/* ------------------------------------------------------------------- */

		default:
			break;
	}

	if(ret == 0)
		return(0);
		
	sc->sc_isac_version = 0;
	sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;

	switch(sc->sc_isac_version)
	{
		case ISAC_VA:
		case ISAC_VB1:
                case ISAC_VB2:
		case ISAC_VB3:
			break;

		default:
			printf(ISIC_FMT "Error, ISAC version %d unknown!\n",
				ISIC_PARM, sc->sc_isac_version);
			return(0);
			break;
	}

	sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;

	switch(sc->sc_hscx_version)
	{
		case HSCX_VA1:
		case HSCX_VA2:
		case HSCX_VA3:
		case HSCX_V21:
			break;
			
		default:
			printf(ISIC_FMT "Error, HSCX version %d unknown!\n",
				ISIC_PARM, sc->sc_hscx_version);
			return(0);
			break;
	};

	/* ISAC setup */
	
	isic_isac_init(sc);

	/* HSCX setup */

	isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0);
	
	isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0);

	/* setup linktab */

	isic_init_linktab(sc);

	/* set trace level */

	sc->sc_trace = TRACE_OFF;

	sc->sc_state = ISAC_IDLE;

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

	sc->sc_obuf = NULL;
	sc->sc_op = NULL;
	sc->sc_ol = 0;
	sc->sc_freeflag = 0;

	sc->sc_obuf2 = NULL;
	sc->sc_freeflag2 = 0;

#if defined(__FreeBSD__) && __FreeBSD__ >=3
	callout_handle_init(&sc->sc_T3_callout);
	callout_handle_init(&sc->sc_T4_callout);	
#endif
	
	/* init higher protocol layers */
	
	MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp);
	
	/* announce manufacturer and card type */
	
	switch(FLAGS)
	{
		case FLAG_TELES_S0_8:
			drvid = "Teles S0/8 or Niccy 1008";
			break;

		case FLAG_TELES_S0_16:
			drvid = "Teles S0/16, Creatix ISDN S0-16 or Niccy 1016";
			break;

		case FLAG_TELES_S0_163:
			drvid = "Teles S0/16.3";
			break;

		case FLAG_AVM_A1:
			drvid = "AVM A1 or AVM Fritz!Card";
			break;

		case FLAG_AVM_A1_PCMCIA:
			drvid = "AVM PCMCIA Fritz!Card";
			break;

		case FLAG_TELES_S0_163_PnP:
			drvid = "Teles S0/PnP";
			break;

		case FLAG_CREATIX_S0_PnP:
			drvid = "Creatix ISDN S0-16 P&P";
			break;

		case FLAG_USR_ISDN_TA_INT:
			drvid = "USRobotics Sportster ISDN TA intern";
			break;

		case FLAG_DRN_NGO:
			drvid = "Dr. Neuhaus NICCY Go@";
			break;

		case FLAG_DYNALINK:
			drvid = "Dynalink IS64PH";
			break;

		case FLAG_SWS:
			drvid = "Sedlbauer WinSpeed";
			break;

		case FLAG_BLMASTER:
			/* board announcement was done by caller */
			drvid = (char *)0;
			break;

		case FLAG_ELSA_QS1P_ISA:
			drvid = "ELSA QuickStep 1000pro (ISA)";
			break;

		case FLAG_ITK_IX1:
			drvid = "ITK ix1 micro";
			break;

		default:
			drvid = "ERROR, unknown flag used";
			break;
	}
#ifndef __FreeBSD__
	printf("\n");
#endif
	if (drvid)
		printf(ISIC_FMT "%s\n", ISIC_PARM, drvid);

	/* announce chip versions */
	
	if(sc->sc_isac_version >= ISAC_UNKN)
	{
		printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT,
				ISIC_PARM,
				sc->sc_isac_version);
		sc->sc_isac_version = ISAC_UNKN;
	}
	else
	{
		printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT,
				ISIC_PARM,
				ISACversion[sc->sc_isac_version],
				sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
	}

#ifdef __FreeBSD__
	printf("(Addr=0x%lx)\n", (u_long)ISAC_BASE);
#endif
		
	if(sc->sc_hscx_version >= HSCX_UNKN)
	{
		printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
				ISIC_PARM,
				sc->sc_hscx_version);
		sc->sc_hscx_version = HSCX_UNKN;
	}
	else
	{
		printf(ISIC_FMT "HSCX %s" TERMFMT,
				ISIC_PARM,
				HSCXversion[sc->sc_hscx_version]);
	}

#ifdef __FreeBSD__	
	printf("(AddrA=0x%lx, AddrB=0x%lx)\n", (u_long)HSCX_A_BASE, (u_long)HSCX_B_BASE);

	next_isic_unit++;

#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003

	/* set the interrupt handler - no need to change isa_device.h */
	dev->id_intr = (inthand2_t *)isicintr;

#endif

#endif /* __FreeBSD__ */

	return(1);
#undef PARM
#undef FLAGS
}
예제 #25
0
static void
isic_isapnp_attach(device_t parent, device_t self, void *aux)
{
  	static const char *ISACversion[] = {
  		"2085 Version A1/A2 or 2086/2186 Version 1.1",
		"2085 Version B1",
		"2085 Version B2",
		"2085 Version V2.3 (B3)",
		"Unknown Version"
	};

	static const char *HSCXversion[] = {
		"82525 Version A1",
		"Unknown (0x01)",
		"82525 Version A2",
		"Unknown (0x03)",
		"82525 Version A3",
		"82525 or 21525 Version 2.1",
		"Unknown Version"
	};

	struct isic_softc *sc = device_private(self);
	struct isapnp_attach_args *ipa = aux;
	const struct isic_isapnp_card_desc *desc = isic_isapnp_descriptions;
	int i;

	sc->sc_dev = self;
	if (isapnp_config(ipa->ipa_iot, ipa->ipa_memt, ipa)) {
		aprint_error_dev(sc->sc_dev, "error in region allocation\n");
		return;
	}

	for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++)
		if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0)
			break;
	if (i >= NUM_DESCRIPTIONS)
		panic("could not identify isic PnP device");

	/* setup parameters */
	sc->sc_cardtyp = desc->card_type;
	sc->sc_irq = ipa->ipa_irq[0].num;
	desc->allocmaps(ipa, sc);

	/* announce card name */
	printf(": %s\n", desc->name);

	/* establish interrupt handler */
	if (isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num,
	    ipa->ipa_irq[0].type, IPL_NET, isicintr, sc) == NULL)
		aprint_error_dev(sc->sc_dev,
		    "couldn't establish interrupt handler\n");

	/* init card */
	desc->attach(sc);

	/* announce chip versions */
	sc->sc_isac_version = 0;
	sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03;

	switch (sc->sc_isac_version) {
		case ISAC_VA:
		case ISAC_VB1:
                case ISAC_VB2:
		case ISAC_VB3:
			break;

		default:
			aprint_error(ISIC_FMT
			    "Error, ISAC version %d unknown!\n",
			    ISIC_PARM, sc->sc_isac_version);
			return;
			break;
	}

	sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf;

	switch (sc->sc_hscx_version) {
		case HSCX_VA1:
		case HSCX_VA2:
		case HSCX_VA3:
		case HSCX_V21:
			break;

		default:
			aprint_error(ISIC_FMT
			    "Error, HSCX version %d unknown!\n",
			    ISIC_PARM, sc->sc_hscx_version);
			return;
			break;
	};

        sc->sc_intr_valid = ISIC_INTR_DISABLED;

	/* HSCX setup */

	isic_bchannel_setup(sc, HSCX_CH_A, BPROT_NONE, 0);

	isic_bchannel_setup(sc, HSCX_CH_B, BPROT_NONE, 0);

	/* setup linktab */

	isic_init_linktab(sc);

	/* set trace level */

	sc->sc_trace = TRACE_OFF;

	sc->sc_state = ISAC_IDLE;

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

	sc->sc_obuf = NULL;
	sc->sc_op = NULL;
	sc->sc_ol = 0;
	sc->sc_freeflag = 0;

	sc->sc_obuf2 = NULL;
	sc->sc_freeflag2 = 0;

#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
	callout_init(&sc->sc_T3_callout, 0);
	callout_init(&sc->sc_T4_callout, 0);
#endif

	/* announce chip versions */

	if (sc->sc_isac_version >= ISAC_UNKN) {
		aprint_error(ISIC_FMT
		    "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT, ISIC_PARM,
		    sc->sc_isac_version);
		sc->sc_isac_version = ISAC_UNKN;
	} else {
		aprint_error(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT, ISIC_PARM,
		    ISACversion[sc->sc_isac_version],
		    sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
	}

	if (sc->sc_hscx_version >= HSCX_UNKN) {
		aprint_error(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT,
		    ISIC_PARM, sc->sc_hscx_version);
		sc->sc_hscx_version = HSCX_UNKN;
	} else {
		aprint_error(ISIC_FMT "HSCX %s" TERMFMT, ISIC_PARM,
		    HSCXversion[sc->sc_hscx_version]);
	}

	/* init higher protocol layers and save l2 handle */
	isic_attach_bri(sc, desc->name, &isic_std_driver);
}
예제 #26
0
파일: i4b_avm_a1.c 프로젝트: MarginC/kame
/*---------------------------------------------------------------------------*
 *	isic_probe_avma1 - probe for AVM A1 and compatibles
 *---------------------------------------------------------------------------*/
int
isic_probe_avma1(device_t dev)
{
	size_t unit = device_get_unit(dev);	/* get unit */
	struct l1_softc *sc = 0;	/* pointer to softc */
	void *ih = 0;			/* dummy */
	bus_space_tag_t    t;		/* bus things */
	bus_space_handle_t h;
	u_char savebyte;
	u_char byte;

	/* check max unit range */

	if(unit >= ISIC_MAXUNIT)
	{
		printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n",
				unit, unit);
		return(ENXIO);	
	}

	sc = &l1_sc[unit];			/* get pointer to softc */
	sc->sc_unit = unit;			/* set unit */

	/* see if an io base was supplied */
	
	if(!(sc->sc_resources.io_base[0] =
			bus_alloc_resource(dev, SYS_RES_IOPORT,
	                                   &sc->sc_resources.io_rid[0],
	                                   0ul, ~0ul, 1, RF_ACTIVE)))
	{
		printf("isic%d: Could not get iobase for AVM A1/Fritz!\n",
				unit);
		return(ENXIO);
	}

	/* set io base */

	sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
	
	/* release io base */
	
        bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
			sc->sc_resources.io_base[0]);

	switch(sc->sc_port)
	{
		case 0x200:
		case 0x240:
		case 0x300:
		case 0x340:		
			break;
			
		default:
			printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n",
				unit, sc->sc_port);
			return(ENXIO);
			break;
	}

	if(isic_alloc_port(dev, 0, sc->sc_port+AVM_CONF_REG, 0x20))
		return(ENXIO);

	if(isic_alloc_port(dev, 1, sc->sc_port+AVM_ISAC_R_OFFS, 0x20))
		return(ENXIO);

	if(isic_alloc_port(dev, 2, sc->sc_port+AVM_HSCXA_R_OFFS, 0x20))
		return(ENXIO);

	if(isic_alloc_port(dev, 3, sc->sc_port+AVM_HSCXB_R_OFFS, 0x20))
		return(ENXIO);

	if(isic_alloc_port(dev, 4, sc->sc_port+AVM_ISAC_F_OFFS, 0x20))
		return(ENXIO);

	if(isic_alloc_port(dev, 5, sc->sc_port+AVM_HSCXA_F_OFFS, 0x20))
		return(ENXIO);

	if(isic_alloc_port(dev, 6, sc->sc_port+AVM_HSCXB_F_OFFS, 0x20))
		return(ENXIO);

	/* get our irq */

	if(!(sc->sc_resources.irq =
		bus_alloc_resource(dev, SYS_RES_IRQ,
				   &sc->sc_resources.irq_rid,
				   0ul, ~0ul, 1, RF_ACTIVE)))
	{
		printf("isic%d: Could not get an irq for AVM A1/Fritz!\n",unit);
		isic_detach_common(dev);
		return ENXIO;
	}

	/* get the irq number */
	sc->sc_irq = rman_get_start(sc->sc_resources.irq);

	/* register interupt routine */
	bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET,
			(void(*)(void *))(isicintr),
			sc, &ih);

	/* check IRQ validity */

	switch(sc->sc_irq)
	{
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
		case 8:
		case 10:
		case 11:
		case 12:
		case 13:
		case 14:
		case 15:
			break;
			
		default:
			printf("isic%d: Error, invalid IRQ [%d] specified for AVM A1/Fritz!\n",
				unit, sc->sc_irq);
			isic_detach_common(dev);
			return(ENXIO);
			break;
	}		

	sc->clearirq = NULL;
	sc->readreg = avma1_read_reg;
	sc->writereg = avma1_write_reg;

	sc->readfifo = avma1_read_fifo;
	sc->writefifo = avma1_write_fifo;

	/* setup card type */

	sc->sc_cardtyp = CARD_TYPEP_AVMA1;

	/* setup IOM bus type */
	
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* 
	 * Read HSCX A/B VSTR.
	 * Expected value for AVM A1 is 0x04 or 0x05 and for the
	 * AVM Fritz!Card is 0x05 in the least significant bits.
	 */

	if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4))	||
            (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )  
	{
		printf("isic%d: HSCX VSTR test failed for AVM A1/Fritz\n",
			unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			unit, HSCX_READ(1, H_VSTR));
		return(ENXIO);
	}                   

	/* AVM A1 or Fritz! control register bits:	*/
	/*        read                write		*/
	/* 0x01  hscx irq*           RESET		*/
	/* 0x02  isac irq*           clear counter1	*/
	/* 0x04  counter irq*        clear counter2	*/
	/* 0x08  always 0            irq enable		*/
	/* 0x10  read test bit       set test bit	*/
	/* 0x20  always 0            unused		*/

	/*
	 * XXX the following test may be destructive, to prevent the
	 * worst case, we save the byte first, and in case the test
	 * fails, we write back the saved byte .....
	 */

	t = rman_get_bustag(sc->sc_resources.io_base[0]);
	h = rman_get_bushandle(sc->sc_resources.io_base[0]);

	savebyte = bus_space_read_1(t, h, 0);
	
	/* write low to test bit */

	bus_space_write_1(t, h, 0, 0x00);
	
	/* test bit and next higher and lower bit must be 0 */

	if((byte = bus_space_read_1(t, h, 0) & 0x38) != 0x00)
	{
		printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n",
				unit, byte);
		bus_space_write_1(t, h, 0, savebyte);
		return(ENXIO);
	}

	/* write high to test bit */

	bus_space_write_1(t, h, 0, 0x10);
	
	/* test bit must be high, next higher and lower bit must be 0 */

	if((byte = bus_space_read_1(t, h, 0) & 0x38) != 0x10)
	{
		printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n",
				unit, byte);
		bus_space_write_1(t, h, 0, savebyte);
		return(ENXIO);
	}
	return(0);
}
예제 #27
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);
	}
}
예제 #28
0
int
isic_probe_avma1(struct isa_device *dev)
{
	struct isic_softc *sc = &l1_sc[dev->id_unit];
	u_char savebyte;
	u_char byte;
	
	/* check max unit range */
	
	if(dev->id_unit >= ISIC_MAXUNIT)
	{
		printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n",
				dev->id_unit, dev->id_unit);
		return(0);	
	}	
	sc->sc_unit = dev->id_unit;

	/* check IRQ validity */
	
	switch(ffs(dev->id_irq)-1)
	{
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
		case 8:
		case 10:
		case 11:
		case 12:
		case 13:
		case 14:
		case 15:
			break;
			
		default:
			printf("isic%d: Error, invalid IRQ [%d] specified for AVM A1/Fritz!\n",
				dev->id_unit, ffs(dev->id_irq)-1);
			return(0);
			break;
	}		
	sc->sc_irq = dev->id_irq;

	/* check if memory addr specified */

	if(dev->id_maddr)
	{
		printf("isic%d: Error, mem addr 0x%lx specified for AVM A1/Fritz!\n",
			dev->id_unit, (u_long)dev->id_maddr);
		return(0);
	}
		
	dev->id_msize = 0;
	
	/* check if we got an iobase */

	switch(dev->id_iobase)
	{
		case 0x200:
		case 0x240:
		case 0x300:
		case 0x340:		
			break;
			
		default:
			printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n",
				dev->id_unit, dev->id_iobase);
			return(0);
			break;
	}
	sc->sc_port = dev->id_iobase;

	sc->clearirq = NULL;
	sc->readreg = avma1_read_reg;
	sc->writereg = avma1_write_reg;

	sc->readfifo = avma1_read_fifo;
	sc->writefifo = avma1_write_fifo;

	/* setup card type */

	sc->sc_cardtyp = CARD_TYPEP_AVMA1;

	/* setup IOM bus type */
	
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	/* setup ISAC and HSCX base addr */
	
	ISAC_BASE = (caddr_t)dev->id_iobase + 0x1400 - 0x20;

	HSCX_A_BASE = (caddr_t)dev->id_iobase + 0x400 - 0x20;
	HSCX_B_BASE = (caddr_t)dev->id_iobase + 0xc00 - 0x20;

	/* 
	 * Read HSCX A/B VSTR.
	 * Expected value for AVM A1 is 0x04 or 0x05 and for the
	 * AVM Fritz!Card is 0x05 in the least significant bits.
	 */

	if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4))	||
            (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )  
	{
		printf("isic%d: HSCX VSTR test failed for AVM A1/Fritz\n",
			dev->id_unit);
		printf("isic%d: HSC0: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(0, H_VSTR));
		printf("isic%d: HSC1: VSTR: %#x\n",
			dev->id_unit, HSCX_READ(1, H_VSTR));
		return (0);
	}                   

	/* AVM A1 or Fritz! control register bits:	*/
	/*        read                write		*/
	/* 0x01  hscx irq*           RESET		*/
	/* 0x02  isac irq*           clear counter1	*/
	/* 0x04  counter irq*        clear counter2	*/
	/* 0x08  always 0            irq enable		*/
	/* 0x10  read test bit       set test bit	*/
	/* 0x20  always 0            unused		*/

	/*
	 * XXX the following test may be destructive, to prevent the
	 * worst case, we save the byte first, and in case the test
	 * fails, we write back the saved byte .....
	 */

	savebyte = inb(dev->id_iobase + AVM_CONF_REG);
	
	/* write low to test bit */

	outb(dev->id_iobase + AVM_CONF_REG, 0x00);
	
	/* test bit and next higher and lower bit must be 0 */

	if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x00)
	{
		printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n",
				dev->id_unit, byte);
		outb(dev->id_iobase + AVM_CONF_REG, savebyte);
		return (0);
	}

	/* write high to test bit */

	outb(dev->id_iobase + AVM_CONF_REG, 0x10);
	
	/* test bit must be high, next higher and lower bit must be 0 */

	if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x10)
	{
		printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n",
				dev->id_unit, byte);
		outb(dev->id_iobase + AVM_CONF_REG, savebyte);
		return (0);
	}

	return (1);
}
예제 #29
0
/*---------------------------------------------------------------------------*
 *	isic_probe_s0163 - probe routine for Teles S0/16.3
 *---------------------------------------------------------------------------*/
int
isic_probe_s0163(device_t dev)
{
	size_t unit = device_get_unit(dev);	/* get unit */
	struct l1_softc *sc = 0;	/* pointer to softc */
	void *ih = 0;			/* dummy */
	bus_space_tag_t    t;		/* bus things */
	bus_space_handle_t h;
	u_int8_t b0,b1,b2;		/* signature */

	/* check max unit range */

	if(unit >= ISIC_MAXUNIT)
	{
		kprintf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles 16.3!\n",
				unit, unit);
		return(ENXIO);	
	}

	sc = &l1_sc[unit];			/* get pointer to softc */
	sc->sc_unit = unit;			/* set unit */

	/* see if an io base was supplied */
	
	if(!(sc->sc_resources.io_base[0] =
			bus_alloc_resource(dev, SYS_RES_IOPORT,
	                                   &sc->sc_resources.io_rid[0],
	                                   0ul, ~0ul, 1, RF_ACTIVE)))
	{
		kprintf("isic%d: Could not get iobase for Teles S0/16.3.\n",
				unit);
		return(ENXIO);
	}

	/* set io base */

	sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
	/* Release the resource -  re-allocate later with correct size	*/
        bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
			sc->sc_resources.io_base[0]);
	
	switch(sc->sc_port)
	{
		case 0xd80:
		case 0xe80:
		case 0xf80:
			break;
			
		case 0x180:
		case 0x280:
		case 0x380:
			kprintf("isic%d: Error, instead of using iobase 0x%x for your Teles S0/16.3,\n",
				unit, sc->sc_port);
			kprintf("isic%d:        please use 0x%x in the kernel configuration file!\n",
				unit, sc->sc_port+0xc00);			
			isic_detach_common(dev);
			return(ENXIO);
			break;
	
		default:
			kprintf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n",
				unit, sc->sc_port);
			isic_detach_common(dev);
			return(ENXIO);
			break;
	}
	
	/* set io port resources */

	sc->sc_resources.io_rid[0] = 0;	
	bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port, 0x20);
	sc->sc_resources.io_base[0] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[0],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[0])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port);
		isic_detach_common(dev);
		return ENXIO;
	}
	sc->sc_resources.io_rid[1] = 1;	
	bus_set_resource(dev, SYS_RES_IOPORT, 1,
		sc->sc_port-ISAC_OFFS, 0x20);
	sc->sc_resources.io_base[1] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[1],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[1])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port-ISAC_OFFS);
		isic_detach_common(dev);
		return ENXIO;
	}
	
	sc->sc_resources.io_rid[2] = 2;
	bus_set_resource(dev, SYS_RES_IOPORT, 2,
		sc->sc_port-HSCXA_OFFS, 0x20);
	sc->sc_resources.io_base[2] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[2],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[2])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port-HSCXA_OFFS);
		isic_detach_common(dev);
		return ENXIO;
	}

	sc->sc_resources.io_rid[3] = 3;
	bus_set_resource(dev, SYS_RES_IOPORT, 3,
		sc->sc_port-HSCXB_OFFS, 0x20);
	sc->sc_resources.io_base[3] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[3],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[3])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port-HSCXB_OFFS);
		isic_detach_common(dev);
		return ENXIO;
	}

	/* setup access routines */

	sc->clearirq = NULL;
	sc->readreg = tels0163_read_reg;
	sc->writereg = tels0163_write_reg;

	sc->readfifo = tels0163_read_fifo;
	sc->writefifo = tels0163_write_fifo;

	/* setup card type */
	
	sc->sc_cardtyp= CARD_TYPEP_16_3;

	/* setup IOM bus type */
	
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	t = rman_get_bustag(sc->sc_resources.io_base[0]);
	h = rman_get_bushandle(sc->sc_resources.io_base[0]);

	b0 = bus_space_read_1(t, h, 0);
	b1 = bus_space_read_1(t, h, 1);
	b2 = bus_space_read_1(t, h, 2);
	
	if ( b0 != 0x51 && b0 != 0x10 ) {
		kprintf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!\n",
			unit, b0);
		isic_detach_common(dev);
		return ENXIO;
	}
	
	if ( b1 != 0x93 ) {
		kprintf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n",
			unit, b1);
		isic_detach_common(dev);
		return ENXIO;
	}
	if (( b2 != 0x1c ) && ( b2 != 0x1f )) {
		kprintf("isic%d: Error, signature 3 0x%x != (0x1c || 0x1f) for Teles S0/16.3!\n",
			unit, b2);
		isic_detach_common(dev);
		return ENXIO;	
	}
	
	/* 
	 * Read HSCX A/B VSTR.  Expected value for the S0/16.3 card is
	 * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
	 */
	 
	if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4))	||
            (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )  
	{
		kprintf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
			unit);
		kprintf("isic%d: HSC0: VSTR: %#x\n",
			unit, HSCX_READ(0, H_VSTR));
		kprintf("isic%d: HSC1: VSTR: %#x\n",
			unit, HSCX_READ(1, H_VSTR));
		isic_detach_common(dev);
		return (ENXIO);
	}                   

	/* get our irq */

	if(!(sc->sc_resources.irq =
		bus_alloc_resource(dev, SYS_RES_IRQ,
		&sc->sc_resources.irq_rid,
		0ul, ~0ul, 1, RF_ACTIVE)))
	{
		kprintf("isic%d: Could not get IRQ for Teles S0/16.3.\n",unit);
		isic_detach_common(dev);
		return ENXIO;
	}

	/* get the irq number */
	sc->sc_irq = rman_get_start(sc->sc_resources.irq);

	switch(sc->sc_irq)
	{
		case 2:
		case 9:
		case 5:
		case 10:
		case 12:
		case 15:
			break;

		default:
			kprintf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
				unit, sc->sc_irq);
			isic_detach_common(dev);
			return(ENXIO);
			break;
	}

	/* register interupt routine */
	bus_setup_intr(dev, sc->sc_resources.irq,
		       0, (void(*)(void *))(isicintr),
		       sc, &ih, NULL);

	return (0);
}