debuggers.hg

annotate xen/drivers/pci/setup-res.c @ 3658:0ef6e8e6e85d

bitkeeper revision 1.1159.212.71 (4200f0afX_JumfbEHQex6TdFENULMQ)

Merge labyrinth.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into labyrinth.cl.cam.ac.uk:/auto/groups/xeno/users/iap10/xeno-clone/xen-unstable.bk
author iap10@labyrinth.cl.cam.ac.uk
date Wed Feb 02 15:24:31 2005 +0000 (2005-02-02)
parents dae98734f12e beb0887c54bc
children bbe8541361dd
rev   line source
iap10@274 1 /*
iap10@274 2 * drivers/pci/setup-res.c
iap10@274 3 *
iap10@274 4 * Extruded from code written by
iap10@274 5 * Dave Rusling (david.rusling@reo.mts.dec.com)
iap10@274 6 * David Mosberger (davidm@cs.arizona.edu)
iap10@274 7 * David Miller (davem@redhat.com)
iap10@274 8 *
iap10@274 9 * Support routines for initializing a PCI subsystem.
iap10@274 10 */
iap10@274 11
iap10@274 12 /* fixed for multiple pci buses, 1999 Andrea Arcangeli <andrea@suse.de> */
iap10@274 13
iap10@274 14 /*
iap10@274 15 * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
iap10@274 16 * Resource sorting
iap10@274 17 */
iap10@274 18
kaf24@1248 19 #include <xen/init.h>
kaf24@1248 20 #include <xen/lib.h>
kaf24@1248 21 #include <xen/pci.h>
kaf24@1248 22 #include <xen/errno.h>
kaf24@1248 23 #include <xen/ioport.h>
kaf24@1248 24 #include <xen/cache.h>
kaf24@1248 25 #include <xen/slab.h>
iap10@274 26
iap10@274 27
iap10@274 28 #define DEBUG_CONFIG 0
iap10@274 29 #if DEBUG_CONFIG
iap10@274 30 # define DBGC(args) printk args
iap10@274 31 #else
iap10@274 32 # define DBGC(args)
iap10@274 33 #endif
iap10@274 34
iap10@274 35
iap10@274 36 int __init
iap10@274 37 pci_claim_resource(struct pci_dev *dev, int resource)
iap10@274 38 {
iap10@274 39 struct resource *res = &dev->resource[resource];
iap10@274 40 struct resource *root = pci_find_parent_resource(dev, res);
iap10@274 41 int err;
iap10@274 42
iap10@274 43 err = -EINVAL;
iap10@274 44 if (root != NULL) {
iap10@274 45 err = request_resource(root, res);
iap10@274 46 if (err) {
iap10@274 47 printk(KERN_ERR "PCI: Address space collision on "
iap10@274 48 "region %d of device %s [%lx:%lx]\n",
iap10@274 49 resource, dev->name, res->start, res->end);
iap10@274 50 }
iap10@274 51 } else {
iap10@274 52 printk(KERN_ERR "PCI: No parent found for region %d "
iap10@274 53 "of device %s\n", resource, dev->name);
iap10@274 54 }
iap10@274 55
iap10@274 56 return err;
iap10@274 57 }
iap10@274 58
iap10@274 59 /*
iap10@274 60 * Given the PCI bus a device resides on, try to
iap10@274 61 * find an acceptable resource allocation for a
iap10@274 62 * specific device resource..
iap10@274 63 */
iap10@274 64 static int pci_assign_bus_resource(const struct pci_bus *bus,
iap10@274 65 struct pci_dev *dev,
iap10@274 66 struct resource *res,
iap10@274 67 unsigned long size,
iap10@274 68 unsigned long min,
iap10@274 69 unsigned int type_mask,
iap10@274 70 int resno)
iap10@274 71 {
iap10@274 72 unsigned long align;
iap10@274 73 int i;
iap10@274 74
iap10@274 75 type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
iap10@274 76 for (i = 0 ; i < 4; i++) {
iap10@274 77 struct resource *r = bus->resource[i];
iap10@274 78 if (!r)
iap10@274 79 continue;
iap10@274 80
iap10@274 81 /* type_mask must match */
iap10@274 82 if ((res->flags ^ r->flags) & type_mask)
iap10@274 83 continue;
iap10@274 84
iap10@274 85 /* We cannot allocate a non-prefetching resource
iap10@274 86 from a pre-fetching area */
iap10@274 87 if ((r->flags & IORESOURCE_PREFETCH) &&
iap10@274 88 !(res->flags & IORESOURCE_PREFETCH))
iap10@274 89 continue;
iap10@274 90
iap10@274 91 /* The bridge resources are special, as their
iap10@274 92 size != alignment. Sizing routines return
iap10@274 93 required alignment in the "start" field. */
iap10@274 94 align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start;
iap10@274 95
iap10@274 96 /* Ok, try it out.. */
iap10@274 97 if (allocate_resource(r, res, size, min, -1, align,
iap10@274 98 pcibios_align_resource, dev) < 0)
iap10@274 99 continue;
iap10@274 100
iap10@274 101 /* Update PCI config space. */
iap10@274 102 pcibios_update_resource(dev, r, res, resno);
iap10@274 103 return 0;
iap10@274 104 }
iap10@274 105 return -EBUSY;
iap10@274 106 }
iap10@274 107
iap10@274 108 int
iap10@274 109 pci_assign_resource(struct pci_dev *dev, int i)
iap10@274 110 {
iap10@274 111 const struct pci_bus *bus = dev->bus;
iap10@274 112 struct resource *res = dev->resource + i;
iap10@274 113 unsigned long size, min;
iap10@274 114
iap10@274 115 size = res->end - res->start + 1;
iap10@274 116 min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
iap10@274 117
iap10@274 118 /* First, try exact prefetching match.. */
iap10@274 119 if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) {
iap10@274 120 /*
iap10@274 121 * That failed.
iap10@274 122 *
iap10@274 123 * But a prefetching area can handle a non-prefetching
iap10@274 124 * window (it will just not perform as well).
iap10@274 125 */
iap10@274 126 if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
iap10@274 127 printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
iap10@274 128 i, res->start, res->end, dev->slot_name);
iap10@274 129 return -EBUSY;
iap10@274 130 }
iap10@274 131 }
iap10@274 132
iap10@274 133 DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", res->start,
iap10@274 134 res->end, i, dev->name));
iap10@274 135
iap10@274 136 return 0;
iap10@274 137 }
iap10@274 138
iap10@274 139 /* Sort resources by alignment */
iap10@274 140 void __init
iap10@274 141 pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
iap10@274 142 {
iap10@274 143 int i;
iap10@274 144
iap10@274 145 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
iap10@274 146 struct resource *r;
iap10@274 147 struct resource_list *list, *tmp;
iap10@274 148 unsigned long r_align;
iap10@274 149
iap10@274 150 r = &dev->resource[i];
iap10@274 151 r_align = r->end - r->start;
iap10@274 152
iap10@274 153 if (!(r->flags) || r->parent)
iap10@274 154 continue;
iap10@274 155 if (!r_align) {
iap10@274 156 printk(KERN_WARNING "PCI: Ignore bogus resource %d "
iap10@274 157 "[%lx:%lx] of %s\n",
iap10@274 158 i, r->start, r->end, dev->name);
iap10@274 159 continue;
iap10@274 160 }
iap10@274 161 r_align = (i < PCI_BRIDGE_RESOURCES) ? r_align + 1 : r->start;
iap10@274 162 for (list = head; ; list = list->next) {
iap10@274 163 unsigned long align = 0;
iap10@274 164 struct resource_list *ln = list->next;
iap10@274 165 int idx;
iap10@274 166
iap10@274 167 if (ln) {
iap10@274 168 idx = ln->res - &ln->dev->resource[0];
iap10@274 169 align = (idx < PCI_BRIDGE_RESOURCES) ?
iap10@274 170 ln->res->end - ln->res->start + 1 :
iap10@274 171 ln->res->start;
iap10@274 172 }
iap10@274 173 if (r_align > align) {
iap10@3650 174 tmp = xmalloc(struct resource_list);
iap10@274 175 if (!tmp)
iap10@274 176 panic("pdev_sort_resources(): "
iap10@3650 177 "malloc() failed!\n");
iap10@274 178 tmp->next = ln;
iap10@274 179 tmp->res = r;
iap10@274 180 tmp->dev = dev;
iap10@274 181 list->next = tmp;
iap10@274 182 break;
iap10@274 183 }
iap10@274 184 }
iap10@274 185 }
iap10@274 186 }
iap10@274 187
iap10@274 188 void __init
iap10@274 189 pdev_enable_device(struct pci_dev *dev)
iap10@274 190 {
iap10@274 191 u32 reg;
iap10@274 192 u16 cmd;
iap10@274 193 int i;
iap10@274 194
iap10@274 195 DBGC((KERN_ERR "PCI enable device: (%s)\n", dev->name));
iap10@274 196
iap10@274 197 pci_read_config_word(dev, PCI_COMMAND, &cmd);
iap10@274 198
iap10@274 199 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
iap10@274 200 struct resource *res = &dev->resource[i];
iap10@274 201
iap10@274 202 if (res->flags & IORESOURCE_IO)
iap10@274 203 cmd |= PCI_COMMAND_IO;
iap10@274 204 else if (res->flags & IORESOURCE_MEM)
iap10@274 205 cmd |= PCI_COMMAND_MEMORY;
iap10@274 206 }
iap10@274 207
iap10@274 208 /* Special case, disable the ROM. Several devices act funny
iap10@274 209 (ie. do not respond to memory space writes) when it is left
iap10@274 210 enabled. A good example are QlogicISP adapters. */
iap10@274 211
iap10@274 212 if (dev->rom_base_reg) {
iap10@274 213 pci_read_config_dword(dev, dev->rom_base_reg, &reg);
iap10@274 214 reg &= ~PCI_ROM_ADDRESS_ENABLE;
iap10@274 215 pci_write_config_dword(dev, dev->rom_base_reg, reg);
iap10@274 216 dev->resource[PCI_ROM_RESOURCE].flags &= ~PCI_ROM_ADDRESS_ENABLE;
iap10@274 217 }
iap10@274 218
iap10@274 219 /* All of these (may) have I/O scattered all around and may not
iap10@274 220 use I/O base address registers at all. So we just have to
iap10@274 221 always enable IO to these devices. */
iap10@274 222 if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED
iap10@274 223 || (dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA
iap10@274 224 || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE
iap10@274 225 || (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
iap10@274 226 cmd |= PCI_COMMAND_IO;
iap10@274 227 }
iap10@274 228
iap10@274 229 /* ??? Always turn on bus mastering. If the device doesn't support
iap10@274 230 it, the bit will go into the bucket. */
iap10@274 231 cmd |= PCI_COMMAND_MASTER;
iap10@274 232
iap10@274 233 /* Set the cache line and default latency (32). */
iap10@274 234 pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
iap10@274 235 (32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
iap10@274 236
iap10@274 237 /* Enable the appropriate bits in the PCI command register. */
iap10@274 238 pci_write_config_word(dev, PCI_COMMAND, cmd);
iap10@274 239
iap10@274 240 DBGC((KERN_ERR " cmd reg 0x%x\n", cmd));
iap10@274 241 }