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>
