コード例 #1
0
/*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);
	}
}
コード例 #2
0
ファイル: logi.c プロジェクト: andreiw/polaris
/*ARGSUSED*/
static int
logiattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	int unit;
	struct driver_minor_data *dmdp;
	struct strmseinfo *logiptr = 0;

#ifdef LOGI_DEBUG
	if (logi_debug) {
		PRF("logiattach entry\n");
	}
#endif
	switch (cmd) {
	case DDI_ATTACH:
		unit = ddi_get_instance(dip);

		for (dmdp = logi_minor_data; dmdp->name != NULL; dmdp++) {
			if (ddi_create_minor_node(dip, dmdp->name, dmdp->type,
			    dmdp->minor, DDI_PSEUDO, NULL) == DDI_FAILURE) {

				ddi_remove_minor_node(dip, NULL);
				ddi_prop_remove_all(dip);
#ifdef LOGI_DEBUG
				if (logi_debug)
					PRF("logiattach: "
					    "ddi_create_minor_node failed\n");
#endif
				return (DDI_FAILURE);
			}
		}
		logiunits[unit] = dip;
		/* allocate and initialize state structure */
		logiptr = kmem_zalloc(sizeof (struct strmseinfo), KM_SLEEP);
		logiptr->state = 0;	/* not opened */
		ddi_set_driver_private(dip, logiptr);


		if (ddi_add_intr(dip, (uint_t)0, &logiptr->iblock,
		    (ddi_idevice_cookie_t *)0, logiintr,
		    (caddr_t)logiptr) != DDI_SUCCESS) {

#ifdef LOGI_DEBUG
			if (logi_debug)
				PRF("logiattach: ddi_add_intr failed\n");
#endif
			cmn_err(CE_WARN, "logi: cannot add intr\n");
			return (DDI_FAILURE);
		}

		mutex_init(&logiptr->lock, NULL, MUTEX_DRIVER,
		    (void *)logiptr->iblock);
		ddi_report_dev(dip);
		return (DDI_SUCCESS);
	default:
		return (DDI_FAILURE);
	}
}
コード例 #3
0
ファイル: logi.c プロジェクト: andreiw/polaris
/*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);
	}
}
コード例 #4
0
/*
 * wusb_df_cleanup:
 *	clean up the driver state for detach
 */
static int
wusb_df_cleanup(dev_info_t *dip, wusb_df_state_t *wusb_dfp)
{

	USB_DPRINTF_L3(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
	    "Cleanup: enter");

	if (wusb_dfp->wusb_df_locks_initialized) {

		/* This must be done 1st to prevent more events from coming. */
		usb_unregister_hotplug_cbs(dip);

		/*
		 * At this point, no new activity can be initiated. The driver
		 * has disabled hotplug callbacks. The Solaris framework has
		 * disabled new opens on a device being detached, and does not
		 * allow detaching an open device.
		 *
		 * The following ensures that all driver activity has drained.
		 */
		mutex_enter(&wusb_dfp->wusb_df_mutex);
		(void) wusb_df_serialize_access(wusb_dfp, WUSB_DF_SER_NOSIG);
		wusb_df_release_access(wusb_dfp);
		mutex_exit(&wusb_dfp->wusb_df_mutex);

		/* All device activity has died down. */
		wusb_df_destroy_power_mgmt(wusb_dfp);

		/* start dismantling */
		ddi_remove_minor_node(dip, NULL);

		cv_destroy(&wusb_dfp->wusb_df_serial_cv);
		mutex_destroy(&wusb_dfp->wusb_df_mutex);
	}

	usb_client_detach(dip, wusb_dfp->wusb_df_reg);

	usb_free_log_hdl(wusb_dfp->wusb_df_log_hdl);

	if (wusb_dfp->wusb_df_devinst != NULL) {
		kmem_free(wusb_dfp->wusb_df_devinst,
		    strlen(wusb_dfp->wusb_df_devinst) + 1);
	}

	ddi_soft_state_free(wusb_df_statep, ddi_get_instance(dip));
	ddi_prop_remove_all(dip);

	return (USB_SUCCESS);
}
コード例 #5
0
/*
 * cpunex_bus_ctl()
 *    This routine implements nexus bus ctl operations. Of importance are
 *    DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD
 *    and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup
 *    reg property on the child node and builds and sets the name.
 */
static int
cpunex_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
    void *result)
{
	switch (op) {
		case DDI_CTLOPS_REPORTDEV: {
			dev_info_t *pdip = ddi_get_parent(rdip);
			cmn_err(CE_CONT, "?%s%d at %s%d",
			    ddi_node_name(rdip), ddi_get_instance(rdip),
			    ddi_node_name(pdip), ddi_get_instance(pdip));
			return (DDI_SUCCESS);
		}

		case DDI_CTLOPS_INITCHILD: {
			dev_info_t *cdip = (dev_info_t *)arg;
			int i;
			char caddr[MAXNAMELEN];

			i = ddi_prop_get_int(DDI_DEV_T_ANY, cdip,
			    DDI_PROP_DONTPASS, "reg", -1);

			if (i == -1) {
				cmn_err(CE_NOTE, "!%s(%d): \"reg\" property "
				    "not found", ddi_node_name(cdip),
				    ddi_get_instance(cdip));
				return (DDI_NOT_WELL_FORMED);
			}

			(void) sprintf(caddr, "%d", i);
			ddi_set_name_addr(cdip, caddr);

			return (DDI_SUCCESS);
		}

		case DDI_CTLOPS_UNINITCHILD: {
			ddi_prop_remove_all((dev_info_t *)arg);
			ddi_set_name_addr((dev_info_t *)arg, NULL);
			return (DDI_SUCCESS);
		}

		default: {
			return (ddi_ctlops(dip, rdip, op, arg, result));
		}
	}
}
コード例 #6
0
ファイル: simmstat.c プロジェクト: mikess/illumos-gate
/* ARGSUSED */
static int
simmstat_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
    int instance;
    struct simmstat_soft_state *softsp;

    /* get the instance of this devi */
    instance = ddi_get_instance(devi);

    /* get the soft state pointer for this device node */
    softsp = ddi_get_soft_state(simmstatp, instance);

    switch (cmd) {
    case DDI_SUSPEND:
        return (DDI_SUCCESS);

    case DDI_DETACH:
        (void) fhc_bdlist_lock(softsp->board);
        if (fhc_bd_detachable(softsp->board))
            break;
        else
            fhc_bdlist_unlock();
    /* FALLTHROUGH */

    default:
        return (DDI_FAILURE);
    }

    fhc_bdlist_unlock();

    /* remove the kstat for this board */
    kstat_delete(softsp->simmstat_ksp);

    /* unmap the registers */
    ddi_unmap_regs(softsp->dip, 0,
                   (caddr_t *)&softsp->simmstat_base, 0, 0);

    /* free up the soft state */
    ddi_soft_state_free(simmstatp, instance);
    ddi_prop_remove_all(devi);

    return (DDI_SUCCESS);
}
コード例 #7
0
ファイル: kbad.c プロジェクト: max123/deadbeef
static int
kbad_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	int instance;
	register kbad_devstate_t *rsp;

	switch (cmd) {

	case DDI_DETACH:
		ddi_prop_remove_all(dip);
		instance = ddi_get_instance(dip);
		rsp = ddi_get_soft_state(kbad_state, instance);
		ddi_remove_minor_node(dip, NULL);
		ddi_soft_state_free(kbad_state, instance);
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}
}
コード例 #8
0
ファイル: pppt.c プロジェクト: madhavsuresh/illumos-gate
/*ARGSUSED*/
static int
pppt_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	if (cmd != DDI_DETACH)
		return (DDI_FAILURE);

	PPPT_GLOBAL_LOCK();
	if (pppt_drv_busy()) {
		PPPT_GLOBAL_UNLOCK();
		return (EBUSY);
	}

	ddi_remove_minor_node(dip, NULL);
	ddi_prop_remove_all(dip);

	pppt_global.global_svc_state = PSS_DETACHED;

	PPPT_GLOBAL_UNLOCK();

	return (DDI_SUCCESS);
}
コード例 #9
0
/*
 * detach entry point:
 */
static int
acebus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	int instance = ddi_get_instance(dip);
	ebus_devstate_t *ebus_p = get_acebus_soft_state(instance);

	switch (cmd) {
	case DDI_DETACH:
		DBG1(D_DETACH, ebus_p, "DDI_DETACH dip=%p\n", dip);
		ddi_prop_remove_all(dip);
		kmem_free(ebus_p->rangep, ebus_p->range_cnt *
		    sizeof (struct ebus_pci_rangespec));
		free_acebus_soft_state(instance);
		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		DBG1(D_DETACH, ebus_p, "DDI_SUSPEND dip=%p\n", dip);
		ebus_p->state = SUSPENDED;
		return (DDI_SUCCESS);
	}
	return (DDI_FAILURE);
}
コード例 #10
0
/**
 * 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).
 *
 * @return  corresponding solaris error code.
 */
static int VBoxDrvSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd)
{
    LogFlowFunc(("VBoxDrvSolarisDetach\n"));
    switch (enmCmd)
    {
        case DDI_DETACH:
        {
#ifndef USE_SESSION_HASH
            ddi_remove_minor_node(pDip, NULL);
#else
            int instance = ddi_get_instance(pDip);
            vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance);
            ddi_remove_minor_node(pDip, NULL);
            ddi_soft_state_free(g_pVBoxDrvSolarisState, instance);
#endif
            ddi_prop_remove_all(pDip);
            return DDI_SUCCESS;
        }

        case DDI_SUSPEND:
        {
#if 0
            RTSemFastMutexRequest(g_DevExt.mtxGip);
            if (g_DevExt.pGipTimer && g_DevExt.cGipUsers > 0)
                RTTimerStop(g_DevExt.pGipTimer);

            RTSemFastMutexRelease(g_DevExt.mtxGip);
#endif
            RTPowerSignalEvent(RTPOWEREVENT_SUSPEND);
            LogFlow(("vboxdrv: Falling to suspend mode.\n"));
            return DDI_SUCCESS;

        }

        default:
            return DDI_FAILURE;
    }
}
コード例 #11
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);
	}
}
コード例 #12
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);
	}
}
コード例 #13
0
ファイル: gen_drv.c プロジェクト: andreiw/polaris
static int
gen_create_minor_nodes(dev_info_t *devi, struct dstate *dstatep)
{
	int rval = DDI_SUCCESS;
	char *node_name;

	node_name = ddi_node_name(devi);

	if (strcmp(node_name, "disk_chan") == 0) {
		rval = gen_create_mn_disk_chan(devi);
	} else if (strcmp(node_name, "disk_wwn") == 0) {
		rval = gen_create_mn_disk_wwn(devi);
	} else if (strcmp(node_name, "disk_cdrom") == 0) {
		rval = gen_create_mn_disk_cdrom(devi);
	} else if (strcmp(node_name, "disk_fd") == 0) {
		rval = gen_create_mn_disk_fd(devi);
	} else if (strcmp(node_name, "cgtwenty") == 0) {
		rval = gen_create_display(devi);
	} else if (strcmp(node_name, "genzs") == 0) {
		rval = gen_create_serial(devi);
	} else if (strcmp(node_name, "net") == 0) {
		rval = gen_create_net(devi);
	} else {
		int instance = ddi_get_instance(devi);
		char *node_type;

		/*
		 * Solaris may directly hang the node_type off the minor node
		 * (without making a copy).  Since we free the node_type
		 * property below we need to make a private copy to pass
		 * to ddi_create_minor_node to avoid devinfo snapshot panics.
		 * We store a pointer to our copy in dstate and free it in
		 * gen_detach after the minor nodes have been deleted by
		 * ddi_remove_minor_node.
		 */
		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi,
		    DDI_PROP_DONTPASS, "node-type", &node_type) != 0) {
			cmn_err(CE_WARN, "couldn't get node-type\n");
			return (DDI_FAILURE);
		}
		if (node_type) {
			dstatep->node_type = kmem_alloc(
			    strlen(node_type) + 1, KM_SLEEP);
			(void) strcpy(dstatep->node_type, node_type);
		}
		ddi_prop_free(node_type);

		/* the minor name is the same as the node name */
		if (ddi_create_minor_node(devi, node_name, S_IFCHR,
		    (INST_TO_MINOR(instance)), dstatep->node_type, NULL) !=
		    DDI_SUCCESS) {
			if (dstatep->node_type) {
				kmem_free(dstatep->node_type,
				    strlen(dstatep->node_type) + 1);
				dstatep->node_type = NULL;
			}
			return (DDI_FAILURE);
		}
		return (DDI_SUCCESS);
	}

	if (rval != DDI_SUCCESS) {
		ddi_prop_remove_all(devi);
		ddi_remove_minor_node(devi, NULL);
	}

	return (rval);
}
コード例 #14
0
ファイル: nx1394.c プロジェクト: andreiw/polaris
/*
 * nx1394_bus_ctl()
 *    This routine implements nexus bus ctl operations. Of importance are
 *    DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD
 *    and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup
 *    reg property on the child node and builds and sets the name
 *    (name is of the form GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA], where
 *    GGGGGGGGGGGGGGGG is the GUID and AAAAAAAAAAAA is the optional unit
 *    address).
 */
static int
nx1394_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
    void *result)
{
	int status;

	TNF_PROBE_0_DEBUG(nx1394_bus_ctl_enter, S1394_TNF_SL_NEXUS_STACK, "");

	switch (op) {
	case DDI_CTLOPS_REPORTDEV: {
		dev_info_t *pdip = ddi_get_parent(rdip);
		cmn_err(CE_CONT, "?%s%d at %s%d",
		    ddi_node_name(rdip), ddi_get_instance(rdip),
		    ddi_node_name(pdip), ddi_get_instance(pdip));
		TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "");
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_INITCHILD: {
		dev_info_t *ocdip, *cdip = (dev_info_t *)arg;
		dev_info_t *pdip = ddi_get_parent(cdip);
		int reglen, i;
		uint32_t *regptr;
		char addr[MAXNAMELEN];

		TNF_PROBE_1(nx1394_bus_ctl_init_child,
		    S1394_TNF_SL_HOTPLUG_STACK, "", tnf_opaque, dip, cdip);

		i = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
		    DDI_PROP_DONTPASS, "reg", (int **)&regptr,
		    (uint_t *)&reglen);

		if (i != DDI_PROP_SUCCESS) {
			cmn_err(CE_NOTE, "!%s(%d): \"reg\" property not found",
			    ddi_node_name(cdip), ddi_get_instance(cdip));
			TNF_PROBE_2(nx1394_bus_ctl,
			    S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
			    "Reg property not found", tnf_int, reason, i);
			TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
			    S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
			    "initchild");
			return (DDI_NOT_WELL_FORMED);
		}

		ASSERT(reglen != 0);

		/*
		 * addr is of the format GGGGGGGGGGGGGGGG[,AAAAAAAAAAAA]
		 */
		if (regptr[2] || regptr[3]) {
			(void) sprintf(addr, "%08x%08x,%04x%08x", regptr[0],
			    regptr[1], regptr[2], regptr[3]);
		} else {
			(void) sprintf(addr, "%08x%08x", regptr[0], regptr[1]);
		}
		ddi_prop_free(regptr);
		ddi_set_name_addr(cdip, addr);

		/*
		 * Check for a node with the same name & addr as the current
		 * node. If such a node exists, return failure.
		 */
		if ((ocdip = ndi_devi_find(pdip, ddi_node_name(cdip), addr)) !=
		    NULL && ocdip != cdip) {
			cmn_err(CE_NOTE,
			    "!%s(%d): Duplicate dev_info node found %s@%s",
			    ddi_node_name(cdip), ddi_get_instance(cdip),
			    ddi_node_name(ocdip), addr);
			TNF_PROBE_1(nx1394_bus_ctl,
			    S1394_TNF_SL_NEXUS_ERROR, "", tnf_string, msg,
			    "Duplicate nodes");
			TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
			    S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op,
			    "initchild");
			ddi_set_name_addr(cdip, NULL);
			return (DDI_NOT_WELL_FORMED);
		}

		/*
		 * If HAL (parent dip) has "active-dma-flush" property, then
		 * add property to child as well.  Workaround for active
		 * context flushing bug in Schizo rev 2.1 and 2.2.
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
		    "active-dma-flush") != 0) {
			status = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
			    "active-dma-flush", 1);
			if (status != NDI_SUCCESS) {
				cmn_err(CE_NOTE, "!%s(%d): Unable to add "
				    "\"active-dma-flush\" property",
				    ddi_node_name(cdip),
				    ddi_get_instance(cdip));
				TNF_PROBE_1(nx1394_bus_ctl,
				    S1394_TNF_SL_NEXUS_ERROR, "", tnf_string,
				    msg, "Unable to add \"active-dma-flush\" "
				    "property");
				TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
				    S1394_TNF_SL_NEXUS_STACK, "", tnf_string,
				    op, "initchild");
				ddi_set_name_addr(cdip, NULL);
				return (DDI_NOT_WELL_FORMED);
			}
		}

		TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit,
		    S1394_TNF_SL_NEXUS_STACK, "", tnf_string, op, "initchild");
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_UNINITCHILD: {
		ddi_prop_remove_all((dev_info_t *)arg);
		ddi_set_name_addr((dev_info_t *)arg, NULL);
		TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "", tnf_string, op, "uninitchild");
		return (DDI_SUCCESS);
	}

	case DDI_CTLOPS_IOMIN: {
		status = ddi_ctlops(dip, rdip, op, arg, result);
		TNF_PROBE_1_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "", tnf_string, op, "iomin");
		return (status);
	}

	case DDI_CTLOPS_POWER: {
		return (DDI_SUCCESS);
	}

	/*
	 * These ops correspond to functions that "shouldn't" be called
	 * by a 1394 client driver.
	 */
	case DDI_CTLOPS_DMAPMAPC:
	case DDI_CTLOPS_REPORTINT:
	case DDI_CTLOPS_REGSIZE:
	case DDI_CTLOPS_NREGS:
	case DDI_CTLOPS_SIDDEV:
	case DDI_CTLOPS_SLAVEONLY:
	case DDI_CTLOPS_AFFINITY:
	case DDI_CTLOPS_POKE:
	case DDI_CTLOPS_PEEK: {
		cmn_err(CE_CONT, "!%s(%d): invalid op (%d) from %s(%d)",
		    ddi_node_name(dip), ddi_get_instance(dip),
		    op, ddi_node_name(rdip), ddi_get_instance(rdip));
		TNF_PROBE_2(nx1394_bus_ctl, S1394_TNF_SL_NEXUS_ERROR, "",
		    tnf_string, msg, "invalid op", tnf_int, op, op);
		TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "");
		return (DDI_FAILURE);
	}

	/*
	 * Everything else (e.g. PTOB/BTOP/BTOPR requests) we pass up
	 */
	default: {
		status = ddi_ctlops(dip, rdip, op, arg, result);
		TNF_PROBE_0_DEBUG(nx1394_bus_ctl_exit, S1394_TNF_SL_NEXUS_STACK,
		    "");
		return (status);
	}
	}
}