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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * EHCI Host Controller Driver (EHCI)
31  *
32  * The EHCI driver is a software driver which interfaces to the Universal
33  * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
34  * the Host Controller is defined by the EHCI Host Controller Interface.
35  *
36  * This module contains the EHCI driver isochronous code, which handles all
37  * Checking of status of USB transfers, error recovery and callbacks.
38  */
39 #include <sys/usb/hcd/ehci/ehcid.h>
40 #include <sys/usb/hcd/ehci/ehci_xfer.h>
41 #include <sys/usb/hcd/ehci/ehci_util.h>
42 
43 /* Adjustable variables for the size of isoc pools */
44 int ehci_itd_pool_size = EHCI_ITD_POOL_SIZE;
45 
46 /*
47  * pool functions
48  */
49 int ehci_allocate_isoc_pools(
50 	ehci_state_t		*ehcip);
51 int ehci_get_itd_pool_size();
52 
53 /*
54  * Isochronous Transfer Wrapper Functions
55  */
56 ehci_isoc_xwrapper_t *ehci_allocate_itw_resources(
57 	ehci_state_t 		*ehcip,
58 	ehci_pipe_private_t	*pp,
59 	size_t			itw_length,
60 	usb_flags_t		usb_flags,
61 	size_t 			pkt_count);
62 static ehci_isoc_xwrapper_t *ehci_allocate_itw(
63 	ehci_state_t		*ehcip,
64 	ehci_pipe_private_t	*pp,
65 	size_t			length,
66 	usb_flags_t		usb_flags);
67 void ehci_deallocate_itw(
68 	ehci_state_t		*ehcip,
69 	ehci_pipe_private_t	*pp,
70 	ehci_isoc_xwrapper_t	*itw);
71 static void ehci_free_itw_dma(
72 	ehci_state_t		*ehcip,
73 	ehci_pipe_private_t	*pp,
74 	ehci_isoc_xwrapper_t	*itw);
75 
76 /*
77  * transfer descriptor functions
78  */
79 static ehci_itd_t *ehci_allocate_itd(
80 	ehci_state_t		*ehcip);
81 void ehci_deallocate_itd(
82 	ehci_state_t		*ehcip,
83 	ehci_isoc_xwrapper_t	*itw,
84 	ehci_itd_t		*old_itd);
85 uint_t ehci_calc_num_itds(
86 	ehci_isoc_xwrapper_t	*itw,
87 	size_t 			pkt_count);
88 int ehci_allocate_itds_for_itw(
89 	ehci_state_t		*ehcip,
90 	ehci_isoc_xwrapper_t	*itw,
91 	uint_t			itd_count);
92 static void ehci_deallocate_itds_for_itw(
93 	ehci_state_t		*ehcip,
94 	ehci_isoc_xwrapper_t	*itw);
95 void ehci_insert_itd_on_itw(
96 	ehci_state_t		*ehcip,
97 	ehci_isoc_xwrapper_t	*itw,
98 	ehci_itd_t		*itd);
99 void ehci_insert_itd_into_active_list(
100 	ehci_state_t		*ehcip,
101 	ehci_itd_t		*itd);
102 void ehci_remove_itd_from_active_list(
103 	ehci_state_t		*ehcip,
104 	ehci_itd_t		*itd);
105 ehci_itd_t *ehci_create_done_itd_list(
106 	ehci_state_t		*ehcip);
107 int ehci_insert_isoc_to_pfl(
108 	ehci_state_t		*ehcip,
109 	ehci_pipe_private_t	*pp,
110 	ehci_isoc_xwrapper_t	*itw);
111 void ehci_remove_isoc_from_pfl(
112 	ehci_state_t		*ehcip,
113 	ehci_itd_t		*curr_itd);
114 
115 
116 /*
117  * Isochronous in resource functions
118  */
119 int ehci_allocate_isoc_in_resource(
120 	ehci_state_t		*ehcip,
121 	ehci_pipe_private_t	*pp,
122 	ehci_isoc_xwrapper_t	*tw,
123 	usb_flags_t		flags);
124 void ehci_deallocate_isoc_in_resource(
125 	ehci_state_t		*ehcip,
126 	ehci_pipe_private_t	*pp,
127 	ehci_isoc_xwrapper_t	*itw);
128 
129 /*
130  * memory addr functions
131  */
132 uint32_t ehci_itd_cpu_to_iommu(
133 	ehci_state_t		*ehcip,
134 	ehci_itd_t		*addr);
135 ehci_itd_t *ehci_itd_iommu_to_cpu(
136 	ehci_state_t		*ehcip,
137 	uintptr_t		addr);
138 
139 /*
140  * Error parsing functions
141  */
142 void ehci_parse_isoc_error(
143 	ehci_state_t		*ehcip,
144 	ehci_isoc_xwrapper_t	*itw,
145 	ehci_itd_t		*itd);
146 static usb_cr_t ehci_parse_itd_error(
147 	ehci_state_t		*ehcip,
148 	ehci_isoc_xwrapper_t	*itw,
149 	ehci_itd_t		*itd);
150 static usb_cr_t ehci_parse_sitd_error(
151 	ehci_state_t		*ehcip,
152 	ehci_isoc_xwrapper_t	*itw,
153 	ehci_itd_t		*itd);
154 
155 /*
156  * print functions
157  */
158 void ehci_print_itd(
159 	ehci_state_t		*ehcip,
160 	ehci_itd_t		*itd);
161 
162 
163 /*
164  * ehci_allocate_isoc_pools:
165  *
166  * Allocate the system memory for itd which are for low/full/high speed
167  * Transfer Descriptors. Must be aligned to a 32 byte boundary.
168  */
169 int
170 ehci_allocate_isoc_pools(ehci_state_t	*ehcip)
171 {
172 	ddi_device_acc_attr_t		dev_attr;
173 	size_t				real_length;
174 	int				result;
175 	uint_t				ccount;
176 	int				i;
177 
178 	USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
179 	    "ehci_allocate_isoc_pools:");
180 
181 	/* Byte alignment */
182 	ehcip->ehci_dma_attr.dma_attr_align = EHCI_DMA_ATTR_TD_QH_ALIGNMENT;
183 
184 	/* Allocate the itd pool DMA handle */
185 	result = ddi_dma_alloc_handle(ehcip->ehci_dip,
186 	    &ehcip->ehci_dma_attr,
187 	    DDI_DMA_SLEEP,
188 	    0,
189 	    &ehcip->ehci_itd_pool_dma_handle);
190 
191 	if (result != DDI_SUCCESS) {
192 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
193 		    "ehci_allocate_isoc_pools: Alloc handle failed");
194 
195 		return (DDI_FAILURE);
196 	}
197 
198 	/* The host controller will be little endian */
199 	dev_attr.devacc_attr_version		= DDI_DEVICE_ATTR_V0;
200 	dev_attr.devacc_attr_endian_flags	= DDI_STRUCTURE_LE_ACC;
201 	dev_attr.devacc_attr_dataorder		= DDI_STRICTORDER_ACC;
202 
203 	/* Allocate the memory */
204 	result = ddi_dma_mem_alloc(ehcip->ehci_itd_pool_dma_handle,
205 	    ehci_itd_pool_size * sizeof (ehci_itd_t),
206 	    &dev_attr,
207 	    DDI_DMA_CONSISTENT,
208 	    DDI_DMA_SLEEP,
209 	    0,
210 	    (caddr_t *)&ehcip->ehci_itd_pool_addr,
211 	    &real_length,
212 	    &ehcip->ehci_itd_pool_mem_handle);
213 
214 	if (result != DDI_SUCCESS) {
215 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
216 		    "ehci_allocate_isoc_pools: Alloc memory failed");
217 
218 		return (DDI_FAILURE);
219 	}
220 
221 	/* Map the ITD pool into the I/O address space */
222 	result = ddi_dma_addr_bind_handle(
223 			ehcip->ehci_itd_pool_dma_handle,
224 			NULL,
225 			(caddr_t)ehcip->ehci_itd_pool_addr,
226 			real_length,
227 			DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
228 			DDI_DMA_SLEEP,
229 			NULL,
230 			&ehcip->ehci_itd_pool_cookie,
231 			&ccount);
232 
233 	bzero((void *)ehcip->ehci_itd_pool_addr,
234 			ehci_itd_pool_size * sizeof (ehci_itd_t));
235 
236 	/* Process the result */
237 	if (result == DDI_DMA_MAPPED) {
238 		/* The cookie count should be 1 */
239 		if (ccount != 1) {
240 			USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
241 			    "ehci_allocate_isoc_pools: More than 1 cookie");
242 
243 			return (DDI_FAILURE);
244 		}
245 	} else {
246 		USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
247 		    "ehci_allocate_isoc_pools: Result = %d", result);
248 
249 		ehci_decode_ddi_dma_addr_bind_handle_result(ehcip, result);
250 
251 		return (DDI_FAILURE);
252 	}
253 
254 	/*
255 	 * DMA addresses for ITD pools are bound
256 	 */
257 	ehcip->ehci_dma_addr_bind_flag |= EHCI_ITD_POOL_BOUND;
258 
259 	/* Initialize the ITD pool */
260 	for (i = 0; i < ehci_itd_pool_size; i++) {
261 		Set_ITD(ehcip->ehci_itd_pool_addr[i].itd_state,
262 		    EHCI_ITD_FREE);
263 	}
264 
265 	return (DDI_SUCCESS);
266 }
267 
268 
269 int
270 ehci_get_itd_pool_size()
271 {
272 	return (ehci_itd_pool_size);
273 }
274 
275 
276 /*
277  * Isochronous Transfer Wrapper Functions
278  */
279 /*
280  * ehci_allocate_itw:
281  *
282  * Allocate an iTW and n iTD from the iTD buffer pool and places it into the
283  * ITW.  It does an all or nothing transaction.
284  *
285  * Calculates the number of iTD needed based on pipe speed.
286  * For LOW/FULL speed devices, 1 iTD is needed for each packet.
287  * For HIGH speed device, 1 iTD is needed for 8 to 24 packets, depending on
288  *     the multiplier for "HIGH BANDWIDTH" transfers look at 4.7 in EHCI spec.
289  *
290  * Returns NULL if there is insufficient resources otherwise ITW.
291  */
292 ehci_isoc_xwrapper_t *
293 ehci_allocate_itw_resources(
294 	ehci_state_t 		*ehcip,
295 	ehci_pipe_private_t	*pp,
296 	size_t			itw_length,
297 	usb_flags_t		usb_flags,
298 	size_t 			pkt_count)
299 {
300 	uint_t			itd_count;
301 	ehci_isoc_xwrapper_t	*itw;
302 
303 	itw = ehci_allocate_itw(ehcip, pp, itw_length, usb_flags);
304 
305 	if (itw == NULL) {
306 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
307 		    "ehci_allocate_itw_resources: Unable to allocate ITW");
308 	} else {
309 		itd_count = ehci_calc_num_itds(itw, pkt_count);
310 
311 		if (ehci_allocate_itds_for_itw(ehcip, itw, itd_count) ==
312 		    USB_SUCCESS) {
313 			itw->itw_num_itds = itd_count;
314 		} else {
315 			ehci_deallocate_itw(ehcip, pp, itw);
316 			itw = NULL;
317 		}
318 	}
319 
320 	return (itw);
321 }
322 
323 
324 /*
325  * ehci_allocate_itw:
326  *
327  * Creates a Isochronous Transfer Wrapper (itw) and populate it with this
328  * endpoint's data.  This involves the allocation of DMA resources.
329  *
330  * ITW Fields not set by this function:
331  * - will be populated itds are allocated
332  *   num_ids
333  *   itd_head
334  *   itd_tail
335  *   curr_xfer_reqp
336  *   curr_isoc_pktp
337  *   itw_itd_free_list
338  * - Should be set by the calling function
339  *   itw_handle_callback_value
340  */
341 static ehci_isoc_xwrapper_t *
342 ehci_allocate_itw(
343 	ehci_state_t		*ehcip,
344 	ehci_pipe_private_t	*pp,
345 	size_t			length,
346 	usb_flags_t		usb_flags)
347 {
348 	ddi_device_acc_attr_t	dev_attr;
349 	int			result;
350 	size_t			real_length;
351 	uint_t			ccount;	/* Cookie count */
352 	usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
353 	usba_device_t		*usba_device = ph->p_usba_device;
354 	usb_ep_descr_t		*endpoint = &ph->p_ep;
355 	ehci_isoc_xwrapper_t	*itw;
356 
357 	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
358 	    "ehci_allocate_itw: length = 0x%x flags = 0x%x",
359 	    length, usb_flags);
360 
361 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
362 
363 	/* Allocate space for the transfer wrapper */
364 	itw = kmem_zalloc(sizeof (ehci_isoc_xwrapper_t), KM_NOSLEEP);
365 
366 	if (itw == NULL) {
367 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
368 		    "ehci_allocate_itw: kmem_zalloc failed");
369 
370 		return (NULL);
371 	}
372 
373 	ehcip->ehci_dma_attr.dma_attr_align = EHCI_DMA_ATTR_ALIGNMENT;
374 
375 	/* Allocate the DMA handle */
376 	result = ddi_dma_alloc_handle(ehcip->ehci_dip,
377 	    &ehcip->ehci_dma_attr,
378 	    DDI_DMA_DONTWAIT,
379 	    0,
380 	    &itw->itw_dmahandle);
381 
382 	if (result != DDI_SUCCESS) {
383 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
384 		    "ehci_create_transfer_wrapper: Alloc handle failed");
385 
386 		kmem_free(itw, sizeof (ehci_isoc_xwrapper_t));
387 
388 		return (NULL);
389 	}
390 
391 	/* no need for swapping the raw data in the buffers */
392 	dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
393 	dev_attr.devacc_attr_endian_flags  = DDI_NEVERSWAP_ACC;
394 	dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
395 
396 	/* Allocate the memory */
397 	result = ddi_dma_mem_alloc(itw->itw_dmahandle,
398 	    length,
399 	    &dev_attr,
400 	    DDI_DMA_CONSISTENT,
401 	    DDI_DMA_DONTWAIT,
402 	    NULL,
403 	    (caddr_t *)&itw->itw_buf,
404 	    &real_length,
405 	    &itw->itw_accesshandle);
406 
407 	if (result != DDI_SUCCESS) {
408 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
409 		    "ehci_create_transfer_wrapper: dma_mem_alloc fail");
410 
411 		ddi_dma_free_handle(&itw->itw_dmahandle);
412 		kmem_free(itw, sizeof (ehci_isoc_xwrapper_t));
413 
414 		return (NULL);
415 	}
416 
417 	ASSERT(real_length >= length);
418 
419 	/* Bind the handle */
420 	result = ddi_dma_addr_bind_handle(itw->itw_dmahandle,
421 	    NULL,
422 	    (caddr_t)itw->itw_buf,
423 	    real_length,
424 	    DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
425 	    DDI_DMA_DONTWAIT,
426 	    NULL,
427 	    &itw->itw_cookie,
428 	    &ccount);
429 
430 	if (result == DDI_DMA_MAPPED) {
431 		/* The cookie count should be 1 */
432 		if (ccount != 1) {
433 			USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
434 			    "ehci_create_transfer_wrapper: More than 1 cookie");
435 
436 			result = ddi_dma_unbind_handle(itw->itw_dmahandle);
437 			ASSERT(result == DDI_SUCCESS);
438 
439 			ddi_dma_mem_free(&itw->itw_accesshandle);
440 			ddi_dma_free_handle(&itw->itw_dmahandle);
441 			kmem_free(itw, sizeof (ehci_isoc_xwrapper_t));
442 
443 			return (NULL);
444 		}
445 	} else {
446 		ehci_decode_ddi_dma_addr_bind_handle_result(ehcip, result);
447 
448 		ddi_dma_mem_free(&itw->itw_accesshandle);
449 		ddi_dma_free_handle(&itw->itw_dmahandle);
450 		kmem_free(itw, sizeof (ehci_isoc_xwrapper_t));
451 
452 		return (NULL);
453 	}
454 
455 	/* Store a back pointer to the pipe private structure */
456 	itw->itw_pipe_private = pp;
457 	if (pp->pp_itw_head == NULL) {
458 		pp->pp_itw_head = itw;
459 		pp->pp_itw_tail = itw;
460 	} else {
461 		pp->pp_itw_tail->itw_next = itw;
462 		pp->pp_itw_tail = itw;
463 	}
464 
465 	/*
466 	 * Store transfer information
467 	 * itw_buf has been allocated and will be set later
468 	 */
469 	itw->itw_length = length;
470 	itw->itw_flags = usb_flags;
471 	itw->itw_port_status = usba_device->usb_port_status;
472 	itw->itw_direction = endpoint->bEndpointAddress & USB_EP_DIR_MASK;
473 
474 	/*
475 	 * Store the endpoint information that will be used by the
476 	 * transfer descriptors later.
477 	 */
478 	mutex_enter(&usba_device->usb_mutex);
479 	itw->itw_hub_addr = usba_device->usb_hs_hub_addr;
480 	itw->itw_hub_port = usba_device->usb_hs_hub_port;
481 	itw->itw_endpoint_num = endpoint->bEndpointAddress & USB_EP_NUM_MASK;
482 	itw->itw_device_addr = usba_device->usb_addr;
483 	mutex_exit(&usba_device->usb_mutex);
484 
485 	/* Get and Store 32bit ID */
486 	itw->itw_id = EHCI_GET_ID((void *)itw);
487 	ASSERT(itw->itw_id != NULL);
488 
489 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
490 	    "ehci_create_itw: itw = 0x%p", itw);
491 
492 	return (itw);
493 }
494 
495 
496 /*
497  * ehci_deallocate_itw:
498  *
499  * Deallocate of a Isochronous Transaction Wrapper (TW) and this involves the
500  * freeing of DMA resources.
501  */
502 void
503 ehci_deallocate_itw(
504 	ehci_state_t		*ehcip,
505 	ehci_pipe_private_t	*pp,
506 	ehci_isoc_xwrapper_t	*itw)
507 {
508 	ehci_isoc_xwrapper_t	*prev, *next;
509 
510 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
511 	    "ehci_deallocate_itw: itw = 0x%p", itw);
512 
513 	/*
514 	 * If the transfer wrapper has no Host Controller (HC)
515 	 * Transfer Descriptors (ITD) associated with it,  then
516 	 * remove the transfer wrapper.
517 	 */
518 	if (itw->itw_itd_head) {
519 		ASSERT(itw->itw_itd_tail != NULL);
520 
521 		return;
522 	}
523 
524 	ASSERT(itw->itw_itd_tail == NULL);
525 
526 	/* Make sure we return all the unused itd's to the pool as well */
527 	ehci_deallocate_itds_for_itw(ehcip, itw);
528 
529 	/*
530 	 * If pp->pp_tw_head and pp->pp_tw_tail are pointing to
531 	 * given TW then set the head and  tail  equal to NULL.
532 	 * Otherwise search for this TW in the linked TW's list
533 	 * and then remove this TW from the list.
534 	 */
535 	if (pp->pp_itw_head == itw) {
536 		if (pp->pp_itw_tail == itw) {
537 			pp->pp_itw_head = NULL;
538 			pp->pp_itw_tail = NULL;
539 		} else {
540 			pp->pp_itw_head = itw->itw_next;
541 		}
542 	} else {
543 		prev = pp->pp_itw_head;
544 		next = prev->itw_next;
545 
546 		while (next && (next != itw)) {
547 			prev = next;
548 			next = next->itw_next;
549 		}
550 
551 		if (next == itw) {
552 			prev->itw_next = next->itw_next;
553 
554 			if (pp->pp_itw_tail == itw) {
555 				pp->pp_itw_tail = prev;
556 			}
557 		}
558 	}
559 
560 	/* Free this iTWs dma resources */
561 	ehci_free_itw_dma(ehcip, pp, itw);
562 }
563 
564 
565 /*
566  * ehci_free_itw_dma:
567  *
568  * Free the Isochronous Transfer Wrapper dma resources.
569  */
570 /*ARGSUSED*/
571 static void
572 ehci_free_itw_dma(
573 	ehci_state_t		*ehcip,
574 	ehci_pipe_private_t	*pp,
575 	ehci_isoc_xwrapper_t	*itw)
576 {
577 	int	rval;
578 
579 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
580 	    "ehci_free_itw_dma: itw = 0x%p", itw);
581 
582 	ASSERT(itw != NULL);
583 	ASSERT(itw->itw_id != NULL);
584 
585 	/* Free 32bit ID */
586 	EHCI_FREE_ID((uint32_t)itw->itw_id);
587 
588 	rval = ddi_dma_unbind_handle(itw->itw_dmahandle);
589 	ASSERT(rval == DDI_SUCCESS);
590 
591 	ddi_dma_mem_free(&itw->itw_accesshandle);
592 	ddi_dma_free_handle(&itw->itw_dmahandle);
593 
594 	/* Free transfer wrapper */
595 	kmem_free(itw, sizeof (ehci_isoc_xwrapper_t));
596 }
597 
598 
599 /*
600  * transfer descriptor functions
601  */
602 /*
603  * ehci_allocate_itd:
604  *
605  * Allocate a Transfer Descriptor (iTD) from the iTD buffer pool.
606  */
607 static ehci_itd_t *
608 ehci_allocate_itd(ehci_state_t	*ehcip)
609 {
610 	int		i, state;
611 	ehci_itd_t	*itd;
612 
613 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
614 
615 	/*
616 	 * Search for a blank Transfer Descriptor (iTD)
617 	 * in the iTD buffer pool.
618 	 */
619 	for (i = 0; i < ehci_itd_pool_size; i ++) {
620 		state = Get_ITD(ehcip->ehci_itd_pool_addr[i].itd_state);
621 		if (state == EHCI_ITD_FREE) {
622 			break;
623 		}
624 	}
625 
626 	if (i >= ehci_itd_pool_size) {
627 		USB_DPRINTF_L2(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
628 		    "ehci_allocate_itd: ITD exhausted");
629 
630 		return (NULL);
631 	}
632 
633 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
634 	    "ehci_allocate_itd: Allocated %d", i);
635 
636 	/* Create a new dummy for the end of the ITD list */
637 	itd = &ehcip->ehci_itd_pool_addr[i];
638 
639 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
640 	    "ehci_allocate_itd: itd 0x%p", (void *)itd);
641 
642 	/* Mark the newly allocated ITD as a empty */
643 	Set_ITD(itd->itd_state, EHCI_ITD_DUMMY);
644 
645 	return (itd);
646 }
647 
648 
649 /*
650  * ehci_deallocate_itd:
651  *
652  * Deallocate a Host Controller's (HC) Transfer Descriptor (ITD).
653  *
654  */
655 void
656 ehci_deallocate_itd(
657 	ehci_state_t		*ehcip,
658 	ehci_isoc_xwrapper_t	*itw,
659 	ehci_itd_t		*old_itd)
660 {
661 	ehci_itd_t	*itd, *next_itd;
662 
663 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
664 	    "ehci_deallocate_itd: old_itd = 0x%p", (void *)old_itd);
665 
666 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
667 	ASSERT(Get_ITD(old_itd->itd_trans_wrapper) == itw->itw_id);
668 
669 	/* If it has been marked RECLAIM it has already been removed */
670 	if (Get_ITD(old_itd->itd_state) != EHCI_ITD_RECLAIM) {
671 		ehci_remove_isoc_from_pfl(ehcip, old_itd);
672 	}
673 
674 	/* Make sure the ITD is not in the PFL */
675 	ASSERT(Get_ITD_FRAME(old_itd->itd_frame_number) == 0);
676 
677 	/* Remove the itd from the itw */
678 	itd = itw->itw_itd_head;
679 	if (old_itd != itd) {
680 		next_itd = ehci_itd_iommu_to_cpu(ehcip,
681 		    Get_ITD(itd->itd_itw_next_itd));
682 
683 		while (next_itd != old_itd) {
684 			itd = next_itd;
685 			next_itd = ehci_itd_iommu_to_cpu(ehcip,
686 			    Get_ITD(itd->itd_itw_next_itd));
687 		}
688 
689 		Set_ITD(itd->itd_itw_next_itd, old_itd->itd_itw_next_itd);
690 
691 		if (itd->itd_itw_next_itd == NULL) {
692 			itw->itw_itd_tail = itd;
693 		}
694 	} else {
695 		itw->itw_itd_head = ehci_itd_iommu_to_cpu(
696 			ehcip, Get_ITD(old_itd->itd_itw_next_itd));
697 
698 		if (itw->itw_itd_head == NULL) {
699 			itw->itw_itd_tail = NULL;
700 		}
701 	}
702 
703 	bzero((char *)old_itd, sizeof (ehci_itd_t));
704 	Set_ITD(old_itd->itd_state, EHCI_ITD_FREE);
705 
706 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
707 	    "Dealloc_itd: itd 0x%p", (void *)old_itd);
708 }
709 
710 
711 /*
712  * ehci_calc_num_itds:
713  *
714  * Calculates how many ITDs are needed for this request.
715  * The calculation is based on weather it is an HIGH speed
716  * transaction of a FULL/LOW transaction.
717  *
718  * For FULL/LOW transaction more itds are necessary if it
719  * spans frames.
720  */
721 uint_t
722 ehci_calc_num_itds(
723 	ehci_isoc_xwrapper_t	*itw,
724 	size_t 			pkt_count)
725 {
726 	uint_t			multiplier, itd_count;
727 
728 	/* Allocate the appropriate isoc resources */
729 	if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) {
730 		/* Multiplier needs to be passed in somehow */
731 		multiplier = 1 * 8;
732 		itd_count = pkt_count / multiplier;
733 		if (pkt_count % multiplier) {
734 			itd_count++;
735 		}
736 	} else {
737 		itd_count = pkt_count;
738 	}
739 
740 	return (pkt_count);
741 }
742 
743 /*
744  * ehci_allocate_itds_for_itw:
745  *
746  * Allocate n Transfer Descriptors (TD) from the TD buffer pool and places it
747  * into the TW.
748  *
749  * Returns USB_NO_RESOURCES if it was not able to allocate all the requested TD
750  * otherwise USB_SUCCESS.
751  */
752 int
753 ehci_allocate_itds_for_itw(
754 	ehci_state_t		*ehcip,
755 	ehci_isoc_xwrapper_t	*itw,
756 	uint_t			itd_count)
757 {
758 	ehci_itd_t		*itd;
759 	uint32_t		itd_addr;
760 	int			i;
761 	int			error = USB_SUCCESS;
762 
763 	for (i = 0; i < itd_count; i += 1) {
764 		itd = ehci_allocate_itd(ehcip);
765 		if (itd == NULL) {
766 			error = USB_NO_RESOURCES;
767 			USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
768 			    "ehci_allocate_itds_for_itw: "
769 			    "Unable to allocate %d ITDs",
770 			    itd_count);
771 			break;
772 		}
773 		if (i > 0) {
774 			itd_addr = ehci_itd_cpu_to_iommu(ehcip,
775 			    itw->itw_itd_free_list);
776 			Set_ITD(itd->itd_link_ptr, itd_addr);
777 		}
778 		itw->itw_itd_free_list = itd;
779 	}
780 
781 	return (error);
782 }
783 
784 
785 /*
786  * ehci_deallocate_itds_for_itw:
787  *
788  * Free all allocated resources for Transaction Wrapper (TW).
789  * Does not free the iTW itself.
790  */
791 static void
792 ehci_deallocate_itds_for_itw(
793 	ehci_state_t		*ehcip,
794 	ehci_isoc_xwrapper_t	*itw)
795 {
796 	ehci_itd_t		*itd = NULL;
797 	ehci_itd_t		*temp_itd = NULL;
798 
799 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
800 	    "ehci_free_itw_itd_resources: itw = 0x%p", itw);
801 
802 	itd = itw->itw_itd_free_list;
803 	while (itd != NULL) {
804 		/* Save the pointer to the next itd before destroying it */
805 		temp_itd = ehci_itd_iommu_to_cpu(ehcip,
806 		    Get_ITD(itd->itd_link_ptr));
807 		ehci_deallocate_itd(ehcip, itw, itd);
808 		itd = temp_itd;
809 	}
810 	itw->itw_itd_free_list = NULL;
811 }
812 
813 
814 /*
815  * ehci_insert_itd_on_itw:
816  *
817  * The transfer wrapper keeps a list of all Transfer Descriptors (iTD) that
818  * are allocated for this transfer. Insert a iTD onto this list.
819  */
820 void ehci_insert_itd_on_itw(
821 	ehci_state_t		*ehcip,
822 	ehci_isoc_xwrapper_t	*itw,
823 	ehci_itd_t		*itd)
824 {
825 	/*
826 	 * Set the next pointer to NULL because
827 	 * this is the last ITD on list.
828 	 */
829 	Set_ITD(itd->itd_itw_next_itd, NULL);
830 
831 	if (itw->itw_itd_head == NULL) {
832 		ASSERT(itw->itw_itd_tail == NULL);
833 		itw->itw_itd_head = itd;
834 		itw->itw_itd_tail = itd;
835 	} else {
836 		ehci_itd_t *dummy = (ehci_itd_t *)itw->itw_itd_tail;
837 
838 		ASSERT(dummy != NULL);
839 		ASSERT(Get_ITD(itd->itd_state) == EHCI_ITD_ACTIVE);
840 
841 		/* Add the itd to the end of the list */
842 		Set_ITD(dummy->itd_itw_next_itd,
843 		    ehci_itd_cpu_to_iommu(ehcip, itd));
844 
845 		itw->itw_itd_tail = itd;
846 	}
847 
848 	Set_ITD(itd->itd_trans_wrapper, (uint32_t)itw->itw_id);
849 }
850 
851 
852 /*
853  * ehci_insert_itd_into_active_list:
854  *
855  * Add current ITD into the active ITD list in reverse order.
856  * When he done list is created, remove it in the reverse order.
857  */
858 void
859 ehci_insert_itd_into_active_list(
860 	ehci_state_t		*ehcip,
861 	ehci_itd_t		*itd)
862 {
863 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
864 	ASSERT(itd != NULL);
865 
866 	Set_ITD(itd->itd_next_active_itd,
867 	    ehci_itd_cpu_to_iommu(ehcip, ehcip->ehci_active_itd_list));
868 	ehcip->ehci_active_itd_list = itd;
869 }
870 
871 
872 /*
873  * ehci_remove_itd_from_active_list:
874  *
875  * Remove current ITD from the active ITD list.
876  */
877 void
878 ehci_remove_itd_from_active_list(
879 	ehci_state_t		*ehcip,
880 	ehci_itd_t		*itd)
881 {
882 	ehci_itd_t		*curr_itd, *next_itd;
883 
884 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
885 	ASSERT(itd != NULL);
886 
887 	curr_itd = ehcip->ehci_active_itd_list;
888 
889 	if (curr_itd == itd) {
890 		ehcip->ehci_active_itd_list =
891 		    ehci_itd_iommu_to_cpu(ehcip, itd->itd_next_active_itd);
892 		itd->itd_next_active_itd = NULL;
893 
894 		return;
895 	}
896 
897 	next_itd = ehci_itd_iommu_to_cpu(ehcip, curr_itd->itd_next_active_itd);
898 	while (next_itd != itd) {
899 		curr_itd = next_itd;
900 		if (curr_itd) {
901 			next_itd = ehci_itd_iommu_to_cpu(ehcip,
902 			    curr_itd->itd_next_active_itd);
903 		} else {
904 			break;
905 		}
906 	}
907 
908 	if ((curr_itd) && (next_itd == itd)) {
909 		Set_ITD(curr_itd->itd_next_active_itd,
910 		    Get_ITD(itd->itd_next_active_itd));
911 		Set_ITD(itd->itd_next_active_itd, NULL);
912 	} else {
913 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
914 		    "ehci_remove_itd_from_active_list: "
915 			"Unable to find ITD in active_itd_list");
916 	}
917 }
918 
919 
920 /*
921  * ehci_create_done_itd_list:
922  *
923  * Traverse the active list and create a done list and remove them
924  * from the active list.
925  */
926 ehci_itd_t *
927 ehci_create_done_itd_list(
928 	ehci_state_t		*ehcip)
929 {
930 	usb_frame_number_t	current_frame_number;
931 	usb_frame_number_t	itd_frame_number, itd_reclaim_number;
932 	ehci_itd_t		*curr_itd = NULL, *next_itd = NULL;
933 	ehci_itd_t		*done_itd_list = NULL;
934 	uint_t			state;
935 
936 	USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
937 	    "ehci_create_done_itd_list:");
938 
939 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
940 
941 	/*
942 	 * Get the current frame number.
943 	 * Only process itd that were inserted before the current
944 	 * frame number.
945 	 */
946 	current_frame_number = ehci_get_current_frame_number(ehcip);
947 
948 	curr_itd = ehcip->ehci_active_itd_list;
949 
950 	while (curr_itd) {
951 		/* Get next itd from the active itd list */
952 		next_itd = ehci_itd_iommu_to_cpu(ehcip,
953 		    Get_ITD(curr_itd->itd_next_active_itd));
954 
955 		/*
956 		 * If haven't past the frame number that the ITD was
957 		 * suppose to be executed, don't touch it.  Just in
958 		 * case it is being processed by the HCD and cause
959 		 * a race condition.
960 		 */
961 		itd_frame_number = Get_ITD_FRAME(curr_itd->itd_frame_number);
962 		itd_reclaim_number =
963 		    Get_ITD_FRAME(curr_itd->itd_reclaim_number);
964 
965 		/* Get the ITD state */
966 		state = Get_ITD(curr_itd->itd_state);
967 
968 		if (((state == EHCI_ITD_ACTIVE) &&
969 			(itd_frame_number < current_frame_number)) ||
970 		    ((state == EHCI_ITD_RECLAIM) &&
971 			(itd_reclaim_number < current_frame_number))) {
972 
973 			/* Remove this ITD from active ITD list */
974 			ehci_remove_itd_from_active_list(ehcip, curr_itd);
975 
976 			/*
977 			 * Create the done list in reverse order, since the
978 			 * active list was also created in reverse order.
979 			 */
980 			Set_ITD(curr_itd->itd_next_active_itd,
981 			    ehci_itd_cpu_to_iommu(ehcip, done_itd_list));
982 			done_itd_list = curr_itd;
983 		}
984 
985 		curr_itd = next_itd;
986 	}
987 
988 	return (done_itd_list);
989 }
990 
991 
992 /*
993  * ehci_insert_isoc_to_pfl:
994  *
995  * Insert a ITD request into the Host Controller's isochronous list.
996  * All the ITDs in the ITW will be added the PFL at once.  Either all
997  * of them will make it or none of them will.
998  */
999 int
1000 ehci_insert_isoc_to_pfl(
1001 	ehci_state_t		*ehcip,
1002 	ehci_pipe_private_t	*pp,
1003 	ehci_isoc_xwrapper_t	*itw)
1004 {
1005 	usb_isoc_req_t		*isoc_reqp = itw->itw_curr_xfer_reqp;
1006 	usb_frame_number_t	current_frame_number, start_frame_number;
1007 	uint_t			ddic, pfl_number;
1008 	ehci_periodic_frame_list_t *periodic_frame_list =
1009 	    ehcip->ehci_periodic_frame_list_tablep;
1010 	uint32_t		addr, port_status;
1011 	ehci_itd_t		*itd;
1012 
1013 	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1014 	    "ehci_insert_isoc_to_pfl: "
1015 	    "isoc flags 0x%x", isoc_reqp->isoc_attributes);
1016 
1017 	/*
1018 	 * Enter critical, while programming the usb frame number
1019 	 * and inserting current isochronous TD into the ED's list.
1020 	 */
1021 	ddic = ddi_enter_critical();
1022 
1023 	/* Get the current frame number */
1024 	current_frame_number = ehci_get_current_frame_number(ehcip);
1025 
1026 	/*
1027 	 * Check the given isochronous flags and get the frame number
1028 	 * to insert the itd into.
1029 	 */
1030 	switch (isoc_reqp->isoc_attributes &
1031 	    (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) {
1032 	case USB_ATTRS_ISOC_START_FRAME:
1033 
1034 		/* Starting frame number is specified */
1035 		if (pp->pp_flag & EHCI_ISOC_XFER_CONTINUE) {
1036 			/* Get the starting usb frame number */
1037 			start_frame_number = pp->pp_next_frame_number;
1038 		} else {
1039 			/* Check for the Starting usb frame number */
1040 			if ((isoc_reqp->isoc_frame_no == 0) ||
1041 			    ((isoc_reqp->isoc_frame_no +
1042 				isoc_reqp->isoc_pkts_count) <
1043 				current_frame_number)) {
1044 
1045 				/* Exit the critical */
1046 				ddi_exit_critical(ddic);
1047 
1048 				USB_DPRINTF_L2(PRINT_MASK_LISTS,
1049 				    ehcip->ehci_log_hdl,
1050 				    "ehci_insert_isoc_to_pfl:"
1051 				    "Invalid starting frame number");
1052 
1053 				return (USB_INVALID_START_FRAME);
1054 			}
1055 
1056 			/* Get the starting usb frame number */
1057 			start_frame_number = isoc_reqp->isoc_frame_no;
1058 
1059 			pp->pp_next_frame_number = 0;
1060 		}
1061 		break;
1062 	case USB_ATTRS_ISOC_XFER_ASAP:
1063 		/* ehci has to specify starting frame number */
1064 		if ((pp->pp_next_frame_number) &&
1065 		    (pp->pp_next_frame_number > current_frame_number)) {
1066 			/*
1067 			 * Get the next usb frame number.
1068 			 */
1069 			start_frame_number = pp->pp_next_frame_number;
1070 		} else {
1071 			/*
1072 			 * Add appropriate offset to the current usb
1073 			 * frame number and use it as a starting frame
1074 			 * number.
1075 			 */
1076 			start_frame_number =
1077 			    current_frame_number + EHCI_FRAME_OFFSET;
1078 		}
1079 
1080 		if (!(pp->pp_flag & EHCI_ISOC_XFER_CONTINUE)) {
1081 			isoc_reqp->isoc_frame_no = start_frame_number;
1082 		}
1083 		break;
1084 	default:
1085 		/* Exit the critical */
1086 		ddi_exit_critical(ddic);
1087 
1088 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1089 		    "ehci_insert_isoc_to_pfl: Either starting "
1090 		    "frame number or ASAP flags are not set, attrs = 0x%x",
1091 		    isoc_reqp->isoc_attributes);
1092 
1093 		return (USB_NO_FRAME_NUMBER);
1094 	}
1095 
1096 	if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) {
1097 		port_status = 0;
1098 	} else {
1099 		port_status = EHCI_ITD_LINK_REF_SITD;
1100 	}
1101 
1102 	itd = itw->itw_itd_head;
1103 	while (itd) {
1104 		/* Find the appropriate frame list to put the itd into */
1105 		pfl_number = start_frame_number % EHCI_NUM_PERIODIC_FRAME_LISTS;
1106 
1107 		addr = Get_PFLT(periodic_frame_list->
1108 		    ehci_periodic_frame_list_table[pfl_number]);
1109 		Set_ITD(itd->itd_link_ptr, addr);
1110 
1111 		/* Set the link_ref correctly as ITD or SITD. */
1112 		addr = ehci_itd_cpu_to_iommu(ehcip, itd) & EHCI_ITD_LINK_PTR;
1113 		addr |= port_status;
1114 
1115 		Set_PFLT(periodic_frame_list->
1116 		    ehci_periodic_frame_list_table[pfl_number], addr);
1117 
1118 		/* Save which frame the ITD was inserted into */
1119 		Set_ITD_FRAME(itd->itd_frame_number, start_frame_number);
1120 
1121 		ehci_insert_itd_into_active_list(ehcip, itd);
1122 
1123 		/* Get the next ITD in the ITW */
1124 		itd = ehci_itd_iommu_to_cpu(ehcip,
1125 		    Get_ITD(itd->itd_itw_next_itd));
1126 
1127 		start_frame_number++;
1128 	}
1129 
1130 	/* Exit the critical */
1131 	ddi_exit_critical(ddic);
1132 
1133 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1134 	    "ehci_isoc_to_pfl: "
1135 	    "current frame number 0x%llx start frame number 0x%llx num itds %d",
1136 	    current_frame_number, start_frame_number, itw->itw_num_itds);
1137 
1138 	/*
1139 	 * Increment this saved frame number by current number
1140 	 * of data packets needs to be transfer.
1141 	 */
1142 	pp->pp_next_frame_number = start_frame_number;
1143 
1144 	/*
1145 	 * Set EHCI_ISOC_XFER_CONTINUE flag in order to send other
1146 	 * isochronous packets,  part of the current isoch request
1147 	 * in the subsequent frames.
1148 	 */
1149 	pp->pp_flag |= EHCI_ISOC_XFER_CONTINUE;
1150 
1151 	return (USB_SUCCESS);
1152 }
1153 
1154 
1155 /*
1156  * ehci_remove_isoc_to_pfl:
1157  *
1158  * Remove an ITD request from the Host Controller's isochronous list.
1159  * If we can't find it, something has gone wrong.
1160  */
1161 void
1162 ehci_remove_isoc_from_pfl(
1163 	ehci_state_t		*ehcip,
1164 	ehci_itd_t		*curr_itd)
1165 {
1166 	ehci_periodic_frame_list_t *periodic_frame_list;
1167 	uint_t		pfl_number;
1168 	uint32_t	next_addr, curr_itd_addr;
1169 	uint32_t	link_ref;
1170 	ehci_itd_t	*prev_itd = NULL;
1171 
1172 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
1173 	    "ehci_remove_isoc_from_pfl:");
1174 
1175 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1176 
1177 	/* Get the address of the current itd */
1178 	curr_itd_addr = ehci_itd_cpu_to_iommu(ehcip, curr_itd);
1179 
1180 	/*
1181 	 * Remove this ITD from the PFL
1182 	 * But first we need to find it in the PFL
1183 	 */
1184 	periodic_frame_list = ehcip->ehci_periodic_frame_list_tablep;
1185 	pfl_number = Get_ITD_FRAME(curr_itd->itd_frame_number) %
1186 	    EHCI_NUM_PERIODIC_FRAME_LISTS;
1187 
1188 	USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
1189 	    "ehci_remove_isoc_from_pfl: itd = 0x%p pfl number 0x%x",
1190 	    curr_itd, pfl_number);
1191 
1192 	next_addr = Get_PFLT(periodic_frame_list->
1193 	    ehci_periodic_frame_list_table[pfl_number]);
1194 	while ((next_addr & EHCI_ITD_LINK_PTR) !=
1195 	    (curr_itd_addr & EHCI_ITD_LINK_PTR)) {
1196 
1197 		link_ref = next_addr & EHCI_ITD_LINK_REF;
1198 
1199 		if ((link_ref == EHCI_ITD_LINK_REF_ITD) ||
1200 		    (link_ref == EHCI_ITD_LINK_REF_SITD)) {
1201 
1202 			prev_itd = ehci_itd_iommu_to_cpu(ehcip,
1203 			    (next_addr & EHCI_ITD_LINK_PTR));
1204 			next_addr = Get_ITD(prev_itd->itd_link_ptr);
1205 		} else {
1206 
1207 			break;
1208 		}
1209 	}
1210 
1211 	/*
1212 	 * If the next itd is the current itd, that means we found it.
1213 	 * Set the previous's ITD link ptr to the Curr_ITD's link ptr.
1214 	 * But do not touch the Curr_ITD's link ptr.
1215 	 */
1216 	if ((next_addr & EHCI_ITD_LINK_PTR) ==
1217 	    (curr_itd_addr & EHCI_ITD_LINK_PTR)) {
1218 
1219 		next_addr = Get_ITD(curr_itd->itd_link_ptr);
1220 
1221 		if (prev_itd == NULL) {
1222 			/* This means PFL points to this ITD */
1223 			Set_PFLT(periodic_frame_list->
1224 			    ehci_periodic_frame_list_table[pfl_number],
1225 			    next_addr);
1226 		} else {
1227 			/* Set the previous ITD's itd_link_ptr */
1228 			Set_ITD(prev_itd->itd_link_ptr, next_addr);
1229 		}
1230 
1231 		Set_ITD_FRAME(curr_itd->itd_frame_number, 0);
1232 	} else {
1233 		ASSERT((next_addr & EHCI_ITD_LINK_PTR) ==
1234 		    (curr_itd_addr & EHCI_ITD_LINK_PTR));
1235 		USB_DPRINTF_L3(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl,
1236 		    "ehci_remove_isoc_from_pfl: Unable to find ITD in PFL");
1237 	}
1238 }
1239 
1240 
1241 /*
1242  * Isochronous in resource functions
1243  */
1244 /*
1245  * ehci_allocate_periodic_in_resource
1246  *
1247  * Allocate interrupt request structure for the interrupt IN transfer.
1248  */
1249 int
1250 ehci_allocate_isoc_in_resource(
1251 	ehci_state_t		*ehcip,
1252 	ehci_pipe_private_t	*pp,
1253 	ehci_isoc_xwrapper_t	*itw,
1254 	usb_flags_t		flags)
1255 {
1256 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
1257 	usb_isoc_req_t		*orig_isoc_reqp, *clone_isoc_reqp;
1258 
1259 	USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1260 	    "ehci_allocate_isoc_in_resource:"
1261 	    "pp = 0x%p itw = 0x%p flags = 0x%x", pp, itw, flags);
1262 
1263 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1264 	ASSERT(itw->itw_curr_xfer_reqp == NULL);
1265 
1266 	/* Get the client periodic in request pointer */
1267 	orig_isoc_reqp = (usb_isoc_req_t *)(pp->pp_client_periodic_in_reqp);
1268 
1269 	ASSERT(orig_isoc_reqp != NULL);
1270 
1271 	clone_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip,
1272 	    orig_isoc_reqp, flags);
1273 
1274 	if (clone_isoc_reqp == NULL) {
1275 		USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1276 		    "ehci_allocate_isoc_in_resource: Isochronous"
1277 		    "request structure allocation failed");
1278 
1279 		return (USB_NO_RESOURCES);
1280 	}
1281 
1282 	/*
1283 	 * Save the client's isochronous request pointer and
1284 	 * length of isochronous transfer in transfer wrapper.
1285 	 * The dup'ed request is saved in pp_client_periodic_in_reqp
1286 	 */
1287 	itw->itw_curr_xfer_reqp = orig_isoc_reqp;
1288 	itw->itw_length = clone_isoc_reqp->isoc_pkts_length;
1289 	pp->pp_client_periodic_in_reqp = (usb_opaque_t)clone_isoc_reqp;
1290 
1291 	mutex_enter(&ph->p_mutex);
1292 	ph->p_req_count++;
1293 	mutex_exit(&ph->p_mutex);
1294 
1295 	pp->pp_state = EHCI_PIPE_STATE_ACTIVE;
1296 
1297 	return (USB_SUCCESS);
1298 }
1299 
1300 
1301 /*
1302  * ehci_deallocate_isoc_in_resource
1303  *
1304  * Deallocate interrupt request structure for the interrupt IN transfer.
1305  */
1306 void
1307 ehci_deallocate_isoc_in_resource(
1308 	ehci_state_t		*ehcip,
1309 	ehci_pipe_private_t	*pp,
1310 	ehci_isoc_xwrapper_t	*itw)
1311 {
1312 	usba_pipe_handle_data_t	*ph = pp->pp_pipe_handle;
1313 	uchar_t			ep_attr = ph->p_ep.bmAttributes;
1314 	usb_isoc_req_t		*isoc_reqp;
1315 
1316 	USB_DPRINTF_L4(PRINT_MASK_LISTS,
1317 	    ehcip->ehci_log_hdl,
1318 	    "ehci_deallocate_isoc_in_resource: "
1319 	    "pp = 0x%p itw = 0x%p", pp, itw);
1320 
1321 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1322 	ASSERT((ep_attr & USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH);
1323 
1324 	isoc_reqp = itw->itw_curr_xfer_reqp;
1325 
1326 	/* Check the current periodic in request pointer */
1327 	if (isoc_reqp) {
1328 		itw->itw_curr_xfer_reqp = NULL;
1329 		itw->itw_curr_isoc_pktp = NULL;
1330 
1331 		mutex_enter(&ph->p_mutex);
1332 		ph->p_req_count--;
1333 		mutex_exit(&ph->p_mutex);
1334 
1335 		usb_free_isoc_req(isoc_reqp);
1336 
1337 		/* Set periodic in pipe state to idle */
1338 		pp->pp_state = EHCI_PIPE_STATE_IDLE;
1339 	}
1340 }
1341 
1342 
1343 /*
1344  * ehci_itd_cpu_to_iommu:
1345  *
1346  * This function converts for the given Transfer Descriptor (ITD) CPU address
1347  * to IO address.
1348  */
1349 uint32_t
1350 ehci_itd_cpu_to_iommu(
1351 	ehci_state_t	*ehcip,
1352 	ehci_itd_t	*addr)
1353 {
1354 	uint32_t	td;
1355 
1356 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1357 
1358 	if (addr == NULL) {
1359 
1360 		return (NULL);
1361 	}
1362 
1363 	td = (uint32_t)ehcip->ehci_itd_pool_cookie.dmac_address +
1364 	    (uint32_t)((uintptr_t)addr -
1365 		(uintptr_t)(ehcip->ehci_itd_pool_addr));
1366 
1367 	ASSERT(((uint32_t) (sizeof (ehci_itd_t) *
1368 		(addr - ehcip->ehci_itd_pool_addr))) ==
1369 	    ((uint32_t)((uintptr_t)addr - (uintptr_t)
1370 		(ehcip->ehci_itd_pool_addr))));
1371 
1372 	ASSERT(td >= ehcip->ehci_itd_pool_cookie.dmac_address);
1373 	ASSERT(td <= ehcip->ehci_itd_pool_cookie.dmac_address +
1374 	    sizeof (ehci_itd_t) * ehci_itd_pool_size);
1375 
1376 	return (td);
1377 }
1378 
1379 
1380 /*
1381  * ehci_itd_iommu_to_cpu:
1382  *
1383  * This function converts for the given Transfer Descriptor (ITD) IO address
1384  * to CPU address.
1385  */
1386 ehci_itd_t *
1387 ehci_itd_iommu_to_cpu(
1388 	ehci_state_t	*ehcip,
1389 	uintptr_t	addr)
1390 {
1391 	ehci_itd_t	*itd;
1392 
1393 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1394 
1395 	if (addr == NULL) {
1396 
1397 		return (NULL);
1398 	}
1399 
1400 	itd = (ehci_itd_t *)((uintptr_t)
1401 	    (addr - ehcip->ehci_itd_pool_cookie.dmac_address) +
1402 	    (uintptr_t)ehcip->ehci_itd_pool_addr);
1403 
1404 	ASSERT(itd >= ehcip->ehci_itd_pool_addr);
1405 	ASSERT((uintptr_t)itd <= (uintptr_t)ehcip->ehci_itd_pool_addr +
1406 	    (uintptr_t)(sizeof (ehci_itd_t) * ehci_itd_pool_size));
1407 
1408 	return (itd);
1409 }
1410 
1411 
1412 /*
1413  * Error parsing functions
1414  */
1415 void ehci_parse_isoc_error(
1416 	ehci_state_t		*ehcip,
1417 	ehci_isoc_xwrapper_t	*itw,
1418 	ehci_itd_t		*itd) {
1419 
1420 	usb_isoc_req_t		*isoc_reqp;
1421 	usb_isoc_pkt_descr_t	*isoc_pkt_descr;
1422 	usb_cr_t 		error;
1423 
1424 	ASSERT(mutex_owned(&ehcip->ehci_int_mutex));
1425 
1426 	isoc_reqp = itw->itw_curr_xfer_reqp;
1427 	isoc_pkt_descr = itw->itw_curr_isoc_pktp;
1428 
1429 	if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) {
1430 		error = ehci_parse_itd_error(ehcip, itw, itd);
1431 	} else {
1432 		error = ehci_parse_sitd_error(ehcip, itw, itd);
1433 	}
1434 
1435 	/* Write the status of isoc data packet */
1436 	isoc_pkt_descr->isoc_pkt_status = error;
1437 
1438 	if (error != USB_CR_OK) {
1439 		isoc_reqp->isoc_error_count++;
1440 
1441 		USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1442 		    "ehci_parse_isoc_error: Error %d Device Address %d "
1443 		    "Endpoint number %d", error, itw->itw_device_addr,
1444 		    itw->itw_endpoint_num);
1445 	}
1446 
1447 	itw->itw_curr_isoc_pktp++;
1448 }
1449 
1450 
1451 /* ARGSUSED */
1452 static usb_cr_t ehci_parse_itd_error(
1453 	ehci_state_t		*ehcip,
1454 	ehci_isoc_xwrapper_t	*itw,
1455 	ehci_itd_t		*itd) {
1456 
1457 	return (USB_NOT_SUPPORTED);
1458 }
1459 
1460 static usb_cr_t ehci_parse_sitd_error(
1461 	ehci_state_t		*ehcip,
1462 	ehci_isoc_xwrapper_t	*itw,
1463 	ehci_itd_t		*itd) {
1464 
1465 	uint32_t		status;
1466 	usb_cr_t 		error;
1467 	usb_isoc_pkt_descr_t	*isoc_pkt_descr;
1468 	uint32_t		residue;
1469 
1470 	isoc_pkt_descr = itw->itw_curr_isoc_pktp;
1471 
1472 	status = Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) &
1473 	    EHCI_SITD_XFER_STATUS_MASK;
1474 
1475 	switch (status) {
1476 	case EHCI_SITD_XFER_ACTIVE:
1477 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1478 		    "ehci_check_for_sitd_error: NOT ACCESSED");
1479 		error = USB_CR_NOT_ACCESSED;
1480 
1481 		break;
1482 	case EHCI_SITD_XFER_ERROR:
1483 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1484 		    "ehci_check_for_sitd_error: TT ERROR");
1485 
1486 		error = USB_CR_UNSPECIFIED_ERR;
1487 
1488 		break;
1489 	case EHCI_SITD_XFER_DATA_BUFFER_ERR:
1490 		if (itw->itw_direction == USB_EP_DIR_OUT) {
1491 			USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1492 			    "ehci_check_for_sitd_error: BUFFER Underrun");
1493 			error = USB_CR_BUFFER_UNDERRUN;
1494 		} else {
1495 			USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1496 			    "ehci_check_for_sitd_error: BUFFER Overrun");
1497 			error = USB_CR_BUFFER_OVERRUN;
1498 		}
1499 
1500 		break;
1501 	case EHCI_SITD_XFER_BABBLE:
1502 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1503 		    "ehci_check_for_sitd_error: BABBLE");
1504 		error = USB_CR_DATA_OVERRUN;
1505 
1506 		break;
1507 	case EHCI_SITD_XFER_XACT_ERROR:
1508 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1509 		    "ehci_check_for_sitd_error: XACT ERROR");
1510 
1511 		error = USB_CR_DEV_NOT_RESP;
1512 		break;
1513 	case EHCI_SITD_XFER_MISSED_UFRAME:
1514 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1515 		    "ehci_check_for_sitd_error: MISSED UFRAME");
1516 
1517 		error = USB_CR_NOT_ACCESSED;
1518 		break;
1519 	default:
1520 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
1521 		    "ehci_check_for_sitd_error: NO ERROR");
1522 		error = USB_CR_OK;
1523 
1524 		break;
1525 	}
1526 
1527 	/* This is HCD specific and may not have this information */
1528 	residue =
1529 	    (Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) &
1530 		EHCI_SITD_XFER_TOTAL_MASK) >>
1531 	    EHCI_SITD_XFER_TOTAL_SHIFT;
1532 
1533 	/*
1534 	 * Subtract the residue from the isoc_pkt_descr that
1535 	 * was set when this ITD was inserted.
1536 	 */
1537 	isoc_pkt_descr->isoc_pkt_actual_length -= residue;
1538 
1539 	return (error);
1540 }
1541 
1542 
1543 /*
1544  * debug print functions
1545  */
1546 void
1547 ehci_print_itd(
1548 	ehci_state_t	*ehcip,
1549 	ehci_itd_t	*itd)
1550 {
1551 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1552 	    "ehci_print_itd: itd = 0x%p", (void *)itd);
1553 
1554 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1555 	    "\titd_link_ptr: 0x%x ", Get_ITD(itd->itd_link_ptr));
1556 
1557 	if ((Get_ITD(itd->itd_link_ptr) & EHCI_ITD_LINK_REF) ==
1558 	    EHCI_ITD_LINK_REF_ITD) {
1559 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1560 		    "\titd_ctrl0: 0x%x ",
1561 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL0]));
1562 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1563 		    "\titd_ctrl1: 0x%x ",
1564 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL1]));
1565 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1566 		    "\titd_ctrl2: 0x%x ",
1567 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL2]));
1568 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1569 		    "\titd_ctrl3: 0x%x ",
1570 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL3]));
1571 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1572 		    "\titd_ctrl4: 0x%x ",
1573 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL4]));
1574 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1575 		    "\titd_ctrl5: 0x%x ",
1576 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL5]));
1577 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1578 		    "\titd_ctrl6: 0x%x ",
1579 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL6]));
1580 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1581 		    "\titd_ctrl7: 0x%x ",
1582 		    Get_ITD(itd->itd_body[EHCI_ITD_CTRL7]));
1583 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1584 		    "\titd_buffer0: 0x%x ",
1585 		    Get_ITD(itd->itd_body[EHCI_ITD_BUFFER0]));
1586 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1587 		    "\titd_buffer1: 0x%x ",
1588 		    Get_ITD(itd->itd_body[EHCI_ITD_BUFFER1]));
1589 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1590 		    "\titd_buffer2: 0x%x ",
1591 		    Get_ITD(itd->itd_body[EHCI_ITD_BUFFER2]));
1592 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1593 		    "\titd_buffer3: 0x%x ",
1594 		    Get_ITD(itd->itd_body[EHCI_ITD_BUFFER3]));
1595 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1596 		    "\titd_buffer4: 0x%x ",
1597 		    Get_ITD(itd->itd_body[EHCI_ITD_BUFFER4]));
1598 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1599 		    "\titd_buffer5: 0x%x ",
1600 		    Get_ITD(itd->itd_body[EHCI_ITD_BUFFER5]));
1601 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1602 		    "\titd_buffer6: 0x%x ",
1603 		    Get_ITD(itd->itd_body[EHCI_ITD_BUFFER6]));
1604 	} else {
1605 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1606 		    "\tsitd_ctrl: 0x%x ",
1607 		    Get_ITD(itd->itd_body[EHCI_SITD_CTRL]));
1608 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1609 		    "\tsitd_uframe_sched: 0x%x ",
1610 		    Get_ITD(itd->itd_body[EHCI_SITD_UFRAME_SCHED]));
1611 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1612 		    "\tsitd_xfer_state: 0x%x ",
1613 		    Get_ITD(itd->itd_body[EHCI_SITD_XFER_STATE]));
1614 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1615 		    "\tsitd_buffer0: 0x%x ",
1616 		    Get_ITD(itd->itd_body[EHCI_SITD_BUFFER0]));
1617 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1618 		    "\tsitd_buffer1: 0x%x ",
1619 		    Get_ITD(itd->itd_body[EHCI_SITD_BUFFER1]));
1620 		USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1621 		    "\tsitd_prev_sitd: 0x%x ",
1622 		    Get_ITD(itd->itd_body[EHCI_SITD_PREV_SITD]));
1623 	}
1624 
1625 	/* HCD private fields */
1626 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1627 	    "\titd_trans_wrapper: 0x%x ",
1628 	    Get_ITD(itd->itd_trans_wrapper));
1629 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1630 	    "\titd_itw_next_itd: 0x%x ",
1631 	    Get_ITD(itd->itd_itw_next_itd));
1632 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1633 	    "\titd_state: 0x%x ",
1634 	    Get_ITD(itd->itd_state));
1635 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1636 	    "\titd_frame_number: 0x%x ",
1637 	    Get_ITD(itd->itd_frame_number));
1638 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1639 	    "\titd_reclaim_number: 0x%x ",
1640 	    Get_ITD(itd->itd_reclaim_number));
1641 	USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl,
1642 	    "\titd_next_active_itd: 0x%x ",
1643 	    Get_ITD(itd->itd_next_active_itd));
1644 }
1645