pci_machdep.c revision 1.34 1 /* $NetBSD: pci_machdep.c,v 1.34 2007/02/09 21:37:49 macallan Exp $ */
2
3 /*
4 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
5 * Copyright (c) 1994 Charles M. Hannum. 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. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Charles M. Hannum.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Machine-specific functions for PCI autoconfiguration.
35 *
36 * On PCs, there are two methods of generating PCI configuration cycles.
37 * We try to detect the appropriate mechanism for this machine and set
38 * up a few function pointers to access the correct method directly.
39 *
40 * The configuration method can be hard-coded in the config file by
41 * using `options PCI_CONF_MODE=N', where `N' is the configuration mode
42 * as defined section 3.6.4.1, `Generating Configuration Cycles'.
43 */
44
45 #include <sys/cdefs.h>
46 __KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.34 2007/02/09 21:37:49 macallan Exp $");
47
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/time.h>
51 #include <sys/systm.h>
52 #include <sys/errno.h>
53 #include <sys/device.h>
54
55 #include <uvm/uvm_extern.h>
56
57 #define _MACPPC_BUS_DMA_PRIVATE
58 #include <machine/bus.h>
59
60 #include <machine/autoconf.h>
61 #include <machine/pio.h>
62 #include <machine/intr.h>
63
64 #include <dev/pci/pcivar.h>
65 #include <dev/pci/pcireg.h>
66 #include <dev/pci/ppbreg.h>
67 #include <dev/pci/pcidevs.h>
68
69 #include <dev/ofw/openfirm.h>
70 #include <dev/ofw/ofw_pci.h>
71
72 #include "opt_macppc.h"
73
74 static void fixpci __P((int, pci_chipset_tag_t));
75 static int find_node_intr __P((int, u_int32_t *, u_int32_t *));
76 static void fix_cardbus_bridge(int, pci_chipset_tag_t, pcitag_t);
77
78 #ifdef PB3400_CARDBUS_HACK
79 int cardbus_number = 2;
80 const char *pb3400_compat[] = {"AAPL,3400/2400", NULL};
81 #endif
82
83 /*
84 * PCI doesn't have any special needs; just use the generic versions
85 * of these functions.
86 */
87 struct macppc_bus_dma_tag pci_bus_dma_tag = {
88 0, /* _bounce_thresh */
89 _bus_dmamap_create,
90 _bus_dmamap_destroy,
91 _bus_dmamap_load,
92 _bus_dmamap_load_mbuf,
93 _bus_dmamap_load_uio,
94 _bus_dmamap_load_raw,
95 _bus_dmamap_unload,
96 NULL, /* _dmamap_sync */
97 _bus_dmamem_alloc,
98 _bus_dmamem_free,
99 _bus_dmamem_map,
100 _bus_dmamem_unmap,
101 _bus_dmamem_mmap,
102 };
103
104 void
105 pci_attach_hook(parent, self, pba)
106 struct device *parent, *self;
107 struct pcibus_attach_args *pba;
108 {
109 pci_chipset_tag_t pc = pba->pba_pc;
110 int bus = pba->pba_bus;
111 int node, nn, sz;
112 int32_t busrange[2];
113
114 for (node = pc->node; node; node = nn) {
115 sz = OF_getprop(node, "bus-range", busrange, 8);
116 if (sz == 8 && busrange[0] == bus) {
117 fixpci(node, pc);
118 return;
119 }
120 if ((nn = OF_child(node)) != 0)
121 continue;
122 while ((nn = OF_peer(node)) == 0) {
123 node = OF_parent(node);
124 if (node == pc->node)
125 return; /* not found */
126 }
127 }
128 }
129
130 int
131 pci_bus_maxdevs(pc, busno)
132 pci_chipset_tag_t pc;
133 int busno;
134 {
135
136 /*
137 * Bus number is irrelevant. Configuration Mechanism 1 is in
138 * use, can have devices 0-32 (i.e. the `normal' range).
139 */
140 return 32;
141 }
142
143 pcitag_t
144 pci_make_tag(pc, bus, device, function)
145 pci_chipset_tag_t pc;
146 int bus, device, function;
147 {
148 pcitag_t tag;
149
150 if (bus >= 256 || device >= 32 || function >= 8)
151 panic("pci_make_tag: bad request");
152
153 /* XXX magic number */
154 tag = 0x80000000 | (bus << 16) | (device << 11) | (function << 8);
155
156 return tag;
157 }
158
159 void
160 pci_decompose_tag(pc, tag, bp, dp, fp)
161 pci_chipset_tag_t pc;
162 pcitag_t tag;
163 int *bp, *dp, *fp;
164 {
165
166 if (bp != NULL)
167 *bp = (tag >> 16) & 0xff;
168 if (dp != NULL)
169 *dp = (tag >> 11) & 0x1f;
170 if (fp != NULL)
171 *fp = (tag >> 8) & 0x07;
172 }
173
174 pcireg_t
175 pci_conf_read(pc, tag, reg)
176 pci_chipset_tag_t pc;
177 pcitag_t tag;
178 int reg;
179 {
180
181 return (*pc->conf_read)(pc, tag, reg);
182 }
183
184 void
185 pci_conf_write(pc, tag, reg, data)
186 pci_chipset_tag_t pc;
187 pcitag_t tag;
188 int reg;
189 pcireg_t data;
190 {
191
192 (*pc->conf_write)(pc, tag, reg, data);
193 }
194
195 int
196 pci_intr_map(pa, ihp)
197 struct pci_attach_args *pa;
198 pci_intr_handle_t *ihp;
199 {
200 int pin = pa->pa_intrpin;
201 int line = pa->pa_intrline;
202
203 #if DEBUG
204 printf("%s: pin: %d, line: %d\n", __FUNCTION__, pin, line);
205 #endif
206
207 if (pin == 0) {
208 /* No IRQ used. */
209 aprint_error("pci_intr_map: interrupt pin %d\n", pin);
210 goto bad;
211 }
212
213 if (pin > 4) {
214 aprint_error("pci_intr_map: bad interrupt pin %d\n", pin);
215 goto bad;
216 }
217
218 /*
219 * Section 6.2.4, `Miscellaneous Functions', says that 255 means
220 * `unknown' or `no connection' on a PC. We assume that a device with
221 * `no connection' either doesn't have an interrupt (in which case the
222 * pin number should be 0, and would have been noticed above), or
223 * wasn't configured by the BIOS (in which case we punt, since there's
224 * no real way we can know how the interrupt lines are mapped in the
225 * hardware).
226 *
227 * XXX
228 * Since IRQ 0 is only used by the clock, and we can't actually be sure
229 * that the BIOS did its job, we also recognize that as meaning that
230 * the BIOS has not configured the device.
231 */
232 if (line == 0 || line == 255) {
233 aprint_error("pci_intr_map: no mapping for pin %c\n", '@' + pin);
234 goto bad;
235 } else {
236 if (line >= ICU_LEN) {
237 aprint_error("pci_intr_map: bad interrupt line %d\n", line);
238 goto bad;
239 }
240 }
241
242 *ihp = line;
243 return 0;
244
245 bad:
246 *ihp = -1;
247 return 1;
248 }
249
250 const char *
251 pci_intr_string(pc, ih)
252 pci_chipset_tag_t pc;
253 pci_intr_handle_t ih;
254 {
255 static char irqstr[8]; /* 4 + 2 + NULL + sanity */
256
257 if (ih == 0 || ih >= ICU_LEN)
258 panic("pci_intr_string: bogus handle 0x%x", ih);
259
260 sprintf(irqstr, "irq %d", ih);
261 return (irqstr);
262
263 }
264
265 const struct evcnt *
266 pci_intr_evcnt(pc, ih)
267 pci_chipset_tag_t pc;
268 pci_intr_handle_t ih;
269 {
270
271 /* XXX for now, no evcnt parent reported */
272 return NULL;
273 }
274
275 void *
276 pci_intr_establish(pc, ih, level, func, arg)
277 pci_chipset_tag_t pc;
278 pci_intr_handle_t ih;
279 int level, (*func) __P((void *));
280 void *arg;
281 {
282
283 if (ih == 0 || ih >= ICU_LEN)
284 panic("pci_intr_establish: bogus handle 0x%x", ih);
285
286 return intr_establish(ih, IST_LEVEL, level, func, arg);
287 }
288
289 void
290 pci_intr_disestablish(pc, cookie)
291 pci_chipset_tag_t pc;
292 void *cookie;
293 {
294
295 intr_disestablish(cookie);
296 }
297
298 #define pcibus(x) \
299 (((x) & OFW_PCI_PHYS_HI_BUSMASK) >> OFW_PCI_PHYS_HI_BUSSHIFT)
300 #define pcidev(x) \
301 (((x) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT)
302 #define pcifunc(x) \
303 (((x) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT)
304
305 void
306 fixpci(parent, pc)
307 int parent;
308 pci_chipset_tag_t pc;
309 {
310 int node;
311 pcitag_t tag;
312 pcireg_t csr, intr, id, cr;
313 int len, i, ilen;
314 int32_t irqs[4];
315 struct {
316 u_int32_t phys_hi, phys_mid, phys_lo;
317 u_int32_t size_hi, size_lo;
318 } addr[8];
319 struct {
320 u_int32_t phys_hi, phys_mid, phys_lo;
321 u_int32_t icells[5];
322 } iaddr;
323
324 /*
325 * first hack - here we make the Ethernet portion of a
326 * UMAX E100 card work
327 */
328 #ifdef UMAX_E100_HACK
329 tag = pci_make_tag(pc, 0, 17, 0);
330 id = pci_conf_read(pc, tag, PCI_ID_REG);
331 if ((PCI_VENDOR(id) == PCI_VENDOR_DEC) &&
332 (PCI_PRODUCT(id) == PCI_PRODUCT_DEC_21140)) {
333 /* this could be one */
334 pcireg_t isp, reg;
335 pcitag_t tag_isp = pci_make_tag(pc, 0, 13, 0);
336 /*
337 * here we go. We shouldn't encounter this anywhere else
338 * than on a UMAX S900 with an E100 board
339 * look at 00:0d:00 for a Qlogic ISP 1020 to
340 * make sure we really have an E100 here
341 */
342 printf("\nfound E100 candidate tlp");
343 isp = pci_conf_read(pc, tag_isp, PCI_ID_REG);
344 if ((PCI_VENDOR(isp) == PCI_VENDOR_QLOGIC) &&
345 (PCI_PRODUCT(isp) == PCI_PRODUCT_QLOGIC_ISP1020)) {
346
347 aprint_verbose("\nenabling UMAX E100 ethernet");
348
349 pci_conf_write(pc, tag, 0x14, 0x80000000);
350
351 /* now enable MMIO and busmastering */
352 reg = pci_conf_read(pc, tag,
353 PCI_COMMAND_STATUS_REG);
354 reg |= PCI_COMMAND_MEM_ENABLE |
355 PCI_COMMAND_MASTER_ENABLE;
356 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
357 reg);
358
359 /* and finally the interrupt */
360 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
361 reg &= ~PCI_INTERRUPT_LINE_MASK;
362 reg |= 23;
363 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
364 }
365 }
366 #endif
367
368 len = OF_getprop(parent, "#interrupt-cells", &ilen, sizeof(ilen));
369 if (len < 0)
370 ilen = 0;
371 for (node = OF_child(parent); node; node = OF_peer(node)) {
372 len = OF_getprop(node, "assigned-addresses", addr,
373 sizeof(addr));
374 if (len < (int)sizeof(addr[0]))
375 continue;
376
377 tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
378 pcidev(addr[0].phys_hi),
379 pcifunc(addr[0].phys_hi));
380
381 /*
382 * Make sure the IO and MEM enable bits are set in the CSR.
383 */
384 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
385 csr &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE);
386
387 for (i = 0; i < len / sizeof(addr[0]); i++) {
388 switch (addr[i].phys_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
389 case OFW_PCI_PHYS_HI_SPACE_IO:
390 csr |= PCI_COMMAND_IO_ENABLE;
391 break;
392
393 case OFW_PCI_PHYS_HI_SPACE_MEM32:
394 case OFW_PCI_PHYS_HI_SPACE_MEM64:
395 csr |= PCI_COMMAND_MEM_ENABLE;
396 break;
397 }
398 }
399
400 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
401
402 /*
403 * Make sure the line register is programmed with the
404 * interrupt mapping.
405 */
406 if (ilen == 0) {
407 /*
408 * Early Apple OFW implementation don't handle
409 * interrupts as defined by the OFW PCI bindings.
410 */
411 len = OF_getprop(node, "AAPL,interrupts", irqs, 4);
412 } else {
413 iaddr.phys_hi = addr[0].phys_hi;
414 iaddr.phys_mid = addr[0].phys_mid;
415 iaddr.phys_lo = addr[0].phys_lo;
416 /*
417 * Thankfully, PCI can only have one entry in its
418 * "interrupts" property.
419 */
420 len = OF_getprop(node, "interrupts", &iaddr.icells[0],
421 4*ilen);
422 if (len != 4*ilen)
423 continue;
424 len = find_node_intr(node, &iaddr.phys_hi, irqs);
425 }
426 if (len <= 0) {
427 /*
428 * If we still don't have an interrupt, try one
429 * more time. This case covers devices behind the
430 * PCI-PCI bridge in a UMAX S900 or similar (9500?)
431 * system. These slots all share the bridge's
432 * interrupt.
433 */
434 len = find_node_intr(node, &addr[0].phys_hi, irqs);
435 if (len <= 0)
436 continue;
437 }
438
439 /*
440 * For PowerBook 2400, 3400 and original G3:
441 * check if we have a 2nd ohare PIC - if so frob the built-in
442 * tlp's IRQ to 60
443 * first see if we have something on bus 0 device 13 and if
444 * it's a DEC 21041
445 */
446 id = pci_conf_read(pc, tag, PCI_ID_REG);
447 if ((tag == pci_make_tag(pc, 0, 13, 0)) &&
448 (PCI_VENDOR(id) == PCI_VENDOR_DEC) &&
449 (PCI_PRODUCT(id) == PCI_PRODUCT_DEC_21041)) {
450
451 /* now look for the 2nd ohare */
452 if (OF_finddevice("/bandit/pci106b,7") != -1) {
453
454 irqs[0] = 60;
455 aprint_verbose("\nohare: frobbing tlp IRQ to 60");
456 }
457 }
458
459 intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
460 intr &= ~PCI_INTERRUPT_LINE_MASK;
461 intr |= irqs[0] & PCI_INTERRUPT_LINE_MASK;
462 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
463
464 /* fix secondary bus numbers on CardBus bridges */
465 cr = pci_conf_read(pc, tag, PCI_CLASS_REG);
466 if ((PCI_CLASS(cr) == PCI_CLASS_BRIDGE) &&
467 (PCI_SUBCLASS(cr) == PCI_SUBCLASS_BRIDGE_CARDBUS)) {
468 uint32_t bi, busid;
469
470 /*
471 * we found a CardBus bridge. Check if the bus number
472 * is sane
473 */
474 bi = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
475 busid = bi & 0xff;
476 if (busid == 0) {
477 fix_cardbus_bridge(node, pc, tag);
478 }
479 }
480 }
481 }
482
483 static void
484 fix_cardbus_bridge(int node, pci_chipset_tag_t pc, pcitag_t tag)
485 {
486 uint32_t bus_number = 0xffffffff;
487 pcireg_t bi;
488 int bus, dev, fn, ih, len;
489 char path[256];
490
491 #if PB3400_CARDBUS_HACK
492 int root_node;
493
494 root_node = OF_finddevice("/");
495 if (of_compatible(root_node, pb3400_compat) != -1) {
496
497 bus_number = cardbus_number;
498 cardbus_number++;
499 } else {
500 #endif
501 ih = OF_open(path);
502 OF_call_method("load-ata", ih, 0, 0);
503 OF_close(ih);
504
505 OF_getprop(node, "AAPL,bus-id", &bus_number,
506 sizeof(bus_number));
507 #if PB3400_CARDBUS_HACK
508 }
509 #endif
510 if (bus_number != 0xffffffff) {
511
512 len = OF_package_to_path(node, path, sizeof(path));
513 path[len] = 0;
514 aprint_verbose("\n%s: fixing bus number to %d", path, bus_number);
515 pci_decompose_tag(pc, tag, &bus, &dev, &fn);
516 bi = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
517 bi &= 0xff000000;
518 /* XXX subordinate is always 32 here */
519 bi |= (bus & 0xff) | (bus_number << 8) | 0x200000;
520 pci_conf_write(pc, tag, PPB_REG_BUSINFO, bi);
521 }
522 }
523
524 /*
525 * Find PCI IRQ of the node from OF tree.
526 */
527 int
528 find_node_intr(node, addr, intr)
529 int node;
530 u_int32_t *addr, *intr;
531 {
532 int parent, len, mlen, iparent;
533 int match, i;
534 u_int32_t map[160];
535 const u_int32_t *mp;
536 u_int32_t imapmask[8], maskedaddr[8];
537 u_int32_t acells, icells;
538 char name[32];
539
540 /* XXXSL: 1st check for a interrupt-parent property */
541 if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) == sizeof(iparent))
542 {
543 /* How many cells to specify an interrupt ?? */
544 if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
545 return -1;
546
547 if (OF_getprop(node, "interrupts", &map, sizeof(map)) != (icells * 4))
548 return -1;
549
550 memcpy(intr, map, icells * 4);
551 return (icells * 4);
552 }
553
554 parent = OF_parent(node);
555 len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
556 mlen = OF_getprop(parent, "interrupt-map-mask", imapmask,
557 sizeof(imapmask));
558
559 if (mlen != -1)
560 memcpy(maskedaddr, addr, mlen);
561 again:
562 if (len == -1 || mlen == -1)
563 goto nomap;
564
565 #ifdef DIAGNOSTIC
566 if (mlen == sizeof(imapmask)) {
567 aprint_error("interrupt-map too long\n");
568 return -1;
569 }
570 #endif
571
572 /* mask addr by "interrupt-map-mask" */
573 for (i = 0; i < mlen / 4; i++)
574 maskedaddr[i] &= imapmask[i];
575
576 mp = map;
577 i = 0;
578 while (len > mlen) {
579 match = memcmp(maskedaddr, mp, mlen);
580 mp += mlen / 4;
581 len -= mlen;
582
583 /*
584 * We must read "#address-cells" and "#interrupt-cells" each
585 * time because each interrupt-parent may be different.
586 */
587 iparent = *mp++;
588 len -= 4;
589 i = OF_getprop(iparent, "#address-cells", &acells, 4);
590 if (i <= 0)
591 acells = 0;
592 else if (i != 4)
593 return -1;
594 if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
595 return -1;
596
597 /* Found. */
598 if (match == 0) {
599 /*
600 * We matched on address/interrupt, but are we done?
601 */
602 if (acells == 0) { /* XXX */
603 /*
604 * If we are at the interrupt controller,
605 * we are finally done. Save the result and
606 * return.
607 */
608 memcpy(intr, mp, icells * 4);
609 return icells * 4;
610 }
611 /*
612 * We are now at an intermedia interrupt node. We
613 * need to use its interrupt mask and map the
614 * supplied address/interrupt via its map.
615 */
616 mlen = OF_getprop(iparent, "interrupt-map-mask",
617 imapmask, sizeof(imapmask));
618 #ifdef DIAGNOSTIC
619 if (mlen != (acells + icells)*4) {
620 aprint_error("interrupt-map inconsistent (%d, %d)\n",
621 mlen, (acells + icells)*4);
622 return -1;
623 }
624 #endif
625 memcpy(maskedaddr, mp, mlen);
626 len = OF_getprop(iparent, "interrupt-map", map,
627 sizeof(map));
628 goto again;
629 }
630
631 mp += (acells + icells);
632 len -= (acells + icells) * 4;
633 }
634
635 nomap:
636 /*
637 * If the node has no interrupt property and the parent is a
638 * pci-bridge, use parent's interrupt. This occurs on a PCI
639 * slot. (e.g. AHA-3940)
640 */
641 memset(name, 0, sizeof(name));
642 OF_getprop(parent, "name", name, sizeof(name));
643 if (strcmp(name, "pci-bridge") == 0) {
644 len = OF_getprop(parent, "AAPL,interrupts", intr, 4) ;
645 if (len == 4)
646 return len;
647 #if 0
648 /*
649 * XXX I don't know what is the correct local address.
650 * XXX Use the first entry for now.
651 */
652 len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
653 if (len >= 36) {
654 addr = &map[5];
655 return find_node_intr(parent, addr, intr);
656 }
657 #endif
658 }
659
660 /*
661 * If all else fails, attempt to get AAPL, interrupts property.
662 * Grackle, at least, uses this instead of above in some cases.
663 */
664 len = OF_getprop(node, "AAPL,interrupts", intr, 4) ;
665 if (len == 4)
666 return len;
667
668 return -1;
669 }
670