PSARC 2009/056 Removal of ISA Pseudo Node
6813425 Remove /isa pseudo node for x86
--- 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"