/* * name_child * * This function is called from pcmu_init_child to name a node. It is * also passed as a callback for node merging functions. * * return value: DDI_SUCCESS, DDI_FAILURE */ static int name_child(dev_info_t *child, char *name, int namelen) { pci_regspec_t *pcmu_rp; int reglen; uint_t func; char **unit_addr; uint_t n; /* * Set the address portion of the node name based on * unit-address property, if it exists. * The interpretation of the unit-address is DD[,F] * where DD is the device id and F is the function. */ if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) == DDI_PROP_SUCCESS) { if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { cmn_err(CE_WARN, "unit-address property in %s.conf" " not well-formed", ddi_driver_name(child)); ddi_prop_free(unit_addr); return (DDI_FAILURE); } (void) snprintf(name, namelen, "%s", *unit_addr); ddi_prop_free(unit_addr); return (DDI_SUCCESS); } /* * The unit-address property is does not exist. Set the address * portion of the node name based on the function and device number. */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg", (int **)&pcmu_rp, (uint_t *)®len) == DDI_SUCCESS) { if (((reglen * sizeof (int)) % sizeof (pci_regspec_t)) != 0) { cmn_err(CE_WARN, "reg property not well-formed"); return (DDI_FAILURE); } func = PCI_REG_FUNC_G(pcmu_rp[0].pci_phys_hi); if (func != 0) { (void) snprintf(name, namelen, "%x,%x", PCI_REG_DEV_G(pcmu_rp[0].pci_phys_hi), func); } else { (void) snprintf(name, namelen, "%x", PCI_REG_DEV_G(pcmu_rp[0].pci_phys_hi)); } ddi_prop_free(pcmu_rp); return (DDI_SUCCESS); } cmn_err(CE_WARN, "cannot name pci child '%s'", ddi_node_name(child)); return (DDI_FAILURE); }
/* * name_child * * This function is called from init_child to name a node. It is * also passed as a callback for node merging functions. * * return value: DDI_SUCCESS, DDI_FAILURE */ static int ppb_name_child(dev_info_t *child, char *name, int namelen) { pci_regspec_t *pci_rp; uint_t slot, func; char **unit_addr; uint_t n; /* * Pseudo nodes indicate a prototype node with per-instance * properties to be merged into the real h/w device node. * The interpretation of the unit-address is DD[,F] * where DD is the device id and F is the function. */ if (ndi_dev_is_persistent_node(child) == 0) { if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "cannot name node from %s.conf", ddi_driver_name(child)); return (DDI_FAILURE); } if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { cmn_err(CE_WARN, "unit-address property in %s.conf" " not well-formed", ddi_driver_name(child)); ddi_prop_free(unit_addr); return (DDI_FAILURE); } (void) snprintf(name, namelen, "%s", *unit_addr); ddi_prop_free(unit_addr); return (DDI_SUCCESS); } /* * Get the address portion of the node name based on * the function and device number. */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) { return (DDI_FAILURE); } slot = PCI_REG_DEV_G(pci_rp[0].pci_phys_hi); func = PCI_REG_FUNC_G(pci_rp[0].pci_phys_hi); if (func != 0) (void) snprintf(name, namelen, "%x,%x", slot, func); else (void) snprintf(name, namelen, "%x", slot); ddi_prop_free(pci_rp); return (DDI_SUCCESS); }
static void isa_create_ranges_prop(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); } if (!pseudo_isa) (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); }
static int ppb_name_child(dev_info_t *child, char *name, int namelen) { pci_regspec_t *pci_rp; uint_t slot, func; char **unit_addr; uint_t n; /* * For .conf nodes, use unit-address property as name */ if (ndi_dev_is_persistent_node(child) == 0) { if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "unit-address", &unit_addr, &n) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "cannot find unit-address in %s.conf", ddi_driver_name(child)); return (DDI_FAILURE); } if (n != 1 || *unit_addr == NULL || **unit_addr == 0) { cmn_err(CE_WARN, "unit-address property in %s.conf" " not well-formed", ddi_driver_name(child)); ddi_prop_free(unit_addr); return (DDI_SUCCESS); } (void) snprintf(name, namelen, "%s", *unit_addr); ddi_prop_free(unit_addr); return (DDI_SUCCESS); } /* get child "reg" property */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, &n) != DDI_SUCCESS) { return (DDI_FAILURE); } /* copy the device identifications */ slot = PCI_REG_DEV_G(pci_rp->pci_phys_hi); func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); if (func != 0) (void) snprintf(name, namelen, "%x,%x", slot, func); else (void) snprintf(name, namelen, "%x", slot); ddi_prop_free(pci_rp); return (DDI_SUCCESS); }
int mp_find_cpu(dev_info_t *dip, void *arg) { extern int get_portid_ddi(dev_info_t *, dev_info_t **); struct mp_find_cpu_arg *target = (struct mp_find_cpu_arg *)arg; char *type; int rv = DDI_WALK_CONTINUE; int cpuid; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "device_type", &type)) return (DDI_WALK_CONTINUE); if (strcmp(type, "cpu") != 0) goto out; cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "cpuid", -1); if (cpuid == -1) cpuid = get_portid_ddi(dip, NULL); if (cpuid != target->cpuid) goto out; /* Found it */ rv = DDI_WALK_TERMINATE; target->dip = dip; out: ddi_prop_free(type); return (rv); }
/* * vdds_match_niu_node -- callback function to verify a node is the * NIU Hybrid node. */ static int vdds_match_niu_node(dev_info_t *dip, void *arg) { vdds_cb_arg_t *warg = (vdds_cb_arg_t *)arg; char *name; vdds_reg_t *reg_p; uint_t reglen; int rv; uint32_t addr_hi; name = ddi_node_name(dip); if (strcmp(name, "network") != 0) { return (DDI_WALK_CONTINUE); } rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", (int **)®_p, ®len); if (rv != DDI_PROP_SUCCESS) { DWARN(NULL, "Failed to get reg property dip=0x%p", dip); return (DDI_WALK_CONTINUE); } addr_hi = reg_p->addr_hi; DBG1(NULL, "addr_hi = 0x%x dip=0x%p", addr_hi, dip); ddi_prop_free(reg_p); if (addr_hi == HVCOOKIE(warg->cookie)) { warg->dip = dip; if (!e_ddi_branch_held(dip)) e_ddi_branch_hold(dip); DBG1(NULL, "Found dip = 0x%p", dip); return (DDI_WALK_TERMINATE); } return (DDI_WALK_CONTINUE); }
static int gfxp_pci_get_bsf(dev_info_t *dip, uint8_t *bus, uint8_t *dev, uint8_t *func) { pci_regspec_t *pci_rp; uint32_t length; int rc; /* get "reg" property */ rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, (uint_t *)&length); if ((rc != DDI_SUCCESS) || (length < (sizeof (pci_regspec_t) / sizeof (int)))) { return (DDI_FAILURE); } *bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi); *dev = PCI_REG_DEV_G(pci_rp->pci_phys_hi); *func = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); /* * free the memory allocated by ddi_prop_lookup_int_array(). */ ddi_prop_free(pci_rp); return (DDI_SUCCESS); }
int mp_find_cpu(dev_info_t *dip, void *arg) { struct mp_find_cpu_arg *target = (struct mp_find_cpu_arg *)arg; char *type; int rv = DDI_WALK_CONTINUE; int cpuid; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "device_type", &type)) return (DDI_WALK_CONTINUE); if (strcmp(type, "cpu") != 0) goto out; cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", -1); if (cpuid == -1) { cmn_err(CE_PANIC, "reg prop not found in cpu node"); } cpuid = PROM_CFGHDL_TO_CPUID(cpuid); if (cpuid != target->cpuid) goto out; /* Found it */ rv = DDI_WALK_TERMINATE; target->dip = dip; out: ddi_prop_free(type); return (rv); }
int _init(void) { int err; char tty_irq_param[9] = "ttyX-irq"; char *tty_irq; int i; if ((err = mod_install(&modlinkage)) != 0) return (err); /* Check if any tty irqs are overridden by eeprom config */ for (i = 0; i < num_BIOS_serial; i++) { tty_irq_param[3] = 'a' + i; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, tty_irq_param, &tty_irq) == DDI_PROP_SUCCESS) { long data; if (ddi_strtol(tty_irq, NULL, 0, &data) == 0) { asy_intrs[i] = (int)data; asy_intr_override |= 1<<i; } ddi_prop_free(tty_irq); } } impl_bus_add_probe(isa_enumerate); return (0); }
/* * function to read the PCI Bus, Device, and function numbers for the * device instance. * * dev - handle to device private data */ int oce_get_bdf(struct oce_dev *dev) { pci_regspec_t *pci_rp; uint32_t length; int rc; /* Get "reg" property */ rc = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dev->dip, 0, "reg", (int **)&pci_rp, (uint_t *)&length); if ((rc != DDI_SUCCESS) || (length < (sizeof (pci_regspec_t) / sizeof (int)))) { oce_log(dev, CE_WARN, MOD_CONFIG, "Failed to read \"reg\" property, Status = 0x%x", rc); return (rc); } dev->pci_bus = PCI_REG_BUS_G(pci_rp->pci_phys_hi); dev->pci_device = PCI_REG_DEV_G(pci_rp->pci_phys_hi); dev->pci_function = PCI_REG_FUNC_G(pci_rp->pci_phys_hi); oce_log(dev, CE_NOTE, MOD_CONFIG, "\"reg\" property num=%d, Bus=%d, Device=%d, Function=%d", length, dev->pci_bus, dev->pci_device, dev->pci_function); /* Free the memory allocated by ddi_prop_lookup_int_array() */ ddi_prop_free(pci_rp); return (rc); }
/* * Get the numeric value of the property "name" in vmxnet3s.conf for * the corresponding device instance. * If the property isn't found or if it doesn't satisfy the conditions, * "def" is returned. * * Returns: * The value of the property or "def". */ int vmxnet3_getprop(vmxnet3_softc_t *dp, char *name, int min, int max, int def) { int ret = def; int *props; uint_t nprops; if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dp->dip, DDI_PROP_DONTPASS, name, &props, &nprops) == DDI_PROP_SUCCESS) { if (dp->instance < nprops) { ret = props[dp->instance]; } else { VMXNET3_WARN(dp, "property %s not available for this " "device\n", name); } ddi_prop_free(props); } if (ret < min || ret > max) { ASSERT(def >= min && def <= max); VMXNET3_WARN(dp, "property %s invalid (%d <= %d <= %d)\n", name, min, ret, max); ret = def; } VMXNET3_DEBUG(dp, 2, "getprop(%s) -> %d\n", name, ret); return (ret); }
/*ARGSUSED*/ static int fipe_search_ioat_dev(dev_info_t *dip, void *arg) { char *unit; struct fipe_pci_ioat_id *id; int i, max, venid, devid, subvenid, subsysid; /* Query PCI id properties. */ venid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "vendor-id", 0xffffffff); if (venid == 0xffffffff) { return (DDI_WALK_CONTINUE); } devid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "device-id", 0xffffffff); if (devid == 0xffffffff) { return (DDI_WALK_CONTINUE); } subvenid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "subsystem-vendor-id", 0xffffffff); if (subvenid == 0xffffffff) { return (DDI_WALK_CONTINUE); } subsysid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "subsystem-id", 0xffffffff); if (subvenid == 0xffffffff) { return (DDI_WALK_CONTINUE); } if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "unit-address", &unit) != DDI_PROP_SUCCESS) { return (DDI_WALK_CONTINUE); } max = sizeof (fipe_pci_ioat_ids) / sizeof (fipe_pci_ioat_ids[0]); for (i = 0; i < max; i++) { id = &fipe_pci_ioat_ids[i]; if ((id->venid == 0xffffu || id->venid == venid) && (id->devid == 0xffffu || id->devid == devid) && (id->subvenid == 0xffffu || id->subvenid == subvenid) && (id->subsysid == 0xffffu || id->subsysid == subsysid) && (id->unitaddr == NULL || strcmp(id->unitaddr, unit) == 0)) { break; } } ddi_prop_free(unit); if (i >= max) { return (DDI_WALK_CONTINUE); } /* Found IOAT device, hold one reference count. */ ndi_hold_devi(dip); fipe_ioat_ctrl.ioat_dev_info = dip; return (DDI_WALK_TERMINATE); }
int get_bdf(dev_info_t *dip, int *bus, int *device, int *func) { pci_regspec_t *pci_rp; int len; if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", (int **)&pci_rp, (uint_t *)&len) != DDI_SUCCESS) return (-1); if (len < (sizeof (pci_regspec_t) / sizeof (int))) { ddi_prop_free(pci_rp); return (-1); } if (bus != NULL) *bus = (int)PCI_REG_BUS_G(pci_rp->pci_phys_hi); if (device != NULL) *device = (int)PCI_REG_DEV_G(pci_rp->pci_phys_hi); if (func != NULL) *func = (int)PCI_REG_FUNC_G(pci_rp->pci_phys_hi); ddi_prop_free(pci_rp); return (0); }
/* * Check's if this child is a PCI device. * Child is a PCI device if: * parent has a dev_type of "pci" * -and- * child does not have a dev_type of "pciex" * * If the parent is not of dev_type "pci", then assume it is "pciex" and all * children should support using PCIe style MMCFG access. * * If parent's dev_type is "pci" and child is "pciex", then also enable using * PCIe style MMCFG access. This covers the case where NPE is "pci" and a PCIe * RP is beneath. */ boolean_t npe_child_is_pci(dev_info_t *dip) { char *dev_type; boolean_t parent_is_pci, child_is_pciex; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip), DDI_PROP_DONTPASS, "device_type", &dev_type) == DDI_PROP_SUCCESS) { parent_is_pci = (strcmp(dev_type, "pci") == 0); ddi_prop_free(dev_type); } else { parent_is_pci = B_FALSE; } if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "device_type", &dev_type) == DDI_PROP_SUCCESS) { child_is_pciex = (strcmp(dev_type, "pciex") == 0); ddi_prop_free(dev_type); } else { child_is_pciex = B_FALSE; } return (parent_is_pci && !child_is_pciex); }
/* * sets master_ops_debug flag from propertyu passed by the boot */ static void set_master_ops_debug_flags() { char *prop; long flags; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "master_ops_debug", &prop) == DDI_PROP_SUCCESS) { long data; if (ddi_strtol(prop, NULL, 0, &data) == 0) { master_ops_debug = (unsigned long)data; e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(), "master_ops_debug"); e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), "master_ops_debug", data); } ddi_prop_free(prop); } }
static int name_child(dev_info_t *child, char *name, int namelen) { char *unitaddr; ddi_set_parent_data(child, NULL); name[0] = '\0'; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, ACPIDEV_PROP_NAME_UNIT_ADDR, &unitaddr) == DDI_SUCCESS) { (void) strlcpy(name, unitaddr, namelen); ddi_prop_free(unitaddr); } else { ACPINEX_DEBUG(CE_NOTE, "!acpinex: failed to lookup child " "unit-address prop for %p.", (void *)child); } return (DDI_SUCCESS); }
/* * Get boot property value for fastreboot_onpanic. * * NOTE: If fastreboot_onpanic is set to non-zero in /etc/system, * new setting passed in via "-B fastreboot_onpanic" is ignored. * This order of precedence is to enable developers debugging panics * that occur early in boot to utilize Fast Reboot on panic. */ static void fastboot_get_bootprop(void) { int val = 0xaa, len, ret; dev_info_t *devi; char *propstr = NULL; devi = ddi_root_node(); ret = ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, FASTREBOOT_ONPANIC, &propstr); if (ret == DDI_PROP_SUCCESS) { if (FASTREBOOT_ONPANIC_NOTSET(propstr)) val = 0; else if (FASTREBOOT_ONPANIC_ISSET(propstr)) val = UA_FASTREBOOT_ONPANIC; /* * Only set fastreboot_onpanic to the value passed in * if it's not already set to non-zero, and the value * has indeed been passed in via command line. */ if (!fastreboot_onpanic && val != 0xaa) fastreboot_onpanic = val; ddi_prop_free(propstr); } else if (ret != DDI_PROP_NOT_FOUND && ret != DDI_PROP_UNDEFINED) { cmn_err(CE_NOTE, "!%s value is invalid, will be ignored", FASTREBOOT_ONPANIC); } len = sizeof (fastreboot_onpanic_cmdline); ret = ddi_getlongprop_buf(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS, FASTREBOOT_ONPANIC_CMDLINE, fastreboot_onpanic_cmdline, &len); if (ret == DDI_PROP_BUF_TOO_SMALL) cmn_err(CE_NOTE, "!%s value is too long, will be ignored", FASTREBOOT_ONPANIC_CMDLINE); }
/* * vdds_match_niu_nexus -- callback function to verify a node is the * NIU nexus node. */ static int vdds_match_niu_nexus(dev_info_t *dip, void *arg) { vdds_cb_arg_t *warg = (vdds_cb_arg_t *)arg; vdds_reg_t *reg_p; char *name; uint64_t hdl; uint_t reglen; int rv; if (dip == ddi_root_node()) { return (DDI_WALK_CONTINUE); } name = ddi_node_name(dip); if (strcmp(name, "niu") != 0) { return (DDI_WALK_CONTINUE); } rv = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg", (int **)®_p, ®len); if (rv != DDI_PROP_SUCCESS) { DWARN(NULL, "Failed to get reg property dip=0x%p", dip); return (DDI_WALK_CONTINUE); } hdl = reg_p->addr_hi & 0x0FFFFFFF; ddi_prop_free(reg_p); DBG2(NULL, "Handle = 0x%lx dip=0x%p", hdl, dip); if (hdl == NIUCFGHDL(warg->cookie)) { /* Hold before returning */ if (!e_ddi_branch_held(dip)) e_ddi_branch_hold(dip); warg->dip = dip; DBG2(NULL, "Found dip = 0x%p", dip); return (DDI_WALK_TERMINATE); } return (DDI_WALK_CONTINUE); }
static int acebus_update_props(ebus_devstate_t *ebus_p) { dev_info_t *dip = ebus_p->dip; struct ebus_pci_rangespec er[2], *erp; pci_regspec_t *pci_rp, *prp; int length, rnums, imask[3], i, found = 0; /* * If "ranges" property is found, then the device is initialized * by OBP, hence simply return. * Otherwise we create all the properties here. */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ranges", (int **)&erp, (uint_t *)&length) == DDI_PROP_SUCCESS) { ddi_prop_free(erp); return (DDI_SUCCESS); } /* * interrupt-map is the only property that comes from a .conf file. * Since it doesn't have the nodeid field set, it must be done here. * Other properties can come from OBP or created here. */ if (acebus_set_imap(dip) != DDI_SUCCESS) { return (DDI_FAILURE); } /* * Create the "ranges" property. * Ebus has BAR0 and BAR1 allocated (both in memory space). * Other BARs are 0. * Hence there are 2 memory ranges it operates in. (one for each BAR). * ie. there are 2 entries in its ranges property. */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "assigned-addresses", (int **)&pci_rp, (uint_t *)&length) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d: Could not get assigned-addresses", ddi_driver_name(dip), ddi_get_instance(dip)); return (DDI_FAILURE); } /* * Create the 1st mem range in which it operates corresponding * to BAR0 */ er[0].ebus_phys_hi = EBUS_CHILD_PHYS_LOW_RANGE; rnums = (length * sizeof (int))/sizeof (pci_regspec_t); for (i = 0; i < rnums; i++) { prp = pci_rp + i; if (PCI_REG_REG_G(prp->pci_phys_hi) == er[0].ebus_phys_hi) { found = 1; break; } } if (!found) { cmn_err(CE_WARN, "No assigned space for memory range 0."); ddi_prop_free(pci_rp); return (DDI_FAILURE); } found = 0; er[0].ebus_phys_low = 0; er[0].pci_phys_hi = prp->pci_phys_hi; er[0].pci_phys_mid = prp->pci_phys_mid; er[0].pci_phys_low = prp->pci_phys_low; er[0].rng_size = prp->pci_size_low; /* * Create the 2nd mem range in which it operates corresponding * to BAR1 */ er[1].ebus_phys_hi = EBUS_CHILD_PHYS_HI_RANGE; for (i = 0; i < rnums; i++) { prp = pci_rp + i; if (PCI_REG_REG_G(prp->pci_phys_hi) == er[1].ebus_phys_hi) { found = 1; break; } } if (!found) { cmn_err(CE_WARN, "No assigned space for memory range 1."); ddi_prop_free(pci_rp); return (DDI_FAILURE); } er[1].ebus_phys_low = 0; er[1].pci_phys_hi = prp->pci_phys_hi; er[1].pci_phys_mid = prp->pci_phys_mid; er[1].pci_phys_low = prp->pci_phys_low; er[1].rng_size = prp->pci_size_low; ddi_prop_free(pci_rp); length = sizeof (er) / sizeof (int); if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, "ranges", (int *)er, length) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d: Could not create ranges property", ddi_driver_name(dip), ddi_get_instance(dip)); return (DDI_FAILURE); } /* The following properties are as defined by PCI 1275 bindings. */ if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, "#address-cells", 2) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, "#size-cells", 1) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, "#interrupt-cells", 1) != DDI_PROP_SUCCESS) return (DDI_FAILURE); imask[0] = 0x1f; imask[1] = 0x00ffffff; imask[2] = 0x00000003; length = sizeof (imask) / sizeof (int); if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, "interrupt-map-mask", (int *)imask, length) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d: Could not update imap mask property", ddi_driver_name(dip), ddi_get_instance(dip)); return (DDI_FAILURE); } return (DDI_SUCCESS); }
/* * Return 1 if instance block was assigned for the path. * * For multi-port NIC cards, sequential instance assignment across all * ports on a card is highly desirable since the ppa is typically the * same as the instance number, and the ppa is used in the NIC's public * /dev name. This sequential assignment typically occurs as a result * of in_preassign_instance() after initial install, or by * i_ndi_init_hw_children() for NIC ports that share a common parent. * * Some NIC cards however use multi-function bridge chips, and to * support sequential instance assignment accross all ports, without * disabling multi-threaded attach, we have a (currently) undocumented * hack to allocate instance numbers in contiguous blocks based on * driver.conf properties. * * ^ * /---------- ------------\ * pci@0 pci@0,1 MULTI-FUNCTION BRIDGE CHIP * / \ / \ * FJSV,e4ta@4 FJSV,e4ta@4,1 FJSV,e4ta@6 FJSV,e4ta@6,1 NIC PORTS * n n+2 n+2 n+3 INSTANCE * * For the above example, the following driver.conf properties would be * used to guarantee sequential instance number assignment. * * ddi-instance-blocks ="ib-FJSVe4ca", "ib-FJSVe4ta", "ib-generic"; * ib-FJSVe4ca = "/pci@0/FJSV,e4ca@4", "/pci@0/FJSV,e4ca@4,1", * "/pci@0,1/FJSV,e4ca@6", "/pci@0,1/FJSV,e4ca@6,1"; * ib-FJSVe4ta = "/pci@0/FJSV,e4ta@4", "/pci@0/FJSV,e4ta@4,1", * "/pci@0,1/FJSV,e4ta@6", "/pci@0,1/FJSV,e4ta@6,1"; * ib-generic = "/pci@0/network@4", "/pci@0/network@4,1", * "/pci@0,1/network@6", "/pci@0,1/network@6,1"; * * The value of the 'ddi-instance-blocks' property references a series * of card specific properties, like 'ib-FJSV-e4ta', who's value * defines a single 'instance block'. The 'instance block' describes * all the paths below a multi-function bridge, where each path is * called an 'instance path'. The 'instance block' property value is a * series of 'instance paths'. The number of 'instance paths' in an * 'instance block' defines the size of the instance block, and the * ordering of the 'instance paths' defines the instance number * assignment order for paths going through the 'instance block'. * * In the instance assignment code below, if a (path, driver) that * currently has no instance number has a path that goes through an * 'instance block', then block instance number allocation occurs. The * block allocation code will find a sequential set of unused instance * numbers, and assign instance numbers for all the paths in the * 'instance block'. Each path is assigned a persistent instance * number, even paths that don't exist in the device tree or fail * probe(9E). */ static int in_assign_instance_block(dev_info_t *dip) { char **ibn; /* instance block names */ uint_t nibn; /* number of instance block names */ uint_t ibni; /* ibn index */ char *driver; major_t major; char *path; char *addr; int plen; char **ibp; /* instance block paths */ uint_t nibp; /* number of paths in instance block */ uint_t ibpi; /* ibp index */ int ibplen; /* length of instance block path */ char *ipath; int instance_base; int splice; int i; /* check for fresh install case (in miniroot) */ if (DEVI(dip)->devi_instance != -1) return (0); /* already assigned */ /* * Check to see if we need to allocate a block of contiguous instance * numbers by looking for the 'ddi-instance-blocks' property. */ if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ddi-instance-blocks", &ibn, &nibn) != DDI_SUCCESS) return (0); /* no instance block needed */ /* * Get information out about node we are processing. * * NOTE: Since the node is not yet at DS_INITIALIZED, ddi_pathname() * will not return the unit-address of the final path component even * though the node has an established devi_addr unit-address - so we * need to add the unit-address by hand. */ driver = (char *)ddi_driver_name(dip); major = ddi_driver_major(dip); path = kmem_alloc(MAXPATHLEN, KM_SLEEP); (void) ddi_pathname(dip, path); if ((addr = ddi_get_name_addr(dip)) != NULL) { (void) strcat(path, "@"); (void) strcat(path, addr); } plen = strlen(path); /* loop through instance block names */ for (ibni = 0; ibni < nibn; ibni++) { if (ibn[ibni] == NULL) continue; /* lookup instance block */ if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, ibn[ibni], &ibp, &nibp) != DDI_SUCCESS) { cmn_err(CE_WARN, "no devinition for instance block '%s' in %s.conf", ibn[ibni], driver); continue; } /* Does 'path' go through this instance block? */ for (ibpi = 0; ibpi < nibp; ibpi++) { if (ibp[ibpi] == NULL) continue; ibplen = strlen(ibp[ibpi]); if ((ibplen <= plen) && (strcmp(ibp[ibpi], path + plen - ibplen) == 0)) break; } if (ibpi >= nibp) { ddi_prop_free(ibp); continue; /* no try next instance block */ } /* yes, allocate and assign instances for all paths in block */ /* * determine where we splice in instance paths and verify * that none of the paths are too long. */ splice = plen - ibplen; for (i = 0; i < nibp; i++) { if ((splice + strlen(ibp[i])+ 1) >= MAXPATHLEN) { cmn_err(CE_WARN, "path %d through instance block '%s' from " "%s.conf too long", i, ibn[ibni], driver); break; } } if (i < nibp) { ddi_prop_free(ibp); continue; /* too long */ } /* allocate the instance block - no more failures */ instance_base = in_next_instance_block(major, nibp); ipath = kmem_alloc(MAXPATHLEN, KM_SLEEP); for (ibpi = 0; ibpi < nibp; ibpi++) { if (ibp[ibpi] == NULL) continue; (void) strcpy(ipath, path); (void) strcpy(ipath + splice, ibp[ibpi]); (void) in_pathin(ipath, instance_base + ibpi, driver, NULL); } /* free allocations */ kmem_free(ipath, MAXPATHLEN); ddi_prop_free(ibp); kmem_free(path, MAXPATHLEN); ddi_prop_free(ibn); /* notify devfsadmd to sync of path_to_inst file */ mutex_enter(&e_ddi_inst_state.ins_serial); i_log_devfs_instance_mod(); e_ddi_inst_state.ins_dirty = 1; mutex_exit(&e_ddi_inst_state.ins_serial); return (1); } /* our path did not go through any of of the instance blocks */ kmem_free(path, MAXPATHLEN); ddi_prop_free(ibn); return (0); }
/*ARGSUSED*/ static int emul64_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, scsi_hba_tran_t *tran, struct scsi_device *sd) { struct emul64 *emul64; emul64_tgt_t *tgt; char **geo_vidpid = NULL; char *geo, *vidpid; uint32_t *geoip = NULL; uint_t length; uint_t length2; lldaddr_t sector_count; char prop_name[15]; int ret = DDI_FAILURE; emul64 = TRAN2EMUL64(tran); EMUL64_MUTEX_ENTER(emul64); /* * We get called for each target driver.conf node, multiple * nodes may map to the same tgt,lun (sd.conf, st.conf, etc). * Check to see if transport to tgt,lun already established. */ tgt = find_tgt(emul64, sd->sd_address.a_target, sd->sd_address.a_lun); if (tgt) { ret = DDI_SUCCESS; goto out; } /* see if we have driver.conf specified device for this target,lun */ (void) snprintf(prop_name, sizeof (prop_name), "targ_%d_%d", sd->sd_address.a_target, sd->sd_address.a_lun); if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba_dip, DDI_PROP_DONTPASS, prop_name, &geo_vidpid, &length) != DDI_PROP_SUCCESS) goto out; if (length < 2) { cmn_err(CE_WARN, "emul64: %s property does not have 2 " "elements", prop_name); goto out; } /* pick geometry name and vidpid string from string array */ geo = *geo_vidpid; vidpid = *(geo_vidpid + 1); /* lookup geometry property integer array */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba_dip, DDI_PROP_DONTPASS, geo, (int **)&geoip, &length2) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "emul64: didn't get prop '%s'", geo); goto out; } if (length2 < 6) { cmn_err(CE_WARN, "emul64: property %s does not have 6 " "elements", *geo_vidpid); goto out; } /* allocate and initialize tgt structure for tgt,lun */ tgt = kmem_zalloc(sizeof (emul64_tgt_t), KM_SLEEP); rw_init(&tgt->emul64_tgt_nw_lock, NULL, RW_DRIVER, NULL); mutex_init(&tgt->emul64_tgt_blk_lock, NULL, MUTEX_DRIVER, NULL); /* create avl for data block storage */ avl_create(&tgt->emul64_tgt_data, emul64_bsd_blkcompare, sizeof (blklist_t), offsetof(blklist_t, bl_node)); /* save scsi_address and vidpid */ bcopy(sd, &tgt->emul64_tgt_saddr, sizeof (struct scsi_address)); (void) strncpy(tgt->emul64_tgt_inq, vidpid, sizeof (emul64->emul64_tgt->emul64_tgt_inq)); /* * The high order 4 bytes of the sector count always come first in * emul64.conf. They are followed by the low order 4 bytes. Not * all CPU types want them in this order, but laddr_t takes care of * this for us. We then pick up geometry (ncyl X nheads X nsect). */ sector_count._p._u = *(geoip + 0); sector_count._p._l = *(geoip + 1); /* * On 32-bit platforms, fix block size if it's greater than the * allowable maximum. */ #if !defined(_LP64) if (sector_count._f > DK_MAX_BLOCKS) sector_count._f = DK_MAX_BLOCKS; #endif tgt->emul64_tgt_sectors = sector_count._f; tgt->emul64_tgt_dtype = *(geoip + 2); tgt->emul64_tgt_ncyls = *(geoip + 3); tgt->emul64_tgt_nheads = *(geoip + 4); tgt->emul64_tgt_nsect = *(geoip + 5); /* insert target structure into list */ tgt->emul64_tgt_next = emul64->emul64_tgt; emul64->emul64_tgt = tgt; ret = DDI_SUCCESS; out: EMUL64_MUTEX_EXIT(emul64); if (geoip) ddi_prop_free(geoip); if (geo_vidpid) ddi_prop_free(geo_vidpid); return (ret); }
/* * cnex_find_chan_dip -- Find the dip of a device that is corresponding * to the specific channel. Below are the details on how the dip * is derived. * * - In the MD, the cfg-handle is expected to be unique for * virtual-device nodes that have the same 'name' property value. * This value is expected to be the same as that of "reg" property * of the corresponding OBP device node. * * - The value of the 'name' property of a virtual-device node * in the MD is expected to be the same for the corresponding * OBP device node. * * - Find the virtual-device node corresponding to a channel-endpoint * by walking backwards. Then obtain the values for the 'name' and * 'cfg-handle' properties. * * - Walk all the children of the cnex, find a matching dip which * has the same 'name' and 'reg' property values. * * - The channels that have no corresponding device driver are * treated as if they correspond to the cnex driver, * that is, return cnex dip for them. This means, the * cnex acts as an umbrella device driver. Note, this is * for 'intrstat' statistics purposes only. As a result of this, * the 'intrstat' shows cnex as the device that is servicing the * interrupts corresponding to these channels. * * For now, only one such case is known, that is, the channels that * are used by the "domain-services". */ static dev_info_t * cnex_find_chan_dip(dev_info_t *dip, uint64_t chan_id, md_t *mdp, mde_cookie_t mde) { int listsz; int num_nodes; int num_devs; uint64_t cfghdl; char *md_name; mde_cookie_t *listp; dev_info_t *cdip = NULL; num_nodes = md_node_count(mdp); ASSERT(num_nodes > 0); listsz = num_nodes * sizeof (mde_cookie_t); listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP); num_devs = md_scan_dag(mdp, mde, md_find_name(mdp, "virtual-device"), md_find_name(mdp, "back"), listp); ASSERT(num_devs <= 1); if (num_devs <= 0) { DWARN("cnex_find_chan_dip:channel(0x%llx): " "No virtual-device found\n", chan_id); goto fdip_exit; } if (md_get_prop_str(mdp, listp[0], "name", &md_name) != 0) { DWARN("cnex_find_chan_dip:channel(0x%llx): " "name property not found\n", chan_id); goto fdip_exit; } D1("cnex_find_chan_dip: channel(0x%llx): virtual-device " "name property value = %s\n", chan_id, md_name); if (md_get_prop_val(mdp, listp[0], "cfg-handle", &cfghdl) != 0) { DWARN("cnex_find_chan_dip:channel(0x%llx): virtual-device's " "cfg-handle property not found\n", chan_id); goto fdip_exit; } D1("cnex_find_chan_dip:channel(0x%llx): virtual-device cfg-handle " " property value = 0x%x\n", chan_id, cfghdl); for (cdip = ddi_get_child(dip); cdip != NULL; cdip = ddi_get_next_sibling(cdip)) { int *cnex_regspec; uint32_t reglen; char *dev_name; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, "name", &dev_name) != DDI_PROP_SUCCESS) { DWARN("cnex_find_chan_dip: name property not" " found for dip(0x%p)\n", cdip); continue; } if (strcmp(md_name, dev_name) != 0) { ddi_prop_free(dev_name); continue; } ddi_prop_free(dev_name); if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS, "reg", &cnex_regspec, ®len) != DDI_SUCCESS) { DWARN("cnex_find_chan_dip: reg property not" " found for dip(0x%p)\n", cdip); continue; } if (*cnex_regspec == cfghdl) { D1("cnex_find_chan_dip:channel(0x%llx): found " "dip(0x%p) drvname=%s\n", chan_id, cdip, ddi_driver_name(cdip)); ddi_prop_free(cnex_regspec); break; } ddi_prop_free(cnex_regspec); } fdip_exit: if (cdip == NULL) { /* * If a virtual-device node exists but no dip found, * then for now print a DEBUG error message only. */ if (num_devs > 0) { DERR("cnex_find_chan_dip:channel(0x%llx): " "No device found\n", chan_id); } /* If no dip was found, return cnex device's dip. */ cdip = dip; } kmem_free(listp, listsz); D1("cnex_find_chan_dip:channel(0x%llx): returning dip=0x%p\n", chan_id, cdip); return (cdip); }
static int zfs_vfs_mount(struct mount *mp, vnode_t devvp, user_addr_t data, vfs_context_t context) { char *osname = NULL; size_t osnamelen = 0; int error = 0; int canwrite; /* * Get the objset name (the "special" mount argument). * The filesystem that we mount as root is defined in the * "zfs-bootfs" property. */ if (data) { user_addr_t fspec = USER_ADDR_NULL; #ifndef __APPLE__ if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "zfs-bootfs", &zfs_bootpath) != DDI_SUCCESS) return (EIO); error = parse_bootpath(zfs_bootpath, rootfs.bo_name); ddi_prop_free(zfs_bootpath); #endif osname = kmem_alloc(MAXPATHLEN, KM_SLEEP); if (vfs_context_is64bit(context)) { if ( (error = copyin(data, (caddr_t)&fspec, sizeof(fspec))) ) goto out; } else { #ifdef ZFS_LEOPARD_ONLY char *tmp; #else user32_addr_t tmp; #endif if ( (error = copyin(data, (caddr_t)&tmp, sizeof(tmp))) ) goto out; /* munge into LP64 addr */ fspec = CAST_USER_ADDR_T(tmp); } if ( (error = copyinstr(fspec, osname, MAXPATHLEN, &osnamelen)) ) goto out; } #if 0 if (mvp->v_type != VDIR) return (ENOTDIR); mutex_enter(&mvp->v_lock); if ((uap->flags & MS_REMOUNT) == 0 && (uap->flags & MS_OVERLAY) == 0 && (mvp->v_count != 1 || (mvp->v_flag & VROOT))) { mutex_exit(&mvp->v_lock); return (EBUSY); } mutex_exit(&mvp->v_lock); /* * ZFS does not support passing unparsed data in via MS_DATA. * Users should use the MS_OPTIONSTR interface; this means * that all option parsing is already done and the options struct * can be interrogated. */ if ((uap->flags & MS_DATA) && uap->datalen > 0) return (EINVAL); /* * Get the objset name (the "special" mount argument). */ if (error = pn_get(uap->spec, fromspace, &spn)) return (error); osname = spn.pn_path; #endif /* * Check for mount privilege? * * If we don't have privilege then see if * we have local permission to allow it */ #ifndef __APPLE__ error = secpolicy_fs_mount(cr, mvp, vfsp); if (error) { error = dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr); if (error == 0) { vattr_t vattr; /* * Make sure user is the owner of the mount point * or has sufficient privileges. */ vattr.va_mask = AT_UID; if (error = VOP_GETATTR(mvp, &vattr, 0, cr)) { goto out; } if (error = secpolicy_vnode_owner(cr, vattr.va_uid)) { goto out; } if (error = VOP_ACCESS(mvp, VWRITE, 0, cr)) { goto out; } secpolicy_fs_mount_clearopts(cr, vfsp); } else { goto out; } } #endif error = zfs_domount(mp, 0, osname, context); if (error) printf("zfs_vfs_mount: error %d\n", error); if (error == 0) { zfsvfs_t *zfsvfs = NULL; /* Make the Finder treat sub file systems just like a folder */ if (strpbrk(osname, "/")) vfs_setflags(mp, (u_int64_t)((unsigned int)MNT_DONTBROWSE)); /* Indicate to VFS that we support ACLs. */ vfs_setextendedsecurity(mp); /* Advisory locking should be handled at the VFS layer */ vfs_setlocklocal(mp); /* * Mac OS X needs a file system modify time * * We use the mtime of the "com.apple.system.mtime" * extended attribute, which is associated with the * file system root directory. * * Here we need to take a ref on z_mtime_vp to keep it around. * If the attribute isn't there, attempt to create it. */ zfsvfs = vfs_fsprivate(mp); if (zfsvfs->z_mtime_vp == NULL) { struct vnode * rvp; struct vnode *xdvp = NULLVP; struct vnode *xvp = NULLVP; znode_t *rootzp; timestruc_t modify_time; cred_t *cr; timestruc_t now; int flag; int result; if (zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp) != 0) { goto out; } rvp = ZTOV(rootzp); cr = (cred_t *)vfs_context_ucred(context); /* Grab the hidden attribute directory vnode. */ result = zfs_get_xattrdir(rootzp, &xdvp, cr, CREATE_XATTR_DIR); vnode_put(rvp); /* all done with root vnode */ rvp = NULL; if (result) { goto out; } /* * HACK - workaround missing vnode_setnoflush() KPI... * * We tag zfsvfs so that zfs_attach_vnode() can then set * vnfs_marksystem when the vnode gets created. */ zfsvfs->z_last_unmount_time = 0xBADC0DE; zfsvfs->z_last_mtime_synced = VTOZ(xdvp)->z_id; flag = vfs_isrdonly(mp) ? 0 : ZEXISTS; /* Lookup or create the named attribute. */ if ( zfs_obtain_xattr(VTOZ(xdvp), ZFS_MTIME_XATTR, S_IRUSR | S_IWUSR, cr, &xvp, flag) ) { zfsvfs->z_last_unmount_time = 0; zfsvfs->z_last_mtime_synced = 0; vnode_put(xdvp); goto out; } gethrestime(&now); ZFS_TIME_ENCODE(&now, VTOZ(xvp)->z_phys->zp_mtime); vnode_put(xdvp); vnode_ref(xvp); zfsvfs->z_mtime_vp = xvp; ZFS_TIME_DECODE(&modify_time, VTOZ(xvp)->z_phys->zp_mtime); zfsvfs->z_last_unmount_time = modify_time.tv_sec; zfsvfs->z_last_mtime_synced = modify_time.tv_sec; /* * Keep this referenced vnode from impeding an unmount. * * XXX vnode_setnoflush() is MIA from KPI (see workaround above). */ #if 0 vnode_setnoflush(xvp); #endif vnode_put(xvp); } } out: if (osname) { kmem_free(osname, MAXPATHLEN); } return (error); }
void spa_free_bootprop(char *value) { ddi_prop_free(value); }
/* * This function takes in the ac-interrupt-map property from the .conf file, * fills in the 'nodeid' information and then creates the 'interrupt-map' * property. */ static int acebus_set_imap(dev_info_t *dip) { int *imapp, *timapp, length, num, i, default_ival = 0; dev_info_t *tdip = dip; int *port_id, imap_ok = 1; int ilength; int acebus_default_se_imap[5]; /* * interrupt-map is specified via .conf file in hotplug mode, * since the child configuration is static. * It could even be hardcoded in the driver. */ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ac-interrupt-map", (int **)&imapp, (uint_t *)&ilength) != DDI_PROP_SUCCESS) { /* assume default implementation */ acebus_default_se_imap[0] = 0x14; acebus_default_se_imap[1] = 0x400000; acebus_default_se_imap[2] = 1; acebus_default_se_imap[3] = 0; acebus_default_se_imap[4] = 2; imapp = acebus_default_se_imap; ilength = 5; default_ival = 1; } num = ilength / 5; /* there are 5 integer cells in our property */ timapp = imapp; for (i = 0; i < num; i++) { if (*(timapp+i*5+3) == 0) imap_ok = 0; } if (imap_ok) { if (!default_ival) ddi_prop_free(imapp); return (DDI_SUCCESS); } while (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, tdip, DDI_PROP_DONTPASS, "upa-portid", (int **)&port_id, (uint_t *)&length) != DDI_PROP_SUCCESS) { tdip = ddi_get_parent(tdip); if (tdip == NULL) { cmn_err(CE_WARN, "%s%d: Could not get imap parent", ddi_driver_name(dip), ddi_get_instance(dip)); if (!default_ival) ddi_prop_free(imapp); return (DDI_FAILURE); } } timapp = imapp; for (i = 0; i < num; i++) { *(timapp+i*5+3) = ddi_get_nodeid(tdip); } if (ddi_prop_update_int_array(DDI_DEV_T_NONE, dip, "interrupt-map", imapp, ilength) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d: Could not update AC imap property", ddi_driver_name(dip), ddi_get_instance(dip)); if (!default_ival) ddi_prop_free(imapp); return (DDI_FAILURE); } if (!default_ival) ddi_prop_free(imapp); return (DDI_SUCCESS); }
/* * The VGA device could be under a subtractive PCI bridge on some systems. * Though the PCI_BCNF_BCNTRL_VGA_ENABLE bit is not set on such subtractive * PCI bridge, the subtractive PCI bridge can forward VGA access if no other * agent claims the access. * The vga_enable element in param acts as a flag, if not set, ignore the * checking for the PCI_BCNF_BCNTRL_VGA_ENABLE bit of the PCI bridge during * the search. */ static int find_fb_dev(dev_info_t *dip, void *param) { struct find_fb_dev_param *p = param; char *dev_type; dev_info_t *pdip; char *parent_type; if (dip == ddi_root_node()) return (DDI_WALK_CONTINUE); if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "device_type", &dev_type) != DDI_SUCCESS) return (DDI_WALK_PRUNECHILD); if ((strcmp(dev_type, "isa") == 0) || (strcmp(dev_type, "eisa") == 0)) { ddi_prop_free(dev_type); return (DDI_WALK_CONTINUE); } if ((strcmp(dev_type, "pci") == 0) || (strcmp(dev_type, "pciex") == 0)) { ddi_acc_handle_t pci_conf; uint16_t data16; char *nodename; ddi_prop_free(dev_type); if (!p->vga_enable) return (DDI_WALK_CONTINUE); nodename = ddi_node_name(dip); /* * If the node is not a PCI-to-PCI bridge, continue traversing * (it could be the root node), otherwise, check for the * VGAEnable bit to be set in the Bridge Control Register. */ if (strcmp(nodename, "pci") == 0) { if (is_pci_bridge(dip) == B_FALSE) return (DDI_WALK_CONTINUE); } if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS) return (DDI_WALK_PRUNECHILD); if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS) return (DDI_WALK_PRUNECHILD); data16 = pci_config_get16(pci_conf, PCI_BCNF_BCNTRL); pci_config_teardown(&pci_conf); if (data16 & PCI_BCNF_BCNTRL_VGA_ENABLE) return (DDI_WALK_CONTINUE); return (DDI_WALK_PRUNECHILD); } if (strcmp(dev_type, "display") != 0) { ddi_prop_free(dev_type); return (DDI_WALK_CONTINUE); } ddi_prop_free(dev_type); if ((pdip = ddi_get_parent(dip)) == NULL) return (DDI_WALK_PRUNECHILD); if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS, "device_type", &parent_type) != DDI_SUCCESS) return (DDI_WALK_PRUNECHILD); if ((strcmp(parent_type, "isa") == 0) || (strcmp(parent_type, "eisa") == 0)) { p->found_dip = dip; ddi_prop_free(parent_type); return (DDI_WALK_TERMINATE); } if ((strcmp(parent_type, "pci") == 0) || (strcmp(parent_type, "pciex") == 0)) { ddi_acc_handle_t pci_conf; uint16_t data16; ddi_prop_free(parent_type); if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS) return (DDI_WALK_PRUNECHILD); if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS) return (DDI_WALK_PRUNECHILD); data16 = pci_config_get16(pci_conf, PCI_CONF_COMM); pci_config_teardown(&pci_conf); if (!(data16 & PCI_COMM_IO)) return (DDI_WALK_PRUNECHILD); p->found_dip = dip; return (DDI_WALK_TERMINATE); } ddi_prop_free(parent_type); return (DDI_WALK_PRUNECHILD); }
/* * Process acpi-user-options property if present */ static void acpica_process_user_options() { static int processed = 0; int acpi_user_options; char *acpi_prop; /* * return if acpi-user-options has already been processed */ if (processed) return; else processed = 1; /* converts acpi-user-options from type string to int, if any */ if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "acpi-user-options", &acpi_prop) == DDI_PROP_SUCCESS) { long data; int ret; ret = ddi_strtol(acpi_prop, NULL, 0, &data); if (ret == 0) { e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(), "acpi-user-options"); e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(), "acpi-user-options", data); } ddi_prop_free(acpi_prop); } /* * fetch the optional options property */ acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "acpi-user-options", 0); /* * Note that 'off' has precedence over 'on' * Also note - all cases of ACPI_OUSER_MASK * provided here, no default: case is present */ switch (acpi_user_options & ACPI_OUSER_MASK) { case ACPI_OUSER_DFLT: acpica_enable = acpica_check_bios_date(1999, 1, 1); break; case ACPI_OUSER_ON: acpica_enable = TRUE; break; case ACPI_OUSER_OFF: case ACPI_OUSER_OFF | ACPI_OUSER_ON: acpica_enable = FALSE; break; } acpi_init_level = ACPI_FULL_INITIALIZATION; /* * special test here; may be generalized in the * future - test for a machines that are known to * work only in legacy mode, and set OUSER_LEGACY if * we're on one */ if (acpica_metro_old_bios()) acpi_user_options |= ACPI_OUSER_LEGACY; /* * If legacy mode is specified, set initialization * options to avoid entering ACPI mode and hooking SCI * - basically try to act like legacy acpi_intp */ if ((acpi_user_options & ACPI_OUSER_LEGACY) != 0) acpi_init_level |= (ACPI_NO_ACPI_ENABLE | ACPI_NO_HANDLER_INIT); /* * modify default ACPI CA debug output level for non-DEBUG builds * (to avoid BIOS debug chatter in /var/adm/messages) */ if (acpica_muzzle_debug_output) AcpiDbgLevel = 0; }
int gfxp_vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd, gfxp_vgatext_softc_ptr_t ptr) { struct vgatext_softc *softc = (struct vgatext_softc *)ptr; int unit = ddi_get_instance(devi); int error; char *parent_type = NULL; int reg_rnumber; off_t reg_offset; off_t mem_offset; char *cons; int pci_pcie_bus = 0; int value; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: vgatext_resume(softc); return (DDI_SUCCESS); default: return (DDI_FAILURE); } /* DDI_ATTACH */ softc->devi = devi; /* Copy and init DEVI */ softc->polledio.arg = (struct vis_polledio_arg *)softc; softc->polledio.display = vgatext_polled_display; softc->polledio.copy = vgatext_polled_copy; softc->polledio.cursor = vgatext_polled_cursor; mutex_init(&(softc->lock), NULL, MUTEX_DRIVER, NULL); error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi), DDI_PROP_DONTPASS, "device_type", &parent_type); if (error != DDI_SUCCESS) { cmn_err(CE_WARN, MYNAME ": can't determine parent type."); goto fail; } /* Not enable AGP and DRM by default */ if (STREQ(parent_type, "isa") || STREQ(parent_type, "eisa")) { reg_rnumber = vgatext_get_isa_reg_index(devi, 1, VGA_REG_ADDR, ®_offset); if (reg_rnumber < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for registers"); error = DDI_FAILURE; goto fail; } softc->fb_regno = vgatext_get_isa_reg_index(devi, 0, VGA_MEM_ADDR, &mem_offset); if (softc->fb_regno < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for memory"); error = DDI_FAILURE; goto fail; } } else if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) { pci_pcie_bus = 1; reg_rnumber = vgatext_get_pci_reg_index(devi, PCI_REG_ADDR_M|PCI_REG_REL_M, PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR, ®_offset); if (reg_rnumber < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for registers"); error = DDI_FAILURE; goto fail; } softc->fb_regno = vgatext_get_pci_reg_index(devi, PCI_REG_ADDR_M|PCI_REG_REL_M, PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR, &mem_offset); if (softc->fb_regno < 0) { cmn_err(CE_WARN, MYNAME ": can't find reg entry for memory"); error = DDI_FAILURE; goto fail; } } else { cmn_err(CE_WARN, MYNAME ": unknown parent type \"%s\".", parent_type); error = DDI_FAILURE; goto fail; } ddi_prop_free(parent_type); parent_type = NULL; error = ddi_regs_map_setup(devi, reg_rnumber, (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE, &dev_attr, &softc->regs.handle); if (error != DDI_SUCCESS) goto fail; softc->regs.mapped = B_TRUE; softc->fb_size = VGA_MEM_SIZE; error = ddi_regs_map_setup(devi, softc->fb_regno, (caddr_t *)&softc->fb.addr, mem_offset, softc->fb_size, &dev_attr, &softc->fb.handle); if (error != DDI_SUCCESS) goto fail; softc->fb.mapped = B_TRUE; if (ddi_get8(softc->regs.handle, softc->regs.addr + VGA_MISC_R) & VGA_MISC_IOA_SEL) softc->text_base = (caddr_t)softc->fb.addr + VGA_COLOR_BASE; else softc->text_base = (caddr_t)softc->fb.addr + VGA_MONO_BASE; if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(), DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) { if (strcmp(cons, "graphics") == 0) { happyface_boot = 1; vgatext_silent = 1; softc->current_base = softc->shadow; } else { softc->current_base = softc->text_base; } ddi_prop_free(cons); } else { softc->current_base = softc->text_base; } error = ddi_prop_create(makedevice(DDI_MAJOR_T_UNKNOWN, unit), devi, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0); if (error != DDI_SUCCESS) goto fail; gfxp_check_for_console(devi, softc, pci_pcie_bus); value = GFXP_IS_CONSOLE(softc) ? 1 : 0; if (ddi_prop_update_int(DDI_DEV_T_NONE, devi, "primary-controller", value) != DDI_SUCCESS) { cmn_err(CE_WARN, "Can not %s primary-controller " "property for driver", value ? "set" : "clear"); } /* only do this if not in graphics mode */ if ((vgatext_silent == 0) && (GFXP_IS_CONSOLE(softc))) { vgatext_init(softc); vgatext_save_colormap(softc); } return (DDI_SUCCESS); fail: if (parent_type != NULL) ddi_prop_free(parent_type); (void) gfxp_vgatext_detach(devi, DDI_DETACH, (void *)softc); return (error); }
static int console_type() { static int boot_console = CONS_INVALID; char *cons; dev_info_t *root; if (boot_console != CONS_INVALID) return (boot_console); #if defined(__xpv) if (!DOMAIN_IS_INITDOMAIN(xen_info) || bcons_hypervisor_redirect()) { boot_console = CONS_HYPERVISOR; return (boot_console); } #endif /* __xpv */ /* * console is defined by "console" property, with * fallback on the old "input-device" property. * If "input-device" is not defined either, also check "output-device". */ boot_console = CONS_SCREEN; /* default is screen/kb */ root = ddi_root_node(); if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root, DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) || (ddi_prop_lookup_string(DDI_DEV_T_ANY, root, DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS) || (ddi_prop_lookup_string(DDI_DEV_T_ANY, root, DDI_PROP_DONTPASS, "output-device", &cons) == DDI_SUCCESS)) { if (strcmp(cons, "ttya") == 0) { boot_console = CONS_TTYA; } else if (strcmp(cons, "ttyb") == 0) { boot_console = CONS_TTYB; } else if (strcmp(cons, "usb-serial") == 0) { (void) i_ddi_attach_hw_nodes("ehci"); (void) i_ddi_attach_hw_nodes("uhci"); (void) i_ddi_attach_hw_nodes("ohci"); /* * USB device enumerate asynchronously. * Wait 2 seconds for USB serial devices to attach. */ delay(drv_usectohz(2000000)); boot_console = CONS_USBSER; #if defined(__xpv) } else if (strcmp(cons, "hypervisor") == 0) { boot_console = CONS_HYPERVISOR; #endif /* __xpv */ } ddi_prop_free(cons); } /* * If the console is configured to use a framebuffer but none * could be found, fallback to "ttya" since it's likely to exist * and it matches longstanding behavior on SPARC. */ if (boot_console == CONS_SCREEN && plat_fbpath() == NULL) boot_console = CONS_TTYA; return (boot_console); }
static void gfxp_check_for_console(dev_info_t *devi, struct vgatext_softc *softc, int pci_pcie_bus) { ddi_acc_handle_t pci_conf; dev_info_t *pdevi; uint16_t data16; /* * Based on Section 11.3, "PCI Display Subsystem Initialization", * of the 1.1 PCI-to-PCI Bridge Architecture Specification * determine if this is the boot console device. First, see * if the SBIOS has turned on PCI I/O for this device. Then if * this is PCI/PCI-E, verify the parent bridge has VGAEnable set. */ if (pci_config_setup(devi, &pci_conf) != DDI_SUCCESS) { cmn_err(CE_WARN, MYNAME ": can't get PCI conf handle"); return; } data16 = pci_config_get16(pci_conf, PCI_CONF_COMM); if (data16 & PCI_COMM_IO) softc->flags |= GFXP_FLAG_CONSOLE; pci_config_teardown(&pci_conf); /* If IO not enabled or ISA/EISA, just return */ if (!(softc->flags & GFXP_FLAG_CONSOLE) || !pci_pcie_bus) return; /* * Check for VGA Enable in the Bridge Control register for all * PCI/PCIEX parents. If not set all the way up the chain, * this cannot be the boot console. */ pdevi = ddi_get_parent(devi); while (pdevi) { int error; ddi_acc_handle_t ppci_conf; char *parent_type = NULL; error = ddi_prop_lookup_string(DDI_DEV_T_ANY, pdevi, DDI_PROP_DONTPASS, "device_type", &parent_type); if (error != DDI_SUCCESS) { return; } /* Verify still on the PCI/PCIEX parent tree */ if (!STREQ(parent_type, "pci") && !STREQ(parent_type, "pciex")) { ddi_prop_free(parent_type); return; } ddi_prop_free(parent_type); parent_type = NULL; if (pci_config_setup(pdevi, &ppci_conf) != DDI_SUCCESS) { /* No registers on root node, done with check */ return; } data16 = pci_config_get16(ppci_conf, PCI_BCNF_BCNTRL); pci_config_teardown(&ppci_conf); if (!(data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)) { softc->flags &= ~GFXP_FLAG_CONSOLE; return; } pdevi = ddi_get_parent(pdevi); } }