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