Date: Thu, 30 Nov 2000 12:55:07 +0200 (EET) From: vlad@infonet.com.ua To: FreeBSD-gnats-submit@freebsd.org Subject: kern/23190: WaveLan problem in 4.* branch Message-ID: <200011301055.eAUAt7B32943@highlander.sumdu.edu.ua>
next in thread | raw e-mail | index | archive | help
>Number: 23190 >Category: kern >Synopsis: Lucent WaveLan PCMCI radio-ethernet card fails to be found in FreeBSD 4.* >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Thu Nov 30 03:00:01 PST 2000 >Closed-Date: >Last-Modified: >Originator: Vlad Marchenko >Release: FreeBSD 4.2-STABLE i386 >Organization: SumDU >Environment: >Description: WaveLan supplied as PCMCI ISA adapter with PCMCI adapter plugged in. With FreeBSD 3.* it works perfectly - you have to configure your kernel with pcmci and add wi0 device. However when you try to get it working with FreeBSD 4 - it won't found it on a boot stage. We played hard with different kernel options, default and from NEWCARD - everything is useless. But as soon as you downgrade sys/pccard/pcic.c back to 3.STABLE (src/sys/pccard/pcic.c 2000/02/21 06:56:29 1.88) then is runs fine! And one more with PCI to PCMCI adapter instead ISA-PCMCI it doesn't work neither with 3-STABLE nor 4-STABLE >How-To-Repeat: Just try it (you need to have wavelan, though) - if anyone from FreeBSD team wants to play with this - we can deal about account at the host with WaveLan and 4-STABLE. Any suggestions will be greatly apreciated. Thanks. >Fix: Run this patch: --- src/sys/pccard/pcic.c 2000/10/15 04:12:43 1.89.2.3 +++ src/sys/pccard/pcic.c 2000/02/21 06:56:29 1.88 @@ -27,7 +27,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/sys/pccard/pcic.c,v 1.89.2.3 2000/10/15 04:12:43 sanpei Exp $ + * $FreeBSD: src/sys/pccard/pcic.c,v 1.88 2000/02/21 06:56:29 imp Exp $ */ #include <sys/param.h> @@ -40,14 +40,10 @@ #include <pccard/i82365.h> #include <pccard/cardinfo.h> +#include <pccard/driver.h> #include <pccard/slot.h> +#include <pccard/pcic.h> -/* Get pnp IDs */ -#include <isa/isavar.h> -#include <dev/pcic/i82365reg.h> - -#include "card_if.h" - /* * Prototypes for interrupt handler. */ @@ -80,22 +76,9 @@ u_char *regs; /* Pointer to regs in mem */ } pcic_slots[PCIC_MAX_SLOTS]; +static int pcic_irq; static struct slot_ctrl cinfo; -static struct isa_pnp_id pcic_ids[] = { - {PCIC_PNP_82365, NULL}, /* PNP0E00 */ - {PCIC_PNP_CL_PD6720, NULL}, /* PNP0E01 */ - {PCIC_PNP_VLSI_82C146, NULL}, /* PNP0E02 */ - {PCIC_PNP_82365_CARDBUS, NULL}, /* PNP0E03 */ - {PCIC_PNP_ACTIONTEC, NULL}, /* AEI0218 */ - {PCIC_PNP_SCM_SWAPBOX, NULL}, /* SCM0469 */ - {0} -}; - -static int validunits = 0; - -#define GET_UNIT(d) *(int *)device_get_softc(d) -#define SET_UNIT(d,u) *(int *)device_get_softc(d) = (u) /* * Internal inline functions for accessing the PCIC. @@ -270,9 +253,9 @@ */ /* - * VLSI 82C146 has incompatibilities about the I/O address of slot 1. - * Assume it's the only PCIC whose vendor ID is 0x84, - * contact Warner Losh <imp@freebsd.org> if correct. + * VLSI 82C146 has incompatibilities about the I/O address + * of slot 1. Assume it's the only PCIC whose vendor ID is 0x84, + * contact Nate Williams <nate@FreeBSD.org> if incorrect. */ static int pcic_probe(device_t dev) @@ -281,16 +264,16 @@ struct slot *slt; struct pcic_slot *sp; unsigned char c; + void *ih; char *name; + int i; int error; - struct resource *r; + struct resource *res = 0; int rid; static int maybe_vlsi = 0; - /* Check isapnp ids */ - error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids); - if (error == ENXIO) - return (ENXIO); + if (device_get_unit(dev) != 0) + return ENXIO; /* * Initialise controller information structure. @@ -305,28 +288,24 @@ cinfo.resume = pcic_resume; cinfo.maxmem = PCIC_MEM_WIN; cinfo.maxio = PCIC_IO_WIN; - - if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) - bus_set_resource(dev, SYS_RES_IOPORT, 0, PCIC_INDEX0, 2); - rid = 0; - r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); - if (!r) { - if (bootverbose) - device_printf(dev, "Cannot get I/O range\n"); - return ENOMEM; - } - sp = &pcic_slots[validunits * PCIC_CARD_SLOTS]; - for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) { + sp = pcic_slots; + for (slotnum = 0; slotnum < PCIC_MAX_SLOTS; slotnum++, sp++) { /* * Initialise the PCIC slot table. */ sp->getb = getb1; sp->putb = putb1; - sp->index = rman_get_start(r); - sp->data = sp->index + 1; - sp->offset = slotnum * PCIC_SLOT_SIZE; - /* + if (slotnum < 4) { + sp->index = PCIC_INDEX_0; + sp->data = PCIC_DATA_0; + sp->offset = slotnum * PCIC_SLOT_SIZE; + } else { + sp->index = PCIC_INDEX_1; + sp->data = PCIC_DATA_1; + sp->offset = (slotnum - 4) * PCIC_SLOT_SIZE; + } + /* * XXX - Screwed up slot 1 on the VLSI chips. According to * the Linux PCMCIA code from David Hinds, working chipsets * return 0x84 from their (correct) ID ports, while the broken @@ -465,13 +444,47 @@ * Allocate a slot and initialise the data structures. */ validslots++; - sp->slotnum = slotnum + validunits * PCIC_CARD_SLOTS; + sp->slotnum = slotnum; slt = pccard_alloc_slot(&cinfo); if (slt == 0) continue; slt->cdata = sp; sp->slt = slt; /* + * If we haven't allocated an interrupt for the controller, + * then attempt to get one. + */ + if (pcic_irq == 0) { + /* See if the user has requested a specific IRQ */ + if (!getenv_int("machdep.pccard.pcic_irq", &pcic_irq)) + pcic_irq = -1; + rid = 0; + if (pcic_irq) { + if (pcic_irq < 0) + pcic_irq = 0; + res = bus_alloc_resource(dev, SYS_RES_IRQ, + &rid, pcic_irq, ~0, 1, RF_ACTIVE); + } + if (res) { + error = bus_setup_intr(dev, res, + INTR_TYPE_MISC, pcicintr, NULL, &ih); + if (error) { + bus_release_resource(dev, SYS_RES_IRQ, + rid, res); + return error; + } + pcic_irq = rman_get_start(res); + printf("pcic: management irq %d\n", pcic_irq); + } else { + if (pcic_irq) + printf("pcic: polling mode, can't alloc %d\n", + pcic_irq); + else + printf("pcic: polling mode\n"); + pcic_irq = 0; + } + } + /* * Modem cards send the speaker audio (dialing noises) * to the host's speaker. Cirrus Logic PCIC chips must * enable this. There is also a Low Power Dynamic Mode bit @@ -481,89 +494,33 @@ if (sp->controller == PCIC_PD672X) { setb(sp, PCIC_MISC1, PCIC_SPKR_EN); setb(sp, PCIC_MISC2, PCIC_LPDM_EN); - } - } - bus_release_resource(dev, SYS_RES_IOPORT, rid, r); - return(validslots ? 0 : ENXIO); -} - -static int -pcic_attach(device_t dev) -{ - void *ih; - int rid; - struct resource *r; - int irq; - int error; - struct pcic_slot *sp; - int i; - int stat; - - SET_UNIT(dev, validunits); - sp = &pcic_slots[GET_UNIT(dev) * PCIC_CARD_SLOTS]; - for (i = 0; i < PCIC_CARD_SLOTS; i++, sp++) { - if (sp->slt) - device_add_child(dev, NULL, -1); - } - validunits++; - - rid = 0; - r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); - if (!r) { - return ENXIO; - } - - irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0); - if (irq == 0) { - /* See if the user has requested a specific IRQ */ - if (!getenv_int("machdep.pccard.pcic_irq", &irq)) - irq = 0; - } - rid = 0; - r = 0; - if (irq >= 0) { - r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, - ~0, 1, RF_ACTIVE); - } - if (r) { - error = bus_setup_intr(dev, r, INTR_TYPE_MISC, - pcicintr, (void *) GET_UNIT(dev), &ih); - if (error) { - bus_release_resource(dev, SYS_RES_IRQ, rid, r); - return error; } - irq = rman_get_start(r); - device_printf(dev, "management irq %d\n", irq); - } else { - irq = 0; - } - if (irq == 0) { - pcictimeout_ch = timeout(pcictimeout, (void *) GET_UNIT(dev), hz/2); - device_printf(dev, "Polling mode\n"); - } - - sp = &pcic_slots[GET_UNIT(dev) * PCIC_CARD_SLOTS]; - for (i = 0; i < PCIC_CARD_SLOTS; i++, sp++) { - /* Assign IRQ */ - sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0xF); - - /* Check for changes */ + /* + * Check for a card in this slot. + */ setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST); - if (sp->slt == NULL) - continue; - stat = sp->getb(sp, PCIC_STATUS); - if (bootverbose) - printf("stat is %x\n", stat); - if ((stat & PCIC_CD) != PCIC_CD) { - sp->slt->laststate = sp->slt->state = empty; + if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) != PCIC_CD) { + slt->laststate = slt->state = empty; } else { - sp->slt->laststate = sp->slt->state = filled; + slt->laststate = slt->state = filled; pccard_event(sp->slt, card_inserted); } - sp->slt->irq = irq; + /* + * Assign IRQ for slot changes + */ + if (pcic_irq > 0) + sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); + else if (pcic_irq == 0) + sp->putb(sp, PCIC_STAT_INT, 0xF); + } + if (validslots && pcic_irq <= 0) + pcictimeout_ch = timeout(pcictimeout, 0, hz/2); + if (validslots) { + for (i = 0; i < validslots; i++) { + device_add_child(dev, NULL, -1); + } } - - return (bus_generic_attach(dev)); + return(validslots ? 0 : ENXIO); } /* @@ -690,7 +647,8 @@ if (irq == 0) clrb(sp, PCIC_INT_GEN, 0xF); else - sp->putb(sp, PCIC_INT_GEN, (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); + sp->putb(sp, PCIC_INT_GEN, + (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); } /* @@ -753,8 +711,8 @@ static void pcictimeout(void *chan) { - pcicintr(chan); - pcictimeout_ch = timeout(pcictimeout, chan, hz/2); + pcicintr(0); + pcictimeout_ch = timeout(pcictimeout, 0, hz/2); } /* @@ -768,14 +726,11 @@ { int slot, s; unsigned char chg; - int unit = (int) arg; - struct pcic_slot *sp = &pcic_slots[unit * PCIC_CARD_SLOTS]; + struct pcic_slot *sp = pcic_slots; s = splhigh(); - for (slot = 0; slot < PCIC_CARD_SLOTS; slot++, sp++) { + for (slot = 0; slot < PCIC_MAX_SLOTS; slot++, sp++) { if (sp->slt && (chg = sp->getb(sp, PCIC_STAT_CHG)) != 0) { - if (bootverbose) - printf("Slot %d chg = 0x%x\n", slot, chg); if (chg & PCIC_CDTCH) { if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) == PCIC_CD) { @@ -797,7 +752,8 @@ { struct pcic_slot *sp = slt->cdata; - sp->putb(sp, PCIC_STAT_INT, (slt->irq << 4) | 0xF); + if (pcic_irq > 0) + sp->putb(sp, PCIC_STAT_INT, (pcic_irq << 4) | 0xF); if (sp->controller == PCIC_PD672X) { setb(sp, PCIC_MISC1, PCIC_SPKR_EN); setb(sp, PCIC_MISC2, PCIC_LPDM_EN); @@ -812,7 +768,8 @@ int err; switch (type) { - case SYS_RES_IOPORT: { + case SYS_RES_IOPORT: + { struct io_desc *ip; ip = &devi->slt->io[rid]; if (ip->flags == 0) { @@ -836,7 +793,8 @@ * interrupt messages. */ break; - case SYS_RES_MEMORY: { + case SYS_RES_MEMORY: + { struct mem_desc *mp; if (rid >= NUM_MEM_WINDOWS) return EINVAL; @@ -864,7 +822,8 @@ int err; switch (type) { - case SYS_RES_IOPORT: { + case SYS_RES_IOPORT: + { struct io_desc *ip = &devi->slt->io[rid]; ip->flags &= ~IODF_ACTIVE; err = pcic_io(devi->slt, rid); @@ -875,7 +834,8 @@ } case SYS_RES_IRQ: break; - case SYS_RES_MEMORY: { + case SYS_RES_MEMORY: + { struct mem_desc *mp = &devi->slt->mem[rid]; mp->flags &= ~(MDF_ACTIVE | MDF_ATTR); err = pcic_memory(devi->slt, rid); @@ -892,13 +852,13 @@ } static int -pcic_setup_intr(device_t dev, device_t child, struct resource *irq, +pcic_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t *intr, void *arg, void **cookiep) { struct pccard_devinfo *devi = device_get_ivars(child); int err; - err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg, + err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg, cookiep); if (err == 0) pcic_mapirq(devi->slt, rman_get_start(irq)); @@ -907,7 +867,7 @@ rman_get_start(irq)); return (err); } - + static int pcic_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) @@ -918,46 +878,10 @@ return (bus_generic_teardown_intr(dev, child, irq, cookie)); } -static int -pcic_set_res_flags(device_t bus, device_t child, int restype, int rid, - u_long value) -{ - struct pccard_devinfo *devi = device_get_ivars(child); - int err = 0; - - switch (restype) { - case SYS_RES_MEMORY: { - struct mem_desc *mp = &devi->slt->mem[rid]; - if (value) - mp->flags |= MDF_ATTR; - else - mp->flags &= ~MDF_ATTR; - err = pcic_memory(devi->slt, rid); - break; - } - default: - err = EOPNOTSUPP; - } - return (err); -} - -static int -pcic_get_res_flags(device_t bus, device_t child, int restype, int rid, - u_long *value) -{ - return (EOPNOTSUPP); -} - -static int -pcic_set_memory_offset(device_t bus, device_t child, int rid, u_int32_t offset) -{ - return (EOPNOTSUPP); -} - static device_method_t pcic_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pcic_probe), - DEVMETHOD(device_attach, pcic_attach), + DEVMETHOD(device_attach, bus_generic_attach), DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), @@ -972,11 +896,6 @@ DEVMETHOD(bus_setup_intr, pcic_setup_intr), DEVMETHOD(bus_teardown_intr, pcic_teardown_intr), - /* Card interface */ - DEVMETHOD(card_set_res_flags, pcic_set_res_flags), - DEVMETHOD(card_get_res_flags, pcic_get_res_flags), - DEVMETHOD(card_set_memory_offset, pcic_set_memory_offset), - { 0, 0 } }; @@ -985,7 +904,7 @@ static driver_t pcic_driver = { "pcic", pcic_methods, - sizeof(int) + 1, /* no softc */ }; DRIVER_MODULE(pcic, isa, pcic_driver, pcic_devclass, 0, 0); >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200011301055.eAUAt7B32943>