Commit f2aa58c6f4a208350d05f0994e2e5422acc13c65
1 parent
611493d9
UniNorth PCI bridge support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@955 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
407 additions
and
48 deletions
hw/pci.c
| @@ -45,7 +45,7 @@ typedef struct PCIBridge { | @@ -45,7 +45,7 @@ typedef struct PCIBridge { | ||
| 45 | PCIDevice **pci_bus[256]; | 45 | PCIDevice **pci_bus[256]; |
| 46 | } PCIBridge; | 46 | } PCIBridge; |
| 47 | 47 | ||
| 48 | -static PCIBridge pci_bridge; | 48 | +static PCIBridge pci_bridge[3]; |
| 49 | target_phys_addr_t pci_mem_base; | 49 | target_phys_addr_t pci_mem_base; |
| 50 | static int pci_irq_index; | 50 | static int pci_irq_index; |
| 51 | static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS]; | 51 | static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS]; |
| @@ -56,7 +56,7 @@ PCIDevice *pci_register_device(const char *name, int instance_size, | @@ -56,7 +56,7 @@ PCIDevice *pci_register_device(const char *name, int instance_size, | ||
| 56 | PCIConfigReadFunc *config_read, | 56 | PCIConfigReadFunc *config_read, |
| 57 | PCIConfigWriteFunc *config_write) | 57 | PCIConfigWriteFunc *config_write) |
| 58 | { | 58 | { |
| 59 | - PCIBridge *s = &pci_bridge; | 59 | + PCIBridge *s = &pci_bridge[0]; |
| 60 | PCIDevice *pci_dev, **bus; | 60 | PCIDevice *pci_dev, **bus; |
| 61 | 61 | ||
| 62 | if (pci_irq_index >= PCI_DEVICES_MAX) | 62 | if (pci_irq_index >= PCI_DEVICES_MAX) |
| @@ -70,6 +70,10 @@ PCIDevice *pci_register_device(const char *name, int instance_size, | @@ -70,6 +70,10 @@ PCIDevice *pci_register_device(const char *name, int instance_size, | ||
| 70 | bus = s->pci_bus[bus_num]; | 70 | bus = s->pci_bus[bus_num]; |
| 71 | if (devfn < 0) { | 71 | if (devfn < 0) { |
| 72 | for(devfn = 0 ; devfn < 256; devfn += 8) { | 72 | for(devfn = 0 ; devfn < 256; devfn += 8) { |
| 73 | +#ifdef TARGET_PPC | ||
| 74 | + if ((devfn >> 3) < 11) | ||
| 75 | + continue; | ||
| 76 | +#endif | ||
| 73 | if (!bus[devfn]) | 77 | if (!bus[devfn]) |
| 74 | goto found; | 78 | goto found; |
| 75 | } | 79 | } |
| @@ -425,7 +429,7 @@ static uint32_t pci_data_readl(void* opaque, uint32_t addr) | @@ -425,7 +429,7 @@ static uint32_t pci_data_readl(void* opaque, uint32_t addr) | ||
| 425 | 429 | ||
| 426 | void i440fx_init(void) | 430 | void i440fx_init(void) |
| 427 | { | 431 | { |
| 428 | - PCIBridge *s = &pci_bridge; | 432 | + PCIBridge *s = &pci_bridge[0]; |
| 429 | PCIDevice *d; | 433 | PCIDevice *d; |
| 430 | 434 | ||
| 431 | register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s); | 435 | register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s); |
| @@ -604,7 +608,7 @@ static CPUReadMemoryFunc *PPC_PCIIO_read[] = { | @@ -604,7 +608,7 @@ static CPUReadMemoryFunc *PPC_PCIIO_read[] = { | ||
| 604 | 608 | ||
| 605 | void pci_prep_init(void) | 609 | void pci_prep_init(void) |
| 606 | { | 610 | { |
| 607 | - PCIBridge *s = &pci_bridge; | 611 | + PCIBridge *s = &pci_bridge[0]; |
| 608 | PCIDevice *d; | 612 | PCIDevice *d; |
| 609 | int PPC_io_memory; | 613 | int PPC_io_memory; |
| 610 | 614 | ||
| @@ -629,7 +633,9 @@ void pci_prep_init(void) | @@ -629,7 +633,9 @@ void pci_prep_init(void) | ||
| 629 | 633 | ||
| 630 | /* pmac pci init */ | 634 | /* pmac pci init */ |
| 631 | 635 | ||
| 632 | -static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint32_t val) | 636 | +/* Grackle PCI host */ |
| 637 | +static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr, | ||
| 638 | + uint32_t val) | ||
| 633 | { | 639 | { |
| 634 | PCIBridge *s = opaque; | 640 | PCIBridge *s = opaque; |
| 635 | #ifdef TARGET_WORDS_BIGENDIAN | 641 | #ifdef TARGET_WORDS_BIGENDIAN |
| @@ -638,7 +644,7 @@ static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint3 | @@ -638,7 +644,7 @@ static void pci_pmac_config_writel (void *opaque, target_phys_addr_t addr, uint3 | ||
| 638 | s->config_reg = val; | 644 | s->config_reg = val; |
| 639 | } | 645 | } |
| 640 | 646 | ||
| 641 | -static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr) | 647 | +static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr) |
| 642 | { | 648 | { |
| 643 | PCIBridge *s = opaque; | 649 | PCIBridge *s = opaque; |
| 644 | uint32_t val; | 650 | uint32_t val; |
| @@ -650,25 +656,27 @@ static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr) | @@ -650,25 +656,27 @@ static uint32_t pci_pmac_config_readl (void *opaque, target_phys_addr_t addr) | ||
| 650 | return val; | 656 | return val; |
| 651 | } | 657 | } |
| 652 | 658 | ||
| 653 | -static CPUWriteMemoryFunc *pci_pmac_config_write[] = { | ||
| 654 | - &pci_pmac_config_writel, | ||
| 655 | - &pci_pmac_config_writel, | ||
| 656 | - &pci_pmac_config_writel, | 659 | +static CPUWriteMemoryFunc *pci_grackle_config_write[] = { |
| 660 | + &pci_grackle_config_writel, | ||
| 661 | + &pci_grackle_config_writel, | ||
| 662 | + &pci_grackle_config_writel, | ||
| 657 | }; | 663 | }; |
| 658 | 664 | ||
| 659 | -static CPUReadMemoryFunc *pci_pmac_config_read[] = { | ||
| 660 | - &pci_pmac_config_readl, | ||
| 661 | - &pci_pmac_config_readl, | ||
| 662 | - &pci_pmac_config_readl, | 665 | +static CPUReadMemoryFunc *pci_grackle_config_read[] = { |
| 666 | + &pci_grackle_config_readl, | ||
| 667 | + &pci_grackle_config_readl, | ||
| 668 | + &pci_grackle_config_readl, | ||
| 663 | }; | 669 | }; |
| 664 | 670 | ||
| 665 | -static void pci_pmac_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) | 671 | +static void pci_grackle_writeb (void *opaque, target_phys_addr_t addr, |
| 672 | + uint32_t val) | ||
| 666 | { | 673 | { |
| 667 | PCIBridge *s = opaque; | 674 | PCIBridge *s = opaque; |
| 668 | pci_data_write(s, addr, val, 1); | 675 | pci_data_write(s, addr, val, 1); |
| 669 | } | 676 | } |
| 670 | 677 | ||
| 671 | -static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val) | 678 | +static void pci_grackle_writew (void *opaque, target_phys_addr_t addr, |
| 679 | + uint32_t val) | ||
| 672 | { | 680 | { |
| 673 | PCIBridge *s = opaque; | 681 | PCIBridge *s = opaque; |
| 674 | #ifdef TARGET_WORDS_BIGENDIAN | 682 | #ifdef TARGET_WORDS_BIGENDIAN |
| @@ -677,7 +685,8 @@ static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val | @@ -677,7 +685,8 @@ static void pci_pmac_writew (void *opaque, target_phys_addr_t addr, uint32_t val | ||
| 677 | pci_data_write(s, addr, val, 2); | 685 | pci_data_write(s, addr, val, 2); |
| 678 | } | 686 | } |
| 679 | 687 | ||
| 680 | -static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val) | 688 | +static void pci_grackle_writel (void *opaque, target_phys_addr_t addr, |
| 689 | + uint32_t val) | ||
| 681 | { | 690 | { |
| 682 | PCIBridge *s = opaque; | 691 | PCIBridge *s = opaque; |
| 683 | #ifdef TARGET_WORDS_BIGENDIAN | 692 | #ifdef TARGET_WORDS_BIGENDIAN |
| @@ -686,7 +695,7 @@ static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val | @@ -686,7 +695,7 @@ static void pci_pmac_writel (void *opaque, target_phys_addr_t addr, uint32_t val | ||
| 686 | pci_data_write(s, addr, val, 4); | 695 | pci_data_write(s, addr, val, 4); |
| 687 | } | 696 | } |
| 688 | 697 | ||
| 689 | -static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr) | 698 | +static uint32_t pci_grackle_readb (void *opaque, target_phys_addr_t addr) |
| 690 | { | 699 | { |
| 691 | PCIBridge *s = opaque; | 700 | PCIBridge *s = opaque; |
| 692 | uint32_t val; | 701 | uint32_t val; |
| @@ -694,7 +703,7 @@ static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr) | @@ -694,7 +703,7 @@ static uint32_t pci_pmac_readb (void *opaque, target_phys_addr_t addr) | ||
| 694 | return val; | 703 | return val; |
| 695 | } | 704 | } |
| 696 | 705 | ||
| 697 | -static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr) | 706 | +static uint32_t pci_grackle_readw (void *opaque, target_phys_addr_t addr) |
| 698 | { | 707 | { |
| 699 | PCIBridge *s = opaque; | 708 | PCIBridge *s = opaque; |
| 700 | uint32_t val; | 709 | uint32_t val; |
| @@ -705,7 +714,131 @@ static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr) | @@ -705,7 +714,131 @@ static uint32_t pci_pmac_readw (void *opaque, target_phys_addr_t addr) | ||
| 705 | return val; | 714 | return val; |
| 706 | } | 715 | } |
| 707 | 716 | ||
| 708 | -static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr) | 717 | +static uint32_t pci_grackle_readl (void *opaque, target_phys_addr_t addr) |
| 718 | +{ | ||
| 719 | + PCIBridge *s = opaque; | ||
| 720 | + uint32_t val; | ||
| 721 | + | ||
| 722 | + val = pci_data_read(s, addr, 4); | ||
| 723 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 724 | + val = bswap32(val); | ||
| 725 | +#endif | ||
| 726 | + return val; | ||
| 727 | +} | ||
| 728 | + | ||
| 729 | +static CPUWriteMemoryFunc *pci_grackle_write[] = { | ||
| 730 | + &pci_grackle_writeb, | ||
| 731 | + &pci_grackle_writew, | ||
| 732 | + &pci_grackle_writel, | ||
| 733 | +}; | ||
| 734 | + | ||
| 735 | +static CPUReadMemoryFunc *pci_grackle_read[] = { | ||
| 736 | + &pci_grackle_readb, | ||
| 737 | + &pci_grackle_readw, | ||
| 738 | + &pci_grackle_readl, | ||
| 739 | +}; | ||
| 740 | + | ||
| 741 | +/* Uninorth PCI host (for all Mac99 and newer machines */ | ||
| 742 | +static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr, | ||
| 743 | + uint32_t val) | ||
| 744 | +{ | ||
| 745 | + PCIBridge *s = opaque; | ||
| 746 | + int i; | ||
| 747 | + | ||
| 748 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 749 | + val = bswap32(val); | ||
| 750 | +#endif | ||
| 751 | + | ||
| 752 | + for (i = 11; i < 32; i++) { | ||
| 753 | + if ((val & (1 << i)) != 0) | ||
| 754 | + break; | ||
| 755 | + } | ||
| 756 | +#if 0 | ||
| 757 | + s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11); | ||
| 758 | +#else | ||
| 759 | + s->config_reg = 0x80000000 | (0 << 16) | (val & 0x7FC) | (i << 11); | ||
| 760 | +#endif | ||
| 761 | +} | ||
| 762 | + | ||
| 763 | +static uint32_t pci_unin_main_config_readl (void *opaque, | ||
| 764 | + target_phys_addr_t addr) | ||
| 765 | +{ | ||
| 766 | + PCIBridge *s = opaque; | ||
| 767 | + uint32_t val; | ||
| 768 | + int devfn; | ||
| 769 | + | ||
| 770 | + devfn = (s->config_reg >> 8) & 0xFF; | ||
| 771 | + val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC); | ||
| 772 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 773 | + val = bswap32(val); | ||
| 774 | +#endif | ||
| 775 | + | ||
| 776 | + return val; | ||
| 777 | +} | ||
| 778 | + | ||
| 779 | +static CPUWriteMemoryFunc *pci_unin_main_config_write[] = { | ||
| 780 | + &pci_unin_main_config_writel, | ||
| 781 | + &pci_unin_main_config_writel, | ||
| 782 | + &pci_unin_main_config_writel, | ||
| 783 | +}; | ||
| 784 | + | ||
| 785 | +static CPUReadMemoryFunc *pci_unin_main_config_read[] = { | ||
| 786 | + &pci_unin_main_config_readl, | ||
| 787 | + &pci_unin_main_config_readl, | ||
| 788 | + &pci_unin_main_config_readl, | ||
| 789 | +}; | ||
| 790 | + | ||
| 791 | +static void pci_unin_main_writeb (void *opaque, target_phys_addr_t addr, | ||
| 792 | + uint32_t val) | ||
| 793 | +{ | ||
| 794 | + PCIBridge *s = opaque; | ||
| 795 | + pci_data_write(s, addr & 7, val, 1); | ||
| 796 | +} | ||
| 797 | + | ||
| 798 | +static void pci_unin_main_writew (void *opaque, target_phys_addr_t addr, | ||
| 799 | + uint32_t val) | ||
| 800 | +{ | ||
| 801 | + PCIBridge *s = opaque; | ||
| 802 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 803 | + val = bswap16(val); | ||
| 804 | +#endif | ||
| 805 | + pci_data_write(s, addr & 7, val, 2); | ||
| 806 | +} | ||
| 807 | + | ||
| 808 | +static void pci_unin_main_writel (void *opaque, target_phys_addr_t addr, | ||
| 809 | + uint32_t val) | ||
| 810 | +{ | ||
| 811 | + PCIBridge *s = opaque; | ||
| 812 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 813 | + val = bswap32(val); | ||
| 814 | +#endif | ||
| 815 | + pci_data_write(s, addr & 7, val, 4); | ||
| 816 | +} | ||
| 817 | + | ||
| 818 | +static uint32_t pci_unin_main_readb (void *opaque, target_phys_addr_t addr) | ||
| 819 | +{ | ||
| 820 | + PCIBridge *s = opaque; | ||
| 821 | + uint32_t val; | ||
| 822 | + | ||
| 823 | + val = pci_data_read(s, addr & 7, 1); | ||
| 824 | + | ||
| 825 | + return val; | ||
| 826 | +} | ||
| 827 | + | ||
| 828 | +static uint32_t pci_unin_main_readw (void *opaque, target_phys_addr_t addr) | ||
| 829 | +{ | ||
| 830 | + PCIBridge *s = opaque; | ||
| 831 | + uint32_t val; | ||
| 832 | + | ||
| 833 | + val = pci_data_read(s, addr & 7, 2); | ||
| 834 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 835 | + val = bswap16(val); | ||
| 836 | +#endif | ||
| 837 | + | ||
| 838 | + return val; | ||
| 839 | +} | ||
| 840 | + | ||
| 841 | +static uint32_t pci_unin_main_readl (void *opaque, target_phys_addr_t addr) | ||
| 709 | { | 842 | { |
| 710 | PCIBridge *s = opaque; | 843 | PCIBridge *s = opaque; |
| 711 | uint32_t val; | 844 | uint32_t val; |
| @@ -714,37 +847,246 @@ static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr) | @@ -714,37 +847,246 @@ static uint32_t pci_pmac_readl (void *opaque, target_phys_addr_t addr) | ||
| 714 | #ifdef TARGET_WORDS_BIGENDIAN | 847 | #ifdef TARGET_WORDS_BIGENDIAN |
| 715 | val = bswap32(val); | 848 | val = bswap32(val); |
| 716 | #endif | 849 | #endif |
| 850 | + | ||
| 851 | + return val; | ||
| 852 | +} | ||
| 853 | + | ||
| 854 | +static CPUWriteMemoryFunc *pci_unin_main_write[] = { | ||
| 855 | + &pci_unin_main_writeb, | ||
| 856 | + &pci_unin_main_writew, | ||
| 857 | + &pci_unin_main_writel, | ||
| 858 | +}; | ||
| 859 | + | ||
| 860 | +static CPUReadMemoryFunc *pci_unin_main_read[] = { | ||
| 861 | + &pci_unin_main_readb, | ||
| 862 | + &pci_unin_main_readw, | ||
| 863 | + &pci_unin_main_readl, | ||
| 864 | +}; | ||
| 865 | + | ||
| 866 | +static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr, | ||
| 867 | + uint32_t val) | ||
| 868 | +{ | ||
| 869 | + PCIBridge *s = opaque; | ||
| 870 | + | ||
| 871 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 872 | + val = bswap32(val); | ||
| 873 | +#endif | ||
| 874 | + s->config_reg = 0x80000000 | (val & ~0x00000001); | ||
| 875 | +} | ||
| 876 | + | ||
| 877 | +static uint32_t pci_unin_config_readl (void *opaque, | ||
| 878 | + target_phys_addr_t addr) | ||
| 879 | +{ | ||
| 880 | + PCIBridge *s = opaque; | ||
| 881 | + uint32_t val; | ||
| 882 | + | ||
| 883 | + val = (s->config_reg | 0x00000001) & ~0x80000000; | ||
| 884 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 885 | + val = bswap32(val); | ||
| 886 | +#endif | ||
| 887 | + | ||
| 888 | + return val; | ||
| 889 | +} | ||
| 890 | + | ||
| 891 | +static CPUWriteMemoryFunc *pci_unin_config_write[] = { | ||
| 892 | + &pci_unin_config_writel, | ||
| 893 | + &pci_unin_config_writel, | ||
| 894 | + &pci_unin_config_writel, | ||
| 895 | +}; | ||
| 896 | + | ||
| 897 | +static CPUReadMemoryFunc *pci_unin_config_read[] = { | ||
| 898 | + &pci_unin_config_readl, | ||
| 899 | + &pci_unin_config_readl, | ||
| 900 | + &pci_unin_config_readl, | ||
| 901 | +}; | ||
| 902 | + | ||
| 903 | +static void pci_unin_writeb (void *opaque, target_phys_addr_t addr, | ||
| 904 | + uint32_t val) | ||
| 905 | +{ | ||
| 906 | + PCIBridge *s = opaque; | ||
| 907 | + pci_data_write(s, addr & 3, val, 1); | ||
| 908 | +} | ||
| 909 | + | ||
| 910 | +static void pci_unin_writew (void *opaque, target_phys_addr_t addr, | ||
| 911 | + uint32_t val) | ||
| 912 | +{ | ||
| 913 | + PCIBridge *s = opaque; | ||
| 914 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 915 | + val = bswap16(val); | ||
| 916 | +#endif | ||
| 917 | + pci_data_write(s, addr & 3, val, 2); | ||
| 918 | +} | ||
| 919 | + | ||
| 920 | +static void pci_unin_writel (void *opaque, target_phys_addr_t addr, | ||
| 921 | + uint32_t val) | ||
| 922 | +{ | ||
| 923 | + PCIBridge *s = opaque; | ||
| 924 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 925 | + val = bswap32(val); | ||
| 926 | +#endif | ||
| 927 | + pci_data_write(s, addr & 3, val, 4); | ||
| 928 | +} | ||
| 929 | + | ||
| 930 | +static uint32_t pci_unin_readb (void *opaque, target_phys_addr_t addr) | ||
| 931 | +{ | ||
| 932 | + PCIBridge *s = opaque; | ||
| 933 | + uint32_t val; | ||
| 934 | + | ||
| 935 | + val = pci_data_read(s, addr & 3, 1); | ||
| 936 | + | ||
| 937 | + return val; | ||
| 938 | +} | ||
| 939 | + | ||
| 940 | +static uint32_t pci_unin_readw (void *opaque, target_phys_addr_t addr) | ||
| 941 | +{ | ||
| 942 | + PCIBridge *s = opaque; | ||
| 943 | + uint32_t val; | ||
| 944 | + | ||
| 945 | + val = pci_data_read(s, addr & 3, 2); | ||
| 946 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 947 | + val = bswap16(val); | ||
| 948 | +#endif | ||
| 949 | + | ||
| 950 | + return val; | ||
| 951 | +} | ||
| 952 | + | ||
| 953 | +static uint32_t pci_unin_readl (void *opaque, target_phys_addr_t addr) | ||
| 954 | +{ | ||
| 955 | + PCIBridge *s = opaque; | ||
| 956 | + uint32_t val; | ||
| 957 | + | ||
| 958 | + val = pci_data_read(s, addr & 3, 4); | ||
| 959 | +#ifdef TARGET_WORDS_BIGENDIAN | ||
| 960 | + val = bswap32(val); | ||
| 961 | +#endif | ||
| 962 | + | ||
| 717 | return val; | 963 | return val; |
| 718 | } | 964 | } |
| 719 | 965 | ||
| 720 | -static CPUWriteMemoryFunc *pci_pmac_write[] = { | ||
| 721 | - &pci_pmac_writeb, | ||
| 722 | - &pci_pmac_writew, | ||
| 723 | - &pci_pmac_writel, | 966 | +static CPUWriteMemoryFunc *pci_unin_write[] = { |
| 967 | + &pci_unin_writeb, | ||
| 968 | + &pci_unin_writew, | ||
| 969 | + &pci_unin_writel, | ||
| 724 | }; | 970 | }; |
| 725 | 971 | ||
| 726 | -static CPUReadMemoryFunc *pci_pmac_read[] = { | ||
| 727 | - &pci_pmac_readb, | ||
| 728 | - &pci_pmac_readw, | ||
| 729 | - &pci_pmac_readl, | 972 | +static CPUReadMemoryFunc *pci_unin_read[] = { |
| 973 | + &pci_unin_readb, | ||
| 974 | + &pci_unin_readw, | ||
| 975 | + &pci_unin_readl, | ||
| 730 | }; | 976 | }; |
| 731 | 977 | ||
| 732 | void pci_pmac_init(void) | 978 | void pci_pmac_init(void) |
| 733 | { | 979 | { |
| 734 | - PCIBridge *s = &pci_bridge; | 980 | + PCIBridge *s; |
| 735 | PCIDevice *d; | 981 | PCIDevice *d; |
| 736 | int pci_mem_config, pci_mem_data; | 982 | int pci_mem_config, pci_mem_data; |
| 737 | 983 | ||
| 738 | - pci_mem_config = cpu_register_io_memory(0, pci_pmac_config_read, | ||
| 739 | - pci_pmac_config_write, s); | ||
| 740 | - pci_mem_data = cpu_register_io_memory(0, pci_pmac_read, pci_pmac_write, s); | ||
| 741 | - | ||
| 742 | - cpu_register_physical_memory(0xfec00000, 0x1000, pci_mem_config); | ||
| 743 | - cpu_register_physical_memory(0xfee00000, 0x1000, pci_mem_data); | ||
| 744 | - | ||
| 745 | - d = pci_register_device("MPC106", sizeof(PCIDevice), 0, 0, | 984 | + /* Use values found on a real PowerMac */ |
| 985 | + /* Uninorth main bus */ | ||
| 986 | + s = &pci_bridge[0]; | ||
| 987 | + pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read, | ||
| 988 | + pci_unin_main_config_write, s); | ||
| 989 | + pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read, | ||
| 990 | + pci_unin_main_write, s); | ||
| 991 | + cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config); | ||
| 992 | + cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data); | ||
| 993 | + | ||
| 994 | + d = pci_register_device("Uni-north main", sizeof(PCIDevice), 0, 11 << 3, | ||
| 746 | NULL, NULL); | 995 | NULL, NULL); |
| 996 | + d->config[0x00] = 0x6b; // vendor_id : Apple | ||
| 997 | + d->config[0x01] = 0x10; | ||
| 998 | + d->config[0x02] = 0x1F; // device_id | ||
| 999 | + d->config[0x03] = 0x00; | ||
| 1000 | + d->config[0x08] = 0x00; // revision | ||
| 1001 | + d->config[0x0A] = 0x00; // class_sub = pci host | ||
| 1002 | + d->config[0x0B] = 0x06; // class_base = PCI_bridge | ||
| 1003 | + d->config[0x0C] = 0x08; // cache_line_size | ||
| 1004 | + d->config[0x0D] = 0x10; // latency_timer | ||
| 1005 | + d->config[0x0E] = 0x00; // header_type | ||
| 1006 | + d->config[0x34] = 0x00; // capabilities_pointer | ||
| 1007 | + | ||
| 1008 | +#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly | ||
| 1009 | + /* pci-to-pci bridge */ | ||
| 1010 | + d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3, | ||
| 1011 | + NULL, NULL); | ||
| 1012 | + d->config[0x00] = 0x11; // vendor_id : TI | ||
| 1013 | + d->config[0x01] = 0x10; | ||
| 1014 | + d->config[0x02] = 0x26; // device_id | ||
| 1015 | + d->config[0x03] = 0x00; | ||
| 1016 | + d->config[0x08] = 0x05; // revision | ||
| 1017 | + d->config[0x0A] = 0x04; // class_sub = pci2pci | ||
| 1018 | + d->config[0x0B] = 0x06; // class_base = PCI_bridge | ||
| 1019 | + d->config[0x0C] = 0x08; // cache_line_size | ||
| 1020 | + d->config[0x0D] = 0x20; // latency_timer | ||
| 1021 | + d->config[0x0E] = 0x01; // header_type | ||
| 1022 | + | ||
| 1023 | + d->config[0x18] = 0x01; // primary_bus | ||
| 1024 | + d->config[0x19] = 0x02; // secondary_bus | ||
| 1025 | + d->config[0x1A] = 0x02; // subordinate_bus | ||
| 1026 | + d->config[0x1B] = 0x20; // secondary_latency_timer | ||
| 1027 | + d->config[0x1C] = 0x11; // io_base | ||
| 1028 | + d->config[0x1D] = 0x01; // io_limit | ||
| 1029 | + d->config[0x20] = 0x00; // memory_base | ||
| 1030 | + d->config[0x21] = 0x80; | ||
| 1031 | + d->config[0x22] = 0x00; // memory_limit | ||
| 1032 | + d->config[0x23] = 0x80; | ||
| 1033 | + d->config[0x24] = 0x01; // prefetchable_memory_base | ||
| 1034 | + d->config[0x25] = 0x80; | ||
| 1035 | + d->config[0x26] = 0xF1; // prefectchable_memory_limit | ||
| 1036 | + d->config[0x27] = 0x7F; | ||
| 1037 | + // d->config[0x34] = 0xdc // capabilities_pointer | ||
| 1038 | +#endif | ||
| 1039 | +#if 0 // XXX: not needed for now | ||
| 1040 | + /* Uninorth AGP bus */ | ||
| 1041 | + s = &pci_bridge[1]; | ||
| 1042 | + pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, | ||
| 1043 | + pci_unin_config_write, s); | ||
| 1044 | + pci_mem_data = cpu_register_io_memory(0, pci_unin_read, | ||
| 1045 | + pci_unin_write, s); | ||
| 1046 | + cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config); | ||
| 1047 | + cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data); | ||
| 1048 | + | ||
| 1049 | + d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3, | ||
| 1050 | + NULL, NULL); | ||
| 1051 | + d->config[0x00] = 0x6b; // vendor_id : Apple | ||
| 1052 | + d->config[0x01] = 0x10; | ||
| 1053 | + d->config[0x02] = 0x20; // device_id | ||
| 1054 | + d->config[0x03] = 0x00; | ||
| 1055 | + d->config[0x08] = 0x00; // revision | ||
| 1056 | + d->config[0x0A] = 0x00; // class_sub = pci host | ||
| 1057 | + d->config[0x0B] = 0x06; // class_base = PCI_bridge | ||
| 1058 | + d->config[0x0C] = 0x08; // cache_line_size | ||
| 1059 | + d->config[0x0D] = 0x10; // latency_timer | ||
| 1060 | + d->config[0x0E] = 0x00; // header_type | ||
| 1061 | + // d->config[0x34] = 0x80; // capabilities_pointer | ||
| 1062 | +#endif | ||
| 747 | 1063 | ||
| 1064 | +#if 0 // XXX: not needed for now | ||
| 1065 | + /* Uninorth internal bus */ | ||
| 1066 | + s = &pci_bridge[2]; | ||
| 1067 | + pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, | ||
| 1068 | + pci_unin_config_write, s); | ||
| 1069 | + pci_mem_data = cpu_register_io_memory(0, pci_unin_read, | ||
| 1070 | + pci_unin_write, s); | ||
| 1071 | + cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config); | ||
| 1072 | + cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data); | ||
| 1073 | + | ||
| 1074 | + d = pci_register_device("Uni-north internal", sizeof(PCIDevice), | ||
| 1075 | + 3, 11 << 3, NULL, NULL); | ||
| 1076 | + d->config[0x00] = 0x6b; // vendor_id : Apple | ||
| 1077 | + d->config[0x01] = 0x10; | ||
| 1078 | + d->config[0x02] = 0x1E; // device_id | ||
| 1079 | + d->config[0x03] = 0x00; | ||
| 1080 | + d->config[0x08] = 0x00; // revision | ||
| 1081 | + d->config[0x0A] = 0x00; // class_sub = pci host | ||
| 1082 | + d->config[0x0B] = 0x06; // class_base = PCI_bridge | ||
| 1083 | + d->config[0x0C] = 0x08; // cache_line_size | ||
| 1084 | + d->config[0x0D] = 0x10; // latency_timer | ||
| 1085 | + d->config[0x0E] = 0x00; // header_type | ||
| 1086 | + d->config[0x34] = 0x00; // capabilities_pointer | ||
| 1087 | +#endif | ||
| 1088 | + | ||
| 1089 | +#if 0 // Grackle ? | ||
| 748 | /* same values as PearPC - check this */ | 1090 | /* same values as PearPC - check this */ |
| 749 | d->config[0x00] = 0x11; // vendor_id | 1091 | d->config[0x00] = 0x11; // vendor_id |
| 750 | d->config[0x01] = 0x10; | 1092 | d->config[0x01] = 0x10; |
| @@ -770,6 +1112,7 @@ void pci_pmac_init(void) | @@ -770,6 +1112,7 @@ void pci_pmac_init(void) | ||
| 770 | d->config[0x25] = 0x84; | 1112 | d->config[0x25] = 0x84; |
| 771 | d->config[0x26] = 0x00; // prefetchable_memory_limit | 1113 | d->config[0x26] = 0x00; // prefetchable_memory_limit |
| 772 | d->config[0x27] = 0x85; | 1114 | d->config[0x27] = 0x85; |
| 1115 | +#endif | ||
| 773 | } | 1116 | } |
| 774 | 1117 | ||
| 775 | /***********************************************************/ | 1118 | /***********************************************************/ |
| @@ -878,7 +1221,7 @@ static void pci_info_device(PCIDevice *d) | @@ -878,7 +1221,7 @@ static void pci_info_device(PCIDevice *d) | ||
| 878 | 1221 | ||
| 879 | void pci_info(void) | 1222 | void pci_info(void) |
| 880 | { | 1223 | { |
| 881 | - PCIBridge *s = &pci_bridge; | 1224 | + PCIBridge *s = &pci_bridge[0]; |
| 882 | PCIDevice **bus; | 1225 | PCIDevice **bus; |
| 883 | int bus_num, devfn; | 1226 | int bus_num, devfn; |
| 884 | 1227 | ||
| @@ -928,7 +1271,7 @@ static void isa_outl(uint32_t val, uint32_t addr) | @@ -928,7 +1271,7 @@ static void isa_outl(uint32_t val, uint32_t addr) | ||
| 928 | 1271 | ||
| 929 | static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) | 1272 | static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) |
| 930 | { | 1273 | { |
| 931 | - PCIBridge *s = &pci_bridge; | 1274 | + PCIBridge *s = &pci_bridge[0]; |
| 932 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | 1275 | s->config_reg = 0x80000000 | (d->bus_num << 16) | |
| 933 | (d->devfn << 8) | addr; | 1276 | (d->devfn << 8) | addr; |
| 934 | pci_data_write(s, 0, val, 4); | 1277 | pci_data_write(s, 0, val, 4); |
| @@ -936,7 +1279,7 @@ static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) | @@ -936,7 +1279,7 @@ static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) | ||
| 936 | 1279 | ||
| 937 | static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) | 1280 | static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) |
| 938 | { | 1281 | { |
| 939 | - PCIBridge *s = &pci_bridge; | 1282 | + PCIBridge *s = &pci_bridge[0]; |
| 940 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | 1283 | s->config_reg = 0x80000000 | (d->bus_num << 16) | |
| 941 | (d->devfn << 8) | (addr & ~3); | 1284 | (d->devfn << 8) | (addr & ~3); |
| 942 | pci_data_write(s, addr & 3, val, 2); | 1285 | pci_data_write(s, addr & 3, val, 2); |
| @@ -944,7 +1287,7 @@ static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) | @@ -944,7 +1287,7 @@ static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) | ||
| 944 | 1287 | ||
| 945 | static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) | 1288 | static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) |
| 946 | { | 1289 | { |
| 947 | - PCIBridge *s = &pci_bridge; | 1290 | + PCIBridge *s = &pci_bridge[0]; |
| 948 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | 1291 | s->config_reg = 0x80000000 | (d->bus_num << 16) | |
| 949 | (d->devfn << 8) | (addr & ~3); | 1292 | (d->devfn << 8) | (addr & ~3); |
| 950 | pci_data_write(s, addr & 3, val, 1); | 1293 | pci_data_write(s, addr & 3, val, 1); |
| @@ -952,7 +1295,7 @@ static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) | @@ -952,7 +1295,7 @@ static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) | ||
| 952 | 1295 | ||
| 953 | static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) | 1296 | static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) |
| 954 | { | 1297 | { |
| 955 | - PCIBridge *s = &pci_bridge; | 1298 | + PCIBridge *s = &pci_bridge[0]; |
| 956 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | 1299 | s->config_reg = 0x80000000 | (d->bus_num << 16) | |
| 957 | (d->devfn << 8) | addr; | 1300 | (d->devfn << 8) | addr; |
| 958 | return pci_data_read(s, 0, 4); | 1301 | return pci_data_read(s, 0, 4); |
| @@ -960,7 +1303,7 @@ static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) | @@ -960,7 +1303,7 @@ static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) | ||
| 960 | 1303 | ||
| 961 | static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) | 1304 | static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) |
| 962 | { | 1305 | { |
| 963 | - PCIBridge *s = &pci_bridge; | 1306 | + PCIBridge *s = &pci_bridge[0]; |
| 964 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | 1307 | s->config_reg = 0x80000000 | (d->bus_num << 16) | |
| 965 | (d->devfn << 8) | (addr & ~3); | 1308 | (d->devfn << 8) | (addr & ~3); |
| 966 | return pci_data_read(s, addr & 3, 2); | 1309 | return pci_data_read(s, addr & 3, 2); |
| @@ -968,7 +1311,7 @@ static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) | @@ -968,7 +1311,7 @@ static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) | ||
| 968 | 1311 | ||
| 969 | static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) | 1312 | static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) |
| 970 | { | 1313 | { |
| 971 | - PCIBridge *s = &pci_bridge; | 1314 | + PCIBridge *s = &pci_bridge[0]; |
| 972 | s->config_reg = 0x80000000 | (d->bus_num << 16) | | 1315 | s->config_reg = 0x80000000 | (d->bus_num << 16) | |
| 973 | (d->devfn << 8) | (addr & ~3); | 1316 | (d->devfn << 8) | (addr & ~3); |
| 974 | return pci_data_read(s, addr & 3, 1); | 1317 | return pci_data_read(s, addr & 3, 1); |
| @@ -1036,8 +1379,21 @@ static void pci_bios_init_device(PCIDevice *d) | @@ -1036,8 +1379,21 @@ static void pci_bios_init_device(PCIDevice *d) | ||
| 1036 | /* VGA: map frame buffer to default Bochs VBE address */ | 1379 | /* VGA: map frame buffer to default Bochs VBE address */ |
| 1037 | pci_set_io_region_addr(d, 0, 0xE0000000); | 1380 | pci_set_io_region_addr(d, 0, 0xE0000000); |
| 1038 | break; | 1381 | break; |
| 1382 | + case 0x0800: | ||
| 1383 | + /* PIC */ | ||
| 1384 | + vendor_id = pci_config_readw(d, PCI_VENDOR_ID); | ||
| 1385 | + device_id = pci_config_readw(d, PCI_DEVICE_ID); | ||
| 1386 | + if (vendor_id == 0x1014) { | ||
| 1387 | + /* IBM */ | ||
| 1388 | + if (device_id == 0x0046 || device_id == 0xFFFF) { | ||
| 1389 | + /* MPIC & MPIC2 */ | ||
| 1390 | + pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000); | ||
| 1391 | + } | ||
| 1392 | + } | ||
| 1393 | + break; | ||
| 1039 | case 0xff00: | 1394 | case 0xff00: |
| 1040 | - if (vendor_id == 0x0106b && device_id == 0x0017) { | 1395 | + if (vendor_id == 0x0106b && |
| 1396 | + (device_id == 0x0017 || device_id == 0x0022)) { | ||
| 1041 | /* macio bridge */ | 1397 | /* macio bridge */ |
| 1042 | pci_set_io_region_addr(d, 0, 0x80800000); | 1398 | pci_set_io_region_addr(d, 0, 0x80800000); |
| 1043 | } | 1399 | } |
| @@ -1076,7 +1432,7 @@ static void pci_bios_init_device(PCIDevice *d) | @@ -1076,7 +1432,7 @@ static void pci_bios_init_device(PCIDevice *d) | ||
| 1076 | */ | 1432 | */ |
| 1077 | void pci_bios_init(void) | 1433 | void pci_bios_init(void) |
| 1078 | { | 1434 | { |
| 1079 | - PCIBridge *s = &pci_bridge; | 1435 | + PCIBridge *s = &pci_bridge[0]; |
| 1080 | PCIDevice **bus; | 1436 | PCIDevice **bus; |
| 1081 | int bus_num, devfn, i, irq; | 1437 | int bus_num, devfn, i, irq; |
| 1082 | uint8_t elcr[2]; | 1438 | uint8_t elcr[2]; |
| @@ -1115,10 +1471,13 @@ void pci_bios_init(void) | @@ -1115,10 +1471,13 @@ void pci_bios_init(void) | ||
| 1115 | */ | 1471 | */ |
| 1116 | void pci_ppc_bios_init(void) | 1472 | void pci_ppc_bios_init(void) |
| 1117 | { | 1473 | { |
| 1118 | - PCIBridge *s = &pci_bridge; | 1474 | + PCIBridge *s = &pci_bridge[0]; |
| 1119 | PCIDevice **bus; | 1475 | PCIDevice **bus; |
| 1120 | - int bus_num, devfn, i, irq; | 1476 | + int bus_num, devfn; |
| 1477 | +#if 0 | ||
| 1478 | + int i, irq; | ||
| 1121 | uint8_t elcr[2]; | 1479 | uint8_t elcr[2]; |
| 1480 | +#endif | ||
| 1122 | 1481 | ||
| 1123 | pci_bios_io_addr = 0xc000; | 1482 | pci_bios_io_addr = 0xc000; |
| 1124 | pci_bios_mem_addr = 0xc0000000; | 1483 | pci_bios_mem_addr = 0xc0000000; |