Commit 69b910399a3c40620a5213adaeb14a37366d97ac
1 parent
158156d1
PCI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@818 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
10 changed files
with
842 additions
and
30 deletions
Changelog
... | ... | @@ -8,6 +8,9 @@ version 0.5.6: |
8 | 8 | - int13 CDROM BIOS fix (aka Solaris x86 install CD fix) |
9 | 9 | - int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix) |
10 | 10 | - BSR/BSF "undefined behaviour" fix |
11 | + - vmdk2raw: convert VMware disk images to raw images | |
12 | + - PCI support | |
13 | + - NE2K PCI support | |
11 | 14 | |
12 | 15 | version 0.5.5: |
13 | 16 | ... | ... |
Makefile.target
... | ... | @@ -232,7 +232,7 @@ ifeq ($(ARCH),alpha) |
232 | 232 | endif |
233 | 233 | |
234 | 234 | # must use static linking to avoid leaving stuff in virtual address space |
235 | -VL_OBJS=vl.o osdep.o block.o monitor.o | |
235 | +VL_OBJS=vl.o osdep.o block.o monitor.o pci.o pci2isa.o | |
236 | 236 | |
237 | 237 | ifeq ($(TARGET_ARCH), i386) |
238 | 238 | # Hardware support | ... | ... |
hw/ide.c
... | ... | @@ -1433,18 +1433,14 @@ static void ide_guess_geometry(IDEState *s) |
1433 | 1433 | } |
1434 | 1434 | } |
1435 | 1435 | |
1436 | -void ide_init(int iobase, int iobase2, int irq, | |
1437 | - BlockDriverState *hd0, BlockDriverState *hd1) | |
1436 | +static void ide_init2(IDEState *ide_state, int irq, | |
1437 | + BlockDriverState *hd0, BlockDriverState *hd1) | |
1438 | 1438 | { |
1439 | - IDEState *s, *ide_state; | |
1439 | + IDEState *s; | |
1440 | 1440 | static int drive_serial = 1; |
1441 | 1441 | int i, cylinders, heads, secs; |
1442 | 1442 | int64_t nb_sectors; |
1443 | 1443 | |
1444 | - ide_state = qemu_mallocz(sizeof(IDEState) * 2); | |
1445 | - if (!ide_state) | |
1446 | - return; | |
1447 | - | |
1448 | 1444 | for(i = 0; i < 2; i++) { |
1449 | 1445 | s = ide_state + i; |
1450 | 1446 | if (i == 0) |
... | ... | @@ -1483,6 +1479,22 @@ void ide_init(int iobase, int iobase2, int irq, |
1483 | 1479 | s->irq = irq; |
1484 | 1480 | ide_reset(s); |
1485 | 1481 | } |
1482 | +} | |
1483 | + | |
1484 | +/***********************************************************/ | |
1485 | +/* ISA IDE definitions */ | |
1486 | + | |
1487 | +void isa_ide_init(int iobase, int iobase2, int irq, | |
1488 | + BlockDriverState *hd0, BlockDriverState *hd1) | |
1489 | +{ | |
1490 | + IDEState *ide_state; | |
1491 | + | |
1492 | + ide_state = qemu_mallocz(sizeof(IDEState) * 2); | |
1493 | + if (!ide_state) | |
1494 | + return; | |
1495 | + | |
1496 | + ide_init2(ide_state, irq, hd0, hd1); | |
1497 | + | |
1486 | 1498 | register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state); |
1487 | 1499 | register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state); |
1488 | 1500 | if (iobase2) { |
... | ... | @@ -1496,3 +1508,87 @@ void ide_init(int iobase, int iobase2, int irq, |
1496 | 1508 | register_ioport_write(iobase, 4, 4, ide_data_writel, ide_state); |
1497 | 1509 | register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state); |
1498 | 1510 | } |
1511 | + | |
1512 | +/***********************************************************/ | |
1513 | +/* PCI IDE definitions */ | |
1514 | + | |
1515 | +typedef struct PCIIDEState { | |
1516 | + PCIDevice dev; | |
1517 | + IDEState ide_if[4]; | |
1518 | +} PCIIDEState; | |
1519 | + | |
1520 | +static uint32_t ide_read_config(PCIDevice *d, | |
1521 | + uint32_t address, int len) | |
1522 | +{ | |
1523 | + uint32_t val; | |
1524 | + val = 0; | |
1525 | + memcpy(&val, d->config + address, len); | |
1526 | + return val; | |
1527 | +} | |
1528 | + | |
1529 | +static void ide_write_config(PCIDevice *d, | |
1530 | + uint32_t address, uint32_t val, int len) | |
1531 | +{ | |
1532 | + memcpy(d->config + address, &val, len); | |
1533 | +} | |
1534 | + | |
1535 | +static void ide_map(PCIDevice *pci_dev, int region_num, | |
1536 | + uint32_t addr, uint32_t size, int type) | |
1537 | +{ | |
1538 | + PCIIDEState *d = (PCIIDEState *)pci_dev; | |
1539 | + IDEState *ide_state; | |
1540 | + | |
1541 | + if (region_num <= 3) { | |
1542 | + ide_state = &d->ide_if[(region_num >> 1) * 2]; | |
1543 | + if (region_num & 1) { | |
1544 | + register_ioport_read(addr + 2, 1, 1, ide_status_read, ide_state); | |
1545 | + register_ioport_write(addr + 2, 1, 1, ide_cmd_write, ide_state); | |
1546 | + } else { | |
1547 | + register_ioport_write(addr, 8, 1, ide_ioport_write, ide_state); | |
1548 | + register_ioport_read(addr, 8, 1, ide_ioport_read, ide_state); | |
1549 | + | |
1550 | + /* data ports */ | |
1551 | + register_ioport_write(addr, 2, 2, ide_data_writew, ide_state); | |
1552 | + register_ioport_read(addr, 2, 2, ide_data_readw, ide_state); | |
1553 | + register_ioport_write(addr, 4, 4, ide_data_writel, ide_state); | |
1554 | + register_ioport_read(addr, 4, 4, ide_data_readl, ide_state); | |
1555 | + } | |
1556 | + } | |
1557 | +} | |
1558 | + | |
1559 | +/* hd_table must contain 4 block drivers */ | |
1560 | +void pci_ide_init(BlockDriverState **hd_table) | |
1561 | +{ | |
1562 | + PCIIDEState *d; | |
1563 | + uint8_t *pci_conf; | |
1564 | + | |
1565 | + d = (PCIIDEState *)pci_register_device("IDE", sizeof(PCIIDEState), | |
1566 | + 0, -1, | |
1567 | + ide_read_config, | |
1568 | + ide_write_config); | |
1569 | + pci_conf = d->dev.config; | |
1570 | + pci_conf[0x00] = 0x86; // Intel | |
1571 | + pci_conf[0x01] = 0x80; | |
1572 | + pci_conf[0x02] = 0x00; // fake | |
1573 | + pci_conf[0x03] = 0x01; // fake | |
1574 | + pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE | |
1575 | + pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage | |
1576 | + pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic | |
1577 | + | |
1578 | + pci_conf[0x2c] = 0x86; // subsys vendor | |
1579 | + pci_conf[0x2d] = 0x80; // subsys vendor | |
1580 | + pci_conf[0x2e] = 0x00; // fake | |
1581 | + pci_conf[0x2f] = 0x01; // fake | |
1582 | + | |
1583 | + pci_register_io_region((PCIDevice *)d, 0, 0x8, | |
1584 | + PCI_ADDRESS_SPACE_IO, ide_map); | |
1585 | + pci_register_io_region((PCIDevice *)d, 1, 0x4, | |
1586 | + PCI_ADDRESS_SPACE_IO, ide_map); | |
1587 | + pci_register_io_region((PCIDevice *)d, 2, 0x8, | |
1588 | + PCI_ADDRESS_SPACE_IO, ide_map); | |
1589 | + pci_register_io_region((PCIDevice *)d, 3, 0x4, | |
1590 | + PCI_ADDRESS_SPACE_IO, ide_map); | |
1591 | + | |
1592 | + ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]); | |
1593 | + ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]); | |
1594 | +} | ... | ... |
hw/ne2000.c
... | ... | @@ -368,7 +368,7 @@ static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr) |
368 | 368 | } |
369 | 369 | |
370 | 370 | static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr, |
371 | - uint32_t val) | |
371 | + uint32_t val) | |
372 | 372 | { |
373 | 373 | if (addr < 32 || |
374 | 374 | (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
... | ... | @@ -382,8 +382,17 @@ static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr, |
382 | 382 | addr &= ~1; /* XXX: check exact behaviour if not even */ |
383 | 383 | if (addr < 32 || |
384 | 384 | (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
385 | - s->mem[addr] = val; | |
386 | - s->mem[addr + 1] = val >> 8; | |
385 | + *(uint16_t *)(s->mem + addr) = cpu_to_le16(val); | |
386 | + } | |
387 | +} | |
388 | + | |
389 | +static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr, | |
390 | + uint32_t val) | |
391 | +{ | |
392 | + addr &= ~3; /* XXX: check exact behaviour if not even */ | |
393 | + if (addr < 32 || | |
394 | + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { | |
395 | + *(uint32_t *)(s->mem + addr) = cpu_to_le32(val); | |
387 | 396 | } |
388 | 397 | } |
389 | 398 | |
... | ... | @@ -402,12 +411,23 @@ static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr) |
402 | 411 | addr &= ~1; /* XXX: check exact behaviour if not even */ |
403 | 412 | if (addr < 32 || |
404 | 413 | (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { |
405 | - return s->mem[addr] | (s->mem[addr + 1] << 8); | |
414 | + return le16_to_cpu(*(uint16_t *)(s->mem + addr)); | |
406 | 415 | } else { |
407 | 416 | return 0xffff; |
408 | 417 | } |
409 | 418 | } |
410 | 419 | |
420 | +static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr) | |
421 | +{ | |
422 | + addr &= ~3; /* XXX: check exact behaviour if not even */ | |
423 | + if (addr < 32 || | |
424 | + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { | |
425 | + return le32_to_cpu(*(uint32_t *)(s->mem + addr)); | |
426 | + } else { | |
427 | + return 0xffffffff; | |
428 | + } | |
429 | +} | |
430 | + | |
411 | 431 | static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
412 | 432 | { |
413 | 433 | NE2000State *s = opaque; |
... | ... | @@ -468,6 +488,53 @@ static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr) |
468 | 488 | return ret; |
469 | 489 | } |
470 | 490 | |
491 | +static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val) | |
492 | +{ | |
493 | + NE2000State *s = opaque; | |
494 | + | |
495 | +#ifdef DEBUG_NE2000 | |
496 | + printf("NE2000: asic writel val=0x%04x\n", val); | |
497 | +#endif | |
498 | + if (s->rcnt == 0) | |
499 | + return; | |
500 | + /* 32 bit access */ | |
501 | + ne2000_mem_writel(s, s->rsar, val); | |
502 | + s->rsar += 4; | |
503 | + s->rcnt -= 4; | |
504 | + /* wrap */ | |
505 | + if (s->rsar == s->stop) | |
506 | + s->rsar = s->start; | |
507 | + if (s->rcnt == 0) { | |
508 | + /* signal end of transfert */ | |
509 | + s->isr |= ENISR_RDC; | |
510 | + ne2000_update_irq(s); | |
511 | + } | |
512 | +} | |
513 | + | |
514 | +static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr) | |
515 | +{ | |
516 | + NE2000State *s = opaque; | |
517 | + int ret; | |
518 | + | |
519 | + /* 32 bit access */ | |
520 | + ret = ne2000_mem_readl(s, s->rsar); | |
521 | + s->rsar += 4; | |
522 | + s->rcnt -= 4; | |
523 | + | |
524 | + /* wrap */ | |
525 | + if (s->rsar == s->stop) | |
526 | + s->rsar = s->start; | |
527 | + if (s->rcnt == 0) { | |
528 | + /* signal end of transfert */ | |
529 | + s->isr |= ENISR_RDC; | |
530 | + ne2000_update_irq(s); | |
531 | + } | |
532 | +#ifdef DEBUG_NE2000 | |
533 | + printf("NE2000: asic readl val=0x%04x\n", ret); | |
534 | +#endif | |
535 | + return ret; | |
536 | +} | |
537 | + | |
471 | 538 | static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
472 | 539 | { |
473 | 540 | /* nothing to do (end of reset pulse) */ |
... | ... | @@ -480,7 +547,7 @@ static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr) |
480 | 547 | return 0; |
481 | 548 | } |
482 | 549 | |
483 | -void ne2000_init(int base, int irq, NetDriverState *nd) | |
550 | +void isa_ne2000_init(int base, int irq, NetDriverState *nd) | |
484 | 551 | { |
485 | 552 | NE2000State *s; |
486 | 553 | |
... | ... | @@ -505,3 +572,78 @@ void ne2000_init(int base, int irq, NetDriverState *nd) |
505 | 572 | |
506 | 573 | qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); |
507 | 574 | } |
575 | + | |
576 | +/***********************************************************/ | |
577 | +/* PCI NE2000 definitions */ | |
578 | + | |
579 | +typedef struct PCINE2000State { | |
580 | + PCIDevice dev; | |
581 | + NE2000State ne2000; | |
582 | +} PCINE2000State; | |
583 | + | |
584 | +static uint32_t ne2000_read_config(PCIDevice *d, | |
585 | + uint32_t address, int len) | |
586 | +{ | |
587 | + uint32_t val; | |
588 | + val = 0; | |
589 | + memcpy(&val, d->config + address, len); | |
590 | + return val; | |
591 | +} | |
592 | + | |
593 | +static void ne2000_write_config(PCIDevice *d, | |
594 | + uint32_t address, uint32_t val, int len) | |
595 | +{ | |
596 | + memcpy(d->config + address, &val, len); | |
597 | +} | |
598 | + | |
599 | +static void ne2000_map(PCIDevice *pci_dev, int region_num, | |
600 | + uint32_t addr, uint32_t size, int type) | |
601 | +{ | |
602 | + PCINE2000State *d = (PCINE2000State *)pci_dev; | |
603 | + NE2000State *s = &d->ne2000; | |
604 | + | |
605 | + register_ioport_write(addr, 16, 1, ne2000_ioport_write, s); | |
606 | + register_ioport_read(addr, 16, 1, ne2000_ioport_read, s); | |
607 | + | |
608 | + register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s); | |
609 | + register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s); | |
610 | + register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s); | |
611 | + register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s); | |
612 | + register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s); | |
613 | + register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s); | |
614 | + | |
615 | + register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s); | |
616 | + register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); | |
617 | +} | |
618 | + | |
619 | +void pci_ne2000_init(NetDriverState *nd) | |
620 | +{ | |
621 | + PCINE2000State *d; | |
622 | + NE2000State *s; | |
623 | + uint8_t *pci_conf; | |
624 | + | |
625 | + d = (PCINE2000State *)pci_register_device("NE2000", sizeof(PCINE2000State), | |
626 | + 0, -1, | |
627 | + ne2000_read_config, | |
628 | + ne2000_write_config); | |
629 | + pci_conf = d->dev.config; | |
630 | + pci_conf[0x00] = 0xec; // Realtek 8029 | |
631 | + pci_conf[0x01] = 0x10; | |
632 | + pci_conf[0x02] = 0x29; | |
633 | + pci_conf[0x03] = 0x80; | |
634 | + pci_conf[0x0a] = 0x00; // ethernet network controller | |
635 | + pci_conf[0x0b] = 0x02; | |
636 | + pci_conf[0x0e] = 0x00; // header_type | |
637 | + | |
638 | + /* XXX: do that in the BIOS */ | |
639 | + pci_conf[0x3c] = 11; // interrupt line | |
640 | + pci_conf[0x3d] = 1; // interrupt pin | |
641 | + | |
642 | + pci_register_io_region((PCIDevice *)d, 0, 0x100, | |
643 | + PCI_ADDRESS_SPACE_IO, ne2000_map); | |
644 | + s = &d->ne2000; | |
645 | + s->irq = 11; | |
646 | + s->nd = nd; | |
647 | + ne2000_reset(s); | |
648 | + qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); | |
649 | +} | ... | ... |
hw/pc.c
... | ... | @@ -380,6 +380,11 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, |
380 | 380 | stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01); |
381 | 381 | } |
382 | 382 | |
383 | + if (pci_enabled) { | |
384 | + i440fx_init(); | |
385 | + piix3_init(); | |
386 | + } | |
387 | + | |
383 | 388 | /* init basic PC hardware */ |
384 | 389 | register_ioport_write(0x80, 1, 1, ioport80_write, NULL); |
385 | 390 | |
... | ... | @@ -401,17 +406,25 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, |
401 | 406 | fd = serial_open_device(); |
402 | 407 | serial_init(0x3f8, 4, fd); |
403 | 408 | |
404 | - nb_nics1 = nb_nics; | |
405 | - if (nb_nics1 > NE2000_NB_MAX) | |
406 | - nb_nics1 = NE2000_NB_MAX; | |
407 | - for(i = 0; i < nb_nics1; i++) { | |
408 | - ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]); | |
409 | - } | |
409 | + if (pci_enabled) { | |
410 | + for(i = 0; i < nb_nics; i++) { | |
411 | + pci_ne2000_init(&nd_table[i]); | |
412 | + } | |
413 | + pci_ide_init(bs_table); | |
414 | + } else { | |
415 | + nb_nics1 = nb_nics; | |
416 | + if (nb_nics1 > NE2000_NB_MAX) | |
417 | + nb_nics1 = NE2000_NB_MAX; | |
418 | + for(i = 0; i < nb_nics1; i++) { | |
419 | + isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]); | |
420 | + } | |
410 | 421 | |
411 | - for(i = 0; i < 2; i++) { | |
412 | - ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], | |
413 | - bs_table[2 * i], bs_table[2 * i + 1]); | |
422 | + for(i = 0; i < 2; i++) { | |
423 | + isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], | |
424 | + bs_table[2 * i], bs_table[2 * i + 1]); | |
425 | + } | |
414 | 426 | } |
427 | + | |
415 | 428 | kbd_init(); |
416 | 429 | DMA_init(); |
417 | 430 | |
... | ... | @@ -426,4 +439,10 @@ void pc_init(int ram_size, int vga_ram_size, int boot_device, |
426 | 439 | floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); |
427 | 440 | |
428 | 441 | cmos_init(ram_size, boot_device); |
442 | + | |
443 | + /* must be done after all PCI devices are instanciated */ | |
444 | + /* XXX: should be done in the Bochs BIOS */ | |
445 | + if (pci_enabled) { | |
446 | + pci_bios_init(); | |
447 | + } | |
429 | 448 | } | ... | ... |
hw/pci.c
0 โ 100644
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 | +typedef struct PCIBridge { | |
29 | + uint32_t config_reg; | |
30 | + PCIDevice **pci_bus[256]; | |
31 | +} PCIBridge; | |
32 | + | |
33 | +static PCIBridge pci_bridge; | |
34 | +target_phys_addr_t pci_mem_base; | |
35 | + | |
36 | +/* -1 for devfn means auto assign */ | |
37 | +PCIDevice *pci_register_device(const char *name, int instance_size, | |
38 | + int bus_num, int devfn, | |
39 | + PCIConfigReadFunc *config_read, | |
40 | + PCIConfigWriteFunc *config_write) | |
41 | +{ | |
42 | + PCIBridge *s = &pci_bridge; | |
43 | + PCIDevice *pci_dev, **bus; | |
44 | + | |
45 | + if (!s->pci_bus[bus_num]) { | |
46 | + s->pci_bus[bus_num] = qemu_mallocz(256 * sizeof(PCIDevice *)); | |
47 | + if (!s->pci_bus[bus_num]) | |
48 | + return NULL; | |
49 | + } | |
50 | + bus = s->pci_bus[bus_num]; | |
51 | + if (devfn < 0) { | |
52 | + for(devfn = 0 ; devfn < 256; devfn += 8) { | |
53 | + if (!bus[devfn]) | |
54 | + goto found; | |
55 | + } | |
56 | + return NULL; | |
57 | + found: ; | |
58 | + } | |
59 | + pci_dev = qemu_mallocz(instance_size); | |
60 | + if (!pci_dev) | |
61 | + return NULL; | |
62 | + pci_dev->bus_num = bus_num; | |
63 | + pci_dev->devfn = devfn; | |
64 | + pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); | |
65 | + pci_dev->config_read = config_read; | |
66 | + pci_dev->config_write = config_write; | |
67 | + bus[devfn] = pci_dev; | |
68 | + return pci_dev; | |
69 | +} | |
70 | + | |
71 | +void pci_register_io_region(PCIDevice *pci_dev, int region_num, | |
72 | + uint32_t size, int type, | |
73 | + PCIMapIORegionFunc *map_func) | |
74 | +{ | |
75 | + PCIIORegion *r; | |
76 | + | |
77 | + if ((unsigned int)region_num >= 6) | |
78 | + return; | |
79 | + r = &pci_dev->io_regions[region_num]; | |
80 | + r->addr = -1; | |
81 | + r->size = size; | |
82 | + r->type = type; | |
83 | + r->map_func = map_func; | |
84 | +} | |
85 | + | |
86 | +static void pci_config_writel(void* opaque, uint32_t addr, uint32_t val) | |
87 | +{ | |
88 | + PCIBridge *s = opaque; | |
89 | + s->config_reg = val; | |
90 | +} | |
91 | + | |
92 | +static uint32_t pci_config_readl(void* opaque, uint32_t addr) | |
93 | +{ | |
94 | + PCIBridge *s = opaque; | |
95 | + return s->config_reg; | |
96 | +} | |
97 | + | |
98 | +static void unmap_region(PCIIORegion *r) | |
99 | +{ | |
100 | + if (r->addr == -1) | |
101 | + return; | |
102 | +#ifdef DEBUG_PCI | |
103 | + printf("unmap addr=%08x size=%08x\n", r->addr, r->size); | |
104 | +#endif | |
105 | + if (r->type & PCI_ADDRESS_SPACE_IO) { | |
106 | + isa_unassign_ioport(r->addr, r->size); | |
107 | + } else { | |
108 | + cpu_register_physical_memory(r->addr + pci_mem_base, r->size, | |
109 | + IO_MEM_UNASSIGNED); | |
110 | + } | |
111 | +} | |
112 | + | |
113 | +static void pci_data_write(void *opaque, uint32_t addr, | |
114 | + uint32_t val, int len) | |
115 | +{ | |
116 | + PCIBridge *s = opaque; | |
117 | + PCIDevice **bus, *pci_dev; | |
118 | + int config_addr, reg; | |
119 | + | |
120 | +#if defined(DEBUG_PCI) && 0 | |
121 | + printf("pci_data_write: addr=%08x val=%08x len=%d\n", | |
122 | + s->config_reg, val, len); | |
123 | +#endif | |
124 | + if (!(s->config_reg & (1 << 31))) { | |
125 | + return; | |
126 | + } | |
127 | + if ((s->config_reg & 0x3) != 0) { | |
128 | + return; | |
129 | + } | |
130 | + bus = s->pci_bus[(s->config_reg >> 16) & 0xff]; | |
131 | + if (!bus) | |
132 | + return; | |
133 | + pci_dev = bus[(s->config_reg >> 8) & 0xff]; | |
134 | + if (!pci_dev) | |
135 | + return; | |
136 | + config_addr = (s->config_reg & 0xfc) | (addr & 3); | |
137 | + | |
138 | +#if defined(DEBUG_PCI) | |
139 | + printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n", | |
140 | + pci_dev->name, config_addr, val, len); | |
141 | +#endif | |
142 | + if (len == 4 && (config_addr >= 0x10 && config_addr < 0x10 + 4 * 6)) { | |
143 | + PCIIORegion *r; | |
144 | + reg = (config_addr - 0x10) >> 2; | |
145 | + r = &pci_dev->io_regions[reg]; | |
146 | + if (r->size == 0) | |
147 | + goto default_config; | |
148 | + if (val != 0xffffffff && val != 0) { | |
149 | + /* XXX: the memory assignment should be global to handle | |
150 | + overlaps, but it is not needed at this stage */ | |
151 | + /* first unmap the old region */ | |
152 | + unmap_region(r); | |
153 | + /* change the address */ | |
154 | + if (r->type & PCI_ADDRESS_SPACE_IO) | |
155 | + r->addr = val & ~0x3; | |
156 | + else | |
157 | + r->addr = val & ~0xf; | |
158 | +#ifdef DEBUG_PCI | |
159 | + printf("map addr=%08x size=%08x type=%d\n", | |
160 | + r->addr, r->size, r->type); | |
161 | +#endif | |
162 | + r->map_func(pci_dev, reg, r->addr, r->size, r->type); | |
163 | + } | |
164 | + /* now compute the stored value */ | |
165 | + val &= ~(r->size - 1); | |
166 | + val |= r->type; | |
167 | + *(uint32_t *)(pci_dev->config + 0x10 + reg * 4) = cpu_to_le32(val); | |
168 | + } else { | |
169 | + default_config: | |
170 | + pci_dev->config_write(pci_dev, config_addr, val, len); | |
171 | + } | |
172 | +} | |
173 | + | |
174 | +static uint32_t pci_data_read(void *opaque, uint32_t addr, | |
175 | + int len) | |
176 | +{ | |
177 | + PCIBridge *s = opaque; | |
178 | + PCIDevice **bus, *pci_dev; | |
179 | + int config_addr; | |
180 | + uint32_t val; | |
181 | + | |
182 | + if (!(s->config_reg & (1 << 31))) | |
183 | + goto fail; | |
184 | + if ((s->config_reg & 0x3) != 0) | |
185 | + goto fail; | |
186 | + bus = s->pci_bus[(s->config_reg >> 16) & 0xff]; | |
187 | + if (!bus) | |
188 | + goto fail; | |
189 | + pci_dev = bus[(s->config_reg >> 8) & 0xff]; | |
190 | + if (!pci_dev) { | |
191 | + fail: | |
192 | + val = 0; | |
193 | + goto the_end; | |
194 | + } | |
195 | + config_addr = (s->config_reg & 0xfc) | (addr & 3); | |
196 | + val = pci_dev->config_read(pci_dev, config_addr, len); | |
197 | +#if defined(DEBUG_PCI) | |
198 | + printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", | |
199 | + pci_dev->name, config_addr, val, len); | |
200 | +#endif | |
201 | + the_end: | |
202 | +#if defined(DEBUG_PCI) && 0 | |
203 | + printf("pci_data_read: addr=%08x val=%08x len=%d\n", | |
204 | + s->config_reg, val, len); | |
205 | +#endif | |
206 | + return val; | |
207 | +} | |
208 | + | |
209 | +static void pci_data_writeb(void* opaque, uint32_t addr, uint32_t val) | |
210 | +{ | |
211 | + pci_data_write(opaque, addr, val, 1); | |
212 | +} | |
213 | + | |
214 | +static void pci_data_writew(void* opaque, uint32_t addr, uint32_t val) | |
215 | +{ | |
216 | + pci_data_write(opaque, addr, val, 2); | |
217 | +} | |
218 | + | |
219 | +static void pci_data_writel(void* opaque, uint32_t addr, uint32_t val) | |
220 | +{ | |
221 | + pci_data_write(opaque, addr, val, 4); | |
222 | +} | |
223 | + | |
224 | +static uint32_t pci_data_readb(void* opaque, uint32_t addr) | |
225 | +{ | |
226 | + return pci_data_read(opaque, addr, 1); | |
227 | +} | |
228 | + | |
229 | +static uint32_t pci_data_readw(void* opaque, uint32_t addr) | |
230 | +{ | |
231 | + return pci_data_read(opaque, addr, 2); | |
232 | +} | |
233 | + | |
234 | +static uint32_t pci_data_readl(void* opaque, uint32_t addr) | |
235 | +{ | |
236 | + return pci_data_read(opaque, addr, 4); | |
237 | +} | |
238 | + | |
239 | +/* i440FX PCI bridge */ | |
240 | + | |
241 | +static uint32_t i440_read_config(PCIDevice *d, | |
242 | + uint32_t address, int len) | |
243 | +{ | |
244 | + uint32_t val; | |
245 | + val = 0; | |
246 | + memcpy(&val, d->config + address, len); | |
247 | + return val; | |
248 | +} | |
249 | + | |
250 | +static void i440_write_config(PCIDevice *d, | |
251 | + uint32_t address, uint32_t val, int len) | |
252 | +{ | |
253 | + memcpy(d->config + address, &val, len); | |
254 | +} | |
255 | + | |
256 | +void i440fx_init(void) | |
257 | +{ | |
258 | + PCIBridge *s = &pci_bridge; | |
259 | + PCIDevice *d; | |
260 | + | |
261 | + register_ioport_write(0xcf8, 4, 4, pci_config_writel, s); | |
262 | + register_ioport_read(0xcf8, 4, 4, pci_config_readl, s); | |
263 | + | |
264 | + register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s); | |
265 | + register_ioport_write(0xcfc, 4, 2, pci_data_writew, s); | |
266 | + register_ioport_write(0xcfc, 4, 4, pci_data_writel, s); | |
267 | + register_ioport_read(0xcfc, 4, 1, pci_data_readb, s); | |
268 | + register_ioport_read(0xcfc, 4, 2, pci_data_readw, s); | |
269 | + register_ioport_read(0xcfc, 4, 4, pci_data_readl, s); | |
270 | + | |
271 | + d = pci_register_device("i440FX", sizeof(PCIDevice), 0, 0, | |
272 | + i440_read_config, i440_write_config); | |
273 | + | |
274 | + d->config[0x00] = 0x86; // vendor_id | |
275 | + d->config[0x01] = 0x80; | |
276 | + d->config[0x02] = 0x37; // device_id | |
277 | + d->config[0x03] = 0x12; | |
278 | + d->config[0x08] = 0x02; // revision | |
279 | + d->config[0x0a] = 0x04; // class_sub = pci2pci | |
280 | + d->config[0x0b] = 0x06; // class_base = PCI_bridge | |
281 | + d->config[0x0c] = 0x01; // line_size in 32 bit words | |
282 | + d->config[0x0e] = 0x01; // header_type | |
283 | +} | |
284 | + | |
285 | +/* NOTE: the following should be done by the BIOS */ | |
286 | + | |
287 | +static uint32_t pci_bios_io_addr; | |
288 | +static uint32_t pci_bios_mem_addr; | |
289 | + | |
290 | +static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) | |
291 | +{ | |
292 | + PCIBridge *s = &pci_bridge; | |
293 | + PCIIORegion *r; | |
294 | + | |
295 | + s->config_reg = 0x80000000 | (d->bus_num << 16) | | |
296 | + (d->devfn << 8) | (0x10 + region_num * 4); | |
297 | + pci_data_write(s, 0, addr, 4); | |
298 | + r = &d->io_regions[region_num]; | |
299 | + | |
300 | + /* enable memory mappings */ | |
301 | + if (r->type & PCI_ADDRESS_SPACE_IO) | |
302 | + d->config[0x04] |= 1; | |
303 | + else | |
304 | + d->config[0x04] |= 2; | |
305 | +} | |
306 | + | |
307 | + | |
308 | +static void pci_bios_init_device(PCIDevice *d) | |
309 | +{ | |
310 | + int class; | |
311 | + PCIIORegion *r; | |
312 | + uint32_t *paddr; | |
313 | + int i; | |
314 | + | |
315 | + class = d->config[0x0a] | (d->config[0x0b] << 8); | |
316 | + switch(class) { | |
317 | + case 0x0101: | |
318 | + /* IDE: we map it as in ISA mode */ | |
319 | + pci_set_io_region_addr(d, 0, 0x1f0); | |
320 | + pci_set_io_region_addr(d, 1, 0x3f4); | |
321 | + pci_set_io_region_addr(d, 2, 0x170); | |
322 | + pci_set_io_region_addr(d, 3, 0x374); | |
323 | + break; | |
324 | + default: | |
325 | + /* default memory mappings */ | |
326 | + for(i = 0; i < 6; i++) { | |
327 | + r = &d->io_regions[i]; | |
328 | + if (r->size) { | |
329 | + if (r->type & PCI_ADDRESS_SPACE_IO) | |
330 | + paddr = &pci_bios_io_addr; | |
331 | + else | |
332 | + paddr = &pci_bios_mem_addr; | |
333 | + *paddr = (*paddr + r->size - 1) & ~(r->size - 1); | |
334 | + pci_set_io_region_addr(d, i, *paddr); | |
335 | + *paddr += r->size; | |
336 | + } | |
337 | + } | |
338 | + break; | |
339 | + } | |
340 | +} | |
341 | + | |
342 | +/* | |
343 | + * This function initializes the PCI devices as a normal PCI BIOS | |
344 | + * would do. It is provided just in case the BIOS has no support for | |
345 | + * PCI. | |
346 | + */ | |
347 | +void pci_bios_init(void) | |
348 | +{ | |
349 | + PCIBridge *s = &pci_bridge; | |
350 | + PCIDevice **bus; | |
351 | + int bus_num, devfn; | |
352 | + | |
353 | + pci_bios_io_addr = 0xc000; | |
354 | + pci_bios_mem_addr = 0xf0000000; | |
355 | + | |
356 | + for(bus_num = 0; bus_num < 256; bus_num++) { | |
357 | + bus = s->pci_bus[bus_num]; | |
358 | + if (bus) { | |
359 | + for(devfn = 0; devfn < 256; devfn++) { | |
360 | + if (bus[devfn]) | |
361 | + pci_bios_init_device(bus[devfn]); | |
362 | + } | |
363 | + } | |
364 | + } | |
365 | +} | |
366 | + | |
367 | + | ... | ... |
hw/pci2isa.c
0 โ 100644
1 | +/* | |
2 | + * QEMU PCI to ISA bridge | |
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 | +typedef struct PIIX3State { | |
29 | + PCIDevice dev; | |
30 | + uint8_t elcr1; | |
31 | + uint8_t elcr2; | |
32 | +} PIIX3State; | |
33 | + | |
34 | +static void piix3_reset(PIIX3State *d) | |
35 | +{ | |
36 | + uint8_t *pci_conf = d->dev.config; | |
37 | + | |
38 | + pci_conf[0x04] = 0x07; // master, memory and I/O | |
39 | + pci_conf[0x05] = 0x00; | |
40 | + pci_conf[0x06] = 0x00; | |
41 | + pci_conf[0x07] = 0x02; // PCI_status_devsel_medium | |
42 | + pci_conf[0x4c] = 0x4d; | |
43 | + pci_conf[0x4e] = 0x03; | |
44 | + pci_conf[0x4f] = 0x00; | |
45 | + pci_conf[0x60] = 0x80; | |
46 | + pci_conf[0x69] = 0x02; | |
47 | + pci_conf[0x70] = 0x80; | |
48 | + pci_conf[0x76] = 0x0c; | |
49 | + pci_conf[0x77] = 0x0c; | |
50 | + pci_conf[0x78] = 0x02; | |
51 | + pci_conf[0x79] = 0x00; | |
52 | + pci_conf[0x80] = 0x00; | |
53 | + pci_conf[0x82] = 0x00; | |
54 | + pci_conf[0xa0] = 0x08; | |
55 | + pci_conf[0xa0] = 0x08; | |
56 | + pci_conf[0xa2] = 0x00; | |
57 | + pci_conf[0xa3] = 0x00; | |
58 | + pci_conf[0xa4] = 0x00; | |
59 | + pci_conf[0xa5] = 0x00; | |
60 | + pci_conf[0xa6] = 0x00; | |
61 | + pci_conf[0xa7] = 0x00; | |
62 | + pci_conf[0xa8] = 0x0f; | |
63 | + pci_conf[0xaa] = 0x00; | |
64 | + pci_conf[0xab] = 0x00; | |
65 | + pci_conf[0xac] = 0x00; | |
66 | + pci_conf[0xae] = 0x00; | |
67 | + | |
68 | + d->elcr1 = 0x00; | |
69 | + d->elcr2 = 0x00; | |
70 | +} | |
71 | + | |
72 | +static uint32_t piix3_read_config(PCIDevice *d, | |
73 | + uint32_t address, int len) | |
74 | +{ | |
75 | + uint32_t val; | |
76 | + val = 0; | |
77 | + memcpy(&val, d->config + address, len); | |
78 | + return val; | |
79 | +} | |
80 | + | |
81 | +static void piix3_write_config(PCIDevice *d, | |
82 | + uint32_t address, uint32_t val, int len) | |
83 | +{ | |
84 | + memcpy(d->config + address, &val, len); | |
85 | +} | |
86 | + | |
87 | +void piix3_init(void) | |
88 | +{ | |
89 | + PIIX3State *d; | |
90 | + uint8_t *pci_conf; | |
91 | + | |
92 | + d = (PIIX3State *)pci_register_device("PIIX3", sizeof(PIIX3State), | |
93 | + 0, -1, | |
94 | + piix3_read_config, | |
95 | + piix3_write_config); | |
96 | + pci_conf = d->dev.config; | |
97 | + | |
98 | + pci_conf[0x00] = 0x86; // Intel | |
99 | + pci_conf[0x01] = 0x80; | |
100 | + pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1) | |
101 | + pci_conf[0x03] = 0x70; | |
102 | + pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA | |
103 | + pci_conf[0x0b] = 0x06; // class_base = PCI_bridge | |
104 | + pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic | |
105 | + | |
106 | + piix3_reset(d); | |
107 | +} | ... | ... |
hw/ppc_prep.c
... | ... | @@ -962,13 +962,13 @@ void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device, |
962 | 962 | if (nb_nics1 > NE2000_NB_MAX) |
963 | 963 | nb_nics1 = NE2000_NB_MAX; |
964 | 964 | for(i = 0; i < nb_nics1; i++) { |
965 | - ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]); | |
965 | + isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]); | |
966 | 966 | } |
967 | 967 | #endif |
968 | 968 | |
969 | 969 | for(i = 0; i < 2; i++) { |
970 | - ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], | |
971 | - bs_table[2 * i], bs_table[2 * i + 1]); | |
970 | + isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], | |
971 | + bs_table[2 * i], bs_table[2 * i + 1]); | |
972 | 972 | } |
973 | 973 | kbd_init(); |
974 | 974 | AUD_init(); | ... | ... |
vl.c
... | ... | @@ -121,6 +121,7 @@ SerialState *serial_console; |
121 | 121 | QEMUTimer *gui_timer; |
122 | 122 | int vm_running; |
123 | 123 | int audio_enabled = 0; |
124 | +int pci_enabled = 0; | |
124 | 125 | |
125 | 126 | /***********************************************************/ |
126 | 127 | /* x86 ISA bus support */ |
... | ... | @@ -238,6 +239,21 @@ int register_ioport_write(int start, int length, int size, |
238 | 239 | return 0; |
239 | 240 | } |
240 | 241 | |
242 | +void isa_unassign_ioport(int start, int length) | |
243 | +{ | |
244 | + int i; | |
245 | + | |
246 | + for(i = start; i < start + length; i++) { | |
247 | + ioport_read_table[0][i] = default_ioport_readb; | |
248 | + ioport_read_table[1][i] = default_ioport_readw; | |
249 | + ioport_read_table[2][i] = default_ioport_readl; | |
250 | + | |
251 | + ioport_write_table[0][i] = default_ioport_writeb; | |
252 | + ioport_write_table[1][i] = default_ioport_writew; | |
253 | + ioport_write_table[2][i] = default_ioport_writel; | |
254 | + } | |
255 | +} | |
256 | + | |
241 | 257 | void pstrcpy(char *buf, int buf_size, const char *str) |
242 | 258 | { |
243 | 259 | int c; |
... | ... | @@ -1973,6 +1989,7 @@ enum { |
1973 | 1989 | QEMU_OPTION_hdachs, |
1974 | 1990 | QEMU_OPTION_L, |
1975 | 1991 | QEMU_OPTION_no_code_copy, |
1992 | + QEMU_OPTION_pci, | |
1976 | 1993 | }; |
1977 | 1994 | |
1978 | 1995 | typedef struct QEMUOption { |
... | ... | @@ -1999,7 +2016,7 @@ const QEMUOption qemu_options[] = { |
1999 | 2016 | |
2000 | 2017 | { "nics", HAS_ARG, QEMU_OPTION_nics}, |
2001 | 2018 | { "macaddr", HAS_ARG, QEMU_OPTION_macaddr}, |
2002 | - { "n", HAS_ARG, QEMU_OPTION_d }, | |
2019 | + { "n", HAS_ARG, QEMU_OPTION_n }, | |
2003 | 2020 | { "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd }, |
2004 | 2021 | #ifdef CONFIG_SLIRP |
2005 | 2022 | { "user-net", 0, QEMU_OPTION_user_net }, |
... | ... | @@ -2017,6 +2034,7 @@ const QEMUOption qemu_options[] = { |
2017 | 2034 | { "hdachs", HAS_ARG, QEMU_OPTION_hdachs }, |
2018 | 2035 | { "L", HAS_ARG, QEMU_OPTION_L }, |
2019 | 2036 | { "no-code-copy", 0, QEMU_OPTION_no_code_copy }, |
2037 | + { "pci", 0, QEMU_OPTION_pci }, | |
2020 | 2038 | { NULL }, |
2021 | 2039 | }; |
2022 | 2040 | |
... | ... | @@ -2286,6 +2304,9 @@ int main(int argc, char **argv) |
2286 | 2304 | case QEMU_OPTION_S: |
2287 | 2305 | start_emulation = 0; |
2288 | 2306 | break; |
2307 | + case QEMU_OPTION_pci: | |
2308 | + pci_enabled = 1; | |
2309 | + break; | |
2289 | 2310 | } |
2290 | 2311 | } |
2291 | 2312 | } | ... | ... |
vl.h
... | ... | @@ -218,7 +218,7 @@ typedef void QEMUTimerCB(void *opaque); |
218 | 218 | |
219 | 219 | /* The real time clock should be used only for stuff which does not |
220 | 220 | change the virtual machine state, as it is run even if the virtual |
221 | - machine is stopped. The real time clock has a frequency or 1000 | |
221 | + machine is stopped. The real time clock has a frequency of 1000 | |
222 | 222 | Hz. */ |
223 | 223 | extern QEMUClock *rt_clock; |
224 | 224 | |
... | ... | @@ -360,6 +360,61 @@ int register_ioport_read(int start, int length, int size, |
360 | 360 | IOPortReadFunc *func, void *opaque); |
361 | 361 | int register_ioport_write(int start, int length, int size, |
362 | 362 | IOPortWriteFunc *func, void *opaque); |
363 | +void isa_unassign_ioport(int start, int length); | |
364 | + | |
365 | +/* PCI bus */ | |
366 | + | |
367 | +extern int pci_enabled; | |
368 | + | |
369 | +extern target_phys_addr_t pci_mem_base; | |
370 | + | |
371 | +typedef struct PCIDevice PCIDevice; | |
372 | + | |
373 | +typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, | |
374 | + uint32_t address, uint32_t data, int len); | |
375 | +typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, | |
376 | + uint32_t address, int len); | |
377 | +typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, | |
378 | + uint32_t addr, uint32_t size, int type); | |
379 | + | |
380 | +#define PCI_ADDRESS_SPACE_MEM 0x00 | |
381 | +#define PCI_ADDRESS_SPACE_IO 0x01 | |
382 | +#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 | |
383 | + | |
384 | +typedef struct PCIIORegion { | |
385 | + uint32_t addr; | |
386 | + uint32_t size; | |
387 | + uint8_t type; | |
388 | + PCIMapIORegionFunc *map_func; | |
389 | +} PCIIORegion; | |
390 | + | |
391 | +struct PCIDevice { | |
392 | + /* PCI config space */ | |
393 | + uint8_t config[256]; | |
394 | + | |
395 | + /* the following fields are read only */ | |
396 | + int bus_num; | |
397 | + int devfn; | |
398 | + char name[64]; | |
399 | + PCIIORegion io_regions[6]; | |
400 | + | |
401 | + /* do not access the following fields */ | |
402 | + PCIConfigReadFunc *config_read; | |
403 | + PCIConfigWriteFunc *config_write; | |
404 | +}; | |
405 | + | |
406 | +PCIDevice *pci_register_device(const char *name, int instance_size, | |
407 | + int bus_num, int devfn, | |
408 | + PCIConfigReadFunc *config_read, | |
409 | + PCIConfigWriteFunc *config_write); | |
410 | + | |
411 | +void pci_register_io_region(PCIDevice *pci_dev, int region_num, | |
412 | + uint32_t size, int type, | |
413 | + PCIMapIORegionFunc *map_func); | |
414 | + | |
415 | +void i440fx_init(void); | |
416 | +void piix3_init(void); | |
417 | +void pci_bios_init(void); | |
363 | 418 | |
364 | 419 | /* vga.c */ |
365 | 420 | |
... | ... | @@ -397,8 +452,9 @@ void sdl_display_init(DisplayState *ds); |
397 | 452 | |
398 | 453 | extern BlockDriverState *bs_table[MAX_DISKS]; |
399 | 454 | |
400 | -void ide_init(int iobase, int iobase2, int irq, | |
401 | - BlockDriverState *hd0, BlockDriverState *hd1); | |
455 | +void isa_ide_init(int iobase, int iobase2, int irq, | |
456 | + BlockDriverState *hd0, BlockDriverState *hd1); | |
457 | +void pci_ide_init(BlockDriverState **hd_table); | |
402 | 458 | |
403 | 459 | /* oss.c */ |
404 | 460 | typedef enum { |
... | ... | @@ -446,7 +502,8 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); |
446 | 502 | |
447 | 503 | /* ne2000.c */ |
448 | 504 | |
449 | -void ne2000_init(int base, int irq, NetDriverState *nd); | |
505 | +void isa_ne2000_init(int base, int irq, NetDriverState *nd); | |
506 | +void pci_ne2000_init(NetDriverState *nd); | |
450 | 507 | |
451 | 508 | /* pckbd.c */ |
452 | 509 | ... | ... |