Exemplo n.º 1
0
/*
 * wusb_df_detach:
 *	detach or suspend driver instance
 *
 * Note: in detach, only contention threads is from pm and disconnnect.
 */
static int
wusb_df_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	int		instance = ddi_get_instance(dip);
	wusb_df_state_t	*wusb_dfp =
	    ddi_get_soft_state(wusb_df_statep, instance);
	int		rval = DDI_FAILURE;

	switch (cmd) {
	case DDI_DETACH:

		USB_DPRINTF_L4(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
		    "Detach: enter for detach");

		rval = wusb_df_cleanup(dip, wusb_dfp);

		break;
	case DDI_SUSPEND:
		USB_DPRINTF_L4(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
		    "Detach: enter for suspend");

		rval = wusb_df_cpr_suspend(dip);
	default:

		break;
	}

	return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
}
Exemplo n.º 2
0
static void
wusb_df_pm_busy_component(wusb_df_state_t *wusb_dfp)
{
	ASSERT(!mutex_owned(&wusb_dfp->wusb_df_mutex));

	mutex_enter(&wusb_dfp->wusb_df_mutex);
	if (wusb_dfp->wusb_df_pm == NULL) {
		USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
		    "wusb_df_pm_busy_component: pm = NULL");
		goto done;
	}

	wusb_dfp->wusb_df_pm->wusb_df_pm_busy++;
	USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
	    "wusb_df_pm_busy_component: %d",
	    wusb_dfp->wusb_df_pm->wusb_df_pm_busy);

	mutex_exit(&wusb_dfp->wusb_df_mutex);

	if (pm_busy_component(wusb_dfp->wusb_df_dip, 0) != DDI_SUCCESS) {
		mutex_enter(&wusb_dfp->wusb_df_mutex);
		wusb_dfp->wusb_df_pm->wusb_df_pm_busy--;

		USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
		    "wusb_df_pm_busy_component: %d",
		    wusb_dfp->wusb_df_pm->wusb_df_pm_busy);
		mutex_exit(&wusb_dfp->wusb_df_mutex);


	}
	return;
done:
		mutex_exit(&wusb_dfp->wusb_df_mutex);

}
Exemplo n.º 3
0
/* ARGSUSED */
static void
ehci_sendup_itd_message(
	ehci_state_t		*ehcip,
	ehci_pipe_private_t	*pp,
	ehci_isoc_xwrapper_t	*itw,
	ehci_itd_t		*td,
	usb_cr_t		error)
{
	usb_isoc_req_t		*isoc_reqp = itw->itw_curr_xfer_reqp;
	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
	size_t			length;
	uchar_t			*buf;
	mblk_t			*mp;

	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));

	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
	    "ehci_sendup_itd_message:");

	ASSERT(itw != NULL);

	length = itw->itw_length;

	/* Copy the data into the mblk_t */
	buf = (uchar_t *)itw->itw_buf;

	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
	    "ehci_sendup_itd_message: length %d error %d", length, error);

	/* Get the message block */
	mp = isoc_reqp->isoc_data;

	ASSERT(mp != NULL);

	if (length) {
		/* Sync IO buffer */
		Sync_IO_Buffer(itw->itw_dmahandle, length);

		/* Copy the data into the message */
		bcopy(buf, mp->b_rptr, length);

		/* Increment the write pointer */
		mp->b_wptr = mp->b_wptr + length;
	} else {
		USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
		    "ehci_sendup_itd_message: Zero length packet");
	}

	ehci_hcdi_isoc_callback(ph, itw, error);
}
Exemplo n.º 4
0
/*ARGSUSED*/
static int
uftdi_close_port(ds_hdl_t hdl, uint_t portno)
{
	uftdi_state_t *uf = (uftdi_state_t *)hdl;

	USB_DPRINTF_L4(DPRINT_CLOSE, uf->uf_lh, "uftdi_close_port %d", portno);

	ASSERT(portno == 0);

	mutex_enter(&uf->uf_lock);

	/* free resources and finalize state */
	freemsg(uf->uf_rx_mp);
	uf->uf_rx_mp = NULL;

	freemsg(uf->uf_tx_mp);
	uf->uf_tx_mp = NULL;

	uf->uf_port_state = UFTDI_PORT_CLOSED;
	mutex_exit(&uf->uf_lock);

	uftdi_pm_set_idle(uf);

	return (USB_SUCCESS);
}
Exemplo n.º 5
0
static int
uftdi_send_data(uftdi_state_t *uf, mblk_t *data)
{
	usb_bulk_req_t *br;
	int len = MBLKL(data);
	int rval;

	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh,
	    "uftdi_send_data: %d 0x%x 0x%x 0x%x", len, data->b_rptr[0],
	    (len > 1) ? data->b_rptr[1] : 0, (len > 2) ? data->b_rptr[2] : 0);

	ASSERT(!mutex_owned(&uf->uf_lock));

	br = usb_alloc_bulk_req(uf->uf_dip, 0, USB_FLAGS_SLEEP);
	br->bulk_data = data;
	br->bulk_len = len;
	br->bulk_timeout = UFTDI_BULKOUT_TIMEOUT;
	br->bulk_cb = uftdi_bulkout_cb;
	br->bulk_exc_cb = uftdi_bulkout_cb;
	br->bulk_client_private = (usb_opaque_t)uf;
	br->bulk_attributes = USB_ATTRS_AUTOCLEARING;

	rval = usb_pipe_bulk_xfer(uf->uf_bulkout_ph, br, 0);

	if (rval != USB_SUCCESS) {
		USB_DPRINTF_L2(DPRINT_OUT_PIPE, uf->uf_lh,
		    "uftdi_send_data: xfer failed %d", rval);
		br->bulk_data = NULL;
		usb_free_bulk_req(br);
	}

	return (rval);
}
Exemplo n.º 6
0
/*
 * start receiving data
 */
static int
uftdi_rx_start(uftdi_state_t *uf)
{
	usb_bulk_req_t *br;
	int rval;

	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh, "uftdi_rx_start");

	ASSERT(mutex_owned(&uf->uf_lock));

	uf->uf_bulkin_state = UFTDI_PIPE_BUSY;
	mutex_exit(&uf->uf_lock);

	br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_xfer_sz, USB_FLAGS_SLEEP);
	br->bulk_len = uf->uf_xfer_sz;
	br->bulk_timeout = UFTDI_BULKIN_TIMEOUT;
	br->bulk_cb = uftdi_bulkin_cb;
	br->bulk_exc_cb = uftdi_bulkin_cb;
	br->bulk_client_private = (usb_opaque_t)uf;
	br->bulk_attributes = USB_ATTRS_AUTOCLEARING | USB_ATTRS_SHORT_XFER_OK;

	rval = usb_pipe_bulk_xfer(uf->uf_bulkin_ph, br, 0);

	if (rval != USB_SUCCESS) {
		USB_DPRINTF_L2(DPRINT_IN_PIPE, uf->uf_lh,
		    "uftdi_rx_start: xfer failed %d", rval);
		usb_free_bulk_req(br);
	}

	mutex_enter(&uf->uf_lock);
	if (rval != USB_SUCCESS)
		uf->uf_bulkin_state = UFTDI_PIPE_IDLE;

	return (rval);
}
Exemplo n.º 7
0
/*ARGSUSED*/
static void
uftdi_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
{
	uftdi_state_t	*uf = (uftdi_state_t *)req->bulk_client_private;
	int		data_len;
	mblk_t		*data = req->bulk_data;

	data_len = data ? MBLKL(data) : 0;

	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh,
	    "uftdi_bulkout_cb: cr=%d len=%d",
	    req->bulk_completion_reason, data_len);

	if (uf->uf_port_state == UFTDI_PORT_OPEN &&
	    req->bulk_completion_reason && data_len > 0) {
		uftdi_put_head(&uf->uf_tx_mp, data);
		req->bulk_data = NULL;
	}

	usb_free_bulk_req(req);

	/* notify GSD */
	if (uf->uf_cb.cb_tx)
		uf->uf_cb.cb_tx(uf->uf_cb.cb_arg);

	/* send more */
	mutex_enter(&uf->uf_lock);
	uf->uf_bulkout_state = UFTDI_PIPE_IDLE;
	if (uf->uf_tx_mp == NULL)
		cv_broadcast(&uf->uf_tx_cv);
	else
		uftdi_tx_start(uf, NULL);
	mutex_exit(&uf->uf_lock);
}
Exemplo n.º 8
0
static int
uftdi_pwrlvl3(uftdi_state_t *uf)
{
	int rval;

	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pwrlvl3");

	switch (uf->uf_dev_state) {
	case USB_DEV_PWRED_DOWN:
		/* Issue USB D0 command to the device here */
		rval = usb_set_device_pwrlvl0(uf->uf_dip);
		ASSERT(rval == USB_SUCCESS);

		uf->uf_dev_state = USB_DEV_ONLINE;
		uf->uf_pm->pm_cur_power = USB_DEV_OS_FULL_PWR;

		/*FALLTHROUGH*/
	case USB_DEV_ONLINE:
		/* we are already in full power */

		/*FALLTHROUGH*/
	case USB_DEV_DISCONNECTED:
	case USB_DEV_SUSPENDED:
		return (USB_SUCCESS);
	default:
		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh,
		    "uftdi_pwrlvl3: illegal device state");
		return (USB_FAILURE);
	}
}
Exemplo n.º 9
0
/*
 * ehci_reclaim_isoc:
 *
 * "Reclaim" itds that were marked as RECLAIM.
 */
static void
ehci_reclaim_isoc(
	ehci_state_t		*ehcip,
	ehci_isoc_xwrapper_t	*itw,
	ehci_itd_t		*itd,
	ehci_pipe_private_t	*pp)
{
	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
	    "ehci_reclaim_isoc: itd = 0x%p", itd);

	/*
	 * These are itds that were marked "RECLAIM"
	 * by the pipe cleanup.
	 *
	 * Decrement the num_itds and the periodic in
	 * request count if necessary.
	 */
	if ((--itw->itw_num_itds == 0) && (itw->itw_curr_xfer_reqp)) {
		if (itw->itw_direction == USB_EP_DIR_IN) {

			pp->pp_cur_periodic_req_cnt--;

			ehci_deallocate_isoc_in_resource(ehcip, pp, itw);
		} else {
			ehci_hcdi_isoc_callback(pp->pp_pipe_handle, itw,
			    USB_CR_FLUSHED);
		}
	}

	/* Deallocate this transfer descriptor */
	ehci_deallocate_itd(ehcip, itw, itd);
}
Exemplo n.º 10
0
/*ARGSUSED*/
static int
uftdi_fifo_flush(ds_hdl_t hdl, uint_t portno, int dir)
{
	uftdi_state_t *uf = (uftdi_state_t *)hdl;

	ASSERT(portno == 0);

	USB_DPRINTF_L4(DPRINT_CTLOP, uf->uf_lh,
	    "uftdi_fifo_flush: dir=0x%x", dir);

	mutex_enter(&uf->uf_lock);
	ASSERT(uf->uf_port_state == UFTDI_PORT_OPEN);

	if (dir & DS_TX) {
		freemsg(uf->uf_tx_mp);
		uf->uf_tx_mp = NULL;
	}

	if (dir & DS_RX) {
		freemsg(uf->uf_rx_mp);
		uf->uf_rx_mp = NULL;
	}
	mutex_exit(&uf->uf_lock);

	if (dir & DS_TX)
		(void) uftdi_cmd_vendor_write0(uf,
		    FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_TX, uf->uf_hwport);

	if (dir & DS_RX)
		(void) uftdi_cmd_vendor_write0(uf,
		    FTDI_SIO_RESET, FTDI_SIO_RESET_PURGE_RX, uf->uf_hwport);

	return (USB_SUCCESS);
}
Exemplo n.º 11
0
/*
 * ehci_hcdi_get_max_isoc_pkts:
 *
 * Return maximum isochronous packets per usb isochronous request
 */
uint_t
ehci_hcdi_get_max_isoc_pkts(usba_device_t	*usba_device)
{
	ehci_state_t		*ehcip = ehci_obtain_state(
		usba_device->usb_root_hub_dip);
	uint_t			max_isoc_pkts_per_request;
	int			rval;

	mutex_enter(&ehcip->ehci_int_mutex);
	rval = ehci_state_is_operational(ehcip);
	mutex_exit(&ehcip->ehci_int_mutex);

	if (rval != USB_SUCCESS) {

		return (rval);
	}

	max_isoc_pkts_per_request = EHCI_MAX_ISOC_PKTS_PER_XFER;

	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
	    "ehci_hcdi_get_max_isoc_pkts: maximum isochronous"
	    "packets per usb isochronous request = 0x%x",
	    max_isoc_pkts_per_request);

	return (max_isoc_pkts_per_request);
}
Exemplo n.º 12
0
/*ARGSUSED*/
int
ehci_hcdi_pipe_stop_isoc_polling(
	usba_pipe_handle_data_t	*ph,
	usb_flags_t		flags)
{
	ehci_state_t		*ehcip = ehci_obtain_state(
				    ph->p_usba_device->usb_root_hub_dip);
	int			rval;

	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
	    "ehci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x",
	    (void *)ph, flags);

	mutex_enter(&ehcip->ehci_int_mutex);
	rval = ehci_state_is_operational(ehcip);

	if (rval != USB_SUCCESS) {
		mutex_exit(&ehcip->ehci_int_mutex);

		return (rval);
	}

	rval = ehci_stop_periodic_pipe_polling(ehcip, ph, flags);

	mutex_exit(&ehcip->ehci_int_mutex);

	return (rval);
}
Exemplo n.º 13
0
/*
 * Functions to handle power transition for OS levels 0 -> 3
 * The same level as OS state, different from USB state
 */
static int
uftdi_pwrlvl0(uftdi_state_t *uf)
{
	int	rval;

	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pwrlvl0");

	switch (uf->uf_dev_state) {
	case USB_DEV_ONLINE:
		/* issue USB D3 command to the device */
		rval = usb_set_device_pwrlvl3(uf->uf_dip);
		ASSERT(rval == USB_SUCCESS);

		uf->uf_dev_state = USB_DEV_PWRED_DOWN;
		uf->uf_pm->pm_cur_power = USB_DEV_OS_PWR_OFF;

		/*FALLTHROUGH*/
	case USB_DEV_DISCONNECTED:
	case USB_DEV_SUSPENDED:
		/* allow a disconnect/cpr'ed device to go to lower power */
		return (USB_SUCCESS);
	case USB_DEV_PWRED_DOWN:
	default:
		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh,
		    "uftdi_pwrlvl0: illegal device state");
		return (USB_FAILURE);
	}
}
Exemplo n.º 14
0
/*
 * ehci_hcdi_get_current_frame_number:
 *
 * Return the current usb frame number
 */
usb_frame_number_t
ehci_hcdi_get_current_frame_number(usba_device_t	*usba_device)
{
	ehci_state_t		*ehcip = ehci_obtain_state(
		usba_device->usb_root_hub_dip);
	usb_frame_number_t	frame_number;
	int			rval;

	ehcip = ehci_obtain_state(usba_device->usb_root_hub_dip);

	mutex_enter(&ehcip->ehci_int_mutex);
	rval = ehci_state_is_operational(ehcip);

	if (rval != USB_SUCCESS) {
		mutex_exit(&ehcip->ehci_int_mutex);

		return (rval);
	}

	frame_number = ehci_get_current_frame_number(ehcip);

	mutex_exit(&ehcip->ehci_int_mutex);

	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
	    "ehci_hcdi_get_current_frame_number: "
	    "Current frame number 0x%llx", frame_number);

	return (frame_number);
}
Exemplo n.º 15
0
/* ARGSUSED */
int
ehci_hcdi_bulk_transfer_size(
	usba_device_t	*usba_device,
	size_t		*size)
{
	ehci_state_t	*ehcip = ehci_obtain_state(
			    usba_device->usb_root_hub_dip);
	int		rval;

	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
	    "ehci_hcdi_bulk_transfer_size:");

	mutex_enter(&ehcip->ehci_int_mutex);
	rval = ehci_state_is_operational(ehcip);
	mutex_exit(&ehcip->ehci_int_mutex);

	if (rval != USB_SUCCESS) {

		return (rval);
	}

	/* VIA VT6202 may not handle bigger xfers well, workaround. */
	if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) &&
	    (ehci_vt62x2_workaround & EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)) {
		*size = EHCI_VIA_MAX_BULK_XFER_SIZE;
	} else {
		*size = EHCI_MAX_BULK_XFER_SIZE;
	}

	return (USB_SUCCESS);
}
Exemplo n.º 16
0
/* ARGSUSED */
int
ehci_hcdi_pipe_reset(
	usba_pipe_handle_data_t	*ph,
	usb_flags_t		usb_flags)
{
	ehci_state_t		*ehcip = ehci_obtain_state(
				    ph->p_usba_device->usb_root_hub_dip);
	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
	int			error = USB_SUCCESS;

	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
	    "ehci_hcdi_pipe_reset:");

	/*
	 * Check and handle root hub pipe reset.
	 */
	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {

		error = ehci_handle_root_hub_pipe_reset(ph, usb_flags);
		return (error);
	}

	mutex_enter(&ehcip->ehci_int_mutex);

	/* Set pipe state to pipe reset */
	pp->pp_state = EHCI_PIPE_STATE_RESET;

	ehci_pipe_cleanup(ehcip, ph);

	mutex_exit(&ehcip->ehci_int_mutex);

	return (error);
}
Exemplo n.º 17
0
/*
 * ehci_insert_isoc_req:
 *
 * Insert an isochronous request into the Host Controller's
 * isochronous list.
 */
int
ehci_insert_isoc_req(
	ehci_state_t			*ehcip,
	ehci_pipe_private_t		*pp,
	ehci_isoc_xwrapper_t		*itw,
	usb_flags_t			usb_flags)
{
	int			error;

	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
	    "ehci_insert_isoc_req: flags = 0x%x port status = 0x%x",
	    usb_flags, itw->itw_port_status);

	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));

	ASSERT(itw->itw_curr_xfer_reqp != NULL);
	ASSERT(itw->itw_curr_xfer_reqp->isoc_pkt_descr != NULL);

	/*
	 * Save address of first usb isochronous packet descriptor.
	 */
	itw->itw_curr_isoc_pktp = itw->itw_curr_xfer_reqp->isoc_pkt_descr;

	if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) {
		error = USB_NOT_SUPPORTED;
	} else {
		error = ehci_insert_sitd_req(ehcip, pp, itw, usb_flags);
	}

	return (error);
}
Exemplo n.º 18
0
/*
 * wusb_df_disconnect_callback:
 *	Called when device hotplug-removed.
 *		Close pipes. (This does not attempt to contact device.)
 *		Set state to DISCONNECTED
 */
static int
wusb_df_disconnect_callback(dev_info_t *dip)
{
	int instance = ddi_get_instance(dip);
	wusb_df_state_t	*wusb_dfp =
	    ddi_get_soft_state(wusb_df_statep, instance);


	USB_DPRINTF_L4(PRINT_MASK_CB, wusb_dfp->wusb_df_log_hdl,
	    "disconnect: enter");

	mutex_enter(&wusb_dfp->wusb_df_mutex);
	(void) wusb_df_serialize_access(wusb_dfp, WUSB_DF_SER_NOSIG);

	/*
	 * Save any state of device or IO in progress required by
	 * wusb_df_restore_device_state for proper device "thawing" later.
	 */
	wusb_dfp->wusb_df_dev_state = USB_DEV_DISCONNECTED;

	wusb_df_release_access(wusb_dfp);
	mutex_exit(&wusb_dfp->wusb_df_mutex);

	return (USB_SUCCESS);
}
Exemplo n.º 19
0
/*
 * wusb_df_init_power_mgmt:
 *	Initialize power management and remote wakeup functionality.
 *	No mutex is necessary in this function as it's called only by attach.
 */
static void
wusb_df_init_power_mgmt(wusb_df_state_t *wusb_dfp)
{
	wusb_df_power_t *wusb_dfpm;
	uint_t		pwr_states;

	USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
	    "init_power_mgmt enter");

	/*
	 * If remote wakeup is not available you may not want to do
	 * power management.
	 */
	/* Allocate the state structure */
	wusb_dfpm = kmem_zalloc(sizeof (wusb_df_power_t), KM_SLEEP);
	wusb_dfp->wusb_df_pm = wusb_dfpm;
	wusb_dfpm->wusb_df_state = wusb_dfp;
	wusb_dfpm->wusb_df_pm_capabilities = 0;
	wusb_dfpm->wusb_df_current_power = USB_DEV_OS_FULL_PWR;

	if (usb_create_pm_components(wusb_dfp->wusb_df_dip, &pwr_states) ==
	    USB_SUCCESS) {

		USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
		    "wusb_df_init_power_mgmt: created PM components");

		wusb_dfpm->wusb_df_pwr_states = (uint8_t)pwr_states;
		(void) pm_raise_power(wusb_dfp->wusb_df_dip, 0,
		    USB_DEV_OS_FULL_PWR);

		if (usb_handle_remote_wakeup(wusb_dfp->wusb_df_dip,
		    USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) {
			wusb_dfpm->wusb_df_wakeup_enabled = 1;
		} else {
			USB_DPRINTF_L2(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
			    "wusb_df_init_power_mgmt:"
			    "fail to enable remote wakeup");
		}

	} else {
		USB_DPRINTF_L2(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
		    "wusb_df_init_power_mgmt: create_pm_compts failed");
	}
	USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
	    "wusb_df_init_power_mgmt: end");

}
Exemplo n.º 20
0
/*
 * ds_reconnect
 */
static int
uftdi_reconnect(ds_hdl_t hdl)
{
	uftdi_state_t *uf = (uftdi_state_t *)hdl;

	USB_DPRINTF_L4(DPRINT_HOTPLUG, uf->uf_lh, "uftdi_reconnect");
	return (uftdi_restore_device_state(uf));
}
Exemplo n.º 21
0
/*ARGSUSED*/
int
usb_set_device_pwrlvl3(dev_info_t *dip)
{
	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
	    "usb_set_device_pwrlvl3 : Not Yet Implemented");

	return (USB_SUCCESS);
}
Exemplo n.º 22
0
static int
uftdi_pwrlvl2(uftdi_state_t *uf)
{
	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pwrlvl2");

	/* issue USB D1 command to the device */
	(void) usb_set_device_pwrlvl1(uf->uf_dip);
	return (USB_FAILURE);
}
Exemplo n.º 23
0
/*
 * usb device driver unregistration
 */
void
usb_unregister_dev_driver(dev_info_t *dip)
{
	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
	    "usb_unregister_dev_driver: unregister the registered "
	    "driver: dip =0x%p", (void *)dip);

	ASSERT(dip == usb_cap.dip);
	usb_cap.dip = NULL;
	usb_cap.usba_dev_driver_cb = NULL;
}
Exemplo n.º 24
0
/*
 * ehci_hcdi_pipe_bulk_xfer:
 */
int
ehci_hcdi_pipe_bulk_xfer(
	usba_pipe_handle_data_t	*ph,
	usb_bulk_req_t		*bulk_reqp,
	usb_flags_t		usb_flags)
{
	ehci_state_t		*ehcip = ehci_obtain_state(
				    ph->p_usba_device->usb_root_hub_dip);
	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
	int			rval, error = USB_SUCCESS;
	ehci_trans_wrapper_t	*tw;

	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
	    "ehci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = %x",
	    (void *)ph, bulk_reqp, usb_flags);

	mutex_enter(&ehcip->ehci_int_mutex);
	rval = ehci_state_is_operational(ehcip);

	if (rval != USB_SUCCESS) {
		mutex_exit(&ehcip->ehci_int_mutex);

		return (rval);
	}

	/*
	 *  Check whether pipe is in halted state.
	 */
	if (pp->pp_state == EHCI_PIPE_STATE_ERROR) {

		USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
		    "ehci_hcdi_pipe_bulk_xfer:"
		    "Pipe is in error state, need pipe reset to continue");

		mutex_exit(&ehcip->ehci_int_mutex);

		return (USB_FAILURE);
	}

	/* Allocate a transfer wrapper */
	if ((tw = ehci_allocate_bulk_resources(ehcip, pp, bulk_reqp,
	    usb_flags)) == NULL) {

		error = USB_NO_RESOURCES;
	} else {
		/* Add the QTD into the Host Controller's bulk list */
		ehci_insert_bulk_req(ehcip, ph, bulk_reqp, tw, usb_flags);
	}

	mutex_exit(&ehcip->ehci_int_mutex);

	return (error);
}
Exemplo n.º 25
0
/* USBA framework initializations */
void
usba_usbai_initialization()
{
	usbai_log_handle = usb_alloc_log_hdl(NULL, "usbai", &usbai_errlevel,
	    &usbai_errmask, NULL, 0);

	USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
	    "usba_usbai_initialization");

	mutex_init(&usba_print_mutex, NULL, MUTEX_DRIVER, NULL);
	mutex_init(&usbai_mutex, NULL, MUTEX_DRIVER, NULL);
}
Exemplo n.º 26
0
/*
 * ehci_hcdi_isoc_callback:
 *
 * Convenience wrapper around usba_hcdi_cb() other than root hub.
 */
void
ehci_hcdi_isoc_callback(
	usba_pipe_handle_data_t	*ph,
	ehci_isoc_xwrapper_t	*itw,
	usb_cr_t		completion_reason)
{
	ehci_state_t		*ehcip = ehci_obtain_state(
				    ph->p_usba_device->usb_root_hub_dip);
	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
	usb_opaque_t		curr_xfer_reqp;
	uint_t			pipe_state = 0;

	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
	    "ehci_hcdi_isoc_callback: ph = 0x%p, itw = 0x%p, cr = 0x%x",
	    (void *)ph, itw, completion_reason);

	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));

	/* Set the pipe state as per completion reason */
	switch (completion_reason) {
	case USB_CR_OK:
		pipe_state = pp->pp_state;
		break;
	case USB_CR_NO_RESOURCES:
	case USB_CR_NOT_SUPPORTED:
	case USB_CR_PIPE_RESET:
	case USB_CR_STOPPED_POLLING:
		pipe_state = EHCI_PIPE_STATE_IDLE;
		break;
	case USB_CR_PIPE_CLOSING:
		break;
	}

	pp->pp_state = pipe_state;

	if (itw && itw->itw_curr_xfer_reqp) {
		curr_xfer_reqp = (usb_opaque_t)itw->itw_curr_xfer_reqp;
		itw->itw_curr_xfer_reqp = NULL;
	} else {
		ASSERT(pp->pp_client_periodic_in_reqp != NULL);

		curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
		pp->pp_client_periodic_in_reqp = NULL;
	}

	ASSERT(curr_xfer_reqp != NULL);

	mutex_exit(&ehcip->ehci_int_mutex);

	usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason);

	mutex_enter(&ehcip->ehci_int_mutex);
}
Exemplo n.º 27
0
/*
 * ehci_isoc_pipe_cleanup
 *
 * Cleanup ehci isoc pipes.
 */
void ehci_isoc_pipe_cleanup(
	ehci_state_t		*ehcip,
	usba_pipe_handle_data_t *ph) {
	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
	uint_t			pipe_state = pp->pp_state;
	usb_cr_t		completion_reason;

	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
	    "ehci_isoc_pipe_cleanup: ph = 0x%p", (void *)ph);

	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));

	/* Stop all further processing */
	ehci_mark_reclaim_isoc(ehcip, pp);

	/*
	 * Wait for processing all completed transfers
	 * and send result upstream/
	 */
	ehci_wait_for_isoc_completion(ehcip, pp);

	/* Go ahead and remove all remaining itds if there are any */
	ehci_remove_isoc_itds(ehcip, pp);

	switch (pipe_state) {
	case EHCI_PIPE_STATE_CLOSE:
		completion_reason = USB_CR_PIPE_CLOSING;
		break;
	case EHCI_PIPE_STATE_RESET:
	case EHCI_PIPE_STATE_STOP_POLLING:
		/* Set completion reason */
		completion_reason = (pipe_state ==
		    EHCI_PIPE_STATE_RESET) ?
		    USB_CR_PIPE_RESET: USB_CR_STOPPED_POLLING;

		/* Set pipe state to idle */
		pp->pp_state = EHCI_PIPE_STATE_IDLE;

		break;
	}

	/*
	 * Do the callback for the original client
	 * periodic IN request.
	 */
	if ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) ==
	    USB_EP_DIR_IN) {

		ehci_do_client_periodic_in_req_callback(
		    ehcip, pp, completion_reason);
	}
}
Exemplo n.º 28
0
/*
 * wusb_df_destroy_power_mgmt:
 *	Shut down and destroy power management and remote wakeup functionality.
 */
static void
wusb_df_destroy_power_mgmt(wusb_df_state_t *wusb_dfp)
{
	USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
	    "destroy_power_mgmt enter");

	ASSERT(!mutex_owned(&wusb_dfp->wusb_df_mutex));

	mutex_enter(&wusb_dfp->wusb_df_mutex);
	if (!wusb_dfp->wusb_df_pm) {
		mutex_exit(&wusb_dfp->wusb_df_mutex);
		return;
	}
	mutex_exit(&wusb_dfp->wusb_df_mutex);

	(void) wusb_df_pm_busy_component(wusb_dfp);

	mutex_enter(&wusb_dfp->wusb_df_mutex);
	if (wusb_dfp->wusb_df_dev_state != USB_DEV_DISCONNECTED) {

		if (wusb_dfp->wusb_df_pm->wusb_df_wakeup_enabled) {
			mutex_exit(&wusb_dfp->wusb_df_mutex);

			(void) pm_raise_power(wusb_dfp->wusb_df_dip, 0,
			    USB_DEV_OS_FULL_PWR);
			if (usb_handle_remote_wakeup(wusb_dfp->wusb_df_dip,
			    USB_REMOTE_WAKEUP_DISABLE) != USB_SUCCESS) {
				USB_DPRINTF_L2(PRINT_MASK_PM,
				    wusb_dfp->wusb_df_log_hdl,
				    "wusb_df_destroy_power_mgmt: "
				    "Error disabling rmt wakeup");
			}
			mutex_enter(&wusb_dfp->wusb_df_mutex);

		}
	}
	mutex_exit(&wusb_dfp->wusb_df_mutex);

	/*
	 * Since remote wakeup is disabled now,
	 * no one can raise power
	 * and get to device once power is lowered here.
	 */
	(void) pm_lower_power(wusb_dfp->wusb_df_dip, 0, USB_DEV_OS_PWR_OFF);
	wusb_df_pm_idle_component(wusb_dfp);

	mutex_enter(&wusb_dfp->wusb_df_mutex);
	kmem_free(wusb_dfp->wusb_df_pm, sizeof (wusb_df_power_t));
	wusb_dfp->wusb_df_pm = NULL;
	mutex_exit(&wusb_dfp->wusb_df_mutex);
}
Exemplo n.º 29
0
/*
 * wusb_df_cpr_suspend:
 *	Clean up device.
 *	Wait for any IO to finish, then close pipes.
 *	Quiesce device.
 */
static int
wusb_df_cpr_suspend(dev_info_t *dip)
{
	int		instance = ddi_get_instance(dip);
	wusb_df_state_t	*wusb_dfp =
	    ddi_get_soft_state(wusb_df_statep, instance);

	USB_DPRINTF_L4(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
	    "suspend enter");

	/* Serialize to prevent races with detach, open, device access. */
	mutex_enter(&wusb_dfp->wusb_df_mutex);
	(void) wusb_df_serialize_access(wusb_dfp, WUSB_DF_SER_NOSIG);
	mutex_exit(&wusb_dfp->wusb_df_mutex);

	wusb_df_pm_busy_component(wusb_dfp);

	mutex_enter(&wusb_dfp->wusb_df_mutex);

	/* Access device here to clean it up. */

	wusb_dfp->wusb_df_dev_state = USB_DEV_SUSPENDED;

	/*
	 * Save any state of device required by wusb_df_restore_device_state
	 * for proper device "thawing" later.
	 */

	wusb_df_release_access(wusb_dfp);
	mutex_exit(&wusb_dfp->wusb_df_mutex);

	wusb_df_pm_idle_component(wusb_dfp);

	USB_DPRINTF_L4(PRINT_MASK_ATTA, wusb_dfp->wusb_df_log_hdl,
	    "suspend: success");

	return (USB_SUCCESS);
}
/*
 * scsa2usb_handle_status_start:
 *	Receive status data
 */
static int
scsa2usb_handle_status_start(scsa2usb_state_t *scsa2usbp,
    usb_bulk_req_t *req)
{
	int rval;

	USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
	    "scsa2usb_handle_status_start: req = 0x%p", (void *)req);

	ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex));

	/* setup up for receiving CSW */
#ifdef	SCSA2USB_BULK_ONLY_TEST
	req->bulk_attributes = 0;
#else
	req->bulk_attributes = USB_ATTRS_SHORT_XFER_OK;
#endif	/* SCSA2USB_BULK_ONLY_TEST */
	req->bulk_len = CSW_LEN;

	SCSA2USB_FREE_MSG(req->bulk_data);
	req->bulk_data = allocb_wait(req->bulk_len,
	    BPRI_LO, STR_NOSIG, NULL);

	/* Issue the request */
	mutex_exit(&scsa2usbp->scsa2usb_mutex);

	ASSERT(req->bulk_timeout);
	rval = usb_pipe_bulk_xfer(scsa2usbp->scsa2usb_bulkin_pipe, req,
	    USB_FLAGS_SLEEP);
	mutex_enter(&scsa2usbp->scsa2usb_mutex);

	USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle,
	    "scsa2usb_handle_status_start: END rval = 0x%x", rval);

	if (rval != USB_SUCCESS) {
		if (scsa2usbp->scsa2usb_pkt_state == SCSA2USB_PKT_PROCESS_CSW) {
			scsa2usb_bulk_only_reset_recovery(scsa2usbp);

			return (rval);
		}

		if (req->bulk_completion_reason == USB_CR_STALL) {
			(void) scsa2usb_clear_ept_stall(scsa2usbp,
			    scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress,
			    scsa2usbp->scsa2usb_bulkin_pipe, "bulk-in");
		}
	}

	return (rval);
}