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; | ... | ... |