Merge signal handler branch
[linux-2.6] / arch / mips / pci / ops-bridge.c
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 };