|
|
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 */
934: return;
935: }
936:
937: config->regions[reg] = pci_config_read32(addr, config_addr);
938:
939: /* get region size */
940:
941: pci_config_write32(addr, config_addr, 0xffffffff);
942: smask = pci_config_read32(addr, config_addr);
943: if (smask == 0x00000000 || smask == 0xffffffff)
944: return;
945:
946: if (smask & 0x00000001 && reg != 6) {
947: /* I/O space */
948: base = *io_base;
949: min_align = 1 << 7;
950: amask = 0x00000001;
951: } else {
952: /* Memory Space */
953: base = *mem_base;
954: min_align = 1 << 16;
955: amask = 0x0000000F;
956: if (reg == 6) {
957: smask |= 1; /* ROM */
958: }
959: }
960: *p_omask = smask & amask;
961: smask &= ~amask;
962: size = (~smask) + 1;
963: config->sizes[reg] = size;
964: reloc = base;
965: if (size < min_align)
966: size = min_align;
967: reloc = (reloc + size -1) & ~(size - 1);
968: if (*io_base == base) {
969: *io_base = reloc + size;
970: reloc -= arch->io_base;
971: } else {
972: *mem_base = reloc + size;
973: }
974: pci_config_write32(addr, config_addr, reloc | *p_omask);
975: config->assigned[reg] = reloc | *p_omask;
976: }
977:
978: static void ob_pci_configure_irq(pci_addr addr, pci_config_t *config)
979: {
980: uint8_t irq_pin, irq_line;
981:
982: irq_pin = pci_config_read8(addr, PCI_INTERRUPT_PIN);
983: if (irq_pin) {
984: config->irq_pin = irq_pin;
985: irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3;
986: irq_line = arch->irqs[irq_pin];
987: pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line);
988: config->irq_line = irq_line;
989: } else
990: config->irq_line = -1;
991: }
992:
993: static void
994: ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
995: unsigned long *mem_base, unsigned long *io_base)
996:
997: {
998: uint32_t omask;
999: uint16_t cmd;
1000: int reg;
1001: pci_addr config_addr;
1002:
1003: ob_pci_configure_irq(addr, config);
1004:
1005: omask = 0x00000000;
1006: for (reg = 0; reg < num_regs; ++reg) {
1007: config_addr = PCI_BASE_ADDR_0 + reg * 4;
1008:
1009: ob_pci_configure_bar(addr, config, reg, config_addr,
1010: &omask, mem_base,
1011: io_base);
1012: }
1013:
1014: if (rom_bar) {
1015: config_addr = rom_bar;
1016: ob_pci_configure_bar(addr, config, reg, config_addr,
1017: &omask, mem_base, io_base);
1018: }
1019: cmd = pci_config_read16(addr, PCI_COMMAND);
1020: cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
1021: pci_config_write16(addr, PCI_COMMAND, cmd);
1022: }
1023:
1024: static void ob_configure_pci_device(const char* parent_path,
1025: int *bus_num, unsigned long *mem_base, unsigned long *io_base,
1026: int bus, int devnum, int fn, int *p_is_multi);
1027:
1028: static void ob_scan_pci_bus(int *bus_num, unsigned long *mem_base,
1029: unsigned long *io_base, const char *path,
1030: int bus)
1031: {
1032: int devnum, fn, is_multi;
1033:
1034: PCI_DPRINTF("\nScanning bus %d at %s...\n", bus, path);
1035:
1036: for (devnum = 0; devnum < 32; devnum++) {
1037: is_multi = 0;
1038: for (fn = 0; fn==0 || (is_multi && fn<8); fn++) {
1039: ob_configure_pci_device(path, bus_num, mem_base, io_base,
1040: bus, devnum, fn, &is_multi);
1041:
1042: }
1043: }
1044: }
1045:
1046: static void ob_configure_pci_bridge(pci_addr addr,
1047: int *bus_num, unsigned long *mem_base,
1048: unsigned long *io_base,
1049: int primary_bus, pci_config_t *config)
1050: {
1051: config->primary_bus = primary_bus;
1052: pci_config_write8(addr, PCI_PRIMARY_BUS, config->primary_bus);
1053:
1054: config->secondary_bus = *bus_num;
1055: pci_config_write8(addr, PCI_SECONDARY_BUS, config->secondary_bus);
1056:
1057: config->subordinate_bus = 0xff;
1058: pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
1059:
1060: PCI_DPRINTF("scanning new pci bus %u under bridge %s\n",
1061: config->secondary_bus, config->path);
1062:
1063: /* make pci bridge parent device, prepare for recursion */
1064:
1065: ob_scan_pci_bus(bus_num, mem_base, io_base,
1066: config->path, config->secondary_bus);
1067:
1068: /* bus scan updates *bus_num to last revealed pci bus number */
1069: config->subordinate_bus = *bus_num;
1070: pci_config_write8(addr, PCI_SUBORDINATE_BUS, config->subordinate_bus);
1071:
1072: PCI_DPRINTF("bridge %s PCI bus primary=%d secondary=%d subordinate=%d\n",
1073: config->path, config->primary_bus, config->secondary_bus,
1074: config->subordinate_bus);
1075:
1076: pci_set_bus_range(config);
1077: }
1078:
1079: static int ob_pci_read_identification(int bus, int devnum, int fn,
1080: int *p_vid, int *p_did,
1081: uint8_t *p_class, uint8_t *p_subclass)
1082: {
1083: int vid, did;
1084: uint32_t ccode;
1085: pci_addr addr;
1086:
1087: #ifdef CONFIG_XBOX
1088: if (pci_xbox_blacklisted (bus, devnum, fn))
1089: return;
1090: #endif
1091: addr = PCI_ADDR(bus, devnum, fn);
1092: vid = pci_config_read16(addr, PCI_VENDOR_ID);
1093: did = pci_config_read16(addr, PCI_DEVICE_ID);
1094:
1095: if (vid==0xffff || vid==0) {
1096: return 0;
1097: }
1098:
1099: if (p_vid) {
1100: *p_vid = vid;
1101: }
1102:
1103: if (p_did) {
1104: *p_did = did;
1105: }
1106:
1107: ccode = pci_config_read16(addr, PCI_CLASS_DEVICE);
1108:
1109: if (p_class) {
1110: *p_class = ccode >> 8;
1111: }
1112:
1113: if (p_subclass) {
1114: *p_subclass = ccode;
1115: }
1116:
1117: return 1;
1118: }
1119:
1120: static void ob_configure_pci_device(const char* parent_path,
1121: int *bus_num, unsigned long *mem_base, unsigned long *io_base,
1122: int bus, int devnum, int fn, int *p_is_multi)
1123: {
1124: int vid, did;
1125: unsigned int htype;
1126: pci_addr addr;
1127: pci_config_t config = {};
1128: const pci_dev_t *pci_dev;
1129: uint8_t class, subclass, iface;
1130: int num_bars, rom_bar;
1131:
1132: phandle_t phandle = 0;
1133: int is_host_bridge = 0;
1134:
1135: if (!ob_pci_read_identification(bus, devnum, fn, &vid, &did, &class, &subclass)) {
1136: return;
1137: }
1138:
1139: addr = PCI_ADDR(bus, devnum, fn);
1140: iface = pci_config_read8(addr, PCI_CLASS_PROG);
1141:
1142: pci_dev = pci_find_device(class, subclass, iface,
1143: vid, did);
1144:
1145: PCI_DPRINTF("%x:%x.%x - %x:%x - ", bus, devnum, fn,
1146: vid, did);
1147:
1148: htype = pci_config_read8(addr, PCI_HEADER_TYPE);
1149:
1150: if (fn == 0) {
1151: if (p_is_multi) {
1152: *p_is_multi = htype & 0x80;
1153: }
1154: }
1155:
1156: /* stop adding host bridge accessible from it's primary bus
1157: PCI host bridge is to be added by host code
1158: */
1159: if (class == PCI_BASE_CLASS_BRIDGE &&
1160: subclass == PCI_SUBCLASS_BRIDGE_HOST) {
1161: is_host_bridge = 1;
1162: }
1163:
1164: if (is_host_bridge) {
1165: /* reuse device tree node */
1166: PCI_DPRINTF("host bridge found - ");
1167: snprintf(config.path, sizeof(config.path),
1168: "%s", parent_path);
1169: } else if (pci_dev == NULL || pci_dev->name == NULL) {
1170: snprintf(config.path, sizeof(config.path),
1171: "%s/pci%x,%x", parent_path, vid, did);
1172: }
1173: else {
1174: snprintf(config.path, sizeof(config.path),
1175: "%s/%s", parent_path, pci_dev->name);
1176: }
1177:
1178: PCI_DPRINTF("%s - ", config.path);
1179:
1180: config.dev = addr & 0x00FFFFFF;
1181:
1182: switch (class) {
1183: case PCI_BASE_CLASS_BRIDGE:
1184: if (subclass != PCI_SUBCLASS_BRIDGE_HOST) {
1185: REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle);
1186: }
1187: break;
1188: default:
1189: REGISTER_NAMED_NODE_PHANDLE(ob_pci_simple_node, config.path, phandle);
1190: break;
1191: }
1192:
1193: if (is_host_bridge) {
1194: phandle = find_dev(config.path);
1195:
1196: if (get_property(phandle, "vendor-id", NULL)) {
1197: PCI_DPRINTF("host bridge already configured\n");
1198: return;
1199: }
1200: }
1201:
1202: activate_dev(phandle);
1203:
1204: if (htype & PCI_HEADER_TYPE_BRIDGE) {
1205: num_bars = 2;
1206: rom_bar = PCI_ROM_ADDRESS1;
1207: } else {
1208: num_bars = 6;
1209: rom_bar = PCI_ROM_ADDRESS;
1210: }
1211:
1212: ob_pci_configure(addr, &config, num_bars, rom_bar,
1213: mem_base, io_base);
1214:
1215: ob_pci_add_properties(phandle, addr, pci_dev, &config, num_bars);
1216:
1217: if (!is_host_bridge) {
1218: pci_set_reg(phandle, &config, num_bars);
1219: }
1220:
1221: /* call device-specific configuration callback */
1222: if (pci_dev && pci_dev->config_cb) {
1223: //activate_device(config.path);
1224: pci_dev->config_cb(&config);
1225: }
1226:
1227: /* device is configured so we may move it out of scope */
1228: device_end();
1229:
1230: /* scan bus behind bridge device */
1231: //if (htype & PCI_HEADER_TYPE_BRIDGE && class == PCI_BASE_CLASS_BRIDGE) {
1232: if ( class == PCI_BASE_CLASS_BRIDGE &&
1233: ( subclass == PCI_SUBCLASS_BRIDGE_PCI ||
1234: subclass == PCI_SUBCLASS_BRIDGE_HOST ) ) {
1235:
1236: if (subclass == PCI_SUBCLASS_BRIDGE_PCI) {
1237: /* reserve next pci bus number for this PCI bridge */
1238: ++(*bus_num);
1239: }
1240:
1241: ob_configure_pci_bridge(addr, bus_num, mem_base, io_base, bus, &config);
1242: }
1243: }
1244:
1245: int ob_pci_init(void)
1246: {
1247: int bus, devnum, fn;
1248: uint8_t class, subclass;
1249: unsigned long mem_base, io_base;
1250:
1251: pci_config_t config = {}; /* host bridge */
1252: phandle_t phandle_host;
1253:
1254: PCI_DPRINTF("Initializing PCI host bridge...\n");
1255:
1256: activate_device("/");
1257:
1258: /* Find all PCI bridges */
1259:
1260: mem_base = arch->pci_mem_base;
1261: /* I/O ports under 0x400 are used by devices mapped at fixed
1262: location. */
1263: io_base = arch->io_base + 0x400;
1264:
1265: bus = 0;
1266:
1267: for (devnum = 0; devnum < 32; devnum++) {
1268: /* scan only fn 0 */
1269: fn = 0;
1270:
1271: if (!ob_pci_read_identification(bus, devnum, fn,
1272: 0, 0, &class, &subclass)) {
1273: continue;
1274: }
1275:
1276: if (class != PCI_BASE_CLASS_BRIDGE || subclass != PCI_SUBCLASS_BRIDGE_HOST) {
1277: continue;
1278: }
1279:
1280: /* create root node for host PCI bridge */
1281:
1282: /* configure */
1283: snprintf(config.path, sizeof(config.path), "/pci");
1284:
1285: REGISTER_NAMED_NODE_PHANDLE(ob_pci_bus_node, config.path, phandle_host);
1286:
1287: pci_host_set_reg(phandle_host);
1288:
1289: /* update device path after changing "reg" property */
1290: ob_pci_reload_device_path(phandle_host, &config);
1291:
1292: ob_configure_pci_device(config.path, &bus, &mem_base, &io_base,
1293: bus, devnum, fn, 0);
1294:
1295: /* we expect single host PCI bridge
1296: but this may be machine-specific */
1297: break;
1298: }
1299:
1300:
1301: device_end();
1302:
1303: return 0;
1304: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.