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