diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/pci/ops-bridge.c | 306 | ||||
-rw-r--r-- | arch/mips/pci/pci-ip27.c | 292 |
3 files changed, 308 insertions, 292 deletions
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index fb50d410773b..bb6b6226a57a 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile | |||
@@ -43,7 +43,7 @@ obj-$(CONFIG_MOMENCO_OCELOT_C) += fixup-ocelot-c.o pci-ocelot-c.o | |||
43 | obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o | 43 | obj-$(CONFIG_MOMENCO_OCELOT_G) += fixup-ocelot-g.o pci-ocelot-g.o |
44 | obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \ | 44 | obj-$(CONFIG_PMC_YOSEMITE) += fixup-yosemite.o ops-titan.o ops-titan-ht.o \ |
45 | pci-yosemite.o | 45 | pci-yosemite.o |
46 | obj-$(CONFIG_SGI_IP27) += pci-ip27.o | 46 | obj-$(CONFIG_SGI_IP27) += ops-bridge.o pci-ip27.o |
47 | obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o | 47 | obj-$(CONFIG_SGI_IP32) += fixup-ip32.o ops-mace.o pci-ip32.o |
48 | obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o | 48 | obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o |
49 | obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o | 49 | obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o |
diff --git a/arch/mips/pci/ops-bridge.c b/arch/mips/pci/ops-bridge.c new file mode 100644 index 000000000000..1fa09929cd7a --- /dev/null +++ b/arch/mips/pci/ops-bridge.c | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 1999, 2000, 04, 06 Ralf Baechle (ralf@linux-mips.org) | ||
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||
8 | */ | ||
9 | #include <linux/pci.h> | ||
10 | #include <asm/paccess.h> | ||
11 | #include <asm/pci/bridge.h> | ||
12 | #include <asm/sn/arch.h> | ||
13 | #include <asm/sn/intr.h> | ||
14 | #include <asm/sn/sn0/hub.h> | ||
15 | |||
16 | /* | ||
17 | * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is | ||
18 | * not really documented, so right now I can't write code which uses it. | ||
19 | * Therefore we use type 0 accesses for now even though they won't work | ||
20 | * correcly for PCI-to-PCI bridges. | ||
21 | * | ||
22 | * The function is complicated by the ultimate brokeness of the IOC3 chip | ||
23 | * which is used in SGI systems. The IOC3 can only handle 32-bit PCI | ||
24 | * accesses and does only decode parts of it's address space. | ||
25 | */ | ||
26 | |||
27 | static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, | ||
28 | int where, int size, u32 * value) | ||
29 | { | ||
30 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
31 | bridge_t *bridge = bc->base; | ||
32 | int slot = PCI_SLOT(devfn); | ||
33 | int fn = PCI_FUNC(devfn); | ||
34 | volatile void *addr; | ||
35 | u32 cf, shift, mask; | ||
36 | int res; | ||
37 | |||
38 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
39 | if (get_dbe(cf, (u32 *) addr)) | ||
40 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
41 | |||
42 | /* | ||
43 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
44 | * generic PCI code a chance to look at it for real ... | ||
45 | */ | ||
46 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
47 | goto oh_my_gawd; | ||
48 | |||
49 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
50 | |||
51 | if (size == 1) | ||
52 | res = get_dbe(*value, (u8 *) addr); | ||
53 | else if (size == 2) | ||
54 | res = get_dbe(*value, (u16 *) addr); | ||
55 | else | ||
56 | res = get_dbe(*value, (u32 *) addr); | ||
57 | |||
58 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
59 | |||
60 | oh_my_gawd: | ||
61 | |||
62 | /* | ||
63 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
64 | * generic PCI code a chance to look at the wrong register. | ||
65 | */ | ||
66 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
67 | *value = 0; | ||
68 | return PCIBIOS_SUCCESSFUL; | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
73 | * anything but 32-bit words ... | ||
74 | */ | ||
75 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
76 | |||
77 | if (get_dbe(cf, (u32 *) addr)) | ||
78 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
79 | |||
80 | shift = ((where & 3) << 3); | ||
81 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
82 | *value = (cf >> shift) & mask; | ||
83 | |||
84 | return PCIBIOS_SUCCESSFUL; | ||
85 | } | ||
86 | |||
87 | static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, | ||
88 | int where, int size, u32 * value) | ||
89 | { | ||
90 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
91 | bridge_t *bridge = bc->base; | ||
92 | int busno = bus->number; | ||
93 | int slot = PCI_SLOT(devfn); | ||
94 | int fn = PCI_FUNC(devfn); | ||
95 | volatile void *addr; | ||
96 | u32 cf, shift, mask; | ||
97 | int res; | ||
98 | |||
99 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
100 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
101 | if (get_dbe(cf, (u32 *) addr)) | ||
102 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
103 | |||
104 | /* | ||
105 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
106 | * generic PCI code a chance to look at it for real ... | ||
107 | */ | ||
108 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
109 | goto oh_my_gawd; | ||
110 | |||
111 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
112 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
113 | |||
114 | if (size == 1) | ||
115 | res = get_dbe(*value, (u8 *) addr); | ||
116 | else if (size == 2) | ||
117 | res = get_dbe(*value, (u16 *) addr); | ||
118 | else | ||
119 | res = get_dbe(*value, (u32 *) addr); | ||
120 | |||
121 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
122 | |||
123 | oh_my_gawd: | ||
124 | |||
125 | /* | ||
126 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
127 | * generic PCI code a chance to look at the wrong register. | ||
128 | */ | ||
129 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
130 | *value = 0; | ||
131 | return PCIBIOS_SUCCESSFUL; | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
136 | * anything but 32-bit words ... | ||
137 | */ | ||
138 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
139 | addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; | ||
140 | |||
141 | if (get_dbe(cf, (u32 *) addr)) | ||
142 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
143 | |||
144 | shift = ((where & 3) << 3); | ||
145 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
146 | *value = (cf >> shift) & mask; | ||
147 | |||
148 | return PCIBIOS_SUCCESSFUL; | ||
149 | } | ||
150 | |||
151 | static int pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
152 | int where, int size, u32 * value) | ||
153 | { | ||
154 | if (bus->number > 0) | ||
155 | return pci_conf1_read_config(bus, devfn, where, size, value); | ||
156 | |||
157 | return pci_conf0_read_config(bus, devfn, where, size, value); | ||
158 | } | ||
159 | |||
160 | static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, | ||
161 | int where, int size, u32 value) | ||
162 | { | ||
163 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
164 | bridge_t *bridge = bc->base; | ||
165 | int slot = PCI_SLOT(devfn); | ||
166 | int fn = PCI_FUNC(devfn); | ||
167 | volatile void *addr; | ||
168 | u32 cf, shift, mask, smask; | ||
169 | int res; | ||
170 | |||
171 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
172 | if (get_dbe(cf, (u32 *) addr)) | ||
173 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
174 | |||
175 | /* | ||
176 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
177 | * generic PCI code a chance to look at it for real ... | ||
178 | */ | ||
179 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
180 | goto oh_my_gawd; | ||
181 | |||
182 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
183 | |||
184 | if (size == 1) { | ||
185 | res = put_dbe(value, (u8 *) addr); | ||
186 | } else if (size == 2) { | ||
187 | res = put_dbe(value, (u16 *) addr); | ||
188 | } else { | ||
189 | res = put_dbe(value, (u32 *) addr); | ||
190 | } | ||
191 | |||
192 | if (res) | ||
193 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
194 | |||
195 | return PCIBIOS_SUCCESSFUL; | ||
196 | |||
197 | oh_my_gawd: | ||
198 | |||
199 | /* | ||
200 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
201 | * generic PCI code a chance to touch the wrong register. | ||
202 | */ | ||
203 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
204 | return PCIBIOS_SUCCESSFUL; | ||
205 | |||
206 | /* | ||
207 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
208 | * anything but 32-bit words ... | ||
209 | */ | ||
210 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
211 | |||
212 | if (get_dbe(cf, (u32 *) addr)) | ||
213 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
214 | |||
215 | shift = ((where & 3) << 3); | ||
216 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
217 | smask = mask << shift; | ||
218 | |||
219 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
220 | if (put_dbe(cf, (u32 *) addr)) | ||
221 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
222 | |||
223 | return PCIBIOS_SUCCESSFUL; | ||
224 | } | ||
225 | |||
226 | static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, | ||
227 | int where, int size, u32 value) | ||
228 | { | ||
229 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
230 | bridge_t *bridge = bc->base; | ||
231 | int slot = PCI_SLOT(devfn); | ||
232 | int fn = PCI_FUNC(devfn); | ||
233 | int busno = bus->number; | ||
234 | volatile void *addr; | ||
235 | u32 cf, shift, mask, smask; | ||
236 | int res; | ||
237 | |||
238 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
239 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
240 | if (get_dbe(cf, (u32 *) addr)) | ||
241 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
242 | |||
243 | /* | ||
244 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
245 | * generic PCI code a chance to look at it for real ... | ||
246 | */ | ||
247 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
248 | goto oh_my_gawd; | ||
249 | |||
250 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
251 | |||
252 | if (size == 1) { | ||
253 | res = put_dbe(value, (u8 *) addr); | ||
254 | } else if (size == 2) { | ||
255 | res = put_dbe(value, (u16 *) addr); | ||
256 | } else { | ||
257 | res = put_dbe(value, (u32 *) addr); | ||
258 | } | ||
259 | |||
260 | if (res) | ||
261 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
262 | |||
263 | return PCIBIOS_SUCCESSFUL; | ||
264 | |||
265 | oh_my_gawd: | ||
266 | |||
267 | /* | ||
268 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
269 | * generic PCI code a chance to touch the wrong register. | ||
270 | */ | ||
271 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
272 | return PCIBIOS_SUCCESSFUL; | ||
273 | |||
274 | /* | ||
275 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
276 | * anything but 32-bit words ... | ||
277 | */ | ||
278 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
279 | |||
280 | if (get_dbe(cf, (u32 *) addr)) | ||
281 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
282 | |||
283 | shift = ((where & 3) << 3); | ||
284 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
285 | smask = mask << shift; | ||
286 | |||
287 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
288 | if (put_dbe(cf, (u32 *) addr)) | ||
289 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
290 | |||
291 | return PCIBIOS_SUCCESSFUL; | ||
292 | } | ||
293 | |||
294 | static int pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
295 | int where, int size, u32 value) | ||
296 | { | ||
297 | if (bus->number > 0) | ||
298 | return pci_conf1_write_config(bus, devfn, where, size, value); | ||
299 | |||
300 | return pci_conf0_write_config(bus, devfn, where, size, value); | ||
301 | } | ||
302 | |||
303 | struct pci_ops bridge_pci_ops = { | ||
304 | .read = pci_read_config, | ||
305 | .write = pci_write_config, | ||
306 | }; | ||
diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 662196d9fb58..80eb9af9ecdf 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c | |||
@@ -40,297 +40,7 @@ static struct bridge_controller bridges[MAX_PCI_BUSSES]; | |||
40 | struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | 40 | struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; |
41 | int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; | 41 | int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; |
42 | 42 | ||
43 | /* | 43 | extern struct pci_ops bridge_pci_ops; |
44 | * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is | ||
45 | * not really documented, so right now I can't write code which uses it. | ||
46 | * Therefore we use type 0 accesses for now even though they won't work | ||
47 | * correcly for PCI-to-PCI bridges. | ||
48 | * | ||
49 | * The function is complicated by the ultimate brokeness of the IOC3 chip | ||
50 | * which is used in SGI systems. The IOC3 can only handle 32-bit PCI | ||
51 | * accesses and does only decode parts of it's address space. | ||
52 | */ | ||
53 | |||
54 | static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, | ||
55 | int where, int size, u32 * value) | ||
56 | { | ||
57 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
58 | bridge_t *bridge = bc->base; | ||
59 | int slot = PCI_SLOT(devfn); | ||
60 | int fn = PCI_FUNC(devfn); | ||
61 | volatile void *addr; | ||
62 | u32 cf, shift, mask; | ||
63 | int res; | ||
64 | |||
65 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
66 | if (get_dbe(cf, (u32 *) addr)) | ||
67 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
68 | |||
69 | /* | ||
70 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
71 | * generic PCI code a chance to look at it for real ... | ||
72 | */ | ||
73 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
74 | goto oh_my_gawd; | ||
75 | |||
76 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
77 | |||
78 | if (size == 1) | ||
79 | res = get_dbe(*value, (u8 *) addr); | ||
80 | else if (size == 2) | ||
81 | res = get_dbe(*value, (u16 *) addr); | ||
82 | else | ||
83 | res = get_dbe(*value, (u32 *) addr); | ||
84 | |||
85 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
86 | |||
87 | oh_my_gawd: | ||
88 | |||
89 | /* | ||
90 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
91 | * generic PCI code a chance to look at the wrong register. | ||
92 | */ | ||
93 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
94 | *value = 0; | ||
95 | return PCIBIOS_SUCCESSFUL; | ||
96 | } | ||
97 | |||
98 | /* | ||
99 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
100 | * anything but 32-bit words ... | ||
101 | */ | ||
102 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
103 | |||
104 | if (get_dbe(cf, (u32 *) addr)) | ||
105 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
106 | |||
107 | shift = ((where & 3) << 3); | ||
108 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
109 | *value = (cf >> shift) & mask; | ||
110 | |||
111 | return PCIBIOS_SUCCESSFUL; | ||
112 | } | ||
113 | |||
114 | static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, | ||
115 | int where, int size, u32 * value) | ||
116 | { | ||
117 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
118 | bridge_t *bridge = bc->base; | ||
119 | int busno = bus->number; | ||
120 | int slot = PCI_SLOT(devfn); | ||
121 | int fn = PCI_FUNC(devfn); | ||
122 | volatile void *addr; | ||
123 | u32 cf, shift, mask; | ||
124 | int res; | ||
125 | |||
126 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
127 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
128 | if (get_dbe(cf, (u32 *) addr)) | ||
129 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
130 | |||
131 | /* | ||
132 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
133 | * generic PCI code a chance to look at it for real ... | ||
134 | */ | ||
135 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
136 | goto oh_my_gawd; | ||
137 | |||
138 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
139 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
140 | |||
141 | if (size == 1) | ||
142 | res = get_dbe(*value, (u8 *) addr); | ||
143 | else if (size == 2) | ||
144 | res = get_dbe(*value, (u16 *) addr); | ||
145 | else | ||
146 | res = get_dbe(*value, (u32 *) addr); | ||
147 | |||
148 | return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
149 | |||
150 | oh_my_gawd: | ||
151 | |||
152 | /* | ||
153 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
154 | * generic PCI code a chance to look at the wrong register. | ||
155 | */ | ||
156 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { | ||
157 | *value = 0; | ||
158 | return PCIBIOS_SUCCESSFUL; | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
163 | * anything but 32-bit words ... | ||
164 | */ | ||
165 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
166 | addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; | ||
167 | |||
168 | if (get_dbe(cf, (u32 *) addr)) | ||
169 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
170 | |||
171 | shift = ((where & 3) << 3); | ||
172 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
173 | *value = (cf >> shift) & mask; | ||
174 | |||
175 | return PCIBIOS_SUCCESSFUL; | ||
176 | } | ||
177 | |||
178 | static int pci_read_config(struct pci_bus *bus, unsigned int devfn, | ||
179 | int where, int size, u32 * value) | ||
180 | { | ||
181 | if (bus->number > 0) | ||
182 | return pci_conf1_read_config(bus, devfn, where, size, value); | ||
183 | |||
184 | return pci_conf0_read_config(bus, devfn, where, size, value); | ||
185 | } | ||
186 | |||
187 | static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, | ||
188 | int where, int size, u32 value) | ||
189 | { | ||
190 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
191 | bridge_t *bridge = bc->base; | ||
192 | int slot = PCI_SLOT(devfn); | ||
193 | int fn = PCI_FUNC(devfn); | ||
194 | volatile void *addr; | ||
195 | u32 cf, shift, mask, smask; | ||
196 | int res; | ||
197 | |||
198 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[PCI_VENDOR_ID]; | ||
199 | if (get_dbe(cf, (u32 *) addr)) | ||
200 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
201 | |||
202 | /* | ||
203 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
204 | * generic PCI code a chance to look at it for real ... | ||
205 | */ | ||
206 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
207 | goto oh_my_gawd; | ||
208 | |||
209 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].c[where ^ (4 - size)]; | ||
210 | |||
211 | if (size == 1) { | ||
212 | res = put_dbe(value, (u8 *) addr); | ||
213 | } else if (size == 2) { | ||
214 | res = put_dbe(value, (u16 *) addr); | ||
215 | } else { | ||
216 | res = put_dbe(value, (u32 *) addr); | ||
217 | } | ||
218 | |||
219 | if (res) | ||
220 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
221 | |||
222 | return PCIBIOS_SUCCESSFUL; | ||
223 | |||
224 | oh_my_gawd: | ||
225 | |||
226 | /* | ||
227 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
228 | * generic PCI code a chance to touch the wrong register. | ||
229 | */ | ||
230 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
231 | return PCIBIOS_SUCCESSFUL; | ||
232 | |||
233 | /* | ||
234 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
235 | * anything but 32-bit words ... | ||
236 | */ | ||
237 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
238 | |||
239 | if (get_dbe(cf, (u32 *) addr)) | ||
240 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
241 | |||
242 | shift = ((where & 3) << 3); | ||
243 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
244 | smask = mask << shift; | ||
245 | |||
246 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
247 | if (put_dbe(cf, (u32 *) addr)) | ||
248 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
249 | |||
250 | return PCIBIOS_SUCCESSFUL; | ||
251 | } | ||
252 | |||
253 | static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, | ||
254 | int where, int size, u32 value) | ||
255 | { | ||
256 | struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); | ||
257 | bridge_t *bridge = bc->base; | ||
258 | int slot = PCI_SLOT(devfn); | ||
259 | int fn = PCI_FUNC(devfn); | ||
260 | int busno = bus->number; | ||
261 | volatile void *addr; | ||
262 | u32 cf, shift, mask, smask; | ||
263 | int res; | ||
264 | |||
265 | bridge->b_pci_cfg = (busno << 16) | (slot << 11); | ||
266 | addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; | ||
267 | if (get_dbe(cf, (u32 *) addr)) | ||
268 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
269 | |||
270 | /* | ||
271 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
272 | * generic PCI code a chance to look at it for real ... | ||
273 | */ | ||
274 | if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) | ||
275 | goto oh_my_gawd; | ||
276 | |||
277 | addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; | ||
278 | |||
279 | if (size == 1) { | ||
280 | res = put_dbe(value, (u8 *) addr); | ||
281 | } else if (size == 2) { | ||
282 | res = put_dbe(value, (u16 *) addr); | ||
283 | } else { | ||
284 | res = put_dbe(value, (u32 *) addr); | ||
285 | } | ||
286 | |||
287 | if (res) | ||
288 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
289 | |||
290 | return PCIBIOS_SUCCESSFUL; | ||
291 | |||
292 | oh_my_gawd: | ||
293 | |||
294 | /* | ||
295 | * IOC3 is fucked fucked beyond believe ... Don't even give the | ||
296 | * generic PCI code a chance to touch the wrong register. | ||
297 | */ | ||
298 | if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) | ||
299 | return PCIBIOS_SUCCESSFUL; | ||
300 | |||
301 | /* | ||
302 | * IOC3 is fucked fucked beyond believe ... Don't try to access | ||
303 | * anything but 32-bit words ... | ||
304 | */ | ||
305 | addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; | ||
306 | |||
307 | if (get_dbe(cf, (u32 *) addr)) | ||
308 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
309 | |||
310 | shift = ((where & 3) << 3); | ||
311 | mask = (0xffffffffU >> ((4 - size) << 3)); | ||
312 | smask = mask << shift; | ||
313 | |||
314 | cf = (cf & ~smask) | ((value & mask) << shift); | ||
315 | if (put_dbe(cf, (u32 *) addr)) | ||
316 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
317 | |||
318 | return PCIBIOS_SUCCESSFUL; | ||
319 | } | ||
320 | |||
321 | static int pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
322 | int where, int size, u32 value) | ||
323 | { | ||
324 | if (bus->number > 0) | ||
325 | return pci_conf1_write_config(bus, devfn, where, size, value); | ||
326 | |||
327 | return pci_conf0_write_config(bus, devfn, where, size, value); | ||
328 | } | ||
329 | |||
330 | static struct pci_ops bridge_pci_ops = { | ||
331 | .read = pci_read_config, | ||
332 | .write = pci_write_config, | ||
333 | }; | ||
334 | 44 | ||
335 | int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) | 45 | int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) |
336 | { | 46 | { |