/*---------------------------------------------------------------------------* * allocate an io port *---------------------------------------------------------------------------*/ static int isic_alloc_port(device_t dev, int rid, u_int base, u_int len) { size_t unit = device_get_unit(dev); struct l1_softc *sc = &l1_sc[unit]; sc->sc_resources.io_rid[rid] = rid; bus_set_resource(dev, SYS_RES_IOPORT, rid, base, len); if(!(sc->sc_resources.io_base[rid] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[rid], 0ul, ~0ul, 1, RF_ACTIVE))) { printf("isic%d: Error, failed to reserve io #%d!\n", unit, rid); isic_detach_common(dev); return(ENXIO); } return(0); }
/*---------------------------------------------------------------------------* * attach for ISA PnP cards *---------------------------------------------------------------------------*/ static int isic_pnp_attach(device_t dev) { u_int32_t vend_id = isa_get_vendorid(dev); /* vendor id */ unsigned int unit = device_get_unit(dev); /* get unit */ const char *name = device_get_desc(dev); /* get description */ struct l1_softc *sc = 0; /* softc */ void *ih = 0; /* a dummy */ int ret; /* see if we are out of bounds */ if(unit >= ISIC_MAXUNIT) { printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n", unit, unit, name); return ENXIO; } /* get information structure for this unit */ sc = &l1_sc[unit]; /* get io_base */ 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_pnp_attach: Couldn't get my io_base.\n"); return ENXIO; } /* will not be used for pnp devices */ sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); /* get irq, release io_base if we don't get it */ 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 irq.\n",unit); isic_detach_common(dev); return ENXIO; } /* not needed */ sc->sc_irq = rman_get_start(sc->sc_resources.irq); /* set flag so we know what this card is */ ret = ENXIO; switch(vend_id) { #if defined(TEL_S0_16_3_P) || defined(CRTX_S0_P) || defined(COMPAQ_M610) case VID_TEL163PNP: sc->sc_cardtyp = CARD_TYPEP_163P; ret = isic_attach_Cs0P(dev); break; case VID_CREATIXPP: sc->sc_cardtyp = CARD_TYPEP_CS0P; ret = isic_attach_Cs0P(dev); break; case VID_COMPAQ_M610: sc->sc_cardtyp = CARD_TYPEP_COMPAQ_M610; ret = isic_attach_Cs0P(dev); break; #endif #ifdef DYNALINK case VID_DYNALINK: sc->sc_cardtyp = CARD_TYPEP_DYNALINK; ret = isic_attach_Dyn(dev); break; #endif #ifdef SEDLBAUER case VID_SEDLBAUER: sc->sc_cardtyp = CARD_TYPEP_SWS; ret = isic_attach_sws(dev); break; #endif #ifdef DRN_NGO case VID_NICCYGO: sc->sc_cardtyp = CARD_TYPEP_DRNNGO; ret = isic_attach_drnngo(dev); break; #endif #ifdef ELSA_QS1ISA case VID_ELSAQS1P: sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA; ret = isic_attach_Eqs1pi(dev); break; #endif #ifdef ITKIX1 case VID_ITK0025: sc->sc_cardtyp = CARD_TYPEP_ITKIX1; ret = isic_attach_itkix1(dev); break; #endif #ifdef SIEMENS_ISURF2 case VID_SIESURF2: sc->sc_cardtyp = CARD_TYPEP_SIE_ISURF2; ret = isic_attach_siemens_isurf(dev); break; #endif #ifdef ASUSCOM_IPAC case VID_ASUSCOM_IPAC: sc->sc_cardtyp = CARD_TYPEP_ASUSCOMIPAC; ret = isic_attach_asi(dev); break; #endif #ifdef EICON_DIVA case VID_EICON_DIVA_20: sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; ret = isic_attach_diva(dev); break; case VID_EICON_DIVA_202: sc->sc_cardtyp = CARD_TYPEP_DIVA_ISA; ret = isic_attach_diva_ipac(dev); break; #endif default: printf("isic%d: Error, no driver for %s\n", unit, name); ret = ENXIO; break; } if(ret) { isic_detach_common(dev); return ENXIO; } if(isic_attach_common(dev)) { /* unset flag */ sc->sc_cardtyp = CARD_TYPEP_UNK; /* free irq here, it hasn't been attached yet */ bus_release_resource(dev,SYS_RES_IRQ,sc->sc_resources.irq_rid, sc->sc_resources.irq); sc->sc_resources.irq = 0; isic_detach_common(dev); return ENXIO; } else { /* setup intr routine */ bus_setup_intr(dev,sc->sc_resources.irq,INTR_TYPE_NET, (void(*)(void*))isicintr, sc,&ih); return 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); }
/*---------------------------------------------------------------------------* * allocate an io port - based on code in isa_isic.c *---------------------------------------------------------------------------*/ static int usrtai_alloc_port(device_t dev) { size_t unit = device_get_unit(dev); struct l1_softc *sc = &l1_sc[unit]; int i, num = 0; bus_size_t base; /* 49 io mappings: 1 config and 48x8 registers */ /* config at offset 0x8000 */ base = sc->sc_port + 0x8000; if (base < 0 || base > 0x0ffff) return 1; sc->sc_resources.io_rid[num] = num; bus_set_resource(dev, SYS_RES_IOPORT, num, base, 1); if(!(sc->sc_resources.io_base[num] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[num], 0ul, ~0ul, 1, RF_ACTIVE))) { kprintf("isic%d: Error, failed to reserve io #%dport %#x!\n", unit, num, base); isic_detach_common(dev); return(ENXIO); } num++; /* HSCX A at offset 0 */ base = sc->sc_port; for (i = 0; i < 16; i++) { if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) return 1; sc->sc_resources.io_rid[num] = num; bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8); if(!(sc->sc_resources.io_base[num] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[num], 0ul, ~0ul, 1, RF_ACTIVE))) { kprintf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024); isic_detach_common(dev); return(ENXIO); } ++num; } /* HSCX B at offset 0x4000 */ base = sc->sc_port + 0x4000; for (i = 0; i < 16; i++) { if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) return 1; sc->sc_resources.io_rid[num] = num; bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8); if(!(sc->sc_resources.io_base[num] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[num], 0ul, ~0ul, 1, RF_ACTIVE))) { kprintf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024); isic_detach_common(dev); return(ENXIO); } ++num; } /* ISAC at offset 0xc000 */ base = sc->sc_port + 0xc000; for (i = 0; i < 16; i++) { if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) return 1; sc->sc_resources.io_rid[num] = num; bus_set_resource(dev, SYS_RES_IOPORT, num, base+i*1024, 8); if(!(sc->sc_resources.io_base[num] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[num], 0ul, ~0ul, 1, RF_ACTIVE))) { kprintf("isic%d: Error, failed to reserve io #%d port %#x!\n", unit, num, base+i*1024); isic_detach_common(dev); return(ENXIO); } ++num; } return(0); }
/*---------------------------------------------------------------------------* * 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); }
/*---------------------------------------------------------------------------* * isic_attach_Cs0P - attach Creatix / Teles PnP *---------------------------------------------------------------------------*/ int isic_attach_Cs0P(device_t dev) { u_int32_t iobase1; u_int32_t iobase2; u_int32_t iocfg = 0; /* quiet bogus gcc warning */ int unit = device_get_unit(dev); struct l1_softc *sc = &l1_sc[unit]; bus_space_tag_t t; bus_space_handle_t h; /* * this card needs a second io_base, * free resources if we don't get it */ sc->sc_resources.io_rid[1] = 1; if(!(sc->sc_resources.io_base[1] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[1], 0UL, ~0UL, 1, RF_ACTIVE))) { printf("isic%d: Could not get io area 1 for Creatix / Teles PnP!\n", unit); isic_detach_common(dev); return ENXIO; } /* * Compaq M610 has a cfg io area, * we need it */ if (sc->sc_cardtyp == CARD_TYPEP_COMPAQ_M610) { sc->sc_resources.io_rid[2] = 2; if(!(sc->sc_resources.io_base[2] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[2], 0UL, ~0UL, 1, RF_ACTIVE))) { printf("isic%d: Could not get cfg io area for Compaq Microcom 610\n", unit); isic_detach_common(dev); return ENXIO; } iocfg = rman_get_start(sc->sc_resources.io_base[2]); bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[2], sc->sc_resources.io_base[2]); } /* remember the io base addresses */ if (sc->sc_cardtyp != CARD_TYPEP_COMPAQ_M610) { iobase1 = rman_get_start(sc->sc_resources.io_base[0]); iobase2 = rman_get_start(sc->sc_resources.io_base[1]); } else { iobase1 = rman_get_start(sc->sc_resources.io_base[1]); iobase2 = rman_get_start(sc->sc_resources.io_base[0]); } /* * because overlapping resources are invalid, * release the first and second io port resource */ bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0], sc->sc_resources.io_base[0]); bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[1], sc->sc_resources.io_base[1]); /* set and allocate a base io address for the ISAC chip */ sc->sc_resources.io_rid[2] = 2; bus_set_resource(dev, SYS_RES_IOPORT, 2, iobase1-0x20, 0x40); if(!(sc->sc_resources.io_base[2] = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_resources.io_rid[2], 0ul, ~0ul, 1, RF_ACTIVE))) { printf("isic%d: Could not get io area 2 for Creatix / Teles PnP!\n", unit); isic_detach_common(dev); return ENXIO; } /* set and allocate a resource for the HSCX channel A */ sc->sc_resources.io_rid[3] = 3; /*XXX*/ /* FIXME !!!! * the width of the resource is too small, there are accesses * to it with an offset of 0x3e into the next resource. anyway, * it seems to work and i have no idea how to do 2 resources * overlapping each other. */ #if 0 bus_set_resource(dev, SYS_RES_IOPORT, 3, iobase2-0x20, 0x20); #else bus_set_resource(dev, SYS_RES_IOPORT, 3, iobase2-0x20, 0x10); #endif if(!(sc->sc_resources.io_base[3] = bus_alloc_resource(dev,SYS_RES_IOPORT, &sc->sc_resources.io_rid[3], 0ul,~0ul, 1, RF_ACTIVE))) { printf("isic%d: Could not get io area 3 for Creatix / Teles PnP!\n", unit); isic_detach_common(dev); return ENXIO; } /* set and allocate a resources for the HSCX channel B */ sc->sc_resources.io_rid[4] = 4; bus_set_resource(dev, SYS_RES_IOPORT, 4, iobase2, 0x40); if(!(sc->sc_resources.io_base[4] = bus_alloc_resource(dev,SYS_RES_IOPORT, &sc->sc_resources.io_rid[4], 0ul, ~0ul, 1, RF_ACTIVE))) { printf("isic%d: Could not get io area 4 for Creatix / Teles PnP!\n", unit); isic_detach_common(dev); return ENXIO; } /* * set and allocate a resource for the cfg io * for compaq m610 */ if (sc->sc_cardtyp == CARD_TYPEP_COMPAQ_M610) { sc->sc_resources.io_rid[5] = 5; bus_set_resource(dev, SYS_RES_IOPORT, 5, iocfg, 0x01); if(!(sc->sc_resources.io_base[5] = bus_alloc_resource(dev,SYS_RES_IOPORT, &sc->sc_resources.io_rid[5], 0ul, ~0ul, 1, RF_ACTIVE))) { printf("isic%d: Could not get cfg io area for Compaq Microcom 610!\n", unit); isic_detach_common(dev); return ENXIO; } } /* 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 */ if (sc->sc_cardtyp != CARD_TYPEP_COMPAQ_M610) 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; /* enable the card */ if (sc->sc_cardtyp != CARD_TYPEP_COMPAQ_M610) { t = rman_get_bustag(sc->sc_resources.io_base[2]); h = rman_get_bushandle(sc->sc_resources.io_base[2]); bus_space_write_1(t, h, 0x3c, 0); DELAY(SEC_DELAY / 10); bus_space_write_1(t, h, 0x3c, 1); DELAY(SEC_DELAY / 10); } else { t = rman_get_bustag(sc->sc_resources.io_base[5]); h = rman_get_bushandle(sc->sc_resources.io_base[5]); bus_space_write_1(t, h, 0xff, 0); DELAY(SEC_DELAY / 10); bus_space_write_1(t, h, 0x00, 1); DELAY(SEC_DELAY / 10); } return 0; }
/*---------------------------------------------------------------------------* * isic_probe_s016 - probe for Teles S0/16 and compatibles *---------------------------------------------------------------------------*/ int isic_probe_s016(device_t dev) { size_t unit = device_get_unit(dev); /* get unit */ struct l1_softc *sc = 0; /* softc */ void *ih = 0; /* dummy */ u_int8_t b0,b1,b2; /* for signature */ bus_space_tag_t t; /* bus things */ bus_space_handle_t h; /* check max unit range */ if(unit >= ISIC_MAXUNIT) { printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\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 allocate i/o port for Teles S0/16.\n", unit); return(ENXIO); } sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]); /* * check if the provided io port is valid */ switch(sc->sc_port) { case 0xd80: case 0xe80: case 0xf80: break; default: printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n", unit, sc->sc_port); isic_detach_common(dev); return(ENXIO); break; } /* allocate memory resource */ if(!(sc->sc_resources.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->sc_resources.mem_rid, 0ul, ~0ul, TELES_S016_MEMSIZE, RF_ACTIVE))) { printf("isic%d: Could not allocate memory for Teles S0/16.\n", unit); isic_detach_common(dev); return(ENXIO); } /* * get virtual addr. */ sc->sc_vmem_addr = rman_get_virtual(sc->sc_resources.mem); /* * check for valid adresses */ switch(kvtop(sc->sc_vmem_addr)) { case 0xc0000: case 0xc2000: case 0xc4000: case 0xc6000: case 0xc8000: case 0xca000: case 0xcc000: case 0xce000: case 0xd0000: case 0xd2000: case 0xd4000: case 0xd6000: case 0xd8000: case 0xda000: case 0xdc000: case 0xde000: break; default: printf("isic%d: Error, invalid memory address 0x%lx for Teles S0/16!\n", unit, kvtop(sc->sc_vmem_addr)); isic_detach_common(dev); return(ENXIO); break; } /* setup ISAC access routines */ sc->clearirq = NULL; sc->readreg = tels016_read_reg; sc->writereg = tels016_write_reg; sc->readfifo = tels016_read_fifo; sc->writefifo = tels016_write_fifo; /* setup card type */ sc->sc_cardtyp = CARD_TYPEP_16; /* setup IOM bus type */ sc->sc_bustyp = BUS_TYPE_IOM1; sc->sc_ipac = 0; sc->sc_bfifolen = HSCX_FIFO_LEN; /* setup ISAC base addr, though we don't really need it */ ISAC_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x100); /* setup HSCX base addr */ HSCX_A_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x180); HSCX_B_BASE = (caddr_t)((sc->sc_vmem_addr) + 0x1c0); t = rman_get_bustag(sc->sc_resources.io_base[0]); h = rman_get_bushandle(sc->sc_resources.io_base[0]); /* get signature bytes */ b0 = bus_space_read_1(t, h, 0); b1 = bus_space_read_1(t, h, 1); b2 = bus_space_read_1(t, h, 2); /* check signature bytes */ if(b0 != 0x51) { printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n", unit, b0); isic_detach_common(dev); return(ENXIO); } if(b1 != 0x93) { printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n", unit, b1); isic_detach_common(dev); return(ENXIO); } if((b2 != 0x1e) && (b2 != 0x1f)) { printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n", unit, b2); 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))) { printf("isic%d: Could not allocate irq for Teles S0/16.\n", unit); isic_detach_common(dev); return ENXIO; } /* register interupt routine */ bus_setup_intr(dev, sc->sc_resources.irq, INTR_TYPE_NET, (void(*)(void *))(isicintr), sc, &ih); /* get the irq number */ sc->sc_irq = rman_get_start(sc->sc_resources.irq); /* check IRQ validity */ if((intr_no[sc->sc_irq]) == 1) { printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n", unit, sc->sc_irq); isic_detach_common(dev); return(ENXIO); } return (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); }