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