diff options
author | gj <gj@FreeBSD.org> | 2000-02-21 02:10:10 +0000 |
---|---|---|
committer | gj <gj@FreeBSD.org> | 2000-02-21 02:10:10 +0000 |
commit | 75e6ea817c517c136c75bc341475d572349eadd1 (patch) | |
tree | f8395cacd30684055ce5bb55cbecd54daf04419f /sys/i4b | |
parent | 342be865629c3d818530a03b3a63b1cc1e9e7792 (diff) | |
download | FreeBSD-src-75e6ea817c517c136c75bc341475d572349eadd1.zip FreeBSD-src-75e6ea817c517c136c75bc341475d572349eadd1.tar.gz |
Newbus-ify the USR Sportster TA Intern driver.
Enable the driver in sys/conf/files.i386.
In isa/isavar.h increase ISA_NPORT from 32 to 50. This is required
because this brain-damaged card maps 49 (!) port ranges. This does
not have a negative impact because this value only specifies the maximum
number of entries in a linked list and not the size of an array which
is allocated in all drivers.
The register/fifo access routines were not newbus-ified because
1) I knew that the old code worked and is simpler and more efficient
2) the if_ed driver does something similar and
3) the newbus macros collapse to inb/outb anyway.
Reviewed and tested by: hm
Approved by: jkh
Diffstat (limited to 'sys/i4b')
-rw-r--r-- | sys/i4b/layer1/i4b_usr_sti.c | 354 |
1 files changed, 299 insertions, 55 deletions
diff --git a/sys/i4b/layer1/i4b_usr_sti.c b/sys/i4b/layer1/i4b_usr_sti.c index 9c58ee8..2540ae4 100644 --- a/sys/i4b/layer1/i4b_usr_sti.c +++ b/sys/i4b/layer1/i4b_usr_sti.c @@ -54,6 +54,10 @@ #ifdef __FreeBSD__ #include <machine/clock.h> #include <i386/isa/isa_device.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> +#include <sys/rman.h> #else #include <machine/bus.h> #include <sys/device.h> @@ -92,92 +96,291 @@ static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 }; #ifdef __FreeBSD__ +/* prototypes */ +int isic_probe_usrtai __P((device_t)); +int isic_attach_usrtai __P((device_t)); + #define ADDR(reg) \ (((reg/4) * 1024) + ((reg%4) * 2)) +#ifdef USRTA_DEBUG_PORTACCESS +int debugcntr; +#define USRTA_DEBUG(fmt) \ + if (++debugcntr < 1000) printf fmt; +#else +#define USRTA_DEBUG(fmt) +#endif + /*---------------------------------------------------------------------------* * USRobotics read fifo routine *---------------------------------------------------------------------------*/ static void -usrtai_read_fifo(void *buf, const void *base, size_t len) +usrtai_read_fifo(struct l1_softc *sc, int what, void *buf, size_t size) { register int offset = 0; + register unsigned int base = 0; + +USRTA_DEBUG(("usrtai_read_fifo: what %d size %d\n", what, size)) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_read_fifo: invalid what %d\n", what); + return; + } - for(;len > 0; len--, offset++) - *((u_char *)buf + offset) = inb((int)base + ADDR(offset)); + for(;size > 0; size--, offset++) + { + *((u_char *)buf + offset) = inb(base + ADDR(offset)); + } } /*---------------------------------------------------------------------------* * USRobotics write fifo routine *---------------------------------------------------------------------------*/ static void -usrtai_write_fifo(void *base, const void *buf, size_t len) +usrtai_write_fifo(struct l1_softc *sc, int what, void *data, size_t size) { register int offset = 0; + register unsigned int base = 0; + +USRTA_DEBUG(("usrtai_write_fifo: what %d size %d\n", what, size)) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_write_fifo: invalid what %d\n", what); + return; + } + - for(;len > 0; len--, offset++) - outb((int)base + ADDR(offset), *((u_char *)buf + offset)); + for(;size > 0; size--, offset++) + { + outb(base + ADDR(offset), *((u_char *)data + offset)); + } } /*---------------------------------------------------------------------------* * USRobotics write register routine *---------------------------------------------------------------------------*/ static void -usrtai_write_reg(u_char *base, u_int offset, u_int v) +usrtai_write_reg(struct l1_softc *sc, int what, bus_size_t offs, u_int8_t data) { - outb((int)base + ADDR(offset), (u_char)v); + register unsigned int base = 0; + +USRTA_DEBUG(("usrtai_write_reg: what %d ADDR(%d) %d data %#x\n", what, offs, ADDR(offs), data)) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_write_reg invalid what %d\n", what); + return; + } + + outb(base + ADDR(offs), (u_char)data); } /*---------------------------------------------------------------------------* * USRobotics read register routine *---------------------------------------------------------------------------*/ -static u_char -usrtai_read_reg(u_char *base, u_int offset) +static u_int8_t +usrtai_read_reg(struct l1_softc *sc, int what, bus_size_t offs) { - return(inb((int)base + ADDR(offset))); + register unsigned int base = 0; + u_int8_t byte; + +USRTA_DEBUG(("usrtai_read_reg: what %d ADDR(%d) %d..", what, offs, ADDR(offs))) + switch (what) + { + case ISIC_WHAT_ISAC: + base = (unsigned int)ISAC_BASE; + break; + case ISIC_WHAT_HSCXA: + base = (unsigned int)HSCX_A_BASE; + break; + case ISIC_WHAT_HSCXB: + base = (unsigned int)HSCX_B_BASE; + break; + default: + printf("usrtai_read_reg: invalid what %d\n", what); + return(0); + } + + byte = inb(base + ADDR(offs)); +USRTA_DEBUG(("usrtai_read_reg: got %#x\n", byte)) + return(byte); +} + +/*---------------------------------------------------------------------------* + * 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))) + { + printf("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))) + { + printf("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))) + { + printf("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))) + { + printf("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_usrtai - probe for USR *---------------------------------------------------------------------------*/ int -isic_probe_usrtai(struct isa_device *dev) +isic_probe_usrtai(device_t dev) { - struct isic_softc *sc = &isic_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; + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + void *ih = 0; /* dummy */ - /* check IRQ validity */ + /* check max unit range */ - if((intr_no[ffs(dev->id_irq) - 1]) == 0) + if(unit >= ISIC_MAXUNIT) { - printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n", - dev->id_unit, (ffs(dev->id_irq))-1); - return(0); + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for USR Sportster TA!\n", + unit, unit); + return(ENXIO); } - sc->sc_irq = dev->id_irq; - /* check if memory addr specified */ + sc = &l1_sc[unit]; /* get pointer to softc */ + sc->sc_unit = unit; /* set unit */ + sc->sc_flags = FLAG_USR_ISDN_TA_INT; /* set flags */ - if(dev->id_maddr) + /* 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: Error, mem addr 0x%lx specified for USR Sportster TA!\n", - dev->id_unit, (u_long)dev->id_maddr); - return(0); + printf("isic%d: Could not get iobase for USR Sportster TA!\n", + unit); + return(ENXIO); } - dev->id_msize = 0; + + /* 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(dev->id_iobase) + switch(sc->sc_port) { case 0x200: case 0x208: @@ -199,12 +402,49 @@ isic_probe_usrtai(struct isa_device *dev) default: printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n", - dev->id_unit, dev->id_iobase); + unit, sc->sc_port); return(0); break; } - sc->sc_port = dev->id_iobase; - + + /* allocate all the ports needed */ + + if(usrtai_alloc_port(dev)) + { + printf("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))) + { + printf("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, INTR_TYPE_NET, + (void(*)(void *))(isicintr), + sc, &ih); + + /* check IRQ validity */ + + if(intr_no[sc->sc_irq] == 0) + { + printf("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; @@ -227,9 +467,9 @@ isic_probe_usrtai(struct isa_device *dev) /* setup ISAC and HSCX base addr */ - ISAC_BASE = (caddr_t)dev->id_iobase + USR_ISAC_OFF; - HSCX_A_BASE = (caddr_t)dev->id_iobase + USR_HSCXA_OFF; - HSCX_B_BASE = (caddr_t)dev->id_iobase + USR_HSCXB_OFF; + 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 @@ -240,48 +480,52 @@ isic_probe_usrtai(struct isa_device *dev) ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) { printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n", - dev->id_unit); + unit); printf("isic%d: HSC0: VSTR: %#x\n", - dev->id_unit, HSCX_READ(0, H_VSTR)); + unit, HSCX_READ(0, H_VSTR)); printf("isic%d: HSC1: VSTR: %#x\n", - dev->id_unit, HSCX_READ(1, H_VSTR)); - return (0); + unit, HSCX_READ(1, H_VSTR)); + return (1); } - return (1); + return (0); } /*---------------------------------------------------------------------------* * isic_attach_usrtai - attach USR *---------------------------------------------------------------------------*/ int -isic_attach_usrtai(struct isa_device *dev) +isic_attach_usrtai(device_t dev) { u_char irq = 0; + size_t unit = device_get_unit(dev); /* get unit */ + struct l1_softc *sc = 0; /* pointer to softc */ + sc = &l1_sc[unit]; /* get pointer to softc */ + /* reset the HSCX and ISAC chips */ - outb(dev->id_iobase + USR_INTL_OFF, USR_RES_BIT); + outb(sc->sc_port + USR_INTL_OFF, USR_RES_BIT); DELAY(SEC_DELAY / 10); - outb(dev->id_iobase + USR_INTL_OFF, 0x00); + outb(sc->sc_port + USR_INTL_OFF, 0x00); DELAY(SEC_DELAY / 10); /* setup IRQ */ - if((irq = intr_no[ffs(dev->id_irq) - 1]) == 0) + if((irq = intr_no[sc->sc_irq]) == 0) { printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n", - dev->id_unit, ffs(dev->id_irq)-1); - return(0); + unit, sc->sc_irq); + return(1); } /* configure and enable irq */ - outb(dev->id_iobase + USR_INTL_OFF, irq | USR_INTE_BIT); + outb(sc->sc_port + USR_INTL_OFF, irq | USR_INTE_BIT); DELAY(SEC_DELAY / 10); - return (1); + return (0); } #else /* end of FreeBSD, start NetBSD */ |