Annotation of qemu/roms/openbios/drivers/pci.c, revision 1.1.1.2

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.