/* * Create properties of various data types for testing devfs events. */ static int gen_create_properties(dev_info_t *devi) { int int_val = 3023; int int_array[] = { 3, 10, 304, 230, 4}; int64_t int64_val = 20; int64_t int64_array[] = { 12, 24, 36, 48}; char *string_val = "Dev_node_prop"; char *string_array[] = {"Dev_node_prop:0", "Dev_node_prop:1", "Dev_node_prop:2", "Dev_node_prop:3"}; uchar_t byte_array[] = { (uchar_t)0xaa, (uchar_t)0x55, (uchar_t)0x12, (uchar_t)0xcd }; char bytes[] = { (char)0x00, (char)0xef, (char)0xff }; if (ddi_prop_update_int(DDI_DEV_T_NONE, devi, "int", int_val) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_int_array(DDI_DEV_T_NONE, devi, "int-array", int_array, sizeof (int_array) / sizeof (int)) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_int64(DDI_DEV_T_NONE, devi, "int64", int64_val) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_int64_array(DDI_DEV_T_NONE, devi, "int64-array", int64_array, sizeof (int64_array) / sizeof (int64_t)) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "string", string_val) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_string_array(DDI_DEV_T_NONE, devi, "string-array", string_array, sizeof (string_array) / sizeof (char *)) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP, "boolean", NULL, 0) != DDI_PROP_SUCCESS) return (DDI_FAILURE); if (ddi_prop_update_byte_array(DDI_DEV_T_NONE, devi, "byte-array", byte_array, sizeof (byte_array)) != DDI_PROP_SUCCESS) return (DDI_FAILURE); /* untyped property */ if (ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP, "untyped", (caddr_t)bytes, sizeof (bytes)) != DDI_PROP_SUCCESS) return (DDI_FAILURE); return (DDI_SUCCESS); }
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); }
/* * 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); }