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