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 int i = 0; 458 uint_t new_port_status = 0, old_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 (i = 0; i < uhcip->uhci_root_hub.rh_num_ports; i++) { 474 old_port_status = Get_OpReg16(PORTSC[i]); 475 if (!(old_port_status & HCR_PORT_ENABLE)) { 476 Set_OpReg16(PORTSC[i], 477 (old_port_status | HCR_PORT_ENABLE)); 478 drv_usecwait(UHCI_ONE_MS * 2); 479 new_port_status = Get_OpReg16(PORTSC[i]); 480 /* 481 * Refresh Root Hub port status 482 */ 483 uhcip->uhci_root_hub.rh_port_status[i] = 484 new_port_status; 485 uhcip->uhci_root_hub.rh_port_changes[i] |= 486 ((old_port_status ^ new_port_status) & 0xff); 487 } 488 } 489 490 /* 491 * Return failure immediately for any other pipe reset on the root 492 * hub except control or interrupt pipe. 493 */ 494 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 495 switch (UHCI_XFER_TYPE(&ph->p_ep)) { 496 case USB_EP_ATTR_CONTROL: 497 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 498 "uhci_hcdi_pipe_reset: Pipe reset for root" 499 "hub control pipe successful"); 500 501 break; 502 case USB_EP_ATTR_INTR: 503 mutex_enter(&uhcip->uhci_int_mutex); 504 uhcip->uhci_root_hub.rh_pipe_state = 505 UHCI_PIPE_STATE_IDLE; 506 507 /* Do interrupt pipe cleanup */ 508 uhci_root_hub_intr_pipe_cleanup(uhcip, 509 USB_CR_PIPE_RESET); 510 511 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 512 "uhci_hcdi_pipe_reset: Pipe reset for " 513 "root hub interrupt pipe successful"); 514 mutex_exit(&uhcip->uhci_int_mutex); 515 516 break; 517 default: 518 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 519 "uhci_hcdi_pipe_reset: Root hub pipe reset failed"); 520 521 return (USB_FAILURE); 522 } 523 524 return (USB_SUCCESS); 525 } 526 527 mutex_enter(&uhcip->uhci_int_mutex); 528 529 /* 530 * Set the active bit in to INACTIVE for all the remaining TD's of 531 * this end point. Set the active bit for the dummy td. This will 532 * generate an interrupt at the end of the frame. After receiving 533 * the interrupt, it is safe to to manipulate the lattice. 534 */ 535 uhci_modify_td_active_bits(uhcip, pp); 536 537 /* Initialize the element pointer */ 538 if (UHCI_XFER_TYPE(eptd) != USB_EP_ATTR_ISOCH) { 539 UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr); 540 SetQH32(uhcip, pp->pp_qh->element_ptr, 541 TD_PADDR(pp->pp_qh->td_tailp)); 542 } 543 544 (void) uhci_wait_for_sof(uhcip); 545 546 /* 547 * Save the data toggle and clear the pipe. 548 */ 549 switch (UHCI_XFER_TYPE(eptd)) { 550 case USB_EP_ATTR_CONTROL: 551 case USB_EP_ATTR_INTR: 552 uhci_remove_tds_tws(uhcip, ph); 553 break; 554 case USB_EP_ATTR_BULK: 555 SetQH32(uhcip, pp->pp_qh->element_ptr, 556 TD_PADDR(pp->pp_qh->td_tailp)); 557 uhci_remove_bulk_tds_tws(uhcip, pp, UHCI_IN_RESET); 558 break; 559 case USB_EP_ATTR_ISOCH: 560 uhci_remove_isoc_tds_tws(uhcip, pp); 561 break; 562 default: 563 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 564 "uhci_hcdi_pipe_reset: Unknown xfer type"); 565 break; 566 } 567 568 /* 569 * Do the callback for the original client 570 * periodic IN request. 571 */ 572 if (pp->pp_client_periodic_in_reqp) { 573 uhci_hcdi_callback(uhcip, pp, ph, NULL, USB_CR_PIPE_RESET); 574 } 575 576 /* 577 * Since the endpoint is stripped of Transfer Descriptors (TD), 578 * reset the state of the periodic pipe to IDLE. 579 */ 580 pp->pp_state = UHCI_PIPE_STATE_IDLE; 581 582 mutex_exit(&uhcip->uhci_int_mutex); 583 584 return (USB_SUCCESS); 585 } 586 587 /* 588 * uhci_hcdi_pipe_reset_data_toggle: 589 */ 590 void 591 uhci_hcdi_pipe_reset_data_toggle( 592 usba_pipe_handle_data_t *ph) 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 598 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 599 "uhci_hcdi_pipe_reset_data_toggle:"); 600 601 mutex_enter(&uhcip->uhci_int_mutex); 602 603 mutex_enter(&ph->p_mutex); 604 pp->pp_data_toggle = 0; 605 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress, 606 pp->pp_data_toggle); 607 mutex_exit(&ph->p_mutex); 608 609 mutex_exit(&uhcip->uhci_int_mutex); 610 611 } 612 613 /* 614 * uhci_hcdi_pipe_ctrl_xfer: 615 */ 616 int 617 uhci_hcdi_pipe_ctrl_xfer( 618 usba_pipe_handle_data_t *ph, 619 usb_ctrl_req_t *ctrl_reqp, 620 usb_flags_t flags) 621 { 622 uhci_state_t *uhcip = uhci_obtain_state( 623 ph->p_usba_device->usb_root_hub_dip); 624 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 625 int error; 626 627 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 628 "uhci_hcdi_pipe_ctrl_xfer: req=0x%p, ph=0x%p, flags=0x%x", 629 (void *)ctrl_reqp, (void *)ph, flags); 630 631 mutex_enter(&uhcip->uhci_int_mutex); 632 error = uhci_state_is_operational(uhcip); 633 634 if (error != USB_SUCCESS) { 635 mutex_exit(&uhcip->uhci_int_mutex); 636 637 return (error); 638 } 639 640 ASSERT(pp->pp_state == UHCI_PIPE_STATE_IDLE); 641 642 /* 643 * Check and handle root hub control request. 644 */ 645 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 646 error = uhci_handle_root_hub_request(uhcip, ph, ctrl_reqp); 647 mutex_exit(&uhcip->uhci_int_mutex); 648 649 return (error); 650 } 651 652 /* Insert the td's on the endpoint */ 653 if ((error = uhci_insert_ctrl_td(uhcip, ph, ctrl_reqp, flags)) != 654 USB_SUCCESS) { 655 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 656 "uhci_hcdi_pipe_ctrl_xfer: No resources"); 657 } 658 mutex_exit(&uhcip->uhci_int_mutex); 659 660 return (error); 661 } 662 663 664 /* 665 * uhci_hcdi_pipe_bulk_xfer: 666 */ 667 int 668 uhci_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t *pipe_handle, 669 usb_bulk_req_t *bulk_reqp, usb_flags_t usb_flags) 670 { 671 int error; 672 uhci_state_t *uhcip; 673 674 uhcip = uhci_obtain_state(pipe_handle->p_usba_device->usb_root_hub_dip); 675 676 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 677 "uhci_hcdi_pipe_bulk_xfer: Flags = 0x%x", usb_flags); 678 679 /* Check the size of bulk request */ 680 if (bulk_reqp->bulk_len > UHCI_BULK_MAX_XFER_SIZE) { 681 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 682 "uhci_hcdi_pipe_bulk_xfer: req size 0x%x is more than 0x%x", 683 bulk_reqp->bulk_len, UHCI_BULK_MAX_XFER_SIZE); 684 685 return (USB_FAILURE); 686 } 687 688 mutex_enter(&uhcip->uhci_int_mutex); 689 690 error = uhci_state_is_operational(uhcip); 691 692 if (error != USB_SUCCESS) { 693 mutex_exit(&uhcip->uhci_int_mutex); 694 695 return (error); 696 } 697 /* Add the TD into the Host Controller's bulk list */ 698 if ((error = uhci_insert_bulk_td(uhcip, pipe_handle, bulk_reqp, 699 usb_flags)) != USB_SUCCESS) { 700 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 701 "uhci_hcdi_pipe_bulk_xfer: uhci_insert_bulk_td failed"); 702 } 703 mutex_exit(&uhcip->uhci_int_mutex); 704 705 return (error); 706 } 707 708 709 /* 710 * uhci_hcdi_bulk_transfer_size: 711 * Return maximum bulk transfer size 712 */ 713 int 714 uhci_hcdi_bulk_transfer_size( 715 usba_device_t *usba_device, 716 size_t *size) 717 { 718 uhci_state_t *uhcip = uhci_obtain_state( 719 usba_device->usb_root_hub_dip); 720 int rval; 721 722 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 723 "uhci_hcdi_bulk_transfer_size:"); 724 725 mutex_enter(&uhcip->uhci_int_mutex); 726 rval = uhci_state_is_operational(uhcip); 727 728 if (rval != USB_SUCCESS) { 729 mutex_exit(&uhcip->uhci_int_mutex); 730 731 return (rval); 732 } 733 734 *size = uhci_bulk_transfer_size; 735 mutex_exit(&uhcip->uhci_int_mutex); 736 737 return (USB_SUCCESS); 738 } 739 740 741 /* 742 * uhci_hcdi_pipe_intr_xfer: 743 */ 744 int 745 uhci_hcdi_pipe_intr_xfer( 746 usba_pipe_handle_data_t *ph, 747 usb_intr_req_t *req, 748 usb_flags_t flags) 749 { 750 uhci_state_t *uhcip = uhci_obtain_state( 751 ph->p_usba_device->usb_root_hub_dip); 752 753 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 754 "uhci_hcdi_pipe_intr_xfer: req=0x%p, uf=0x%x", (void *)req, flags); 755 756 if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN) { 757 758 return (uhci_start_periodic_pipe_polling(uhcip, ph, 759 (usb_opaque_t)req, flags)); 760 } else { 761 762 return (uhci_send_intr_data(uhcip, ph, req, flags)); 763 } 764 } 765 766 767 /* 768 * uhci_send_intr_data(): 769 * send data to interrupt out pipe 770 */ 771 static int 772 uhci_send_intr_data( 773 uhci_state_t *uhcip, 774 usba_pipe_handle_data_t *pipe_handle, 775 usb_intr_req_t *req, 776 usb_flags_t flags) 777 { 778 int rval; 779 780 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 781 "uhci_send_intr_data:"); 782 783 mutex_enter(&uhcip->uhci_int_mutex); 784 785 rval = uhci_state_is_operational(uhcip); 786 787 if (rval != USB_SUCCESS) { 788 mutex_exit(&uhcip->uhci_int_mutex); 789 790 return (rval); 791 } 792 793 /* Add the TD into the Host Controller's interrupt list */ 794 if ((rval = uhci_insert_intr_td(uhcip, pipe_handle, req, flags)) != 795 USB_SUCCESS) { 796 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 797 "uhci_send_intr_data: No resources"); 798 } 799 mutex_exit(&uhcip->uhci_int_mutex); 800 801 return (rval); 802 } 803 804 805 /* 806 * uhci_hcdi_pipe_stop_intr_polling() 807 */ 808 int 809 uhci_hcdi_pipe_stop_intr_polling( 810 usba_pipe_handle_data_t *pipe_handle, 811 usb_flags_t flags) 812 { 813 uhci_state_t *uhcip = 814 uhci_obtain_state(pipe_handle->p_usba_device->usb_root_hub_dip); 815 int rval; 816 817 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 818 "uhci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x", 819 (void *)pipe_handle, flags); 820 mutex_enter(&uhcip->uhci_int_mutex); 821 822 rval = uhci_stop_periodic_pipe_polling(uhcip, pipe_handle, flags); 823 824 mutex_exit(&uhcip->uhci_int_mutex); 825 826 return (rval); 827 } 828 829 830 /* 831 * uhci_hcdi_get_current_frame_number 832 * Get the current frame number. 833 * Return whether the request is handled successfully. 834 */ 835 int 836 uhci_hcdi_get_current_frame_number( 837 usba_device_t *usba_device, 838 usb_frame_number_t *frame_number) 839 { 840 uhci_state_t *uhcip = uhci_obtain_state(usba_device->usb_root_hub_dip); 841 int rval; 842 843 mutex_enter(&uhcip->uhci_int_mutex); 844 rval = uhci_state_is_operational(uhcip); 845 846 if (rval != USB_SUCCESS) { 847 mutex_exit(&uhcip->uhci_int_mutex); 848 849 return (rval); 850 } 851 852 *frame_number = uhci_get_sw_frame_number(uhcip); 853 mutex_exit(&uhcip->uhci_int_mutex); 854 855 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 856 "uhci_hcdi_get_current_frame_number: %llx", 857 (unsigned long long)(*frame_number)); 858 859 return (rval); 860 } 861 862 863 /* 864 * uhci_hcdi_get_max_isoc_pkts 865 * Get the maximum number of isoc packets per USB Isoch request. 866 * Return whether the request is handled successfully. 867 */ 868 int 869 uhci_hcdi_get_max_isoc_pkts( 870 usba_device_t *usba_device, 871 uint_t *max_isoc_pkts_per_request) 872 { 873 uhci_state_t *uhcip = uhci_obtain_state(usba_device->usb_root_hub_dip); 874 int rval; 875 876 mutex_enter(&uhcip->uhci_int_mutex); 877 rval = uhci_state_is_operational(uhcip); 878 879 if (rval != USB_SUCCESS) { 880 mutex_exit(&uhcip->uhci_int_mutex); 881 882 return (rval); 883 } 884 885 *max_isoc_pkts_per_request = UHCI_MAX_ISOC_PKTS; 886 mutex_exit(&uhcip->uhci_int_mutex); 887 888 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 889 "uhci_hcdi_get_max_isoc_pkts: 0x%x", UHCI_MAX_ISOC_PKTS); 890 891 return (rval); 892 } 893 894 895 /* 896 * uhci_hcdi_pipe_isoc_xfer: 897 */ 898 int 899 uhci_hcdi_pipe_isoc_xfer( 900 usba_pipe_handle_data_t *ph, 901 usb_isoc_req_t *isoc_reqp, 902 usb_flags_t flags) 903 { 904 uhci_state_t *uhcip; 905 906 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 907 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 908 "uhci_hcdi_pipe_isoc_xfer: req=0x%p, uf=0x%x", 909 (void *)isoc_reqp, flags); 910 911 if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_IN) { 912 913 return (uhci_start_periodic_pipe_polling(uhcip, ph, 914 (usb_opaque_t)isoc_reqp, flags)); 915 } else { 916 917 return (uhci_pipe_send_isoc_data(uhcip, ph, isoc_reqp, flags)); 918 } 919 } 920 921 922 /* 923 * uhci_hcdi_pipe_stop_isoc_polling() 924 */ 925 int 926 uhci_hcdi_pipe_stop_isoc_polling( 927 usba_pipe_handle_data_t *ph, 928 usb_flags_t flags) 929 { 930 uhci_state_t *uhcip = 931 uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 932 int rval; 933 934 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 935 "uhci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x", 936 (void *)ph, flags); 937 938 mutex_enter(&uhcip->uhci_int_mutex); 939 rval = uhci_state_is_operational(uhcip); 940 941 if (rval != USB_SUCCESS) { 942 mutex_exit(&uhcip->uhci_int_mutex); 943 944 return (rval); 945 } 946 947 rval = uhci_stop_periodic_pipe_polling(uhcip, ph, flags); 948 949 mutex_exit(&uhcip->uhci_int_mutex); 950 951 return (rval); 952 } 953 954 955 /* 956 * uhci_start_periodic_pipe_polling: 957 */ 958 static int 959 uhci_start_periodic_pipe_polling( 960 uhci_state_t *uhcip, 961 usba_pipe_handle_data_t *ph, 962 usb_opaque_t in_reqp, 963 usb_flags_t flags) 964 { 965 int n, num_tds; 966 int error; 967 usb_intr_req_t *intr_reqp = (usb_intr_req_t *)in_reqp; 968 usb_ep_descr_t *eptd = &ph->p_ep; 969 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 970 971 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 972 "uhci_start_periodic_pipe_polling: flags: 0x%x, ep%d", 973 flags, eptd->bEndpointAddress); 974 975 mutex_enter(&uhcip->uhci_int_mutex); 976 977 error = uhci_state_is_operational(uhcip); 978 979 if (error != USB_SUCCESS) { 980 mutex_exit(&uhcip->uhci_int_mutex); 981 982 return (error); 983 } 984 985 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 986 uint_t pipe_state = uhcip->uhci_root_hub.rh_pipe_state; 987 988 ASSERT(pipe_state == UHCI_PIPE_STATE_IDLE); 989 ASSERT(UHCI_XFER_DIR(eptd) == USB_EP_DIR_IN); 990 991 /* ONE_XFER not supported */ 992 ASSERT((intr_reqp->intr_attributes & 993 USB_ATTRS_ONE_XFER) == 0); 994 ASSERT(uhcip->uhci_root_hub.rh_client_intr_req == NULL); 995 uhcip->uhci_root_hub.rh_client_intr_req = intr_reqp; 996 997 if ((error = uhci_root_hub_allocate_intr_pipe_resource( 998 uhcip, flags)) != USB_SUCCESS) { 999 /* reset the client interrupt request pointer */ 1000 uhcip->uhci_root_hub.rh_client_intr_req = NULL; 1001 1002 mutex_exit(&uhcip->uhci_int_mutex); 1003 1004 return (error); 1005 } 1006 1007 uhcip->uhci_root_hub.rh_pipe_state = USB_PIPE_STATE_ACTIVE; 1008 1009 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1010 "uhci_start_periodic_pipe_polling: " 1011 "Start intr polling for root hub successful"); 1012 1013 /* check if we need to send the reset data up? */ 1014 if (uhcip->uhci_root_hub.rh_status) { 1015 uhci_root_hub_reset_occurred(uhcip, 1016 uhcip->uhci_root_hub.rh_status - 1); 1017 1018 uhcip->uhci_root_hub.rh_status = 0; 1019 } 1020 mutex_exit(&uhcip->uhci_int_mutex); 1021 1022 return (error); 1023 } 1024 1025 /* save the original client's periodic IN request */ 1026 pp->pp_client_periodic_in_reqp = in_reqp; 1027 1028 ASSERT(pp->pp_state != UHCI_PIPE_STATE_ACTIVE); 1029 /* 1030 * 1031 * This pipe is uninitialized. If it is an isoc 1032 * receive request, insert four times the same 1033 * request so that we do not lose any frames. 1034 */ 1035 if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_ISOCH) { 1036 for (n = 0; n < 5; n++) { 1037 if ((error = uhci_start_isoc_receive_polling( 1038 uhcip, ph, NULL, flags)) != USB_SUCCESS) { 1039 1040 USB_DPRINTF_L2(PRINT_MASK_INTR, 1041 uhcip->uhci_log_hdl, 1042 "uhci_start_periodic_pipe_polling: " 1043 "Start isoc polling failed %d", n); 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 if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_INTR) { 1054 if ((pp->pp_node < POLLING_FREQ_7MS) && 1055 (!(intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER))) { 1056 num_tds = 5; 1057 } else { 1058 num_tds = 1; 1059 } 1060 1061 /* 1062 * This pipe is uninitialized. 1063 * Insert a TD on the interrupt ED. 1064 */ 1065 for (n = 0; n < num_tds; n++) { 1066 if ((error = uhci_insert_intr_td(uhcip, ph, NULL, 1067 flags)) != USB_SUCCESS) { 1068 USB_DPRINTF_L2(PRINT_MASK_INTR, 1069 uhcip->uhci_log_hdl, 1070 "uhci_start_periodic_pipe_polling: " 1071 "Start polling failed"); 1072 1073 pp->pp_client_periodic_in_reqp = NULL; 1074 mutex_exit(&uhcip->uhci_int_mutex); 1075 1076 return (error); 1077 } 1078 } 1079 } 1080 1081 pp->pp_state = UHCI_PIPE_STATE_ACTIVE; 1082 1083 mutex_exit(&uhcip->uhci_int_mutex); 1084 1085 return (error); 1086 } 1087 1088 1089 /* 1090 * uhci_hcdi_periodic_pipe_stop_polling: 1091 */ 1092 static int 1093 uhci_stop_periodic_pipe_polling(uhci_state_t *uhcip, 1094 usba_pipe_handle_data_t *ph, usb_flags_t flags) 1095 { 1096 uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private; 1097 usb_ep_descr_t *eptd = &ph->p_ep; 1098 1099 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1100 "uhci_stop_periodic_pipe_polling: flags = 0x%x", flags); 1101 1102 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 1103 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1104 ASSERT(UHCI_XFER_DIR(eptd) == USB_EP_DIR_IN); 1105 1106 if (uhcip->uhci_root_hub.rh_pipe_state == 1107 UHCI_PIPE_STATE_ACTIVE) { 1108 uhcip->uhci_root_hub.rh_pipe_state = 1109 UHCI_PIPE_STATE_IDLE; 1110 1111 /* Do interrupt pipe cleanup */ 1112 uhci_root_hub_intr_pipe_cleanup(uhcip, 1113 USB_CR_STOPPED_POLLING); 1114 1115 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1116 "uhci_stop_periodic_pipe_polling: Stop intr " 1117 "polling for root hub successful"); 1118 1119 } else { 1120 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1121 "uhci_stop_periodic_pipe_polling: " 1122 "Intr polling for root hub is already stopped"); 1123 } 1124 1125 return (USB_SUCCESS); 1126 } 1127 1128 if (pp->pp_state != UHCI_PIPE_STATE_ACTIVE) { 1129 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1130 "uhci_stop_periodic_pipe_polling: Polling already stopped"); 1131 1132 return (USB_SUCCESS); 1133 } 1134 1135 /* 1136 * Set the terminate bits in all the tds in the queue and 1137 * in the element_ptr. 1138 * Do not deallocate the bandwidth or tear down the DMA 1139 */ 1140 uhci_modify_td_active_bits(uhcip, pp); 1141 (void) uhci_wait_for_sof(uhcip); 1142 1143 if (UHCI_XFER_TYPE(eptd) == USB_EP_ATTR_ISOCH) { 1144 uhci_remove_isoc_tds_tws(uhcip, pp); 1145 pp->pp_state = UHCI_PIPE_STATE_IDLE; 1146 } else { 1147 UHCI_SET_TERMINATE_BIT(pp->pp_qh->element_ptr); 1148 uhci_update_intr_td_data_toggle(uhcip, pp); 1149 SetQH32(uhcip, pp->pp_qh->element_ptr, 1150 TD_PADDR(pp->pp_qh->td_tailp)); 1151 uhci_remove_tds_tws(uhcip, ph); 1152 } 1153 1154 pp->pp_state = UHCI_PIPE_STATE_IDLE; 1155 1156 if (pp->pp_client_periodic_in_reqp) { 1157 uhci_hcdi_callback(uhcip, pp, ph, NULL, USB_CR_STOPPED_POLLING); 1158 } 1159 1160 return (USB_SUCCESS); 1161 } 1162 1163 1164 /* 1165 * uhci_hcdi_pipe_send_isoc_data: 1166 * Handles the isoc write request. 1167 */ 1168 static int 1169 uhci_pipe_send_isoc_data( 1170 uhci_state_t *uhcip, 1171 usba_pipe_handle_data_t *ph, 1172 usb_isoc_req_t *isoc_req, 1173 usb_flags_t usb_flags) 1174 { 1175 int error; 1176 size_t max_isoc_xfer_sz, length; 1177 1178 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1179 "uhci_pipe_send_isoc_data: isoc_req = %p flags = %x", 1180 (void *)isoc_req, usb_flags); 1181 1182 ASSERT(isoc_req->isoc_pkts_count < UHCI_MAX_ISOC_PKTS); 1183 1184 /* Calculate the maximum isochronous transfer size */ 1185 max_isoc_xfer_sz = UHCI_MAX_ISOC_PKTS * ph->p_ep.wMaxPacketSize; 1186 1187 /* Check the size of isochronous request */ 1188 ASSERT(isoc_req->isoc_data != NULL); 1189 length = MBLKL(isoc_req->isoc_data); 1190 1191 if (length > max_isoc_xfer_sz) { 1192 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1193 "uhci_pipe_send_isoc_data: Maximum isoc request size %lx " 1194 "Given isoc request size %lx", max_isoc_xfer_sz, length); 1195 1196 return (USB_INVALID_REQUEST); 1197 } 1198 1199 1200 /* 1201 * Check whether we can insert these tds? 1202 * At any point of time, we can insert maximum of 1024 isoc td's, 1203 * size of frame list table. 1204 */ 1205 if (isoc_req->isoc_pkts_count > UHCI_MAX_ISOC_PKTS) { 1206 1207 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl, 1208 "uhci_pipe_send_isoc_data: request too big"); 1209 1210 return (USB_INVALID_REQUEST); 1211 } 1212 1213 /* Add the TD into the Host Controller's isoc list */ 1214 mutex_enter(&uhcip->uhci_int_mutex); 1215 1216 error = uhci_state_is_operational(uhcip); 1217 1218 if (error != USB_SUCCESS) { 1219 mutex_exit(&uhcip->uhci_int_mutex); 1220 1221 return (error); 1222 } 1223 1224 if ((error = uhci_insert_isoc_td(uhcip, ph, isoc_req, 1225 length, usb_flags)) != USB_SUCCESS) { 1226 1227 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl, 1228 "uhci_pipe_send_isoc_data: Unable to insert the isoc_req," 1229 "Error = %d", error); 1230 } 1231 mutex_exit(&uhcip->uhci_int_mutex); 1232 1233 return (error); 1234 } 1235 1236 1237 /* 1238 * uhci_update_intr_td_data_toggle 1239 * Update the data toggle and save in the usba_device structure 1240 */ 1241 static void 1242 uhci_update_intr_td_data_toggle(uhci_state_t *uhcip, uhci_pipe_private_t *pp) 1243 { 1244 uint32_t paddr_tail, element_ptr; 1245 uhci_td_t *next_td; 1246 1247 /* Find the next td that would have been executed */ 1248 element_ptr = GetQH32(uhcip, pp->pp_qh->element_ptr) & 1249 QH_ELEMENT_PTR_MASK; 1250 next_td = TD_VADDR(element_ptr); 1251 paddr_tail = TD_PADDR(pp->pp_qh->td_tailp); 1252 1253 /* 1254 * If element_ptr points to the dummy td, then the data toggle in 1255 * pp_data_toggle is correct. Otherwise update the data toggle in 1256 * the pipe private 1257 */ 1258 if (element_ptr != paddr_tail) { 1259 pp->pp_data_toggle = GetTD_dtogg(uhcip, next_td); 1260 } 1261 1262 USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl, 1263 "uhci_update_intr_td_data_toggle: " 1264 "pp %p toggle %x element ptr %x ptail %x", 1265 (void *)pp, pp->pp_data_toggle, element_ptr, paddr_tail); 1266 1267 uhci_save_data_toggle(pp); 1268 } 1269