|
|
1.1 root 1: /*
2: * OpenBIOS pci driver
3: *
4: * This driver is compliant to the
5: * PCI bus binding to IEEE 1275-1994 Rev 2.1
6: *
7: * (C) 2004 Stefan Reinauer <[email protected]>
8: * (C) 2005 Ed Schouten <[email protected]>
9: *
10: * Some parts from OpenHackWare-0.4, Copyright (c) 2004-2005 Jocelyn Mayer
11: *
12: * This program is free software; you can redistribute it and/or
13: * modify it under the terms of the GNU General Public License
14: * version 2
15: *
16: */
17:
18: #include "config.h"
19: #include "libopenbios/bindings.h"
20: #include "kernel/kernel.h"
21: #include "drivers/pci.h"
22: #include "libc/byteorder.h"
23: #include "libc/vsprintf.h"
24:
25: #include "drivers/drivers.h"
26: #include "drivers/vga.h"
27: #include "timer.h"
28: #include "pci.h"
29: #include "pci_database.h"
30: #ifdef CONFIG_DRIVER_MACIO
31: #include "cuda.h"
32: #include "macio.h"
33: #endif
34:
35: #if defined (CONFIG_DEBUG_PCI)
36: # define PCI_DPRINTF(format, ...) printk(format, ## __VA_ARGS__)
37: #else
38: # define PCI_DPRINTF(format, ...) do { } while (0)
39: #endif
40:
41: #define set_bool_property(ph, name) set_property(ph, name, NULL, 0);
42:
43: /* DECLARE data structures for the nodes. */
44:
45: DECLARE_UNNAMED_NODE( ob_pci_bus_node, INSTALL_OPEN, 2*sizeof(int) );
46: DECLARE_UNNAMED_NODE( ob_pci_simple_node, INSTALL_OPEN, 2*sizeof(int) );
47:
48: const pci_arch_t *arch;
49:
50: #define IS_NOT_RELOCATABLE 0x80000000
51: #define IS_PREFETCHABLE 0x40000000
52: #define IS_ALIASED 0x20000000
53:
54: enum {
55: CONFIGURATION_SPACE = 0,
56: IO_SPACE = 1,
57: MEMORY_SPACE_32 = 2,
58: MEMORY_SPACE_64 = 3,
59: };
60:
61: static int encode_int32_cells(int num_cells, u32 *prop, ucell val)
62: {
63: int i = 0;
64:
65: /* hi ... lo */
66: for (i=0; i < num_cells; ++i) {
67: prop[num_cells - i - 1] = val;
68: val >>= 16;
69: val >>= 16;
70: }
71:
72: return num_cells;
73: }
74:
75: static inline int pci_encode_phys_addr(u32 *phys, int flags, int space_code,
76: pci_addr dev, uint8_t reg, uint64_t addr)
77: {
78:
79: /* phys.hi */
80:
81: phys[0] = flags | (space_code << 24) | dev | reg;
82:
83: /* phys.mid */
84:
85: phys[1] = addr >> 32;
86:
87: /* phys.lo */
88:
89: phys[2] = addr;
90:
91: return 3;
92: }
93:
94: static inline int pci_encode_size(u32 *prop, uint64_t size)
95: {
96: return encode_int32_cells(2, prop, size);
97: }
98:
99: static int host_address_cells(void)
100: {
101: return get_int_property(find_dev("/"), "#address-cells", NULL);
102: }
103:
104: static int host_encode_phys_addr(u32 *prop, ucell addr)
105: {
106: return encode_int32_cells(host_address_cells(), prop, addr);
107: }
108:
109: static int host_size_cells(void)
110: {
111: return get_int_property(find_dev("/"), "#size-cells", NULL);
112: }
113:
114: /*
115: static int parent_address_cells(void)
116: {
117: phandle_t parent_ph = ih_to_phandle(my_parent());
118: return get_int_property(parent_ph, "#address-cells", NULL);
119: }
120:
121: static int parent_size_cells(void)
122: {
123: phandle_t parent_ph = ih_to_phandle(my_parent());
124: return get_int_property(parent_ph, "#size-cells", NULL);
125: }
126: */
127:
128: #if defined(CONFIG_DEBUG_PCI)
129: static void dump_reg_property(const char* description, int nreg, u32 *reg)
130: {
131: int i;
132: printk("%s reg", description);
133: for (i=0; i < nreg; ++i) {
134: printk(" %08X", reg[i]);
135: }
136: printk("\n");
137: }
138: #endif
139:
140: static void
141: ob_pci_open(int *idx)
142: {
143: int ret=1;
144: RET ( -ret );
145: }
146:
147: static void
148: ob_pci_close(int *idx)
149: {
150: }
151:
152: static void
153: ob_pci_initialize(int *idx)
154: {
155: }
156:
157: /* ( str len -- phys.lo phys.mid phys.hi ) */
158:
159: static void
160: ob_pci_decode_unit(int *idx)
161: {
162: ucell hi, mid, lo;
163: const char *arg = pop_fstr_copy();
164: int dev, fn, reg, ss, n, p, t;
165: int bus = 0; /* no information */
166: char *ptr;
167:
168: PCI_DPRINTF("ob_pci_decode_unit idx=%p\n", idx);
169:
170: fn = 0;
171: reg = 0;
172: n = 0;
173: p = 0;
174: t = 0;
175:
176: ptr = (char*)arg;
177: if (*ptr == 'n') {
178: n = IS_NOT_RELOCATABLE;
179: ptr++;
180: }
181: if (*ptr == 'i') {
182: ss = IO_SPACE;
183: ptr++;
184: if (*ptr == 't') {
185: t = IS_ALIASED;
186: ptr++;
187: }
188:
189: /* DD,F,RR,NNNNNNNN */
190:
191: dev = strtol(ptr, &ptr, 16);
192: ptr++;
193: fn = strtol(ptr, &ptr, 16);
194: ptr++;
195: reg = strtol(ptr, &ptr, 16);
196: ptr++;
197: lo = strtol(ptr, &ptr, 16);
198: mid = 0;
199:
200: } else if (*ptr == 'm') {
201: ss = MEMORY_SPACE_32;
202: ptr++;
203: if (*ptr == 't') {
204: t = IS_ALIASED;
205: ptr++;
206: }
207: if (*ptr == 'p') {
208: p = IS_PREFETCHABLE;
209: ptr++;
210: }
211:
212: /* DD,F,RR,NNNNNNNN */
213:
214: dev = strtol(ptr, &ptr, 16);
215: ptr++;
216: fn = strtol(ptr, &ptr, 16);
217: ptr++;
218: reg = strtol(ptr, &ptr, 16);
219: ptr++;
220: lo = strtol(ptr, &ptr, 16);
221: mid = 0;
222:
223: } else if (*ptr == 'x') {
224: unsigned long long addr64;
225: ss = MEMORY_SPACE_64;
226: ptr++;
227: if (*ptr == 'p') {
228: p = IS_PREFETCHABLE;
229: ptr++;
230: }
231:
232: /* DD,F,RR,NNNNNNNNNNNNNNNN */
233:
234: dev = strtol(ptr, &ptr, 16);
235: ptr++;
236: fn = strtol(ptr, &ptr, 16);
237: ptr++;
238: reg = strtol(ptr, &ptr, 16);
239: ptr++;
240: addr64 = strtoll(ptr, &ptr, 16);
241: lo = (ucell)addr64;
242: mid = addr64 >> 32;
243:
244: } else {
245: ss = CONFIGURATION_SPACE;
246: /* "DD" or "DD,FF" */
247: dev = strtol(ptr, &ptr, 16);
248: if (*ptr == ',') {
249: ptr++;
250: fn = strtol(ptr, NULL, 16);
251: }
252: lo = 0;
253: mid = 0;
254: }
255: free((char*)arg);
256:
257: hi = n | p | t | (ss << 24) | (bus << 16) | (dev << 11) | (fn << 8) | reg;
258:
259: PUSH(lo);
260: PUSH(mid);
261: PUSH(hi);
262:
263: PCI_DPRINTF("ob_pci_decode_unit idx=%p addr="
264: FMT_ucellx " " FMT_ucellx " " FMT_ucellx "\n",
265: idx, lo, mid, hi);
266: }
267:
268: /* ( phys.lo phy.mid phys.hi -- str len ) */
269:
270: static void
271: ob_pci_encode_unit(int *idx)
272: {
273: char buf[28];
274: cell hi = POP();
275: cell mid = POP();
276: cell lo = POP();
277: int n, p, t, ss, dev, fn, reg;
278:
279: n = hi & IS_NOT_RELOCATABLE;
280: p = hi & IS_PREFETCHABLE;
281: t = hi & IS_ALIASED;
282: ss = (hi >> 24) & 0x03;
283:
284: dev = (hi >> 11) & 0x1F;
285: fn = (hi >> 8) & 0x07;
286: reg = hi & 0xFF;
287:
288: switch(ss) {
289: case CONFIGURATION_SPACE:
290:
291: if (fn == 0) /* DD */
292: snprintf(buf, sizeof(buf), "%x", dev);
293: else /* DD,F */
294: snprintf(buf, sizeof(buf), "%x,%x", dev, fn);
295: break;
296:
297: case IO_SPACE:
298:
299: /* [n]i[t]DD,F,RR,NNNNNNNN */
300: snprintf(buf, sizeof(buf), "%si%s%x,%x,%x," FMT_ucellx,
301: n ? "n" : "", /* relocatable */
302: t ? "t" : "", /* aliased */
303: dev, fn, reg, t ? lo & 0x03FF : lo);
304: break;
305:
306: case MEMORY_SPACE_32:
307:
308: /* [n]m[t][p]DD,F,RR,NNNNNNNN */
309: snprintf(buf, sizeof(buf), "%sm%s%s%x,%x,%x," FMT_ucellx,
310: n ? "n" : "", /* relocatable */
311: t ? "t" : "", /* aliased */
312: p ? "p" : "", /* prefetchable */
313: dev, fn, reg, lo );
314: break;
315:
316: case MEMORY_SPACE_64:
317:
318: /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN */
319: snprintf(buf, sizeof(buf), "%sx%s%x,%x,%x,%llx",
320: n ? "n" : "", /* relocatable */
321: p ? "p" : "", /* prefetchable */
322: dev, fn, reg, ((long long)mid << 32) | (long long)lo);
323: break;
324: }
325: push_str(buf);
326:
327: PCI_DPRINTF("ob_pci_encode_unit space=%d dev=%d fn=%d buf=%s\n",
328: ss, dev, fn, buf);
329: }
330:
331: NODE_METHODS(ob_pci_bus_node) = {
332: { NULL, ob_pci_initialize },
333: { "open", ob_pci_open },
334: { "close", ob_pci_close },
335: { "decode-unit", ob_pci_decode_unit },
336: { "encode-unit", ob_pci_encode_unit },
337: };
338:
339: NODE_METHODS(ob_pci_simple_node) = {
340: { NULL, ob_pci_initialize },
341: { "open", ob_pci_open },
342: { "close", ob_pci_close },
343: };
344:
345: static void pci_set_bus_range(const pci_config_t *config)
346: {
347: phandle_t dev = find_dev(config->path);
348: u32 props[2];
349:
350: props[0] = config->secondary_bus;
351: props[1] = config->subordinate_bus;
352:
353: PCI_DPRINTF("setting bus range for %s PCI device, "
354: "package handle " FMT_ucellx " "
355: "bus primary=%d secondary=%d subordinate=%d\n",
356: config->path,
357: dev,
358: config->primary_bus,
359: config->secondary_bus,
360: config->subordinate_bus);
361:
362:
363: set_property(dev, "bus-range", (char *)props, 2 * sizeof(props[0]));
364: }
365:
366: static void pci_host_set_interrupt_map(const pci_config_t *config)
367: {
368: /* XXX We currently have a hook in the MPIC init code to fill in its handle.
369: * If you want to have interrupt maps for your PCI host bus, add your
370: * architecture to the #if and make your bridge detect code fill in its
371: * handle too.
372: *
373: * It would be great if someone clever could come up with a more universal
374: * mechanism here.
375: */
376: #if defined(CONFIG_PPC)
377: phandle_t dev = get_cur_dev();
378: u32 props[7 * 4];
379: int i;
380:
381: #if defined(CONFIG_PPC)
382: /* Oldworld macs do interrupt maps differently */
383: if(!is_newworld())
384: return;
385: #endif
386:
387: for (i = 0; i < (7*4); i+=7) {
388: props[i+PCI_INT_MAP_PCI0] = 0;
389: props[i+PCI_INT_MAP_PCI1] = 0;
390: props[i+PCI_INT_MAP_PCI2] = 0;
391: props[i+PCI_INT_MAP_PCI_INT] = (i / 7) + 1; // starts at PINA=1
392: props[i+PCI_INT_MAP_PIC_HANDLE] = 0; // gets patched in later
393: props[i+PCI_INT_MAP_PIC_INT] = arch->irqs[i / 7];
394: props[i+PCI_INT_MAP_PIC_POL] = 3;
395: }
396: set_property(dev, "interrupt-map", (char *)props, 7 * 4 * sizeof(props[0]));
397:
398: props[PCI_INT_MAP_PCI0] = 0;
399: props[PCI_INT_MAP_PCI1] = 0;
400: props[PCI_INT_MAP_PCI2] = 0;
401: props[PCI_INT_MAP_PCI_INT] = 0x7;
402:
403: set_property(dev, "interrupt-map-mask", (char *)props, 4 * sizeof(props[0]));
404: #endif
405: }
406:
407: static void pci_host_set_reg(phandle_t phandle)
408: {
409: phandle_t dev = phandle;
410:
411: /* at most 2 integers for address and size */
412: u32 props[4];
413: int ncells = 0;
414:
415: ncells += encode_int32_cells(host_address_cells(), props + ncells,
416: arch->cfg_base);
417:
418: ncells += encode_int32_cells(host_size_cells(), props + ncells,
419: arch->cfg_len);
420:
421: set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
422:
423: #if defined(CONFIG_DEBUG_PCI)
424: dump_reg_property("pci_host_set_reg", 4, props);
425: #endif
426: }
427:
428: /* child-phys : parent-phys : size */
429: /* 3 cells for PCI : 2 cells for 64bit parent : 2 cells for PCI */
430:
431: static void pci_host_set_ranges(const pci_config_t *config)
432: {
433: phandle_t dev = get_cur_dev();
434: u32 props[32];
435: int ncells;
436:
437: ncells = 0;
438: /* first encode PCI configuration space */
439: {
440: ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
441: config->dev, 0, 0);
442: ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr);
443: ncells += pci_encode_size(props + ncells, arch->cfg_len);
444: }
445:
446: if (arch->io_base) {
447: ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE,
448: config->dev, 0, 0);
449: ncells += host_encode_phys_addr(props + ncells, arch->io_base);
450: ncells += pci_encode_size(props + ncells, arch->io_len);
451: }
452: if (arch->rbase) {
453: ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
454: config->dev, 0, 0);
455: ncells += host_encode_phys_addr(props + ncells, arch->rbase);
456: ncells += pci_encode_size(props + ncells, arch->rlen);
457: }
458: if (arch->host_mem_base) {
459: ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32,
460: config->dev, 0, arch->pci_mem_base);
461: ncells += host_encode_phys_addr(props + ncells, arch->host_mem_base);
462: ncells += pci_encode_size(props + ncells, arch->mem_len);
463: }
464: set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
465: }
466:
467: static unsigned long pci_bus_addr_to_host_addr(uint32_t ba)
468: {
469: #ifdef CONFIG_SPARC64
470: return arch->cfg_data + (unsigned long)ba;
471: #else
472: return (unsigned long)ba;
473: #endif
474: }
475:
476: int host_config_cb(const pci_config_t *config)
477: {
478: //XXX this overrides "reg" property
479: pci_host_set_reg(get_cur_dev());
480: pci_host_set_ranges(config);
481: pci_host_set_interrupt_map(config);
482:
483: return 0;
484: }
485:
486: static int sabre_configure(phandle_t dev)
487: {
488: uint32_t props[28];
489:
490: props[0] = 0xc0000000;
491: props[1] = 0x20000000;
492: set_property(dev, "virtual-dma", (char *)props, 2 * sizeof(props[0]));
493: props[0] = 1;
494: set_property(dev, "#virtual-dma-size-cells", (char *)props,
495: sizeof(props[0]));
496: set_property(dev, "#virtual-dma-addr-cells", (char *)props,
497: sizeof(props[0]));
498: props[0] = 0x000007f0;
499: props[1] = 0x000007ee;
500: props[2] = 0x000007ef;
501: props[3] = 0x000007e5;
502: set_property(dev, "interrupts", (char *)props, 4 * sizeof(props[0]));
503: props[0] = 0x0000001f;
504: set_property(dev, "upa-portid", (char *)props, 1 * sizeof(props[0]));
505: return 0;
506: }
507:
508: int sabre_config_cb(const pci_config_t *config)
509: {
510: host_config_cb(config);
511:
512: return sabre_configure(get_cur_dev());
513: }
514:
515: int bridge_config_cb(const pci_config_t *config)
516: {
517: phandle_t aliases;
518:
519: aliases = find_dev("/aliases");
520: set_property(aliases, "bridge", config->path, strlen(config->path) + 1);
521:
522: return 0;
523: }
524:
525: int ide_config_cb2 (const pci_config_t *config)
526: {
527: ob_ide_init(config->path,
528: config->assigned[0] & ~0x0000000F,
529: config->assigned[1] & ~0x0000000F,
530: config->assigned[2] & ~0x0000000F,
531: config->assigned[3] & ~0x0000000F);
532: return 0;
533: }
534:
535: int eth_config_cb (const pci_config_t *config)
536: {
537: phandle_t ph = get_cur_dev();
538:
539: set_property(ph, "network-type", "ethernet", 9);
540: set_property(ph, "removable", "network", 8);
541: set_property(ph, "category", "net", 4);
542:
543: return 0;
544: }
545:
546: static inline void pci_decode_pci_addr(pci_addr addr, int *flags,
547: int *space_code, uint32_t *mask)
548: {
549: *flags = 0;
550:
551: if (addr & 0x01) {
552: *space_code = IO_SPACE;
553: *mask = 0x00000001;
554: } else {
555: if (addr & 0x04) {
556: *space_code = MEMORY_SPACE_64;
557: *flags |= IS_NOT_RELOCATABLE; /* XXX: why not relocatable? */
558: } else {
559: *space_code = MEMORY_SPACE_32;
560: }
561:
562: if (addr & 0x08) {
563: *flags |= IS_PREFETCHABLE;
564: }
565:
566: *mask = 0x0000000F;
567: }
568: }
569:
570: /*
571: * "Designing PCI Cards and Drivers for Power Macintosh Computers", p. 454
572: *
573: * "AAPL,address" provides an array of 32-bit logical addresses
574: * Nth entry corresponding to Nth "assigned-address" base address entry.
575: */
576:
577: static void pci_set_AAPL_address(const pci_config_t *config)
578: {
579: phandle_t dev = get_cur_dev();
580: cell props[7];
581: int ncells, i;
582:
583: ncells = 0;
584: for (i = 0; i < 6; i++) {
585: if (!config->assigned[i] || !config->sizes[i])
586: continue;
587: props[ncells++] = config->assigned[i] & ~0x0000000F;
588: }
589: if (ncells)
590: set_property(dev, "AAPL,address", (char *)props,
591: ncells * sizeof(cell));
592: }
593:
594: static void pci_set_assigned_addresses(phandle_t phandle,
595: const pci_config_t *config, int num_bars)
596: {
597: phandle_t dev = phandle;
598: u32 props[32];
599: int ncells;
600: int i;
601: uint32_t mask;
602: int flags, space_code;
603:
604: ncells = 0;
605: for (i = 0; i < num_bars; i++) {
606: /* consider only bars with non-zero region size */
607: if (!config->sizes[i])
608: continue;
609: pci_decode_pci_addr(config->assigned[i],
610: &flags, &space_code, &mask);
611:
612: ncells += pci_encode_phys_addr(props + ncells,
613: flags, space_code, config->dev,
614: PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
615: config->assigned[i] & ~mask);
616:
617: props[ncells++] = 0x00000000;
618: props[ncells++] = config->sizes[i];
619: }
620: if (ncells)
621: set_property(dev, "assigned-addresses", (char *)props,
622: ncells * sizeof(props[0]));
623: }
624:
625: /* call after writing "reg" property to update config->path */
626: static void ob_pci_reload_device_path(phandle_t phandle, pci_config_t *config)
627: {
628: /* since "name" and "reg" are now assigned
629: we need to reload current node name */
630:
631: PUSH(phandle);
632: fword("get-package-path");
633: char *new_path = pop_fstr_copy();
634: if (new_path) {
635: if (0 != strcmp(config->path, new_path)) {
636: PCI_DPRINTF("\n=== CHANGED === package path old=%s new=%s\n",
637: config->path, new_path);
638: strncpy(config->path, new_path, sizeof(config->path));
639: config->path[sizeof(config->path)-1] = '\0';
640: }
641: free(new_path);
642: } else {
643: PCI_DPRINTF("\n=== package path old=%s new=NULL\n", config->path);
644: }
645: }
646:
647: static void pci_set_reg(phandle_t phandle,
648: pci_config_t *config, int num_bars)
649: {
650: phandle_t dev = phandle;
651: u32 props[38];
652: int ncells;
653: int i;
654: uint32_t mask;
655: int space_code, flags;
656:
657: ncells = 0;
658:
659: /* first (addr, size) pair is the beginning of configuration address space */
660: ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE,
661: config->dev, 0, 0);
662:
663: ncells += pci_encode_size(props + ncells, 0);
664:
665: for (i = 0; i < num_bars; i++) {
666: /* consider only bars with non-zero region size */
667: if (!config->sizes[i])
668: continue;
669:
670: pci_decode_pci_addr(config->regions[i],
671: &flags, &space_code, &mask);
672:
673: ncells += pci_encode_phys_addr(props + ncells,
674: flags, space_code, config->dev,
675: PCI_BASE_ADDR_0 + (i * sizeof(uint32_t)),
676: config->regions[i] & ~mask);
677:
678: /* set size */
679: ncells += pci_encode_size(props + ncells, config->sizes[i]);
680: }
681:
682: set_property(dev, "reg", (char *)props, ncells * sizeof(props[0]));
683: ob_pci_reload_device_path(dev, config);
684:
685: #if defined(CONFIG_DEBUG_PCI)
686: dump_reg_property("pci_set_reg", ncells, props);
687: #endif
688: }
689:
690:
691: static void pci_set_ranges(const pci_config_t *config)
692: {
693: phandle_t dev = get_cur_dev();
694: u32 props[32];
695: int ncells;
696: int i;
697: uint32_t mask;
698: int flags;
699: int space_code;
700:
701: ncells = 0;
702: for (i = 0; i < 6; i++) {
703: if (!config->assigned[i] || !config->sizes[i])
704: continue;
705:
706: /* child address */
707:
708: props[ncells++] = 0x00000000;
709:
710: /* parent address */
711:
712: pci_decode_pci_addr(config->assigned[i],
713: &flags, &space_code, &mask);
714: ncells += pci_encode_phys_addr(props + ncells, flags, space_code,
715: config->dev, 0x10 + i * 4,
716: config->assigned[i] & ~mask);
717:
718: /* size */
719:
720: props[ncells++] = config->sizes[i];
721: }
722: set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0]));
723: }
724:
725: int macio_heathrow_config_cb (const pci_config_t *config)
726: {
727: pci_set_ranges(config);
728:
729: #ifdef CONFIG_DRIVER_MACIO
730: ob_macio_heathrow_init(config->path, config->assigned[0] & ~0x0000000F);
731: #endif
732: return 0;
733: }
734:
735: int macio_keylargo_config_cb (const pci_config_t *config)
736: {
737: pci_set_ranges(config);
738:
739: #ifdef CONFIG_DRIVER_MACIO
740: ob_macio_keylargo_init(config->path, config->assigned[0] & ~0x0000000F);
741: #endif
742: return 0;
743: }
744:
745: int vga_config_cb (const pci_config_t *config)
746: {
747: if (config->assigned[0] != 0x00000000)
748: vga_vbe_init(config->path,
749: pci_bus_addr_to_host_addr(config->assigned[0] & ~0x0000000F),
750: config->sizes[0],
751: pci_bus_addr_to_host_addr(config->assigned[1] & ~0x0000000F),
752: config->sizes[1]);
753: return 0;
754: }
755:
756: int ebus_config_cb(const pci_config_t *config)
757: {
758: #ifdef CONFIG_DRIVER_EBUS
759: #ifdef CONFIG_DRIVER_FLOPPY
760: ob_floppy_init(config->path, "fdthree", 0x3f0ULL, 0);
761: #endif
762: #ifdef CONFIG_DRIVER_PC_SERIAL
763: ob_pc_serial_init(config->path, "su", arch->io_base, 0x3f8ULL, 0);
764: #endif
765: #ifdef CONFIG_DRIVER_PC_KBD
766: ob_pc_kbd_init(config->path, "kb_ps2", arch->io_base, 0x60ULL, 0);
767: #endif
768: #endif
769: return 0;
770: }
771:
772: static void ob_pci_add_properties(phandle_t phandle,
773: pci_addr addr, const pci_dev_t *pci_dev,
774: const pci_config_t *config, int num_bars)
775: {
776: /* cannot use get_cur_dev() path resolution since "name" and "reg"
777: properties are being changed */
778: phandle_t dev=phandle;
779: int status,id;
780: uint16_t vendor_id, device_id;
781: uint8_t rev;
782: uint32_t class_code;
783:
784: vendor_id = pci_config_read16(addr, PCI_VENDOR_ID);
785: device_id = pci_config_read16(addr, PCI_DEVICE_ID);
786: rev = pci_config_read8(addr, PCI_REVISION_ID);
787: class_code = pci_config_read16(addr, PCI_CLASS_DEVICE);
788:
789: if (pci_dev) {
790: /**/
791: if (pci_dev->name) {
792: push_str(pci_dev->name);
793: fword("encode-string");
794: push_str("name");
795: fword("property");
796: } else {
797: char path[256];
798: snprintf(path, sizeof(path),
799: "pci%x,%x", vendor_id, device_id);
800: push_str(path);
801: fword("encode-string");
802: push_str("name");
803: fword("property");
804: }
805: } else {
806: PCI_DPRINTF("*** missing pci_dev\n");
807: }
808:
809: /* create properties as described in 2.5 */
810:
811: set_int_property(dev, "vendor-id", vendor_id);
812: set_int_property(dev, "device-id", device_id);
813: set_int_property(dev, "revision-id", rev);
814: set_int_property(dev, "class-code", class_code << 8);
815:
816: if (config->irq_pin) {
817: OLDWORLD(set_int_property(dev, "AAPL,interrupts",
818: config->irq_line));
819: set_int_property(dev, "interrupts", config->irq_pin);
820: }
821:
822: set_int_property(dev, "min-grant", pci_config_read8(addr, PCI_MIN_GNT));
823: set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT));
824:
825: status=pci_config_read16(addr, PCI_STATUS);
826:
827: set_int_property(dev, "devsel-speed",
828: (status&PCI_STATUS_DEVSEL_MASK)>>10);
829:
830: if(status&PCI_STATUS_FAST_BACK)
831: set_bool_property(dev, "fast-back-to-back");
832: if(status&PCI_STATUS_66MHZ)
833: set_bool_property(dev, "66mhz-capable");
834: if(status&PCI_STATUS_UDF)
835: set_bool_property(dev, "udf-supported");
836:
837: id=pci_config_read16(addr, PCI_SUBSYSTEM_VENDOR_ID);
838: if(id)
839: set_int_property(dev, "subsystem-vendor-id", id);
840: id=pci_config_read16(addr, PCI_SUBSYSTEM_ID);
841: if(id)
842: set_int_property(dev, "subsystem-id", id);
843:
844: set_int_property(dev, "cache-line-size",
845: pci_config_read16(addr, PCI_CACHE_LINE_SIZE));
846:
847: if (pci_dev) {
848: if (pci_dev->type) {
849: push_str(pci_dev->type);
850: fword("encode-string");
851: push_str("device_type");
852: fword("property");
853: }
854: if (pci_dev->model) {
855: push_str(pci_dev->model);
856: fword("encode-string");
857: push_str("model");
858: fword("property");
859: }
860: if (pci_dev->compat)
861: set_property(dev, "compatible",
862: pci_dev->compat, pci_compat_len(pci_dev));
863:
864: if (pci_dev->acells)
865: set_int_property(dev, "#address-cells",
866: pci_dev->acells);
867: if (pci_dev->scells)
868: set_int_property(dev, "#size-cells",
869: pci_dev->scells);
870: if (pci_dev->icells)
871: set_int_property(dev, "#interrupt-cells",
872: pci_dev->icells);
873: }
874:
875: pci_set_assigned_addresses(phandle, config, num_bars);
876: OLDWORLD(pci_set_AAPL_address(config));
877:
878: PCI_DPRINTF("\n");
879: }
880:
881: #ifdef CONFIG_XBOX
882: static char pci_xbox_blacklisted (int bus, int devnum, int fn)
883: {
884: /*
885: * The Xbox MCPX chipset is a derivative of the nForce 1
886: * chipset. It almost has the same bus layout; some devices
887: * cannot be used, because they have been removed.
888: */
889:
890: /*
891: * Devices 00:00.1 and 00:00.2 used to be memory controllers on
892: * the nForce chipset, but on the Xbox, using them will lockup
893: * the chipset.
894: */
895: if ((bus == 0) && (devnum == 0) && ((fn == 1) || (fn == 2)))
896: return 1;
897:
898: /*
899: * Bus 1 only contains a VGA controller at 01:00.0. When you try
900: * to probe beyond that device, you only get garbage, which
901: * could cause lockups.
902: */
903: if ((bus == 1) && ((devnum != 0) || (fn != 0)))
904: return 1;
905:
906: /*
907: * Bus 2 used to contain the AGP controller, but the Xbox MCPX
908: * doesn't have one. Probing it can cause lockups.
909: */
910: if (bus >= 2)
911: return 1;
912:
913: /*
914: * The device is not blacklisted.
915: */
916: return 0;
917: }
918: #endif
919:
920: static void ob_pci_configure_bar(pci_addr addr, pci_config_t *config,
921: int reg, int config_addr,
922: uint32_t *p_omask,
923: unsigned long *mem_base,
924: unsigned long *io_base)
925: {
926: uint32_t smask, amask, size, reloc, min_align;
927: unsigned long base;
928:
929: config->assigned[reg] = 0x00000000;
930: config->sizes[reg] = 0x00000000;
931:
932: if ((*p_omask & 0x0000000f) == 0x4) {
933: /* 64 bits memory mapping */
1.1.1.2 ! root 934: PCI_DPRINTF("Skipping 64 bit BARs for %s\n", config->path);
1.1 root 935: return;
936: }
937:
938: config->regions[reg] = pci_config_read32(addr, config_addr);
939:
940: /* get region size */
941:
942: pci_config_write32(addr, config_addr, 0xffffffff);
943: smask = pci_config_read32(addr, config_addr);
944: if (smask == 0x00000000 || smask == 0xffffffff)
945: return;
946:
947: if (smask & 0x00000001 && reg != 6) {
948: /* I/O space */
949: base = *io_base;
950: min_align = 1 << 7;
951: amask = 0x00000001;
952: } else {
953: /* Memory Space */
954: base = *mem_base;
955: min_align = 1 << 16;
956: amask = 0x0000000F;
957: if (reg == 6) {
958: smask |= 1; /* ROM */
959: }
960: }
961: *p_omask = smask & amask;
962: smask &= ~amask;
963: size = (~smask) + 1;
964: config->sizes[reg] = size;
965: reloc = base;
966: if (size < min_align)
967: size = min_align;
968: reloc = (reloc + size -1) & ~(size - 1);
969: if (*io_base == base) {
1.1.1.2 ! root 970: PCI_DPRINTF("changing io_base from 0x%lx to 0x%x\n",
! 971: *io_base, reloc + size);
1.1 root 972: *io_base = reloc + size;
973: } else {
1.1.1.2 ! root 974: PCI_DPRINTF("changing mem_base from 0x%lx to 0x%x\n",
! 975: *mem_base, reloc + size);
1.1 root 976: *mem_base = reloc + size;
977: }
1.1.1.2 ! root 978: PCI_DPRINTF("Configuring BARs for %s: reloc 0x%x omask 0x%x "
! 979: "io_base 0x%lx mem_base 0x%lx size 0x%x\n",
! 980: config->path, reloc, *p_omask, *io_base, *mem_base, size);
1.1 root 981: pci_config_write32(addr, config_addr, reloc | *p_omask);
982: config->assigned[reg] = reloc | *p_omask;
983: }
984:
985: static void ob_pci_configure_irq(pci_addr addr, pci_config_t *config)
986: {
987: uint8_t irq_pin, irq_line;
988:
989: irq_pin = pci_config_read8(addr, PCI_INTERRUPT_PIN);
990: if (irq_pin) {
991: config->irq_pin = irq_pin;
992: irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3;
993: irq_line = arch->irqs[irq_pin];
994: pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line);
995: config->irq_line = irq_line;
996: } else
997: config->irq_line = -1;
998: }
999:
1000: static void
1001: ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
1002: unsigned long *mem_base, unsigned long *io_base)
1003:
1004: {
1005: uint32_t omask;
1006: uint16_t cmd;
1007: int reg;
1008: pci_addr config_addr;
1009:
1010: ob_pci_configure_irq(addr, config);
1011:
1012: omask = 0x00000000;
1013: for (reg = 0; reg < num_regs; ++reg) {
1014: config_addr = PCI_BASE_ADDR_0 + reg * 4;
1015:
1016: ob_pci_configure_bar(addr, config, reg, config_addr,
1017: &omask, mem_base,
1018: io_base);
1019: }
1020:
1021: if (rom_bar) {
1022: config_addr = rom_bar;
1023: ob_pci_configure_bar(addr, config, reg, config_addr,
1024: &omask, mem_base, io_base);
1025: }
1026: cmd = pci_config_read16(addr, PCI_COMMAND);
1027: cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
1028: pci_config_write16(addr, PCI_COMMAND, cmd);
1029: }
1030:
1031: static void ob_configure_pci_device(const char* parent_path,
1032: int *bus_num, unsigned long *mem_base, unsigned long *io_base,
1033: int bus, int devnum, int fn, int *p_is_multi);
1034:
1035: static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base,
1036: unsigned long *io_base, const char *path,
1037: int bus)
1038: {
1039: int devnum, fn, is_multi;
1040:
1041: PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path);
1042:
1043: for (devnum = 0; devnum < 32; devnum++) {
1044: is_multi = 0;
1045: for (fn = 0; fn==0 || (is_multi && fn<8); fn++) {
1046: ob_configure_pci_device(path, bus_num, mem_base, io_base,
1047: bus, devnum, fn, &is_multi);
1048:
1049: }
1050: }
1051: }
1052:
1053: static void ob_configure_pci_bridge(pci_addr addr,
1054: int *bus_num, unsigned long *mem_base,
1055: unsigned long *io_base,
1056: int primary_bus, pci_config_t *config)
1057: {
1058: config->primary_bus = primary_bus;
1059: pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus);
1060:
1061: config->secondary_bus = *bus_num;
1062: pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus);
1063:
1064: config->subordinate_bus = 0xff;
1065: pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
1066:
1067: PCI_DPRINTF("scanning new pci bus %u under bridge %s\n",
1068: config->secondary_bus, config->path);
1069:
1070: /* make pci bridge parent device, prepare for recursion */
1071:
1072: ob_scan_pci_bus(bus_num, mem_base, io_base,
1073: config->path, config->secondary_bus);
1074:
1075: /* bus scan updates *bus_num to last revealed pci bus number */
1076: config->subordinate_bus = *bus_num;
1077: pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
1078:
1079: PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n",
1080: config->path, config->primary_bus, config->secondary_bus,
1081: config->subordinate_bus);
1082:
1083: pci_set_bus_range(config);
1084: }
1085:
1086: static int ob_pci_read_identification(int bus, int devnum, int fn,
1087: int *p_vid, int *p_did,
1088: uint8_t *p_class, uint8_t *p_subclass)
1089: {
1090: int vid, did;
1091: uint32_t ccode;
1092: pci_addr addr;
1093:
1094: #ifdef CONFIG_XBOX
1095: if (pci_xbox_blacklisted (bus, devnum, fn))
1096: return;
1097: #endif
1098: addr = PCI_ADDR(bus, devnum, fn);
1099: vid = pci_config_read16(addr, PCI_VENDOR_ID);
1100: did = pci_config_read16(addr, PCI_DEVICE_ID);
1101:
1102: if (vid==0xffff || vid==0) {
1103: return 0;
1104: }
1105:
1106: if (p_vid) {
1107: *p_vid = vid;
1108: }
1109:
1110: if (p_did) {
1111: *p_did = did;
1112: }
1113:
1114: ccode = pci_config_read16(addr, PCI_CLASS_DEVICE);
1115:
1116: if (p_class) {
1117: *p_class = ccode >> 8;
1118: }
1119:
1120: if (p_subclass) {
1121: *p_subclass = ccode;
1122: }
1123:
1124: return 1;
1125: }
1126:
1127: static void ob_configure_pci_device(const char* parent_path,
1128: int *bus_num, unsigned long *mem_base, unsigned long *io_base,
1129: int bus, int devnum, int fn, int *p_is_multi)
1130: {
1131: int vid, did;
1132: unsigned int htype;
1133: pci_addr addr;
1134: pci_config_t config = {};
1135: const pci_dev_t *pci_dev;
1136: uint8_t class, subclass, iface;
1137: int num_bars, rom_bar;
1138:
1139: phandle_t phandle = 0;
1140: int is_host_bridge = 0;
1141:
1142: if (!ob_pci_read_identification(bus, devnum, fn, &vid, &did, &class, &subclass)) {
1143: return;
1144: }
1145:
1146: addr = PCI_ADDR(bus, devnum, fn);
1147: iface = pci_config_read8(addr, PCI_CLASS_PROG);
1148:
1149: pci_dev = pci_find_device(class, subclass, iface,
1150: vid, did);
1151:
1152: PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn,
1153: vid, did);
1154:
1155: htype = pci_config_read8(addr, PCI_HEADER_TYPE);
1156:
1157: if (fn == 0) {
1158: if (p_is_multi) {
1159: *p_is_multi = htype & 0x80;
1160: }
1161: }
1162:
1163: /* stop adding host bridge accessible from it's primary bus
1164: PCI host bridge is to be added by host code
1165: */
1166: if (class == PCI_BASE_CLASS_BRIDGE &&
1167: subclass == PCI_SUBCLASS_BRIDGE_HOST) {
1168: is_host_bridge = 1;
1169: }
1170:
1171: if (is_host_bridge) {
1172: /* reuse device tree node */
1173: PCI_DPRINTF("host bridge found - ");
1174: snprintf(config.path, sizeof(config.path),
1175: "%s", parent_path);
1176: } else if (pci_dev == NULL || pci_dev->name == NULL) {
1177: snprintf(config.path, sizeof(config.path),
1178: "%s/pci%x,%x", parent_path, vid, did);
1179: }
1180: else {
1181: snprintf(config.path, sizeof(config.path),
1182: "%s/%s", parent_path, pci_dev->name);
1183: }
1184:
1185: PCI_DPRINTF("%s - ", config.path);
1186:
1187: config.dev = addr & 0x00FFFFFF;
1188:
1189: switch (class) {
1190: case PCI_BASE_CLASS_BRIDGE:
1191: if (subclass != PCI_SUBCLASS_BRIDGE_HOST) {
1192: REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle);
1193: }
1194: break;
1195: default:
1196: REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle);
1197: break;
1198: }
1199:
1200: if (is_host_bridge) {
1201: phandle = find_dev(config.path);
1202:
1203: if (get_property(phandle, "vendor-id", NULL)) {
1204: PCI_DPRINTF("host bridge already configured\n");
1205: return;
1206: }
1207: }
1208:
1209: activate_dev(phandle);
1210:
1211: if (htype & PCI_HEADER_TYPE_BRIDGE) {
1212: num_bars = 2;
1213: rom_bar = PCI_ROM_ADDRESS1;
1214: } else {
1215: num_bars = 6;
1216: rom_bar = PCI_ROM_ADDRESS;
1217: }
1218:
1219: ob_pci_configure(addr, &config, num_bars, rom_bar,
1220: mem_base, io_base);
1221:
1222: ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars);
1223:
1224: if (!is_host_bridge) {
1225: pci_set_reg(phandle, &config, num_bars);
1226: }
1227:
1228: /* call device-specific configuration callback */
1229: if (pci_dev && pci_dev->config_cb) {
1230: //activate_device(config.path);
1231: pci_dev->config_cb(&config);
1232: }
1233:
1234: /* device is configured so we may move it out of scope */
1235: device_end();
1236:
1237: /* scan bus behind bridge device */
1238: //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) {
1239: if ( class == PCI_BASE_CLASS_BRIDGE &&
1240: ( subclass == PCI_SUBCLASS_BRIDGE_PCI ||
1241: subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) {
1242:
1243: if (subclass == PCI_SUBCLASS_BRIDGE_PCI) {
1244: /* reserve next pci bus number for this PCI bridge */
1245: ++(*bus_num);
1246: }
1247:
1248: ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config);
1249: }
1250: }
1251:
1252: int ob_pci_init(void)
1253: {
1254: int bus, devnum, fn;
1255: uint8_t class, subclass;
1256: unsigned long mem_base, io_base;
1257:
1258: pci_config_t config = {}; /* host bridge */
1259: phandle_t phandle_host;
1260:
1261: PCI_DPRINTF("Initializing PCI host bridge...\n");
1262:
1263: activate_device("/");
1264:
1265: /* Find all PCI bridges */
1266:
1267: mem_base = arch->pci_mem_base;
1268: /* I/O ports under 0x400 are used by devices mapped at fixed
1269: location. */
1.1.1.2 ! root 1270: io_base = 0x400;
1.1 root 1271:
1272: bus = 0;
1273:
1274: for (devnum = 0; devnum < 32; devnum++) {
1275: /* scan only fn 0 */
1276: fn = 0;
1277:
1278: if (!ob_pci_read_identification(bus, devnum, fn,
1279: 0, 0, &class, &subclass)) {
1280: continue;
1281: }
1282:
1283: if (class != PCI_BASE_CLASS_BRIDGE || subclass != PCI_SUBCLASS_BRIDGE_HOST) {
1284: continue;
1285: }
1286:
1287: /* create root node for host PCI bridge */
1288:
1289: /* configure */
1290: snprintf(config.path, sizeof(config.path), "/pci");
1291:
1292: REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host);
1293:
1294: pci_host_set_reg(phandle_host);
1295:
1296: /* update device path after changing "reg" property */
1297: ob_pci_reload_device_path(phandle_host, &config);
1298:
1299: ob_configure_pci_device(config.path, &bus, &mem_base, &io_base,
1300: bus, devnum, fn, 0);
1301:
1302: /* we expect single host PCI bridge
1303: but this may be machine-specific */
1304: break;
1305: }
1306:
1307:
1308: device_end();
1309:
1310: return 0;
1311: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.