Commit 8a8696a3c4c2bc977a202fc80890aa170ff70812
1 parent
89980284
support for opaque data on memory I/Os - PCI ROM memory support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@876 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
79 additions
and
46 deletions
hw/pci.c
| ... | ... | @@ -100,7 +100,7 @@ void pci_register_io_region(PCIDevice *pci_dev, int region_num, |
| 100 | 100 | { |
| 101 | 101 | PCIIORegion *r; |
| 102 | 102 | |
| 103 | - if ((unsigned int)region_num >= 6) | |
| 103 | + if ((unsigned int)region_num >= PCI_NUM_REGIONS) | |
| 104 | 104 | return; |
| 105 | 105 | r = &pci_dev->io_regions[region_num]; |
| 106 | 106 | r->addr = -1; |
| ... | ... | @@ -125,16 +125,21 @@ static void pci_update_mappings(PCIDevice *d) |
| 125 | 125 | { |
| 126 | 126 | PCIIORegion *r; |
| 127 | 127 | int cmd, i; |
| 128 | - uint32_t last_addr, new_addr; | |
| 128 | + uint32_t last_addr, new_addr, config_ofs; | |
| 129 | 129 | |
| 130 | 130 | cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND)); |
| 131 | - for(i = 0; i < 6; i++) { | |
| 131 | + for(i = 0; i < PCI_NUM_REGIONS; i++) { | |
| 132 | 132 | r = &d->io_regions[i]; |
| 133 | + if (i == PCI_ROM_SLOT) { | |
| 134 | + config_ofs = 0x30; | |
| 135 | + } else { | |
| 136 | + config_ofs = 0x10 + i * 4; | |
| 137 | + } | |
| 133 | 138 | if (r->size != 0) { |
| 134 | 139 | if (r->type & PCI_ADDRESS_SPACE_IO) { |
| 135 | 140 | if (cmd & PCI_COMMAND_IO) { |
| 136 | 141 | new_addr = le32_to_cpu(*(uint32_t *)(d->config + |
| 137 | - 0x10 + i * 4)); | |
| 142 | + config_ofs)); | |
| 138 | 143 | new_addr = new_addr & ~(r->size - 1); |
| 139 | 144 | last_addr = new_addr + r->size - 1; |
| 140 | 145 | /* NOTE: we have only 64K ioports on PC */ |
| ... | ... | @@ -148,7 +153,10 @@ static void pci_update_mappings(PCIDevice *d) |
| 148 | 153 | } else { |
| 149 | 154 | if (cmd & PCI_COMMAND_MEMORY) { |
| 150 | 155 | new_addr = le32_to_cpu(*(uint32_t *)(d->config + |
| 151 | - 0x10 + i * 4)); | |
| 156 | + config_ofs)); | |
| 157 | + /* the ROM slot has a specific enable bit */ | |
| 158 | + if (i == PCI_ROM_SLOT && !(new_addr & 1)) | |
| 159 | + goto no_mem_map; | |
| 152 | 160 | new_addr = new_addr & ~(r->size - 1); |
| 153 | 161 | last_addr = new_addr + r->size - 1; |
| 154 | 162 | /* NOTE: we do not support wrapping */ |
| ... | ... | @@ -160,6 +168,7 @@ static void pci_update_mappings(PCIDevice *d) |
| 160 | 168 | new_addr = -1; |
| 161 | 169 | } |
| 162 | 170 | } else { |
| 171 | + no_mem_map: | |
| 163 | 172 | new_addr = -1; |
| 164 | 173 | } |
| 165 | 174 | } |
| ... | ... | @@ -216,18 +225,28 @@ void pci_default_write_config(PCIDevice *d, |
| 216 | 225 | int can_write, i; |
| 217 | 226 | uint32_t end, addr; |
| 218 | 227 | |
| 219 | - if (len == 4 && (address >= 0x10 && address < 0x10 + 4 * 6)) { | |
| 228 | + if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || | |
| 229 | + (address >= 0x30 && address < 0x34))) { | |
| 220 | 230 | PCIIORegion *r; |
| 221 | 231 | int reg; |
| 222 | 232 | |
| 223 | - reg = (address - 0x10) >> 2; | |
| 233 | + if ( address >= 0x30 ) { | |
| 234 | + reg = PCI_ROM_SLOT; | |
| 235 | + }else{ | |
| 236 | + reg = (address - 0x10) >> 2; | |
| 237 | + } | |
| 224 | 238 | r = &d->io_regions[reg]; |
| 225 | 239 | if (r->size == 0) |
| 226 | 240 | goto default_config; |
| 227 | 241 | /* compute the stored value */ |
| 228 | - val &= ~(r->size - 1); | |
| 229 | - val |= r->type; | |
| 230 | - *(uint32_t *)(d->config + 0x10 + reg * 4) = cpu_to_le32(val); | |
| 242 | + if (reg == PCI_ROM_SLOT) { | |
| 243 | + /* keep ROM enable bit */ | |
| 244 | + val &= (~(r->size - 1)) | 1; | |
| 245 | + } else { | |
| 246 | + val &= ~(r->size - 1); | |
| 247 | + val |= r->type; | |
| 248 | + } | |
| 249 | + *(uint32_t *)(d->config + address) = cpu_to_le32(val); | |
| 231 | 250 | pci_update_mappings(d); |
| 232 | 251 | return; |
| 233 | 252 | } |
| ... | ... | @@ -484,16 +503,16 @@ static inline void set_config(PCIBridge *s, target_phys_addr_t addr) |
| 484 | 503 | s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8); |
| 485 | 504 | } |
| 486 | 505 | |
| 487 | -static void PPC_PCIIO_writeb (target_phys_addr_t addr, uint32_t val) | |
| 506 | +static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 488 | 507 | { |
| 489 | - PCIBridge *s = &pci_bridge; | |
| 508 | + PCIBridge *s = opaque; | |
| 490 | 509 | set_config(s, addr); |
| 491 | 510 | pci_data_write(s, addr, val, 1); |
| 492 | 511 | } |
| 493 | 512 | |
| 494 | -static void PPC_PCIIO_writew (target_phys_addr_t addr, uint32_t val) | |
| 513 | +static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 495 | 514 | { |
| 496 | - PCIBridge *s = &pci_bridge; | |
| 515 | + PCIBridge *s = opaque; | |
| 497 | 516 | set_config(s, addr); |
| 498 | 517 | #ifdef TARGET_WORDS_BIGENDIAN |
| 499 | 518 | val = bswap16(val); |
| ... | ... | @@ -501,9 +520,9 @@ static void PPC_PCIIO_writew (target_phys_addr_t addr, uint32_t val) |
| 501 | 520 | pci_data_write(s, addr, val, 2); |
| 502 | 521 | } |
| 503 | 522 | |
| 504 | -static void PPC_PCIIO_writel (target_phys_addr_t addr, uint32_t val) | |
| 523 | +static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 505 | 524 | { |
| 506 | - PCIBridge *s = &pci_bridge; | |
| 525 | + PCIBridge *s = opaque; | |
| 507 | 526 | set_config(s, addr); |
| 508 | 527 | #ifdef TARGET_WORDS_BIGENDIAN |
| 509 | 528 | val = bswap32(val); |
| ... | ... | @@ -511,18 +530,18 @@ static void PPC_PCIIO_writel (target_phys_addr_t addr, uint32_t val) |
| 511 | 530 | pci_data_write(s, addr, val, 4); |
| 512 | 531 | } |
| 513 | 532 | |
| 514 | -static uint32_t PPC_PCIIO_readb (target_phys_addr_t addr) | |
| 533 | +static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr) | |
| 515 | 534 | { |
| 516 | - PCIBridge *s = &pci_bridge; | |
| 535 | + PCIBridge *s = opaque; | |
| 517 | 536 | uint32_t val; |
| 518 | 537 | set_config(s, addr); |
| 519 | 538 | val = pci_data_read(s, addr, 1); |
| 520 | 539 | return val; |
| 521 | 540 | } |
| 522 | 541 | |
| 523 | -static uint32_t PPC_PCIIO_readw (target_phys_addr_t addr) | |
| 542 | +static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr) | |
| 524 | 543 | { |
| 525 | - PCIBridge *s = &pci_bridge; | |
| 544 | + PCIBridge *s = opaque; | |
| 526 | 545 | uint32_t val; |
| 527 | 546 | set_config(s, addr); |
| 528 | 547 | val = pci_data_read(s, addr, 2); |
| ... | ... | @@ -532,9 +551,9 @@ static uint32_t PPC_PCIIO_readw (target_phys_addr_t addr) |
| 532 | 551 | return val; |
| 533 | 552 | } |
| 534 | 553 | |
| 535 | -static uint32_t PPC_PCIIO_readl (target_phys_addr_t addr) | |
| 554 | +static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr) | |
| 536 | 555 | { |
| 537 | - PCIBridge *s = &pci_bridge; | |
| 556 | + PCIBridge *s = opaque; | |
| 538 | 557 | uint32_t val; |
| 539 | 558 | set_config(s, addr); |
| 540 | 559 | val = pci_data_read(s, addr, 4); |
| ... | ... | @@ -558,10 +577,12 @@ static CPUReadMemoryFunc *PPC_PCIIO_read[] = { |
| 558 | 577 | |
| 559 | 578 | void pci_prep_init(void) |
| 560 | 579 | { |
| 580 | + PCIBridge *s = &pci_bridge; | |
| 561 | 581 | PCIDevice *d; |
| 562 | 582 | int PPC_io_memory; |
| 563 | 583 | |
| 564 | - PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, PPC_PCIIO_write); | |
| 584 | + PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, | |
| 585 | + PPC_PCIIO_write, s); | |
| 565 | 586 | cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory); |
| 566 | 587 | |
| 567 | 588 | d = pci_register_device("PREP PCI Bridge", sizeof(PCIDevice), 0, 0, |
| ... | ... | @@ -581,18 +602,18 @@ void pci_prep_init(void) |
| 581 | 602 | |
| 582 | 603 | /* pmac pci init */ |
| 583 | 604 | |
| 584 | -static void pci_pmac_config_writel (target_phys_addr_t addr, uint32_t val) | |
| 605 | +static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 585 | 606 | { |
| 586 | - PCIBridge *s = &pci_bridge; | |
| 607 | + PCIBridge *s = opaque; | |
| 587 | 608 | #ifdef TARGET_WORDS_BIGENDIAN |
| 588 | 609 | val = bswap32(val); |
| 589 | 610 | #endif |
| 590 | 611 | s->config_reg = val; |
| 591 | 612 | } |
| 592 | 613 | |
| 593 | -static uint32_t pci_pmac_config_readl (target_phys_addr_t addr) | |
| 614 | +static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr) | |
| 594 | 615 | { |
| 595 | - PCIBridge *s = &pci_bridge; | |
| 616 | + PCIBridge *s = opaque; | |
| 596 | 617 | uint32_t val; |
| 597 | 618 | |
| 598 | 619 | val = s->config_reg; |
| ... | ... | @@ -614,41 +635,41 @@ static CPUReadMemoryFunc *pci_pmac_config_read[] = { |
| 614 | 635 | &pci_pmac_config_readl, |
| 615 | 636 | }; |
| 616 | 637 | |
| 617 | -static void pci_pmac_writeb (target_phys_addr_t addr, uint32_t val) | |
| 638 | +static void pci_pmac_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 618 | 639 | { |
| 619 | - PCIBridge *s = &pci_bridge; | |
| 640 | + PCIBridge *s = opaque; | |
| 620 | 641 | pci_data_write(s, addr, val, 1); |
| 621 | 642 | } |
| 622 | 643 | |
| 623 | -static void pci_pmac_writew (target_phys_addr_t addr, uint32_t val) | |
| 644 | +static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 624 | 645 | { |
| 625 | - PCIBridge *s = &pci_bridge; | |
| 646 | + PCIBridge *s = opaque; | |
| 626 | 647 | #ifdef TARGET_WORDS_BIGENDIAN |
| 627 | 648 | val = bswap16(val); |
| 628 | 649 | #endif |
| 629 | 650 | pci_data_write(s, addr, val, 2); |
| 630 | 651 | } |
| 631 | 652 | |
| 632 | -static void pci_pmac_writel (target_phys_addr_t addr, uint32_t val) | |
| 653 | +static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val) | |
| 633 | 654 | { |
| 634 | - PCIBridge *s = &pci_bridge; | |
| 655 | + PCIBridge *s = opaque; | |
| 635 | 656 | #ifdef TARGET_WORDS_BIGENDIAN |
| 636 | 657 | val = bswap32(val); |
| 637 | 658 | #endif |
| 638 | 659 | pci_data_write(s, addr, val, 4); |
| 639 | 660 | } |
| 640 | 661 | |
| 641 | -static uint32_t pci_pmac_readb (target_phys_addr_t addr) | |
| 662 | +static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr) | |
| 642 | 663 | { |
| 643 | - PCIBridge *s = &pci_bridge; | |
| 664 | + PCIBridge *s = opaque; | |
| 644 | 665 | uint32_t val; |
| 645 | 666 | val = pci_data_read(s, addr, 1); |
| 646 | 667 | return val; |
| 647 | 668 | } |
| 648 | 669 | |
| 649 | -static uint32_t pci_pmac_readw (target_phys_addr_t addr) | |
| 670 | +static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr) | |
| 650 | 671 | { |
| 651 | - PCIBridge *s = &pci_bridge; | |
| 672 | + PCIBridge *s = opaque; | |
| 652 | 673 | uint32_t val; |
| 653 | 674 | val = pci_data_read(s, addr, 2); |
| 654 | 675 | #ifdef TARGET_WORDS_BIGENDIAN |
| ... | ... | @@ -657,9 +678,9 @@ static uint32_t pci_pmac_readw (target_phys_addr_t addr) |
| 657 | 678 | return val; |
| 658 | 679 | } |
| 659 | 680 | |
| 660 | -static uint32_t pci_pmac_readl (target_phys_addr_t addr) | |
| 681 | +static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr) | |
| 661 | 682 | { |
| 662 | - PCIBridge *s = &pci_bridge; | |
| 683 | + PCIBridge *s = opaque; | |
| 663 | 684 | uint32_t val; |
| 664 | 685 | |
| 665 | 686 | val = pci_data_read(s, addr, 4); |
| ... | ... | @@ -683,12 +704,13 @@ static CPUReadMemoryFunc *pci_pmac_read[] = { |
| 683 | 704 | |
| 684 | 705 | void pci_pmac_init(void) |
| 685 | 706 | { |
| 707 | + PCIBridge *s = &pci_bridge; | |
| 686 | 708 | PCIDevice *d; |
| 687 | 709 | int pci_mem_config, pci_mem_data; |
| 688 | 710 | |
| 689 | 711 | pci_mem_config = cpu_register_io_memory(0, pci_pmac_config_read, |
| 690 | - pci_pmac_config_write); | |
| 691 | - pci_mem_data = cpu_register_io_memory(0, pci_pmac_read, pci_pmac_write); | |
| 712 | + pci_pmac_config_write, s); | |
| 713 | + pci_mem_data = cpu_register_io_memory(0, pci_pmac_read, pci_pmac_write, s); | |
| 692 | 714 | |
| 693 | 715 | cpu_register_physical_memory(0xfec00000, 0x1000, pci_mem_config); |
| 694 | 716 | cpu_register_physical_memory(0xfee00000, 0x1000, pci_mem_data); |
| ... | ... | @@ -812,7 +834,7 @@ static void pci_info_device(PCIDevice *d) |
| 812 | 834 | if (d->config[PCI_INTERRUPT_PIN] != 0) { |
| 813 | 835 | printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]); |
| 814 | 836 | } |
| 815 | - for(i = 0;i < 6; i++) { | |
| 837 | + for(i = 0;i < PCI_NUM_REGIONS; i++) { | |
| 816 | 838 | r = &d->io_regions[i]; |
| 817 | 839 | if (r->size != 0) { |
| 818 | 840 | printf(" BAR%d: ", i); |
| ... | ... | @@ -934,13 +956,22 @@ static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) |
| 934 | 956 | { |
| 935 | 957 | PCIIORegion *r; |
| 936 | 958 | uint16_t cmd; |
| 959 | + uint32_t ofs; | |
| 960 | + | |
| 961 | + if ( region_num == PCI_ROM_SLOT ) { | |
| 962 | + ofs = 0x30; | |
| 963 | + }else{ | |
| 964 | + ofs = 0x10 + region_num * 4; | |
| 965 | + } | |
| 937 | 966 | |
| 938 | - pci_config_writel(d, 0x10 + region_num * 4, addr); | |
| 967 | + pci_config_writel(d, ofs, addr); | |
| 939 | 968 | r = &d->io_regions[region_num]; |
| 940 | 969 | |
| 941 | 970 | /* enable memory mappings */ |
| 942 | 971 | cmd = pci_config_readw(d, PCI_COMMAND); |
| 943 | - if (r->type & PCI_ADDRESS_SPACE_IO) | |
| 972 | + if ( region_num == PCI_ROM_SLOT ) | |
| 973 | + cmd |= 2; | |
| 974 | + else if (r->type & PCI_ADDRESS_SPACE_IO) | |
| 944 | 975 | cmd |= 1; |
| 945 | 976 | else |
| 946 | 977 | cmd |= 2; |
| ... | ... | @@ -977,7 +1008,7 @@ static void pci_bios_init_device(PCIDevice *d) |
| 977 | 1008 | break; |
| 978 | 1009 | default: |
| 979 | 1010 | /* default memory mappings */ |
| 980 | - for(i = 0; i < 6; i++) { | |
| 1011 | + for(i = 0; i < PCI_NUM_REGIONS; i++) { | |
| 981 | 1012 | r = &d->io_regions[i]; |
| 982 | 1013 | if (r->size) { |
| 983 | 1014 | if (r->type & PCI_ADDRESS_SPACE_IO) | ... | ... |
vl.h
| ... | ... | @@ -391,6 +391,8 @@ typedef struct PCIIORegion { |
| 391 | 391 | PCIMapIORegionFunc *map_func; |
| 392 | 392 | } PCIIORegion; |
| 393 | 393 | |
| 394 | +#define PCI_ROM_SLOT 6 | |
| 395 | +#define PCI_NUM_REGIONS 7 | |
| 394 | 396 | struct PCIDevice { |
| 395 | 397 | /* PCI config space */ |
| 396 | 398 | uint8_t config[256]; |
| ... | ... | @@ -399,7 +401,7 @@ struct PCIDevice { |
| 399 | 401 | int bus_num; |
| 400 | 402 | int devfn; |
| 401 | 403 | char name[64]; |
| 402 | - PCIIORegion io_regions[6]; | |
| 404 | + PCIIORegion io_regions[PCI_NUM_REGIONS]; | |
| 403 | 405 | |
| 404 | 406 | /* do not access the following fields */ |
| 405 | 407 | PCIConfigReadFunc *config_read; | ... | ... |