ia64/xen-unstable

view linux-2.4.27-xen-sparse/arch/xen/kernel/pci-pc.c @ 2621:9402048e2325

bitkeeper revision 1.1159.1.218 (416a8128OiHXHyk_Sy8FsA0YUQcEnA)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xeno.bk-26dom0
into freefall.cl.cam.ac.uk:/local/scratch/cl349/xeno.bk-26dom0
author cl349@freefall.cl.cam.ac.uk
date Mon Oct 11 12:48:40 2004 +0000 (2004-10-11)
parents 869c20f2977b
children b914ff7d73b5 3f929065a1d1
line source
1 /*
2 * Low-Level PCI Support for PC
3 *
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
5 *
6 * Adjusted to use Xen's interface by Rolf Neugebauer, Intel Research Cambridge
7 * Further modifications by Keir Fraser, University of Cambridge
8 */
10 #include <linux/config.h>
11 #include <linux/types.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/pci.h>
15 #include <linux/init.h>
16 #include <linux/ioport.h>
18 #include <asm/segment.h>
19 #include <asm/io.h>
21 #include <asm/hypervisor-ifs/hypervisor-if.h>
22 #include <asm/hypervisor-ifs/physdev.h>
24 #include "pci-i386.h"
26 /*
27 * NB. The following interface functions are not included here:
28 * 1. void eisa_set_level_irq(unsigned int irq)
29 * 2. irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
30 * 3. int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
31 * All are used by the ACPI driver. This should be ported to Xen if it is
32 * ever required -- Xen is the ultimate source for IRQ-routing knowledge.
33 */
35 struct pci_ops *pci_root_ops = NULL;
37 int (*pci_config_read)(int seg, int bus, int dev, int fn,
38 int reg, int len, u32 *value) = NULL;
39 int (*pci_config_write)(int seg, int bus, int dev, int fn,
40 int reg, int len, u32 value) = NULL;
42 unsigned int pci_probe = PCI_PROBE_BIOS;
44 struct pci_fixup pcibios_fixups[] = { { 0 } };
46 static int pci_confx_read(int seg, int bus, int dev, int fn, int reg,
47 int len, u32 *value)
48 {
49 int ret;
50 physdev_op_t op;
52 if (bus > 255 || dev > 31 || fn > 7 || reg > 255)
53 return -EINVAL;
55 op.cmd = PHYSDEVOP_PCI_CFGREG_READ;
56 op.u.pci_cfgreg_read.bus = bus;
57 op.u.pci_cfgreg_read.dev = dev;
58 op.u.pci_cfgreg_read.func = fn;
59 op.u.pci_cfgreg_read.reg = reg;
60 op.u.pci_cfgreg_read.len = len;
62 if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
63 return ret;
65 *value = op.u.pci_cfgreg_read.value;
67 return 0;
68 }
70 static int pci_confx_write(int seg, int bus, int dev, int fn, int reg,
71 int len, u32 value)
72 {
73 int ret;
74 physdev_op_t op;
76 if ((bus > 255 || dev > 31 || fn > 7 || reg > 255))
77 return -EINVAL;
79 op.cmd = PHYSDEVOP_PCI_CFGREG_WRITE;
80 op.u.pci_cfgreg_write.bus = bus;
81 op.u.pci_cfgreg_write.dev = dev;
82 op.u.pci_cfgreg_write.func = fn;
83 op.u.pci_cfgreg_write.reg = reg;
84 op.u.pci_cfgreg_write.len = len;
85 op.u.pci_cfgreg_write.value = value;
87 if ( (ret = HYPERVISOR_physdev_op(&op)) != 0 )
88 return ret;
89 return 0;
90 }
93 static int pci_confx_read_config_byte(struct pci_dev *dev,
94 int where, u8 *value)
95 {
96 int result;
97 u32 data;
99 result = pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
100 PCI_FUNC(dev->devfn), where, 1, &data);
102 *value = (u8)data;
104 return result;
105 }
107 static int pci_confx_read_config_word(struct pci_dev *dev,
108 int where, u16 *value)
109 {
110 int result;
111 u32 data;
113 result = pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
114 PCI_FUNC(dev->devfn), where, 2, &data);
116 *value = (u16)data;
118 return result;
119 }
121 static int pci_confx_read_config_dword(struct pci_dev *dev,
122 int where, u32 *value)
123 {
124 return pci_confx_read(0, dev->bus->number, PCI_SLOT(dev->devfn),
125 PCI_FUNC(dev->devfn), where, 4, value);
126 }
128 static int pci_confx_write_config_byte(struct pci_dev *dev,
129 int where, u8 value)
130 {
131 return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
132 PCI_FUNC(dev->devfn), where, 1, value);
133 }
135 static int pci_confx_write_config_word(struct pci_dev *dev,
136 int where, u16 value)
137 {
138 return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
139 PCI_FUNC(dev->devfn), where, 2, value);
140 }
142 static int pci_confx_write_config_dword(struct pci_dev *dev,
143 int where, u32 value)
144 {
145 return pci_confx_write(0, dev->bus->number, PCI_SLOT(dev->devfn),
146 PCI_FUNC(dev->devfn), where, 4, value);
147 }
149 static struct pci_ops pci_conf_xen = {
150 pci_confx_read_config_byte,
151 pci_confx_read_config_word,
152 pci_confx_read_config_dword,
153 pci_confx_write_config_byte,
154 pci_confx_write_config_word,
155 pci_confx_write_config_dword
156 };
158 void pcibios_penalize_isa_irq(int irq)
159 {
160 /* nothing */
161 }
163 void __devinit pcibios_fixup_bus(struct pci_bus *b)
164 {
165 pci_read_bridge_bases(b);
166 }
168 struct pci_bus * __devinit pcibios_scan_root(int busnum)
169 {
170 struct list_head *list;
171 struct pci_bus *bus;
173 list_for_each ( list, &pci_root_buses )
174 {
175 bus = pci_bus_b(list);
176 if ( bus->number == busnum )
177 return bus;
178 }
180 printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);
181 return pci_scan_bus(busnum, pci_root_ops, NULL);
182 }
184 void __init pcibios_init(void)
185 {
186 int bus;
187 physdev_op_t op;
189 if ( !pci_probe )
190 return;
192 pci_root_ops = &pci_conf_xen;
193 pci_config_read = pci_confx_read;
194 pci_config_write = pci_confx_write;
196 pcibios_set_cacheline_size();
198 op.cmd = PHYSDEVOP_PCI_PROBE_ROOT_BUSES;
199 if ( HYPERVISOR_physdev_op(&op) != 0 )
200 {
201 printk(KERN_WARNING "PCI: System does not support PCI\n");
202 return;
203 }
205 printk(KERN_INFO "PCI: Probing PCI hardware\n");
206 for ( bus = 0; bus < 256; bus++ )
207 if ( test_bit(bus, &op.u.pci_probe_root_buses.busmask[0]) )
208 (void)pcibios_scan_root(bus);
210 pcibios_resource_survey();
211 }
213 char * __devinit pcibios_setup(char *str)
214 {
215 if ( !strcmp(str, "off") )
216 pci_probe = 0;
217 return NULL;
218 }
220 unsigned int pcibios_assign_all_busses(void)
221 {
222 return 0;
223 }
225 int pcibios_enable_device(struct pci_dev *dev, int mask)
226 {
227 int err;
228 u8 pin;
229 physdev_op_t op;
231 /* Inform Xen that we are going to use this device. */
232 op.cmd = PHYSDEVOP_PCI_INITIALISE_DEVICE;
233 op.u.pci_initialise_device.bus = dev->bus->number;
234 op.u.pci_initialise_device.dev = PCI_SLOT(dev->devfn);
235 op.u.pci_initialise_device.func = PCI_FUNC(dev->devfn);
236 if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
237 return err;
239 /* Now we can bind to the very final IRQ line. */
240 pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &pin);
241 dev->irq = pin;
243 /* Turn on device I/O and memory access as necessary. */
244 if ( (err = pcibios_enable_resources(dev, mask)) < 0 )
245 return err;
247 /* Sanity-check that an interrupt-producing device is routed to an IRQ. */
248 pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
249 if ( pin != 0 )
250 {
251 if ( dev->irq != 0 )
252 printk(KERN_INFO "PCI: Obtained IRQ %d for device %s\n",
253 dev->irq, dev->slot_name);
254 else
255 printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of "
256 "device %s.\n", 'A' + pin - 1, dev->slot_name);
257 }
259 return 0;
260 }