bandit.c revision 1.7 1 /* $NetBSD: bandit.c,v 1.7 1999/02/04 14:54:00 tsubai Exp $ */
2
3 /*
4 * Copyright 1991-1998 by Open Software Foundation, Inc.
5 * All Rights Reserved
6 *
7 * Permission to use, copy, modify, and distribute this software and
8 * its documentation for any purpose and without fee is hereby granted,
9 * provided that the above copyright notice appears in all copies and
10 * that both the copyright notice and this permission notice appear in
11 * supporting documentation.
12 *
13 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
14 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
15 * FOR A PARTICULAR PURPOSE.
16 *
17 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
20 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23 /*
24 * Copyright 1991-1998 by Apple Computer, Inc.
25 * All Rights Reserved
26 *
27 * Permission to use, copy, modify, and distribute this software and
28 * its documentation for any purpose and without fee is hereby granted,
29 * provided that the above copyright notice appears in all copies and
30 * that both the copyright notice and this permission notice appear in
31 * supporting documentation.
32 *
33 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
34 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE.
36 *
37 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
38 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
39 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
40 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
41 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
42 */
43
44 #include <sys/param.h>
45 #include <sys/device.h>
46 #include <sys/systm.h>
47
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pcivar.h>
50 #include <dev/ofw/openfirm.h>
51
52 #include <machine/bus.h>
53
54 #define PCI_BANDIT 11
55
56 #define PCI_REG_BANDIT_CFG 0x40
57 #define PCI_REG_ADDR_MASK 0x48
58 #define PCI_REG_MODE_SELECT 0x50
59 #define PCI_REG_ARBUS_HOLDOFF 0x58
60
61 #define PCI_MS_BYTESWAP 0x001 /* Enable Big Endian mode. (R/W)*/
62 #define PCI_MS_PASSATOMIC 0x002 /* PCI Bus to ARBus Lock are always allowed (R)*/
63 #define PCI_MS_NUMBER_MASK 0x00C /* PCI Bus Number (R) */
64 #define PCI_MS_IS_SYNC 0x010 /* Is Synchronous (1) or Async (0) ? (R)*/
65 #define PCI_MS_VGA_SPACE 0x020 /* Map VGA I/O space (R/W) */
66 #define PCI_MS_IO_COHERENT 0x040 /* I/O Coherent (R/W) */
67 #define PCI_MS_INT_ENABLE 0x080 /* Allow TEA or PCI Abort INT to pass to Grand Central (R/W) */
68
69 #define BANDIT_SPECIAL_CYCLE 0xe00000 /* Special Cycle offset */
70
71 static void bandit_init __P((pci_chipset_tag_t));
72 static void scan_pci_devs __P((void));
73 static void config_slot __P((int, pci_chipset_tag_t, int));
74
75 void
76 pci_init()
77 {
78 scan_pci_devs();
79 }
80
81 void
82 bandit_init(pc)
83 pci_chipset_tag_t pc;
84 {
85 u_int status;
86 pcitag_t tag;
87
88 tag = pci_make_tag(pc, 0, PCI_BANDIT, 0);
89 if ((pci_conf_read(pc, tag, PCI_ID_REG) & 0xffff) == 0xffff)
90 return;
91
92 status = pci_conf_read(pc, tag, PCI_REG_MODE_SELECT);
93
94 if ((status & PCI_MS_IO_COHERENT) == 0) {
95 status |= PCI_MS_IO_COHERENT;
96 pci_conf_write(pc, tag, PCI_REG_MODE_SELECT, status);
97 }
98
99 return;
100 }
101
102
103 void
104 scan_pci_devs()
105 {
106 int node;
107 char name[64];
108 int n = 0;
109 u_int reg[2];
110
111 bzero(pci_bridges, sizeof(pci_bridges));
112
113 node = OF_peer(0);
114 node = OF_child(node);
115
116 while (node) {
117 if (OF_getprop(node, "name", name, sizeof(name)) <= 0)
118 continue;
119 if (strcmp(name, "bandit") == 0 ||
120 strcmp(name, "chaos") == 0) {
121 int child;
122
123 if (OF_getprop(node, "reg", reg, sizeof(reg)) != 8)
124 continue;
125
126 pci_bridges[n].iot = (bus_space_tag_t)reg[0];
127 pci_bridges[n].addr = mapiodev(reg[0] + 0x800000, 4);
128 pci_bridges[n].data = mapiodev(reg[0] + 0xc00000, 4);
129 pci_bridges[n].pc = n;
130
131 if (OF_getprop(node, "bus-range",
132 reg, sizeof(reg)) != 8) {
133 pci_bridges[n].addr = NULL;
134 continue;
135 }
136 pci_bridges[n].bus = reg[0];
137
138 bandit_init(n);
139
140 child = OF_child(node);
141 while (child) {
142 config_slot(child, n, -1);
143 child = OF_peer(child);
144 }
145 n++;
146 }
147 if (strcmp(name, "pci") == 0) { /* XXX This is not a bandit :) */
148 int child;
149
150 if (OF_getprop(node, "reg", reg, sizeof(reg)) != 8)
151 continue;
152
153 pci_bridges[n].iot = (bus_space_tag_t)reg[0];
154 pci_bridges[n].addr = mapiodev(0xfec00000, 4); /* XXX */
155 pci_bridges[n].data = mapiodev(0xfee00000, 4); /* XXX */
156 pci_bridges[n].pc = PCI_CHIPSET_MPC106; /* for now */
157
158 if (OF_getprop(node, "bus-range",
159 reg, sizeof(reg)) != 8) {
160 pci_bridges[n].addr = NULL;
161 continue;
162 }
163 pci_bridges[n].bus = reg[0];
164
165 child = OF_child(node);
166 while (child) {
167 config_slot(child, pci_bridges[n].pc, -1);
168 child = OF_peer(child);
169 }
170 n++;
171 }
172
173 node = OF_peer(node);
174 }
175 }
176
177 void
178 config_slot(node, pc, irq)
179 int node;
180 pci_chipset_tag_t pc;
181 int irq;
182 {
183 pcitag_t tag;
184 int sp, intr, csr;
185 int bus, dev, func;
186 int sz;
187 u_int reg[40], *rp;
188 char name[16];
189
190 bzero(name, sizeof(name));
191 OF_getprop(node, "name", name, sizeof(name));
192 if (strcmp(name, "pci-bridge") == 0) {
193 if (irq == -1)
194 OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq));
195
196 node = OF_child(node);
197 while (node) {
198 config_slot(node, pc, irq);
199 node = OF_peer(node);
200 }
201 return;
202 }
203
204 sz = OF_getprop(node, "assigned-addresses", reg, sizeof(reg));
205 if (sz < 4)
206 return;
207
208 /*
209 * npt000ss bbbbbbbb dddddfff rrrrrrrr
210 *
211 * ss space code (01:I/O, 10:32bit mem)
212 * b... 8-bit Bus Number
213 * d... 5-bit Device Number
214 * f... 3-bit Function Number
215 * r... 8-bit Register Number
216 */
217 rp = ®[0];
218 bus = (*rp >> 16) & 0xff;
219 dev = (*rp >> 11) & 0x1f;
220 func = (*rp >> 8) & 0x07;
221
222 tag = pci_make_tag(pc, bus, dev, func);
223 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
224
225 /* Fix mem/io bits */
226 while (sz > 0) {
227 sp = (*rp >> 24) & 0x03;
228 if (sp == 1)
229 csr |= PCI_COMMAND_IO_ENABLE;
230 if (sp == 2)
231 csr |= PCI_COMMAND_MEM_ENABLE;
232 sz -= 5 * sizeof(int);
233 rp += 5;
234 }
235
236 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
237
238 /* Fix intr bits */
239 if (irq == -1 &&
240 OF_getprop(node, "AAPL,interrupts", &irq, sizeof(irq)) == -1 &&
241 OF_getprop(node, "interrupts", &irq, sizeof(irq)) == -1)
242 return;
243
244 /* XXX USB on iMac */
245 if (bus == 0 && dev == 20 && func == 0 && irq == 1)
246 irq = 28;
247
248 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
249 intr = (intr & 0xffffff00) | (irq & 0xff);
250 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
251 }
252
253 /*
254 * slot A1 pci0 dev 13 irq 23
255 * B1 pci0 dev 14 irq 24
256 * C1 pci0 dev 15 irq 25
257 * D2 pci1 dev 13 irq 27
258 * E2 pci1 dev 14 irq 28
259 * F2 pci1 dev 15 irq 29
260 */
261