bandit.c revision 1.10 1 1.10 tsubai /* $NetBSD: bandit.c,v 1.10 1999/05/05 08:43:53 tsubai Exp $ */
2 1.9 thorpej
3 1.9 thorpej /*-
4 1.9 thorpej * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 1.9 thorpej * All rights reserved.
6 1.9 thorpej *
7 1.9 thorpej * This code is derived from software contributed to The NetBSD Foundation
8 1.9 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 1.9 thorpej * NASA Ames Research Center.
10 1.9 thorpej *
11 1.9 thorpej * Redistribution and use in source and binary forms, with or without
12 1.9 thorpej * modification, are permitted provided that the following conditions
13 1.9 thorpej * are met:
14 1.9 thorpej * 1. Redistributions of source code must retain the above copyright
15 1.9 thorpej * notice, this list of conditions and the following disclaimer.
16 1.9 thorpej * 2. Redistributions in binary form must reproduce the above copyright
17 1.9 thorpej * notice, this list of conditions and the following disclaimer in the
18 1.9 thorpej * documentation and/or other materials provided with the distribution.
19 1.9 thorpej * 3. All advertising materials mentioning features or use of this software
20 1.9 thorpej * must display the following acknowledgement:
21 1.9 thorpej * This product includes software developed by the NetBSD
22 1.9 thorpej * Foundation, Inc. and its contributors.
23 1.9 thorpej * 4. Neither the name of The NetBSD Foundation nor the names of its
24 1.9 thorpej * contributors may be used to endorse or promote products derived
25 1.9 thorpej * from this software without specific prior written permission.
26 1.9 thorpej *
27 1.9 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 1.9 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 1.9 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 1.9 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 1.9 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 1.9 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 1.9 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 1.9 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 1.9 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 1.9 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 1.9 thorpej * POSSIBILITY OF SUCH DAMAGE.
38 1.9 thorpej */
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.9 thorpej #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.1 tsubai static void scan_pci_devs __P((void));
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.1 tsubai pci_init()
115 1.1 tsubai {
116 1.9 thorpej
117 1.1 tsubai scan_pci_devs();
118 1.1 tsubai }
119 1.1 tsubai
120 1.9 thorpej static void
121 1.1 tsubai bandit_init(pc)
122 1.1 tsubai pci_chipset_tag_t pc;
123 1.1 tsubai {
124 1.1 tsubai u_int status;
125 1.1 tsubai pcitag_t tag;
126 1.1 tsubai
127 1.1 tsubai tag = pci_make_tag(pc, 0, PCI_BANDIT, 0);
128 1.1 tsubai if ((pci_conf_read(pc, tag, PCI_ID_REG) & 0xffff) == 0xffff)
129 1.1 tsubai return;
130 1.1 tsubai
131 1.9 thorpej status = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
132 1.1 tsubai
133 1.1 tsubai if ((status & PCI_MS_IO_COHERENT) == 0) {
134 1.1 tsubai status |= PCI_MS_IO_COHERENT;
135 1.1 tsubai pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, status);
136 1.1 tsubai }
137 1.1 tsubai }
138 1.1 tsubai
139 1.1 tsubai
140 1.9 thorpej static void
141 1.1 tsubai scan_pci_devs()
142 1.1 tsubai {
143 1.9 thorpej int reglen, node, child, n, is_bandit, is_mpc106;
144 1.1 tsubai char name[64];
145 1.9 thorpej u_int32_t *p, reg[36];
146 1.1 tsubai
147 1.2 tsubai bzero(pci_bridges, sizeof(pci_bridges));
148 1.1 tsubai
149 1.1 tsubai node = OF_peer(0);
150 1.1 tsubai node = OF_child(node);
151 1.1 tsubai
152 1.9 thorpej for (n = 0; node != 0; node = OF_peer(node)) {
153 1.1 tsubai if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
154 1.1 tsubai continue;
155 1.1 tsubai
156 1.9 thorpej is_bandit = (strcmp(name, "bandit") == 0 ||
157 1.9 thorpej strcmp(name, "chaos") == 0) ? 1 : 0;
158 1.1 tsubai
159 1.9 thorpej /* XXX for now */
160 1.9 thorpej is_mpc106 = (strcmp(name, "pci") == 0) ? 1 : 0;
161 1.5 tsubai
162 1.9 thorpej if (is_bandit == 0 && is_mpc106 == 0)
163 1.9 thorpej continue;
164 1.5 tsubai
165 1.9 thorpej /*
166 1.9 thorpej * Get the "ranges" property. We're expecting 6 32-bit
167 1.9 thorpej * values for each address space:
168 1.9 thorpej *
169 1.9 thorpej * phys.hi phys.mid phys.lo host size.hi size.lo
170 1.9 thorpej *
171 1.9 thorpej * Note that the MPC106 maps PCI memory space into
172 1.9 thorpej * two regions, one of which has a 24-bit addressing
173 1.9 thorpej * mode. We don't know the order of the "ranges"
174 1.9 thorpej * property, but both Address Map modes of the MPC106
175 1.9 thorpej * map the 32-bit memory range at a lower host address
176 1.9 thorpej * than the 24-bit range. We always pick the lower
177 1.9 thorpej * of the memory ranges for this reason.
178 1.9 thorpej */
179 1.9 thorpej
180 1.9 thorpej pci_bridges[n].memt = (bus_space_tag_t) 0xffffffff;
181 1.9 thorpej
182 1.9 thorpej reglen = OF_getproplen(node, "ranges");
183 1.9 thorpej if (reglen > sizeof(reg) || reglen <= 0 ||
184 1.9 thorpej reglen % (6 * sizeof(u_int32_t)) != 0)
185 1.9 thorpej continue; /* eek */
186 1.9 thorpej
187 1.9 thorpej reglen = OF_getprop(node, "ranges", reg, sizeof(reg));
188 1.9 thorpej
189 1.9 thorpej for (p = reg; reglen > 0;
190 1.9 thorpej reglen -= (6 * sizeof(u_int32_t)), p += 6) {
191 1.9 thorpej switch (p[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
192 1.9 thorpej case OFW_PCI_PHYS_HI_SPACE_IO:
193 1.9 thorpej pci_bridges[n].iot =
194 1.9 thorpej (bus_space_tag_t) p[3];
195 1.9 thorpej break;
196 1.9 thorpej
197 1.9 thorpej case OFW_PCI_PHYS_HI_SPACE_MEM32:
198 1.9 thorpej #if 0 /* XXX XXX XXX */
199 1.9 thorpej if (pci_bridges[n].memt >
200 1.9 thorpej (bus_space_tag_t)p[3])
201 1.9 thorpej pci_bridges[n].memt =
202 1.9 thorpej (bus_space_tag_t) p[3];
203 1.9 thorpej #else
204 1.9 thorpej /*
205 1.9 thorpej * XXX The Power Mac firmware seems to
206 1.9 thorpej * XXX include the PCI memory space base
207 1.9 thorpej * XXX in the device's BARs. We can remove
208 1.9 thorpej * XXX this kludge from here once we
209 1.9 thorpej * XXX fix the bus_space(9) implelentation.
210 1.9 thorpej */
211 1.9 thorpej pci_bridges[n].memt = (bus_space_tag_t) 0;
212 1.9 thorpej #endif
213 1.9 thorpej break;
214 1.1 tsubai
215 1.9 thorpej /* XXX What about OFW_PCI_PHYS_HI_SPACE_MEM64? */
216 1.1 tsubai }
217 1.1 tsubai }
218 1.2 tsubai
219 1.9 thorpej /*
220 1.9 thorpej * The "bus-range" property tells us our PCI bus number.
221 1.9 thorpej */
222 1.9 thorpej if (OF_getprop(node, "bus-range", reg, sizeof(reg)) != 8)
223 1.9 thorpej continue;
224 1.9 thorpej
225 1.9 thorpej pci_bridges[n].bus = reg[0];
226 1.9 thorpej
227 1.9 thorpej /*
228 1.9 thorpej * Map the PCI configuration space access registers,
229 1.9 thorpej * and perform any PCI-Host bridge initialization.
230 1.9 thorpej */
231 1.9 thorpej if (is_bandit) {
232 1.9 thorpej /* XXX magic numbers */
233 1.2 tsubai if (OF_getprop(node, "reg", reg, sizeof(reg)) != 8)
234 1.2 tsubai continue;
235 1.9 thorpej pci_bridges[n].addr = mapiodev(reg[0] + 0x800000, 4);
236 1.9 thorpej pci_bridges[n].data = mapiodev(reg[0] + 0xc00000, 4);
237 1.9 thorpej pci_bridges[n].pc = n;
238 1.9 thorpej bandit_init(n);
239 1.9 thorpej } else if (is_mpc106) {
240 1.9 thorpej /* XXX magic numbers */
241 1.9 thorpej pci_bridges[n].addr = mapiodev(0xfec00000, 4);
242 1.9 thorpej pci_bridges[n].data = mapiodev(0xfee00000, 4);
243 1.2 tsubai pci_bridges[n].pc = PCI_CHIPSET_MPC106; /* for now */
244 1.9 thorpej }
245 1.4 tsubai
246 1.9 thorpej /*
247 1.9 thorpej * Configure all of the PCI devices attached to this
248 1.9 thorpej * PCI-Host bridge.
249 1.9 thorpej */
250 1.9 thorpej child = OF_child(node);
251 1.9 thorpej while (child) {
252 1.9 thorpej config_slot(child, pci_bridges[n].pc, -1);
253 1.9 thorpej child = OF_peer(child);
254 1.2 tsubai }
255 1.2 tsubai
256 1.9 thorpej /* Bridge found, increment bridge instance. */
257 1.9 thorpej n++;
258 1.1 tsubai }
259 1.1 tsubai }
260 1.1 tsubai
261 1.9 thorpej static void
262 1.7 tsubai config_slot(node, pc, irq)
263 1.1 tsubai int node;
264 1.3 tsubai pci_chipset_tag_t pc;
265 1.7 tsubai int irq;
266 1.1 tsubai {
267 1.1 tsubai pcitag_t tag;
268 1.9 thorpej pcireg_t csr, intr;
269 1.9 thorpej int i, sz;
270 1.3 tsubai int bus, dev, func;
271 1.9 thorpej u_int32_t reg[40], *rp;
272 1.7 tsubai char name[16];
273 1.8 tsubai struct {
274 1.9 thorpej u_int32_t device;
275 1.9 thorpej u_int32_t junk[3];
276 1.9 thorpej u_int32_t intrnode;
277 1.9 thorpej u_int32_t interrupt;
278 1.8 tsubai } imap[16];
279 1.7 tsubai
280 1.7 tsubai bzero(name, sizeof(name));
281 1.7 tsubai OF_getprop(node, "name", name, sizeof(name));
282 1.7 tsubai if (strcmp(name, "pci-bridge") == 0) {
283 1.7 tsubai if (irq == -1)
284 1.7 tsubai OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq));
285 1.7 tsubai
286 1.7 tsubai node = OF_child(node);
287 1.7 tsubai while (node) {
288 1.7 tsubai config_slot(node, pc, irq);
289 1.7 tsubai node = OF_peer(node);
290 1.7 tsubai }
291 1.7 tsubai return;
292 1.7 tsubai }
293 1.1 tsubai
294 1.3 tsubai sz = OF_getprop(node, "assigned-addresses", reg, sizeof(reg));
295 1.3 tsubai if (sz < 4)
296 1.1 tsubai return;
297 1.1 tsubai
298 1.9 thorpej rp = reg;
299 1.9 thorpej bus = (rp[0] & OFW_PCI_PHYS_HI_BUSMASK) >>
300 1.9 thorpej OFW_PCI_PHYS_HI_BUSSHIFT;
301 1.9 thorpej dev = (rp[0] & OFW_PCI_PHYS_HI_DEVICEMASK) >>
302 1.9 thorpej OFW_PCI_PHYS_HI_DEVICESHIFT;
303 1.9 thorpej func = (rp[0] & OFW_PCI_PHYS_HI_FUNCTIONMASK) >>
304 1.9 thorpej OFW_PCI_PHYS_HI_FUNCTIONSHIFT;
305 1.3 tsubai
306 1.3 tsubai tag = pci_make_tag(pc, bus, dev, func);
307 1.9 thorpej csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
308 1.3 tsubai
309 1.9 thorpej /*
310 1.9 thorpej * Make sure the IO and MEM enable bits are set in the CSR.
311 1.9 thorpej */
312 1.10 tsubai csr &= ~(PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE);
313 1.9 thorpej for (; sz > 0; sz -= 5 * sizeof(u_int32_t), rp += 5) {
314 1.9 thorpej switch (rp[0] & OFW_PCI_PHYS_HI_SPACEMASK) {
315 1.9 thorpej case OFW_PCI_PHYS_HI_SPACE_IO:
316 1.3 tsubai csr |= PCI_COMMAND_IO_ENABLE;
317 1.9 thorpej break;
318 1.9 thorpej
319 1.9 thorpej case OFW_PCI_PHYS_HI_SPACE_MEM32:
320 1.3 tsubai csr |= PCI_COMMAND_MEM_ENABLE;
321 1.9 thorpej break;
322 1.9 thorpej }
323 1.3 tsubai }
324 1.3 tsubai
325 1.3 tsubai pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
326 1.1 tsubai
327 1.9 thorpej /*
328 1.9 thorpej * Make sure the line register is programmed with the interrupt
329 1.9 thorpej * mapping.
330 1.9 thorpej */
331 1.7 tsubai if (irq == -1 &&
332 1.7 tsubai OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq)) == -1 &&
333 1.7 tsubai OF_getprop(node, "interrupts", &irq, sizeof(irq)) == -1)
334 1.7 tsubai return;
335 1.1 tsubai
336 1.8 tsubai if (irq == 1) { /* XXX */
337 1.8 tsubai sz = OF_getprop(OF_parent(node), "interrupt-map",
338 1.9 thorpej imap, sizeof(imap));
339 1.8 tsubai if (sz != -1) {
340 1.8 tsubai for (i = 0; i < sz / sizeof(*imap); i++) {
341 1.8 tsubai /* XXX should use interrupt-map-mask */
342 1.9 thorpej if (((imap[i].device &
343 1.9 thorpej OFW_PCI_PHYS_HI_DEVICEMASK) >>
344 1.9 thorpej OFW_PCI_PHYS_HI_DEVICESHIFT) == dev) {
345 1.8 tsubai irq = imap[i].interrupt;
346 1.8 tsubai break;
347 1.8 tsubai }
348 1.8 tsubai }
349 1.8 tsubai }
350 1.8 tsubai }
351 1.7 tsubai
352 1.7 tsubai intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
353 1.9 thorpej intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
354 1.9 thorpej (irq & PCI_INTERRUPT_LINE_MASK);
355 1.7 tsubai pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
356 1.1 tsubai }
357