Annotation of qemu/hw/pci.c, revision 1.1.1.5

1.1       root        1: /*
                      2:  * QEMU PCI bus manager
                      3:  *
                      4:  * Copyright (c) 2004 Fabrice Bellard
                      5:  * 
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: #include "vl.h"
                     25: 
                     26: //#define DEBUG_PCI
                     27: 
                     28: struct PCIBus {
                     29:     int bus_num;
                     30:     int devfn_min;
1.1.1.4   root       31:     pci_set_irq_fn set_irq;
1.1.1.5 ! root       32:     pci_map_irq_fn map_irq;
1.1       root       33:     uint32_t config_reg; /* XXX: suppress */
                     34:     /* low level pic */
                     35:     SetIRQFunc *low_set_irq;
                     36:     void *irq_opaque;
                     37:     PCIDevice *devices[256];
1.1.1.5 ! root       38:     PCIDevice *parent_dev;
        !            39:     PCIBus *next;
        !            40:     /* The bus IRQ state is the logical OR of the connected devices.
        !            41:        Keep a count of the number of devices with raised IRQs.  */
        !            42:     int irq_count[];
1.1       root       43: };
                     44: 
1.1.1.5 ! root       45: static void pci_update_mappings(PCIDevice *d);
        !            46: 
1.1       root       47: target_phys_addr_t pci_mem_base;
                     48: static int pci_irq_index;
                     49: static PCIBus *first_bus;
                     50: 
1.1.1.5 ! root       51: PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
        !            52:                          void *pic, int devfn_min, int nirq)
1.1       root       53: {
                     54:     PCIBus *bus;
1.1.1.5 ! root       55:     bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
1.1.1.4   root       56:     bus->set_irq = set_irq;
1.1.1.5 ! root       57:     bus->map_irq = map_irq;
1.1.1.4   root       58:     bus->irq_opaque = pic;
                     59:     bus->devfn_min = devfn_min;
1.1       root       60:     first_bus = bus;
                     61:     return bus;
                     62: }
                     63: 
1.1.1.5 ! root       64: PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
        !            65: {
        !            66:     PCIBus *bus;
        !            67:     bus = qemu_mallocz(sizeof(PCIBus));
        !            68:     bus->map_irq = map_irq;
        !            69:     bus->parent_dev = dev;
        !            70:     bus->next = dev->bus->next;
        !            71:     dev->bus->next = bus;
        !            72:     return bus;
        !            73: }
        !            74: 
1.1.1.4   root       75: int pci_bus_num(PCIBus *s)
                     76: {
                     77:     return s->bus_num;
                     78: }
                     79: 
1.1.1.5 ! root       80: void pci_device_save(PCIDevice *s, QEMUFile *f)
1.1       root       81: {
1.1.1.5 ! root       82:     qemu_put_be32(f, 1); /* PCI device version */
1.1       root       83:     qemu_put_buffer(f, s->config, 256);
                     84: }
                     85: 
1.1.1.5 ! root       86: int pci_device_load(PCIDevice *s, QEMUFile *f)
1.1       root       87: {
1.1.1.5 ! root       88:     uint32_t version_id;
        !            89:     version_id = qemu_get_be32(f);
1.1       root       90:     if (version_id != 1)
                     91:         return -EINVAL;
                     92:     qemu_get_buffer(f, s->config, 256);
1.1.1.5 ! root       93:     pci_update_mappings(s);
1.1       root       94:     return 0;
                     95: }
                     96: 
                     97: /* -1 for devfn means auto assign */
                     98: PCIDevice *pci_register_device(PCIBus *bus, const char *name, 
                     99:                                int instance_size, int devfn,
                    100:                                PCIConfigReadFunc *config_read, 
                    101:                                PCIConfigWriteFunc *config_write)
                    102: {
                    103:     PCIDevice *pci_dev;
                    104: 
                    105:     if (pci_irq_index >= PCI_DEVICES_MAX)
                    106:         return NULL;
                    107:     
                    108:     if (devfn < 0) {
                    109:         for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
                    110:             if (!bus->devices[devfn])
                    111:                 goto found;
                    112:         }
                    113:         return NULL;
                    114:     found: ;
                    115:     }
                    116:     pci_dev = qemu_mallocz(instance_size);
                    117:     if (!pci_dev)
                    118:         return NULL;
                    119:     pci_dev->bus = bus;
                    120:     pci_dev->devfn = devfn;
                    121:     pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
1.1.1.5 ! root      122:     memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
1.1       root      123: 
                    124:     if (!config_read)
                    125:         config_read = pci_default_read_config;
                    126:     if (!config_write)
                    127:         config_write = pci_default_write_config;
                    128:     pci_dev->config_read = config_read;
                    129:     pci_dev->config_write = config_write;
                    130:     pci_dev->irq_index = pci_irq_index++;
                    131:     bus->devices[devfn] = pci_dev;
                    132:     return pci_dev;
                    133: }
                    134: 
                    135: void pci_register_io_region(PCIDevice *pci_dev, int region_num, 
                    136:                             uint32_t size, int type, 
                    137:                             PCIMapIORegionFunc *map_func)
                    138: {
                    139:     PCIIORegion *r;
1.1.1.3   root      140:     uint32_t addr;
1.1       root      141: 
                    142:     if ((unsigned int)region_num >= PCI_NUM_REGIONS)
                    143:         return;
                    144:     r = &pci_dev->io_regions[region_num];
                    145:     r->addr = -1;
                    146:     r->size = size;
                    147:     r->type = type;
                    148:     r->map_func = map_func;
1.1.1.3   root      149:     if (region_num == PCI_ROM_SLOT) {
                    150:         addr = 0x30;
                    151:     } else {
                    152:         addr = 0x10 + region_num * 4;
                    153:     }
                    154:     *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
1.1       root      155: }
                    156: 
1.1.1.4   root      157: target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
1.1       root      158: {
1.1.1.4   root      159:     return addr + pci_mem_base;
1.1       root      160: }
                    161: 
                    162: static void pci_update_mappings(PCIDevice *d)
                    163: {
                    164:     PCIIORegion *r;
                    165:     int cmd, i;
                    166:     uint32_t last_addr, new_addr, config_ofs;
                    167:     
                    168:     cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
                    169:     for(i = 0; i < PCI_NUM_REGIONS; i++) {
                    170:         r = &d->io_regions[i];
                    171:         if (i == PCI_ROM_SLOT) {
                    172:             config_ofs = 0x30;
                    173:         } else {
                    174:             config_ofs = 0x10 + i * 4;
                    175:         }
                    176:         if (r->size != 0) {
                    177:             if (r->type & PCI_ADDRESS_SPACE_IO) {
                    178:                 if (cmd & PCI_COMMAND_IO) {
                    179:                     new_addr = le32_to_cpu(*(uint32_t *)(d->config + 
                    180:                                                          config_ofs));
                    181:                     new_addr = new_addr & ~(r->size - 1);
                    182:                     last_addr = new_addr + r->size - 1;
                    183:                     /* NOTE: we have only 64K ioports on PC */
                    184:                     if (last_addr <= new_addr || new_addr == 0 ||
                    185:                         last_addr >= 0x10000) {
                    186:                         new_addr = -1;
                    187:                     }
                    188:                 } else {
                    189:                     new_addr = -1;
                    190:                 }
                    191:             } else {
                    192:                 if (cmd & PCI_COMMAND_MEMORY) {
                    193:                     new_addr = le32_to_cpu(*(uint32_t *)(d->config + 
                    194:                                                          config_ofs));
                    195:                     /* the ROM slot has a specific enable bit */
                    196:                     if (i == PCI_ROM_SLOT && !(new_addr & 1))
                    197:                         goto no_mem_map;
                    198:                     new_addr = new_addr & ~(r->size - 1);
                    199:                     last_addr = new_addr + r->size - 1;
                    200:                     /* NOTE: we do not support wrapping */
                    201:                     /* XXX: as we cannot support really dynamic
                    202:                        mappings, we handle specific values as invalid
                    203:                        mappings. */
                    204:                     if (last_addr <= new_addr || new_addr == 0 ||
                    205:                         last_addr == -1) {
                    206:                         new_addr = -1;
                    207:                     }
                    208:                 } else {
                    209:                 no_mem_map:
                    210:                     new_addr = -1;
                    211:                 }
                    212:             }
                    213:             /* now do the real mapping */
                    214:             if (new_addr != r->addr) {
                    215:                 if (r->addr != -1) {
                    216:                     if (r->type & PCI_ADDRESS_SPACE_IO) {
                    217:                         int class;
                    218:                         /* NOTE: specific hack for IDE in PC case:
                    219:                            only one byte must be mapped. */
                    220:                         class = d->config[0x0a] | (d->config[0x0b] << 8);
                    221:                         if (class == 0x0101 && r->size == 4) {
                    222:                             isa_unassign_ioport(r->addr + 2, 1);
                    223:                         } else {
                    224:                             isa_unassign_ioport(r->addr, r->size);
                    225:                         }
                    226:                     } else {
1.1.1.4   root      227:                         cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
1.1       root      228:                                                      r->size, 
                    229:                                                      IO_MEM_UNASSIGNED);
                    230:                     }
                    231:                 }
                    232:                 r->addr = new_addr;
                    233:                 if (r->addr != -1) {
                    234:                     r->map_func(d, i, r->addr, r->size, r->type);
                    235:                 }
                    236:             }
                    237:         }
                    238:     }
                    239: }
                    240: 
                    241: uint32_t pci_default_read_config(PCIDevice *d, 
                    242:                                  uint32_t address, int len)
                    243: {
                    244:     uint32_t val;
1.1.1.5 ! root      245: 
1.1       root      246:     switch(len) {
                    247:     default:
                    248:     case 4:
1.1.1.5 ! root      249:        if (address <= 0xfc) {
        !           250:            val = le32_to_cpu(*(uint32_t *)(d->config + address));
        !           251:            break;
        !           252:        }
        !           253:        /* fall through */
        !           254:     case 2:
        !           255:         if (address <= 0xfe) {
        !           256:            val = le16_to_cpu(*(uint16_t *)(d->config + address));
        !           257:            break;
        !           258:        }
        !           259:        /* fall through */
        !           260:     case 1:
        !           261:         val = d->config[address];
1.1       root      262:         break;
                    263:     }
                    264:     return val;
                    265: }
                    266: 
                    267: void pci_default_write_config(PCIDevice *d, 
                    268:                               uint32_t address, uint32_t val, int len)
                    269: {
                    270:     int can_write, i;
                    271:     uint32_t end, addr;
                    272: 
                    273:     if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || 
                    274:                      (address >= 0x30 && address < 0x34))) {
                    275:         PCIIORegion *r;
                    276:         int reg;
                    277: 
                    278:         if ( address >= 0x30 ) {
                    279:             reg = PCI_ROM_SLOT;
                    280:         }else{
                    281:             reg = (address - 0x10) >> 2;
                    282:         }
                    283:         r = &d->io_regions[reg];
                    284:         if (r->size == 0)
                    285:             goto default_config;
                    286:         /* compute the stored value */
                    287:         if (reg == PCI_ROM_SLOT) {
                    288:             /* keep ROM enable bit */
                    289:             val &= (~(r->size - 1)) | 1;
                    290:         } else {
                    291:             val &= ~(r->size - 1);
                    292:             val |= r->type;
                    293:         }
                    294:         *(uint32_t *)(d->config + address) = cpu_to_le32(val);
                    295:         pci_update_mappings(d);
                    296:         return;
                    297:     }
                    298:  default_config:
                    299:     /* not efficient, but simple */
                    300:     addr = address;
                    301:     for(i = 0; i < len; i++) {
                    302:         /* default read/write accesses */
                    303:         switch(d->config[0x0e]) {
                    304:         case 0x00:
                    305:         case 0x80:
                    306:             switch(addr) {
                    307:             case 0x00:
                    308:             case 0x01:
                    309:             case 0x02:
                    310:             case 0x03:
                    311:             case 0x08:
                    312:             case 0x09:
                    313:             case 0x0a:
                    314:             case 0x0b:
                    315:             case 0x0e:
                    316:             case 0x10 ... 0x27: /* base */
                    317:             case 0x30 ... 0x33: /* rom */
                    318:             case 0x3d:
                    319:                 can_write = 0;
                    320:                 break;
                    321:             default:
                    322:                 can_write = 1;
                    323:                 break;
                    324:             }
                    325:             break;
                    326:         default:
                    327:         case 0x01:
                    328:             switch(addr) {
                    329:             case 0x00:
                    330:             case 0x01:
                    331:             case 0x02:
                    332:             case 0x03:
                    333:             case 0x08:
                    334:             case 0x09:
                    335:             case 0x0a:
                    336:             case 0x0b:
                    337:             case 0x0e:
                    338:             case 0x38 ... 0x3b: /* rom */
                    339:             case 0x3d:
                    340:                 can_write = 0;
                    341:                 break;
                    342:             default:
                    343:                 can_write = 1;
                    344:                 break;
                    345:             }
                    346:             break;
                    347:         }
                    348:         if (can_write) {
                    349:             d->config[addr] = val;
                    350:         }
1.1.1.5 ! root      351:         if (++addr > 0xff)
        !           352:                break;
1.1       root      353:         val >>= 8;
                    354:     }
                    355: 
                    356:     end = address + len;
                    357:     if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) {
                    358:         /* if the command register is modified, we must modify the mappings */
                    359:         pci_update_mappings(d);
                    360:     }
                    361: }
                    362: 
1.1.1.4   root      363: void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
1.1       root      364: {
                    365:     PCIBus *s = opaque;
                    366:     PCIDevice *pci_dev;
                    367:     int config_addr, bus_num;
                    368:     
                    369: #if defined(DEBUG_PCI) && 0
                    370:     printf("pci_data_write: addr=%08x val=%08x len=%d\n",
1.1.1.4   root      371:            addr, val, len);
1.1       root      372: #endif
1.1.1.4   root      373:     bus_num = (addr >> 16) & 0xff;
1.1.1.5 ! root      374:     while (s && s->bus_num != bus_num)
        !           375:         s = s->next;
        !           376:     if (!s)
1.1       root      377:         return;
1.1.1.4   root      378:     pci_dev = s->devices[(addr >> 8) & 0xff];
1.1       root      379:     if (!pci_dev)
                    380:         return;
1.1.1.4   root      381:     config_addr = addr & 0xff;
1.1       root      382: #if defined(DEBUG_PCI)
                    383:     printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
                    384:            pci_dev->name, config_addr, val, len);
                    385: #endif
                    386:     pci_dev->config_write(pci_dev, config_addr, val, len);
                    387: }
                    388: 
1.1.1.4   root      389: uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
1.1       root      390: {
                    391:     PCIBus *s = opaque;
                    392:     PCIDevice *pci_dev;
                    393:     int config_addr, bus_num;
                    394:     uint32_t val;
                    395: 
1.1.1.4   root      396:     bus_num = (addr >> 16) & 0xff;
1.1.1.5 ! root      397:     while (s && s->bus_num != bus_num)
        !           398:         s= s->next;
        !           399:     if (!s)
1.1       root      400:         goto fail;
1.1.1.4   root      401:     pci_dev = s->devices[(addr >> 8) & 0xff];
1.1       root      402:     if (!pci_dev) {
                    403:     fail:
                    404:         switch(len) {
                    405:         case 1:
                    406:             val = 0xff;
                    407:             break;
                    408:         case 2:
                    409:             val = 0xffff;
                    410:             break;
                    411:         default:
                    412:         case 4:
                    413:             val = 0xffffffff;
                    414:             break;
                    415:         }
                    416:         goto the_end;
                    417:     }
1.1.1.4   root      418:     config_addr = addr & 0xff;
1.1       root      419:     val = pci_dev->config_read(pci_dev, config_addr, len);
                    420: #if defined(DEBUG_PCI)
                    421:     printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
                    422:            pci_dev->name, config_addr, val, len);
                    423: #endif
                    424:  the_end:
                    425: #if defined(DEBUG_PCI) && 0
                    426:     printf("pci_data_read: addr=%08x val=%08x len=%d\n",
1.1.1.4   root      427:            addr, val, len);
1.1       root      428: #endif
                    429:     return val;
                    430: }
                    431: 
1.1.1.4   root      432: /***********************************************************/
                    433: /* generic PCI irq support */
1.1       root      434: 
1.1.1.4   root      435: /* 0 <= irq_num <= 3. level must be 0 or 1 */
                    436: void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
1.1       root      437: {
1.1.1.5 ! root      438:     PCIBus *bus;
        !           439:     int change;
        !           440:     
        !           441:     change = level - pci_dev->irq_state[irq_num];
        !           442:     if (!change)
        !           443:         return;
        !           444: 
        !           445:     pci_dev->irq_state[irq_num] = level;
        !           446:     for (;;) {
        !           447:         bus = pci_dev->bus;
        !           448:         irq_num = bus->map_irq(pci_dev, irq_num);
        !           449:         if (bus->set_irq)
        !           450:             break;
        !           451:         pci_dev = bus->parent_dev;
        !           452:     }
        !           453:     bus->irq_count[irq_num] += change;
        !           454:     bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
1.1       root      455: }
                    456: 
1.1.1.4   root      457: /***********************************************************/
                    458: /* monitor info on PCI */
1.1       root      459: 
1.1.1.4   root      460: typedef struct {
                    461:     uint16_t class;
                    462:     const char *desc;
                    463: } pci_class_desc;
                    464: 
                    465: static pci_class_desc pci_class_descriptions[] = 
                    466: {
1.1.1.5 ! root      467:     { 0x0100, "SCSI controller"},
1.1.1.4   root      468:     { 0x0101, "IDE controller"},
                    469:     { 0x0200, "Ethernet controller"},
                    470:     { 0x0300, "VGA controller"},
                    471:     { 0x0600, "Host bridge"},
                    472:     { 0x0601, "ISA bridge"},
                    473:     { 0x0604, "PCI bridge"},
                    474:     { 0x0c03, "USB controller"},
                    475:     { 0, NULL}
                    476: };
1.1       root      477: 
1.1.1.4   root      478: static void pci_info_device(PCIDevice *d)
1.1       root      479: {
1.1.1.4   root      480:     int i, class;
                    481:     PCIIORegion *r;
                    482:     pci_class_desc *desc;
1.1       root      483: 
1.1.1.4   root      484:     term_printf("  Bus %2d, device %3d, function %d:\n",
                    485:            d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
                    486:     class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
                    487:     term_printf("    ");
                    488:     desc = pci_class_descriptions;
                    489:     while (desc->desc && class != desc->class)
                    490:         desc++;
                    491:     if (desc->desc) {
                    492:         term_printf("%s", desc->desc);
                    493:     } else {
                    494:         term_printf("Class %04x", class);
1.1       root      495:     }
1.1.1.4   root      496:     term_printf(": PCI device %04x:%04x\n",
                    497:            le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
                    498:            le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))));
1.1       root      499: 
1.1.1.4   root      500:     if (d->config[PCI_INTERRUPT_PIN] != 0) {
                    501:         term_printf("      IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
1.1       root      502:     }
1.1.1.5 ! root      503:     if (class == 0x0604) {
        !           504:         term_printf("      BUS %d.\n", d->config[0x19]);
        !           505:     }
1.1.1.4   root      506:     for(i = 0;i < PCI_NUM_REGIONS; i++) {
                    507:         r = &d->io_regions[i];
                    508:         if (r->size != 0) {
                    509:             term_printf("      BAR%d: ", i);
                    510:             if (r->type & PCI_ADDRESS_SPACE_IO) {
                    511:                 term_printf("I/O at 0x%04x [0x%04x].\n", 
                    512:                        r->addr, r->addr + r->size - 1);
                    513:             } else {
                    514:                 term_printf("32 bit memory at 0x%08x [0x%08x].\n", 
                    515:                        r->addr, r->addr + r->size - 1);
                    516:             }
                    517:         }
1.1       root      518:     }
1.1.1.5 ! root      519:     if (class == 0x0604 && d->config[0x19] != 0) {
        !           520:         pci_for_each_device(d->config[0x19], pci_info_device);
        !           521:     }
1.1       root      522: }
                    523: 
1.1.1.5 ! root      524: void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
1.1       root      525: {
1.1.1.4   root      526:     PCIBus *bus = first_bus;
1.1       root      527:     PCIDevice *d;
1.1.1.4   root      528:     int devfn;
1.1       root      529:     
1.1.1.5 ! root      530:     while (bus && bus->bus_num != bus_num)
        !           531:         bus = bus->next;
1.1.1.4   root      532:     if (bus) {
                    533:         for(devfn = 0; devfn < 256; devfn++) {
                    534:             d = bus->devices[devfn];
                    535:             if (d)
                    536:                 fn(d);
                    537:         }
1.1       root      538:     }
                    539: }
                    540: 
1.1.1.4   root      541: void pci_info(void)
1.1       root      542: {
1.1.1.5 ! root      543:     pci_for_each_device(0, pci_info_device);
1.1       root      544: }
1.1.1.3   root      545: 
                    546: /* Initialize a PCI NIC.  */
1.1.1.5 ! root      547: void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
1.1.1.3   root      548: {
                    549:     if (strcmp(nd->model, "ne2k_pci") == 0) {
1.1.1.5 ! root      550:         pci_ne2000_init(bus, nd, devfn);
1.1.1.3   root      551:     } else if (strcmp(nd->model, "rtl8139") == 0) {
1.1.1.5 ! root      552:         pci_rtl8139_init(bus, nd, devfn);
1.1.1.4   root      553:     } else if (strcmp(nd->model, "pcnet") == 0) {
1.1.1.5 ! root      554:         pci_pcnet_init(bus, nd, devfn);
1.1.1.3   root      555:     } else {
                    556:         fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
                    557:         exit (1);
                    558:     }
                    559: }
                    560: 
1.1.1.5 ! root      561: typedef struct {
        !           562:     PCIDevice dev;
        !           563:     PCIBus *bus;
        !           564: } PCIBridge;
        !           565: 
        !           566: void pci_bridge_write_config(PCIDevice *d, 
        !           567:                              uint32_t address, uint32_t val, int len)
        !           568: {
        !           569:     PCIBridge *s = (PCIBridge *)d;
        !           570: 
        !           571:     if (address == 0x19 || (address == 0x18 && len > 1)) {
        !           572:         if (address == 0x19)
        !           573:             s->bus->bus_num = val & 0xff;
        !           574:         else
        !           575:             s->bus->bus_num = (val >> 8) & 0xff;
        !           576: #if defined(DEBUG_PCI)
        !           577:         printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
        !           578: #endif
        !           579:     }
        !           580:     pci_default_write_config(d, address, val, len);
        !           581: }
        !           582: 
        !           583: PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
        !           584:                         pci_map_irq_fn map_irq, const char *name)
        !           585: {
        !           586:     PCIBridge *s;
        !           587:     s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge), 
        !           588:                                          devfn, NULL, pci_bridge_write_config);
        !           589:     s->dev.config[0x00] = id >> 16;
        !           590:     s->dev.config[0x01] = id > 24;
        !           591:     s->dev.config[0x02] = id; // device_id
        !           592:     s->dev.config[0x03] = id >> 8;
        !           593:     s->dev.config[0x04] = 0x06; // command = bus master, pci mem
        !           594:     s->dev.config[0x05] = 0x00;
        !           595:     s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
        !           596:     s->dev.config[0x07] = 0x00; // status = fast devsel
        !           597:     s->dev.config[0x08] = 0x00; // revision
        !           598:     s->dev.config[0x09] = 0x00; // programming i/f
        !           599:     s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge
        !           600:     s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge
        !           601:     s->dev.config[0x0D] = 0x10; // latency_timer
        !           602:     s->dev.config[0x0E] = 0x81; // header_type
        !           603:     s->dev.config[0x1E] = 0xa0; // secondary status
        !           604: 
        !           605:     s->bus = pci_register_secondary_bus(&s->dev, map_irq);
        !           606:     return s->bus;
        !           607: }

unix.superglobalmegacorp.com