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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * This module contains the specific uhci code used in POLLED mode. 29 */ 30 #include <sys/usb/hcd/uhci/uhcid.h> 31 #include <sys/usb/hcd/uhci/uhcipolled.h> 32 33 #ifndef __sparc 34 extern void invalidate_cache(); 35 #endif 36 /* 37 * Internal Function Prototypes 38 */ 39 /* Polled initialization routine */ 40 static int uhci_polled_init(usba_pipe_handle_data_t *, uhci_state_t *, 41 usb_console_info_impl_t *); 42 43 /* Polled fini routine */ 44 static int uhci_polled_fini(uhci_polled_t *, uhci_state_t *); 45 46 /* Polled save state routine */ 47 static void uhci_polled_save_state(uhci_polled_t *); 48 49 /* Polled restore state routine */ 50 static void uhci_polled_restore_state(uhci_polled_t *); 51 52 /* Polled read routines */ 53 static int uhci_polled_insert_td_on_qh(uhci_polled_t *, 54 usba_pipe_handle_data_t *); 55 static uhci_trans_wrapper_t 56 *uhci_polled_create_tw(uhci_state_t *); 57 58 59 /* 60 * POLLED entry points 61 * 62 * These functions are entry points into the POLLED code. 63 */ 64 65 /* 66 * uhci_hcdi_polled_input_init: 67 * This is the initialization routine for handling the USB keyboard 68 * in POLLED mode. This routine is not called from POLLED mode, so 69 * it is OK to acquire mutexes. 70 */ 71 int 72 uhci_hcdi_polled_input_init(usba_pipe_handle_data_t *ph, 73 uchar_t **polled_buf, 74 usb_console_info_impl_t *console_input_info) 75 { 76 int ret; 77 uhci_polled_t *uhci_polledp; 78 uhci_state_t *uhcip; 79 80 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 81 82 /* 83 * Grab the uhci_int_mutex so that things don't change on us 84 * if an interrupt comes in. 85 */ 86 mutex_enter(&uhcip->uhci_int_mutex); 87 ret = uhci_polled_init(ph, uhcip, console_input_info); 88 if (ret != USB_SUCCESS) { 89 mutex_exit(&uhcip->uhci_int_mutex); 90 91 return (ret); 92 } 93 94 uhci_polledp = (uhci_polled_t *)console_input_info->uci_private; 95 /* 96 * Mark the structure so that if we are using it, we don't free 97 * the structures if one of them is unplugged. 98 */ 99 uhci_polledp->uhci_polled_flags |= POLLED_INPUT_MODE; 100 101 /* 102 * This is the buffer we will copy characters into. It will be 103 * copied into at this layer, so we need to keep track of it. 104 */ 105 uhci_polledp->uhci_polled_buf = 106 (uchar_t *)kmem_zalloc(POLLED_RAW_BUF_SIZE, KM_SLEEP); 107 108 *polled_buf = uhci_polledp->uhci_polled_buf; 109 110 mutex_exit(&uhcip->uhci_int_mutex); 111 return (USB_SUCCESS); 112 } 113 114 115 /* 116 * uhci_hcdi_polled_input_fini: 117 */ 118 int 119 uhci_hcdi_polled_input_fini(usb_console_info_impl_t *info) 120 { 121 int ret; 122 uhci_state_t *uhcip; 123 uhci_polled_t *uhci_polledp; 124 125 uhci_polledp = (uhci_polled_t *)info->uci_private; 126 uhcip = uhci_polledp->uhci_polled_uhcip; 127 mutex_enter(&uhcip->uhci_int_mutex); 128 129 /* Free the buffer that we copied data into */ 130 kmem_free(uhci_polledp->uhci_polled_buf, POLLED_RAW_BUF_SIZE); 131 ret = uhci_polled_fini(uhci_polledp, uhcip); 132 info->uci_private = NULL; 133 mutex_exit(&uhcip->uhci_int_mutex); 134 135 return (ret); 136 } 137 138 139 /* 140 * uhci_hcdi_polled_input_enter: 141 * This is where we enter into POLLED mode. This routine sets up 142 * everything so that calls to uhci_hcdi_polled_read will return 143 * characters. 144 */ 145 int 146 uhci_hcdi_polled_input_enter(usb_console_info_impl_t *info) 147 { 148 uhci_polled_t *uhci_polledp; 149 150 uhci_polledp = (uhci_polled_t *)info->uci_private; 151 uhci_polledp->uhci_polled_entry++; 152 153 /* 154 * If the controller is already switched over, just return 155 */ 156 if (uhci_polledp->uhci_polled_entry > 1) { 157 158 return (USB_SUCCESS); 159 } 160 161 uhci_polled_save_state(uhci_polledp); 162 uhci_polledp->uhci_polled_flags |= POLLED_INPUT_MODE_INUSE; 163 164 return (USB_SUCCESS); 165 } 166 167 168 /* 169 * uhci_hcdi_polled_input_exit: 170 * This is where we exit POLLED mode. This routine restores 171 * everything that is needed to continue operation. 172 */ 173 int 174 uhci_hcdi_polled_input_exit(usb_console_info_impl_t *info) 175 { 176 uhci_polled_t *uhci_polledp; 177 178 uhci_polledp = (uhci_polled_t *)info->uci_private; 179 uhci_polledp->uhci_polled_entry--; 180 181 /* 182 * If there are still outstanding "enters", just return 183 */ 184 if (uhci_polledp->uhci_polled_entry > 0) { 185 186 return (USB_SUCCESS); 187 } 188 189 uhci_polledp->uhci_polled_flags &= ~POLLED_INPUT_MODE_INUSE; 190 uhci_polled_restore_state(uhci_polledp); 191 192 return (USB_SUCCESS); 193 } 194 195 196 /* 197 * uhci_hcdi_polled_read: 198 * Get a key character 199 */ 200 int 201 uhci_hcdi_polled_read(usb_console_info_impl_t *info, uint_t *num_characters) 202 { 203 uhci_state_t *uhcip; 204 uhci_polled_t *uhci_polledp; 205 uhci_td_t *td; 206 uhci_trans_wrapper_t *tw; 207 ushort_t intr_status; 208 209 uhci_polledp = (uhci_polled_t *)info->uci_private; 210 uhcip = uhci_polledp->uhci_polled_uhcip; 211 212 /* 213 * This is a temporary work around for halt problem. The upper 214 * layer code does not call the right sequence of entry points 215 * points for reading a character in a polled mode. Once the 216 * upper layer code is fixed, the following code (two lines) 217 * must be removed. 218 */ 219 if (uhci_polledp->uhci_polled_entry == 0) { 220 if (uhci_hcdi_polled_input_enter(info) != USB_SUCCESS) { 221 cmn_err(CE_WARN, "Entering Polled Mode failed"); 222 } 223 } 224 225 #ifndef lint 226 _NOTE(NO_COMPETING_THREADS_NOW); 227 #endif 228 #ifndef __sparc 229 invalidate_cache(); 230 #endif 231 232 td = uhci_polledp->uhci_polled_td; 233 234 /* 235 * Check to see if there are any TD's on the done head. 236 */ 237 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) { 238 *num_characters = 0; 239 } else { 240 241 /* 242 * If the TD does not complete, retry. 243 */ 244 if ((GetTD_status(uhcip, td) & TD_STATUS_MASK) || 245 (GetTD_alen(uhcip, td) == ZERO_LENGTH)) { 246 *num_characters = 0; 247 SetTD_alen(uhcip, td, 0); 248 } else { 249 *num_characters = GetTD_alen(uhcip, td) + 1; 250 251 tw = td->tw; 252 253 /* Copy the data into the message */ 254 ddi_rep_get8(tw->tw_accesshandle, 255 (uint8_t *)uhci_polledp->uhci_polled_buf, 256 (uint8_t *)td->tw->tw_buf, 257 *num_characters, DDI_DEV_AUTOINCR); 258 } 259 260 /* 261 * Insert the td again into the lattice. 262 */ 263 SetTD_dtogg(uhcip, td, GetTD_dtogg(uhcip, td) == 0 ? 1 : 0); 264 265 SetTD_status(uhcip, td, UHCI_TD_ACTIVE); 266 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr, 267 TD_PADDR(td)); 268 269 /* Clear the interrupt status register */ 270 intr_status = Get_OpReg16(USBSTS); 271 Set_OpReg16(USBSTS, intr_status); 272 } 273 274 #ifndef lint 275 _NOTE(COMPETING_THREADS_NOW); 276 #endif 277 278 return (USB_SUCCESS); 279 } 280 281 /* 282 * uhci_hcdi_polled_output_init: 283 * This is the initialization routine for handling the USB serial 284 * output in POLLED mode. This routine is called after input_init 285 * succeeded. 286 */ 287 int 288 uhci_hcdi_polled_output_init(usba_pipe_handle_data_t *ph, 289 usb_console_info_impl_t *console_output_info) 290 { 291 int ret; 292 uhci_polled_t *uhci_polledp; 293 uhci_state_t *uhcip; 294 295 uhcip = uhci_obtain_state(ph->p_usba_device->usb_root_hub_dip); 296 297 /* 298 * Grab the uhci_int_mutex so that things don't change on us 299 * if an interrupt comes in. 300 */ 301 mutex_enter(&uhcip->uhci_int_mutex); 302 ret = uhci_polled_init(ph, uhcip, console_output_info); 303 if (ret != USB_SUCCESS) { 304 mutex_exit(&uhcip->uhci_int_mutex); 305 306 return (ret); 307 } 308 309 uhci_polledp = (uhci_polled_t *)console_output_info->uci_private; 310 /* 311 * Mark the structure so that if we are using it, we don't free 312 * the structures if one of them is unplugged. 313 */ 314 uhci_polledp->uhci_polled_flags |= POLLED_OUTPUT_MODE; 315 316 mutex_exit(&uhcip->uhci_int_mutex); 317 318 return (USB_SUCCESS); 319 } 320 321 322 /* 323 * uhci_hcdi_polled_output_fini: 324 */ 325 int 326 uhci_hcdi_polled_output_fini(usb_console_info_impl_t *info) 327 { 328 int ret; 329 uhci_state_t *uhcip; 330 uhci_polled_t *uhci_polledp; 331 332 uhci_polledp = (uhci_polled_t *)info->uci_private; 333 uhcip = uhci_polledp->uhci_polled_uhcip; 334 mutex_enter(&uhcip->uhci_int_mutex); 335 336 ret = uhci_polled_fini(uhci_polledp, uhcip); 337 info->uci_private = NULL; 338 mutex_exit(&uhcip->uhci_int_mutex); 339 340 return (ret); 341 } 342 343 344 /* 345 * uhci_hcdi_polled_output_enter: 346 * everything is done in input enter 347 */ 348 int 349 uhci_hcdi_polled_output_enter(usb_console_info_impl_t *info) 350 { 351 uhci_state_t *uhcip; 352 uhci_polled_t *uhci_polledp; 353 354 uhci_polledp = (uhci_polled_t *)info->uci_private; 355 uhcip = uhci_polledp->uhci_polled_uhcip; 356 357 /* 358 * Check if the number of devices reaches the max number 359 * we can support in polled mode 360 */ 361 if (uhcip->uhci_polled_count + 1 > MAX_NUM_FOR_KEYBORAD) { 362 363 return (USB_FAILURE); 364 } 365 366 return (USB_SUCCESS); 367 } 368 369 370 /* 371 * uhci_hcdi_polled_output_exit: 372 * everything is done in input exit 373 */ 374 /*ARGSUSED*/ 375 int 376 uhci_hcdi_polled_output_exit(usb_console_info_impl_t *info) 377 { 378 return (USB_SUCCESS); 379 } 380 381 /* 382 * uhci_hcdi_polled_write: 383 * Put a key character -- rewrite this! 384 */ 385 int 386 uhci_hcdi_polled_write(usb_console_info_impl_t *info, uchar_t *buf, 387 uint_t num_characters, uint_t *num_characters_written) 388 { 389 int i; 390 uhci_state_t *uhcip; 391 uhci_polled_t *uhci_polledp; 392 uhci_td_t *td; 393 uhci_trans_wrapper_t *tw; 394 uhci_pipe_private_t *pp; 395 usba_pipe_handle_data_t *ph; 396 397 #ifndef lint 398 _NOTE(NO_COMPETING_THREADS_NOW); 399 #endif 400 401 uhci_polledp = (uhci_polled_t *)info->uci_private; 402 uhcip = uhci_polledp->uhci_polled_uhcip; 403 ph = uhci_polledp->uhci_polled_ph; 404 pp = (uhci_pipe_private_t *)ph->p_hcd_private; 405 406 td = uhci_polledp->uhci_polled_td; 407 tw = td->tw; 408 409 /* copy transmit buffer */ 410 if (num_characters > POLLED_RAW_BUF_SIZE) { 411 cmn_err(CE_NOTE, "polled write size %d bigger than %d", 412 num_characters, POLLED_RAW_BUF_SIZE); 413 num_characters = POLLED_RAW_BUF_SIZE; 414 } 415 tw->tw_length = num_characters; 416 ddi_put8(tw->tw_accesshandle, (uint8_t *)tw->tw_buf, *buf); 417 ddi_rep_put8(tw->tw_accesshandle, buf, (uint8_t *)tw->tw_buf, 418 num_characters, DDI_DEV_AUTOINCR); 419 420 bzero((char *)td, sizeof (uhci_td_t)); 421 422 td->tw = tw; 423 SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT); 424 SetTD_status(uhcip, td, UHCI_TD_ACTIVE); 425 SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION); 426 SetTD_mlen(uhcip, td, num_characters - 1); 427 SetTD_dtogg(uhcip, td, pp->pp_data_toggle); 428 ADJ_DATA_TOGGLE(pp); 429 SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr); 430 SetTD_endpt(uhcip, td, ph->p_ep.bEndpointAddress & 431 END_POINT_ADDRESS_MASK); 432 SetTD_PID(uhcip, td, PID_OUT); 433 SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address); 434 435 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr, 436 TD_PADDR(td)); 437 438 /* 439 * Now, add the endpoint to the lattice that we will hang our 440 * TD's off of. 441 */ 442 for (i = uhcip->uhci_polled_count; i < NUM_FRAME_LST_ENTRIES; 443 i += MIN_LOW_SPEED_POLL_INTERVAL) { 444 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i], 445 QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD); 446 } 447 448 /* wait for xfer to finish */ 449 while (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) 450 #ifndef __sparc 451 invalidate_cache(); 452 #else 453 ; 454 #endif 455 *num_characters_written = GetTD_alen(uhcip, td) + 1; 456 457 /* Now, remove the endpoint from the lattice */ 458 for (i = uhcip->uhci_polled_count; i < NUM_FRAME_LST_ENTRIES; 459 i += MIN_LOW_SPEED_POLL_INTERVAL) { 460 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i], 461 HC_END_OF_LIST); 462 } 463 464 #ifndef lint 465 _NOTE(COMPETING_THREADS_NOW); 466 #endif 467 468 return (USB_SUCCESS); 469 } 470 471 472 /* 473 * uhci_polled_init: 474 * Initialize generic information that is needed to provide USB/POLLED 475 * support. 476 */ 477 static int 478 uhci_polled_init(usba_pipe_handle_data_t *ph, 479 uhci_state_t *uhcip, 480 usb_console_info_impl_t *console_info) 481 { 482 uhci_polled_t *uhci_polledp; 483 484 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 485 486 /* 487 * If the structure has already been initialized, then we don't 488 * need to redo it. 489 */ 490 if (console_info->uci_private != NULL) { 491 492 return (USB_SUCCESS); 493 } 494 495 /* Allocate and intitialize a polled mode state structure */ 496 uhci_polledp = kmem_zalloc(sizeof (uhci_polled_t), KM_SLEEP); 497 498 /* 499 * Keep a copy of normal mode state structure and pipe handle. 500 */ 501 uhci_polledp->uhci_polled_uhcip = uhcip; 502 uhci_polledp->uhci_polled_ph = ph; 503 504 /* 505 * Allocate a queue head for the device. This queue head wiil be 506 * put in action when we switch to polled mode in _enter point. 507 */ 508 uhci_polledp->uhci_polled_qh = uhci_alloc_queue_head(uhcip); 509 510 if (uhci_polledp->uhci_polled_qh == NULL) { 511 kmem_free(uhci_polledp, sizeof (uhci_polled_t)); 512 513 return (USB_NO_RESOURCES); 514 } 515 516 /* 517 * Insert a TD onto the queue head. 518 */ 519 if ((uhci_polled_insert_td_on_qh(uhci_polledp, 520 uhci_polledp->uhci_polled_ph)) != USB_SUCCESS) { 521 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE; 522 kmem_free(uhci_polledp, sizeof (uhci_polled_t)); 523 524 return (USB_NO_RESOURCES); 525 } 526 527 console_info->uci_private = (usb_console_info_private_t)uhci_polledp; 528 529 return (USB_SUCCESS); 530 } 531 532 533 /* 534 * uhci_polled_fini: 535 */ 536 static int 537 uhci_polled_fini(uhci_polled_t *uhci_polledp, uhci_state_t *uhcip) 538 { 539 uhci_td_t *td = uhci_polledp->uhci_polled_td; 540 541 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 542 543 /* 544 * Free the transfer wrapper 545 */ 546 uhci_free_tw(uhcip, td->tw); 547 548 /* 549 * Free the queue head and transfer descriptor allocated. 550 */ 551 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE; 552 uhci_polledp->uhci_polled_td->flag = TD_FLAG_FREE; 553 554 /* 555 * Deallocate the memory for the polled mode state structure. 556 */ 557 kmem_free(uhci_polledp, sizeof (uhci_polled_t)); 558 559 return (USB_SUCCESS); 560 } 561 562 563 /* 564 * uhci_polled_save_state: 565 */ 566 static void 567 uhci_polled_save_state(uhci_polled_t *uhci_polledp) 568 { 569 int i; 570 uhci_td_t *td, *polled_td; 571 uhci_state_t *uhcip; 572 usba_pipe_handle_data_t *ph; 573 574 #ifndef lint 575 _NOTE(NO_COMPETING_THREADS_NOW); 576 #endif 577 578 /* 579 * If either of these two flags are set, then we have already 580 * saved off the state information and setup the controller. 581 */ 582 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) { 583 #ifndef lint 584 _NOTE(COMPETING_THREADS_NOW); 585 #endif 586 587 return; 588 } 589 590 uhcip = uhci_polledp->uhci_polled_uhcip; 591 592 /* 593 * Check if the number of keyboard reaches the max number we can 594 * support in polled mode 595 */ 596 if (++ uhcip->uhci_polled_count > MAX_NUM_FOR_KEYBORAD) { 597 #ifndef lint 598 _NOTE(COMPETING_THREADS_NOW); 599 #endif 600 return; 601 } 602 603 /* 604 * Get the normal mode usb pipe handle. 605 */ 606 ph = (usba_pipe_handle_data_t *)uhci_polledp->uhci_polled_ph; 607 /* 608 * Only the first keyboard enter disable the interrutps, stop the 609 * host controller processing and initialize the interrupt table. 610 */ 611 if (uhcip->uhci_polled_count == 1) { 612 /* 613 * Disable interrupts to prevent the interrupt handler getting 614 * called while we are switing to POLLed mode. 615 */ 616 617 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 618 619 /* 620 * Stop the HC controller from processing TD's 621 */ 622 Set_OpReg16(USBCMD, 0); 623 624 /* 625 * Save the current interrupt lattice and replace this lattice 626 * with an lattice used in POLLED mode. We will restore lattice 627 * back when we exit from the POLLED mode. 628 */ 629 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) { 630 uhcip->uhci_polled_save_IntTble[i] = 631 uhcip->uhci_frame_lst_tablep[i]; 632 } 633 634 /* 635 * Zero out the entire interrupt lattice tree. 636 */ 637 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) { 638 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i], 639 HC_END_OF_LIST); 640 } 641 } 642 643 /* 644 * Now, add the endpoint to the lattice that we will hang our 645 * TD's off of. We (assume always) need to poll this device at 646 * every 8 ms. 647 */ 648 for (i = uhcip->uhci_polled_count - 1; i < NUM_FRAME_LST_ENTRIES; 649 i += MIN_LOW_SPEED_POLL_INTERVAL) { 650 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i], 651 QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD); 652 } 653 654 /* 655 * Adjust the data toggle 656 */ 657 td = uhcip->uhci_outst_tds_head; 658 while (td != NULL) { 659 if (td->tw->tw_pipe_private->pp_pipe_handle == ph) { 660 polled_td = uhci_polledp->uhci_polled_td; 661 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) { 662 SetTD_dtogg(uhcip, polled_td, 663 GetTD_dtogg(uhcip, td)); 664 } else { 665 SetTD_dtogg(uhcip, polled_td, 666 (GetTD_dtogg(uhcip, td) ^ 1)); 667 uhcip->uhci_polled_flag = 668 UHCI_POLLED_FLAG_TD_COMPL; 669 } 670 break; 671 } 672 td = td->outst_td_next; 673 } 674 /* 675 * Only the first keyboard enter reset the frame number and start 676 * the host controler processing. 677 */ 678 if (uhcip->uhci_polled_count == 1) { 679 /* Set the frame number to zero */ 680 Set_OpReg16(FRNUM, 0); 681 682 /* 683 * Start the Host controller processing 684 */ 685 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 | 686 USBCMD_REG_CONFIG_FLAG)); 687 } 688 689 #ifndef lint 690 _NOTE(COMPETING_THREADS_NOW); 691 #endif 692 } 693 694 695 /* 696 * uhci_polled_restore_state: 697 */ 698 static void 699 uhci_polled_restore_state(uhci_polled_t *uhci_polledp) 700 { 701 int i; 702 ushort_t real_data_toggle; 703 uhci_td_t *td, *polled_td; 704 uhci_state_t *uhcip; 705 uhci_pipe_private_t *pp; 706 707 #ifndef lint 708 _NOTE(NO_COMPETING_THREADS_NOW); 709 #endif 710 /* 711 * If this flags is set, then we are still using this structure, 712 * so don't restore any controller state information yet. 713 */ 714 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) { 715 #ifndef lint 716 _NOTE(COMPETING_THREADS_NOW); 717 #endif 718 return; 719 } 720 721 uhcip = uhci_polledp->uhci_polled_uhcip; 722 uhcip->uhci_polled_count --; 723 724 /* Just first leave keyboard entry turn off the controller */ 725 if (Get_OpReg16(USBCMD)) { 726 Set_OpReg16(USBCMD, 0x0); 727 } 728 /* Only the last leave keyboard entry restore the interrupt table */ 729 if (uhcip->uhci_polled_count == 0) { 730 /* 731 * Replace the lattice 732 */ 733 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) { 734 uhcip->uhci_frame_lst_tablep[i] = 735 uhcip->uhci_polled_save_IntTble[i]; 736 } 737 } 738 739 /* 740 * Adjust data toggle 741 */ 742 pp = (uhci_pipe_private_t *) 743 uhci_polledp->uhci_polled_ph->p_hcd_private; 744 745 polled_td = uhci_polledp->uhci_polled_td; 746 real_data_toggle = (GetTD_status(uhcip, polled_td) & UHCI_TD_ACTIVE) ? 747 GetTD_dtogg(uhcip, polled_td) : 748 !GetTD_dtogg(uhcip, polled_td); 749 750 td = uhcip->uhci_outst_tds_head; 751 while (td != NULL) { 752 if (td->tw->tw_pipe_private->pp_pipe_handle == 753 uhci_polledp->uhci_polled_ph) { 754 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) { 755 SetTD_dtogg(uhcip, td, real_data_toggle); 756 pp->pp_data_toggle = 757 (real_data_toggle == 0) ? 1 : 0; 758 } else { 759 pp->pp_data_toggle = real_data_toggle; 760 } 761 } 762 td = td->outst_td_next; 763 } 764 765 /* 766 * Only the last leave keyboard entry enable the interrupts, 767 * start Host controller processing. 768 */ 769 if (uhcip->uhci_polled_count == 0) { 770 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS); 771 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 | 772 USBCMD_REG_CONFIG_FLAG)); 773 if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TD_COMPL) { 774 uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_TRUE; 775 } 776 } 777 778 #ifndef lint 779 _NOTE(COMPETING_THREADS_NOW); 780 #endif 781 } 782 783 784 /* 785 * uhci_polled_insert_td: 786 * Initializes the transfer descriptor for polling and inserts on the 787 * polled queue head. This will be put in action when entered in to 788 * polled mode. 789 */ 790 static int 791 uhci_polled_insert_td_on_qh(uhci_polled_t *uhci_polledp, 792 usba_pipe_handle_data_t *ph) 793 { 794 uhci_td_t *td; 795 uhci_state_t *uhcip = uhci_polledp->uhci_polled_uhcip; 796 usb_ep_descr_t *eptd; 797 uhci_trans_wrapper_t *tw; 798 uint_t direction; 799 800 /* Create the transfer wrapper */ 801 if ((tw = uhci_polled_create_tw(uhci_polledp->uhci_polled_uhcip)) == 802 NULL) { 803 804 return (USB_FAILURE); 805 } 806 807 /* Use the dummy TD allocated for the queue head */ 808 td = uhci_polledp->uhci_polled_qh->td_tailp; 809 bzero((char *)td, sizeof (uhci_td_t)); 810 811 uhci_polledp->uhci_polled_td = td; 812 td->tw = tw; 813 td->flag = TD_FLAG_BUSY; 814 SetTD32(uhcip, td->link_ptr, HC_END_OF_LIST); 815 816 mutex_enter(&ph->p_usba_device->usb_mutex); 817 if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) { 818 SetTD_ls(uhcip, td, LOW_SPEED_DEVICE); 819 } 820 821 eptd = &ph->p_ep; 822 direction = (UHCI_XFER_DIR(eptd) == USB_EP_DIR_OUT) ? PID_OUT : PID_IN; 823 SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT); 824 SetTD_mlen(uhcip, td, POLLED_RAW_BUF_SIZE - 1); 825 SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr); 826 SetTD_endpt(uhcip, td, eptd->bEndpointAddress & END_POINT_ADDRESS_MASK); 827 SetTD_PID(uhcip, td, direction); 828 SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address); 829 SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION); 830 SetTD_status(uhcip, td, UHCI_TD_ACTIVE); 831 mutex_exit(&ph->p_usba_device->usb_mutex); 832 833 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr, TD_PADDR(td)); 834 835 return (USB_SUCCESS); 836 } 837 838 839 /* 840 * uhci_polled_create_wrapper_t: 841 * Creates the transfer wrapper used in polled mode. 842 */ 843 static uhci_trans_wrapper_t * 844 uhci_polled_create_tw(uhci_state_t *uhcip) 845 { 846 uint_t result, ccount; 847 size_t real_length; 848 uhci_trans_wrapper_t *tw; 849 ddi_device_acc_attr_t dev_attr; 850 851 /* Allocate space for the transfer wrapper */ 852 if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), KM_NOSLEEP)) == 853 NULL) { 854 855 return (NULL); 856 } 857 858 tw->tw_length = POLLED_RAW_BUF_SIZE; 859 860 /* Allocate the DMA handle */ 861 if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip, 862 &uhcip->uhci_dma_attr, DDI_DMA_DONTWAIT, 0, &tw->tw_dmahandle)) != 863 DDI_SUCCESS) { 864 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 865 866 return (NULL); 867 } 868 869 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 870 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 871 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 872 873 /* Allocate the memory */ 874 if ((result = ddi_dma_mem_alloc(tw->tw_dmahandle, POLLED_RAW_BUF_SIZE, 875 &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 876 &tw->tw_buf, &real_length, &tw->tw_accesshandle)) != 877 DDI_SUCCESS) { 878 ddi_dma_free_handle(&tw->tw_dmahandle); 879 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 880 881 return (NULL); 882 } 883 884 /* Bind the handle */ 885 if ((result = ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL, 886 tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT, 887 DDI_DMA_DONTWAIT, NULL, &tw->tw_cookie, &ccount)) != 888 DDI_DMA_MAPPED) { 889 ddi_dma_mem_free(&tw->tw_accesshandle); 890 ddi_dma_free_handle(&tw->tw_dmahandle); 891 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 892 893 return (NULL); 894 } 895 896 /* The cookie count should be 1 */ 897 if (ccount != 1) { 898 result = ddi_dma_unbind_handle(tw->tw_dmahandle); 899 ASSERT(result == DDI_SUCCESS); 900 901 ddi_dma_mem_free(&tw->tw_accesshandle); 902 ddi_dma_free_handle(&tw->tw_dmahandle); 903 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 904 905 return (NULL); 906 } 907 908 return (tw); 909 } 910