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
27static 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
60oh_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
87static 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
123oh_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
151static 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
160static 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
197oh_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
226static 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
265oh_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
294static 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
303struct pci_ops bridge_pci_ops = {
304	.read	= pci_read_config,
305	.write	= pci_write_config,
306};
307