Warner,

Thanks again for making all of that much more clear.

Since I originally composed this mail I've hacked out a patch to OLDCARD
to bit-bang the registers on the 5C475E. I also mapped out which IRQs
were actually in use and which were not; and manually changed the 'irq'
entry in /etc/pccard.conf to reflect this.

It looks as though being able to flip function routing separately from
CSC routing is what does the trick, correct me if I'm wrong; things have
suddenly decided to work.

pccard0: Assigning gpr400: io 0x300-0x31f irq 3 mem 0xd4000-0xd4fff

- I've tested with a CDROM drive and a CF card, as well as a ZoomAir wireless
card. The offending GPR400 card gets its irq from pccardd just fine now.
Aside from some PRISM2 bitching when placed into monitor mode (sometimes
to be expected), everything seems to be fine.

- I've placed the datasheet online in case anyone needs to grab it for
reference:  http://www.incunabulum.com/tmp/5C475E.pdf

- Please see patch (and whine) attached. If I'm barking up the wrong tree
totally, comments would be appreciated.

Thanks! Now I'll tackle that nasty driver.

BMS
diff -uNr pccard.orig/i82365.h pccard/i82365.h
--- pccard.orig/i82365.h        Wed Jul 31 21:01:10 2002
+++ pccard/i82365.h     Sat Sep  7 03:32:48 2002
@@ -146,6 +146,7 @@
 #define                PCIC_IOCARD     0x20
 #define                PCIC_MEMCARD    0x00
 #define        PCIC_INTR_ENA   0x10    /* PCI CSC Interrupt enable */
+#define PCIC_INTR_MASK 0x0F    /* Ricoh: Mask for routed ISA IRQ */
 
 /* For the Card Status Change register (PCIC_STAT_CHG) */
 #define PCIC_CDTCH     0x08    /* Card Detect Change */
diff -uNr pccard.orig/pcic_pci.c pccard/pcic_pci.c
--- pccard.orig/pcic_pci.c      Wed Jul 31 21:01:11 2002
+++ pccard/pcic_pci.c   Sat Sep  7 13:50:48 2002
@@ -73,10 +73,20 @@
  * routing doesn't work.  It is purposely vague and undocumented
  * at the moment.  Sadly, this seems to be needed way too often.
  */
-static int pcic_intr_path = (int)pcic_iw_pci;
-TUNABLE_INT("hw.pcic.intr_path", &pcic_intr_path);
-SYSCTL_INT(_hw_pcic, OID_AUTO, intr_path, CTLFLAG_RD, &pcic_intr_path, 0,
-    "Which path to send the interrupts over.");
+static int pcic_csc_intr_path = (int)pcic_iw_pci;
+TUNABLE_INT("hw.pcic.csc_intr_path", &pcic_csc_intr_path); /* XXX */
+SYSCTL_INT(_hw_pcic, OID_AUTO, csc_intr_path, CTLFLAG_RD,
+&pcic_csc_intr_path, 0, "Which path to send card services interrupts over.");
+
+static int pcic_func_intr_path = (int)pcic_iw_pci;
+TUNABLE_INT("hw.pcic.func_intr_path", &pcic_func_intr_path);
+SYSCTL_INT(_hw_pcic, OID_AUTO, func_intr_path, CTLFLAG_RD,
+&pcic_func_intr_path, 0, "Which path to send function interrupts over.");
+
+static int pcic_func_irq = 0;
+TUNABLE_INT("hw.pcic.func_irq", &pcic_func_irq);
+SYSCTL_INT(_hw_pcic, OID_AUTO, func_irq, CTLFLAG_RD,
+&pcic_func_irq, 0, "Override IRQ for routing of function interrupt via ISA. ");
 
 static int pcic_init_routing = 0;
 TUNABLE_INT("hw.pcic.init_routing", &pcic_init_routing);
@@ -575,8 +585,19 @@
 static void
 pcic_pci_ricoh_init(device_t dev)
 {
-       u_int16_t       brgcntl;
-       u_int32_t       device_id = pci_get_devid(dev);
+#if defined(PCIC_ISA_FUNC_ROUTING)
+        struct pcic_softc      *sc;
+        struct pcic_slot       *sp;
+        struct resource                *res;
+       u_int16_t                intgen;
+#endif
+       u_int16_t                brgcntl;
+       u_int32_t                device_id = pci_get_devid(dev);
+
+#if defined(PCIC_ISA_FUNC_ROUTING)
+        sc = (struct pcic_softc *) device_get_softc(dev);
+        sp = &sc->slots[0];
+#endif
 
        switch (device_id) {
        case PCI_DEVICE_ID_RICOH_RL5C465:
@@ -592,6 +613,38 @@
                break;
        }
        pcic_pci_cardbus_init(dev);
+
+#if defined(PCIC_ISA_FUNC_ROUTING)
+       /* 
+        * Force ISA interrupt routing for the function interrupt,
+        * and not the CSC interrupt.
+        */
+       if ((sc->func_route == pcic_iw_isa) && pcic_func_irq != 0) {
+               int rid;
+
+               /* Allocate the ISA function IRQ. This never gets freed. */
+                res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+                       pcic_func_irq, pcic_func_irq, 1, RF_ACTIVE);
+               if (!res)
+                       panic("Could not allocate ISA function IRQ!\N");
+
+               device_printf(dev, "using ISA function irq %d\n",
+                       pcic_func_irq);
+
+               pcic_pci_gen_func(sp, pcic_iw_isa);
+               intgen = sp->getb(sp, PCIC_INT_GEN);
+               intgen &= ~(PCIC_INTR_MASK);
+               intgen |= pcic_func_irq;
+               sp->putb(sp, PCIC_INT_GEN, intgen);
+
+               /*
+                * XXX: Blindly catch any interrupts which might have been
+                * generated as a result of writing to PCIC_INT_GEN.
+                */
+               bus_space_write_4(sp->bst, sp->bsh, CB_SOCKET_EVENT,
+                       0xffffffff);
+       }
+#endif
 }
 
 /*
@@ -1057,7 +1110,7 @@
         * for an explaination of ISA vs PCI interrupts. XXX Might be other
         * special cases as well.
         */
-       if (pcic_intr_path == pcic_iw_pci && 
+       if (pcic_csc_intr_path == pcic_iw_pci && 
            device_id != PCI_DEVICE_ID_PCIC_CLPD6729) {
                rid = 0;
 #ifdef __i386__
@@ -1238,8 +1291,8 @@
                        sc->flags = PCIC_CARDBUS_POWER;
                }
                sp->slt = (struct slot *) 1;
-               sc->csc_route = pcic_intr_path;
-               sc->func_route = pcic_intr_path;
+               sc->csc_route = pcic_csc_intr_path;
+               sc->func_route = pcic_func_intr_path;
                stat = bus_space_read_4(sp->bst, sp->bsh, CB_SOCKET_STATE);
                sc->cd_present = (stat & CB_SS_CD) == 0;        
        }
It appears to be academic for the time being, though, as pccardd can't
allocate the resources the card needs. On my Sony Vaio, when the ACPI
bios is told to configure non-boot devices (Plug and Play OS = NO),
it muxes everything onto IRQ 9. This includes the pcic0 device (both for
card services, and for function). Unfortunately the device I'm working
with doesn't support IRQ 9.

Now I see that some good work had been done around the problem of PCI and
ISA interrupt routing. When I put the bridge on this system into polling
mode, and run pccardd, the box hangs (forcing a break into DDB reveals
that other interrupts are still being serviced, but pccardd is hanging).

I've been doing my testing from single user with filesystems except /var
mounted readonly, /var also has softupdates enabled (4.6-STABLE).

I managed to pull the data sheet for the Ricoh 5C475E controller. Apparently
setting the CB_BCR_INT_EXCA bit on this variant allows the IREQ#/CREQ# line
for 16-bit cards to be routed to an ISA IRQ. I assume this is what
sc->func_route in pcic*.c refers to.

My guess is that the Win2k cardbus driver has enough smarts to set things up
in this way, as it allocates IRQ 7 for the 16-bit device, even though the
cardbus controller itself is sharing IRQ 9. However, without being able to
snapshot registers, I can't be entirely sure.

I realize that I'm doing this work on OLDCARD, but I'm quite desperate to
get things working, so I've attached a patch with what I'm currently doing.

Reply via email to