Date: Tue, 31 Oct 2000 02:57:03 -0800 From: Mike Smith <msmith@freebsd.org> To: MIHIRA Sanpei Yoshiro <sanpei@sanpei.org> Cc: mobile@FreeBSD.org Subject: Re: [CardBus] NEWCARD with IBM ThinkPad600 Message-ID: <200010311057.e9VAv3426942@mass.osd.bsdi.com> In-Reply-To: Your message of "Sat, 28 Oct 2000 17:32:25 %2B0900." <200010280832.e9S8WPx02273@lavender.sanpei.org>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multipart MIME message. --==_Exmh_17416091890 Content-Type: text/plain; charset=us-ascii > > I tested NEWCARD(CardBus) on IBM ThinkPad600. But I could not. > > I think this is IRQ problem. How can I use CardBus? > > pci0: <PCI bus> on pcib0 > pccbb0: <TI1250 PCI-CardBus Bridge> mem 0x20301000-0x20301fff at device 2.0 on pci0 > pci_cfgintr: 0:2:A is not routed to a unique interrupt Ok. Can you please test the attached patch? This should be able to route you an interrupt (and if not, we can fix it so that it will). You'll want to remove the acpica code from your kernel again (as I mentioned in the previous email) since it's not routing interrupts (yet). Regards, Mike --==_Exmh_17416091890 Content-Type: text/plain ; name="pci_cfgreg.diff"; charset=us-ascii Content-Description: pci_cfgreg.diff Content-Disposition: attachment; filename="pci_cfgreg.diff" Index: pci_cfgreg.c =================================================================== RCS file: /local0/src/src/sys/i386/pci/pci_cfgreg.c,v retrieving revision 1.70 diff -u -r1.70 pci_cfgreg.c --- pci_cfgreg.c 2000/10/19 08:06:50 1.70 +++ pci_cfgreg.c 2000/10/31 10:55:48 @@ -52,6 +52,11 @@ static int devmax; static int usebios; +static int pci_cfgintr_unique(struct PIR_entry *pe, int pin); +static int pci_cfgintr_linked(struct PIR_entry *pe, int pin); +static int pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin); +static int pci_cfgintr_virgin(struct PIR_entry *pe, int pin); + static int pcibios_cfgread(int bus, int slot, int func, int reg, int bytes); static void pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); static int pcibios_cfgopen(void); @@ -59,7 +64,7 @@ static void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); static int pcireg_cfgopen(void); -static struct PIR_entry *pci_route_table; +static struct PIR_table *pci_route_table; static int pci_route_count; /* @@ -96,7 +101,7 @@ ck += cv[i]; } if (ck == 0) { - pci_route_table = &pt->pt_entry[0]; + pci_route_table = pt; pci_route_count = (pt->pt_header.ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry); printf("Using $PIR table, %d entries at %p\n", pci_route_count, pci_route_table); } @@ -131,11 +136,9 @@ /* * Route a PCI interrupt * - * XXX this needs to learn to actually route uninitialised interrupts as well - * as just returning interrupts for stuff that's already initialised. - * * XXX we don't do anything "right" with the function number in the PIR table - * (because the consumer isn't currently passing it in). + * (because the consumer isn't currently passing it in). We don't care + * anyway, due to the way PCI interrupts are assigned. */ int pci_cfgintr(int bus, int device, int pin) @@ -151,18 +154,20 @@ /* * Scan the entry table for a contender */ - for (i = 0, pe = pci_route_table; i < pci_route_count; i++, pe++) { + for (i = 0, pe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, pe++) { if ((bus != pe->pe_bus) || (device != pe->pe_device)) continue; - if (!powerof2(pe->pe_intpin[pin - 1].irqs)) { - printf("pci_cfgintr: %d:%d:%c is not routed to a unique interrupt\n", - bus, device, 'A' + pin - 1); - break; - } - irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1; - printf("pci_cfgintr: %d:%d:%c routed to irq %d\n", - bus, device, 'A' + pin - 1, irq); + irq = pci_cfgintr_unique(pe, pin); + if (irq == 255) + irq = pci_cfgintr_linked(pe, pin); + if (irq == 255) + irq = pci_cfgintr_virgin(pe, pin); + + if (irq == 255) + break; + + /* * Ask the BIOS to route the interrupt */ @@ -171,9 +176,150 @@ args.ecx = (irq << 8) | (0xa + pin - 1); /* pin value is 0xa - 0xd */ bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL)); - /* XXX if it fails, we should smack the router hardware directly */ + /* + * XXX if it fails, we should try to smack the router hardware directly + */ + printf("pci_cfgintr: %d:%d INT%c routed to irq %d\n", + bus, device, 'A' + pin - 1, irq); return(irq); + } + + printf("pci_cfgintr: can't route an interrupt to %d:%d INT%c\n", bus, device, 'A' + pin - 1); + return(255); +} + +/* + * Look to see if the routing table claims this pin is uniquely routed. + */ +static int +pci_cfgintr_unique(struct PIR_entry *pe, int pin) +{ + int irq; + + if (powerof2(pe->pe_intpin[pin - 1].irqs)) { + irq = ffs(pe->pe_intpin[pin - 1].irqs) - 1; + printf("pci_cfgintr_unique: hard-routed to irq %d\n", irq); + return(irq); + } + return(255); +} + +/* + * Look for another device which shares the same link byte and + * already has a unique IRQ, or which has had one routed already. + */ +static int +pci_cfgintr_linked(struct PIR_entry *pe, int pin) +{ + struct PIR_entry *oe; + struct PIR_intpin *pi; + int i, j, irq; + + /* + * Scan table slots. + */ + for (i = 0, oe = &pci_route_table->pt_entry[0]; i < pci_route_count; i++, oe++) { + + /* scan interrupt pins */ + for (j = 0, pi = &oe->pe_intpin[0]; j < 4; j++, pi++) { + + /* don't look at the entry we're trying to match with */ + if ((pe == oe) && (i == (pin - 1))) + continue; + + /* compare link bytes */ + if (pi->link != pe->pe_intpin[pin - 1].link) + continue; + + /* link destination mapped to a unique interrupt? */ + if (powerof2(pi->irqs)) { + irq = ffs(pi->irqs) - 1; + printf("pci_cfgintr_linked: linked (%x) to hard-routed irq %d\n", + pi->link, irq); + return(irq); + } + + /* look for the real PCI device that matches this table entry */ + if ((irq = pci_cfgintr_search(pe, oe->pe_bus, oe->pe_device, j, pin)) != 255) + return(irq); + } + } + return(255); +} + +/* + * Scan for the real PCI device at (bus)/(device) using intpin (matchpin) and + * see if it has already been assigned an interrupt. + */ +static int +pci_cfgintr_search(struct PIR_entry *pe, int bus, int device, int matchpin, int pin) +{ + devclass_t pci_devclass; + device_t *pci_devices; + int pci_count; + device_t *pci_children; + int pci_childcount; + device_t *busp, *childp; + int i, j, irq; + + /* + * Find all the PCI busses. + */ + pci_count = 0; + if ((pci_devclass = devclass_find("pci")) != NULL) + devclass_get_devices(pci_devclass, &pci_devices, &pci_count); + + /* + * Scan all the PCI busses/devices looking for this one. + */ + for (i = 0, busp = pci_devices; i < pci_count; i++, busp++) { + pci_childcount = 0; + device_get_children(*busp, &pci_children, &pci_childcount); + + for (j = 0, childp = pci_children; j < pci_childcount; j++, childp++) { + if ((pci_get_bus(*childp) == bus) && + (pci_get_slot(*childp) == device) && + (pci_get_intpin(*childp) == matchpin) && + ((irq = pci_get_irq(*childp)) != 255)) { + printf("pci_cfgintr_search: linked (%x) to configured irq %d at %d:%d:%d\n", + irq, pe->pe_intpin[pin - 1].link, + pci_get_bus(*childp), pci_get_slot(*childp), pci_get_function(*childp)); + return(irq); + } + } + } + return(255); +} + +/* + * Pick a suitable IRQ from those listed as routable to this device. + */ +static int +pci_cfgintr_virgin(struct PIR_entry *pe, int pin) +{ + int irq, ibit; + + /* first scan the set of PCI-only interrupts and see if any of these are routable */ + for (irq = 0; irq < 16; irq++) { + ibit = (1 << irq); + + /* can we use this interrupt? */ + if ((pci_route_table->pt_header.ph_pci_irqs & ibit) && + (pe->pe_intpin[pin - 1].irqs & ibit)) { + printf("pci_cfgintr_virgin: using routable PCI-only interrupt %d\n", irq); + return(irq); + } + } + + /* life is tough, so just pick an interrupt */ + for (irq = 0; irq < 16; irq++) { + ibit = (1 << irq); + + if (pe->pe_intpin[pin - 1].irqs & ibit) { + printf("pci_cfgintr_virgin: using routable interrupt %d\n", irq); + return(irq); + } } return(255); } --==_Exmh_17416091890 Content-Type: text/plain; charset=us-ascii ... every activity meets with opposition, everyone who acts has his rivals and unfortunately opponents also. But not because people want to be opponents, rather because the tasks and relationships force people to take different points of view. [Dr. Fritz Todt] V I C T O R Y N O T V E N G E A N C E --==_Exmh_17416091890-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-mobile" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010311057.e9VAv3426942>