> uhci chipsets.  As I said previously, I know a "special" UHCI driver was
> released by Microsoft/VIA that corrected a lot of problems that were being
> had with VIA's chipset.  I would persue a fix for it myself, but I don't

The old VIA random bit stuff is covered in the Linux USB

> know enough about the host controller code to be able to talk one-to-one
> to a VIA representative.  If the maintainer of one of the *uhci.c drivers
> were to look into it, I think it definitely be worth doing.

Lots of VIA boards have what appear to be incorrect $PIR IRQ routing tables.
Windows uses other methods for IRQ routing so generally works out, Linux
uses the $PIR table so does not.

-- this hack tends to fix most of them ->

>From [EMAIL PROTECTED] Sun Nov 04 22:07:34 2001
Return-path: <[EMAIL PROTECTED]>
Envelope-to: [EMAIL PROTECTED]
Delivery-date: Sun, 04 Nov 2001 22:07:34 +0000
Received: from colorfullife.com ([216.156.138.34])
        by the-village.bc.nu with esmtp (Exim 3.22 #1)
        id 160VQT-0003Du-00
        for [EMAIL PROTECTED]; Sun, 04 Nov 2001 22:07:33 +0000
Received: from dbl.localdomain (localhost [127.0.0.1])
        by colorfullife.com (8.11.6/8.11.6) with ESMTP id fA4M1CL25528;
        Sun, 4 Nov 2001 17:01:13 -0500
Received: from colorfullife.com (IDENT:[EMAIL PROTECTED] [172.17.4.1])
        by dbl.localdomain (8.11.2/8.11.2) with ESMTP id fA4LxvU12362;
        Sun, 4 Nov 2001 23:00:03 +0100
Sender: [EMAIL PROTECTED]
Message-ID: <[EMAIL PROTECTED]>
Date: Sun, 04 Nov 2001 22:59:57 +0100
From: Manfred Spraul <[EMAIL PROTECTED]>
X-Mailer: Mozilla 4.76 [en] (X11; U; Linux 2.4.13-ac7 i686)
X-Accept-Language: en, de
MIME-Version: 1.0
To: Alan Cox <[EMAIL PROTECTED]>
CC: [EMAIL PROTECTED]
Subject: pci-irq.c
Content-Type: multipart/mixed;
 boundary="------------7B3CDC07A9A97CDC876B3336"
Status: RO

This is a multi-part message in MIME format.
--------------7B3CDC07A9A97CDC876B3336
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi Alan,

attached is my cleanup of pci-irq.c.
It works with all my mobos (piix, ali, via) and should fix the vaio
problem.

The main change is a code cleanup (do not scan first for a good irq,
and then discard the result and use what's currently installed in
the irq router, etc) and documentation.

Actual changes:
* if r->set exists, then always write our idea of the irq number
into the irq router, even if we use the bios supplied dev->irq number.
* ignore 'dev2->irq' mismatches - if they exist (e.g. Toms vaio),
then we must solve them by either using 'dev->irq' or 'dev2->irq'.
Just looking away means that one device won't work.
* bounds checking in pirq_via_set. I think I saw pirq=0x58 with my
ali board, I must check the docu if that can be right.

But I doubt that this solves your via sound problems.
via sound interrupts are handled with special code in via_quirks,
and that code is not pirq compatible. Do you have lspci -vxx /
dump_pirq output?

--
        Manfred
--------------7B3CDC07A9A97CDC876B3336
Content-Type: text/plain; charset=us-ascii;
 name="patch-pciirq-experimental"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="patch-pciirq-experimental"

--- 2.4/arch/i386/kernel/pci-irq.c      Sat Nov  3 19:51:08 2001
+++ build-2.4/arch/i386/kernel/pci-irq.c        Sun Nov  4 22:47:22 2001
@@ -197,13 +197,24 @@
  */
 static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
 {
-       return read_config_nybble(router, 0x55, pirq);
+       /* the internal devices (APCI, MC97, AC97, USB port 1 and 2
+        * are handled by quirk_via_acpi and quirk_via_irqpic
+        */
+       if (pirq < 6)
+               return read_config_nybble(router, 0x55, pirq);
+       return 0;
 }
 
 static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int 
irq)
 {
-       write_config_nybble(router, 0x55, pirq, irq);
-       return 1;
+       /* the internal devices (APCI, MC97, AC97, USB port 1 and 2
+        * are handled by quirk_via_acpi and quirk_via_irqpic
+        */
+       if (pirq < 6) {
+               write_config_nybble(router, 0x55, pirq, irq);
+               return 1;
+       }
+       return 0;
 }
 
 /*
@@ -536,8 +547,8 @@
 {
        u8 pin;
        struct irq_info *info;
-       int i, pirq, newirq;
-       int irq = 0;
+       int i, pirq;
+       int irq;
        u32 mask;
        struct irq_router *r = pirq_router;
        struct pci_dev *dev2;
@@ -570,48 +581,65 @@
        mask &= pcibios_irq_mask;
 
        /*
-        * Find the best IRQ to assign: use the one
-        * reported by the device if possible.
+        * Find the best IRQ to assign:
+        * 1) hardcoded into pirq 0xf?
+        * 2) dev->irq.
+        *      There are 2 sources for dev->irq:
+        *      a) stored by the bios into PCI_INTERRUPT_LINE
+        *      b) multiple devices share one pirq, then the loop
+        *         at the end of this function writes to dev->irq
+        * 3) stored by the bios into the irq router
+        * 4) only if assign is set: search for a low penalty irq
         */
-       newirq = dev->irq;
-       if (!newirq && assign) {
-               for (i = 0; i < 16; i++) {
-                       if (!(mask & (1 << i)))
-                               continue;
-                       if (pirq_penalty[i] < pirq_penalty[newirq] &&
-                           !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, 
"pci-test", dev)) {
-                               free_irq(i, dev);
-                               newirq = i;
-                       }
-               }
-       }
-       DBG(" -> newirq=%d", newirq);
-
-       /* Check if it is hardcoded */
        if ((pirq & 0xf0) == 0xf0) {
                irq = pirq & 0xf;
                DBG(" -> hardcoded IRQ %d\n", irq);
                msg = "Hardcoded";
+       } else if (dev->irq) {
+               irq = dev->irq;
+               DBG(" -> preselected IRQ %d\n", irq);
+               msg = "Preselected";
+               if (!(mask & (1<<irq)))
+                       printk(KERN_INFO "PCI: pirq table doesn't match preselected 
+IRQ for %s, using preselected irq.\n", dev->slot_name);
        } else if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) {
                DBG(" -> got IRQ %d\n", irq);
                msg = "Found";
-       } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) {
-               DBG(" -> assigning IRQ %d", newirq);
-               if (r->set(pirq_router_dev, dev, pirq, newirq)) {
-                       eisa_set_level_irq(newirq);
-                       DBG(" ... OK\n");
-                       msg = "Assigned";
-                       irq = newirq;
+               if (!(mask & (1<<irq)))
+                       printk(KERN_INFO "PCI: pirq table doesn't match IRQ router 
+setting for %s, using irq router setting.\n", dev->slot_name);
+       } else if (assign) {
+               for (i = 0; i < 16; i++) {
+                       if (!(mask & (1 << i)))
+                               continue;
+                       if (pirq_penalty[i] < pirq_penalty[irq] &&
+                           !request_irq(i, pcibios_test_irq_handler, SA_SHIRQ, 
+"pci-test", dev)) {
+                               free_irq(i, dev);
+                               irq = i;
+                       }
                }
-       }
+               DBG(" -> assigning irq=%d\n", irq);
+               msg = "Assigned";
+       } else
+               return 0;
+       if (!irq)
+               return 0;
 
-       if (!irq) {
-               DBG(" ... failed\n");
-               if (newirq && mask == (1 << newirq)) {
-                       msg = "Guessed";
-                       irq = newirq;
-               } else
-                       return 0;
+       if ((pirq & 0xf0) != 0xf0 && r->set && (dev->class >> 8) != 
+PCI_CLASS_DISPLAY_VGA) {
+               /* always rewrite our idea of the interrupt routing back into
+                * the irq router
+                */
+               if (r->set(pirq_router_dev, dev, pirq, irq)) {
+                       DBG("Set succeeded\n");
+                       eisa_set_level_irq(irq);
+               } else {
+                       DBG("Set failed\n");
+                       /* We ignore this error unless there is no way 
+                        * the irq routing could work without a successful
+                        * r->set().
+                        */
+                       if (!strcmp(msg, "Assigned") && mask != (1<<irq)) {
+                               return 0;
+                       }
+               }
        }
        printk(KERN_INFO "PCI: %s IRQ %d for device %s\n", msg, irq, dev->slot_name);
 
@@ -625,11 +653,13 @@
                if (!info)
                        continue;
                if (info->irq[pin].link == pirq) {
-                       /* We refuse to override the dev->irq information. Give a 
warning! */
+                       /* Give a warning if we have to overwrite dev->irq information.
+                        * This only happens when multiple devices share one pirq, and
+                        * the bios claims that it routes them to different irq 
+numbers.
+                        */
                        if (dev2->irq && dev2->irq != irq) {
                                printk(KERN_INFO "IRQ routing conflict for %s, have 
irq %d, want irq %d\n",
                                       dev2->slot_name, dev2->irq, irq);
-                               continue;
                        }
                        dev2->irq = irq;
                        pirq_penalty[irq]++;

--------------7B3CDC07A9A97CDC876B3336--



_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to