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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Universal Host Controller Driver (UHCI)
30  *
31  * The UHCI driver is a driver which interfaces to the Universal
32  * Serial Bus Driver (USBA) and the Host Controller (HC). The interface to
33  * the Host Controller is defined by the Universal Host Controller Interface.
34  * This file contains the code for HCDI entry points.
35  */
36 #include <sys/usb/hcd/uhci/uhcid.h>
37 #include <sys/usb/hcd/uhci/uhcitgt.h>
38 #include <sys/usb/hcd/uhci/uhciutil.h>
39 #include <sys/strsun.h>
40 
41 /* function prototypes */
42 static int	uhci_pipe_send_isoc_data(uhci_state_t *uhcip,
43 			usba_pipe_handle_data_t *ph, usb_isoc_req_t *isoc_req,
44 			usb_flags_t usb_flags);
45 static int	uhci_send_intr_data(uhci_state_t *uhcip,
46 			usba_pipe_handle_data_t	*pipe_handle,
47 			usb_intr_req_t		*req,
48 			usb_flags_t		flags);
49 static int	uhci_start_periodic_pipe_polling(uhci_state_t *uhcip,
50 			usba_pipe_handle_data_t	*ph,
51 			usb_opaque_t		reqp,
52 			usb_flags_t		flags);
53 static int	uhci_stop_periodic_pipe_polling(uhci_state_t *uhcip,
54 			usba_pipe_handle_data_t	*ph,
55 			usb_flags_t		flags);
56 static void	uhci_update_intr_td_data_toggle(uhci_state_t *uhcip,
57 			uhci_pipe_private_t *pp);
58 
59 
60 /* Maximum bulk transfer size */
61 int uhci_bulk_transfer_size = UHCI_BULK_MAX_XFER_SIZE;
62 
63 /*
64  * uhci_hcdi_pipe_open:
65  *	Member of HCD Ops structure and called during client specific pipe open
66  *	Add the pipe to the data structure representing the device and allocate
67  *	bandwidth for the pipe if it is a interrupt or isochronous endpoint.
68  */
69 int
70 uhci_hcdi_pipe_open(usba_pipe_handle_data_t *ph, usb_flags_t flags)
71 {
72 	uint_t			node = 0;
73 	usb_addr_t		usb_addr;
74 	uhci_state_t		*uhcip;
75 	uhci_pipe_private_t	*pp;
76 	int			rval, error = USB_SUCCESS;
77 
78 	ASSERT(ph);
79 
80 	usb_addr = ph->p_usba_device->usb_addr;
81 	uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
82 
83 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
84 	    "uhci_hcdi_pipe_open: addr = 0x%x, ep%d", usb_addr,
85 	    ph->p_ep.bEndpointAddress & USB_EP_NUM_MASK);
86 
87 	sema_p(&uhcip->uhci_ocsem);
88 
89 	mutex_enter(&uhcip->uhci_int_mutex);
90 	rval = uhci_state_is_operational(uhcip);
91 	mutex_exit(&uhcip->uhci_int_mutex);
92 
93 	if (rval != USB_SUCCESS) {
94 		sema_v(&uhcip->uhci_ocsem);
95 
96 		return (rval);
97 	}
98 
99 	/*
100 	 * Return failure immediately for any other pipe open on the root hub
101 	 * except control or interrupt pipe.
102 	 */
103 	if (usb_addr == ROOT_HUB_ADDR) {
104 		switch (UHCI_XFER_TYPE(&ph->p_ep)) {
105 		case USB_EP_ATTR_CONTROL:
106 			USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
107 			    "uhci_hcdi_pipe_open: Root hub control pipe");
108 			break;
109 		case USB_EP_ATTR_INTR:
110 			ASSERT(UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN);
111 
112 			mutex_enter(&uhcip->uhci_int_mutex);
113 			uhcip->uhci_root_hub.rh_intr_pipe_handle = ph;
114 
115 			/*
116 			 * Set the state of the root hub interrupt
117 			 * pipe as IDLE.
118 			 */
119 			uhcip->uhci_root_hub.rh_pipe_state =
120 			    UHCI_PIPE_STATE_IDLE;
121 
122 			ASSERT(uhcip->uhci_root_hub.rh_client_intr_req == NULL);
123 			uhcip->uhci_root_hub.rh_client_intr_req = NULL;
124 
125 			ASSERT(uhcip->uhci_root_hub.rh_curr_intr_reqp == NULL);
126 			uhcip->uhci_root_hub.rh_curr_intr_reqp = NULL;
127 
128 			USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
129 			    "uhci_hcdi_pipe_open: Root hub interrupt "
130 			    "pipe open succeeded");
131 			mutex_exit(&uhcip->uhci_int_mutex);
132 			sema_v(&uhcip->uhci_ocsem);
133 
134 			return (USB_SUCCESS);
135 		default:
136 			USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
137 			    "uhci_hcdi_pipe_open: Root hub pipe open failed");
138 			sema_v(&uhcip->uhci_ocsem);
139 
140 			return (USB_FAILURE);
141 		}
142 	}
143 
144 	/*
145 	 * A portion of the bandwidth is reserved for the non-periodic
146 	 * transfers  i.e control and bulk transfers in each  of one
147 	 * mill second frame period & usually it will be 10% of frame
148 	 * period. Hence there is no need to check for the available
149 	 * bandwidth before adding the control or bulk endpoints.
150 	 *
151 	 * There is a need to check for the available bandwidth before
152 	 * adding the periodic transfers i.e interrupt & isochronous, since
153 	 * all these periodic transfers are guaranteed transfers. Usually,
154 	 * 90% of the total frame time is reserved for periodic transfers.
155 	 */
156 	if (UHCI_PERIODIC_ENDPOINT(&ph->p_ep)) {
157 		/* Zero Max Packet size endpoints are not supported */
158 		if (ph->p_ep.wMaxPacketSize == 0) {
159 			USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
160 			    "uhci_hcdi_pipe_open: Zero length packet");
161 			sema_v(&uhcip->uhci_ocsem);
162 
163 			return (USB_FAILURE);
164 		}
165 
166 		mutex_enter(&uhcip->uhci_int_mutex);
167 		mutex_enter(&ph->p_mutex);
168 
169 		error = uhci_allocate_bandwidth(uhcip, ph, &node);
170 		if (error != USB_SUCCESS) {
171 
172 			USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
173 			    "uhci_hcdi_pipe_open: Bandwidth allocation failed");
174 			mutex_exit(&ph->p_mutex);
175 			mutex_exit(&uhcip->uhci_int_mutex);
176 			sema_v(&uhcip->uhci_ocsem);
177 
178 			return (error);
179 		}
180 
181 		mutex_exit(&ph->p_mutex);
182 		mutex_exit(&uhcip->uhci_int_mutex);
183 	}
184 
185 	/* Create the HCD pipe private structure */
186 	pp = kmem_zalloc(sizeof (uhci_pipe_private_t),
187 	    (flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP);
188 	if (pp == NULL) {
189 		USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
190 		    "uhci_hcdi_pipe_open: pp allocation failure");
191 
192 		if (UHCI_PERIODIC_ENDPOINT(&ph->p_ep)) {
193 			mutex_enter(&uhcip->uhci_int_mutex);
194 			uhci_deallocate_bandwidth(uhcip, ph);
195 			mutex_exit(&uhcip->uhci_int_mutex);
196 		}
197 		sema_v(&uhcip->uhci_ocsem);
198 
199 		return (USB_NO_RESOURCES);
200 	}
201 
202 	mutex_enter(&uhcip->uhci_int_mutex);
203 	rval = uhci_state_is_operational(uhcip);
204 
205 	if (rval != USB_SUCCESS) {
206 		kmem_free(ph, sizeof (uhci_pipe_private_t));
207 		mutex_exit(&uhcip->uhci_int_mutex);
208 		sema_v(&uhcip->uhci_ocsem);
209 
210 		return (rval);
211 	}
212 	pp->pp_node = node;	/* Store the node in the interrupt lattice */
213 
214 	/* Initialize frame number */
215 	pp->pp_frame_num = INVALID_FRNUM;
216 
217 	/* Set the state of pipe as IDLE */
218 	pp->pp_state = UHCI_PIPE_STATE_IDLE;
219 
220 	/* Store a pointer to the pipe handle */
221 	pp->pp_pipe_handle = ph;
222 
223 	/* Store the pointer in the pipe handle */
224 	mutex_enter(&ph->p_mutex);
225 	ph->p_hcd_private = (usb_opaque_t)pp;
226 
227 	/* Store a copy of the pipe policy */
228 	bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
229 	mutex_exit(&ph->p_mutex);
230 
231 	/* don't check for ROOT_HUB here anymore */
232 	if (UHCI_XFER_TYPE(&ph->p_ep) != USB_EP_ATTR_ISOCH) {
233 		/* Allocate the host controller endpoint descriptor */
234 		pp->pp_qh = uhci_alloc_queue_head(uhcip);
235 
236 		if (pp->pp_qh == NULL) {
237 			USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
238 			    "uhci_hcdi_pipe_open: QH allocation failed");
239 
240 			if (UHCI_PERIODIC_ENDPOINT(&ph->p_ep)) {
241 				uhci_deallocate_bandwidth(uhcip, ph);
242 			}
243 
244 			mutex_enter(&ph->p_mutex);
245 
246 			/*
247 			 * Deallocate the hcd private portion
248 			 * of the pipe handle.
249 			 */
250 			kmem_free(ph->p_hcd_private,
251 			    sizeof (uhci_pipe_private_t));
252 
253 			/*
254 			 * Set the private structure in the
255 			 * pipe handle equal to NULL.
256 			 */
257 			ph->p_hcd_private = NULL;
258 			mutex_exit(&ph->p_mutex);
259 			mutex_exit(&uhcip->uhci_int_mutex);
260 
261 			sema_v(&uhcip->uhci_ocsem);
262 
263 			return (USB_NO_RESOURCES);
264 		}
265 
266 		/*
267 		 * Insert the endpoint onto the host controller's
268 		 * appropriate endpoint list. The host controller
269 		 * will not schedule this endpoint until there are
270 		 * any TD's to process.
271 		 */
272 		uhci_insert_qh(uhcip, ph);
273 	}
274 
275 	/*
276 	 * Restore the data toggle from usb device structure.
277 	 */
278 	if (((ph->p_ep.bmAttributes) & USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR ||
279 	    ((ph->p_ep.bmAttributes) & USB_EP_ATTR_MASK) == USB_EP_ATTR_BULK) {
280 		mutex_enter(&ph->p_mutex);
281 
282 		pp->pp_data_toggle = usba_hcdi_get_data_toggle(
283 		    ph->p_usba_device, ph->p_ep.bEndpointAddress);
284 		mutex_exit(&ph->p_mutex);
285 	}
286 
287 	mutex_exit(&uhcip->uhci_int_mutex);
288 	sema_v(&uhcip->uhci_ocsem);
289 
290 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
291 	    "uhci_hcdi_pipe_open: ph = 0x%p", (void *)ph);
292 
293 	return (USB_SUCCESS);
294 }
295 
296 
297 /*
298  * uhci_hcdi_pipe_close:
299  *	Member of HCD Ops structure and called during the client specific pipe
300  *	close. Remove the pipe to the data structure representing the device
301  *	deallocate bandwidth for the pipe if it is an intr or isoch endpoint.
302  */
303 int
304 uhci_hcdi_pipe_close(usba_pipe_handle_data_t *ph, usb_flags_t usb_flags)
305 {
306 	usb_addr_t		usb_addr;
307 	uhci_state_t		*uhcip;
308 	usb_ep_descr_t		*eptd = &ph->p_ep;
309 	uhci_pipe_private_t	*pp;
310 
311 	uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
312 	pp = (uhci_pipe_private_t *)ph->p_hcd_private;
313 	usb_addr = ph->p_usba_device->usb_addr;
314 
315 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
316 	    "uhci_hcdi_pipe_close: addr = 0x%x, ep%d, flags = 0x%x", usb_addr,
317 	    eptd->bEndpointAddress, usb_flags);
318 
319 	sema_p(&uhcip->uhci_ocsem);
320 
321 	mutex_enter(&uhcip->uhci_int_mutex);
322 
323 	/*
324 	 * Check whether the pipe is a root hub
325 	 */
326 	if (usb_addr == ROOT_HUB_ADDR) {
327 		switch (UHCI_XFER_TYPE(eptd)) {
328 		case USB_EP_ATTR_CONTROL:
329 			USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
330 			    "uhci_hcdi_pipe_close: Root hub control pipe "
331 			    "close succeeded");
332 
333 			break;
334 		case USB_EP_ATTR_INTR:
335 			ASSERT((eptd->bEndpointAddress &
336 			    USB_EP_NUM_MASK) == 1);
337 
338 			/* Do interrupt pipe cleanup */
339 			uhci_root_hub_intr_pipe_cleanup(uhcip,
340 			    USB_CR_PIPE_CLOSING);
341 
342 			ASSERT(uhcip->uhci_root_hub.rh_pipe_state ==
343 			    UHCI_PIPE_STATE_IDLE);
344 
345 			uhcip->uhci_root_hub.rh_intr_pipe_handle = NULL;
346 
347 			USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
348 			    "uhci_hcdi_pipe_close: Root hub interrupt "
349 			    "pipe close succeeded");
350 
351 			uhcip->uhci_root_hub.rh_pipe_state =
352 			    UHCI_PIPE_STATE_IDLE;
353 
354 			mutex_exit(&uhcip->uhci_int_mutex);
355 			sema_v(&uhcip->uhci_ocsem);
356 			return (USB_SUCCESS);
357 		}
358 	} else {
359 		/*
360 		 * Stop all the transactions if it is not the root hub.
361 		 */
362 		if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_INTR) {
363 			/*
364 			 * Stop polling on the pipe to prevent any subsequently
365 			 * queued tds (while we're waiting for SOF, below)
366 			 * from being executed
367 			 */
368 			pp->pp_state = UHCI_PIPE_STATE_IDLE;
369 		}
370 
371 		/* Disable all outstanding tds */
372 		uhci_modify_td_active_bits(uhcip, pp);
373 
374 		/* Prevent this queue from being executed */
375 		if (UHCI_XFER_TYPE(eptd) != USB_EP_ATTR_ISOCH) {
376 			UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr);
377 		}
378 
379 		/* Wait for the next start of frame */
380 		(void) uhci_wait_for_sof(uhcip);
381 
382 		ASSERT(eptd != NULL);
383 
384 		switch (UHCI_XFER_TYPE(eptd)) {
385 		case USB_EP_ATTR_INTR:
386 			uhci_update_intr_td_data_toggle(uhcip, pp);
387 			/* FALLTHROUGH */
388 		case USB_EP_ATTR_CONTROL:
389 			uhci_remove_tds_tws(uhcip, ph);
390 			break;
391 		case USB_EP_ATTR_BULK:
392 			SetQH32(uhcip, pp->pp_qh->element_ptr,
393 			    TD_PADDR(pp->pp_qh->td_tailp));
394 			uhci_remove_bulk_tds_tws(uhcip, pp, UHCI_IN_CLOSE);
395 			uhci_save_data_toggle(pp);
396 			break;
397 		case USB_EP_ATTR_ISOCH:
398 			uhci_remove_isoc_tds_tws(uhcip, pp);
399 			break;
400 		default:
401 			USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
402 			    "uhci_hcdi_pipe_close: Unknown xfer type");
403 			break;
404 		}
405 
406 		/*
407 		 * Remove the endoint descriptor from Host Controller's
408 		 * appropriate endpoint list. Isochronous pipes dont have
409 		 * any queue heads attached to it.
410 		 */
411 		if (UHCI_XFER_TYPE(eptd) != USB_EP_ATTR_ISOCH) {
412 			uhci_remove_qh(uhcip, pp);
413 		}
414 
415 		/*
416 		 * Do the callback for the original client
417 		 * periodic IN request.
418 		 */
419 		if (pp->pp_client_periodic_in_reqp) {
420 			uhci_hcdi_callback(uhcip, pp, ph, NULL,
421 			    USB_CR_PIPE_CLOSING);
422 		}
423 
424 		/* Deallocate bandwidth */
425 		if (UHCI_PERIODIC_ENDPOINT(eptd)) {
426 			mutex_enter(&ph->p_mutex);
427 			uhci_deallocate_bandwidth(uhcip, ph);
428 			mutex_exit(&ph->p_mutex);
429 		}
430 	}
431 
432 	/* Deallocate the hcd private portion of the pipe handle.  */
433 
434 	mutex_enter(&ph->p_mutex);
435 	kmem_free(ph->p_hcd_private, sizeof (uhci_pipe_private_t));
436 	ph->p_hcd_private = NULL;
437 	mutex_exit(&ph->p_mutex);
438 
439 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
440 	    "uhci_hcdi_pipe_close: ph = 0x%p", (void *)ph);
441 
442 	mutex_exit(&uhcip->uhci_int_mutex);
443 	sema_v(&uhcip->uhci_ocsem);
444 
445 	return (USB_SUCCESS);
446 }
447 
448 
449 /*
450  * uhci_hcdi_pipe_reset:
451  */
452 int
453 uhci_hcdi_pipe_reset(usba_pipe_handle_data_t *ph, usb_flags_t usb_flags)
454 {
455 	uhci_state_t		*uhcip = uhci_obtain_state(
456 	    ph->p_usba_device->usb_root_hub_dip);
457 	uhci_pipe_private_t	*pp = (uhci_pipe_private_t *)ph->p_hcd_private;
458 	usb_ep_descr_t		*eptd = &ph->p_ep;
459 
460 	USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
461 	    "uhci_hcdi_pipe_reset: usb_flags = 0x%x", usb_flags);
462 
463 	/*
464 	 * Return failure immediately for any other pipe reset on the root
465 	 * hub except control or interrupt pipe.
466 	 */
467 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
468 		switch (UHCI_XFER_TYPE(&ph->p_ep)) {
469 		case USB_EP_ATTR_CONTROL:
470 			USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
471 			    "uhci_hcdi_pipe_reset: Pipe reset for root"
472 			    "hub control pipe successful");
473 
474 			break;
475 		case USB_EP_ATTR_INTR:
476 			mutex_enter(&uhcip->uhci_int_mutex);
477 			uhcip->uhci_root_hub.rh_pipe_state =
478 			    UHCI_PIPE_STATE_IDLE;
479 
480 			/* Do interrupt pipe cleanup */
481 			uhci_root_hub_intr_pipe_cleanup(uhcip,
482 			    USB_CR_PIPE_RESET);
483 
484 			USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
485 			    "uhci_hcdi_pipe_reset: Pipe reset for "
486 			    "root hub interrupt pipe successful");
487 			mutex_exit(&uhcip->uhci_int_mutex);
488 
489 			break;
490 		default:
491 			USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
492 			    "uhci_hcdi_pipe_reset: Root hub pipe reset failed");
493 
494 			return (USB_FAILURE);
495 		}
496 
497 		return (USB_SUCCESS);
498 	}
499 
500 	mutex_enter(&uhcip->uhci_int_mutex);
501 
502 	/*
503 	 * Set the active bit in to INACTIVE for all the remaining TD's of
504 	 * this end point.  Set the active bit for the dummy td. This will
505 	 * generate an interrupt at the end of the frame.  After receiving
506 	 * the interrupt, it is safe to to manipulate the lattice.
507 	 */
508 	uhci_modify_td_active_bits(uhcip, pp);
509 
510 	/* Initialize the element pointer */
511 	if (UHCI_XFER_TYPE(eptd) != USB_EP_ATTR_ISOCH) {
512 		UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr);
513 		SetQH32(uhcip, pp->pp_qh->element_ptr,
514 		    TD_PADDR(pp->pp_qh->td_tailp));
515 	}
516 
517 	(void) uhci_wait_for_sof(uhcip);
518 
519 	/*
520 	 * Save the data toggle and clear the pipe.
521 	 */
522 	switch (UHCI_XFER_TYPE(eptd)) {
523 	case USB_EP_ATTR_CONTROL:
524 	case USB_EP_ATTR_INTR:
525 		uhci_remove_tds_tws(uhcip, ph);
526 		break;
527 	case USB_EP_ATTR_BULK:
528 		SetQH32(uhcip, pp->pp_qh->element_ptr,
529 		    TD_PADDR(pp->pp_qh->td_tailp));
530 		uhci_remove_bulk_tds_tws(uhcip, pp, UHCI_IN_RESET);
531 		break;
532 	case USB_EP_ATTR_ISOCH:
533 		uhci_remove_isoc_tds_tws(uhcip, pp);
534 		break;
535 	default:
536 		USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
537 		    "uhci_hcdi_pipe_reset: Unknown xfer type");
538 		break;
539 	}
540 
541 	/*
542 	 * Do the callback for the original client
543 	 * periodic IN request.
544 	 */
545 	if (pp->pp_client_periodic_in_reqp) {
546 		uhci_hcdi_callback(uhcip, pp, ph, NULL, USB_CR_PIPE_RESET);
547 	}
548 
549 	/*
550 	 * Since the endpoint is stripped of Transfer Descriptors (TD),
551 	 * reset the state of the periodic pipe to IDLE.
552 	 */
553 	pp->pp_state = UHCI_PIPE_STATE_IDLE;
554 
555 	mutex_exit(&uhcip->uhci_int_mutex);
556 
557 	return (USB_SUCCESS);
558 }
559 
560 
561 /*
562  * uhci_hcdi_pipe_ctrl_xfer:
563  */
564 int
565 uhci_hcdi_pipe_ctrl_xfer(
566 	usba_pipe_handle_data_t	*ph,
567 	usb_ctrl_req_t		*ctrl_reqp,
568 	usb_flags_t		flags)
569 {
570 	uhci_state_t *uhcip = uhci_obtain_state(
571 	    ph->p_usba_device->usb_root_hub_dip);
572 	uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
573 	int error;
574 
575 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
576 	    "uhci_hcdi_pipe_ctrl_xfer: req=0x%p, ph=0x%p, flags=0x%x",
577 	    (void *)ctrl_reqp, (void *)ph, flags);
578 
579 	mutex_enter(&uhcip->uhci_int_mutex);
580 	error = uhci_state_is_operational(uhcip);
581 
582 	if (error != USB_SUCCESS) {
583 		mutex_exit(&uhcip->uhci_int_mutex);
584 
585 		return (error);
586 	}
587 
588 	ASSERT(pp->pp_state == UHCI_PIPE_STATE_IDLE);
589 
590 	/*
591 	 * Check and handle root hub control request.
592 	 */
593 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
594 		error = uhci_handle_root_hub_request(uhcip, ph, ctrl_reqp);
595 		mutex_exit(&uhcip->uhci_int_mutex);
596 
597 		return (error);
598 	}
599 
600 	/* Insert the td's on the endpoint */
601 	if ((error = uhci_insert_ctrl_td(uhcip, ph, ctrl_reqp, flags)) !=
602 	    USB_SUCCESS) {
603 		USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
604 		    "uhci_hcdi_pipe_ctrl_xfer: No resources");
605 	}
606 	mutex_exit(&uhcip->uhci_int_mutex);
607 
608 	return (error);
609 }
610 
611 
612 /*
613  * uhci_hcdi_pipe_bulk_xfer:
614  */
615 int
616 uhci_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t *pipe_handle,
617     usb_bulk_req_t *bulk_reqp, usb_flags_t usb_flags)
618 {
619 	int		error;
620 	uhci_state_t	*uhcip;
621 
622 	uhcip = uhci_obtain_state(pipe_handle->p_usba_device->usb_root_hub_dip);
623 
624 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
625 	    "uhci_hcdi_pipe_bulk_xfer: Flags = 0x%x", usb_flags);
626 
627 	/* Check the size of bulk request */
628 	if (bulk_reqp->bulk_len > UHCI_BULK_MAX_XFER_SIZE) {
629 		USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
630 		    "uhci_hcdi_pipe_bulk_xfer: req size 0x%x is more than 0x%x",
631 		    bulk_reqp->bulk_len, UHCI_BULK_MAX_XFER_SIZE);
632 
633 		return (USB_FAILURE);
634 	}
635 
636 	mutex_enter(&uhcip->uhci_int_mutex);
637 
638 	error = uhci_state_is_operational(uhcip);
639 
640 	if (error != USB_SUCCESS) {
641 		mutex_exit(&uhcip->uhci_int_mutex);
642 
643 		return (error);
644 	}
645 	/* Add the TD into the Host Controller's bulk list */
646 	if ((error = uhci_insert_bulk_td(uhcip, pipe_handle, bulk_reqp,
647 	    usb_flags)) != USB_SUCCESS) {
648 		USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
649 		    "uhci_hcdi_pipe_bulk_xfer: uhci_insert_bulk_td failed");
650 	}
651 	mutex_exit(&uhcip->uhci_int_mutex);
652 
653 	return (error);
654 }
655 
656 
657 /*
658  * uhci_hcdi_bulk_transfer_size:
659  *	Return maximum bulk transfer size
660  */
661 int
662 uhci_hcdi_bulk_transfer_size(
663 	usba_device_t	*usba_device,
664 	size_t		*size)
665 {
666 	uhci_state_t	*uhcip = uhci_obtain_state(
667 	    usba_device->usb_root_hub_dip);
668 	int		rval;
669 
670 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
671 	    "uhci_hcdi_bulk_transfer_size:");
672 
673 	mutex_enter(&uhcip->uhci_int_mutex);
674 	rval = uhci_state_is_operational(uhcip);
675 
676 	if (rval != USB_SUCCESS) {
677 		mutex_exit(&uhcip->uhci_int_mutex);
678 
679 		return (rval);
680 	}
681 
682 	*size = uhci_bulk_transfer_size;
683 	mutex_exit(&uhcip->uhci_int_mutex);
684 
685 	return (USB_SUCCESS);
686 }
687 
688 
689 /*
690  * uhci_hcdi_pipe_intr_xfer:
691  */
692 int
693 uhci_hcdi_pipe_intr_xfer(
694 	usba_pipe_handle_data_t	*ph,
695 	usb_intr_req_t		*req,
696 	usb_flags_t		flags)
697 {
698 	uhci_state_t	*uhcip = uhci_obtain_state(
699 	    ph->p_usba_device->usb_root_hub_dip);
700 
701 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
702 	    "uhci_hcdi_pipe_intr_xfer: req=0x%p, uf=0x%x", (void *)req, flags);
703 
704 	if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN) {
705 
706 		return (uhci_start_periodic_pipe_polling(uhcip, ph,
707 		    (usb_opaque_t)req, flags));
708 	} else {
709 
710 		return (uhci_send_intr_data(uhcip, ph, req, flags));
711 	}
712 }
713 
714 
715 /*
716  * uhci_send_intr_data():
717  *	send data to interrupt out pipe
718  */
719 static int
720 uhci_send_intr_data(
721 	uhci_state_t		*uhcip,
722 	usba_pipe_handle_data_t	*pipe_handle,
723 	usb_intr_req_t		*req,
724 	usb_flags_t		flags)
725 {
726 	int	rval;
727 
728 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
729 	    "uhci_send_intr_data:");
730 
731 	mutex_enter(&uhcip->uhci_int_mutex);
732 
733 	rval = uhci_state_is_operational(uhcip);
734 
735 	if (rval != USB_SUCCESS) {
736 		mutex_exit(&uhcip->uhci_int_mutex);
737 
738 		return (rval);
739 	}
740 
741 	/* Add the TD into the Host Controller's interrupt list */
742 	if ((rval = uhci_insert_intr_td(uhcip, pipe_handle, req, flags)) !=
743 	    USB_SUCCESS) {
744 		USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
745 		    "uhci_send_intr_data: No resources");
746 	}
747 	mutex_exit(&uhcip->uhci_int_mutex);
748 
749 	return (rval);
750 }
751 
752 
753 /*
754  * uhci_hcdi_pipe_stop_intr_polling()
755  */
756 int
757 uhci_hcdi_pipe_stop_intr_polling(
758 	usba_pipe_handle_data_t *pipe_handle,
759 	usb_flags_t		flags)
760 {
761 	uhci_state_t *uhcip =
762 	    uhci_obtain_state(pipe_handle->p_usba_device->usb_root_hub_dip);
763 	int		rval;
764 
765 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
766 	    "uhci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x",
767 	    (void *)pipe_handle, flags);
768 	mutex_enter(&uhcip->uhci_int_mutex);
769 
770 	rval = uhci_stop_periodic_pipe_polling(uhcip, pipe_handle, flags);
771 
772 	mutex_exit(&uhcip->uhci_int_mutex);
773 
774 	return (rval);
775 }
776 
777 
778 /*
779  * uhci_hcdi_get_current_frame_number
780  *	Get the current frame number.
781  *	Return whether the request is handled successfully.
782  */
783 int
784 uhci_hcdi_get_current_frame_number(
785 	usba_device_t		*usba_device,
786 	usb_frame_number_t	*frame_number)
787 {
788 	uhci_state_t *uhcip = uhci_obtain_state(usba_device->usb_root_hub_dip);
789 	int		rval;
790 
791 	mutex_enter(&uhcip->uhci_int_mutex);
792 	rval = uhci_state_is_operational(uhcip);
793 
794 	if (rval != USB_SUCCESS) {
795 		mutex_exit(&uhcip->uhci_int_mutex);
796 
797 		return (rval);
798 	}
799 
800 	*frame_number = uhci_get_sw_frame_number(uhcip);
801 	mutex_exit(&uhcip->uhci_int_mutex);
802 
803 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
804 	    "uhci_hcdi_get_current_frame_number: %llx",
805 	    (unsigned long long)(*frame_number));
806 
807 	return (rval);
808 }
809 
810 
811 /*
812  * uhci_hcdi_get_max_isoc_pkts
813  *	Get the maximum number of isoc packets per USB Isoch request.
814  *	Return whether the request is handled successfully.
815  */
816 int
817 uhci_hcdi_get_max_isoc_pkts(
818 	usba_device_t	*usba_device,
819 	uint_t		*max_isoc_pkts_per_request)
820 {
821 	uhci_state_t *uhcip = uhci_obtain_state(usba_device->usb_root_hub_dip);
822 	int		rval;
823 
824 	mutex_enter(&uhcip->uhci_int_mutex);
825 	rval = uhci_state_is_operational(uhcip);
826 
827 	if (rval != USB_SUCCESS) {
828 		mutex_exit(&uhcip->uhci_int_mutex);
829 
830 		return (rval);
831 	}
832 
833 	*max_isoc_pkts_per_request = UHCI_MAX_ISOC_PKTS;
834 	mutex_exit(&uhcip->uhci_int_mutex);
835 
836 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
837 	    "uhci_hcdi_get_max_isoc_pkts: 0x%x", UHCI_MAX_ISOC_PKTS);
838 
839 	return (rval);
840 }
841 
842 
843 /*
844  * uhci_hcdi_pipe_isoc_xfer:
845  */
846 int
847 uhci_hcdi_pipe_isoc_xfer(
848 	usba_pipe_handle_data_t	*ph,
849 	usb_isoc_req_t		*isoc_reqp,
850 	usb_flags_t		flags)
851 {
852 	uhci_state_t	*uhcip;
853 
854 	uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
855 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
856 	    "uhci_hcdi_pipe_isoc_xfer: req=0x%p, uf=0x%x",
857 	    (void *)isoc_reqp, flags);
858 
859 	if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN) {
860 
861 		return (uhci_start_periodic_pipe_polling(uhcip, ph,
862 		    (usb_opaque_t)isoc_reqp, flags));
863 	} else {
864 
865 		return (uhci_pipe_send_isoc_data(uhcip, ph, isoc_reqp, flags));
866 	}
867 }
868 
869 
870 /*
871  * uhci_hcdi_pipe_stop_isoc_polling()
872  */
873 int
874 uhci_hcdi_pipe_stop_isoc_polling(
875 	usba_pipe_handle_data_t	*ph,
876 	usb_flags_t		flags)
877 {
878 	uhci_state_t *uhcip =
879 	    uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip);
880 	int		rval;
881 
882 	USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
883 	    "uhci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x",
884 	    (void *)ph, flags);
885 
886 	mutex_enter(&uhcip->uhci_int_mutex);
887 	rval = uhci_state_is_operational(uhcip);
888 
889 	if (rval != USB_SUCCESS) {
890 		mutex_exit(&uhcip->uhci_int_mutex);
891 
892 		return (rval);
893 	}
894 
895 	rval = uhci_stop_periodic_pipe_polling(uhcip, ph, flags);
896 
897 	mutex_exit(&uhcip->uhci_int_mutex);
898 
899 	return (rval);
900 }
901 
902 
903 /*
904  * uhci_start_periodic_pipe_polling:
905  */
906 static int
907 uhci_start_periodic_pipe_polling(
908 	uhci_state_t		*uhcip,
909 	usba_pipe_handle_data_t	*ph,
910 	usb_opaque_t		in_reqp,
911 	usb_flags_t		flags)
912 {
913 	int			n, num_tds;
914 	int			error;
915 	usb_intr_req_t		*intr_reqp = (usb_intr_req_t *)in_reqp;
916 	usb_ep_descr_t		*eptd = &ph->p_ep;
917 	uhci_pipe_private_t	*pp = (uhci_pipe_private_t *)ph->p_hcd_private;
918 
919 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
920 	    "uhci_start_periodic_pipe_polling: flags: 0x%x, ep%d",
921 	    flags, eptd->bEndpointAddress);
922 
923 	mutex_enter(&uhcip->uhci_int_mutex);
924 
925 	error = uhci_state_is_operational(uhcip);
926 
927 	if (error != USB_SUCCESS) {
928 		mutex_exit(&uhcip->uhci_int_mutex);
929 
930 		return (error);
931 	}
932 
933 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
934 		uint_t	pipe_state = uhcip->uhci_root_hub.rh_pipe_state;
935 
936 		ASSERT(pipe_state == UHCI_PIPE_STATE_IDLE);
937 		ASSERT(UHCI_XFER_DIR(eptd) == USB_EP_DIR_IN);
938 
939 		/* ONE_XFER not supported */
940 		ASSERT((intr_reqp->intr_attributes &
941 		    USB_ATTRS_ONE_XFER) == 0);
942 		ASSERT(uhcip->uhci_root_hub.rh_client_intr_req == NULL);
943 		uhcip->uhci_root_hub.rh_client_intr_req = intr_reqp;
944 
945 		if ((error = uhci_root_hub_allocate_intr_pipe_resource(
946 		    uhcip, flags)) != USB_SUCCESS) {
947 			/* reset the client interrupt request pointer */
948 			uhcip->uhci_root_hub.rh_client_intr_req = NULL;
949 
950 			mutex_exit(&uhcip->uhci_int_mutex);
951 
952 			return (error);
953 		}
954 
955 		uhcip->uhci_root_hub.rh_pipe_state = USB_PIPE_STATE_ACTIVE;
956 
957 		USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
958 		    "uhci_start_periodic_pipe_polling: "
959 		    "Start intr polling for root hub successful");
960 
961 		/* check if we need to send the reset data up? */
962 		if (uhcip->uhci_root_hub.rh_status) {
963 			uhci_root_hub_reset_occurred(uhcip,
964 			    uhcip->uhci_root_hub.rh_status - 1);
965 
966 			uhcip->uhci_root_hub.rh_status = 0;
967 		}
968 		mutex_exit(&uhcip->uhci_int_mutex);
969 
970 		return (error);
971 	}
972 
973 	/* save the original client's periodic IN request */
974 	pp->pp_client_periodic_in_reqp = in_reqp;
975 
976 	ASSERT(pp->pp_state != UHCI_PIPE_STATE_ACTIVE);
977 	/*
978 	 *
979 	 * This pipe is uninitialized. If it is an isoc
980 	 * receive request, insert four times the same
981 	 * request so that we do not lose any frames.
982 	 */
983 	if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_ISOCH) {
984 		for (n = 0; n < 5; n++) {
985 			if ((error = uhci_start_isoc_receive_polling(
986 			    uhcip, ph, NULL, flags)) != USB_SUCCESS) {
987 
988 				USB_DPRINTF_L2(PRINT_MASK_INTR,
989 				    uhcip->uhci_log_hdl,
990 				    "uhci_start_periodic_pipe_polling: "
991 				    "Start isoc polling failed %d", n);
992 
993 				pp->pp_client_periodic_in_reqp = NULL;
994 				mutex_exit(&uhcip->uhci_int_mutex);
995 
996 				return (error);
997 			}
998 		}
999 	}
1000 
1001 	if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_INTR) {
1002 		if ((pp->pp_node < POLLING_FREQ_7MS) &&
1003 		    (!(intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER))) {
1004 			num_tds = 5;
1005 		} else {
1006 			num_tds = 1;
1007 		}
1008 
1009 		/*
1010 		 * This pipe is uninitialized.
1011 		 * Insert a TD on the interrupt ED.
1012 		 */
1013 		for (n = 0; n < num_tds; n++) {
1014 			if ((error = uhci_insert_intr_td(uhcip, ph, NULL,
1015 			    flags)) != USB_SUCCESS) {
1016 				USB_DPRINTF_L2(PRINT_MASK_INTR,
1017 				    uhcip->uhci_log_hdl,
1018 				    "uhci_start_periodic_pipe_polling: "
1019 				    "Start polling failed");
1020 
1021 				pp->pp_client_periodic_in_reqp = NULL;
1022 				mutex_exit(&uhcip->uhci_int_mutex);
1023 
1024 				return (error);
1025 			}
1026 		}
1027 	}
1028 
1029 	pp->pp_state = UHCI_PIPE_STATE_ACTIVE;
1030 
1031 	mutex_exit(&uhcip->uhci_int_mutex);
1032 
1033 	return (error);
1034 }
1035 
1036 
1037 /*
1038  * uhci_hcdi_periodic_pipe_stop_polling:
1039  */
1040 static int
1041 uhci_stop_periodic_pipe_polling(uhci_state_t *uhcip,
1042 	usba_pipe_handle_data_t  *ph, usb_flags_t flags)
1043 {
1044 	uhci_pipe_private_t	*pp = (uhci_pipe_private_t *)ph->p_hcd_private;
1045 	usb_ep_descr_t		*eptd = &ph->p_ep;
1046 
1047 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
1048 	    "uhci_stop_periodic_pipe_polling: flags = 0x%x", flags);
1049 
1050 	ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1051 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
1052 		ASSERT(UHCI_XFER_DIR(eptd) == USB_EP_DIR_IN);
1053 
1054 		if (uhcip->uhci_root_hub.rh_pipe_state ==
1055 		    UHCI_PIPE_STATE_ACTIVE) {
1056 			uhcip->uhci_root_hub.rh_pipe_state =
1057 			    UHCI_PIPE_STATE_IDLE;
1058 
1059 			/* Do interrupt pipe cleanup */
1060 			uhci_root_hub_intr_pipe_cleanup(uhcip,
1061 			    USB_CR_STOPPED_POLLING);
1062 
1063 			USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
1064 			    "uhci_stop_periodic_pipe_polling: Stop intr "
1065 			    "polling for root hub successful");
1066 
1067 		} else {
1068 			USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1069 			    "uhci_stop_periodic_pipe_polling: "
1070 			    "Intr polling for root hub is already stopped");
1071 		}
1072 
1073 		return (USB_SUCCESS);
1074 	}
1075 
1076 	if (pp->pp_state != UHCI_PIPE_STATE_ACTIVE) {
1077 		USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl,
1078 		    "uhci_stop_periodic_pipe_polling: Polling already stopped");
1079 
1080 		return (USB_SUCCESS);
1081 	}
1082 
1083 	/*
1084 	 * Set the terminate bits in all the tds in the queue and
1085 	 * in the element_ptr.
1086 	 * Do not deallocate the bandwidth or tear down the DMA
1087 	 */
1088 	uhci_modify_td_active_bits(uhcip, pp);
1089 	(void) uhci_wait_for_sof(uhcip);
1090 
1091 	if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_ISOCH) {
1092 		uhci_remove_isoc_tds_tws(uhcip, pp);
1093 		pp->pp_state = UHCI_PIPE_STATE_IDLE;
1094 	} else {
1095 		UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr);
1096 		uhci_update_intr_td_data_toggle(uhcip, pp);
1097 		SetQH32(uhcip, pp->pp_qh->element_ptr,
1098 		    TD_PADDR(pp->pp_qh->td_tailp));
1099 		uhci_remove_tds_tws(uhcip, ph);
1100 	}
1101 
1102 	pp->pp_state = UHCI_PIPE_STATE_IDLE;
1103 
1104 	if (pp->pp_client_periodic_in_reqp) {
1105 		uhci_hcdi_callback(uhcip, pp, ph, NULL, USB_CR_STOPPED_POLLING);
1106 	}
1107 
1108 	return (USB_SUCCESS);
1109 }
1110 
1111 
1112 /*
1113  * uhci_hcdi_pipe_send_isoc_data:
1114  *	Handles the isoc write request.
1115  */
1116 static int
1117 uhci_pipe_send_isoc_data(
1118 	uhci_state_t		*uhcip,
1119 	usba_pipe_handle_data_t	*ph,
1120 	usb_isoc_req_t		*isoc_req,
1121 	usb_flags_t		usb_flags)
1122 {
1123 	int			error;
1124 	size_t			max_isoc_xfer_sz, length;
1125 
1126 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
1127 	    "uhci_pipe_send_isoc_data: isoc_req = %p flags = %x",
1128 	    (void *)isoc_req, usb_flags);
1129 
1130 	ASSERT(isoc_req->isoc_pkts_count < UHCI_MAX_ISOC_PKTS);
1131 
1132 	/* Calculate the maximum isochronous transfer size */
1133 	max_isoc_xfer_sz = UHCI_MAX_ISOC_PKTS * ph->p_ep.wMaxPacketSize;
1134 
1135 	/* Check the size of isochronous request */
1136 	ASSERT(isoc_req->isoc_data != NULL);
1137 	length = MBLKL(isoc_req->isoc_data);
1138 
1139 	if (length > max_isoc_xfer_sz) {
1140 		USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
1141 		    "uhci_pipe_send_isoc_data: Maximum isoc request size %lx "
1142 		    "Given isoc request size %lx", max_isoc_xfer_sz, length);
1143 
1144 		return (USB_INVALID_REQUEST);
1145 	}
1146 
1147 
1148 	/*
1149 	 * Check whether we can insert these tds?
1150 	 * At any point of time, we can insert maximum of 1024 isoc td's,
1151 	 * size of frame list table.
1152 	 */
1153 	if (isoc_req->isoc_pkts_count > UHCI_MAX_ISOC_PKTS) {
1154 
1155 		USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
1156 		    "uhci_pipe_send_isoc_data: request too big");
1157 
1158 		return (USB_INVALID_REQUEST);
1159 	}
1160 
1161 	/* Add the TD into the Host Controller's isoc list */
1162 	mutex_enter(&uhcip->uhci_int_mutex);
1163 
1164 	error = uhci_state_is_operational(uhcip);
1165 
1166 	if (error != USB_SUCCESS) {
1167 		mutex_exit(&uhcip->uhci_int_mutex);
1168 
1169 		return (error);
1170 	}
1171 
1172 	if ((error = uhci_insert_isoc_td(uhcip, ph, isoc_req,
1173 	    length, usb_flags)) != USB_SUCCESS) {
1174 
1175 		USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
1176 		    "uhci_pipe_send_isoc_data: Unable to insert the isoc_req,"
1177 		    "Error = %d", error);
1178 	}
1179 	mutex_exit(&uhcip->uhci_int_mutex);
1180 
1181 	return (error);
1182 }
1183 
1184 
1185 /*
1186  * uhci_update_intr_td_data_toggle
1187  *	Update the data toggle and save in the usba_device structure
1188  */
1189 static void
1190 uhci_update_intr_td_data_toggle(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
1191 {
1192 	uint32_t	paddr_tail, element_ptr;
1193 	uhci_td_t	*next_td;
1194 
1195 	/* Find the next td that would have been executed */
1196 	element_ptr = GetQH32(uhcip, pp->pp_qh->element_ptr) &
1197 	    QH_ELEMENT_PTR_MASK;
1198 	next_td = TD_VADDR(element_ptr);
1199 	paddr_tail = TD_PADDR(pp->pp_qh->td_tailp);
1200 
1201 	/*
1202 	 * If element_ptr points to the dummy td, then the data toggle in
1203 	 * pp_data_toggle is correct. Otherwise update the data toggle in
1204 	 * the pipe private
1205 	 */
1206 	if (element_ptr != paddr_tail) {
1207 		pp->pp_data_toggle = GetTD_dtogg(uhcip, next_td);
1208 	}
1209 
1210 	USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
1211 	    "uhci_update_intr_td_data_toggle: "
1212 	    "pp %p toggle %x element ptr %x ptail %x",
1213 	    (void *)pp, pp->pp_data_toggle, element_ptr, paddr_tail);
1214 
1215 	uhci_save_data_toggle(pp);
1216 }
1217