bandit.c revision 1.8.2.2 1 /* $NetBSD: bandit.c,v 1.8.2.2 1999/05/06 19:38:49 perry Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright 1991-1998 by Open Software Foundation, Inc.
42 * All Rights Reserved
43 *
44 * Permission to use, copy, modify, and distribute this software and
45 * its documentation for any purpose and without fee is hereby granted,
46 * provided that the above copyright notice appears in all copies and
47 * that both the copyright notice and this permission notice appear in
48 * supporting documentation.
49 *
50 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
51 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
52 * FOR A PARTICULAR PURPOSE.
53 *
54 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
55 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
56 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
57 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
58 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
59 */
60 /*
61 * Copyright 1991-1998 by Apple Computer, Inc.
62 * All Rights Reserved
63 *
64 * Permission to use, copy, modify, and distribute this software and
65 * its documentation for any purpose and without fee is hereby granted,
66 * provided that the above copyright notice appears in all copies and
67 * that both the copyright notice and this permission notice appear in
68 * supporting documentation.
69 *
70 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
71 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
72 * FOR A PARTICULAR PURPOSE.
73 *
74 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
75 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
76 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
77 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
78 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
79 */
80
81 #include <sys/param.h>
82 #include <sys/device.h>
83 #include <sys/systm.h>
84
85 #include <dev/pci/pcireg.h>
86 #include <dev/pci/pcivar.h>
87 #include <dev/ofw/openfirm.h>
88 #include <dev/ofw/ofw_pci.h>
89
90 #include <machine/bus.h>
91
92 #define PCI_BANDIT 11
93
94 #define PCI_REG_BANDIT_CFG 0x40
95 #define PCI_REG_ADDR_MASK 0x48
96 #define PCI_REG_MODE_SELECT 0x50
97 #define PCI_REG_ARBUS_HOLDOFF 0x58
98
99 #define PCI_MS_BYTESWAP 0x001 /* Enable Big Endian mode. (R/W)*/
100 #define PCI_MS_PASSATOMIC 0x002 /* PCI Bus to ARBus Lock are always allowed (R)*/
101 #define PCI_MS_NUMBER_MASK 0x00C /* PCI Bus Number (R) */
102 #define PCI_MS_IS_SYNC 0x010 /* Is Synchronous (1) or Async (0) ? (R)*/
103 #define PCI_MS_VGA_SPACE 0x020 /* Map VGA I/O space (R/W) */
104 #define PCI_MS_IO_COHERENT 0x040 /* I/O Coherent (R/W) */
105 #define PCI_MS_INT_ENABLE 0x080 /* Allow TEA or PCI Abort INT to pass to Grand Central (R/W) */
106
107 #define BANDIT_SPECIAL_CYCLE 0xe00000 /* Special Cycle offset */
108
109 static void bandit_init __P((pci_chipset_tag_t));
110 static void scan_pci_devs __P((int));
111 static void config_slot __P((int, pci_chipset_tag_t, int));
112
113 void
114 pci_init(canmap)
115 int canmap;
116 {
117
118 scan_pci_devs(canmap);
119 }
120
121 static void
122 bandit_init(pc)
123 pci_chipset_tag_t pc;
124 {
125 u_int status;
126 pcitag_t tag;
127
128 tag = pci_make_tag(pc, 0, PCI_BANDIT, 0);
129 if ((pci_conf_read(pc, tag, PCI_ID_REG) & 0xffff) == 0xffff)
130 return;
131
132 status = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
133
134 if ((status & PCI_MS_IO_COHERENT) == 0) {
135 status |= PCI_MS_IO_COHERENT;
136 pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, status);
137 }
138 }
139
140
141 static void
142 scan_pci_devs(canmap)
143 int canmap;
144 {
145 int reglen, node, child, n, is_bandit, is_mpc106;
146 char name[64];
147 u_int32_t *p, reg[36];
148
149 bzero(pci_bridges, sizeof(pci_bridges));
150
151 node = OF_peer(0);
152 node = OF_child(node);
153
154 for (n = 0; node != 0; node = OF_peer(node)) {
155 if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
156 continue;
157
158 is_bandit = (strcmp(name, "bandit") == 0 ||
159 strcmp(name, "chaos") == 0) ? 1 : 0;
160
161 /* XXX for now */
162 is_mpc106 = (strcmp(name, "pci") == 0) ? 1 : 0;
163
164 if (is_bandit == 0 && is_mpc106 == 0)
165 continue;
166
167 /*
168 * Get the "ranges" property. We're expecting 6 32-bit
169 * values for each address space:
170 *
171 * phys.hi phys.mid phys.lo host size.hi size.lo
172 *
173 * Note that the MPC106 maps PCI memory space into
174 * two regions, one of which has a 24-bit addressing
175 * mode. We don't know the order of the "ranges"
176 * property, but both Address Map modes of the MPC106
177 * map the 32-bit memory range at a lower host address
178 * than the 24-bit range. We always pick the lower
179 * of the memory ranges for this reason.
180 */
181
182 pci_bridges[n].memt = (bus_space_tag_t) 0xffffffff;
183
184 reglen = OF_getproplen(node, "ranges");
185 if (reglen > sizeof(reg) || reglen <= 0 ||
186 reglen % (6 * sizeof(u_int32_t)) != 0)
187 continue; /* eek */
188
189 reglen = OF_getprop(node, "ranges", reg, sizeof(reg));
190
191 for (p = reg; reglen > 0;
192 reglen -= (6 * sizeof(u_int32_t)), p += 6) {
193 switch (p[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
194 case OFW_PCI_PHYS_HI_SPACE_IO:
195 pci_bridges[n].iot =
196 (bus_space_tag_t) p[3];
197 break;
198
199 case OFW_PCI_PHYS_HI_SPACE_MEM32:
200 #if 0 /* XXX XXX XXX */
201 if (pci_bridges[n].memt >
202 (bus_space_tag_t)p[3])
203 pci_bridges[n].memt =
204 (bus_space_tag_t) p[3];
205 #else
206 /*
207 * XXX The Power Mac firmware seems to
208 * XXX include the PCI memory space base
209 * XXX in the device's BARs. We can remove
210 * XXX this kludge from here once we
211 * XXX fix the bus_space(9) implelentation.
212 */
213 pci_bridges[n].memt = (bus_space_tag_t) 0;
214 #endif
215 break;
216
217 /* XXX What about OFW_PCI_PHYS_HI_SPACE_MEM64? */
218 }
219 }
220
221 /*
222 * The "bus-range" property tells us our PCI bus number.
223 */
224 if (OF_getprop(node, "bus-range", reg, sizeof(reg)) != 8)
225 continue;
226
227 pci_bridges[n].bus = reg[0];
228 pci_bridges[n].present = 1;
229
230 /*
231 * Map the PCI configuration space access registers,
232 * and perform any PCI-Host bridge initialization.
233 */
234 if (is_bandit) {
235 /* XXX magic numbers */
236 pci_bridges[n].pc = n;
237 if (canmap) {
238 if (OF_getprop(node, "reg", reg,
239 sizeof(reg)) != 8)
240 continue;
241 pci_bridges[n].addr =
242 mapiodev(reg[0] + 0x800000, 4);
243 pci_bridges[n].data =
244 mapiodev(reg[0] + 0xc00000, 4);
245 bandit_init(n);
246 }
247 } else if (is_mpc106) {
248 /* XXX magic numbers */
249 pci_bridges[n].pc = PCI_CHIPSET_MPC106; /* for now */
250 if (canmap) {
251 pci_bridges[n].addr = mapiodev(0xfec00000, 4);
252 pci_bridges[n].data = mapiodev(0xfee00000, 4);
253 }
254 }
255
256 if (canmap) {
257 /*
258 * Configure all of the PCI devices attached to this
259 * PCI-Host bridge.
260 */
261 child = OF_child(node);
262 while (child) {
263 config_slot(child, pci_bridges[n].pc, -1);
264 child = OF_peer(child);
265 }
266 }
267
268 /* Bridge found, increment bridge instance. */
269 n++;
270 }
271 }
272
273 static void
274 config_slot(node, pc, irq)
275 int node;
276 pci_chipset_tag_t pc;
277 int irq;
278 {
279 pcitag_t tag;
280 pcireg_t csr, intr;
281 int i, sz;
282 int bus, dev, func;
283 u_int32_t reg[40], *rp;
284 char name[16];
285 struct {
286 u_int32_t device;
287 u_int32_t junk[3];
288 u_int32_t intrnode;
289 u_int32_t interrupt;
290 } imap[16];
291
292 bzero(name, sizeof(name));
293 OF_getprop(node, "name", name, sizeof(name));
294 if (strcmp(name, "pci-bridge") == 0) {
295 if (irq == -1)
296 OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq));
297
298 node = OF_child(node);
299 while (node) {
300 config_slot(node, pc, irq);
301 node = OF_peer(node);
302 }
303 return;
304 }
305
306 sz = OF_getprop(node, "assigned-addresses", reg, sizeof(reg));
307 if (sz < 4)
308 return;
309
310 rp = reg;
311 bus = (rp[0] & OFW_PCI_PHYS_HI_BUSMASK) >>
312 OFW_PCI_PHYS_HI_BUSSHIFT;
313 dev = (rp[0] & OFW_PCI_PHYS_HI_DEVICEMASK) >>
314 OFW_PCI_PHYS_HI_DEVICESHIFT;
315 func = (rp[0] & OFW_PCI_PHYS_HI_FUNCTIONMASK) >>
316 OFW_PCI_PHYS_HI_FUNCTIONSHIFT;
317
318 tag = pci_make_tag(pc, bus, dev, func);
319 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
320
321 /*
322 * Make sure the IO and MEM enable bits are set in the CSR.
323 */
324 csr &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
325 for (; sz > 0; sz -= 5 * sizeof(u_int32_t), rp += 5) {
326 switch (rp[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
327 case OFW_PCI_PHYS_HI_SPACE_IO:
328 csr |= PCI_COMMAND_IO_ENABLE;
329 break;
330
331 case OFW_PCI_PHYS_HI_SPACE_MEM32:
332 csr |= PCI_COMMAND_MEM_ENABLE;
333 break;
334 }
335 }
336
337 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
338
339 /*
340 * Make sure the line register is programmed with the interrupt
341 * mapping.
342 */
343 if (irq == -1 &&
344 OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq)) == -1 &&
345 OF_getprop(node, "interrupts", &irq, sizeof(irq)) == -1)
346 return;
347
348 if (irq == 1) { /* XXX */
349 sz = OF_getprop(OF_parent(node), "interrupt-map",
350 imap, sizeof(imap));
351 if (sz != -1) {
352 for (i = 0; i < sz / sizeof(*imap); i++) {
353 /* XXX should use interrupt-map-mask */
354 if (((imap[i].device &
355 OFW_PCI_PHYS_HI_DEVICEMASK) >>
356 OFW_PCI_PHYS_HI_DEVICESHIFT) == dev) {
357 irq = imap[i].interrupt;
358 break;
359 }
360 }
361 }
362 }
363
364 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
365 intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
366 (irq & PCI_INTERRUPT_LINE_MASK);
367 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
368 }
369