Skip site navigation (1)Skip section navigation (2)
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>