PSARC 2009/056 Removal of ISA Pseudo Node
authorJudy Chen <Judy.Chen@Sun.COM>
Tue, 24 Mar 2009 10:24:01 +0800
changeset 9149 3b20bb584283
parent 9148 cbc850545d32
child 9150 74da91783a73
PSARC 2009/056 Removal of ISA Pseudo Node 6813425 Remove /isa pseudo node for x86
usr/src/tools/scripts/bfu.sh
usr/src/uts/i86pc/io/consplat.c
usr/src/uts/i86pc/io/isa.c
usr/src/uts/i86pc/isa/Makefile
usr/src/uts/i86pc/os/ddi_impl.c
usr/src/uts/i86xpv/isa/Makefile
usr/src/uts/intel/io/pci/pci_boot.c
usr/src/uts/intel/os/driver_aliases
--- a/usr/src/tools/scripts/bfu.sh	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/tools/scripts/bfu.sh	Tue Mar 24 10:24:01 2009 +0800
@@ -4168,6 +4168,24 @@
 	fi
 }
 
+fixup_isa_bkbfu()
+{
+	aliasfile=$rootprefix/etc/driver_aliases
+	parentalias=$rootprefix/bfu.parent/etc/driver_aliases
+	isaalias="pciclass,060100"
+
+	if [ $target_isa != i386 ]; then
+		return;
+	fi
+
+	# bfu forwards, just return
+	egrep -s "\"$isaalias\"" $parentalias && return
+
+	# remove the pciclass,060100 entry for isa when going backwards
+	egrep -s "\"$isaalias\"" $aliasfile || return
+	/tmp/bfubin/update_drv -b $root -d -i "$isaalias" isa >/dev/null 2>&1
+}
+
 #
 # Check to see if root in $1 has a mounted boot, and that
 # it's mounted at the right place for bfu to handle it.
@@ -8130,6 +8148,8 @@
 
 	tx_check_bkbfu
 
+	fixup_isa_bkbfu
+
 	update_aac_conf
 
 	if [ $target_isa = i386 ]; then
--- a/usr/src/uts/i86pc/io/consplat.c	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/uts/i86pc/io/consplat.c	Tue Mar 24 10:24:01 2009 +0800
@@ -20,12 +20,10 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 /*
  * isa-specific console configuration routines
  */
@@ -49,6 +47,8 @@
 #include <sys/boot_console.h>
 #endif
 
+extern int pseudo_isa;
+
 /* The names of currently supported graphics drivers on x86 */
 static char *
 gfxdrv_name[] = {
@@ -156,17 +156,48 @@
 	return (console_type() == CONS_SCREEN);
 }
 
+static char *
+plat_devpath(char *name, char *path)
+{
+	major_t major;
+	dev_info_t *dip, *pdip;
+
+	if ((major = ddi_name_to_major(name)) == (major_t)-1)
+		return (NULL);
+
+	if ((dip = devnamesp[major].dn_head) == NULL)
+		return (NULL);
+
+	pdip = ddi_get_parent(dip);
+	if (i_ddi_attach_node_hierarchy(pdip) != DDI_SUCCESS)
+		return (NULL);
+	if (ddi_initchild(pdip, dip) != DDI_SUCCESS)
+		return (NULL);
+
+	(void) ddi_pathname(dip, path);
+
+	return (path);
+}
+
 /*
  * Return generic path to keyboard device from the alias.
  */
 char *
 plat_kbdpath(void)
 {
+	static char kbpath[MAXPATHLEN];
+
 	/*
 	 * Hardcode to isa keyboard path
 	 * XXX make it settable via bootprop?
 	 */
-	return ("/isa/i8042@1,60/keyboard@0");
+	if (pseudo_isa)
+		return ("/isa/i8042@1,60/keyboard@0");
+
+	if (plat_devpath("kb8042", kbpath) == NULL)
+		return (NULL);
+
+	return (kbpath);
 }
 
 /*
@@ -225,11 +256,19 @@
 char *
 plat_mousepath(void)
 {
+	static char mpath[MAXPATHLEN];
+
 	/*
 	 * Hardcode to isa mouse path
 	 * XXX make it settable via bootprop?
 	 */
-	return ("/isa/i8042@1,60/mouse@1");
+	if (pseudo_isa)
+		return ("/isa/i8042@1,60/mouse@1");
+
+	if (plat_devpath("mouse8042", mpath) == NULL)
+		return (NULL);
+
+	return (mpath);
 }
 
 /* return path of first usb serial device */
@@ -254,6 +293,42 @@
 	return (us_path);
 }
 
+static char *
+plat_ttypath(int inum)
+{
+	static char *defaultpath[] = {
+	    "/isa/asy@1,3f8:a",
+	    "/isa/asy@1,2f8:b"
+	};
+	static char path[MAXPATHLEN];
+	char *bp;
+	major_t major;
+	dev_info_t *dip;
+
+	if (pseudo_isa)
+		return (defaultpath[inum]);
+
+	if ((major = ddi_name_to_major("asy")) == (major_t)-1)
+		return (NULL);
+
+	if ((dip = devnamesp[major].dn_head) == NULL)
+		return (NULL);
+
+	while (inum-- > 0) {
+		if ((dip = ddi_get_next(dip)) == NULL)
+			return (NULL);
+	}
+
+	if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
+		return (NULL);
+
+	(void) ddi_pathname(dip, path);
+	bp = path + strlen(path);
+	(void) snprintf(bp, 3, ":%s", DEVI(dip)->devi_minor->ddm_name);
+
+	return (path);
+}
+
 /*
  * Lacking support for com2 and com3, if that matters.
  * Another possible enhancement could be to use properties
@@ -268,9 +343,9 @@
 		return ("/xpvd/xencons@0");
 #endif /* __xpv */
 	case CONS_TTYA:
-		return ("/isa/asy@1,3f8:a");
+		return (plat_ttypath(0));
 	case CONS_TTYB:
-		return ("/isa/asy@1,2f8:b");
+		return (plat_ttypath(1));
 	case CONS_USBSER:
 		return (plat_usbser_path());
 	case CONS_SCREEN:
@@ -289,9 +364,9 @@
 		return ("/xpvd/xencons@0");
 #endif /* __xpv */
 	case CONS_TTYA:
-		return ("/isa/asy@1,3f8:a");
+		return (plat_ttypath(0));
 	case CONS_TTYB:
-		return ("/isa/asy@1,2f8:b");
+		return (plat_ttypath(1));
 	case CONS_USBSER:
 		return (plat_usbser_path());
 	case CONS_SCREEN:
--- a/usr/src/uts/i86pc/io/isa.c	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/uts/i86pc/io/isa.c	Tue Mar 24 10:24:01 2009 +0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,17 +43,45 @@
 #include <sys/sunddi.h>
 #include <sys/sunndi.h>
 #include <sys/acpi/acpi_enum.h>
+#include <sys/mach_intr.h>
+#include <sys/pci.h>
+#include <sys/note.h>
 #if defined(__xpv)
 #include <sys/hypervisor.h>
 #include <sys/evtchn_impl.h>
 #endif
 
-
+extern int pseudo_isa;
 extern int isa_resource_setup(void);
+extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *,
+    psm_intr_op_t, int *);
+extern void pci_remove_isa_resources(int, uint32_t, uint32_t);
 static char USED_RESOURCES[] = "used-resources";
 static void isa_alloc_nodes(dev_info_t *);
 static void enumerate_BIOS_serial(dev_info_t *);
+static void isa_postattach(dev_info_t *);
 
+/*
+ * The following typedef is used to represent an entry in the "ranges"
+ * property of a pci-isa bridge device node.
+ */
+typedef struct {
+	uint32_t child_high;
+	uint32_t child_low;
+	uint32_t parent_high;
+	uint32_t parent_mid;
+	uint32_t parent_low;
+	uint32_t size;
+} pib_ranges_t;
+
+typedef struct {
+	uint32_t base;
+	uint32_t len;
+} used_ranges_t;
+
+#define	USED_CELL_SIZE	2	/* 1 byte addr, 1 byte size */
+#define	ISA_ADDR_IO	1	/* IO address space */
+#define	ISA_ADDR_MEM	0	/* memory adress space */
 #define	BIOS_DATA_AREA	0x400
 /*
  * #define ISA_DEBUG 1
@@ -98,6 +126,10 @@
  */
 
 static int
+isa_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
+    off_t offset, off_t len, caddr_t *vaddrp);
+
+static int
 isa_dma_allochdl(dev_info_t *, dev_info_t *, ddi_dma_attr_t *,
     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *);
 
@@ -108,9 +140,13 @@
 static int
 isa_ctlops(dev_info_t *, dev_info_t *, ddi_ctl_enum_t, void *, void *);
 
+static int
+isa_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
+    ddi_intr_handle_impl_t *hdlp, void *result);
+
 struct bus_ops isa_bus_ops = {
 	BUSO_REV,
-	i_ddi_bus_map,
+	isa_bus_map,
 	NULL,
 	NULL,
 	NULL,
@@ -137,7 +173,7 @@
 	NULL,		/* (*bus_fm_access_enter)(); */
 	NULL,		/* (*bus_fm_access_exit)(); */
 	NULL,		/* (*bus_power)(); */
-	i_ddi_intr_ops	/* (*bus_intr_op)(); */
+	isa_intr_ops	/* (*bus_intr_op)(); */
 };
 
 
@@ -155,7 +191,7 @@
 	nulldev,		/* identify */
 	nulldev,		/* probe */
 	isa_attach,		/* attach */
-	nodev,			/* detach */
+	nulldev,		/* detach */
 	nodev,			/* reset */
 	(struct cb_ops *)0,	/* driver operations */
 	&isa_bus_ops,		/* bus operations */
@@ -213,8 +249,14 @@
 	}
 #endif
 
-	if (cmd != DDI_ATTACH)
+	switch (cmd) {
+	case DDI_ATTACH:
+		break;
+	case DDI_RESUME:
+		return (DDI_SUCCESS);
+	default:
 		return (DDI_FAILURE);
+	}
 
 	if ((rval = i_dmae_init(devi)) == DDI_SUCCESS) {
 		ddi_report_dev(devi);
@@ -225,9 +267,210 @@
 		 */
 		isa_alloc_nodes(devi);
 	}
+
+	if (!pseudo_isa)
+		isa_postattach(devi);
+
 	return (rval);
 }
 
+#define	SET_RNGS(rng_p, used_p, ctyp, ptyp) do {			\
+		(rng_p)->child_high = (ctyp);				\
+		(rng_p)->child_low = (rng_p)->parent_low = (used_p)->base; \
+		(rng_p)->parent_high = (ptyp);				\
+		(rng_p)->parent_mid = 0;				\
+		(rng_p)->size = (used_p)->len;				\
+		_NOTE(CONSTCOND) } while (0)
+static uint_t
+isa_used_to_ranges(int ctype, int *array, uint_t size, pib_ranges_t *ranges)
+{
+	used_ranges_t *used_p;
+	pib_ranges_t *rng_p = ranges;
+	uint_t	i, ptype;
+
+	ptype = (ctype == ISA_ADDR_IO) ? PCI_ADDR_IO : PCI_ADDR_MEM32;
+	ptype |= PCI_REG_REL_M;
+	size /= USED_CELL_SIZE;
+	used_p = (used_ranges_t *)array;
+	SET_RNGS(rng_p, used_p, ctype, ptype);
+	for (i = 1, used_p++; i < size; i++, used_p++) {
+		/* merge ranges record if applicable */
+		if (rng_p->child_low + rng_p->size == used_p->base)
+			rng_p->size += used_p->len;
+		else {
+			rng_p++;
+			SET_RNGS(rng_p, used_p, ctype, ptype);
+		}
+	}
+	return (rng_p - ranges + 1);
+}
+
+void
+isa_remove_res_from_pci(int type, int *array, uint_t size)
+{
+	int i;
+	used_ranges_t *used_p;
+
+	size /= USED_CELL_SIZE;
+	used_p = (used_ranges_t *)array;
+	for (i = 0; i < size; i++, used_p++)
+		pci_remove_isa_resources(type, used_p->base, used_p->len);
+}
+
+static void
+isa_postattach(dev_info_t *dip)
+{
+	dev_info_t *used;
+	int *ioarray, *memarray, status;
+	uint_t nio = 0, nmem = 0, nrng = 0, n;
+	pib_ranges_t *ranges;
+
+	used = ddi_find_devinfo("used-resources", -1, 0);
+	if (used == NULL) {
+		cmn_err(CE_WARN, "Failed to find used-resources <%s>\n",
+		    ddi_get_name(dip));
+		return;
+	}
+	status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used,
+	    DDI_PROP_DONTPASS, "io-space", &ioarray, &nio);
+	if (status != DDI_PROP_SUCCESS && status != DDI_PROP_NOT_FOUND) {
+		cmn_err(CE_WARN, "io-space property failure for %s (%x)\n",
+		    ddi_get_name(used), status);
+		return;
+	}
+	status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, used,
+	    DDI_PROP_DONTPASS, "device-memory", &memarray, &nmem);
+	if (status != DDI_PROP_SUCCESS && status != DDI_PROP_NOT_FOUND) {
+		cmn_err(CE_WARN, "device-memory property failure for %s (%x)\n",
+		    ddi_get_name(used), status);
+		return;
+	}
+	n = (nio + nmem) / USED_CELL_SIZE;
+	ranges =  (pib_ranges_t *)kmem_zalloc(sizeof (pib_ranges_t) * n,
+	    KM_SLEEP);
+
+	if (nio != 0) {
+		nrng = isa_used_to_ranges(ISA_ADDR_IO, ioarray, nio, ranges);
+		isa_remove_res_from_pci(ISA_ADDR_IO, ioarray, nio);
+		ddi_prop_free(ioarray);
+	}
+	if (nmem != 0) {
+		nrng += isa_used_to_ranges(ISA_ADDR_MEM, memarray, nmem,
+		    ranges + nrng);
+		isa_remove_res_from_pci(ISA_ADDR_MEM, memarray, nmem);
+		ddi_prop_free(memarray);
+	}
+
+	(void) ndi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges",
+	    (int *)ranges, nrng * sizeof (pib_ranges_t) / sizeof (int));
+	kmem_free(ranges, sizeof (pib_ranges_t) * n);
+}
+
+/*ARGSUSED*/
+static int
+isa_apply_range(dev_info_t *dip, struct regspec *isa_reg_p,
+    pci_regspec_t *pci_reg_p)
+{
+	pib_ranges_t *ranges, *rng_p;
+	int len, i, offset, nrange;
+	static char out_of_range[] =
+	    "Out of range register specification from device node <%s>";
+
+	if (ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
+	    "ranges", (caddr_t)&ranges, &len) != DDI_SUCCESS) {
+		cmn_err(CE_WARN, "Can't get %s ranges property",
+		    ddi_get_name(dip));
+		return (DDI_ME_REGSPEC_RANGE);
+	}
+	nrange = len / sizeof (pib_ranges_t);
+	rng_p = ranges;
+	for (i = 0; i < nrange; i++, rng_p++) {
+		/* Check for correct space */
+		if (isa_reg_p->regspec_bustype != rng_p->child_high)
+			continue;
+
+		/* Detect whether request entirely fits within a range */
+		if (isa_reg_p->regspec_addr < rng_p->child_low)
+			continue;
+		if ((isa_reg_p->regspec_addr + isa_reg_p->regspec_size) >
+		    (rng_p->child_low + rng_p->size))
+			continue;
+
+		offset = isa_reg_p->regspec_addr - rng_p->child_low;
+
+		pci_reg_p->pci_phys_hi = rng_p->parent_high;
+		pci_reg_p->pci_phys_mid = 0;
+		pci_reg_p->pci_phys_low = rng_p->parent_low + offset;
+		pci_reg_p->pci_size_hi = 0;
+		pci_reg_p->pci_size_low = isa_reg_p->regspec_size;
+
+		break;
+	}
+	kmem_free(ranges, len);
+	if (i == nrange) {
+		cmn_err(CE_WARN, out_of_range, ddi_get_name(dip));
+		return (DDI_ME_REGSPEC_RANGE);
+	}
+
+	return (DDI_SUCCESS);
+}
+
+static int
+isa_bus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
+    off_t offset, off_t len, caddr_t *vaddrp)
+{
+	struct regspec tmp_reg, *rp;
+	pci_regspec_t vreg;
+	ddi_map_req_t mr = *mp;		/* Get private copy of request */
+	int error;
+
+	if (pseudo_isa)
+		return (i_ddi_bus_map(dip, rdip, mp, offset, len, vaddrp));
+
+	mp = &mr;
+
+	/*
+	 * First, if given an rnumber, convert it to a regspec...
+	 */
+	if (mp->map_type == DDI_MT_RNUMBER)  {
+
+		int rnumber = mp->map_obj.rnumber;
+
+		rp = i_ddi_rnumber_to_regspec(rdip, rnumber);
+		if (rp == (struct regspec *)0)
+			return (DDI_ME_RNUMBER_RANGE);
+
+		/*
+		 * Convert the given ddi_map_req_t from rnumber to regspec...
+		 */
+		mp->map_type = DDI_MT_REGSPEC;
+		mp->map_obj.rp = rp;
+	}
+
+	/*
+	 * Adjust offset and length correspnding to called values...
+	 * XXX: A non-zero length means override the one in the regspec.
+	 * XXX: (Regardless of what's in the parent's range)
+	 */
+
+	tmp_reg = *(mp->map_obj.rp);		/* Preserve underlying data */
+	rp = mp->map_obj.rp = &tmp_reg;		/* Use tmp_reg in request */
+
+	rp->regspec_addr += (uint_t)offset;
+	if (len != 0)
+		rp->regspec_size = (uint_t)len;
+
+	if ((error = isa_apply_range(dip, rp, &vreg)) != 0)
+		return (error);
+	mp->map_obj.rp = (struct regspec *)&vreg;
+
+	/*
+	 * Call my parents bus_map function with modified values...
+	 */
+
+	return (ddi_map(dip, mp, (off_t)0, (off_t)0, vaddrp));
+}
+
 static int
 isa_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *dma_attr,
     int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep)
@@ -372,6 +615,9 @@
 isa_ctlops(dev_info_t *dip, dev_info_t *rdip,
 	ddi_ctl_enum_t ctlop, void *arg, void *result)
 {
+	int rn;
+	struct ddi_parent_private_data *pdp;
+
 	switch (ctlop) {
 	case DDI_CTLOPS_REPORTDEV:
 		if (rdip == (dev_info_t *)0)
@@ -408,11 +654,190 @@
 		else
 			return (DDI_FAILURE);
 
+	case DDI_CTLOPS_REGSIZE:
+	case DDI_CTLOPS_NREGS:
+		if (rdip == (dev_info_t *)0)
+			return (DDI_FAILURE);
+
+		if ((pdp = ddi_get_parent_data(rdip)) == NULL)
+			return (DDI_FAILURE);
+
+		if (ctlop == DDI_CTLOPS_NREGS) {
+			*(int *)result = pdp->par_nreg;
+		} else {
+			rn = *(int *)arg;
+			if (rn >= pdp->par_nreg)
+				return (DDI_FAILURE);
+			*(off_t *)result = (off_t)pdp->par_reg[rn].regspec_size;
+		}
+		return (DDI_SUCCESS);
+
+	case DDI_CTLOPS_ATTACH:
+	case DDI_CTLOPS_DETACH:
+	case DDI_CTLOPS_PEEK:
+	case DDI_CTLOPS_POKE:
+		return (DDI_FAILURE);
+
 	default:
 		return (ddi_ctlops(dip, rdip, ctlop, arg, result));
 	}
 }
 
+static struct intrspec *
+isa_get_ispec(dev_info_t *rdip, int inum)
+{
+	struct ddi_parent_private_data *pdp = ddi_get_parent_data(rdip);
+
+	/* Validate the interrupt number */
+	if (inum >= pdp->par_nintr)
+		return (NULL);
+
+	/* Get the interrupt structure pointer and return that */
+	return ((struct intrspec *)&pdp->par_intr[inum]);
+}
+
+static int
+isa_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op,
+    ddi_intr_handle_impl_t *hdlp, void *result)
+{
+	struct intrspec *ispec;
+
+	if (pseudo_isa)
+		return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result));
+
+
+	/* Process the interrupt operation */
+	switch (intr_op) {
+	case DDI_INTROP_GETCAP:
+		/* First check with pcplusmp */
+		if (psm_intr_ops == NULL)
+			return (DDI_FAILURE);
+
+		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_GET_CAP, result)) {
+			*(int *)result = 0;
+			return (DDI_FAILURE);
+		}
+		break;
+	case DDI_INTROP_SETCAP:
+		if (psm_intr_ops == NULL)
+			return (DDI_FAILURE);
+
+		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_CAP, result))
+			return (DDI_FAILURE);
+		break;
+	case DDI_INTROP_ALLOC:
+		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
+			return (DDI_FAILURE);
+		hdlp->ih_pri = ispec->intrspec_pri;
+		*(int *)result = hdlp->ih_scratch1;
+		break;
+	case DDI_INTROP_FREE:
+		break;
+	case DDI_INTROP_GETPRI:
+		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
+			return (DDI_FAILURE);
+		*(int *)result = ispec->intrspec_pri;
+		break;
+	case DDI_INTROP_SETPRI:
+		/* Validate the interrupt priority passed to us */
+		if (*(int *)result > LOCK_LEVEL)
+			return (DDI_FAILURE);
+
+		/* Ensure that PSM is all initialized and ispec is ok */
+		if ((psm_intr_ops == NULL) ||
+		    ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL))
+			return (DDI_FAILURE);
+
+		/* update the ispec with the new priority */
+		ispec->intrspec_pri =  *(int *)result;
+		break;
+	case DDI_INTROP_ADDISR:
+		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
+			return (DDI_FAILURE);
+		ispec->intrspec_func = hdlp->ih_cb_func;
+		break;
+	case DDI_INTROP_REMISR:
+		if (hdlp->ih_type != DDI_INTR_TYPE_FIXED)
+			return (DDI_FAILURE);
+		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
+			return (DDI_FAILURE);
+		ispec->intrspec_func = (uint_t (*)()) 0;
+		break;
+	case DDI_INTROP_ENABLE:
+		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
+			return (DDI_FAILURE);
+
+		/* Call psmi to translate irq with the dip */
+		if (psm_intr_ops == NULL)
+			return (DDI_FAILURE);
+
+		((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
+		(void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR,
+		    (int *)&hdlp->ih_vector);
+
+		/* Add the interrupt handler */
+		if (!add_avintr((void *)hdlp, ispec->intrspec_pri,
+		    hdlp->ih_cb_func, DEVI(rdip)->devi_name, hdlp->ih_vector,
+		    hdlp->ih_cb_arg1, hdlp->ih_cb_arg2, NULL, rdip))
+			return (DDI_FAILURE);
+		break;
+	case DDI_INTROP_DISABLE:
+		if ((ispec = isa_get_ispec(rdip, hdlp->ih_inum)) == NULL)
+			return (DDI_FAILURE);
+
+		/* Call psm_ops() to translate irq with the dip */
+		if (psm_intr_ops == NULL)
+			return (DDI_FAILURE);
+
+		((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec;
+		(void) (*psm_intr_ops)(rdip, hdlp,
+		    PSM_INTR_OP_XLATE_VECTOR, (int *)&hdlp->ih_vector);
+
+		/* Remove the interrupt handler */
+		rem_avintr((void *)hdlp, ispec->intrspec_pri,
+		    hdlp->ih_cb_func, hdlp->ih_vector);
+		break;
+	case DDI_INTROP_SETMASK:
+		if (psm_intr_ops == NULL)
+			return (DDI_FAILURE);
+
+		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_SET_MASK, NULL))
+			return (DDI_FAILURE);
+		break;
+	case DDI_INTROP_CLRMASK:
+		if (psm_intr_ops == NULL)
+			return (DDI_FAILURE);
+
+		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_CLEAR_MASK, NULL))
+			return (DDI_FAILURE);
+		break;
+	case DDI_INTROP_GETPENDING:
+		if (psm_intr_ops == NULL)
+			return (DDI_FAILURE);
+
+		if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_GET_PENDING,
+		    result)) {
+			*(int *)result = 0;
+			return (DDI_FAILURE);
+		}
+		break;
+	case DDI_INTROP_NAVAIL:
+	case DDI_INTROP_NINTRS:
+		*(int *)result = i_ddi_get_intx_nintrs(rdip);
+		if (*(int *)result == 0) {
+			return (DDI_FAILURE);
+		}
+		break;
+	case DDI_INTROP_SUPPORTED_TYPES:
+		*(int *)result = DDI_INTR_TYPE_FIXED;	/* Always ... */
+		break;
+	default:
+		return (DDI_FAILURE);
+	}
+
+	return (DDI_SUCCESS);
+}
+
 static void
 isa_vendor(uint32_t id, char *vendor)
 {
--- a/usr/src/uts/i86pc/isa/Makefile	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/uts/i86pc/isa/Makefile	Tue Mar 24 10:24:01 2009 +0800
@@ -20,11 +20,9 @@
 #
 #
 # uts/i86pc/isa/Makefile
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
-#
 #	This makefile drives the production of the ISA nexus driver
 #
 #	i86pc implementation architecture dependent
@@ -63,7 +61,7 @@
 
 #
 #       Dependency
-LDFLAGS         += -dy -Nmisc/acpica -Nmisc/busra
+LDFLAGS         += -dy -Nmisc/acpica -Nmisc/busra -Nmisc/pci_autoconfig
 
 #
 # Define our version of dma_engine and i8237A interfaces
--- a/usr/src/uts/i86pc/os/ddi_impl.c	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/uts/i86pc/os/ddi_impl.c	Tue Mar 24 10:24:01 2009 +0800
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -86,6 +86,8 @@
 
 uint64_t ramdisk_start, ramdisk_end;
 
+int pseudo_isa = 0;
+
 /*
  * Forward declarations
  */
@@ -203,10 +205,17 @@
 	 * isa is "kind of" a pseudo node
 	 */
 #if defined(__xpv)
-	if (DOMAIN_IS_INITDOMAIN(xen_info))
+	if (DOMAIN_IS_INITDOMAIN(xen_info)) {
+		if (pseudo_isa)
+			(void) i_ddi_attach_pseudo_node("isa");
+		else
+			(void) i_ddi_attach_hw_nodes("isa");
+	}
+#else
+	if (pseudo_isa)
 		(void) i_ddi_attach_pseudo_node("isa");
-#else
-	(void) i_ddi_attach_pseudo_node("isa");
+	else
+		(void) i_ddi_attach_hw_nodes("isa");
 #endif
 
 	/* reprogram devices not set up by firmware (BIOS) */
@@ -2530,13 +2539,15 @@
 	ASSERT(err == 0);
 
 	/* isa node */
-	ndi_devi_alloc_sleep(ddi_root_node(), "isa",
-	    (pnode_t)DEVI_SID_NODEID, &isa_dip);
-	(void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip,
-	    "device_type", "isa");
-	(void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip,
-	    "bus-type", "isa");
-	(void) ndi_devi_bind_driver(isa_dip, 0);
+	if (pseudo_isa) {
+		ndi_devi_alloc_sleep(ddi_root_node(), "isa",
+		    (pnode_t)DEVI_SID_NODEID, &isa_dip);
+		(void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip,
+		    "device_type", "isa");
+		(void) ndi_prop_update_string(DDI_DEV_T_NONE, isa_dip,
+		    "bus-type", "isa");
+		(void) ndi_devi_bind_driver(isa_dip, 0);
+	}
 
 	/*
 	 * Read in the properties from the boot.
--- a/usr/src/uts/i86xpv/isa/Makefile	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/uts/i86xpv/isa/Makefile	Tue Mar 24 10:24:01 2009 +0800
@@ -20,11 +20,9 @@
 #
 
 #
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
-#
 #	This makefile drives the production of the ISA nexus driver
 #
 #	i86xpv implementation architecture dependent
@@ -63,7 +61,7 @@
 
 #
 #       Dependency
-LDFLAGS         += -dy -Nmisc/acpica -Nmisc/busra
+LDFLAGS         += -dy -Nmisc/acpica -Nmisc/busra -Nmisc/pci_autoconfig
 
 #
 # Define our version of dma_engine and i8237A interfaces
--- a/usr/src/uts/intel/io/pci/pci_boot.c	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/uts/intel/io/pci/pci_boot.c	Tue Mar 24 10:24:01 2009 +0800
@@ -82,6 +82,7 @@
 	boolean_t reprogram;	/* this device needs to be reprogrammed */
 };
 
+extern int pseudo_isa;
 extern int pci_bios_nbus;
 static uchar_t max_dev_pci = 32;	/* PCI standard */
 int pci_boot_debug = 0;
@@ -297,54 +298,21 @@
 	}
 }
 
-static void
-remove_resource_range(struct memlist **list, int *ranges, int range_count)
-{
-	struct range {
-		uint32_t base;
-		uint32_t len;
-	};
-	int index;
-
-	for (index = 0; index < range_count; index++) {
-		/* all done if list is or has become empty */
-		if (*list == NULL)
-			break;
-		(void) memlist_remove(list,
-		    (uint64_t)((struct range *)ranges)[index].base,
-		    (uint64_t)((struct range *)ranges)[index].len);
-	}
-}
-
-static void
-remove_used_resources()
+void
+pci_remove_isa_resources(int type, uint32_t base, uint32_t size)
 {
-	dev_info_t *used;
-	int	*narray;
-	uint_t	ncount;
-	int	status;
-	int	bus;
-
-	used = ddi_find_devinfo("used-resources", -1, 0);
-	if (used == NULL)
-		return;
+	int bus;
+	struct memlist  **list;
 
-	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++)
-			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++)
-			remove_resource_range(&pci_bus_res[bus].mem_space,
-			    narray, ncount / 2);
-		ddi_prop_free(narray);
+	for (bus = 0; bus <= pci_bios_nbus; bus++) {
+		if (type == 1)
+			list = &pci_bus_res[bus].io_ports;
+		else
+			list = &pci_bus_res[bus].mem_space;
+		/* skip if list is or has become empty */
+		if (*list == NULL)
+			continue;
+		(void) memlist_remove(list, base, size);
 	}
 }
 
@@ -952,8 +920,6 @@
 		ddi_prop_free(onoff);
 	}
 
-	/* remove used-resources from PCI resource maps */
-	remove_used_resources();
 	remove_subtractive_res();
 
 	/* reprogram the non-subtractive PPB */
@@ -1411,6 +1377,9 @@
 
 }
 
+#define	is_isa(bc, sc)	\
+	(((bc) == PCI_CLASS_BRIDGE) && ((sc) == PCI_BRIDGE_ISA))
+
 static void
 process_devfunc(uchar_t bus, uchar_t dev, uchar_t func, uchar_t header,
     ushort_t vendorid, int config_op)
@@ -1469,6 +1438,8 @@
 
 	if (is_display(classcode))
 		(void) snprintf(nodename, sizeof (nodename), "display");
+	else if (!pseudo_isa && is_isa(basecl, subcl))
+		(void) snprintf(nodename, sizeof (nodename), "isa");
 	else if (subvenid != 0)
 		(void) snprintf(nodename, sizeof (nodename),
 		    "pci%x,%x", subvenid, subdevid);
@@ -1690,6 +1661,13 @@
 			gfxp->g_next->g_prev = gfxp;
 	}
 
+	/* special handling for isa */
+	if (!pseudo_isa && is_isa(basecl, subcl)) {
+		/* add device_type */
+		(void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
+		    "device_type", "isa");
+	}
+
 	if (reprogram && (entry != NULL))
 		entry->reprogram = B_TRUE;
 }
--- a/usr/src/uts/intel/os/driver_aliases	Mon Mar 23 17:56:34 2009 -0700
+++ b/usr/src/uts/intel/os/driver_aliases	Tue Mar 24 10:24:01 2009 +0800
@@ -49,3 +49,4 @@
 xpv "pci5853,1.1"
 amd_iommu "pci1022,11ff"
 amd_iommu "pci1002,5a23"
+isa "pciclass,060100"