659 } |
659 } |
660 |
660 |
661 subbus = pci_getb(bus, dev, func, PCI_BCNF_SUBBUS); |
661 subbus = pci_getb(bus, dev, func, PCI_BCNF_SUBBUS); |
662 parbus = pci_bus_res[secbus].par_bus; |
662 parbus = pci_bus_res[secbus].par_bus; |
663 ASSERT(parbus == bus); |
663 ASSERT(parbus == bus); |
|
664 cmd_reg = pci_getw(bus, dev, func, PCI_CONF_COMM); |
664 |
665 |
665 /* |
666 /* |
666 * If we have a Cardbus bridge, but no bus space |
667 * If we have a Cardbus bridge, but no bus space |
667 */ |
668 */ |
668 if (pci_bus_res[secbus].num_cbb != 0 && |
669 if (pci_bus_res[secbus].num_cbb != 0 && |
773 |
774 |
774 goto cmd_enable; |
775 goto cmd_enable; |
775 } |
776 } |
776 |
777 |
777 /* |
778 /* |
778 * io_base > io_limit means that the bridge was not configured |
779 * Check to see if we need to reprogram I/O space, either because the |
779 * This may have been set by the BIOS or by add_ppb_props() |
780 * parent bus needed reprogramming and so do we, or because I/O space is |
780 * if I/O space is disabled in the Command register. |
781 * disabled in base/limit or command register. |
781 */ |
782 */ |
782 io_base = pci_getb(bus, dev, func, PCI_BCNF_IO_BASE_LOW); |
783 io_base = pci_getb(bus, dev, func, PCI_BCNF_IO_BASE_LOW); |
783 io_limit = pci_getb(bus, dev, func, PCI_BCNF_IO_LIMIT_LOW); |
784 io_limit = pci_getb(bus, dev, func, PCI_BCNF_IO_LIMIT_LOW); |
784 io_base = (io_base & 0xf0) << 8; |
785 io_base = (io_base & 0xf0) << 8; |
785 io_limit = ((io_limit & 0xf0) << 8) | 0xfff; |
786 io_limit = ((io_limit & 0xf0) << 8) | 0xfff; |
786 |
787 |
787 if (pci_bus_res[parbus].io_reprogram || (io_base > io_limit)) { |
788 if (pci_bus_res[parbus].io_reprogram || (io_base > io_limit) || |
|
789 (!(cmd_reg & PCI_COMM_IO))) { |
788 if (pci_bus_res[secbus].io_ports_used) { |
790 if (pci_bus_res[secbus].io_ports_used) { |
789 memlist_merge(&pci_bus_res[secbus].io_ports_used, |
791 memlist_merge(&pci_bus_res[secbus].io_ports_used, |
790 &pci_bus_res[secbus].io_ports); |
792 &pci_bus_res[secbus].io_ports); |
791 } |
793 } |
792 if (pci_bus_res[secbus].io_ports && |
794 if (pci_bus_res[secbus].io_ports && |
846 bus, dev, func, io_base, io_limit); |
848 bus, dev, func, io_base, io_limit); |
847 } |
849 } |
848 } |
850 } |
849 |
851 |
850 /* |
852 /* |
851 * mem_base > mem_limit |
853 * Check memory space as we did I/O space. |
852 */ |
854 */ |
853 mem_base = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_MEM_BASE); |
855 mem_base = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_MEM_BASE); |
854 mem_base = (mem_base & 0xfff0) << 16; |
856 mem_base = (mem_base & 0xfff0) << 16; |
855 mem_limit = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_MEM_LIMIT); |
857 mem_limit = (uint_t)pci_getw(bus, dev, func, PCI_BCNF_MEM_LIMIT); |
856 mem_limit = ((mem_limit & 0xfff0) << 16) |0xfffff; |
858 mem_limit = ((mem_limit & 0xfff0) << 16) | 0xfffff; |
857 if (pci_bus_res[parbus].mem_reprogram || (mem_base > mem_limit)) { |
859 |
|
860 if (pci_bus_res[parbus].mem_reprogram || (mem_base > mem_limit) || |
|
861 (!(cmd_reg & PCI_COMM_MAE))) { |
858 if (pci_bus_res[secbus].mem_space_used) { |
862 if (pci_bus_res[secbus].mem_space_used) { |
859 memlist_merge(&pci_bus_res[secbus].mem_space_used, |
863 memlist_merge(&pci_bus_res[secbus].mem_space_used, |
860 &pci_bus_res[secbus].mem_space); |
864 &pci_bus_res[secbus].mem_space); |
861 } |
865 } |
862 if (pci_bus_res[secbus].mem_space && |
866 if (pci_bus_res[secbus].mem_space && |
915 bus, dev, func, mem_base, mem_limit); |
919 bus, dev, func, mem_base, mem_limit); |
916 } |
920 } |
917 } |
921 } |
918 |
922 |
919 cmd_enable: |
923 cmd_enable: |
920 cmd_reg = pci_getw(bus, dev, func, PCI_CONF_COMM); |
|
921 if (pci_bus_res[secbus].io_ports) |
924 if (pci_bus_res[secbus].io_ports) |
922 cmd_reg |= PCI_COMM_IO | PCI_COMM_ME; |
925 cmd_reg |= PCI_COMM_IO | PCI_COMM_ME; |
923 if (pci_bus_res[secbus].mem_space) |
926 if (pci_bus_res[secbus].mem_space) |
924 cmd_reg |= PCI_COMM_MAE | PCI_COMM_ME; |
927 cmd_reg |= PCI_COMM_MAE | PCI_COMM_ME; |
925 pci_putw(bus, dev, func, PCI_CONF_COMM, cmd_reg); |
928 pci_putw(bus, dev, func, PCI_CONF_COMM, cmd_reg); |