xref: /onnv-gate/usr/src/uts/common/io/usb/hwa/hwahc/hwahc_util.c (revision 10912:bb04b6e33d44)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * The Data Transfer Interface driver for Host Wire Adapter device
28  *
29  * This file mainly contains the entries for HCDI interfaces.
30  */
31 #include <sys/usb/usba/usba_impl.h> /* usba_get_dip */
32 #include <sys/usb/hwa/hwahc/hwahc.h>
33 #include <sys/usb/hwa/hwahc/hwahc_util.h>
34 #include <sys/strsubr.h>
35 #include <sys/strsun.h> /* MBLKL */
36 
37 #define	WUSB_GTK 1
38 #define	WUSB_PTK 2
39 
40 /* function prototypes */
41 static int hwahc_state_is_operational(hwahc_state_t *hwahcp);
42 static hwahc_state_t *hwahc_obtain_state(dev_info_t *dip);
43 static void hwahc_wait_for_xfer_completion(hwahc_state_t *hwahcp,
44 	hwahc_pipe_private_t *pp);
45 static void hwahc_traverse_requests(hwahc_state_t *hwahcp,
46 	hwahc_pipe_private_t *pp);
47 static void hwahc_pipe_cleanup(hwahc_state_t *hwahcp,
48 	usba_pipe_handle_data_t *ph);
49 int hwahc_set_dev_encrypt(usb_pipe_handle_t ph, uint8_t ifc,
50 	usb_port_t index, wusb_secrt_data_t *secrt_data, uint8_t type);
51 
52 static int hwahc_hcdi_pm_support(dev_info_t *dip);
53 static int hwahc_hcdi_pipe_open(usba_pipe_handle_data_t *ph,
54 	usb_flags_t flags);
55 static int hwahc_hcdi_pipe_close(usba_pipe_handle_data_t *ph,
56 	usb_flags_t flags);
57 static int hwahc_hcdi_pipe_reset(usba_pipe_handle_data_t *ph,
58 	usb_flags_t flags);
59 static void hwahc_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t *ph);
60 static int hwahc_hcdi_pipe_ctrl_xfer(usba_pipe_handle_data_t *ph,
61 	usb_ctrl_req_t *ctrl_reqp, usb_flags_t usb_flags);
62 static int hwahc_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t *ph,
63 	usb_bulk_req_t *bulk_reqp, usb_flags_t usb_flags);
64 static int hwahc_hcdi_pipe_intr_xfer(usba_pipe_handle_data_t *ph,
65 	usb_intr_req_t *intr_reqp, usb_flags_t usb_flags);
66 static int hwahc_hcdi_pipe_isoc_xfer(usba_pipe_handle_data_t *ph,
67 	usb_isoc_req_t *isoc_reqp, usb_flags_t usb_flags);
68 static int hwahc_hcdi_bulk_transfer_size(usba_device_t *usba_device,
69 	size_t *size);
70 static int hwahc_hcdi_pipe_stop_intr_polling(usba_pipe_handle_data_t *ph,
71 	usb_flags_t flags);
72 static int hwahc_hcdi_pipe_stop_isoc_polling(usba_pipe_handle_data_t *ph,
73 	usb_flags_t flags);
74 static int hwahc_hcdi_get_current_frame_number(usba_device_t *usba_device,
75 	usb_frame_number_t *frame_number);
76 static int hwahc_hcdi_get_max_isoc_pkts(usba_device_t *usba_device,
77 	uint_t *max_pkts);
78 static int hwahc_hcdi_polled_input_init(usba_pipe_handle_data_t *ph,
79 	uchar_t **polled_buf, usb_console_info_impl_t *console_input_info);
80 static int hwahc_hcdi_polled_input_fini(usb_console_info_impl_t *info);
81 static int hwahc_hcdi_polled_input_enter(usb_console_info_impl_t *info);
82 static int hwahc_hcdi_polled_input_exit(usb_console_info_impl_t *info);
83 static int hwahc_hcdi_polled_read(usb_console_info_impl_t *info,
84 	uint_t *num_characters);
85 usba_hcdi_ops_t *hwahc_alloc_hcdi_ops(hwahc_state_t *hwahcp);
86 
87 extern void *hwahc_statep;
88 
89 /* Check the Host controller state and return proper values */
90 static int
91 hwahc_state_is_operational(hwahc_state_t *hwahcp)
92 {
93 	int	rval;
94 
95 	ASSERT(mutex_owned(&hwahcp->hwahc_mutex));
96 
97 	if (hwahcp->hwahc_dev_state != USB_DEV_ONLINE) {
98 
99 		return (USB_FAILURE);
100 	}
101 
102 	switch (hwahcp->hwahc_hc_soft_state) {
103 	case HWAHC_CTRL_INIT_STATE:
104 		rval = USB_FAILURE;
105 		break;
106 	case HWAHC_CTRL_OPERATIONAL_STATE:
107 		/* still need to check if channel is operational */
108 		if (hwahcp->hwahc_hw_state != HWAHC_HW_STARTED) {
109 			rval = USB_FAILURE;
110 		} else {
111 			rval = USB_SUCCESS;
112 		}
113 
114 		break;
115 	case HWAHC_CTRL_ERROR_STATE:
116 		rval = USB_HC_HARDWARE_ERROR;
117 		break;
118 	default:
119 		rval = USB_FAILURE;
120 		break;
121 	}
122 
123 	return (rval);
124 }
125 
126 /* get soft state pointer */
127 hwahc_state_t *
128 hwahc_obtain_state(dev_info_t *dip)
129 {
130 	int instance = ddi_get_instance(dip);
131 
132 	hwahc_state_t *hwahcp = ddi_get_soft_state(hwahc_statep, instance);
133 
134 	ASSERT(hwahcp != NULL);
135 
136 	return (hwahcp);
137 }
138 
139 
140 /*
141  * Do not support wusb bus PM now
142  */
143 /* ARGSUSED */
144 static int
145 hwahc_hcdi_pm_support(dev_info_t *dip)
146 {
147 	return (USB_FAILURE);
148 }
149 
150 static void
151 /* ARGSUSED */
152 hwahc_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t *ph)
153 {
154 	/* don't do anything now */
155 }
156 
157 /* Wait for processing all completed transfers and to send results */
158 static void
159 hwahc_wait_for_xfer_completion(hwahc_state_t *hwahcp, hwahc_pipe_private_t *pp)
160 {
161 	wusb_wa_rpipe_hdl_t	*hdl = pp->pp_rp;
162 	clock_t			xfer_cmpl_time_wait;
163 
164 	mutex_enter(&hdl->rp_mutex);
165 	if (hdl->rp_state != WA_RPIPE_STATE_ACTIVE) {
166 		mutex_exit(&hdl->rp_mutex);
167 
168 		return;
169 	}
170 	mutex_exit(&hdl->rp_mutex);
171 
172 	/* wait 3s */
173 	xfer_cmpl_time_wait = drv_usectohz(3000000);
174 	(void) cv_timedwait(&pp->pp_xfer_cmpl_cv, &hwahcp->hwahc_mutex,
175 	    ddi_get_lbolt() + xfer_cmpl_time_wait);
176 
177 	mutex_enter(&hdl->rp_mutex);
178 	if (hdl->rp_state == WA_RPIPE_STATE_ACTIVE) {
179 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
180 		    "hwahc_wait_for_xfer_completion: no transfer completion "
181 		    "confirmation received");
182 	}
183 	mutex_exit(&hdl->rp_mutex);
184 }
185 
186 /* remove all the unprocessed requests and do callback */
187 /* ARGSUSED */
188 static void
189 hwahc_traverse_requests(hwahc_state_t *hwahcp, hwahc_pipe_private_t *pp)
190 {
191 	wusb_wa_rpipe_hdl_t	*hdl = pp->pp_rp;
192 	wusb_wa_trans_wrapper_t	*wr;
193 
194 	mutex_enter(&hdl->rp_mutex);
195 
196 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
197 	    "hwahc_traverse_requests: pp = 0x%p, wr=%p", (void*)pp,
198 	    (void *)hdl->rp_curr_wr);
199 
200 	wr = hdl->rp_curr_wr;
201 	if (wr != NULL) {
202 		wusb_wa_stop_xfer_timer(wr);
203 		hdl->rp_state = WA_RPIPE_STATE_IDLE;
204 		hdl->rp_curr_wr = NULL;
205 		wr->wr_state = WR_ABORTED;
206 		mutex_exit(&hdl->rp_mutex);
207 
208 		mutex_exit(&hwahcp->hwahc_mutex);
209 
210 		/*
211 		 * This CR is to tell USBA to mark this pipe as IDLE,
212 		 * so that do not queue client requests at USBA. Requests
213 		 * sent after pipe close/reset will be handled by hwahc.
214 		 */
215 		wr->wr_cb(wr->wr_wa_data, wr, USB_CR_NOT_SUPPORTED, 0);
216 
217 		mutex_enter(&hwahcp->hwahc_mutex);
218 		mutex_enter(&hdl->rp_mutex);
219 	}
220 	mutex_exit(&hdl->rp_mutex);
221 }
222 
223 /* process periodic(INTR/ISOC) requests */
224 static void
225 hwahc_do_client_periodic_in_req_callback(hwahc_state_t *hwahcp,
226 	hwahc_pipe_private_t *pp, usb_cr_t completion_reason)
227 {
228 	usb_ep_descr_t	*eptd;
229 
230 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
231 	    "hwahc_do_client_periodic_in_req_callback: enter");
232 
233 	/*
234 	 * Check for Interrupt/Isochronous IN, whether we need to do
235 	 * callback for the original client's periodic IN request.
236 	 */
237 	eptd = &(pp->pp_pipe_handle->p_ep);
238 	if (pp->pp_client_periodic_in_reqp) {
239 		if (WUSB_ISOC_ENDPOINT(eptd)) {
240 			/* not supported */
241 			USB_DPRINTF_L4(PRINT_MASK_HCDI,
242 			    hwahcp->hwahc_log_handle,
243 			    "hwahc_do_client_periodic_in_req_callback: "
244 			    "ISOC xfer not support");
245 		} else {
246 			/*
247 			 * NULL wr to tell the function that we're done and
248 			 * should clear pipe's pp_client_periodic_in_reqp
249 			 */
250 			wusb_wa_callback(&hwahcp->hwahc_wa_data,
251 			    pp->pp_pipe_handle, NULL, completion_reason);
252 		}
253 	}
254 
255 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
256 	    "hwahc_do_client_periodic_in_req_callback: end");
257 }
258 
259 /*
260  * clean up the pipe, called by pipe_close/pipe_reset
261  *	- Abort RPipe operation
262  *	- Clean pending requests queueing on this pipe
263  */
264 static void
265 hwahc_pipe_cleanup(hwahc_state_t *hwahcp, usba_pipe_handle_data_t *ph)
266 {
267 	hwahc_pipe_private_t	*pp;
268 	wusb_wa_rpipe_hdl_t	*hdl;
269 	int			rval;
270 	usb_ep_descr_t		*eptd;
271 	usb_cr_t		completion_reason;
272 
273 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
274 
275 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
276 	    "hwahc_pipe_cleanup: ph = 0x%p, p_req_cnt, ep=0x%02x,"
277 	    " state=%d", (void *) ph, ph->p_ep.bEndpointAddress,
278 	    pp->pp_state);
279 
280 	ASSERT(mutex_owned(&hwahcp->hwahc_mutex));
281 	ASSERT(!servicing_interrupt());
282 
283 	hdl = pp->pp_rp;
284 
285 	if (hwahcp->hwahc_dev_state == USB_DEV_ONLINE) {
286 		/* abort rpipe */
287 		mutex_enter(&hdl->rp_mutex);
288 
289 		/* if active, abort the requests */
290 		if (hdl->rp_state == WA_RPIPE_STATE_ACTIVE) {
291 			mutex_exit(&hdl->rp_mutex);
292 			mutex_exit(&hwahcp->hwahc_mutex);
293 			rval = wusb_wa_rpipe_abort(hwahcp->hwahc_dip,
294 			    hwahcp->hwahc_default_pipe, hdl);
295 			mutex_enter(&hwahcp->hwahc_mutex);
296 			mutex_enter(&hdl->rp_mutex);
297 		}
298 		mutex_exit(&hdl->rp_mutex);
299 
300 		/* wait for transfers to complete */
301 		hwahc_wait_for_xfer_completion(hwahcp, pp);
302 	}
303 
304 	/* remove all unprocessed requests on this pipe and do callback */
305 	hwahc_traverse_requests(hwahcp, pp);
306 
307 	switch (pp->pp_state) {
308 	case HWAHC_PIPE_STATE_CLOSE:
309 		completion_reason = USB_CR_PIPE_CLOSING;
310 
311 		mutex_exit(&hwahcp->hwahc_mutex);
312 		(void) wusb_wa_rpipe_reset(hwahcp->hwahc_dip, ph, hdl, 0);
313 		mutex_enter(&hwahcp->hwahc_mutex);
314 
315 		break;
316 	case HWAHC_PIPE_STATE_RESET:
317 	case HWAHC_PIPE_STATE_ERROR:
318 		completion_reason = USB_CR_PIPE_RESET;
319 		if (hwahcp->hwahc_dev_state == USB_DEV_ONLINE) {
320 			mutex_exit(&hwahcp->hwahc_mutex);
321 			/*
322 			 * reset WA's RPipe.
323 			 * If this pipe is not bound to the default endpoint,
324 			 * also send a clear_feature request to that ep.
325 			 */
326 			rval = wusb_wa_rpipe_reset(hwahcp->hwahc_dip,
327 			    ph, hdl, 1);
328 			mutex_enter(&hwahcp->hwahc_mutex);
329 
330 			USB_DPRINTF_L4(PRINT_MASK_HCDI,
331 			    hwahcp->hwahc_log_handle,
332 			    "hwahc_pipe_cleanup: rp reset, rv=%d",
333 			    rval);
334 
335 			pp->pp_state = HWAHC_PIPE_STATE_IDLE;
336 		}
337 
338 		break;
339 	case HWAHC_PIPE_STATE_STOP_POLLING:
340 		completion_reason = USB_CR_STOPPED_POLLING;
341 		pp->pp_state = HWAHC_PIPE_STATE_IDLE;
342 
343 		break;
344 	}
345 
346 	/*
347 	 * Do the callback for the original client
348 	 * periodic IN request.
349 	 */
350 	eptd = &ph->p_ep;
351 
352 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
353 	    "hwahc_pipe_cleanup: end");
354 
355 	if ((WUSB_PERIODIC_ENDPOINT(eptd)) &&
356 	    ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) ==
357 	    USB_EP_DIR_IN)) {
358 		mutex_exit(&hwahcp->hwahc_mutex);
359 
360 		hwahc_do_client_periodic_in_req_callback(
361 		    hwahcp, pp, completion_reason);
362 
363 		mutex_enter(&hwahcp->hwahc_mutex);
364 	}
365 }
366 
367 /*
368  * set the pipe's parent device information
369  */
370 static int
371 hwahc_set_pipe_dev_info(hwahc_state_t *hwahcp,
372     usba_pipe_handle_data_t *ph, hwahc_pipe_private_t *pp)
373 {
374 	dev_info_t *dip = NULL;
375 	wusb_hc_data_t *hc_data;
376 	int i;
377 
378 	dip = usba_get_dip((usb_pipe_handle_t)ph->p_ph_impl);
379 	if (dip == NULL) {
380 
381 		return (USB_FAILURE);
382 	}
383 
384 	hc_data = &hwahcp->hwahc_hc_data;
385 
386 	mutex_enter(&hc_data->hc_mutex);
387 	for (i = 1; i <= hc_data->hc_num_ports; i++) {
388 		if ((dip == hc_data->hc_children_dips[i])) {
389 			pp->pp_wdev = hc_data->hc_dev_infos[i];
390 
391 			USB_DPRINTF_L3(DPRINT_MASK_HCDI,
392 			    hwahcp->hwahc_log_handle,
393 			    "hwahc_set_pipe_dev_info: pp(%p) device(%p) set",
394 			    (void *) pp, (void *) pp->pp_wdev);
395 
396 			break;
397 		}
398 	}
399 
400 	mutex_exit(&hc_data->hc_mutex);
401 
402 	if (pp->pp_wdev) {
403 		return (USB_SUCCESS);
404 	} else {
405 		return (USB_FAILURE);
406 	}
407 }
408 
409 /*
410  * HWA HCDI entry points
411  *
412  * The Host Controller Driver Interfaces (HCDI) are the software interfaces
413  * between the Universal Serial Bus Layer (USBA) and the Host Controller
414  * Driver (HCD). The HCDI interfaces or entry points are subject to change.
415  */
416 
417 /*
418  * hwahc_hcdi_pipe_open:
419  * Member of HCD Ops structure and called during client specific pipe open.
420  * Assign rpipe for wireless transaction to work.
421  * The rpipe is assigned to an endpoint until the endpoint is closed.
422  */
423 static int
424 hwahc_hcdi_pipe_open(
425 	usba_pipe_handle_data_t	*ph,
426 	usb_flags_t		flags)
427 {
428 	int			rval;
429 	hwahc_state_t		*hwahcp;
430 	int			kmflag;
431 	hwahc_pipe_private_t	*pp;
432 	usb_ep_descr_t		*epdt = &ph->p_ep;
433 	uint8_t			type;
434 	wusb_wa_data_t		*wa;
435 
436 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
437 	wa = &hwahcp->hwahc_wa_data;
438 
439 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
440 	    "hwahc_hcdi_pipe_open: hwahc=0x%p, ph=0x%p,"
441 	    " addr = 0x%x, ep=0x%02X", (void *) hwahcp, (void *) ph,
442 	    ph->p_usba_device->usb_addr, epdt->bEndpointAddress);
443 
444 	kmflag = (flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
445 
446 	if (ph->p_hcd_private) {
447 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
448 		    "hwahc_hcdi_pipe_open: Pipe is already opened");
449 
450 		return (USB_FAILURE);
451 	}
452 
453 	pp = kmem_zalloc(sizeof (hwahc_pipe_private_t), kmflag);
454 	if (pp == NULL) {
455 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
456 		    "hwahc_hcdi_pipe_open: alloc pp failed");
457 
458 		return (USB_NO_RESOURCES);
459 	}
460 
461 	mutex_enter(&hwahcp->hwahc_mutex);
462 
463 	if (hwahc_set_pipe_dev_info(hwahcp, ph, pp) < 0) {
464 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
465 		    "hwahc_hcdi_pipe_open: set pipe dev_info failed");
466 		mutex_exit(&hwahcp->hwahc_mutex);
467 
468 		return (USB_FAILURE);
469 	}
470 
471 	rval = hwahc_state_is_operational(hwahcp);
472 	if (rval != USB_SUCCESS) {
473 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
474 		    "hwahc_hcdi_pipe_open: state error: %d", rval);
475 		kmem_free(pp, sizeof (hwahc_pipe_private_t));
476 		mutex_exit(&hwahcp->hwahc_mutex);
477 
478 		return (rval);
479 	}
480 
481 	/* assign rpipe to the endpoint */
482 	type = epdt->bmAttributes & USB_EP_ATTR_MASK;
483 	rval = wusb_wa_get_rpipe(&hwahcp->hwahc_wa_data,
484 	    hwahcp->hwahc_default_pipe, type, &pp->pp_rp,
485 	    PRINT_MASK_HCDI, hwahcp->hwahc_log_handle);
486 	if (rval != USB_SUCCESS) {
487 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
488 		    "hwahc_hcdi_pipe_open: getting rpipe failed");
489 		kmem_free(pp, sizeof (hwahc_pipe_private_t));
490 		mutex_exit(&hwahcp->hwahc_mutex);
491 
492 		return (USB_NO_RESOURCES);
493 	}
494 
495 	mutex_exit(&hwahcp->hwahc_mutex);
496 	/* target the rpipe to the endpoint */
497 	rval = wusb_wa_set_rpipe_target(hwahcp->hwahc_dip, wa,
498 	    hwahcp->hwahc_default_pipe, ph, pp->pp_rp);
499 	mutex_enter(&hwahcp->hwahc_mutex);
500 
501 	if (rval != USB_SUCCESS) {
502 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
503 		    "hwahc_hcdi_pipe_open: set target for rpipe failed");
504 		(void) wusb_wa_release_rpipe(wa, pp->pp_rp);
505 		kmem_free(pp, sizeof (hwahc_pipe_private_t));
506 		mutex_exit(&hwahcp->hwahc_mutex);
507 
508 		return (USB_FAILURE);
509 	}
510 
511 	pp->pp_pipe_handle = ph;
512 	cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL);
513 
514 	mutex_enter(&ph->p_mutex);
515 	ph->p_hcd_private = (usb_opaque_t)pp;
516 	bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
517 	mutex_exit(&ph->p_mutex);
518 
519 	pp->pp_state = HWAHC_PIPE_STATE_IDLE;
520 	hwahcp->hwahc_open_pipe_count++;
521 	mutex_exit(&hwahcp->hwahc_mutex);
522 
523 	return (USB_SUCCESS);
524 }
525 
526 
527 /*
528  * hwahc_hcdi_pipe_close:
529  * Member of HCD Ops structure and called during the client specific pipe
530  * close.
531  * Remove unprocessed transfers from the pipe and free rpipe resource.
532  */
533 /* ARGSUSED */
534 static int
535 hwahc_hcdi_pipe_close(
536 	usba_pipe_handle_data_t	*ph,
537 	usb_flags_t		flags)
538 {
539 	hwahc_state_t		*hwahcp;
540 	hwahc_pipe_private_t	*pp;
541 	usb_ep_descr_t		*epdt = &ph->p_ep;
542 
543 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
544 
545 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
546 	    "hwahc_hcdi_pipe_close:ph=0x%p addr = 0x%x, ep = 0x%x",
547 	    (void *) ph, ph->p_usba_device->usb_addr,
548 	    epdt->bEndpointAddress);
549 
550 	ASSERT(ph->p_hcd_private != NULL);
551 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
552 
553 	mutex_enter(&hwahcp->hwahc_mutex);
554 
555 	pp->pp_state = HWAHC_PIPE_STATE_CLOSE;
556 
557 	hwahc_pipe_cleanup(hwahcp, ph);
558 
559 	mutex_exit(&hwahcp->hwahc_mutex);
560 
561 	wusb_wa_clear_dev_ep(ph); /* clear the remote dev's endpoint */
562 	mutex_enter(&hwahcp->hwahc_mutex);
563 
564 	(void) wusb_wa_release_rpipe(&hwahcp->hwahc_wa_data, pp->pp_rp);
565 
566 	mutex_enter(&ph->p_mutex);
567 	cv_destroy(&pp->pp_xfer_cmpl_cv);
568 	kmem_free(pp, sizeof (hwahc_pipe_private_t));
569 	ph->p_hcd_private = NULL;
570 	mutex_exit(&ph->p_mutex);
571 	hwahcp->hwahc_open_pipe_count--;
572 	mutex_exit(&hwahcp->hwahc_mutex);
573 
574 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
575 	    "hwahc_hcdi_pipe_close: end");
576 
577 	return (USB_SUCCESS);
578 }
579 
580 
581 /*
582  * hwahc_hcdi_pipe_reset:
583  *	- clean up this pipe and change its state
584  */
585 /* ARGSUSED */
586 static int
587 hwahc_hcdi_pipe_reset(
588 	usba_pipe_handle_data_t	*ph,
589 	usb_flags_t		flags)
590 {
591 	hwahc_state_t		*hwahcp;
592 	hwahc_pipe_private_t	*pp;
593 
594 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
595 
596 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
597 	    "hwahc_hcdi_pipe_reset: ph = 0x%p, ep=0x%02x",
598 	    (void *) ph, ph->p_ep.bEndpointAddress);
599 
600 	ASSERT(ph->p_hcd_private != NULL);
601 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
602 
603 	mutex_enter(&hwahcp->hwahc_mutex);
604 	pp->pp_state = HWAHC_PIPE_STATE_RESET;
605 	hwahc_pipe_cleanup(hwahcp, ph);
606 	mutex_exit(&hwahcp->hwahc_mutex);
607 
608 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
609 	    "hwahc_hcdi_pipe_reset: end");
610 
611 	return (USB_SUCCESS);
612 }
613 
614 
615 /*
616  * hwahc_hcdi_pipe_ctrl_xfer:
617  *	- usba_hcdi_pipe_ctrl_xfer entry
618  *	- check pipe state
619  *	- call wa_xfer to do this request
620  */
621 static int
622 hwahc_hcdi_pipe_ctrl_xfer(
623 	usba_pipe_handle_data_t	*ph,
624 	usb_ctrl_req_t		*ctrl_reqp,
625 	usb_flags_t		usb_flags)
626 {
627 	hwahc_state_t		*hwahcp;
628 	hwahc_pipe_private_t	*pp;
629 	int			rval;
630 	uint8_t			ep_addr = ph->p_ep.bEndpointAddress;
631 
632 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
633 
634 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
635 	    "hwahc_hcdi_pipe_ctrl_xfer: hwahcp=0x%p ph = 0x%p"
636 	    " reqp = 0x%p flags = %x", (void *) hwahcp, (void *) ph,
637 	    (void *) ctrl_reqp, usb_flags);
638 
639 	ASSERT(ph->p_hcd_private != NULL);
640 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
641 
642 	mutex_enter(&hwahcp->hwahc_mutex);
643 	rval = hwahc_state_is_operational(hwahcp);
644 	if (rval != USB_SUCCESS) {
645 		mutex_exit(&hwahcp->hwahc_mutex);
646 
647 		return (rval);
648 	}
649 
650 	/*
651 	 * if doing ctrl transfer on non-zero pipe and its state is error
652 	 * The default endpoint is critical for any other operations.
653 	 * We should not depend on upper layer to reset it.
654 	 */
655 	if ((pp->pp_state == HWAHC_PIPE_STATE_ERROR)) {
656 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
657 		    "hwahc_hcdi_pipe_ctrl_xfer: Pipe(%d) is in error"
658 		    " state, need pipe reset to continue", ep_addr);
659 
660 		if (ep_addr == 0) {
661 			/*
662 			 * some error with the RPipe of EP 0,
663 			 * we need to reset this RPipe by ourself
664 			 */
665 			mutex_exit(&hwahcp->hwahc_mutex);
666 			(void) wusb_wa_rpipe_reset(hwahcp->hwahc_dip, ph,
667 			    pp->pp_rp, 1);
668 			mutex_enter(&hwahcp->hwahc_mutex);
669 			pp->pp_state = 0;
670 		} else {
671 		/* client driver should clear non-default endpoint's state */
672 			mutex_exit(&hwahcp->hwahc_mutex);
673 
674 			return (USB_FAILURE);
675 		}
676 	} else if ((pp->pp_state != HWAHC_PIPE_STATE_IDLE) &&
677 	    (pp->pp_state != HWAHC_PIPE_STATE_ERROR)) {
678 			mutex_exit(&hwahcp->hwahc_mutex);
679 
680 			return (USB_PIPE_ERROR);
681 	}
682 
683 	mutex_exit(&hwahcp->hwahc_mutex);
684 
685 	rval = wusb_wa_ctrl_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph,
686 	    ctrl_reqp, usb_flags);
687 	if (rval != USB_SUCCESS) {
688 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
689 		    "hwahc_hcdi_pipe_ctrl_xfer failed, rval = %d", rval);
690 	}
691 
692 
693 	return (rval);
694 }
695 
696 
697 /*
698  * hwahc_hcdi_pipe_bulk_xfer:
699  *	- usba_hcid_pipe_bulk_xfer entry
700  *	- check the target pipe status first
701  *	- process this request
702  */
703 static int
704 hwahc_hcdi_pipe_bulk_xfer(
705 	usba_pipe_handle_data_t	*ph,
706 	usb_bulk_req_t		*bulk_reqp,
707 	usb_flags_t		usb_flags)
708 {
709 	hwahc_state_t		*hwahcp;
710 	hwahc_pipe_private_t	*pp;
711 	int			rval;
712 
713 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
714 
715 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
716 	    "hwahc_hcdi_pipe_bulk_xfer: hwahcp=0x%p ph = 0x%p reqp = 0x%p"
717 	    " flags = %x", (void *) hwahcp, (void *) ph,
718 	    (void *) bulk_reqp, usb_flags);
719 
720 	ASSERT(ph->p_hcd_private != NULL);
721 
722 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
723 
724 	mutex_enter(&hwahcp->hwahc_mutex);
725 	rval = hwahc_state_is_operational(hwahcp);
726 	if (rval != USB_SUCCESS) {
727 		mutex_exit(&hwahcp->hwahc_mutex);
728 
729 		return (rval);
730 	}
731 
732 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
733 	    "hwahc_hcdi_pipe_bulk_xfer: pp = 0x%p state= %x", (void *) pp,
734 	    pp->pp_state);
735 
736 	if (pp->pp_state == HWAHC_PIPE_STATE_ERROR) {
737 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
738 		    "hwahc_hcdi_pipe_bulk_xfer: "
739 		    "Pipe is in error state, need pipe reset to continue");
740 
741 		mutex_exit(&hwahcp->hwahc_mutex);
742 
743 		return (USB_FAILURE);
744 	}
745 
746 	mutex_exit(&hwahcp->hwahc_mutex);
747 	rval = wusb_wa_bulk_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph,
748 	    bulk_reqp, usb_flags);
749 	mutex_enter(&hwahcp->hwahc_mutex);
750 	if (rval != USB_SUCCESS) {
751 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
752 		    "hwahc_hcdi_pipe_bulk_xfer failed, rval = %d", rval);
753 	}
754 	mutex_exit(&hwahcp->hwahc_mutex);
755 
756 	return (rval);
757 }
758 
759 /*
760  * hwahc_hcdi_pipe_intr_xfer:
761  *	- usba_hcdi_pipe_intr_xfer entry
762  *	- check pipe state
763  *	- process this request
764  */
765 static int
766 hwahc_hcdi_pipe_intr_xfer(
767 	usba_pipe_handle_data_t	*ph,
768 	usb_intr_req_t		*intr_reqp,
769 	usb_flags_t		usb_flags)
770 {
771 	hwahc_state_t		*hwahcp;
772 	hwahc_pipe_private_t	*pp;
773 	int			rval, pipe_dir;
774 
775 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
776 
777 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
778 	    "hwahc_hcdi_pipe_intr_xfer: hwahcp=0x%p ph = 0x%p"
779 	    " reqp = 0x%p flags = %x", (void *) hwahcp, (void *) ph,
780 	    (void *) intr_reqp, usb_flags);
781 
782 	ASSERT(ph->p_hcd_private != NULL);
783 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
784 
785 	mutex_enter(&hwahcp->hwahc_mutex);
786 	rval = hwahc_state_is_operational(hwahcp);
787 	if (rval != USB_SUCCESS) {
788 		mutex_exit(&hwahcp->hwahc_mutex);
789 
790 		return (rval);
791 	}
792 
793 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
794 	    "hwahc_hcdi_pipe_intr_xfer: pp = 0x%p state= %x", (void *) pp,
795 	    pp->pp_state);
796 
797 	if (pp->pp_state == HWAHC_PIPE_STATE_ERROR) {
798 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
799 		    "hwahc_hcdi_pipe_intr_xfer: "
800 		    "Pipe is in error state, need pipe reset to continue");
801 
802 		mutex_exit(&hwahcp->hwahc_mutex);
803 
804 		return (USB_FAILURE);
805 	}
806 
807 	pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
808 
809 
810 	mutex_exit(&hwahcp->hwahc_mutex);
811 	rval = wusb_wa_intr_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph,
812 	    intr_reqp, usb_flags);
813 	mutex_enter(&hwahcp->hwahc_mutex);
814 	if (rval != USB_SUCCESS) {
815 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
816 		    "hwahc_hcdi_pipe_intr_xfer failed, rval = %d", rval);
817 	}
818 
819 	if ((pipe_dir == USB_EP_DIR_IN) &&(rval == USB_SUCCESS)) {
820 		/*
821 		 * the request has been submitted successfully,
822 		 * save the original one; free this request when polling
823 		 * stopped
824 		 */
825 		pp->pp_client_periodic_in_reqp = (usb_opaque_t)intr_reqp;
826 		pp->pp_state = HWAHC_PIPE_STATE_ACTIVE;
827 	}
828 
829 	mutex_exit(&hwahcp->hwahc_mutex);
830 
831 	return (rval);
832 }
833 
834 /*
835  * hwahc_hcdi_pipe_isoc_xfer:
836  */
837 /* ARGSUSED */
838 static int
839 hwahc_hcdi_pipe_isoc_xfer(
840 	usba_pipe_handle_data_t	*ph,
841 	usb_isoc_req_t		*isoc_reqp,
842 	usb_flags_t		usb_flags)
843 {
844 	return (USB_NOT_SUPPORTED);
845 }
846 
847 
848 /*
849  * hwahc_hcdi_bulk_transfer_size:
850  *
851  * Return maximum bulk transfer size
852  */
853 /* ARGSUSED */
854 static int
855 hwahc_hcdi_bulk_transfer_size(
856 	usba_device_t	*usba_device,
857 	size_t		*size)
858 {
859 	hwahc_state_t		*hwahcp;
860 	int			rval;
861 
862 	hwahcp = hwahc_obtain_state(usba_device->usb_root_hub_dip);
863 
864 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
865 	    "hwahc_hcdi_bulk_transfer_size:");
866 
867 	mutex_enter(&hwahcp->hwahc_mutex);
868 	rval = hwahc_state_is_operational(hwahcp);
869 	mutex_exit(&hwahcp->hwahc_mutex);
870 
871 	if (rval != USB_SUCCESS) {
872 
873 		return (rval);
874 	}
875 
876 	*size = WA_MAX_SEG_COUNT * 1024;
877 
878 	return (USB_SUCCESS);
879 }
880 
881 /*
882  * hwahc_hcdi_pipe_stop_intr_polling()
883  */
884 /* ARGSUSED */
885 static int
886 hwahc_hcdi_pipe_stop_intr_polling(
887 	usba_pipe_handle_data_t	*ph,
888 	usb_flags_t		flags)
889 {
890 	hwahc_state_t		*hwahcp;
891 	hwahc_pipe_private_t	*pp;
892 
893 	hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip);
894 
895 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
896 	    "hwahc_hcdi_pipe_stop_intr_polling: hwahcp=0x%p ph = 0x%p"
897 	    " flags = %x", (void *) hwahcp, (void *) ph, flags);
898 
899 	ASSERT(ph->p_hcd_private != NULL);
900 
901 	mutex_enter(&hwahcp->hwahc_mutex);
902 	pp = (hwahc_pipe_private_t *)ph->p_hcd_private;
903 
904 	if (pp->pp_state != HWAHC_PIPE_STATE_ACTIVE) {
905 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
906 		    "hwahc_hcdi_pipe_stop_intr_polling: "
907 		    "Polling already stopped");
908 		mutex_exit(&hwahcp->hwahc_mutex);
909 
910 		return (USB_SUCCESS);
911 	}
912 
913 	pp->pp_state = HWAHC_PIPE_STATE_STOP_POLLING;
914 
915 	hwahc_pipe_cleanup(hwahcp, ph);
916 
917 	mutex_exit(&hwahcp->hwahc_mutex);
918 
919 	return (USB_SUCCESS);
920 }
921 
922 
923 /*
924  * hwahc_hcdi_pipe_stop_isoc_polling()
925  */
926 /*ARGSUSED*/
927 static int
928 hwahc_hcdi_pipe_stop_isoc_polling(
929 	usba_pipe_handle_data_t	*ph,
930 	usb_flags_t		flags)
931 {
932 	return (USB_NOT_SUPPORTED);
933 }
934 
935 
936 /*
937  * hwahc_hcdi_get_current_frame_number:
938  *
939  * Get the current usb frame number.
940  * Return whether the request is handled successfully
941  */
942 /* ARGSUSED */
943 static int
944 hwahc_hcdi_get_current_frame_number(
945 	usba_device_t		*usba_device,
946 	usb_frame_number_t	*frame_number)
947 {
948 	return (USB_NOT_SUPPORTED);
949 }
950 
951 
952 /*
953  * hwahc_hcdi_get_max_isoc_pkts:
954  *
955  * Get maximum isochronous packets per usb isochronous request.
956  * Return whether the request is handled successfully
957  */
958 /* ARGSUSED */
959 static int
960 hwahc_hcdi_get_max_isoc_pkts(
961 	usba_device_t	*usba_device,
962 	uint_t		*max_pkts)
963 {
964 	return (USB_NOT_SUPPORTED);
965 }
966 
967 
968 /*
969  * POLLED entry points
970  *
971  * These functions are entry points into the POLLED code.
972  */
973 /*
974  * hwahc_hcdi_polled_input_init:
975  *
976  * This is the initialization routine for handling the USB keyboard
977  * in POLLED mode.  This routine is not called from POLLED mode, so
978  * it is OK to acquire mutexes.
979  */
980 /* ARGSUSED */
981 static int
982 hwahc_hcdi_polled_input_init(
983 	usba_pipe_handle_data_t	*ph,
984 	uchar_t			**polled_buf,
985 	usb_console_info_impl_t	*console_input_info)
986 {
987 	return (USB_FAILURE);
988 }
989 
990 
991 /*
992  * hwahc_hcdi_polled_input_fini:
993  */
994 /* ARGSUSED */
995 static int
996 hwahc_hcdi_polled_input_fini(usb_console_info_impl_t *info)
997 {
998 	return (USB_FAILURE);
999 }
1000 
1001 
1002 /*
1003  * hwahc_hcdi_polled_input_enter:
1004  *
1005  * This is where we enter into POLLED mode.  This routine sets up
1006  * everything so that calls to	hwahc_hcdi_polled_read will return
1007  * characters.
1008  */
1009 /* ARGSUSED */
1010 static int
1011 hwahc_hcdi_polled_input_enter(usb_console_info_impl_t *info)
1012 {
1013 	return (USB_FAILURE);
1014 }
1015 
1016 
1017 /*
1018  * hwahc_hcdi_polled_input_exit:
1019  *
1020  * This is where we exit POLLED mode. This routine restores
1021  * everything that is needed to continue operation.
1022  */
1023 /* ARGSUSED */
1024 static int
1025 hwahc_hcdi_polled_input_exit(usb_console_info_impl_t *info)
1026 {
1027 	return (USB_FAILURE);
1028 }
1029 
1030 
1031 /*
1032  * hwahc_hcdi_polled_read:
1033  *
1034  * Get a key character
1035  */
1036 /* ARGSUSED */
1037 static int
1038 hwahc_hcdi_polled_read(
1039 	usb_console_info_impl_t	*info,
1040 	uint_t			*num_characters)
1041 {
1042 	return (USB_FAILURE);
1043 }
1044 
1045 
1046 /*
1047  * hwahc_alloc_hcdi_ops:
1048  *
1049  * The HCDI interfaces or entry points are the software interfaces used by
1050  * the Universal Serial Bus Driver  (USBA) to  access the services of the
1051  * Host Controller Driver (HCD).  During HCD initialization, inform  USBA
1052  * about all available HCDI interfaces or entry points.
1053  */
1054 usba_hcdi_ops_t *
1055 hwahc_alloc_hcdi_ops(hwahc_state_t *hwahcp)
1056 {
1057 	usba_hcdi_ops_t			*usba_hcdi_ops;
1058 
1059 	USB_DPRINTF_L2(PRINT_MASK_ATTA, hwahcp->hwahc_log_handle,
1060 	    "hwahc_alloc_hcdi_ops:");
1061 
1062 	usba_hcdi_ops = usba_alloc_hcdi_ops();
1063 
1064 	usba_hcdi_ops->usba_hcdi_ops_version = HCDI_OPS_VERSION;
1065 
1066 	usba_hcdi_ops->usba_hcdi_pm_support = hwahc_hcdi_pm_support;
1067 	usba_hcdi_ops->usba_hcdi_pipe_open = hwahc_hcdi_pipe_open;
1068 	usba_hcdi_ops->usba_hcdi_pipe_close = hwahc_hcdi_pipe_close;
1069 
1070 	usba_hcdi_ops->usba_hcdi_pipe_reset = hwahc_hcdi_pipe_reset;
1071 	usba_hcdi_ops->usba_hcdi_pipe_reset_data_toggle =
1072 	    hwahc_hcdi_pipe_reset_data_toggle;
1073 
1074 	usba_hcdi_ops->usba_hcdi_pipe_ctrl_xfer = hwahc_hcdi_pipe_ctrl_xfer;
1075 	usba_hcdi_ops->usba_hcdi_pipe_bulk_xfer = hwahc_hcdi_pipe_bulk_xfer;
1076 	usba_hcdi_ops->usba_hcdi_pipe_intr_xfer = hwahc_hcdi_pipe_intr_xfer;
1077 	usba_hcdi_ops->usba_hcdi_pipe_isoc_xfer = hwahc_hcdi_pipe_isoc_xfer;
1078 
1079 	usba_hcdi_ops->usba_hcdi_bulk_transfer_size =
1080 	    hwahc_hcdi_bulk_transfer_size;
1081 
1082 	usba_hcdi_ops->usba_hcdi_pipe_stop_intr_polling =
1083 	    hwahc_hcdi_pipe_stop_intr_polling;
1084 	usba_hcdi_ops->usba_hcdi_pipe_stop_isoc_polling =
1085 	    hwahc_hcdi_pipe_stop_isoc_polling;
1086 
1087 	usba_hcdi_ops->usba_hcdi_get_current_frame_number =
1088 	    hwahc_hcdi_get_current_frame_number;
1089 	usba_hcdi_ops->usba_hcdi_get_max_isoc_pkts =
1090 	    hwahc_hcdi_get_max_isoc_pkts;
1091 
1092 	usba_hcdi_ops->usba_hcdi_console_input_init =
1093 	    hwahc_hcdi_polled_input_init;
1094 	usba_hcdi_ops->usba_hcdi_console_input_enter =
1095 	    hwahc_hcdi_polled_input_enter;
1096 	usba_hcdi_ops->usba_hcdi_console_read =
1097 	    hwahc_hcdi_polled_read;
1098 	usba_hcdi_ops->usba_hcdi_console_input_exit =
1099 	    hwahc_hcdi_polled_input_exit;
1100 	usba_hcdi_ops->usba_hcdi_console_input_fini =
1101 	    hwahc_hcdi_polled_input_fini;
1102 
1103 	return (usba_hcdi_ops);
1104 }
1105 
1106 
1107 /*
1108  * Set cluster ID.
1109  * see 8.5.3.11
1110  */
1111 int
1112 hwahc_set_cluster_id(dev_info_t *dip, uint8_t cluster_id)
1113 {
1114 	usb_cr_t	completion_reason;
1115 	usb_cb_flags_t	cb_flags;
1116 	int		rval;
1117 	hwahc_state_t	*hwahcp;
1118 
1119 	if (dip == NULL) {
1120 
1121 		return (USB_INVALID_ARGS);
1122 	}
1123 
1124 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1125 	if (hwahcp == NULL) {
1126 
1127 		return (USB_INVALID_ARGS);
1128 	}
1129 
1130 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1131 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
1132 	    HWA_REQ_SET_CLUSTER_ID,
1133 	    cluster_id,
1134 	    hwahcp->hwahc_wa_data.wa_ifno,
1135 	    0,
1136 	    NULL, 0,
1137 	    &completion_reason, &cb_flags, 0);
1138 
1139 	if (rval != USB_SUCCESS) {
1140 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1141 		    "Set_Cluster_ID fails: rval=%d cr=%d cb=0x%x",
1142 		    rval, completion_reason, cb_flags);
1143 	}
1144 
1145 	return (rval);
1146 }
1147 
1148 /*
1149  * Set WUSB Stream Index. see 8.5.3.13
1150  */
1151 int
1152 hwahc_set_stream_idx(dev_info_t *dip, uint8_t stream_idx)
1153 {
1154 	usb_cr_t	completion_reason;
1155 	usb_cb_flags_t	cb_flags;
1156 	int		rval;
1157 	hwahc_state_t	*hwahcp;
1158 
1159 	if ((dip == NULL))  {
1160 
1161 		return (USB_INVALID_ARGS);
1162 	}
1163 
1164 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1165 	if (hwahcp == NULL) {
1166 
1167 		return (USB_INVALID_ARGS);
1168 	}
1169 
1170 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1171 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
1172 	    HWA_REQ_SET_STREAM_IDX,
1173 	    stream_idx,
1174 	    hwahcp->hwahc_wa_data.wa_ifno,
1175 	    0, NULL, 0, &completion_reason,
1176 	    &cb_flags, 0);
1177 
1178 	if (rval != USB_SUCCESS) {
1179 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1180 		    "Set_Stream_Idx fails: rval=%d cr=%d cb=0x%x",
1181 		    rval, completion_reason, cb_flags);
1182 	}
1183 
1184 	return (rval);
1185 }
1186 
1187 /*
1188  * 8.5.3.12 - Set WUSB MAS
1189  *	Caller must ensure the data is WUSB_SET_WUSB_MAS_LEN long.
1190  */
1191 int
1192 hwahc_set_wusb_mas(dev_info_t *dip, uint8_t *data)
1193 {
1194 	usb_cr_t	completion_reason;
1195 	usb_cb_flags_t	cb_flags;
1196 	mblk_t		*blk;
1197 	int		rval, i;
1198 	hwahc_state_t	*hwahcp;
1199 
1200 	if ((dip == NULL))  {
1201 
1202 		return (USB_INVALID_ARGS);
1203 	}
1204 
1205 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1206 	if (hwahcp == NULL) {
1207 
1208 		return (USB_INVALID_ARGS);
1209 	}
1210 
1211 	blk = allocb_wait(WUSB_SET_WUSB_MAS_LEN, BPRI_LO, STR_NOSIG, NULL);
1212 
1213 	for (i = 0; i < WUSB_SET_WUSB_MAS_LEN; i++) {
1214 		*blk->b_wptr++ = data[i];
1215 	}
1216 
1217 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1218 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
1219 	    HWA_REQ_SET_WUSB_MAS,
1220 	    0,
1221 	    hwahcp->hwahc_wa_data.wa_ifno,
1222 	    WUSB_SET_WUSB_MAS_LEN,
1223 	    &blk, 0,
1224 	    &completion_reason, &cb_flags, 0);
1225 
1226 	if (rval != USB_SUCCESS) {
1227 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1228 		    "Set_WUSB_MAS fails: rval=%d cr=%d cb=0x%x",
1229 		    rval, completion_reason, cb_flags);
1230 	}
1231 	freemsg(blk);
1232 
1233 	return (rval);
1234 }
1235 
1236 /* 8.5.3.1 - Add MMC IE */
1237 int
1238 hwahc_add_mmc_ie(dev_info_t *dip, uint8_t interval, uint8_t rcnt,
1239 	uint8_t iehdl, uint16_t len, uint8_t *data)
1240 {
1241 	usb_cr_t	completion_reason;
1242 	usb_cb_flags_t	cb_flags;
1243 	mblk_t		*blk;
1244 	int		i, rval;
1245 	hwahc_state_t	*hwahcp;
1246 
1247 	if (dip == NULL)  {
1248 
1249 		return (USB_INVALID_ARGS);
1250 	}
1251 
1252 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1253 	if (hwahcp == NULL) {
1254 
1255 		return (USB_INVALID_ARGS);
1256 	}
1257 
1258 	blk = allocb_wait(len, BPRI_LO, STR_NOSIG, NULL);
1259 
1260 	for (i = 0; i < len; i++) {
1261 		*blk->b_wptr++ = data[i];
1262 	}
1263 
1264 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1265 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
1266 	    HWA_REQ_ADD_MMC_IE,
1267 	    (interval << 8) | rcnt,
1268 	    (iehdl << 8) | hwahcp->hwahc_wa_data.wa_ifno,
1269 	    len,
1270 	    &blk, 0,
1271 	    &completion_reason, &cb_flags, 0);
1272 
1273 	if (rval != USB_SUCCESS) {
1274 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1275 		    "Add_MMC_IE fails: rval=%d cr=%d cb=0x%x",
1276 		    rval, completion_reason, cb_flags);
1277 	}
1278 
1279 	freemsg(blk);
1280 
1281 	return (rval);
1282 }
1283 
1284 /* 8.5.3.5 - Remove MMC IE */
1285 int
1286 hwahc_remove_mmc_ie(dev_info_t *dip, uint8_t iehdl)
1287 {
1288 	usb_cr_t	completion_reason;
1289 	usb_cb_flags_t	cb_flags;
1290 	int		rval;
1291 	hwahc_state_t	*hwahcp;
1292 
1293 	if (dip == NULL) {
1294 
1295 		return (USB_INVALID_ARGS);
1296 	}
1297 
1298 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1299 	if (hwahcp == NULL) {
1300 		return (USB_INVALID_ARGS);
1301 	}
1302 
1303 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1304 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
1305 	    HWA_REQ_REMOVE_MMC_IE,
1306 	    0,
1307 	    (iehdl << 8) | hwahcp->hwahc_wa_data.wa_ifno,
1308 	    0,
1309 	    NULL, 0,
1310 	    &completion_reason, &cb_flags, 0);
1311 
1312 	if (rval != USB_SUCCESS) {
1313 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1314 		    "Remove_MMC_IE fails: rval=%d cr=%d cb=0x%x",
1315 		    rval, completion_reason, cb_flags);
1316 	}
1317 
1318 	return (rval);
1319 }
1320 
1321 /* 8.5.3.14 - WUSB Channel Stop */
1322 int
1323 hwahc_stop_ch(dev_info_t *dip, uint32_t timeoff)
1324 {
1325 	int		rval;
1326 	usb_cr_t	completion_reason;
1327 	usb_cb_flags_t	cb_flags;
1328 	hwahc_state_t	*hwahcp;
1329 
1330 	if (dip == NULL) {
1331 
1332 		return (USB_INVALID_ARGS);
1333 	}
1334 
1335 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1336 	if (hwahcp == NULL) {
1337 
1338 		return (USB_INVALID_ARGS);
1339 	}
1340 
1341 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1342 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
1343 	    HWA_REQ_CH_STOP,
1344 	    timeoff & 0x00ffffff,
1345 	    hwahcp->hwahc_wa_data.wa_ifno,
1346 	    0,
1347 	    NULL, 0,
1348 	    &completion_reason, &cb_flags, 0);
1349 
1350 	if (rval != USB_SUCCESS) {
1351 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1352 		    "WUSB_Ch_Stop fails: rval=%d cr=%d cb=0x%x",
1353 		    rval, completion_reason, cb_flags);
1354 	}
1355 
1356 	return (rval);
1357 }
1358 
1359 /* 8.5. 3.10 - Set Num DNTS Slots */
1360 int
1361 hwahc_set_num_dnts(dev_info_t *dip, uint8_t interval, uint8_t nslots)
1362 {
1363 	usb_cr_t	completion_reason;
1364 	usb_cb_flags_t	cb_flags;
1365 	int		rval;
1366 	hwahc_state_t	*hwahcp;
1367 
1368 	if (dip == NULL) {
1369 
1370 		return (USB_INVALID_ARGS);
1371 	}
1372 
1373 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1374 	if (hwahcp == NULL) {
1375 
1376 		return (USB_INVALID_ARGS);
1377 	}
1378 
1379 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1380 	    WUSB_CLASS_IF_REQ_OUT_TYPE,
1381 	    HWA_REQ_SET_NUM_DNTS,
1382 	    (interval << 8) | nslots,
1383 	    hwahcp->hwahc_wa_data.wa_ifno,
1384 	    0,
1385 	    NULL, 0,
1386 	    &completion_reason, &cb_flags, 0);
1387 
1388 	if (rval != USB_SUCCESS) {
1389 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1390 		    "Set_Num_DNTS fails: rval=%d cr=%d cb=0x%x",
1391 		    rval, completion_reason, cb_flags);
1392 	}
1393 
1394 	return (rval);
1395 }
1396 
1397 /* set encryptiion type for host */
1398 int
1399 hwahc_set_encrypt(dev_info_t *dip, usb_port_t port, uint8_t type)
1400 {
1401 	hwahc_state_t	*hwahcp;
1402 	int		rval;
1403 
1404 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
1405 	    ddi_get_instance(dip))) == NULL) {
1406 
1407 		return (USB_INVALID_ARGS);
1408 	}
1409 	/* DEVICE INDEX */
1410 	rval = hwahc_set_dev_encrypt(hwahcp->hwahc_default_pipe,
1411 	    hwahcp->hwahc_wa_data.wa_ifno, port - 1,
1412 	    &hwahcp->hwahc_secrt_data, type);
1413 	if (rval != USB_SUCCESS) {
1414 		USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle,
1415 		    "hwahc_set_encrypt: set device encryption for port %d "
1416 		    "failed", port);
1417 	}
1418 
1419 	return (rval);
1420 }
1421 
1422 
1423 /*
1424  * Set Device Key for WUSB host, refer to WUSB 1.0/8.5.3.8
1425  *
1426  * Set group/device key:
1427  * devindex = actual port number - 1, so it is zero based
1428  *
1429  */
1430 int hwahc_set_keys(hwahc_state_t *hwahcp, usb_key_descr_t *key_descr,
1431     size_t klen, uint8_t devindex, uint8_t keydex, uint8_t flag)
1432 {
1433 	usb_ctrl_setup_t	setup;
1434 	usb_cr_t		cr;
1435 	usb_cb_flags_t		cb_flags;
1436 	mblk_t			*pdata;
1437 	int			rval;
1438 	uint8_t			keyindex;
1439 
1440 	USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1441 	    "hwahc_set_keys: klen = %d, devindex = %d", (int)klen,
1442 	    devindex);
1443 
1444 	/* Table 7-21 and Errata 2005/07 */
1445 	if (flag == WUSB_GTK) {
1446 		if (devindex != 0) {
1447 			return (USB_FAILURE);
1448 		}
1449 
1450 		/* See 7.3.2.4 for key index format */
1451 		keyindex = (1 << 5) | keydex;
1452 	} else if (flag == WUSB_PTK) {
1453 
1454 		keyindex = keydex;
1455 	} else {
1456 
1457 		return (USB_FAILURE);
1458 	}
1459 
1460 	setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV |
1461 	    USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF;
1462 	setup.bRequest = USB_REQ_SET_DESCR;
1463 	setup.wValue = (USB_DESCR_TYPE_KEY << 8) | keyindex;
1464 	setup.wIndex = devindex << 8 | hwahcp->hwahc_wa_data.wa_ifno;
1465 	setup.wLength = (uint16_t)klen;
1466 	setup.attrs = USB_ATTRS_NONE;
1467 
1468 	if ((pdata = allocb(klen, BPRI_HI)) == NULL) {
1469 
1470 		return (USB_FAILURE);
1471 	}
1472 	bcopy(key_descr, pdata->b_wptr, klen);
1473 	pdata->b_wptr += klen;
1474 
1475 	rval = usb_pipe_ctrl_xfer_wait(hwahcp->hwahc_default_pipe, &setup,
1476 	    &pdata, &cr, &cb_flags, USB_FLAGS_SLEEP);
1477 
1478 	if (rval != USB_SUCCESS) {
1479 		USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1480 		    "hwahc_set_keys:fail, rv=%d,cr=%d,cb=%d", rval, cr,
1481 		    cb_flags);
1482 	}
1483 
1484 	freemsg(pdata);
1485 
1486 	return (rval);
1487 }
1488 
1489 /* set PTK for host */
1490 int
1491 hwahc_set_ptk(dev_info_t *dip, usb_key_descr_t *key_descr, size_t klen,
1492 	usb_port_t port)
1493 {
1494 	hwahc_state_t	*hwahcp;
1495 	int		rval;
1496 	uint8_t		keyindex = 1;
1497 
1498 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
1499 	    ddi_get_instance(dip))) == NULL) {
1500 
1501 		return (USB_INVALID_ARGS);
1502 	}
1503 	/* DEVICE INDEX */
1504 	rval = hwahc_set_keys(hwahcp, key_descr, klen, port - 1, keyindex,
1505 	    WUSB_PTK);
1506 	if (rval != USB_SUCCESS) {
1507 		USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle,
1508 		    "hwahc_set_ptk: set device key descr for port %d "
1509 		    "failed", port);
1510 	}
1511 
1512 	return (rval);
1513 }
1514 
1515 /* set GTK for host */
1516 int
1517 hwahc_set_gtk(dev_info_t *dip, usb_key_descr_t *key_descr, size_t klen)
1518 {
1519 	hwahc_state_t		*hwahcp;
1520 	int			rval;
1521 
1522 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
1523 	    ddi_get_instance(dip))) == NULL) {
1524 
1525 		return (USB_INVALID_ARGS);
1526 	}
1527 
1528 	rval = hwahc_set_keys(hwahcp, key_descr, klen, 0, 0, WUSB_GTK);
1529 	if (rval != USB_SUCCESS) {
1530 		USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle,
1531 		    "hwahc_set_gtk: set group key descr failed");
1532 	}
1533 
1534 	return (rval);
1535 }
1536 
1537 /*
1538  * set device info for host
1539  * Section 8.5.3.7.
1540  */
1541 int
1542 hwahc_set_device_info(dev_info_t *dip, wusb_dev_info_t *dev_info,
1543 	usb_port_t port)
1544 {
1545 	hwahc_state_t		*hwahcp;
1546 	int			rval;
1547 	hwa_dev_info_t		info;
1548 	usb_ctrl_setup_t	setup;
1549 	usb_cr_t		cr;
1550 	usb_cb_flags_t		cb_flags;
1551 	mblk_t			*pdata;
1552 
1553 	if ((hwahcp = ddi_get_soft_state(hwahc_statep,
1554 	    ddi_get_instance(dip))) == NULL) {
1555 
1556 		return (USB_INVALID_ARGS);
1557 	}
1558 
1559 	/* the device can use all the host's reserved MASes to communicate */
1560 	(void) memcpy(info.bmDeviceAvailablilityInfo,
1561 	    hwahcp->hwahc_hc_data.hc_mas, WUSB_SET_WUSB_MAS_LEN);
1562 
1563 	info.bDeviceAddress = dev_info->wdev_addr;
1564 
1565 	/* To tell HWA device what data rates this child device supports */
1566 	if (dev_info->wdev_uwb_descr == NULL) {
1567 		/* bitmap, see7.4.1.1. Must support 53.3/106.7/200 Mbps */
1568 		info.wPHYRates[0] = WUSB_DATA_RATE_BIT_53 |
1569 		    WUSB_DATA_RATE_BIT_106 | WUSB_DATA_RATE_BIT_200;
1570 		info.wPHYRates[1] = 0;
1571 	} else {
1572 		info.wPHYRates[0] =
1573 		    dev_info->wdev_uwb_descr->wPHYRates && 0xff;
1574 		info.wPHYRates[1] =
1575 		    (dev_info->wdev_uwb_descr->wPHYRates >> 8) && 0xff;
1576 	}
1577 	info.bmDeviceAttribute = 0;
1578 
1579 	setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV |
1580 	    USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF;
1581 	setup.bRequest = HWA_REQ_SET_DEVICE_INFO;
1582 	setup.wValue = 0;
1583 
1584 	/* DEVICE INDEX */
1585 	setup.wIndex = (port - 1) << 8 | hwahcp->hwahc_wa_data.wa_ifno;
1586 	setup.wLength = WUSB_SET_DEV_INFO_LEN;
1587 	setup.attrs = USB_ATTRS_NONE;
1588 
1589 	if ((pdata = allocb(WUSB_SET_DEV_INFO_LEN, BPRI_HI)) == NULL) {
1590 
1591 		return (USB_FAILURE);
1592 	}
1593 	bcopy(&info, pdata->b_wptr, WUSB_SET_DEV_INFO_LEN);
1594 	pdata->b_wptr += WUSB_SET_DEV_INFO_LEN;
1595 
1596 	rval = usb_pipe_ctrl_xfer_wait(hwahcp->hwahc_default_pipe, &setup,
1597 	    &pdata, &cr, &cb_flags, USB_FLAGS_SLEEP);
1598 
1599 	freemsg(pdata);
1600 
1601 	return (rval);
1602 }
1603 
1604 /*
1605  * 8.5.3.2 - 8.5.3.4 Get Time
1606  * time_type:
1607  *	WUSB_TIME_ADJ	- Get BPST Adjustment
1608  *	WUSB_TIME_BPST	- Get BPST Time
1609  *	WUSB_TIME_WUSB	- Get WUSB Time
1610  */
1611 int
1612 hwahc_get_time(dev_info_t *dip, uint8_t time_type,
1613     uint16_t len, uint32_t *time)
1614 {
1615 	usb_cr_t	completion_reason;
1616 	usb_cb_flags_t	cb_flags;
1617 	mblk_t		*blk = NULL;
1618 	int		rval;
1619 	uint8_t		*data;
1620 	uint16_t	length;
1621 	hwahc_state_t	*hwahcp = NULL;
1622 
1623 	if (dip == NULL) {
1624 
1625 		return (USB_INVALID_ARGS);
1626 	}
1627 
1628 	hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip));
1629 	if (hwahcp == NULL) {
1630 
1631 		return (USB_INVALID_ARGS);
1632 	}
1633 
1634 	/* according to WUSB 8.5.3, len is 1 or 3 */
1635 	if ((len != 1) && (len != 3)) {
1636 
1637 		return (USB_INVALID_ARGS);
1638 	}
1639 
1640 	rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe,
1641 	    WUSB_CLASS_IF_REQ_OUT_TYPE, HWA_REQ_GET_TIME,
1642 	    time_type, hwahcp->hwahc_wa_data.wa_ifno,
1643 	    len, &blk, 0, &completion_reason, &cb_flags, 0);
1644 
1645 	if (rval != USB_SUCCESS) {
1646 		freemsg(blk);
1647 
1648 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1649 		    "Get_Time fails: rval=%d cr=%d cb=0x%x",
1650 		    rval, completion_reason, cb_flags);
1651 
1652 		return (rval);
1653 	} else if (blk == NULL) {
1654 		USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle,
1655 		    "Get_Time returns null data");
1656 
1657 		return (USB_FAILURE);
1658 	} else {
1659 		length = MBLKL(blk);
1660 
1661 		if (length < len) {
1662 			freemsg(blk);
1663 
1664 			USB_DPRINTF_L2(PRINT_MASK_HCDI,
1665 			    hwahcp->hwahc_log_handle,
1666 			    "Get_Time returns short length %d", length);
1667 
1668 			return (USB_FAILURE);
1669 		}
1670 
1671 		data = blk->b_rptr;
1672 		if (len == 1) {
1673 			*time = *data;
1674 		} else {
1675 			*time = (data[2] << 16) | (data[1] << 8) | data[0];
1676 		}
1677 		freemsg(blk);
1678 
1679 		return (USB_SUCCESS);
1680 	}
1681 }
1682