ebus.c revision 1.41 1 /* $NetBSD: ebus.c,v 1.41 2003/08/27 15:59:54 mrg Exp $ */
2
3 /*
4 * Copyright (c) 1999, 2000, 2001 Matthew R. Green
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: ebus.c,v 1.41 2003/08/27 15:59:54 mrg Exp $");
33
34 #include "opt_ddb.h"
35
36 /*
37 * UltraSPARC 5 and beyond ebus support.
38 *
39 * note that this driver is not complete:
40 * - interrupt establish is written and appears to work
41 * - bus map code is written and appears to work
42 * - ebus2 DMA code is completely unwritten, we just punt to
43 * the iommu.
44 */
45
46 #ifdef DEBUG
47 #define EDB_PROM 0x01
48 #define EDB_CHILD 0x02
49 #define EDB_INTRMAP 0x04
50 #define EDB_BUSMAP 0x08
51 int ebus_debug = 0;
52 #define DPRINTF(l, s) do { if (ebus_debug & l) printf s; } while (0)
53 #else
54 #define DPRINTF(l, s)
55 #endif
56
57 #include <sys/param.h>
58 #include <sys/conf.h>
59 #include <sys/device.h>
60 #include <sys/errno.h>
61 #include <sys/extent.h>
62 #include <sys/malloc.h>
63 #include <sys/systm.h>
64 #include <sys/time.h>
65
66 #define _SPARC_BUS_DMA_PRIVATE
67 #include <machine/bus.h>
68 #include <machine/autoconf.h>
69 #include <machine/openfirm.h>
70
71 #include <dev/pci/pcivar.h>
72 #include <dev/pci/pcireg.h>
73 #include <dev/pci/pcidevs.h>
74
75 #include <sparc64/dev/iommureg.h>
76 #include <sparc64/dev/iommuvar.h>
77 #include <sparc64/dev/psychoreg.h>
78 #include <sparc64/dev/psychovar.h>
79 #include <dev/ebus/ebusreg.h>
80 #include <dev/ebus/ebusvar.h>
81 #include <sparc64/sparc64/cache.h>
82
83 struct ebus_softc {
84 struct device sc_dev;
85
86 int sc_node;
87
88 bus_space_tag_t sc_memtag; /* from pci */
89 bus_space_tag_t sc_iotag; /* from pci */
90 bus_space_tag_t sc_childbustag; /* pass to children */
91 bus_dma_tag_t sc_dmatag;
92
93 struct ebus_ranges *sc_range;
94 struct ebus_interrupt_map *sc_intmap;
95 struct ebus_interrupt_map_mask sc_intmapmask;
96
97 int sc_nrange; /* counters */
98 int sc_nintmap;
99 };
100
101 int ebus_match __P((struct device *, struct cfdata *, void *));
102 void ebus_attach __P((struct device *, struct device *, void *));
103
104 CFATTACH_DECL(ebus, sizeof(struct ebus_softc),
105 ebus_match, ebus_attach, NULL, NULL);
106
107 bus_space_tag_t ebus_alloc_bus_tag __P((struct ebus_softc *, int));
108
109 int ebus_setup_attach_args __P((struct ebus_softc *, int,
110 struct ebus_attach_args *));
111 void ebus_destroy_attach_args __P((struct ebus_attach_args *));
112 int ebus_print __P((void *, const char *));
113 void ebus_find_ino __P((struct ebus_softc *, struct ebus_attach_args *));
114 int ebus_find_node __P((struct pci_attach_args *));
115
116 /*
117 * here are our bus space and bus DMA routines.
118 */
119 static paddr_t ebus_bus_mmap __P((bus_space_tag_t, bus_addr_t, off_t, int, int));
120 static int _ebus_bus_map __P((bus_space_tag_t, bus_addr_t, bus_size_t, int,
121 vaddr_t, bus_space_handle_t *));
122 static void *ebus_intr_establish __P((bus_space_tag_t, int, int,
123 int (*) __P((void *)), void *, void(*)__P((void))));
124
125 int
126 ebus_match(parent, match, aux)
127 struct device *parent;
128 struct cfdata *match;
129 void *aux;
130 {
131 struct pci_attach_args *pa = aux;
132 char name[10];
133 int node;
134
135 /* Only attach if there's a PROM node. */
136 node = PCITAG_NODE(pa->pa_tag);
137 if (node == -1) return (0);
138
139 /* Match a real ebus */
140 OF_getprop(node, "name", &name, sizeof(name));
141 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
142 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN &&
143 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_EBUS &&
144 strcmp(name, "ebus") == 0)
145 return (1);
146
147 /* Or a real ebus III */
148 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
149 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN &&
150 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_EBUSIII &&
151 strcmp(name, "ebus") == 0)
152 return (1);
153
154 /* Or a PCI-ISA bridge XXX I hope this is on-board. */
155 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
156 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) {
157 return (1);
158 }
159
160 return (0);
161 }
162
163 /*
164 * attach an ebus and all it's children. this code is modeled
165 * after the sbus code which does similar things.
166 */
167 void
168 ebus_attach(parent, self, aux)
169 struct device *parent, *self;
170 void *aux;
171 {
172 struct ebus_softc *sc = (struct ebus_softc *)self;
173 struct pci_attach_args *pa = aux;
174 struct ebus_attach_args eba;
175 struct ebus_interrupt_map_mask *immp;
176 int node, nmapmask, error;
177 char devinfo[256];
178
179 printf("\n");
180
181 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo);
182 printf("%s: %s, revision 0x%02x\n", self->dv_xname, devinfo,
183 PCI_REVISION(pa->pa_class));
184
185 sc->sc_memtag = pa->pa_memt;
186 sc->sc_iotag = pa->pa_iot;
187 sc->sc_childbustag = ebus_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE);
188 sc->sc_dmatag = pa->pa_dmat;
189
190 node = PCITAG_NODE(pa->pa_tag);
191 if (node == -1)
192 panic("could not find ebus node");
193
194 sc->sc_node = node;
195
196 /*
197 * fill in our softc with information from the prom
198 */
199 sc->sc_intmap = NULL;
200 sc->sc_range = NULL;
201 error = PROM_getprop(node, "interrupt-map",
202 sizeof(struct ebus_interrupt_map),
203 &sc->sc_nintmap, &sc->sc_intmap);
204 switch (error) {
205 case 0:
206 immp = &sc->sc_intmapmask;
207 error = PROM_getprop(node, "interrupt-map-mask",
208 sizeof(struct ebus_interrupt_map_mask), &nmapmask,
209 &immp);
210 if (error)
211 panic("could not get ebus interrupt-map-mask");
212 if (nmapmask != 1)
213 panic("ebus interrupt-map-mask is broken");
214 break;
215 case ENOENT:
216 break;
217 default:
218 panic("ebus interrupt-map: error %d", error);
219 break;
220 }
221
222 error = PROM_getprop(node, "ranges", sizeof(struct ebus_ranges),
223 &sc->sc_nrange, &sc->sc_range);
224 if (error)
225 panic("ebus ranges: error %d", error);
226
227 /*
228 * now attach all our children
229 */
230 DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node));
231 for (node = firstchild(node); node; node = nextsibling(node)) {
232 char *name = PROM_getpropstring(node, "name");
233
234 if (ebus_setup_attach_args(sc, node, &eba) != 0) {
235 printf("ebus_attach: %s: incomplete\n", name);
236 continue;
237 } else {
238 DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n",
239 eba.ea_name));
240 (void)config_found(self, &eba, ebus_print);
241 }
242 ebus_destroy_attach_args(&eba);
243 }
244 }
245
246 int
247 ebus_setup_attach_args(sc, node, ea)
248 struct ebus_softc *sc;
249 int node;
250 struct ebus_attach_args *ea;
251 {
252 int n, rv;
253
254 bzero(ea, sizeof(struct ebus_attach_args));
255 rv = PROM_getprop(node, "name", 1, &n, &ea->ea_name);
256 if (rv != 0)
257 return (rv);
258 ea->ea_name[n] = '\0';
259
260 ea->ea_node = node;
261 ea->ea_bustag = sc->sc_childbustag;
262 ea->ea_dmatag = sc->sc_dmatag;
263
264 rv = PROM_getprop(node, "reg", sizeof(struct ebus_regs), &ea->ea_nreg,
265 &ea->ea_reg);
266 if (rv)
267 return (rv);
268
269 rv = PROM_getprop(node, "address", sizeof(u_int32_t), &ea->ea_nvaddr,
270 &ea->ea_vaddr);
271 if (rv != ENOENT) {
272 if (rv)
273 return (rv);
274
275 if (ea->ea_nreg != ea->ea_nvaddr)
276 printf("ebus loses: device %s: %d regs and %d addrs\n",
277 ea->ea_name, ea->ea_nreg, ea->ea_nvaddr);
278 } else
279 ea->ea_nvaddr = 0;
280
281 if (PROM_getprop(node, "interrupts", sizeof(u_int32_t), &ea->ea_nintr,
282 &ea->ea_intr))
283 ea->ea_nintr = 0;
284 else
285 ebus_find_ino(sc, ea);
286
287 return (0);
288 }
289
290 void
291 ebus_destroy_attach_args(ea)
292 struct ebus_attach_args *ea;
293 {
294
295 if (ea->ea_name)
296 free((void *)ea->ea_name, M_DEVBUF);
297 if (ea->ea_reg)
298 free((void *)ea->ea_reg, M_DEVBUF);
299 if (ea->ea_intr)
300 free((void *)ea->ea_intr, M_DEVBUF);
301 if (ea->ea_vaddr)
302 free((void *)ea->ea_vaddr, M_DEVBUF);
303 }
304
305 int
306 ebus_print(aux, p)
307 void *aux;
308 const char *p;
309 {
310 struct ebus_attach_args *ea = aux;
311 int i;
312
313 if (p)
314 aprint_normal("%s at %s", ea->ea_name, p);
315 for (i = 0; i < ea->ea_nreg; i++)
316 aprint_normal("%s %x-%x", i == 0 ? " addr" : ",",
317 ea->ea_reg[i].lo,
318 ea->ea_reg[i].lo + ea->ea_reg[i].size - 1);
319 for (i = 0; i < ea->ea_nintr; i++)
320 aprint_normal(" ipl %d", ea->ea_intr[i]);
321 return (UNCONF);
322 }
323
324
325 /*
326 * find the INO values for each interrupt and fill them in.
327 *
328 * for each "reg" property of this device, mask it's hi and lo
329 * values with the "interrupt-map-mask"'s hi/lo values, and also
330 * mask the interrupt number with the interrupt mask. search the
331 * "interrupt-map" list for matching values of hi, lo and interrupt
332 * to give the INO for this interrupt.
333 */
334 void
335 ebus_find_ino(sc, ea)
336 struct ebus_softc *sc;
337 struct ebus_attach_args *ea;
338 {
339 u_int32_t hi, lo, intr;
340 int i, j, k;
341
342 if (sc->sc_nintmap == 0) {
343 for (i = 0; i < ea->ea_nintr; i++) {
344 OF_mapintr(ea->ea_node, &ea->ea_intr[i],
345 sizeof(ea->ea_intr[0]),
346 sizeof(ea->ea_intr[0]));
347 }
348 return;
349 }
350
351 DPRINTF(EDB_INTRMAP,
352 ("ebus_find_ino: searching %d interrupts", ea->ea_nintr));
353
354 for (j = 0; j < ea->ea_nintr; j++) {
355
356 intr = ea->ea_intr[j] & sc->sc_intmapmask.intr;
357
358 DPRINTF(EDB_INTRMAP,
359 ("; intr %x masked to %x", ea->ea_intr[j], intr));
360 for (i = 0; i < ea->ea_nreg; i++) {
361 hi = ea->ea_reg[i].hi & sc->sc_intmapmask.hi;
362 lo = ea->ea_reg[i].lo & sc->sc_intmapmask.lo;
363
364 DPRINTF(EDB_INTRMAP,
365 ("; reg hi.lo %08x.%08x masked to %08x.%08x",
366 ea->ea_reg[i].hi, ea->ea_reg[i].lo, hi, lo));
367 for (k = 0; k < sc->sc_nintmap; k++) {
368 DPRINTF(EDB_INTRMAP,
369 ("; checking hi.lo %08x.%08x intr %x",
370 sc->sc_intmap[k].hi, sc->sc_intmap[k].lo,
371 sc->sc_intmap[k].intr));
372 if (hi == sc->sc_intmap[k].hi &&
373 lo == sc->sc_intmap[k].lo &&
374 intr == sc->sc_intmap[k].intr) {
375 ea->ea_intr[j] =
376 sc->sc_intmap[k].cintr;
377 DPRINTF(EDB_INTRMAP,
378 ("; FOUND IT! changing to %d\n",
379 sc->sc_intmap[k].cintr));
380 goto next_intr;
381 }
382 }
383 }
384 next_intr:;
385 }
386 }
387
388 /*
389 * bus space support. <sparc64/dev/psychoreg.h> has a discussion
390 * about PCI physical addresses, which also applies to ebus.
391 */
392 bus_space_tag_t
393 ebus_alloc_bus_tag(sc, type)
394 struct ebus_softc *sc;
395 int type;
396 {
397 bus_space_tag_t bt;
398
399 bt = (bus_space_tag_t)
400 malloc(sizeof(struct sparc_bus_space_tag), M_DEVBUF, M_NOWAIT);
401 if (bt == NULL)
402 panic("could not allocate ebus bus tag");
403
404 bzero(bt, sizeof *bt);
405 bt->cookie = sc;
406 bt->parent = sc->sc_memtag;
407 bt->type = type;
408 bt->sparc_bus_map = _ebus_bus_map;
409 bt->sparc_bus_mmap = ebus_bus_mmap;
410 bt->sparc_intr_establish = ebus_intr_establish;
411 return (bt);
412 }
413
414 static int
415 _ebus_bus_map(t, ba, size, flags, va, hp)
416 bus_space_tag_t t;
417 bus_addr_t ba;
418 bus_size_t size;
419 int flags;
420 vaddr_t va;
421 bus_space_handle_t *hp;
422 {
423 struct ebus_softc *sc = t->cookie;
424 paddr_t offset;
425 u_int bar;
426 int i, ss;
427
428 bar = BUS_ADDR_IOSPACE(ba);
429 offset = BUS_ADDR_PADDR(ba);
430
431 DPRINTF(EDB_BUSMAP,
432 ("\n_ebus_bus_map: bar %d offset %08x sz %x flags %x va %p\n",
433 (int)bar, (u_int32_t)offset, (u_int32_t)size,
434 flags, (void *)va));
435
436 for (i = 0; i < sc->sc_nrange; i++) {
437 bus_addr_t pciaddr;
438
439 if (bar != sc->sc_range[i].child_hi)
440 continue;
441 if (offset < sc->sc_range[i].child_lo ||
442 (offset + size) >
443 (sc->sc_range[i].child_lo + sc->sc_range[i].size))
444 continue;
445
446 /* Isolate address space and find the right tag */
447 ss = (sc->sc_range[i].phys_hi>>24)&3;
448 switch (ss) {
449 case 1: /* I/O space */
450 t = sc->sc_iotag;
451 break;
452 case 2: /* Memory space */
453 t = sc->sc_memtag;
454 break;
455 case 0: /* Config space */
456 case 3: /* 64-bit Memory space */
457 default: /* WTF? */
458 /* We don't handle these */
459 panic("_ebus_bus_map: illegal space %x", ss);
460 break;
461 }
462 pciaddr = ((bus_addr_t)sc->sc_range[i].phys_mid << 32UL) |
463 sc->sc_range[i].phys_lo;
464 pciaddr += offset;
465
466 DPRINTF(EDB_BUSMAP,
467 ("_ebus_bus_map: mapping to PCI addr %x\n",
468 (u_int32_t)pciaddr));
469
470 /* pass it onto the psycho */
471 return (bus_space_map(t, pciaddr, size, flags, hp));
472 }
473 DPRINTF(EDB_BUSMAP, (": FAILED\n"));
474 return (EINVAL);
475 }
476
477 static paddr_t
478 ebus_bus_mmap(t, paddr, off, prot, flags)
479 bus_space_tag_t t;
480 bus_addr_t paddr;
481 off_t off;
482 int prot;
483 int flags;
484 {
485 bus_addr_t offset = paddr;
486 struct ebus_softc *sc = t->cookie;
487 int i;
488
489 for (i = 0; i < sc->sc_nrange; i++) {
490 bus_addr_t paddr = ((bus_addr_t)sc->sc_range[i].child_hi << 32) |
491 sc->sc_range[i].child_lo;
492
493 if (offset != paddr)
494 continue;
495
496 DPRINTF(EDB_BUSMAP, ("\n_ebus_bus_mmap: mapping paddr %qx\n",
497 (unsigned long long)paddr));
498 return (bus_space_mmap(sc->sc_memtag, paddr, off,
499 prot, flags));
500 }
501
502 return (-1);
503 }
504
505 /*
506 * install an interrupt handler for a ebus device
507 */
508 void *
509 ebus_intr_establish(t, pri, level, handler, arg, fastvec)
510 bus_space_tag_t t;
511 int pri;
512 int level;
513 int (*handler) __P((void *));
514 void *arg;
515 void (*fastvec) __P((void)); /* ignored */
516 {
517
518 return (bus_intr_establish(t->parent, pri, level, handler, arg));
519 }
520