pci.c 17.6 KB
Newer Older
B
bellard 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * QEMU PCI bus manager
 *
 * Copyright (c) 2004 Fabrice Bellard
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#include "vl.h"

//#define DEBUG_PCI

28 29 30
struct PCIBus {
    int bus_num;
    int devfn_min;
P
pbrook 已提交
31
    pci_set_irq_fn set_irq;
32
    pci_map_irq_fn map_irq;
33
    uint32_t config_reg; /* XXX: suppress */
34 35 36
    /* low level pic */
    SetIRQFunc *low_set_irq;
    void *irq_opaque;
37
    PCIDevice *devices[256];
P
pbrook 已提交
38 39
    PCIDevice *parent_dev;
    PCIBus *next;
40 41
    /* The bus IRQ state is the logical OR of the connected devices.
       Keep a count of the number of devices with raised IRQs.  */
P
pbrook 已提交
42
    int irq_count[];
43
};
B
bellard 已提交
44

B
bellard 已提交
45 46
static void pci_update_mappings(PCIDevice *d);

B
bellard 已提交
47
target_phys_addr_t pci_mem_base;
48
static int pci_irq_index;
49 50
static PCIBus *first_bus;

51
PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
P
pbrook 已提交
52
                         void *pic, int devfn_min, int nirq)
53 54
{
    PCIBus *bus;
P
pbrook 已提交
55
    bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int)));
P
pbrook 已提交
56
    bus->set_irq = set_irq;
57
    bus->map_irq = map_irq;
P
pbrook 已提交
58 59
    bus->irq_opaque = pic;
    bus->devfn_min = devfn_min;
60 61 62
    first_bus = bus;
    return bus;
}
B
bellard 已提交
63

P
pbrook 已提交
64 65 66 67 68 69 70 71 72 73 74
PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq)
{
    PCIBus *bus;
    bus = qemu_mallocz(sizeof(PCIBus));
    bus->map_irq = map_irq;
    bus->parent_dev = dev;
    bus->next = dev->bus->next;
    dev->bus->next = bus;
    return bus;
}

P
pbrook 已提交
75 76 77 78 79
int pci_bus_num(PCIBus *s)
{
    return s->bus_num;
}

B
bellard 已提交
80
void pci_device_save(PCIDevice *s, QEMUFile *f)
81
{
B
bellard 已提交
82
    qemu_put_be32(f, 1); /* PCI device version */
83 84 85
    qemu_put_buffer(f, s->config, 256);
}

B
bellard 已提交
86
int pci_device_load(PCIDevice *s, QEMUFile *f)
87
{
B
bellard 已提交
88 89
    uint32_t version_id;
    version_id = qemu_get_be32(f);
90 91 92
    if (version_id != 1)
        return -EINVAL;
    qemu_get_buffer(f, s->config, 256);
B
bellard 已提交
93
    pci_update_mappings(s);
94 95 96
    return 0;
}

B
bellard 已提交
97
/* -1 for devfn means auto assign */
98 99
PCIDevice *pci_register_device(PCIBus *bus, const char *name, 
                               int instance_size, int devfn,
B
bellard 已提交
100 101 102
                               PCIConfigReadFunc *config_read, 
                               PCIConfigWriteFunc *config_write)
{
103
    PCIDevice *pci_dev;
B
bellard 已提交
104

105 106 107
    if (pci_irq_index >= PCI_DEVICES_MAX)
        return NULL;
    
B
bellard 已提交
108
    if (devfn < 0) {
109 110
        for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
            if (!bus->devices[devfn])
B
bellard 已提交
111 112 113 114 115 116 117 118
                goto found;
        }
        return NULL;
    found: ;
    }
    pci_dev = qemu_mallocz(instance_size);
    if (!pci_dev)
        return NULL;
119
    pci_dev->bus = bus;
B
bellard 已提交
120 121
    pci_dev->devfn = devfn;
    pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
122
    memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
123 124 125 126 127

    if (!config_read)
        config_read = pci_default_read_config;
    if (!config_write)
        config_write = pci_default_write_config;
B
bellard 已提交
128 129
    pci_dev->config_read = config_read;
    pci_dev->config_write = config_write;
130
    pci_dev->irq_index = pci_irq_index++;
131
    bus->devices[devfn] = pci_dev;
B
bellard 已提交
132 133 134 135 136 137 138 139
    return pci_dev;
}

void pci_register_io_region(PCIDevice *pci_dev, int region_num, 
                            uint32_t size, int type, 
                            PCIMapIORegionFunc *map_func)
{
    PCIIORegion *r;
P
pbrook 已提交
140
    uint32_t addr;
B
bellard 已提交
141

142
    if ((unsigned int)region_num >= PCI_NUM_REGIONS)
B
bellard 已提交
143 144 145 146 147 148
        return;
    r = &pci_dev->io_regions[region_num];
    r->addr = -1;
    r->size = size;
    r->type = type;
    r->map_func = map_func;
P
pbrook 已提交
149 150 151 152 153 154
    if (region_num == PCI_ROM_SLOT) {
        addr = 0x30;
    } else {
        addr = 0x10 + region_num * 4;
    }
    *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
B
bellard 已提交
155 156
}

P
pbrook 已提交
157
target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
B
bellard 已提交
158
{
P
pbrook 已提交
159
    return addr + pci_mem_base;
B
bellard 已提交
160 161
}

162 163 164 165
static void pci_update_mappings(PCIDevice *d)
{
    PCIIORegion *r;
    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 172 173 174 175
        if (i == PCI_ROM_SLOT) {
            config_ofs = 0x30;
        } else {
            config_ofs = 0x10 + i * 4;
        }
176 177 178 179
        if (r->size != 0) {
            if (r->type & PCI_ADDRESS_SPACE_IO) {
                if (cmd & PCI_COMMAND_IO) {
                    new_addr = le32_to_cpu(*(uint32_t *)(d->config + 
180
                                                         config_ofs));
181 182 183 184 185 186 187 188 189 190 191 192 193
                    new_addr = new_addr & ~(r->size - 1);
                    last_addr = new_addr + r->size - 1;
                    /* NOTE: we have only 64K ioports on PC */
                    if (last_addr <= new_addr || new_addr == 0 ||
                        last_addr >= 0x10000) {
                        new_addr = -1;
                    }
                } else {
                    new_addr = -1;
                }
            } else {
                if (cmd & PCI_COMMAND_MEMORY) {
                    new_addr = le32_to_cpu(*(uint32_t *)(d->config + 
194 195 196 197
                                                         config_ofs));
                    /* the ROM slot has a specific enable bit */
                    if (i == PCI_ROM_SLOT && !(new_addr & 1))
                        goto no_mem_map;
198 199 200 201 202 203 204 205 206 207 208
                    new_addr = new_addr & ~(r->size - 1);
                    last_addr = new_addr + r->size - 1;
                    /* NOTE: we do not support wrapping */
                    /* XXX: as we cannot support really dynamic
                       mappings, we handle specific values as invalid
                       mappings. */
                    if (last_addr <= new_addr || new_addr == 0 ||
                        last_addr == -1) {
                        new_addr = -1;
                    }
                } else {
209
                no_mem_map:
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
                    new_addr = -1;
                }
            }
            /* now do the real mapping */
            if (new_addr != r->addr) {
                if (r->addr != -1) {
                    if (r->type & PCI_ADDRESS_SPACE_IO) {
                        int class;
                        /* NOTE: specific hack for IDE in PC case:
                           only one byte must be mapped. */
                        class = d->config[0x0a] | (d->config[0x0b] << 8);
                        if (class == 0x0101 && r->size == 4) {
                            isa_unassign_ioport(r->addr + 2, 1);
                        } else {
                            isa_unassign_ioport(r->addr, r->size);
                        }
                    } else {
P
pbrook 已提交
227
                        cpu_register_physical_memory(pci_to_cpu_addr(r->addr),
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
                                                     r->size, 
                                                     IO_MEM_UNASSIGNED);
                    }
                }
                r->addr = new_addr;
                if (r->addr != -1) {
                    r->map_func(d, i, r->addr, r->size, r->type);
                }
            }
        }
    }
}

uint32_t pci_default_read_config(PCIDevice *d, 
                                 uint32_t address, int len)
B
bellard 已提交
243
{
244
    uint32_t val;
245

246 247 248
    switch(len) {
    default:
    case 4:
249 250 251 252 253 254 255 256 257 258 259 260 261
	if (address <= 0xfc) {
	    val = le32_to_cpu(*(uint32_t *)(d->config + address));
	    break;
	}
	/* fall through */
    case 2:
        if (address <= 0xfe) {
	    val = le16_to_cpu(*(uint16_t *)(d->config + address));
	    break;
	}
	/* fall through */
    case 1:
        val = d->config[address];
262 263 264 265 266 267 268 269 270
        break;
    }
    return val;
}

void pci_default_write_config(PCIDevice *d, 
                              uint32_t address, uint32_t val, int len)
{
    int can_write, i;
B
bellard 已提交
271
    uint32_t end, addr;
272

273 274
    if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || 
                     (address >= 0x30 && address < 0x34))) {
275 276 277
        PCIIORegion *r;
        int reg;

278 279 280 281 282
        if ( address >= 0x30 ) {
            reg = PCI_ROM_SLOT;
        }else{
            reg = (address - 0x10) >> 2;
        }
283 284 285 286
        r = &d->io_regions[reg];
        if (r->size == 0)
            goto default_config;
        /* compute the stored value */
287 288 289 290 291 292 293 294
        if (reg == PCI_ROM_SLOT) {
            /* keep ROM enable bit */
            val &= (~(r->size - 1)) | 1;
        } else {
            val &= ~(r->size - 1);
            val |= r->type;
        }
        *(uint32_t *)(d->config + address) = cpu_to_le32(val);
295
        pci_update_mappings(d);
B
bellard 已提交
296
        return;
297 298 299
    }
 default_config:
    /* not efficient, but simple */
B
bellard 已提交
300
    addr = address;
301 302
    for(i = 0; i < len; i++) {
        /* default read/write accesses */
303
        switch(d->config[0x0e]) {
304
        case 0x00:
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
        case 0x80:
            switch(addr) {
            case 0x00:
            case 0x01:
            case 0x02:
            case 0x03:
            case 0x08:
            case 0x09:
            case 0x0a:
            case 0x0b:
            case 0x0e:
            case 0x10 ... 0x27: /* base */
            case 0x30 ... 0x33: /* rom */
            case 0x3d:
                can_write = 0;
                break;
            default:
                can_write = 1;
                break;
            }
325 326
            break;
        default:
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
        case 0x01:
            switch(addr) {
            case 0x00:
            case 0x01:
            case 0x02:
            case 0x03:
            case 0x08:
            case 0x09:
            case 0x0a:
            case 0x0b:
            case 0x0e:
            case 0x38 ... 0x3b: /* rom */
            case 0x3d:
                can_write = 0;
                break;
            default:
                can_write = 1;
                break;
            }
346 347 348
            break;
        }
        if (can_write) {
B
bellard 已提交
349
            d->config[addr] = val;
350
        }
351 352
        if (++addr > 0xff)
        	break;
353 354 355 356 357 358 359
        val >>= 8;
    }

    end = address + len;
    if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) {
        /* if the command register is modified, we must modify the mappings */
        pci_update_mappings(d);
B
bellard 已提交
360 361 362
    }
}

P
pbrook 已提交
363
void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
B
bellard 已提交
364
{
365 366 367
    PCIBus *s = opaque;
    PCIDevice *pci_dev;
    int config_addr, bus_num;
B
bellard 已提交
368 369 370
    
#if defined(DEBUG_PCI) && 0
    printf("pci_data_write: addr=%08x val=%08x len=%d\n",
P
pbrook 已提交
371
           addr, val, len);
B
bellard 已提交
372
#endif
P
pbrook 已提交
373
    bus_num = (addr >> 16) & 0xff;
P
pbrook 已提交
374 375 376
    while (s && s->bus_num != bus_num)
        s = s->next;
    if (!s)
B
bellard 已提交
377
        return;
P
pbrook 已提交
378
    pci_dev = s->devices[(addr >> 8) & 0xff];
B
bellard 已提交
379 380
    if (!pci_dev)
        return;
P
pbrook 已提交
381
    config_addr = addr & 0xff;
B
bellard 已提交
382 383 384 385
#if defined(DEBUG_PCI)
    printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
           pci_dev->name, config_addr, val, len);
#endif
386
    pci_dev->config_write(pci_dev, config_addr, val, len);
B
bellard 已提交
387 388
}

P
pbrook 已提交
389
uint32_t pci_data_read(void *opaque, uint32_t addr, int len)
B
bellard 已提交
390
{
391 392 393
    PCIBus *s = opaque;
    PCIDevice *pci_dev;
    int config_addr, bus_num;
B
bellard 已提交
394 395
    uint32_t val;

P
pbrook 已提交
396
    bus_num = (addr >> 16) & 0xff;
P
pbrook 已提交
397 398 399
    while (s && s->bus_num != bus_num)
        s= s->next;
    if (!s)
B
bellard 已提交
400
        goto fail;
P
pbrook 已提交
401
    pci_dev = s->devices[(addr >> 8) & 0xff];
B
bellard 已提交
402 403
    if (!pci_dev) {
    fail:
404 405 406 407 408 409 410 411 412 413 414 415
        switch(len) {
        case 1:
            val = 0xff;
            break;
        case 2:
            val = 0xffff;
            break;
        default:
        case 4:
            val = 0xffffffff;
            break;
        }
B
bellard 已提交
416 417
        goto the_end;
    }
P
pbrook 已提交
418
    config_addr = addr & 0xff;
B
bellard 已提交
419 420 421 422 423 424 425 426
    val = pci_dev->config_read(pci_dev, config_addr, len);
#if defined(DEBUG_PCI)
    printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
           pci_dev->name, config_addr, val, len);
#endif
 the_end:
#if defined(DEBUG_PCI) && 0
    printf("pci_data_read: addr=%08x val=%08x len=%d\n",
P
pbrook 已提交
427
           addr, val, len);
B
bellard 已提交
428 429 430 431
#endif
    return val;
}

P
pbrook 已提交
432 433
/***********************************************************/
/* generic PCI irq support */
434

P
pbrook 已提交
435 436
/* 0 <= irq_num <= 3. level must be 0 or 1 */
void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
B
bellard 已提交
437
{
P
pbrook 已提交
438 439 440 441 442 443
    PCIBus *bus;
    int change;
    
    change = level - pci_dev->irq_state[irq_num];
    if (!change)
        return;
444 445

    pci_dev->irq_state[irq_num] = level;
P
pbrook 已提交
446 447
    for (;;) {
        bus = pci_dev->bus;
P
pbrook 已提交
448
        irq_num = bus->map_irq(pci_dev, irq_num);
P
pbrook 已提交
449 450
        if (bus->set_irq)
            break;
P
pbrook 已提交
451 452 453
        pci_dev = bus->parent_dev;
    }
    bus->irq_count[irq_num] += change;
454
    bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0);
B
bellard 已提交
455 456
}

P
pbrook 已提交
457 458
/***********************************************************/
/* monitor info on PCI */
459

460 461 462 463 464 465 466
typedef struct {
    uint16_t class;
    const char *desc;
} pci_class_desc;

static pci_class_desc pci_class_descriptions[] = 
{
P
pbrook 已提交
467
    { 0x0100, "SCSI controller"},
468 469 470 471 472 473 474 475 476 477
    { 0x0101, "IDE controller"},
    { 0x0200, "Ethernet controller"},
    { 0x0300, "VGA controller"},
    { 0x0600, "Host bridge"},
    { 0x0601, "ISA bridge"},
    { 0x0604, "PCI bridge"},
    { 0x0c03, "USB controller"},
    { 0, NULL}
};

P
pbrook 已提交
478
static void pci_info_device(PCIDevice *d)
479
{
P
pbrook 已提交
480 481
    int i, class;
    PCIIORegion *r;
482
    pci_class_desc *desc;
483

P
pbrook 已提交
484 485 486 487
    term_printf("  Bus %2d, device %3d, function %d:\n",
           d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
    class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
    term_printf("    ");
488 489 490 491 492 493
    desc = pci_class_descriptions;
    while (desc->desc && class != desc->class)
        desc++;
    if (desc->desc) {
        term_printf("%s", desc->desc);
    } else {
P
pbrook 已提交
494
        term_printf("Class %04x", class);
495
    }
P
pbrook 已提交
496 497 498
    term_printf(": PCI device %04x:%04x\n",
           le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
           le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))));
499

P
pbrook 已提交
500 501
    if (d->config[PCI_INTERRUPT_PIN] != 0) {
        term_printf("      IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
502
    }
P
pbrook 已提交
503 504 505
    if (class == 0x0604) {
        term_printf("      BUS %d.\n", d->config[0x19]);
    }
P
pbrook 已提交
506 507 508 509 510 511 512 513 514 515 516 517
    for(i = 0;i < PCI_NUM_REGIONS; i++) {
        r = &d->io_regions[i];
        if (r->size != 0) {
            term_printf("      BAR%d: ", i);
            if (r->type & PCI_ADDRESS_SPACE_IO) {
                term_printf("I/O at 0x%04x [0x%04x].\n", 
                       r->addr, r->addr + r->size - 1);
            } else {
                term_printf("32 bit memory at 0x%08x [0x%08x].\n", 
                       r->addr, r->addr + r->size - 1);
            }
        }
B
bellard 已提交
518
    }
P
pbrook 已提交
519 520 521
    if (class == 0x0604 && d->config[0x19] != 0) {
        pci_for_each_device(d->config[0x19], pci_info_device);
    }
522 523
}

P
pbrook 已提交
524
void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d))
525
{
P
pbrook 已提交
526
    PCIBus *bus = first_bus;
527
    PCIDevice *d;
P
pbrook 已提交
528
    int devfn;
529
    
P
pbrook 已提交
530 531
    while (bus && bus->bus_num != bus_num)
        bus = bus->next;
P
pbrook 已提交
532 533 534 535 536 537
    if (bus) {
        for(devfn = 0; devfn < 256; devfn++) {
            d = bus->devices[devfn];
            if (d)
                fn(d);
        }
B
bellard 已提交
538 539 540
    }
}

P
pbrook 已提交
541
void pci_info(void)
B
bellard 已提交
542
{
P
pbrook 已提交
543
    pci_for_each_device(0, pci_info_device);
B
bellard 已提交
544
}
545 546

/* Initialize a PCI NIC.  */
547
void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn)
548 549
{
    if (strcmp(nd->model, "ne2k_pci") == 0) {
550
        pci_ne2000_init(bus, nd, devfn);
551
    } else if (strcmp(nd->model, "rtl8139") == 0) {
552
        pci_rtl8139_init(bus, nd, devfn);
B
bellard 已提交
553
    } else if (strcmp(nd->model, "pcnet") == 0) {
554
        pci_pcnet_init(bus, nd, devfn);
555 556 557 558 559 560
    } else {
        fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
        exit (1);
    }
}

P
pbrook 已提交
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
typedef struct {
    PCIDevice dev;
    PCIBus *bus;
} PCIBridge;

void pci_bridge_write_config(PCIDevice *d, 
                             uint32_t address, uint32_t val, int len)
{
    PCIBridge *s = (PCIBridge *)d;

    if (address == 0x19 || (address == 0x18 && len > 1)) {
        if (address == 0x19)
            s->bus->bus_num = val & 0xff;
        else
            s->bus->bus_num = (val >> 8) & 0xff;
#if defined(DEBUG_PCI)
        printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
#endif
    }
    pci_default_write_config(d, address, val, len);
}

PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id,
                        pci_map_irq_fn map_irq, const char *name)
{
    PCIBridge *s;
    s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge), 
                                         devfn, NULL, pci_bridge_write_config);
    s->dev.config[0x00] = id >> 16;
T
ths 已提交
590
    s->dev.config[0x01] = id >> 24;
P
pbrook 已提交
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
    s->dev.config[0x02] = id; // device_id
    s->dev.config[0x03] = id >> 8;
    s->dev.config[0x04] = 0x06; // command = bus master, pci mem
    s->dev.config[0x05] = 0x00;
    s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error
    s->dev.config[0x07] = 0x00; // status = fast devsel
    s->dev.config[0x08] = 0x00; // revision
    s->dev.config[0x09] = 0x00; // programming i/f
    s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge
    s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge
    s->dev.config[0x0D] = 0x10; // latency_timer
    s->dev.config[0x0E] = 0x81; // header_type
    s->dev.config[0x1E] = 0xa0; // secondary status

    s->bus = pci_register_secondary_bus(&s->dev, map_irq);
    return s->bus;
}