xref: /onnv-gate/usr/src/uts/common/io/usb/hwa/hwahc/hwahc_util.c (revision 11066:cebb50cbe4f9)
19430SRaymond.Chen@Sun.COM /*
29430SRaymond.Chen@Sun.COM  * CDDL HEADER START
39430SRaymond.Chen@Sun.COM  *
49430SRaymond.Chen@Sun.COM  * The contents of this file are subject to the terms of the
59430SRaymond.Chen@Sun.COM  * Common Development and Distribution License (the "License").
69430SRaymond.Chen@Sun.COM  * You may not use this file except in compliance with the License.
79430SRaymond.Chen@Sun.COM  *
89430SRaymond.Chen@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99430SRaymond.Chen@Sun.COM  * or http://www.opensolaris.org/os/licensing.
109430SRaymond.Chen@Sun.COM  * See the License for the specific language governing permissions
119430SRaymond.Chen@Sun.COM  * and limitations under the License.
129430SRaymond.Chen@Sun.COM  *
139430SRaymond.Chen@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
149430SRaymond.Chen@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159430SRaymond.Chen@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
169430SRaymond.Chen@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
179430SRaymond.Chen@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
189430SRaymond.Chen@Sun.COM  *
199430SRaymond.Chen@Sun.COM  * CDDL HEADER END
209430SRaymond.Chen@Sun.COM  */
219430SRaymond.Chen@Sun.COM /*
229430SRaymond.Chen@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
239430SRaymond.Chen@Sun.COM  * Use is subject to license terms.
249430SRaymond.Chen@Sun.COM  */
259430SRaymond.Chen@Sun.COM 
269430SRaymond.Chen@Sun.COM /*
279430SRaymond.Chen@Sun.COM  * The Data Transfer Interface driver for Host Wire Adapter device
289430SRaymond.Chen@Sun.COM  *
299430SRaymond.Chen@Sun.COM  * This file mainly contains the entries for HCDI interfaces.
309430SRaymond.Chen@Sun.COM  */
319430SRaymond.Chen@Sun.COM #include <sys/usb/usba/usba_impl.h> /* usba_get_dip */
329430SRaymond.Chen@Sun.COM #include <sys/usb/hwa/hwahc/hwahc.h>
339430SRaymond.Chen@Sun.COM #include <sys/usb/hwa/hwahc/hwahc_util.h>
349430SRaymond.Chen@Sun.COM #include <sys/strsubr.h>
359430SRaymond.Chen@Sun.COM #include <sys/strsun.h> /* MBLKL */
369430SRaymond.Chen@Sun.COM 
379430SRaymond.Chen@Sun.COM #define	WUSB_GTK 1
389430SRaymond.Chen@Sun.COM #define	WUSB_PTK 2
399430SRaymond.Chen@Sun.COM 
409430SRaymond.Chen@Sun.COM /* function prototypes */
419430SRaymond.Chen@Sun.COM static int hwahc_state_is_operational(hwahc_state_t *hwahcp);
429430SRaymond.Chen@Sun.COM static hwahc_state_t *hwahc_obtain_state(dev_info_t *dip);
439430SRaymond.Chen@Sun.COM static void hwahc_wait_for_xfer_completion(hwahc_state_t *hwahcp,
449430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t *pp);
459430SRaymond.Chen@Sun.COM static void hwahc_traverse_requests(hwahc_state_t *hwahcp,
469430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t *pp);
479430SRaymond.Chen@Sun.COM static void hwahc_pipe_cleanup(hwahc_state_t *hwahcp,
489430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t *ph);
499430SRaymond.Chen@Sun.COM int hwahc_set_dev_encrypt(usb_pipe_handle_t ph, uint8_t ifc,
509430SRaymond.Chen@Sun.COM 	usb_port_t index, wusb_secrt_data_t *secrt_data, uint8_t type);
519430SRaymond.Chen@Sun.COM 
529430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pm_support(dev_info_t *dip);
539430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_open(usba_pipe_handle_data_t *ph,
549430SRaymond.Chen@Sun.COM 	usb_flags_t flags);
559430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_close(usba_pipe_handle_data_t *ph,
569430SRaymond.Chen@Sun.COM 	usb_flags_t flags);
579430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_reset(usba_pipe_handle_data_t *ph,
589430SRaymond.Chen@Sun.COM 	usb_flags_t flags);
599430SRaymond.Chen@Sun.COM static void hwahc_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t *ph);
609430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_ctrl_xfer(usba_pipe_handle_data_t *ph,
619430SRaymond.Chen@Sun.COM 	usb_ctrl_req_t *ctrl_reqp, usb_flags_t usb_flags);
629430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t *ph,
639430SRaymond.Chen@Sun.COM 	usb_bulk_req_t *bulk_reqp, usb_flags_t usb_flags);
649430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_intr_xfer(usba_pipe_handle_data_t *ph,
659430SRaymond.Chen@Sun.COM 	usb_intr_req_t *intr_reqp, usb_flags_t usb_flags);
669430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_isoc_xfer(usba_pipe_handle_data_t *ph,
679430SRaymond.Chen@Sun.COM 	usb_isoc_req_t *isoc_reqp, usb_flags_t usb_flags);
689430SRaymond.Chen@Sun.COM static int hwahc_hcdi_bulk_transfer_size(usba_device_t *usba_device,
699430SRaymond.Chen@Sun.COM 	size_t *size);
709430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_stop_intr_polling(usba_pipe_handle_data_t *ph,
719430SRaymond.Chen@Sun.COM 	usb_flags_t flags);
729430SRaymond.Chen@Sun.COM static int hwahc_hcdi_pipe_stop_isoc_polling(usba_pipe_handle_data_t *ph,
739430SRaymond.Chen@Sun.COM 	usb_flags_t flags);
749430SRaymond.Chen@Sun.COM static int hwahc_hcdi_get_current_frame_number(usba_device_t *usba_device,
759430SRaymond.Chen@Sun.COM 	usb_frame_number_t *frame_number);
769430SRaymond.Chen@Sun.COM static int hwahc_hcdi_get_max_isoc_pkts(usba_device_t *usba_device,
779430SRaymond.Chen@Sun.COM 	uint_t *max_pkts);
789430SRaymond.Chen@Sun.COM static int hwahc_hcdi_polled_input_init(usba_pipe_handle_data_t *ph,
799430SRaymond.Chen@Sun.COM 	uchar_t **polled_buf, usb_console_info_impl_t *console_input_info);
809430SRaymond.Chen@Sun.COM static int hwahc_hcdi_polled_input_fini(usb_console_info_impl_t *info);
819430SRaymond.Chen@Sun.COM static int hwahc_hcdi_polled_input_enter(usb_console_info_impl_t *info);
829430SRaymond.Chen@Sun.COM static int hwahc_hcdi_polled_input_exit(usb_console_info_impl_t *info);
839430SRaymond.Chen@Sun.COM static int hwahc_hcdi_polled_read(usb_console_info_impl_t *info,
849430SRaymond.Chen@Sun.COM 	uint_t *num_characters);
859430SRaymond.Chen@Sun.COM usba_hcdi_ops_t *hwahc_alloc_hcdi_ops(hwahc_state_t *hwahcp);
869430SRaymond.Chen@Sun.COM 
879430SRaymond.Chen@Sun.COM extern void *hwahc_statep;
889430SRaymond.Chen@Sun.COM 
899430SRaymond.Chen@Sun.COM /* Check the Host controller state and return proper values */
909430SRaymond.Chen@Sun.COM static int
hwahc_state_is_operational(hwahc_state_t * hwahcp)919430SRaymond.Chen@Sun.COM hwahc_state_is_operational(hwahc_state_t *hwahcp)
929430SRaymond.Chen@Sun.COM {
939430SRaymond.Chen@Sun.COM 	int	rval;
949430SRaymond.Chen@Sun.COM 
959430SRaymond.Chen@Sun.COM 	ASSERT(mutex_owned(&hwahcp->hwahc_mutex));
969430SRaymond.Chen@Sun.COM 
979430SRaymond.Chen@Sun.COM 	if (hwahcp->hwahc_dev_state != USB_DEV_ONLINE) {
989430SRaymond.Chen@Sun.COM 
999430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
1009430SRaymond.Chen@Sun.COM 	}
1019430SRaymond.Chen@Sun.COM 
1029430SRaymond.Chen@Sun.COM 	switch (hwahcp->hwahc_hc_soft_state) {
1039430SRaymond.Chen@Sun.COM 	case HWAHC_CTRL_INIT_STATE:
1049430SRaymond.Chen@Sun.COM 		rval = USB_FAILURE;
1059430SRaymond.Chen@Sun.COM 		break;
1069430SRaymond.Chen@Sun.COM 	case HWAHC_CTRL_OPERATIONAL_STATE:
1079430SRaymond.Chen@Sun.COM 		/* still need to check if channel is operational */
1089430SRaymond.Chen@Sun.COM 		if (hwahcp->hwahc_hw_state != HWAHC_HW_STARTED) {
1099430SRaymond.Chen@Sun.COM 			rval = USB_FAILURE;
1109430SRaymond.Chen@Sun.COM 		} else {
1119430SRaymond.Chen@Sun.COM 			rval = USB_SUCCESS;
1129430SRaymond.Chen@Sun.COM 		}
1139430SRaymond.Chen@Sun.COM 
1149430SRaymond.Chen@Sun.COM 		break;
1159430SRaymond.Chen@Sun.COM 	case HWAHC_CTRL_ERROR_STATE:
1169430SRaymond.Chen@Sun.COM 		rval = USB_HC_HARDWARE_ERROR;
1179430SRaymond.Chen@Sun.COM 		break;
1189430SRaymond.Chen@Sun.COM 	default:
1199430SRaymond.Chen@Sun.COM 		rval = USB_FAILURE;
1209430SRaymond.Chen@Sun.COM 		break;
1219430SRaymond.Chen@Sun.COM 	}
1229430SRaymond.Chen@Sun.COM 
1239430SRaymond.Chen@Sun.COM 	return (rval);
1249430SRaymond.Chen@Sun.COM }
1259430SRaymond.Chen@Sun.COM 
1269430SRaymond.Chen@Sun.COM /* get soft state pointer */
1279430SRaymond.Chen@Sun.COM hwahc_state_t *
hwahc_obtain_state(dev_info_t * dip)1289430SRaymond.Chen@Sun.COM hwahc_obtain_state(dev_info_t *dip)
1299430SRaymond.Chen@Sun.COM {
1309430SRaymond.Chen@Sun.COM 	int instance = ddi_get_instance(dip);
1319430SRaymond.Chen@Sun.COM 
1329430SRaymond.Chen@Sun.COM 	hwahc_state_t *hwahcp = ddi_get_soft_state(hwahc_statep, instance);
1339430SRaymond.Chen@Sun.COM 
1349430SRaymond.Chen@Sun.COM 	ASSERT(hwahcp != NULL);
1359430SRaymond.Chen@Sun.COM 
1369430SRaymond.Chen@Sun.COM 	return (hwahcp);
1379430SRaymond.Chen@Sun.COM }
1389430SRaymond.Chen@Sun.COM 
1399430SRaymond.Chen@Sun.COM 
1409430SRaymond.Chen@Sun.COM /*
1419430SRaymond.Chen@Sun.COM  * Do not support wusb bus PM now
1429430SRaymond.Chen@Sun.COM  */
1439430SRaymond.Chen@Sun.COM /* ARGSUSED */
1449430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pm_support(dev_info_t * dip)1459430SRaymond.Chen@Sun.COM hwahc_hcdi_pm_support(dev_info_t *dip)
1469430SRaymond.Chen@Sun.COM {
1479430SRaymond.Chen@Sun.COM 	return (USB_FAILURE);
1489430SRaymond.Chen@Sun.COM }
1499430SRaymond.Chen@Sun.COM 
1509430SRaymond.Chen@Sun.COM static void
1519430SRaymond.Chen@Sun.COM /* ARGSUSED */
hwahc_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t * ph)1529430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t *ph)
1539430SRaymond.Chen@Sun.COM {
1549430SRaymond.Chen@Sun.COM 	/* don't do anything now */
1559430SRaymond.Chen@Sun.COM }
1569430SRaymond.Chen@Sun.COM 
1579430SRaymond.Chen@Sun.COM /* Wait for processing all completed transfers and to send results */
1589430SRaymond.Chen@Sun.COM static void
hwahc_wait_for_xfer_completion(hwahc_state_t * hwahcp,hwahc_pipe_private_t * pp)1599430SRaymond.Chen@Sun.COM hwahc_wait_for_xfer_completion(hwahc_state_t *hwahcp, hwahc_pipe_private_t *pp)
1609430SRaymond.Chen@Sun.COM {
1619430SRaymond.Chen@Sun.COM 	wusb_wa_rpipe_hdl_t	*hdl = pp->pp_rp;
1629430SRaymond.Chen@Sun.COM 
1639430SRaymond.Chen@Sun.COM 	mutex_enter(&hdl->rp_mutex);
1649430SRaymond.Chen@Sun.COM 	if (hdl->rp_state != WA_RPIPE_STATE_ACTIVE) {
1659430SRaymond.Chen@Sun.COM 		mutex_exit(&hdl->rp_mutex);
1669430SRaymond.Chen@Sun.COM 
1679430SRaymond.Chen@Sun.COM 		return;
1689430SRaymond.Chen@Sun.COM 	}
1699430SRaymond.Chen@Sun.COM 	mutex_exit(&hdl->rp_mutex);
1709430SRaymond.Chen@Sun.COM 
1719430SRaymond.Chen@Sun.COM 	/* wait 3s */
172*11066Srafael.vanoni@sun.com 	(void) cv_reltimedwait(&pp->pp_xfer_cmpl_cv, &hwahcp->hwahc_mutex,
173*11066Srafael.vanoni@sun.com 	    drv_usectohz(3000000), TR_CLOCK_TICK);
1749430SRaymond.Chen@Sun.COM 
1759430SRaymond.Chen@Sun.COM 	mutex_enter(&hdl->rp_mutex);
1769430SRaymond.Chen@Sun.COM 	if (hdl->rp_state == WA_RPIPE_STATE_ACTIVE) {
1779430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1789430SRaymond.Chen@Sun.COM 		    "hwahc_wait_for_xfer_completion: no transfer completion "
1799430SRaymond.Chen@Sun.COM 		    "confirmation received");
1809430SRaymond.Chen@Sun.COM 	}
1819430SRaymond.Chen@Sun.COM 	mutex_exit(&hdl->rp_mutex);
1829430SRaymond.Chen@Sun.COM }
1839430SRaymond.Chen@Sun.COM 
1849430SRaymond.Chen@Sun.COM /* remove all the unprocessed requests and do callback */
1859430SRaymond.Chen@Sun.COM /* ARGSUSED */
1869430SRaymond.Chen@Sun.COM static void
hwahc_traverse_requests(hwahc_state_t * hwahcp,hwahc_pipe_private_t * pp)1879430SRaymond.Chen@Sun.COM hwahc_traverse_requests(hwahc_state_t *hwahcp, hwahc_pipe_private_t *pp)
1889430SRaymond.Chen@Sun.COM {
1899430SRaymond.Chen@Sun.COM 	wusb_wa_rpipe_hdl_t	*hdl = pp->pp_rp;
1909430SRaymond.Chen@Sun.COM 	wusb_wa_trans_wrapper_t	*wr;
1919430SRaymond.Chen@Sun.COM 
1929430SRaymond.Chen@Sun.COM 	mutex_enter(&hdl->rp_mutex);
1939430SRaymond.Chen@Sun.COM 
1949430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1959430SRaymond.Chen@Sun.COM 	    "hwahc_traverse_requests: pp = 0x%p, wr=%p", (void*)pp,
1969430SRaymond.Chen@Sun.COM 	    (void *)hdl->rp_curr_wr);
1979430SRaymond.Chen@Sun.COM 
1989430SRaymond.Chen@Sun.COM 	wr = hdl->rp_curr_wr;
1999430SRaymond.Chen@Sun.COM 	if (wr != NULL) {
2009430SRaymond.Chen@Sun.COM 		wusb_wa_stop_xfer_timer(wr);
2019430SRaymond.Chen@Sun.COM 		hdl->rp_state = WA_RPIPE_STATE_IDLE;
2029430SRaymond.Chen@Sun.COM 		hdl->rp_curr_wr = NULL;
2039430SRaymond.Chen@Sun.COM 		wr->wr_state = WR_ABORTED;
2049430SRaymond.Chen@Sun.COM 		mutex_exit(&hdl->rp_mutex);
2059430SRaymond.Chen@Sun.COM 
2069430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
2079430SRaymond.Chen@Sun.COM 
2089430SRaymond.Chen@Sun.COM 		/*
2099430SRaymond.Chen@Sun.COM 		 * This CR is to tell USBA to mark this pipe as IDLE,
2109430SRaymond.Chen@Sun.COM 		 * so that do not queue client requests at USBA. Requests
2119430SRaymond.Chen@Sun.COM 		 * sent after pipe close/reset will be handled by hwahc.
2129430SRaymond.Chen@Sun.COM 		 */
2139430SRaymond.Chen@Sun.COM 		wr->wr_cb(wr->wr_wa_data, wr, USB_CR_NOT_SUPPORTED, 0);
2149430SRaymond.Chen@Sun.COM 
2159430SRaymond.Chen@Sun.COM 		mutex_enter(&hwahcp->hwahc_mutex);
2169430SRaymond.Chen@Sun.COM 		mutex_enter(&hdl->rp_mutex);
2179430SRaymond.Chen@Sun.COM 	}
2189430SRaymond.Chen@Sun.COM 	mutex_exit(&hdl->rp_mutex);
2199430SRaymond.Chen@Sun.COM }
2209430SRaymond.Chen@Sun.COM 
2219430SRaymond.Chen@Sun.COM /* process periodic(INTR/ISOC) requests */
2229430SRaymond.Chen@Sun.COM static void
hwahc_do_client_periodic_in_req_callback(hwahc_state_t * hwahcp,hwahc_pipe_private_t * pp,usb_cr_t completion_reason)2239430SRaymond.Chen@Sun.COM hwahc_do_client_periodic_in_req_callback(hwahc_state_t *hwahcp,
2249430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t *pp, usb_cr_t completion_reason)
2259430SRaymond.Chen@Sun.COM {
2269430SRaymond.Chen@Sun.COM 	usb_ep_descr_t	*eptd;
2279430SRaymond.Chen@Sun.COM 
2289430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
2299430SRaymond.Chen@Sun.COM 	    "hwahc_do_client_periodic_in_req_callback: enter");
2309430SRaymond.Chen@Sun.COM 
2319430SRaymond.Chen@Sun.COM 	/*
2329430SRaymond.Chen@Sun.COM 	 * Check for Interrupt/Isochronous IN, whether we need to do
2339430SRaymond.Chen@Sun.COM 	 * callback for the original client's periodic IN request.
2349430SRaymond.Chen@Sun.COM 	 */
2359430SRaymond.Chen@Sun.COM 	eptd = &(pp->pp_pipe_handle->p_ep);
2369430SRaymond.Chen@Sun.COM 	if (pp->pp_client_periodic_in_reqp) {
2379430SRaymond.Chen@Sun.COM 		if (WUSB_ISOC_ENDPOINT(eptd)) {
2389430SRaymond.Chen@Sun.COM 			/* not supported */
2399430SRaymond.Chen@Sun.COM 			USB_DPRINTF_L4(PRINT_MASK_HCDI,
2409430SRaymond.Chen@Sun.COM 			    hwahcp->hwahc_log_handle,
2419430SRaymond.Chen@Sun.COM 			    "hwahc_do_client_periodic_in_req_callback: "
2429430SRaymond.Chen@Sun.COM 			    "ISOC xfer not support");
2439430SRaymond.Chen@Sun.COM 		} else {
2449430SRaymond.Chen@Sun.COM 			/*
2459430SRaymond.Chen@Sun.COM 			 * NULL wr to tell the function that we're done and
2469430SRaymond.Chen@Sun.COM 			 * should clear pipe's pp_client_periodic_in_reqp
2479430SRaymond.Chen@Sun.COM 			 */
2489430SRaymond.Chen@Sun.COM 			wusb_wa_callback(&hwahcp->hwahc_wa_data,
2499430SRaymond.Chen@Sun.COM 			    pp->pp_pipe_handle, NULL, completion_reason);
2509430SRaymond.Chen@Sun.COM 		}
2519430SRaymond.Chen@Sun.COM 	}
2529430SRaymond.Chen@Sun.COM 
2539430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
2549430SRaymond.Chen@Sun.COM 	    "hwahc_do_client_periodic_in_req_callback: end");
2559430SRaymond.Chen@Sun.COM }
2569430SRaymond.Chen@Sun.COM 
2579430SRaymond.Chen@Sun.COM /*
2589430SRaymond.Chen@Sun.COM  * clean up the pipe, called by pipe_close/pipe_reset
2599430SRaymond.Chen@Sun.COM  *	- Abort RPipe operation
2609430SRaymond.Chen@Sun.COM  *	- Clean pending requests queueing on this pipe
2619430SRaymond.Chen@Sun.COM  */
2629430SRaymond.Chen@Sun.COM static void
hwahc_pipe_cleanup(hwahc_state_t * hwahcp,usba_pipe_handle_data_t * ph)2639430SRaymond.Chen@Sun.COM hwahc_pipe_cleanup(hwahc_state_t *hwahcp, usba_pipe_handle_data_t *ph)
2649430SRaymond.Chen@Sun.COM {
2659430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
2669430SRaymond.Chen@Sun.COM 	wusb_wa_rpipe_hdl_t	*hdl;
2679430SRaymond.Chen@Sun.COM 	int			rval;
2689430SRaymond.Chen@Sun.COM 	usb_ep_descr_t		*eptd;
2699430SRaymond.Chen@Sun.COM 	usb_cr_t		completion_reason;
2709430SRaymond.Chen@Sun.COM 
2719430SRaymond.Chen@Sun.COM 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
2729430SRaymond.Chen@Sun.COM 
2739430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
2749430SRaymond.Chen@Sun.COM 	    "hwahc_pipe_cleanup: ph = 0x%p, p_req_cnt, ep=0x%02x,"
2759430SRaymond.Chen@Sun.COM 	    " state=%d", (void *) ph, ph->p_ep.bEndpointAddress,
2769430SRaymond.Chen@Sun.COM 	    pp->pp_state);
2779430SRaymond.Chen@Sun.COM 
2789430SRaymond.Chen@Sun.COM 	ASSERT(mutex_owned(&hwahcp->hwahc_mutex));
2799430SRaymond.Chen@Sun.COM 	ASSERT(!servicing_interrupt());
2809430SRaymond.Chen@Sun.COM 
2819430SRaymond.Chen@Sun.COM 	hdl = pp->pp_rp;
2829430SRaymond.Chen@Sun.COM 
2839430SRaymond.Chen@Sun.COM 	if (hwahcp->hwahc_dev_state == USB_DEV_ONLINE) {
2849430SRaymond.Chen@Sun.COM 		/* abort rpipe */
2859430SRaymond.Chen@Sun.COM 		mutex_enter(&hdl->rp_mutex);
2869430SRaymond.Chen@Sun.COM 
2879430SRaymond.Chen@Sun.COM 		/* if active, abort the requests */
2889430SRaymond.Chen@Sun.COM 		if (hdl->rp_state == WA_RPIPE_STATE_ACTIVE) {
2899797SRaymond.Chen@Sun.COM 			mutex_exit(&hdl->rp_mutex);
2909797SRaymond.Chen@Sun.COM 			mutex_exit(&hwahcp->hwahc_mutex);
2919430SRaymond.Chen@Sun.COM 			rval = wusb_wa_rpipe_abort(hwahcp->hwahc_dip,
2929430SRaymond.Chen@Sun.COM 			    hwahcp->hwahc_default_pipe, hdl);
2939797SRaymond.Chen@Sun.COM 			mutex_enter(&hwahcp->hwahc_mutex);
2949797SRaymond.Chen@Sun.COM 			mutex_enter(&hdl->rp_mutex);
2959430SRaymond.Chen@Sun.COM 		}
2969430SRaymond.Chen@Sun.COM 		mutex_exit(&hdl->rp_mutex);
2979430SRaymond.Chen@Sun.COM 
2989430SRaymond.Chen@Sun.COM 		/* wait for transfers to complete */
2999430SRaymond.Chen@Sun.COM 		hwahc_wait_for_xfer_completion(hwahcp, pp);
3009430SRaymond.Chen@Sun.COM 	}
3019430SRaymond.Chen@Sun.COM 
3029430SRaymond.Chen@Sun.COM 	/* remove all unprocessed requests on this pipe and do callback */
3039430SRaymond.Chen@Sun.COM 	hwahc_traverse_requests(hwahcp, pp);
3049430SRaymond.Chen@Sun.COM 
3059430SRaymond.Chen@Sun.COM 	switch (pp->pp_state) {
3069430SRaymond.Chen@Sun.COM 	case HWAHC_PIPE_STATE_CLOSE:
3079430SRaymond.Chen@Sun.COM 		completion_reason = USB_CR_PIPE_CLOSING;
3089797SRaymond.Chen@Sun.COM 
3099797SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
3109430SRaymond.Chen@Sun.COM 		(void) wusb_wa_rpipe_reset(hwahcp->hwahc_dip, ph, hdl, 0);
3119797SRaymond.Chen@Sun.COM 		mutex_enter(&hwahcp->hwahc_mutex);
3129430SRaymond.Chen@Sun.COM 
3139430SRaymond.Chen@Sun.COM 		break;
3149430SRaymond.Chen@Sun.COM 	case HWAHC_PIPE_STATE_RESET:
3159430SRaymond.Chen@Sun.COM 	case HWAHC_PIPE_STATE_ERROR:
3169430SRaymond.Chen@Sun.COM 		completion_reason = USB_CR_PIPE_RESET;
3179430SRaymond.Chen@Sun.COM 		if (hwahcp->hwahc_dev_state == USB_DEV_ONLINE) {
3189430SRaymond.Chen@Sun.COM 			mutex_exit(&hwahcp->hwahc_mutex);
3199430SRaymond.Chen@Sun.COM 			/*
3209430SRaymond.Chen@Sun.COM 			 * reset WA's RPipe.
3219430SRaymond.Chen@Sun.COM 			 * If this pipe is not bound to the default endpoint,
3229430SRaymond.Chen@Sun.COM 			 * also send a clear_feature request to that ep.
3239430SRaymond.Chen@Sun.COM 			 */
3249430SRaymond.Chen@Sun.COM 			rval = wusb_wa_rpipe_reset(hwahcp->hwahc_dip,
3259430SRaymond.Chen@Sun.COM 			    ph, hdl, 1);
3269430SRaymond.Chen@Sun.COM 			mutex_enter(&hwahcp->hwahc_mutex);
3279430SRaymond.Chen@Sun.COM 
3289430SRaymond.Chen@Sun.COM 			USB_DPRINTF_L4(PRINT_MASK_HCDI,
3299430SRaymond.Chen@Sun.COM 			    hwahcp->hwahc_log_handle,
3309430SRaymond.Chen@Sun.COM 			    "hwahc_pipe_cleanup: rp reset, rv=%d",
3319430SRaymond.Chen@Sun.COM 			    rval);
3329430SRaymond.Chen@Sun.COM 
3339430SRaymond.Chen@Sun.COM 			pp->pp_state = HWAHC_PIPE_STATE_IDLE;
3349430SRaymond.Chen@Sun.COM 		}
3359430SRaymond.Chen@Sun.COM 
3369430SRaymond.Chen@Sun.COM 		break;
3379430SRaymond.Chen@Sun.COM 	case HWAHC_PIPE_STATE_STOP_POLLING:
3389430SRaymond.Chen@Sun.COM 		completion_reason = USB_CR_STOPPED_POLLING;
3399430SRaymond.Chen@Sun.COM 		pp->pp_state = HWAHC_PIPE_STATE_IDLE;
3409430SRaymond.Chen@Sun.COM 
3419430SRaymond.Chen@Sun.COM 		break;
3429430SRaymond.Chen@Sun.COM 	}
3439430SRaymond.Chen@Sun.COM 
3449430SRaymond.Chen@Sun.COM 	/*
3459430SRaymond.Chen@Sun.COM 	 * Do the callback for the original client
3469430SRaymond.Chen@Sun.COM 	 * periodic IN request.
3479430SRaymond.Chen@Sun.COM 	 */
3489430SRaymond.Chen@Sun.COM 	eptd = &ph->p_ep;
3499430SRaymond.Chen@Sun.COM 
3509430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
3519430SRaymond.Chen@Sun.COM 	    "hwahc_pipe_cleanup: end");
3529430SRaymond.Chen@Sun.COM 
3539430SRaymond.Chen@Sun.COM 	if ((WUSB_PERIODIC_ENDPOINT(eptd)) &&
3549430SRaymond.Chen@Sun.COM 	    ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) ==
3559430SRaymond.Chen@Sun.COM 	    USB_EP_DIR_IN)) {
3569430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
3579430SRaymond.Chen@Sun.COM 
3589430SRaymond.Chen@Sun.COM 		hwahc_do_client_periodic_in_req_callback(
3599430SRaymond.Chen@Sun.COM 		    hwahcp, pp, completion_reason);
3609430SRaymond.Chen@Sun.COM 
3619430SRaymond.Chen@Sun.COM 		mutex_enter(&hwahcp->hwahc_mutex);
3629430SRaymond.Chen@Sun.COM 	}
3639430SRaymond.Chen@Sun.COM }
3649430SRaymond.Chen@Sun.COM 
3659430SRaymond.Chen@Sun.COM /*
3669430SRaymond.Chen@Sun.COM  * set the pipe's parent device information
3679430SRaymond.Chen@Sun.COM  */
3689430SRaymond.Chen@Sun.COM static int
hwahc_set_pipe_dev_info(hwahc_state_t * hwahcp,usba_pipe_handle_data_t * ph,hwahc_pipe_private_t * pp)3699430SRaymond.Chen@Sun.COM hwahc_set_pipe_dev_info(hwahc_state_t *hwahcp,
3709430SRaymond.Chen@Sun.COM     usba_pipe_handle_data_t *ph, hwahc_pipe_private_t *pp)
3719430SRaymond.Chen@Sun.COM {
3729430SRaymond.Chen@Sun.COM 	dev_info_t *dip = NULL;
3739430SRaymond.Chen@Sun.COM 	wusb_hc_data_t *hc_data;
3749430SRaymond.Chen@Sun.COM 	int i;
3759430SRaymond.Chen@Sun.COM 
3769430SRaymond.Chen@Sun.COM 	dip = usba_get_dip((usb_pipe_handle_t)ph->p_ph_impl);
3779430SRaymond.Chen@Sun.COM 	if (dip == NULL) {
3789430SRaymond.Chen@Sun.COM 
3799430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
3809430SRaymond.Chen@Sun.COM 	}
3819430SRaymond.Chen@Sun.COM 
3829430SRaymond.Chen@Sun.COM 	hc_data = &hwahcp->hwahc_hc_data;
3839430SRaymond.Chen@Sun.COM 
3849430SRaymond.Chen@Sun.COM 	mutex_enter(&hc_data->hc_mutex);
3859430SRaymond.Chen@Sun.COM 	for (i = 1; i <= hc_data->hc_num_ports; i++) {
3869430SRaymond.Chen@Sun.COM 		if ((dip == hc_data->hc_children_dips[i])) {
3879430SRaymond.Chen@Sun.COM 			pp->pp_wdev = hc_data->hc_dev_infos[i];
3889430SRaymond.Chen@Sun.COM 
3899430SRaymond.Chen@Sun.COM 			USB_DPRINTF_L3(DPRINT_MASK_HCDI,
3909430SRaymond.Chen@Sun.COM 			    hwahcp->hwahc_log_handle,
3919430SRaymond.Chen@Sun.COM 			    "hwahc_set_pipe_dev_info: pp(%p) device(%p) set",
3929430SRaymond.Chen@Sun.COM 			    (void *) pp, (void *) pp->pp_wdev);
3939430SRaymond.Chen@Sun.COM 
3949430SRaymond.Chen@Sun.COM 			break;
3959430SRaymond.Chen@Sun.COM 		}
3969430SRaymond.Chen@Sun.COM 	}
3979430SRaymond.Chen@Sun.COM 
3989430SRaymond.Chen@Sun.COM 	mutex_exit(&hc_data->hc_mutex);
3999430SRaymond.Chen@Sun.COM 
4009430SRaymond.Chen@Sun.COM 	if (pp->pp_wdev) {
4019430SRaymond.Chen@Sun.COM 		return (USB_SUCCESS);
4029430SRaymond.Chen@Sun.COM 	} else {
4039430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
4049430SRaymond.Chen@Sun.COM 	}
4059430SRaymond.Chen@Sun.COM }
4069430SRaymond.Chen@Sun.COM 
4079430SRaymond.Chen@Sun.COM /*
4089430SRaymond.Chen@Sun.COM  * HWA HCDI entry points
4099430SRaymond.Chen@Sun.COM  *
4109430SRaymond.Chen@Sun.COM  * The Host Controller Driver Interfaces (HCDI) are the software interfaces
4119430SRaymond.Chen@Sun.COM  * between the Universal Serial Bus Layer (USBA) and the Host Controller
4129430SRaymond.Chen@Sun.COM  * Driver (HCD). The HCDI interfaces or entry points are subject to change.
4139430SRaymond.Chen@Sun.COM  */
4149430SRaymond.Chen@Sun.COM 
4159430SRaymond.Chen@Sun.COM /*
4169430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_open:
4179430SRaymond.Chen@Sun.COM  * Member of HCD Ops structure and called during client specific pipe open.
4189430SRaymond.Chen@Sun.COM  * Assign rpipe for wireless transaction to work.
4199430SRaymond.Chen@Sun.COM  * The rpipe is assigned to an endpoint until the endpoint is closed.
4209430SRaymond.Chen@Sun.COM  */
4219430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_open(usba_pipe_handle_data_t * ph,usb_flags_t flags)4229430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_open(
4239430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
4249430SRaymond.Chen@Sun.COM 	usb_flags_t		flags)
4259430SRaymond.Chen@Sun.COM {
4269430SRaymond.Chen@Sun.COM 	int			rval;
4279430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
4289430SRaymond.Chen@Sun.COM 	int			kmflag;
4299430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
4309430SRaymond.Chen@Sun.COM 	usb_ep_descr_t		*epdt = &ph->p_ep;
4319430SRaymond.Chen@Sun.COM 	uint8_t			type;
4329430SRaymond.Chen@Sun.COM 	wusb_wa_data_t		*wa;
4339430SRaymond.Chen@Sun.COM 
4349430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
4359430SRaymond.Chen@Sun.COM 	wa = &hwahcp->hwahc_wa_data;
4369430SRaymond.Chen@Sun.COM 
4379430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
4389430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_open: hwahc=0x%p, ph=0x%p,"
4399430SRaymond.Chen@Sun.COM 	    " addr = 0x%x, ep=0x%02X", (void *) hwahcp, (void *) ph,
4409430SRaymond.Chen@Sun.COM 	    ph->p_usba_device->usb_addr, epdt->bEndpointAddress);
4419430SRaymond.Chen@Sun.COM 
4429430SRaymond.Chen@Sun.COM 	kmflag = (flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
4439430SRaymond.Chen@Sun.COM 
4449430SRaymond.Chen@Sun.COM 	if (ph->p_hcd_private) {
4459430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
4469430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_open: Pipe is already opened");
4479430SRaymond.Chen@Sun.COM 
4489430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
4499430SRaymond.Chen@Sun.COM 	}
4509430SRaymond.Chen@Sun.COM 
4519430SRaymond.Chen@Sun.COM 	pp = kmem_zalloc(sizeof (hwahc_pipe_private_t), kmflag);
4529430SRaymond.Chen@Sun.COM 	if (pp == NULL) {
4539430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
4549430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_open: alloc pp failed");
4559430SRaymond.Chen@Sun.COM 
4569430SRaymond.Chen@Sun.COM 		return (USB_NO_RESOURCES);
4579430SRaymond.Chen@Sun.COM 	}
4589430SRaymond.Chen@Sun.COM 
4599430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
4609430SRaymond.Chen@Sun.COM 
4619430SRaymond.Chen@Sun.COM 	if (hwahc_set_pipe_dev_info(hwahcp, ph, pp) < 0) {
4629430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
4639430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_open: set pipe dev_info failed");
4649430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
4659430SRaymond.Chen@Sun.COM 
4669430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
4679430SRaymond.Chen@Sun.COM 	}
4689430SRaymond.Chen@Sun.COM 
4699430SRaymond.Chen@Sun.COM 	rval = hwahc_state_is_operational(hwahcp);
4709430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
4719430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
4729430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_open: state error: %d", rval);
4739430SRaymond.Chen@Sun.COM 		kmem_free(pp, sizeof (hwahc_pipe_private_t));
4749430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
4759430SRaymond.Chen@Sun.COM 
4769430SRaymond.Chen@Sun.COM 		return (rval);
4779430SRaymond.Chen@Sun.COM 	}
4789430SRaymond.Chen@Sun.COM 
4799430SRaymond.Chen@Sun.COM 	/* assign rpipe to the endpoint */
4809430SRaymond.Chen@Sun.COM 	type = epdt->bmAttributes & USB_EP_ATTR_MASK;
4819430SRaymond.Chen@Sun.COM 	rval = wusb_wa_get_rpipe(&hwahcp->hwahc_wa_data,
4829430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_default_pipe, type, &pp->pp_rp,
4839430SRaymond.Chen@Sun.COM 	    PRINT_MASK_HCDI, hwahcp->hwahc_log_handle);
4849430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
4859430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
4869430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_open: getting rpipe failed");
4879430SRaymond.Chen@Sun.COM 		kmem_free(pp, sizeof (hwahc_pipe_private_t));
4889430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
4899430SRaymond.Chen@Sun.COM 
4909430SRaymond.Chen@Sun.COM 		return (USB_NO_RESOURCES);
4919430SRaymond.Chen@Sun.COM 	}
4929430SRaymond.Chen@Sun.COM 
4939430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
4949430SRaymond.Chen@Sun.COM 	/* target the rpipe to the endpoint */
4959430SRaymond.Chen@Sun.COM 	rval = wusb_wa_set_rpipe_target(hwahcp->hwahc_dip, wa,
4969430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_default_pipe, ph, pp->pp_rp);
4979430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
4989430SRaymond.Chen@Sun.COM 
4999430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
5009430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
5019430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_open: set target for rpipe failed");
50210912SRaymond.Chen@Sun.COM 		(void) wusb_wa_release_rpipe(wa, pp->pp_rp);
5039430SRaymond.Chen@Sun.COM 		kmem_free(pp, sizeof (hwahc_pipe_private_t));
5049430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
5059430SRaymond.Chen@Sun.COM 
5069430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
5079430SRaymond.Chen@Sun.COM 	}
5089430SRaymond.Chen@Sun.COM 
5099430SRaymond.Chen@Sun.COM 	pp->pp_pipe_handle = ph;
5109430SRaymond.Chen@Sun.COM 	cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL);
5119430SRaymond.Chen@Sun.COM 
5129430SRaymond.Chen@Sun.COM 	mutex_enter(&ph->p_mutex);
5139430SRaymond.Chen@Sun.COM 	ph->p_hcd_private = (usb_opaque_t)pp;
5149430SRaymond.Chen@Sun.COM 	bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
5159430SRaymond.Chen@Sun.COM 	mutex_exit(&ph->p_mutex);
5169430SRaymond.Chen@Sun.COM 
5179430SRaymond.Chen@Sun.COM 	pp->pp_state = HWAHC_PIPE_STATE_IDLE;
5189430SRaymond.Chen@Sun.COM 	hwahcp->hwahc_open_pipe_count++;
5199430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
5209430SRaymond.Chen@Sun.COM 
5219430SRaymond.Chen@Sun.COM 	return (USB_SUCCESS);
5229430SRaymond.Chen@Sun.COM }
5239430SRaymond.Chen@Sun.COM 
5249430SRaymond.Chen@Sun.COM 
5259430SRaymond.Chen@Sun.COM /*
5269430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_close:
5279430SRaymond.Chen@Sun.COM  * Member of HCD Ops structure and called during the client specific pipe
5289430SRaymond.Chen@Sun.COM  * close.
5299430SRaymond.Chen@Sun.COM  * Remove unprocessed transfers from the pipe and free rpipe resource.
5309430SRaymond.Chen@Sun.COM  */
5319430SRaymond.Chen@Sun.COM /* ARGSUSED */
5329430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_close(usba_pipe_handle_data_t * ph,usb_flags_t flags)5339430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_close(
5349430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
5359430SRaymond.Chen@Sun.COM 	usb_flags_t		flags)
5369430SRaymond.Chen@Sun.COM {
5379430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
5389430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
5399430SRaymond.Chen@Sun.COM 	usb_ep_descr_t		*epdt = &ph->p_ep;
5409430SRaymond.Chen@Sun.COM 
5419430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
5429430SRaymond.Chen@Sun.COM 
5439430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
5449430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_close:ph=0x%p addr = 0x%x, ep = 0x%x",
5459430SRaymond.Chen@Sun.COM 	    (void *) ph, ph->p_usba_device->usb_addr,
5469430SRaymond.Chen@Sun.COM 	    epdt->bEndpointAddress);
5479430SRaymond.Chen@Sun.COM 
5489430SRaymond.Chen@Sun.COM 	ASSERT(ph->p_hcd_private != NULL);
5499430SRaymond.Chen@Sun.COM 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
5509430SRaymond.Chen@Sun.COM 
5519430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
5529430SRaymond.Chen@Sun.COM 
5539430SRaymond.Chen@Sun.COM 	pp->pp_state = HWAHC_PIPE_STATE_CLOSE;
5549430SRaymond.Chen@Sun.COM 
5559430SRaymond.Chen@Sun.COM 	hwahc_pipe_cleanup(hwahcp, ph);
5569430SRaymond.Chen@Sun.COM 
5579430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
5589430SRaymond.Chen@Sun.COM 
5599430SRaymond.Chen@Sun.COM 	wusb_wa_clear_dev_ep(ph); /* clear the remote dev's endpoint */
5609430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
5619430SRaymond.Chen@Sun.COM 
56210912SRaymond.Chen@Sun.COM 	(void) wusb_wa_release_rpipe(&hwahcp->hwahc_wa_data, pp->pp_rp);
5639430SRaymond.Chen@Sun.COM 
5649430SRaymond.Chen@Sun.COM 	mutex_enter(&ph->p_mutex);
5659430SRaymond.Chen@Sun.COM 	cv_destroy(&pp->pp_xfer_cmpl_cv);
5669430SRaymond.Chen@Sun.COM 	kmem_free(pp, sizeof (hwahc_pipe_private_t));
5679430SRaymond.Chen@Sun.COM 	ph->p_hcd_private = NULL;
5689430SRaymond.Chen@Sun.COM 	mutex_exit(&ph->p_mutex);
5699430SRaymond.Chen@Sun.COM 	hwahcp->hwahc_open_pipe_count--;
5709430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
5719430SRaymond.Chen@Sun.COM 
5729430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
5739430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_close: end");
5749430SRaymond.Chen@Sun.COM 
5759430SRaymond.Chen@Sun.COM 	return (USB_SUCCESS);
5769430SRaymond.Chen@Sun.COM }
5779430SRaymond.Chen@Sun.COM 
5789430SRaymond.Chen@Sun.COM 
5799430SRaymond.Chen@Sun.COM /*
5809430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_reset:
5819430SRaymond.Chen@Sun.COM  *	- clean up this pipe and change its state
5829430SRaymond.Chen@Sun.COM  */
5839430SRaymond.Chen@Sun.COM /* ARGSUSED */
5849430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_reset(usba_pipe_handle_data_t * ph,usb_flags_t flags)5859430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_reset(
5869430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
5879430SRaymond.Chen@Sun.COM 	usb_flags_t		flags)
5889430SRaymond.Chen@Sun.COM {
5899430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
5909430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
5919430SRaymond.Chen@Sun.COM 
5929430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
5939430SRaymond.Chen@Sun.COM 
5949430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
5959430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_reset: ph = 0x%p, ep=0x%02x",
5969430SRaymond.Chen@Sun.COM 	    (void *) ph, ph->p_ep.bEndpointAddress);
5979430SRaymond.Chen@Sun.COM 
5989430SRaymond.Chen@Sun.COM 	ASSERT(ph->p_hcd_private != NULL);
5999430SRaymond.Chen@Sun.COM 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
6009430SRaymond.Chen@Sun.COM 
6019430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
6029430SRaymond.Chen@Sun.COM 	pp->pp_state = HWAHC_PIPE_STATE_RESET;
6039430SRaymond.Chen@Sun.COM 	hwahc_pipe_cleanup(hwahcp, ph);
6049430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
6059430SRaymond.Chen@Sun.COM 
6069430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
6079430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_reset: end");
6089430SRaymond.Chen@Sun.COM 
6099430SRaymond.Chen@Sun.COM 	return (USB_SUCCESS);
6109430SRaymond.Chen@Sun.COM }
6119430SRaymond.Chen@Sun.COM 
6129430SRaymond.Chen@Sun.COM 
6139430SRaymond.Chen@Sun.COM /*
6149430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_ctrl_xfer:
6159430SRaymond.Chen@Sun.COM  *	- usba_hcdi_pipe_ctrl_xfer entry
6169430SRaymond.Chen@Sun.COM  *	- check pipe state
6179430SRaymond.Chen@Sun.COM  *	- call wa_xfer to do this request
6189430SRaymond.Chen@Sun.COM  */
6199430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_ctrl_xfer(usba_pipe_handle_data_t * ph,usb_ctrl_req_t * ctrl_reqp,usb_flags_t usb_flags)6209430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_ctrl_xfer(
6219430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
6229430SRaymond.Chen@Sun.COM 	usb_ctrl_req_t		*ctrl_reqp,
6239430SRaymond.Chen@Sun.COM 	usb_flags_t		usb_flags)
6249430SRaymond.Chen@Sun.COM {
6259430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
6269430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
6279430SRaymond.Chen@Sun.COM 	int			rval;
6289430SRaymond.Chen@Sun.COM 	uint8_t			ep_addr = ph->p_ep.bEndpointAddress;
6299430SRaymond.Chen@Sun.COM 
6309430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
6319430SRaymond.Chen@Sun.COM 
6329430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
6339430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_ctrl_xfer: hwahcp=0x%p ph = 0x%p"
6349430SRaymond.Chen@Sun.COM 	    " reqp = 0x%p flags = %x", (void *) hwahcp, (void *) ph,
6359430SRaymond.Chen@Sun.COM 	    (void *) ctrl_reqp, usb_flags);
6369430SRaymond.Chen@Sun.COM 
6379430SRaymond.Chen@Sun.COM 	ASSERT(ph->p_hcd_private != NULL);
6389430SRaymond.Chen@Sun.COM 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
6399430SRaymond.Chen@Sun.COM 
6409430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
6419430SRaymond.Chen@Sun.COM 	rval = hwahc_state_is_operational(hwahcp);
6429430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
6439430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
6449430SRaymond.Chen@Sun.COM 
6459430SRaymond.Chen@Sun.COM 		return (rval);
6469430SRaymond.Chen@Sun.COM 	}
6479430SRaymond.Chen@Sun.COM 
6489430SRaymond.Chen@Sun.COM 	/*
6499430SRaymond.Chen@Sun.COM 	 * if doing ctrl transfer on non-zero pipe and its state is error
6509430SRaymond.Chen@Sun.COM 	 * The default endpoint is critical for any other operations.
6519430SRaymond.Chen@Sun.COM 	 * We should not depend on upper layer to reset it.
6529430SRaymond.Chen@Sun.COM 	 */
6539430SRaymond.Chen@Sun.COM 	if ((pp->pp_state == HWAHC_PIPE_STATE_ERROR)) {
6549430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
6559430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_ctrl_xfer: Pipe(%d) is in error"
6569430SRaymond.Chen@Sun.COM 		    " state, need pipe reset to continue", ep_addr);
6579430SRaymond.Chen@Sun.COM 
6589430SRaymond.Chen@Sun.COM 		if (ep_addr == 0) {
6599430SRaymond.Chen@Sun.COM 			/*
6609430SRaymond.Chen@Sun.COM 			 * some error with the RPipe of EP 0,
6619430SRaymond.Chen@Sun.COM 			 * we need to reset this RPipe by ourself
6629430SRaymond.Chen@Sun.COM 			 */
6639430SRaymond.Chen@Sun.COM 			mutex_exit(&hwahcp->hwahc_mutex);
66410912SRaymond.Chen@Sun.COM 			(void) wusb_wa_rpipe_reset(hwahcp->hwahc_dip, ph,
6659430SRaymond.Chen@Sun.COM 			    pp->pp_rp, 1);
6669430SRaymond.Chen@Sun.COM 			mutex_enter(&hwahcp->hwahc_mutex);
6679430SRaymond.Chen@Sun.COM 			pp->pp_state = 0;
6689430SRaymond.Chen@Sun.COM 		} else {
6699430SRaymond.Chen@Sun.COM 		/* client driver should clear non-default endpoint's state */
6709430SRaymond.Chen@Sun.COM 			mutex_exit(&hwahcp->hwahc_mutex);
6719430SRaymond.Chen@Sun.COM 
6729430SRaymond.Chen@Sun.COM 			return (USB_FAILURE);
6739430SRaymond.Chen@Sun.COM 		}
6749430SRaymond.Chen@Sun.COM 	} else if ((pp->pp_state != HWAHC_PIPE_STATE_IDLE) &&
6759430SRaymond.Chen@Sun.COM 	    (pp->pp_state != HWAHC_PIPE_STATE_ERROR)) {
6769430SRaymond.Chen@Sun.COM 			mutex_exit(&hwahcp->hwahc_mutex);
6779430SRaymond.Chen@Sun.COM 
6789430SRaymond.Chen@Sun.COM 			return (USB_PIPE_ERROR);
6799430SRaymond.Chen@Sun.COM 	}
6809430SRaymond.Chen@Sun.COM 
6819430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
6829430SRaymond.Chen@Sun.COM 
6839430SRaymond.Chen@Sun.COM 	rval = wusb_wa_ctrl_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph,
6849430SRaymond.Chen@Sun.COM 	    ctrl_reqp, usb_flags);
6859430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
6869430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
6879430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_ctrl_xfer failed, rval = %d", rval);
6889430SRaymond.Chen@Sun.COM 	}
6899430SRaymond.Chen@Sun.COM 
6909430SRaymond.Chen@Sun.COM 
6919430SRaymond.Chen@Sun.COM 	return (rval);
6929430SRaymond.Chen@Sun.COM }
6939430SRaymond.Chen@Sun.COM 
6949430SRaymond.Chen@Sun.COM 
6959430SRaymond.Chen@Sun.COM /*
6969430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_bulk_xfer:
6979430SRaymond.Chen@Sun.COM  *	- usba_hcid_pipe_bulk_xfer entry
6989430SRaymond.Chen@Sun.COM  *	- check the target pipe status first
6999430SRaymond.Chen@Sun.COM  *	- process this request
7009430SRaymond.Chen@Sun.COM  */
7019430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t * ph,usb_bulk_req_t * bulk_reqp,usb_flags_t usb_flags)7029430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_bulk_xfer(
7039430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
7049430SRaymond.Chen@Sun.COM 	usb_bulk_req_t		*bulk_reqp,
7059430SRaymond.Chen@Sun.COM 	usb_flags_t		usb_flags)
7069430SRaymond.Chen@Sun.COM {
7079430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
7089430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
7099430SRaymond.Chen@Sun.COM 	int			rval;
7109430SRaymond.Chen@Sun.COM 
7119430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
7129430SRaymond.Chen@Sun.COM 
7139430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
7149430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_bulk_xfer: hwahcp=0x%p ph = 0x%p reqp = 0x%p"
7159430SRaymond.Chen@Sun.COM 	    " flags = %x", (void *) hwahcp, (void *) ph,
7169430SRaymond.Chen@Sun.COM 	    (void *) bulk_reqp, usb_flags);
7179430SRaymond.Chen@Sun.COM 
7189430SRaymond.Chen@Sun.COM 	ASSERT(ph->p_hcd_private != NULL);
7199430SRaymond.Chen@Sun.COM 
7209430SRaymond.Chen@Sun.COM 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
7219430SRaymond.Chen@Sun.COM 
7229430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
7239430SRaymond.Chen@Sun.COM 	rval = hwahc_state_is_operational(hwahcp);
7249430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
7259430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
7269430SRaymond.Chen@Sun.COM 
7279430SRaymond.Chen@Sun.COM 		return (rval);
7289430SRaymond.Chen@Sun.COM 	}
7299430SRaymond.Chen@Sun.COM 
7309430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
7319430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_bulk_xfer: pp = 0x%p state= %x", (void *) pp,
7329430SRaymond.Chen@Sun.COM 	    pp->pp_state);
7339430SRaymond.Chen@Sun.COM 
7349430SRaymond.Chen@Sun.COM 	if (pp->pp_state == HWAHC_PIPE_STATE_ERROR) {
7359430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
7369430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_bulk_xfer: "
7379430SRaymond.Chen@Sun.COM 		    "Pipe is in error state, need pipe reset to continue");
7389430SRaymond.Chen@Sun.COM 
7399430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
7409430SRaymond.Chen@Sun.COM 
7419430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
7429430SRaymond.Chen@Sun.COM 	}
7439430SRaymond.Chen@Sun.COM 
7449430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
7459430SRaymond.Chen@Sun.COM 	rval = wusb_wa_bulk_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph,
7469430SRaymond.Chen@Sun.COM 	    bulk_reqp, usb_flags);
7479430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
7489430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
7499430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
7509430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_bulk_xfer failed, rval = %d", rval);
7519430SRaymond.Chen@Sun.COM 	}
7529430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
7539430SRaymond.Chen@Sun.COM 
7549430SRaymond.Chen@Sun.COM 	return (rval);
7559430SRaymond.Chen@Sun.COM }
7569430SRaymond.Chen@Sun.COM 
7579430SRaymond.Chen@Sun.COM /*
7589430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_intr_xfer:
7599430SRaymond.Chen@Sun.COM  *	- usba_hcdi_pipe_intr_xfer entry
7609430SRaymond.Chen@Sun.COM  *	- check pipe state
7619430SRaymond.Chen@Sun.COM  *	- process this request
7629430SRaymond.Chen@Sun.COM  */
7639430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_intr_xfer(usba_pipe_handle_data_t * ph,usb_intr_req_t * intr_reqp,usb_flags_t usb_flags)7649430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_intr_xfer(
7659430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
7669430SRaymond.Chen@Sun.COM 	usb_intr_req_t		*intr_reqp,
7679430SRaymond.Chen@Sun.COM 	usb_flags_t		usb_flags)
7689430SRaymond.Chen@Sun.COM {
7699430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
7709430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
7719430SRaymond.Chen@Sun.COM 	int			rval, pipe_dir;
7729430SRaymond.Chen@Sun.COM 
7739430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
7749430SRaymond.Chen@Sun.COM 
7759430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
7769430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_intr_xfer: hwahcp=0x%p ph = 0x%p"
7779430SRaymond.Chen@Sun.COM 	    " reqp = 0x%p flags = %x", (void *) hwahcp, (void *) ph,
7789430SRaymond.Chen@Sun.COM 	    (void *) intr_reqp, usb_flags);
7799430SRaymond.Chen@Sun.COM 
7809430SRaymond.Chen@Sun.COM 	ASSERT(ph->p_hcd_private != NULL);
7819430SRaymond.Chen@Sun.COM 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
7829430SRaymond.Chen@Sun.COM 
7839430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
7849430SRaymond.Chen@Sun.COM 	rval = hwahc_state_is_operational(hwahcp);
7859430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
7869430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
7879430SRaymond.Chen@Sun.COM 
7889430SRaymond.Chen@Sun.COM 		return (rval);
7899430SRaymond.Chen@Sun.COM 	}
7909430SRaymond.Chen@Sun.COM 
7919430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
7929430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_intr_xfer: pp = 0x%p state= %x", (void *) pp,
7939430SRaymond.Chen@Sun.COM 	    pp->pp_state);
7949430SRaymond.Chen@Sun.COM 
7959430SRaymond.Chen@Sun.COM 	if (pp->pp_state == HWAHC_PIPE_STATE_ERROR) {
7969430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
7979430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_intr_xfer: "
7989430SRaymond.Chen@Sun.COM 		    "Pipe is in error state, need pipe reset to continue");
7999430SRaymond.Chen@Sun.COM 
8009430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
8019430SRaymond.Chen@Sun.COM 
8029430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
8039430SRaymond.Chen@Sun.COM 	}
8049430SRaymond.Chen@Sun.COM 
8059430SRaymond.Chen@Sun.COM 	pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
8069430SRaymond.Chen@Sun.COM 
8079430SRaymond.Chen@Sun.COM 
8089430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
8099430SRaymond.Chen@Sun.COM 	rval = wusb_wa_intr_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph,
8109430SRaymond.Chen@Sun.COM 	    intr_reqp, usb_flags);
8119430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
8129430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
8139430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
8149430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_intr_xfer failed, rval = %d", rval);
8159430SRaymond.Chen@Sun.COM 	}
8169430SRaymond.Chen@Sun.COM 
8179430SRaymond.Chen@Sun.COM 	if ((pipe_dir == USB_EP_DIR_IN) &&(rval == USB_SUCCESS)) {
8189430SRaymond.Chen@Sun.COM 		/*
8199430SRaymond.Chen@Sun.COM 		 * the request has been submitted successfully,
8209430SRaymond.Chen@Sun.COM 		 * save the original one; free this request when polling
8219430SRaymond.Chen@Sun.COM 		 * stopped
8229430SRaymond.Chen@Sun.COM 		 */
8239430SRaymond.Chen@Sun.COM 		pp->pp_client_periodic_in_reqp = (usb_opaque_t)intr_reqp;
8249430SRaymond.Chen@Sun.COM 		pp->pp_state = HWAHC_PIPE_STATE_ACTIVE;
8259430SRaymond.Chen@Sun.COM 	}
8269430SRaymond.Chen@Sun.COM 
8279430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
8289430SRaymond.Chen@Sun.COM 
8299430SRaymond.Chen@Sun.COM 	return (rval);
8309430SRaymond.Chen@Sun.COM }
8319430SRaymond.Chen@Sun.COM 
8329430SRaymond.Chen@Sun.COM /*
8339430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_isoc_xfer:
8349430SRaymond.Chen@Sun.COM  */
8359430SRaymond.Chen@Sun.COM /* ARGSUSED */
8369430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_isoc_xfer(usba_pipe_handle_data_t * ph,usb_isoc_req_t * isoc_reqp,usb_flags_t usb_flags)8379430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_isoc_xfer(
8389430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
8399430SRaymond.Chen@Sun.COM 	usb_isoc_req_t		*isoc_reqp,
8409430SRaymond.Chen@Sun.COM 	usb_flags_t		usb_flags)
8419430SRaymond.Chen@Sun.COM {
8429430SRaymond.Chen@Sun.COM 	return (USB_NOT_SUPPORTED);
8439430SRaymond.Chen@Sun.COM }
8449430SRaymond.Chen@Sun.COM 
8459430SRaymond.Chen@Sun.COM 
8469430SRaymond.Chen@Sun.COM /*
8479430SRaymond.Chen@Sun.COM  * hwahc_hcdi_bulk_transfer_size:
8489430SRaymond.Chen@Sun.COM  *
8499430SRaymond.Chen@Sun.COM  * Return maximum bulk transfer size
8509430SRaymond.Chen@Sun.COM  */
8519430SRaymond.Chen@Sun.COM /* ARGSUSED */
8529430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_bulk_transfer_size(usba_device_t * usba_device,size_t * size)8539430SRaymond.Chen@Sun.COM hwahc_hcdi_bulk_transfer_size(
8549430SRaymond.Chen@Sun.COM 	usba_device_t	*usba_device,
8559430SRaymond.Chen@Sun.COM 	size_t		*size)
8569430SRaymond.Chen@Sun.COM {
8579430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
8589430SRaymond.Chen@Sun.COM 	int			rval;
8599430SRaymond.Chen@Sun.COM 
8609430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(usba_device->usb_root_hub_dip);
8619430SRaymond.Chen@Sun.COM 
8629430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
8639430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_bulk_transfer_size:");
8649430SRaymond.Chen@Sun.COM 
8659430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
8669430SRaymond.Chen@Sun.COM 	rval = hwahc_state_is_operational(hwahcp);
8679430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
8689430SRaymond.Chen@Sun.COM 
8699430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
8709430SRaymond.Chen@Sun.COM 
8719430SRaymond.Chen@Sun.COM 		return (rval);
8729430SRaymond.Chen@Sun.COM 	}
8739430SRaymond.Chen@Sun.COM 
8749430SRaymond.Chen@Sun.COM 	*size = WA_MAX_SEG_COUNT * 1024;
8759430SRaymond.Chen@Sun.COM 
8769430SRaymond.Chen@Sun.COM 	return (USB_SUCCESS);
8779430SRaymond.Chen@Sun.COM }
8789430SRaymond.Chen@Sun.COM 
8799430SRaymond.Chen@Sun.COM /*
8809430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_stop_intr_polling()
8819430SRaymond.Chen@Sun.COM  */
8829430SRaymond.Chen@Sun.COM /* ARGSUSED */
8839430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_stop_intr_polling(usba_pipe_handle_data_t * ph,usb_flags_t flags)8849430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_stop_intr_polling(
8859430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
8869430SRaymond.Chen@Sun.COM 	usb_flags_t		flags)
8879430SRaymond.Chen@Sun.COM {
8889430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
8899430SRaymond.Chen@Sun.COM 	hwahc_pipe_private_t	*pp;
8909430SRaymond.Chen@Sun.COM 
8919430SRaymond.Chen@Sun.COM 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
8929430SRaymond.Chen@Sun.COM 
8939430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
8949430SRaymond.Chen@Sun.COM 	    "hwahc_hcdi_pipe_stop_intr_polling: hwahcp=0x%p ph = 0x%p"
8959430SRaymond.Chen@Sun.COM 	    " flags = %x", (void *) hwahcp, (void *) ph, flags);
8969430SRaymond.Chen@Sun.COM 
8979430SRaymond.Chen@Sun.COM 	ASSERT(ph->p_hcd_private != NULL);
8989430SRaymond.Chen@Sun.COM 
8999430SRaymond.Chen@Sun.COM 	mutex_enter(&hwahcp->hwahc_mutex);
9009430SRaymond.Chen@Sun.COM 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
9019430SRaymond.Chen@Sun.COM 
9029430SRaymond.Chen@Sun.COM 	if (pp->pp_state != HWAHC_PIPE_STATE_ACTIVE) {
9039430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
9049430SRaymond.Chen@Sun.COM 		    "hwahc_hcdi_pipe_stop_intr_polling: "
9059430SRaymond.Chen@Sun.COM 		    "Polling already stopped");
9069430SRaymond.Chen@Sun.COM 		mutex_exit(&hwahcp->hwahc_mutex);
9079430SRaymond.Chen@Sun.COM 
9089430SRaymond.Chen@Sun.COM 		return (USB_SUCCESS);
9099430SRaymond.Chen@Sun.COM 	}
9109430SRaymond.Chen@Sun.COM 
9119430SRaymond.Chen@Sun.COM 	pp->pp_state = HWAHC_PIPE_STATE_STOP_POLLING;
9129430SRaymond.Chen@Sun.COM 
9139430SRaymond.Chen@Sun.COM 	hwahc_pipe_cleanup(hwahcp, ph);
9149430SRaymond.Chen@Sun.COM 
9159430SRaymond.Chen@Sun.COM 	mutex_exit(&hwahcp->hwahc_mutex);
9169430SRaymond.Chen@Sun.COM 
9179430SRaymond.Chen@Sun.COM 	return (USB_SUCCESS);
9189430SRaymond.Chen@Sun.COM }
9199430SRaymond.Chen@Sun.COM 
9209430SRaymond.Chen@Sun.COM 
9219430SRaymond.Chen@Sun.COM /*
9229430SRaymond.Chen@Sun.COM  * hwahc_hcdi_pipe_stop_isoc_polling()
9239430SRaymond.Chen@Sun.COM  */
9249430SRaymond.Chen@Sun.COM /*ARGSUSED*/
9259430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_pipe_stop_isoc_polling(usba_pipe_handle_data_t * ph,usb_flags_t flags)9269430SRaymond.Chen@Sun.COM hwahc_hcdi_pipe_stop_isoc_polling(
9279430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
9289430SRaymond.Chen@Sun.COM 	usb_flags_t		flags)
9299430SRaymond.Chen@Sun.COM {
9309430SRaymond.Chen@Sun.COM 	return (USB_NOT_SUPPORTED);
9319430SRaymond.Chen@Sun.COM }
9329430SRaymond.Chen@Sun.COM 
9339430SRaymond.Chen@Sun.COM 
9349430SRaymond.Chen@Sun.COM /*
9359430SRaymond.Chen@Sun.COM  * hwahc_hcdi_get_current_frame_number:
9369430SRaymond.Chen@Sun.COM  *
9379430SRaymond.Chen@Sun.COM  * Get the current usb frame number.
9389430SRaymond.Chen@Sun.COM  * Return whether the request is handled successfully
9399430SRaymond.Chen@Sun.COM  */
9409430SRaymond.Chen@Sun.COM /* ARGSUSED */
9419430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_get_current_frame_number(usba_device_t * usba_device,usb_frame_number_t * frame_number)9429430SRaymond.Chen@Sun.COM hwahc_hcdi_get_current_frame_number(
9439430SRaymond.Chen@Sun.COM 	usba_device_t		*usba_device,
9449430SRaymond.Chen@Sun.COM 	usb_frame_number_t	*frame_number)
9459430SRaymond.Chen@Sun.COM {
9469430SRaymond.Chen@Sun.COM 	return (USB_NOT_SUPPORTED);
9479430SRaymond.Chen@Sun.COM }
9489430SRaymond.Chen@Sun.COM 
9499430SRaymond.Chen@Sun.COM 
9509430SRaymond.Chen@Sun.COM /*
9519430SRaymond.Chen@Sun.COM  * hwahc_hcdi_get_max_isoc_pkts:
9529430SRaymond.Chen@Sun.COM  *
9539430SRaymond.Chen@Sun.COM  * Get maximum isochronous packets per usb isochronous request.
9549430SRaymond.Chen@Sun.COM  * Return whether the request is handled successfully
9559430SRaymond.Chen@Sun.COM  */
9569430SRaymond.Chen@Sun.COM /* ARGSUSED */
9579430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_get_max_isoc_pkts(usba_device_t * usba_device,uint_t * max_pkts)9589430SRaymond.Chen@Sun.COM hwahc_hcdi_get_max_isoc_pkts(
9599430SRaymond.Chen@Sun.COM 	usba_device_t	*usba_device,
9609430SRaymond.Chen@Sun.COM 	uint_t		*max_pkts)
9619430SRaymond.Chen@Sun.COM {
9629430SRaymond.Chen@Sun.COM 	return (USB_NOT_SUPPORTED);
9639430SRaymond.Chen@Sun.COM }
9649430SRaymond.Chen@Sun.COM 
9659430SRaymond.Chen@Sun.COM 
9669430SRaymond.Chen@Sun.COM /*
9679430SRaymond.Chen@Sun.COM  * POLLED entry points
9689430SRaymond.Chen@Sun.COM  *
9699430SRaymond.Chen@Sun.COM  * These functions are entry points into the POLLED code.
9709430SRaymond.Chen@Sun.COM  */
9719430SRaymond.Chen@Sun.COM /*
9729430SRaymond.Chen@Sun.COM  * hwahc_hcdi_polled_input_init:
9739430SRaymond.Chen@Sun.COM  *
9749430SRaymond.Chen@Sun.COM  * This is the initialization routine for handling the USB keyboard
9759430SRaymond.Chen@Sun.COM  * in POLLED mode.  This routine is not called from POLLED mode, so
9769430SRaymond.Chen@Sun.COM  * it is OK to acquire mutexes.
9779430SRaymond.Chen@Sun.COM  */
9789430SRaymond.Chen@Sun.COM /* ARGSUSED */
9799430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_polled_input_init(usba_pipe_handle_data_t * ph,uchar_t ** polled_buf,usb_console_info_impl_t * console_input_info)9809430SRaymond.Chen@Sun.COM hwahc_hcdi_polled_input_init(
9819430SRaymond.Chen@Sun.COM 	usba_pipe_handle_data_t	*ph,
9829430SRaymond.Chen@Sun.COM 	uchar_t			**polled_buf,
9839430SRaymond.Chen@Sun.COM 	usb_console_info_impl_t	*console_input_info)
9849430SRaymond.Chen@Sun.COM {
9859430SRaymond.Chen@Sun.COM 	return (USB_FAILURE);
9869430SRaymond.Chen@Sun.COM }
9879430SRaymond.Chen@Sun.COM 
9889430SRaymond.Chen@Sun.COM 
9899430SRaymond.Chen@Sun.COM /*
9909430SRaymond.Chen@Sun.COM  * hwahc_hcdi_polled_input_fini:
9919430SRaymond.Chen@Sun.COM  */
9929430SRaymond.Chen@Sun.COM /* ARGSUSED */
9939430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_polled_input_fini(usb_console_info_impl_t * info)9949430SRaymond.Chen@Sun.COM hwahc_hcdi_polled_input_fini(usb_console_info_impl_t *info)
9959430SRaymond.Chen@Sun.COM {
9969430SRaymond.Chen@Sun.COM 	return (USB_FAILURE);
9979430SRaymond.Chen@Sun.COM }
9989430SRaymond.Chen@Sun.COM 
9999430SRaymond.Chen@Sun.COM 
10009430SRaymond.Chen@Sun.COM /*
10019430SRaymond.Chen@Sun.COM  * hwahc_hcdi_polled_input_enter:
10029430SRaymond.Chen@Sun.COM  *
10039430SRaymond.Chen@Sun.COM  * This is where we enter into POLLED mode.  This routine sets up
10049430SRaymond.Chen@Sun.COM  * everything so that calls to	hwahc_hcdi_polled_read will return
10059430SRaymond.Chen@Sun.COM  * characters.
10069430SRaymond.Chen@Sun.COM  */
10079430SRaymond.Chen@Sun.COM /* ARGSUSED */
10089430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_polled_input_enter(usb_console_info_impl_t * info)10099430SRaymond.Chen@Sun.COM hwahc_hcdi_polled_input_enter(usb_console_info_impl_t *info)
10109430SRaymond.Chen@Sun.COM {
10119430SRaymond.Chen@Sun.COM 	return (USB_FAILURE);
10129430SRaymond.Chen@Sun.COM }
10139430SRaymond.Chen@Sun.COM 
10149430SRaymond.Chen@Sun.COM 
10159430SRaymond.Chen@Sun.COM /*
10169430SRaymond.Chen@Sun.COM  * hwahc_hcdi_polled_input_exit:
10179430SRaymond.Chen@Sun.COM  *
10189430SRaymond.Chen@Sun.COM  * This is where we exit POLLED mode. This routine restores
10199430SRaymond.Chen@Sun.COM  * everything that is needed to continue operation.
10209430SRaymond.Chen@Sun.COM  */
10219430SRaymond.Chen@Sun.COM /* ARGSUSED */
10229430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_polled_input_exit(usb_console_info_impl_t * info)10239430SRaymond.Chen@Sun.COM hwahc_hcdi_polled_input_exit(usb_console_info_impl_t *info)
10249430SRaymond.Chen@Sun.COM {
10259430SRaymond.Chen@Sun.COM 	return (USB_FAILURE);
10269430SRaymond.Chen@Sun.COM }
10279430SRaymond.Chen@Sun.COM 
10289430SRaymond.Chen@Sun.COM 
10299430SRaymond.Chen@Sun.COM /*
10309430SRaymond.Chen@Sun.COM  * hwahc_hcdi_polled_read:
10319430SRaymond.Chen@Sun.COM  *
10329430SRaymond.Chen@Sun.COM  * Get a key character
10339430SRaymond.Chen@Sun.COM  */
10349430SRaymond.Chen@Sun.COM /* ARGSUSED */
10359430SRaymond.Chen@Sun.COM static int
hwahc_hcdi_polled_read(usb_console_info_impl_t * info,uint_t * num_characters)10369430SRaymond.Chen@Sun.COM hwahc_hcdi_polled_read(
10379430SRaymond.Chen@Sun.COM 	usb_console_info_impl_t	*info,
10389430SRaymond.Chen@Sun.COM 	uint_t			*num_characters)
10399430SRaymond.Chen@Sun.COM {
10409430SRaymond.Chen@Sun.COM 	return (USB_FAILURE);
10419430SRaymond.Chen@Sun.COM }
10429430SRaymond.Chen@Sun.COM 
10439430SRaymond.Chen@Sun.COM 
10449430SRaymond.Chen@Sun.COM /*
10459430SRaymond.Chen@Sun.COM  * hwahc_alloc_hcdi_ops:
10469430SRaymond.Chen@Sun.COM  *
10479430SRaymond.Chen@Sun.COM  * The HCDI interfaces or entry points are the software interfaces used by
10489430SRaymond.Chen@Sun.COM  * the Universal Serial Bus Driver  (USBA) to  access the services of the
10499430SRaymond.Chen@Sun.COM  * Host Controller Driver (HCD).  During HCD initialization, inform  USBA
10509430SRaymond.Chen@Sun.COM  * about all available HCDI interfaces or entry points.
10519430SRaymond.Chen@Sun.COM  */
10529430SRaymond.Chen@Sun.COM usba_hcdi_ops_t *
hwahc_alloc_hcdi_ops(hwahc_state_t * hwahcp)10539430SRaymond.Chen@Sun.COM hwahc_alloc_hcdi_ops(hwahc_state_t *hwahcp)
10549430SRaymond.Chen@Sun.COM {
10559430SRaymond.Chen@Sun.COM 	usba_hcdi_ops_t			*usba_hcdi_ops;
10569430SRaymond.Chen@Sun.COM 
10579430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L2(PRINT_MASK_ATTA, hwahcp->hwahc_log_handle,
10589430SRaymond.Chen@Sun.COM 	    "hwahc_alloc_hcdi_ops:");
10599430SRaymond.Chen@Sun.COM 
10609430SRaymond.Chen@Sun.COM 	usba_hcdi_ops = usba_alloc_hcdi_ops();
10619430SRaymond.Chen@Sun.COM 
10629430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_ops_version = HCDI_OPS_VERSION;
10639430SRaymond.Chen@Sun.COM 
10649430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pm_support = hwahc_hcdi_pm_support;
10659430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_open = hwahc_hcdi_pipe_open;
10669430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_close = hwahc_hcdi_pipe_close;
10679430SRaymond.Chen@Sun.COM 
10689430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_reset = hwahc_hcdi_pipe_reset;
10699430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_reset_data_toggle =
10709430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_pipe_reset_data_toggle;
10719430SRaymond.Chen@Sun.COM 
10729430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_ctrl_xfer = hwahc_hcdi_pipe_ctrl_xfer;
10739430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_bulk_xfer = hwahc_hcdi_pipe_bulk_xfer;
10749430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_intr_xfer = hwahc_hcdi_pipe_intr_xfer;
10759430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_isoc_xfer = hwahc_hcdi_pipe_isoc_xfer;
10769430SRaymond.Chen@Sun.COM 
10779430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_bulk_transfer_size =
10789430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_bulk_transfer_size;
10799430SRaymond.Chen@Sun.COM 
10809430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_stop_intr_polling =
10819430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_pipe_stop_intr_polling;
10829430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_pipe_stop_isoc_polling =
10839430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_pipe_stop_isoc_polling;
10849430SRaymond.Chen@Sun.COM 
10859430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_get_current_frame_number =
10869430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_get_current_frame_number;
10879430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_get_max_isoc_pkts =
10889430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_get_max_isoc_pkts;
10899430SRaymond.Chen@Sun.COM 
10909430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_console_input_init =
10919430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_polled_input_init;
10929430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_console_input_enter =
10939430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_polled_input_enter;
10949430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_console_read =
10959430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_polled_read;
10969430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_console_input_exit =
10979430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_polled_input_exit;
10989430SRaymond.Chen@Sun.COM 	usba_hcdi_ops->usba_hcdi_console_input_fini =
10999430SRaymond.Chen@Sun.COM 	    hwahc_hcdi_polled_input_fini;
11009430SRaymond.Chen@Sun.COM 
11019430SRaymond.Chen@Sun.COM 	return (usba_hcdi_ops);
11029430SRaymond.Chen@Sun.COM }
11039430SRaymond.Chen@Sun.COM 
11049430SRaymond.Chen@Sun.COM 
11059430SRaymond.Chen@Sun.COM /*
11069430SRaymond.Chen@Sun.COM  * Set cluster ID.
11079430SRaymond.Chen@Sun.COM  * see 8.5.3.11
11089430SRaymond.Chen@Sun.COM  */
11099430SRaymond.Chen@Sun.COM int
hwahc_set_cluster_id(dev_info_t * dip,uint8_t cluster_id)11109430SRaymond.Chen@Sun.COM hwahc_set_cluster_id(dev_info_t *dip, uint8_t cluster_id)
11119430SRaymond.Chen@Sun.COM {
11129430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
11139430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
11149430SRaymond.Chen@Sun.COM 	int		rval;
11159430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
11169430SRaymond.Chen@Sun.COM 
11179430SRaymond.Chen@Sun.COM 	if (dip == NULL) {
11189430SRaymond.Chen@Sun.COM 
11199430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
11209430SRaymond.Chen@Sun.COM 	}
11219430SRaymond.Chen@Sun.COM 
11229430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
11239430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
11249430SRaymond.Chen@Sun.COM 
11259430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
11269430SRaymond.Chen@Sun.COM 	}
11279430SRaymond.Chen@Sun.COM 
11289430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
11299430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
11309430SRaymond.Chen@Sun.COM 	    HWA_REQ_SET_CLUSTER_ID,
11319430SRaymond.Chen@Sun.COM 	    cluster_id,
11329430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_wa_data.wa_ifno,
11339430SRaymond.Chen@Sun.COM 	    0,
11349430SRaymond.Chen@Sun.COM 	    NULL, 0,
11359430SRaymond.Chen@Sun.COM 	    &completion_reason, &cb_flags, 0);
11369430SRaymond.Chen@Sun.COM 
11379430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
11389430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
11399430SRaymond.Chen@Sun.COM 		    "Set_Cluster_ID fails: rval=%d cr=%d cb=0x%x",
11409430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
11419430SRaymond.Chen@Sun.COM 	}
11429430SRaymond.Chen@Sun.COM 
11439430SRaymond.Chen@Sun.COM 	return (rval);
11449430SRaymond.Chen@Sun.COM }
11459430SRaymond.Chen@Sun.COM 
11469430SRaymond.Chen@Sun.COM /*
11479430SRaymond.Chen@Sun.COM  * Set WUSB Stream Index. see 8.5.3.13
11489430SRaymond.Chen@Sun.COM  */
11499430SRaymond.Chen@Sun.COM int
hwahc_set_stream_idx(dev_info_t * dip,uint8_t stream_idx)11509430SRaymond.Chen@Sun.COM hwahc_set_stream_idx(dev_info_t *dip, uint8_t stream_idx)
11519430SRaymond.Chen@Sun.COM {
11529430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
11539430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
11549430SRaymond.Chen@Sun.COM 	int		rval;
11559430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
11569430SRaymond.Chen@Sun.COM 
11579430SRaymond.Chen@Sun.COM 	if ((dip == NULL))  {
11589430SRaymond.Chen@Sun.COM 
11599430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
11609430SRaymond.Chen@Sun.COM 	}
11619430SRaymond.Chen@Sun.COM 
11629430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
11639430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
11649430SRaymond.Chen@Sun.COM 
11659430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
11669430SRaymond.Chen@Sun.COM 	}
11679430SRaymond.Chen@Sun.COM 
11689430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
11699430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
11709430SRaymond.Chen@Sun.COM 	    HWA_REQ_SET_STREAM_IDX,
11719430SRaymond.Chen@Sun.COM 	    stream_idx,
11729430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_wa_data.wa_ifno,
11739430SRaymond.Chen@Sun.COM 	    0, NULL, 0, &completion_reason,
11749430SRaymond.Chen@Sun.COM 	    &cb_flags, 0);
11759430SRaymond.Chen@Sun.COM 
11769430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
11779430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
11789430SRaymond.Chen@Sun.COM 		    "Set_Stream_Idx fails: rval=%d cr=%d cb=0x%x",
11799430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
11809430SRaymond.Chen@Sun.COM 	}
11819430SRaymond.Chen@Sun.COM 
11829430SRaymond.Chen@Sun.COM 	return (rval);
11839430SRaymond.Chen@Sun.COM }
11849430SRaymond.Chen@Sun.COM 
11859430SRaymond.Chen@Sun.COM /*
11869430SRaymond.Chen@Sun.COM  * 8.5.3.12 - Set WUSB MAS
11879430SRaymond.Chen@Sun.COM  *	Caller must ensure the data is WUSB_SET_WUSB_MAS_LEN long.
11889430SRaymond.Chen@Sun.COM  */
11899430SRaymond.Chen@Sun.COM int
hwahc_set_wusb_mas(dev_info_t * dip,uint8_t * data)11909430SRaymond.Chen@Sun.COM hwahc_set_wusb_mas(dev_info_t *dip, uint8_t *data)
11919430SRaymond.Chen@Sun.COM {
11929430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
11939430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
11949430SRaymond.Chen@Sun.COM 	mblk_t		*blk;
11959430SRaymond.Chen@Sun.COM 	int		rval, i;
11969430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
11979430SRaymond.Chen@Sun.COM 
11989430SRaymond.Chen@Sun.COM 	if ((dip == NULL))  {
11999430SRaymond.Chen@Sun.COM 
12009430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
12019430SRaymond.Chen@Sun.COM 	}
12029430SRaymond.Chen@Sun.COM 
12039430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
12049430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
12059430SRaymond.Chen@Sun.COM 
12069430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
12079430SRaymond.Chen@Sun.COM 	}
12089430SRaymond.Chen@Sun.COM 
12099430SRaymond.Chen@Sun.COM 	blk = allocb_wait(WUSB_SET_WUSB_MAS_LEN, BPRI_LO, STR_NOSIG, NULL);
12109430SRaymond.Chen@Sun.COM 
12119430SRaymond.Chen@Sun.COM 	for (i = 0; i < WUSB_SET_WUSB_MAS_LEN; i++) {
12129430SRaymond.Chen@Sun.COM 		*blk->b_wptr++ = data[i];
12139430SRaymond.Chen@Sun.COM 	}
12149430SRaymond.Chen@Sun.COM 
12159430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
12169430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
12179430SRaymond.Chen@Sun.COM 	    HWA_REQ_SET_WUSB_MAS,
12189430SRaymond.Chen@Sun.COM 	    0,
12199430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_wa_data.wa_ifno,
12209430SRaymond.Chen@Sun.COM 	    WUSB_SET_WUSB_MAS_LEN,
12219430SRaymond.Chen@Sun.COM 	    &blk, 0,
12229430SRaymond.Chen@Sun.COM 	    &completion_reason, &cb_flags, 0);
12239430SRaymond.Chen@Sun.COM 
12249430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
12259430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
12269430SRaymond.Chen@Sun.COM 		    "Set_WUSB_MAS fails: rval=%d cr=%d cb=0x%x",
12279430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
12289430SRaymond.Chen@Sun.COM 	}
12299430SRaymond.Chen@Sun.COM 	freemsg(blk);
12309430SRaymond.Chen@Sun.COM 
12319430SRaymond.Chen@Sun.COM 	return (rval);
12329430SRaymond.Chen@Sun.COM }
12339430SRaymond.Chen@Sun.COM 
12349430SRaymond.Chen@Sun.COM /* 8.5.3.1 - Add MMC IE */
12359430SRaymond.Chen@Sun.COM int
hwahc_add_mmc_ie(dev_info_t * dip,uint8_t interval,uint8_t rcnt,uint8_t iehdl,uint16_t len,uint8_t * data)12369430SRaymond.Chen@Sun.COM hwahc_add_mmc_ie(dev_info_t *dip, uint8_t interval, uint8_t rcnt,
12379430SRaymond.Chen@Sun.COM 	uint8_t iehdl, uint16_t len, uint8_t *data)
12389430SRaymond.Chen@Sun.COM {
12399430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
12409430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
12419430SRaymond.Chen@Sun.COM 	mblk_t		*blk;
12429430SRaymond.Chen@Sun.COM 	int		i, rval;
12439430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
12449430SRaymond.Chen@Sun.COM 
12459430SRaymond.Chen@Sun.COM 	if (dip == NULL)  {
12469430SRaymond.Chen@Sun.COM 
12479430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
12489430SRaymond.Chen@Sun.COM 	}
12499430SRaymond.Chen@Sun.COM 
12509430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
12519430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
12529430SRaymond.Chen@Sun.COM 
12539430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
12549430SRaymond.Chen@Sun.COM 	}
12559430SRaymond.Chen@Sun.COM 
12569430SRaymond.Chen@Sun.COM 	blk = allocb_wait(len, BPRI_LO, STR_NOSIG, NULL);
12579430SRaymond.Chen@Sun.COM 
12589430SRaymond.Chen@Sun.COM 	for (i = 0; i < len; i++) {
12599430SRaymond.Chen@Sun.COM 		*blk->b_wptr++ = data[i];
12609430SRaymond.Chen@Sun.COM 	}
12619430SRaymond.Chen@Sun.COM 
12629430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
12639430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
12649430SRaymond.Chen@Sun.COM 	    HWA_REQ_ADD_MMC_IE,
12659430SRaymond.Chen@Sun.COM 	    (interval << 8) | rcnt,
12669430SRaymond.Chen@Sun.COM 	    (iehdl << 8) | hwahcp->hwahc_wa_data.wa_ifno,
12679430SRaymond.Chen@Sun.COM 	    len,
12689430SRaymond.Chen@Sun.COM 	    &blk, 0,
12699430SRaymond.Chen@Sun.COM 	    &completion_reason, &cb_flags, 0);
12709430SRaymond.Chen@Sun.COM 
12719430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
12729430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
12739430SRaymond.Chen@Sun.COM 		    "Add_MMC_IE fails: rval=%d cr=%d cb=0x%x",
12749430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
12759430SRaymond.Chen@Sun.COM 	}
12769430SRaymond.Chen@Sun.COM 
12779430SRaymond.Chen@Sun.COM 	freemsg(blk);
12789430SRaymond.Chen@Sun.COM 
12799430SRaymond.Chen@Sun.COM 	return (rval);
12809430SRaymond.Chen@Sun.COM }
12819430SRaymond.Chen@Sun.COM 
12829430SRaymond.Chen@Sun.COM /* 8.5.3.5 - Remove MMC IE */
12839430SRaymond.Chen@Sun.COM int
hwahc_remove_mmc_ie(dev_info_t * dip,uint8_t iehdl)12849430SRaymond.Chen@Sun.COM hwahc_remove_mmc_ie(dev_info_t *dip, uint8_t iehdl)
12859430SRaymond.Chen@Sun.COM {
12869430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
12879430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
12889430SRaymond.Chen@Sun.COM 	int		rval;
12899430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
12909430SRaymond.Chen@Sun.COM 
12919430SRaymond.Chen@Sun.COM 	if (dip == NULL) {
12929430SRaymond.Chen@Sun.COM 
12939430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
12949430SRaymond.Chen@Sun.COM 	}
12959430SRaymond.Chen@Sun.COM 
12969430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
12979430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
12989430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
12999430SRaymond.Chen@Sun.COM 	}
13009430SRaymond.Chen@Sun.COM 
13019430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
13029430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
13039430SRaymond.Chen@Sun.COM 	    HWA_REQ_REMOVE_MMC_IE,
13049430SRaymond.Chen@Sun.COM 	    0,
13059430SRaymond.Chen@Sun.COM 	    (iehdl << 8) | hwahcp->hwahc_wa_data.wa_ifno,
13069430SRaymond.Chen@Sun.COM 	    0,
13079430SRaymond.Chen@Sun.COM 	    NULL, 0,
13089430SRaymond.Chen@Sun.COM 	    &completion_reason, &cb_flags, 0);
13099430SRaymond.Chen@Sun.COM 
13109430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
13119430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
13129430SRaymond.Chen@Sun.COM 		    "Remove_MMC_IE fails: rval=%d cr=%d cb=0x%x",
13139430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
13149430SRaymond.Chen@Sun.COM 	}
13159430SRaymond.Chen@Sun.COM 
13169430SRaymond.Chen@Sun.COM 	return (rval);
13179430SRaymond.Chen@Sun.COM }
13189430SRaymond.Chen@Sun.COM 
13199430SRaymond.Chen@Sun.COM /* 8.5.3.14 - WUSB Channel Stop */
13209430SRaymond.Chen@Sun.COM int
hwahc_stop_ch(dev_info_t * dip,uint32_t timeoff)13219430SRaymond.Chen@Sun.COM hwahc_stop_ch(dev_info_t *dip, uint32_t timeoff)
13229430SRaymond.Chen@Sun.COM {
13239430SRaymond.Chen@Sun.COM 	int		rval;
13249430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
13259430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
13269430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
13279430SRaymond.Chen@Sun.COM 
13289430SRaymond.Chen@Sun.COM 	if (dip == NULL) {
13299430SRaymond.Chen@Sun.COM 
13309430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
13319430SRaymond.Chen@Sun.COM 	}
13329430SRaymond.Chen@Sun.COM 
13339430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
13349430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
13359430SRaymond.Chen@Sun.COM 
13369430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
13379430SRaymond.Chen@Sun.COM 	}
13389430SRaymond.Chen@Sun.COM 
13399430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
13409430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
13419430SRaymond.Chen@Sun.COM 	    HWA_REQ_CH_STOP,
13429430SRaymond.Chen@Sun.COM 	    timeoff & 0x00ffffff,
13439430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_wa_data.wa_ifno,
13449430SRaymond.Chen@Sun.COM 	    0,
13459430SRaymond.Chen@Sun.COM 	    NULL, 0,
13469430SRaymond.Chen@Sun.COM 	    &completion_reason, &cb_flags, 0);
13479430SRaymond.Chen@Sun.COM 
13489430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
13499430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
13509430SRaymond.Chen@Sun.COM 		    "WUSB_Ch_Stop fails: rval=%d cr=%d cb=0x%x",
13519430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
13529430SRaymond.Chen@Sun.COM 	}
13539430SRaymond.Chen@Sun.COM 
13549430SRaymond.Chen@Sun.COM 	return (rval);
13559430SRaymond.Chen@Sun.COM }
13569430SRaymond.Chen@Sun.COM 
13579430SRaymond.Chen@Sun.COM /* 8.5. 3.10 - Set Num DNTS Slots */
13589430SRaymond.Chen@Sun.COM int
hwahc_set_num_dnts(dev_info_t * dip,uint8_t interval,uint8_t nslots)13599430SRaymond.Chen@Sun.COM hwahc_set_num_dnts(dev_info_t *dip, uint8_t interval, uint8_t nslots)
13609430SRaymond.Chen@Sun.COM {
13619430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
13629430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
13639430SRaymond.Chen@Sun.COM 	int		rval;
13649430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
13659430SRaymond.Chen@Sun.COM 
13669430SRaymond.Chen@Sun.COM 	if (dip == NULL) {
13679430SRaymond.Chen@Sun.COM 
13689430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
13699430SRaymond.Chen@Sun.COM 	}
13709430SRaymond.Chen@Sun.COM 
13719430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
13729430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
13739430SRaymond.Chen@Sun.COM 
13749430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
13759430SRaymond.Chen@Sun.COM 	}
13769430SRaymond.Chen@Sun.COM 
13779430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
13789430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
13799430SRaymond.Chen@Sun.COM 	    HWA_REQ_SET_NUM_DNTS,
13809430SRaymond.Chen@Sun.COM 	    (interval << 8) | nslots,
13819430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_wa_data.wa_ifno,
13829430SRaymond.Chen@Sun.COM 	    0,
13839430SRaymond.Chen@Sun.COM 	    NULL, 0,
13849430SRaymond.Chen@Sun.COM 	    &completion_reason, &cb_flags, 0);
13859430SRaymond.Chen@Sun.COM 
13869430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
13879430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
13889430SRaymond.Chen@Sun.COM 		    "Set_Num_DNTS fails: rval=%d cr=%d cb=0x%x",
13899430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
13909430SRaymond.Chen@Sun.COM 	}
13919430SRaymond.Chen@Sun.COM 
13929430SRaymond.Chen@Sun.COM 	return (rval);
13939430SRaymond.Chen@Sun.COM }
13949430SRaymond.Chen@Sun.COM 
13959430SRaymond.Chen@Sun.COM /* set encryptiion type for host */
13969430SRaymond.Chen@Sun.COM int
hwahc_set_encrypt(dev_info_t * dip,usb_port_t port,uint8_t type)13979430SRaymond.Chen@Sun.COM hwahc_set_encrypt(dev_info_t *dip, usb_port_t port, uint8_t type)
13989430SRaymond.Chen@Sun.COM {
13999430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
14009430SRaymond.Chen@Sun.COM 	int		rval;
14019430SRaymond.Chen@Sun.COM 
14029430SRaymond.Chen@Sun.COM 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
14039430SRaymond.Chen@Sun.COM 	    ddi_get_instance(dip))) == NULL) {
14049430SRaymond.Chen@Sun.COM 
14059430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
14069430SRaymond.Chen@Sun.COM 	}
14079430SRaymond.Chen@Sun.COM 	/* DEVICE INDEX */
14089430SRaymond.Chen@Sun.COM 	rval = hwahc_set_dev_encrypt(hwahcp->hwahc_default_pipe,
14099430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_wa_data.wa_ifno, port - 1,
14109430SRaymond.Chen@Sun.COM 	    &hwahcp->hwahc_secrt_data, type);
14119430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
14129430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle,
14139430SRaymond.Chen@Sun.COM 		    "hwahc_set_encrypt: set device encryption for port %d "
14149430SRaymond.Chen@Sun.COM 		    "failed", port);
14159430SRaymond.Chen@Sun.COM 	}
14169430SRaymond.Chen@Sun.COM 
14179430SRaymond.Chen@Sun.COM 	return (rval);
14189430SRaymond.Chen@Sun.COM }
14199430SRaymond.Chen@Sun.COM 
14209430SRaymond.Chen@Sun.COM 
14219430SRaymond.Chen@Sun.COM /*
14229430SRaymond.Chen@Sun.COM  * Set Device Key for WUSB host, refer to WUSB 1.0/8.5.3.8
14239430SRaymond.Chen@Sun.COM  *
14249430SRaymond.Chen@Sun.COM  * Set group/device key:
14259430SRaymond.Chen@Sun.COM  * devindex = actual port number - 1, so it is zero based
14269430SRaymond.Chen@Sun.COM  *
14279430SRaymond.Chen@Sun.COM  */
hwahc_set_keys(hwahc_state_t * hwahcp,usb_key_descr_t * key_descr,size_t klen,uint8_t devindex,uint8_t keydex,uint8_t flag)14289430SRaymond.Chen@Sun.COM int hwahc_set_keys(hwahc_state_t *hwahcp, usb_key_descr_t *key_descr,
14299430SRaymond.Chen@Sun.COM     size_t klen, uint8_t devindex, uint8_t keydex, uint8_t flag)
14309430SRaymond.Chen@Sun.COM {
14319430SRaymond.Chen@Sun.COM 	usb_ctrl_setup_t	setup;
14329430SRaymond.Chen@Sun.COM 	usb_cr_t		cr;
14339430SRaymond.Chen@Sun.COM 	usb_cb_flags_t		cb_flags;
14349430SRaymond.Chen@Sun.COM 	mblk_t			*pdata;
14359430SRaymond.Chen@Sun.COM 	int			rval;
14369430SRaymond.Chen@Sun.COM 	uint8_t			keyindex;
14379430SRaymond.Chen@Sun.COM 
14389430SRaymond.Chen@Sun.COM 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
14399430SRaymond.Chen@Sun.COM 	    "hwahc_set_keys: klen = %d, devindex = %d", (int)klen,
14409430SRaymond.Chen@Sun.COM 	    devindex);
14419430SRaymond.Chen@Sun.COM 
14429430SRaymond.Chen@Sun.COM 	/* Table 7-21 and Errata 2005/07 */
14439430SRaymond.Chen@Sun.COM 	if (flag == WUSB_GTK) {
14449430SRaymond.Chen@Sun.COM 		if (devindex != 0) {
14459430SRaymond.Chen@Sun.COM 			return (USB_FAILURE);
14469430SRaymond.Chen@Sun.COM 		}
14479430SRaymond.Chen@Sun.COM 
14489430SRaymond.Chen@Sun.COM 		/* See 7.3.2.4 for key index format */
14499430SRaymond.Chen@Sun.COM 		keyindex = (1 << 5) | keydex;
14509430SRaymond.Chen@Sun.COM 	} else if (flag == WUSB_PTK) {
14519430SRaymond.Chen@Sun.COM 
14529430SRaymond.Chen@Sun.COM 		keyindex = keydex;
14539430SRaymond.Chen@Sun.COM 	} else {
14549430SRaymond.Chen@Sun.COM 
14559430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
14569430SRaymond.Chen@Sun.COM 	}
14579430SRaymond.Chen@Sun.COM 
14589430SRaymond.Chen@Sun.COM 	setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV |
14599430SRaymond.Chen@Sun.COM 	    USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF;
14609430SRaymond.Chen@Sun.COM 	setup.bRequest = USB_REQ_SET_DESCR;
14619430SRaymond.Chen@Sun.COM 	setup.wValue = (USB_DESCR_TYPE_KEY << 8) | keyindex;
14629430SRaymond.Chen@Sun.COM 	setup.wIndex = devindex << 8 | hwahcp->hwahc_wa_data.wa_ifno;
14639430SRaymond.Chen@Sun.COM 	setup.wLength = (uint16_t)klen;
14649430SRaymond.Chen@Sun.COM 	setup.attrs = USB_ATTRS_NONE;
14659430SRaymond.Chen@Sun.COM 
14669430SRaymond.Chen@Sun.COM 	if ((pdata = allocb(klen, BPRI_HI)) == NULL) {
14679430SRaymond.Chen@Sun.COM 
14689430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
14699430SRaymond.Chen@Sun.COM 	}
14709430SRaymond.Chen@Sun.COM 	bcopy(key_descr, pdata->b_wptr, klen);
14719430SRaymond.Chen@Sun.COM 	pdata->b_wptr += klen;
14729430SRaymond.Chen@Sun.COM 
14739430SRaymond.Chen@Sun.COM 	rval = usb_pipe_ctrl_xfer_wait(hwahcp->hwahc_default_pipe, &setup,
14749430SRaymond.Chen@Sun.COM 	    &pdata, &cr, &cb_flags, USB_FLAGS_SLEEP);
14759430SRaymond.Chen@Sun.COM 
14769430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
14779430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
14789430SRaymond.Chen@Sun.COM 		    "hwahc_set_keys:fail, rv=%d,cr=%d,cb=%d", rval, cr,
14799430SRaymond.Chen@Sun.COM 		    cb_flags);
14809430SRaymond.Chen@Sun.COM 	}
14819430SRaymond.Chen@Sun.COM 
14829430SRaymond.Chen@Sun.COM 	freemsg(pdata);
14839430SRaymond.Chen@Sun.COM 
14849430SRaymond.Chen@Sun.COM 	return (rval);
14859430SRaymond.Chen@Sun.COM }
14869430SRaymond.Chen@Sun.COM 
14879430SRaymond.Chen@Sun.COM /* set PTK for host */
14889430SRaymond.Chen@Sun.COM int
hwahc_set_ptk(dev_info_t * dip,usb_key_descr_t * key_descr,size_t klen,usb_port_t port)14899430SRaymond.Chen@Sun.COM hwahc_set_ptk(dev_info_t *dip, usb_key_descr_t *key_descr, size_t klen,
14909430SRaymond.Chen@Sun.COM 	usb_port_t port)
14919430SRaymond.Chen@Sun.COM {
14929430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp;
14939430SRaymond.Chen@Sun.COM 	int		rval;
14949430SRaymond.Chen@Sun.COM 	uint8_t		keyindex = 1;
14959430SRaymond.Chen@Sun.COM 
14969430SRaymond.Chen@Sun.COM 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
14979430SRaymond.Chen@Sun.COM 	    ddi_get_instance(dip))) == NULL) {
14989430SRaymond.Chen@Sun.COM 
14999430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
15009430SRaymond.Chen@Sun.COM 	}
15019430SRaymond.Chen@Sun.COM 	/* DEVICE INDEX */
15029430SRaymond.Chen@Sun.COM 	rval = hwahc_set_keys(hwahcp, key_descr, klen, port - 1, keyindex,
15039430SRaymond.Chen@Sun.COM 	    WUSB_PTK);
15049430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
15059430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle,
15069430SRaymond.Chen@Sun.COM 		    "hwahc_set_ptk: set device key descr for port %d "
15079430SRaymond.Chen@Sun.COM 		    "failed", port);
15089430SRaymond.Chen@Sun.COM 	}
15099430SRaymond.Chen@Sun.COM 
15109430SRaymond.Chen@Sun.COM 	return (rval);
15119430SRaymond.Chen@Sun.COM }
15129430SRaymond.Chen@Sun.COM 
15139430SRaymond.Chen@Sun.COM /* set GTK for host */
15149430SRaymond.Chen@Sun.COM int
hwahc_set_gtk(dev_info_t * dip,usb_key_descr_t * key_descr,size_t klen)15159430SRaymond.Chen@Sun.COM hwahc_set_gtk(dev_info_t *dip, usb_key_descr_t *key_descr, size_t klen)
15169430SRaymond.Chen@Sun.COM {
15179430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
15189430SRaymond.Chen@Sun.COM 	int			rval;
15199430SRaymond.Chen@Sun.COM 
15209430SRaymond.Chen@Sun.COM 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
15219430SRaymond.Chen@Sun.COM 	    ddi_get_instance(dip))) == NULL) {
15229430SRaymond.Chen@Sun.COM 
15239430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
15249430SRaymond.Chen@Sun.COM 	}
15259430SRaymond.Chen@Sun.COM 
15269430SRaymond.Chen@Sun.COM 	rval = hwahc_set_keys(hwahcp, key_descr, klen, 0, 0, WUSB_GTK);
15279430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
15289430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle,
15299430SRaymond.Chen@Sun.COM 		    "hwahc_set_gtk: set group key descr failed");
15309430SRaymond.Chen@Sun.COM 	}
15319430SRaymond.Chen@Sun.COM 
15329430SRaymond.Chen@Sun.COM 	return (rval);
15339430SRaymond.Chen@Sun.COM }
15349430SRaymond.Chen@Sun.COM 
15359430SRaymond.Chen@Sun.COM /*
15369430SRaymond.Chen@Sun.COM  * set device info for host
15379430SRaymond.Chen@Sun.COM  * Section 8.5.3.7.
15389430SRaymond.Chen@Sun.COM  */
15399430SRaymond.Chen@Sun.COM int
hwahc_set_device_info(dev_info_t * dip,wusb_dev_info_t * dev_info,usb_port_t port)15409430SRaymond.Chen@Sun.COM hwahc_set_device_info(dev_info_t *dip, wusb_dev_info_t *dev_info,
15419430SRaymond.Chen@Sun.COM 	usb_port_t port)
15429430SRaymond.Chen@Sun.COM {
15439430SRaymond.Chen@Sun.COM 	hwahc_state_t		*hwahcp;
15449430SRaymond.Chen@Sun.COM 	int			rval;
15459430SRaymond.Chen@Sun.COM 	hwa_dev_info_t		info;
15469430SRaymond.Chen@Sun.COM 	usb_ctrl_setup_t	setup;
15479430SRaymond.Chen@Sun.COM 	usb_cr_t		cr;
15489430SRaymond.Chen@Sun.COM 	usb_cb_flags_t		cb_flags;
15499430SRaymond.Chen@Sun.COM 	mblk_t			*pdata;
15509430SRaymond.Chen@Sun.COM 
15519430SRaymond.Chen@Sun.COM 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
15529430SRaymond.Chen@Sun.COM 	    ddi_get_instance(dip))) == NULL) {
15539430SRaymond.Chen@Sun.COM 
15549430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
15559430SRaymond.Chen@Sun.COM 	}
15569430SRaymond.Chen@Sun.COM 
15579430SRaymond.Chen@Sun.COM 	/* the device can use all the host's reserved MASes to communicate */
15589430SRaymond.Chen@Sun.COM 	(void) memcpy(info.bmDeviceAvailablilityInfo,
15599430SRaymond.Chen@Sun.COM 	    hwahcp->hwahc_hc_data.hc_mas, WUSB_SET_WUSB_MAS_LEN);
15609430SRaymond.Chen@Sun.COM 
15619430SRaymond.Chen@Sun.COM 	info.bDeviceAddress = dev_info->wdev_addr;
15629430SRaymond.Chen@Sun.COM 
15639430SRaymond.Chen@Sun.COM 	/* To tell HWA device what data rates this child device supports */
15649430SRaymond.Chen@Sun.COM 	if (dev_info->wdev_uwb_descr == NULL) {
15659430SRaymond.Chen@Sun.COM 		/* bitmap, see7.4.1.1. Must support 53.3/106.7/200 Mbps */
15669430SRaymond.Chen@Sun.COM 		info.wPHYRates[0] = WUSB_DATA_RATE_BIT_53 |
15679430SRaymond.Chen@Sun.COM 		    WUSB_DATA_RATE_BIT_106 | WUSB_DATA_RATE_BIT_200;
15689430SRaymond.Chen@Sun.COM 		info.wPHYRates[1] = 0;
15699430SRaymond.Chen@Sun.COM 	} else {
15709430SRaymond.Chen@Sun.COM 		info.wPHYRates[0] =
15719430SRaymond.Chen@Sun.COM 		    dev_info->wdev_uwb_descr->wPHYRates && 0xff;
15729430SRaymond.Chen@Sun.COM 		info.wPHYRates[1] =
15739430SRaymond.Chen@Sun.COM 		    (dev_info->wdev_uwb_descr->wPHYRates >> 8) && 0xff;
15749430SRaymond.Chen@Sun.COM 	}
15759430SRaymond.Chen@Sun.COM 	info.bmDeviceAttribute = 0;
15769430SRaymond.Chen@Sun.COM 
15779430SRaymond.Chen@Sun.COM 	setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV |
15789430SRaymond.Chen@Sun.COM 	    USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF;
15799430SRaymond.Chen@Sun.COM 	setup.bRequest = HWA_REQ_SET_DEVICE_INFO;
15809430SRaymond.Chen@Sun.COM 	setup.wValue = 0;
15819430SRaymond.Chen@Sun.COM 
15829430SRaymond.Chen@Sun.COM 	/* DEVICE INDEX */
15839430SRaymond.Chen@Sun.COM 	setup.wIndex = (port - 1) << 8 | hwahcp->hwahc_wa_data.wa_ifno;
15849430SRaymond.Chen@Sun.COM 	setup.wLength = WUSB_SET_DEV_INFO_LEN;
15859430SRaymond.Chen@Sun.COM 	setup.attrs = USB_ATTRS_NONE;
15869430SRaymond.Chen@Sun.COM 
15879430SRaymond.Chen@Sun.COM 	if ((pdata = allocb(WUSB_SET_DEV_INFO_LEN, BPRI_HI)) == NULL) {
15889430SRaymond.Chen@Sun.COM 
15899430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
15909430SRaymond.Chen@Sun.COM 	}
15919430SRaymond.Chen@Sun.COM 	bcopy(&info, pdata->b_wptr, WUSB_SET_DEV_INFO_LEN);
15929430SRaymond.Chen@Sun.COM 	pdata->b_wptr += WUSB_SET_DEV_INFO_LEN;
15939430SRaymond.Chen@Sun.COM 
15949430SRaymond.Chen@Sun.COM 	rval = usb_pipe_ctrl_xfer_wait(hwahcp->hwahc_default_pipe, &setup,
15959430SRaymond.Chen@Sun.COM 	    &pdata, &cr, &cb_flags, USB_FLAGS_SLEEP);
15969430SRaymond.Chen@Sun.COM 
15979430SRaymond.Chen@Sun.COM 	freemsg(pdata);
15989430SRaymond.Chen@Sun.COM 
15999430SRaymond.Chen@Sun.COM 	return (rval);
16009430SRaymond.Chen@Sun.COM }
16019430SRaymond.Chen@Sun.COM 
16029430SRaymond.Chen@Sun.COM /*
16039430SRaymond.Chen@Sun.COM  * 8.5.3.2 - 8.5.3.4 Get Time
16049430SRaymond.Chen@Sun.COM  * time_type:
16059430SRaymond.Chen@Sun.COM  *	WUSB_TIME_ADJ	- Get BPST Adjustment
16069430SRaymond.Chen@Sun.COM  *	WUSB_TIME_BPST	- Get BPST Time
16079430SRaymond.Chen@Sun.COM  *	WUSB_TIME_WUSB	- Get WUSB Time
16089430SRaymond.Chen@Sun.COM  */
16099430SRaymond.Chen@Sun.COM int
hwahc_get_time(dev_info_t * dip,uint8_t time_type,uint16_t len,uint32_t * time)16109430SRaymond.Chen@Sun.COM hwahc_get_time(dev_info_t *dip, uint8_t time_type,
16119430SRaymond.Chen@Sun.COM     uint16_t len, uint32_t *time)
16129430SRaymond.Chen@Sun.COM {
16139430SRaymond.Chen@Sun.COM 	usb_cr_t	completion_reason;
16149430SRaymond.Chen@Sun.COM 	usb_cb_flags_t	cb_flags;
16159430SRaymond.Chen@Sun.COM 	mblk_t		*blk = NULL;
16169430SRaymond.Chen@Sun.COM 	int		rval;
16179430SRaymond.Chen@Sun.COM 	uint8_t		*data;
16189430SRaymond.Chen@Sun.COM 	uint16_t	length;
16199430SRaymond.Chen@Sun.COM 	hwahc_state_t	*hwahcp = NULL;
16209430SRaymond.Chen@Sun.COM 
16219430SRaymond.Chen@Sun.COM 	if (dip == NULL) {
16229430SRaymond.Chen@Sun.COM 
16239430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
16249430SRaymond.Chen@Sun.COM 	}
16259430SRaymond.Chen@Sun.COM 
16269430SRaymond.Chen@Sun.COM 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
16279430SRaymond.Chen@Sun.COM 	if (hwahcp == NULL) {
16289430SRaymond.Chen@Sun.COM 
16299430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
16309430SRaymond.Chen@Sun.COM 	}
16319430SRaymond.Chen@Sun.COM 
16329430SRaymond.Chen@Sun.COM 	/* according to WUSB 8.5.3, len is 1 or 3 */
16339430SRaymond.Chen@Sun.COM 	if ((len != 1) && (len != 3)) {
16349430SRaymond.Chen@Sun.COM 
16359430SRaymond.Chen@Sun.COM 		return (USB_INVALID_ARGS);
16369430SRaymond.Chen@Sun.COM 	}
16379430SRaymond.Chen@Sun.COM 
16389430SRaymond.Chen@Sun.COM 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
16399430SRaymond.Chen@Sun.COM 	    WUSB_CLASS_IF_REQ_OUT_TYPE, HWA_REQ_GET_TIME,
16409430SRaymond.Chen@Sun.COM 	    time_type, hwahcp->hwahc_wa_data.wa_ifno,
16419430SRaymond.Chen@Sun.COM 	    len, &blk, 0, &completion_reason, &cb_flags, 0);
16429430SRaymond.Chen@Sun.COM 
16439430SRaymond.Chen@Sun.COM 	if (rval != USB_SUCCESS) {
16449430SRaymond.Chen@Sun.COM 		freemsg(blk);
16459430SRaymond.Chen@Sun.COM 
16469430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
16479430SRaymond.Chen@Sun.COM 		    "Get_Time fails: rval=%d cr=%d cb=0x%x",
16489430SRaymond.Chen@Sun.COM 		    rval, completion_reason, cb_flags);
16499430SRaymond.Chen@Sun.COM 
16509430SRaymond.Chen@Sun.COM 		return (rval);
16519430SRaymond.Chen@Sun.COM 	} else if (blk == NULL) {
16529430SRaymond.Chen@Sun.COM 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
16539430SRaymond.Chen@Sun.COM 		    "Get_Time returns null data");
16549430SRaymond.Chen@Sun.COM 
16559430SRaymond.Chen@Sun.COM 		return (USB_FAILURE);
16569430SRaymond.Chen@Sun.COM 	} else {
16579430SRaymond.Chen@Sun.COM 		length = MBLKL(blk);
16589430SRaymond.Chen@Sun.COM 
16599430SRaymond.Chen@Sun.COM 		if (length < len) {
16609430SRaymond.Chen@Sun.COM 			freemsg(blk);
16619430SRaymond.Chen@Sun.COM 
16629430SRaymond.Chen@Sun.COM 			USB_DPRINTF_L2(PRINT_MASK_HCDI,
16639430SRaymond.Chen@Sun.COM 			    hwahcp->hwahc_log_handle,
16649430SRaymond.Chen@Sun.COM 			    "Get_Time returns short length %d", length);
16659430SRaymond.Chen@Sun.COM 
16669430SRaymond.Chen@Sun.COM 			return (USB_FAILURE);
16679430SRaymond.Chen@Sun.COM 		}
16689430SRaymond.Chen@Sun.COM 
16699430SRaymond.Chen@Sun.COM 		data = blk->b_rptr;
16709430SRaymond.Chen@Sun.COM 		if (len == 1) {
16719430SRaymond.Chen@Sun.COM 			*time = *data;
16729430SRaymond.Chen@Sun.COM 		} else {
16739430SRaymond.Chen@Sun.COM 			*time = (data[2] << 16) | (data[1] << 8) | data[0];
16749430SRaymond.Chen@Sun.COM 		}
16759430SRaymond.Chen@Sun.COM 		freemsg(blk);
16769430SRaymond.Chen@Sun.COM 
16779430SRaymond.Chen@Sun.COM 		return (USB_SUCCESS);
16789430SRaymond.Chen@Sun.COM 	}
16799430SRaymond.Chen@Sun.COM }
1680