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); }
/*---------------------------------------------------------------------------* * 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); }
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); }
/*---------------------------------------------------------------------------* * 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); } }
/* 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; }
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; }
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); }
/*---------------------------------------------------------------------------* * 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); }
/*---------------------------------------------------------------------------* * 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); } }
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); }
/*---------------------------------------------------------------------------* * 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); }
/*---------------------------------------------------------------------------* * 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); }
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); }
/*---------------------------------------------------------------------------* * 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); }
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); }
/*---------------------------------------------------------------------------* * 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; }
/*---------------------------------------------------------------------------* * 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); }
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 }
/*---------------------------------------------------------------------------* * 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); }
/*---------------------------------------------------------------------------* * 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); } }
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 }
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); }
/*---------------------------------------------------------------------------* * 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); }
/*---------------------------------------------------------------------------* * 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); } }
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); }
/*---------------------------------------------------------------------------* * 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); }