1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * Universal Host Controller Driver (UHCI)
29 *
30 * The UHCI driver is a driver which interfaces to the Universal
31 * Serial Bus Driver (USBA) and the Host Controller (HC). The interface to
32 * the Host Controller is defined by the UHCI.
33 * This file contains misc functions.
34 */
35 #include <sys/usb/hcd/uhci/uhcid.h>
36 #include <sys/usb/hcd/uhci/uhciutil.h>
37 #include <sys/usb/hcd/uhci/uhcipolled.h>
38
39 #include <sys/disp.h>
40
41 /* Globals */
42 extern uint_t uhci_td_pool_size; /* Num TDs */
43 extern uint_t uhci_qh_pool_size; /* Num QHs */
44 extern ushort_t uhci_tree_bottom_nodes[];
45 extern void *uhci_statep;
46
47 /* function prototypes */
48 static void uhci_build_interrupt_lattice(uhci_state_t *uhcip);
49 static int uhci_init_frame_lst_table(dev_info_t *dip, uhci_state_t *uhcip);
50
51 static uint_t uhci_lattice_height(uint_t bandwidth);
52 static uint_t uhci_lattice_parent(uint_t node);
53 static uint_t uhci_leftmost_leaf(uint_t node, uint_t height);
54 static uint_t uhci_compute_total_bandwidth(usb_ep_descr_t *endpoint,
55 usb_port_status_t port_status);
56
57 static int uhci_bandwidth_adjust(uhci_state_t *uhcip,
58 usb_ep_descr_t *endpoint, usb_port_status_t port_status);
59
60 static uhci_td_t *uhci_allocate_td_from_pool(uhci_state_t *uhcip);
61 static void uhci_fill_in_td(uhci_state_t *uhcip,
62 uhci_td_t *td, uhci_td_t *current_dummy,
63 uint32_t buffer_offset, size_t length,
64 uhci_pipe_private_t *pp, uchar_t PID,
65 usb_req_attrs_t attrs, uhci_trans_wrapper_t *tw);
66 static uint32_t uhci_get_tw_paddr_by_offs(uhci_state_t *uhcip,
67 uint32_t buffer_offset, size_t length,
68 uhci_trans_wrapper_t *tw);
69 static uhci_trans_wrapper_t *uhci_create_transfer_wrapper(
70 uhci_state_t *uhcip, uhci_pipe_private_t *pp,
71 size_t length, usb_flags_t usb_flags);
72 static uhci_trans_wrapper_t *uhci_create_isoc_transfer_wrapper(
73 uhci_state_t *uhcip, uhci_pipe_private_t *pp,
74 usb_isoc_req_t *req, size_t length,
75 usb_flags_t usb_flags);
76
77 static int uhci_create_setup_pkt(uhci_state_t *uhcip,
78 uhci_pipe_private_t *pp, uhci_trans_wrapper_t *tw);
79 static void uhci_insert_ctrl_qh(uhci_state_t *uhcip,
80 uhci_pipe_private_t *pp);
81 static void uhci_remove_ctrl_qh(uhci_state_t *uhcip,
82 uhci_pipe_private_t *pp);
83 static void uhci_insert_intr_qh(uhci_state_t *uhcip,
84 uhci_pipe_private_t *pp);
85 static void uhci_remove_intr_qh(uhci_state_t *uhcip,
86 uhci_pipe_private_t *pp);
87 static void uhci_remove_bulk_qh(uhci_state_t *uhcip,
88 uhci_pipe_private_t *pp);
89 static void uhci_insert_bulk_qh(uhci_state_t *uhcip,
90 uhci_pipe_private_t *pp);
91 static void uhci_handle_bulk_td_errors(uhci_state_t *uhcip, uhci_td_t *td);
92 static int uhci_alloc_memory_for_tds(uhci_state_t *uhcip, uint_t num_tds,
93 uhci_bulk_isoc_xfer_t *info);
94 static int uhci_alloc_bulk_isoc_tds(uhci_state_t *uhcip, uint_t num_tds,
95 uhci_bulk_isoc_xfer_t *info);
96 static void uhci_get_isoc_td_by_index(uhci_state_t *uhcip,
97 uhci_bulk_isoc_xfer_t *info, uint_t index,
98 uhci_td_t **tdpp, uhci_bulk_isoc_td_pool_t **td_pool_pp);
99 static void uhci_get_bulk_td_by_paddr(uhci_state_t *uhcip,
100 uhci_bulk_isoc_xfer_t *info, uint32_t paddr,
101 uhci_bulk_isoc_td_pool_t **td_pool_pp);
102
103 static int uhci_handle_isoc_receive(uhci_state_t *uhcip,
104 uhci_pipe_private_t *pp, uhci_trans_wrapper_t *tw);
105 static void uhci_delete_isoc_td(uhci_state_t *uhcip,
106 uhci_td_t *td);
107 #ifdef DEBUG
108 static void uhci_print_td(uhci_state_t *uhcip, uhci_td_t *td);
109 static void uhci_print_qh(uhci_state_t *uhcip, queue_head_t *qh);
110 #endif
111
112
113 /*
114 * uhci_build_interrupt_lattice:
115 *
116 * Construct the interrupt lattice tree using static Queue Head pointers.
117 * This interrupt lattice tree will have total of 63 queue heads and the
118 * Host Controller (HC) processes queue heads every frame.
119 */
120 static void
121 uhci_build_interrupt_lattice(uhci_state_t *uhcip)
122 {
123 int half_list = NUM_INTR_QH_LISTS / 2;
124 uint16_t i, j, k;
125 uhci_td_t *sof_td, *isoc_td;
126 uintptr_t addr;
127 queue_head_t *list_array = uhcip->uhci_qh_pool_addr;
128 queue_head_t *tmp_qh;
129 frame_lst_table_t *frame_lst_tablep =
130 uhcip->uhci_frame_lst_tablep;
131
132 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
133 "uhci_build_interrupt_lattice:");
134
135 /*
136 * Reserve the first 63 queue head structures in the pool as static
137 * queue heads & these are required for constructing interrupt
138 * lattice tree.
139 */
140 for (i = 0; i < NUM_INTR_QH_LISTS; i++) {
141 SetQH32(uhcip, list_array[i].link_ptr, HC_END_OF_LIST);
142 SetQH32(uhcip, list_array[i].element_ptr, HC_END_OF_LIST);
143 list_array[i].qh_flag = QUEUE_HEAD_FLAG_STATIC;
144 list_array[i].node = i;
145 }
146
147 /* Build the interrupt lattice tree */
148 for (i = 0; i < half_list - 1; i++) {
149 /*
150 * The next pointer in the host controller queue head
151 * descriptor must contain an iommu address. Calculate
152 * the offset into the cpu address and add this to the
153 * starting iommu address.
154 */
155 addr = QH_PADDR(&list_array[i]) | HC_QUEUE_HEAD;
156
157 SetQH32(uhcip, list_array[2*i + 1].link_ptr, addr);
158 SetQH32(uhcip, list_array[2*i + 2].link_ptr, addr);
159 }
160
161 /*
162 * Initialize the interrupt list in the Frame list Table
163 * so that it points to the bottom of the tree.
164 */
165 for (i = 0, j = 0; i < pow_2(TREE_HEIGHT); i++) {
166 addr = QH_PADDR(&list_array[half_list + i - 1]);
167 for (k = 0; k < pow_2(VIRTUAL_TREE_HEIGHT); k++) {
168 SetFL32(uhcip,
169 frame_lst_tablep[uhci_tree_bottom_nodes[j++]],
170 addr | HC_QUEUE_HEAD);
171 }
172 }
173
174 /*
175 * Create a controller and bulk Queue heads
176 */
177 uhcip->uhci_ctrl_xfers_q_head = uhci_alloc_queue_head(uhcip);
178 tmp_qh = uhcip->uhci_ctrl_xfers_q_tail = uhcip->uhci_ctrl_xfers_q_head;
179
180 SetQH32(uhcip, list_array[0].link_ptr,
181 (QH_PADDR(tmp_qh) | HC_QUEUE_HEAD));
182
183 uhcip->uhci_bulk_xfers_q_head = uhci_alloc_queue_head(uhcip);
184 uhcip->uhci_bulk_xfers_q_tail = uhcip->uhci_bulk_xfers_q_head;
185 SetQH32(uhcip, tmp_qh->link_ptr,
186 (QH_PADDR(uhcip->uhci_bulk_xfers_q_head)|HC_QUEUE_HEAD));
187
188 SetQH32(uhcip, uhcip->uhci_bulk_xfers_q_head->link_ptr, HC_END_OF_LIST);
189
190 /*
191 * Add a dummy TD to the static queue head 0. THis is used
192 * to generate an at the end of frame.
193 */
194 sof_td = uhci_allocate_td_from_pool(uhcip);
195
196 SetQH32(uhcip, list_array[0].element_ptr,
197 TD_PADDR(sof_td) | HC_TD_HEAD);
198 SetTD32(uhcip, sof_td->link_ptr, HC_END_OF_LIST);
199 uhcip->uhci_sof_td = sof_td;
200
201 /*
202 * Add a dummy td that is used to generate an interrupt for
203 * every 1024 frames.
204 */
205 isoc_td = uhci_allocate_td_from_pool(uhcip);
206 SetTD32(uhcip, isoc_td->link_ptr, HC_END_OF_LIST);
207 uhcip->uhci_isoc_td = isoc_td;
208
209 uhcip->uhci_isoc_qh = uhci_alloc_queue_head(uhcip);
210 SetQH32(uhcip, uhcip->uhci_isoc_qh->link_ptr,
211 GetFL32(uhcip, uhcip->uhci_frame_lst_tablep[MAX_FRAME_NUM]));
212 SetQH32(uhcip, uhcip->uhci_isoc_qh->element_ptr, TD_PADDR(isoc_td));
213 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[MAX_FRAME_NUM],
214 QH_PADDR(uhcip->uhci_isoc_qh) | HC_QUEUE_HEAD);
215 }
216
217
218 /*
219 * uhci_allocate_pools:
220 * Allocate the system memory for the Queue Heads Descriptor and
221 * for the Transfer Descriptor (TD) pools. Both QH and TD structures
222 * must be aligned to a 16 byte boundary.
223 */
224 int
225 uhci_allocate_pools(uhci_state_t *uhcip)
226 {
227 dev_info_t *dip = uhcip->uhci_dip;
228 size_t real_length;
229 int i, result;
230 uint_t ccount;
231 ddi_device_acc_attr_t dev_attr;
232
233 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
234 "uhci_allocate_pools:");
235
236 /* The host controller will be little endian */
237 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
238 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
239 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
240
241 /* Allocate the TD pool DMA handle */
242 if (ddi_dma_alloc_handle(dip, &uhcip->uhci_dma_attr, DDI_DMA_SLEEP, 0,
243 &uhcip->uhci_td_pool_dma_handle) != DDI_SUCCESS) {
244
245 return (USB_FAILURE);
246 }
247
248 /* Allocate the memory for the TD pool */
249 if (ddi_dma_mem_alloc(uhcip->uhci_td_pool_dma_handle,
250 uhci_td_pool_size * sizeof (uhci_td_t),
251 &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
252 (caddr_t *)&uhcip->uhci_td_pool_addr, &real_length,
253 &uhcip->uhci_td_pool_mem_handle)) {
254
255 return (USB_FAILURE);
256 }
257
258 /* Map the TD pool into the I/O address space */
259 result = ddi_dma_addr_bind_handle(uhcip->uhci_td_pool_dma_handle,
260 NULL, (caddr_t)uhcip->uhci_td_pool_addr, real_length,
261 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
262 NULL, &uhcip->uhci_td_pool_cookie, &ccount);
263
264 bzero((void *)uhcip->uhci_td_pool_addr,
265 uhci_td_pool_size * sizeof (uhci_td_t));
266
267 /* Process the result */
268 if (result == DDI_DMA_MAPPED) {
269 /* The cookie count should be 1 */
270 if (ccount != 1) {
271 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
272 "uhci_allocate_pools: More than 1 cookie");
273
274 return (USB_FAILURE);
275 }
276 } else {
277 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
278 "uhci_allocate_pools: Result = %d", result);
279
280 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip, result);
281
282 return (USB_FAILURE);
283 }
284
285 uhcip->uhci_dma_addr_bind_flag |= UHCI_TD_POOL_BOUND;
286
287 /* Initialize the TD pool */
288 for (i = 0; i < uhci_td_pool_size; i++) {
289 uhcip->uhci_td_pool_addr[i].flag = TD_FLAG_FREE;
290 }
291
292 /* Allocate the TD pool DMA handle */
293 if (ddi_dma_alloc_handle(dip, &uhcip->uhci_dma_attr, DDI_DMA_SLEEP,
294 0, &uhcip->uhci_qh_pool_dma_handle) != DDI_SUCCESS) {
295
296 return (USB_FAILURE);
297 }
298
299 /* Allocate the memory for the QH pool */
300 if (ddi_dma_mem_alloc(uhcip->uhci_qh_pool_dma_handle,
301 uhci_qh_pool_size * sizeof (queue_head_t),
302 &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
303 (caddr_t *)&uhcip->uhci_qh_pool_addr, &real_length,
304 &uhcip->uhci_qh_pool_mem_handle) != DDI_SUCCESS) {
305
306 return (USB_FAILURE);
307 }
308
309 result = ddi_dma_addr_bind_handle(uhcip->uhci_qh_pool_dma_handle,
310 NULL, (caddr_t)uhcip->uhci_qh_pool_addr, real_length,
311 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
312 &uhcip->uhci_qh_pool_cookie, &ccount);
313
314 /* Process the result */
315 if (result == DDI_DMA_MAPPED) {
316 /* The cookie count should be 1 */
317 if (ccount != 1) {
318 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
319 "uhci_allocate_pools: More than 1 cookie");
320
321 return (USB_FAILURE);
322 }
323 } else {
324 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip, result);
325
326 return (USB_FAILURE);
327 }
328
329 uhcip->uhci_dma_addr_bind_flag |= UHCI_QH_POOL_BOUND;
330
331 bzero((void *)uhcip->uhci_qh_pool_addr,
332 uhci_qh_pool_size * sizeof (queue_head_t));
333
334 /* Initialize the QH pool */
335 for (i = 0; i < uhci_qh_pool_size; i ++) {
336 uhcip->uhci_qh_pool_addr[i].qh_flag = QUEUE_HEAD_FLAG_FREE;
337 }
338
339 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
340 "uhci_allocate_pools: Completed");
341
342 return (USB_SUCCESS);
343 }
344
345
346 /*
347 * uhci_free_pools:
348 * Cleanup on attach failure or detach
349 */
350 void
351 uhci_free_pools(uhci_state_t *uhcip)
352 {
353 int i, flag, rval;
354 uhci_td_t *td;
355 uhci_trans_wrapper_t *tw;
356
357 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
358 "uhci_free_pools:");
359
360 if (uhcip->uhci_td_pool_addr && uhcip->uhci_td_pool_mem_handle) {
361 for (i = 0; i < uhci_td_pool_size; i ++) {
362 td = &uhcip->uhci_td_pool_addr[i];
363
364 flag = uhcip->uhci_td_pool_addr[i].flag;
365 if ((flag != TD_FLAG_FREE) &&
366 (flag != TD_FLAG_DUMMY) && (td->tw != NULL)) {
367 tw = td->tw;
368 uhci_free_tw(uhcip, tw);
369 }
370
371 }
372
373 if (uhcip->uhci_dma_addr_bind_flag & UHCI_TD_POOL_BOUND) {
374 rval = ddi_dma_unbind_handle(
375 uhcip->uhci_td_pool_dma_handle);
376 ASSERT(rval == DDI_SUCCESS);
377 }
378
379 ddi_dma_mem_free(&uhcip->uhci_td_pool_mem_handle);
380 }
381
382 /* Free the TD pool */
383 if (uhcip->uhci_td_pool_dma_handle) {
384 ddi_dma_free_handle(&uhcip->uhci_td_pool_dma_handle);
385 }
386
387 if (uhcip->uhci_qh_pool_addr && uhcip->uhci_qh_pool_mem_handle) {
388 if (uhcip->uhci_dma_addr_bind_flag & UHCI_QH_POOL_BOUND) {
389 rval = ddi_dma_unbind_handle(
390 uhcip->uhci_qh_pool_dma_handle);
391 ASSERT(rval == DDI_SUCCESS);
392 }
393 ddi_dma_mem_free(&uhcip->uhci_qh_pool_mem_handle);
394 }
395
396 /* Free the QH pool */
397 if (uhcip->uhci_qh_pool_dma_handle) {
398 ddi_dma_free_handle(&uhcip->uhci_qh_pool_dma_handle);
399 }
400
401 /* Free the Frame list Table area */
402 if (uhcip->uhci_frame_lst_tablep && uhcip->uhci_flt_mem_handle) {
403 if (uhcip->uhci_dma_addr_bind_flag & UHCI_FLA_POOL_BOUND) {
404 rval = ddi_dma_unbind_handle(
405 uhcip->uhci_flt_dma_handle);
406 ASSERT(rval == DDI_SUCCESS);
407 }
408 ddi_dma_mem_free(&uhcip->uhci_flt_mem_handle);
409 }
410
411 if (uhcip->uhci_flt_dma_handle) {
412 ddi_dma_free_handle(&uhcip->uhci_flt_dma_handle);
413 }
414 }
415
416
417 /*
418 * uhci_decode_ddi_dma_addr_bind_handle_result:
419 * Process the return values of ddi_dma_addr_bind_handle()
420 */
421 void
422 uhci_decode_ddi_dma_addr_bind_handle_result(uhci_state_t *uhcip, int result)
423 {
424 char *msg;
425
426 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
427 "uhci_decode_ddi_dma_addr_bind_handle_result:");
428
429 switch (result) {
430 case DDI_DMA_PARTIAL_MAP:
431 msg = "Partial transfers not allowed";
432 break;
433 case DDI_DMA_INUSE:
434 msg = "Handle is in use";
435 break;
436 case DDI_DMA_NORESOURCES:
437 msg = "No resources";
438 break;
439 case DDI_DMA_NOMAPPING:
440 msg = "No mapping";
441 break;
442 case DDI_DMA_TOOBIG:
443 msg = "Object is too big";
444 break;
445 default:
446 msg = "Unknown dma error";
447 }
448
449 USB_DPRINTF_L4(PRINT_MASK_ALL, uhcip->uhci_log_hdl, "%s", msg);
450 }
451
452
453 /*
454 * uhci_init_ctlr:
455 * Initialize the Host Controller (HC).
456 */
457 int
458 uhci_init_ctlr(uhci_state_t *uhcip)
459 {
460 dev_info_t *dip = uhcip->uhci_dip;
461 uint_t cmd_reg;
462 uint_t frame_base_addr;
463
464 mutex_enter(&uhcip->uhci_int_mutex);
465
466 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_init_ctlr:");
467
468 /*
469 * When USB legacy mode is enabled, the BIOS manages the USB keyboard
470 * attached to the UHCI controller. It has been observed that some
471 * times the BIOS does not clear the interrupts in the legacy mode
472 * register in the PCI configuration space. So, disable the SMI intrs
473 * and route the intrs to PIRQD here.
474 */
475 pci_config_put16(uhcip->uhci_config_handle,
476 LEGACYMODE_REG_OFFSET, LEGACYMODE_REG_INIT_VALUE);
477
478 /*
479 * Disable all the interrupts.
480 */
481 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
482
483 cmd_reg = Get_OpReg16(USBCMD);
484 cmd_reg &= (~USBCMD_REG_HC_RUN);
485
486 /* Stop the controller */
487 Set_OpReg16(USBCMD, cmd_reg);
488
489 /* Reset the host controller */
490 Set_OpReg16(USBCMD, USBCMD_REG_GBL_RESET);
491
492 /* Wait 10ms for reset to complete */
493 mutex_exit(&uhcip->uhci_int_mutex);
494 delay(drv_usectohz(UHCI_RESET_DELAY));
495 mutex_enter(&uhcip->uhci_int_mutex);
496
497 Set_OpReg16(USBCMD, 0);
498
499 /* Set the frame number to zero */
500 Set_OpReg16(FRNUM, 0);
501
502 if (uhcip->uhci_hc_soft_state == UHCI_CTLR_INIT_STATE) {
503 /* Initialize the Frame list base address area */
504 if (uhci_init_frame_lst_table(dip, uhcip) != USB_SUCCESS) {
505 mutex_exit(&uhcip->uhci_int_mutex);
506
507 return (USB_FAILURE);
508 }
509 }
510
511 /* Save the contents of the Frame Interval Registers */
512 uhcip->uhci_frame_interval = Get_OpReg8(SOFMOD);
513
514 frame_base_addr = uhcip->uhci_flt_cookie.dmac_address;
515
516 /* Set the Frame list base address */
517 Set_OpReg32(FRBASEADD, frame_base_addr);
518
519 /*
520 * Begin sending SOFs
521 * Set the Host Controller Functional State to Operational
522 */
523 cmd_reg = Get_OpReg16(USBCMD);
524 cmd_reg |= (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
525 USBCMD_REG_CONFIG_FLAG);
526
527 Set_OpReg16(USBCMD, cmd_reg);
528
529 /*
530 * Verify the Command and interrupt enable registers,
531 * a sanity check whether actually initialized or not
532 */
533 cmd_reg = Get_OpReg16(USBCMD);
534
535 if (!(cmd_reg & (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
536 USBCMD_REG_CONFIG_FLAG))) {
537 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
538 "uhci_init_ctlr: Controller initialization failed");
539 mutex_exit(&uhcip->uhci_int_mutex);
540
541 return (USB_FAILURE);
542 }
543
544 /*
545 * Set the ioc bit of the isoc intr td. This enables
546 * the generation of an interrupt for every 1024 frames.
547 */
548 SetTD_ioc(uhcip, uhcip->uhci_isoc_td, 1);
549
550 /* Set host controller soft state to operational */
551 uhcip->uhci_hc_soft_state = UHCI_CTLR_OPERATIONAL_STATE;
552 mutex_exit(&uhcip->uhci_int_mutex);
553
554 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
555 "uhci_init_ctlr: Completed");
556
557 return (USB_SUCCESS);
558 }
559
560
561 /*
562 * uhci_uninit_ctlr:
563 * uninitialize the Host Controller (HC).
564 */
565 void
566 uhci_uninit_ctlr(uhci_state_t *uhcip)
567 {
568 if (uhcip->uhci_regs_handle) {
569 /* Disable all the interrupts. */
570 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
571
572 /* Complete the current transaction and then halt. */
573 Set_OpReg16(USBCMD, 0);
574
575 /* Wait for sometime */
576 mutex_exit(&uhcip->uhci_int_mutex);
577 delay(drv_usectohz(UHCI_TIMEWAIT));
578 mutex_enter(&uhcip->uhci_int_mutex);
579 }
580 }
581
582
583 /*
584 * uhci_map_regs:
585 * The Host Controller (HC) contains a set of on-chip operational
586 * registers and which should be mapped into a non-cacheable
587 * portion of the system addressable space.
588 */
589 int
590 uhci_map_regs(uhci_state_t *uhcip)
591 {
592 dev_info_t *dip = uhcip->uhci_dip;
593 int index;
594 uint32_t regs_prop_len;
595 int32_t *regs_list;
596 uint16_t command_reg;
597 ddi_device_acc_attr_t attr;
598
599 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_map_regs:");
600
601 /* The host controller will be little endian */
602 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
603 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
604 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
605
606 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, uhcip->uhci_dip,
607 DDI_PROP_DONTPASS, "reg", ®s_list, ®s_prop_len) !=
608 DDI_PROP_SUCCESS) {
609
610 return (USB_FAILURE);
611 }
612
613 for (index = 0; index * 5 < regs_prop_len; index++) {
614 if (regs_list[index * 5] & UHCI_PROP_MASK) {
615 break;
616 }
617 }
618
619 /*
620 * Deallocate the memory allocated by the ddi_prop_lookup_int_array
621 */
622 ddi_prop_free(regs_list);
623
624 if (index * 5 >= regs_prop_len) {
625
626 return (USB_FAILURE);
627 }
628
629 /* Map in operational registers */
630 if (ddi_regs_map_setup(dip, index, (caddr_t *)&uhcip->uhci_regsp,
631 0, sizeof (hc_regs_t), &attr, &uhcip->uhci_regs_handle) !=
632 DDI_SUCCESS) {
633 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
634 "ddi_regs_map_setup: failed");
635
636 return (USB_FAILURE);
637 }
638
639 if (pci_config_setup(dip, &uhcip->uhci_config_handle) != DDI_SUCCESS) {
640 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
641 "uhci_map_regs: Config error");
642
643 return (USB_FAILURE);
644 }
645
646 /* Make sure Memory Access Enable and Master Enable are set */
647 command_reg = pci_config_get16(uhcip->uhci_config_handle,
648 PCI_CONF_COMM);
649 if (!(command_reg & (PCI_COMM_MAE | PCI_COMM_ME))) {
650 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
651 "uhci_map_regs: No MAE/ME");
652 }
653
654 command_reg |= PCI_COMM_MAE | PCI_COMM_ME;
655 pci_config_put16(uhcip->uhci_config_handle, PCI_CONF_COMM, command_reg);
656
657 /*
658 * Check whether I/O base address is configured and enabled.
659 */
660 if (!(command_reg & PCI_COMM_IO)) {
661 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
662 "I/O Base address access disabled");
663
664 return (USB_FAILURE);
665 }
666 /*
667 * Get the IO base address of the controller
668 */
669 uhcip->uhci_iobase = (pci_config_get16(uhcip->uhci_config_handle,
670 PCI_CONF_IOBASE) & PCI_CONF_IOBASE_MASK);
671
672 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
673 "uhci_map_regs: Completed");
674
675 return (USB_SUCCESS);
676 }
677
678
679 void
680 uhci_unmap_regs(uhci_state_t *uhcip)
681 {
682 /* Unmap the UHCI registers */
683 if (uhcip->uhci_regs_handle) {
684 /* Reset the host controller */
685 Set_OpReg16(USBCMD, USBCMD_REG_GBL_RESET);
686
687 ddi_regs_map_free(&uhcip->uhci_regs_handle);
688 }
689
690 if (uhcip->uhci_config_handle) {
691 pci_config_teardown(&uhcip->uhci_config_handle);
692 }
693 }
694
695
696 /*
697 * uhci_set_dma_attributes:
698 * Set the limits in the DMA attributes structure. Most of the values used
699 * in the DMA limit structres are the default values as specified by the
700 * Writing PCI device drivers document.
701 */
702 void
703 uhci_set_dma_attributes(uhci_state_t *uhcip)
704 {
705 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
706 "uhci_set_dma_attributes:");
707
708 /* Initialize the DMA attributes */
709 uhcip->uhci_dma_attr.dma_attr_version = DMA_ATTR_V0;
710 uhcip->uhci_dma_attr.dma_attr_addr_lo = 0x00000000ull;
711 uhcip->uhci_dma_attr.dma_attr_addr_hi = 0xfffffff0ull;
712
713 /* 32 bit addressing */
714 uhcip->uhci_dma_attr.dma_attr_count_max = 0xffffffull;
715
716 /*
717 * Setting the dam_att_align to 512, some times fails the
718 * binding handle. I dont know why ? But setting to 16 will
719 * be right for our case (16 byte alignment required per
720 * UHCI spec for TD descriptors).
721 */
722
723 /* 16 byte alignment */
724 uhcip->uhci_dma_attr.dma_attr_align = 0x10;
725
726 /*
727 * Since PCI specification is byte alignment, the
728 * burstsize field should be set to 1 for PCI devices.
729 */
730 uhcip->uhci_dma_attr.dma_attr_burstsizes = 0x1;
731
732 uhcip->uhci_dma_attr.dma_attr_minxfer = 0x1;
733 uhcip->uhci_dma_attr.dma_attr_maxxfer = 0xffffffull;
734 uhcip->uhci_dma_attr.dma_attr_seg = 0xffffffffull;
735 uhcip->uhci_dma_attr.dma_attr_sgllen = 1;
736 uhcip->uhci_dma_attr.dma_attr_granular = 1;
737 uhcip->uhci_dma_attr.dma_attr_flags = 0;
738 }
739
740
741 uint_t
742 pow_2(uint_t x)
743 {
744 return ((x == 0) ? 1 : (1 << x));
745 }
746
747
748 uint_t
749 log_2(uint_t x)
750 {
751 int ret_val = 0;
752
753 while (x != 1) {
754 ret_val++;
755 x = x >> 1;
756 }
757
758 return (ret_val);
759 }
760
761
762 /*
763 * uhci_obtain_state:
764 */
765 uhci_state_t *
766 uhci_obtain_state(dev_info_t *dip)
767 {
768 int instance = ddi_get_instance(dip);
769 uhci_state_t *state = ddi_get_soft_state(uhci_statep, instance);
770
771 ASSERT(state != NULL);
772
773 return (state);
774 }
775
776
777 /*
778 * uhci_alloc_hcdi_ops:
779 * The HCDI interfaces or entry points are the software interfaces used by
780 * the Universal Serial Bus Driver (USBA) to access the services of the
781 * Host Controller Driver (HCD). During HCD initialization, inform USBA
782 * about all available HCDI interfaces or entry points.
783 */
784 usba_hcdi_ops_t *
785 uhci_alloc_hcdi_ops(uhci_state_t *uhcip)
786 {
787 usba_hcdi_ops_t *hcdi_ops;
788
789 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
790 "uhci_alloc_hcdi_ops:");
791
792 hcdi_ops = usba_alloc_hcdi_ops();
793
794 hcdi_ops->usba_hcdi_ops_version = HCDI_OPS_VERSION_1;
795
796 hcdi_ops->usba_hcdi_pipe_open = uhci_hcdi_pipe_open;
797 hcdi_ops->usba_hcdi_pipe_close = uhci_hcdi_pipe_close;
798 hcdi_ops->usba_hcdi_pipe_reset = uhci_hcdi_pipe_reset;
799 hcdi_ops->usba_hcdi_pipe_reset_data_toggle =
800 uhci_hcdi_pipe_reset_data_toggle;
801
802 hcdi_ops->usba_hcdi_pipe_ctrl_xfer = uhci_hcdi_pipe_ctrl_xfer;
803 hcdi_ops->usba_hcdi_pipe_bulk_xfer = uhci_hcdi_pipe_bulk_xfer;
804 hcdi_ops->usba_hcdi_pipe_intr_xfer = uhci_hcdi_pipe_intr_xfer;
805 hcdi_ops->usba_hcdi_pipe_isoc_xfer = uhci_hcdi_pipe_isoc_xfer;
806
807 hcdi_ops->usba_hcdi_bulk_transfer_size = uhci_hcdi_bulk_transfer_size;
808 hcdi_ops->usba_hcdi_pipe_stop_intr_polling =
809 uhci_hcdi_pipe_stop_intr_polling;
810 hcdi_ops->usba_hcdi_pipe_stop_isoc_polling =
811 uhci_hcdi_pipe_stop_isoc_polling;
812
813 hcdi_ops->usba_hcdi_get_current_frame_number =
814 uhci_hcdi_get_current_frame_number;
815 hcdi_ops->usba_hcdi_get_max_isoc_pkts = uhci_hcdi_get_max_isoc_pkts;
816
817 hcdi_ops->usba_hcdi_console_input_init = uhci_hcdi_polled_input_init;
818 hcdi_ops->usba_hcdi_console_input_enter = uhci_hcdi_polled_input_enter;
819 hcdi_ops->usba_hcdi_console_read = uhci_hcdi_polled_read;
820 hcdi_ops->usba_hcdi_console_input_exit = uhci_hcdi_polled_input_exit;
821 hcdi_ops->usba_hcdi_console_input_fini = uhci_hcdi_polled_input_fini;
822
823 hcdi_ops->usba_hcdi_console_output_init = uhci_hcdi_polled_output_init;
824 hcdi_ops->usba_hcdi_console_output_enter =
825 uhci_hcdi_polled_output_enter;
826 hcdi_ops->usba_hcdi_console_write = uhci_hcdi_polled_write;
827 hcdi_ops->usba_hcdi_console_output_exit = uhci_hcdi_polled_output_exit;
828 hcdi_ops->usba_hcdi_console_output_fini = uhci_hcdi_polled_output_fini;
829
830 return (hcdi_ops);
831 }
832
833
834 /*
835 * uhci_init_frame_lst_table :
836 * Allocate the system memory and initialize Host Controller
837 * Frame list table area The starting of the Frame list Table
838 * area must be 4096 byte aligned.
839 */
840 static int
841 uhci_init_frame_lst_table(dev_info_t *dip, uhci_state_t *uhcip)
842 {
843 int result;
844 uint_t ccount;
845 size_t real_length;
846 ddi_device_acc_attr_t dev_attr;
847
848 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
849
850 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
851 "uhci_init_frame_lst_table:");
852
853 /* The host controller will be little endian */
854 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
855 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
856 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
857
858 /* 4K alignment required */
859 uhcip->uhci_dma_attr.dma_attr_align = 0x1000;
860
861 /* Create space for the HCCA block */
862 if (ddi_dma_alloc_handle(dip, &uhcip->uhci_dma_attr, DDI_DMA_SLEEP,
863 0, &uhcip->uhci_flt_dma_handle) != DDI_SUCCESS) {
864
865 return (USB_FAILURE);
866 }
867
868 /* Reset to default 16 bytes */
869 uhcip->uhci_dma_attr.dma_attr_align = 0x10;
870
871 if (ddi_dma_mem_alloc(uhcip->uhci_flt_dma_handle,
872 SIZE_OF_FRAME_LST_TABLE, &dev_attr, DDI_DMA_CONSISTENT,
873 DDI_DMA_SLEEP, 0, (caddr_t *)&uhcip->uhci_frame_lst_tablep,
874 &real_length, &uhcip->uhci_flt_mem_handle)) {
875
876 return (USB_FAILURE);
877 }
878
879 /* Map the whole Frame list base area into the I/O address space */
880 result = ddi_dma_addr_bind_handle(uhcip->uhci_flt_dma_handle,
881 NULL, (caddr_t)uhcip->uhci_frame_lst_tablep, real_length,
882 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
883 &uhcip->uhci_flt_cookie, &ccount);
884
885 if (result == DDI_DMA_MAPPED) {
886 /* The cookie count should be 1 */
887 if (ccount != 1) {
888 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
889 "uhci_init_frame_list_table: More than 1 cookie");
890
891 return (USB_FAILURE);
892 }
893 } else {
894 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip, result);
895
896 return (USB_FAILURE);
897 }
898
899 uhcip->uhci_dma_addr_bind_flag |= UHCI_FLA_POOL_BOUND;
900
901 bzero((void *)uhcip->uhci_frame_lst_tablep, real_length);
902
903 /* Initialize the interrupt lists */
904 uhci_build_interrupt_lattice(uhcip);
905
906 return (USB_SUCCESS);
907 }
908
909
910 /*
911 * uhci_alloc_queue_head:
912 * Allocate a queue head
913 */
914 queue_head_t *
915 uhci_alloc_queue_head(uhci_state_t *uhcip)
916 {
917 int index;
918 uhci_td_t *dummy_td;
919 queue_head_t *queue_head;
920
921 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
922 "uhci_alloc_queue_head");
923
924 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
925
926 /* Allocate a dummy td first. */
927 if ((dummy_td = uhci_allocate_td_from_pool(uhcip)) == NULL) {
928
929 USB_DPRINTF_L2(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
930 "uhci_alloc_queue_head: allocate td from pool failed");
931
932 return (NULL);
933 }
934
935 /*
936 * The first 63 queue heads in the Queue Head (QH)
937 * buffer pool are reserved for building interrupt lattice
938 * tree. Search for a blank Queue head in the QH buffer pool.
939 */
940 for (index = NUM_STATIC_NODES; index < uhci_qh_pool_size; index++) {
941 if (uhcip->uhci_qh_pool_addr[index].qh_flag ==
942 QUEUE_HEAD_FLAG_FREE) {
943 break;
944 }
945 }
946
947 USB_DPRINTF_L3(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
948 "uhci_alloc_queue_head: Allocated %d", index);
949
950 if (index == uhci_qh_pool_size) {
951 USB_DPRINTF_L2(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
952 "uhci_alloc_queue_head: All QH exhausted");
953
954 /* Free the dummy td allocated for this qh. */
955 dummy_td->flag = TD_FLAG_FREE;
956
957 return (NULL);
958 }
959
960 queue_head = &uhcip->uhci_qh_pool_addr[index];
961 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
962 "uhci_alloc_queue_head: Allocated address 0x%p",
963 (void *)queue_head);
964
965 bzero((void *)queue_head, sizeof (queue_head_t));
966 SetQH32(uhcip, queue_head->link_ptr, HC_END_OF_LIST);
967 SetQH32(uhcip, queue_head->element_ptr, HC_END_OF_LIST);
968 queue_head->prev_qh = NULL;
969 queue_head->qh_flag = QUEUE_HEAD_FLAG_BUSY;
970
971 bzero((char *)dummy_td, sizeof (uhci_td_t));
972 queue_head->td_tailp = dummy_td;
973 SetQH32(uhcip, queue_head->element_ptr, TD_PADDR(dummy_td));
974
975 return (queue_head);
976 }
977
978
979 /*
980 * uhci_allocate_bandwidth:
981 * Figure out whether or not this interval may be supported. Return
982 * the index into the lattice if it can be supported. Return
983 * allocation failure if it can not be supported.
984 */
985 int
986 uhci_allocate_bandwidth(
987 uhci_state_t *uhcip,
988 usba_pipe_handle_data_t *pipe_handle,
989 uint_t *node)
990 {
991 int bandwidth; /* Requested bandwidth */
992 uint_t min, min_index;
993 uint_t i;
994 uint_t height; /* Bandwidth's height in the tree */
995 uint_t leftmost;
996 uint_t length;
997 uint32_t paddr;
998 queue_head_t *tmp_qh;
999 usb_ep_descr_t *endpoint = &pipe_handle->p_ep;
1000
1001 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1002
1003 /*
1004 * Calculate the length in bytes of a transaction on this
1005 * periodic endpoint.
1006 */
1007 mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1008
1009 length = uhci_compute_total_bandwidth(endpoint,
1010 pipe_handle->p_usba_device->usb_port_status);
1011 mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1012
1013 /*
1014 * If the length in bytes plus the allocated bandwidth exceeds
1015 * the maximum, return bandwidth allocation failure.
1016 */
1017 if ((length + uhcip->uhci_bandwidth_intr_min +
1018 uhcip->uhci_bandwidth_isoch_sum) > (MAX_PERIODIC_BANDWIDTH)) {
1019 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1020 "uhci_allocate_bandwidth: "
1021 "Reached maximum bandwidth value and cannot allocate "
1022 "bandwidth for a given Interrupt/Isoch endpoint");
1023
1024 return (USB_NO_BANDWIDTH);
1025 }
1026
1027 /*
1028 * ISOC xfers are not supported at this point type
1029 */
1030 if (UHCI_XFER_TYPE(endpoint) == USB_EP_ATTR_ISOCH) {
1031 uhcip->uhci_bandwidth_isoch_sum += length;
1032
1033 return (USB_SUCCESS);
1034 }
1035
1036 /*
1037 * This is an interrupt endpoint.
1038 * Adjust bandwidth to be a power of 2
1039 */
1040 mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1041 bandwidth = uhci_bandwidth_adjust(uhcip, endpoint,
1042 pipe_handle->p_usba_device->usb_port_status);
1043 mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1044
1045 /*
1046 * If this bandwidth can't be supported,
1047 * return allocation failure.
1048 */
1049 if (bandwidth == USB_FAILURE) {
1050
1051 return (USB_FAILURE);
1052 }
1053
1054 USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1055 "The new bandwidth is %d", bandwidth);
1056
1057 /* Find the leaf with the smallest allocated bandwidth */
1058 min_index = 0;
1059 min = uhcip->uhci_bandwidth[0];
1060
1061 for (i = 1; i < NUM_FRAME_LST_ENTRIES; i++) {
1062 if (uhcip->uhci_bandwidth[i] < min) {
1063 min_index = i;
1064 min = uhcip->uhci_bandwidth[i];
1065 }
1066 }
1067
1068 USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1069 "The leaf with minimal bandwidth %d, "
1070 "The smallest bandwidth %d", min_index, min);
1071
1072 /*
1073 * Find the index into the lattice given the
1074 * leaf with the smallest allocated bandwidth.
1075 */
1076 height = uhci_lattice_height(bandwidth);
1077 USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1078 "The height is %d", height);
1079
1080 *node = uhci_tree_bottom_nodes[min_index];
1081
1082 /* check if there are isocs TDs scheduled for this frame */
1083 if (uhcip->uhci_isoc_q_tailp[*node]) {
1084 paddr = (uhcip->uhci_isoc_q_tailp[*node]->link_ptr &
1085 FRAME_LST_PTR_MASK);
1086 } else {
1087 paddr = (uhcip->uhci_frame_lst_tablep[*node] &
1088 FRAME_LST_PTR_MASK);
1089 }
1090
1091 tmp_qh = QH_VADDR(paddr);
1092 *node = tmp_qh->node;
1093 for (i = 0; i < height; i++) {
1094 *node = uhci_lattice_parent(*node);
1095 }
1096
1097 USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1098 "The real node is %d", *node);
1099
1100 /*
1101 * Find the leftmost leaf in the subtree specified by the node.
1102 */
1103 leftmost = uhci_leftmost_leaf(*node, height);
1104 USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1105 "Leftmost %d", leftmost);
1106
1107 for (i = leftmost; i < leftmost +
1108 (NUM_FRAME_LST_ENTRIES/bandwidth); i ++) {
1109
1110 if ((length + uhcip->uhci_bandwidth_isoch_sum +
1111 uhcip->uhci_bandwidth[i]) > MAX_PERIODIC_BANDWIDTH) {
1112
1113 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1114 "uhci_allocate_bandwidth: "
1115 "Reached maximum bandwidth value and cannot "
1116 "allocate bandwidth for Interrupt endpoint");
1117
1118 return (USB_NO_BANDWIDTH);
1119 }
1120 }
1121
1122 /*
1123 * All the leaves for this node must be updated with the bandwidth.
1124 */
1125 for (i = leftmost; i < leftmost +
1126 (NUM_FRAME_LST_ENTRIES/bandwidth); i ++) {
1127 uhcip->uhci_bandwidth[i] += length;
1128 }
1129
1130 /* Find the leaf with the smallest allocated bandwidth */
1131 min_index = 0;
1132 min = uhcip->uhci_bandwidth[0];
1133
1134 for (i = 1; i < NUM_FRAME_LST_ENTRIES; i++) {
1135 if (uhcip->uhci_bandwidth[i] < min) {
1136 min_index = i;
1137 min = uhcip->uhci_bandwidth[i];
1138 }
1139 }
1140
1141 /* Save the minimum for later use */
1142 uhcip->uhci_bandwidth_intr_min = min;
1143
1144 return (USB_SUCCESS);
1145 }
1146
1147
1148 /*
1149 * uhci_deallocate_bandwidth:
1150 * Deallocate bandwidth for the given node in the lattice
1151 * and the length of transfer.
1152 */
1153 void
1154 uhci_deallocate_bandwidth(uhci_state_t *uhcip,
1155 usba_pipe_handle_data_t *pipe_handle)
1156 {
1157 uint_t bandwidth;
1158 uint_t height;
1159 uint_t leftmost;
1160 uint_t i;
1161 uint_t min;
1162 usb_ep_descr_t *endpoint = &pipe_handle->p_ep;
1163 uint_t node, length;
1164 uhci_pipe_private_t *pp =
1165 (uhci_pipe_private_t *)pipe_handle->p_hcd_private;
1166
1167 /* This routine is protected by the uhci_int_mutex */
1168 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1169
1170 /* Obtain the length */
1171 mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1172 length = uhci_compute_total_bandwidth(endpoint,
1173 pipe_handle->p_usba_device->usb_port_status);
1174 mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1175
1176 /*
1177 * If this is an isochronous endpoint, just delete endpoint's
1178 * bandwidth from the total allocated isochronous bandwidth.
1179 */
1180 if (UHCI_XFER_TYPE(endpoint) == USB_EP_ATTR_ISOCH) {
1181 uhcip->uhci_bandwidth_isoch_sum -= length;
1182
1183 return;
1184 }
1185
1186 /* Obtain the node */
1187 node = pp->pp_node;
1188
1189 /* Adjust bandwidth to be a power of 2 */
1190 mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1191 bandwidth = uhci_bandwidth_adjust(uhcip, endpoint,
1192 pipe_handle->p_usba_device->usb_port_status);
1193 mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1194
1195 /* Find the height in the tree */
1196 height = uhci_lattice_height(bandwidth);
1197
1198 /*
1199 * Find the leftmost leaf in the subtree specified by the node
1200 */
1201 leftmost = uhci_leftmost_leaf(node, height);
1202
1203 /* Delete the bandwith from the appropriate lists */
1204 for (i = leftmost; i < leftmost + (NUM_FRAME_LST_ENTRIES/bandwidth);
1205 i ++) {
1206 uhcip->uhci_bandwidth[i] -= length;
1207 }
1208
1209 min = uhcip->uhci_bandwidth[0];
1210
1211 /* Recompute the minimum */
1212 for (i = 1; i < NUM_FRAME_LST_ENTRIES; i++) {
1213 if (uhcip->uhci_bandwidth[i] < min) {
1214 min = uhcip->uhci_bandwidth[i];
1215 }
1216 }
1217
1218 /* Save the minimum for later use */
1219 uhcip->uhci_bandwidth_intr_min = min;
1220 }
1221
1222
1223 /*
1224 * uhci_compute_total_bandwidth:
1225 *
1226 * Given a periodic endpoint (interrupt or isochronous) determine the total
1227 * bandwidth for one transaction. The UHCI host controller traverses the
1228 * endpoint descriptor lists on a first-come-first-serve basis. When the HC
1229 * services an endpoint, only a single transaction attempt is made. The HC
1230 * moves to the next Endpoint Descriptor after the first transaction attempt
1231 * rather than finishing the entire Transfer Descriptor. Therefore, when a
1232 * Transfer Descriptor is inserted into the lattice, we will only count the
1233 * number of bytes for one transaction.
1234 *
1235 * The following are the formulas used for calculating bandwidth in terms
1236 * bytes and it is for the single USB full speed and low speed transaction
1237 * respectively. The protocol overheads will be different for each of type
1238 * of USB transfer and all these formulas & protocol overheads are derived
1239 * from the 5.9.3 section of USB Specification & with the help of Bandwidth
1240 * Analysis white paper which is posted on the USB developer forum.
1241 *
1242 * Full-Speed:
1243 * Protocol overhead + ((MaxPacketSize * 7)/6 ) + Host_Delay
1244 *
1245 * Low-Speed:
1246 * Protocol overhead + Hub LS overhead +
1247 * (Low-Speed clock * ((MaxPacketSize * 7)/6 )) + Host_Delay
1248 */
1249 static uint_t
1250 uhci_compute_total_bandwidth(usb_ep_descr_t *endpoint,
1251 usb_port_status_t port_status)
1252 {
1253 uint_t bandwidth;
1254 ushort_t MaxPacketSize = endpoint->wMaxPacketSize;
1255
1256 /* Add Host Controller specific delay to required bandwidth */
1257 bandwidth = HOST_CONTROLLER_DELAY;
1258
1259 /* Add bit-stuffing overhead */
1260 MaxPacketSize = (ushort_t)((MaxPacketSize * 7) / 6);
1261
1262 /* Low Speed interrupt transaction */
1263 if (port_status == USBA_LOW_SPEED_DEV) {
1264 /* Low Speed interrupt transaction */
1265 bandwidth += (LOW_SPEED_PROTO_OVERHEAD +
1266 HUB_LOW_SPEED_PROTO_OVERHEAD +
1267 (LOW_SPEED_CLOCK * MaxPacketSize));
1268 } else {
1269 /* Full Speed transaction */
1270 bandwidth += MaxPacketSize;
1271
1272 if (UHCI_XFER_TYPE(endpoint) == USB_EP_ATTR_INTR) {
1273 /* Full Speed interrupt transaction */
1274 bandwidth += FS_NON_ISOC_PROTO_OVERHEAD;
1275 } else {
1276 /* Isochronus and input transaction */
1277 if (UHCI_XFER_DIR(endpoint) == USB_EP_DIR_IN) {
1278 bandwidth += FS_ISOC_INPUT_PROTO_OVERHEAD;
1279 } else {
1280 /* Isochronus and output transaction */
1281 bandwidth += FS_ISOC_OUTPUT_PROTO_OVERHEAD;
1282 }
1283 }
1284 }
1285
1286 return (bandwidth);
1287 }
1288
1289
1290 /*
1291 * uhci_bandwidth_adjust:
1292 */
1293 static int
1294 uhci_bandwidth_adjust(
1295 uhci_state_t *uhcip,
1296 usb_ep_descr_t *endpoint,
1297 usb_port_status_t port_status)
1298 {
1299 int i = 0;
1300 uint_t interval;
1301
1302 /*
1303 * Get the polling interval from the endpoint descriptor
1304 */
1305 interval = endpoint->bInterval;
1306
1307 /*
1308 * The bInterval value in the endpoint descriptor can range
1309 * from 1 to 255ms. The interrupt lattice has 32 leaf nodes,
1310 * and the host controller cycles through these nodes every
1311 * 32ms. The longest polling interval that the controller
1312 * supports is 32ms.
1313 */
1314
1315 /*
1316 * Return an error if the polling interval is less than 1ms
1317 * and greater than 255ms
1318 */
1319 if ((interval < MIN_POLL_INTERVAL) || (interval > MAX_POLL_INTERVAL)) {
1320 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1321 "uhci_bandwidth_adjust: Endpoint's poll interval must be "
1322 "between %d and %d ms", MIN_POLL_INTERVAL,
1323 MAX_POLL_INTERVAL);
1324
1325 return (USB_FAILURE);
1326 }
1327
1328 /*
1329 * According USB Specifications, a full-speed endpoint can
1330 * specify a desired polling interval 1ms to 255ms and a low
1331 * speed endpoints are limited to specifying only 10ms to
1332 * 255ms. But some old keyboards & mice uses polling interval
1333 * of 8ms. For compatibility purpose, we are using polling
1334 * interval between 8ms & 255ms for low speed endpoints.
1335 */
1336 if ((port_status == USBA_LOW_SPEED_DEV) &&
1337 (interval < MIN_LOW_SPEED_POLL_INTERVAL)) {
1338 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1339 "uhci_bandwidth_adjust: Low speed endpoint's poll interval "
1340 "must be >= %d ms, adjusted",
1341 MIN_LOW_SPEED_POLL_INTERVAL);
1342
1343 interval = MIN_LOW_SPEED_POLL_INTERVAL;
1344 }
1345
1346 /*
1347 * If polling interval is greater than 32ms,
1348 * adjust polling interval equal to 32ms.
1349 */
1350 if (interval > 32) {
1351 interval = 32;
1352 }
1353
1354 /*
1355 * Find the nearest power of 2 that's less
1356 * than interval.
1357 */
1358 while ((pow_2(i)) <= interval) {
1359 i++;
1360 }
1361
1362 return (pow_2((i - 1)));
1363 }
1364
1365
1366 /*
1367 * uhci_lattice_height:
1368 * Given the requested bandwidth, find the height in the tree at
1369 * which the nodes for this bandwidth fall. The height is measured
1370 * as the number of nodes from the leaf to the level specified by
1371 * bandwidth The root of the tree is at height TREE_HEIGHT.
1372 */
1373 static uint_t
1374 uhci_lattice_height(uint_t bandwidth)
1375 {
1376 return (TREE_HEIGHT - (log_2(bandwidth)));
1377 }
1378
1379
1380 static uint_t
1381 uhci_lattice_parent(uint_t node)
1382 {
1383 return (((node % 2) == 0) ? ((node/2) - 1) : (node/2));
1384 }
1385
1386
1387 /*
1388 * uhci_leftmost_leaf:
1389 * Find the leftmost leaf in the subtree specified by the node.
1390 * Height refers to number of nodes from the bottom of the tree
1391 * to the node, including the node.
1392 */
1393 static uint_t
1394 uhci_leftmost_leaf(uint_t node, uint_t height)
1395 {
1396 node = pow_2(height + VIRTUAL_TREE_HEIGHT) * (node+1) -
1397 NUM_FRAME_LST_ENTRIES;
1398 return (node);
1399 }
1400
1401
1402 /*
1403 * uhci_insert_qh:
1404 * Add the Queue Head (QH) into the Host Controller's (HC)
1405 * appropriate queue head list.
1406 */
1407 void
1408 uhci_insert_qh(uhci_state_t *uhcip, usba_pipe_handle_data_t *ph)
1409 {
1410 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
1411
1412 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1413 "uhci_insert_qh:");
1414
1415 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1416
1417 switch (UHCI_XFER_TYPE(&ph->p_ep)) {
1418 case USB_EP_ATTR_CONTROL:
1419 uhci_insert_ctrl_qh(uhcip, pp);
1420 break;
1421 case USB_EP_ATTR_BULK:
1422 uhci_insert_bulk_qh(uhcip, pp);
1423 break;
1424 case USB_EP_ATTR_INTR:
1425 uhci_insert_intr_qh(uhcip, pp);
1426 break;
1427 case USB_EP_ATTR_ISOCH:
1428 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
1429 "uhci_insert_qh: Illegal request");
1430 break;
1431 }
1432 }
1433
1434
1435 /*
1436 * uhci_insert_ctrl_qh:
1437 * Insert a control QH into the Host Controller's (HC) control QH list.
1438 */
1439 static void
1440 uhci_insert_ctrl_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
1441 {
1442 queue_head_t *qh = pp->pp_qh;
1443
1444 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1445 "uhci_insert_ctrl_qh:");
1446
1447 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1448
1449 if (uhcip->uhci_ctrl_xfers_q_head == uhcip->uhci_ctrl_xfers_q_tail) {
1450 uhcip->uhci_ctrl_xfers_q_head->prev_qh = UHCI_INVALID_PTR;
1451 }
1452
1453 SetQH32(uhcip, qh->link_ptr,
1454 GetQH32(uhcip, uhcip->uhci_ctrl_xfers_q_tail->link_ptr));
1455 qh->prev_qh = uhcip->uhci_ctrl_xfers_q_tail;
1456 SetQH32(uhcip, uhcip->uhci_ctrl_xfers_q_tail->link_ptr,
1457 QH_PADDR(qh) | HC_QUEUE_HEAD);
1458 uhcip->uhci_ctrl_xfers_q_tail = qh;
1459
1460 }
1461
1462
1463 /*
1464 * uhci_insert_bulk_qh:
1465 * Insert a bulk QH into the Host Controller's (HC) bulk QH list.
1466 */
1467 static void
1468 uhci_insert_bulk_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
1469 {
1470 queue_head_t *qh = pp->pp_qh;
1471
1472 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1473 "uhci_insert_bulk_qh:");
1474
1475 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1476
1477 if (uhcip->uhci_bulk_xfers_q_head == uhcip->uhci_bulk_xfers_q_tail) {
1478 uhcip->uhci_bulk_xfers_q_head->prev_qh = UHCI_INVALID_PTR;
1479 } else if (uhcip->uhci_bulk_xfers_q_head->link_ptr ==
1480 uhcip->uhci_bulk_xfers_q_tail->link_ptr) {
1481
1482 /* If there is already a loop, we should keep the loop. */
1483 qh->link_ptr = uhcip->uhci_bulk_xfers_q_tail->link_ptr;
1484 }
1485
1486 qh->prev_qh = uhcip->uhci_bulk_xfers_q_tail;
1487 SetQH32(uhcip, uhcip->uhci_bulk_xfers_q_tail->link_ptr,
1488 QH_PADDR(qh) | HC_QUEUE_HEAD);
1489 uhcip->uhci_bulk_xfers_q_tail = qh;
1490 }
1491
1492
1493 /*
1494 * uhci_insert_intr_qh:
1495 * Insert a periodic Queue head i.e Interrupt queue head into the
1496 * Host Controller's (HC) interrupt lattice tree.
1497 */
1498 static void
1499 uhci_insert_intr_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
1500 {
1501 uint_t node = pp->pp_node; /* The appropriate node was */
1502 /* found during the opening */
1503 /* of the pipe. */
1504 queue_head_t *qh = pp->pp_qh;
1505 queue_head_t *next_lattice_qh, *lattice_qh;
1506
1507 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1508 "uhci_insert_intr_qh:");
1509
1510 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1511
1512 /* Find the lattice queue head */
1513 lattice_qh = &uhcip->uhci_qh_pool_addr[node];
1514 next_lattice_qh =
1515 QH_VADDR(GetQH32(uhcip, lattice_qh->link_ptr) & QH_LINK_PTR_MASK);
1516
1517 next_lattice_qh->prev_qh = qh;
1518 qh->link_ptr = lattice_qh->link_ptr;
1519 qh->prev_qh = lattice_qh;
1520 SetQH32(uhcip, lattice_qh->link_ptr, QH_PADDR(qh) | HC_QUEUE_HEAD);
1521 pp->pp_data_toggle = 0;
1522 }
1523
1524
1525 /*
1526 * uhci_insert_intr_td:
1527 * Create a TD and a data buffer for an interrupt endpoint.
1528 */
1529 int
1530 uhci_insert_intr_td(
1531 uhci_state_t *uhcip,
1532 usba_pipe_handle_data_t *ph,
1533 usb_intr_req_t *req,
1534 usb_flags_t flags)
1535 {
1536 int error, pipe_dir;
1537 uint_t length, mps;
1538 uint32_t buf_offs;
1539 uhci_td_t *tmp_td;
1540 usb_intr_req_t *intr_reqp;
1541 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
1542 uhci_trans_wrapper_t *tw;
1543
1544 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1545 "uhci_insert_intr_td: req: 0x%p", (void *)req);
1546
1547 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1548
1549 /* Get the interrupt pipe direction */
1550 pipe_dir = UHCI_XFER_DIR(&ph->p_ep);
1551
1552 /* Get the current interrupt request pointer */
1553 if (req) {
1554 length = req->intr_len;
1555 } else {
1556 ASSERT(pipe_dir == USB_EP_DIR_IN);
1557 length = (pp->pp_client_periodic_in_reqp) ?
1558 (((usb_intr_req_t *)pp->
1559 pp_client_periodic_in_reqp)->intr_len) :
1560 ph->p_ep.wMaxPacketSize;
1561 }
1562
1563 /* Check the size of interrupt request */
1564 if (length > UHCI_MAX_TD_XFER_SIZE) {
1565
1566 /* the length shouldn't exceed 8K */
1567 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1568 "uhci_insert_intr_td: Intr request size 0x%x is "
1569 "more than 0x%x", length, UHCI_MAX_TD_XFER_SIZE);
1570
1571 return (USB_INVALID_REQUEST);
1572 }
1573
1574 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1575 "uhci_insert_intr_td: length: 0x%x", length);
1576
1577 /* Allocate a transaction wrapper */
1578 if ((tw = uhci_create_transfer_wrapper(uhcip, pp, length, flags)) ==
1579 NULL) {
1580
1581 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1582 "uhci_insert_intr_td: TW allocation failed");
1583
1584 return (USB_NO_RESOURCES);
1585 }
1586
1587 /*
1588 * Initialize the callback and any callback
1589 * data for when the td completes.
1590 */
1591 tw->tw_handle_td = uhci_handle_intr_td;
1592 tw->tw_handle_callback_value = NULL;
1593 tw->tw_direction = (pipe_dir == USB_EP_DIR_OUT) ?
1594 PID_OUT : PID_IN;
1595 tw->tw_curr_xfer_reqp = (usb_opaque_t)req;
1596
1597 /*
1598 * If it is an Interrupt IN request and interrupt request is NULL,
1599 * allocate the usb interrupt request structure for the current
1600 * interrupt polling request.
1601 */
1602 if (tw->tw_direction == PID_IN) {
1603 if ((error = uhci_allocate_periodic_in_resource(uhcip,
1604 pp, tw, flags)) != USB_SUCCESS) {
1605 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1606 "uhci_insert_intr_td: Interrupt request structure "
1607 "allocation failed");
1608
1609 /* free the transfer wrapper */
1610 uhci_deallocate_tw(uhcip, pp, tw);
1611
1612 return (error);
1613 }
1614 }
1615
1616 intr_reqp = (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1617 ASSERT(tw->tw_curr_xfer_reqp != NULL);
1618
1619 tw->tw_timeout_cnt = (intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) ?
1620 intr_reqp->intr_timeout : 0;
1621
1622 /* DATA IN */
1623 if (tw->tw_direction == PID_IN) {
1624 /* Insert the td onto the queue head */
1625 error = uhci_insert_hc_td(uhcip, 0,
1626 length, pp, tw, PID_IN, intr_reqp->intr_attributes);
1627
1628 if (error != USB_SUCCESS) {
1629
1630 uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
1631 /* free the transfer wrapper */
1632 uhci_deallocate_tw(uhcip, pp, tw);
1633
1634 return (USB_NO_RESOURCES);
1635 }
1636 tw->tw_bytes_xfered = 0;
1637
1638 return (USB_SUCCESS);
1639 }
1640
1641 if (req->intr_len) {
1642 /* DATA OUT */
1643 ASSERT(req->intr_data != NULL);
1644
1645 /* Copy the data into the message */
1646 ddi_rep_put8(tw->tw_accesshandle, req->intr_data->b_rptr,
1647 (uint8_t *)tw->tw_buf, req->intr_len, DDI_DEV_AUTOINCR);
1648 }
1649
1650 /* set tw->tw_claim flag, so that nobody else works on this tw. */
1651 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
1652
1653 mps = ph->p_ep.wMaxPacketSize;
1654 buf_offs = 0;
1655
1656 /* Insert tds onto the queue head */
1657 while (length > 0) {
1658
1659 error = uhci_insert_hc_td(uhcip, buf_offs,
1660 (length > mps) ? mps : length,
1661 pp, tw, PID_OUT,
1662 intr_reqp->intr_attributes);
1663
1664 if (error != USB_SUCCESS) {
1665 /* no resource. */
1666 break;
1667 }
1668
1669 if (length <= mps) {
1670 /* inserted all data. */
1671 length = 0;
1672
1673 } else {
1674
1675 buf_offs += mps;
1676 length -= mps;
1677 }
1678 }
1679
1680 if (error != USB_SUCCESS) {
1681
1682 USB_DPRINTF_L2(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
1683 "uhci_insert_intr_td: allocate td failed, free resource");
1684
1685 /* remove all the tds */
1686 while (tw->tw_hctd_head != NULL) {
1687 uhci_delete_td(uhcip, tw->tw_hctd_head);
1688 }
1689
1690 tw->tw_claim = UHCI_NOT_CLAIMED;
1691 uhci_deallocate_tw(uhcip, pp, tw);
1692
1693 return (error);
1694 }
1695
1696 /* allow HC to xfer the tds of this tw */
1697 tmp_td = tw->tw_hctd_head;
1698 while (tmp_td != NULL) {
1699
1700 SetTD_status(uhcip, tmp_td, UHCI_TD_ACTIVE);
1701 tmp_td = tmp_td->tw_td_next;
1702 }
1703
1704 tw->tw_bytes_xfered = 0;
1705 tw->tw_claim = UHCI_NOT_CLAIMED;
1706
1707 return (error);
1708 }
1709
1710
1711 /*
1712 * uhci_create_transfer_wrapper:
1713 * Create a Transaction Wrapper (TW) for non-isoc transfer types.
1714 * This involves the allocating of DMA resources.
1715 *
1716 * For non-isoc transfers, one DMA handle and one DMA buffer are
1717 * allocated per transfer. The DMA buffer may contain multiple
1718 * DMA cookies and the cookies should meet certain alignment
1719 * requirement to be able to fit in the multiple TDs. The alignment
1720 * needs to ensure:
1721 * 1. the size of a cookie be larger than max TD length (0x500)
1722 * 2. the size of a cookie be a multiple of wMaxPacketSize of the
1723 * ctrl/bulk pipes
1724 *
1725 * wMaxPacketSize for ctrl and bulk pipes may be 8, 16, 32 or 64 bytes.
1726 * So the alignment should be a multiple of 64. wMaxPacketSize for intr
1727 * pipes is a little different since it only specifies the max to be
1728 * 64 bytes, but as long as an intr transfer is limited to max TD length,
1729 * any alignment can work if the cookie size is larger than max TD length.
1730 *
1731 * Considering the above conditions, 2K alignment is used. 4K alignment
1732 * should also be fine.
1733 */
1734 static uhci_trans_wrapper_t *
1735 uhci_create_transfer_wrapper(
1736 uhci_state_t *uhcip,
1737 uhci_pipe_private_t *pp,
1738 size_t length,
1739 usb_flags_t usb_flags)
1740 {
1741 size_t real_length;
1742 uhci_trans_wrapper_t *tw;
1743 ddi_device_acc_attr_t dev_attr;
1744 ddi_dma_attr_t dma_attr;
1745 int kmem_flag;
1746 int (*dmamem_wait)(caddr_t);
1747 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
1748
1749 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1750 "uhci_create_transfer_wrapper: length = 0x%lx flags = 0x%x",
1751 length, usb_flags);
1752
1753 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1754
1755 /* isochronous pipe should not call into this function */
1756 if (UHCI_XFER_TYPE(&ph->p_ep) == USB_EP_ATTR_ISOCH) {
1757
1758 return (NULL);
1759 }
1760
1761 /* SLEEP flag should not be used while holding mutex */
1762 kmem_flag = KM_NOSLEEP;
1763 dmamem_wait = DDI_DMA_DONTWAIT;
1764
1765 /* Allocate space for the transfer wrapper */
1766 if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), kmem_flag)) ==
1767 NULL) {
1768 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1769 "uhci_create_transfer_wrapper: kmem_alloc failed");
1770
1771 return (NULL);
1772 }
1773
1774 /* zero-length packet doesn't need to allocate dma memory */
1775 if (length == 0) {
1776
1777 goto dmadone;
1778 }
1779
1780 /* allow sg lists for transfer wrapper dma memory */
1781 bcopy(&uhcip->uhci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
1782 dma_attr.dma_attr_sgllen = UHCI_DMA_ATTR_SGLLEN;
1783 dma_attr.dma_attr_align = UHCI_DMA_ATTR_ALIGN;
1784
1785 /* Store the transfer length */
1786 tw->tw_length = length;
1787
1788 /* Allocate the DMA handle */
1789 if (ddi_dma_alloc_handle(uhcip->uhci_dip, &dma_attr, dmamem_wait,
1790 0, &tw->tw_dmahandle) != DDI_SUCCESS) {
1791 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1792 "uhci_create_transfer_wrapper: Alloc handle failed");
1793 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
1794
1795 return (NULL);
1796 }
1797
1798 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1799 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
1800 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1801
1802 /* Allocate the memory */
1803 if (ddi_dma_mem_alloc(tw->tw_dmahandle, tw->tw_length, &dev_attr,
1804 DDI_DMA_CONSISTENT, dmamem_wait, NULL, (caddr_t *)&tw->tw_buf,
1805 &real_length, &tw->tw_accesshandle) != DDI_SUCCESS) {
1806 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1807 "uhci_create_transfer_wrapper: dma_mem_alloc fail");
1808 ddi_dma_free_handle(&tw->tw_dmahandle);
1809 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
1810
1811 return (NULL);
1812 }
1813
1814 ASSERT(real_length >= length);
1815
1816 /* Bind the handle */
1817 if (ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL,
1818 (caddr_t)tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
1819 dmamem_wait, NULL, &tw->tw_cookie, &tw->tw_ncookies) !=
1820 DDI_DMA_MAPPED) {
1821 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1822 "uhci_create_transfer_wrapper: Bind handle failed");
1823 ddi_dma_mem_free(&tw->tw_accesshandle);
1824 ddi_dma_free_handle(&tw->tw_dmahandle);
1825 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
1826
1827 return (NULL);
1828 }
1829
1830 tw->tw_cookie_idx = 0;
1831 tw->tw_dma_offs = 0;
1832
1833 dmadone:
1834 /*
1835 * Only allow one wrapper to be added at a time. Insert the
1836 * new transaction wrapper into the list for this pipe.
1837 */
1838 if (pp->pp_tw_head == NULL) {
1839 pp->pp_tw_head = tw;
1840 pp->pp_tw_tail = tw;
1841 } else {
1842 pp->pp_tw_tail->tw_next = tw;
1843 pp->pp_tw_tail = tw;
1844 ASSERT(tw->tw_next == NULL);
1845 }
1846
1847 /* Store a back pointer to the pipe private structure */
1848 tw->tw_pipe_private = pp;
1849
1850 /* Store the transfer type - synchronous or asynchronous */
1851 tw->tw_flags = usb_flags;
1852
1853 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1854 "uhci_create_transfer_wrapper: tw = 0x%p, ncookies = %u",
1855 (void *)tw, tw->tw_ncookies);
1856
1857 return (tw);
1858 }
1859
1860
1861 /*
1862 * uhci_insert_hc_td:
1863 * Insert a Transfer Descriptor (TD) on an QH.
1864 */
1865 int
1866 uhci_insert_hc_td(
1867 uhci_state_t *uhcip,
1868 uint32_t buffer_offset,
1869 size_t hcgtd_length,
1870 uhci_pipe_private_t *pp,
1871 uhci_trans_wrapper_t *tw,
1872 uchar_t PID,
1873 usb_req_attrs_t attrs)
1874 {
1875 uhci_td_t *td, *current_dummy;
1876 queue_head_t *qh = pp->pp_qh;
1877
1878 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1879
1880 if ((td = uhci_allocate_td_from_pool(uhcip)) == NULL) {
1881
1882 return (USB_NO_RESOURCES);
1883 }
1884
1885 current_dummy = qh->td_tailp;
1886
1887 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
1888 "uhci_insert_hc_td: td %p, attrs = 0x%x", (void *)td, attrs);
1889
1890 /*
1891 * Fill in the current dummy td and
1892 * add the new dummy to the end.
1893 */
1894 uhci_fill_in_td(uhcip, td, current_dummy, buffer_offset,
1895 hcgtd_length, pp, PID, attrs, tw);
1896
1897 /*
1898 * Allow HC hardware xfer the td, except interrupt out td.
1899 */
1900 if ((tw->tw_handle_td != uhci_handle_intr_td) || (PID != PID_OUT)) {
1901
1902 SetTD_status(uhcip, current_dummy, UHCI_TD_ACTIVE);
1903 }
1904
1905 /* Insert this td onto the tw */
1906
1907 if (tw->tw_hctd_head == NULL) {
1908 ASSERT(tw->tw_hctd_tail == NULL);
1909 tw->tw_hctd_head = current_dummy;
1910 tw->tw_hctd_tail = current_dummy;
1911 } else {
1912 /* Add the td to the end of the list */
1913 tw->tw_hctd_tail->tw_td_next = current_dummy;
1914 tw->tw_hctd_tail = current_dummy;
1915 }
1916
1917 /*
1918 * Insert the TD on to the QH. When this occurs,
1919 * the Host Controller will see the newly filled in TD
1920 */
1921 current_dummy->outst_td_next = NULL;
1922 current_dummy->outst_td_prev = uhcip->uhci_outst_tds_tail;
1923 if (uhcip->uhci_outst_tds_head == NULL) {
1924 uhcip->uhci_outst_tds_head = current_dummy;
1925 } else {
1926 uhcip->uhci_outst_tds_tail->outst_td_next = current_dummy;
1927 }
1928 uhcip->uhci_outst_tds_tail = current_dummy;
1929 current_dummy->tw = tw;
1930
1931 return (USB_SUCCESS);
1932 }
1933
1934
1935 /*
1936 * uhci_fill_in_td:
1937 * Fill in the fields of a Transfer Descriptor (TD).
1938 */
1939 static void
1940 uhci_fill_in_td(
1941 uhci_state_t *uhcip,
1942 uhci_td_t *td,
1943 uhci_td_t *current_dummy,
1944 uint32_t buffer_offset,
1945 size_t length,
1946 uhci_pipe_private_t *pp,
1947 uchar_t PID,
1948 usb_req_attrs_t attrs,
1949 uhci_trans_wrapper_t *tw)
1950 {
1951 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
1952 uint32_t buf_addr;
1953
1954 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
1955 "uhci_fill_in_td: td 0x%p buf_offs 0x%x len 0x%lx "
1956 "attrs 0x%x", (void *)td, buffer_offset, length, attrs);
1957
1958 /*
1959 * If this is an isochronous TD, just return
1960 */
1961 if (UHCI_XFER_TYPE(&ph->p_ep) == USB_EP_ATTR_ISOCH) {
1962
1963 return;
1964 }
1965
1966 /* The maximum transfer length of UHCI cannot exceed 0x500 bytes */
1967 ASSERT(length <= UHCI_MAX_TD_XFER_SIZE);
1968
1969 bzero((char *)td, sizeof (uhci_td_t)); /* Clear the TD */
1970 SetTD32(uhcip, current_dummy->link_ptr, TD_PADDR(td));
1971
1972 if (attrs & USB_ATTRS_SHORT_XFER_OK) {
1973 SetTD_spd(uhcip, current_dummy, 1);
1974 }
1975
1976 mutex_enter(&ph->p_usba_device->usb_mutex);
1977 if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
1978 SetTD_ls(uhcip, current_dummy, LOW_SPEED_DEVICE);
1979 }
1980
1981 SetTD_c_err(uhcip, current_dummy, UHCI_MAX_ERR_COUNT);
1982 SetTD_mlen(uhcip, current_dummy,
1983 (length == 0) ? ZERO_LENGTH : (length - 1));
1984 SetTD_dtogg(uhcip, current_dummy, pp->pp_data_toggle);
1985
1986 /* Adjust the data toggle bit */
1987 ADJ_DATA_TOGGLE(pp);
1988
1989 SetTD_devaddr(uhcip, current_dummy, ph->p_usba_device->usb_addr);
1990 SetTD_endpt(uhcip, current_dummy,
1991 ph->p_ep.bEndpointAddress & END_POINT_ADDRESS_MASK);
1992 SetTD_PID(uhcip, current_dummy, PID);
1993 SetTD_ioc(uhcip, current_dummy, INTERRUPT_ON_COMPLETION);
1994
1995 buf_addr = uhci_get_tw_paddr_by_offs(uhcip, buffer_offset, length, tw);
1996 SetTD32(uhcip, current_dummy->buffer_address, buf_addr);
1997
1998 td->qh_td_prev = current_dummy;
1999 current_dummy->qh_td_prev = NULL;
2000 pp->pp_qh->td_tailp = td;
2001 mutex_exit(&ph->p_usba_device->usb_mutex);
2002 }
2003
2004 /*
2005 * uhci_get_tw_paddr_by_offs:
2006 * Walk through the DMA cookies of a TW buffer to retrieve
2007 * the device address used for a TD.
2008 *
2009 * buffer_offset - the starting offset into the TW buffer, where the
2010 * TD should transfer from. When a TW has more than
2011 * one TD, the TDs must be filled in increasing order.
2012 */
2013 static uint32_t
2014 uhci_get_tw_paddr_by_offs(
2015 uhci_state_t *uhcip,
2016 uint32_t buffer_offset,
2017 size_t length,
2018 uhci_trans_wrapper_t *tw)
2019 {
2020 uint32_t buf_addr;
2021 int rem_len;
2022
2023 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2024 "uhci_get_tw_paddr_by_offs: buf_offs 0x%x len 0x%lx",
2025 buffer_offset, length);
2026
2027 /*
2028 * TDs must be filled in increasing DMA offset order.
2029 * tw_dma_offs is initialized to be 0 at TW creation and
2030 * is only increased in this function.
2031 */
2032 ASSERT(length == 0 || buffer_offset >= tw->tw_dma_offs);
2033
2034 if (length == 0) {
2035 buf_addr = 0;
2036
2037 return (buf_addr);
2038 }
2039
2040 /*
2041 * Advance to the next DMA cookie until finding the cookie
2042 * that buffer_offset falls in.
2043 * It is very likely this loop will never repeat more than
2044 * once. It is here just to accommodate the case buffer_offset
2045 * is increased by multiple cookies during two consecutive
2046 * calls into this function. In that case, the interim DMA
2047 * buffer is allowed to be skipped.
2048 */
2049 while ((tw->tw_dma_offs + tw->tw_cookie.dmac_size) <=
2050 buffer_offset) {
2051 /*
2052 * tw_dma_offs always points to the starting offset
2053 * of a cookie
2054 */
2055 tw->tw_dma_offs += tw->tw_cookie.dmac_size;
2056 ddi_dma_nextcookie(tw->tw_dmahandle, &tw->tw_cookie);
2057 tw->tw_cookie_idx++;
2058 ASSERT(tw->tw_cookie_idx < tw->tw_ncookies);
2059 }
2060
2061 /*
2062 * Counting the remained buffer length to be filled in
2063 * the TDs for current DMA cookie
2064 */
2065 rem_len = (tw->tw_dma_offs + tw->tw_cookie.dmac_size) -
2066 buffer_offset;
2067
2068 /* Calculate the beginning address of the buffer */
2069 ASSERT(length <= rem_len);
2070 buf_addr = (buffer_offset - tw->tw_dma_offs) +
2071 tw->tw_cookie.dmac_address;
2072
2073 USB_DPRINTF_L3(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2074 "uhci_get_tw_paddr_by_offs: dmac_addr 0x%x dmac_size "
2075 "0x%lx idx %d", buf_addr, tw->tw_cookie.dmac_size,
2076 tw->tw_cookie_idx);
2077
2078 return (buf_addr);
2079 }
2080
2081
2082 /*
2083 * uhci_modify_td_active_bits:
2084 * Sets active bit in all the tds of QH to INACTIVE so that
2085 * the HC stops processing the TD's related to the QH.
2086 */
2087 void
2088 uhci_modify_td_active_bits(
2089 uhci_state_t *uhcip,
2090 uhci_pipe_private_t *pp)
2091 {
2092 uhci_td_t *td_head;
2093 usb_ep_descr_t *ept = &pp->pp_pipe_handle->p_ep;
2094 uhci_trans_wrapper_t *tw_head = pp->pp_tw_head;
2095
2096 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2097 "uhci_modify_td_active_bits: tw head %p", (void *)tw_head);
2098
2099 while (tw_head != NULL) {
2100 tw_head->tw_claim = UHCI_MODIFY_TD_BITS_CLAIMED;
2101 td_head = tw_head->tw_hctd_head;
2102
2103 while (td_head) {
2104 if (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_ISOCH) {
2105 SetTD_status(uhcip, td_head,
2106 GetTD_status(uhcip, td_head) & TD_INACTIVE);
2107 } else {
2108 SetTD32(uhcip, td_head->link_ptr,
2109 GetTD32(uhcip, td_head->link_ptr) |
2110 HC_END_OF_LIST);
2111 }
2112
2113 td_head = td_head->tw_td_next;
2114 }
2115 tw_head = tw_head->tw_next;
2116 }
2117 }
2118
2119
2120 /*
2121 * uhci_insert_ctrl_td:
2122 * Create a TD and a data buffer for a control Queue Head.
2123 */
2124 int
2125 uhci_insert_ctrl_td(
2126 uhci_state_t *uhcip,
2127 usba_pipe_handle_data_t *ph,
2128 usb_ctrl_req_t *ctrl_reqp,
2129 usb_flags_t flags)
2130 {
2131 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2132 uhci_trans_wrapper_t *tw;
2133 size_t ctrl_buf_size;
2134
2135 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2136 "uhci_insert_ctrl_td: timeout: 0x%x", ctrl_reqp->ctrl_timeout);
2137
2138 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2139
2140 /*
2141 * If we have a control data phase, make the data buffer start
2142 * on the next 64-byte boundary so as to ensure the DMA cookie
2143 * can fit in the multiple TDs. The buffer in the range of
2144 * [SETUP_SIZE, UHCI_CTRL_EPT_MAX_SIZE) is just for padding
2145 * and not to be transferred.
2146 */
2147 if (ctrl_reqp->ctrl_wLength) {
2148 ctrl_buf_size = UHCI_CTRL_EPT_MAX_SIZE +
2149 ctrl_reqp->ctrl_wLength;
2150 } else {
2151 ctrl_buf_size = SETUP_SIZE;
2152 }
2153
2154 /* Allocate a transaction wrapper */
2155 if ((tw = uhci_create_transfer_wrapper(uhcip, pp,
2156 ctrl_buf_size, flags)) == NULL) {
2157 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2158 "uhci_insert_ctrl_td: TW allocation failed");
2159
2160 return (USB_NO_RESOURCES);
2161 }
2162
2163 pp->pp_data_toggle = 0;
2164
2165 tw->tw_curr_xfer_reqp = (usb_opaque_t)ctrl_reqp;
2166 tw->tw_bytes_xfered = 0;
2167 tw->tw_bytes_pending = ctrl_reqp->ctrl_wLength;
2168 tw->tw_timeout_cnt = max(UHCI_CTRL_TIMEOUT, ctrl_reqp->ctrl_timeout);
2169
2170 /*
2171 * Initialize the callback and any callback
2172 * data for when the td completes.
2173 */
2174 tw->tw_handle_td = uhci_handle_ctrl_td;
2175 tw->tw_handle_callback_value = NULL;
2176
2177 if ((uhci_create_setup_pkt(uhcip, pp, tw)) != USB_SUCCESS) {
2178 tw->tw_ctrl_state = 0;
2179
2180 /* free the transfer wrapper */
2181 uhci_deallocate_tw(uhcip, pp, tw);
2182
2183 return (USB_NO_RESOURCES);
2184 }
2185
2186 tw->tw_ctrl_state = SETUP;
2187
2188 return (USB_SUCCESS);
2189 }
2190
2191
2192 /*
2193 * uhci_create_setup_pkt:
2194 * create a setup packet to initiate a control transfer.
2195 *
2196 * OHCI driver has seen the case where devices fail if there is
2197 * more than one control transfer to the device within a frame.
2198 * So, the UHCI ensures that only one TD will be put on the control
2199 * pipe to one device (to be consistent with OHCI driver).
2200 */
2201 static int
2202 uhci_create_setup_pkt(
2203 uhci_state_t *uhcip,
2204 uhci_pipe_private_t *pp,
2205 uhci_trans_wrapper_t *tw)
2206 {
2207 int sdata;
2208 usb_ctrl_req_t *req = (usb_ctrl_req_t *)tw->tw_curr_xfer_reqp;
2209
2210 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2211 "uhci_create_setup_pkt: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%p",
2212 req->ctrl_bmRequestType, req->ctrl_bRequest, req->ctrl_wValue,
2213 req->ctrl_wIndex, req->ctrl_wLength, (void *)req->ctrl_data);
2214
2215 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2216 ASSERT(tw != NULL);
2217
2218 /* Create the first four bytes of the setup packet */
2219 sdata = (req->ctrl_bmRequestType | (req->ctrl_bRequest << 8) |
2220 (req->ctrl_wValue << 16));
2221 ddi_put32(tw->tw_accesshandle, (uint_t *)tw->tw_buf, sdata);
2222
2223 /* Create the second four bytes */
2224 sdata = (uint32_t)(req->ctrl_wIndex | (req->ctrl_wLength << 16));
2225 ddi_put32(tw->tw_accesshandle,
2226 (uint_t *)(tw->tw_buf + sizeof (uint_t)), sdata);
2227
2228 /*
2229 * The TD's are placed on the QH one at a time.
2230 * Once this TD is placed on the done list, the
2231 * data or status phase TD will be enqueued.
2232 */
2233 if ((uhci_insert_hc_td(uhcip, 0, SETUP_SIZE,
2234 pp, tw, PID_SETUP, req->ctrl_attributes)) != USB_SUCCESS) {
2235
2236 return (USB_NO_RESOURCES);
2237 }
2238
2239 USB_DPRINTF_L3(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2240 "Create_setup: pp = 0x%p, attrs = 0x%x", (void *)pp,
2241 req->ctrl_attributes);
2242
2243 /*
2244 * If this control transfer has a data phase, record the
2245 * direction. If the data phase is an OUT transaction ,
2246 * copy the data into the buffer of the transfer wrapper.
2247 */
2248 if (req->ctrl_wLength != 0) {
2249 /* There is a data stage. Find the direction */
2250 if (req->ctrl_bmRequestType & USB_DEV_REQ_DEV_TO_HOST) {
2251 tw->tw_direction = PID_IN;
2252 } else {
2253 tw->tw_direction = PID_OUT;
2254
2255 /* Copy the data into the buffer */
2256 ddi_rep_put8(tw->tw_accesshandle,
2257 req->ctrl_data->b_rptr,
2258 (uint8_t *)(tw->tw_buf + UHCI_CTRL_EPT_MAX_SIZE),
2259 req->ctrl_wLength,
2260 DDI_DEV_AUTOINCR);
2261 }
2262 }
2263
2264 return (USB_SUCCESS);
2265 }
2266
2267
2268 /*
2269 * uhci_create_stats:
2270 * Allocate and initialize the uhci kstat structures
2271 */
2272 void
2273 uhci_create_stats(uhci_state_t *uhcip)
2274 {
2275 int i;
2276 char kstatname[KSTAT_STRLEN];
2277 char *usbtypes[USB_N_COUNT_KSTATS] =
2278 {"ctrl", "isoch", "bulk", "intr"};
2279 uint_t instance = uhcip->uhci_instance;
2280 const char *dname = ddi_driver_name(uhcip->uhci_dip);
2281 uhci_intrs_stats_t *isp;
2282
2283 if (UHCI_INTRS_STATS(uhcip) == NULL) {
2284 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,intrs",
2285 dname, instance);
2286 UHCI_INTRS_STATS(uhcip) = kstat_create("usba", instance,
2287 kstatname, "usb_interrupts", KSTAT_TYPE_NAMED,
2288 sizeof (uhci_intrs_stats_t) / sizeof (kstat_named_t),
2289 KSTAT_FLAG_PERSISTENT);
2290
2291 if (UHCI_INTRS_STATS(uhcip) != NULL) {
2292 isp = UHCI_INTRS_STATS_DATA(uhcip);
2293 kstat_named_init(&isp->uhci_intrs_hc_halted,
2294 "HC Halted", KSTAT_DATA_UINT64);
2295 kstat_named_init(&isp->uhci_intrs_hc_process_err,
2296 "HC Process Errors", KSTAT_DATA_UINT64);
2297 kstat_named_init(&isp->uhci_intrs_host_sys_err,
2298 "Host Sys Errors", KSTAT_DATA_UINT64);
2299 kstat_named_init(&isp->uhci_intrs_resume_detected,
2300 "Resume Detected", KSTAT_DATA_UINT64);
2301 kstat_named_init(&isp->uhci_intrs_usb_err_intr,
2302 "USB Error", KSTAT_DATA_UINT64);
2303 kstat_named_init(&isp->uhci_intrs_usb_intr,
2304 "USB Interrupts", KSTAT_DATA_UINT64);
2305 kstat_named_init(&isp->uhci_intrs_total,
2306 "Total Interrupts", KSTAT_DATA_UINT64);
2307 kstat_named_init(&isp->uhci_intrs_not_claimed,
2308 "Not Claimed", KSTAT_DATA_UINT64);
2309
2310 UHCI_INTRS_STATS(uhcip)->ks_private = uhcip;
2311 UHCI_INTRS_STATS(uhcip)->ks_update = nulldev;
2312 kstat_install(UHCI_INTRS_STATS(uhcip));
2313 }
2314 }
2315
2316 if (UHCI_TOTAL_STATS(uhcip) == NULL) {
2317 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,total",
2318 dname, instance);
2319 UHCI_TOTAL_STATS(uhcip) = kstat_create("usba", instance,
2320 kstatname, "usb_byte_count", KSTAT_TYPE_IO, 1,
2321 KSTAT_FLAG_PERSISTENT);
2322
2323 if (UHCI_TOTAL_STATS(uhcip) != NULL) {
2324 kstat_install(UHCI_TOTAL_STATS(uhcip));
2325 }
2326 }
2327
2328 for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
2329 if (uhcip->uhci_count_stats[i] == NULL) {
2330 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,%s",
2331 dname, instance, usbtypes[i]);
2332 uhcip->uhci_count_stats[i] = kstat_create("usba",
2333 instance, kstatname, "usb_byte_count",
2334 KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
2335
2336 if (uhcip->uhci_count_stats[i] != NULL) {
2337 kstat_install(uhcip->uhci_count_stats[i]);
2338 }
2339 }
2340 }
2341 }
2342
2343
2344 /*
2345 * uhci_destroy_stats:
2346 * Clean up uhci kstat structures
2347 */
2348 void
2349 uhci_destroy_stats(uhci_state_t *uhcip)
2350 {
2351 int i;
2352
2353 if (UHCI_INTRS_STATS(uhcip)) {
2354 kstat_delete(UHCI_INTRS_STATS(uhcip));
2355 UHCI_INTRS_STATS(uhcip) = NULL;
2356 }
2357
2358 if (UHCI_TOTAL_STATS(uhcip)) {
2359 kstat_delete(UHCI_TOTAL_STATS(uhcip));
2360 UHCI_TOTAL_STATS(uhcip) = NULL;
2361 }
2362
2363 for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
2364 if (uhcip->uhci_count_stats[i]) {
2365 kstat_delete(uhcip->uhci_count_stats[i]);
2366 uhcip->uhci_count_stats[i] = NULL;
2367 }
2368 }
2369 }
2370
2371
2372 void
2373 uhci_do_intrs_stats(uhci_state_t *uhcip, int val)
2374 {
2375 if (UHCI_INTRS_STATS(uhcip) == NULL) {
2376
2377 return;
2378 }
2379
2380 UHCI_INTRS_STATS_DATA(uhcip)->uhci_intrs_total.value.ui64++;
2381 switch (val) {
2382 case USBSTS_REG_HC_HALTED:
2383 UHCI_INTRS_STATS_DATA(uhcip)->uhci_intrs_hc_halted.value.ui64++;
2384 break;
2385 case USBSTS_REG_HC_PROCESS_ERR:
2386 UHCI_INTRS_STATS_DATA(uhcip)->
2387 uhci_intrs_hc_process_err.value.ui64++;
2388 break;
2389 case USBSTS_REG_HOST_SYS_ERR:
2390 UHCI_INTRS_STATS_DATA(uhcip)->
2391 uhci_intrs_host_sys_err.value.ui64++;
2392 break;
2393 case USBSTS_REG_RESUME_DETECT:
2394 UHCI_INTRS_STATS_DATA(uhcip)->
2395 uhci_intrs_resume_detected.value.ui64++;
2396 break;
2397 case USBSTS_REG_USB_ERR_INTR:
2398 UHCI_INTRS_STATS_DATA(uhcip)->
2399 uhci_intrs_usb_err_intr.value.ui64++;
2400 break;
2401 case USBSTS_REG_USB_INTR:
2402 UHCI_INTRS_STATS_DATA(uhcip)->uhci_intrs_usb_intr.value.ui64++;
2403 break;
2404 default:
2405 UHCI_INTRS_STATS_DATA(uhcip)->
2406 uhci_intrs_not_claimed.value.ui64++;
2407 break;
2408 }
2409 }
2410
2411
2412 void
2413 uhci_do_byte_stats(uhci_state_t *uhcip, size_t len, uint8_t attr, uint8_t addr)
2414 {
2415 uint8_t type = attr & USB_EP_ATTR_MASK;
2416 uint8_t dir = addr & USB_EP_DIR_MASK;
2417
2418 switch (dir) {
2419 case USB_EP_DIR_IN:
2420 UHCI_TOTAL_STATS_DATA(uhcip)->reads++;
2421 UHCI_TOTAL_STATS_DATA(uhcip)->nread += len;
2422 switch (type) {
2423 case USB_EP_ATTR_CONTROL:
2424 UHCI_CTRL_STATS(uhcip)->reads++;
2425 UHCI_CTRL_STATS(uhcip)->nread += len;
2426 break;
2427 case USB_EP_ATTR_BULK:
2428 UHCI_BULK_STATS(uhcip)->reads++;
2429 UHCI_BULK_STATS(uhcip)->nread += len;
2430 break;
2431 case USB_EP_ATTR_INTR:
2432 UHCI_INTR_STATS(uhcip)->reads++;
2433 UHCI_INTR_STATS(uhcip)->nread += len;
2434 break;
2435 case USB_EP_ATTR_ISOCH:
2436 UHCI_ISOC_STATS(uhcip)->reads++;
2437 UHCI_ISOC_STATS(uhcip)->nread += len;
2438 break;
2439 }
2440 break;
2441 case USB_EP_DIR_OUT:
2442 UHCI_TOTAL_STATS_DATA(uhcip)->writes++;
2443 UHCI_TOTAL_STATS_DATA(uhcip)->nwritten += len;
2444 switch (type) {
2445 case USB_EP_ATTR_CONTROL:
2446 UHCI_CTRL_STATS(uhcip)->writes++;
2447 UHCI_CTRL_STATS(uhcip)->nwritten += len;
2448 break;
2449 case USB_EP_ATTR_BULK:
2450 UHCI_BULK_STATS(uhcip)->writes++;
2451 UHCI_BULK_STATS(uhcip)->nwritten += len;
2452 break;
2453 case USB_EP_ATTR_INTR:
2454 UHCI_INTR_STATS(uhcip)->writes++;
2455 UHCI_INTR_STATS(uhcip)->nwritten += len;
2456 break;
2457 case USB_EP_ATTR_ISOCH:
2458 UHCI_ISOC_STATS(uhcip)->writes++;
2459 UHCI_ISOC_STATS(uhcip)->nwritten += len;
2460 break;
2461 }
2462 break;
2463 }
2464 }
2465
2466
2467 /*
2468 * uhci_free_tw:
2469 * Free the Transfer Wrapper (TW).
2470 */
2471 void
2472 uhci_free_tw(uhci_state_t *uhcip, uhci_trans_wrapper_t *tw)
2473 {
2474 int rval, i;
2475
2476 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl, "uhci_free_tw:");
2477
2478 ASSERT(tw != NULL);
2479
2480 if (tw->tw_isoc_strtlen > 0) {
2481 ASSERT(tw->tw_isoc_bufs != NULL);
2482 for (i = 0; i < tw->tw_ncookies; i++) {
2483 rval = ddi_dma_unbind_handle(
2484 tw->tw_isoc_bufs[i].dma_handle);
2485 ASSERT(rval == USB_SUCCESS);
2486 ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
2487 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
2488 }
2489 kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
2490 } else if (tw->tw_dmahandle != NULL) {
2491 rval = ddi_dma_unbind_handle(tw->tw_dmahandle);
2492 ASSERT(rval == DDI_SUCCESS);
2493
2494 ddi_dma_mem_free(&tw->tw_accesshandle);
2495 ddi_dma_free_handle(&tw->tw_dmahandle);
2496 }
2497
2498 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
2499 }
2500
2501
2502 /*
2503 * uhci_deallocate_tw:
2504 * Deallocate of a Transaction Wrapper (TW) and this involves
2505 * the freeing of DMA resources.
2506 */
2507 void
2508 uhci_deallocate_tw(uhci_state_t *uhcip,
2509 uhci_pipe_private_t *pp, uhci_trans_wrapper_t *tw)
2510 {
2511 uhci_trans_wrapper_t *head;
2512
2513 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2514 "uhci_deallocate_tw:");
2515
2516 /*
2517 * If the transfer wrapper has no Host Controller (HC)
2518 * Transfer Descriptors (TD) associated with it, then
2519 * remove the transfer wrapper. The transfers are done
2520 * in FIFO order, so this should be the first transfer
2521 * wrapper on the list.
2522 */
2523 if (tw->tw_hctd_head != NULL) {
2524 ASSERT(tw->tw_hctd_tail != NULL);
2525
2526 return;
2527 }
2528
2529 ASSERT(tw->tw_hctd_tail == NULL);
2530 ASSERT(pp->pp_tw_head != NULL);
2531
2532 /*
2533 * If pp->pp_tw_head is NULL, set the tail also to NULL.
2534 */
2535 head = pp->pp_tw_head;
2536
2537 if (head == tw) {
2538 pp->pp_tw_head = head->tw_next;
2539 if (pp->pp_tw_head == NULL) {
2540 pp->pp_tw_tail = NULL;
2541 }
2542 } else {
2543 while (head->tw_next != tw)
2544 head = head->tw_next;
2545 head->tw_next = tw->tw_next;
2546 if (tw->tw_next == NULL) {
2547 pp->pp_tw_tail = head;
2548 }
2549 }
2550 uhci_free_tw(uhcip, tw);
2551 }
2552
2553
2554 void
2555 uhci_delete_td(uhci_state_t *uhcip, uhci_td_t *td)
2556 {
2557 uhci_td_t *tmp_td;
2558 uhci_trans_wrapper_t *tw = td->tw;
2559
2560 if ((td->outst_td_next == NULL) && (td->outst_td_prev == NULL)) {
2561 uhcip->uhci_outst_tds_head = NULL;
2562 uhcip->uhci_outst_tds_tail = NULL;
2563 } else if (td->outst_td_next == NULL) {
2564 td->outst_td_prev->outst_td_next = NULL;
2565 uhcip->uhci_outst_tds_tail = td->outst_td_prev;
2566 } else if (td->outst_td_prev == NULL) {
2567 td->outst_td_next->outst_td_prev = NULL;
2568 uhcip->uhci_outst_tds_head = td->outst_td_next;
2569 } else {
2570 td->outst_td_prev->outst_td_next = td->outst_td_next;
2571 td->outst_td_next->outst_td_prev = td->outst_td_prev;
2572 }
2573
2574 tmp_td = tw->tw_hctd_head;
2575
2576 if (tmp_td != td) {
2577 while (tmp_td->tw_td_next != td) {
2578 tmp_td = tmp_td->tw_td_next;
2579 }
2580 ASSERT(tmp_td);
2581 tmp_td->tw_td_next = td->tw_td_next;
2582 if (td->tw_td_next == NULL) {
2583 tw->tw_hctd_tail = tmp_td;
2584 }
2585 } else {
2586 tw->tw_hctd_head = tw->tw_hctd_head->tw_td_next;
2587 if (tw->tw_hctd_head == NULL) {
2588 tw->tw_hctd_tail = NULL;
2589 }
2590 }
2591
2592 td->flag = TD_FLAG_FREE;
2593 }
2594
2595
2596 void
2597 uhci_remove_tds_tws(
2598 uhci_state_t *uhcip,
2599 usba_pipe_handle_data_t *ph)
2600 {
2601 usb_opaque_t curr_reqp;
2602 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2603 usb_ep_descr_t *ept = &pp->pp_pipe_handle->p_ep;
2604 uhci_trans_wrapper_t *tw_tmp;
2605 uhci_trans_wrapper_t *tw_head = pp->pp_tw_head;
2606
2607 while (tw_head != NULL) {
2608 tw_tmp = tw_head;
2609 tw_head = tw_head->tw_next;
2610
2611 curr_reqp = tw_tmp->tw_curr_xfer_reqp;
2612 if (curr_reqp) {
2613 /* do this for control/bulk/intr */
2614 if ((tw_tmp->tw_direction == PID_IN) &&
2615 (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_INTR)) {
2616 uhci_deallocate_periodic_in_resource(uhcip,
2617 pp, tw_tmp);
2618 } else {
2619 uhci_hcdi_callback(uhcip, pp,
2620 pp->pp_pipe_handle, tw_tmp, USB_CR_FLUSHED);
2621 }
2622 } /* end of curr_reqp */
2623
2624 if (tw_tmp->tw_claim != UHCI_MODIFY_TD_BITS_CLAIMED) {
2625 continue;
2626 }
2627
2628 while (tw_tmp->tw_hctd_head != NULL) {
2629 uhci_delete_td(uhcip, tw_tmp->tw_hctd_head);
2630 }
2631
2632 uhci_deallocate_tw(uhcip, pp, tw_tmp);
2633 }
2634 }
2635
2636
2637 /*
2638 * uhci_remove_qh:
2639 * Remove the Queue Head from the Host Controller's
2640 * appropriate QH list.
2641 */
2642 void
2643 uhci_remove_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2644 {
2645 uhci_td_t *dummy_td;
2646
2647 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2648
2649 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2650 "uhci_remove_qh:");
2651
2652 dummy_td = pp->pp_qh->td_tailp;
2653 dummy_td->flag = TD_FLAG_FREE;
2654
2655 switch (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep)) {
2656 case USB_EP_ATTR_CONTROL:
2657 uhci_remove_ctrl_qh(uhcip, pp);
2658 break;
2659 case USB_EP_ATTR_BULK:
2660 uhci_remove_bulk_qh(uhcip, pp);
2661 break;
2662 case USB_EP_ATTR_INTR:
2663 uhci_remove_intr_qh(uhcip, pp);
2664 break;
2665 }
2666 }
2667
2668
2669 static void
2670 uhci_remove_intr_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2671 {
2672 queue_head_t *qh = pp->pp_qh;
2673 queue_head_t *next_lattice_qh =
2674 QH_VADDR(GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK);
2675
2676 qh->prev_qh->link_ptr = qh->link_ptr;
2677 next_lattice_qh->prev_qh = qh->prev_qh;
2678 qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
2679
2680 }
2681
2682 /*
2683 * uhci_remove_bulk_qh:
2684 * Remove a bulk QH from the Host Controller's QH list. There may be a
2685 * loop for bulk QHs, we must care about this while removing a bulk QH.
2686 */
2687 static void
2688 uhci_remove_bulk_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2689 {
2690 queue_head_t *qh = pp->pp_qh;
2691 queue_head_t *next_lattice_qh;
2692 uint32_t paddr;
2693
2694 paddr = (GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK);
2695 next_lattice_qh = (qh == uhcip->uhci_bulk_xfers_q_tail) ?
2696 0 : QH_VADDR(paddr);
2697
2698 if ((qh == uhcip->uhci_bulk_xfers_q_tail) &&
2699 (qh->prev_qh == uhcip->uhci_bulk_xfers_q_head)) {
2700 SetQH32(uhcip, qh->prev_qh->link_ptr, HC_END_OF_LIST);
2701 } else {
2702 qh->prev_qh->link_ptr = qh->link_ptr;
2703 }
2704
2705 if (next_lattice_qh == NULL) {
2706 uhcip->uhci_bulk_xfers_q_tail = qh->prev_qh;
2707 } else {
2708 next_lattice_qh->prev_qh = qh->prev_qh;
2709 }
2710
2711 qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
2712
2713 }
2714
2715
2716 static void
2717 uhci_remove_ctrl_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2718 {
2719 queue_head_t *qh = pp->pp_qh;
2720 queue_head_t *next_lattice_qh =
2721 QH_VADDR(GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK);
2722
2723 qh->prev_qh->link_ptr = qh->link_ptr;
2724 if (next_lattice_qh->prev_qh != NULL) {
2725 next_lattice_qh->prev_qh = qh->prev_qh;
2726 } else {
2727 uhcip->uhci_ctrl_xfers_q_tail = qh->prev_qh;
2728 }
2729
2730 qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
2731 }
2732
2733
2734 /*
2735 * uhci_allocate_td_from_pool:
2736 * Allocate a Transfer Descriptor (TD) from the TD buffer pool.
2737 */
2738 static uhci_td_t *
2739 uhci_allocate_td_from_pool(uhci_state_t *uhcip)
2740 {
2741 int index;
2742 uhci_td_t *td;
2743
2744 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2745
2746 /*
2747 * Search for a blank Transfer Descriptor (TD)
2748 * in the TD buffer pool.
2749 */
2750 for (index = 0; index < uhci_td_pool_size; index ++) {
2751 if (uhcip->uhci_td_pool_addr[index].flag == TD_FLAG_FREE) {
2752 break;
2753 }
2754 }
2755
2756 if (index == uhci_td_pool_size) {
2757 USB_DPRINTF_L2(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2758 "uhci_allocate_td_from_pool: TD exhausted");
2759
2760 return (NULL);
2761 }
2762
2763 USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2764 "uhci_allocate_td_from_pool: Allocated %d", index);
2765
2766 /* Create a new dummy for the end of the TD list */
2767 td = &uhcip->uhci_td_pool_addr[index];
2768
2769 /* Mark the newly allocated TD as a dummy */
2770 td->flag = TD_FLAG_DUMMY;
2771 td->qh_td_prev = NULL;
2772
2773 return (td);
2774 }
2775
2776
2777 /*
2778 * uhci_insert_bulk_td:
2779 */
2780 int
2781 uhci_insert_bulk_td(
2782 uhci_state_t *uhcip,
2783 usba_pipe_handle_data_t *ph,
2784 usb_bulk_req_t *req,
2785 usb_flags_t flags)
2786 {
2787 size_t length;
2788 uint_t mps; /* MaxPacketSize */
2789 uint_t num_bulk_tds, i, j;
2790 uint32_t buf_offs;
2791 uhci_td_t *bulk_td_ptr;
2792 uhci_td_t *current_dummy, *tmp_td;
2793 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2794 uhci_trans_wrapper_t *tw;
2795 uhci_bulk_isoc_xfer_t *bulk_xfer_info;
2796 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
2797
2798 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2799 "uhci_insert_bulk_td: req: 0x%p, flags = 0x%x", (void *)req, flags);
2800
2801 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2802
2803 /*
2804 * Create transfer wrapper
2805 */
2806 if ((tw = uhci_create_transfer_wrapper(uhcip, pp, req->bulk_len,
2807 flags)) == NULL) {
2808 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2809 "uhci_insert_bulk_td: TW allocation failed");
2810
2811 return (USB_NO_RESOURCES);
2812 }
2813
2814 tw->tw_bytes_xfered = 0;
2815 tw->tw_bytes_pending = req->bulk_len;
2816 tw->tw_handle_td = uhci_handle_bulk_td;
2817 tw->tw_handle_callback_value = (usb_opaque_t)req->bulk_data;
2818 tw->tw_timeout_cnt = req->bulk_timeout;
2819 tw->tw_data = req->bulk_data;
2820 tw->tw_curr_xfer_reqp = (usb_opaque_t)req;
2821
2822 /* Get the bulk pipe direction */
2823 tw->tw_direction = (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) ?
2824 PID_OUT : PID_IN;
2825
2826 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2827 "uhci_insert_bulk_td: direction: 0x%x", tw->tw_direction);
2828
2829 /* If the DATA OUT, copy the data into transfer buffer. */
2830 if (tw->tw_direction == PID_OUT) {
2831 if (req->bulk_len) {
2832 ASSERT(req->bulk_data != NULL);
2833
2834 /* Copy the data into the message */
2835 ddi_rep_put8(tw->tw_accesshandle,
2836 req->bulk_data->b_rptr,
2837 (uint8_t *)tw->tw_buf,
2838 req->bulk_len, DDI_DEV_AUTOINCR);
2839 }
2840 }
2841
2842 /* Get the max packet size. */
2843 length = mps = pp->pp_pipe_handle->p_ep.wMaxPacketSize;
2844
2845 /*
2846 * Calculate number of TD's to insert in the current frame interval.
2847 * Max number TD's allowed (driver implementation) is 128
2848 * in one frame interval. Once all the TD's are completed
2849 * then the remaining TD's will be inserted into the lattice
2850 * in the uhci_handle_bulk_td().
2851 */
2852 if ((tw->tw_bytes_pending / mps) >= MAX_NUM_BULK_TDS_PER_XFER) {
2853 num_bulk_tds = MAX_NUM_BULK_TDS_PER_XFER;
2854 } else {
2855 num_bulk_tds = (tw->tw_bytes_pending / mps);
2856
2857 if (tw->tw_bytes_pending % mps || tw->tw_bytes_pending == 0) {
2858 num_bulk_tds++;
2859 length = (tw->tw_bytes_pending % mps);
2860 }
2861 }
2862
2863 /*
2864 * Allocate memory for the bulk xfer information structure
2865 */
2866 if ((bulk_xfer_info = kmem_zalloc(
2867 sizeof (uhci_bulk_isoc_xfer_t), KM_NOSLEEP)) == NULL) {
2868 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2869 "uhci_insert_bulk_td: kmem_zalloc failed");
2870
2871 /* Free the transfer wrapper */
2872 uhci_deallocate_tw(uhcip, pp, tw);
2873
2874 return (USB_FAILURE);
2875 }
2876
2877 /* Allocate memory for the bulk TD's */
2878 if (uhci_alloc_bulk_isoc_tds(uhcip, num_bulk_tds, bulk_xfer_info) !=
2879 USB_SUCCESS) {
2880 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2881 "uhci_insert_bulk_td: alloc_bulk_isoc_tds failed");
2882
2883 kmem_free(bulk_xfer_info, sizeof (uhci_bulk_isoc_xfer_t));
2884
2885 /* Free the transfer wrapper */
2886 uhci_deallocate_tw(uhcip, pp, tw);
2887
2888 return (USB_FAILURE);
2889 }
2890
2891 td_pool_ptr = &bulk_xfer_info->td_pools[0];
2892 bulk_td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
2893 bulk_td_ptr[0].qh_td_prev = NULL;
2894 current_dummy = pp->pp_qh->td_tailp;
2895 buf_offs = 0;
2896 pp->pp_qh->bulk_xfer_info = bulk_xfer_info;
2897
2898 /* Fill up all the bulk TD's */
2899 for (i = 0; i < bulk_xfer_info->num_pools; i++) {
2900 for (j = 0; j < (td_pool_ptr->num_tds - 1); j++) {
2901 uhci_fill_in_bulk_isoc_td(uhcip, &bulk_td_ptr[j],
2902 &bulk_td_ptr[j+1], BULKTD_PADDR(td_pool_ptr,
2903 &bulk_td_ptr[j+1]), ph, buf_offs, mps, tw);
2904 buf_offs += mps;
2905 }
2906
2907 /* fill in the last TD */
2908 if (i == (bulk_xfer_info->num_pools - 1)) {
2909 uhci_fill_in_bulk_isoc_td(uhcip, &bulk_td_ptr[j],
2910 current_dummy, TD_PADDR(current_dummy),
2911 ph, buf_offs, length, tw);
2912 } else {
2913 /* fill in the TD at the tail of a pool */
2914 tmp_td = &bulk_td_ptr[j];
2915 td_pool_ptr = &bulk_xfer_info->td_pools[i + 1];
2916 bulk_td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
2917 uhci_fill_in_bulk_isoc_td(uhcip, tmp_td,
2918 &bulk_td_ptr[0], BULKTD_PADDR(td_pool_ptr,
2919 &bulk_td_ptr[0]), ph, buf_offs, mps, tw);
2920 buf_offs += mps;
2921 }
2922 }
2923
2924 bulk_xfer_info->num_tds = (ushort_t)num_bulk_tds;
2925
2926 /*
2927 * Point the end of the lattice tree to the start of the bulk xfers
2928 * queue head. This allows the HC to execute the same Queue Head/TD
2929 * in the same frame. There are some bulk devices, which NAKs after
2930 * completing each TD. As a result, the performance on such devices
2931 * is very bad. This loop will provide a chance to execute NAk'ed
2932 * bulk TDs again in the same frame.
2933 */
2934 if (uhcip->uhci_pending_bulk_cmds++ == 0) {
2935 uhcip->uhci_bulk_xfers_q_tail->link_ptr =
2936 uhcip->uhci_bulk_xfers_q_head->link_ptr;
2937 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
2938 "uhci_insert_bulk_td: count = %d no tds %d",
2939 uhcip->uhci_pending_bulk_cmds, num_bulk_tds);
2940 }
2941
2942 /* Insert on the bulk queue head for the execution by HC */
2943 SetQH32(uhcip, pp->pp_qh->element_ptr,
2944 bulk_xfer_info->td_pools[0].cookie.dmac_address);
2945
2946 return (USB_SUCCESS);
2947 }
2948
2949
2950 /*
2951 * uhci_fill_in_bulk_isoc_td
2952 * Fills the bulk/isoc TD
2953 *
2954 * offset - different meanings for bulk and isoc TDs:
2955 * starting offset into the TW buffer for a bulk TD
2956 * and the index into the isoc packet list for an isoc TD
2957 */
2958 void
2959 uhci_fill_in_bulk_isoc_td(uhci_state_t *uhcip, uhci_td_t *current_td,
2960 uhci_td_t *next_td,
2961 uint32_t next_td_paddr,
2962 usba_pipe_handle_data_t *ph,
2963 uint_t offset,
2964 uint_t length,
2965 uhci_trans_wrapper_t *tw)
2966 {
2967 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2968 usb_ep_descr_t *ept = &pp->pp_pipe_handle->p_ep;
2969 uint32_t buf_addr;
2970
2971 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2972 "uhci_fill_in_bulk_isoc_td: tw 0x%p offs 0x%x length 0x%x",
2973 (void *)tw, offset, length);
2974
2975 bzero((char *)current_td, sizeof (uhci_td_t));
2976 SetTD32(uhcip, current_td->link_ptr, next_td_paddr | HC_DEPTH_FIRST);
2977
2978 switch (UHCI_XFER_TYPE(ept)) {
2979 case USB_EP_ATTR_ISOCH:
2980 if (((usb_isoc_req_t *)tw->tw_curr_xfer_reqp)->isoc_attributes
2981 & USB_ATTRS_SHORT_XFER_OK) {
2982 SetTD_spd(uhcip, current_td, 1);
2983 }
2984 break;
2985 case USB_EP_ATTR_BULK:
2986 if (((usb_bulk_req_t *)tw->tw_curr_xfer_reqp)->bulk_attributes
2987 & USB_ATTRS_SHORT_XFER_OK) {
2988 SetTD_spd(uhcip, current_td, 1);
2989 }
2990 break;
2991 }
2992
2993 mutex_enter(&ph->p_usba_device->usb_mutex);
2994
2995 SetTD_c_err(uhcip, current_td, UHCI_MAX_ERR_COUNT);
2996 SetTD_status(uhcip, current_td, UHCI_TD_ACTIVE);
2997 SetTD_ioc(uhcip, current_td, INTERRUPT_ON_COMPLETION);
2998 SetTD_mlen(uhcip, current_td,
2999 (length == 0) ? ZERO_LENGTH : (length - 1));
3000 SetTD_dtogg(uhcip, current_td, pp->pp_data_toggle);
3001 SetTD_devaddr(uhcip, current_td, ph->p_usba_device->usb_addr);
3002 SetTD_endpt(uhcip, current_td, ph->p_ep.bEndpointAddress &
3003 END_POINT_ADDRESS_MASK);
3004 SetTD_PID(uhcip, current_td, tw->tw_direction);
3005
3006 /* Get the right buffer address for the current TD */
3007 switch (UHCI_XFER_TYPE(ept)) {
3008 case USB_EP_ATTR_ISOCH:
3009 buf_addr = tw->tw_isoc_bufs[offset].cookie.dmac_address;
3010 break;
3011 case USB_EP_ATTR_BULK:
3012 buf_addr = uhci_get_tw_paddr_by_offs(uhcip, offset,
3013 length, tw);
3014 break;
3015 }
3016 SetTD32(uhcip, current_td->buffer_address, buf_addr);
3017
3018 /*
3019 * Adjust the data toggle.
3020 * The data toggle bit must always be 0 for isoc transfers.
3021 * And set the "iso" bit in the TD for isoc transfers.
3022 */
3023 if (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_ISOCH) {
3024 pp->pp_data_toggle = 0;
3025 SetTD_iso(uhcip, current_td, 1);
3026 } else {
3027 ADJ_DATA_TOGGLE(pp);
3028 next_td->qh_td_prev = current_td;
3029 pp->pp_qh->td_tailp = next_td;
3030 }
3031
3032 current_td->outst_td_next = NULL;
3033 current_td->outst_td_prev = uhcip->uhci_outst_tds_tail;
3034 if (uhcip->uhci_outst_tds_head == NULL) {
3035 uhcip->uhci_outst_tds_head = current_td;
3036 } else {
3037 uhcip->uhci_outst_tds_tail->outst_td_next = current_td;
3038 }
3039 uhcip->uhci_outst_tds_tail = current_td;
3040 current_td->tw = tw;
3041
3042 if (tw->tw_hctd_head == NULL) {
3043 ASSERT(tw->tw_hctd_tail == NULL);
3044 tw->tw_hctd_head = current_td;
3045 tw->tw_hctd_tail = current_td;
3046 } else {
3047 /* Add the td to the end of the list */
3048 tw->tw_hctd_tail->tw_td_next = current_td;
3049 tw->tw_hctd_tail = current_td;
3050 }
3051
3052 mutex_exit(&ph->p_usba_device->usb_mutex);
3053 }
3054
3055
3056 /*
3057 * uhci_alloc_bulk_isoc_tds:
3058 * - Allocates the isoc/bulk TD pools. It will allocate one whole
3059 * pool to store all the TDs if the system allows. Only when the
3060 * first allocation fails, it tries to allocate several small
3061 * pools with each pool limited in physical page size.
3062 */
3063 static int
3064 uhci_alloc_bulk_isoc_tds(
3065 uhci_state_t *uhcip,
3066 uint_t num_tds,
3067 uhci_bulk_isoc_xfer_t *info)
3068 {
3069 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3070 "uhci_alloc_bulk_isoc_tds: num_tds: 0x%x info: 0x%p",
3071 num_tds, (void *)info);
3072
3073 info->num_pools = 1;
3074 /* allocate as a whole pool at the first time */
3075 if (uhci_alloc_memory_for_tds(uhcip, num_tds, info) !=
3076 USB_SUCCESS) {
3077 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3078 "alloc_memory_for_tds failed: num_tds %d num_pools %d",
3079 num_tds, info->num_pools);
3080
3081 /* reduce the td number per pool and alloc again */
3082 info->num_pools = num_tds / UHCI_MAX_TD_NUM_PER_POOL;
3083 if (num_tds % UHCI_MAX_TD_NUM_PER_POOL) {
3084 info->num_pools++;
3085 }
3086
3087 if (uhci_alloc_memory_for_tds(uhcip, num_tds, info) !=
3088 USB_SUCCESS) {
3089 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3090 "alloc_memory_for_tds failed: num_tds %d "
3091 "num_pools %d", num_tds, info->num_pools);
3092
3093 return (USB_NO_RESOURCES);
3094 }
3095 }
3096
3097 return (USB_SUCCESS);
3098 }
3099
3100
3101 /*
3102 * uhci_alloc_memory_for_tds:
3103 * - Allocates memory for the isoc/bulk td pools.
3104 */
3105 static int
3106 uhci_alloc_memory_for_tds(
3107 uhci_state_t *uhcip,
3108 uint_t num_tds,
3109 uhci_bulk_isoc_xfer_t *info)
3110 {
3111 int result, i, j, err;
3112 size_t real_length;
3113 uint_t ccount, num;
3114 ddi_device_acc_attr_t dev_attr;
3115 uhci_bulk_isoc_td_pool_t *td_pool_ptr1, *td_pool_ptr2;
3116
3117 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3118 "uhci_alloc_memory_for_tds: num_tds: 0x%x info: 0x%p "
3119 "num_pools: %u", num_tds, (void *)info, info->num_pools);
3120
3121 /* The host controller will be little endian */
3122 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3123 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
3124 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3125
3126 /* Allocate the TD pool structures */
3127 info->td_pools = kmem_zalloc((sizeof (uhci_bulk_isoc_td_pool_t) *
3128 info->num_pools), KM_SLEEP);
3129
3130 for (i = 0; i < info->num_pools; i++) {
3131 if (info->num_pools == 1) {
3132 num = num_tds;
3133 } else if (i < (info->num_pools - 1)) {
3134 num = UHCI_MAX_TD_NUM_PER_POOL;
3135 } else {
3136 num = (num_tds % UHCI_MAX_TD_NUM_PER_POOL);
3137 }
3138
3139 td_pool_ptr1 = &info->td_pools[i];
3140
3141 /* Allocate the bulk TD pool DMA handle */
3142 if (ddi_dma_alloc_handle(uhcip->uhci_dip,
3143 &uhcip->uhci_dma_attr, DDI_DMA_SLEEP, 0,
3144 &td_pool_ptr1->dma_handle) != DDI_SUCCESS) {
3145
3146 for (j = 0; j < i; j++) {
3147 td_pool_ptr2 = &info->td_pools[j];
3148 result = ddi_dma_unbind_handle(
3149 td_pool_ptr2->dma_handle);
3150 ASSERT(result == DDI_SUCCESS);
3151 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3152 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3153 }
3154
3155 kmem_free(info->td_pools,
3156 (sizeof (uhci_bulk_isoc_td_pool_t) *
3157 info->num_pools));
3158
3159 return (USB_FAILURE);
3160 }
3161
3162 /* Allocate the memory for the bulk TD pool */
3163 if (ddi_dma_mem_alloc(td_pool_ptr1->dma_handle,
3164 num * sizeof (uhci_td_t), &dev_attr,
3165 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
3166 &td_pool_ptr1->pool_addr, &real_length,
3167 &td_pool_ptr1->mem_handle) != DDI_SUCCESS) {
3168
3169 ddi_dma_free_handle(&td_pool_ptr1->dma_handle);
3170
3171 for (j = 0; j < i; j++) {
3172 td_pool_ptr2 = &info->td_pools[j];
3173 result = ddi_dma_unbind_handle(
3174 td_pool_ptr2->dma_handle);
3175 ASSERT(result == DDI_SUCCESS);
3176 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3177 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3178 }
3179
3180 kmem_free(info->td_pools,
3181 (sizeof (uhci_bulk_isoc_td_pool_t) *
3182 info->num_pools));
3183
3184 return (USB_FAILURE);
3185 }
3186
3187 /* Map the bulk TD pool into the I/O address space */
3188 result = ddi_dma_addr_bind_handle(td_pool_ptr1->dma_handle,
3189 NULL, (caddr_t)td_pool_ptr1->pool_addr, real_length,
3190 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
3191 &td_pool_ptr1->cookie, &ccount);
3192
3193 /* Process the result */
3194 err = USB_SUCCESS;
3195
3196 if (result != DDI_DMA_MAPPED) {
3197 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3198 "uhci_allocate_memory_for_tds: Result = %d",
3199 result);
3200 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip,
3201 result);
3202
3203 err = USB_FAILURE;
3204 }
3205
3206 if ((result == DDI_DMA_MAPPED) && (ccount != 1)) {
3207 /* The cookie count should be 1 */
3208 USB_DPRINTF_L2(PRINT_MASK_ATTA,
3209 uhcip->uhci_log_hdl,
3210 "uhci_allocate_memory_for_tds: "
3211 "More than 1 cookie");
3212
3213 result = ddi_dma_unbind_handle(
3214 td_pool_ptr1->dma_handle);
3215 ASSERT(result == DDI_SUCCESS);
3216
3217 err = USB_FAILURE;
3218 }
3219
3220 if (err == USB_FAILURE) {
3221
3222 ddi_dma_mem_free(&td_pool_ptr1->mem_handle);
3223 ddi_dma_free_handle(&td_pool_ptr1->dma_handle);
3224
3225 for (j = 0; j < i; j++) {
3226 td_pool_ptr2 = &info->td_pools[j];
3227 result = ddi_dma_unbind_handle(
3228 td_pool_ptr2->dma_handle);
3229 ASSERT(result == DDI_SUCCESS);
3230 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3231 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3232 }
3233
3234 kmem_free(info->td_pools,
3235 (sizeof (uhci_bulk_isoc_td_pool_t) *
3236 info->num_pools));
3237
3238 return (USB_FAILURE);
3239 }
3240
3241 bzero((void *)td_pool_ptr1->pool_addr,
3242 num * sizeof (uhci_td_t));
3243 td_pool_ptr1->num_tds = (ushort_t)num;
3244 }
3245
3246 return (USB_SUCCESS);
3247 }
3248
3249
3250 /*
3251 * uhci_handle_bulk_td:
3252 *
3253 * Handles the completed bulk transfer descriptors
3254 */
3255 void
3256 uhci_handle_bulk_td(uhci_state_t *uhcip, uhci_td_t *td)
3257 {
3258 uint_t num_bulk_tds, index, td_count, j;
3259 usb_cr_t error;
3260 uint_t length, bytes_xfered;
3261 ushort_t MaxPacketSize;
3262 uint32_t buf_offs, paddr;
3263 uhci_td_t *bulk_td_ptr, *current_dummy, *td_head;
3264 uhci_td_t *tmp_td;
3265 queue_head_t *qh, *next_qh;
3266 uhci_trans_wrapper_t *tw = td->tw;
3267 uhci_pipe_private_t *pp = tw->tw_pipe_private;
3268 uhci_bulk_isoc_xfer_t *bulk_xfer_info;
3269 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3270 usba_pipe_handle_data_t *ph;
3271
3272 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3273 "uhci_handle_bulk_td: td = 0x%p tw = 0x%p", (void *)td, (void *)tw);
3274
3275 /*
3276 * Update the tw_bytes_pending, and tw_bytes_xfered
3277 */
3278 bytes_xfered = ZERO_LENGTH;
3279
3280 /*
3281 * Check whether there are any errors occurred in the xfer.
3282 * If so, update the data_toggle for the queue head and
3283 * return error to the upper layer.
3284 */
3285 if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
3286 uhci_handle_bulk_td_errors(uhcip, td);
3287
3288 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3289 "uhci_handle_bulk_td: error; data toggle: 0x%x",
3290 pp->pp_data_toggle);
3291
3292 return;
3293 }
3294
3295 /*
3296 * Update the tw_bytes_pending, and tw_bytes_xfered
3297 */
3298 bytes_xfered = GetTD_alen(uhcip, td);
3299 if (bytes_xfered != ZERO_LENGTH) {
3300 tw->tw_bytes_pending -= (bytes_xfered + 1);
3301 tw->tw_bytes_xfered += (bytes_xfered + 1);
3302 }
3303
3304 /*
3305 * Get Bulk pipe information and pipe handle
3306 */
3307 bulk_xfer_info = pp->pp_qh->bulk_xfer_info;
3308 ph = tw->tw_pipe_private->pp_pipe_handle;
3309
3310 /*
3311 * Check whether data underrun occurred.
3312 * If so, complete the transfer
3313 * Update the data toggle bit
3314 */
3315 if (bytes_xfered != GetTD_mlen(uhcip, td)) {
3316 bulk_xfer_info->num_tds = 1;
3317 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3318 "uhci_handle_bulk_td: Data underrun occured");
3319
3320 pp->pp_data_toggle = GetTD_dtogg(uhcip, td) == 0 ? 1 : 0;
3321 }
3322
3323 /*
3324 * If the TD's in the current frame are completed, then check
3325 * whether we have any more bytes to xfer. If so, insert TD's.
3326 * If no more bytes needs to be transferred, then do callback to the
3327 * upper layer.
3328 * If the TD's in the current frame are not completed, then
3329 * just delete the TD from the linked lists.
3330 */
3331 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3332 "uhci_handle_bulk_td: completed TD data toggle: 0x%x",
3333 GetTD_dtogg(uhcip, td));
3334
3335 if (--bulk_xfer_info->num_tds == 0) {
3336 uhci_delete_td(uhcip, td);
3337
3338 if ((tw->tw_bytes_pending) &&
3339 (GetTD_mlen(uhcip, td) - GetTD_alen(uhcip, td) == 0)) {
3340
3341 MaxPacketSize = pp->pp_pipe_handle->p_ep.wMaxPacketSize;
3342 length = MaxPacketSize;
3343
3344 qh = pp->pp_qh;
3345 paddr = GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK;
3346 if (GetQH32(uhcip, qh->link_ptr) !=
3347 GetQH32(uhcip,
3348 uhcip->uhci_bulk_xfers_q_head->link_ptr)) {
3349 next_qh = QH_VADDR(paddr);
3350 SetQH32(uhcip, qh->prev_qh->link_ptr,
3351 paddr|(0x2));
3352 next_qh->prev_qh = qh->prev_qh;
3353 SetQH32(uhcip, qh->link_ptr,
3354 GetQH32(uhcip,
3355 uhcip->uhci_bulk_xfers_q_head->link_ptr));
3356 qh->prev_qh = uhcip->uhci_bulk_xfers_q_tail;
3357 SetQH32(uhcip,
3358 uhcip->uhci_bulk_xfers_q_tail->link_ptr,
3359 QH_PADDR(qh) | 0x2);
3360 uhcip->uhci_bulk_xfers_q_tail = qh;
3361 }
3362
3363 if ((tw->tw_bytes_pending / MaxPacketSize) >=
3364 MAX_NUM_BULK_TDS_PER_XFER) {
3365 num_bulk_tds = MAX_NUM_BULK_TDS_PER_XFER;
3366 } else {
3367 num_bulk_tds =
3368 (tw->tw_bytes_pending / MaxPacketSize);
3369 if (tw->tw_bytes_pending % MaxPacketSize) {
3370 num_bulk_tds++;
3371 length = (tw->tw_bytes_pending %
3372 MaxPacketSize);
3373 }
3374 }
3375
3376 current_dummy = pp->pp_qh->td_tailp;
3377 td_pool_ptr = &bulk_xfer_info->td_pools[0];
3378 bulk_td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
3379 buf_offs = tw->tw_bytes_xfered;
3380 td_count = num_bulk_tds;
3381 index = 0;
3382
3383 /* reuse the TDs to transfer more data */
3384 while (td_count > 0) {
3385 for (j = 0;
3386 (j < (td_pool_ptr->num_tds - 1)) &&
3387 (td_count > 1); j++, td_count--) {
3388 uhci_fill_in_bulk_isoc_td(uhcip,
3389 &bulk_td_ptr[j], &bulk_td_ptr[j+1],
3390 BULKTD_PADDR(td_pool_ptr,
3391 &bulk_td_ptr[j+1]), ph, buf_offs,
3392 MaxPacketSize, tw);
3393 buf_offs += MaxPacketSize;
3394 }
3395
3396 if (td_count == 1) {
3397 uhci_fill_in_bulk_isoc_td(uhcip,
3398 &bulk_td_ptr[j], current_dummy,
3399 TD_PADDR(current_dummy), ph,
3400 buf_offs, length, tw);
3401
3402 break;
3403 } else {
3404 tmp_td = &bulk_td_ptr[j];
3405 ASSERT(index <
3406 (bulk_xfer_info->num_pools - 1));
3407 td_pool_ptr = &bulk_xfer_info->
3408 td_pools[index + 1];
3409 bulk_td_ptr = (uhci_td_t *)
3410 td_pool_ptr->pool_addr;
3411 uhci_fill_in_bulk_isoc_td(uhcip,
3412 tmp_td, &bulk_td_ptr[0],
3413 BULKTD_PADDR(td_pool_ptr,
3414 &bulk_td_ptr[0]), ph, buf_offs,
3415 MaxPacketSize, tw);
3416 buf_offs += MaxPacketSize;
3417 td_count--;
3418 index++;
3419 }
3420 }
3421
3422 pp->pp_qh->bulk_xfer_info = bulk_xfer_info;
3423 bulk_xfer_info->num_tds = (ushort_t)num_bulk_tds;
3424 SetQH32(uhcip, pp->pp_qh->element_ptr,
3425 bulk_xfer_info->td_pools[0].cookie.dmac_address);
3426 } else {
3427 usba_pipe_handle_data_t *usb_pp = pp->pp_pipe_handle;
3428
3429 pp->pp_qh->bulk_xfer_info = NULL;
3430
3431 if (tw->tw_bytes_pending) {
3432 /* Update the element pointer */
3433 SetQH32(uhcip, pp->pp_qh->element_ptr,
3434 TD_PADDR(pp->pp_qh->td_tailp));
3435
3436 /* Remove all the tds */
3437 td_head = tw->tw_hctd_head;
3438 while (td_head != NULL) {
3439 uhci_delete_td(uhcip, td_head);
3440 td_head = tw->tw_hctd_head;
3441 }
3442 }
3443
3444 if (tw->tw_direction == PID_IN) {
3445 usb_req_attrs_t attrs = ((usb_bulk_req_t *)
3446 tw->tw_curr_xfer_reqp)->bulk_attributes;
3447
3448 error = USB_CR_OK;
3449
3450 /* Data run occurred */
3451 if (tw->tw_bytes_pending &&
3452 (!(attrs & USB_ATTRS_SHORT_XFER_OK))) {
3453 error = USB_CR_DATA_UNDERRUN;
3454 }
3455
3456 uhci_sendup_td_message(uhcip, error, tw);
3457 } else {
3458 uhci_do_byte_stats(uhcip, tw->tw_length,
3459 usb_pp->p_ep.bmAttributes,
3460 usb_pp->p_ep.bEndpointAddress);
3461
3462 /* Data underrun occurred */
3463 if (tw->tw_bytes_pending) {
3464
3465 tw->tw_data->b_rptr +=
3466 tw->tw_bytes_xfered;
3467
3468 USB_DPRINTF_L2(PRINT_MASK_ATTA,
3469 uhcip->uhci_log_hdl,
3470 "uhci_handle_bulk_td: "
3471 "data underrun occurred");
3472
3473 uhci_hcdi_callback(uhcip, pp,
3474 tw->tw_pipe_private->pp_pipe_handle,
3475 tw, USB_CR_DATA_UNDERRUN);
3476 } else {
3477 uhci_hcdi_callback(uhcip, pp,
3478 tw->tw_pipe_private->pp_pipe_handle,
3479 tw, USB_CR_OK);
3480 }
3481 } /* direction */
3482
3483 /* Deallocate DMA memory */
3484 uhci_deallocate_tw(uhcip, pp, tw);
3485 for (j = 0; j < bulk_xfer_info->num_pools; j++) {
3486 td_pool_ptr = &bulk_xfer_info->td_pools[j];
3487 (void) ddi_dma_unbind_handle(
3488 td_pool_ptr->dma_handle);
3489 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
3490 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
3491 }
3492 kmem_free(bulk_xfer_info->td_pools,
3493 (sizeof (uhci_bulk_isoc_td_pool_t) *
3494 bulk_xfer_info->num_pools));
3495 kmem_free(bulk_xfer_info,
3496 sizeof (uhci_bulk_isoc_xfer_t));
3497
3498 /*
3499 * When there are no pending bulk commands, point the
3500 * end of the lattice tree to NULL. This will make sure
3501 * that the HC control does not loop anymore and PCI
3502 * bus is not affected.
3503 */
3504 if (--uhcip->uhci_pending_bulk_cmds == 0) {
3505 uhcip->uhci_bulk_xfers_q_tail->link_ptr =
3506 HC_END_OF_LIST;
3507 USB_DPRINTF_L3(PRINT_MASK_ATTA,
3508 uhcip->uhci_log_hdl,
3509 "uhci_handle_bulk_td: count = %d",
3510 uhcip->uhci_pending_bulk_cmds);
3511 }
3512 }
3513 } else {
3514 uhci_delete_td(uhcip, td);
3515 }
3516 }
3517
3518
3519 void
3520 uhci_handle_bulk_td_errors(uhci_state_t *uhcip, uhci_td_t *td)
3521 {
3522 usb_cr_t usb_err;
3523 uint32_t paddr_tail, element_ptr, paddr;
3524 uhci_td_t *next_td;
3525 uhci_pipe_private_t *pp;
3526 uhci_trans_wrapper_t *tw = td->tw;
3527 usba_pipe_handle_data_t *ph;
3528 uhci_bulk_isoc_td_pool_t *td_pool_ptr = NULL;
3529
3530 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3531 "uhci_handle_bulk_td_errors: td = %p", (void *)td);
3532
3533 #ifdef DEBUG
3534 uhci_print_td(uhcip, td);
3535 #endif
3536
3537 tw = td->tw;
3538 ph = tw->tw_pipe_private->pp_pipe_handle;
3539 pp = (uhci_pipe_private_t *)ph->p_hcd_private;
3540
3541 /*
3542 * Find the type of error occurred and return the error
3543 * to the upper layer. And adjust the data toggle.
3544 */
3545 element_ptr = GetQH32(uhcip, pp->pp_qh->element_ptr) &
3546 QH_ELEMENT_PTR_MASK;
3547 paddr_tail = TD_PADDR(pp->pp_qh->td_tailp);
3548
3549 /*
3550 * If a timeout occurs before a transfer has completed,
3551 * the timeout handler sets the CRC/Timeout bit and clears the Active
3552 * bit in the link_ptr for each td in the transfer.
3553 * It then waits (at least) 1 ms so that any tds the controller might
3554 * have been executing will have completed.
3555 * So at this point element_ptr will point to either:
3556 * 1) the next td for the transfer (which has not been executed,
3557 * and has the CRC/Timeout status bit set and Active bit cleared),
3558 * 2) the dummy td for this qh.
3559 * So if the element_ptr does not point to the dummy td, we know
3560 * it points to the next td that would have been executed.
3561 * That td has the data toggle we want to save.
3562 * All outstanding tds have been marked as CRC/Timeout,
3563 * so it doesn't matter which td we pass to uhci_parse_td_error
3564 * for the error status.
3565 */
3566 if (element_ptr != paddr_tail) {
3567 paddr = (element_ptr & QH_ELEMENT_PTR_MASK);
3568 uhci_get_bulk_td_by_paddr(uhcip, pp->pp_qh->bulk_xfer_info,
3569 paddr, &td_pool_ptr);
3570 next_td = BULKTD_VADDR(td_pool_ptr, paddr);
3571 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3572 "uhci_handle_bulk_td_errors: next td = %p",
3573 (void *)next_td);
3574
3575 usb_err = uhci_parse_td_error(uhcip, pp, next_td);
3576 } else {
3577 usb_err = uhci_parse_td_error(uhcip, pp, td);
3578 }
3579
3580 /*
3581 * Update the link pointer.
3582 */
3583 SetQH32(uhcip, pp->pp_qh->element_ptr, TD_PADDR(pp->pp_qh->td_tailp));
3584
3585 /*
3586 * Send up number of bytes transferred before the error condition.
3587 */
3588 if ((tw->tw_direction == PID_OUT) && tw->tw_data) {
3589 tw->tw_data->b_rptr += tw->tw_bytes_xfered;
3590 }
3591
3592 uhci_remove_bulk_tds_tws(uhcip, tw->tw_pipe_private, UHCI_IN_ERROR);
3593
3594 /*
3595 * When there are no pending bulk commands, point the end of the
3596 * lattice tree to NULL. This will make sure that the HC control
3597 * does not loop anymore and PCI bus is not affected.
3598 */
3599 if (--uhcip->uhci_pending_bulk_cmds == 0) {
3600 uhcip->uhci_bulk_xfers_q_tail->link_ptr = HC_END_OF_LIST;
3601 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3602 "uhci_handle_bulk_td_errors: count = %d",
3603 uhcip->uhci_pending_bulk_cmds);
3604 }
3605
3606 uhci_hcdi_callback(uhcip, pp, ph, tw, usb_err);
3607 uhci_deallocate_tw(uhcip, pp, tw);
3608 }
3609
3610
3611 /*
3612 * uhci_get_bulk_td_by_paddr:
3613 * Obtain the address of the TD pool the physical address falls in.
3614 *
3615 * td_pool_pp - pointer to the address of the TD pool containing the paddr
3616 */
3617 /* ARGSUSED */
3618 static void
3619 uhci_get_bulk_td_by_paddr(
3620 uhci_state_t *uhcip,
3621 uhci_bulk_isoc_xfer_t *info,
3622 uint32_t paddr,
3623 uhci_bulk_isoc_td_pool_t **td_pool_pp)
3624 {
3625 uint_t i = 0;
3626
3627 while (i < info->num_pools) {
3628 *td_pool_pp = &info->td_pools[i];
3629 if (((*td_pool_pp)->cookie.dmac_address <= paddr) &&
3630 (((*td_pool_pp)->cookie.dmac_address +
3631 (*td_pool_pp)->cookie.dmac_size) > paddr)) {
3632
3633 break;
3634 }
3635 i++;
3636 }
3637
3638 ASSERT(i < info->num_pools);
3639 }
3640
3641
3642 void
3643 uhci_remove_bulk_tds_tws(
3644 uhci_state_t *uhcip,
3645 uhci_pipe_private_t *pp,
3646 int what)
3647 {
3648 uint_t rval, i;
3649 uhci_td_t *head;
3650 uhci_td_t *head_next;
3651 usb_opaque_t curr_reqp;
3652 uhci_bulk_isoc_xfer_t *info;
3653 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3654
3655 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3656
3657 if ((info = pp->pp_qh->bulk_xfer_info) == NULL) {
3658
3659 return;
3660 }
3661
3662 head = uhcip->uhci_outst_tds_head;
3663
3664 while (head) {
3665 uhci_trans_wrapper_t *tw_tmp = head->tw;
3666 head_next = head->outst_td_next;
3667
3668 if (pp->pp_qh == tw_tmp->tw_pipe_private->pp_qh) {
3669 curr_reqp = tw_tmp->tw_curr_xfer_reqp;
3670 if (curr_reqp &&
3671 ((what == UHCI_IN_CLOSE) ||
3672 (what == UHCI_IN_RESET))) {
3673 uhci_hcdi_callback(uhcip, pp,
3674 pp->pp_pipe_handle,
3675 tw_tmp, USB_CR_FLUSHED);
3676 } /* end of curr_reqp */
3677
3678 uhci_delete_td(uhcip, head);
3679
3680 if (what == UHCI_IN_CLOSE || what == UHCI_IN_RESET) {
3681 ASSERT(info->num_tds > 0);
3682 if (--info->num_tds == 0) {
3683 uhci_deallocate_tw(uhcip, pp, tw_tmp);
3684
3685 /*
3686 * This will make sure that the HC
3687 * does not loop anymore when there
3688 * are no pending bulk commands.
3689 */
3690 if (--uhcip->uhci_pending_bulk_cmds
3691 == 0) {
3692 uhcip->uhci_bulk_xfers_q_tail->
3693 link_ptr = HC_END_OF_LIST;
3694 USB_DPRINTF_L3(PRINT_MASK_ATTA,
3695 uhcip->uhci_log_hdl,
3696 "uhci_remove_bulk_tds_tws:"
3697 " count = %d",
3698 uhcip->
3699 uhci_pending_bulk_cmds);
3700 }
3701 }
3702 }
3703 }
3704
3705 head = head_next;
3706 }
3707
3708 if (what == UHCI_IN_CLOSE || what == UHCI_IN_RESET) {
3709 ASSERT(info->num_tds == 0);
3710 }
3711
3712 for (i = 0; i < info->num_pools; i++) {
3713 td_pool_ptr = &info->td_pools[i];
3714 rval = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
3715 ASSERT(rval == DDI_SUCCESS);
3716 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
3717 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
3718 }
3719 kmem_free(info->td_pools, (sizeof (uhci_bulk_isoc_td_pool_t) *
3720 info->num_pools));
3721 kmem_free(info, sizeof (uhci_bulk_isoc_xfer_t));
3722 pp->pp_qh->bulk_xfer_info = NULL;
3723 }
3724
3725
3726 /*
3727 * uhci_save_data_toggle ()
3728 * Save the data toggle in the usba_device structure
3729 */
3730 void
3731 uhci_save_data_toggle(uhci_pipe_private_t *pp)
3732 {
3733 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
3734
3735 /* Save the data toggle in the usb devices structure. */
3736 mutex_enter(&ph->p_mutex);
3737 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
3738 pp->pp_data_toggle);
3739 mutex_exit(&ph->p_mutex);
3740 }
3741
3742 /*
3743 * uhci_create_isoc_transfer_wrapper:
3744 * Create a Transaction Wrapper (TW) for isoc transfer.
3745 * This involves the allocating of DMA resources.
3746 *
3747 * For isoc transfers, one isoc transfer includes multiple packets
3748 * and each packet may have a different length. So each packet is
3749 * transfered by one TD. We only know the individual packet length
3750 * won't exceed 1023 bytes, but we don't know exactly the lengths.
3751 * It is hard to make one physically discontiguous DMA buffer which
3752 * can fit in all the TDs like what can be done to the ctrl/bulk/
3753 * intr transfers. It is also undesirable to make one physically
3754 * contiguous DMA buffer for all the packets, since this may easily
3755 * fail when the system is in low memory. So an individual DMA
3756 * buffer is allocated for an individual isoc packet and each DMA
3757 * buffer is physically contiguous. An extra structure is allocated
3758 * to save the multiple DMA handles.
3759 */
3760 static uhci_trans_wrapper_t *
3761 uhci_create_isoc_transfer_wrapper(
3762 uhci_state_t *uhcip,
3763 uhci_pipe_private_t *pp,
3764 usb_isoc_req_t *req,
3765 size_t length,
3766 usb_flags_t usb_flags)
3767 {
3768 int result;
3769 size_t real_length, strtlen, xfer_size;
3770 uhci_trans_wrapper_t *tw;
3771 ddi_device_acc_attr_t dev_attr;
3772 ddi_dma_attr_t dma_attr;
3773 int kmem_flag;
3774 int (*dmamem_wait)(caddr_t);
3775 uint_t i, j, ccount;
3776 usb_isoc_req_t *tmp_req = req;
3777
3778 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3779
3780 if (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep) != USB_EP_ATTR_ISOCH) {
3781
3782 return (NULL);
3783 }
3784
3785 if ((req == NULL) && (UHCI_XFER_DIR(&pp->pp_pipe_handle->p_ep) ==
3786 USB_EP_DIR_IN)) {
3787 tmp_req = (usb_isoc_req_t *)pp->pp_client_periodic_in_reqp;
3788 }
3789
3790 if (tmp_req == NULL) {
3791
3792 return (NULL);
3793 }
3794
3795
3796 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3797 "uhci_create_isoc_transfer_wrapper: length = 0x%lx flags = 0x%x",
3798 length, usb_flags);
3799
3800 /* SLEEP flag should not be used in interrupt context */
3801 if (servicing_interrupt()) {
3802 kmem_flag = KM_NOSLEEP;
3803 dmamem_wait = DDI_DMA_DONTWAIT;
3804 } else {
3805 kmem_flag = KM_SLEEP;
3806 dmamem_wait = DDI_DMA_SLEEP;
3807 }
3808
3809 /* Allocate space for the transfer wrapper */
3810 if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), kmem_flag)) ==
3811 NULL) {
3812 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3813 "uhci_create_isoc_transfer_wrapper: kmem_alloc failed");
3814
3815 return (NULL);
3816 }
3817
3818 /* Allocate space for the isoc buffer handles */
3819 strtlen = sizeof (uhci_isoc_buf_t) * tmp_req->isoc_pkts_count;
3820 if ((tw->tw_isoc_bufs = kmem_zalloc(strtlen, kmem_flag)) == NULL) {
3821 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3822 "uhci_create_isoc_transfer_wrapper: kmem_alloc "
3823 "isoc buffer failed");
3824 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3825
3826 return (NULL);
3827 }
3828
3829 bcopy(&uhcip->uhci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
3830 dma_attr.dma_attr_sgllen = 1;
3831
3832 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3833 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
3834 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3835
3836 /* Store the transfer length */
3837 tw->tw_length = length;
3838
3839 for (i = 0; i < tmp_req->isoc_pkts_count; i++) {
3840 tw->tw_isoc_bufs[i].index = (ushort_t)i;
3841
3842 /* Allocate the DMA handle */
3843 if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip, &dma_attr,
3844 dmamem_wait, 0, &tw->tw_isoc_bufs[i].dma_handle)) !=
3845 DDI_SUCCESS) {
3846 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3847 "uhci_create_isoc_transfer_wrapper: "
3848 "Alloc handle %d failed", i);
3849
3850 for (j = 0; j < i; j++) {
3851 result = ddi_dma_unbind_handle(
3852 tw->tw_isoc_bufs[j].dma_handle);
3853 ASSERT(result == USB_SUCCESS);
3854 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3855 mem_handle);
3856 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3857 dma_handle);
3858 }
3859 kmem_free(tw->tw_isoc_bufs, strtlen);
3860 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3861
3862 return (NULL);
3863 }
3864
3865 /* Allocate the memory */
3866 xfer_size = tmp_req->isoc_pkt_descr[i].isoc_pkt_length;
3867 if ((result = ddi_dma_mem_alloc(tw->tw_isoc_bufs[i].dma_handle,
3868 xfer_size, &dev_attr, DDI_DMA_CONSISTENT, dmamem_wait,
3869 NULL, (caddr_t *)&tw->tw_isoc_bufs[i].buf_addr,
3870 &real_length, &tw->tw_isoc_bufs[i].mem_handle)) !=
3871 DDI_SUCCESS) {
3872 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3873 "uhci_create_isoc_transfer_wrapper: "
3874 "dma_mem_alloc %d fail", i);
3875 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
3876
3877 for (j = 0; j < i; j++) {
3878 result = ddi_dma_unbind_handle(
3879 tw->tw_isoc_bufs[j].dma_handle);
3880 ASSERT(result == USB_SUCCESS);
3881 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3882 mem_handle);
3883 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3884 dma_handle);
3885 }
3886 kmem_free(tw->tw_isoc_bufs, strtlen);
3887 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3888
3889 return (NULL);
3890 }
3891
3892 ASSERT(real_length >= xfer_size);
3893
3894 /* Bind the handle */
3895 result = ddi_dma_addr_bind_handle(
3896 tw->tw_isoc_bufs[i].dma_handle, NULL,
3897 (caddr_t)tw->tw_isoc_bufs[i].buf_addr, real_length,
3898 DDI_DMA_RDWR|DDI_DMA_CONSISTENT, dmamem_wait, NULL,
3899 &tw->tw_isoc_bufs[i].cookie, &ccount);
3900
3901 if ((result == DDI_DMA_MAPPED) && (ccount == 1)) {
3902 tw->tw_isoc_bufs[i].length = xfer_size;
3903
3904 continue;
3905 } else {
3906 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3907 "uhci_create_isoc_transfer_wrapper: "
3908 "Bind handle %d failed", i);
3909 if (result == DDI_DMA_MAPPED) {
3910 result = ddi_dma_unbind_handle(
3911 tw->tw_isoc_bufs[i].dma_handle);
3912 ASSERT(result == USB_SUCCESS);
3913 }
3914 ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
3915 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
3916
3917 for (j = 0; j < i; j++) {
3918 result = ddi_dma_unbind_handle(
3919 tw->tw_isoc_bufs[j].dma_handle);
3920 ASSERT(result == USB_SUCCESS);
3921 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3922 mem_handle);
3923 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3924 dma_handle);
3925 }
3926 kmem_free(tw->tw_isoc_bufs, strtlen);
3927 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3928
3929 return (NULL);
3930 }
3931 }
3932
3933 tw->tw_ncookies = tmp_req->isoc_pkts_count;
3934 tw->tw_isoc_strtlen = strtlen;
3935
3936 /*
3937 * Only allow one wrapper to be added at a time. Insert the
3938 * new transaction wrapper into the list for this pipe.
3939 */
3940 if (pp->pp_tw_head == NULL) {
3941 pp->pp_tw_head = tw;
3942 pp->pp_tw_tail = tw;
3943 } else {
3944 pp->pp_tw_tail->tw_next = tw;
3945 pp->pp_tw_tail = tw;
3946 ASSERT(tw->tw_next == NULL);
3947 }
3948
3949 /* Store a back pointer to the pipe private structure */
3950 tw->tw_pipe_private = pp;
3951
3952 /* Store the transfer type - synchronous or asynchronous */
3953 tw->tw_flags = usb_flags;
3954
3955 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3956 "uhci_create_isoc_transfer_wrapper: tw = 0x%p, ncookies = %u",
3957 (void *)tw, tw->tw_ncookies);
3958
3959 return (tw);
3960 }
3961
3962 /*
3963 * uhci_insert_isoc_td:
3964 * - Create transfer wrapper
3965 * - Allocate memory for the isoc td's
3966 * - Fill up all the TD's and submit to the HC
3967 * - Update all the linked lists
3968 */
3969 int
3970 uhci_insert_isoc_td(
3971 uhci_state_t *uhcip,
3972 usba_pipe_handle_data_t *ph,
3973 usb_isoc_req_t *isoc_req,
3974 size_t length,
3975 usb_flags_t flags)
3976 {
3977 int rval = USB_SUCCESS;
3978 int error;
3979 uint_t ddic;
3980 uint32_t i, j, index;
3981 uint32_t bytes_to_xfer;
3982 uint32_t expired_frames = 0;
3983 usb_frame_number_t start_frame, end_frame, current_frame;
3984 uhci_td_t *td_ptr;
3985 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
3986 uhci_trans_wrapper_t *tw;
3987 uhci_bulk_isoc_xfer_t *isoc_xfer_info;
3988 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3989
3990 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
3991 "uhci_insert_isoc_td: ph = 0x%p isoc req = %p length = %lu",
3992 (void *)ph, (void *)isoc_req, length);
3993
3994 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3995
3996 /* Allocate a transfer wrapper */
3997 if ((tw = uhci_create_isoc_transfer_wrapper(uhcip, pp, isoc_req,
3998 length, flags)) == NULL) {
3999 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4000 "uhci_insert_isoc_td: TW allocation failed");
4001
4002 return (USB_NO_RESOURCES);
4003 }
4004
4005 /* Save current isochronous request pointer */
4006 tw->tw_curr_xfer_reqp = (usb_opaque_t)isoc_req;
4007
4008 /*
4009 * Initialize the transfer wrapper. These values are useful
4010 * for sending back the reply.
4011 */
4012 tw->tw_handle_td = uhci_handle_isoc_td;
4013 tw->tw_handle_callback_value = NULL;
4014 tw->tw_direction = (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) ?
4015 PID_OUT : PID_IN;
4016
4017 /*
4018 * If the transfer isoc send, then copy the data from the request
4019 * to the transfer wrapper.
4020 */
4021 if ((tw->tw_direction == PID_OUT) && length) {
4022 uchar_t *p;
4023
4024 ASSERT(isoc_req->isoc_data != NULL);
4025 p = isoc_req->isoc_data->b_rptr;
4026
4027 /* Copy the data into the message */
4028 for (i = 0; i < isoc_req->isoc_pkts_count; i++) {
4029 ddi_rep_put8(tw->tw_isoc_bufs[i].mem_handle,
4030 p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
4031 isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
4032 DDI_DEV_AUTOINCR);
4033 p += isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
4034 }
4035 }
4036
4037 if (tw->tw_direction == PID_IN) {
4038 if ((rval = uhci_allocate_periodic_in_resource(uhcip, pp, tw,
4039 flags)) != USB_SUCCESS) {
4040 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4041 "uhci_insert_isoc_td: isoc_req_t alloc failed");
4042 uhci_deallocate_tw(uhcip, pp, tw);
4043
4044 return (rval);
4045 }
4046
4047 isoc_req = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
4048 }
4049
4050 tw->tw_isoc_req = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
4051
4052 /* Get the pointer to the isoc_xfer_info structure */
4053 isoc_xfer_info = (uhci_bulk_isoc_xfer_t *)&tw->tw_xfer_info;
4054 isoc_xfer_info->num_tds = isoc_req->isoc_pkts_count;
4055
4056 /*
4057 * Allocate memory for isoc tds
4058 */
4059 if ((rval = uhci_alloc_bulk_isoc_tds(uhcip, isoc_req->isoc_pkts_count,
4060 isoc_xfer_info)) != USB_SUCCESS) {
4061 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4062 "uhci_alloc_bulk_isoc_td: Memory allocation failure");
4063
4064 if (tw->tw_direction == PID_IN) {
4065 uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
4066 }
4067 uhci_deallocate_tw(uhcip, pp, tw);
4068
4069 return (rval);
4070 }
4071
4072 /*
4073 * Get the isoc td pool address, buffer address and
4074 * max packet size that the device supports.
4075 */
4076 td_pool_ptr = &isoc_xfer_info->td_pools[0];
4077 td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
4078 index = 0;
4079
4080 /*
4081 * Fill up the isoc tds
4082 */
4083 USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4084 "uhci_insert_isoc_td : isoc pkts %d", isoc_req->isoc_pkts_count);
4085
4086 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4087 for (j = 0; j < td_pool_ptr->num_tds; j++) {
4088 bytes_to_xfer =
4089 isoc_req->isoc_pkt_descr[index].isoc_pkt_length;
4090
4091 uhci_fill_in_bulk_isoc_td(uhcip, &td_ptr[j],
4092 (uhci_td_t *)NULL, HC_END_OF_LIST, ph, index,
4093 bytes_to_xfer, tw);
4094 td_ptr[j].isoc_pkt_index = (ushort_t)index;
4095 index++;
4096 }
4097
4098 if (i < (isoc_xfer_info->num_pools - 1)) {
4099 td_pool_ptr = &isoc_xfer_info->td_pools[i + 1];
4100 td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
4101 }
4102 }
4103
4104 /*
4105 * Get the starting frame number.
4106 * The client drivers sets the flag USB_ATTRS_ISOC_XFER_ASAP to inform
4107 * the HCD to care of starting frame number.
4108 *
4109 * Following code is very time critical. So, perform atomic execution.
4110 */
4111 ddic = ddi_enter_critical();
4112 current_frame = uhci_get_sw_frame_number(uhcip);
4113
4114 if (isoc_req->isoc_attributes & USB_ATTRS_ISOC_START_FRAME) {
4115 start_frame = isoc_req->isoc_frame_no;
4116 end_frame = start_frame + isoc_req->isoc_pkts_count;
4117
4118 /* Check available frames */
4119 if ((end_frame - current_frame) < UHCI_MAX_ISOC_FRAMES) {
4120 if (current_frame > start_frame) {
4121 if ((current_frame + FRNUM_OFFSET) <
4122 end_frame) {
4123 expired_frames = current_frame +
4124 FRNUM_OFFSET - start_frame;
4125 start_frame = current_frame +
4126 FRNUM_OFFSET;
4127 } else {
4128 rval = USB_INVALID_START_FRAME;
4129 }
4130 }
4131 } else {
4132 rval = USB_INVALID_START_FRAME;
4133 }
4134
4135 } else if (isoc_req->isoc_attributes & USB_ATTRS_ISOC_XFER_ASAP) {
4136 start_frame = pp->pp_frame_num;
4137
4138 if (start_frame == INVALID_FRNUM) {
4139 start_frame = current_frame + FRNUM_OFFSET;
4140 } else if (current_frame > start_frame) {
4141 start_frame = current_frame + FRNUM_OFFSET;
4142 }
4143
4144 end_frame = start_frame + isoc_req->isoc_pkts_count;
4145 isoc_req->isoc_frame_no = start_frame;
4146
4147 }
4148
4149 if (rval != USB_SUCCESS) {
4150
4151 /* Exit the critical */
4152 ddi_exit_critical(ddic);
4153
4154 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4155 "uhci_insert_isoc_td: Invalid starting frame number");
4156
4157 if (tw->tw_direction == PID_IN) {
4158 uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
4159 }
4160
4161 while (tw->tw_hctd_head) {
4162 uhci_delete_td(uhcip, tw->tw_hctd_head);
4163 }
4164
4165 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4166 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4167 error = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
4168 ASSERT(error == DDI_SUCCESS);
4169 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4170 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4171 }
4172 kmem_free(isoc_xfer_info->td_pools,
4173 (sizeof (uhci_bulk_isoc_td_pool_t) *
4174 isoc_xfer_info->num_pools));
4175
4176 uhci_deallocate_tw(uhcip, pp, tw);
4177
4178 return (rval);
4179 }
4180
4181 for (i = 0; i < expired_frames; i++) {
4182 isoc_req->isoc_pkt_descr[i].isoc_pkt_status =
4183 USB_CR_NOT_ACCESSED;
4184 isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length =
4185 isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
4186 uhci_get_isoc_td_by_index(uhcip, isoc_xfer_info, i,
4187 &td_ptr, &td_pool_ptr);
4188 uhci_delete_td(uhcip, td_ptr);
4189 --isoc_xfer_info->num_tds;
4190 }
4191
4192 /*
4193 * Add the TD's to the HC list
4194 */
4195 start_frame = (start_frame & 0x3ff);
4196 for (; i < isoc_req->isoc_pkts_count; i++) {
4197 uhci_get_isoc_td_by_index(uhcip, isoc_xfer_info, i,
4198 &td_ptr, &td_pool_ptr);
4199 if (uhcip->uhci_isoc_q_tailp[start_frame]) {
4200 td_ptr->isoc_prev =
4201 uhcip->uhci_isoc_q_tailp[start_frame];
4202 td_ptr->isoc_next = NULL;
4203 td_ptr->link_ptr =
4204 uhcip->uhci_isoc_q_tailp[start_frame]->link_ptr;
4205 uhcip->uhci_isoc_q_tailp[start_frame]->isoc_next =
4206 td_ptr;
4207 SetTD32(uhcip,
4208 uhcip->uhci_isoc_q_tailp[start_frame]->link_ptr,
4209 ISOCTD_PADDR(td_pool_ptr, td_ptr));
4210 uhcip->uhci_isoc_q_tailp[start_frame] = td_ptr;
4211 } else {
4212 uhcip->uhci_isoc_q_tailp[start_frame] = td_ptr;
4213 td_ptr->isoc_next = NULL;
4214 td_ptr->isoc_prev = NULL;
4215 SetTD32(uhcip, td_ptr->link_ptr,
4216 GetFL32(uhcip,
4217 uhcip->uhci_frame_lst_tablep[start_frame]));
4218 SetFL32(uhcip,
4219 uhcip->uhci_frame_lst_tablep[start_frame],
4220 ISOCTD_PADDR(td_pool_ptr, td_ptr));
4221 }
4222 td_ptr->starting_frame = (uint_t)start_frame;
4223
4224 if (++start_frame == NUM_FRAME_LST_ENTRIES)
4225 start_frame = 0;
4226 }
4227
4228 ddi_exit_critical(ddic);
4229 pp->pp_frame_num = end_frame;
4230
4231 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4232 "uhci_insert_isoc_td: current frame number 0x%llx, pipe frame num"
4233 " 0x%llx", (unsigned long long)current_frame,
4234 (unsigned long long)(pp->pp_frame_num));
4235
4236 return (rval);
4237 }
4238
4239
4240 /*
4241 * uhci_get_isoc_td_by_index:
4242 * Obtain the addresses of the TD pool and the TD at the index.
4243 *
4244 * tdpp - pointer to the address of the TD at the isoc packet index
4245 * td_pool_pp - pointer to the address of the TD pool containing
4246 * the specified TD
4247 */
4248 /* ARGSUSED */
4249 static void
4250 uhci_get_isoc_td_by_index(
4251 uhci_state_t *uhcip,
4252 uhci_bulk_isoc_xfer_t *info,
4253 uint_t index,
4254 uhci_td_t **tdpp,
4255 uhci_bulk_isoc_td_pool_t **td_pool_pp)
4256 {
4257 uint_t i = 0, j = 0;
4258 uhci_td_t *td_ptr;
4259
4260 while (j < info->num_pools) {
4261 if ((i + info->td_pools[j].num_tds) <= index) {
4262 i += info->td_pools[j].num_tds;
4263 j++;
4264 } else {
4265 i = index - i;
4266
4267 break;
4268 }
4269 }
4270
4271 ASSERT(j < info->num_pools);
4272 *td_pool_pp = &info->td_pools[j];
4273 td_ptr = (uhci_td_t *)((*td_pool_pp)->pool_addr);
4274 *tdpp = &td_ptr[i];
4275 }
4276
4277
4278 /*
4279 * uhci_handle_isoc_td:
4280 * Handles the completed isoc tds
4281 */
4282 void
4283 uhci_handle_isoc_td(uhci_state_t *uhcip, uhci_td_t *td)
4284 {
4285 uint_t rval, i;
4286 uint32_t pkt_index = td->isoc_pkt_index;
4287 usb_cr_t cr;
4288 uhci_trans_wrapper_t *tw = td->tw;
4289 usb_isoc_req_t *isoc_req = (usb_isoc_req_t *)tw->tw_isoc_req;
4290 uhci_pipe_private_t *pp = tw->tw_pipe_private;
4291 uhci_bulk_isoc_xfer_t *isoc_xfer_info = &tw->tw_xfer_info;
4292 usba_pipe_handle_data_t *usb_pp;
4293 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
4294
4295 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4296 "uhci_handle_isoc_td: td = 0x%p, pp = 0x%p, tw = 0x%p, req = 0x%p, "
4297 "index = %x", (void *)td, (void *)pp, (void *)tw, (void *)isoc_req,
4298 pkt_index);
4299
4300 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4301
4302 usb_pp = pp->pp_pipe_handle;
4303
4304 /*
4305 * Check whether there are any errors occurred. If so, update error
4306 * count and return it to the upper.But never return a non zero
4307 * completion reason.
4308 */
4309 cr = USB_CR_OK;
4310 if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
4311 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4312 "uhci_handle_isoc_td: Error Occurred: TD Status = %x",
4313 GetTD_status(uhcip, td));
4314 isoc_req->isoc_error_count++;
4315 }
4316
4317 if (isoc_req != NULL) {
4318 isoc_req->isoc_pkt_descr[pkt_index].isoc_pkt_status = cr;
4319 isoc_req->isoc_pkt_descr[pkt_index].isoc_pkt_actual_length =
4320 (GetTD_alen(uhcip, td) == ZERO_LENGTH) ? 0 :
4321 GetTD_alen(uhcip, td) + 1;
4322 }
4323
4324 uhci_delete_isoc_td(uhcip, td);
4325
4326 if (--isoc_xfer_info->num_tds != 0) {
4327 USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4328 "uhci_handle_isoc_td: Number of TDs %d",
4329 isoc_xfer_info->num_tds);
4330
4331 return;
4332 }
4333
4334 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
4335 if (tw->tw_direction == PID_IN) {
4336 uhci_sendup_td_message(uhcip, cr, tw);
4337
4338 if ((uhci_handle_isoc_receive(uhcip, pp, tw)) != USB_SUCCESS) {
4339 USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4340 "uhci_handle_isoc_td: Drop message");
4341 }
4342
4343 } else {
4344 /* update kstats only for OUT. sendup_td_msg() does it for IN */
4345 uhci_do_byte_stats(uhcip, tw->tw_length,
4346 usb_pp->p_ep.bmAttributes, usb_pp->p_ep.bEndpointAddress);
4347
4348 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, USB_CR_OK);
4349 }
4350
4351 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4352 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4353 rval = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
4354 ASSERT(rval == DDI_SUCCESS);
4355 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4356 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4357 }
4358 kmem_free(isoc_xfer_info->td_pools,
4359 (sizeof (uhci_bulk_isoc_td_pool_t) *
4360 isoc_xfer_info->num_pools));
4361 uhci_deallocate_tw(uhcip, pp, tw);
4362 }
4363
4364
4365 /*
4366 * uhci_handle_isoc_receive:
4367 * - Sends the isoc data to the client
4368 * - Inserts another isoc receive request
4369 */
4370 static int
4371 uhci_handle_isoc_receive(
4372 uhci_state_t *uhcip,
4373 uhci_pipe_private_t *pp,
4374 uhci_trans_wrapper_t *tw)
4375 {
4376 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4377 "uhci_handle_isoc_receive: tw = 0x%p", (void *)tw);
4378
4379 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4380
4381 /*
4382 * -- check for pipe state being polling before
4383 * inserting a new request. Check when is TD
4384 * de-allocation being done? (so we can reuse the same TD)
4385 */
4386 if (uhci_start_isoc_receive_polling(uhcip,
4387 pp->pp_pipe_handle, (usb_isoc_req_t *)tw->tw_curr_xfer_reqp,
4388 0) != USB_SUCCESS) {
4389 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4390 "uhci_handle_isoc_receive: receive polling failed");
4391
4392 return (USB_FAILURE);
4393 }
4394
4395 return (USB_SUCCESS);
4396 }
4397
4398
4399 /*
4400 * uhci_delete_isoc_td:
4401 * - Delete from the outstanding command queue
4402 * - Delete from the tw queue
4403 * - Delete from the isoc queue
4404 * - Delete from the HOST CONTROLLER list
4405 */
4406 static void
4407 uhci_delete_isoc_td(uhci_state_t *uhcip, uhci_td_t *td)
4408 {
4409 uint32_t starting_frame = td->starting_frame;
4410
4411 if ((td->isoc_next == NULL) && (td->isoc_prev == NULL)) {
4412 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[starting_frame],
4413 GetTD32(uhcip, td->link_ptr));
4414 uhcip->uhci_isoc_q_tailp[starting_frame] = 0;
4415 } else if (td->isoc_next == NULL) {
4416 td->isoc_prev->link_ptr = td->link_ptr;
4417 td->isoc_prev->isoc_next = NULL;
4418 uhcip->uhci_isoc_q_tailp[starting_frame] = td->isoc_prev;
4419 } else if (td->isoc_prev == NULL) {
4420 td->isoc_next->isoc_prev = NULL;
4421 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[starting_frame],
4422 GetTD32(uhcip, td->link_ptr));
4423 } else {
4424 td->isoc_prev->isoc_next = td->isoc_next;
4425 td->isoc_next->isoc_prev = td->isoc_prev;
4426 td->isoc_prev->link_ptr = td->link_ptr;
4427 }
4428
4429 uhci_delete_td(uhcip, td);
4430 }
4431
4432
4433 /*
4434 * uhci_send_isoc_receive
4435 * - Allocates usb_isoc_request
4436 * - Updates the isoc request
4437 * - Inserts the isoc td's into the HC processing list.
4438 */
4439 int
4440 uhci_start_isoc_receive_polling(
4441 uhci_state_t *uhcip,
4442 usba_pipe_handle_data_t *ph,
4443 usb_isoc_req_t *isoc_req,
4444 usb_flags_t usb_flags)
4445 {
4446 int ii, error;
4447 size_t max_isoc_xfer_size, length, isoc_pkts_length;
4448 ushort_t isoc_pkt_count;
4449 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
4450 usb_isoc_pkt_descr_t *isoc_pkt_descr;
4451
4452 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4453 "uhci_start_isoc_receive_polling: usb_flags = %x", usb_flags);
4454
4455 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4456
4457 max_isoc_xfer_size = ph->p_ep.wMaxPacketSize * UHCI_MAX_ISOC_PKTS;
4458
4459 if (isoc_req) {
4460 isoc_pkt_descr = isoc_req->isoc_pkt_descr;
4461 isoc_pkt_count = isoc_req->isoc_pkts_count;
4462 isoc_pkts_length = isoc_req->isoc_pkts_length;
4463 } else {
4464 isoc_pkt_descr = ((usb_isoc_req_t *)
4465 pp->pp_client_periodic_in_reqp)->isoc_pkt_descr;
4466 isoc_pkt_count = ((usb_isoc_req_t *)
4467 pp->pp_client_periodic_in_reqp)->isoc_pkts_count;
4468 isoc_pkts_length = ((usb_isoc_req_t *)
4469 pp->pp_client_periodic_in_reqp)->isoc_pkts_length;
4470 }
4471
4472 for (ii = 0, length = 0; ii < isoc_pkt_count; ii++) {
4473 length += isoc_pkt_descr->isoc_pkt_length;
4474 isoc_pkt_descr++;
4475 }
4476
4477 if ((isoc_pkts_length) && (isoc_pkts_length != length)) {
4478
4479 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4480 "uhci_start_isoc_receive_polling: isoc_pkts_length 0x%lx "
4481 "is not equal to the sum of all pkt lengths 0x%lx in "
4482 "an isoc request", isoc_pkts_length, length);
4483
4484 return (USB_FAILURE);
4485 }
4486
4487 /* Check the size of isochronous request */
4488 if (length > max_isoc_xfer_size) {
4489 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4490 "uhci_start_isoc_receive_polling: "
4491 "Max isoc request size = %lx, Given isoc req size = %lx",
4492 max_isoc_xfer_size, length);
4493
4494 return (USB_FAILURE);
4495 }
4496
4497 /* Add the TD into the Host Controller's isoc list */
4498 error = uhci_insert_isoc_td(uhcip, ph, isoc_req, length, usb_flags);
4499
4500 return (error);
4501 }
4502
4503
4504 /*
4505 * uhci_remove_isoc_tds_tws
4506 * This routine scans the pipe and removes all the td's
4507 * and transfer wrappers and deallocates the memory
4508 * associated with those td's and tw's.
4509 */
4510 void
4511 uhci_remove_isoc_tds_tws(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
4512 {
4513 uint_t rval, i;
4514 uhci_td_t *tmp_td, *td_head;
4515 usb_isoc_req_t *isoc_req;
4516 uhci_trans_wrapper_t *tmp_tw, *tw_head;
4517 uhci_bulk_isoc_xfer_t *isoc_xfer_info;
4518 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
4519
4520 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4521 "uhci_remove_isoc_tds_tws: pp = %p", (void *)pp);
4522
4523 tw_head = pp->pp_tw_head;
4524 while (tw_head) {
4525 tmp_tw = tw_head;
4526 tw_head = tw_head->tw_next;
4527 td_head = tmp_tw->tw_hctd_head;
4528 if (tmp_tw->tw_direction == PID_IN) {
4529 uhci_deallocate_periodic_in_resource(uhcip, pp,
4530 tmp_tw);
4531 } else if (tmp_tw->tw_direction == PID_OUT) {
4532 uhci_hcdi_callback(uhcip, pp, pp->pp_pipe_handle,
4533 tmp_tw, USB_CR_FLUSHED);
4534 }
4535
4536 while (td_head) {
4537 tmp_td = td_head;
4538 td_head = td_head->tw_td_next;
4539 uhci_delete_isoc_td(uhcip, tmp_td);
4540 }
4541
4542 isoc_req = (usb_isoc_req_t *)tmp_tw->tw_isoc_req;
4543 if (isoc_req) {
4544 usb_free_isoc_req(isoc_req);
4545 }
4546
4547 ASSERT(tmp_tw->tw_hctd_head == NULL);
4548
4549 if (tmp_tw->tw_xfer_info.td_pools) {
4550 isoc_xfer_info =
4551 (uhci_bulk_isoc_xfer_t *)&tmp_tw->tw_xfer_info;
4552 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4553 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4554 rval = ddi_dma_unbind_handle(
4555 td_pool_ptr->dma_handle);
4556 ASSERT(rval == DDI_SUCCESS);
4557 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4558 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4559 }
4560 kmem_free(isoc_xfer_info->td_pools,
4561 (sizeof (uhci_bulk_isoc_td_pool_t) *
4562 isoc_xfer_info->num_pools));
4563 }
4564
4565 uhci_deallocate_tw(uhcip, pp, tmp_tw);
4566 }
4567 }
4568
4569
4570 /*
4571 * uhci_isoc_update_sw_frame_number()
4572 * to avoid code duplication, call uhci_get_sw_frame_number()
4573 */
4574 void
4575 uhci_isoc_update_sw_frame_number(uhci_state_t *uhcip)
4576 {
4577 (void) uhci_get_sw_frame_number(uhcip);
4578 }
4579
4580
4581 /*
4582 * uhci_get_sw_frame_number:
4583 * Hold the uhci_int_mutex before calling this routine.
4584 */
4585 uint64_t
4586 uhci_get_sw_frame_number(uhci_state_t *uhcip)
4587 {
4588 uint64_t sw_frnum, hw_frnum, current_frnum;
4589
4590 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4591
4592 sw_frnum = uhcip->uhci_sw_frnum;
4593 hw_frnum = Get_OpReg16(FRNUM);
4594
4595 /*
4596 * Check bit 10 in the software counter and hardware frame counter.
4597 * If both are same, then don't increment the software frame counter
4598 * (Bit 10 of hw frame counter toggle for every 1024 frames)
4599 * The lower 11 bits of software counter contains the hardware frame
4600 * counter value. The MSB (bit 10) of software counter is incremented
4601 * for every 1024 frames either here or in get frame number routine.
4602 */
4603 if ((sw_frnum & UHCI_BIT_10_MASK) == (hw_frnum & UHCI_BIT_10_MASK)) {
4604 /* The MSB of hw counter did not toggle */
4605 current_frnum = ((sw_frnum & (SW_FRNUM_MASK)) | hw_frnum);
4606 } else {
4607 /*
4608 * The hw counter wrapped around. And the interrupt handler
4609 * did not get a chance to update the sw frame counter.
4610 * So, update the sw frame counter and return correct frame no.
4611 */
4612 sw_frnum >>= UHCI_SIZE_OF_HW_FRNUM - 1;
4613 current_frnum =
4614 ((++sw_frnum << (UHCI_SIZE_OF_HW_FRNUM - 1)) | hw_frnum);
4615 }
4616 uhcip->uhci_sw_frnum = current_frnum;
4617
4618 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4619 "uhci_get_sw_frame_number: sw=%lld hd=%lld",
4620 (unsigned long long)(uhcip->uhci_sw_frnum),
4621 (unsigned long long)hw_frnum);
4622
4623 return (current_frnum);
4624 }
4625
4626
4627 /*
4628 * uhci_cmd_timeout_hdlr:
4629 * This routine will get called for every second. It checks for
4630 * timed out control commands/bulk commands. Timeout any commands
4631 * that exceeds the time out period specified by the pipe policy.
4632 */
4633 void
4634 uhci_cmd_timeout_hdlr(void *arg)
4635 {
4636 uint_t flag = B_FALSE;
4637 uhci_td_t *head, *tmp_td;
4638 uhci_state_t *uhcip = (uhci_state_t *)arg;
4639 uhci_pipe_private_t *pp;
4640
4641 /*
4642 * Check whether any of the control xfers are timed out.
4643 * If so, complete those commands with time out as reason.
4644 */
4645 mutex_enter(&uhcip->uhci_int_mutex);
4646 head = uhcip->uhci_outst_tds_head;
4647
4648 while (head) {
4649 /*
4650 * If timeout out is zero, then dont timeout command.
4651 */
4652 if (head->tw->tw_timeout_cnt == 0) {
4653 head = head->outst_td_next;
4654 continue;
4655 }
4656
4657 if (!(head->tw->tw_flags & TW_TIMEOUT_FLAG)) {
4658 head->tw->tw_flags |= TW_TIMEOUT_FLAG;
4659 --head->tw->tw_timeout_cnt;
4660 }
4661
4662 /* only do it for bulk and control TDs */
4663 if ((head->tw->tw_timeout_cnt == 0) &&
4664 (head->tw->tw_handle_td != uhci_handle_isoc_td)) {
4665
4666 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
4667 "Command timed out: td = %p", (void *)head);
4668
4669 head->tw->tw_claim = UHCI_TIMEOUT_HDLR_CLAIMED;
4670
4671 /*
4672 * Check finally whether the command completed
4673 */
4674 if (GetTD_status(uhcip, head) & UHCI_TD_ACTIVE) {
4675 SetTD32(uhcip, head->link_ptr,
4676 GetTD32(uhcip, head->link_ptr) |
4677 HC_END_OF_LIST);
4678 pp = head->tw->tw_pipe_private;
4679 SetQH32(uhcip, pp->pp_qh->element_ptr,
4680 GetQH32(uhcip, pp->pp_qh->element_ptr) |
4681 HC_END_OF_LIST);
4682 }
4683
4684 flag = B_TRUE;
4685 }
4686
4687 head = head->outst_td_next;
4688 }
4689
4690 if (flag) {
4691 (void) uhci_wait_for_sof(uhcip);
4692 }
4693
4694 head = uhcip->uhci_outst_tds_head;
4695 while (head) {
4696 if (head->tw->tw_flags & TW_TIMEOUT_FLAG) {
4697 head->tw->tw_flags &= ~TW_TIMEOUT_FLAG;
4698 }
4699 if (head->tw->tw_claim == UHCI_TIMEOUT_HDLR_CLAIMED) {
4700 head->tw->tw_claim = UHCI_NOT_CLAIMED;
4701 tmp_td = head->tw->tw_hctd_head;
4702 while (tmp_td) {
4703 SetTD_status(uhcip, tmp_td,
4704 UHCI_TD_CRC_TIMEOUT);
4705 tmp_td = tmp_td->tw_td_next;
4706 }
4707 }
4708 head = head->outst_td_next;
4709 }
4710
4711 /*
4712 * Process the td which was completed before shifting from normal
4713 * mode to polled mode
4714 */
4715 if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TRUE) {
4716 uhci_process_submitted_td_queue(uhcip);
4717 uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_FALSE;
4718 } else if (flag) {
4719 /* Process the completed/timed out commands */
4720 uhci_process_submitted_td_queue(uhcip);
4721 }
4722
4723 /* Re-register the control/bulk/intr commands' timeout handler */
4724 if (uhcip->uhci_cmd_timeout_id) {
4725 uhcip->uhci_cmd_timeout_id = timeout(uhci_cmd_timeout_hdlr,
4726 (void *)uhcip, UHCI_ONE_SECOND);
4727 }
4728
4729 mutex_exit(&uhcip->uhci_int_mutex);
4730 }
4731
4732
4733 /*
4734 * uhci_wait_for_sof:
4735 * Wait for the start of the next frame (implying any changes made in the
4736 * lattice have now taken effect).
4737 * To be sure this is the case, we wait for the completion of the current
4738 * frame (which might have already been pending), then another complete
4739 * frame to ensure everything has taken effect.
4740 */
4741 int
4742 uhci_wait_for_sof(uhci_state_t *uhcip)
4743 {
4744 int n, error;
4745 ushort_t cmd_reg;
4746 usb_frame_number_t before_frame_number, after_frame_number;
4747 clock_t rval;
4748 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4749 "uhci_wait_for_sof: uhcip = %p", (void *)uhcip);
4750
4751 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4752
4753 error = uhci_state_is_operational(uhcip);
4754
4755 if (error != USB_SUCCESS) {
4756
4757 return (error);
4758 }
4759
4760 before_frame_number = uhci_get_sw_frame_number(uhcip);
4761 for (n = 0; n < MAX_SOF_WAIT_COUNT; n++) {
4762 SetTD_ioc(uhcip, uhcip->uhci_sof_td, 1);
4763 uhcip->uhci_cv_signal = B_TRUE;
4764
4765 rval = cv_reltimedwait(&uhcip->uhci_cv_SOF,
4766 &uhcip->uhci_int_mutex, UHCI_ONE_SECOND, TR_CLOCK_TICK);
4767
4768 after_frame_number = uhci_get_sw_frame_number(uhcip);
4769 if ((rval == -1) &&
4770 (after_frame_number <= before_frame_number)) {
4771 cmd_reg = Get_OpReg16(USBCMD);
4772 Set_OpReg16(USBCMD, (cmd_reg | USBCMD_REG_HC_RUN));
4773 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
4774 after_frame_number = uhci_get_sw_frame_number(uhcip);
4775 }
4776 before_frame_number = after_frame_number;
4777 }
4778
4779 SetTD_ioc(uhcip, uhcip->uhci_sof_td, 0);
4780
4781 return (uhcip->uhci_cv_signal ? USB_FAILURE : USB_SUCCESS);
4782
4783 }
4784
4785 /*
4786 * uhci_allocate_periodic_in_resource:
4787 * Allocate interrupt/isochronous request structure for the
4788 * interrupt/isochronous IN transfer.
4789 */
4790 int
4791 uhci_allocate_periodic_in_resource(
4792 uhci_state_t *uhcip,
4793 uhci_pipe_private_t *pp,
4794 uhci_trans_wrapper_t *tw,
4795 usb_flags_t flags)
4796 {
4797 size_t length = 0;
4798 usb_opaque_t client_periodic_in_reqp;
4799 usb_intr_req_t *cur_intr_req;
4800 usb_isoc_req_t *curr_isoc_reqp;
4801 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
4802
4803 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4804 "uhci_allocate_periodic_in_resource:\n\t"
4805 "ph = 0x%p, pp = 0x%p, tw = 0x%p, flags = 0x%x",
4806 (void *)ph, (void *)pp, (void *)tw, flags);
4807
4808 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4809
4810 /* Check the current periodic in request pointer */
4811 if (tw->tw_curr_xfer_reqp) {
4812 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4813 "uhci_allocate_periodic_in_resource: Interrupt "
4814 "request structure already exists: "
4815 "allocation failed");
4816
4817 return (USB_SUCCESS);
4818 }
4819
4820 /* Get the client periodic in request pointer */
4821 client_periodic_in_reqp = pp->pp_client_periodic_in_reqp;
4822
4823 /*
4824 * If it a periodic IN request and periodic request is NULL,
4825 * allocate corresponding usb periodic IN request for the
4826 * current periodic polling request and copy the information
4827 * from the saved periodic request structure.
4828 */
4829 if (UHCI_XFER_TYPE(&ph->p_ep) == USB_EP_ATTR_INTR) {
4830 /* Get the interrupt transfer length */
4831 length = ((usb_intr_req_t *)client_periodic_in_reqp)->
4832 intr_len;
4833
4834 cur_intr_req = usba_hcdi_dup_intr_req(ph->p_dip,
4835 (usb_intr_req_t *)client_periodic_in_reqp, length, flags);
4836 if (cur_intr_req == NULL) {
4837 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4838 "uhci_allocate_periodic_in_resource: Interrupt "
4839 "request structure allocation failed");
4840
4841 return (USB_NO_RESOURCES);
4842 }
4843
4844 /* Check and save the timeout value */
4845 tw->tw_timeout_cnt = (cur_intr_req->intr_attributes &
4846 USB_ATTRS_ONE_XFER) ? cur_intr_req->intr_timeout: 0;
4847 tw->tw_curr_xfer_reqp = (usb_opaque_t)cur_intr_req;
4848 tw->tw_length = cur_intr_req->intr_len;
4849 } else {
4850 ASSERT(client_periodic_in_reqp != NULL);
4851
4852 if ((curr_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip,
4853 (usb_isoc_req_t *)client_periodic_in_reqp, flags)) ==
4854 NULL) {
4855 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4856 "uhci_allocate_periodic_in_resource: Isochronous "
4857 "request structure allocation failed");
4858
4859 return (USB_NO_RESOURCES);
4860 }
4861
4862 /*
4863 * Save the client's isochronous request pointer and
4864 * length of isochronous transfer in transfer wrapper.
4865 * The dup'ed request is saved in pp_client_periodic_in_reqp
4866 */
4867 tw->tw_curr_xfer_reqp =
4868 (usb_opaque_t)pp->pp_client_periodic_in_reqp;
4869 pp->pp_client_periodic_in_reqp = (usb_opaque_t)curr_isoc_reqp;
4870 }
4871
4872 mutex_enter(&ph->p_mutex);
4873 ph->p_req_count++;
4874 mutex_exit(&ph->p_mutex);
4875
4876 return (USB_SUCCESS);
4877 }
4878
4879
4880 /*
4881 * uhci_deallocate_periodic_in_resource:
4882 * Deallocate interrupt/isochronous request structure for the
4883 * interrupt/isochronous IN transfer.
4884 */
4885 void
4886 uhci_deallocate_periodic_in_resource(
4887 uhci_state_t *uhcip,
4888 uhci_pipe_private_t *pp,
4889 uhci_trans_wrapper_t *tw)
4890 {
4891 usb_opaque_t curr_xfer_reqp;
4892 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
4893
4894 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4895 "uhci_deallocate_periodic_in_resource: "
4896 "pp = 0x%p tw = 0x%p", (void *)pp, (void *)tw);
4897
4898 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4899
4900 curr_xfer_reqp = tw->tw_curr_xfer_reqp;
4901 if (curr_xfer_reqp) {
4902 /*
4903 * Reset periodic in request usb isoch
4904 * packet request pointers to null.
4905 */
4906 tw->tw_curr_xfer_reqp = NULL;
4907 tw->tw_isoc_req = NULL;
4908
4909 mutex_enter(&ph->p_mutex);
4910 ph->p_req_count--;
4911 mutex_exit(&ph->p_mutex);
4912
4913 /*
4914 * Free pre-allocated interrupt or isochronous requests.
4915 */
4916 switch (UHCI_XFER_TYPE(&ph->p_ep)) {
4917 case USB_EP_ATTR_INTR:
4918 usb_free_intr_req((usb_intr_req_t *)curr_xfer_reqp);
4919 break;
4920 case USB_EP_ATTR_ISOCH:
4921 usb_free_isoc_req((usb_isoc_req_t *)curr_xfer_reqp);
4922 break;
4923 }
4924 }
4925 }
4926
4927
4928 /*
4929 * uhci_hcdi_callback()
4930 * convenience wrapper around usba_hcdi_callback()
4931 */
4932 void
4933 uhci_hcdi_callback(uhci_state_t *uhcip, uhci_pipe_private_t *pp,
4934 usba_pipe_handle_data_t *ph, uhci_trans_wrapper_t *tw, usb_cr_t cr)
4935 {
4936 usb_opaque_t curr_xfer_reqp;
4937
4938 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4939 "uhci_hcdi_callback: ph = 0x%p, tw = 0x%p, cr = 0x%x",
4940 (void *)ph, (void *)tw, cr);
4941
4942 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4943
4944 if (tw && tw->tw_curr_xfer_reqp) {
4945 curr_xfer_reqp = tw->tw_curr_xfer_reqp;
4946 tw->tw_curr_xfer_reqp = NULL;
4947 tw->tw_isoc_req = NULL;
4948 } else {
4949 ASSERT(pp->pp_client_periodic_in_reqp != NULL);
4950
4951 curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
4952 pp->pp_client_periodic_in_reqp = NULL;
4953 }
4954
4955 ASSERT(curr_xfer_reqp != NULL);
4956
4957 mutex_exit(&uhcip->uhci_int_mutex);
4958 usba_hcdi_cb(ph, curr_xfer_reqp, cr);
4959 mutex_enter(&uhcip->uhci_int_mutex);
4960 }
4961
4962
4963 /*
4964 * uhci_state_is_operational:
4965 *
4966 * Check the Host controller state and return proper values.
4967 */
4968 int
4969 uhci_state_is_operational(uhci_state_t *uhcip)
4970 {
4971 int val;
4972
4973 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4974
4975 switch (uhcip->uhci_hc_soft_state) {
4976 case UHCI_CTLR_INIT_STATE:
4977 case UHCI_CTLR_SUSPEND_STATE:
4978 val = USB_FAILURE;
4979 break;
4980 case UHCI_CTLR_OPERATIONAL_STATE:
4981 val = USB_SUCCESS;
4982 break;
4983 case UHCI_CTLR_ERROR_STATE:
4984 val = USB_HC_HARDWARE_ERROR;
4985 break;
4986 default:
4987 val = USB_FAILURE;
4988 break;
4989 }
4990
4991 return (val);
4992 }
4993
4994
4995 #ifdef DEBUG
4996 static void
4997 uhci_print_td(uhci_state_t *uhcip, uhci_td_t *td)
4998 {
4999 uint_t *ptr = (uint_t *)td;
5000
5001 #ifndef lint
5002 _NOTE(NO_COMPETING_THREADS_NOW);
5003 #endif
5004 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5005 "\tDWORD 1 0x%x\t DWORD 2 0x%x", ptr[0], ptr[1]);
5006 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5007 "\tDWORD 3 0x%x\t DWORD 4 0x%x", ptr[2], ptr[3]);
5008 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5009 "\tBytes xfered = %d", td->tw->tw_bytes_xfered);
5010 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5011 "\tBytes Pending = %d", td->tw->tw_bytes_pending);
5012 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5013 "Queue Head Details:");
5014 uhci_print_qh(uhcip, td->tw->tw_pipe_private->pp_qh);
5015
5016 #ifndef lint
5017 _NOTE(COMPETING_THREADS_NOW);
5018 #endif
5019 }
5020
5021
5022 static void
5023 uhci_print_qh(uhci_state_t *uhcip, queue_head_t *qh)
5024 {
5025 uint_t *ptr = (uint_t *)qh;
5026
5027 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5028 "\tLink Ptr = %x Element Ptr = %x", ptr[0], ptr[1]);
5029 }
5030 #endif