fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / pci / setup-bus.c
index 7f0f6c2..89f3036 100644 (file)
@@ -29,9 +29,9 @@
 
 #define DEBUG_CONFIG 1
 #if DEBUG_CONFIG
-# define DBGC(args)     printk args
+#define DBG(x...)     printk(x)
 #else
-# define DBGC(args)
+#define DBG(x...)
 #endif
 
 #define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
@@ -40,8 +40,8 @@
  * FIXME: IO should be max 256 bytes.  However, since we may
  * have a P2P bridge below a cardbus bridge, we need 4K.
  */
-#define CARDBUS_IO_SIZE                (4096)
-#define CARDBUS_MEM_SIZE       (32*1024*1024)
+#define CARDBUS_IO_SIZE                (256)
+#define CARDBUS_MEM_SIZE       (64*1024*1024)
 
 static void __devinit
 pbus_assign_resources_sorted(struct pci_bus *bus)
@@ -51,15 +51,22 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
        struct resource_list head, *list, *tmp;
        int idx;
 
-       bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA;
-
        head.next = NULL;
        list_for_each_entry(dev, &bus->devices, bus_list) {
                u16 class = dev->class >> 8;
 
-               if (class == PCI_CLASS_DISPLAY_VGA
-                               || class == PCI_CLASS_NOT_DEFINED_VGA)
-                       bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
+               /* Don't touch classless devices or host bridges or ioapics.  */
+               if (class == PCI_CLASS_NOT_DEFINED ||
+                   class == PCI_CLASS_BRIDGE_HOST)
+                       continue;
+
+               /* Don't touch ioapic devices already enabled by firmware */
+               if (class == PCI_CLASS_SYSTEM_PIC) {
+                       u16 command;
+                       pci_read_config_word(dev, PCI_COMMAND, &command);
+                       if (command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
+                               continue;
+               }
 
                pdev_sort_resources(dev, &head);
        }
@@ -67,15 +74,18 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
        for (list = head.next; list;) {
                res = list->res;
                idx = res - &list->dev->resource[0];
-               pci_assign_resource(list->dev, idx);
+               if (pci_assign_resource(list->dev, idx)) {
+                       res->start = 0;
+                       res->end = 0;
+                       res->flags = 0;
+               }
                tmp = list;
                list = list->next;
                kfree(tmp);
        }
 }
 
-static void __devinit
-pci_setup_cardbus(struct pci_bus *bus)
+void pci_setup_cardbus(struct pci_bus *bus)
 {
        struct pci_dev *bridge = bus->self;
        struct pci_bus_region region;
@@ -127,6 +137,7 @@ pci_setup_cardbus(struct pci_bus *bus)
                                        region.end);
        }
 }
+EXPORT_SYMBOL(pci_setup_cardbus);
 
 /* Initialize bridges with base/limit values we have collected.
    PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
@@ -146,8 +157,7 @@ pci_setup_bridge(struct pci_bus *bus)
        struct pci_bus_region region;
        u32 l, io_upper16;
 
-       DBGC((KERN_INFO "PCI: Bus %d, bridge: %s\n",
-                       bus->number, pci_name(bridge)));
+       DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge));
 
        /* Set up the top and bottom of the PCI I/O segment for this bus. */
        pcibios_resource_to_bus(bridge, &region, bus->resource[0]);
@@ -158,14 +168,14 @@ pci_setup_bridge(struct pci_bus *bus)
                l |= region.end & 0xf000;
                /* Set up upper 16 bits of I/O base/limit. */
                io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
-               DBGC((KERN_INFO "  IO window: %04lx-%04lx\n",
-                               region.start, region.end));
+               DBG(KERN_INFO "  IO window: %04lx-%04lx\n",
+                               region.start, region.end);
        }
        else {
                /* Clear upper 16 bits of I/O base/limit. */
                io_upper16 = 0;
                l = 0x00f0;
-               DBGC((KERN_INFO "  IO window: disabled.\n"));
+               DBG(KERN_INFO "  IO window: disabled.\n");
        }
        /* Temporarily disable the I/O range before updating PCI_IO_BASE. */
        pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
@@ -180,12 +190,12 @@ pci_setup_bridge(struct pci_bus *bus)
        if (bus->resource[1]->flags & IORESOURCE_MEM) {
                l = (region.start >> 16) & 0xfff0;
                l |= region.end & 0xfff00000;
-               DBGC((KERN_INFO "  MEM window: %08lx-%08lx\n",
-                               region.start, region.end));
+               DBG(KERN_INFO "  MEM window: %08lx-%08lx\n",
+                               region.start, region.end);
        }
        else {
                l = 0x0000fff0;
-               DBGC((KERN_INFO "  MEM window: disabled.\n"));
+               DBG(KERN_INFO "  MEM window: disabled.\n");
        }
        pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
 
@@ -199,12 +209,12 @@ pci_setup_bridge(struct pci_bus *bus)
        if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
                l = (region.start >> 16) & 0xfff0;
                l |= region.end & 0xfff00000;
-               DBGC((KERN_INFO "  PREFETCH window: %08lx-%08lx\n",
-                               region.start, region.end));
+               DBG(KERN_INFO "  PREFETCH window: %08lx-%08lx\n",
+                               region.start, region.end);
        }
        else {
                l = 0x0000fff0;
-               DBGC((KERN_INFO "  PREFETCH window: disabled.\n"));
+               DBG(KERN_INFO "  PREFETCH window: disabled.\n");
        }
        pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
 
@@ -266,6 +276,8 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type)
 
        for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
                r = bus->resource[i];
+               if (r == &ioport_resource || r == &iomem_resource)
+                       continue;
                if (r && (r->flags & type_mask) == type && !r->parent)
                        return r;
        }
@@ -352,8 +364,10 @@ pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
                        order = __ffs(align) - 20;
                        if (order > 11) {
                                printk(KERN_WARNING "PCI: region %s/%d "
-                                      "too large: %lx-%lx\n",
-                                      pci_name(dev), i, r->start, r->end);
+                                      "too large: %llx-%llx\n",
+                                       pci_name(dev), i,
+                                       (unsigned long long)r->start,
+                                       (unsigned long long)r->end);
                                r->flags = 0;
                                continue;
                        }
@@ -499,12 +513,6 @@ pci_bus_assign_resources(struct pci_bus *bus)
 
        pbus_assign_resources_sorted(bus);
 
-       if (bus->bridge_ctl & PCI_BRIDGE_CTL_VGA) {
-               /* Propagate presence of the VGA to upstream bridges */
-               for (b = bus; b->parent; b = b->parent) {
-                       b->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
-               }
-       }
        list_for_each_entry(dev, &bus->devices, bus_list) {
                b = dev->subordinate;
                if (!b)
@@ -533,15 +541,16 @@ EXPORT_SYMBOL(pci_bus_assign_resources);
 void __init
 pci_assign_unassigned_resources(void)
 {
-       struct list_head *ln;
+       struct pci_bus *bus;
 
        /* Depth first, calculate sizes and alignments of all
           subordinate buses. */
-       for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
-               pci_bus_size_bridges(pci_bus_b(ln));
+       list_for_each_entry(bus, &pci_root_buses, node) {
+               pci_bus_size_bridges(bus);
+       }
        /* Depth last, allocate resources and update the hardware. */
-       for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) {
-               pci_bus_assign_resources(pci_bus_b(ln));
-               pci_enable_bridges(pci_bus_b(ln));
+       list_for_each_entry(bus, &pci_root_buses, node) {
+               pci_bus_assign_resources(bus);
+               pci_enable_bridges(bus);
        }
 }