/* * 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 gen_create_mn_disk_wwn(dev_info_t *devi) { struct driver_minor_data *dmdp; int instance = ddi_get_instance(devi); char *address = ddi_get_name_addr(devi); int target, lun; if (address[0] >= '0' && address[0] <= '9' && strchr(address, ',')) { target = atod(address); address = strchr(address, ','); lun = atod(++address); } else { /* this hack is for rm_stale_link() testing */ target = 10; lun = 5; } if (ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP, "target", (caddr_t)&target, sizeof (int)) != DDI_PROP_SUCCESS) { return (DDI_FAILURE); } if (ddi_prop_create(DDI_DEV_T_NONE, devi, DDI_PROP_CANSLEEP, "lun", (caddr_t)&lun, sizeof (int)) != DDI_PROP_SUCCESS) { return (DDI_FAILURE); } for (dmdp = disk_minor_data; dmdp->name != NULL; dmdp++) { if (ddi_create_minor_node(devi, dmdp->name, dmdp->type, (INST_TO_MINOR(instance)) | dmdp->minor, DDI_NT_BLOCK_WWN, NULL) != DDI_SUCCESS) { return (DDI_FAILURE); } } return (DDI_SUCCESS); }
void pcmu_pbm_create(pcmu_t *pcmu_p) { pcmu_pbm_t *pcbm_p; int len; dev_info_t *dip = pcmu_p->pcmu_dip; /* * Allocate a state structure for the PBM and cross-link it * to its per pci node state structure. */ pcbm_p = (pcmu_pbm_t *)kmem_zalloc(sizeof (pcmu_pbm_t), KM_SLEEP); pcmu_p->pcmu_pcbm_p = pcbm_p; pcbm_p->pcbm_pcmu_p = pcmu_p; len = snprintf(pcbm_p->pcbm_nameinst_str, sizeof (pcbm_p->pcbm_nameinst_str), "%s%d", NAMEINST(dip)); pcbm_p->pcbm_nameaddr_str = pcbm_p->pcbm_nameinst_str + ++len; (void) snprintf(pcbm_p->pcbm_nameaddr_str, sizeof (pcbm_p->pcbm_nameinst_str) - len, "%s@%s", NAMEADDR(dip)); pcmu_pbm_setup(pcbm_p); PCMU_DBG4(PCMU_DBG_ATTACH, dip, "pcmu_pbm_create: ctrl=%x, afsr=%x, afar=%x, diag=%x\n", pcbm_p->pcbm_ctrl_reg, pcbm_p->pcbm_async_flt_status_reg, pcbm_p->pcbm_async_flt_addr_reg, pcbm_p->pcbm_diag_reg); PCMU_DBG1(PCMU_DBG_ATTACH, dip, "pcmu_pbm_create: conf=%x\n", pcbm_p->pcbm_config_header); /* * Register a function to disable pbm error interrupts during a panic. */ bus_func_register(BF_TYPE_ERRDIS, (busfunc_t)pcmu_pbm_disable_errors, pcbm_p); /* * create the interrupt-priorities property if it doesn't * already exist to provide a hint as to the PIL level for * our interrupt. */ if (ddi_getproplen(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "interrupt-priorities", &len) != DDI_PROP_SUCCESS) { /* Create the interrupt-priorities property. */ (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "interrupt-priorities", (caddr_t)pcmu_pil, sizeof (pcmu_pil)); } pcmu_pbm_configure(pcbm_p); }
/* * power management related initialization specific to px * called by px_attach() */ static int px_pwr_setup(dev_info_t *dip) { pcie_pwr_t *pwr_p; int instance = ddi_get_instance(dip); px_t *px_p = INST_TO_STATE(instance); ddi_intr_handle_impl_t hdl; ASSERT(PCIE_PMINFO(dip)); pwr_p = PCIE_NEXUS_PMINFO(dip); ASSERT(pwr_p); /* * indicate support LDI (Layered Driver Interface) * Create the property, if it is not already there */ if (!ddi_prop_exists(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS, DDI_KERNEL_IOCTL)) { if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0) != DDI_PROP_SUCCESS) { DBG(DBG_PWR, dip, "can't create kernel ioctl prop\n"); return (DDI_FAILURE); } } /* No support for device PM. We are always at full power */ pwr_p->pwr_func_lvl = PM_LEVEL_D0; mutex_init(&px_p->px_l23ready_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(px_pwr_pil)); cv_init(&px_p->px_l23ready_cv, NULL, CV_DRIVER, NULL); /* Initialize handle */ bzero(&hdl, sizeof (ddi_intr_handle_impl_t)); hdl.ih_cb_arg1 = px_p; hdl.ih_ver = DDI_INTR_VERSION; hdl.ih_state = DDI_IHDL_STATE_ALLOC; hdl.ih_dip = dip; hdl.ih_pri = px_pwr_pil; /* Add PME_TO_ACK message handler */ hdl.ih_cb_func = (ddi_intr_handler_t *)px_pmeq_intr; if (px_add_msiq_intr(dip, dip, &hdl, MSG_REC, (msgcode_t)PCIE_PME_ACK_MSG, -1, &px_p->px_pm_msiq_id) != DDI_SUCCESS) { DBG(DBG_PWR, dip, "px_pwr_setup: couldn't add " " PME_TO_ACK intr\n"); goto pwr_setup_err1; } px_lib_msg_setmsiq(dip, PCIE_PME_ACK_MSG, px_p->px_pm_msiq_id); px_lib_msg_setvalid(dip, PCIE_PME_ACK_MSG, PCIE_MSG_VALID); if (px_ib_update_intr_state(px_p, px_p->px_dip, hdl.ih_inum, px_msiqid_to_devino(px_p, px_p->px_pm_msiq_id), px_pwr_pil, PX_INTR_STATE_ENABLE, MSG_REC, PCIE_PME_ACK_MSG) != DDI_SUCCESS) { DBG(DBG_PWR, dip, "px_pwr_setup: PME_TO_ACK update interrupt" " state failed\n"); goto px_pwrsetup_err_state; } return (DDI_SUCCESS); px_pwrsetup_err_state: px_lib_msg_setvalid(dip, PCIE_PME_ACK_MSG, PCIE_MSG_INVALID); (void) px_rem_msiq_intr(dip, dip, &hdl, MSG_REC, PCIE_PME_ACK_MSG, px_p->px_pm_msiq_id); pwr_setup_err1: mutex_destroy(&px_p->px_l23ready_lock); cv_destroy(&px_p->px_l23ready_cv); return (DDI_FAILURE); }
/** * Attach entry point, to attach a device to the system or resume it. * * @param pDip The module structure instance. * @param enmCmd Operation type (attach/resume). * * @return corresponding solaris error code. */ static int VBoxDrvSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd) { LogFlowFunc(("VBoxDrvSolarisAttach\n")); switch (enmCmd) { case DDI_ATTACH: { int rc; #ifdef USE_SESSION_HASH int instance = ddi_get_instance(pDip); vbox_devstate_t *pState; if (ddi_soft_state_zalloc(g_pVBoxDrvSolarisState, instance) != DDI_SUCCESS) { LogRel(("VBoxDrvSolarisAttach: state alloc failed\n")); return DDI_FAILURE; } pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance); #endif /* * Register for suspend/resume notifications */ rc = ddi_prop_create(DDI_DEV_T_NONE, pDip, DDI_PROP_CANSLEEP /* kmem alloc can sleep */, "pm-hardware-state", "needs-suspend-resume", sizeof("needs-suspend-resume")); if (rc != DDI_PROP_SUCCESS) LogRel(("vboxdrv: Suspend/Resume notification registration failed.\n")); /* * Register ourselves as a character device, pseudo-driver */ #ifdef VBOX_WITH_HARDENING rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME_SYS, S_IFCHR, 0 /*minor*/, DDI_PSEUDO, 0, NULL, NULL, 0600); #else rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME_SYS, S_IFCHR, 0 /*minor*/, DDI_PSEUDO, 0, "none", "none", 0666); #endif if (rc == DDI_SUCCESS) { rc = ddi_create_priv_minor_node(pDip, DEVICE_NAME_USR, S_IFCHR, 1 /*minor*/, DDI_PSEUDO, 0, "none", "none", 0666); if (rc == DDI_SUCCESS) { #ifdef USE_SESSION_HASH pState->pDip = pDip; #endif ddi_report_dev(pDip); return DDI_SUCCESS; } ddi_remove_minor_node(pDip, NULL); } return DDI_FAILURE; } case DDI_RESUME: { #if 0 RTSemFastMutexRequest(g_DevExt.mtxGip); if (g_DevExt.pGipTimer) RTTimerStart(g_DevExt.pGipTimer, 0); RTSemFastMutexRelease(g_DevExt.mtxGip); #endif RTPowerSignalEvent(RTPOWEREVENT_RESUME); LogFlow(("vboxdrv: Awakened from suspend.\n")); return DDI_SUCCESS; } default: return DDI_FAILURE; } return DDI_FAILURE; }
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 bd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { int inst; bd_handle_t hdl; bd_t *bd; bd_drive_t drive; int rv; char name[16]; char kcache[32]; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: /* We don't do anything native for suspend/resume */ return (DDI_SUCCESS); default: return (DDI_FAILURE); } inst = ddi_get_instance(dip); hdl = ddi_get_parent_data(dip); (void) snprintf(name, sizeof (name), "%s%d", ddi_driver_name(dip), ddi_get_instance(dip)); (void) snprintf(kcache, sizeof (kcache), "%s_xfer", name); if (hdl == NULL) { cmn_err(CE_WARN, "%s: missing parent data!", name); return (DDI_FAILURE); } if (ddi_soft_state_zalloc(bd_state, inst) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s: unable to zalloc soft state!", name); return (DDI_FAILURE); } bd = ddi_get_soft_state(bd_state, inst); if (hdl->h_dma) { bd->d_dma = *(hdl->h_dma); bd->d_dma.dma_attr_granular = max(DEV_BSIZE, bd->d_dma.dma_attr_granular); bd->d_use_dma = B_TRUE; if (bd->d_maxxfer && (bd->d_maxxfer != bd->d_dma.dma_attr_maxxfer)) { cmn_err(CE_WARN, "%s: inconsistent maximum transfer size!", name); /* We force it */ bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer; } else { bd->d_maxxfer = bd->d_dma.dma_attr_maxxfer; } } else { bd->d_use_dma = B_FALSE; if (bd->d_maxxfer == 0) { bd->d_maxxfer = 1024 * 1024; } } bd->d_ops = hdl->h_ops; bd->d_private = hdl->h_private; bd->d_blkshift = 9; /* 512 bytes, to start */ if (bd->d_maxxfer % DEV_BSIZE) { cmn_err(CE_WARN, "%s: maximum transfer misaligned!", name); bd->d_maxxfer &= ~(DEV_BSIZE - 1); } if (bd->d_maxxfer < DEV_BSIZE) { cmn_err(CE_WARN, "%s: maximum transfer size too small!", name); ddi_soft_state_free(bd_state, inst); return (DDI_FAILURE); } bd->d_dip = dip; bd->d_handle = hdl; hdl->h_bd = bd; ddi_set_driver_private(dip, bd); mutex_init(&bd->d_iomutex, NULL, MUTEX_DRIVER, NULL); mutex_init(&bd->d_ocmutex, NULL, MUTEX_DRIVER, NULL); mutex_init(&bd->d_statemutex, NULL, MUTEX_DRIVER, NULL); cv_init(&bd->d_statecv, NULL, CV_DRIVER, NULL); list_create(&bd->d_waitq, sizeof (bd_xfer_impl_t), offsetof(struct bd_xfer_impl, i_linkage)); list_create(&bd->d_runq, sizeof (bd_xfer_impl_t), offsetof(struct bd_xfer_impl, i_linkage)); bd->d_cache = kmem_cache_create(kcache, sizeof (bd_xfer_impl_t), 8, bd_xfer_ctor, bd_xfer_dtor, NULL, bd, NULL, 0); bd->d_ksp = kstat_create(ddi_driver_name(dip), inst, NULL, "disk", KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT); if (bd->d_ksp != NULL) { bd->d_ksp->ks_lock = &bd->d_iomutex; kstat_install(bd->d_ksp); bd->d_kiop = bd->d_ksp->ks_data; } else { /* * Even if we cannot create the kstat, we create a * scratch kstat. The reason for this is to ensure * that we can update the kstat all of the time, * without adding an extra branch instruction. */ bd->d_kiop = kmem_zalloc(sizeof (kstat_io_t), KM_SLEEP); } cmlb_alloc_handle(&bd->d_cmlbh); bd->d_state = DKIO_NONE; bzero(&drive, sizeof (drive)); bd->d_ops.o_drive_info(bd->d_private, &drive); bd->d_qsize = drive.d_qsize; bd->d_removable = drive.d_removable; bd->d_hotpluggable = drive.d_hotpluggable; if (drive.d_maxxfer && drive.d_maxxfer < bd->d_maxxfer) bd->d_maxxfer = drive.d_maxxfer; rv = cmlb_attach(dip, &bd_tg_ops, DTYPE_DIRECT, bd->d_removable, bd->d_hotpluggable, drive.d_lun >= 0 ? DDI_NT_BLOCK_CHAN : DDI_NT_BLOCK, CMLB_FAKE_LABEL_ONE_PARTITION, bd->d_cmlbh, 0); if (rv != 0) { cmlb_free_handle(&bd->d_cmlbh); kmem_cache_destroy(bd->d_cache); mutex_destroy(&bd->d_iomutex); mutex_destroy(&bd->d_ocmutex); mutex_destroy(&bd->d_statemutex); cv_destroy(&bd->d_statecv); list_destroy(&bd->d_waitq); list_destroy(&bd->d_runq); if (bd->d_ksp != NULL) { kstat_delete(bd->d_ksp); bd->d_ksp = NULL; } else { kmem_free(bd->d_kiop, sizeof (kstat_io_t)); } ddi_soft_state_free(bd_state, inst); return (DDI_FAILURE); } if (bd->d_ops.o_devid_init != NULL) { rv = bd->d_ops.o_devid_init(bd->d_private, dip, &bd->d_devid); if (rv == DDI_SUCCESS) { if (ddi_devid_register(dip, bd->d_devid) != DDI_SUCCESS) { cmn_err(CE_WARN, "%s: unable to register devid", name); } } } /* * Add a zero-length attribute to tell the world we support * kernel ioctls (for layered drivers). Also set up properties * used by HAL to identify removable media. */ (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0); if (bd->d_removable) { (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "removable-media", NULL, 0); } if (bd->d_hotpluggable) { (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "hotpluggable", NULL, 0); } ddi_report_dev(dip); return (DDI_SUCCESS); }
/* * attach entry point: * * normal attach: * * create soft state structure (dip, reg, nreg and state fields) * map in configuration header * make sure device is properly configured * report device */ static int acebus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { ebus_devstate_t *ebus_p; /* per ebus state pointer */ int instance; DBG1(D_ATTACH, NULL, "dip=%x\n", dip); switch (cmd) { case DDI_ATTACH: /* * Allocate soft state for this instance. */ instance = ddi_get_instance(dip); if (ddi_soft_state_zalloc(per_acebus_state, instance) != DDI_SUCCESS) { DBG(D_ATTACH, NULL, "failed to alloc soft state\n"); return (DDI_FAILURE); } ebus_p = get_acebus_soft_state(instance); ebus_p->dip = dip; /* * Make sure the master enable and memory access enable * bits are set in the config command register. */ if (!acebus_config(ebus_p)) { free_acebus_soft_state(instance); return (DDI_FAILURE); } (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "no-dma-interrupt-sync", NULL, 0); /* Get our ranges property for mapping child registers. */ if (acebus_get_ranges_prop(ebus_p) != DDI_SUCCESS) { free_acebus_soft_state(instance); return (DDI_FAILURE); } /* * Make the state as attached and report the device. */ ebus_p->state = ATTACHED; ddi_report_dev(dip); DBG(D_ATTACH, ebus_p, "returning\n"); return (DDI_SUCCESS); case DDI_RESUME: instance = ddi_get_instance(dip); ebus_p = get_acebus_soft_state(instance); /* * Make sure the master enable and memory access enable * bits are set in the config command register. */ if (!acebus_config(ebus_p)) { free_acebus_soft_state(instance); return (DDI_FAILURE); } ebus_p->state = RESUMED; return (DDI_SUCCESS); } return (DDI_FAILURE); }
/* * If bridge is PM capable, set up PM state for nexus. */ static void ppb_pwr_setup(ppb_devstate_t *ppb, dev_info_t *pdip) { char *comp_array[5]; int i; ddi_acc_handle_t conf_hdl; uint8_t pmcsr_bse; uint16_t pmcap; /* * Determine if bridge is PM capable. If not, leave ppb_pwr_p NULL * and return. */ if (pci_config_setup(pdip, &ppb->ppb_conf_hdl) != DDI_SUCCESS) { return; } conf_hdl = ppb->ppb_conf_hdl; /* * Locate and store the power management cap_ptr for future references. */ if ((PCI_CAP_LOCATE(conf_hdl, PCI_CAP_ID_PM, &ppb->ppb_pm_cap_ptr)) == DDI_FAILURE) { DEBUG0(DBG_PWR, pdip, "bridge does not support PM. PCI" " PM data structure not found in config header\n"); pci_config_teardown(&conf_hdl); return; } /* * Allocate PM state structure for ppb. */ ppb->ppb_pwr_p = (pci_pwr_t *) kmem_zalloc(sizeof (pci_pwr_t), KM_SLEEP); ppb->ppb_pwr_p->pwr_fp = 0; pmcsr_bse = PCI_CAP_GET8(conf_hdl, NULL, ppb->ppb_pm_cap_ptr, PCI_PMCSR_BSE); pmcap = PCI_CAP_GET16(conf_hdl, NULL, ppb->ppb_pm_cap_ptr, PCI_PMCAP); if (pmcap == PCI_CAP_EINVAL16 || pmcsr_bse == PCI_CAP_EINVAL8) { pci_config_teardown(&conf_hdl); return; } if (pmcap & PCI_PMCAP_D1) { DEBUG0(DBG_PWR, pdip, "setup: B1 state supported\n"); ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B1_CAPABLE; } else { DEBUG0(DBG_PWR, pdip, "setup: B1 state NOT supported\n"); } if (pmcap & PCI_PMCAP_D2) { DEBUG0(DBG_PWR, pdip, "setup: B2 state supported\n"); ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B2_CAPABLE; } else { DEBUG0(DBG_PWR, pdip, "setup: B2 via D2 NOT supported\n"); } if (pmcsr_bse & PCI_PMCSR_BSE_BPCC_EN) { DEBUG0(DBG_PWR, pdip, "setup: bridge power/clock control enable\n"); } else { DEBUG0(DBG_PWR, pdip, "setup: bridge power/clock control disabled\n"); kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t)); ppb->ppb_pwr_p = NULL; pci_config_teardown(&conf_hdl); return; } /* * PCI states D0 and D3 always are supported for normal PCI * devices. D1 and D2 are optional which are checked for above. * Bridge function states D0-D3 correspond to secondary bus states * B0-B3, EXCEPT if PCI_PMCSR_BSE_B2_B3 is set. In this case, setting * the bridge function to D3 will set the bridge bus to state B2 instead * of B3. D2 will not correspond to B2 (and in fact, probably * won't be D2 capable). Implicitly, this means that if * PCI_PMCSR_BSE_B2_B3 is set, the bus will not be B3 capable. */ if (pmcsr_bse & PCI_PMCSR_BSE_B2_B3) { ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B2_CAPABLE; DEBUG0(DBG_PWR, pdip, "B2 supported via D3\n"); } else { ppb->ppb_pwr_p->pwr_flags |= PCI_PWR_B3_CAPABLE; DEBUG0(DBG_PWR, pdip, "B3 supported via D3\n"); } ppb->ppb_pwr_p->pwr_dip = pdip; mutex_init(&ppb->ppb_pwr_p->pwr_mutex, NULL, MUTEX_DRIVER, NULL); i = 0; comp_array[i++] = "NAME=PCI bridge PM"; if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B3_CAPABLE) { comp_array[i++] = "0=Clock/Power Off (B3)"; } if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B2_CAPABLE) { comp_array[i++] = "1=Clock Off (B2)"; } if (ppb->ppb_pwr_p->pwr_flags & PCI_PWR_B1_CAPABLE) { comp_array[i++] = "2=Bus Inactive (B1)"; } comp_array[i++] = "3=Full Power (B0)"; /* * Create pm-components property. It does not already exist. */ if (ddi_prop_update_string_array(DDI_DEV_T_NONE, pdip, "pm-components", comp_array, i) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d pm-components prop update failed", ddi_driver_name(pdip), ddi_get_instance(pdip)); pci_config_teardown(&conf_hdl); mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex); kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t)); ppb->ppb_pwr_p = NULL; return; } if (ddi_prop_create(DDI_DEV_T_NONE, pdip, DDI_PROP_CANSLEEP, "pm-want-child-notification?", NULL, NULL) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "%s%d fail to create pm-want-child-notification? prop", ddi_driver_name(pdip), ddi_get_instance(pdip)); (void) ddi_prop_remove(DDI_DEV_T_NONE, pdip, "pm-components"); pci_config_teardown(&conf_hdl); mutex_destroy(&ppb->ppb_pwr_p->pwr_mutex); kmem_free(ppb->ppb_pwr_p, sizeof (pci_pwr_t)); ppb->ppb_pwr_p = NULL; return; } ppb->ppb_pwr_p->current_lvl = pci_pwr_current_lvl(ppb->ppb_pwr_p); }
static int ds1287_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { struct ds1287 *softsp; DPRINTF("ds1287_attach\n"); switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (instance != -1) { cmn_err(CE_WARN, "ds1287_attach: Another instance is already " "attached."); return (DDI_FAILURE); } instance = ddi_get_instance(dip); if (v_rtc_addr_reg == NULL) { cmn_err(CE_WARN, "ds1287_attach: v_rtc_addr_reg is NULL"); return (DDI_FAILURE); } /* * Allocate softc information. */ if (ddi_soft_state_zalloc(ds1287_state, instance) != DDI_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to allocate " "soft states."); return (DDI_FAILURE); } softsp = ddi_get_soft_state(ds1287_state, instance); DPRINTF("ds1287_attach: instance=%d softsp=0x%p\n", instance, (void *)softsp); softsp->dip = dip; if (ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, "interrupt-priorities", (caddr_t)&ds1287_interrupt_priority, sizeof (int)) != DDI_PROP_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to create \"" "interrupt-priorities\" property."); goto error; } /* add the softint */ ds1287_lo_iblock = (ddi_iblock_cookie_t)(uintptr_t) ipltospl(ds1287_softint_priority); if (ddi_add_softintr(dip, DDI_SOFTINT_FIXED, &ds1287_softintr_id, &ds1287_lo_iblock, NULL, ds1287_softintr, (caddr_t)softsp) != DDI_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to add low interrupt."); goto error1; } /* add the hi interrupt */ if (ddi_add_intr(dip, 0, NULL, (ddi_idevice_cookie_t *) &ds1287_hi_iblock, ds1287_intr, NULL) != DDI_SUCCESS) { cmn_err(CE_WARN, "ds1287_attach: Failed to add high " "interrupt."); goto error2; } /* * Combination of instance number and clone number 0 is used for * creating the minor node. */ if (ddi_create_minor_node(dip, "power_button", S_IFCHR, (instance << 8) + 0, "ddi_power_button", NULL) == DDI_FAILURE) { cmn_err(CE_WARN, "ds1287_attach: Failed to create minor node"); goto error3; } ddi_report_dev(dip); return (DDI_SUCCESS); error3: ddi_remove_intr(dip, 0, NULL); error2: ddi_remove_softintr(ds1287_softintr_id); error1: (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "interrupt-priorities"); error: ddi_soft_state_free(ds1287_state, instance); return (DDI_FAILURE); }
static int pca9556_attach(dev_info_t *dip) { pca9556_unit_t *pcap; int instance = ddi_get_instance(dip); char name[MAXNAMELEN]; char *device_name; minor_t minor; int i, num_ports; if (ddi_soft_state_zalloc(pca9556_soft_statep, instance) != 0) { cmn_err(CE_WARN, "%s%d failed to zalloc softstate", ddi_get_name(dip), instance); return (DDI_FAILURE); } pcap = ddi_get_soft_state(pca9556_soft_statep, instance); if (pcap == NULL) return (DDI_FAILURE); mutex_init(&pcap->pca9556_mutex, NULL, MUTEX_DRIVER, NULL); cv_init(&pcap->pca9556_cv, NULL, CV_DRIVER, NULL); (void) snprintf(pcap->pca9556_name, sizeof (pcap->pca9556_name), "%s_%d", ddi_driver_name(dip), instance); device_name = ddi_get_name(dip); if (strcmp(device_name, "i2c-pca9555") == 0) { num_ports = PCA9555_NUM_PORTS; pcap->pca9555_device = B_TRUE; } else { num_ports = PCA9556_NUM_PORTS; pcap->pca9555_device = B_FALSE; minor = INST_TO_MINOR(instance); } for (i = 0; i < num_ports; i++) { if (!(pcap->pca9555_device)) { (void) snprintf(pcap->pca9556_name, sizeof (pcap->pca9556_name), "%s_%d", ddi_driver_name(dip), instance); (void) snprintf(name, sizeof (name), "%s", pcap->pca9556_name); } else { (void) sprintf(name, "port_%d", i); minor = INST_TO_MINOR(instance) | PORT_TO_MINOR(I2C_PORT(i)); } if (ddi_create_minor_node(dip, name, S_IFCHR, minor, PCA9556_NODE_TYPE, NULL) == DDI_FAILURE) { cmn_err(CE_WARN, "%s: failed to create node for %s", pcap->pca9556_name, name); pca9556_detach(dip); return (DDI_FAILURE); } } pcap->pca9556_flags |= PCA9556_MINORFLAG; /* * Add a zero-length attribute to tell the world we support * kernel ioctls (for layered drivers) */ (void) ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0); /* * preallocate a single buffer for all reads and writes */ if (i2c_transfer_alloc(pcap->pca9556_hdl, &pcap->pca9556_transfer, 2, 2, I2C_SLEEP) != I2C_SUCCESS) { cmn_err(CE_WARN, "%s i2c_transfer_alloc failed", pcap->pca9556_name); pca9556_detach(dip); return (DDI_FAILURE); } pcap->pca9556_flags |= PCA9556_TBUFFLAG; pcap->pca9556_transfer->i2c_version = I2C_XFER_REV; if (i2c_client_register(dip, &pcap->pca9556_hdl) != I2C_SUCCESS) { ddi_remove_minor_node(dip, NULL); cmn_err(CE_WARN, "%s i2c_client_register failed", pcap->pca9556_name); pca9556_detach(dip); return (DDI_FAILURE); } pcap->pca9556_flags |= PCA9556_REGFLAG; /* * Store the dip for future dip. */ pcap->pca9556_dip = dip; return (DDI_SUCCESS); }