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 Universal Host Controller Interface. 33 * This file contains the code for HCDI entry points. 34 */ 35 #include <sys/usb/hcd/uhci/uhcid.h> 36 #include <sys/usb/hcd/uhci/uhcitgt.h> 37 #include <sys/usb/hcd/uhci/uhciutil.h> 38 #include <sys/strsun.h> 39 40 /* function prototypes */ 41 static int uhci_pipe_send_isoc_data(uhci_state_t *uhcip, 42 usba_pipe_handle_data_t *ph, usb_isoc_req_t *isoc_req, 43 usb_flags_t usb_flags); 44 static int uhci_send_intr_data(uhci_state_t *uhcip, 45 usba_pipe_handle_data_t *pipe_handle, 46 usb_intr_req_t *req, 47 usb_flags_t flags); 48 static int uhci_start_periodic_pipe_polling(uhci_state_t *uhcip, 49 usba_pipe_handle_data_t *ph, 50 usb_opaque_t reqp, 51 usb_flags_t flags); 52 static int uhci_stop_periodic_pipe_polling(uhci_state_t *uhcip, 53 usba_pipe_handle_data_t *ph, 54 usb_flags_t flags); 55 static void uhci_update_intr_td_data_toggle(uhci_state_t *uhcip, 56 uhci_pipe_private_t *pp); 57 58 59 /* Maximum bulk transfer size */ 60 int uhci_bulk_transfer_size = UHCI_BULK_MAX_XFER_SIZE; 61 62 /* 63 * uhci_hcdi_pipe_open: 64 * Member of HCD Ops structure and called during client specific pipe open 65 * Add the pipe to the data structure representing the device and allocate 66 * bandwidth for the pipe if it is a interrupt or isochronous endpoint. 67 */ 68 int 69 uhci_hcdi_pipe_open(usba_pipe_handle_data_t *ph, usb_flags_t flags) 70 { 71 uint_t node = 0; 72 usb_addr_t usb_addr; 73 uhci_state_t *uhcip; 74 uhci_pipe_private_t *pp; 75 int rval, error = USB_SUCCESS; 76 77 ASSERT(ph); 78 79 usb_addr = ph->p_usba_device->usb_addr; 80 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 81 82 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 83 "uhci_hcdi_pipe_open: addr = 0x%x, ep%d", usb_addr, 84 ph->p_ep.bEndpointAddress & USB_EP_NUM_MASK); 85 86 sema_p(&uhcip->uhci_ocsem); 87 88 mutex_enter(&uhcip->uhci_int_mutex); 89 rval = uhci_state_is_operational(uhcip); 90 mutex_exit(&uhcip->uhci_int_mutex); 91 92 if (rval != USB_SUCCESS) { 93 sema_v(&uhcip->uhci_ocsem); 94 95 return (rval); 96 } 97 98 /* 99 * Return failure immediately for any other pipe open on the root hub 100 * except control or interrupt pipe. 101 */ 102 if (usb_addr == ROOT_HUB_ADDR) { 103 switch (UHCI_XFER_TYPE(&ph->p_ep)) { 104 case USB_EP_ATTR_CONTROL: 105 USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 106 "uhci_hcdi_pipe_open: Root hub control pipe"); 107 break; 108 case USB_EP_ATTR_INTR: 109 ASSERT(UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN); 110 111 mutex_enter(&uhcip->uhci_int_mutex); 112 uhcip->uhci_root_hub.rh_intr_pipe_handle = ph; 113 114 /* 115 * Set the state of the root hub interrupt 116 * pipe as IDLE. 117 */ 118 uhcip->uhci_root_hub.rh_pipe_state = 119 UHCI_PIPE_STATE_IDLE; 120 121 ASSERT(uhcip->uhci_root_hub.rh_client_intr_req == NULL); 122 uhcip->uhci_root_hub.rh_client_intr_req = NULL; 123 124 ASSERT(uhcip->uhci_root_hub.rh_curr_intr_reqp == NULL); 125 uhcip->uhci_root_hub.rh_curr_intr_reqp = NULL; 126 127 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 128 "uhci_hcdi_pipe_open: Root hub interrupt " 129 "pipe open succeeded"); 130 mutex_exit(&uhcip->uhci_int_mutex); 131 sema_v(&uhcip->uhci_ocsem); 132 133 return (USB_SUCCESS); 134 default: 135 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 136 "uhci_hcdi_pipe_open: Root hub pipe open failed"); 137 sema_v(&uhcip->uhci_ocsem); 138 139 return (USB_FAILURE); 140 } 141 } 142 143 /* 144 * A portion of the bandwidth is reserved for the non-periodic 145 * transfers i.e control and bulk transfers in each of one 146 * mill second frame period & usually it will be 10% of frame 147 * period. Hence there is no need to check for the available 148 * bandwidth before adding the control or bulk endpoints. 149 * 150 * There is a need to check for the available bandwidth before 151 * adding the periodic transfers i.e interrupt & isochronous, since 152 * all these periodic transfers are guaranteed transfers. Usually, 153 * 90% of the total frame time is reserved for periodic transfers. 154 */ 155 if (UHCI_PERIODIC_ENDPOINT(&ph->p_ep)) { 156 /* Zero Max Packet size endpoints are not supported */ 157 if (ph->p_ep.wMaxPacketSize == 0) { 158 USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 159 "uhci_hcdi_pipe_open: Zero length packet"); 160 sema_v(&uhcip->uhci_ocsem); 161 162 return (USB_FAILURE); 163 } 164 165 mutex_enter(&uhcip->uhci_int_mutex); 166 mutex_enter(&ph->p_mutex); 167 168 error = uhci_allocate_bandwidth(uhcip, ph, &node); 169 if (error != USB_SUCCESS) { 170 171 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 172 "uhci_hcdi_pipe_open: Bandwidth allocation failed"); 173 mutex_exit(&ph->p_mutex); 174 mutex_exit(&uhcip->uhci_int_mutex); 175 sema_v(&uhcip->uhci_ocsem); 176 177 return (error); 178 } 179 180 mutex_exit(&ph->p_mutex); 181 mutex_exit(&uhcip->uhci_int_mutex); 182 } 183 184 /* Create the HCD pipe private structure */ 185 pp = kmem_zalloc(sizeof (uhci_pipe_private_t), 186 (flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP); 187 if (pp == NULL) { 188 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 189 "uhci_hcdi_pipe_open: pp allocation failure"); 190 191 if (UHCI_PERIODIC_ENDPOINT(&ph->p_ep)) { 192 mutex_enter(&uhcip->uhci_int_mutex); 193 uhci_deallocate_bandwidth(uhcip, ph); 194 mutex_exit(&uhcip->uhci_int_mutex); 195 } 196 sema_v(&uhcip->uhci_ocsem); 197 198 return (USB_NO_RESOURCES); 199 } 200 201 mutex_enter(&uhcip->uhci_int_mutex); 202 rval = uhci_state_is_operational(uhcip); 203 204 if (rval != USB_SUCCESS) { 205 kmem_free(ph, sizeof (uhci_pipe_private_t)); 206 mutex_exit(&uhcip->uhci_int_mutex); 207 sema_v(&uhcip->uhci_ocsem); 208 209 return (rval); 210 } 211 pp->pp_node = node; /* Store the node in the interrupt lattice */ 212 213 /* Initialize frame number */ 214 pp->pp_frame_num = INVALID_FRNUM; 215 216 /* Set the state of pipe as IDLE */ 217 pp->pp_state = UHCI_PIPE_STATE_IDLE; 218 219 /* Store a pointer to the pipe handle */ 220 pp->pp_pipe_handle = ph; 221 222 /* Store the pointer in the pipe handle */ 223 mutex_enter(&ph->p_mutex); 224 ph->p_hcd_private = (usb_opaque_t)pp; 225 226 /* Store a copy of the pipe policy */ 227 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t)); 228 mutex_exit(&ph->p_mutex); 229 230 /* don't check for ROOT_HUB here anymore */ 231 if (UHCI_XFER_TYPE(&ph->p_ep) != USB_EP_ATTR_ISOCH) { 232 /* Allocate the host controller endpoint descriptor */ 233 pp->pp_qh = uhci_alloc_queue_head(uhcip); 234 235 if (pp->pp_qh == NULL) { 236 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 237 "uhci_hcdi_pipe_open: QH allocation failed"); 238 239 if (UHCI_PERIODIC_ENDPOINT(&ph->p_ep)) { 240 uhci_deallocate_bandwidth(uhcip, ph); 241 } 242 243 mutex_enter(&ph->p_mutex); 244 245 /* 246 * Deallocate the hcd private portion 247 * of the pipe handle. 248 */ 249 kmem_free(ph->p_hcd_private, 250 sizeof (uhci_pipe_private_t)); 251 252 /* 253 * Set the private structure in the 254 * pipe handle equal to NULL. 255 */ 256 ph->p_hcd_private = NULL; 257 mutex_exit(&ph->p_mutex); 258 mutex_exit(&uhcip->uhci_int_mutex); 259 260 sema_v(&uhcip->uhci_ocsem); 261 262 return (USB_NO_RESOURCES); 263 } 264 265 /* 266 * Insert the endpoint onto the host controller's 267 * appropriate endpoint list. The host controller 268 * will not schedule this endpoint until there are 269 * any TD's to process. 270 */ 271 uhci_insert_qh(uhcip, ph); 272 } 273 274 /* 275 * Restore the data toggle from usb device structure. 276 */ 277 if (((ph->p_ep.bmAttributes) & USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR || 278 ((ph->p_ep.bmAttributes) & USB_EP_ATTR_MASK) == USB_EP_ATTR_BULK) { 279 mutex_enter(&ph->p_mutex); 280 281 pp->pp_data_toggle = usba_hcdi_get_data_toggle( 282 ph->p_usba_device, ph->p_ep.bEndpointAddress); 283 mutex_exit(&ph->p_mutex); 284 } 285 286 mutex_exit(&uhcip->uhci_int_mutex); 287 sema_v(&uhcip->uhci_ocsem); 288 289 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 290 "uhci_hcdi_pipe_open: ph = 0x%p", (void *)ph); 291 292 return (USB_SUCCESS); 293 } 294 295 296 /* 297 * uhci_hcdi_pipe_close: 298 * Member of HCD Ops structure and called during the client specific pipe 299 * close. Remove the pipe to the data structure representing the device 300 * deallocate bandwidth for the pipe if it is an intr or isoch endpoint. 301 */ 302 int 303 uhci_hcdi_pipe_close(usba_pipe_handle_data_t *ph, usb_flags_t usb_flags) 304 { 305 usb_addr_t usb_addr; 306 uhci_state_t *uhcip; 307 usb_ep_descr_t *eptd = &ph->p_ep; 308 uhci_pipe_private_t *pp; 309 310 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 311 pp = (uhci_pipe_private_t *)ph->p_hcd_private; 312 usb_addr = ph->p_usba_device->usb_addr; 313 314 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 315 "uhci_hcdi_pipe_close: addr = 0x%x, ep%d, flags = 0x%x", usb_addr, 316 eptd->bEndpointAddress, usb_flags); 317 318 sema_p(&uhcip->uhci_ocsem); 319 320 mutex_enter(&uhcip->uhci_int_mutex); 321 322 /* 323 * Check whether the pipe is a root hub 324 */ 325 if (usb_addr == ROOT_HUB_ADDR) { 326 switch (UHCI_XFER_TYPE(eptd)) { 327 case USB_EP_ATTR_CONTROL: 328 USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 329 "uhci_hcdi_pipe_close: Root hub control pipe " 330 "close succeeded"); 331 332 break; 333 case USB_EP_ATTR_INTR: 334 ASSERT((eptd->bEndpointAddress & 335 USB_EP_NUM_MASK) == 1); 336 337 /* Do interrupt pipe cleanup */ 338 uhci_root_hub_intr_pipe_cleanup(uhcip, 339 USB_CR_PIPE_CLOSING); 340 341 ASSERT(uhcip->uhci_root_hub.rh_pipe_state == 342 UHCI_PIPE_STATE_IDLE); 343 344 uhcip->uhci_root_hub.rh_intr_pipe_handle = NULL; 345 346 USB_DPRINTF_L3(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 347 "uhci_hcdi_pipe_close: Root hub interrupt " 348 "pipe close succeeded"); 349 350 uhcip->uhci_root_hub.rh_pipe_state = 351 UHCI_PIPE_STATE_IDLE; 352 353 mutex_exit(&uhcip->uhci_int_mutex); 354 sema_v(&uhcip->uhci_ocsem); 355 return (USB_SUCCESS); 356 } 357 } else { 358 /* 359 * Stop all the transactions if it is not the root hub. 360 */ 361 if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_INTR) { 362 /* 363 * Stop polling on the pipe to prevent any subsequently 364 * queued tds (while we're waiting for SOF, below) 365 * from being executed 366 */ 367 pp->pp_state = UHCI_PIPE_STATE_IDLE; 368 } 369 370 /* Disable all outstanding tds */ 371 uhci_modify_td_active_bits(uhcip, pp); 372 373 /* Prevent this queue from being executed */ 374 if (UHCI_XFER_TYPE(eptd) != USB_EP_ATTR_ISOCH) { 375 UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr); 376 } 377 378 /* Wait for the next start of frame */ 379 (void) uhci_wait_for_sof(uhcip); 380 381 ASSERT(eptd != NULL); 382 383 switch (UHCI_XFER_TYPE(eptd)) { 384 case USB_EP_ATTR_INTR: 385 uhci_update_intr_td_data_toggle(uhcip, pp); 386 /* FALLTHROUGH */ 387 case USB_EP_ATTR_CONTROL: 388 uhci_remove_tds_tws(uhcip, ph); 389 break; 390 case USB_EP_ATTR_BULK: 391 SetQH32(uhcip, pp->pp_qh->element_ptr, 392 TD_PADDR(pp->pp_qh->td_tailp)); 393 uhci_remove_bulk_tds_tws(uhcip, pp, UHCI_IN_CLOSE); 394 uhci_save_data_toggle(pp); 395 break; 396 case USB_EP_ATTR_ISOCH: 397 uhci_remove_isoc_tds_tws(uhcip, pp); 398 break; 399 default: 400 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 401 "uhci_hcdi_pipe_close: Unknown xfer type"); 402 break; 403 } 404 405 /* 406 * Remove the endoint descriptor from Host Controller's 407 * appropriate endpoint list. Isochronous pipes dont have 408 * any queue heads attached to it. 409 */ 410 if (UHCI_XFER_TYPE(eptd) != USB_EP_ATTR_ISOCH) { 411 uhci_remove_qh(uhcip, pp); 412 } 413 414 /* 415 * Do the callback for the original client 416 * periodic IN request. 417 */ 418 if (pp->pp_client_periodic_in_reqp) { 419 uhci_hcdi_callback(uhcip, pp, ph, NULL, 420 USB_CR_PIPE_CLOSING); 421 } 422 423 /* Deallocate bandwidth */ 424 if (UHCI_PERIODIC_ENDPOINT(eptd)) { 425 mutex_enter(&ph->p_mutex); 426 uhci_deallocate_bandwidth(uhcip, ph); 427 mutex_exit(&ph->p_mutex); 428 } 429 } 430 431 /* Deallocate the hcd private portion of the pipe handle. */ 432 433 mutex_enter(&ph->p_mutex); 434 kmem_free(ph->p_hcd_private, sizeof (uhci_pipe_private_t)); 435 ph->p_hcd_private = NULL; 436 mutex_exit(&ph->p_mutex); 437 438 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 439 "uhci_hcdi_pipe_close: ph = 0x%p", (void *)ph); 440 441 mutex_exit(&uhcip->uhci_int_mutex); 442 sema_v(&uhcip->uhci_ocsem); 443 444 return (USB_SUCCESS); 445 } 446 447 448 /* 449 * uhci_hcdi_pipe_reset: 450 */ 451 int 452 uhci_hcdi_pipe_reset(usba_pipe_handle_data_t *ph, usb_flags_t usb_flags) 453 { 454 uhci_state_t *uhcip = uhci_obtain_state( 455 ph->p_usba_device->usb_root_hub_dip); 456 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 457 usb_ep_descr_t *eptd = &ph->p_ep; 458 459 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 460 "uhci_hcdi_pipe_reset: usb_flags = 0x%x", usb_flags); 461 462 /* 463 * Return failure immediately for any other pipe reset on the root 464 * hub except control or interrupt pipe. 465 */ 466 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 467 switch (UHCI_XFER_TYPE(&ph->p_ep)) { 468 case USB_EP_ATTR_CONTROL: 469 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 470 "uhci_hcdi_pipe_reset: Pipe reset for root" 471 "hub control pipe successful"); 472 473 break; 474 case USB_EP_ATTR_INTR: 475 mutex_enter(&uhcip->uhci_int_mutex); 476 uhcip->uhci_root_hub.rh_pipe_state = 477 UHCI_PIPE_STATE_IDLE; 478 479 /* Do interrupt pipe cleanup */ 480 uhci_root_hub_intr_pipe_cleanup(uhcip, 481 USB_CR_PIPE_RESET); 482 483 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 484 "uhci_hcdi_pipe_reset: Pipe reset for " 485 "root hub interrupt pipe successful"); 486 mutex_exit(&uhcip->uhci_int_mutex); 487 488 break; 489 default: 490 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 491 "uhci_hcdi_pipe_reset: Root hub pipe reset failed"); 492 493 return (USB_FAILURE); 494 } 495 496 return (USB_SUCCESS); 497 } 498 499 mutex_enter(&uhcip->uhci_int_mutex); 500 501 /* 502 * Set the active bit in to INACTIVE for all the remaining TD's of 503 * this end point. Set the active bit for the dummy td. This will 504 * generate an interrupt at the end of the frame. After receiving 505 * the interrupt, it is safe to to manipulate the lattice. 506 */ 507 uhci_modify_td_active_bits(uhcip, pp); 508 509 /* Initialize the element pointer */ 510 if (UHCI_XFER_TYPE(eptd) != USB_EP_ATTR_ISOCH) { 511 UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr); 512 SetQH32(uhcip, pp->pp_qh->element_ptr, 513 TD_PADDR(pp->pp_qh->td_tailp)); 514 } 515 516 (void) uhci_wait_for_sof(uhcip); 517 518 /* 519 * Save the data toggle and clear the pipe. 520 */ 521 switch (UHCI_XFER_TYPE(eptd)) { 522 case USB_EP_ATTR_CONTROL: 523 case USB_EP_ATTR_INTR: 524 uhci_remove_tds_tws(uhcip, ph); 525 break; 526 case USB_EP_ATTR_BULK: 527 SetQH32(uhcip, pp->pp_qh->element_ptr, 528 TD_PADDR(pp->pp_qh->td_tailp)); 529 uhci_remove_bulk_tds_tws(uhcip, pp, UHCI_IN_RESET); 530 break; 531 case USB_EP_ATTR_ISOCH: 532 uhci_remove_isoc_tds_tws(uhcip, pp); 533 break; 534 default: 535 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 536 "uhci_hcdi_pipe_reset: Unknown xfer type"); 537 break; 538 } 539 540 /* 541 * Do the callback for the original client 542 * periodic IN request. 543 */ 544 if (pp->pp_client_periodic_in_reqp) { 545 uhci_hcdi_callback(uhcip, pp, ph, NULL, USB_CR_PIPE_RESET); 546 } 547 548 /* 549 * Since the endpoint is stripped of Transfer Descriptors (TD), 550 * reset the state of the periodic pipe to IDLE. 551 */ 552 pp->pp_state = UHCI_PIPE_STATE_IDLE; 553 554 mutex_exit(&uhcip->uhci_int_mutex); 555 556 return (USB_SUCCESS); 557 } 558 559 /* 560 * uhci_hcdi_pipe_reset_data_toggle: 561 */ 562 void 563 uhci_hcdi_pipe_reset_data_toggle( 564 usba_pipe_handle_data_t *ph) 565 { 566 uhci_state_t *uhcip = uhci_obtain_state( 567 ph->p_usba_device->usb_root_hub_dip); 568 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 569 570 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 571 "uhci_hcdi_pipe_reset_data_toggle:"); 572 573 mutex_enter(&uhcip->uhci_int_mutex); 574 575 mutex_enter(&ph->p_mutex); 576 pp->pp_data_toggle = 0; 577 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress, 578 pp->pp_data_toggle); 579 mutex_exit(&ph->p_mutex); 580 581 mutex_exit(&uhcip->uhci_int_mutex); 582 583 } 584 585 /* 586 * uhci_hcdi_pipe_ctrl_xfer: 587 */ 588 int 589 uhci_hcdi_pipe_ctrl_xfer( 590 usba_pipe_handle_data_t *ph, 591 usb_ctrl_req_t *ctrl_reqp, 592 usb_flags_t flags) 593 { 594 uhci_state_t *uhcip = uhci_obtain_state( 595 ph->p_usba_device->usb_root_hub_dip); 596 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 597 int error; 598 599 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 600 "uhci_hcdi_pipe_ctrl_xfer: req=0x%p, ph=0x%p, flags=0x%x", 601 (void *)ctrl_reqp, (void *)ph, flags); 602 603 mutex_enter(&uhcip->uhci_int_mutex); 604 error = uhci_state_is_operational(uhcip); 605 606 if (error != USB_SUCCESS) { 607 mutex_exit(&uhcip->uhci_int_mutex); 608 609 return (error); 610 } 611 612 ASSERT(pp->pp_state == UHCI_PIPE_STATE_IDLE); 613 614 /* 615 * Check and handle root hub control request. 616 */ 617 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 618 error = uhci_handle_root_hub_request(uhcip, ph, ctrl_reqp); 619 mutex_exit(&uhcip->uhci_int_mutex); 620 621 return (error); 622 } 623 624 /* Insert the td's on the endpoint */ 625 if ((error = uhci_insert_ctrl_td(uhcip, ph, ctrl_reqp, flags)) != 626 USB_SUCCESS) { 627 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 628 "uhci_hcdi_pipe_ctrl_xfer: No resources"); 629 } 630 mutex_exit(&uhcip->uhci_int_mutex); 631 632 return (error); 633 } 634 635 636 /* 637 * uhci_hcdi_pipe_bulk_xfer: 638 */ 639 int 640 uhci_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t *pipe_handle, 641 usb_bulk_req_t *bulk_reqp, usb_flags_t usb_flags) 642 { 643 int error; 644 uhci_state_t *uhcip; 645 646 uhcip = uhci_obtain_state(pipe_handle->p_usba_device->usb_root_hub_dip); 647 648 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 649 "uhci_hcdi_pipe_bulk_xfer: Flags = 0x%x", usb_flags); 650 651 /* Check the size of bulk request */ 652 if (bulk_reqp->bulk_len > UHCI_BULK_MAX_XFER_SIZE) { 653 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 654 "uhci_hcdi_pipe_bulk_xfer: req size 0x%x is more than 0x%x", 655 bulk_reqp->bulk_len, UHCI_BULK_MAX_XFER_SIZE); 656 657 return (USB_FAILURE); 658 } 659 660 mutex_enter(&uhcip->uhci_int_mutex); 661 662 error = uhci_state_is_operational(uhcip); 663 664 if (error != USB_SUCCESS) { 665 mutex_exit(&uhcip->uhci_int_mutex); 666 667 return (error); 668 } 669 /* Add the TD into the Host Controller's bulk list */ 670 if ((error = uhci_insert_bulk_td(uhcip, pipe_handle, bulk_reqp, 671 usb_flags)) != USB_SUCCESS) { 672 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 673 "uhci_hcdi_pipe_bulk_xfer: uhci_insert_bulk_td failed"); 674 } 675 mutex_exit(&uhcip->uhci_int_mutex); 676 677 return (error); 678 } 679 680 681 /* 682 * uhci_hcdi_bulk_transfer_size: 683 * Return maximum bulk transfer size 684 */ 685 int 686 uhci_hcdi_bulk_transfer_size( 687 usba_device_t *usba_device, 688 size_t *size) 689 { 690 uhci_state_t *uhcip = uhci_obtain_state( 691 usba_device->usb_root_hub_dip); 692 int rval; 693 694 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 695 "uhci_hcdi_bulk_transfer_size:"); 696 697 mutex_enter(&uhcip->uhci_int_mutex); 698 rval = uhci_state_is_operational(uhcip); 699 700 if (rval != USB_SUCCESS) { 701 mutex_exit(&uhcip->uhci_int_mutex); 702 703 return (rval); 704 } 705 706 *size = uhci_bulk_transfer_size; 707 mutex_exit(&uhcip->uhci_int_mutex); 708 709 return (USB_SUCCESS); 710 } 711 712 713 /* 714 * uhci_hcdi_pipe_intr_xfer: 715 */ 716 int 717 uhci_hcdi_pipe_intr_xfer( 718 usba_pipe_handle_data_t *ph, 719 usb_intr_req_t *req, 720 usb_flags_t flags) 721 { 722 uhci_state_t *uhcip = uhci_obtain_state( 723 ph->p_usba_device->usb_root_hub_dip); 724 725 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 726 "uhci_hcdi_pipe_intr_xfer: req=0x%p, uf=0x%x", (void *)req, flags); 727 728 if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN) { 729 730 return (uhci_start_periodic_pipe_polling(uhcip, ph, 731 (usb_opaque_t)req, flags)); 732 } else { 733 734 return (uhci_send_intr_data(uhcip, ph, req, flags)); 735 } 736 } 737 738 739 /* 740 * uhci_send_intr_data(): 741 * send data to interrupt out pipe 742 */ 743 static int 744 uhci_send_intr_data( 745 uhci_state_t *uhcip, 746 usba_pipe_handle_data_t *pipe_handle, 747 usb_intr_req_t *req, 748 usb_flags_t flags) 749 { 750 int rval; 751 752 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 753 "uhci_send_intr_data:"); 754 755 mutex_enter(&uhcip->uhci_int_mutex); 756 757 rval = uhci_state_is_operational(uhcip); 758 759 if (rval != USB_SUCCESS) { 760 mutex_exit(&uhcip->uhci_int_mutex); 761 762 return (rval); 763 } 764 765 /* Add the TD into the Host Controller's interrupt list */ 766 if ((rval = uhci_insert_intr_td(uhcip, pipe_handle, req, flags)) != 767 USB_SUCCESS) { 768 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 769 "uhci_send_intr_data: No resources"); 770 } 771 mutex_exit(&uhcip->uhci_int_mutex); 772 773 return (rval); 774 } 775 776 777 /* 778 * uhci_hcdi_pipe_stop_intr_polling() 779 */ 780 int 781 uhci_hcdi_pipe_stop_intr_polling( 782 usba_pipe_handle_data_t *pipe_handle, 783 usb_flags_t flags) 784 { 785 uhci_state_t *uhcip = 786 uhci_obtain_state(pipe_handle->p_usba_device->usb_root_hub_dip); 787 int rval; 788 789 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 790 "uhci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x", 791 (void *)pipe_handle, flags); 792 mutex_enter(&uhcip->uhci_int_mutex); 793 794 rval = uhci_stop_periodic_pipe_polling(uhcip, pipe_handle, flags); 795 796 mutex_exit(&uhcip->uhci_int_mutex); 797 798 return (rval); 799 } 800 801 802 /* 803 * uhci_hcdi_get_current_frame_number 804 * Get the current frame number. 805 * Return whether the request is handled successfully. 806 */ 807 int 808 uhci_hcdi_get_current_frame_number( 809 usba_device_t *usba_device, 810 usb_frame_number_t *frame_number) 811 { 812 uhci_state_t *uhcip = uhci_obtain_state(usba_device->usb_root_hub_dip); 813 int rval; 814 815 mutex_enter(&uhcip->uhci_int_mutex); 816 rval = uhci_state_is_operational(uhcip); 817 818 if (rval != USB_SUCCESS) { 819 mutex_exit(&uhcip->uhci_int_mutex); 820 821 return (rval); 822 } 823 824 *frame_number = uhci_get_sw_frame_number(uhcip); 825 mutex_exit(&uhcip->uhci_int_mutex); 826 827 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 828 "uhci_hcdi_get_current_frame_number: %llx", 829 (unsigned long long)(*frame_number)); 830 831 return (rval); 832 } 833 834 835 /* 836 * uhci_hcdi_get_max_isoc_pkts 837 * Get the maximum number of isoc packets per USB Isoch request. 838 * Return whether the request is handled successfully. 839 */ 840 int 841 uhci_hcdi_get_max_isoc_pkts( 842 usba_device_t *usba_device, 843 uint_t *max_isoc_pkts_per_request) 844 { 845 uhci_state_t *uhcip = uhci_obtain_state(usba_device->usb_root_hub_dip); 846 int rval; 847 848 mutex_enter(&uhcip->uhci_int_mutex); 849 rval = uhci_state_is_operational(uhcip); 850 851 if (rval != USB_SUCCESS) { 852 mutex_exit(&uhcip->uhci_int_mutex); 853 854 return (rval); 855 } 856 857 *max_isoc_pkts_per_request = UHCI_MAX_ISOC_PKTS; 858 mutex_exit(&uhcip->uhci_int_mutex); 859 860 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 861 "uhci_hcdi_get_max_isoc_pkts: 0x%x", UHCI_MAX_ISOC_PKTS); 862 863 return (rval); 864 } 865 866 867 /* 868 * uhci_hcdi_pipe_isoc_xfer: 869 */ 870 int 871 uhci_hcdi_pipe_isoc_xfer( 872 usba_pipe_handle_data_t *ph, 873 usb_isoc_req_t *isoc_reqp, 874 usb_flags_t flags) 875 { 876 uhci_state_t *uhcip; 877 878 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 879 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 880 "uhci_hcdi_pipe_isoc_xfer: req=0x%p, uf=0x%x", 881 (void *)isoc_reqp, flags); 882 883 if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN) { 884 885 return (uhci_start_periodic_pipe_polling(uhcip, ph, 886 (usb_opaque_t)isoc_reqp, flags)); 887 } else { 888 889 return (uhci_pipe_send_isoc_data(uhcip, ph, isoc_reqp, flags)); 890 } 891 } 892 893 894 /* 895 * uhci_hcdi_pipe_stop_isoc_polling() 896 */ 897 int 898 uhci_hcdi_pipe_stop_isoc_polling( 899 usba_pipe_handle_data_t *ph, 900 usb_flags_t flags) 901 { 902 uhci_state_t *uhcip = 903 uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 904 int rval; 905 906 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 907 "uhci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x", 908 (void *)ph, flags); 909 910 mutex_enter(&uhcip->uhci_int_mutex); 911 rval = uhci_state_is_operational(uhcip); 912 913 if (rval != USB_SUCCESS) { 914 mutex_exit(&uhcip->uhci_int_mutex); 915 916 return (rval); 917 } 918 919 rval = uhci_stop_periodic_pipe_polling(uhcip, ph, flags); 920 921 mutex_exit(&uhcip->uhci_int_mutex); 922 923 return (rval); 924 } 925 926 927 /* 928 * uhci_start_periodic_pipe_polling: 929 */ 930 static int 931 uhci_start_periodic_pipe_polling( 932 uhci_state_t *uhcip, 933 usba_pipe_handle_data_t *ph, 934 usb_opaque_t in_reqp, 935 usb_flags_t flags) 936 { 937 int n, num_tds; 938 int error; 939 usb_intr_req_t *intr_reqp = (usb_intr_req_t *)in_reqp; 940 usb_ep_descr_t *eptd = &ph->p_ep; 941 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 942 943 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 944 "uhci_start_periodic_pipe_polling: flags: 0x%x, ep%d", 945 flags, eptd->bEndpointAddress); 946 947 mutex_enter(&uhcip->uhci_int_mutex); 948 949 error = uhci_state_is_operational(uhcip); 950 951 if (error != USB_SUCCESS) { 952 mutex_exit(&uhcip->uhci_int_mutex); 953 954 return (error); 955 } 956 957 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 958 uint_t pipe_state = uhcip->uhci_root_hub.rh_pipe_state; 959 960 ASSERT(pipe_state == UHCI_PIPE_STATE_IDLE); 961 ASSERT(UHCI_XFER_DIR(eptd) == USB_EP_DIR_IN); 962 963 /* ONE_XFER not supported */ 964 ASSERT((intr_reqp->intr_attributes & 965 USB_ATTRS_ONE_XFER) == 0); 966 ASSERT(uhcip->uhci_root_hub.rh_client_intr_req == NULL); 967 uhcip->uhci_root_hub.rh_client_intr_req = intr_reqp; 968 969 if ((error = uhci_root_hub_allocate_intr_pipe_resource( 970 uhcip, flags)) != USB_SUCCESS) { 971 /* reset the client interrupt request pointer */ 972 uhcip->uhci_root_hub.rh_client_intr_req = NULL; 973 974 mutex_exit(&uhcip->uhci_int_mutex); 975 976 return (error); 977 } 978 979 uhcip->uhci_root_hub.rh_pipe_state = USB_PIPE_STATE_ACTIVE; 980 981 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 982 "uhci_start_periodic_pipe_polling: " 983 "Start intr polling for root hub successful"); 984 985 /* check if we need to send the reset data up? */ 986 if (uhcip->uhci_root_hub.rh_status) { 987 uhci_root_hub_reset_occurred(uhcip, 988 uhcip->uhci_root_hub.rh_status - 1); 989 990 uhcip->uhci_root_hub.rh_status = 0; 991 } 992 mutex_exit(&uhcip->uhci_int_mutex); 993 994 return (error); 995 } 996 997 /* save the original client's periodic IN request */ 998 pp->pp_client_periodic_in_reqp = in_reqp; 999 1000 ASSERT(pp->pp_state != UHCI_PIPE_STATE_ACTIVE); 1001 /* 1002 * 1003 * This pipe is uninitialized. If it is an isoc 1004 * receive request, insert four times the same 1005 * request so that we do not lose any frames. 1006 */ 1007 if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_ISOCH) { 1008 for (n = 0; n < 5; n++) { 1009 if ((error = uhci_start_isoc_receive_polling( 1010 uhcip, ph, NULL, flags)) != USB_SUCCESS) { 1011 1012 USB_DPRINTF_L2(PRINT_MASK_INTR, 1013 uhcip->uhci_log_hdl, 1014 "uhci_start_periodic_pipe_polling: " 1015 "Start isoc polling failed %d", n); 1016 1017 pp->pp_client_periodic_in_reqp = NULL; 1018 mutex_exit(&uhcip->uhci_int_mutex); 1019 1020 return (error); 1021 } 1022 } 1023 } 1024 1025 if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_INTR) { 1026 if ((pp->pp_node < POLLING_FREQ_7MS) && 1027 (!(intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER))) { 1028 num_tds = 5; 1029 } else { 1030 num_tds = 1; 1031 } 1032 1033 /* 1034 * This pipe is uninitialized. 1035 * Insert a TD on the interrupt ED. 1036 */ 1037 for (n = 0; n < num_tds; n++) { 1038 if ((error = uhci_insert_intr_td(uhcip, ph, NULL, 1039 flags)) != USB_SUCCESS) { 1040 USB_DPRINTF_L2(PRINT_MASK_INTR, 1041 uhcip->uhci_log_hdl, 1042 "uhci_start_periodic_pipe_polling: " 1043 "Start polling failed"); 1044 1045 pp->pp_client_periodic_in_reqp = NULL; 1046 mutex_exit(&uhcip->uhci_int_mutex); 1047 1048 return (error); 1049 } 1050 } 1051 } 1052 1053 pp->pp_state = UHCI_PIPE_STATE_ACTIVE; 1054 1055 mutex_exit(&uhcip->uhci_int_mutex); 1056 1057 return (error); 1058 } 1059 1060 1061 /* 1062 * uhci_hcdi_periodic_pipe_stop_polling: 1063 */ 1064 static int 1065 uhci_stop_periodic_pipe_polling(uhci_state_t *uhcip, 1066 usba_pipe_handle_data_t *ph, usb_flags_t flags) 1067 { 1068 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 1069 usb_ep_descr_t *eptd = &ph->p_ep; 1070 1071 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1072 "uhci_stop_periodic_pipe_polling: flags = 0x%x", flags); 1073 1074 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 1075 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1076 ASSERT(UHCI_XFER_DIR(eptd) == USB_EP_DIR_IN); 1077 1078 if (uhcip->uhci_root_hub.rh_pipe_state == 1079 UHCI_PIPE_STATE_ACTIVE) { 1080 uhcip->uhci_root_hub.rh_pipe_state = 1081 UHCI_PIPE_STATE_IDLE; 1082 1083 /* Do interrupt pipe cleanup */ 1084 uhci_root_hub_intr_pipe_cleanup(uhcip, 1085 USB_CR_STOPPED_POLLING); 1086 1087 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1088 "uhci_stop_periodic_pipe_polling: Stop intr " 1089 "polling for root hub successful"); 1090 1091 } else { 1092 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1093 "uhci_stop_periodic_pipe_polling: " 1094 "Intr polling for root hub is already stopped"); 1095 } 1096 1097 return (USB_SUCCESS); 1098 } 1099 1100 if (pp->pp_state != UHCI_PIPE_STATE_ACTIVE) { 1101 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1102 "uhci_stop_periodic_pipe_polling: Polling already stopped"); 1103 1104 return (USB_SUCCESS); 1105 } 1106 1107 /* 1108 * Set the terminate bits in all the tds in the queue and 1109 * in the element_ptr. 1110 * Do not deallocate the bandwidth or tear down the DMA 1111 */ 1112 uhci_modify_td_active_bits(uhcip, pp); 1113 (void) uhci_wait_for_sof(uhcip); 1114 1115 if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_ISOCH) { 1116 uhci_remove_isoc_tds_tws(uhcip, pp); 1117 pp->pp_state = UHCI_PIPE_STATE_IDLE; 1118 } else { 1119 UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr); 1120 uhci_update_intr_td_data_toggle(uhcip, pp); 1121 SetQH32(uhcip, pp->pp_qh->element_ptr, 1122 TD_PADDR(pp->pp_qh->td_tailp)); 1123 uhci_remove_tds_tws(uhcip, ph); 1124 } 1125 1126 pp->pp_state = UHCI_PIPE_STATE_IDLE; 1127 1128 if (pp->pp_client_periodic_in_reqp) { 1129 uhci_hcdi_callback(uhcip, pp, ph, NULL, USB_CR_STOPPED_POLLING); 1130 } 1131 1132 return (USB_SUCCESS); 1133 } 1134 1135 1136 /* 1137 * uhci_hcdi_pipe_send_isoc_data: 1138 * Handles the isoc write request. 1139 */ 1140 static int 1141 uhci_pipe_send_isoc_data( 1142 uhci_state_t *uhcip, 1143 usba_pipe_handle_data_t *ph, 1144 usb_isoc_req_t *isoc_req, 1145 usb_flags_t usb_flags) 1146 { 1147 int error; 1148 size_t max_isoc_xfer_sz, length; 1149 1150 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1151 "uhci_pipe_send_isoc_data: isoc_req = %p flags = %x", 1152 (void *)isoc_req, usb_flags); 1153 1154 ASSERT(isoc_req->isoc_pkts_count < UHCI_MAX_ISOC_PKTS); 1155 1156 /* Calculate the maximum isochronous transfer size */ 1157 max_isoc_xfer_sz = UHCI_MAX_ISOC_PKTS * ph->p_ep.wMaxPacketSize; 1158 1159 /* Check the size of isochronous request */ 1160 ASSERT(isoc_req->isoc_data != NULL); 1161 length = MBLKL(isoc_req->isoc_data); 1162 1163 if (length > max_isoc_xfer_sz) { 1164 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1165 "uhci_pipe_send_isoc_data: Maximum isoc request size %lx " 1166 "Given isoc request size %lx", max_isoc_xfer_sz, length); 1167 1168 return (USB_INVALID_REQUEST); 1169 } 1170 1171 1172 /* 1173 * Check whether we can insert these tds? 1174 * At any point of time, we can insert maximum of 1024 isoc td's, 1175 * size of frame list table. 1176 */ 1177 if (isoc_req->isoc_pkts_count > UHCI_MAX_ISOC_PKTS) { 1178 1179 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl, 1180 "uhci_pipe_send_isoc_data: request too big"); 1181 1182 return (USB_INVALID_REQUEST); 1183 } 1184 1185 /* Add the TD into the Host Controller's isoc list */ 1186 mutex_enter(&uhcip->uhci_int_mutex); 1187 1188 error = uhci_state_is_operational(uhcip); 1189 1190 if (error != USB_SUCCESS) { 1191 mutex_exit(&uhcip->uhci_int_mutex); 1192 1193 return (error); 1194 } 1195 1196 if ((error = uhci_insert_isoc_td(uhcip, ph, isoc_req, 1197 length, usb_flags)) != USB_SUCCESS) { 1198 1199 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl, 1200 "uhci_pipe_send_isoc_data: Unable to insert the isoc_req," 1201 "Error = %d", error); 1202 } 1203 mutex_exit(&uhcip->uhci_int_mutex); 1204 1205 return (error); 1206 } 1207 1208 1209 /* 1210 * uhci_update_intr_td_data_toggle 1211 * Update the data toggle and save in the usba_device structure 1212 */ 1213 static void 1214 uhci_update_intr_td_data_toggle(uhci_state_t *uhcip, uhci_pipe_private_t *pp) 1215 { 1216 uint32_t paddr_tail, element_ptr; 1217 uhci_td_t *next_td; 1218 1219 /* Find the next td that would have been executed */ 1220 element_ptr = GetQH32(uhcip, pp->pp_qh->element_ptr) & 1221 QH_ELEMENT_PTR_MASK; 1222 next_td = TD_VADDR(element_ptr); 1223 paddr_tail = TD_PADDR(pp->pp_qh->td_tailp); 1224 1225 /* 1226 * If element_ptr points to the dummy td, then the data toggle in 1227 * pp_data_toggle is correct. Otherwise update the data toggle in 1228 * the pipe private 1229 */ 1230 if (element_ptr != paddr_tail) { 1231 pp->pp_data_toggle = GetTD_dtogg(uhcip, next_td); 1232 } 1233 1234 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1235 "uhci_update_intr_td_data_toggle: " 1236 "pp %p toggle %x element ptr %x ptail %x", 1237 (void *)pp, pp->pp_data_toggle, element_ptr, paddr_tail); 1238 1239 uhci_save_data_toggle(pp); 1240 } 1241