changeset 2950:449abdd74783

6354996 pci_boot.c incorrectly accounts for system resources in PCI configuration
author myers
date Fri, 20 Oct 2006 07:29:03 -0700
parents 5581081d0989
children 8e5048c1f58e
files usr/src/uts/i86pc/io/acpica/acpi_enum.c usr/src/uts/i86pc/io/pci/pci_boot.c
diffstat 2 files changed, 75 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/i86pc/io/acpica/acpi_enum.c	Fri Oct 20 07:07:59 2006 -0700
+++ b/usr/src/uts/i86pc/io/acpica/acpi_enum.c	Fri Oct 20 07:29:03 2006 -0700
@@ -2,9 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -279,8 +278,9 @@
 		    addr16.Maximum,
 		    addr16.AddressLength);
 	}
-	if (addr16.ResourceType != ACPI_MEMORY_RANGE &&
-	    addr16.ResourceType != ACPI_IO_RANGE) {
+	if (addr16.ProducerConsumer == ACPI_PRODUCER ||
+	    (addr16.ResourceType != ACPI_MEMORY_RANGE &&
+	    addr16.ResourceType != ACPI_IO_RANGE)) {
 		return;
 	}
 	if (addr16.AddressLength > 0) {
@@ -330,8 +330,9 @@
 		    addr32.Maximum,
 		    addr32.AddressLength);
 	}
-	if (addr32.ResourceType != ACPI_MEMORY_RANGE &&
-	    addr32.ResourceType != ACPI_IO_RANGE) {
+	if (addr32.ProducerConsumer == ACPI_PRODUCER ||
+	    (addr32.ResourceType != ACPI_MEMORY_RANGE &&
+	    addr32.ResourceType != ACPI_IO_RANGE)) {
 		return;
 	}
 	if (addr32.AddressLength > 0) {
@@ -391,8 +392,9 @@
 		    addr64.Maximum,
 		    addr64.AddressLength);
 	}
-	if (addr64.ResourceType != ACPI_MEMORY_RANGE &&
-	    addr64.ResourceType != ACPI_IO_RANGE) {
+	if (addr64.ProducerConsumer == ACPI_PRODUCER ||
+	    (addr64.ResourceType != ACPI_MEMORY_RANGE &&
+	    addr64.ResourceType != ACPI_IO_RANGE)) {
 		return;
 	}
 	if (addr64.AddressLength > 0) {
--- a/usr/src/uts/i86pc/io/pci/pci_boot.c	Fri Oct 20 07:07:59 2006 -0700
+++ b/usr/src/uts/i86pc/io/pci/pci_boot.c	Fri Oct 20 07:29:03 2006 -0700
@@ -356,6 +356,62 @@
 	}
 }
 
+static void
+remove_resource_range(struct memlist **list, int *ranges, int range_count)
+{
+	struct range {
+		uint32_t base;
+		uint32_t len;
+	};
+	int index;
+
+	ASSERT(*list != NULL);
+
+	for (index = 0; index < range_count; index++) {
+		(void) memlist_remove(list,
+		    (uint64_t)((struct range *)ranges)[index].base,
+		    (uint64_t)((struct range *)ranges)[index].len);
+	}
+}
+
+static void
+remove_used_resources()
+{
+	dev_info_t *used;
+	int	*narray;
+	uint_t	ncount;
+	int	status;
+	int	bus;
+
+	used = ddi_find_devinfo("used-resources", -1, 0);
+	if (used == NULL) {
+		printf("pci_boot did not find used-resources\n");
+		return;
+	}
+
+	status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used,
+	    DDI_PROP_DONTPASS, "io-space", &narray, &ncount);
+	if (status == DDI_PROP_SUCCESS) {
+		for (bus = 0; bus <= pci_bios_nbus; bus++)
+			if (pci_bus_res[bus].io_ports != NULL)
+				remove_resource_range(
+				    &pci_bus_res[bus].io_ports,
+				    narray, ncount / 2);
+		ddi_prop_free(narray);
+	}
+
+	status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used,
+	    DDI_PROP_DONTPASS, "device-memory", &narray, &ncount);
+	if (status == DDI_PROP_SUCCESS) {
+		for (bus = 0; bus <= pci_bios_nbus; bus++)
+			if (pci_bus_res[bus].mem_space != NULL)
+				remove_resource_range(
+				    &pci_bus_res[bus].mem_space,
+				    narray, ncount / 2);
+		ddi_prop_free(narray);
+	}
+}
+
 void
 pci_reprogram(void)
 {
@@ -386,6 +442,9 @@
 		ddi_prop_free(onoff);
 	}
 
+	/* remove used-resources from PCI resource maps */
+	remove_used_resources();
+
 	for (i = 0; i <= pci_bios_nbus; i++) {
 		/* configure devices not configured by bios */
 		if (pci_reconfig)
@@ -435,14 +494,15 @@
 	/*
 	 * Special treatment of bus 0:
 	 * If no resource from MPSPEC/HRT, copy pcimem from boot
-	 * and make io space the entire range. There is no difference
-	 * between prefetchable memory or not.
+	 * and make I/O space the entire range starting at 0x100. There
+	 * is no difference between prefetchable memory or not.
 	 */
 	if (pci_bus_res[0].mem_space == NULL)
 		pci_bus_res[0].mem_space =
 		    memlist_dup(bootops->boot_mem->pcimem);
+	/* Exclude 0x00 to 0xff of the I/O space, used by all PCs */
 	if (pci_bus_res[0].io_ports == NULL)
-		memlist_insert(&pci_bus_res[0].io_ports, 0, 0x10000);
+		memlist_insert(&pci_bus_res[0].io_ports, 0x100, 0xff00);
 }
 
 /*