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 = (uhci_polled_t *)kmem_zalloc(sizeof (uhci_polled_t), 497 KM_SLEEP); 498 499 /* 500 * Keep a copy of normal mode state structure and pipe handle. 501 */ 502 uhci_polledp->uhci_polled_uhcip = uhcip; 503 uhci_polledp->uhci_polled_ph = ph; 504 505 /* 506 * Allocate a queue head for the device. This queue head wiil be 507 * put in action when we switch to polled mode in _enter point. 508 */ 509 uhci_polledp->uhci_polled_qh = uhci_alloc_queue_head(uhcip); 510 511 if (uhci_polledp->uhci_polled_qh == NULL) { 512 kmem_free(uhci_polledp, sizeof (uhci_polled_t)); 513 514 return (USB_NO_RESOURCES); 515 } 516 517 /* 518 * Insert a TD onto the queue head. 519 */ 520 if ((uhci_polled_insert_td_on_qh(uhci_polledp, 521 uhci_polledp->uhci_polled_ph)) != USB_SUCCESS) { 522 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE; 523 kmem_free(uhci_polledp, sizeof (uhci_polled_t)); 524 525 return (USB_NO_RESOURCES); 526 } 527 528 console_info->uci_private = (usb_console_info_private_t)uhci_polledp; 529 530 return (USB_SUCCESS); 531 } 532 533 534 /* 535 * uhci_polled_fini: 536 */ 537 static int 538 uhci_polled_fini(uhci_polled_t *uhci_polledp, uhci_state_t *uhcip) 539 { 540 uhci_td_t *td = uhci_polledp->uhci_polled_td; 541 542 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 543 544 /* 545 * Free the transfer wrapper 546 */ 547 uhci_free_tw(uhcip, td->tw); 548 549 /* 550 * Free the queue head and transfer descriptor allocated. 551 */ 552 uhci_polledp->uhci_polled_qh->qh_flag = QUEUE_HEAD_FLAG_FREE; 553 uhci_polledp->uhci_polled_td->flag = TD_FLAG_FREE; 554 555 /* 556 * Deallocate the memory for the polled mode state structure. 557 */ 558 kmem_free(uhci_polledp, sizeof (uhci_polled_t)); 559 560 return (USB_SUCCESS); 561 } 562 563 564 /* 565 * uhci_polled_save_state: 566 */ 567 static void 568 uhci_polled_save_state(uhci_polled_t *uhci_polledp) 569 { 570 int i; 571 uhci_td_t *td, *polled_td; 572 uhci_state_t *uhcip; 573 usba_pipe_handle_data_t *ph; 574 575 #ifndef lint 576 _NOTE(NO_COMPETING_THREADS_NOW); 577 #endif 578 579 /* 580 * If either of these two flags are set, then we have already 581 * saved off the state information and setup the controller. 582 */ 583 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) { 584 #ifndef lint 585 _NOTE(COMPETING_THREADS_NOW); 586 #endif 587 588 return; 589 } 590 591 uhcip = uhci_polledp->uhci_polled_uhcip; 592 593 /* 594 * Check if the number of keyboard reaches the max number we can 595 * support in polled mode 596 */ 597 if (++ uhcip->uhci_polled_count > MAX_NUM_FOR_KEYBORAD) { 598 #ifndef lint 599 _NOTE(COMPETING_THREADS_NOW); 600 #endif 601 return; 602 } 603 604 /* 605 * Get the normal mode usb pipe handle. 606 */ 607 ph = (usba_pipe_handle_data_t *)uhci_polledp->uhci_polled_ph; 608 /* 609 * Only the first keyboard enter disable the interrutps, stop the 610 * host controller processing and initialize the interrupt table. 611 */ 612 if (uhcip->uhci_polled_count == 1) { 613 /* 614 * Disable interrupts to prevent the interrupt handler getting 615 * called while we are switing to POLLed mode. 616 */ 617 618 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 619 620 /* 621 * Stop the HC controller from processing TD's 622 */ 623 Set_OpReg16(USBCMD, 0); 624 625 /* 626 * Save the current interrupt lattice and replace this lattice 627 * with an lattice used in POLLED mode. We will restore lattice 628 * back when we exit from the POLLED mode. 629 */ 630 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) { 631 uhcip->uhci_polled_save_IntTble[i] = 632 uhcip->uhci_frame_lst_tablep[i]; 633 } 634 635 /* 636 * Zero out the entire interrupt lattice tree. 637 */ 638 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) { 639 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i], 640 HC_END_OF_LIST); 641 } 642 } 643 644 /* 645 * Now, add the endpoint to the lattice that we will hang our 646 * TD's off of. We (assume always) need to poll this device at 647 * every 8 ms. 648 */ 649 for (i = uhcip->uhci_polled_count - 1; i < NUM_FRAME_LST_ENTRIES; 650 i += MIN_LOW_SPEED_POLL_INTERVAL) { 651 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[i], 652 QH_PADDR(uhci_polledp->uhci_polled_qh) | HC_QUEUE_HEAD); 653 } 654 655 /* 656 * Adjust the data toggle 657 */ 658 td = uhcip->uhci_outst_tds_head; 659 while (td != NULL) { 660 if (td->tw->tw_pipe_private->pp_pipe_handle == ph) { 661 polled_td = uhci_polledp->uhci_polled_td; 662 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) { 663 SetTD_dtogg(uhcip, polled_td, 664 GetTD_dtogg(uhcip, td)); 665 } else { 666 SetTD_dtogg(uhcip, polled_td, 667 (GetTD_dtogg(uhcip, td) ^ 1)); 668 uhcip->uhci_polled_flag = 669 UHCI_POLLED_FLAG_TD_COMPL; 670 } 671 break; 672 } 673 td = td->outst_td_next; 674 } 675 /* 676 * Only the first keyboard enter reset the frame number and start 677 * the host controler processing. 678 */ 679 if (uhcip->uhci_polled_count == 1) { 680 /* Set the frame number to zero */ 681 Set_OpReg16(FRNUM, 0); 682 683 /* 684 * Start the Host controller processing 685 */ 686 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 | 687 USBCMD_REG_CONFIG_FLAG)); 688 } 689 690 #ifndef lint 691 _NOTE(COMPETING_THREADS_NOW); 692 #endif 693 } 694 695 696 /* 697 * uhci_polled_restore_state: 698 */ 699 static void 700 uhci_polled_restore_state(uhci_polled_t *uhci_polledp) 701 { 702 int i; 703 ushort_t real_data_toggle; 704 uhci_td_t *td, *polled_td; 705 uhci_state_t *uhcip; 706 uhci_pipe_private_t *pp; 707 708 #ifndef lint 709 _NOTE(NO_COMPETING_THREADS_NOW); 710 #endif 711 /* 712 * If this flags is set, then we are still using this structure, 713 * so don't restore any controller state information yet. 714 */ 715 if (uhci_polledp->uhci_polled_flags & POLLED_INPUT_MODE_INUSE) { 716 #ifndef lint 717 _NOTE(COMPETING_THREADS_NOW); 718 #endif 719 return; 720 } 721 722 uhcip = uhci_polledp->uhci_polled_uhcip; 723 uhcip->uhci_polled_count --; 724 725 /* Just first leave keyboard entry turn off the controller */ 726 if (Get_OpReg16(USBCMD)) { 727 Set_OpReg16(USBCMD, 0x0); 728 } 729 /* Only the last leave keyboard entry restore the interrupt table */ 730 if (uhcip->uhci_polled_count == 0) { 731 /* 732 * Replace the lattice 733 */ 734 for (i = 0; i < NUM_FRAME_LST_ENTRIES; i++) { 735 uhcip->uhci_frame_lst_tablep[i] = 736 uhcip->uhci_polled_save_IntTble[i]; 737 } 738 } 739 740 /* 741 * Adjust data toggle 742 */ 743 pp = (uhci_pipe_private_t *) 744 uhci_polledp->uhci_polled_ph->p_hcd_private; 745 746 polled_td = uhci_polledp->uhci_polled_td; 747 real_data_toggle = (GetTD_status(uhcip, polled_td) & UHCI_TD_ACTIVE) ? 748 GetTD_dtogg(uhcip, polled_td) : 749 !GetTD_dtogg(uhcip, polled_td); 750 751 td = uhcip->uhci_outst_tds_head; 752 while (td != NULL) { 753 if (td->tw->tw_pipe_private->pp_pipe_handle == 754 uhci_polledp->uhci_polled_ph) { 755 if (GetTD_status(uhcip, td) & UHCI_TD_ACTIVE) { 756 SetTD_dtogg(uhcip, td, real_data_toggle); 757 pp->pp_data_toggle = 758 (real_data_toggle == 0) ? 1 : 0; 759 } else { 760 pp->pp_data_toggle = (uchar_t)real_data_toggle; 761 } 762 } 763 td = td->outst_td_next; 764 } 765 766 /* 767 * Only the last leave keyboard entry enable the interrupts, 768 * start Host controller processing. 769 */ 770 if (uhcip->uhci_polled_count == 0) { 771 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS); 772 Set_OpReg16(USBCMD, (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 | 773 USBCMD_REG_CONFIG_FLAG)); 774 if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TD_COMPL) { 775 uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_TRUE; 776 } 777 } 778 779 #ifndef lint 780 _NOTE(COMPETING_THREADS_NOW); 781 #endif 782 } 783 784 785 /* 786 * uhci_polled_insert_td: 787 * Initializes the transfer descriptor for polling and inserts on the 788 * polled queue head. This will be put in action when entered in to 789 * polled mode. 790 */ 791 static int 792 uhci_polled_insert_td_on_qh(uhci_polled_t *uhci_polledp, 793 usba_pipe_handle_data_t *ph) 794 { 795 uhci_td_t *td; 796 uhci_state_t *uhcip = uhci_polledp->uhci_polled_uhcip; 797 usb_ep_descr_t *eptd; 798 uhci_trans_wrapper_t *tw; 799 uint_t direction; 800 801 /* Create the transfer wrapper */ 802 if ((tw = uhci_polled_create_tw(uhci_polledp->uhci_polled_uhcip)) == 803 NULL) { 804 805 return (USB_FAILURE); 806 } 807 808 /* Use the dummy TD allocated for the queue head */ 809 td = uhci_polledp->uhci_polled_qh->td_tailp; 810 bzero((char *)td, sizeof (uhci_td_t)); 811 812 uhci_polledp->uhci_polled_td = td; 813 td->tw = tw; 814 td->flag = TD_FLAG_BUSY; 815 SetTD32(uhcip, td->link_ptr, HC_END_OF_LIST); 816 817 mutex_enter(&ph->p_usba_device->usb_mutex); 818 if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) { 819 SetTD_ls(uhcip, td, LOW_SPEED_DEVICE); 820 } 821 822 eptd = &ph->p_ep; 823 direction = (UHCI_XFER_DIR(eptd) == USB_EP_DIR_OUT) ? PID_OUT : PID_IN; 824 SetTD_c_err(uhcip, td, UHCI_MAX_ERR_COUNT); 825 SetTD_mlen(uhcip, td, POLLED_RAW_BUF_SIZE - 1); 826 SetTD_devaddr(uhcip, td, ph->p_usba_device->usb_addr); 827 SetTD_endpt(uhcip, td, eptd->bEndpointAddress & END_POINT_ADDRESS_MASK); 828 SetTD_PID(uhcip, td, direction); 829 SetTD32(uhcip, td->buffer_address, tw->tw_cookie.dmac_address); 830 SetTD_ioc(uhcip, td, INTERRUPT_ON_COMPLETION); 831 SetTD_status(uhcip, td, UHCI_TD_ACTIVE); 832 mutex_exit(&ph->p_usba_device->usb_mutex); 833 834 SetQH32(uhcip, uhci_polledp->uhci_polled_qh->element_ptr, TD_PADDR(td)); 835 836 return (USB_SUCCESS); 837 } 838 839 840 /* 841 * uhci_polled_create_wrapper_t: 842 * Creates the transfer wrapper used in polled mode. 843 */ 844 static uhci_trans_wrapper_t * 845 uhci_polled_create_tw(uhci_state_t *uhcip) 846 { 847 uint_t result, ccount; 848 size_t real_length; 849 uhci_trans_wrapper_t *tw; 850 ddi_device_acc_attr_t dev_attr; 851 852 /* Allocate space for the transfer wrapper */ 853 if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), KM_NOSLEEP)) == 854 NULL) { 855 856 return (NULL); 857 } 858 859 tw->tw_length = POLLED_RAW_BUF_SIZE; 860 861 /* Allocate the DMA handle */ 862 if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip, 863 &uhcip->uhci_dma_attr, DDI_DMA_DONTWAIT, 0, &tw->tw_dmahandle)) != 864 DDI_SUCCESS) { 865 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 866 867 return (NULL); 868 } 869 870 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 871 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 872 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 873 874 /* Allocate the memory */ 875 if ((result = ddi_dma_mem_alloc(tw->tw_dmahandle, POLLED_RAW_BUF_SIZE, 876 &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 877 &tw->tw_buf, &real_length, &tw->tw_accesshandle)) != 878 DDI_SUCCESS) { 879 ddi_dma_free_handle(&tw->tw_dmahandle); 880 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 881 882 return (NULL); 883 } 884 885 /* Bind the handle */ 886 if ((result = ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL, 887 tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT, 888 DDI_DMA_DONTWAIT, NULL, &tw->tw_cookie, &ccount)) != 889 DDI_DMA_MAPPED) { 890 ddi_dma_mem_free(&tw->tw_accesshandle); 891 ddi_dma_free_handle(&tw->tw_dmahandle); 892 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 893 894 return (NULL); 895 } 896 897 /* The cookie count should be 1 */ 898 if (ccount != 1) { 899 result = ddi_dma_unbind_handle(tw->tw_dmahandle); 900 ASSERT(result == DDI_SUCCESS); 901 902 ddi_dma_mem_free(&tw->tw_accesshandle); 903 ddi_dma_free_handle(&tw->tw_dmahandle); 904 kmem_free(tw, sizeof (uhci_trans_wrapper_t)); 905 906 return (NULL); 907 } 908 909 return (tw); 910 } 911