Subject: Re: CardBus PCI
To: None <mcr@sandelman.ottawa.on.ca>
From: Hayakawa Koichi <haya@ilink.sony.co.jp>
List: tech-kern
Date: 04/25/2001 12:32:00
Hello,
From: Michael Richardson <mcr@sandelman.ottawa.on.ca>
Subject: Re: CardBus PCI
Date: Tue, 24 Apr 2001 14:30:41 -0400
Message-ID: <200104241830.f3OIUfh14054@marajade.sandelman.ottawa.on.ca>
> As I look through things, I think that we need to adjust the way that
> PCI devices establish interrupts, or at least hack pci_intr_map
> to realize that it is behind a cardbus bridge.
We should assign correct intrrupt-line-number to
pba_intrline, at least for i386. I attach a patch at the
end of this mail (Sorry I don't compile it, because I have
no NetBSD machine on me now). This patch intends to write
cardbus's interrupt line number on all PCI funtion's
interrupt line registers.
# I don't know why sc_intrswiz is needed;-)
> The more that I think about it, the more that I think that we need
> a new value for pci_chipset_tag_t. Does this make sense?
Yes, logically. But, maybe this value is not used, at least
on i386.
--
HAYAKAWA, Koichi
P.S. I think we should unify PCI and CardBus (and
CompactPCI, possibly) handler, but...
*** rbus_ppb.c Wed Apr 25 11:58:38 2001
--- rbus_ppb.c Wed Apr 25 12:29:21 2001
***************
*** 163,168 ****
--- 163,169 ----
char devinfo[256];
pcireg_t busdata;
int mybus;
+ int device, function, nfunctions;
mybus = ct->ct_bus;
***************
*** 207,216 ****
pba.pba_pc = psc->sc_pc;
pba.pba_flags = PCI_FLAGS_IO_ENABLED|PCI_FLAGS_MEM_ENABLED;
pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
! /*pba.pba_intrswiz = 0 ca->ca_intrswiz*/;
! /*pba.pba_intrtag = psc->sc_intrtag;*/
! /*pba.pba_intrline = parent_sc->sc_intrline; */
config_found(self, &pba, rppbprint);
}
--- 208,265 ----
pba.pba_pc = psc->sc_pc;
pba.pba_flags = PCI_FLAGS_IO_ENABLED|PCI_FLAGS_MEM_ENABLED;
pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
! pba.pba_intrswiz = 0;
! pba.pba_intrtag = 0;
! pba.pba_intrline = parent_sc->sc_intrline;
+ for (device = 0; device < 32; device++) {
+ pcitag_t tag;
+ pcireg_t id, class, intr, bhlcr, csr;
+ struct pci_attach_args pa;
+ int pin;
+
+ tag = pci_make_tag(pc, pba.pba_bus, device, 0);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+
+ /* Invalid vendor ID value? */
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+ /* XXX Not invalid, but we've done this ~forever. */
+ if (PCI_VENDOR(id) == 0)
+ continue;
+
+ bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
+ if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
+ (qd != NULL &&
+ (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
+ nfunctions = 8;
+ else
+ nfunctions = 1;
+
+ for (function = 0; function < nfunctions; function++) {
+ tag = pci_make_tag(pc, pba.pba_bus, device, function);
+ id = pci_conf_read(pc, tag, PCI_ID_REG);
+
+ /* Invalid vendor ID value? */
+ if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+ continue;
+ /* XXX Not invalid, but we've done this ~forever. */
+ if (PCI_VENDOR(id) == 0)
+ continue;
+
+ intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
+
+ if (PCI_INTERRUPT_PIN(intr) == 0) {
+ /* No interrupt required */
+ continue;
+ }
+
+ intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
+ intr |= ((PCI_INTERRUPT_LINE_MASK & parent_sc->sc_intrline) << PCI_INTERRUPT_LINE_SHIFT);
+ pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
+ }
+ }
+
config_found(self, &pba, rppbprint);
}