bandit.c revision 1.10 1 /* $NetBSD: bandit.c,v 1.10 1999/05/05 08:43:53 tsubai 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((void));
111 static void config_slot __P((int, pci_chipset_tag_t, int));
112
113 void
114 pci_init()
115 {
116
117 scan_pci_devs();
118 }
119
120 static void
121 bandit_init(pc)
122 pci_chipset_tag_t pc;
123 {
124 u_int status;
125 pcitag_t tag;
126
127 tag = pci_make_tag(pc, 0, PCI_BANDIT, 0);
128 if ((pci_conf_read(pc, tag, PCI_ID_REG) & 0xffff) == 0xffff)
129 return;
130
131 status = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
132
133 if ((status & PCI_MS_IO_COHERENT) == 0) {
134 status |= PCI_MS_IO_COHERENT;
135 pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, status);
136 }
137 }
138
139
140 static void
141 scan_pci_devs()
142 {
143 int reglen, node, child, n, is_bandit, is_mpc106;
144 char name[64];
145 u_int32_t *p, reg[36];
146
147 bzero(pci_bridges, sizeof(pci_bridges));
148
149 node = OF_peer(0);
150 node = OF_child(node);
151
152 for (n = 0; node != 0; node = OF_peer(node)) {
153 if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
154 continue;
155
156 is_bandit = (strcmp(name, "bandit") == 0 ||
157 strcmp(name, "chaos") == 0) ? 1 : 0;
158
159 /* XXX for now */
160 is_mpc106 = (strcmp(name, "pci") == 0) ? 1 : 0;
161
162 if (is_bandit == 0 && is_mpc106 == 0)
163 continue;
164
165 /*
166 * Get the "ranges" property. We're expecting 6 32-bit
167 * values for each address space:
168 *
169 * phys.hi phys.mid phys.lo host size.hi size.lo
170 *
171 * Note that the MPC106 maps PCI memory space into
172 * two regions, one of which has a 24-bit addressing
173 * mode. We don't know the order of the "ranges"
174 * property, but both Address Map modes of the MPC106
175 * map the 32-bit memory range at a lower host address
176 * than the 24-bit range. We always pick the lower
177 * of the memory ranges for this reason.
178 */
179
180 pci_bridges[n].memt = (bus_space_tag_t) 0xffffffff;
181
182 reglen = OF_getproplen(node, "ranges");
183 if (reglen > sizeof(reg) || reglen <= 0 ||
184 reglen % (6 * sizeof(u_int32_t)) != 0)
185 continue; /* eek */
186
187 reglen = OF_getprop(node, "ranges", reg, sizeof(reg));
188
189 for (p = reg; reglen > 0;
190 reglen -= (6 * sizeof(u_int32_t)), p += 6) {
191 switch (p[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
192 case OFW_PCI_PHYS_HI_SPACE_IO:
193 pci_bridges[n].iot =
194 (bus_space_tag_t) p[3];
195 break;
196
197 case OFW_PCI_PHYS_HI_SPACE_MEM32:
198 #if 0 /* XXX XXX XXX */
199 if (pci_bridges[n].memt >
200 (bus_space_tag_t)p[3])
201 pci_bridges[n].memt =
202 (bus_space_tag_t) p[3];
203 #else
204 /*
205 * XXX The Power Mac firmware seems to
206 * XXX include the PCI memory space base
207 * XXX in the device's BARs. We can remove
208 * XXX this kludge from here once we
209 * XXX fix the bus_space(9) implelentation.
210 */
211 pci_bridges[n].memt = (bus_space_tag_t) 0;
212 #endif
213 break;
214
215 /* XXX What about OFW_PCI_PHYS_HI_SPACE_MEM64? */
216 }
217 }
218
219 /*
220 * The "bus-range" property tells us our PCI bus number.
221 */
222 if (OF_getprop(node, "bus-range", reg, sizeof(reg)) != 8)
223 continue;
224
225 pci_bridges[n].bus = reg[0];
226
227 /*
228 * Map the PCI configuration space access registers,
229 * and perform any PCI-Host bridge initialization.
230 */
231 if (is_bandit) {
232 /* XXX magic numbers */
233 if (OF_getprop(node, "reg", reg, sizeof(reg)) != 8)
234 continue;
235 pci_bridges[n].addr = mapiodev(reg[0] + 0x800000, 4);
236 pci_bridges[n].data = mapiodev(reg[0] + 0xc00000, 4);
237 pci_bridges[n].pc = n;
238 bandit_init(n);
239 } else if (is_mpc106) {
240 /* XXX magic numbers */
241 pci_bridges[n].addr = mapiodev(0xfec00000, 4);
242 pci_bridges[n].data = mapiodev(0xfee00000, 4);
243 pci_bridges[n].pc = PCI_CHIPSET_MPC106; /* for now */
244 }
245
246 /*
247 * Configure all of the PCI devices attached to this
248 * PCI-Host bridge.
249 */
250 child = OF_child(node);
251 while (child) {
252 config_slot(child, pci_bridges[n].pc, -1);
253 child = OF_peer(child);
254 }
255
256 /* Bridge found, increment bridge instance. */
257 n++;
258 }
259 }
260
261 static void
262 config_slot(node, pc, irq)
263 int node;
264 pci_chipset_tag_t pc;
265 int irq;
266 {
267 pcitag_t tag;
268 pcireg_t csr, intr;
269 int i, sz;
270 int bus, dev, func;
271 u_int32_t reg[40], *rp;
272 char name[16];
273 struct {
274 u_int32_t device;
275 u_int32_t junk[3];
276 u_int32_t intrnode;
277 u_int32_t interrupt;
278 } imap[16];
279
280 bzero(name, sizeof(name));
281 OF_getprop(node, "name", name, sizeof(name));
282 if (strcmp(name, "pci-bridge") == 0) {
283 if (irq == -1)
284 OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq));
285
286 node = OF_child(node);
287 while (node) {
288 config_slot(node, pc, irq);
289 node = OF_peer(node);
290 }
291 return;
292 }
293
294 sz = OF_getprop(node, "assigned-addresses", reg, sizeof(reg));
295 if (sz < 4)
296 return;
297
298 rp = reg;
299 bus = (rp[0] & OFW_PCI_PHYS_HI_BUSMASK) >>
300 OFW_PCI_PHYS_HI_BUSSHIFT;
301 dev = (rp[0] & OFW_PCI_PHYS_HI_DEVICEMASK) >>
302 OFW_PCI_PHYS_HI_DEVICESHIFT;
303 func = (rp[0] & OFW_PCI_PHYS_HI_FUNCTIONMASK) >>
304 OFW_PCI_PHYS_HI_FUNCTIONSHIFT;
305
306 tag = pci_make_tag(pc, bus, dev, func);
307 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
308
309 /*
310 * Make sure the IO and MEM enable bits are set in the CSR.
311 */
312 csr &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
313 for (; sz > 0; sz -= 5 * sizeof(u_int32_t), rp += 5) {
314 switch (rp[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
315 case OFW_PCI_PHYS_HI_SPACE_IO:
316 csr |= PCI_COMMAND_IO_ENABLE;
317 break;
318
319 case OFW_PCI_PHYS_HI_SPACE_MEM32:
320 csr |= PCI_COMMAND_MEM_ENABLE;
321 break;
322 }
323 }
324
325 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
326
327 /*
328 * Make sure the line register is programmed with the interrupt
329 * mapping.
330 */
331 if (irq == -1 &&
332 OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq)) == -1 &&
333 OF_getprop(node, "interrupts", &irq, sizeof(irq)) == -1)
334 return;
335
336 if (irq == 1) { /* XXX */
337 sz = OF_getprop(OF_parent(node), "interrupt-map",
338 imap, sizeof(imap));
339 if (sz != -1) {
340 for (i = 0; i < sz / sizeof(*imap); i++) {
341 /* XXX should use interrupt-map-mask */
342 if (((imap[i].device &
343 OFW_PCI_PHYS_HI_DEVICEMASK) >>
344 OFW_PCI_PHYS_HI_DEVICESHIFT) == dev) {
345 irq = imap[i].interrupt;
346 break;
347 }
348 }
349 }
350 }
351
352 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
353 intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
354 (irq & PCI_INTERRUPT_LINE_MASK);
355 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
356 }
357