11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	linux/arch/alpha/kernel/pci.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Extruded from code written by
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Dave Rusling (david.rusling@reo.mts.dec.com)
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	David Mosberger (davidm@cs.arizona.edu)
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2.3.x PCI/resources, 1999 Andrea Arcangeli <andrea@suse.de> */
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	     PCI-PCI bridges cleanup
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/cache.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/machvec.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "proto.h"
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "pci_impl.h"
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Some string constants used by the various core logics.
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char *const pci_io_names[] = {
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  "PCI IO bus 0", "PCI IO bus 1", "PCI IO bus 2", "PCI IO bus 3",
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  "PCI IO bus 4", "PCI IO bus 5", "PCI IO bus 6", "PCI IO bus 7"
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char *const pci_mem_names[] = {
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  "PCI mem bus 0", "PCI mem bus 1", "PCI mem bus 2", "PCI mem bus 3",
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  "PCI mem bus 4", "PCI mem bus 5", "PCI mem bus 6", "PCI mem bus 7"
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsconst char pci_hae0_name[] = "HAE0";
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
47151d16d531c5bc60bad9dc62102be18f11b4280aBjorn Helgaas * If PCI_PROBE_ONLY in pci_flags is set, we don't change any PCI resource
48151d16d531c5bc60bad9dc62102be18f11b4280aBjorn Helgaas * assignments.
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The PCI controller list.
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_controller *hose_head, **hose_tail = &hose_head;
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_controller *pci_isa_hose;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Quirks.
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsquirk_isa_bridge(struct pci_dev *dev)
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->class = PCI_CLASS_BRIDGE_ISA << 8;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsquirk_cypress(struct pci_dev *dev)
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
72a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky	/* The Notorious Cy82C693 chip.  */
73a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky
74a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky	/* The generic legacy mode IDE fixup in drivers/pci/probe.c
75a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky	   doesn't work correctly with the Cypress IDE controller as
76a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky	   it has non-standard register layout.  Fix that.  */
77a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky	if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
78a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky		dev->resource[2].start = dev->resource[3].start = 0;
79a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky		dev->resource[2].end = dev->resource[3].end = 0;
80a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky		dev->resource[2].flags = dev->resource[3].flags = 0;
81a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky		if (PCI_FUNC(dev->devfn) == 2) {
82a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky			dev->resource[0].start = 0x170;
83a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky			dev->resource[0].end = 0x177;
84a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky			dev->resource[1].start = 0x376;
85a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky			dev->resource[1].end = 0x376;
86a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky		}
87a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky	}
88a744e0160ac5804b763449aa34d3991dc21af0beIvan Kokshaysky
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The Cypress bridge responds on the PCI bus in the address range
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   0xffff0000-0xffffffff (conventional x86 BIOS ROM).  There is no
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   way to turn this off.  The bridge also supports several extended
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   BIOS ranges (disabled after power-up), and some consoles do turn
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   them on.  So if we use a large direct-map window, or a large SG
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   window, we must avoid the entire 0xfff00000-0xffffffff region.  */
9572cff12397cd6648b8b5abfaeb00502f45b76cb8Ivan Kokshaysky	if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA) {
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (__direct_map_base + __direct_map_size >= 0xfff00000UL)
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			__direct_map_size = 0xfff00000UL - __direct_map_base;
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct pci_controller *hose = dev->sysdata;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct pci_iommu_arena *pci = hose->sg_pci;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (pci && pci->dma_base + pci->size >= 0xfff00000UL)
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				pci->size = 0xfff00000UL - pci->dma_base;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Called for each device after PCI setup is done. */
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_fixup_final(struct pci_dev *dev)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int class = dev->class >> 8;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (class == PCI_CLASS_BRIDGE_ISA || class == PCI_CLASS_BRIDGE_EISA) {
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->dma_mask = MAX_ISA_DMA_ADDRESS - 1;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		isa_bridge = dev;
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Just declaring that the power-of-ten prefixes are actually the
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   power-of-two ones doesn't make it true :) */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define KB			1024
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MB			(1024*KB)
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GB			(1024*MB)
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
127b26b2d494b659f988b4d75eb394dfa0ddac415c9Dominik Brodowskiresource_size_t
1283b7a17fcdae532d29dffab9d564a28be08960988Dominik Brodowskipcibios_align_resource(void *data, const struct resource *res,
129e31dd6e4520439ceae4753f32dd2da2c345e929aGreg Kroah-Hartman		       resource_size_t size, resource_size_t align)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev = data;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_controller *hose = dev->sysdata;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long alignto;
134e31dd6e4520439ceae4753f32dd2da2c345e929aGreg Kroah-Hartman	resource_size_t start = res->start;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (res->flags & IORESOURCE_IO) {
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Make sure we start at our min on all hoses */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start - hose->io_space->start < PCIBIOS_MIN_IO)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start = PCIBIOS_MIN_IO + hose->io_space->start;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Put everything into 0x00-0xff region modulo 0x400
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start & 0x300)
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start = (start + 0x3ff) & ~0x3ff;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if	(res->flags & IORESOURCE_MEM) {
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Make sure we start at our min on all hoses */
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (start - hose->mem_space->start < PCIBIOS_MIN_MEM)
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			start = PCIBIOS_MIN_MEM + hose->mem_space->start;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * The following holds at least for the Low Cost
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Alpha implementation of the PCI interface:
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * In sparse memory address space, the first
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * octant (16MB) of every 128MB segment is
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * aliased to the very first 16 MB of the
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * address space (i.e., it aliases the ISA
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * memory address space).  Thus, we try to
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * avoid allocating PCI devices in that range.
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Can be allocated in 2nd-7th octant only.
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Devices that need more than 112MB of
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * address space must be accessed through
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * dense memory space only!
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Align to multiple of size of minimum base.  */
1695f0e3da6e186598bbd2569410ab60fa645ba00c9Randy Dunlap		alignto = max_t(resource_size_t, 0x1000, align);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		start = ALIGN(start, alignto);
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (hose->sparse_mem_base && size <= 7 * 16*MB) {
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (((start / (16*MB)) & 0x7) == 0) {
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start &= ~(128*MB - 1);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start += 16*MB;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start  = ALIGN(start, alignto);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (start/(128*MB) != (start + size - 1)/(128*MB)) {
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start &= ~(128*MB - 1);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start += (128 + 16)*MB;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				start  = ALIGN(start, alignto);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
185b26b2d494b659f988b4d75eb394dfa0ddac415c9Dominik Brodowski	return start;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef KB
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef MB
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef GB
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_init(void)
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (alpha_mv.init_pci)
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		alpha_mv.init_pci();
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssubsys_initcall(pcibios_init);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201ed5f6561436a1a0b38f4130bdb1fed00f14e60b5Al Virochar * __devinit
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_setup(char *str)
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return str;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ALPHA_RESTORE_SRM_SETUP
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pdev_srm_saved_conf *srm_saved_configs;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
210ed5f6561436a1a0b38f4130bdb1fed00f14e60b5Al Virovoid __devinit
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspdev_save_srm_config(struct pci_dev *dev)
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pdev_srm_saved_conf *tmp;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static int printed = 0;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
216151d16d531c5bc60bad9dc62102be18f11b4280aBjorn Helgaas	if (!alpha_using_srm || pci_has_flag(PCI_PROBE_ONLY))
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!printed) {
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_INFO "pci: enabling save/restore of SRM state\n");
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printed = 1;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!tmp) {
226bbb8d343affd21850849fa4d41bf91c7527a3d04Harvey Harrison		printk(KERN_ERR "%s: kmalloc() failed!\n", __func__);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp->next = srm_saved_configs;
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tmp->dev = dev;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_save_state(dev);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	srm_saved_configs = tmp;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspci_restore_srm_config(void)
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pdev_srm_saved_conf *tmp;
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* No need to restore if probed only. */
243151d16d531c5bc60bad9dc62102be18f11b4280aBjorn Helgaas	if (pci_has_flag(PCI_PROBE_ONLY))
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Restore SRM config. */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (tmp = srm_saved_configs; tmp; tmp = tmp->next) {
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_restore_state(tmp->dev);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
253ed5f6561436a1a0b38f4130bdb1fed00f14e60b5Al Virovoid __devinit
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_fixup_bus(struct pci_bus *bus)
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev = bus->self;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
258151d16d531c5bc60bad9dc62102be18f11b4280aBjorn Helgaas	if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		pci_read_bridge_bases(bus);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(dev, &bus->devices, bus_list) {
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pdev_save_srm_config(dev);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_update_irq(struct pci_dev *dev, int irq)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_enable_device(struct pci_dev *dev, int mask)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27710f000a2fd805e8ccfe988e8615545467bb7f7dfBjorn Helgaas	return pci_enable_resources(dev, mask);
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  If we set up a device for bus mastering, we need to check the latency
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  timer as certain firmware forgets to set it properly, as seen
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  on SX164 and LX164 with SRM.
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_set_master(struct pci_dev *dev)
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 lat;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lat >= 16) return;
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk("PCI: Setting latency timer of device %s to 64\n",
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							pci_name(dev));
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29672cff12397cd6648b8b5abfaeb00502f45b76cb8Ivan Kokshayskyvoid __init
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_claim_one_bus(struct pci_bus *b)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *child_bus;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(dev, &b->devices, bus_list) {
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct resource *r = &dev->resource[i];
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (r->parent || !r->start || !r->flags)
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				continue;
310151d16d531c5bc60bad9dc62102be18f11b4280aBjorn Helgaas			if (pci_has_flag(PCI_PROBE_ONLY) ||
311151d16d531c5bc60bad9dc62102be18f11b4280aBjorn Helgaas			    (r->flags & IORESOURCE_PCI_FIXED))
31272cff12397cd6648b8b5abfaeb00502f45b76cb8Ivan Kokshaysky				pci_claim_resource(dev, i);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(child_bus, &b->children, node)
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pcibios_claim_one_bus(child_bus);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldspcibios_claim_console_setup(void)
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *b;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	list_for_each_entry(b, &pci_root_buses, node)
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pcibios_claim_one_bus(b);
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscommon_init_pci(void)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_controller *hose;
333a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas	struct list_head resources;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_bus *bus;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int next_busno;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int need_domain_info = 0;
337a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas	u32 pci_mem_end;
338a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas	u32 sg_base;
339a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas	unsigned long end;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Scan all of the recorded PCI controllers.  */
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
343a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		sg_base = hose->sg_pci ? hose->sg_pci->dma_base : ~0;
344a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas
345a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		/* Adjust hose mem_space limit to prevent PCI allocations
346a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		   in the iommu windows. */
347a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		pci_mem_end = min((u32)__direct_map_base, sg_base) - 1;
348a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		end = hose->mem_space->start + pci_mem_end;
349a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		if (hose->mem_space->end > end)
350a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas			hose->mem_space->end = end;
351a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas
352a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		INIT_LIST_HEAD(&resources);
353c04d9e35790013606f18cf56db07f80c3a339608Bjorn Helgaas		pci_add_resource_offset(&resources, hose->io_space,
354c04d9e35790013606f18cf56db07f80c3a339608Bjorn Helgaas					hose->io_space->start);
355c04d9e35790013606f18cf56db07f80c3a339608Bjorn Helgaas		pci_add_resource_offset(&resources, hose->mem_space,
356c04d9e35790013606f18cf56db07f80c3a339608Bjorn Helgaas					hose->mem_space->start);
357a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas
358a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas		bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops,
359a2f33da11ab9efba25d41e959de6338a9078fb36Bjorn Helgaas					hose, &resources);
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hose->bus = bus;
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hose->need_domain_info = need_domain_info;
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		next_busno = bus->subordinate + 1;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Don't allow 8-bit bus number overflow inside the hose -
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   reserve some space for bridges. */
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (next_busno > 224) {
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			next_busno = 0;
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			need_domain_info = 1;
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37172cff12397cd6648b8b5abfaeb00502f45b76cb8Ivan Kokshaysky	pcibios_claim_console_setup();
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_assign_unassigned_resources();
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct pci_controller * __init
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsalloc_pci_controller(void)
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_controller *hose;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hose = alloc_bootmem(sizeof(*hose));
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*hose_tail = hose;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	hose_tail = &hose->next;
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return hose;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct resource * __init
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsalloc_resource(void)
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct resource *res;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	res = alloc_bootmem(sizeof(*res));
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return res;
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Provide information on locations of various I/O regions in physical
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   memory.  Do this on a per-card basis so that we choose the right hose.  */
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage long
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_controller *hose;
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *dev;
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* from hose or from bus.devfn */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (which & IOBASE_FROM_HOSE) {
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for(hose = hose_head; hose; hose = hose->next)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (hose->index == bus) break;
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!hose) return -ENODEV;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Special hook for ISA access.  */
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (bus == 0 && dfn == 0) {
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			hose = pci_isa_hose;
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
421074cec54d1049ab580ecd0026623b553e0e270c4Alan Cox			dev = pci_get_bus_and_slot(bus, dfn);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!dev)
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -ENODEV;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			hose = dev->sysdata;
425074cec54d1049ab580ecd0026623b553e0e270c4Alan Cox			pci_dev_put(dev);
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (which & ~IOBASE_FROM_HOSE) {
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IOBASE_HOSE:
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return hose->index;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IOBASE_SPARSE_MEM:
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return hose->sparse_mem_base;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IOBASE_DENSE_MEM:
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return hose->dense_mem_base;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IOBASE_SPARSE_IO:
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return hose->sparse_io_base;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IOBASE_DENSE_IO:
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return hose->dense_io_base;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case IOBASE_ROOT_BUS:
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return hose->bus->number;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -EOPNOTSUPP;
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
447f2971c4c3197935f409bff202b9ab67416981dd7Michael S. Tsirkin/* Destroy an __iomem token.  Not copied from lib/iomap.c.  */
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid pci_iounmap(struct pci_dev *dev, void __iomem * addr)
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (__is_mmio(addr))
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iounmap(addr);
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(pci_iounmap);
4568255cf35d503db7c1b26ae53b6b7f23ada82316fAdrian Bunk
4578255cf35d503db7c1b26ae53b6b7f23ada82316fAdrian Bunk/* FIXME: Some boxes have multiple ISA bridges! */
4588255cf35d503db7c1b26ae53b6b7f23ada82316fAdrian Bunkstruct pci_dev *isa_bridge;
4598255cf35d503db7c1b26ae53b6b7f23ada82316fAdrian BunkEXPORT_SYMBOL(isa_bridge);
460