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