コード例 #1
0
ファイル: pci.c プロジェクト: MatiasNAmendola/AuroraUX-SunOS
/*ARGSUSED*/
static int
pci_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	/*
	 * Use the minor number as constructed by pcihp, as the index value to
	 * ddi_soft_state_zalloc.
	 */
	int instance = ddi_get_instance(devi);
	pci_state_t *pcip = NULL;
	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}

	if (ddi_prop_update_string(DDI_DEV_T_NONE, devi, "device_type", "pci")
	    != DDI_PROP_SUCCESS) {
		cmn_err(CE_WARN, "pci:  'device_type' prop create failed");
	}

	if (ddi_soft_state_zalloc(pci_statep, instance) == DDI_SUCCESS) {
		pcip = ddi_get_soft_state(pci_statep, instance);
	}

	if (pcip == NULL) {
		goto bad_soft_state;
	}

	pcip->pci_dip = devi;
	pcip->pci_soft_state = PCI_SOFT_STATE_CLOSED;

	/*
	 * Initialize hotplug support on this bus. At minimum
	 * (for non hotplug bus) this would create ":devctl" minor
	 * node to support DEVCTL_DEVICE_* and DEVCTL_BUS_* ioctls
	 * to this bus.
	 */
	if (pcihp_init(devi) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "pci: Failed to setup hotplug framework");
		goto bad_pcihp_init;
	}

	/* Second arg: initialize for pci, not pci_express */
	if (pcitool_init(devi, B_FALSE) != DDI_SUCCESS) {
		goto bad_pcitool_init;
	}

	pcip->pci_fmcap = DDI_FM_ERRCB_CAPABLE |
	    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
	ddi_fm_init(devi, &pcip->pci_fmcap, &pcip->pci_fm_ibc);
	mutex_init(&pcip->pci_mutex, NULL, MUTEX_DRIVER, NULL);
	mutex_init(&pcip->pci_err_mutex, NULL, MUTEX_DRIVER,
	    (void *)pcip->pci_fm_ibc);
	mutex_init(&pcip->pci_peek_poke_mutex, NULL, MUTEX_DRIVER,
	    (void *)pcip->pci_fm_ibc);
	if (pcip->pci_fmcap & DDI_FM_ERRCB_CAPABLE) {
		pci_ereport_setup(devi);
		ddi_fm_handler_register(devi, pci_fm_callback, NULL);
	}

	ddi_report_dev(devi);

	return (DDI_SUCCESS);

bad_pcitool_init:
	(void) pcihp_uninit(devi);
bad_pcihp_init:
	ddi_soft_state_free(pci_statep, instance);
bad_soft_state:
	return (DDI_FAILURE);
}
コード例 #2
0
ファイル: sgsbbc.c プロジェクト: andreiw/polaris
static int
sbbc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
	sbbc_softstate_t	*softsp;
	int			instance;
	uint32_t		*pci_intr_enable_reg;
	int			rc = DDI_SUCCESS;

	instance = ddi_get_instance(devi);

	if (!(softsp = ddi_get_soft_state(sbbcp, instance)))
		return (DDI_FAILURE);

	switch (cmd) {
	case DDI_DETACH:
		mutex_enter(&chosen_lock);
		softsp->sbbc_state |= SBBC_STATE_DETACH;
		mutex_exit(&chosen_lock);

		/* only tunnel switch the instance with iosram chosen */
		if (softsp->chosen == TRUE) {
			if (sgsbbc_iosram_switchfrom(softsp) == DDI_FAILURE) {
				SBBC_ERR(CE_WARN, "Cannot unconfigure: "
				    "tunnel switch failed\n");
				return (DDI_FAILURE);
			}
		}

		/* Adjust linked list */
		mutex_enter(&chosen_lock);
		sbbc_remove_instance(softsp);
		mutex_exit(&chosen_lock);

		sbbc_unmap_regs(softsp);
		mutex_destroy(&softsp->sbbc_lock);
		ddi_soft_state_free(sbbcp, instance);

		return (DDI_SUCCESS);

	case DDI_SUSPEND:

		mutex_enter(&softsp->sbbc_lock);

		if ((softsp->suspended == FALSE) && (softsp->chosen == TRUE)) {
			uint32_t	tmp_intr_enabled = 0;

			/*
			 * Disable Interrupts now, turn OFF both INT#A lines
			 */
			pci_intr_enable_reg =  (uint32_t *)
						((char *)softsp->sbbc_regs +
							SBBC_PCI_INT_ENABLE);

			ddi_put32(softsp->sbbc_reg_handle1,
				pci_intr_enable_reg, 0);

			/*
			 * Set intr_in_enabled to 0 so the SC won't send
			 * us interrupt.
			 */
			rc = iosram_read(SBBC_SC_INTR_ENABLED_KEY,
				0, (caddr_t)&intr_in_enabled,
				sizeof (intr_in_enabled));

			if (rc) {
				mutex_exit(&softsp->sbbc_lock);
				return (DDI_FAILURE);
			}

			rc = iosram_write(SBBC_SC_INTR_ENABLED_KEY,
				0, (caddr_t)&tmp_intr_enabled,
				sizeof (tmp_intr_enabled));

			if (rc) {
				mutex_exit(&softsp->sbbc_lock);
				return (DDI_FAILURE);
			}
		}
		softsp->suspended = TRUE;

		mutex_exit(&softsp->sbbc_lock);

		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}

}
コード例 #3
0
ファイル: vboxvideo_drm.c プロジェクト: tigranbs/virtualbox
/**
 * 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).
 *
 * @returns corresponding solaris error code.
 */
static int VBoxVideoSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd)
{
    LogFlow((DEVICE_NAME ":VBoxVideoSolarisAttach pDip=%p enmCmd=%d\n", pDip, enmCmd));
    cmn_err(CE_NOTE, DEVICE_NAME ":attach\n");

    switch (enmCmd)
    {
        case DDI_ATTACH:
        {
            drm_device_t *pState;
            int Instance = ddi_get_instance(pDip);
            int rc = ddi_soft_state_zalloc(g_pVBoxVideoSolarisState, Instance);
            if (rc == DDI_SUCCESS)
            {
                pState = ddi_get_soft_state(g_pVBoxVideoSolarisState, Instance);
                pState->dip = pDip;
                pState->driver = &g_VBoxVideoSolarisDRMDriver;

                /*
                 * Register using the DRM module which will create the minor nodes
                 */
                void *pDRMHandle = drm_supp_register(pDip, pState);
                if (pDRMHandle)
                {
                    pState->drm_handle = pDRMHandle;

                    /*
                     * Probe with our pci-id.
                     * -XXX- is probing really required???
                     */
                    pState->drm_supported = DRM_UNSUPPORT;
                    rc = drm_probe(pState, vboxvideo_pciidlist);
                    if (rc == DDI_SUCCESS)
                    {
                        pState->drm_supported = DRM_SUPPORT;

                        /*
                         * Call the common attach DRM routine.
                         */
                        rc = drm_attach(pState);
                        if (rc == DDI_SUCCESS)
                        {
                            return DDI_SUCCESS;
                        }
                        else
                            LogRel((DEVICE_NAME ":VBoxVideoSolarisAttach drm_attach failed.rc=%d\n", rc));
                    }
                    else
                        LogRel((DEVICE_NAME ":VBoxVideoSolarisAttach drm_probe failed.rc=%d\n", rc));

                    drm_supp_unregister(pDRMHandle);
                }
                else
                    LogRel((DEVICE_NAME ":VBoxVideoSolarisAttach drm_supp_register failed.\n"));

                ddi_soft_state_free(g_pVBoxVideoSolarisState, Instance);
            }
            else
                LogRel((DEVICE_NAME ":VBoxVideoSolarisAttach failed to alloc memory for soft state.rc=%d\n", rc));
            return DDI_FAILURE;
        }

        case DDI_RESUME:
        {
            /* Nothing to do here... */
            return DDI_SUCCESS;
        }
    }
    return DDI_FAILURE;
}
コード例 #4
0
ファイル: gen_drv.c プロジェクト: andreiw/polaris
static int
gen_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
	struct dstate *dstatep;
	int instance;
	int i;
	int rv;
	int rm_power;
	int level_tmp;

#ifdef DEBUG
	int n_devs;
	int n_minorcomps;
	int isclone;
#endif

	switch (cmd) {
	case DDI_DETACH:
		GEN_DEBUG((CE_CONT, "%s%d: DDI_DETACH", ddi_node_name(devi),
		    ddi_get_instance(devi)));

		instance = ddi_get_instance(devi);
		dstatep = ddi_get_soft_state(dstates, instance);
		if (dstatep == NULL) {

			return (DDI_FAILURE);
}

#ifdef DEBUG
		n_devs = ddi_prop_get_int(DDI_DEV_T_ANY, devi, 0,
		    "ndevs", 1);

		isclone = ddi_prop_get_int(DDI_DEV_T_ANY, devi, 0,
		    "isclone", 0);

		n_minorcomps = ddi_prop_get_int(DDI_DEV_T_ANY, devi, 0,
		    "ncomps", 1);
#endif /* DEBUG */

		/*
		 * power off component 1.
		 */
		if (dstatep->flag & PM_SUPPORTED_FLAG) {
			GEN_DEBUG((CE_CONT,
			    "%s%d: DDI_DETACH: pm_lower_power comp 1 level %d",
			    ddi_node_name(devi), ddi_get_instance(devi),
			    MINPWR));
			if (pm_lower_power(dstatep->dip, 1, MINPWR)
			    != DDI_SUCCESS) {
				cmn_err(CE_WARN, "%s%d: DDI_DETACH:\n\t"
				    "pm_lower_power failed for comp 1 to"
				    " level %d\n", ddi_node_name(devi),
				    ddi_get_instance(devi), MINPWR);

				return (DDI_FAILURE);
			}

			/*
			 * check power level. Issue pm_power_has_changed
			 * if not at MINPWR.
			 */
			mutex_enter(&dstatep->lock);
			level_tmp = dstatep->level[1];
			dstatep->level[1] = MINPWR;
			if (dstatep->level[1] != MINPWR) {
				GEN_DEBUG((CE_NOTE, "%s%d: DDI_DETACH:"
				    " power off via pm_power_has_changed"
				    " instead", ddi_node_name(devi),
				    ddi_get_instance(devi)));
				if (pm_power_has_changed(dstatep->dip,
				    1, MINPWR) != DDI_SUCCESS) {
					GEN_DEBUG((CE_NOTE, "%s%d: DDI_DETACH:"
					    " pm_power_has_changed failed for"
					    " comp 1 to level %d",
					    ddi_node_name(devi),
					    ddi_get_instance(devi),
					    MINPWR));
					dstatep->level[1] = level_tmp;
					mutex_exit(&dstatep->lock);

					return (DDI_FAILURE);
				}
			}
			mutex_exit(&dstatep->lock);
		}

		/*
		 * If the LOWER_POWER_FLAG flag is not set,
		 * don't call pm_lowr_power() for comp 0.
		 * This should be used only for the XXXXX@XX,no_invol
		 * devices that export the
		 * no-involuntary-power-cycles property
		 */
		if (!(dstatep->flag & LOWER_POWER_FLAG) &&
		    dstatep->flag & PM_SUPPORTED_FLAG) {
			cmn_err(CE_NOTE, "%s%d: DDI_DETACH:\n\t"
			    " NOT CALLING PM_LOWER_POWER():"
			    " LOWER_POWER_FLAG NOT SET\n",
			    ddi_node_name(devi), ddi_get_instance(devi));
		} else if (dstatep->flag & PM_SUPPORTED_FLAG) {
			GEN_DEBUG((CE_CONT,
			    "%s%d: DDI_DETACH: pm_lower_power comp 0 level %d",
			    ddi_node_name(devi), ddi_get_instance(devi),
			    MINPWR));
			if (pm_lower_power(dstatep->dip, 0, MINPWR)
			    != DDI_SUCCESS) {
				cmn_err(CE_WARN, "%s%d: DDI_DETACH:\n\t"
				    "pm_lower_power failed for comp 0 to"
				    " level %d\n", ddi_node_name(devi),
				    ddi_get_instance(devi), MINPWR);

				return (DDI_FAILURE);
			}

			/*
			 * check power level. Issue pm_power_has_changed
			 * if not at MINPWR.
			 */
			mutex_enter(&dstatep->lock);
			level_tmp = dstatep->level[0];
			dstatep->level[0] = MINPWR;
			if (dstatep->level[0] != MINPWR) {
				GEN_DEBUG((CE_NOTE, "%s%d: DDI_DETACH:"
				    " power off via pm_power_has_changed"
				    " instead", ddi_node_name(devi),
				    ddi_get_instance(devi)));
				if (pm_power_has_changed(dstatep->dip,
				    0, MINPWR) != DDI_SUCCESS) {
					GEN_DEBUG((CE_NOTE, "%s%d: DDI_DETACH:"
					    " pm_power_has_changed failed for"
					    " comp 0 to level %d",
					    ddi_node_name(devi),
					    ddi_get_instance(devi),
					    MINPWR));
					dstatep->level[0] = level_tmp;
					mutex_exit(&dstatep->lock);

					return (DDI_FAILURE);
				}
			}
			mutex_exit(&dstatep->lock);
		}

		GEN_DEBUG((CE_CONT,
		    "%s%d detaching: n_devs=%d n_minorcomps=%d isclone=%d",
		    ddi_node_name(devi), ddi_get_instance(devi),
		    n_devs, n_minorcomps, isclone));

		for (i = 0; i < NUMEVENTS; i++) {
			if (dstatep->gen_cb_ids[i]) {
		(void) ddi_remove_event_handler(dstatep->gen_cb_ids[i]);
				dstatep->gen_cb_ids[i] = NULL;
			}
		}

		ddi_prop_remove_all(devi);
		ddi_remove_minor_node(devi, NULL);
		if (dstatep->node_type)
			kmem_free(dstatep->node_type,
			    strlen(dstatep->node_type) + 1);
		ddi_soft_state_free(dstates, instance);
		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		GEN_DEBUG((CE_CONT, "%s%d: DDI_SUSPEND",
		    ddi_node_name(devi), ddi_get_instance(devi)));

		instance = ddi_get_instance(devi);
		dstatep = ddi_get_soft_state(dstates, instance);
		if (dstatep == NULL) {

			return (DDI_FAILURE);
		}

		/*
		 * fail the suspend if FAIL_SUSPEND_FLAG is set.
		 * clear the FAIL_SUSPEND_FLAG flag
		 */
		mutex_enter(&dstatep->lock);
		if (dstatep->flag & FAIL_SUSPEND_FLAG) {
			GEN_DEBUG((CE_CONT, "%s%d: DDI_SUSPEND:"
			    " FAIL_SUSPEND_FLAG is set,"
			    " fail suspend",
			    ddi_node_name(devi), ddi_get_instance(devi)));
			dstatep->flag &= ~FAIL_SUSPEND_FLAG;
			rv = DDI_FAILURE;
		} else {
			rv = DDI_SUCCESS;
		}
		mutex_exit(&dstatep->lock);

		/*
		 * Issue ddi_removing_power() to determine if the suspend
		 * was initiated by either CPR or DR. If CPR, the system
		 * will be powered OFF; if this driver has set the
		 * NO_INVOL_FLAG, then refuse to suspend. If DR, power
		 * will not be removed, thus allow the suspend.
		 */
		if (dstatep->flag & NO_INVOL_FLAG &&
		    dstatep->flag & PM_SUPPORTED_FLAG) {
			GEN_DEBUG((CE_CONT, "%s%d: DDI_SUSPEND:"
			    " check via ddi_removing_power()",
			    ddi_node_name(devi), ddi_get_instance(devi)));

			rm_power = ddi_removing_power(dstatep->dip);

			if (rm_power < 0) {
				cmn_err(CE_WARN, "%s%d: DDI_SUSPEND:"
				    " ddi_removing_power() failed\n",
				    ddi_node_name(devi),
				    ddi_get_instance(devi));
			} else if (rm_power == 1) {
				/*
				 * CPR: power will be removed
				 */
				GEN_DEBUG((CE_CONT, "%s%d: DDI_SUSPEND:\n\t"
				    " CPR: POWER WILL BE REMOVED, THEREFORE"
				    " REFUSE TO SUSPEND", ddi_node_name(devi),
				    ddi_get_instance(devi)));
				rv = DDI_FAILURE;
			} else if (rm_power == 0) {
				/*
				 * DR: power will not be removed
				 */
				GEN_DEBUG((CE_CONT, "%s%d: DDI_SUSPEND:\n\t"
				    " DR: POWER WILL NOT BE REMOVED, THEREFORE"
				    " ALLOW THE SUSPEND", ddi_node_name(devi),
				    ddi_get_instance(devi)));
				rv = DDI_SUCCESS;
			}
		}

		/*
		 * power OFF via pm_power_has_changed()
		 */
		mutex_enter(&dstatep->lock);
		if (dstatep->flag & PM_SUPPORTED_FLAG &&
		    !(dstatep->flag & NO_INVOL_FLAG)) {
			level_tmp = dstatep->level[0];
			dstatep->level[0] = MINPWR;
			GEN_DEBUG((CE_CONT,
			    "%s%d: DDI_SUSPEND: pm_power_has_changed comp 0"
			    " level %d", ddi_node_name(devi),
			    ddi_get_instance(devi), MINPWR));
			if (pm_power_has_changed(dstatep->dip, 0, MINPWR)
			    != DDI_SUCCESS) {
				cmn_err(CE_WARN, "%s%d: DDI_SUSPEND:\n\t"
				    "pm_power_has_changed failed for comp 0 to"
				    " level %d\n", ddi_node_name(devi),
				    ddi_get_instance(devi), MINPWR);
				dstatep->level[0] = level_tmp;
				mutex_exit(&dstatep->lock);

				return (DDI_FAILURE);
			}
		}
		mutex_exit(&dstatep->lock);

		return (rv);

	default:

		return (DDI_FAILURE);
	}
}
コード例 #5
0
ファイル: sgsbbc.c プロジェクト: andreiw/polaris
static int
sbbc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	int			instance;
	sbbc_softstate_t	*softsp;
	uint32_t		*pci_intr_enable_reg;
	int			len;
#ifdef	DEBUG
	char			name[8];
#endif	/* DEBUG */

	instance = ddi_get_instance(devi);

	switch (cmd) {
	case DDI_ATTACH:

		if (ddi_soft_state_zalloc(sbbcp, instance) != 0)
			return (DDI_FAILURE);

		softsp = ddi_get_soft_state(sbbcp, instance);
		softsp->sbbc_instance = instance;

		/*
		 * Set the dip in the soft state
		 * And get interrupt cookies and initialize the
		 * per instance mutex.
		 */
		softsp_init(softsp, devi);


		/*
		 * Verify that an 'interrupts' property exists for
		 * this device. If not, this instance will be ignored.
		 */
		if (ddi_getproplen(DDI_DEV_T_ANY, softsp->dip,
			DDI_PROP_DONTPASS, "interrupts",
			&len) != DDI_PROP_SUCCESS) {
			SBBC_ERR1(CE_WARN, "No 'interrupts' property for the "
					"SBBC instance %d\n", instance);
			return (DDI_FAILURE);
		}
		/*
		 * Add this instance to the sbbc chosen iosram list
		 * so that it can be used for tunnel switch.
		 */
		mutex_enter(&chosen_lock);
		softsp->sbbc_state = SBBC_STATE_INIT;
		sbbc_add_instance(softsp);

		/*
		 * If this is the chosen IOSRAM and there is no master IOSRAM
		 * yet, then let's set this instance as the master.
		 * if there is a master alreay due to the previous tunnel switch
		 * then keep as is even though this is the chosen.
		 */
		if (sgsbbc_iosram_is_chosen(softsp)) {
			ASSERT(master_iosram);
			softsp->iosram = master_iosram;
			master_iosram->sgsbbc = softsp;

			/* Do 'chosen' init only */
			sbbc_chosen_init(softsp);
		}

		mutex_exit(&chosen_lock);
#ifdef	DEBUG
		(void) sprintf(name, "sbbc%d", instance);

		if (ddi_create_minor_node(devi, name, S_IFCHR, instance,
			NULL, NULL) == DDI_FAILURE) {
			mutex_destroy(&softsp->sbbc_lock);
			ddi_remove_minor_node(devi, NULL);
			ddi_soft_state_free(sbbcp, instance);
			return (DDI_FAILURE);
		}
#endif	/* DEBUG */

		ddi_report_dev(devi);

		return (DDI_SUCCESS);

	case DDI_RESUME:

		if (!(softsp = ddi_get_soft_state(sbbcp, instance)))
			return (DDI_FAILURE);

		mutex_enter(&softsp->sbbc_lock);
		if ((softsp->suspended == TRUE) && (softsp->chosen == TRUE)) {
			/*
			 * Enable Interrupts now, turn on both INT#A lines
			 */
			pci_intr_enable_reg =  (uint32_t *)
					((char *)softsp->sbbc_regs +
						SBBC_PCI_INT_ENABLE);

			ddi_put32(softsp->sbbc_reg_handle1,
				pci_intr_enable_reg,
				(uint32_t)SBBC_PCI_ENABLE_INT_A);

			/*
			 * Reset intr_in_enabled to the original value
			 * so the SC can send us interrupt.
			 */
			if (iosram_write(SBBC_SC_INTR_ENABLED_KEY,
				0, (caddr_t)&intr_in_enabled,
				sizeof (intr_in_enabled))) {

				mutex_exit(&softsp->sbbc_lock);
				return (DDI_FAILURE);
			}
		}
		softsp->suspended = FALSE;

		mutex_exit(&softsp->sbbc_lock);

		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}
}
コード例 #6
0
static int ztdummy_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
    struct ztdummy_state *ztd;
    int instance, status;
    char *getdev_name;
    cyc_time_t when;
    cyc_handler_t hdlr;

    switch (cmd) {
    case DDI_RESUME:
        cmn_err(CE_CONT, "ztdummy: Ignoring attach_RESUME");
        return DDI_FAILURE;
    case DDI_PM_RESUME:
        cmn_err(CE_CONT, "ztdummy: Ignoring attach_PM_RESUME");
        return DDI_FAILURE;
    case DDI_ATTACH:
        break;
    default:
        cmn_err(CE_CONT, "ztdummy: unknown attach command %d", cmd);
        return DDI_FAILURE;
    }

    instance = ddi_get_instance(dip);

    if (ddi_soft_state_zalloc(ztdummy_statep, instance) != DDI_SUCCESS)
    {
      cmn_err(CE_CONT, "ztdummy%d: Failed to alloc soft state", instance);
      return DDI_FAILURE;
    }

    /* Get pointer to that memory */
    ztd = ddi_get_soft_state(ztdummy_statep, instance);

    if (ztd == NULL) {
	    cmn_err(CE_CONT, "ztdummy: Unable to allocate memory\n");
	    ddi_soft_state_free(ztdummy_statep, instance);
	    return DDI_FAILURE;
    }

    ztd->dip = dip;

    if (ztdummy_initialize(ztd)) {
		cmn_err(CE_CONT, "ztdummy: Unable to intialize zaptel driver\n");
		ddi_soft_state_free(ztdummy_statep, instance);
		return DDI_FAILURE;
    }

	/*
	 * Setup a high-resolution timer using an undocumented API in the kernel
	 *
	 * For more information visit the URL below:
	 * http://blogs.sun.com/roller/page/eschrock?entry=inside_the_cyclic_subsystem
	 *
	 */
    hdlr.cyh_func = ztdummy_timer;
    hdlr.cyh_arg = 0;
    hdlr.cyh_level = CY_LOW_LEVEL;

    when.cyt_when = 0;
    when.cyt_interval = 1000000; /* every 1ms */

    mutex_enter(&cpu_lock); 
    ztd->cyclic = cyclic_add(&hdlr, &when);
    mutex_exit(&cpu_lock);

    if (debug)
        cmn_err(CE_CONT, "ztdummy: init() finished\n");
    return 0;
}
コード例 #7
0
ファイル: gen_drv.c プロジェクト: andreiw/polaris
static int
gen_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	int instance = ddi_get_instance(devi);
	struct dstate *dstatep;
	int rval;
	int n_devs;
	int n_minorcomps;
	int isclone;
	ddi_eventcookie_t dev_offline_cookie, dev_reset_cookie;
	ddi_eventcookie_t bus_reset_cookie, bus_quiesce_cookie;
	ddi_eventcookie_t bus_unquiesce_cookie, bus_test_post_cookie;
	int i_init = 0;
	int level_tmp;

	int i;
	char *pm_comp[] = {
		"NAME=leaf0",
		"0=D0",
		"1=D1",
		"2=D2",
		"3=D3",
		"NAME=leaf1",
		"0=off",
		"1=blank",
		"2=on"};
	char *pm_hw_state = {"needs-suspend-resume"};


	switch (cmd) {
	case DDI_ATTACH:

		if (ddi_soft_state_zalloc(dstates, instance) !=
		    DDI_SUCCESS) {
			cmn_err(CE_CONT, "%s%d: can't allocate state\n",
			    ddi_get_name(devi), instance);

			return (DDI_FAILURE);
		}

		dstatep = ddi_get_soft_state(dstates, instance);
		dstatep->dip = devi;
		mutex_init(&dstatep->lock, NULL, MUTEX_DRIVER, NULL);

		n_devs = ddi_prop_get_int(DDI_DEV_T_ANY, devi, 0,
		    "ndevs", 1);

		isclone = ddi_prop_get_int(DDI_DEV_T_ANY, devi, 0,
		    "isclone", 0);

		n_minorcomps = ddi_prop_get_int(DDI_DEV_T_ANY, devi, 0,
		    "ncomps", 1);

		GEN_DEBUG((CE_CONT,
		    "%s%d attaching: n_devs=%d n_minorcomps=%d isclone=%d",
		    ddi_get_name(devi), ddi_get_instance(devi),
		    n_devs, n_minorcomps, isclone));

		if (isclone) {
			if (ddi_create_minor_node(devi, "gen", S_IFCHR,
			    INST_TO_MINOR(instance), mnodetypes[0],
			    isclone) != DDI_SUCCESS) {
				ddi_remove_minor_node(devi, NULL);
				ddi_soft_state_free(dstates, instance);
				cmn_err(CE_WARN, "%s%d: can't create minor "
				"node", ddi_get_name(devi), instance);

				return (DDI_FAILURE);
			}
			rval = DDI_SUCCESS;
		} else {
			rval = gen_create_minor_nodes(devi, dstatep);
			if (rval != DDI_SUCCESS) {
				ddi_prop_remove_all(devi);
				ddi_remove_minor_node(devi, NULL);
				ddi_soft_state_free(dstates, instance);
				cmn_err(CE_WARN, "%s%d: can't create minor "
				"nodes", ddi_get_name(devi), instance);

				return (DDI_FAILURE);
			}
		}

		if (ddi_get_eventcookie(devi, "pshot_dev_offline",
		    &dev_offline_cookie) == DDI_SUCCESS) {
			(void) ddi_add_event_handler(devi, dev_offline_cookie,
			    gen_event_cb, NULL, &(dstatep->gen_cb_ids[0]));
		}

		if (ddi_get_eventcookie(devi, "pshot_dev_reset",
		    &dev_reset_cookie) == DDI_SUCCESS) {
			(void) ddi_add_event_handler(devi, dev_reset_cookie,
			    gen_event_cb, NULL, &(dstatep->gen_cb_ids[1]));
		}

		if (ddi_get_eventcookie(devi, "pshot_bus_reset",
		    &bus_reset_cookie) == DDI_SUCCESS) {
			(void) ddi_add_event_handler(devi, bus_reset_cookie,
			    gen_event_cb, NULL, &(dstatep->gen_cb_ids[2]));
		}

		if (ddi_get_eventcookie(devi, "pshot_bus_quiesce",
		    &bus_quiesce_cookie) == DDI_SUCCESS) {
			(void) ddi_add_event_handler(devi, bus_quiesce_cookie,
			    gen_event_cb, NULL, &(dstatep->gen_cb_ids[3]));
		}

		if (ddi_get_eventcookie(devi, "pshot_bus_unquiesce",
		    &bus_unquiesce_cookie) == DDI_SUCCESS) {
			(void) ddi_add_event_handler(devi,
			    bus_unquiesce_cookie, gen_event_cb,
			    NULL, &(dstatep->gen_cb_ids[4]));
		}

		if (ddi_get_eventcookie(devi, "pshot_bus_test_post",
		    &bus_test_post_cookie) == DDI_SUCCESS) {
			(void) ddi_add_event_handler(devi,
			    bus_test_post_cookie, gen_event_cb,
			    NULL, &(dstatep->gen_cb_ids[5]));
		}

		/*
		 * initialize the devices' pm state
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag &= ~OPEN_FLAG;
		dstatep->flag &= ~PWR_HAS_CHANGED_ON_RESUME_FLAG;
		dstatep->flag &= ~FAIL_SUSPEND_FLAG;
		dstatep->flag &= ~PUP_WITH_PWR_HAS_CHANGED_FLAG;
		dstatep->flag |= LOWER_POWER_FLAG;
		dstatep->flag &= ~NO_INVOL_FLAG;
		dstatep->flag |= PM_SUPPORTED_FLAG;
		dstatep->busy[0] = 0;
		dstatep->busy[1] = 0;
		dstatep->level[0] = -1;
		dstatep->level[1] = -1;
		mutex_exit(&dstatep->lock);

		/*
		 * stash the nodename
		 */
		dstatep->nodename = ddi_node_name(devi);

		/*
		 * Check if the no-involuntary-power-cycles property
		 * was created. Set NO_INVOL_FLAG if so.
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, dstatep->dip,
		    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
		    "no-involuntary-power-cycles") == 1) {
			GEN_DEBUG((CE_CONT,
			    "%s%d: DDI_ATTACH:\n\tno-involuntary-power-cycles"
			    " property was created",
			    ddi_node_name(devi), ddi_get_instance(devi)));
			mutex_enter(&dstatep->lock);
			dstatep->flag |= NO_INVOL_FLAG;
			mutex_exit(&dstatep->lock);
		}

		/*
		 * Check if the dependency-property property
		 * was created.
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, dstatep->dip,
		    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
		    "dependency-property") == 1) {
			GEN_DEBUG((CE_CONT,
			    "%s%d: DDI_ATTACH:\n\tdependency-property"
			    " property was created",
			    ddi_node_name(devi), ddi_get_instance(devi)));
		}

		/*
		 * create the pm-components property. two comps:
		 * 4 levels on comp0, 3 on comp 1.
		 * - skip for a "tape" device, clear PM_SUPPORTED_FLAG
		 */
		if (strcmp(ddi_node_name(devi), "tape") != 0) {
			if (ddi_prop_update_string_array(DDI_DEV_T_NONE, devi,
			    "pm-components", pm_comp, 9) != DDI_PROP_SUCCESS) {
				cmn_err(CE_WARN, "%s%d: %s\n",
				    ddi_node_name(devi),
				    ddi_get_instance(devi),
				    "unable to create \"pm-components\" "
				    " property.");

				return (DDI_FAILURE);
			}
		} else {
			mutex_enter(&dstatep->lock);
			dstatep->flag &= ~PM_SUPPORTED_FLAG;
			mutex_exit(&dstatep->lock);
		}

		/*
		 * Check if the pm-components property was created
		 */
		if (dstatep->flag & PM_SUPPORTED_FLAG) {
			if (ddi_prop_exists(DDI_DEV_T_ANY, dstatep->dip,
			    (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM),
			    "pm-components") != 1) {
				cmn_err(CE_WARN, "%s%d: DDI_ATTACH:\n\t%s",
				    ddi_node_name(devi),
				    ddi_get_instance(devi),
				    "\"pm-components\" property does"
				    " not exist");

				return (DDI_FAILURE);

			} else {
				GEN_DEBUG((CE_CONT, "%s%d: DDI_ATTACH:"
				    " created pm-components property",
				    ddi_node_name(devi),
				    ddi_get_instance(devi)));
			}
		}

		/*
		 * create the pm-hardware-state property.
		 * needed to get DDI_SUSPEND and DDI_RESUME calls
		 */
		if (ddi_prop_update_string(DDI_DEV_T_NONE, devi,
		    "pm-hardware-state", pm_hw_state) != DDI_PROP_SUCCESS) {
			cmn_err(CE_WARN, "%s%d: DDI_ATTACH:\n\t%s\n",
			    ddi_node_name(devi), ddi_get_instance(devi),
			    "unable to create \"pm-hardware-state\" "
			    " property.");

			return (DDI_FAILURE);
		}

		/*
		 * set power levels to max via pm_raise_power(),
		 */
		mutex_enter(&dstatep->lock);
		i_init = (dstatep->flag & PM_SUPPORTED_FLAG) ? 0 : COMPONENTS;
		mutex_exit(&dstatep->lock);
		for (i = i_init; i < COMPONENTS; i++) {
			GEN_DEBUG((CE_CONT,
			    "%s%d: DDI_ATTACH: pm_raise_power comp %d "
			    "to level %d", ddi_node_name(devi),
			    ddi_get_instance(devi), i, maxpwr[i]));
			if (pm_raise_power(dstatep->dip, i, maxpwr[i]) !=
			    DDI_SUCCESS) {
				cmn_err(CE_WARN,
				    "%s%d: DDI_ATTACH: pm_raise_power failed\n",
				    ddi_node_name(devi),
				    ddi_get_instance(devi));
				dstatep->level[i] = -1;

				return (DDI_FAILURE);
			}
		}

		if (rval == DDI_SUCCESS) {
			ddi_report_dev(devi);
		}
		return (rval);


	case DDI_RESUME:
		GEN_DEBUG((CE_CONT, "%s%d: DDI_RESUME", ddi_node_name(devi),
		    ddi_get_instance(devi)));

		dstatep = ddi_get_soft_state(dstates, ddi_get_instance(devi));
		if (dstatep == NULL) {

			return (DDI_FAILURE);
		}

		/*
		 * Call pm_power_has_changed() if flag
		 * PWR_HAS_CHANGED_ON_RESUME_FLAG is set,
		 * then clear the flag
		 */
		mutex_enter(&dstatep->lock);
		i_init = (dstatep->flag & PM_SUPPORTED_FLAG) ? 0 : COMPONENTS;
		mutex_exit(&dstatep->lock);
		if (dstatep->flag & PWR_HAS_CHANGED_ON_RESUME_FLAG) {
			for (i = i_init; i < COMPONENTS; i++) {
				GEN_DEBUG((CE_CONT,
				    "%s%d: DDI_RESUME: pm_power_has_changed "
				    "comp %d to level %d", ddi_node_name(devi),
				    ddi_get_instance(devi), i, maxpwr[i]));
				mutex_enter(&dstatep->lock);
				level_tmp = dstatep->level[i];
				dstatep->level[i] = maxpwr[i];
				if (pm_power_has_changed(dstatep->dip, i,
				    maxpwr[i]) != DDI_SUCCESS) {
					cmn_err(CE_WARN,
					    "%s%d: DDI_RESUME:\n\t"
					    " pm_power_has_changed"
					    " failed: comp %d to level %d\n",
					    ddi_node_name(devi),
					    ddi_get_instance(devi),
					    i, maxpwr[i]);
					dstatep->level[i] = level_tmp;
				}
				mutex_exit(&dstatep->lock);
			}
		} else {
			/*
			 * Call pm_raise_power() instead
			 */
			for (i = i_init; i < COMPONENTS; i++) {
				GEN_DEBUG((CE_CONT,
				    "%s%d: DDI_RESUME: pm_raise_power"
				    " comp %d to level %d",
				    ddi_node_name(devi), ddi_get_instance(devi),
				    i, maxpwr[i]));
				if (pm_raise_power(dstatep->dip, i, maxpwr[i])
				    != DDI_SUCCESS) {
					cmn_err(CE_WARN,
					    "%s%d: DDI_RESUME:"
					    "\n\tpm_raise_power"
					    "failed: comp %d to level %d\n",
					    ddi_node_name(devi),
					    ddi_get_instance(devi),
					    i, maxpwr[i]);
				}
			}
		}

		return (DDI_SUCCESS);

	default:
		GEN_DEBUG((CE_WARN, "attach: default"));
		return (DDI_FAILURE);
	}
}
コード例 #8
0
static int VBoxDrvSolarisClose(dev_t Dev, int flag, int otyp, cred_t *cred)
{
    LogFlowFunc(("VBoxDrvSolarisClose: Dev=%#x\n", Dev));

#ifndef USE_SESSION_HASH
    /*
     * Get the session and free the soft state item.
     */
    vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev));
    if (!pState)
    {
        LogRel(("VBoxDrvSolarisClose: no state data for %#x (%d)\n", Dev, getminor(Dev)));
        return EFAULT;
    }

    PSUPDRVSESSION pSession = pState->pSession;
    pState->pSession = NULL;
    ddi_soft_state_free(g_pVBoxDrvSolarisState, getminor(Dev));

    if (!pSession)
    {
        LogRel(("VBoxDrvSolarisClose: no session in state data for %#x (%d)\n", Dev, getminor(Dev)));
        return EFAULT;
    }
    LogFlow(("VBoxDrvSolarisClose: Dev=%#x pSession=%p pid=%d r0proc=%p thread=%p\n",
            Dev, pSession, RTProcSelf(), RTR0ProcHandleSelf(), RTThreadNativeSelf() ));

#else
    const RTPROCESS Process = RTProcSelf();
    const unsigned  iHash = SESSION_HASH(Process);
    PSUPDRVSESSION  pSession;

    /*
     * Remove from the hash table.
     */
    RTSpinlockAcquire(g_Spinlock);
    pSession = g_apSessionHashTab[iHash];
    if (pSession)
    {
        if (pSession->Process == Process)
        {
            g_apSessionHashTab[iHash] = pSession->pNextHash;
            pSession->pNextHash = NULL;
        }
        else
        {
            PSUPDRVSESSION pPrev = pSession;
            pSession = pSession->pNextHash;
            while (pSession)
            {
                if (pSession->Process == Process)
                {
                    pPrev->pNextHash = pSession->pNextHash;
                    pSession->pNextHash = NULL;
                    break;
                }

                /* next */
                pPrev = pSession;
                pSession = pSession->pNextHash;
            }
        }
    }
    RTSpinlockRelease(g_Spinlock);
    if (!pSession)
    {
        LogRel(("VBoxDrvSolarisClose: WHAT?!? pSession == NULL! This must be a mistake... pid=%d (close)\n", (int)Process));
        return EFAULT;
    }
#endif

    /*
     * Close the session.
     */
    supdrvSessionRelease(pSession);
    return 0;
}
コード例 #9
0
/**
 * open() worker.
 */
static int VBoxDrvSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred)
{
    const bool          fUnrestricted = getminor(*pDev) == 0;
    PSUPDRVSESSION      pSession;
    int                 rc;

    LogFlowFunc(("VBoxDrvSolarisOpen: pDev=%p:%#x\n", pDev, *pDev));

    /*
     * Validate input
     */
    if (   (getminor(*pDev) != 0 && getminor(*pDev) != 1)
        || fType != OTYP_CHR)
        return EINVAL; /* See mmopen for precedent. */

#ifndef USE_SESSION_HASH
    /*
     * Locate a new device open instance.
     *
     * For each open call we'll allocate an item in the soft state of the device.
     * The item index is stored in the dev_t. I hope this is ok...
     */
    vbox_devstate_t *pState = NULL;
    unsigned iOpenInstance;
    for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
    {
        if (    !ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance) /* faster */
            &&  ddi_soft_state_zalloc(g_pVBoxDrvSolarisState, iOpenInstance) == DDI_SUCCESS)
        {
            pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance);
            break;
        }
    }
    if (!pState)
    {
        LogRel(("VBoxDrvSolarisOpen: too many open instances.\n"));
        return ENXIO;
    }

    /*
     * Create a new session.
     */
    rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession);
    if (RT_SUCCESS(rc))
    {
        pSession->Uid = crgetruid(pCred);
        pSession->Gid = crgetrgid(pCred);

        pState->pSession = pSession;
        *pDev = makedevice(getmajor(*pDev), iOpenInstance);
        LogFlow(("VBoxDrvSolarisOpen: Dev=%#x pSession=%p pid=%d r0proc=%p thread=%p\n",
                 *pDev, pSession, RTProcSelf(), RTR0ProcHandleSelf(), RTThreadNativeSelf() ));
        return 0;
    }

    /* failed - clean up */
    ddi_soft_state_free(g_pVBoxDrvSolarisState, iOpenInstance);

#else
    /*
     * Create a new session.
     * Sessions in Solaris driver are mostly useless. It's however needed
     * in VBoxDrvSolarisIOCtlSlow() while calling supdrvIOCtl()
     */
    rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession);
    if (RT_SUCCESS(rc))
    {
        unsigned        iHash;

        pSession->Uid = crgetruid(pCred);
        pSession->Gid = crgetrgid(pCred);

        /*
         * Insert it into the hash table.
         */
# error "Only one entry per process!"
        iHash = SESSION_HASH(pSession->Process);
        RTSpinlockAcquire(g_Spinlock);
        pSession->pNextHash = g_apSessionHashTab[iHash];
        g_apSessionHashTab[iHash] = pSession;
        RTSpinlockRelease(g_Spinlock);
        LogFlow(("VBoxDrvSolarisOpen success\n"));
    }

    int instance;
    for (instance = 0; instance < DEVICE_MAXINSTANCES; instance++)
    {
        vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
        if (pState)
            break;
    }

    if (instance >= DEVICE_MAXINSTANCES)
    {
        LogRel(("VBoxDrvSolarisOpen: All instances exhausted\n"));
        return ENXIO;
    }

    *pDev = makedevice(getmajor(*pDev), instance);
#endif

    return VBoxSupDrvErr2SolarisErr(rc);
}
コード例 #10
0
ファイル: acpinex_drv.c プロジェクト: metricinc/illumos-gate
static int
acpinex_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	int instance;
	acpinex_softstate_t *softsp;

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}

	/* Get and check instance number. */
	instance = ddi_get_instance(devi);
	if (instance >= ACPINEX_INSTANCE_MAX) {
		cmn_err(CE_WARN, "acpinex: instance number %d is out of range "
		    "in acpinex_attach(), max %d.",
		    instance, ACPINEX_INSTANCE_MAX - 1);
		return (DDI_FAILURE);
	}

	/* Get soft state structure. */
	if (ddi_soft_state_zalloc(acpinex_softstates, instance)
	    != DDI_SUCCESS) {
		cmn_err(CE_WARN, "!acpinex: failed to allocate soft state "
		    "object in acpinex_attach().");
		return (DDI_FAILURE);
	}
	softsp = ddi_get_soft_state(acpinex_softstates, instance);

	/* Initialize soft state structure */
	softsp->ans_dip = devi;
	(void) ddi_pathname(devi, softsp->ans_path);
	if (ACPI_FAILURE(acpica_get_handle(devi, &softsp->ans_hdl))) {
		ACPINEX_DEBUG(CE_WARN,
		    "!acpinex: failed to get ACPI handle for %s.",
		    softsp->ans_path);
		ddi_soft_state_free(acpinex_softstates, instance);
		return (DDI_FAILURE);
	}
	mutex_init(&softsp->ans_lock, NULL, MUTEX_DRIVER, NULL);

	/* Install event handler for child/descendant objects. */
	if (acpinex_event_scan(softsp, B_TRUE) != DDI_SUCCESS) {
		cmn_err(CE_WARN, "!acpinex: failed to install event handler "
		    "for children of %s.", softsp->ans_path);
	}

	/* nothing to suspend/resume here */
	(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
	    "pm-hardware-state", "no-suspend-resume");
	(void) ddi_prop_update_int(DDI_DEV_T_NONE, devi,
	    DDI_NO_AUTODETACH, 1);

	acpinex_fm_init(softsp);
	ddi_report_dev(devi);

	return (DDI_SUCCESS);
}
コード例 #11
0
ファイル: simmstat.c プロジェクト: mikess/illumos-gate
static int
simmstat_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
    struct simmstat_soft_state *softsp;
    int instance;

    switch (cmd) {
    case DDI_ATTACH:
        break;

    case DDI_RESUME:
        return (DDI_SUCCESS);

    default:
        return (DDI_FAILURE);
    }

    instance = ddi_get_instance(devi);

    if (ddi_soft_state_zalloc(simmstatp, instance) != DDI_SUCCESS)
        return (DDI_FAILURE);

    softsp = ddi_get_soft_state(simmstatp, instance);

    /* Set the dip in the soft state */
    softsp->dip = devi;

    /* Get the board number from this nodes parent device. */
    softsp->pdip = ddi_get_parent(softsp->dip);
    if ((softsp->board = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->pdip,
                                          DDI_PROP_DONTPASS, OBP_BOARDNUM, -1)) == -1) {
        cmn_err(CE_WARN, "simmstat%d: unable to retrieve %s property",
                instance, OBP_BOARDNUM);
        goto bad;
    }

    DPRINTF(SIMMSTAT_ATTACH_DEBUG, ("simmstat%d: devi= 0x%p\n, "
                                    " softsp=0x%p\n", instance, (void *)devi, (void *)softsp));

    /* map in the registers for this device. */
    if (ddi_map_regs(softsp->dip, 0,
                     (caddr_t *)&softsp->simmstat_base, 0, 0)) {
        cmn_err(CE_WARN, "simmstat%d: unable to map registers",
                instance);
        goto bad;
    }

    /* nothing to suspend/resume here */
    (void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
                                  "pm-hardware-state", "no-suspend-resume");

    /* create the kstats for this device */
    simmstat_add_kstats(softsp);

    ddi_report_dev(devi);

    return (DDI_SUCCESS);

bad:
    ddi_soft_state_free(simmstatp, instance);
    return (DDI_FAILURE);
}
コード例 #12
0
/*
 * heci_remove - Device Removal Routine
 *
 * @pdev: PCI device information struct
 *
 * heci_remove is called by the PCI subsystem to alert the driver
 * that it should release a PCI device.
 */
static int
heci_detach(dev_info_t *dip,  ddi_detach_cmd_t cmd)
{
	struct iamt_heci_device	*dev;
	int err;

	dev = ddi_get_soft_state(heci_soft_state_p, ddi_get_instance(dip));
	ASSERT(dev != NULL);

	switch (cmd) {
	case DDI_SUSPEND:
		err = heci_suspend(dip);
		if (err)
			return (DDI_FAILURE);
		else
			return (DDI_SUCCESS);

	case DDI_DETACH:
		break;

	default:
		return (DDI_FAILURE);
	}

	if (dev->wd_timer)
		(void) untimeout(dev->wd_timer);

	mutex_enter(&dev->device_lock);
	if (dev->wd_file_ext.state == HECI_FILE_CONNECTED &&
	    dev->wd_timeout) {
		dev->wd_timeout = 0;
		dev->wd_due_counter = 0;
		(void) memcpy(dev->wd_data, stop_wd_params,
		    HECI_WD_PARAMS_SIZE);
		dev->stop = 1;
		if (dev->host_buffer_is_empty &&
		    flow_ctrl_creds(dev, &dev->wd_file_ext)) {
			dev->host_buffer_is_empty = 0;

			if (!heci_send_wd(dev)) {
				DBG("send stop WD failed\n");
			} else
				flow_ctrl_reduce(dev, &dev->wd_file_ext);

			dev->wd_pending = 0;
		} else
			dev->wd_pending = 1;

		dev->wd_stoped = 0;

		err = 0;
		while (!dev->wd_stoped && err != -1) {
			err = cv_reltimedwait(&dev->wait_stop_wd,
			    &dev->device_lock, 10*HZ, TR_CLOCK_TICK);
		}

		if (!dev->wd_stoped) {
			DBG("stop wd failed to complete.\n");
		} else {
			DBG("stop wd complete.\n");
		}

	}

	mutex_exit(&dev->device_lock);

	if (dev->iamthif_file_ext.state == HECI_FILE_CONNECTED) {
		dev->iamthif_file_ext.state = HECI_FILE_DISCONNECTING;
		(void) heci_disconnect_host_client(dev,
		    &dev->iamthif_file_ext);
	}
	if (dev->wd_file_ext.state == HECI_FILE_CONNECTED) {
		dev->wd_file_ext.state = HECI_FILE_DISCONNECTING;
		(void) heci_disconnect_host_client(dev,
		    &dev->wd_file_ext);
	}


	/* remove entry if already in list */
	DBG("list del iamthif and wd file list.\n");
	heci_remove_client_from_file_list(dev, dev->wd_file_ext.
	    host_client_id);
	heci_remove_client_from_file_list(dev,
	    dev->iamthif_file_ext.host_client_id);

	dev->iamthif_current_cb = NULL;
	dev->iamthif_file_ext.file = NULL;

	/* disable interrupts */
	heci_csr_disable_interrupts(dev);

	ddi_remove_intr(dip, 0, dev->sc_iblk);

	if (dev->work)
		ddi_taskq_destroy(dev->work);
	if (dev->reinit_tsk)
		ddi_taskq_destroy(dev->reinit_tsk);
	if (dev->mem_addr)
		ddi_regs_map_free(&dev->io_handle);

	if (dev->me_clients && dev->num_heci_me_clients > 0) {
		kmem_free(dev->me_clients, sizeof (struct heci_me_client) *
		    dev->num_heci_me_clients);
	}

	dev->num_heci_me_clients = 0;

	heci_destroy_locks(dev);

	ddi_remove_minor_node(dip, NULL);
	ddi_soft_state_free(heci_soft_state_p, ddi_get_instance(dip));

	return (DDI_SUCCESS);
}