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
uhci_build_interrupt_lattice(uhci_state_t * uhcip)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
uhci_allocate_pools(uhci_state_t * uhcip)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
uhci_free_pools(uhci_state_t * uhcip)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
uhci_decode_ddi_dma_addr_bind_handle_result(uhci_state_t * uhcip,int result)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
uhci_init_ctlr(uhci_state_t * uhcip)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
uhci_uninit_ctlr(uhci_state_t * uhcip)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
uhci_map_regs(uhci_state_t * uhcip)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
uhci_unmap_regs(uhci_state_t * uhcip)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
uhci_set_dma_attributes(uhci_state_t * uhcip)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
pow_2(uint_t x)742 pow_2(uint_t x)
743 {
744 return ((x == 0) ? 1 : (1 << x));
745 }
746
747
748 uint_t
log_2(uint_t x)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 *
uhci_obtain_state(dev_info_t * dip)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 *
uhci_alloc_hcdi_ops(uhci_state_t * uhcip)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
uhci_init_frame_lst_table(dev_info_t * dip,uhci_state_t * uhcip)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 *
uhci_alloc_queue_head(uhci_state_t * uhcip)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
uhci_allocate_bandwidth(uhci_state_t * uhcip,usba_pipe_handle_data_t * pipe_handle,uint_t * node)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
uhci_deallocate_bandwidth(uhci_state_t * uhcip,usba_pipe_handle_data_t * pipe_handle)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
uhci_compute_total_bandwidth(usb_ep_descr_t * endpoint,usb_port_status_t port_status)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
uhci_bandwidth_adjust(uhci_state_t * uhcip,usb_ep_descr_t * endpoint,usb_port_status_t port_status)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
uhci_lattice_height(uint_t bandwidth)1374 uhci_lattice_height(uint_t bandwidth)
1375 {
1376 return (TREE_HEIGHT - (log_2(bandwidth)));
1377 }
1378
1379
1380 static uint_t
uhci_lattice_parent(uint_t node)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
uhci_leftmost_leaf(uint_t node,uint_t height)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
uhci_insert_qh(uhci_state_t * uhcip,usba_pipe_handle_data_t * ph)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
uhci_insert_ctrl_qh(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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
uhci_insert_bulk_qh(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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
uhci_insert_intr_qh(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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
uhci_insert_intr_td(uhci_state_t * uhcip,usba_pipe_handle_data_t * ph,usb_intr_req_t * req,usb_flags_t flags)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 *
uhci_create_transfer_wrapper(uhci_state_t * uhcip,uhci_pipe_private_t * pp,size_t length,usb_flags_t usb_flags)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
uhci_insert_hc_td(uhci_state_t * uhcip,uint32_t buffer_offset,size_t hcgtd_length,uhci_pipe_private_t * pp,uhci_trans_wrapper_t * tw,uchar_t PID,usb_req_attrs_t attrs)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
uhci_fill_in_td(uhci_state_t * uhcip,uhci_td_t * td,uhci_td_t * current_dummy,uint32_t buffer_offset,size_t length,uhci_pipe_private_t * pp,uchar_t PID,usb_req_attrs_t attrs,uhci_trans_wrapper_t * tw)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
uhci_get_tw_paddr_by_offs(uhci_state_t * uhcip,uint32_t buffer_offset,size_t length,uhci_trans_wrapper_t * tw)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
uhci_modify_td_active_bits(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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
uhci_insert_ctrl_td(uhci_state_t * uhcip,usba_pipe_handle_data_t * ph,usb_ctrl_req_t * ctrl_reqp,usb_flags_t flags)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
uhci_create_setup_pkt(uhci_state_t * uhcip,uhci_pipe_private_t * pp,uhci_trans_wrapper_t * tw)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
uhci_create_stats(uhci_state_t * uhcip)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
uhci_destroy_stats(uhci_state_t * uhcip)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
uhci_do_intrs_stats(uhci_state_t * uhcip,int val)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
uhci_do_byte_stats(uhci_state_t * uhcip,size_t len,uint8_t attr,uint8_t addr)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
uhci_free_tw(uhci_state_t * uhcip,uhci_trans_wrapper_t * tw)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
uhci_deallocate_tw(uhci_state_t * uhcip,uhci_pipe_private_t * pp,uhci_trans_wrapper_t * tw)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
uhci_delete_td(uhci_state_t * uhcip,uhci_td_t * td)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
uhci_remove_tds_tws(uhci_state_t * uhcip,usba_pipe_handle_data_t * ph)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
uhci_remove_qh(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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
uhci_remove_intr_qh(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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
uhci_remove_bulk_qh(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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
uhci_remove_ctrl_qh(uhci_state_t * uhcip,uhci_pipe_private_t * pp)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 *
uhci_allocate_td_from_pool(uhci_state_t * uhcip)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
uhci_insert_bulk_td(uhci_state_t * uhcip,usba_pipe_handle_data_t * ph,usb_bulk_req_t * req,usb_flags_t flags)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
uhci_fill_in_bulk_isoc_td(uhci_state_t * uhcip,uhci_td_t * current_td,uhci_td_t * next_td,uint32_t next_td_paddr,usba_pipe_handle_data_t * ph,uint_t offset,uint_t length,uhci_trans_wrapper_t * tw)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
uhci_alloc_bulk_isoc_tds(uhci_state_t * uhcip,uint_t num_tds,uhci_bulk_isoc_xfer_t * info)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
uhci_alloc_memory_for_tds(uhci_state_t * uhcip,uint_t num_tds,uhci_bulk_isoc_xfer_t * info)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 if ((info->td_pools = kmem_zalloc(
3128 (sizeof (uhci_bulk_isoc_td_pool_t) * info->num_pools),
3129 KM_SLEEP)) == NULL) {
3130 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3131 "uhci_alloc_memory_for_tds: alloc td_pools failed");
3132
3133 return (USB_FAILURE);
3134 }
3135
3136 for (i = 0; i < info->num_pools; i++) {
3137 if (info->num_pools == 1) {
3138 num = num_tds;
3139 } else if (i < (info->num_pools - 1)) {
3140 num = UHCI_MAX_TD_NUM_PER_POOL;
3141 } else {
3142 num = (num_tds % UHCI_MAX_TD_NUM_PER_POOL);
3143 }
3144
3145 td_pool_ptr1 = &info->td_pools[i];
3146
3147 /* Allocate the bulk TD pool DMA handle */
3148 if (ddi_dma_alloc_handle(uhcip->uhci_dip,
3149 &uhcip->uhci_dma_attr, DDI_DMA_SLEEP, 0,
3150 &td_pool_ptr1->dma_handle) != DDI_SUCCESS) {
3151
3152 for (j = 0; j < i; j++) {
3153 td_pool_ptr2 = &info->td_pools[j];
3154 result = ddi_dma_unbind_handle(
3155 td_pool_ptr2->dma_handle);
3156 ASSERT(result == DDI_SUCCESS);
3157 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3158 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3159 }
3160
3161 kmem_free(info->td_pools,
3162 (sizeof (uhci_bulk_isoc_td_pool_t) *
3163 info->num_pools));
3164
3165 return (USB_FAILURE);
3166 }
3167
3168 /* Allocate the memory for the bulk TD pool */
3169 if (ddi_dma_mem_alloc(td_pool_ptr1->dma_handle,
3170 num * sizeof (uhci_td_t), &dev_attr,
3171 DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
3172 &td_pool_ptr1->pool_addr, &real_length,
3173 &td_pool_ptr1->mem_handle) != DDI_SUCCESS) {
3174
3175 ddi_dma_free_handle(&td_pool_ptr1->dma_handle);
3176
3177 for (j = 0; j < i; j++) {
3178 td_pool_ptr2 = &info->td_pools[j];
3179 result = ddi_dma_unbind_handle(
3180 td_pool_ptr2->dma_handle);
3181 ASSERT(result == DDI_SUCCESS);
3182 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3183 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3184 }
3185
3186 kmem_free(info->td_pools,
3187 (sizeof (uhci_bulk_isoc_td_pool_t) *
3188 info->num_pools));
3189
3190 return (USB_FAILURE);
3191 }
3192
3193 /* Map the bulk TD pool into the I/O address space */
3194 result = ddi_dma_addr_bind_handle(td_pool_ptr1->dma_handle,
3195 NULL, (caddr_t)td_pool_ptr1->pool_addr, real_length,
3196 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
3197 &td_pool_ptr1->cookie, &ccount);
3198
3199 /* Process the result */
3200 err = USB_SUCCESS;
3201
3202 if (result != DDI_DMA_MAPPED) {
3203 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3204 "uhci_allocate_memory_for_tds: Result = %d",
3205 result);
3206 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip,
3207 result);
3208
3209 err = USB_FAILURE;
3210 }
3211
3212 if ((result == DDI_DMA_MAPPED) && (ccount != 1)) {
3213 /* The cookie count should be 1 */
3214 USB_DPRINTF_L2(PRINT_MASK_ATTA,
3215 uhcip->uhci_log_hdl,
3216 "uhci_allocate_memory_for_tds: "
3217 "More than 1 cookie");
3218
3219 result = ddi_dma_unbind_handle(
3220 td_pool_ptr1->dma_handle);
3221 ASSERT(result == DDI_SUCCESS);
3222
3223 err = USB_FAILURE;
3224 }
3225
3226 if (err == USB_FAILURE) {
3227
3228 ddi_dma_mem_free(&td_pool_ptr1->mem_handle);
3229 ddi_dma_free_handle(&td_pool_ptr1->dma_handle);
3230
3231 for (j = 0; j < i; j++) {
3232 td_pool_ptr2 = &info->td_pools[j];
3233 result = ddi_dma_unbind_handle(
3234 td_pool_ptr2->dma_handle);
3235 ASSERT(result == DDI_SUCCESS);
3236 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3237 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3238 }
3239
3240 kmem_free(info->td_pools,
3241 (sizeof (uhci_bulk_isoc_td_pool_t) *
3242 info->num_pools));
3243
3244 return (USB_FAILURE);
3245 }
3246
3247 bzero((void *)td_pool_ptr1->pool_addr,
3248 num * sizeof (uhci_td_t));
3249 td_pool_ptr1->num_tds = (ushort_t)num;
3250 }
3251
3252 return (USB_SUCCESS);
3253 }
3254
3255
3256 /*
3257 * uhci_handle_bulk_td:
3258 *
3259 * Handles the completed bulk transfer descriptors
3260 */
3261 void
uhci_handle_bulk_td(uhci_state_t * uhcip,uhci_td_t * td)3262 uhci_handle_bulk_td(uhci_state_t *uhcip, uhci_td_t *td)
3263 {
3264 uint_t num_bulk_tds, index, td_count, j;
3265 usb_cr_t error;
3266 uint_t length, bytes_xfered;
3267 ushort_t MaxPacketSize;
3268 uint32_t buf_offs, paddr;
3269 uhci_td_t *bulk_td_ptr, *current_dummy, *td_head;
3270 uhci_td_t *tmp_td;
3271 queue_head_t *qh, *next_qh;
3272 uhci_trans_wrapper_t *tw = td->tw;
3273 uhci_pipe_private_t *pp = tw->tw_pipe_private;
3274 uhci_bulk_isoc_xfer_t *bulk_xfer_info;
3275 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3276 usba_pipe_handle_data_t *ph;
3277
3278 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3279 "uhci_handle_bulk_td: td = 0x%p tw = 0x%p", (void *)td, (void *)tw);
3280
3281 /*
3282 * Update the tw_bytes_pending, and tw_bytes_xfered
3283 */
3284 bytes_xfered = ZERO_LENGTH;
3285
3286 /*
3287 * Check whether there are any errors occurred in the xfer.
3288 * If so, update the data_toggle for the queue head and
3289 * return error to the upper layer.
3290 */
3291 if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
3292 uhci_handle_bulk_td_errors(uhcip, td);
3293
3294 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3295 "uhci_handle_bulk_td: error; data toggle: 0x%x",
3296 pp->pp_data_toggle);
3297
3298 return;
3299 }
3300
3301 /*
3302 * Update the tw_bytes_pending, and tw_bytes_xfered
3303 */
3304 bytes_xfered = GetTD_alen(uhcip, td);
3305 if (bytes_xfered != ZERO_LENGTH) {
3306 tw->tw_bytes_pending -= (bytes_xfered + 1);
3307 tw->tw_bytes_xfered += (bytes_xfered + 1);
3308 }
3309
3310 /*
3311 * Get Bulk pipe information and pipe handle
3312 */
3313 bulk_xfer_info = pp->pp_qh->bulk_xfer_info;
3314 ph = tw->tw_pipe_private->pp_pipe_handle;
3315
3316 /*
3317 * Check whether data underrun occurred.
3318 * If so, complete the transfer
3319 * Update the data toggle bit
3320 */
3321 if (bytes_xfered != GetTD_mlen(uhcip, td)) {
3322 bulk_xfer_info->num_tds = 1;
3323 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3324 "uhci_handle_bulk_td: Data underrun occured");
3325
3326 pp->pp_data_toggle = GetTD_dtogg(uhcip, td) == 0 ? 1 : 0;
3327 }
3328
3329 /*
3330 * If the TD's in the current frame are completed, then check
3331 * whether we have any more bytes to xfer. If so, insert TD's.
3332 * If no more bytes needs to be transferred, then do callback to the
3333 * upper layer.
3334 * If the TD's in the current frame are not completed, then
3335 * just delete the TD from the linked lists.
3336 */
3337 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3338 "uhci_handle_bulk_td: completed TD data toggle: 0x%x",
3339 GetTD_dtogg(uhcip, td));
3340
3341 if (--bulk_xfer_info->num_tds == 0) {
3342 uhci_delete_td(uhcip, td);
3343
3344 if ((tw->tw_bytes_pending) &&
3345 (GetTD_mlen(uhcip, td) - GetTD_alen(uhcip, td) == 0)) {
3346
3347 MaxPacketSize = pp->pp_pipe_handle->p_ep.wMaxPacketSize;
3348 length = MaxPacketSize;
3349
3350 qh = pp->pp_qh;
3351 paddr = GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK;
3352 if (GetQH32(uhcip, qh->link_ptr) !=
3353 GetQH32(uhcip,
3354 uhcip->uhci_bulk_xfers_q_head->link_ptr)) {
3355 next_qh = QH_VADDR(paddr);
3356 SetQH32(uhcip, qh->prev_qh->link_ptr,
3357 paddr|(0x2));
3358 next_qh->prev_qh = qh->prev_qh;
3359 SetQH32(uhcip, qh->link_ptr,
3360 GetQH32(uhcip,
3361 uhcip->uhci_bulk_xfers_q_head->link_ptr));
3362 qh->prev_qh = uhcip->uhci_bulk_xfers_q_tail;
3363 SetQH32(uhcip,
3364 uhcip->uhci_bulk_xfers_q_tail->link_ptr,
3365 QH_PADDR(qh) | 0x2);
3366 uhcip->uhci_bulk_xfers_q_tail = qh;
3367 }
3368
3369 if ((tw->tw_bytes_pending / MaxPacketSize) >=
3370 MAX_NUM_BULK_TDS_PER_XFER) {
3371 num_bulk_tds = MAX_NUM_BULK_TDS_PER_XFER;
3372 } else {
3373 num_bulk_tds =
3374 (tw->tw_bytes_pending / MaxPacketSize);
3375 if (tw->tw_bytes_pending % MaxPacketSize) {
3376 num_bulk_tds++;
3377 length = (tw->tw_bytes_pending %
3378 MaxPacketSize);
3379 }
3380 }
3381
3382 current_dummy = pp->pp_qh->td_tailp;
3383 td_pool_ptr = &bulk_xfer_info->td_pools[0];
3384 bulk_td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
3385 buf_offs = tw->tw_bytes_xfered;
3386 td_count = num_bulk_tds;
3387 index = 0;
3388
3389 /* reuse the TDs to transfer more data */
3390 while (td_count > 0) {
3391 for (j = 0;
3392 (j < (td_pool_ptr->num_tds - 1)) &&
3393 (td_count > 1); j++, td_count--) {
3394 uhci_fill_in_bulk_isoc_td(uhcip,
3395 &bulk_td_ptr[j], &bulk_td_ptr[j+1],
3396 BULKTD_PADDR(td_pool_ptr,
3397 &bulk_td_ptr[j+1]), ph, buf_offs,
3398 MaxPacketSize, tw);
3399 buf_offs += MaxPacketSize;
3400 }
3401
3402 if (td_count == 1) {
3403 uhci_fill_in_bulk_isoc_td(uhcip,
3404 &bulk_td_ptr[j], current_dummy,
3405 TD_PADDR(current_dummy), ph,
3406 buf_offs, length, tw);
3407
3408 break;
3409 } else {
3410 tmp_td = &bulk_td_ptr[j];
3411 ASSERT(index <
3412 (bulk_xfer_info->num_pools - 1));
3413 td_pool_ptr = &bulk_xfer_info->
3414 td_pools[index + 1];
3415 bulk_td_ptr = (uhci_td_t *)
3416 td_pool_ptr->pool_addr;
3417 uhci_fill_in_bulk_isoc_td(uhcip,
3418 tmp_td, &bulk_td_ptr[0],
3419 BULKTD_PADDR(td_pool_ptr,
3420 &bulk_td_ptr[0]), ph, buf_offs,
3421 MaxPacketSize, tw);
3422 buf_offs += MaxPacketSize;
3423 td_count--;
3424 index++;
3425 }
3426 }
3427
3428 pp->pp_qh->bulk_xfer_info = bulk_xfer_info;
3429 bulk_xfer_info->num_tds = (ushort_t)num_bulk_tds;
3430 SetQH32(uhcip, pp->pp_qh->element_ptr,
3431 bulk_xfer_info->td_pools[0].cookie.dmac_address);
3432 } else {
3433 usba_pipe_handle_data_t *usb_pp = pp->pp_pipe_handle;
3434
3435 pp->pp_qh->bulk_xfer_info = NULL;
3436
3437 if (tw->tw_bytes_pending) {
3438 /* Update the element pointer */
3439 SetQH32(uhcip, pp->pp_qh->element_ptr,
3440 TD_PADDR(pp->pp_qh->td_tailp));
3441
3442 /* Remove all the tds */
3443 td_head = tw->tw_hctd_head;
3444 while (td_head != NULL) {
3445 uhci_delete_td(uhcip, td_head);
3446 td_head = tw->tw_hctd_head;
3447 }
3448 }
3449
3450 if (tw->tw_direction == PID_IN) {
3451 usb_req_attrs_t attrs = ((usb_bulk_req_t *)
3452 tw->tw_curr_xfer_reqp)->bulk_attributes;
3453
3454 error = USB_CR_OK;
3455
3456 /* Data run occurred */
3457 if (tw->tw_bytes_pending &&
3458 (!(attrs & USB_ATTRS_SHORT_XFER_OK))) {
3459 error = USB_CR_DATA_UNDERRUN;
3460 }
3461
3462 uhci_sendup_td_message(uhcip, error, tw);
3463 } else {
3464 uhci_do_byte_stats(uhcip, tw->tw_length,
3465 usb_pp->p_ep.bmAttributes,
3466 usb_pp->p_ep.bEndpointAddress);
3467
3468 /* Data underrun occurred */
3469 if (tw->tw_bytes_pending) {
3470
3471 tw->tw_data->b_rptr +=
3472 tw->tw_bytes_xfered;
3473
3474 USB_DPRINTF_L2(PRINT_MASK_ATTA,
3475 uhcip->uhci_log_hdl,
3476 "uhci_handle_bulk_td: "
3477 "data underrun occurred");
3478
3479 uhci_hcdi_callback(uhcip, pp,
3480 tw->tw_pipe_private->pp_pipe_handle,
3481 tw, USB_CR_DATA_UNDERRUN);
3482 } else {
3483 uhci_hcdi_callback(uhcip, pp,
3484 tw->tw_pipe_private->pp_pipe_handle,
3485 tw, USB_CR_OK);
3486 }
3487 } /* direction */
3488
3489 /* Deallocate DMA memory */
3490 uhci_deallocate_tw(uhcip, pp, tw);
3491 for (j = 0; j < bulk_xfer_info->num_pools; j++) {
3492 td_pool_ptr = &bulk_xfer_info->td_pools[j];
3493 (void) ddi_dma_unbind_handle(
3494 td_pool_ptr->dma_handle);
3495 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
3496 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
3497 }
3498 kmem_free(bulk_xfer_info->td_pools,
3499 (sizeof (uhci_bulk_isoc_td_pool_t) *
3500 bulk_xfer_info->num_pools));
3501 kmem_free(bulk_xfer_info,
3502 sizeof (uhci_bulk_isoc_xfer_t));
3503
3504 /*
3505 * When there are no pending bulk commands, point the
3506 * end of the lattice tree to NULL. This will make sure
3507 * that the HC control does not loop anymore and PCI
3508 * bus is not affected.
3509 */
3510 if (--uhcip->uhci_pending_bulk_cmds == 0) {
3511 uhcip->uhci_bulk_xfers_q_tail->link_ptr =
3512 HC_END_OF_LIST;
3513 USB_DPRINTF_L3(PRINT_MASK_ATTA,
3514 uhcip->uhci_log_hdl,
3515 "uhci_handle_bulk_td: count = %d",
3516 uhcip->uhci_pending_bulk_cmds);
3517 }
3518 }
3519 } else {
3520 uhci_delete_td(uhcip, td);
3521 }
3522 }
3523
3524
3525 void
uhci_handle_bulk_td_errors(uhci_state_t * uhcip,uhci_td_t * td)3526 uhci_handle_bulk_td_errors(uhci_state_t *uhcip, uhci_td_t *td)
3527 {
3528 usb_cr_t usb_err;
3529 uint32_t paddr_tail, element_ptr, paddr;
3530 uhci_td_t *next_td;
3531 uhci_pipe_private_t *pp;
3532 uhci_trans_wrapper_t *tw = td->tw;
3533 usba_pipe_handle_data_t *ph;
3534 uhci_bulk_isoc_td_pool_t *td_pool_ptr = NULL;
3535
3536 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3537 "uhci_handle_bulk_td_errors: td = %p", (void *)td);
3538
3539 #ifdef DEBUG
3540 uhci_print_td(uhcip, td);
3541 #endif
3542
3543 tw = td->tw;
3544 ph = tw->tw_pipe_private->pp_pipe_handle;
3545 pp = (uhci_pipe_private_t *)ph->p_hcd_private;
3546
3547 /*
3548 * Find the type of error occurred and return the error
3549 * to the upper layer. And adjust the data toggle.
3550 */
3551 element_ptr = GetQH32(uhcip, pp->pp_qh->element_ptr) &
3552 QH_ELEMENT_PTR_MASK;
3553 paddr_tail = TD_PADDR(pp->pp_qh->td_tailp);
3554
3555 /*
3556 * If a timeout occurs before a transfer has completed,
3557 * the timeout handler sets the CRC/Timeout bit and clears the Active
3558 * bit in the link_ptr for each td in the transfer.
3559 * It then waits (at least) 1 ms so that any tds the controller might
3560 * have been executing will have completed.
3561 * So at this point element_ptr will point to either:
3562 * 1) the next td for the transfer (which has not been executed,
3563 * and has the CRC/Timeout status bit set and Active bit cleared),
3564 * 2) the dummy td for this qh.
3565 * So if the element_ptr does not point to the dummy td, we know
3566 * it points to the next td that would have been executed.
3567 * That td has the data toggle we want to save.
3568 * All outstanding tds have been marked as CRC/Timeout,
3569 * so it doesn't matter which td we pass to uhci_parse_td_error
3570 * for the error status.
3571 */
3572 if (element_ptr != paddr_tail) {
3573 paddr = (element_ptr & QH_ELEMENT_PTR_MASK);
3574 uhci_get_bulk_td_by_paddr(uhcip, pp->pp_qh->bulk_xfer_info,
3575 paddr, &td_pool_ptr);
3576 next_td = BULKTD_VADDR(td_pool_ptr, paddr);
3577 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3578 "uhci_handle_bulk_td_errors: next td = %p",
3579 (void *)next_td);
3580
3581 usb_err = uhci_parse_td_error(uhcip, pp, next_td);
3582 } else {
3583 usb_err = uhci_parse_td_error(uhcip, pp, td);
3584 }
3585
3586 /*
3587 * Update the link pointer.
3588 */
3589 SetQH32(uhcip, pp->pp_qh->element_ptr, TD_PADDR(pp->pp_qh->td_tailp));
3590
3591 /*
3592 * Send up number of bytes transferred before the error condition.
3593 */
3594 if ((tw->tw_direction == PID_OUT) && tw->tw_data) {
3595 tw->tw_data->b_rptr += tw->tw_bytes_xfered;
3596 }
3597
3598 uhci_remove_bulk_tds_tws(uhcip, tw->tw_pipe_private, UHCI_IN_ERROR);
3599
3600 /*
3601 * When there are no pending bulk commands, point the end of the
3602 * lattice tree to NULL. This will make sure that the HC control
3603 * does not loop anymore and PCI bus is not affected.
3604 */
3605 if (--uhcip->uhci_pending_bulk_cmds == 0) {
3606 uhcip->uhci_bulk_xfers_q_tail->link_ptr = HC_END_OF_LIST;
3607 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3608 "uhci_handle_bulk_td_errors: count = %d",
3609 uhcip->uhci_pending_bulk_cmds);
3610 }
3611
3612 uhci_hcdi_callback(uhcip, pp, ph, tw, usb_err);
3613 uhci_deallocate_tw(uhcip, pp, tw);
3614 }
3615
3616
3617 /*
3618 * uhci_get_bulk_td_by_paddr:
3619 * Obtain the address of the TD pool the physical address falls in.
3620 *
3621 * td_pool_pp - pointer to the address of the TD pool containing the paddr
3622 */
3623 /* ARGSUSED */
3624 static void
uhci_get_bulk_td_by_paddr(uhci_state_t * uhcip,uhci_bulk_isoc_xfer_t * info,uint32_t paddr,uhci_bulk_isoc_td_pool_t ** td_pool_pp)3625 uhci_get_bulk_td_by_paddr(
3626 uhci_state_t *uhcip,
3627 uhci_bulk_isoc_xfer_t *info,
3628 uint32_t paddr,
3629 uhci_bulk_isoc_td_pool_t **td_pool_pp)
3630 {
3631 uint_t i = 0;
3632
3633 while (i < info->num_pools) {
3634 *td_pool_pp = &info->td_pools[i];
3635 if (((*td_pool_pp)->cookie.dmac_address <= paddr) &&
3636 (((*td_pool_pp)->cookie.dmac_address +
3637 (*td_pool_pp)->cookie.dmac_size) > paddr)) {
3638
3639 break;
3640 }
3641 i++;
3642 }
3643
3644 ASSERT(i < info->num_pools);
3645 }
3646
3647
3648 void
uhci_remove_bulk_tds_tws(uhci_state_t * uhcip,uhci_pipe_private_t * pp,int what)3649 uhci_remove_bulk_tds_tws(
3650 uhci_state_t *uhcip,
3651 uhci_pipe_private_t *pp,
3652 int what)
3653 {
3654 uint_t rval, i;
3655 uhci_td_t *head;
3656 uhci_td_t *head_next;
3657 usb_opaque_t curr_reqp;
3658 uhci_bulk_isoc_xfer_t *info;
3659 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3660
3661 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3662
3663 if ((info = pp->pp_qh->bulk_xfer_info) == NULL) {
3664
3665 return;
3666 }
3667
3668 head = uhcip->uhci_outst_tds_head;
3669
3670 while (head) {
3671 uhci_trans_wrapper_t *tw_tmp = head->tw;
3672 head_next = head->outst_td_next;
3673
3674 if (pp->pp_qh == tw_tmp->tw_pipe_private->pp_qh) {
3675 curr_reqp = tw_tmp->tw_curr_xfer_reqp;
3676 if (curr_reqp &&
3677 ((what == UHCI_IN_CLOSE) ||
3678 (what == UHCI_IN_RESET))) {
3679 uhci_hcdi_callback(uhcip, pp,
3680 pp->pp_pipe_handle,
3681 tw_tmp, USB_CR_FLUSHED);
3682 } /* end of curr_reqp */
3683
3684 uhci_delete_td(uhcip, head);
3685
3686 if (what == UHCI_IN_CLOSE || what == UHCI_IN_RESET) {
3687 ASSERT(info->num_tds > 0);
3688 if (--info->num_tds == 0) {
3689 uhci_deallocate_tw(uhcip, pp, tw_tmp);
3690
3691 /*
3692 * This will make sure that the HC
3693 * does not loop anymore when there
3694 * are no pending bulk commands.
3695 */
3696 if (--uhcip->uhci_pending_bulk_cmds
3697 == 0) {
3698 uhcip->uhci_bulk_xfers_q_tail->
3699 link_ptr = HC_END_OF_LIST;
3700 USB_DPRINTF_L3(PRINT_MASK_ATTA,
3701 uhcip->uhci_log_hdl,
3702 "uhci_remove_bulk_tds_tws:"
3703 " count = %d",
3704 uhcip->
3705 uhci_pending_bulk_cmds);
3706 }
3707 }
3708 }
3709 }
3710
3711 head = head_next;
3712 }
3713
3714 if (what == UHCI_IN_CLOSE || what == UHCI_IN_RESET) {
3715 ASSERT(info->num_tds == 0);
3716 }
3717
3718 for (i = 0; i < info->num_pools; i++) {
3719 td_pool_ptr = &info->td_pools[i];
3720 rval = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
3721 ASSERT(rval == DDI_SUCCESS);
3722 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
3723 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
3724 }
3725 kmem_free(info->td_pools, (sizeof (uhci_bulk_isoc_td_pool_t) *
3726 info->num_pools));
3727 kmem_free(info, sizeof (uhci_bulk_isoc_xfer_t));
3728 pp->pp_qh->bulk_xfer_info = NULL;
3729 }
3730
3731
3732 /*
3733 * uhci_save_data_toggle ()
3734 * Save the data toggle in the usba_device structure
3735 */
3736 void
uhci_save_data_toggle(uhci_pipe_private_t * pp)3737 uhci_save_data_toggle(uhci_pipe_private_t *pp)
3738 {
3739 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
3740
3741 /* Save the data toggle in the usb devices structure. */
3742 mutex_enter(&ph->p_mutex);
3743 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
3744 pp->pp_data_toggle);
3745 mutex_exit(&ph->p_mutex);
3746 }
3747
3748 /*
3749 * uhci_create_isoc_transfer_wrapper:
3750 * Create a Transaction Wrapper (TW) for isoc transfer.
3751 * This involves the allocating of DMA resources.
3752 *
3753 * For isoc transfers, one isoc transfer includes multiple packets
3754 * and each packet may have a different length. So each packet is
3755 * transfered by one TD. We only know the individual packet length
3756 * won't exceed 1023 bytes, but we don't know exactly the lengths.
3757 * It is hard to make one physically discontiguous DMA buffer which
3758 * can fit in all the TDs like what can be done to the ctrl/bulk/
3759 * intr transfers. It is also undesirable to make one physically
3760 * contiguous DMA buffer for all the packets, since this may easily
3761 * fail when the system is in low memory. So an individual DMA
3762 * buffer is allocated for an individual isoc packet and each DMA
3763 * buffer is physically contiguous. An extra structure is allocated
3764 * to save the multiple DMA handles.
3765 */
3766 static uhci_trans_wrapper_t *
uhci_create_isoc_transfer_wrapper(uhci_state_t * uhcip,uhci_pipe_private_t * pp,usb_isoc_req_t * req,size_t length,usb_flags_t usb_flags)3767 uhci_create_isoc_transfer_wrapper(
3768 uhci_state_t *uhcip,
3769 uhci_pipe_private_t *pp,
3770 usb_isoc_req_t *req,
3771 size_t length,
3772 usb_flags_t usb_flags)
3773 {
3774 int result;
3775 size_t real_length, strtlen, xfer_size;
3776 uhci_trans_wrapper_t *tw;
3777 ddi_device_acc_attr_t dev_attr;
3778 ddi_dma_attr_t dma_attr;
3779 int kmem_flag;
3780 int (*dmamem_wait)(caddr_t);
3781 uint_t i, j, ccount;
3782 usb_isoc_req_t *tmp_req = req;
3783
3784 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3785
3786 if (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep) != USB_EP_ATTR_ISOCH) {
3787
3788 return (NULL);
3789 }
3790
3791 if ((req == NULL) && (UHCI_XFER_DIR(&pp->pp_pipe_handle->p_ep) ==
3792 USB_EP_DIR_IN)) {
3793 tmp_req = (usb_isoc_req_t *)pp->pp_client_periodic_in_reqp;
3794 }
3795
3796 if (tmp_req == NULL) {
3797
3798 return (NULL);
3799 }
3800
3801
3802 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3803 "uhci_create_isoc_transfer_wrapper: length = 0x%lx flags = 0x%x",
3804 length, usb_flags);
3805
3806 /* SLEEP flag should not be used in interrupt context */
3807 if (servicing_interrupt()) {
3808 kmem_flag = KM_NOSLEEP;
3809 dmamem_wait = DDI_DMA_DONTWAIT;
3810 } else {
3811 kmem_flag = KM_SLEEP;
3812 dmamem_wait = DDI_DMA_SLEEP;
3813 }
3814
3815 /* Allocate space for the transfer wrapper */
3816 if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), kmem_flag)) ==
3817 NULL) {
3818 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3819 "uhci_create_isoc_transfer_wrapper: kmem_alloc failed");
3820
3821 return (NULL);
3822 }
3823
3824 /* Allocate space for the isoc buffer handles */
3825 strtlen = sizeof (uhci_isoc_buf_t) * tmp_req->isoc_pkts_count;
3826 if ((tw->tw_isoc_bufs = kmem_zalloc(strtlen, kmem_flag)) == NULL) {
3827 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3828 "uhci_create_isoc_transfer_wrapper: kmem_alloc "
3829 "isoc buffer failed");
3830 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3831
3832 return (NULL);
3833 }
3834
3835 bcopy(&uhcip->uhci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
3836 dma_attr.dma_attr_sgllen = 1;
3837
3838 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3839 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
3840 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3841
3842 /* Store the transfer length */
3843 tw->tw_length = length;
3844
3845 for (i = 0; i < tmp_req->isoc_pkts_count; i++) {
3846 tw->tw_isoc_bufs[i].index = (ushort_t)i;
3847
3848 /* Allocate the DMA handle */
3849 if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip, &dma_attr,
3850 dmamem_wait, 0, &tw->tw_isoc_bufs[i].dma_handle)) !=
3851 DDI_SUCCESS) {
3852 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3853 "uhci_create_isoc_transfer_wrapper: "
3854 "Alloc handle %d failed", i);
3855
3856 for (j = 0; j < i; j++) {
3857 result = ddi_dma_unbind_handle(
3858 tw->tw_isoc_bufs[j].dma_handle);
3859 ASSERT(result == USB_SUCCESS);
3860 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3861 mem_handle);
3862 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3863 dma_handle);
3864 }
3865 kmem_free(tw->tw_isoc_bufs, strtlen);
3866 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3867
3868 return (NULL);
3869 }
3870
3871 /* Allocate the memory */
3872 xfer_size = tmp_req->isoc_pkt_descr[i].isoc_pkt_length;
3873 if ((result = ddi_dma_mem_alloc(tw->tw_isoc_bufs[i].dma_handle,
3874 xfer_size, &dev_attr, DDI_DMA_CONSISTENT, dmamem_wait,
3875 NULL, (caddr_t *)&tw->tw_isoc_bufs[i].buf_addr,
3876 &real_length, &tw->tw_isoc_bufs[i].mem_handle)) !=
3877 DDI_SUCCESS) {
3878 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3879 "uhci_create_isoc_transfer_wrapper: "
3880 "dma_mem_alloc %d fail", i);
3881 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
3882
3883 for (j = 0; j < i; j++) {
3884 result = ddi_dma_unbind_handle(
3885 tw->tw_isoc_bufs[j].dma_handle);
3886 ASSERT(result == USB_SUCCESS);
3887 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3888 mem_handle);
3889 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3890 dma_handle);
3891 }
3892 kmem_free(tw->tw_isoc_bufs, strtlen);
3893 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3894
3895 return (NULL);
3896 }
3897
3898 ASSERT(real_length >= xfer_size);
3899
3900 /* Bind the handle */
3901 result = ddi_dma_addr_bind_handle(
3902 tw->tw_isoc_bufs[i].dma_handle, NULL,
3903 (caddr_t)tw->tw_isoc_bufs[i].buf_addr, real_length,
3904 DDI_DMA_RDWR|DDI_DMA_CONSISTENT, dmamem_wait, NULL,
3905 &tw->tw_isoc_bufs[i].cookie, &ccount);
3906
3907 if ((result == DDI_DMA_MAPPED) && (ccount == 1)) {
3908 tw->tw_isoc_bufs[i].length = xfer_size;
3909
3910 continue;
3911 } else {
3912 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3913 "uhci_create_isoc_transfer_wrapper: "
3914 "Bind handle %d failed", i);
3915 if (result == DDI_DMA_MAPPED) {
3916 result = ddi_dma_unbind_handle(
3917 tw->tw_isoc_bufs[i].dma_handle);
3918 ASSERT(result == USB_SUCCESS);
3919 }
3920 ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
3921 ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
3922
3923 for (j = 0; j < i; j++) {
3924 result = ddi_dma_unbind_handle(
3925 tw->tw_isoc_bufs[j].dma_handle);
3926 ASSERT(result == USB_SUCCESS);
3927 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3928 mem_handle);
3929 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3930 dma_handle);
3931 }
3932 kmem_free(tw->tw_isoc_bufs, strtlen);
3933 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3934
3935 return (NULL);
3936 }
3937 }
3938
3939 tw->tw_ncookies = tmp_req->isoc_pkts_count;
3940 tw->tw_isoc_strtlen = strtlen;
3941
3942 /*
3943 * Only allow one wrapper to be added at a time. Insert the
3944 * new transaction wrapper into the list for this pipe.
3945 */
3946 if (pp->pp_tw_head == NULL) {
3947 pp->pp_tw_head = tw;
3948 pp->pp_tw_tail = tw;
3949 } else {
3950 pp->pp_tw_tail->tw_next = tw;
3951 pp->pp_tw_tail = tw;
3952 ASSERT(tw->tw_next == NULL);
3953 }
3954
3955 /* Store a back pointer to the pipe private structure */
3956 tw->tw_pipe_private = pp;
3957
3958 /* Store the transfer type - synchronous or asynchronous */
3959 tw->tw_flags = usb_flags;
3960
3961 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3962 "uhci_create_isoc_transfer_wrapper: tw = 0x%p, ncookies = %u",
3963 (void *)tw, tw->tw_ncookies);
3964
3965 return (tw);
3966 }
3967
3968 /*
3969 * uhci_insert_isoc_td:
3970 * - Create transfer wrapper
3971 * - Allocate memory for the isoc td's
3972 * - Fill up all the TD's and submit to the HC
3973 * - Update all the linked lists
3974 */
3975 int
uhci_insert_isoc_td(uhci_state_t * uhcip,usba_pipe_handle_data_t * ph,usb_isoc_req_t * isoc_req,size_t length,usb_flags_t flags)3976 uhci_insert_isoc_td(
3977 uhci_state_t *uhcip,
3978 usba_pipe_handle_data_t *ph,
3979 usb_isoc_req_t *isoc_req,
3980 size_t length,
3981 usb_flags_t flags)
3982 {
3983 int rval = USB_SUCCESS;
3984 int error;
3985 uint_t ddic;
3986 uint32_t i, j, index;
3987 uint32_t bytes_to_xfer;
3988 uint32_t expired_frames = 0;
3989 usb_frame_number_t start_frame, end_frame, current_frame;
3990 uhci_td_t *td_ptr;
3991 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
3992 uhci_trans_wrapper_t *tw;
3993 uhci_bulk_isoc_xfer_t *isoc_xfer_info;
3994 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3995
3996 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
3997 "uhci_insert_isoc_td: ph = 0x%p isoc req = %p length = %lu",
3998 (void *)ph, (void *)isoc_req, length);
3999
4000 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4001
4002 /* Allocate a transfer wrapper */
4003 if ((tw = uhci_create_isoc_transfer_wrapper(uhcip, pp, isoc_req,
4004 length, flags)) == NULL) {
4005 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4006 "uhci_insert_isoc_td: TW allocation failed");
4007
4008 return (USB_NO_RESOURCES);
4009 }
4010
4011 /* Save current isochronous request pointer */
4012 tw->tw_curr_xfer_reqp = (usb_opaque_t)isoc_req;
4013
4014 /*
4015 * Initialize the transfer wrapper. These values are useful
4016 * for sending back the reply.
4017 */
4018 tw->tw_handle_td = uhci_handle_isoc_td;
4019 tw->tw_handle_callback_value = NULL;
4020 tw->tw_direction = (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) ?
4021 PID_OUT : PID_IN;
4022
4023 /*
4024 * If the transfer isoc send, then copy the data from the request
4025 * to the transfer wrapper.
4026 */
4027 if ((tw->tw_direction == PID_OUT) && length) {
4028 uchar_t *p;
4029
4030 ASSERT(isoc_req->isoc_data != NULL);
4031 p = isoc_req->isoc_data->b_rptr;
4032
4033 /* Copy the data into the message */
4034 for (i = 0; i < isoc_req->isoc_pkts_count; i++) {
4035 ddi_rep_put8(tw->tw_isoc_bufs[i].mem_handle,
4036 p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
4037 isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
4038 DDI_DEV_AUTOINCR);
4039 p += isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
4040 }
4041 }
4042
4043 if (tw->tw_direction == PID_IN) {
4044 if ((rval = uhci_allocate_periodic_in_resource(uhcip, pp, tw,
4045 flags)) != USB_SUCCESS) {
4046 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4047 "uhci_insert_isoc_td: isoc_req_t alloc failed");
4048 uhci_deallocate_tw(uhcip, pp, tw);
4049
4050 return (rval);
4051 }
4052
4053 isoc_req = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
4054 }
4055
4056 tw->tw_isoc_req = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
4057
4058 /* Get the pointer to the isoc_xfer_info structure */
4059 isoc_xfer_info = (uhci_bulk_isoc_xfer_t *)&tw->tw_xfer_info;
4060 isoc_xfer_info->num_tds = isoc_req->isoc_pkts_count;
4061
4062 /*
4063 * Allocate memory for isoc tds
4064 */
4065 if ((rval = uhci_alloc_bulk_isoc_tds(uhcip, isoc_req->isoc_pkts_count,
4066 isoc_xfer_info)) != USB_SUCCESS) {
4067 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4068 "uhci_alloc_bulk_isoc_td: Memory allocation failure");
4069
4070 if (tw->tw_direction == PID_IN) {
4071 uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
4072 }
4073 uhci_deallocate_tw(uhcip, pp, tw);
4074
4075 return (rval);
4076 }
4077
4078 /*
4079 * Get the isoc td pool address, buffer address and
4080 * max packet size that the device supports.
4081 */
4082 td_pool_ptr = &isoc_xfer_info->td_pools[0];
4083 td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
4084 index = 0;
4085
4086 /*
4087 * Fill up the isoc tds
4088 */
4089 USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4090 "uhci_insert_isoc_td : isoc pkts %d", isoc_req->isoc_pkts_count);
4091
4092 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4093 for (j = 0; j < td_pool_ptr->num_tds; j++) {
4094 bytes_to_xfer =
4095 isoc_req->isoc_pkt_descr[index].isoc_pkt_length;
4096
4097 uhci_fill_in_bulk_isoc_td(uhcip, &td_ptr[j],
4098 (uhci_td_t *)NULL, HC_END_OF_LIST, ph, index,
4099 bytes_to_xfer, tw);
4100 td_ptr[j].isoc_pkt_index = (ushort_t)index;
4101 index++;
4102 }
4103
4104 if (i < (isoc_xfer_info->num_pools - 1)) {
4105 td_pool_ptr = &isoc_xfer_info->td_pools[i + 1];
4106 td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
4107 }
4108 }
4109
4110 /*
4111 * Get the starting frame number.
4112 * The client drivers sets the flag USB_ATTRS_ISOC_XFER_ASAP to inform
4113 * the HCD to care of starting frame number.
4114 *
4115 * Following code is very time critical. So, perform atomic execution.
4116 */
4117 ddic = ddi_enter_critical();
4118 current_frame = uhci_get_sw_frame_number(uhcip);
4119
4120 if (isoc_req->isoc_attributes & USB_ATTRS_ISOC_START_FRAME) {
4121 start_frame = isoc_req->isoc_frame_no;
4122 end_frame = start_frame + isoc_req->isoc_pkts_count;
4123
4124 /* Check available frames */
4125 if ((end_frame - current_frame) < UHCI_MAX_ISOC_FRAMES) {
4126 if (current_frame > start_frame) {
4127 if ((current_frame + FRNUM_OFFSET) <
4128 end_frame) {
4129 expired_frames = current_frame +
4130 FRNUM_OFFSET - start_frame;
4131 start_frame = current_frame +
4132 FRNUM_OFFSET;
4133 } else {
4134 rval = USB_INVALID_START_FRAME;
4135 }
4136 }
4137 } else {
4138 rval = USB_INVALID_START_FRAME;
4139 }
4140
4141 } else if (isoc_req->isoc_attributes & USB_ATTRS_ISOC_XFER_ASAP) {
4142 start_frame = pp->pp_frame_num;
4143
4144 if (start_frame == INVALID_FRNUM) {
4145 start_frame = current_frame + FRNUM_OFFSET;
4146 } else if (current_frame > start_frame) {
4147 start_frame = current_frame + FRNUM_OFFSET;
4148 }
4149
4150 end_frame = start_frame + isoc_req->isoc_pkts_count;
4151 isoc_req->isoc_frame_no = start_frame;
4152
4153 }
4154
4155 if (rval != USB_SUCCESS) {
4156
4157 /* Exit the critical */
4158 ddi_exit_critical(ddic);
4159
4160 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4161 "uhci_insert_isoc_td: Invalid starting frame number");
4162
4163 if (tw->tw_direction == PID_IN) {
4164 uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
4165 }
4166
4167 while (tw->tw_hctd_head) {
4168 uhci_delete_td(uhcip, tw->tw_hctd_head);
4169 }
4170
4171 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4172 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4173 error = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
4174 ASSERT(error == DDI_SUCCESS);
4175 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4176 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4177 }
4178 kmem_free(isoc_xfer_info->td_pools,
4179 (sizeof (uhci_bulk_isoc_td_pool_t) *
4180 isoc_xfer_info->num_pools));
4181
4182 uhci_deallocate_tw(uhcip, pp, tw);
4183
4184 return (rval);
4185 }
4186
4187 for (i = 0; i < expired_frames; i++) {
4188 isoc_req->isoc_pkt_descr[i].isoc_pkt_status =
4189 USB_CR_NOT_ACCESSED;
4190 isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length =
4191 isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
4192 uhci_get_isoc_td_by_index(uhcip, isoc_xfer_info, i,
4193 &td_ptr, &td_pool_ptr);
4194 uhci_delete_td(uhcip, td_ptr);
4195 --isoc_xfer_info->num_tds;
4196 }
4197
4198 /*
4199 * Add the TD's to the HC list
4200 */
4201 start_frame = (start_frame & 0x3ff);
4202 for (; i < isoc_req->isoc_pkts_count; i++) {
4203 uhci_get_isoc_td_by_index(uhcip, isoc_xfer_info, i,
4204 &td_ptr, &td_pool_ptr);
4205 if (uhcip->uhci_isoc_q_tailp[start_frame]) {
4206 td_ptr->isoc_prev =
4207 uhcip->uhci_isoc_q_tailp[start_frame];
4208 td_ptr->isoc_next = NULL;
4209 td_ptr->link_ptr =
4210 uhcip->uhci_isoc_q_tailp[start_frame]->link_ptr;
4211 uhcip->uhci_isoc_q_tailp[start_frame]->isoc_next =
4212 td_ptr;
4213 SetTD32(uhcip,
4214 uhcip->uhci_isoc_q_tailp[start_frame]->link_ptr,
4215 ISOCTD_PADDR(td_pool_ptr, td_ptr));
4216 uhcip->uhci_isoc_q_tailp[start_frame] = td_ptr;
4217 } else {
4218 uhcip->uhci_isoc_q_tailp[start_frame] = td_ptr;
4219 td_ptr->isoc_next = NULL;
4220 td_ptr->isoc_prev = NULL;
4221 SetTD32(uhcip, td_ptr->link_ptr,
4222 GetFL32(uhcip,
4223 uhcip->uhci_frame_lst_tablep[start_frame]));
4224 SetFL32(uhcip,
4225 uhcip->uhci_frame_lst_tablep[start_frame],
4226 ISOCTD_PADDR(td_pool_ptr, td_ptr));
4227 }
4228 td_ptr->starting_frame = (uint_t)start_frame;
4229
4230 if (++start_frame == NUM_FRAME_LST_ENTRIES)
4231 start_frame = 0;
4232 }
4233
4234 ddi_exit_critical(ddic);
4235 pp->pp_frame_num = end_frame;
4236
4237 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4238 "uhci_insert_isoc_td: current frame number 0x%llx, pipe frame num"
4239 " 0x%llx", (unsigned long long)current_frame,
4240 (unsigned long long)(pp->pp_frame_num));
4241
4242 return (rval);
4243 }
4244
4245
4246 /*
4247 * uhci_get_isoc_td_by_index:
4248 * Obtain the addresses of the TD pool and the TD at the index.
4249 *
4250 * tdpp - pointer to the address of the TD at the isoc packet index
4251 * td_pool_pp - pointer to the address of the TD pool containing
4252 * the specified TD
4253 */
4254 /* ARGSUSED */
4255 static void
uhci_get_isoc_td_by_index(uhci_state_t * uhcip,uhci_bulk_isoc_xfer_t * info,uint_t index,uhci_td_t ** tdpp,uhci_bulk_isoc_td_pool_t ** td_pool_pp)4256 uhci_get_isoc_td_by_index(
4257 uhci_state_t *uhcip,
4258 uhci_bulk_isoc_xfer_t *info,
4259 uint_t index,
4260 uhci_td_t **tdpp,
4261 uhci_bulk_isoc_td_pool_t **td_pool_pp)
4262 {
4263 uint_t i = 0, j = 0;
4264 uhci_td_t *td_ptr;
4265
4266 while (j < info->num_pools) {
4267 if ((i + info->td_pools[j].num_tds) <= index) {
4268 i += info->td_pools[j].num_tds;
4269 j++;
4270 } else {
4271 i = index - i;
4272
4273 break;
4274 }
4275 }
4276
4277 ASSERT(j < info->num_pools);
4278 *td_pool_pp = &info->td_pools[j];
4279 td_ptr = (uhci_td_t *)((*td_pool_pp)->pool_addr);
4280 *tdpp = &td_ptr[i];
4281 }
4282
4283
4284 /*
4285 * uhci_handle_isoc_td:
4286 * Handles the completed isoc tds
4287 */
4288 void
uhci_handle_isoc_td(uhci_state_t * uhcip,uhci_td_t * td)4289 uhci_handle_isoc_td(uhci_state_t *uhcip, uhci_td_t *td)
4290 {
4291 uint_t rval, i;
4292 uint32_t pkt_index = td->isoc_pkt_index;
4293 usb_cr_t cr;
4294 uhci_trans_wrapper_t *tw = td->tw;
4295 usb_isoc_req_t *isoc_req = (usb_isoc_req_t *)tw->tw_isoc_req;
4296 uhci_pipe_private_t *pp = tw->tw_pipe_private;
4297 uhci_bulk_isoc_xfer_t *isoc_xfer_info = &tw->tw_xfer_info;
4298 usba_pipe_handle_data_t *usb_pp;
4299 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
4300
4301 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4302 "uhci_handle_isoc_td: td = 0x%p, pp = 0x%p, tw = 0x%p, req = 0x%p, "
4303 "index = %x", (void *)td, (void *)pp, (void *)tw, (void *)isoc_req,
4304 pkt_index);
4305
4306 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4307
4308 usb_pp = pp->pp_pipe_handle;
4309
4310 /*
4311 * Check whether there are any errors occurred. If so, update error
4312 * count and return it to the upper.But never return a non zero
4313 * completion reason.
4314 */
4315 cr = USB_CR_OK;
4316 if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
4317 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4318 "uhci_handle_isoc_td: Error Occurred: TD Status = %x",
4319 GetTD_status(uhcip, td));
4320 isoc_req->isoc_error_count++;
4321 }
4322
4323 if (isoc_req != NULL) {
4324 isoc_req->isoc_pkt_descr[pkt_index].isoc_pkt_status = cr;
4325 isoc_req->isoc_pkt_descr[pkt_index].isoc_pkt_actual_length =
4326 (GetTD_alen(uhcip, td) == ZERO_LENGTH) ? 0 :
4327 GetTD_alen(uhcip, td) + 1;
4328 }
4329
4330 uhci_delete_isoc_td(uhcip, td);
4331
4332 if (--isoc_xfer_info->num_tds != 0) {
4333 USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4334 "uhci_handle_isoc_td: Number of TDs %d",
4335 isoc_xfer_info->num_tds);
4336
4337 return;
4338 }
4339
4340 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
4341 if (tw->tw_direction == PID_IN) {
4342 uhci_sendup_td_message(uhcip, cr, tw);
4343
4344 if ((uhci_handle_isoc_receive(uhcip, pp, tw)) != USB_SUCCESS) {
4345 USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4346 "uhci_handle_isoc_td: Drop message");
4347 }
4348
4349 } else {
4350 /* update kstats only for OUT. sendup_td_msg() does it for IN */
4351 uhci_do_byte_stats(uhcip, tw->tw_length,
4352 usb_pp->p_ep.bmAttributes, usb_pp->p_ep.bEndpointAddress);
4353
4354 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, USB_CR_OK);
4355 }
4356
4357 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4358 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4359 rval = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
4360 ASSERT(rval == DDI_SUCCESS);
4361 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4362 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4363 }
4364 kmem_free(isoc_xfer_info->td_pools,
4365 (sizeof (uhci_bulk_isoc_td_pool_t) *
4366 isoc_xfer_info->num_pools));
4367 uhci_deallocate_tw(uhcip, pp, tw);
4368 }
4369
4370
4371 /*
4372 * uhci_handle_isoc_receive:
4373 * - Sends the isoc data to the client
4374 * - Inserts another isoc receive request
4375 */
4376 static int
uhci_handle_isoc_receive(uhci_state_t * uhcip,uhci_pipe_private_t * pp,uhci_trans_wrapper_t * tw)4377 uhci_handle_isoc_receive(
4378 uhci_state_t *uhcip,
4379 uhci_pipe_private_t *pp,
4380 uhci_trans_wrapper_t *tw)
4381 {
4382 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4383 "uhci_handle_isoc_receive: tw = 0x%p", (void *)tw);
4384
4385 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4386
4387 /*
4388 * -- check for pipe state being polling before
4389 * inserting a new request. Check when is TD
4390 * de-allocation being done? (so we can reuse the same TD)
4391 */
4392 if (uhci_start_isoc_receive_polling(uhcip,
4393 pp->pp_pipe_handle, (usb_isoc_req_t *)tw->tw_curr_xfer_reqp,
4394 0) != USB_SUCCESS) {
4395 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4396 "uhci_handle_isoc_receive: receive polling failed");
4397
4398 return (USB_FAILURE);
4399 }
4400
4401 return (USB_SUCCESS);
4402 }
4403
4404
4405 /*
4406 * uhci_delete_isoc_td:
4407 * - Delete from the outstanding command queue
4408 * - Delete from the tw queue
4409 * - Delete from the isoc queue
4410 * - Delete from the HOST CONTROLLER list
4411 */
4412 static void
uhci_delete_isoc_td(uhci_state_t * uhcip,uhci_td_t * td)4413 uhci_delete_isoc_td(uhci_state_t *uhcip, uhci_td_t *td)
4414 {
4415 uint32_t starting_frame = td->starting_frame;
4416
4417 if ((td->isoc_next == NULL) && (td->isoc_prev == NULL)) {
4418 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[starting_frame],
4419 GetTD32(uhcip, td->link_ptr));
4420 uhcip->uhci_isoc_q_tailp[starting_frame] = 0;
4421 } else if (td->isoc_next == NULL) {
4422 td->isoc_prev->link_ptr = td->link_ptr;
4423 td->isoc_prev->isoc_next = NULL;
4424 uhcip->uhci_isoc_q_tailp[starting_frame] = td->isoc_prev;
4425 } else if (td->isoc_prev == NULL) {
4426 td->isoc_next->isoc_prev = NULL;
4427 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[starting_frame],
4428 GetTD32(uhcip, td->link_ptr));
4429 } else {
4430 td->isoc_prev->isoc_next = td->isoc_next;
4431 td->isoc_next->isoc_prev = td->isoc_prev;
4432 td->isoc_prev->link_ptr = td->link_ptr;
4433 }
4434
4435 uhci_delete_td(uhcip, td);
4436 }
4437
4438
4439 /*
4440 * uhci_send_isoc_receive
4441 * - Allocates usb_isoc_request
4442 * - Updates the isoc request
4443 * - Inserts the isoc td's into the HC processing list.
4444 */
4445 int
uhci_start_isoc_receive_polling(uhci_state_t * uhcip,usba_pipe_handle_data_t * ph,usb_isoc_req_t * isoc_req,usb_flags_t usb_flags)4446 uhci_start_isoc_receive_polling(
4447 uhci_state_t *uhcip,
4448 usba_pipe_handle_data_t *ph,
4449 usb_isoc_req_t *isoc_req,
4450 usb_flags_t usb_flags)
4451 {
4452 int ii, error;
4453 size_t max_isoc_xfer_size, length, isoc_pkts_length;
4454 ushort_t isoc_pkt_count;
4455 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
4456 usb_isoc_pkt_descr_t *isoc_pkt_descr;
4457
4458 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4459 "uhci_start_isoc_receive_polling: usb_flags = %x", usb_flags);
4460
4461 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4462
4463 max_isoc_xfer_size = ph->p_ep.wMaxPacketSize * UHCI_MAX_ISOC_PKTS;
4464
4465 if (isoc_req) {
4466 isoc_pkt_descr = isoc_req->isoc_pkt_descr;
4467 isoc_pkt_count = isoc_req->isoc_pkts_count;
4468 isoc_pkts_length = isoc_req->isoc_pkts_length;
4469 } else {
4470 isoc_pkt_descr = ((usb_isoc_req_t *)
4471 pp->pp_client_periodic_in_reqp)->isoc_pkt_descr;
4472 isoc_pkt_count = ((usb_isoc_req_t *)
4473 pp->pp_client_periodic_in_reqp)->isoc_pkts_count;
4474 isoc_pkts_length = ((usb_isoc_req_t *)
4475 pp->pp_client_periodic_in_reqp)->isoc_pkts_length;
4476 }
4477
4478 for (ii = 0, length = 0; ii < isoc_pkt_count; ii++) {
4479 length += isoc_pkt_descr->isoc_pkt_length;
4480 isoc_pkt_descr++;
4481 }
4482
4483 if ((isoc_pkts_length) && (isoc_pkts_length != length)) {
4484
4485 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4486 "uhci_start_isoc_receive_polling: isoc_pkts_length 0x%lx "
4487 "is not equal to the sum of all pkt lengths 0x%lx in "
4488 "an isoc request", isoc_pkts_length, length);
4489
4490 return (USB_FAILURE);
4491 }
4492
4493 /* Check the size of isochronous request */
4494 if (length > max_isoc_xfer_size) {
4495 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4496 "uhci_start_isoc_receive_polling: "
4497 "Max isoc request size = %lx, Given isoc req size = %lx",
4498 max_isoc_xfer_size, length);
4499
4500 return (USB_FAILURE);
4501 }
4502
4503 /* Add the TD into the Host Controller's isoc list */
4504 error = uhci_insert_isoc_td(uhcip, ph, isoc_req, length, usb_flags);
4505
4506 return (error);
4507 }
4508
4509
4510 /*
4511 * uhci_remove_isoc_tds_tws
4512 * This routine scans the pipe and removes all the td's
4513 * and transfer wrappers and deallocates the memory
4514 * associated with those td's and tw's.
4515 */
4516 void
uhci_remove_isoc_tds_tws(uhci_state_t * uhcip,uhci_pipe_private_t * pp)4517 uhci_remove_isoc_tds_tws(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
4518 {
4519 uint_t rval, i;
4520 uhci_td_t *tmp_td, *td_head;
4521 usb_isoc_req_t *isoc_req;
4522 uhci_trans_wrapper_t *tmp_tw, *tw_head;
4523 uhci_bulk_isoc_xfer_t *isoc_xfer_info;
4524 uhci_bulk_isoc_td_pool_t *td_pool_ptr;
4525
4526 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4527 "uhci_remove_isoc_tds_tws: pp = %p", (void *)pp);
4528
4529 tw_head = pp->pp_tw_head;
4530 while (tw_head) {
4531 tmp_tw = tw_head;
4532 tw_head = tw_head->tw_next;
4533 td_head = tmp_tw->tw_hctd_head;
4534 if (tmp_tw->tw_direction == PID_IN) {
4535 uhci_deallocate_periodic_in_resource(uhcip, pp,
4536 tmp_tw);
4537 } else if (tmp_tw->tw_direction == PID_OUT) {
4538 uhci_hcdi_callback(uhcip, pp, pp->pp_pipe_handle,
4539 tmp_tw, USB_CR_FLUSHED);
4540 }
4541
4542 while (td_head) {
4543 tmp_td = td_head;
4544 td_head = td_head->tw_td_next;
4545 uhci_delete_isoc_td(uhcip, tmp_td);
4546 }
4547
4548 isoc_req = (usb_isoc_req_t *)tmp_tw->tw_isoc_req;
4549 if (isoc_req) {
4550 usb_free_isoc_req(isoc_req);
4551 }
4552
4553 ASSERT(tmp_tw->tw_hctd_head == NULL);
4554
4555 if (tmp_tw->tw_xfer_info.td_pools) {
4556 isoc_xfer_info =
4557 (uhci_bulk_isoc_xfer_t *)&tmp_tw->tw_xfer_info;
4558 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4559 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4560 rval = ddi_dma_unbind_handle(
4561 td_pool_ptr->dma_handle);
4562 ASSERT(rval == DDI_SUCCESS);
4563 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4564 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4565 }
4566 kmem_free(isoc_xfer_info->td_pools,
4567 (sizeof (uhci_bulk_isoc_td_pool_t) *
4568 isoc_xfer_info->num_pools));
4569 }
4570
4571 uhci_deallocate_tw(uhcip, pp, tmp_tw);
4572 }
4573 }
4574
4575
4576 /*
4577 * uhci_isoc_update_sw_frame_number()
4578 * to avoid code duplication, call uhci_get_sw_frame_number()
4579 */
4580 void
uhci_isoc_update_sw_frame_number(uhci_state_t * uhcip)4581 uhci_isoc_update_sw_frame_number(uhci_state_t *uhcip)
4582 {
4583 (void) uhci_get_sw_frame_number(uhcip);
4584 }
4585
4586
4587 /*
4588 * uhci_get_sw_frame_number:
4589 * Hold the uhci_int_mutex before calling this routine.
4590 */
4591 uint64_t
uhci_get_sw_frame_number(uhci_state_t * uhcip)4592 uhci_get_sw_frame_number(uhci_state_t *uhcip)
4593 {
4594 uint64_t sw_frnum, hw_frnum, current_frnum;
4595
4596 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4597
4598 sw_frnum = uhcip->uhci_sw_frnum;
4599 hw_frnum = Get_OpReg16(FRNUM);
4600
4601 /*
4602 * Check bit 10 in the software counter and hardware frame counter.
4603 * If both are same, then don't increment the software frame counter
4604 * (Bit 10 of hw frame counter toggle for every 1024 frames)
4605 * The lower 11 bits of software counter contains the hardware frame
4606 * counter value. The MSB (bit 10) of software counter is incremented
4607 * for every 1024 frames either here or in get frame number routine.
4608 */
4609 if ((sw_frnum & UHCI_BIT_10_MASK) == (hw_frnum & UHCI_BIT_10_MASK)) {
4610 /* The MSB of hw counter did not toggle */
4611 current_frnum = ((sw_frnum & (SW_FRNUM_MASK)) | hw_frnum);
4612 } else {
4613 /*
4614 * The hw counter wrapped around. And the interrupt handler
4615 * did not get a chance to update the sw frame counter.
4616 * So, update the sw frame counter and return correct frame no.
4617 */
4618 sw_frnum >>= UHCI_SIZE_OF_HW_FRNUM - 1;
4619 current_frnum =
4620 ((++sw_frnum << (UHCI_SIZE_OF_HW_FRNUM - 1)) | hw_frnum);
4621 }
4622 uhcip->uhci_sw_frnum = current_frnum;
4623
4624 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4625 "uhci_get_sw_frame_number: sw=%lld hd=%lld",
4626 (unsigned long long)(uhcip->uhci_sw_frnum),
4627 (unsigned long long)hw_frnum);
4628
4629 return (current_frnum);
4630 }
4631
4632
4633 /*
4634 * uhci_cmd_timeout_hdlr:
4635 * This routine will get called for every second. It checks for
4636 * timed out control commands/bulk commands. Timeout any commands
4637 * that exceeds the time out period specified by the pipe policy.
4638 */
4639 void
uhci_cmd_timeout_hdlr(void * arg)4640 uhci_cmd_timeout_hdlr(void *arg)
4641 {
4642 uint_t flag = B_FALSE;
4643 uhci_td_t *head, *tmp_td;
4644 uhci_state_t *uhcip = (uhci_state_t *)arg;
4645 uhci_pipe_private_t *pp;
4646
4647 /*
4648 * Check whether any of the control xfers are timed out.
4649 * If so, complete those commands with time out as reason.
4650 */
4651 mutex_enter(&uhcip->uhci_int_mutex);
4652 head = uhcip->uhci_outst_tds_head;
4653
4654 while (head) {
4655 /*
4656 * If timeout out is zero, then dont timeout command.
4657 */
4658 if (head->tw->tw_timeout_cnt == 0) {
4659 head = head->outst_td_next;
4660 continue;
4661 }
4662
4663 if (!(head->tw->tw_flags & TW_TIMEOUT_FLAG)) {
4664 head->tw->tw_flags |= TW_TIMEOUT_FLAG;
4665 --head->tw->tw_timeout_cnt;
4666 }
4667
4668 /* only do it for bulk and control TDs */
4669 if ((head->tw->tw_timeout_cnt == 0) &&
4670 (head->tw->tw_handle_td != uhci_handle_isoc_td)) {
4671
4672 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
4673 "Command timed out: td = %p", (void *)head);
4674
4675 head->tw->tw_claim = UHCI_TIMEOUT_HDLR_CLAIMED;
4676
4677 /*
4678 * Check finally whether the command completed
4679 */
4680 if (GetTD_status(uhcip, head) & UHCI_TD_ACTIVE) {
4681 SetTD32(uhcip, head->link_ptr,
4682 GetTD32(uhcip, head->link_ptr) |
4683 HC_END_OF_LIST);
4684 pp = head->tw->tw_pipe_private;
4685 SetQH32(uhcip, pp->pp_qh->element_ptr,
4686 GetQH32(uhcip, pp->pp_qh->element_ptr) |
4687 HC_END_OF_LIST);
4688 }
4689
4690 flag = B_TRUE;
4691 }
4692
4693 head = head->outst_td_next;
4694 }
4695
4696 if (flag) {
4697 (void) uhci_wait_for_sof(uhcip);
4698 }
4699
4700 head = uhcip->uhci_outst_tds_head;
4701 while (head) {
4702 if (head->tw->tw_flags & TW_TIMEOUT_FLAG) {
4703 head->tw->tw_flags &= ~TW_TIMEOUT_FLAG;
4704 }
4705 if (head->tw->tw_claim == UHCI_TIMEOUT_HDLR_CLAIMED) {
4706 head->tw->tw_claim = UHCI_NOT_CLAIMED;
4707 tmp_td = head->tw->tw_hctd_head;
4708 while (tmp_td) {
4709 SetTD_status(uhcip, tmp_td,
4710 UHCI_TD_CRC_TIMEOUT);
4711 tmp_td = tmp_td->tw_td_next;
4712 }
4713 }
4714 head = head->outst_td_next;
4715 }
4716
4717 /*
4718 * Process the td which was completed before shifting from normal
4719 * mode to polled mode
4720 */
4721 if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TRUE) {
4722 uhci_process_submitted_td_queue(uhcip);
4723 uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_FALSE;
4724 } else if (flag) {
4725 /* Process the completed/timed out commands */
4726 uhci_process_submitted_td_queue(uhcip);
4727 }
4728
4729 /* Re-register the control/bulk/intr commands' timeout handler */
4730 if (uhcip->uhci_cmd_timeout_id) {
4731 uhcip->uhci_cmd_timeout_id = timeout(uhci_cmd_timeout_hdlr,
4732 (void *)uhcip, UHCI_ONE_SECOND);
4733 }
4734
4735 mutex_exit(&uhcip->uhci_int_mutex);
4736 }
4737
4738
4739 /*
4740 * uhci_wait_for_sof:
4741 * Wait for the start of the next frame (implying any changes made in the
4742 * lattice have now taken effect).
4743 * To be sure this is the case, we wait for the completion of the current
4744 * frame (which might have already been pending), then another complete
4745 * frame to ensure everything has taken effect.
4746 */
4747 int
uhci_wait_for_sof(uhci_state_t * uhcip)4748 uhci_wait_for_sof(uhci_state_t *uhcip)
4749 {
4750 int n, error;
4751 ushort_t cmd_reg;
4752 usb_frame_number_t before_frame_number, after_frame_number;
4753 clock_t rval;
4754 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4755 "uhci_wait_for_sof: uhcip = %p", (void *)uhcip);
4756
4757 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4758
4759 error = uhci_state_is_operational(uhcip);
4760
4761 if (error != USB_SUCCESS) {
4762
4763 return (error);
4764 }
4765
4766 before_frame_number = uhci_get_sw_frame_number(uhcip);
4767 for (n = 0; n < MAX_SOF_WAIT_COUNT; n++) {
4768 SetTD_ioc(uhcip, uhcip->uhci_sof_td, 1);
4769 uhcip->uhci_cv_signal = B_TRUE;
4770
4771 rval = cv_reltimedwait(&uhcip->uhci_cv_SOF,
4772 &uhcip->uhci_int_mutex, UHCI_ONE_SECOND, TR_CLOCK_TICK);
4773
4774 after_frame_number = uhci_get_sw_frame_number(uhcip);
4775 if ((rval == -1) &&
4776 (after_frame_number <= before_frame_number)) {
4777 cmd_reg = Get_OpReg16(USBCMD);
4778 Set_OpReg16(USBCMD, (cmd_reg | USBCMD_REG_HC_RUN));
4779 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
4780 after_frame_number = uhci_get_sw_frame_number(uhcip);
4781 }
4782 before_frame_number = after_frame_number;
4783 }
4784
4785 SetTD_ioc(uhcip, uhcip->uhci_sof_td, 0);
4786
4787 return (uhcip->uhci_cv_signal ? USB_FAILURE : USB_SUCCESS);
4788
4789 }
4790
4791 /*
4792 * uhci_allocate_periodic_in_resource:
4793 * Allocate interrupt/isochronous request structure for the
4794 * interrupt/isochronous IN transfer.
4795 */
4796 int
uhci_allocate_periodic_in_resource(uhci_state_t * uhcip,uhci_pipe_private_t * pp,uhci_trans_wrapper_t * tw,usb_flags_t flags)4797 uhci_allocate_periodic_in_resource(
4798 uhci_state_t *uhcip,
4799 uhci_pipe_private_t *pp,
4800 uhci_trans_wrapper_t *tw,
4801 usb_flags_t flags)
4802 {
4803 size_t length = 0;
4804 usb_opaque_t client_periodic_in_reqp;
4805 usb_intr_req_t *cur_intr_req;
4806 usb_isoc_req_t *curr_isoc_reqp;
4807 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
4808
4809 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4810 "uhci_allocate_periodic_in_resource:\n\t"
4811 "ph = 0x%p, pp = 0x%p, tw = 0x%p, flags = 0x%x",
4812 (void *)ph, (void *)pp, (void *)tw, flags);
4813
4814 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4815
4816 /* Check the current periodic in request pointer */
4817 if (tw->tw_curr_xfer_reqp) {
4818 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4819 "uhci_allocate_periodic_in_resource: Interrupt "
4820 "request structure already exists: "
4821 "allocation failed");
4822
4823 return (USB_SUCCESS);
4824 }
4825
4826 /* Get the client periodic in request pointer */
4827 client_periodic_in_reqp = pp->pp_client_periodic_in_reqp;
4828
4829 /*
4830 * If it a periodic IN request and periodic request is NULL,
4831 * allocate corresponding usb periodic IN request for the
4832 * current periodic polling request and copy the information
4833 * from the saved periodic request structure.
4834 */
4835 if (UHCI_XFER_TYPE(&ph->p_ep) == USB_EP_ATTR_INTR) {
4836 /* Get the interrupt transfer length */
4837 length = ((usb_intr_req_t *)client_periodic_in_reqp)->
4838 intr_len;
4839
4840 cur_intr_req = usba_hcdi_dup_intr_req(ph->p_dip,
4841 (usb_intr_req_t *)client_periodic_in_reqp, length, flags);
4842 if (cur_intr_req == NULL) {
4843 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4844 "uhci_allocate_periodic_in_resource: Interrupt "
4845 "request structure allocation failed");
4846
4847 return (USB_NO_RESOURCES);
4848 }
4849
4850 /* Check and save the timeout value */
4851 tw->tw_timeout_cnt = (cur_intr_req->intr_attributes &
4852 USB_ATTRS_ONE_XFER) ? cur_intr_req->intr_timeout: 0;
4853 tw->tw_curr_xfer_reqp = (usb_opaque_t)cur_intr_req;
4854 tw->tw_length = cur_intr_req->intr_len;
4855 } else {
4856 ASSERT(client_periodic_in_reqp != NULL);
4857
4858 if ((curr_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip,
4859 (usb_isoc_req_t *)client_periodic_in_reqp, flags)) ==
4860 NULL) {
4861 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4862 "uhci_allocate_periodic_in_resource: Isochronous "
4863 "request structure allocation failed");
4864
4865 return (USB_NO_RESOURCES);
4866 }
4867
4868 /*
4869 * Save the client's isochronous request pointer and
4870 * length of isochronous transfer in transfer wrapper.
4871 * The dup'ed request is saved in pp_client_periodic_in_reqp
4872 */
4873 tw->tw_curr_xfer_reqp =
4874 (usb_opaque_t)pp->pp_client_periodic_in_reqp;
4875 pp->pp_client_periodic_in_reqp = (usb_opaque_t)curr_isoc_reqp;
4876 }
4877
4878 mutex_enter(&ph->p_mutex);
4879 ph->p_req_count++;
4880 mutex_exit(&ph->p_mutex);
4881
4882 return (USB_SUCCESS);
4883 }
4884
4885
4886 /*
4887 * uhci_deallocate_periodic_in_resource:
4888 * Deallocate interrupt/isochronous request structure for the
4889 * interrupt/isochronous IN transfer.
4890 */
4891 void
uhci_deallocate_periodic_in_resource(uhci_state_t * uhcip,uhci_pipe_private_t * pp,uhci_trans_wrapper_t * tw)4892 uhci_deallocate_periodic_in_resource(
4893 uhci_state_t *uhcip,
4894 uhci_pipe_private_t *pp,
4895 uhci_trans_wrapper_t *tw)
4896 {
4897 usb_opaque_t curr_xfer_reqp;
4898 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
4899
4900 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4901 "uhci_deallocate_periodic_in_resource: "
4902 "pp = 0x%p tw = 0x%p", (void *)pp, (void *)tw);
4903
4904 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4905
4906 curr_xfer_reqp = tw->tw_curr_xfer_reqp;
4907 if (curr_xfer_reqp) {
4908 /*
4909 * Reset periodic in request usb isoch
4910 * packet request pointers to null.
4911 */
4912 tw->tw_curr_xfer_reqp = NULL;
4913 tw->tw_isoc_req = NULL;
4914
4915 mutex_enter(&ph->p_mutex);
4916 ph->p_req_count--;
4917 mutex_exit(&ph->p_mutex);
4918
4919 /*
4920 * Free pre-allocated interrupt or isochronous requests.
4921 */
4922 switch (UHCI_XFER_TYPE(&ph->p_ep)) {
4923 case USB_EP_ATTR_INTR:
4924 usb_free_intr_req((usb_intr_req_t *)curr_xfer_reqp);
4925 break;
4926 case USB_EP_ATTR_ISOCH:
4927 usb_free_isoc_req((usb_isoc_req_t *)curr_xfer_reqp);
4928 break;
4929 }
4930 }
4931 }
4932
4933
4934 /*
4935 * uhci_hcdi_callback()
4936 * convenience wrapper around usba_hcdi_callback()
4937 */
4938 void
uhci_hcdi_callback(uhci_state_t * uhcip,uhci_pipe_private_t * pp,usba_pipe_handle_data_t * ph,uhci_trans_wrapper_t * tw,usb_cr_t cr)4939 uhci_hcdi_callback(uhci_state_t *uhcip, uhci_pipe_private_t *pp,
4940 usba_pipe_handle_data_t *ph, uhci_trans_wrapper_t *tw, usb_cr_t cr)
4941 {
4942 usb_opaque_t curr_xfer_reqp;
4943
4944 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4945 "uhci_hcdi_callback: ph = 0x%p, tw = 0x%p, cr = 0x%x",
4946 (void *)ph, (void *)tw, cr);
4947
4948 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4949
4950 if (tw && tw->tw_curr_xfer_reqp) {
4951 curr_xfer_reqp = tw->tw_curr_xfer_reqp;
4952 tw->tw_curr_xfer_reqp = NULL;
4953 tw->tw_isoc_req = NULL;
4954 } else {
4955 ASSERT(pp->pp_client_periodic_in_reqp != NULL);
4956
4957 curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
4958 pp->pp_client_periodic_in_reqp = NULL;
4959 }
4960
4961 ASSERT(curr_xfer_reqp != NULL);
4962
4963 mutex_exit(&uhcip->uhci_int_mutex);
4964 usba_hcdi_cb(ph, curr_xfer_reqp, cr);
4965 mutex_enter(&uhcip->uhci_int_mutex);
4966 }
4967
4968
4969 /*
4970 * uhci_state_is_operational:
4971 *
4972 * Check the Host controller state and return proper values.
4973 */
4974 int
uhci_state_is_operational(uhci_state_t * uhcip)4975 uhci_state_is_operational(uhci_state_t *uhcip)
4976 {
4977 int val;
4978
4979 ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4980
4981 switch (uhcip->uhci_hc_soft_state) {
4982 case UHCI_CTLR_INIT_STATE:
4983 case UHCI_CTLR_SUSPEND_STATE:
4984 val = USB_FAILURE;
4985 break;
4986 case UHCI_CTLR_OPERATIONAL_STATE:
4987 val = USB_SUCCESS;
4988 break;
4989 case UHCI_CTLR_ERROR_STATE:
4990 val = USB_HC_HARDWARE_ERROR;
4991 break;
4992 default:
4993 val = USB_FAILURE;
4994 break;
4995 }
4996
4997 return (val);
4998 }
4999
5000
5001 #ifdef DEBUG
5002 static void
uhci_print_td(uhci_state_t * uhcip,uhci_td_t * td)5003 uhci_print_td(uhci_state_t *uhcip, uhci_td_t *td)
5004 {
5005 uint_t *ptr = (uint_t *)td;
5006
5007 #ifndef lint
5008 _NOTE(NO_COMPETING_THREADS_NOW);
5009 #endif
5010 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5011 "\tDWORD 1 0x%x\t DWORD 2 0x%x", ptr[0], ptr[1]);
5012 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5013 "\tDWORD 3 0x%x\t DWORD 4 0x%x", ptr[2], ptr[3]);
5014 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5015 "\tBytes xfered = %d", td->tw->tw_bytes_xfered);
5016 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5017 "\tBytes Pending = %d", td->tw->tw_bytes_pending);
5018 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5019 "Queue Head Details:");
5020 uhci_print_qh(uhcip, td->tw->tw_pipe_private->pp_qh);
5021
5022 #ifndef lint
5023 _NOTE(COMPETING_THREADS_NOW);
5024 #endif
5025 }
5026
5027
5028 static void
uhci_print_qh(uhci_state_t * uhcip,queue_head_t * qh)5029 uhci_print_qh(uhci_state_t *uhcip, queue_head_t *qh)
5030 {
5031 uint_t *ptr = (uint_t *)qh;
5032
5033 USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5034 "\tLink Ptr = %x Element Ptr = %x", ptr[0], ptr[1]);
5035 }
5036 #endif
5037