/*ARGSUSED*/ static int logidetach(dev_info_t *dip, ddi_detach_cmd_t cmd) { dev_info_t *ldevi; struct strmseinfo *logiptr; int instance; switch (cmd) { case DDI_DETACH: /* * check if every instance can be unloaded before actually * starting to unload this one; this prevents the needless * detach/re-attach sequence */ for (instance = 0; instance < LOGI_MAXUNIT; instance++) { if (((ldevi = logiunits[instance]) == NULL) || (logiptr = ddi_get_driver_private(ldevi)) == NULL) continue; } /* * Undo what we did in logiattach & logiprobe, freeing resources * and removing things we installed. The system * framework guarantees we are not active with this devinfo * node in any other entry points at this time. */ instance = ddi_get_instance(dip); if ((instance >= LOGI_MAXUNIT) || (logiptr = ddi_get_driver_private(dip)) == NULL) return (DDI_FAILURE); logiunits[instance] = 0; ddi_prop_remove_all(dip); ddi_remove_minor_node(dip, NULL); mutex_destroy(&logiptr->lock); ddi_remove_intr(dip, 0, logiptr->iblock); kmem_free(logiptr, sizeof (struct strmseinfo)); return (DDI_SUCCESS); default: #ifdef LOGI_DEBUG if (logi_debug) { PRF("logidetach: cmd = %d unknown\n", cmd); } #endif return (DDI_FAILURE); } }
/* * audio1575_resume() * * Description: * Resume operation of the device after sleeping or hibernating. * Note that this should never fail, even if hardware goes wonky, * because the current PM framework will panic if it does. * * Arguments: * dev_info_t *dip Pointer to the device's dev_info struct * * Returns: * DDI_SUCCESS The driver was resumed */ static int audio1575_resume(dev_info_t *dip) { audio1575_state_t *statep; audio_dev_t *adev; /* we've already allocated the state structure so get ptr */ statep = ddi_get_driver_private(dip); adev = statep->adev; ASSERT(!mutex_owned(&statep->lock)); if (audio1575_chip_init(statep) != DDI_SUCCESS) { /* * Note that PM gurus say we should return * success here. Failure of audio shouldn't * be considered FATAL to the system. The * upshot is that audio will not progress. */ audio_dev_warn(adev, "DDI_RESUME failed to init chip"); return (DDI_SUCCESS); } /* allow ac97 operations again */ ac97_reset(statep->ac97); audio_dev_resume(adev); return (DDI_SUCCESS); }
/*ARGSUSED*/ static int mouse8042_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { struct mouse_state *state; state = ddi_get_driver_private(dip); switch (cmd) { case DDI_SUSPEND: /* Ignore all data from mouse8042_intr until we fully resume */ state->ready = 0; return (DDI_SUCCESS); case DDI_DETACH: ddi_remove_intr(dip, 0, state->ms_iblock_cookie); mouse8042_dip = NULL; cv_destroy(&state->reset_cv); mutex_destroy(&state->reset_mutex); mutex_destroy(&state->ms_mutex); ddi_prop_remove_all(dip); ddi_regs_map_free(&state->ms_handle); ddi_remove_minor_node(dip, NULL); kmem_free(state, sizeof (struct mouse_state)); return (DDI_SUCCESS); default: return (DDI_FAILURE); } }
/** * Virtio Detach routine that should be called from all Virtio drivers' detach * routines. * * @param pDip The module structure instance. * @param enmCmd Operation type (detach/suspend). * * @return Solaris DDI error code. DDI_SUCCESS or DDI_FAILURE. */ int VirtioDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) { LogFlowFunc((VIRTIOLOGNAME ":VirtioDetach pDip=%p enmCmd=%d\n", pDip, enmCmd)); PVIRTIODEVICE pDevice = ddi_get_driver_private(pDip); if (RT_UNLIKELY(!pDevice)) return DDI_FAILURE; if (enmCmd != DDI_DETACH) { LogRel((VIRTIOLOGNAME ":VirtioDetach: Invalid enmCmd=%#x expected DDI_DETACH.\n", enmCmd)); return DDI_FAILURE; } int rc = pDevice->pDeviceOps->pfnDetach(pDevice); if (rc == DDI_SUCCESS) { pDevice->pHyperOps->pfnDetach(pDevice); pDevice->pDeviceOps->pfnFree(pDevice); pDevice->pvDevice = NULL; pDevice->pHyperOps->pfnFree(pDevice); pDevice->pvHyper = NULL; ddi_set_driver_private(pDevice->pDip, NULL); RTMemFree(pDevice); return DDI_SUCCESS; } else LogRel((VIRTIOLOGNAME ":VirtioDetach: DeviceOps pfnDetach failed. rc=%d\n", rc)); return DDI_FAILURE; }
static int audio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { audio_dev_t *adev; /* pseudo devices don't need S/R support */ if (cmd != DDI_DETACH) { return (DDI_FAILURE); } if (dip == NULL) { return (DDI_FAILURE); } if ((adev = ddi_get_driver_private(dip)) == NULL) { return (DDI_FAILURE); } if (audio_dev_unregister(adev) != DDI_SUCCESS) { return (DDI_FAILURE); } audio_dev_free(adev); return (DDI_SUCCESS); }
static int audioixp_resume(dev_info_t *dip) { audioixp_state_t *statep; audio_dev_t *adev; audioixp_port_t *rec_port, *play_port; statep = ddi_get_driver_private(dip); adev = statep->adev; ASSERT(statep != NULL); if (audioixp_chip_init(statep) != DDI_SUCCESS) { audio_dev_warn(adev, "DDI_RESUME failed to init chip"); return (DDI_SUCCESS); } ac97_resume(statep->ac97); mutex_enter(&statep->inst_lock); statep->suspended = B_FALSE; rec_port = statep->rec_port; play_port = statep->play_port; audioixp_resume_port(rec_port); audioixp_resume_port(play_port); mutex_exit(&statep->inst_lock); return (DDI_SUCCESS); }
/* * audio1575_ddi_quiesce() * * Description: * Implements the quiesce(9e) entry point. * * Arguments: * dev_info_t *dip Pointer to the device's dev_info struct * * Returns: * DDI_SUCCESS The driver was quiesced * DDI_FAILURE The driver couldn't be quiesced */ static int audio1575_ddi_quiesce(dev_info_t *dip) { audio1575_state_t *statep; if ((statep = ddi_get_driver_private(dip)) == NULL) return (DDI_FAILURE); audio1575_dma_stop(statep, B_TRUE); return (DDI_SUCCESS); }
/* * audio1575_suspend() * * Description: * Suspend an instance of the audio1575 driver. * * Arguments: * dev_info_t *dip Pointer to the device's dev_info struct * * Returns: * DDI_SUCCESS The driver was suspended */ static int audio1575_suspend(dev_info_t *dip) { audio1575_state_t *statep; statep = ddi_get_driver_private(dip); audio_dev_suspend(statep->adev); return (DDI_SUCCESS); }
int efe_quiesce(dev_info_t *dip) { efe_t *efep = ddi_get_driver_private(dip); PUTCSR(efep, CSR_GENCTL, GENCTL_RESET); drv_usecwait(RESET_DELAY); PUTCSR(efep, CSR_GENCTL, GENCTL_PWRDWN); return (DDI_SUCCESS); }
/*ARGSUSED2*/ static int logiopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cred_p) { struct strmseinfo *logiptr; int unit; dev_info_t *dip; #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:entered\n"); #endif if (((unit = LOGIUNIT(*devp)) >= LOGI_MAXUNIT) || (dip = logiunits[unit]) == NULL) return (ENODEV); if (!mse_config.present) return (EIO); if ((logiptr = ddi_get_driver_private(dip)) == NULL) return (EIO); if (logiptr->state & M_OPEN) return (EBUSY); mutex_enter(&logiptr->lock); if (q->q_ptr != NULL) { #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:already open\n"); #endif mutex_exit(&logiptr->lock); return (EBUSY); /* already attached */ } q->q_ptr = (caddr_t)logiptr; WR(q)->q_ptr = (caddr_t)logiptr; logiptr->rqp = q; logiptr->wqp = WR(q); qprocson(q); #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:Enable interrupts ioaddr %x\n", BASE_IOA); #endif control_port(0); /* Enable interrupts */ #ifdef LOGI_DEBUG if (logi_debug) printf("logiopen:leaving\n"); #endif oldbuttons = 0; logiptr->state = M_OPEN; mutex_exit(&logiptr->lock); return (0); }
/*ARGSUSED*/ static int emul64_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { struct emul64 *emul64; scsi_hba_tran_t *tran; int instance = ddi_get_instance(dip); /* get transport structure pointer from the dip */ if (!(tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip))) { return (DDI_FAILURE); } /* get soft state from transport structure */ emul64 = TRAN2EMUL64(tran); if (!emul64) { return (DDI_FAILURE); } EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64_detach: cmd = %d", cmd); switch (cmd) { case DDI_DETACH: EMUL64_MUTEX_ENTER(emul64); taskq_destroy(emul64->emul64_taskq); (void) scsi_hba_detach(dip); scsi_hba_tran_free(emul64->emul64_tran); EMUL64_MUTEX_EXIT(emul64); mutex_destroy(EMUL64_REQ_MUTEX(emul64)); mutex_destroy(EMUL64_RESP_MUTEX(emul64)); EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64_detach: done"); ddi_soft_state_free(emul64_state, instance); return (DDI_SUCCESS); case DDI_SUSPEND: return (DDI_SUCCESS); default: return (DDI_FAILURE); } }
/* * audioixp_detach() * * Description: * Detach an instance of the audioixp driver. * * Arguments: * dev_info_t *dip Pointer to the device's dev_info struct * * Returns: * DDI_SUCCESS The driver was detached * DDI_FAILURE The driver couldn't be detached */ static int audioixp_detach(dev_info_t *dip) { audioixp_state_t *statep; statep = ddi_get_driver_private(dip); if (audio_dev_unregister(statep->adev) != DDI_SUCCESS) { return (DDI_FAILURE); } audioixp_destroy(statep); return (DDI_SUCCESS); }
/** * Detach entry point, to detach a device to the system or suspend it. * * @param pDip The module structure instance. * @param enmCmd Operation type (detach/suspend). * * @returns corresponding solaris error code. */ static int VBoxNetAdpSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) { LogFunc((DEVICE_NAME ":VBoxNetAdpSolarisDetach pDip=%p enmCmd=%d\n", pDip, enmCmd)); switch (enmCmd) { case DDI_DETACH: { /* * Unregister and clean up. */ gld_mac_info_t *pMacInfo = ddi_get_driver_private(pDip); if (pMacInfo) { vboxnetadp_state_t *pState = (vboxnetadp_state_t *)pMacInfo->gldm_private; if (pState) { gld_linkstate(pMacInfo, GLD_LINKSTATE_DOWN); int rc = gld_unregister(pMacInfo); if (rc == DDI_SUCCESS) { gld_mac_free(pMacInfo); RTMemFree(pState); return DDI_SUCCESS; } else LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to unregister GLD from MAC layer.rc=%d\n", rc)); } else LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get internal state.\n")); } else LogRel((DEVICE_NAME ":VBoxNetAdpSolarisDetach failed to get driver private GLD data.\n")); return DDI_FAILURE; } case DDI_RESUME: { /* Nothing to do here... */ return DDI_SUCCESS; } /* case DDI_SUSPEND: */ /* case DDI_HOTPLUG_DETACH: */ default: return DDI_FAILURE; } }
static int ddksample_detach (dev_info_t * dip, ddi_detach_cmd_t cmd) { oss_device_t *osdev; int err; ddksample_devc *devc; if (cmd != DDI_DETACH) { cmn_err (CE_WARN, "bad attach cmd %d\n", cmd); return 0; } if (dip == NULL) { cmn_err (CE_WARN, "ddksample_detach: dip==NULL\n"); return DDI_FAILURE; } cmn_err (CE_CONT, "Detach started " DRIVER_NICK "\n"); if ((osdev = ddi_get_driver_private (dip)) == NULL) { cmn_err (CE_WARN, "ddi_get_driver_private() failed\n"); return DDI_SUCCESS; } /* * Check if the device can be removed (not busy) and make sure it will not be * opened any more. */ if ((err = ossddk_disable_device (osdev)) < 0) return DDI_FAILURE; devc = ossddk_osdev_get_devc (osdev); /* * Stop the device and make sure it will not raise any * interrupts any morfe. */ ossddk_unregister_device (osdev); mutex_destroy (&devc->mutex); kmem_free (devc, sizeof (*devc)); return DDI_SUCCESS; }
static int usbser_keyspan_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { if (ddi_get_driver_private(dip) == NULL) { return (keyspan_pre_detach(dip, cmd, usbser_keyspan_statep)); } else { return (usbser_detach(dip, cmd, usbser_keyspan_statep)); } }
/* * quiesce(9E) entry point. * * This function is called when the system is single-threaded at high * PIL with preemption disabled. Therefore, this function must not be blocked. * * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. * DDI_FAILURE indicates an error condition and should almost never happen. */ static int audioixp_quiesce(dev_info_t *dip) { audioixp_state_t *statep; statep = ddi_get_driver_private(dip); ASSERT(statep != NULL); /* disable HW interrupt */ audioixp_disable_intr(statep); /* stop DMA engines */ audioixp_stop_dma(statep); return (DDI_SUCCESS); }
int efe_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { efe_t *efep = ddi_get_driver_private(dip); switch (cmd) { case DDI_DETACH: break; case DDI_SUSPEND: return (efe_suspend(efep)); default: return (DDI_FAILURE); } if (mac_unregister(efep->efe_mh) != 0) { efe_error(dip, "unable to unregister from mac!"); return (DDI_FAILURE); } mii_free(efep->efe_miih); (void) ddi_intr_disable(efep->efe_intrh); (void) ddi_intr_remove_handler(efep->efe_intrh); (void) ddi_intr_free(efep->efe_intrh); mutex_destroy(&efep->efe_txlock); mutex_destroy(&efep->efe_intrlock); if (efep->efe_tx_ring != NULL) { efe_ring_free(&efep->efe_tx_ring); } if (efep->efe_rx_ring != NULL) { efe_ring_free(&efep->efe_rx_ring); } ddi_regs_map_free(&efep->efe_regs_acch); kmem_free(efep, sizeof (efe_t)); return (DDI_SUCCESS); }
static int audioixp_suspend(dev_info_t *dip) { audioixp_state_t *statep; statep = ddi_get_driver_private(dip); ASSERT(statep != NULL); ac97_suspend(statep->ac97); mutex_enter(&statep->inst_lock); statep->suspended = B_TRUE; audioixp_disable_intr(statep); audioixp_stop_dma(statep); mutex_exit(&statep->inst_lock); return (DDI_SUCCESS); }
static int iidetach(dev_info_t *dip, ddi_detach_cmd_t cmd) { struct ii_state *xsp; int instance; intptr_t flags; if (cmd != DDI_DETACH) { return (DDI_FAILURE); } if (_ii_info_top) { return (DDI_FAILURE); /* busy */ } instance = ddi_get_instance(dip); xsp = ddi_get_soft_state(ii_statep, instance); if (xsp == NULL) { cmn_err(CE_WARN, "!ii: detach: could not get state for instance %d.", instance); return (DDI_FAILURE); } flags = (intptr_t)ddi_get_driver_private(dip); if (flags & DIDNODES) ddi_remove_minor_node(dip, NULL); if (flags & DIDINIT) _ii_deinit_dev(); ddi_soft_state_free(ii_statep, instance); if (ii_gkstat) { kstat_delete(ii_gkstat); ii_gkstat = NULL; } return (DDI_SUCCESS); }
static int bd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) { bd_t *bd; bd = ddi_get_driver_private(dip); switch (cmd) { case DDI_DETACH: break; case DDI_SUSPEND: /* We don't suspend, but our parent does */ return (DDI_SUCCESS); default: return (DDI_FAILURE); } if (bd->d_ksp != NULL) { kstat_delete(bd->d_ksp); bd->d_ksp = NULL; } else { kmem_free(bd->d_kiop, sizeof (kstat_io_t)); } cmlb_detach(bd->d_cmlbh, 0); cmlb_free_handle(&bd->d_cmlbh); if (bd->d_devid) ddi_devid_free(bd->d_devid); 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); ddi_soft_state_free(bd_state, ddi_get_instance(dip)); return (DDI_SUCCESS); }
/* * Autoconfiguration entry points. */ int efe_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { ddi_acc_handle_t pci; int types; int count; int actual; uint_t pri; efe_t *efep; mac_register_t *macp; switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: efep = ddi_get_driver_private(dip); return (efe_resume(efep)); default: return (DDI_FAILURE); } /* * PCI configuration. */ if (pci_config_setup(dip, &pci) != DDI_SUCCESS) { efe_error(dip, "unable to setup PCI configuration!"); return (DDI_FAILURE); } pci_config_put16(pci, PCI_CONF_COMM, pci_config_get16(pci, PCI_CONF_COMM) | PCI_COMM_MAE | PCI_COMM_ME); pci_config_teardown(&pci); if (ddi_intr_get_supported_types(dip, &types) != DDI_SUCCESS || !(types & DDI_INTR_TYPE_FIXED)) { efe_error(dip, "fixed interrupts not supported!"); return (DDI_FAILURE); } if (ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count) != DDI_SUCCESS || count != 1) { efe_error(dip, "no fixed interrupts available!"); return (DDI_FAILURE); } /* * Initialize soft state. */ efep = kmem_zalloc(sizeof (efe_t), KM_SLEEP); ddi_set_driver_private(dip, efep); efep->efe_dip = dip; if (ddi_regs_map_setup(dip, 1, (caddr_t *)&efep->efe_regs, 0, 0, &efe_regs_acc_attr, &efep->efe_regs_acch) != DDI_SUCCESS) { efe_error(dip, "unable to setup register mapping!"); goto failure; } efep->efe_rx_ring = efe_ring_alloc(efep->efe_dip, RXDESCL); if (efep->efe_rx_ring == NULL) { efe_error(efep->efe_dip, "unable to allocate rx ring!"); goto failure; } efep->efe_tx_ring = efe_ring_alloc(efep->efe_dip, TXDESCL); if (efep->efe_tx_ring == NULL) { efe_error(efep->efe_dip, "unable to allocate tx ring!"); goto failure; } if (ddi_intr_alloc(dip, &efep->efe_intrh, DDI_INTR_TYPE_FIXED, 0, count, &actual, DDI_INTR_ALLOC_STRICT) != DDI_SUCCESS || actual != count) { efe_error(dip, "unable to allocate fixed interrupt!"); goto failure; } if (ddi_intr_get_pri(efep->efe_intrh, &pri) != DDI_SUCCESS || pri >= ddi_intr_get_hilevel_pri()) { efe_error(dip, "unable to get valid interrupt priority!"); goto failure; } mutex_init(&efep->efe_intrlock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri)); mutex_init(&efep->efe_txlock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri)); /* * Initialize device. */ mutex_enter(&efep->efe_intrlock); mutex_enter(&efep->efe_txlock); efe_reset(efep); mutex_exit(&efep->efe_txlock); mutex_exit(&efep->efe_intrlock); /* Use factory address as default */ efe_getaddr(efep, efep->efe_macaddr); /* * Enable the ISR. */ if (ddi_intr_add_handler(efep->efe_intrh, efe_intr, efep, NULL) != DDI_SUCCESS) { efe_error(dip, "unable to add interrupt handler!"); goto failure; } if (ddi_intr_enable(efep->efe_intrh) != DDI_SUCCESS) { efe_error(dip, "unable to enable interrupt!"); goto failure; } /* * Allocate MII resources. */ if ((efep->efe_miih = mii_alloc(efep, dip, &efe_mii_ops)) == NULL) { efe_error(dip, "unable to allocate mii resources!"); goto failure; } /* * Allocate MAC resources. */ if ((macp = mac_alloc(MAC_VERSION)) == NULL) { efe_error(dip, "unable to allocate mac resources!"); goto failure; } macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; macp->m_driver = efep; macp->m_dip = dip; macp->m_src_addr = efep->efe_macaddr; macp->m_callbacks = &efe_m_callbacks; macp->m_min_sdu = 0; macp->m_max_sdu = ETHERMTU; macp->m_margin = VLAN_TAGSZ; if (mac_register(macp, &efep->efe_mh) != 0) { efe_error(dip, "unable to register with mac!"); goto failure; } mac_free(macp); ddi_report_dev(dip); return (DDI_SUCCESS); failure: if (macp != NULL) { mac_free(macp); } if (efep->efe_miih != NULL) { mii_free(efep->efe_miih); } if (efep->efe_intrh != NULL) { (void) ddi_intr_disable(efep->efe_intrh); (void) ddi_intr_remove_handler(efep->efe_intrh); (void) ddi_intr_free(efep->efe_intrh); } mutex_destroy(&efep->efe_txlock); mutex_destroy(&efep->efe_intrlock); if (efep->efe_tx_ring != NULL) { efe_ring_free(&efep->efe_tx_ring); } if (efep->efe_rx_ring != NULL) { efe_ring_free(&efep->efe_rx_ring); } if (efep->efe_regs_acch != NULL) { ddi_regs_map_free(&efep->efe_regs_acch); } kmem_free(efep, sizeof (efe_t)); return (DDI_FAILURE); }
/*ARGSUSED*/ static int emul64_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { int mutex_initted = 0; struct emul64 *emul64; int instance; scsi_hba_tran_t *tran = NULL; ddi_dma_attr_t tmp_dma_attr; emul64_bsd_get_props(dip); bzero((void *) &tmp_dma_attr, sizeof (tmp_dma_attr)); instance = ddi_get_instance(dip); switch (cmd) { case DDI_ATTACH: break; case DDI_RESUME: tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip); if (!tran) { return (DDI_FAILURE); } emul64 = TRAN2EMUL64(tran); return (DDI_SUCCESS); default: emul64_i_log(NULL, CE_WARN, "emul64%d: Cmd != DDI_ATTACH/DDI_RESUME", instance); return (DDI_FAILURE); } /* * Allocate emul64 data structure. */ if (ddi_soft_state_zalloc(emul64_state, instance) != DDI_SUCCESS) { emul64_i_log(NULL, CE_WARN, "emul64%d: Failed to alloc soft state", instance); return (DDI_FAILURE); } emul64 = (struct emul64 *)ddi_get_soft_state(emul64_state, instance); if (emul64 == (struct emul64 *)NULL) { emul64_i_log(NULL, CE_WARN, "emul64%d: Bad soft state", instance); ddi_soft_state_free(emul64_state, instance); return (DDI_FAILURE); } /* * Allocate a transport structure */ tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP); if (tran == NULL) { cmn_err(CE_WARN, "emul64: scsi_hba_tran_alloc failed\n"); goto fail; } emul64->emul64_tran = tran; emul64->emul64_dip = dip; tran->tran_hba_private = emul64; tran->tran_tgt_private = NULL; tran->tran_tgt_init = emul64_tran_tgt_init; tran->tran_tgt_probe = scsi_hba_probe; tran->tran_tgt_free = NULL; tran->tran_start = emul64_scsi_start; tran->tran_abort = emul64_scsi_abort; tran->tran_reset = emul64_scsi_reset; tran->tran_getcap = emul64_scsi_getcap; tran->tran_setcap = emul64_scsi_setcap; tran->tran_init_pkt = emul64_scsi_init_pkt; tran->tran_destroy_pkt = emul64_scsi_destroy_pkt; tran->tran_dmafree = emul64_scsi_dmafree; tran->tran_sync_pkt = emul64_scsi_sync_pkt; tran->tran_reset_notify = emul64_scsi_reset_notify; tmp_dma_attr.dma_attr_minxfer = 0x1; tmp_dma_attr.dma_attr_burstsizes = 0x7f; /* * Attach this instance of the hba */ if (scsi_hba_attach_setup(dip, &tmp_dma_attr, tran, 0) != DDI_SUCCESS) { cmn_err(CE_WARN, "emul64: scsi_hba_attach failed\n"); goto fail; } emul64->emul64_initiator_id = 2; /* * Look up the scsi-options property */ emul64->emul64_scsi_options = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "scsi-options", EMUL64_DEFAULT_SCSI_OPTIONS); EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64 scsi-options=%x", emul64->emul64_scsi_options); /* mutexes to protect the emul64 request and response queue */ mutex_init(EMUL64_REQ_MUTEX(emul64), NULL, MUTEX_DRIVER, emul64->emul64_iblock); mutex_init(EMUL64_RESP_MUTEX(emul64), NULL, MUTEX_DRIVER, emul64->emul64_iblock); mutex_initted = 1; EMUL64_MUTEX_ENTER(emul64); /* * Initialize the default Target Capabilities and Sync Rates */ emul64_i_initcap(emul64); EMUL64_MUTEX_EXIT(emul64); ddi_report_dev(dip); emul64->emul64_taskq = taskq_create("emul64_comp", emul64_task_nthreads, MINCLSYSPRI, 1, emul64_max_task, 0); return (DDI_SUCCESS); fail: emul64_i_log(NULL, CE_WARN, "emul64%d: Unable to attach", instance); if (mutex_initted) { mutex_destroy(EMUL64_REQ_MUTEX(emul64)); mutex_destroy(EMUL64_RESP_MUTEX(emul64)); } if (tran) { scsi_hba_tran_free(tran); } ddi_soft_state_free(emul64_state, instance); return (DDI_FAILURE); }
static int mouse8042_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { struct mouse_state *state; mblk_t *mp; int instance = ddi_get_instance(dip); static ddi_device_acc_attr_t attr = { DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC, }; int rc; if (cmd == DDI_RESUME) { state = (struct mouse_state *)ddi_get_driver_private(dip); /* Ready to handle inbound data from mouse8042_intr */ state->ready = 1; /* * Send a 0xaa 0x00 upstream. * This causes the vuid module to reset the mouse. */ if (state->ms_rqp != NULL) { if (mp = allocb(1, BPRI_MED)) { *mp->b_wptr++ = 0xaa; putnext(state->ms_rqp, mp); } if (mp = allocb(1, BPRI_MED)) { *mp->b_wptr++ = 0x0; putnext(state->ms_rqp, mp); } } return (DDI_SUCCESS); } if (cmd != DDI_ATTACH) return (DDI_FAILURE); if (mouse8042_dip != NULL) return (DDI_FAILURE); /* allocate and initialize state structure */ state = kmem_zalloc(sizeof (struct mouse_state), KM_SLEEP); state->ms_opened = B_FALSE; state->reset_state = MSE_RESET_IDLE; state->reset_tid = 0; state->bc_id = 0; ddi_set_driver_private(dip, state); /* * In order to support virtual keyboard/mouse, we should distinguish * between internal virtual open and external physical open. * * When the physical devices are opened by application, they will * be unlinked from the virtual device and their data stream will * not be sent to the virtual device. When the opened physical * devices are closed, they will be relinked to the virtual devices. * * All these automatic switch between virtual and physical are * transparent. * * So we change minor node numbering scheme to be: * external node minor num == instance * 2 * internal node minor num == instance * 2 + 1 */ rc = ddi_create_minor_node(dip, "mouse", S_IFCHR, instance * 2, DDI_NT_MOUSE, NULL); if (rc != DDI_SUCCESS) { goto fail_1; } if (ddi_create_internal_pathname(dip, "internal_mouse", S_IFCHR, instance * 2 + 1) != DDI_SUCCESS) { goto fail_2; } rc = ddi_regs_map_setup(dip, 0, (caddr_t *)&state->ms_addr, (offset_t)0, (offset_t)0, &attr, &state->ms_handle); if (rc != DDI_SUCCESS) { goto fail_2; } rc = ddi_get_iblock_cookie(dip, 0, &state->ms_iblock_cookie); if (rc != DDI_SUCCESS) { goto fail_3; } mutex_init(&state->ms_mutex, NULL, MUTEX_DRIVER, state->ms_iblock_cookie); mutex_init(&state->reset_mutex, NULL, MUTEX_DRIVER, state->ms_iblock_cookie); cv_init(&state->reset_cv, NULL, CV_DRIVER, NULL); rc = ddi_add_intr(dip, 0, (ddi_iblock_cookie_t *)NULL, (ddi_idevice_cookie_t *)NULL, mouse8042_intr, (caddr_t)state); if (rc != DDI_SUCCESS) { goto fail_3; } mouse8042_dip = dip; /* Ready to handle inbound data from mouse8042_intr */ state->ready = 1; /* Now that we're attached, announce our presence to the world. */ ddi_report_dev(dip); return (DDI_SUCCESS); fail_3: ddi_regs_map_free(&state->ms_handle); fail_2: ddi_remove_minor_node(dip, NULL); fail_1: kmem_free(state, sizeof (struct mouse_state)); return (rc); }
/* detach(9E) -- Detach a device from the system */ static int SMCG_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) { gld_mac_info_t *macinfo; Adapter_Struc *pAd; smcg_t *smcg; int i; #ifdef DEBUG if (SMCG_debug & SMCGDDI) cmn_err(CE_CONT, SMCG_NAME "_detach(0x%p)", (void *)devinfo); #endif if (cmd != DDI_DETACH) return (DDI_FAILURE); macinfo = ddi_get_driver_private(devinfo); smcg = (smcg_t *)macinfo->gldm_private; pAd = smcg->smcg_pAd; i = 50; mutex_enter(&smcg->rlist_lock); while (smcg->rx_bufs_outstanding > 0) { mutex_exit(&smcg->rlist_lock); delay(drv_usectohz(100000)); if (--i == 0) { cmn_err(CE_WARN, SMCG_NAME "%d: %d buffers not reclaimed", macinfo->gldm_ppa, smcg->rx_bufs_outstanding); return (DDI_FAILURE); } mutex_enter(&smcg->rlist_lock); } smcg->detaching_flag = 1; mutex_exit(&smcg->rlist_lock); /* * Unregister ourselves from the GLD interface * * gld_unregister will: * remove the minor node; * unlink us from the GLD system. */ if (gld_unregister(macinfo) != DDI_SUCCESS) { mutex_enter(&smcg->rlist_lock); smcg->detaching_flag = 0; mutex_exit(&smcg->rlist_lock); return (DDI_FAILURE); } ddi_remove_intr(devinfo, 0, macinfo->gldm_cookie); SMCG_dma_unalloc(smcg); mutex_destroy(&smcg->rbuf_lock); mutex_destroy(&smcg->txbuf_lock); mutex_destroy(&smcg->lm_lock); mutex_destroy(&smcg->rlist_lock); kmem_free(pAd, sizeof (Adapter_Struc)); kmem_free(smcg, sizeof (smcg_t)); gld_mac_free(macinfo); return (DDI_SUCCESS); }
/*ARGSUSED*/ static int mouse8042_open( queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cred_p) { struct mouse_state *state; minor_t minor = getminor(*devp); int rval; if (mouse8042_dip == NULL) return (ENXIO); state = ddi_get_driver_private(mouse8042_dip); mutex_enter(&state->ms_mutex); if (state->ms_opened) { /* * Exit if the same minor node is already open */ if (state->ms_minor == minor) { mutex_exit(&state->ms_mutex); return (0); } /* * Check whether it is switch between physical and virtual * * Opening from virtual while the device is being physically * opened by an application should not happen. So we ASSERT * this in DEBUG version, and return error in the non-DEBUG * case. */ ASSERT(!MOUSE8042_INTERNAL_OPEN(minor)); if (MOUSE8042_INTERNAL_OPEN(minor)) { mutex_exit(&state->ms_mutex); return (EINVAL); } /* * Opening the physical one while it is being underneath * the virtual one. * * consconfig_unlink is called to unlink this device from * the virtual one, thus the old stream serving for this * device under the virtual one is closed, and then the * lower driver's close routine (here is mouse8042_close) * is also called to accomplish the whole stream close. * Here we have to drop the lock because mouse8042_close * also needs the lock. * * For mouse, the old stream is: * consms->["pushmod"->]"mouse_vp driver" * * After the consconfig_unlink returns, the old stream is closed * and we grab the lock again to reopen this device as normal. */ mutex_exit(&state->ms_mutex); /* * If unlink fails, fail the physical open. */ if ((rval = consconfig_unlink(ddi_driver_major(mouse8042_dip), MOUSE8042_INTERNAL_MINOR(minor))) != 0) { return (rval); } mutex_enter(&state->ms_mutex); } q->q_ptr = (caddr_t)state; WR(q)->q_ptr = (caddr_t)state; state->ms_rqp = q; state->ms_wqp = WR(q); qprocson(q); state->ms_minor = minor; state->ms_opened = B_TRUE; mutex_exit(&state->ms_mutex); return (0); }