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  * EHCI Host Controller Driver (EHCI)
30  *
31  * The EHCI driver is a software driver which interfaces to the Universal
32  * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
33  * the Host Controller is defined by the EHCI Host Controller Interface.
34  *
35  * This module contains the EHCI driver isochronous code, which handles all
36  * Checking of status of USB transfers, error recovery and callbacks.
37  */
38 #include <sys/usb/hcd/ehci/ehcid.h>
39 #include <sys/usb/hcd/ehci/ehci_xfer.h>
40 #include <sys/usb/hcd/ehci/ehci_util.h>
41 #include <sys/usb/hcd/ehci/ehci_isoch.h>
42 #include <sys/usb/hcd/ehci/ehci_isoch_util.h>
43 
44 /*
45  * Isochronous initialization functions
46  */
47 int ehci_isoc_init(
48 	ehci_state_t		*ehcip);
49 void ehci_isoc_cleanup(
50 	ehci_state_t		*ehcip);
51 void ehci_isoc_pipe_cleanup(
52 	ehci_state_t		*ehcip,
53 	usba_pipe_handle_data_t *ph);
54 static void ehci_wait_for_isoc_completion(
55 	ehci_state_t		*ehcip,
56 	ehci_pipe_private_t	*pp);
57 
58 /*
59  * Isochronous request functions
60  */
61 ehci_isoc_xwrapper_t *ehci_allocate_isoc_resources(
62 	ehci_state_t		*ehcip,
63 	usba_pipe_handle_data_t *ph,
64 	usb_isoc_req_t		*isoc_reqp,
65 	usb_flags_t		usb_flags);
66 int ehci_insert_isoc_req(
67 	ehci_state_t		*ehcip,
68 	ehci_pipe_private_t	*pp,
69 	ehci_isoc_xwrapper_t	*itw,
70 	usb_flags_t		usb_flags);
71 static int ehci_insert_itd_req(
72 	ehci_state_t		*ehcip,
73 	ehci_pipe_private_t	*pp,
74 	ehci_isoc_xwrapper_t	*itw,
75 	usb_flags_t		usb_flags);
76 static int ehci_insert_sitd_req(
77 	ehci_state_t		*ehcip,
78 	ehci_pipe_private_t	*pp,
79 	ehci_isoc_xwrapper_t	*itw,
80 	usb_flags_t		usb_flags);
81 static int ehci_insert_isoc_with_frame_number(
82 	ehci_state_t		*ehcip,
83 	ehci_pipe_private_t	*pp,
84 	ehci_isoc_xwrapper_t	*itw,
85 	ehci_itd_t		*current_sitd);
86 static void ehci_remove_isoc_itds(
87 	ehci_state_t		*ehcip,
88 	ehci_pipe_private_t	*pp);
89 static void ehci_mark_reclaim_isoc(
90 	ehci_state_t		*ehcip,
91 	ehci_pipe_private_t	*pp);
92 static void ehci_reclaim_isoc(
93 	ehci_state_t		*ehcip,
94 	ehci_isoc_xwrapper_t	*itw,
95 	ehci_itd_t		*itd,
96 	ehci_pipe_private_t	*pp);
97 int	ehci_start_isoc_polling(
98 	ehci_state_t		*ehcip,
99 	usba_pipe_handle_data_t	*ph,
100 	usb_flags_t		flags);
101 
102 /*
103  * Isochronronous handling functions.
104  */
105 void ehci_traverse_active_isoc_list(
106 	ehci_state_t		*ehcip);
107 static void ehci_handle_isoc(
108 	ehci_state_t		*ehcip,
109 	ehci_isoc_xwrapper_t	*itw,
110 	ehci_itd_t		*itd);
111 static void ehci_handle_itd(
112 	ehci_state_t		*ehcip,
113 	ehci_pipe_private_t	*pp,
114 	ehci_isoc_xwrapper_t	*itw,
115 	ehci_itd_t		*itd,
116 	void			*tw_handle_callback_value);
117 static void ehci_sendup_itd_message(
118 	ehci_state_t		*ehcip,
119 	ehci_pipe_private_t	*pp,
120 	ehci_isoc_xwrapper_t	*itw,
121 	ehci_itd_t		*td,
122 	usb_cr_t		error);
123 void ehci_hcdi_isoc_callback(
124 	usba_pipe_handle_data_t	*ph,
125 	ehci_isoc_xwrapper_t	*itw,
126 	usb_cr_t		completion_reason);
127 
128 
129 /*
130  * Isochronous initialization functions
131  */
132 /*
133  * Initialize all the needed resources needed by isochronous pipes.
134  */
135 int
136 ehci_isoc_init(
137 	ehci_state_t		*ehcip)
138 {
139 	return (ehci_allocate_isoc_pools(ehcip));
140 }
141 
142 
143 /*
144  * Cleanup isochronous resources.
145  */
146 void
147 ehci_isoc_cleanup(
148 	ehci_state_t		*ehcip)
149 {
150 	ehci_isoc_xwrapper_t	*itw;
151 	ehci_pipe_private_t	*pp;
152 	ehci_itd_t		*itd;
153 	int			i, ctrl, rval;
154 
155 	/* Free all the buffers */
156 	if (ehcip->ehci_itd_pool_addr && ehcip->ehci_itd_pool_mem_handle) {
157 		for (i = 0; i < ehci_get_itd_pool_size(); i ++) {
158 			itd = &ehcip->ehci_itd_pool_addr[i];
159 			ctrl = Get_ITD(ehcip->
160 			    ehci_itd_pool_addr[i].itd_state);
161 
162 			if ((ctrl != EHCI_ITD_FREE) &&
163 			    (ctrl != EHCI_ITD_DUMMY) &&
164 			    (itd->itd_trans_wrapper)) {
165 
166 				mutex_enter(&ehcip->ehci_int_mutex);
167 
168 				itw = (ehci_isoc_xwrapper_t *)
169 				    EHCI_LOOKUP_ID((uint32_t)
170 				    Get_ITD(itd->itd_trans_wrapper));
171 
172 				/* Obtain the pipe private structure */
173 				pp = itw->itw_pipe_private;
174 
175 				ehci_deallocate_itd(ehcip, itw, itd);
176 				ehci_deallocate_itw(ehcip, pp, itw);
177 
178 				mutex_exit(&ehcip->ehci_int_mutex);
179 			}
180 		}
181 
182 		/*
183 		 * If EHCI_ITD_POOL_BOUND flag is set, then unbind
184 		 * the handle for ITD pools.
185 		 */
186 		if ((ehcip->ehci_dma_addr_bind_flag &
187 		    EHCI_ITD_POOL_BOUND) == EHCI_ITD_POOL_BOUND) {
188 
189 			rval = ddi_dma_unbind_handle(
190 			    ehcip->ehci_itd_pool_dma_handle);
191 
192 			ASSERT(rval == DDI_SUCCESS);
193 		}
194 		ddi_dma_mem_free(&ehcip->ehci_itd_pool_mem_handle);
195 	}
196 
197 	/* Free the ITD pool */
198 	if (ehcip->ehci_itd_pool_dma_handle) {
199 		ddi_dma_free_handle(&ehcip->ehci_itd_pool_dma_handle);
200 	}
201 }
202 
203 
204 /*
205  * ehci_isoc_pipe_cleanup
206  *
207  * Cleanup ehci isoc pipes.
208  */
209 void ehci_isoc_pipe_cleanup(
210 	ehci_state_t		*ehcip,
211 	usba_pipe_handle_data_t *ph) {
212 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
213 	uint_t			pipe_state = pp->pp_state;
214 	usb_cr_t		completion_reason;
215 
216 	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
217 	    "ehci_isoc_pipe_cleanup: ph = 0x%p", (void *)ph);
218 
219 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
220 
221 	/* Stop all further processing */
222 	ehci_mark_reclaim_isoc(ehcip, pp);
223 
224 	/*
225 	 * Wait for processing all completed transfers
226 	 * and send result upstream/
227 	 */
228 	ehci_wait_for_isoc_completion(ehcip, pp);
229 
230 	/* Go ahead and remove all remaining itds if there are any */
231 	ehci_remove_isoc_itds(ehcip, pp);
232 
233 	switch (pipe_state) {
234 	case EHCI_PIPE_STATE_CLOSE:
235 		completion_reason = USB_CR_PIPE_CLOSING;
236 		break;
237 	case EHCI_PIPE_STATE_RESET:
238 	case EHCI_PIPE_STATE_STOP_POLLING:
239 		/* Set completion reason */
240 		completion_reason = (pipe_state ==
241 		    EHCI_PIPE_STATE_RESET) ?
242 		    USB_CR_PIPE_RESET: USB_CR_STOPPED_POLLING;
243 
244 		/* Set pipe state to idle */
245 		pp->pp_state = EHCI_PIPE_STATE_IDLE;
246 
247 		break;
248 	}
249 
250 	/*
251 	 * Do the callback for the original client
252 	 * periodic IN request.
253 	 */
254 	if ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) ==
255 	    USB_EP_DIR_IN) {
256 
257 		ehci_do_client_periodic_in_req_callback(
258 		    ehcip, pp, completion_reason);
259 	}
260 }
261 
262 
263 /*
264  * ehci_wait_for_transfers_completion:
265  *
266  * Wait for processing all completed transfers and to send results
267  * to upstream.
268  */
269 static void
270 ehci_wait_for_isoc_completion(
271 	ehci_state_t		*ehcip,
272 	ehci_pipe_private_t	*pp)
273 {
274 	clock_t			xfer_cmpl_time_wait;
275 
276 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
277 
278 	if (pp->pp_itw_head == NULL) {
279 
280 		return;
281 	}
282 
283 	/* Get the number of clock ticks to wait */
284 	xfer_cmpl_time_wait = drv_usectohz(EHCI_XFER_CMPL_TIMEWAIT * 1000000);
285 
286 	(void) cv_timedwait(&pp->pp_xfer_cmpl_cv,
287 	    &ehcip->ehci_int_mutex,
288 	    ddi_get_lbolt() + xfer_cmpl_time_wait);
289 
290 	if (pp->pp_itw_head) {
291 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
292 		    "ehci_wait_for_isoc_completion: "
293 		    "No transfers completion confirmation received");
294 	}
295 }
296 
297 
298 /*
299  *  Isochronous request functions
300  */
301 /*
302  * ehci_allocate_isoc_resources:
303  *
304  * Calculates the number of tds necessary for a isoch transfer, and
305  * allocates all the necessary resources.
306  *
307  * Returns NULL if there is insufficient resources otherwise ITW.
308  */
309 ehci_isoc_xwrapper_t *
310 ehci_allocate_isoc_resources(
311 	ehci_state_t		*ehcip,
312 	usba_pipe_handle_data_t *ph,
313 	usb_isoc_req_t		*isoc_reqp,
314 	usb_flags_t		usb_flags)
315 {
316 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
317 	int			pipe_dir, i;
318 	uint_t			max_ep_pkt_size, max_isoc_xfer_size;
319 	usb_isoc_pkt_descr_t	*isoc_pkt_descr;
320 	size_t			isoc_pkt_count, isoc_pkts_length;
321 	size_t			itw_xfer_size = 0;
322 	ehci_isoc_xwrapper_t	*itw;
323 
324 	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
325 	    "ehci_allocate_isoc_resources: flags = 0x%x", usb_flags);
326 
327 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
328 
329 	/*
330 	 * Check whether pipe is in halted state.
331 	 */
332 	if (pp->pp_state == EHCI_PIPE_STATE_ERROR) {
333 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
334 		    "ehci_allocate_isoc_resources:"
335 		    "Pipe is in error state, need pipe reset to continue");
336 
337 		return (NULL);
338 	}
339 
340 	/* Calculate the maximum isochronous transfer size we allow */
341 	max_ep_pkt_size = (ph->p_ep.wMaxPacketSize &
342 	    EHCI_ITD_CTRL_MAX_PACKET_MASK) *
343 	    CalculateITDMultiField(ph->p_ep.wMaxPacketSize);
344 
345 	max_isoc_xfer_size = EHCI_MAX_ISOC_PKTS_PER_XFER * max_ep_pkt_size;
346 
347 	/* Get the packet descriptor and number of packets to send */
348 	if (isoc_reqp) {
349 		isoc_pkt_descr = isoc_reqp->isoc_pkt_descr;
350 		isoc_pkt_count = isoc_reqp->isoc_pkts_count;
351 		isoc_pkts_length = isoc_reqp->isoc_pkts_length;
352 	} else {
353 		isoc_pkt_descr = ((usb_isoc_req_t *)
354 		    pp->pp_client_periodic_in_reqp)->isoc_pkt_descr;
355 
356 		isoc_pkt_count = ((usb_isoc_req_t *)
357 		    pp->pp_client_periodic_in_reqp)->isoc_pkts_count;
358 
359 		isoc_pkts_length = ((usb_isoc_req_t *)
360 		    pp->pp_client_periodic_in_reqp)->isoc_pkts_length;
361 	}
362 
363 	/* Calculate the size of the transfer. */
364 	pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
365 	if (pipe_dir == USB_EP_DIR_IN) {
366 		for (i = 0; i < isoc_pkt_count; i++) {
367 			/*
368 			 * isoc_pkt_length is used as Transaction Length and
369 			 * according to EHCI spec Table 3-3, the maximum value
370 			 * allowed is 3072
371 			 */
372 			if (isoc_pkt_descr->isoc_pkt_length > 3072) {
373 
374 				return (NULL);
375 			}
376 
377 			itw_xfer_size += isoc_pkt_descr->isoc_pkt_length;
378 
379 			isoc_pkt_descr++;
380 		}
381 
382 		if ((isoc_pkts_length) &&
383 		    (isoc_pkts_length != itw_xfer_size)) {
384 
385 			USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
386 			    "ehci_allocate_isoc_resources: "
387 			    "isoc_pkts_length 0x%lx is not equal to the sum of "
388 			    "all pkt lengths 0x%lx in an isoc request",
389 			    isoc_pkts_length, itw_xfer_size);
390 
391 			return (NULL);
392 		}
393 
394 	} else {
395 		ASSERT(isoc_reqp != NULL);
396 		itw_xfer_size = isoc_reqp->isoc_data->b_wptr -
397 		    isoc_reqp->isoc_data->b_rptr;
398 	}
399 
400 	/* Check the size of isochronous request */
401 	if (itw_xfer_size > max_isoc_xfer_size) {
402 
403 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
404 		    "ehci_allocate_isoc_resources: Maximum isoc request "
405 		    "size 0x%x Given isoc request size 0x%lx",
406 		    max_isoc_xfer_size, itw_xfer_size);
407 
408 		return (NULL);
409 	}
410 
411 	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
412 	    "ehci_allocate_isoc_resources: length = 0x%lx", itw_xfer_size);
413 
414 	/* Allocate the itw for this request */
415 	if ((itw = ehci_allocate_itw_resources(ehcip, pp, itw_xfer_size,
416 	    usb_flags, isoc_pkt_count)) == NULL) {
417 
418 		return (NULL);
419 	}
420 
421 	itw->itw_handle_callback_value = NULL;
422 
423 	if (pipe_dir == USB_EP_DIR_IN) {
424 		if (ehci_allocate_isoc_in_resource(ehcip, pp, itw, usb_flags) !=
425 		    USB_SUCCESS) {
426 
427 			ehci_deallocate_itw(ehcip, pp, itw);
428 
429 			return (NULL);
430 		}
431 	} else {
432 		if (itw->itw_length) {
433 			ASSERT(isoc_reqp->isoc_data != NULL);
434 
435 			/* Copy the data into the buffer */
436 			bcopy(isoc_reqp->isoc_data->b_rptr,
437 			    itw->itw_buf, itw->itw_length);
438 
439 			Sync_IO_Buffer_for_device(itw->itw_dmahandle,
440 			    itw->itw_length);
441 		}
442 		itw->itw_curr_xfer_reqp = isoc_reqp;
443 	}
444 
445 	return (itw);
446 }
447 
448 
449 /*
450  * ehci_insert_isoc_req:
451  *
452  * Insert an isochronous request into the Host Controller's
453  * isochronous list.
454  */
455 int
456 ehci_insert_isoc_req(
457 	ehci_state_t			*ehcip,
458 	ehci_pipe_private_t		*pp,
459 	ehci_isoc_xwrapper_t		*itw,
460 	usb_flags_t			usb_flags)
461 {
462 	int			error;
463 	ehci_itd_t		*new_itd, *temp_itd;
464 
465 	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
466 	    "ehci_insert_isoc_req: flags = 0x%x port status = 0x%x",
467 	    usb_flags, itw->itw_port_status);
468 
469 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
470 
471 	ASSERT(itw->itw_curr_xfer_reqp != NULL);
472 	ASSERT(itw->itw_curr_xfer_reqp->isoc_pkt_descr != NULL);
473 
474 	/*
475 	 * Save address of first usb isochronous packet descriptor.
476 	 */
477 	itw->itw_curr_isoc_pktp = itw->itw_curr_xfer_reqp->isoc_pkt_descr;
478 
479 	if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) {
480 		error = ehci_insert_itd_req(ehcip, pp, itw, usb_flags);
481 	} else {
482 		error = ehci_insert_sitd_req(ehcip, pp, itw, usb_flags);
483 	}
484 
485 	/* Either all the isocs will be added or none of them will */
486 	error = ehci_insert_isoc_to_pfl(ehcip, pp, itw);
487 
488 	if (error != USB_SUCCESS) {
489 		/*
490 		 * Deallocate all the ITDs, otherwise they will be
491 		 * lost forever.
492 		 */
493 		new_itd = itw->itw_itd_head;
494 		while (new_itd) {
495 			temp_itd = ehci_itd_iommu_to_cpu(ehcip,
496 			    Get_ITD(new_itd->itd_itw_next_itd));
497 			ehci_deallocate_itd(ehcip, itw, new_itd);
498 			new_itd = temp_itd;
499 		}
500 		if ((itw->itw_direction == USB_EP_DIR_IN)) {
501 			ehci_deallocate_isoc_in_resource(ehcip, pp, itw);
502 
503 			if (pp->pp_cur_periodic_req_cnt) {
504 				/*
505 				 * Set pipe state to stop polling and
506 				 * error to no resource. Don't insert
507 				 * any more isoch polling requests.
508 				 */
509 				pp->pp_state =
510 				    EHCI_PIPE_STATE_STOP_POLLING;
511 				pp->pp_error = error;
512 			} else {
513 				/* Set periodic in pipe state to idle */
514 				pp->pp_state = EHCI_PIPE_STATE_IDLE;
515 			}
516 
517 			return (error);
518 		}
519 
520 		/* Save how many packets and data actually went */
521 		itw->itw_num_itds = 0;
522 		itw->itw_length  = 0;
523 	}
524 
525 	/*
526 	 * Reset back to the address of first usb isochronous
527 	 * packet descriptor.
528 	 */
529 	itw->itw_curr_isoc_pktp = itw->itw_curr_xfer_reqp->isoc_pkt_descr;
530 
531 	/* Reset the CONTINUE flag */
532 	pp->pp_flag &= ~EHCI_ISOC_XFER_CONTINUE;
533 
534 	return (error);
535 }
536 
537 
538 /*
539  * ehci_insert_itd_req:
540  *
541  * Insert an ITD request into the Host Controller's isochronous list.
542  */
543 /* ARGSUSED */
544 static int
545 ehci_insert_itd_req(
546 	ehci_state_t		*ehcip,
547 	ehci_pipe_private_t	*pp,
548 	ehci_isoc_xwrapper_t	*itw,
549 	usb_flags_t		usb_flags)
550 {
551 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
552 	usb_isoc_req_t		*curr_isoc_reqp;
553 	usb_isoc_pkt_descr_t	*curr_isoc_pkt_descr;
554 	size_t			curr_isoc_xfer_offset;
555 	size_t			isoc_pkt_length;
556 	uint_t			count, xactcount;
557 	uint32_t		xact_status;
558 	uint32_t		page, pageselected;
559 	uint32_t		buf[EHCI_ITD_BUFFER_LIST_SIZE];
560 	uint16_t		index = 0;
561 	uint16_t		multi = 0;
562 	ehci_itd_t		*new_itd;
563 
564 	/*
565 	 * Get the current isochronous request and packet
566 	 * descriptor pointers.
567 	 */
568 	curr_isoc_reqp = (usb_isoc_req_t *)itw->itw_curr_xfer_reqp;
569 
570 	page = itw->itw_cookie.dmac_address;
571 	ASSERT((page % EHCI_4K_ALIGN) == 0);
572 
573 	USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
574 	    "ehci_insert_itd_req: itw_curr_xfer_reqp = 0x%p page = 0x%x,"
575 	    " pagesize = 0x%lx", (void *)itw->itw_curr_xfer_reqp, page,
576 	    itw->itw_cookie.dmac_size);
577 
578 	/* Insert all the isochronous TDs */
579 	count = 0;
580 	curr_isoc_xfer_offset = 0;
581 
582 	while (count < curr_isoc_reqp->isoc_pkts_count) {
583 
584 		/* Grab a new itd */
585 		new_itd = itw->itw_itd_free_list;
586 
587 		ASSERT(new_itd != NULL);
588 
589 		itw->itw_itd_free_list = ehci_itd_iommu_to_cpu(ehcip,
590 		    Get_ITD(new_itd->itd_link_ptr));
591 		Set_ITD(new_itd->itd_link_ptr, NULL);
592 
593 		bzero(buf, EHCI_ITD_BUFFER_LIST_SIZE * sizeof (uint32_t));
594 
595 		multi = CalculateITDMultiField(ph->p_ep.wMaxPacketSize);
596 
597 		if (multi > EHCI_ITD_CTRL_MULTI_MASK) {
598 			USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
599 			    "ehci_insert_itd_req: Wrong multi value.");
600 
601 			return (USB_FAILURE);
602 		}
603 
604 		/* Fill 8 transaction for every iTD */
605 		for (xactcount = 0, pageselected = 0;
606 		    xactcount < EHCI_ITD_CTRL_LIST_SIZE; xactcount++) {
607 
608 			curr_isoc_pkt_descr = itw->itw_curr_isoc_pktp;
609 
610 			isoc_pkt_length =
611 			    curr_isoc_pkt_descr->isoc_pkt_length;
612 
613 			curr_isoc_pkt_descr->isoc_pkt_actual_length
614 			    = isoc_pkt_length;
615 
616 			xact_status = 0;
617 
618 			if (pageselected < EHCI_ITD_BUFFER_LIST_SIZE) {
619 
620 				buf[pageselected] |= page;
621 			} else {
622 				USB_DPRINTF_L2(PRINT_MASK_INTR,
623 				    ehcip->ehci_log_hdl,
624 				    "ehci_insert_itd_req: "
625 				    "Error in buffer pointer.");
626 
627 				return (USB_FAILURE);
628 			}
629 
630 			xact_status = curr_isoc_xfer_offset;
631 			xact_status |= (pageselected << 12);
632 			xact_status |= isoc_pkt_length << 16;
633 			xact_status |= EHCI_ITD_XFER_ACTIVE;
634 
635 			/* Set IOC on the last TD. */
636 			if (count == (curr_isoc_reqp->isoc_pkts_count - 1)) {
637 				xact_status |= EHCI_ITD_XFER_IOC_ON;
638 			}
639 
640 			USB_DPRINTF_L3(PRINT_MASK_INTR,
641 			    ehcip->ehci_log_hdl,
642 			    "ehci_insert_itd_req: count = 0x%x multi = %d"
643 			    "status = 0x%x page = 0x%x index = %d "
644 			    "pageselected = %d isoc_pkt_length = 0x%lx",
645 			    xactcount, multi, xact_status, page,
646 			    index, pageselected, isoc_pkt_length);
647 
648 			/* Fill in the new itd */
649 			Set_ITD_BODY(new_itd, xactcount, xact_status);
650 
651 			itw->itw_curr_isoc_pktp++;
652 			Set_ITD_INDEX(new_itd, xactcount, index++);
653 
654 			curr_isoc_xfer_offset += isoc_pkt_length;
655 
656 			if (curr_isoc_xfer_offset >= EHCI_4K_ALIGN) {
657 				pageselected ++;
658 				page += EHCI_4K_ALIGN;
659 				curr_isoc_xfer_offset -= EHCI_4K_ALIGN;
660 			}
661 
662 			count ++;
663 			if (count >= curr_isoc_reqp->isoc_pkts_count) {
664 
665 				break;
666 			}
667 		}
668 
669 		buf[0] |= (itw->itw_endpoint_num << 8);
670 		buf[0] |= itw->itw_device_addr;
671 		buf[1] |= ph->p_ep.wMaxPacketSize &
672 		    EHCI_ITD_CTRL_MAX_PACKET_MASK;
673 
674 		if (itw->itw_direction == USB_EP_DIR_IN) {
675 			buf[1] |= EHCI_ITD_CTRL_DIR_IN;
676 		}
677 		buf[2] |= multi;
678 
679 		Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER0, buf[0]);
680 		Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER1, buf[1]);
681 		Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER2, buf[2]);
682 		Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER3, buf[3]);
683 		Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER4, buf[4]);
684 		Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER5, buf[5]);
685 		Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER6, buf[6]);
686 
687 		Set_ITD(new_itd->itd_state, EHCI_ITD_ACTIVE);
688 		ehci_print_itd(ehcip, new_itd);
689 
690 		/*
691 		 * Add this itd to the itw before we add it in the PFL
692 		 * If adding it to the PFL fails, we will have to cleanup.
693 		 */
694 		ehci_insert_itd_on_itw(ehcip, itw, new_itd);
695 
696 	}
697 
698 	return (USB_SUCCESS);
699 }
700 
701 
702 /*
703  * ehci_insert_sitd_req:
704  *
705  * Insert an SITD request into the Host Controller's isochronous list.
706  */
707 /* ARGSUSED */
708 static int
709 ehci_insert_sitd_req(
710 	ehci_state_t		*ehcip,
711 	ehci_pipe_private_t	*pp,
712 	ehci_isoc_xwrapper_t	*itw,
713 	usb_flags_t		usb_flags)
714 {
715 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
716 	usb_isoc_req_t		*curr_isoc_reqp;
717 	usb_isoc_pkt_descr_t	*curr_isoc_pkt_descr;
718 	size_t			curr_isoc_xfer_offset;
719 	size_t			isoc_pkt_length;
720 	uint_t			count;
721 	uint32_t		ctrl, uframe_sched, xfer_state;
722 	uint32_t		page0, page1, prev_sitd;
723 	uint32_t		ssplit_count;
724 	ehci_itd_t		*new_sitd;
725 
726 	/*
727 	 * Get the current isochronous request and packet
728 	 * descriptor pointers.
729 	 */
730 	curr_isoc_reqp = (usb_isoc_req_t *)itw->itw_curr_xfer_reqp;
731 
732 	/* Set the ctrl field */
733 	ctrl = 0;
734 	if (itw->itw_direction == USB_EP_DIR_IN) {
735 		ctrl |= EHCI_SITD_CTRL_DIR_IN;
736 	} else {
737 		ctrl |= EHCI_SITD_CTRL_DIR_OUT;
738 	}
739 
740 	ctrl |= (itw->itw_hub_port << EHCI_SITD_CTRL_PORT_SHIFT) &
741 	    EHCI_SITD_CTRL_PORT_MASK;
742 	ctrl |= (itw->itw_hub_addr << EHCI_SITD_CTRL_HUB_SHIFT) &
743 	    EHCI_SITD_CTRL_HUB_MASK;
744 	ctrl |= (itw->itw_endpoint_num << EHCI_SITD_CTRL_END_PT_SHIFT) &
745 	    EHCI_SITD_CTRL_END_PT_MASK;
746 	ctrl |= (itw->itw_device_addr << EHCI_SITD_CTRL_DEVICE_SHIFT) &
747 	    EHCI_SITD_CTRL_DEVICE_MASK;
748 
749 	/* Set the micro frame schedule */
750 	uframe_sched = 0;
751 	uframe_sched |= (pp->pp_smask << EHCI_SITD_UFRAME_SMASK_SHIFT) &
752 	    EHCI_SITD_UFRAME_SMASK_MASK;
753 	uframe_sched |= (pp->pp_cmask << EHCI_SITD_UFRAME_CMASK_SHIFT) &
754 	    EHCI_SITD_UFRAME_CMASK_MASK;
755 
756 	/* Set the default page information */
757 	page0 = itw->itw_cookie.dmac_address;
758 	page1 = 0;
759 
760 	prev_sitd = EHCI_ITD_LINK_PTR_INVALID;
761 
762 	/*
763 	 * Save the number of isochronous TDs needs
764 	 * to be insert to complete current isochronous request.
765 	 */
766 	itw->itw_num_itds = curr_isoc_reqp->isoc_pkts_count;
767 
768 	/* Insert all the isochronous TDs */
769 	for (count = 0, curr_isoc_xfer_offset = 0;
770 	    count < itw->itw_num_itds; count++) {
771 
772 		curr_isoc_pkt_descr = itw->itw_curr_isoc_pktp;
773 
774 		isoc_pkt_length = curr_isoc_pkt_descr->isoc_pkt_length;
775 		curr_isoc_pkt_descr->isoc_pkt_actual_length = isoc_pkt_length;
776 
777 		/* Set the transfer state information */
778 		xfer_state = 0;
779 
780 		if (itw->itw_direction == USB_EP_DIR_IN) {
781 			/* Set the size to the max packet size */
782 			xfer_state |= (ph->p_ep.wMaxPacketSize <<
783 			    EHCI_SITD_XFER_TOTAL_SHIFT) &
784 			    EHCI_SITD_XFER_TOTAL_MASK;
785 		} else {
786 			/* Set the size to the packet length */
787 			xfer_state |= (isoc_pkt_length <<
788 			    EHCI_SITD_XFER_TOTAL_SHIFT) &
789 			    EHCI_SITD_XFER_TOTAL_MASK;
790 		}
791 		xfer_state |=  EHCI_SITD_XFER_ACTIVE;
792 
793 		/* Set IOC on the last TD. */
794 		if (count == (itw->itw_num_itds - 1)) {
795 			xfer_state |= EHCI_SITD_XFER_IOC_ON;
796 		}
797 
798 		ssplit_count = isoc_pkt_length / MAX_UFRAME_SITD_XFER;
799 		if (isoc_pkt_length % MAX_UFRAME_SITD_XFER) {
800 			ssplit_count++;
801 		}
802 
803 		page1 = (ssplit_count & EHCI_SITD_XFER_TCOUNT_MASK) <<
804 		    EHCI_SITD_XFER_TCOUNT_SHIFT;
805 		if (ssplit_count > 1) {
806 			page1 |= EHCI_SITD_XFER_TP_BEGIN;
807 		} else {
808 			page1 |= EHCI_SITD_XFER_TP_ALL;
809 		}
810 
811 		/* Grab a new sitd */
812 		new_sitd = itw->itw_itd_free_list;
813 
814 		ASSERT(new_sitd != NULL);
815 
816 		itw->itw_itd_free_list = ehci_itd_iommu_to_cpu(ehcip,
817 		    Get_ITD(new_sitd->itd_link_ptr));
818 		Set_ITD(new_sitd->itd_link_ptr, NULL);
819 
820 		/* Fill in the new sitd */
821 		Set_ITD_BODY(new_sitd, EHCI_SITD_CTRL, ctrl);
822 		Set_ITD_BODY(new_sitd, EHCI_SITD_UFRAME_SCHED, uframe_sched);
823 		Set_ITD_BODY(new_sitd, EHCI_SITD_XFER_STATE, xfer_state);
824 		Set_ITD_BODY(new_sitd, EHCI_SITD_BUFFER0,
825 		    page0 + curr_isoc_xfer_offset);
826 		Set_ITD_BODY(new_sitd, EHCI_SITD_BUFFER1, page1);
827 		Set_ITD_BODY(new_sitd, EHCI_SITD_PREV_SITD, prev_sitd);
828 
829 		Set_ITD(new_sitd->itd_state, EHCI_ITD_ACTIVE);
830 
831 		/*
832 		 * Add this itd to the itw before we add it in the PFL
833 		 * If adding it to the PFL fails, we will have to cleanup.
834 		 */
835 		ehci_insert_itd_on_itw(ehcip, itw, new_sitd);
836 
837 		itw->itw_curr_isoc_pktp++;
838 		curr_isoc_xfer_offset += isoc_pkt_length;
839 	}
840 
841 	return (USB_SUCCESS);
842 }
843 
844 
845 /*
846  * ehci_remove_isoc_itds:
847  *
848  * Remove all itds from the PFL.
849  */
850 static void
851 ehci_remove_isoc_itds(
852 	ehci_state_t		*ehcip,
853 	ehci_pipe_private_t	*pp)
854 {
855 	ehci_isoc_xwrapper_t	*curr_itw, *next_itw;
856 	ehci_itd_t		*curr_itd, *next_itd;
857 
858 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
859 	    "ehci_remove_isoc_itds: pp = 0x%p", (void *)pp);
860 
861 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
862 
863 	curr_itw = pp->pp_itw_head;
864 	while (curr_itw) {
865 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
866 		    "ehci_remove_isoc_itds: itw = 0x%p num itds = %d",
867 		    (void *)curr_itw, curr_itw->itw_num_itds);
868 
869 		next_itw = curr_itw->itw_next;
870 
871 		curr_itd = curr_itw->itw_itd_head;
872 		while (curr_itd) {
873 			next_itd = ehci_itd_iommu_to_cpu(ehcip,
874 			    Get_ITD(curr_itd->itd_itw_next_itd));
875 
876 			ehci_reclaim_isoc(ehcip, curr_itw, curr_itd, pp);
877 
878 			curr_itd = next_itd;
879 		}
880 
881 		ehci_deallocate_itw(ehcip, pp, curr_itw);
882 
883 		curr_itw = next_itw;
884 	}
885 }
886 
887 
888 /*
889  * ehci_mark_reclaim_isoc:
890  *
891  * Set active ITDs to RECLAIM.
892  * Return number of ITD that need to be processed.
893  */
894 static void
895 ehci_mark_reclaim_isoc(
896 	ehci_state_t		*ehcip,
897 	ehci_pipe_private_t	*pp)
898 {
899 	usb_frame_number_t	current_frame_number;
900 	ehci_isoc_xwrapper_t	*curr_itw, *next_itw;
901 	ehci_itd_t		*curr_itd, *next_itd;
902 	uint_t			ctrl;
903 	uint_t			isActive;
904 	int			i;
905 
906 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
907 	    "ehci_mark_reclaim_isoc: pp = 0x%p", (void *)pp);
908 
909 	if (pp->pp_itw_head == NULL) {
910 
911 		return;
912 	}
913 
914 	/* Get the current frame number. */
915 	current_frame_number = ehci_get_current_frame_number(ehcip);
916 
917 	/* Traverse the list of transfer descriptors */
918 	curr_itw = pp->pp_itw_head;
919 	while (curr_itw) {
920 		next_itw = curr_itw->itw_next;
921 
922 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
923 		    "ehci_mark_reclaim_isoc: itw = 0x%p num itds = %d",
924 		    (void *)curr_itw, curr_itw->itw_num_itds);
925 
926 		curr_itd = curr_itw->itw_itd_head;
927 		while (curr_itd) {
928 			next_itd = ehci_itd_iommu_to_cpu(ehcip,
929 			    Get_ITD(curr_itd->itd_itw_next_itd));
930 
931 			if (curr_itw->itw_port_status == USBA_HIGH_SPEED_DEV) {
932 
933 				for (i = 0; i < EHCI_ITD_CTRL_LIST_SIZE; i++) {
934 					ctrl = Get_ITD_BODY(curr_itd,
935 					    EHCI_ITD_CTRL0 + i);
936 					isActive = ctrl & EHCI_ITD_XFER_ACTIVE;
937 					/* If still active, deactivate it */
938 					if (isActive) {
939 						ctrl &= ~EHCI_ITD_XFER_ACTIVE;
940 						Set_ITD_BODY(curr_itd,
941 						    EHCI_ITD_CTRL0 + i,
942 						    ctrl);
943 						break;
944 					}
945 				}
946 			} else {
947 				ctrl = Get_ITD_BODY(curr_itd,
948 				    EHCI_SITD_XFER_STATE);
949 				isActive = ctrl & EHCI_SITD_XFER_ACTIVE;
950 				/* If it is still active deactivate it */
951 				if (isActive) {
952 					ctrl &= ~EHCI_SITD_XFER_ACTIVE;
953 					Set_ITD_BODY(curr_itd,
954 					    EHCI_SITD_XFER_STATE,
955 					    ctrl);
956 				}
957 			}
958 
959 			/*
960 			 * If the itd was active put it on the reclaim status,
961 			 * so the interrupt handler will know not to process it.
962 			 * Otherwise leave it alone and let the interrupt
963 			 * handler process it normally.
964 			 */
965 			if (isActive) {
966 				Set_ITD(curr_itd->itd_state, EHCI_ITD_RECLAIM);
967 				Set_ITD_FRAME(curr_itd->itd_reclaim_number,
968 				    current_frame_number);
969 				ehci_remove_isoc_from_pfl(ehcip, curr_itd);
970 			}
971 			curr_itd = next_itd;
972 		}
973 		curr_itw = next_itw;
974 	}
975 }
976 
977 
978 /*
979  * ehci_reclaim_isoc:
980  *
981  * "Reclaim" itds that were marked as RECLAIM.
982  */
983 static void
984 ehci_reclaim_isoc(
985 	ehci_state_t		*ehcip,
986 	ehci_isoc_xwrapper_t	*itw,
987 	ehci_itd_t		*itd,
988 	ehci_pipe_private_t	*pp)
989 {
990 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
991 	    "ehci_reclaim_isoc: itd = 0x%p", (void *)itd);
992 
993 	/*
994 	 * These are itds that were marked "RECLAIM"
995 	 * by the pipe cleanup.
996 	 *
997 	 * Decrement the num_itds and the periodic in
998 	 * request count if necessary.
999 	 */
1000 	if ((--itw->itw_num_itds == 0) && (itw->itw_curr_xfer_reqp)) {
1001 		if (itw->itw_direction == USB_EP_DIR_IN) {
1002 
1003 			pp->pp_cur_periodic_req_cnt--;
1004 
1005 			ehci_deallocate_isoc_in_resource(ehcip, pp, itw);
1006 		} else {
1007 			ehci_hcdi_isoc_callback(pp->pp_pipe_handle, itw,
1008 			    USB_CR_FLUSHED);
1009 		}
1010 	}
1011 
1012 	/* Deallocate this transfer descriptor */
1013 	ehci_deallocate_itd(ehcip, itw, itd);
1014 }
1015 
1016 
1017 /*
1018  * ehci_start_isoc_polling:
1019  *
1020  * Insert the number of periodic requests corresponding to polling
1021  * interval as calculated during pipe open.
1022  */
1023 int
1024 ehci_start_isoc_polling(
1025 	ehci_state_t		*ehcip,
1026 	usba_pipe_handle_data_t	*ph,
1027 	usb_flags_t		flags)
1028 {
1029 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1030 	ehci_isoc_xwrapper_t	*itw_list, *itw;
1031 	int			i, total_itws;
1032 	int			error = USB_SUCCESS;
1033 
1034 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1035 	    "ehci_start_isoc_polling:");
1036 
1037 	/* Allocate all the necessary resources for the IN transfer */
1038 	itw_list = NULL;
1039 	total_itws = pp->pp_max_periodic_req_cnt - pp->pp_cur_periodic_req_cnt;
1040 	for (i = 0; i < total_itws; i += 1) {
1041 		itw = ehci_allocate_isoc_resources(ehcip, ph, NULL, flags);
1042 		if (itw == NULL) {
1043 			error = USB_NO_RESOURCES;
1044 			/* There are not enough resources deallocate the ITWs */
1045 			itw = itw_list;
1046 			while (itw != NULL) {
1047 				itw_list = itw->itw_next;
1048 				ehci_deallocate_isoc_in_resource(
1049 				    ehcip, pp, itw);
1050 				ehci_deallocate_itw(ehcip, pp, itw);
1051 				itw = itw_list;
1052 			}
1053 
1054 			return (error);
1055 		} else {
1056 			if (itw_list == NULL) {
1057 				itw_list = itw;
1058 			}
1059 		}
1060 	}
1061 
1062 	i = 0;
1063 	while (pp->pp_cur_periodic_req_cnt < pp->pp_max_periodic_req_cnt) {
1064 
1065 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1066 		    "ehci_start_isoc_polling: max = %d curr = %d itw = %p:",
1067 		    pp->pp_max_periodic_req_cnt, pp->pp_cur_periodic_req_cnt,
1068 		    (void *)itw_list);
1069 
1070 		itw = itw_list;
1071 		itw_list = itw->itw_next;
1072 
1073 		error = ehci_insert_isoc_req(ehcip, pp, itw, flags);
1074 
1075 		if (error == USB_SUCCESS) {
1076 			pp->pp_cur_periodic_req_cnt++;
1077 		} else {
1078 			/*
1079 			 * Deallocate the remaining tw
1080 			 * The current tw should have already been deallocated
1081 			 */
1082 			itw = itw_list;
1083 			while (itw != NULL) {
1084 				itw_list = itw->itw_next;
1085 				ehci_deallocate_isoc_in_resource(
1086 				    ehcip, pp, itw);
1087 				ehci_deallocate_itw(ehcip, pp, itw);
1088 				itw = itw_list;
1089 			}
1090 			/*
1091 			 * If this is the first req return an error.
1092 			 * Otherwise return success.
1093 			 */
1094 			if (i != 0) {
1095 				error = USB_SUCCESS;
1096 			}
1097 
1098 			break;
1099 		}
1100 		i++;
1101 	}
1102 
1103 	return (error);
1104 }
1105 
1106 
1107 /*
1108  * Isochronronous handling functions.
1109  */
1110 /*
1111  * ehci_traverse_active_isoc_list:
1112  */
1113 void
1114 ehci_traverse_active_isoc_list(
1115 	ehci_state_t		*ehcip)
1116 {
1117 	ehci_isoc_xwrapper_t	*curr_itw;
1118 	ehci_itd_t		*curr_itd, *next_itd;
1119 	uint_t			state;
1120 	ehci_pipe_private_t	*pp;
1121 
1122 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1123 	    "ehci_traverse_active_isoc_list:");
1124 
1125 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1126 
1127 	/* Sync ITD pool */
1128 	Sync_ITD_Pool(ehcip);
1129 
1130 	/* Traverse the list of done itds */
1131 	curr_itd = ehci_create_done_itd_list(ehcip);
1132 	USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1133 	    "ehci_traverse_active_isoc_list: current itd = 0x%p",
1134 	    (void *)curr_itd);
1135 
1136 	while (curr_itd) {
1137 		/* Save the next_itd */
1138 		next_itd = ehci_itd_iommu_to_cpu(ehcip,
1139 		    Get_ITD(curr_itd->itd_next_active_itd));
1140 
1141 		/* Get the transfer wrapper and the pp */
1142 		curr_itw = (ehci_isoc_xwrapper_t *)EHCI_LOOKUP_ID(
1143 		    (uint32_t)Get_ITD(curr_itd->itd_trans_wrapper));
1144 		pp = curr_itw->itw_pipe_private;
1145 
1146 		if (curr_itw->itw_port_status == USBA_HIGH_SPEED_DEV) {
1147 			ehci_print_itd(ehcip, curr_itd);
1148 		} else {
1149 			ehci_print_sitd(ehcip, curr_itd);
1150 		}
1151 
1152 		/* Get the ITD state */
1153 		state = Get_ITD(curr_itd->itd_state);
1154 
1155 		/* Only process the ITDs marked as active. */
1156 		if (state == EHCI_ITD_ACTIVE) {
1157 			ehci_parse_isoc_error(ehcip, curr_itw, curr_itd);
1158 			ehci_handle_isoc(ehcip, curr_itw, curr_itd);
1159 		} else {
1160 			ASSERT(state == EHCI_ITD_RECLAIM);
1161 			ehci_reclaim_isoc(ehcip, curr_itw, curr_itd, pp);
1162 		}
1163 
1164 		/*
1165 		 * Deallocate the transfer wrapper if there are no more
1166 		 * ITD's for the transfer wrapper.  ehci_deallocate_itw()
1167 		 * will  not deallocate the tw for a periodic in endpoint
1168 		 * since it will always have a ITD attached to it.
1169 		 */
1170 		ehci_deallocate_itw(ehcip, pp, curr_itw);
1171 
1172 		/* Check any ISOC is waiting for transfers completion event */
1173 		if (pp->pp_itw_head == NULL) {
1174 			USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1175 			    "ehci_traverse_active_isoc_list: "
1176 			    "Sent transfers completion event pp = 0x%p",
1177 			    (void *)pp);
1178 			cv_signal(&pp->pp_xfer_cmpl_cv);
1179 		}
1180 
1181 		curr_itd = next_itd;
1182 
1183 		USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1184 		    "ehci_traverse_active_isoc_list: state = 0x%x "
1185 		    "pp = 0x%p itw = 0x%p itd = 0x%p next_itd = 0x%p",
1186 		    state, (void *)pp, (void *)curr_itw, (void *)curr_itd,
1187 		    (void *)next_itd);
1188 	}
1189 }
1190 
1191 
1192 static void
1193 ehci_handle_isoc(
1194 	ehci_state_t		*ehcip,
1195 	ehci_isoc_xwrapper_t	*itw,
1196 	ehci_itd_t		*itd)
1197 {
1198 	ehci_pipe_private_t	*pp;	/* Pipe private field */
1199 
1200 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1201 
1202 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1203 	    "ehci_handle_isoc:");
1204 
1205 	/* Obtain the pipe private structure */
1206 	pp = itw->itw_pipe_private;
1207 
1208 	ehci_handle_itd(ehcip, pp, itw, itd, itw->itw_handle_callback_value);
1209 }
1210 
1211 
1212 /*
1213  * ehci_handle_itd:
1214  *
1215  * Handle an (split) isochronous transfer descriptor.
1216  * This function will deallocate the itd from the list as well.
1217  */
1218 /* ARGSUSED */
1219 static void
1220 ehci_handle_itd(
1221 	ehci_state_t		*ehcip,
1222 	ehci_pipe_private_t	*pp,
1223 	ehci_isoc_xwrapper_t	*itw,
1224 	ehci_itd_t		*itd,
1225 	void			*tw_handle_callback_value)
1226 {
1227 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
1228 	usb_isoc_req_t		*curr_isoc_reqp =
1229 	    (usb_isoc_req_t *)itw->itw_curr_xfer_reqp;
1230 	int			error = USB_SUCCESS;
1231 	int			i, index;
1232 
1233 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1234 	    "ehci_handle_itd: pp=0x%p itw=0x%p itd=0x%p "
1235 	    "isoc_reqp=0%p data=0x%p", (void *)pp, (void *)itw, (void *)itd,
1236 	    (void *)curr_isoc_reqp, (void *)curr_isoc_reqp->isoc_data);
1237 
1238 	if (itw->itw_port_status == USBA_HIGH_SPEED_DEV &&
1239 	    curr_isoc_reqp != NULL) {
1240 
1241 		for (i = 0; i < EHCI_ITD_CTRL_LIST_SIZE; i++) {
1242 
1243 			index = Get_ITD_INDEX(itd, i);
1244 			if (index == EHCI_ITD_UNUSED_INDEX) {
1245 
1246 				continue;
1247 			}
1248 			curr_isoc_reqp->
1249 			    isoc_pkt_descr[index].isoc_pkt_actual_length =
1250 			    (Get_ITD_BODY(itd, i) & EHCI_ITD_XFER_LENGTH) >> 16;
1251 		}
1252 	}
1253 
1254 	/*
1255 	 * Decrement the ITDs counter and check whether all the isoc
1256 	 * data has been send or received. If ITDs counter reaches
1257 	 * zero then inform client driver about completion current
1258 	 * isoc request. Otherwise wait for completion of other isoc
1259 	 * ITDs or transactions on this pipe.
1260 	 */
1261 	if (--itw->itw_num_itds != 0) {
1262 		/* Deallocate this transfer descriptor */
1263 		ehci_deallocate_itd(ehcip, itw, itd);
1264 
1265 		return;
1266 	}
1267 
1268 	/*
1269 	 * If this is a isoc in pipe, return the data to the client.
1270 	 * For a isoc out pipe, there is no need to do anything.
1271 	 */
1272 	if (itw->itw_direction == USB_EP_DIR_OUT) {
1273 		USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1274 		    "ehci_handle_itd: Isoc out pipe, isoc_reqp=0x%p, data=0x%p",
1275 		    (void *)curr_isoc_reqp, (void *)curr_isoc_reqp->isoc_data);
1276 
1277 		/* Do the callback */
1278 		ehci_hcdi_isoc_callback(ph, itw, USB_CR_OK);
1279 
1280 		/* Deallocate this transfer descriptor */
1281 		ehci_deallocate_itd(ehcip, itw, itd);
1282 
1283 		return;
1284 	}
1285 
1286 	/* Decrement number of IN isochronous request count */
1287 	pp->pp_cur_periodic_req_cnt--;
1288 
1289 	USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1290 	    "ehci_handle_itd: pp_cur_periodic_req_cnt = 0x%x ",
1291 	    pp->pp_cur_periodic_req_cnt);
1292 
1293 	/* Call ehci_sendup_itd_message to send message to upstream */
1294 	ehci_sendup_itd_message(ehcip, pp, itw, itd, USB_CR_OK);
1295 
1296 	/* Deallocate this transfer descriptor */
1297 	ehci_deallocate_itd(ehcip, itw, itd);
1298 
1299 	/*
1300 	 * If isochronous pipe state is still active, insert next isochronous
1301 	 * request into the Host Controller's isochronous list.
1302 	 */
1303 	if (pp->pp_state != EHCI_PIPE_STATE_ACTIVE) {
1304 
1305 		return;
1306 	}
1307 
1308 	if ((error = ehci_allocate_isoc_in_resource(ehcip, pp, itw, 0)) ==
1309 	    USB_SUCCESS) {
1310 		curr_isoc_reqp = (usb_isoc_req_t *)itw->itw_curr_xfer_reqp;
1311 
1312 		ASSERT(curr_isoc_reqp != NULL);
1313 
1314 		itw->itw_num_itds = ehci_calc_num_itds(itw,
1315 		    curr_isoc_reqp->isoc_pkts_count);
1316 
1317 		if (ehci_allocate_itds_for_itw(ehcip, itw, itw->itw_num_itds) !=
1318 		    USB_SUCCESS) {
1319 			ehci_deallocate_isoc_in_resource(ehcip, pp, itw);
1320 			itw->itw_num_itds = 0;
1321 			error = USB_FAILURE;
1322 		}
1323 	}
1324 
1325 	if ((error != USB_SUCCESS) ||
1326 	    (ehci_insert_isoc_req(ehcip, pp, itw, 0) != USB_SUCCESS)) {
1327 		/*
1328 		 * Set pipe state to stop polling and error to no
1329 		 * resource. Don't insert any more isoch polling
1330 		 * requests.
1331 		 */
1332 		pp->pp_state = EHCI_PIPE_STATE_STOP_POLLING;
1333 		pp->pp_error = USB_CR_NO_RESOURCES;
1334 
1335 	} else {
1336 		/* Increment number of IN isochronous request count */
1337 		pp->pp_cur_periodic_req_cnt++;
1338 
1339 		ASSERT(pp->pp_cur_periodic_req_cnt ==
1340 		    pp->pp_max_periodic_req_cnt);
1341 	}
1342 }
1343 
1344 
1345 /*
1346  * ehci_sendup_qtd_message:
1347  *	copy data, if necessary and do callback
1348  */
1349 /* ARGSUSED */
1350 static void
1351 ehci_sendup_itd_message(
1352 	ehci_state_t		*ehcip,
1353 	ehci_pipe_private_t	*pp,
1354 	ehci_isoc_xwrapper_t	*itw,
1355 	ehci_itd_t		*td,
1356 	usb_cr_t		error)
1357 {
1358 	usb_isoc_req_t		*isoc_reqp = itw->itw_curr_xfer_reqp;
1359 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
1360 	size_t			length;
1361 	uchar_t			*buf;
1362 	mblk_t			*mp;
1363 
1364 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1365 
1366 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1367 	    "ehci_sendup_itd_message:");
1368 
1369 	ASSERT(itw != NULL);
1370 
1371 	length = itw->itw_length;
1372 
1373 	/* Copy the data into the mblk_t */
1374 	buf = (uchar_t *)itw->itw_buf;
1375 
1376 	USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1377 	    "ehci_sendup_itd_message: length %ld error %d", length, error);
1378 
1379 	/* Get the message block */
1380 	mp = isoc_reqp->isoc_data;
1381 
1382 	ASSERT(mp != NULL);
1383 
1384 	if (length) {
1385 		/* Sync IO buffer */
1386 		Sync_IO_Buffer(itw->itw_dmahandle, length);
1387 
1388 		/* Copy the data into the message */
1389 		ddi_rep_get8(itw->itw_accesshandle,
1390 		    mp->b_rptr, buf, length, DDI_DEV_AUTOINCR);
1391 
1392 		/* Increment the write pointer */
1393 		mp->b_wptr = mp->b_wptr + length;
1394 	} else {
1395 		USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1396 		    "ehci_sendup_itd_message: Zero length packet");
1397 	}
1398 
1399 	ehci_hcdi_isoc_callback(ph, itw, error);
1400 }
1401 
1402 
1403 /*
1404  * ehci_hcdi_isoc_callback:
1405  *
1406  * Convenience wrapper around usba_hcdi_cb() other than root hub.
1407  */
1408 void
1409 ehci_hcdi_isoc_callback(
1410 	usba_pipe_handle_data_t	*ph,
1411 	ehci_isoc_xwrapper_t	*itw,
1412 	usb_cr_t		completion_reason)
1413 {
1414 	ehci_state_t		*ehcip = ehci_obtain_state(
1415 	    ph->p_usba_device->usb_root_hub_dip);
1416 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1417 	usb_opaque_t		curr_xfer_reqp;
1418 	uint_t			pipe_state = 0;
1419 
1420 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1421 	    "ehci_hcdi_isoc_callback: ph = 0x%p, itw = 0x%p, cr = 0x%x",
1422 	    (void *)ph, (void *)itw, completion_reason);
1423 
1424 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1425 
1426 	/* Set the pipe state as per completion reason */
1427 	switch (completion_reason) {
1428 	case USB_CR_OK:
1429 		pipe_state = pp->pp_state;
1430 		break;
1431 	case USB_CR_NO_RESOURCES:
1432 	case USB_CR_NOT_SUPPORTED:
1433 	case USB_CR_PIPE_RESET:
1434 	case USB_CR_STOPPED_POLLING:
1435 		pipe_state = EHCI_PIPE_STATE_IDLE;
1436 		break;
1437 	case USB_CR_PIPE_CLOSING:
1438 		break;
1439 	}
1440 
1441 	pp->pp_state = pipe_state;
1442 
1443 	if (itw && itw->itw_curr_xfer_reqp) {
1444 		curr_xfer_reqp = (usb_opaque_t)itw->itw_curr_xfer_reqp;
1445 		itw->itw_curr_xfer_reqp = NULL;
1446 	} else {
1447 		ASSERT(pp->pp_client_periodic_in_reqp != NULL);
1448 
1449 		curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
1450 		pp->pp_client_periodic_in_reqp = NULL;
1451 	}
1452 
1453 	ASSERT(curr_xfer_reqp != NULL);
1454 
1455 	mutex_exit(&ehcip->ehci_int_mutex);
1456 
1457 	usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason);
1458 
1459 	mutex_enter(&ehcip->ehci_int_mutex);
1460 }
1461