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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 /*
  28  * Universal Host Controller Driver (UHCI)
  29  *
  30  * The UHCI driver is a driver which interfaces to the Universal
  31  * Serial Bus Driver (USBA) and the Host Controller (HC). The interface to
  32  * the Host Controller is defined by the UHCI.
  33  * This file contains misc functions.
  34  */
  35 #include <sys/usb/hcd/uhci/uhcid.h>
  36 #include <sys/usb/hcd/uhci/uhciutil.h>
  37 #include <sys/usb/hcd/uhci/uhcipolled.h>
  38 
  39 #include <sys/disp.h>
  40 
  41 /* Globals */
  42 extern uint_t   uhci_td_pool_size;                      /* Num TDs */
  43 extern uint_t   uhci_qh_pool_size;                      /* Num QHs */
  44 extern ushort_t uhci_tree_bottom_nodes[];
  45 extern void     *uhci_statep;
  46 
  47 /* function prototypes */
  48 static void     uhci_build_interrupt_lattice(uhci_state_t *uhcip);
  49 static int      uhci_init_frame_lst_table(dev_info_t *dip, uhci_state_t *uhcip);
  50 
  51 static uint_t   uhci_lattice_height(uint_t bandwidth);
  52 static uint_t   uhci_lattice_parent(uint_t node);
  53 static uint_t   uhci_leftmost_leaf(uint_t node, uint_t height);
  54 static uint_t   uhci_compute_total_bandwidth(usb_ep_descr_t *endpoint,
  55                     usb_port_status_t port_status);
  56 
  57 static int      uhci_bandwidth_adjust(uhci_state_t *uhcip,
  58                     usb_ep_descr_t *endpoint, usb_port_status_t port_status);
  59 
  60 static uhci_td_t *uhci_allocate_td_from_pool(uhci_state_t *uhcip);
  61 static void     uhci_fill_in_td(uhci_state_t *uhcip,
  62                     uhci_td_t *td, uhci_td_t *current_dummy,
  63                     uint32_t buffer_offset, size_t length,
  64                     uhci_pipe_private_t *pp, uchar_t PID,
  65                     usb_req_attrs_t attrs, uhci_trans_wrapper_t *tw);
  66 static uint32_t uhci_get_tw_paddr_by_offs(uhci_state_t *uhcip,
  67                     uint32_t buffer_offset, size_t length,
  68                     uhci_trans_wrapper_t *tw);
  69 static uhci_trans_wrapper_t *uhci_create_transfer_wrapper(
  70                     uhci_state_t *uhcip, uhci_pipe_private_t *pp,
  71                     size_t length, usb_flags_t usb_flags);
  72 static uhci_trans_wrapper_t *uhci_create_isoc_transfer_wrapper(
  73                     uhci_state_t *uhcip, uhci_pipe_private_t *pp,
  74                     usb_isoc_req_t *req, size_t length,
  75                     usb_flags_t usb_flags);
  76 
  77 static int      uhci_create_setup_pkt(uhci_state_t *uhcip,
  78                     uhci_pipe_private_t *pp, uhci_trans_wrapper_t *tw);
  79 static void     uhci_insert_ctrl_qh(uhci_state_t *uhcip,
  80                     uhci_pipe_private_t *pp);
  81 static void     uhci_remove_ctrl_qh(uhci_state_t *uhcip,
  82                     uhci_pipe_private_t *pp);
  83 static void     uhci_insert_intr_qh(uhci_state_t *uhcip,
  84                     uhci_pipe_private_t *pp);
  85 static void     uhci_remove_intr_qh(uhci_state_t *uhcip,
  86                     uhci_pipe_private_t *pp);
  87 static void     uhci_remove_bulk_qh(uhci_state_t *uhcip,
  88                     uhci_pipe_private_t *pp);
  89 static void     uhci_insert_bulk_qh(uhci_state_t *uhcip,
  90                     uhci_pipe_private_t *pp);
  91 static void     uhci_handle_bulk_td_errors(uhci_state_t *uhcip, uhci_td_t *td);
  92 static int      uhci_alloc_memory_for_tds(uhci_state_t *uhcip, uint_t num_tds,
  93                     uhci_bulk_isoc_xfer_t *info);
  94 static int      uhci_alloc_bulk_isoc_tds(uhci_state_t *uhcip, uint_t num_tds,
  95                     uhci_bulk_isoc_xfer_t *info);
  96 static void     uhci_get_isoc_td_by_index(uhci_state_t *uhcip,
  97                     uhci_bulk_isoc_xfer_t *info, uint_t index,
  98                     uhci_td_t **tdpp, uhci_bulk_isoc_td_pool_t **td_pool_pp);
  99 static void     uhci_get_bulk_td_by_paddr(uhci_state_t *uhcip,
 100                     uhci_bulk_isoc_xfer_t *info, uint32_t paddr,
 101                     uhci_bulk_isoc_td_pool_t **td_pool_pp);
 102 
 103 static  int     uhci_handle_isoc_receive(uhci_state_t *uhcip,
 104                 uhci_pipe_private_t *pp, uhci_trans_wrapper_t *tw);
 105 static void     uhci_delete_isoc_td(uhci_state_t *uhcip,
 106                     uhci_td_t *td);
 107 #ifdef DEBUG
 108 static void     uhci_print_td(uhci_state_t *uhcip, uhci_td_t *td);
 109 static void     uhci_print_qh(uhci_state_t *uhcip, queue_head_t *qh);
 110 #endif
 111 
 112 
 113 /*
 114  * uhci_build_interrupt_lattice:
 115  *
 116  * Construct the interrupt lattice tree using static Queue Head pointers.
 117  * This interrupt lattice tree will have total of 63 queue heads and the
 118  * Host Controller (HC) processes queue heads every frame.
 119  */
 120 static void
 121 uhci_build_interrupt_lattice(uhci_state_t *uhcip)
 122 {
 123         int                     half_list = NUM_INTR_QH_LISTS / 2;
 124         uint16_t                i, j, k;
 125         uhci_td_t               *sof_td, *isoc_td;
 126         uintptr_t               addr;
 127         queue_head_t            *list_array = uhcip->uhci_qh_pool_addr;
 128         queue_head_t            *tmp_qh;
 129         frame_lst_table_t       *frame_lst_tablep =
 130             uhcip->uhci_frame_lst_tablep;
 131 
 132         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 133             "uhci_build_interrupt_lattice:");
 134 
 135         /*
 136          * Reserve the first 63 queue head structures in the pool as static
 137          * queue heads & these are required for constructing interrupt
 138          * lattice tree.
 139          */
 140         for (i = 0; i < NUM_INTR_QH_LISTS; i++) {
 141                 SetQH32(uhcip, list_array[i].link_ptr, HC_END_OF_LIST);
 142                 SetQH32(uhcip, list_array[i].element_ptr, HC_END_OF_LIST);
 143                 list_array[i].qh_flag           = QUEUE_HEAD_FLAG_STATIC;
 144                 list_array[i].node              = i;
 145         }
 146 
 147         /* Build the interrupt lattice tree */
 148         for (i = 0; i < half_list - 1; i++) {
 149                 /*
 150                  * The next  pointer in the host controller  queue head
 151                  * descriptor must contain an iommu address. Calculate
 152                  * the offset into the cpu address and add this to the
 153                  * starting iommu address.
 154                  */
 155                 addr = QH_PADDR(&list_array[i]) | HC_QUEUE_HEAD;
 156 
 157                 SetQH32(uhcip, list_array[2*i + 1].link_ptr, addr);
 158                 SetQH32(uhcip, list_array[2*i + 2].link_ptr, addr);
 159         }
 160 
 161         /*
 162          * Initialize the interrupt list in the Frame list Table
 163          * so that it points to the bottom of the tree.
 164          */
 165         for (i = 0, j = 0; i < pow_2(TREE_HEIGHT); i++) {
 166                 addr = QH_PADDR(&list_array[half_list + i - 1]);
 167                 for (k = 0; k <  pow_2(VIRTUAL_TREE_HEIGHT); k++) {
 168                         SetFL32(uhcip,
 169                             frame_lst_tablep[uhci_tree_bottom_nodes[j++]],
 170                             addr | HC_QUEUE_HEAD);
 171                 }
 172         }
 173 
 174         /*
 175          *  Create a controller and bulk Queue heads
 176          */
 177         uhcip->uhci_ctrl_xfers_q_head = uhci_alloc_queue_head(uhcip);
 178         tmp_qh = uhcip->uhci_ctrl_xfers_q_tail = uhcip->uhci_ctrl_xfers_q_head;
 179 
 180         SetQH32(uhcip, list_array[0].link_ptr,
 181             (QH_PADDR(tmp_qh) | HC_QUEUE_HEAD));
 182 
 183         uhcip->uhci_bulk_xfers_q_head = uhci_alloc_queue_head(uhcip);
 184         uhcip->uhci_bulk_xfers_q_tail = uhcip->uhci_bulk_xfers_q_head;
 185         SetQH32(uhcip, tmp_qh->link_ptr,
 186             (QH_PADDR(uhcip->uhci_bulk_xfers_q_head)|HC_QUEUE_HEAD));
 187 
 188         SetQH32(uhcip, uhcip->uhci_bulk_xfers_q_head->link_ptr, HC_END_OF_LIST);
 189 
 190         /*
 191          * Add a dummy TD to the static queue head 0. THis is used
 192          * to generate an at the end of frame.
 193          */
 194         sof_td = uhci_allocate_td_from_pool(uhcip);
 195 
 196         SetQH32(uhcip, list_array[0].element_ptr,
 197             TD_PADDR(sof_td) | HC_TD_HEAD);
 198         SetTD32(uhcip, sof_td->link_ptr, HC_END_OF_LIST);
 199         uhcip->uhci_sof_td = sof_td;
 200 
 201         /*
 202          * Add a dummy td that is used to generate an interrupt for
 203          * every 1024 frames.
 204          */
 205         isoc_td = uhci_allocate_td_from_pool(uhcip);
 206         SetTD32(uhcip, isoc_td->link_ptr, HC_END_OF_LIST);
 207         uhcip->uhci_isoc_td = isoc_td;
 208 
 209         uhcip->uhci_isoc_qh = uhci_alloc_queue_head(uhcip);
 210         SetQH32(uhcip, uhcip->uhci_isoc_qh->link_ptr,
 211             GetFL32(uhcip, uhcip->uhci_frame_lst_tablep[MAX_FRAME_NUM]));
 212         SetQH32(uhcip, uhcip->uhci_isoc_qh->element_ptr, TD_PADDR(isoc_td));
 213         SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[MAX_FRAME_NUM],
 214             QH_PADDR(uhcip->uhci_isoc_qh) | HC_QUEUE_HEAD);
 215 }
 216 
 217 
 218 /*
 219  * uhci_allocate_pools:
 220  *      Allocate the system memory for the Queue Heads Descriptor and
 221  *      for the Transfer Descriptor (TD) pools. Both QH and TD structures
 222  *      must be aligned to a 16 byte boundary.
 223  */
 224 int
 225 uhci_allocate_pools(uhci_state_t *uhcip)
 226 {
 227         dev_info_t              *dip = uhcip->uhci_dip;
 228         size_t                  real_length;
 229         int                     i, result;
 230         uint_t                  ccount;
 231         ddi_device_acc_attr_t   dev_attr;
 232 
 233         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 234             "uhci_allocate_pools:");
 235 
 236         /* The host controller will be little endian */
 237         dev_attr.devacc_attr_version            = DDI_DEVICE_ATTR_V0;
 238         dev_attr.devacc_attr_endian_flags       = DDI_STRUCTURE_LE_ACC;
 239         dev_attr.devacc_attr_dataorder          = DDI_STRICTORDER_ACC;
 240 
 241         /* Allocate the TD pool DMA handle */
 242         if (ddi_dma_alloc_handle(dip, &uhcip->uhci_dma_attr, DDI_DMA_SLEEP, 0,
 243             &uhcip->uhci_td_pool_dma_handle) != DDI_SUCCESS) {
 244 
 245                 return (USB_FAILURE);
 246         }
 247 
 248         /* Allocate the memory for the TD pool */
 249         if (ddi_dma_mem_alloc(uhcip->uhci_td_pool_dma_handle,
 250             uhci_td_pool_size * sizeof (uhci_td_t),
 251             &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
 252             (caddr_t *)&uhcip->uhci_td_pool_addr, &real_length,
 253             &uhcip->uhci_td_pool_mem_handle)) {
 254 
 255                 return (USB_FAILURE);
 256         }
 257 
 258         /* Map the TD pool into the I/O address space */
 259         result = ddi_dma_addr_bind_handle(uhcip->uhci_td_pool_dma_handle,
 260             NULL, (caddr_t)uhcip->uhci_td_pool_addr, real_length,
 261             DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP,
 262             NULL, &uhcip->uhci_td_pool_cookie, &ccount);
 263 
 264         bzero((void *)uhcip->uhci_td_pool_addr,
 265             uhci_td_pool_size * sizeof (uhci_td_t));
 266 
 267         /* Process the result */
 268         if (result == DDI_DMA_MAPPED) {
 269                 /* The cookie count should be 1 */
 270                 if (ccount != 1) {
 271                         USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 272                             "uhci_allocate_pools: More than 1 cookie");
 273 
 274                         return (USB_FAILURE);
 275                 }
 276         } else {
 277                 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 278                     "uhci_allocate_pools: Result = %d", result);
 279 
 280                 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip, result);
 281 
 282                 return (USB_FAILURE);
 283         }
 284 
 285         uhcip->uhci_dma_addr_bind_flag |= UHCI_TD_POOL_BOUND;
 286 
 287         /* Initialize the TD pool */
 288         for (i = 0; i < uhci_td_pool_size; i++) {
 289                 uhcip->uhci_td_pool_addr[i].flag = TD_FLAG_FREE;
 290         }
 291 
 292         /* Allocate the TD pool DMA handle */
 293         if (ddi_dma_alloc_handle(dip, &uhcip->uhci_dma_attr, DDI_DMA_SLEEP,
 294             0, &uhcip->uhci_qh_pool_dma_handle) != DDI_SUCCESS) {
 295 
 296                 return (USB_FAILURE);
 297         }
 298 
 299         /* Allocate the memory for the QH pool */
 300         if (ddi_dma_mem_alloc(uhcip->uhci_qh_pool_dma_handle,
 301             uhci_qh_pool_size * sizeof (queue_head_t),
 302             &dev_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
 303             (caddr_t *)&uhcip->uhci_qh_pool_addr, &real_length,
 304             &uhcip->uhci_qh_pool_mem_handle) != DDI_SUCCESS) {
 305 
 306                 return (USB_FAILURE);
 307         }
 308 
 309         result = ddi_dma_addr_bind_handle(uhcip->uhci_qh_pool_dma_handle,
 310             NULL, (caddr_t)uhcip->uhci_qh_pool_addr, real_length,
 311             DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
 312             &uhcip->uhci_qh_pool_cookie, &ccount);
 313 
 314         /* Process the result */
 315         if (result == DDI_DMA_MAPPED) {
 316                 /* The cookie count should be 1 */
 317                 if (ccount != 1) {
 318                         USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 319                             "uhci_allocate_pools: More than 1 cookie");
 320 
 321                         return (USB_FAILURE);
 322                 }
 323         } else {
 324                 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip, result);
 325 
 326                 return (USB_FAILURE);
 327         }
 328 
 329         uhcip->uhci_dma_addr_bind_flag |= UHCI_QH_POOL_BOUND;
 330 
 331         bzero((void *)uhcip->uhci_qh_pool_addr,
 332             uhci_qh_pool_size * sizeof (queue_head_t));
 333 
 334         /* Initialize the QH pool */
 335         for (i = 0; i < uhci_qh_pool_size; i ++) {
 336                 uhcip->uhci_qh_pool_addr[i].qh_flag = QUEUE_HEAD_FLAG_FREE;
 337         }
 338 
 339         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 340             "uhci_allocate_pools: Completed");
 341 
 342         return (USB_SUCCESS);
 343 }
 344 
 345 
 346 /*
 347  * uhci_free_pools:
 348  *      Cleanup on attach failure or detach
 349  */
 350 void
 351 uhci_free_pools(uhci_state_t *uhcip)
 352 {
 353         int                     i, flag, rval;
 354         uhci_td_t               *td;
 355         uhci_trans_wrapper_t    *tw;
 356 
 357         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 358             "uhci_free_pools:");
 359 
 360         if (uhcip->uhci_td_pool_addr && uhcip->uhci_td_pool_mem_handle) {
 361                 for (i = 0; i < uhci_td_pool_size; i ++) {
 362                         td = &uhcip->uhci_td_pool_addr[i];
 363 
 364                         flag = uhcip->uhci_td_pool_addr[i].flag;
 365                         if ((flag != TD_FLAG_FREE) &&
 366                             (flag != TD_FLAG_DUMMY) && (td->tw != NULL)) {
 367                                 tw = td->tw;
 368                                 uhci_free_tw(uhcip, tw);
 369                         }
 370 
 371                 }
 372 
 373                 if (uhcip->uhci_dma_addr_bind_flag & UHCI_TD_POOL_BOUND) {
 374                         rval = ddi_dma_unbind_handle(
 375                             uhcip->uhci_td_pool_dma_handle);
 376                         ASSERT(rval == DDI_SUCCESS);
 377                 }
 378 
 379                 ddi_dma_mem_free(&uhcip->uhci_td_pool_mem_handle);
 380         }
 381 
 382         /* Free the TD pool */
 383         if (uhcip->uhci_td_pool_dma_handle) {
 384                 ddi_dma_free_handle(&uhcip->uhci_td_pool_dma_handle);
 385         }
 386 
 387         if (uhcip->uhci_qh_pool_addr && uhcip->uhci_qh_pool_mem_handle) {
 388                 if (uhcip->uhci_dma_addr_bind_flag & UHCI_QH_POOL_BOUND) {
 389                         rval = ddi_dma_unbind_handle(
 390                             uhcip->uhci_qh_pool_dma_handle);
 391                         ASSERT(rval == DDI_SUCCESS);
 392                 }
 393                 ddi_dma_mem_free(&uhcip->uhci_qh_pool_mem_handle);
 394         }
 395 
 396         /* Free the QH pool */
 397         if (uhcip->uhci_qh_pool_dma_handle) {
 398                 ddi_dma_free_handle(&uhcip->uhci_qh_pool_dma_handle);
 399         }
 400 
 401         /* Free the Frame list Table area */
 402         if (uhcip->uhci_frame_lst_tablep && uhcip->uhci_flt_mem_handle) {
 403                 if (uhcip->uhci_dma_addr_bind_flag & UHCI_FLA_POOL_BOUND) {
 404                         rval = ddi_dma_unbind_handle(
 405                             uhcip->uhci_flt_dma_handle);
 406                         ASSERT(rval == DDI_SUCCESS);
 407                 }
 408                 ddi_dma_mem_free(&uhcip->uhci_flt_mem_handle);
 409         }
 410 
 411         if (uhcip->uhci_flt_dma_handle) {
 412                 ddi_dma_free_handle(&uhcip->uhci_flt_dma_handle);
 413         }
 414 }
 415 
 416 
 417 /*
 418  * uhci_decode_ddi_dma_addr_bind_handle_result:
 419  *      Process the return values of ddi_dma_addr_bind_handle()
 420  */
 421 void
 422 uhci_decode_ddi_dma_addr_bind_handle_result(uhci_state_t *uhcip, int result)
 423 {
 424         char *msg;
 425 
 426         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
 427             "uhci_decode_ddi_dma_addr_bind_handle_result:");
 428 
 429         switch (result) {
 430         case DDI_DMA_PARTIAL_MAP:
 431                 msg = "Partial transfers not allowed";
 432                 break;
 433         case DDI_DMA_INUSE:
 434                 msg = "Handle is in use";
 435                 break;
 436         case DDI_DMA_NORESOURCES:
 437                 msg = "No resources";
 438                 break;
 439         case DDI_DMA_NOMAPPING:
 440                 msg = "No mapping";
 441                 break;
 442         case DDI_DMA_TOOBIG:
 443                 msg = "Object is too big";
 444                 break;
 445         default:
 446                 msg = "Unknown dma error";
 447         }
 448 
 449         USB_DPRINTF_L4(PRINT_MASK_ALL, uhcip->uhci_log_hdl, "%s", msg);
 450 }
 451 
 452 
 453 /*
 454  * uhci_init_ctlr:
 455  *      Initialize the Host Controller (HC).
 456  */
 457 int
 458 uhci_init_ctlr(uhci_state_t *uhcip)
 459 {
 460         dev_info_t *dip = uhcip->uhci_dip;
 461         uint_t  cmd_reg;
 462         uint_t  frame_base_addr;
 463 
 464         mutex_enter(&uhcip->uhci_int_mutex);
 465 
 466         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_init_ctlr:");
 467 
 468         /*
 469          * When USB legacy mode is enabled, the BIOS manages the USB keyboard
 470          * attached to the UHCI controller. It has been observed that some
 471          * times the BIOS does not clear the interrupts in the legacy mode
 472          * register in the PCI configuration space. So, disable the SMI intrs
 473          * and route the intrs to PIRQD here.
 474          */
 475         pci_config_put16(uhcip->uhci_config_handle,
 476             LEGACYMODE_REG_OFFSET, LEGACYMODE_REG_INIT_VALUE);
 477 
 478         /*
 479          * Disable all the interrupts.
 480          */
 481         Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
 482 
 483         cmd_reg = Get_OpReg16(USBCMD);
 484         cmd_reg &= (~USBCMD_REG_HC_RUN);
 485 
 486         /* Stop the controller */
 487         Set_OpReg16(USBCMD, cmd_reg);
 488 
 489         /* Reset the host controller */
 490         Set_OpReg16(USBCMD, USBCMD_REG_GBL_RESET);
 491 
 492         /* Wait 10ms for reset to complete */
 493         mutex_exit(&uhcip->uhci_int_mutex);
 494         delay(drv_usectohz(UHCI_RESET_DELAY));
 495         mutex_enter(&uhcip->uhci_int_mutex);
 496 
 497         Set_OpReg16(USBCMD, 0);
 498 
 499         /* Set the frame number to zero */
 500         Set_OpReg16(FRNUM, 0);
 501 
 502         if (uhcip->uhci_hc_soft_state == UHCI_CTLR_INIT_STATE) {
 503                 /* Initialize the Frame list base address area */
 504                 if (uhci_init_frame_lst_table(dip, uhcip) != USB_SUCCESS) {
 505                         mutex_exit(&uhcip->uhci_int_mutex);
 506 
 507                         return (USB_FAILURE);
 508                 }
 509         }
 510 
 511         /* Save the contents of the Frame Interval Registers */
 512         uhcip->uhci_frame_interval = Get_OpReg8(SOFMOD);
 513 
 514         frame_base_addr = uhcip->uhci_flt_cookie.dmac_address;
 515 
 516         /* Set the Frame list base address */
 517         Set_OpReg32(FRBASEADD, frame_base_addr);
 518 
 519         /*
 520          * Begin sending SOFs
 521          * Set the Host Controller Functional State to Operational
 522          */
 523         cmd_reg = Get_OpReg16(USBCMD);
 524         cmd_reg |= (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
 525             USBCMD_REG_CONFIG_FLAG);
 526 
 527         Set_OpReg16(USBCMD, cmd_reg);
 528 
 529         /*
 530          * Verify the Command and interrupt enable registers,
 531          * a sanity check whether actually initialized or not
 532          */
 533         cmd_reg = Get_OpReg16(USBCMD);
 534 
 535         if (!(cmd_reg & (USBCMD_REG_HC_RUN | USBCMD_REG_MAXPKT_64 |
 536             USBCMD_REG_CONFIG_FLAG))) {
 537                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 538                     "uhci_init_ctlr: Controller initialization failed");
 539                 mutex_exit(&uhcip->uhci_int_mutex);
 540 
 541                 return (USB_FAILURE);
 542         }
 543 
 544         /*
 545          * Set the ioc bit of the isoc intr td. This enables
 546          * the generation of an interrupt for every 1024 frames.
 547          */
 548         SetTD_ioc(uhcip, uhcip->uhci_isoc_td, 1);
 549 
 550         /* Set host controller soft state to operational */
 551         uhcip->uhci_hc_soft_state = UHCI_CTLR_OPERATIONAL_STATE;
 552         mutex_exit(&uhcip->uhci_int_mutex);
 553 
 554         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 555             "uhci_init_ctlr: Completed");
 556 
 557         return (USB_SUCCESS);
 558 }
 559 
 560 
 561 /*
 562  * uhci_uninit_ctlr:
 563  *      uninitialize the Host Controller (HC).
 564  */
 565 void
 566 uhci_uninit_ctlr(uhci_state_t *uhcip)
 567 {
 568         if (uhcip->uhci_regs_handle) {
 569                 /* Disable all the interrupts. */
 570                 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS);
 571 
 572                 /* Complete the current transaction and then halt. */
 573                 Set_OpReg16(USBCMD, 0);
 574 
 575                 /* Wait for sometime */
 576                 mutex_exit(&uhcip->uhci_int_mutex);
 577                 delay(drv_usectohz(UHCI_TIMEWAIT));
 578                 mutex_enter(&uhcip->uhci_int_mutex);
 579         }
 580 }
 581 
 582 
 583 /*
 584  * uhci_map_regs:
 585  *      The Host Controller (HC) contains a set of on-chip operational
 586  *      registers and which should be mapped into a non-cacheable
 587  *      portion of the system addressable space.
 588  */
 589 int
 590 uhci_map_regs(uhci_state_t *uhcip)
 591 {
 592         dev_info_t              *dip = uhcip->uhci_dip;
 593         int                     index;
 594         uint32_t                regs_prop_len;
 595         int32_t                 *regs_list;
 596         uint16_t                command_reg;
 597         ddi_device_acc_attr_t   attr;
 598 
 599         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_map_regs:");
 600 
 601         /* The host controller will be little endian */
 602         attr.devacc_attr_version        = DDI_DEVICE_ATTR_V0;
 603         attr.devacc_attr_endian_flags   = DDI_STRUCTURE_LE_ACC;
 604         attr.devacc_attr_dataorder      = DDI_STRICTORDER_ACC;
 605 
 606         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, uhcip->uhci_dip,
 607             DDI_PROP_DONTPASS, "reg", &regs_list, &regs_prop_len) !=
 608             DDI_PROP_SUCCESS) {
 609 
 610                 return (USB_FAILURE);
 611         }
 612 
 613         for (index = 0; index * 5 < regs_prop_len; index++) {
 614                 if (regs_list[index * 5] & UHCI_PROP_MASK) {
 615                         break;
 616                 }
 617         }
 618 
 619         /*
 620          * Deallocate the memory allocated by the ddi_prop_lookup_int_array
 621          */
 622         ddi_prop_free(regs_list);
 623 
 624         if (index * 5 >= regs_prop_len) {
 625 
 626                 return (USB_FAILURE);
 627         }
 628 
 629         /* Map in operational registers */
 630         if (ddi_regs_map_setup(dip, index, (caddr_t *)&uhcip->uhci_regsp,
 631             0, sizeof (hc_regs_t), &attr, &uhcip->uhci_regs_handle) !=
 632             DDI_SUCCESS) {
 633                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 634                     "ddi_regs_map_setup: failed");
 635 
 636                 return (USB_FAILURE);
 637         }
 638 
 639         if (pci_config_setup(dip, &uhcip->uhci_config_handle) != DDI_SUCCESS) {
 640                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 641                     "uhci_map_regs: Config error");
 642 
 643                 return (USB_FAILURE);
 644         }
 645 
 646         /* Make sure Memory Access Enable and Master Enable are set */
 647         command_reg = pci_config_get16(uhcip->uhci_config_handle,
 648             PCI_CONF_COMM);
 649         if (!(command_reg & (PCI_COMM_MAE | PCI_COMM_ME))) {
 650                 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 651                     "uhci_map_regs: No MAE/ME");
 652         }
 653 
 654         command_reg |= PCI_COMM_MAE | PCI_COMM_ME;
 655         pci_config_put16(uhcip->uhci_config_handle, PCI_CONF_COMM, command_reg);
 656 
 657         /*
 658          * Check whether I/O base address is configured and enabled.
 659          */
 660         if (!(command_reg & PCI_COMM_IO)) {
 661                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 662                     "I/O Base address access disabled");
 663 
 664                 return (USB_FAILURE);
 665         }
 666         /*
 667          * Get the IO base address of the controller
 668          */
 669         uhcip->uhci_iobase = (pci_config_get16(uhcip->uhci_config_handle,
 670             PCI_CONF_IOBASE) & PCI_CONF_IOBASE_MASK);
 671 
 672         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 673             "uhci_map_regs: Completed");
 674 
 675         return (USB_SUCCESS);
 676 }
 677 
 678 
 679 void
 680 uhci_unmap_regs(uhci_state_t *uhcip)
 681 {
 682         /* Unmap the UHCI registers */
 683         if (uhcip->uhci_regs_handle) {
 684                 /* Reset the host controller */
 685                 Set_OpReg16(USBCMD, USBCMD_REG_GBL_RESET);
 686 
 687                 ddi_regs_map_free(&uhcip->uhci_regs_handle);
 688         }
 689 
 690         if (uhcip->uhci_config_handle) {
 691                 pci_config_teardown(&uhcip->uhci_config_handle);
 692         }
 693 }
 694 
 695 
 696 /*
 697  * uhci_set_dma_attributes:
 698  *      Set the limits in the DMA attributes structure. Most of the values used
 699  *      in the  DMA limit structres are the default values as specified by  the
 700  *      Writing PCI device drivers document.
 701  */
 702 void
 703 uhci_set_dma_attributes(uhci_state_t *uhcip)
 704 {
 705         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 706             "uhci_set_dma_attributes:");
 707 
 708         /* Initialize the DMA attributes */
 709         uhcip->uhci_dma_attr.dma_attr_version = DMA_ATTR_V0;
 710         uhcip->uhci_dma_attr.dma_attr_addr_lo = 0x00000000ull;
 711         uhcip->uhci_dma_attr.dma_attr_addr_hi = 0xfffffff0ull;
 712 
 713         /* 32 bit addressing */
 714         uhcip->uhci_dma_attr.dma_attr_count_max = 0xffffffull;
 715 
 716         /*
 717          * Setting the dam_att_align to 512, some times fails the
 718          * binding handle. I dont know why ? But setting to 16 will
 719          * be right for our case (16 byte alignment required per
 720          * UHCI spec for TD descriptors).
 721          */
 722 
 723         /* 16 byte alignment */
 724         uhcip->uhci_dma_attr.dma_attr_align = 0x10;
 725 
 726         /*
 727          * Since PCI  specification is byte alignment, the
 728          * burstsize field should be set to 1 for PCI devices.
 729          */
 730         uhcip->uhci_dma_attr.dma_attr_burstsizes = 0x1;
 731 
 732         uhcip->uhci_dma_attr.dma_attr_minxfer        = 0x1;
 733         uhcip->uhci_dma_attr.dma_attr_maxxfer        = 0xffffffull;
 734         uhcip->uhci_dma_attr.dma_attr_seg    = 0xffffffffull;
 735         uhcip->uhci_dma_attr.dma_attr_sgllen = 1;
 736         uhcip->uhci_dma_attr.dma_attr_granular       = 1;
 737         uhcip->uhci_dma_attr.dma_attr_flags  = 0;
 738 }
 739 
 740 
 741 uint_t
 742 pow_2(uint_t x)
 743 {
 744         return ((x == 0) ? 1 : (1 << x));
 745 }
 746 
 747 
 748 uint_t
 749 log_2(uint_t x)
 750 {
 751         int ret_val = 0;
 752 
 753         while (x != 1) {
 754                 ret_val++;
 755                 x = x >> 1;
 756         }
 757 
 758         return (ret_val);
 759 }
 760 
 761 
 762 /*
 763  * uhci_obtain_state:
 764  */
 765 uhci_state_t *
 766 uhci_obtain_state(dev_info_t *dip)
 767 {
 768         int instance = ddi_get_instance(dip);
 769         uhci_state_t *state = ddi_get_soft_state(uhci_statep, instance);
 770 
 771         ASSERT(state != NULL);
 772 
 773         return (state);
 774 }
 775 
 776 
 777 /*
 778  * uhci_alloc_hcdi_ops:
 779  *      The HCDI interfaces or entry points are the software interfaces used by
 780  *      the Universal Serial Bus Driver  (USBA) to  access the services of the
 781  *      Host Controller Driver (HCD).  During HCD initialization, inform  USBA
 782  *      about all available HCDI interfaces or entry points.
 783  */
 784 usba_hcdi_ops_t *
 785 uhci_alloc_hcdi_ops(uhci_state_t *uhcip)
 786 {
 787         usba_hcdi_ops_t *hcdi_ops;
 788 
 789         USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
 790             "uhci_alloc_hcdi_ops:");
 791 
 792         hcdi_ops = usba_alloc_hcdi_ops();
 793 
 794         hcdi_ops->usba_hcdi_ops_version = HCDI_OPS_VERSION_1;
 795 
 796         hcdi_ops->usba_hcdi_pipe_open = uhci_hcdi_pipe_open;
 797         hcdi_ops->usba_hcdi_pipe_close       = uhci_hcdi_pipe_close;
 798         hcdi_ops->usba_hcdi_pipe_reset = uhci_hcdi_pipe_reset;
 799         hcdi_ops->usba_hcdi_pipe_reset_data_toggle =
 800             uhci_hcdi_pipe_reset_data_toggle;
 801 
 802         hcdi_ops->usba_hcdi_pipe_ctrl_xfer = uhci_hcdi_pipe_ctrl_xfer;
 803         hcdi_ops->usba_hcdi_pipe_bulk_xfer = uhci_hcdi_pipe_bulk_xfer;
 804         hcdi_ops->usba_hcdi_pipe_intr_xfer = uhci_hcdi_pipe_intr_xfer;
 805         hcdi_ops->usba_hcdi_pipe_isoc_xfer = uhci_hcdi_pipe_isoc_xfer;
 806 
 807         hcdi_ops->usba_hcdi_bulk_transfer_size = uhci_hcdi_bulk_transfer_size;
 808         hcdi_ops->usba_hcdi_pipe_stop_intr_polling =
 809             uhci_hcdi_pipe_stop_intr_polling;
 810         hcdi_ops->usba_hcdi_pipe_stop_isoc_polling =
 811             uhci_hcdi_pipe_stop_isoc_polling;
 812 
 813         hcdi_ops->usba_hcdi_get_current_frame_number =
 814             uhci_hcdi_get_current_frame_number;
 815         hcdi_ops->usba_hcdi_get_max_isoc_pkts = uhci_hcdi_get_max_isoc_pkts;
 816 
 817         hcdi_ops->usba_hcdi_console_input_init = uhci_hcdi_polled_input_init;
 818         hcdi_ops->usba_hcdi_console_input_enter = uhci_hcdi_polled_input_enter;
 819         hcdi_ops->usba_hcdi_console_read = uhci_hcdi_polled_read;
 820         hcdi_ops->usba_hcdi_console_input_exit = uhci_hcdi_polled_input_exit;
 821         hcdi_ops->usba_hcdi_console_input_fini = uhci_hcdi_polled_input_fini;
 822 
 823         hcdi_ops->usba_hcdi_console_output_init = uhci_hcdi_polled_output_init;
 824         hcdi_ops->usba_hcdi_console_output_enter =
 825             uhci_hcdi_polled_output_enter;
 826         hcdi_ops->usba_hcdi_console_write = uhci_hcdi_polled_write;
 827         hcdi_ops->usba_hcdi_console_output_exit = uhci_hcdi_polled_output_exit;
 828         hcdi_ops->usba_hcdi_console_output_fini = uhci_hcdi_polled_output_fini;
 829 
 830         return (hcdi_ops);
 831 }
 832 
 833 
 834 /*
 835  * uhci_init_frame_lst_table :
 836  *      Allocate the system memory and initialize Host Controller
 837  *      Frame list table area The starting of the Frame list Table
 838  *      area must be 4096 byte aligned.
 839  */
 840 static int
 841 uhci_init_frame_lst_table(dev_info_t *dip, uhci_state_t *uhcip)
 842 {
 843         int                     result;
 844         uint_t                  ccount;
 845         size_t                  real_length;
 846         ddi_device_acc_attr_t   dev_attr;
 847 
 848         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
 849 
 850         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 851             "uhci_init_frame_lst_table:");
 852 
 853         /* The host controller will be little endian */
 854         dev_attr.devacc_attr_version            = DDI_DEVICE_ATTR_V0;
 855         dev_attr.devacc_attr_endian_flags       = DDI_STRUCTURE_LE_ACC;
 856         dev_attr.devacc_attr_dataorder          = DDI_STRICTORDER_ACC;
 857 
 858         /* 4K alignment required */
 859         uhcip->uhci_dma_attr.dma_attr_align = 0x1000;
 860 
 861         /* Create space for the HCCA block */
 862         if (ddi_dma_alloc_handle(dip, &uhcip->uhci_dma_attr, DDI_DMA_SLEEP,
 863             0, &uhcip->uhci_flt_dma_handle) != DDI_SUCCESS) {
 864 
 865                 return (USB_FAILURE);
 866         }
 867 
 868         /* Reset to default 16 bytes */
 869         uhcip->uhci_dma_attr.dma_attr_align = 0x10;
 870 
 871         if (ddi_dma_mem_alloc(uhcip->uhci_flt_dma_handle,
 872             SIZE_OF_FRAME_LST_TABLE, &dev_attr, DDI_DMA_CONSISTENT,
 873             DDI_DMA_SLEEP, 0, (caddr_t *)&uhcip->uhci_frame_lst_tablep,
 874             &real_length, &uhcip->uhci_flt_mem_handle)) {
 875 
 876                 return (USB_FAILURE);
 877         }
 878 
 879         /* Map the whole Frame list base area into the I/O address space */
 880         result = ddi_dma_addr_bind_handle(uhcip->uhci_flt_dma_handle,
 881             NULL, (caddr_t)uhcip->uhci_frame_lst_tablep, real_length,
 882             DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
 883             &uhcip->uhci_flt_cookie, &ccount);
 884 
 885         if (result == DDI_DMA_MAPPED) {
 886                 /* The cookie count should be 1 */
 887                 if (ccount != 1) {
 888                         USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
 889                             "uhci_init_frame_list_table: More than 1 cookie");
 890 
 891                         return (USB_FAILURE);
 892                 }
 893         } else {
 894                 uhci_decode_ddi_dma_addr_bind_handle_result(uhcip, result);
 895 
 896                 return (USB_FAILURE);
 897         }
 898 
 899         uhcip->uhci_dma_addr_bind_flag |= UHCI_FLA_POOL_BOUND;
 900 
 901         bzero((void *)uhcip->uhci_frame_lst_tablep, real_length);
 902 
 903         /* Initialize the interrupt lists */
 904         uhci_build_interrupt_lattice(uhcip);
 905 
 906         return (USB_SUCCESS);
 907 }
 908 
 909 
 910 /*
 911  * uhci_alloc_queue_head:
 912  *      Allocate a queue head
 913  */
 914 queue_head_t *
 915 uhci_alloc_queue_head(uhci_state_t *uhcip)
 916 {
 917         int             index;
 918         uhci_td_t       *dummy_td;
 919         queue_head_t    *queue_head;
 920 
 921         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
 922             "uhci_alloc_queue_head");
 923 
 924         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
 925 
 926         /* Allocate a dummy td first. */
 927         if ((dummy_td = uhci_allocate_td_from_pool(uhcip)) == NULL) {
 928 
 929                 USB_DPRINTF_L2(PRINT_MASK_ALLOC,  uhcip->uhci_log_hdl,
 930                     "uhci_alloc_queue_head: allocate td from pool failed");
 931 
 932                 return (NULL);
 933         }
 934 
 935         /*
 936          * The first 63 queue heads in the Queue Head (QH)
 937          * buffer pool are reserved for building interrupt lattice
 938          * tree. Search for a blank Queue head in the QH buffer pool.
 939          */
 940         for (index = NUM_STATIC_NODES; index < uhci_qh_pool_size; index++) {
 941                 if (uhcip->uhci_qh_pool_addr[index].qh_flag ==
 942                     QUEUE_HEAD_FLAG_FREE) {
 943                         break;
 944                 }
 945         }
 946 
 947         USB_DPRINTF_L3(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
 948             "uhci_alloc_queue_head: Allocated %d", index);
 949 
 950         if (index == uhci_qh_pool_size) {
 951                 USB_DPRINTF_L2(PRINT_MASK_ALLOC,  uhcip->uhci_log_hdl,
 952                     "uhci_alloc_queue_head: All QH exhausted");
 953 
 954                 /* Free the dummy td allocated for this qh. */
 955                 dummy_td->flag = TD_FLAG_FREE;
 956 
 957                 return (NULL);
 958         }
 959 
 960         queue_head = &uhcip->uhci_qh_pool_addr[index];
 961         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
 962             "uhci_alloc_queue_head: Allocated address 0x%p",
 963             (void *)queue_head);
 964 
 965         bzero((void *)queue_head, sizeof (queue_head_t));
 966         SetQH32(uhcip, queue_head->link_ptr, HC_END_OF_LIST);
 967         SetQH32(uhcip, queue_head->element_ptr, HC_END_OF_LIST);
 968         queue_head->prev_qh  = NULL;
 969         queue_head->qh_flag  = QUEUE_HEAD_FLAG_BUSY;
 970 
 971         bzero((char *)dummy_td, sizeof (uhci_td_t));
 972         queue_head->td_tailp = dummy_td;
 973         SetQH32(uhcip, queue_head->element_ptr, TD_PADDR(dummy_td));
 974 
 975         return (queue_head);
 976 }
 977 
 978 
 979 /*
 980  * uhci_allocate_bandwidth:
 981  *      Figure out whether or not this interval may be supported. Return
 982  *      the index into the  lattice if it can be supported.  Return
 983  *      allocation failure if it can not be supported.
 984  */
 985 int
 986 uhci_allocate_bandwidth(
 987         uhci_state_t            *uhcip,
 988         usba_pipe_handle_data_t *pipe_handle,
 989         uint_t                  *node)
 990 {
 991         int             bandwidth;      /* Requested bandwidth */
 992         uint_t          min, min_index;
 993         uint_t          i;
 994         uint_t          height;         /* Bandwidth's height in the tree */
 995         uint_t          leftmost;
 996         uint_t          length;
 997         uint32_t        paddr;
 998         queue_head_t    *tmp_qh;
 999         usb_ep_descr_t  *endpoint = &pipe_handle->p_ep;
1000 
1001         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1002 
1003         /*
1004          * Calculate the length in bytes of a transaction on this
1005          * periodic endpoint.
1006          */
1007         mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1008 
1009         length = uhci_compute_total_bandwidth(endpoint,
1010             pipe_handle->p_usba_device->usb_port_status);
1011         mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1012 
1013         /*
1014          * If the length in bytes plus the allocated bandwidth exceeds
1015          * the maximum, return bandwidth allocation failure.
1016          */
1017         if ((length + uhcip->uhci_bandwidth_intr_min +
1018             uhcip->uhci_bandwidth_isoch_sum) > (MAX_PERIODIC_BANDWIDTH)) {
1019                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1020                     "uhci_allocate_bandwidth: "
1021                     "Reached maximum bandwidth value and cannot allocate "
1022                     "bandwidth for a given Interrupt/Isoch endpoint");
1023 
1024                 return (USB_NO_BANDWIDTH);
1025         }
1026 
1027         /*
1028          * ISOC xfers are not supported at this point type
1029          */
1030         if (UHCI_XFER_TYPE(endpoint) == USB_EP_ATTR_ISOCH) {
1031                 uhcip->uhci_bandwidth_isoch_sum += length;
1032 
1033                 return (USB_SUCCESS);
1034         }
1035 
1036         /*
1037          * This is an interrupt endpoint.
1038          * Adjust bandwidth to be a power of 2
1039          */
1040         mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1041         bandwidth = uhci_bandwidth_adjust(uhcip, endpoint,
1042             pipe_handle->p_usba_device->usb_port_status);
1043         mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1044 
1045         /*
1046          * If this bandwidth can't be supported,
1047          * return allocation failure.
1048          */
1049         if (bandwidth == USB_FAILURE) {
1050 
1051                 return (USB_FAILURE);
1052         }
1053 
1054         USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1055             "The new bandwidth is %d", bandwidth);
1056 
1057         /* Find the leaf with the smallest allocated bandwidth */
1058         min_index = 0;
1059         min = uhcip->uhci_bandwidth[0];
1060 
1061         for (i = 1; i < NUM_FRAME_LST_ENTRIES; i++) {
1062                 if (uhcip->uhci_bandwidth[i] < min) {
1063                         min_index = i;
1064                         min = uhcip->uhci_bandwidth[i];
1065                 }
1066         }
1067 
1068         USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1069             "The leaf with minimal bandwidth %d, "
1070             "The smallest bandwidth %d", min_index, min);
1071 
1072         /*
1073          * Find the index into the lattice given the
1074          * leaf with the smallest allocated bandwidth.
1075          */
1076         height = uhci_lattice_height(bandwidth);
1077         USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1078             "The height is %d", height);
1079 
1080         *node = uhci_tree_bottom_nodes[min_index];
1081 
1082         /* check if there are isocs TDs scheduled for this frame */
1083         if (uhcip->uhci_isoc_q_tailp[*node]) {
1084                 paddr = (uhcip->uhci_isoc_q_tailp[*node]->link_ptr &
1085                     FRAME_LST_PTR_MASK);
1086         } else {
1087                 paddr = (uhcip->uhci_frame_lst_tablep[*node] &
1088                     FRAME_LST_PTR_MASK);
1089         }
1090 
1091         tmp_qh = QH_VADDR(paddr);
1092         *node = tmp_qh->node;
1093         for (i = 0; i < height; i++) {
1094                 *node = uhci_lattice_parent(*node);
1095         }
1096 
1097         USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1098             "The real node is %d", *node);
1099 
1100         /*
1101          * Find the leftmost leaf in the subtree specified by the node.
1102          */
1103         leftmost = uhci_leftmost_leaf(*node, height);
1104         USB_DPRINTF_L3(PRINT_MASK_BW, uhcip->uhci_log_hdl,
1105             "Leftmost %d", leftmost);
1106 
1107         for (i = leftmost; i < leftmost +
1108             (NUM_FRAME_LST_ENTRIES/bandwidth); i ++) {
1109 
1110                 if ((length + uhcip->uhci_bandwidth_isoch_sum +
1111                     uhcip->uhci_bandwidth[i]) > MAX_PERIODIC_BANDWIDTH) {
1112 
1113                         USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1114                             "uhci_allocate_bandwidth: "
1115                             "Reached maximum bandwidth value and cannot "
1116                             "allocate bandwidth for Interrupt endpoint");
1117 
1118                         return (USB_NO_BANDWIDTH);
1119                 }
1120         }
1121 
1122         /*
1123          * All the leaves for this node must be updated with the bandwidth.
1124          */
1125         for (i = leftmost; i < leftmost +
1126             (NUM_FRAME_LST_ENTRIES/bandwidth); i ++) {
1127                 uhcip->uhci_bandwidth[i] += length;
1128         }
1129 
1130         /* Find the leaf with the smallest allocated bandwidth */
1131         min_index = 0;
1132         min = uhcip->uhci_bandwidth[0];
1133 
1134         for (i = 1; i < NUM_FRAME_LST_ENTRIES; i++) {
1135                 if (uhcip->uhci_bandwidth[i] < min) {
1136                         min_index = i;
1137                         min = uhcip->uhci_bandwidth[i];
1138                 }
1139         }
1140 
1141         /* Save the minimum for later use */
1142         uhcip->uhci_bandwidth_intr_min = min;
1143 
1144         return (USB_SUCCESS);
1145 }
1146 
1147 
1148 /*
1149  * uhci_deallocate_bandwidth:
1150  *      Deallocate bandwidth for the given node in the lattice
1151  *      and the length of transfer.
1152  */
1153 void
1154 uhci_deallocate_bandwidth(uhci_state_t *uhcip,
1155     usba_pipe_handle_data_t *pipe_handle)
1156 {
1157         uint_t          bandwidth;
1158         uint_t          height;
1159         uint_t          leftmost;
1160         uint_t          i;
1161         uint_t          min;
1162         usb_ep_descr_t  *endpoint = &pipe_handle->p_ep;
1163         uint_t          node, length;
1164         uhci_pipe_private_t *pp =
1165             (uhci_pipe_private_t *)pipe_handle->p_hcd_private;
1166 
1167         /* This routine is protected by the uhci_int_mutex */
1168         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1169 
1170         /* Obtain the length */
1171         mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1172         length = uhci_compute_total_bandwidth(endpoint,
1173             pipe_handle->p_usba_device->usb_port_status);
1174         mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1175 
1176         /*
1177          * If this is an isochronous endpoint, just delete endpoint's
1178          * bandwidth from the total allocated isochronous bandwidth.
1179          */
1180         if (UHCI_XFER_TYPE(endpoint) == USB_EP_ATTR_ISOCH) {
1181                 uhcip->uhci_bandwidth_isoch_sum -= length;
1182 
1183                 return;
1184         }
1185 
1186         /* Obtain the node */
1187         node = pp->pp_node;
1188 
1189         /* Adjust bandwidth to be a power of 2 */
1190         mutex_enter(&pipe_handle->p_usba_device->usb_mutex);
1191         bandwidth = uhci_bandwidth_adjust(uhcip, endpoint,
1192             pipe_handle->p_usba_device->usb_port_status);
1193         mutex_exit(&pipe_handle->p_usba_device->usb_mutex);
1194 
1195         /* Find the height in the tree */
1196         height = uhci_lattice_height(bandwidth);
1197 
1198         /*
1199          * Find the leftmost leaf in the subtree specified by the node
1200          */
1201         leftmost = uhci_leftmost_leaf(node, height);
1202 
1203         /* Delete the bandwith from the appropriate lists */
1204         for (i = leftmost; i < leftmost + (NUM_FRAME_LST_ENTRIES/bandwidth);
1205             i ++) {
1206                 uhcip->uhci_bandwidth[i] -= length;
1207         }
1208 
1209         min = uhcip->uhci_bandwidth[0];
1210 
1211         /* Recompute the minimum */
1212         for (i = 1; i < NUM_FRAME_LST_ENTRIES; i++) {
1213                 if (uhcip->uhci_bandwidth[i] < min) {
1214                         min = uhcip->uhci_bandwidth[i];
1215                 }
1216         }
1217 
1218         /* Save the minimum for later use */
1219         uhcip->uhci_bandwidth_intr_min = min;
1220 }
1221 
1222 
1223 /*
1224  * uhci_compute_total_bandwidth:
1225  *
1226  * Given a periodic endpoint (interrupt or isochronous) determine the total
1227  * bandwidth for one transaction. The UHCI host controller traverses the
1228  * endpoint descriptor lists on a first-come-first-serve basis. When the HC
1229  * services an endpoint, only a single transaction attempt is made. The  HC
1230  * moves to the next Endpoint Descriptor after the first transaction attempt
1231  * rather than finishing the entire Transfer Descriptor. Therefore, when  a
1232  * Transfer Descriptor is inserted into the lattice, we will only count the
1233  * number of bytes for one transaction.
1234  *
1235  * The following are the formulas used for calculating bandwidth in terms
1236  * bytes and it is for the single USB full speed and low speed  transaction
1237  * respectively. The protocol overheads will be different for each of  type
1238  * of USB transfer and all these formulas & protocol overheads are  derived
1239  * from the 5.9.3 section of USB Specification & with the help of Bandwidth
1240  * Analysis white paper which is posted on the USB  developer forum.
1241  *
1242  * Full-Speed:
1243  *        Protocol overhead  + ((MaxPacketSize * 7)/6 )  + Host_Delay
1244  *
1245  * Low-Speed:
1246  *              Protocol overhead  + Hub LS overhead +
1247  *                (Low-Speed clock * ((MaxPacketSize * 7)/6 )) + Host_Delay
1248  */
1249 static uint_t
1250 uhci_compute_total_bandwidth(usb_ep_descr_t *endpoint,
1251                 usb_port_status_t port_status)
1252 {
1253         uint_t          bandwidth;
1254         ushort_t        MaxPacketSize = endpoint->wMaxPacketSize;
1255 
1256         /* Add Host Controller specific delay to required bandwidth */
1257         bandwidth = HOST_CONTROLLER_DELAY;
1258 
1259         /* Add bit-stuffing overhead */
1260         MaxPacketSize = (ushort_t)((MaxPacketSize * 7) / 6);
1261 
1262         /* Low Speed interrupt transaction */
1263         if (port_status == USBA_LOW_SPEED_DEV) {
1264                 /* Low Speed interrupt transaction */
1265                 bandwidth += (LOW_SPEED_PROTO_OVERHEAD +
1266                     HUB_LOW_SPEED_PROTO_OVERHEAD +
1267                     (LOW_SPEED_CLOCK * MaxPacketSize));
1268         } else {
1269                 /* Full Speed transaction */
1270                 bandwidth += MaxPacketSize;
1271 
1272                 if (UHCI_XFER_TYPE(endpoint) == USB_EP_ATTR_INTR) {
1273                         /* Full Speed interrupt transaction */
1274                         bandwidth += FS_NON_ISOC_PROTO_OVERHEAD;
1275                 } else {
1276                         /* Isochronus and input transaction */
1277                         if (UHCI_XFER_DIR(endpoint) == USB_EP_DIR_IN) {
1278                                 bandwidth += FS_ISOC_INPUT_PROTO_OVERHEAD;
1279                         } else {
1280                                 /* Isochronus and output transaction */
1281                                 bandwidth += FS_ISOC_OUTPUT_PROTO_OVERHEAD;
1282                         }
1283                 }
1284         }
1285 
1286         return (bandwidth);
1287 }
1288 
1289 
1290 /*
1291  * uhci_bandwidth_adjust:
1292  */
1293 static int
1294 uhci_bandwidth_adjust(
1295         uhci_state_t            *uhcip,
1296         usb_ep_descr_t          *endpoint,
1297         usb_port_status_t       port_status)
1298 {
1299         int     i = 0;
1300         uint_t  interval;
1301 
1302         /*
1303          * Get the polling interval from the endpoint descriptor
1304          */
1305         interval = endpoint->bInterval;
1306 
1307         /*
1308          * The bInterval value in the endpoint descriptor can range
1309          * from 1 to 255ms. The interrupt lattice has 32 leaf nodes,
1310          * and the host controller cycles through these nodes every
1311          * 32ms. The longest polling  interval that the  controller
1312          * supports is 32ms.
1313          */
1314 
1315         /*
1316          * Return an error if the polling interval is less than 1ms
1317          * and greater than 255ms
1318          */
1319         if ((interval < MIN_POLL_INTERVAL) || (interval > MAX_POLL_INTERVAL)) {
1320                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1321                     "uhci_bandwidth_adjust: Endpoint's poll interval must be "
1322                     "between %d and %d ms", MIN_POLL_INTERVAL,
1323                     MAX_POLL_INTERVAL);
1324 
1325                 return (USB_FAILURE);
1326         }
1327 
1328         /*
1329          * According USB Specifications, a  full-speed endpoint can
1330          * specify a desired polling interval 1ms to 255ms and a low
1331          * speed  endpoints are limited to  specifying only 10ms to
1332          * 255ms. But some old keyboards & mice uses polling interval
1333          * of 8ms. For compatibility  purpose, we are using polling
1334          * interval between 8ms & 255ms for low speed endpoints.
1335          */
1336         if ((port_status == USBA_LOW_SPEED_DEV) &&
1337             (interval < MIN_LOW_SPEED_POLL_INTERVAL)) {
1338                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1339                     "uhci_bandwidth_adjust: Low speed endpoint's poll interval "
1340                     "must be >= %d ms, adjusted",
1341                     MIN_LOW_SPEED_POLL_INTERVAL);
1342 
1343                 interval = MIN_LOW_SPEED_POLL_INTERVAL;
1344         }
1345 
1346         /*
1347          * If polling interval is greater than 32ms,
1348          * adjust polling interval equal to 32ms.
1349          */
1350         if (interval > 32) {
1351                 interval = 32;
1352         }
1353 
1354         /*
1355          * Find the nearest power of 2 that's less
1356          * than interval.
1357          */
1358         while ((pow_2(i)) <= interval) {
1359                 i++;
1360         }
1361 
1362         return (pow_2((i - 1)));
1363 }
1364 
1365 
1366 /*
1367  * uhci_lattice_height:
1368  *      Given the requested bandwidth, find the height in the tree at
1369  *      which the nodes for this bandwidth fall.  The height is measured
1370  *      as the number of nodes from the leaf to the level specified by
1371  *      bandwidth The root of the tree is at height TREE_HEIGHT.
1372  */
1373 static uint_t
1374 uhci_lattice_height(uint_t bandwidth)
1375 {
1376         return (TREE_HEIGHT - (log_2(bandwidth)));
1377 }
1378 
1379 
1380 static uint_t
1381 uhci_lattice_parent(uint_t node)
1382 {
1383         return (((node % 2) == 0) ? ((node/2) - 1) : (node/2));
1384 }
1385 
1386 
1387 /*
1388  * uhci_leftmost_leaf:
1389  *      Find the leftmost leaf in the subtree specified by the node.
1390  *      Height refers to number of nodes from the bottom of the tree
1391  *      to the node,  including the node.
1392  */
1393 static uint_t
1394 uhci_leftmost_leaf(uint_t node, uint_t height)
1395 {
1396         node = pow_2(height + VIRTUAL_TREE_HEIGHT) * (node+1) -
1397             NUM_FRAME_LST_ENTRIES;
1398         return (node);
1399 }
1400 
1401 
1402 /*
1403  * uhci_insert_qh:
1404  *      Add the Queue Head (QH) into the Host Controller's (HC)
1405  *      appropriate queue head list.
1406  */
1407 void
1408 uhci_insert_qh(uhci_state_t *uhcip, usba_pipe_handle_data_t *ph)
1409 {
1410         uhci_pipe_private_t *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
1411 
1412         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1413             "uhci_insert_qh:");
1414 
1415         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1416 
1417         switch (UHCI_XFER_TYPE(&ph->p_ep)) {
1418         case USB_EP_ATTR_CONTROL:
1419                 uhci_insert_ctrl_qh(uhcip, pp);
1420                 break;
1421         case USB_EP_ATTR_BULK:
1422                 uhci_insert_bulk_qh(uhcip, pp);
1423                 break;
1424         case USB_EP_ATTR_INTR:
1425                 uhci_insert_intr_qh(uhcip, pp);
1426                 break;
1427         case USB_EP_ATTR_ISOCH:
1428                         USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
1429                             "uhci_insert_qh: Illegal request");
1430                 break;
1431         }
1432 }
1433 
1434 
1435 /*
1436  * uhci_insert_ctrl_qh:
1437  *      Insert a control QH into the Host Controller's (HC) control QH list.
1438  */
1439 static void
1440 uhci_insert_ctrl_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
1441 {
1442         queue_head_t *qh = pp->pp_qh;
1443 
1444         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1445             "uhci_insert_ctrl_qh:");
1446 
1447         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1448 
1449         if (uhcip->uhci_ctrl_xfers_q_head == uhcip->uhci_ctrl_xfers_q_tail) {
1450                 uhcip->uhci_ctrl_xfers_q_head->prev_qh    = UHCI_INVALID_PTR;
1451         }
1452 
1453         SetQH32(uhcip, qh->link_ptr,
1454             GetQH32(uhcip, uhcip->uhci_ctrl_xfers_q_tail->link_ptr));
1455         qh->prev_qh = uhcip->uhci_ctrl_xfers_q_tail;
1456         SetQH32(uhcip, uhcip->uhci_ctrl_xfers_q_tail->link_ptr,
1457             QH_PADDR(qh) | HC_QUEUE_HEAD);
1458         uhcip->uhci_ctrl_xfers_q_tail = qh;
1459 
1460 }
1461 
1462 
1463 /*
1464  * uhci_insert_bulk_qh:
1465  *      Insert a bulk QH into the Host Controller's (HC) bulk QH list.
1466  */
1467 static void
1468 uhci_insert_bulk_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
1469 {
1470         queue_head_t *qh = pp->pp_qh;
1471 
1472         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1473             "uhci_insert_bulk_qh:");
1474 
1475         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1476 
1477         if (uhcip->uhci_bulk_xfers_q_head == uhcip->uhci_bulk_xfers_q_tail) {
1478                 uhcip->uhci_bulk_xfers_q_head->prev_qh = UHCI_INVALID_PTR;
1479         } else if (uhcip->uhci_bulk_xfers_q_head->link_ptr ==
1480             uhcip->uhci_bulk_xfers_q_tail->link_ptr) {
1481 
1482                 /* If there is already a loop, we should keep the loop. */
1483                 qh->link_ptr = uhcip->uhci_bulk_xfers_q_tail->link_ptr;
1484         }
1485 
1486         qh->prev_qh = uhcip->uhci_bulk_xfers_q_tail;
1487         SetQH32(uhcip, uhcip->uhci_bulk_xfers_q_tail->link_ptr,
1488             QH_PADDR(qh) | HC_QUEUE_HEAD);
1489         uhcip->uhci_bulk_xfers_q_tail = qh;
1490 }
1491 
1492 
1493 /*
1494  * uhci_insert_intr_qh:
1495  *      Insert a periodic Queue head i.e Interrupt queue head into the
1496  *      Host Controller's (HC) interrupt lattice tree.
1497  */
1498 static void
1499 uhci_insert_intr_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
1500 {
1501         uint_t          node = pp->pp_node;  /* The appropriate node was */
1502                                                 /* found during the opening */
1503                                                 /* of the pipe.  */
1504         queue_head_t    *qh = pp->pp_qh;
1505         queue_head_t    *next_lattice_qh, *lattice_qh;
1506 
1507         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1508             "uhci_insert_intr_qh:");
1509 
1510         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1511 
1512         /* Find the lattice queue head */
1513         lattice_qh = &uhcip->uhci_qh_pool_addr[node];
1514         next_lattice_qh =
1515             QH_VADDR(GetQH32(uhcip, lattice_qh->link_ptr) & QH_LINK_PTR_MASK);
1516 
1517         next_lattice_qh->prev_qh = qh;
1518         qh->link_ptr = lattice_qh->link_ptr;
1519         qh->prev_qh  = lattice_qh;
1520         SetQH32(uhcip, lattice_qh->link_ptr, QH_PADDR(qh) | HC_QUEUE_HEAD);
1521         pp->pp_data_toggle = 0;
1522 }
1523 
1524 
1525 /*
1526  * uhci_insert_intr_td:
1527  *      Create a TD and a data buffer for an interrupt endpoint.
1528  */
1529 int
1530 uhci_insert_intr_td(
1531         uhci_state_t            *uhcip,
1532         usba_pipe_handle_data_t *ph,
1533         usb_intr_req_t          *req,
1534         usb_flags_t             flags)
1535 {
1536         int                     error, pipe_dir;
1537         uint_t                  length, mps;
1538         uint32_t                buf_offs;
1539         uhci_td_t               *tmp_td;
1540         usb_intr_req_t          *intr_reqp;
1541         uhci_pipe_private_t     *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
1542         uhci_trans_wrapper_t    *tw;
1543 
1544         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1545             "uhci_insert_intr_td: req: 0x%p", (void *)req);
1546 
1547         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1548 
1549         /* Get the interrupt pipe direction */
1550         pipe_dir = UHCI_XFER_DIR(&ph->p_ep);
1551 
1552         /* Get the current interrupt request pointer */
1553         if (req) {
1554                 length = req->intr_len;
1555         } else {
1556                 ASSERT(pipe_dir == USB_EP_DIR_IN);
1557                 length = (pp->pp_client_periodic_in_reqp) ?
1558                     (((usb_intr_req_t *)pp->
1559                     pp_client_periodic_in_reqp)->intr_len) :
1560                     ph->p_ep.wMaxPacketSize;
1561         }
1562 
1563         /* Check the size of interrupt request */
1564         if (length > UHCI_MAX_TD_XFER_SIZE) {
1565 
1566                 /* the length shouldn't exceed 8K */
1567                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1568                     "uhci_insert_intr_td: Intr request size 0x%x is "
1569                     "more than 0x%x", length, UHCI_MAX_TD_XFER_SIZE);
1570 
1571                 return (USB_INVALID_REQUEST);
1572         }
1573 
1574         USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1575             "uhci_insert_intr_td: length: 0x%x", length);
1576 
1577         /* Allocate a transaction wrapper */
1578         if ((tw = uhci_create_transfer_wrapper(uhcip, pp, length, flags)) ==
1579             NULL) {
1580 
1581                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1582                     "uhci_insert_intr_td: TW allocation failed");
1583 
1584                 return (USB_NO_RESOURCES);
1585         }
1586 
1587         /*
1588          * Initialize the callback and any callback
1589          * data for when the td completes.
1590          */
1591         tw->tw_handle_td = uhci_handle_intr_td;
1592         tw->tw_handle_callback_value = NULL;
1593         tw->tw_direction = (pipe_dir == USB_EP_DIR_OUT) ?
1594             PID_OUT : PID_IN;
1595         tw->tw_curr_xfer_reqp = (usb_opaque_t)req;
1596 
1597         /*
1598          * If it is an Interrupt IN request and interrupt request is NULL,
1599          * allocate the usb interrupt request structure for the current
1600          * interrupt polling request.
1601          */
1602         if (tw->tw_direction == PID_IN) {
1603                 if ((error = uhci_allocate_periodic_in_resource(uhcip,
1604                     pp, tw, flags)) != USB_SUCCESS) {
1605                         USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1606                             "uhci_insert_intr_td: Interrupt request structure "
1607                             "allocation failed");
1608 
1609                         /* free the transfer wrapper */
1610                         uhci_deallocate_tw(uhcip, pp, tw);
1611 
1612                         return (error);
1613                 }
1614         }
1615 
1616         intr_reqp = (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
1617         ASSERT(tw->tw_curr_xfer_reqp != NULL);
1618 
1619         tw->tw_timeout_cnt = (intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) ?
1620             intr_reqp->intr_timeout : 0;
1621 
1622         /* DATA IN */
1623         if (tw->tw_direction == PID_IN) {
1624                 /* Insert the td onto the queue head */
1625                 error = uhci_insert_hc_td(uhcip, 0,
1626                     length, pp, tw, PID_IN, intr_reqp->intr_attributes);
1627 
1628                 if (error != USB_SUCCESS) {
1629 
1630                         uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
1631                         /* free the transfer wrapper */
1632                         uhci_deallocate_tw(uhcip, pp, tw);
1633 
1634                         return (USB_NO_RESOURCES);
1635                 }
1636                 tw->tw_bytes_xfered = 0;
1637 
1638                 return (USB_SUCCESS);
1639         }
1640 
1641         if (req->intr_len) {
1642                 /* DATA OUT */
1643                 ASSERT(req->intr_data != NULL);
1644 
1645                 /* Copy the data into the message */
1646                 ddi_rep_put8(tw->tw_accesshandle, req->intr_data->b_rptr,
1647                     (uint8_t *)tw->tw_buf, req->intr_len, DDI_DEV_AUTOINCR);
1648         }
1649 
1650         /* set tw->tw_claim flag, so that nobody else works on this tw. */
1651         tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
1652 
1653         mps = ph->p_ep.wMaxPacketSize;
1654         buf_offs = 0;
1655 
1656         /* Insert tds onto the queue head */
1657         while (length > 0) {
1658 
1659                 error = uhci_insert_hc_td(uhcip, buf_offs,
1660                     (length > mps) ? mps : length,
1661                     pp, tw, PID_OUT,
1662                     intr_reqp->intr_attributes);
1663 
1664                 if (error != USB_SUCCESS) {
1665                         /* no resource. */
1666                         break;
1667                 }
1668 
1669                 if (length <= mps) {
1670                         /* inserted all data. */
1671                         length = 0;
1672 
1673                 } else {
1674 
1675                         buf_offs += mps;
1676                         length -= mps;
1677                 }
1678         }
1679 
1680         if (error != USB_SUCCESS) {
1681 
1682                 USB_DPRINTF_L2(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
1683                     "uhci_insert_intr_td: allocate td failed, free resource");
1684 
1685                 /* remove all the tds */
1686                 while (tw->tw_hctd_head != NULL) {
1687                         uhci_delete_td(uhcip, tw->tw_hctd_head);
1688                 }
1689 
1690                 tw->tw_claim = UHCI_NOT_CLAIMED;
1691                 uhci_deallocate_tw(uhcip, pp, tw);
1692 
1693                 return (error);
1694         }
1695 
1696         /* allow HC to xfer the tds of this tw */
1697         tmp_td = tw->tw_hctd_head;
1698         while (tmp_td != NULL) {
1699 
1700                 SetTD_status(uhcip, tmp_td, UHCI_TD_ACTIVE);
1701                 tmp_td = tmp_td->tw_td_next;
1702         }
1703 
1704         tw->tw_bytes_xfered = 0;
1705         tw->tw_claim = UHCI_NOT_CLAIMED;
1706 
1707         return (error);
1708 }
1709 
1710 
1711 /*
1712  * uhci_create_transfer_wrapper:
1713  *      Create a Transaction Wrapper (TW) for non-isoc transfer types.
1714  *      This involves the allocating of DMA resources.
1715  *
1716  *      For non-isoc transfers, one DMA handle and one DMA buffer are
1717  *      allocated per transfer. The DMA buffer may contain multiple
1718  *      DMA cookies and the cookies should meet certain alignment
1719  *      requirement to be able to fit in the multiple TDs. The alignment
1720  *      needs to ensure:
1721  *      1. the size of a cookie be larger than max TD length (0x500)
1722  *      2. the size of a cookie be a multiple of wMaxPacketSize of the
1723  *      ctrl/bulk pipes
1724  *
1725  *      wMaxPacketSize for ctrl and bulk pipes may be 8, 16, 32 or 64 bytes.
1726  *      So the alignment should be a multiple of 64. wMaxPacketSize for intr
1727  *      pipes is a little different since it only specifies the max to be
1728  *      64 bytes, but as long as an intr transfer is limited to max TD length,
1729  *      any alignment can work if the cookie size is larger than max TD length.
1730  *
1731  *      Considering the above conditions, 2K alignment is used. 4K alignment
1732  *      should also be fine.
1733  */
1734 static uhci_trans_wrapper_t *
1735 uhci_create_transfer_wrapper(
1736         uhci_state_t            *uhcip,
1737         uhci_pipe_private_t     *pp,
1738         size_t                  length,
1739         usb_flags_t             usb_flags)
1740 {
1741         size_t                  real_length;
1742         uhci_trans_wrapper_t    *tw;
1743         ddi_device_acc_attr_t   dev_attr;
1744         ddi_dma_attr_t          dma_attr;
1745         int                     kmem_flag;
1746         int                     (*dmamem_wait)(caddr_t);
1747         usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
1748 
1749         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1750             "uhci_create_transfer_wrapper: length = 0x%lx flags = 0x%x",
1751             length, usb_flags);
1752 
1753         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1754 
1755         /* isochronous pipe should not call into this function */
1756         if (UHCI_XFER_TYPE(&ph->p_ep) == USB_EP_ATTR_ISOCH) {
1757 
1758                 return (NULL);
1759         }
1760 
1761         /* SLEEP flag should not be used while holding mutex */
1762         kmem_flag = KM_NOSLEEP;
1763         dmamem_wait = DDI_DMA_DONTWAIT;
1764 
1765         /* Allocate space for the transfer wrapper */
1766         if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), kmem_flag)) ==
1767             NULL) {
1768                 USB_DPRINTF_L2(PRINT_MASK_LISTS,  uhcip->uhci_log_hdl,
1769                     "uhci_create_transfer_wrapper: kmem_alloc failed");
1770 
1771                 return (NULL);
1772         }
1773 
1774         /* zero-length packet doesn't need to allocate dma memory */
1775         if (length == 0) {
1776 
1777                 goto dmadone;
1778         }
1779 
1780         /* allow sg lists for transfer wrapper dma memory */
1781         bcopy(&uhcip->uhci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
1782         dma_attr.dma_attr_sgllen = UHCI_DMA_ATTR_SGLLEN;
1783         dma_attr.dma_attr_align = UHCI_DMA_ATTR_ALIGN;
1784 
1785         /* Store the transfer length */
1786         tw->tw_length = length;
1787 
1788         /* Allocate the DMA handle */
1789         if (ddi_dma_alloc_handle(uhcip->uhci_dip, &dma_attr, dmamem_wait,
1790             0, &tw->tw_dmahandle) != DDI_SUCCESS) {
1791                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1792                     "uhci_create_transfer_wrapper: Alloc handle failed");
1793                 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
1794 
1795                 return (NULL);
1796         }
1797 
1798         dev_attr.devacc_attr_version            = DDI_DEVICE_ATTR_V0;
1799         dev_attr.devacc_attr_endian_flags       = DDI_STRUCTURE_LE_ACC;
1800         dev_attr.devacc_attr_dataorder          = DDI_STRICTORDER_ACC;
1801 
1802         /* Allocate the memory */
1803         if (ddi_dma_mem_alloc(tw->tw_dmahandle, tw->tw_length, &dev_attr,
1804             DDI_DMA_CONSISTENT, dmamem_wait, NULL, (caddr_t *)&tw->tw_buf,
1805             &real_length, &tw->tw_accesshandle) != DDI_SUCCESS) {
1806                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1807                     "uhci_create_transfer_wrapper: dma_mem_alloc fail");
1808                 ddi_dma_free_handle(&tw->tw_dmahandle);
1809                 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
1810 
1811                 return (NULL);
1812         }
1813 
1814         ASSERT(real_length >= length);
1815 
1816         /* Bind the handle */
1817         if (ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL,
1818             (caddr_t)tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
1819             dmamem_wait, NULL, &tw->tw_cookie, &tw->tw_ncookies) !=
1820             DDI_DMA_MAPPED) {
1821                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1822                     "uhci_create_transfer_wrapper: Bind handle failed");
1823                 ddi_dma_mem_free(&tw->tw_accesshandle);
1824                 ddi_dma_free_handle(&tw->tw_dmahandle);
1825                 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
1826 
1827                 return (NULL);
1828         }
1829 
1830         tw->tw_cookie_idx = 0;
1831         tw->tw_dma_offs = 0;
1832 
1833 dmadone:
1834         /*
1835          * Only allow one wrapper to be added at a time. Insert the
1836          * new transaction wrapper into the list for this pipe.
1837          */
1838         if (pp->pp_tw_head == NULL) {
1839                 pp->pp_tw_head = tw;
1840                 pp->pp_tw_tail = tw;
1841         } else {
1842                 pp->pp_tw_tail->tw_next = tw;
1843                 pp->pp_tw_tail = tw;
1844                 ASSERT(tw->tw_next == NULL);
1845         }
1846 
1847         /* Store a back pointer to the pipe private structure */
1848         tw->tw_pipe_private = pp;
1849 
1850         /* Store the transfer type - synchronous or asynchronous */
1851         tw->tw_flags = usb_flags;
1852 
1853         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
1854             "uhci_create_transfer_wrapper: tw = 0x%p, ncookies = %u",
1855             (void *)tw, tw->tw_ncookies);
1856 
1857         return (tw);
1858 }
1859 
1860 
1861 /*
1862  * uhci_insert_hc_td:
1863  *      Insert a Transfer Descriptor (TD) on an QH.
1864  */
1865 int
1866 uhci_insert_hc_td(
1867         uhci_state_t            *uhcip,
1868         uint32_t                buffer_offset,
1869         size_t                  hcgtd_length,
1870         uhci_pipe_private_t     *pp,
1871         uhci_trans_wrapper_t    *tw,
1872         uchar_t                 PID,
1873         usb_req_attrs_t         attrs)
1874 {
1875         uhci_td_t       *td, *current_dummy;
1876         queue_head_t    *qh = pp->pp_qh;
1877 
1878         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
1879 
1880         if ((td = uhci_allocate_td_from_pool(uhcip)) == NULL) {
1881 
1882                 return (USB_NO_RESOURCES);
1883         }
1884 
1885         current_dummy = qh->td_tailp;
1886 
1887         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
1888             "uhci_insert_hc_td: td %p, attrs = 0x%x", (void *)td, attrs);
1889 
1890         /*
1891          * Fill in the current dummy td and
1892          * add the new dummy to the end.
1893          */
1894         uhci_fill_in_td(uhcip, td, current_dummy, buffer_offset,
1895             hcgtd_length, pp, PID, attrs, tw);
1896 
1897         /*
1898          * Allow HC hardware xfer the td, except interrupt out td.
1899          */
1900         if ((tw->tw_handle_td != uhci_handle_intr_td) || (PID != PID_OUT)) {
1901 
1902                 SetTD_status(uhcip, current_dummy, UHCI_TD_ACTIVE);
1903         }
1904 
1905         /* Insert this td onto the tw */
1906 
1907         if (tw->tw_hctd_head == NULL) {
1908                 ASSERT(tw->tw_hctd_tail == NULL);
1909                 tw->tw_hctd_head = current_dummy;
1910                 tw->tw_hctd_tail = current_dummy;
1911         } else {
1912                 /* Add the td to the end of the list */
1913                 tw->tw_hctd_tail->tw_td_next = current_dummy;
1914                 tw->tw_hctd_tail = current_dummy;
1915         }
1916 
1917         /*
1918          * Insert the TD on to the QH. When this occurs,
1919          * the Host Controller will see the newly filled in TD
1920          */
1921         current_dummy->outst_td_next  = NULL;
1922         current_dummy->outst_td_prev  = uhcip->uhci_outst_tds_tail;
1923         if (uhcip->uhci_outst_tds_head == NULL) {
1924                 uhcip->uhci_outst_tds_head = current_dummy;
1925         } else {
1926                 uhcip->uhci_outst_tds_tail->outst_td_next = current_dummy;
1927         }
1928         uhcip->uhci_outst_tds_tail = current_dummy;
1929         current_dummy->tw = tw;
1930 
1931         return (USB_SUCCESS);
1932 }
1933 
1934 
1935 /*
1936  * uhci_fill_in_td:
1937  *      Fill in the fields of a Transfer Descriptor (TD).
1938  */
1939 static void
1940 uhci_fill_in_td(
1941         uhci_state_t            *uhcip,
1942         uhci_td_t               *td,
1943         uhci_td_t               *current_dummy,
1944         uint32_t                buffer_offset,
1945         size_t                  length,
1946         uhci_pipe_private_t     *pp,
1947         uchar_t                 PID,
1948         usb_req_attrs_t         attrs,
1949         uhci_trans_wrapper_t    *tw)
1950 {
1951         usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
1952         uint32_t                buf_addr;
1953 
1954         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
1955             "uhci_fill_in_td: td 0x%p buf_offs 0x%x len 0x%lx "
1956             "attrs 0x%x", (void *)td, buffer_offset, length, attrs);
1957 
1958         /*
1959          * If this is an isochronous TD, just return
1960          */
1961         if (UHCI_XFER_TYPE(&ph->p_ep) == USB_EP_ATTR_ISOCH) {
1962 
1963                 return;
1964         }
1965 
1966         /* The maximum transfer length of UHCI cannot exceed 0x500 bytes */
1967         ASSERT(length <= UHCI_MAX_TD_XFER_SIZE);
1968 
1969         bzero((char *)td, sizeof (uhci_td_t));  /* Clear the TD */
1970         SetTD32(uhcip, current_dummy->link_ptr, TD_PADDR(td));
1971 
1972         if (attrs & USB_ATTRS_SHORT_XFER_OK) {
1973                 SetTD_spd(uhcip, current_dummy, 1);
1974         }
1975 
1976         mutex_enter(&ph->p_usba_device->usb_mutex);
1977         if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
1978                 SetTD_ls(uhcip, current_dummy, LOW_SPEED_DEVICE);
1979         }
1980 
1981         SetTD_c_err(uhcip, current_dummy, UHCI_MAX_ERR_COUNT);
1982         SetTD_mlen(uhcip, current_dummy,
1983             (length == 0) ? ZERO_LENGTH : (length - 1));
1984         SetTD_dtogg(uhcip, current_dummy, pp->pp_data_toggle);
1985 
1986         /* Adjust the data toggle bit */
1987         ADJ_DATA_TOGGLE(pp);
1988 
1989         SetTD_devaddr(uhcip, current_dummy,  ph->p_usba_device->usb_addr);
1990         SetTD_endpt(uhcip, current_dummy,
1991             ph->p_ep.bEndpointAddress & END_POINT_ADDRESS_MASK);
1992         SetTD_PID(uhcip, current_dummy, PID);
1993         SetTD_ioc(uhcip, current_dummy, INTERRUPT_ON_COMPLETION);
1994 
1995         buf_addr = uhci_get_tw_paddr_by_offs(uhcip, buffer_offset, length, tw);
1996         SetTD32(uhcip, current_dummy->buffer_address, buf_addr);
1997 
1998         td->qh_td_prev                       = current_dummy;
1999         current_dummy->qh_td_prev    = NULL;
2000         pp->pp_qh->td_tailp               = td;
2001         mutex_exit(&ph->p_usba_device->usb_mutex);
2002 }
2003 
2004 /*
2005  * uhci_get_tw_paddr_by_offs:
2006  *      Walk through the DMA cookies of a TW buffer to retrieve
2007  *      the device address used for a TD.
2008  *
2009  * buffer_offset - the starting offset into the TW buffer, where the
2010  *                 TD should transfer from. When a TW has more than
2011  *                 one TD, the TDs must be filled in increasing order.
2012  */
2013 static uint32_t
2014 uhci_get_tw_paddr_by_offs(
2015         uhci_state_t            *uhcip,
2016         uint32_t                buffer_offset,
2017         size_t                  length,
2018         uhci_trans_wrapper_t    *tw)
2019 {
2020         uint32_t                buf_addr;
2021         int                     rem_len;
2022 
2023         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2024             "uhci_get_tw_paddr_by_offs: buf_offs 0x%x len 0x%lx",
2025             buffer_offset, length);
2026 
2027         /*
2028          * TDs must be filled in increasing DMA offset order.
2029          * tw_dma_offs is initialized to be 0 at TW creation and
2030          * is only increased in this function.
2031          */
2032         ASSERT(length == 0 || buffer_offset >= tw->tw_dma_offs);
2033 
2034         if (length == 0) {
2035                 buf_addr = 0;
2036 
2037                 return (buf_addr);
2038         }
2039 
2040         /*
2041          * Advance to the next DMA cookie until finding the cookie
2042          * that buffer_offset falls in.
2043          * It is very likely this loop will never repeat more than
2044          * once. It is here just to accommodate the case buffer_offset
2045          * is increased by multiple cookies during two consecutive
2046          * calls into this function. In that case, the interim DMA
2047          * buffer is allowed to be skipped.
2048          */
2049         while ((tw->tw_dma_offs + tw->tw_cookie.dmac_size) <=
2050             buffer_offset) {
2051                 /*
2052                  * tw_dma_offs always points to the starting offset
2053                  * of a cookie
2054                  */
2055                 tw->tw_dma_offs += tw->tw_cookie.dmac_size;
2056                 ddi_dma_nextcookie(tw->tw_dmahandle, &tw->tw_cookie);
2057                 tw->tw_cookie_idx++;
2058                 ASSERT(tw->tw_cookie_idx < tw->tw_ncookies);
2059         }
2060 
2061         /*
2062          * Counting the remained buffer length to be filled in
2063          * the TDs for current DMA cookie
2064          */
2065         rem_len = (tw->tw_dma_offs + tw->tw_cookie.dmac_size) -
2066             buffer_offset;
2067 
2068         /* Calculate the beginning address of the buffer */
2069         ASSERT(length <= rem_len);
2070         buf_addr = (buffer_offset - tw->tw_dma_offs) +
2071             tw->tw_cookie.dmac_address;
2072 
2073         USB_DPRINTF_L3(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2074             "uhci_get_tw_paddr_by_offs: dmac_addr 0x%x dmac_size "
2075             "0x%lx idx %d", buf_addr, tw->tw_cookie.dmac_size,
2076             tw->tw_cookie_idx);
2077 
2078         return (buf_addr);
2079 }
2080 
2081 
2082 /*
2083  * uhci_modify_td_active_bits:
2084  *      Sets active bit in all the tds of QH to INACTIVE so that
2085  *      the HC stops processing the TD's related to the QH.
2086  */
2087 void
2088 uhci_modify_td_active_bits(
2089         uhci_state_t            *uhcip,
2090         uhci_pipe_private_t     *pp)
2091 {
2092         uhci_td_t               *td_head;
2093         usb_ep_descr_t          *ept = &pp->pp_pipe_handle->p_ep;
2094         uhci_trans_wrapper_t    *tw_head = pp->pp_tw_head;
2095 
2096         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2097             "uhci_modify_td_active_bits: tw head %p", (void *)tw_head);
2098 
2099         while (tw_head != NULL) {
2100                 tw_head->tw_claim = UHCI_MODIFY_TD_BITS_CLAIMED;
2101                 td_head = tw_head->tw_hctd_head;
2102 
2103                 while (td_head) {
2104                         if (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_ISOCH) {
2105                                 SetTD_status(uhcip, td_head,
2106                                     GetTD_status(uhcip, td_head) & TD_INACTIVE);
2107                         } else {
2108                                 SetTD32(uhcip, td_head->link_ptr,
2109                                     GetTD32(uhcip, td_head->link_ptr) |
2110                                     HC_END_OF_LIST);
2111                         }
2112 
2113                         td_head = td_head->tw_td_next;
2114                 }
2115                 tw_head = tw_head->tw_next;
2116         }
2117 }
2118 
2119 
2120 /*
2121  * uhci_insert_ctrl_td:
2122  *      Create a TD and a data buffer for a control Queue Head.
2123  */
2124 int
2125 uhci_insert_ctrl_td(
2126         uhci_state_t            *uhcip,
2127         usba_pipe_handle_data_t  *ph,
2128         usb_ctrl_req_t          *ctrl_reqp,
2129         usb_flags_t             flags)
2130 {
2131         uhci_pipe_private_t  *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2132         uhci_trans_wrapper_t *tw;
2133         size_t  ctrl_buf_size;
2134 
2135         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2136             "uhci_insert_ctrl_td: timeout: 0x%x", ctrl_reqp->ctrl_timeout);
2137 
2138         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2139 
2140         /*
2141          * If we have a control data phase, make the data buffer start
2142          * on the next 64-byte boundary so as to ensure the DMA cookie
2143          * can fit in the multiple TDs. The buffer in the range of
2144          * [SETUP_SIZE, UHCI_CTRL_EPT_MAX_SIZE) is just for padding
2145          * and not to be transferred.
2146          */
2147         if (ctrl_reqp->ctrl_wLength) {
2148                 ctrl_buf_size = UHCI_CTRL_EPT_MAX_SIZE +
2149                     ctrl_reqp->ctrl_wLength;
2150         } else {
2151                 ctrl_buf_size = SETUP_SIZE;
2152         }
2153 
2154         /* Allocate a transaction wrapper */
2155         if ((tw = uhci_create_transfer_wrapper(uhcip, pp,
2156             ctrl_buf_size, flags)) == NULL) {
2157                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2158                     "uhci_insert_ctrl_td: TW allocation failed");
2159 
2160                 return (USB_NO_RESOURCES);
2161         }
2162 
2163         pp->pp_data_toggle = 0;
2164 
2165         tw->tw_curr_xfer_reqp = (usb_opaque_t)ctrl_reqp;
2166         tw->tw_bytes_xfered = 0;
2167         tw->tw_bytes_pending = ctrl_reqp->ctrl_wLength;
2168         tw->tw_timeout_cnt = max(UHCI_CTRL_TIMEOUT, ctrl_reqp->ctrl_timeout);
2169 
2170         /*
2171          * Initialize the callback and any callback
2172          * data for when the td completes.
2173          */
2174         tw->tw_handle_td = uhci_handle_ctrl_td;
2175         tw->tw_handle_callback_value = NULL;
2176 
2177         if ((uhci_create_setup_pkt(uhcip, pp, tw)) != USB_SUCCESS) {
2178                 tw->tw_ctrl_state = 0;
2179 
2180                 /* free the transfer wrapper */
2181                 uhci_deallocate_tw(uhcip, pp, tw);
2182 
2183                 return (USB_NO_RESOURCES);
2184         }
2185 
2186         tw->tw_ctrl_state = SETUP;
2187 
2188         return (USB_SUCCESS);
2189 }
2190 
2191 
2192 /*
2193  * uhci_create_setup_pkt:
2194  *      create a setup packet to initiate a control transfer.
2195  *
2196  *      OHCI driver has seen the case where devices fail if there is
2197  *      more than one control transfer to the device within a frame.
2198  *      So, the UHCI ensures that only one TD will be put on the control
2199  *      pipe to one device (to be consistent with OHCI driver).
2200  */
2201 static int
2202 uhci_create_setup_pkt(
2203         uhci_state_t            *uhcip,
2204         uhci_pipe_private_t     *pp,
2205         uhci_trans_wrapper_t    *tw)
2206 {
2207         int             sdata;
2208         usb_ctrl_req_t  *req = (usb_ctrl_req_t *)tw->tw_curr_xfer_reqp;
2209 
2210         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2211             "uhci_create_setup_pkt: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%p",
2212             req->ctrl_bmRequestType, req->ctrl_bRequest, req->ctrl_wValue,
2213             req->ctrl_wIndex, req->ctrl_wLength, (void *)req->ctrl_data);
2214 
2215         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2216         ASSERT(tw != NULL);
2217 
2218         /* Create the first four bytes of the setup packet */
2219         sdata = (req->ctrl_bmRequestType | (req->ctrl_bRequest << 8) |
2220             (req->ctrl_wValue << 16));
2221         ddi_put32(tw->tw_accesshandle, (uint_t *)tw->tw_buf, sdata);
2222 
2223         /* Create the second four bytes */
2224         sdata = (uint32_t)(req->ctrl_wIndex | (req->ctrl_wLength << 16));
2225         ddi_put32(tw->tw_accesshandle,
2226             (uint_t *)(tw->tw_buf + sizeof (uint_t)), sdata);
2227 
2228         /*
2229          * The TD's are placed on the QH one at a time.
2230          * Once this TD is placed on the done list, the
2231          * data or status phase TD will be enqueued.
2232          */
2233         if ((uhci_insert_hc_td(uhcip, 0, SETUP_SIZE,
2234             pp, tw, PID_SETUP, req->ctrl_attributes)) != USB_SUCCESS) {
2235 
2236                 return (USB_NO_RESOURCES);
2237         }
2238 
2239         USB_DPRINTF_L3(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2240             "Create_setup: pp = 0x%p, attrs = 0x%x", (void *)pp,
2241             req->ctrl_attributes);
2242 
2243         /*
2244          * If this control transfer has a data phase, record the
2245          * direction. If the data phase is an OUT transaction ,
2246          * copy the data into the buffer of the transfer wrapper.
2247          */
2248         if (req->ctrl_wLength != 0) {
2249                 /* There is a data stage.  Find the direction */
2250                 if (req->ctrl_bmRequestType & USB_DEV_REQ_DEV_TO_HOST) {
2251                         tw->tw_direction = PID_IN;
2252                 } else {
2253                         tw->tw_direction = PID_OUT;
2254 
2255                         /* Copy the data into the buffer */
2256                         ddi_rep_put8(tw->tw_accesshandle,
2257                             req->ctrl_data->b_rptr,
2258                             (uint8_t *)(tw->tw_buf + UHCI_CTRL_EPT_MAX_SIZE),
2259                             req->ctrl_wLength,
2260                             DDI_DEV_AUTOINCR);
2261                 }
2262         }
2263 
2264         return (USB_SUCCESS);
2265 }
2266 
2267 
2268 /*
2269  * uhci_create_stats:
2270  *      Allocate and initialize the uhci kstat structures
2271  */
2272 void
2273 uhci_create_stats(uhci_state_t *uhcip)
2274 {
2275         int                     i;
2276         char                    kstatname[KSTAT_STRLEN];
2277         char                    *usbtypes[USB_N_COUNT_KSTATS] =
2278             {"ctrl", "isoch", "bulk", "intr"};
2279         uint_t                  instance = uhcip->uhci_instance;
2280         const char              *dname = ddi_driver_name(uhcip->uhci_dip);
2281         uhci_intrs_stats_t      *isp;
2282 
2283         if (UHCI_INTRS_STATS(uhcip) == NULL) {
2284                 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,intrs",
2285                     dname, instance);
2286                 UHCI_INTRS_STATS(uhcip) = kstat_create("usba", instance,
2287                     kstatname, "usb_interrupts", KSTAT_TYPE_NAMED,
2288                     sizeof (uhci_intrs_stats_t) / sizeof (kstat_named_t),
2289                     KSTAT_FLAG_PERSISTENT);
2290 
2291                 if (UHCI_INTRS_STATS(uhcip) != NULL) {
2292                         isp = UHCI_INTRS_STATS_DATA(uhcip);
2293                         kstat_named_init(&isp->uhci_intrs_hc_halted,
2294                             "HC Halted", KSTAT_DATA_UINT64);
2295                         kstat_named_init(&isp->uhci_intrs_hc_process_err,
2296                             "HC Process Errors", KSTAT_DATA_UINT64);
2297                         kstat_named_init(&isp->uhci_intrs_host_sys_err,
2298                             "Host Sys Errors", KSTAT_DATA_UINT64);
2299                         kstat_named_init(&isp->uhci_intrs_resume_detected,
2300                             "Resume Detected", KSTAT_DATA_UINT64);
2301                         kstat_named_init(&isp->uhci_intrs_usb_err_intr,
2302                             "USB Error", KSTAT_DATA_UINT64);
2303                         kstat_named_init(&isp->uhci_intrs_usb_intr,
2304                             "USB Interrupts", KSTAT_DATA_UINT64);
2305                         kstat_named_init(&isp->uhci_intrs_total,
2306                             "Total Interrupts", KSTAT_DATA_UINT64);
2307                         kstat_named_init(&isp->uhci_intrs_not_claimed,
2308                             "Not Claimed", KSTAT_DATA_UINT64);
2309 
2310                         UHCI_INTRS_STATS(uhcip)->ks_private = uhcip;
2311                         UHCI_INTRS_STATS(uhcip)->ks_update = nulldev;
2312                         kstat_install(UHCI_INTRS_STATS(uhcip));
2313                 }
2314         }
2315 
2316         if (UHCI_TOTAL_STATS(uhcip) == NULL) {
2317                 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,total",
2318                     dname, instance);
2319                 UHCI_TOTAL_STATS(uhcip) = kstat_create("usba", instance,
2320                     kstatname, "usb_byte_count", KSTAT_TYPE_IO, 1,
2321                     KSTAT_FLAG_PERSISTENT);
2322 
2323                 if (UHCI_TOTAL_STATS(uhcip) != NULL) {
2324                         kstat_install(UHCI_TOTAL_STATS(uhcip));
2325                 }
2326         }
2327 
2328         for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
2329                 if (uhcip->uhci_count_stats[i] == NULL) {
2330                         (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,%s",
2331                             dname, instance, usbtypes[i]);
2332                         uhcip->uhci_count_stats[i] = kstat_create("usba",
2333                             instance, kstatname, "usb_byte_count",
2334                             KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
2335 
2336                         if (uhcip->uhci_count_stats[i] != NULL) {
2337                                 kstat_install(uhcip->uhci_count_stats[i]);
2338                         }
2339                 }
2340         }
2341 }
2342 
2343 
2344 /*
2345  * uhci_destroy_stats:
2346  *      Clean up uhci kstat structures
2347  */
2348 void
2349 uhci_destroy_stats(uhci_state_t *uhcip)
2350 {
2351         int i;
2352 
2353         if (UHCI_INTRS_STATS(uhcip)) {
2354                 kstat_delete(UHCI_INTRS_STATS(uhcip));
2355                 UHCI_INTRS_STATS(uhcip) = NULL;
2356         }
2357 
2358         if (UHCI_TOTAL_STATS(uhcip)) {
2359                 kstat_delete(UHCI_TOTAL_STATS(uhcip));
2360                 UHCI_TOTAL_STATS(uhcip) = NULL;
2361         }
2362 
2363         for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
2364                 if (uhcip->uhci_count_stats[i]) {
2365                         kstat_delete(uhcip->uhci_count_stats[i]);
2366                         uhcip->uhci_count_stats[i] = NULL;
2367                 }
2368         }
2369 }
2370 
2371 
2372 void
2373 uhci_do_intrs_stats(uhci_state_t *uhcip, int val)
2374 {
2375         if (UHCI_INTRS_STATS(uhcip) == NULL) {
2376 
2377                 return;
2378         }
2379 
2380         UHCI_INTRS_STATS_DATA(uhcip)->uhci_intrs_total.value.ui64++;
2381         switch (val) {
2382         case USBSTS_REG_HC_HALTED:
2383                 UHCI_INTRS_STATS_DATA(uhcip)->uhci_intrs_hc_halted.value.ui64++;
2384                 break;
2385         case USBSTS_REG_HC_PROCESS_ERR:
2386                 UHCI_INTRS_STATS_DATA(uhcip)->
2387                     uhci_intrs_hc_process_err.value.ui64++;
2388                 break;
2389         case USBSTS_REG_HOST_SYS_ERR:
2390                 UHCI_INTRS_STATS_DATA(uhcip)->
2391                     uhci_intrs_host_sys_err.value.ui64++;
2392                 break;
2393         case USBSTS_REG_RESUME_DETECT:
2394                 UHCI_INTRS_STATS_DATA(uhcip)->
2395                     uhci_intrs_resume_detected.value.ui64++;
2396                 break;
2397         case USBSTS_REG_USB_ERR_INTR:
2398                 UHCI_INTRS_STATS_DATA(uhcip)->
2399                     uhci_intrs_usb_err_intr.value.ui64++;
2400                 break;
2401         case USBSTS_REG_USB_INTR:
2402                 UHCI_INTRS_STATS_DATA(uhcip)->uhci_intrs_usb_intr.value.ui64++;
2403                 break;
2404         default:
2405                 UHCI_INTRS_STATS_DATA(uhcip)->
2406                     uhci_intrs_not_claimed.value.ui64++;
2407                 break;
2408         }
2409 }
2410 
2411 
2412 void
2413 uhci_do_byte_stats(uhci_state_t *uhcip, size_t len, uint8_t attr, uint8_t addr)
2414 {
2415         uint8_t type = attr & USB_EP_ATTR_MASK;
2416         uint8_t dir = addr & USB_EP_DIR_MASK;
2417 
2418         switch (dir) {
2419         case USB_EP_DIR_IN:
2420                 UHCI_TOTAL_STATS_DATA(uhcip)->reads++;
2421                 UHCI_TOTAL_STATS_DATA(uhcip)->nread += len;
2422                 switch (type) {
2423                 case USB_EP_ATTR_CONTROL:
2424                         UHCI_CTRL_STATS(uhcip)->reads++;
2425                         UHCI_CTRL_STATS(uhcip)->nread += len;
2426                         break;
2427                 case USB_EP_ATTR_BULK:
2428                         UHCI_BULK_STATS(uhcip)->reads++;
2429                         UHCI_BULK_STATS(uhcip)->nread += len;
2430                         break;
2431                 case USB_EP_ATTR_INTR:
2432                         UHCI_INTR_STATS(uhcip)->reads++;
2433                         UHCI_INTR_STATS(uhcip)->nread += len;
2434                         break;
2435                 case USB_EP_ATTR_ISOCH:
2436                         UHCI_ISOC_STATS(uhcip)->reads++;
2437                         UHCI_ISOC_STATS(uhcip)->nread += len;
2438                         break;
2439                 }
2440                 break;
2441         case USB_EP_DIR_OUT:
2442                 UHCI_TOTAL_STATS_DATA(uhcip)->writes++;
2443                 UHCI_TOTAL_STATS_DATA(uhcip)->nwritten += len;
2444                 switch (type) {
2445                 case USB_EP_ATTR_CONTROL:
2446                         UHCI_CTRL_STATS(uhcip)->writes++;
2447                         UHCI_CTRL_STATS(uhcip)->nwritten += len;
2448                         break;
2449                 case USB_EP_ATTR_BULK:
2450                         UHCI_BULK_STATS(uhcip)->writes++;
2451                         UHCI_BULK_STATS(uhcip)->nwritten += len;
2452                         break;
2453                 case USB_EP_ATTR_INTR:
2454                         UHCI_INTR_STATS(uhcip)->writes++;
2455                         UHCI_INTR_STATS(uhcip)->nwritten += len;
2456                         break;
2457                 case USB_EP_ATTR_ISOCH:
2458                         UHCI_ISOC_STATS(uhcip)->writes++;
2459                         UHCI_ISOC_STATS(uhcip)->nwritten += len;
2460                         break;
2461                 }
2462                 break;
2463         }
2464 }
2465 
2466 
2467 /*
2468  * uhci_free_tw:
2469  *      Free the Transfer Wrapper (TW).
2470  */
2471 void
2472 uhci_free_tw(uhci_state_t *uhcip, uhci_trans_wrapper_t *tw)
2473 {
2474         int rval, i;
2475 
2476         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl, "uhci_free_tw:");
2477 
2478         ASSERT(tw != NULL);
2479 
2480         if (tw->tw_isoc_strtlen > 0) {
2481                 ASSERT(tw->tw_isoc_bufs != NULL);
2482                 for (i = 0; i < tw->tw_ncookies; i++) {
2483                         rval = ddi_dma_unbind_handle(
2484                             tw->tw_isoc_bufs[i].dma_handle);
2485                         ASSERT(rval == USB_SUCCESS);
2486                         ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
2487                         ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
2488                 }
2489                 kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
2490         } else if (tw->tw_dmahandle != NULL) {
2491                 rval = ddi_dma_unbind_handle(tw->tw_dmahandle);
2492                 ASSERT(rval == DDI_SUCCESS);
2493 
2494                 ddi_dma_mem_free(&tw->tw_accesshandle);
2495                 ddi_dma_free_handle(&tw->tw_dmahandle);
2496         }
2497 
2498         kmem_free(tw, sizeof (uhci_trans_wrapper_t));
2499 }
2500 
2501 
2502 /*
2503  * uhci_deallocate_tw:
2504  *      Deallocate of a Transaction Wrapper (TW) and this involves
2505  *      the freeing of DMA resources.
2506  */
2507 void
2508 uhci_deallocate_tw(uhci_state_t *uhcip,
2509     uhci_pipe_private_t *pp, uhci_trans_wrapper_t *tw)
2510 {
2511         uhci_trans_wrapper_t    *head;
2512 
2513         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2514             "uhci_deallocate_tw:");
2515 
2516         /*
2517          * If the transfer wrapper has no Host Controller (HC)
2518          * Transfer Descriptors (TD) associated with it,  then
2519          * remove the transfer wrapper. The transfers are done
2520          * in FIFO order, so this should be the first transfer
2521          * wrapper on the list.
2522          */
2523         if (tw->tw_hctd_head != NULL) {
2524                 ASSERT(tw->tw_hctd_tail != NULL);
2525 
2526                 return;
2527         }
2528 
2529         ASSERT(tw->tw_hctd_tail == NULL);
2530         ASSERT(pp->pp_tw_head != NULL);
2531 
2532         /*
2533          * If pp->pp_tw_head is NULL, set the tail also to NULL.
2534          */
2535         head = pp->pp_tw_head;
2536 
2537         if (head == tw) {
2538                 pp->pp_tw_head = head->tw_next;
2539                 if (pp->pp_tw_head == NULL) {
2540                         pp->pp_tw_tail = NULL;
2541                 }
2542         } else {
2543                 while (head->tw_next != tw)
2544                         head = head->tw_next;
2545                 head->tw_next = tw->tw_next;
2546                 if (tw->tw_next == NULL) {
2547                         pp->pp_tw_tail = head;
2548                 }
2549         }
2550         uhci_free_tw(uhcip, tw);
2551 }
2552 
2553 
2554 void
2555 uhci_delete_td(uhci_state_t *uhcip, uhci_td_t *td)
2556 {
2557         uhci_td_t               *tmp_td;
2558         uhci_trans_wrapper_t    *tw = td->tw;
2559 
2560         if ((td->outst_td_next == NULL) && (td->outst_td_prev == NULL)) {
2561                 uhcip->uhci_outst_tds_head = NULL;
2562                 uhcip->uhci_outst_tds_tail = NULL;
2563         } else if (td->outst_td_next == NULL) {
2564                 td->outst_td_prev->outst_td_next = NULL;
2565                 uhcip->uhci_outst_tds_tail = td->outst_td_prev;
2566         } else if (td->outst_td_prev == NULL) {
2567                 td->outst_td_next->outst_td_prev = NULL;
2568                 uhcip->uhci_outst_tds_head = td->outst_td_next;
2569         } else {
2570                 td->outst_td_prev->outst_td_next = td->outst_td_next;
2571                 td->outst_td_next->outst_td_prev = td->outst_td_prev;
2572         }
2573 
2574         tmp_td = tw->tw_hctd_head;
2575 
2576         if (tmp_td != td) {
2577                 while (tmp_td->tw_td_next != td) {
2578                         tmp_td = tmp_td->tw_td_next;
2579                 }
2580                 ASSERT(tmp_td);
2581                 tmp_td->tw_td_next = td->tw_td_next;
2582                 if (td->tw_td_next == NULL) {
2583                         tw->tw_hctd_tail = tmp_td;
2584                 }
2585         } else {
2586                 tw->tw_hctd_head = tw->tw_hctd_head->tw_td_next;
2587                 if (tw->tw_hctd_head == NULL) {
2588                         tw->tw_hctd_tail = NULL;
2589                 }
2590         }
2591 
2592         td->flag  = TD_FLAG_FREE;
2593 }
2594 
2595 
2596 void
2597 uhci_remove_tds_tws(
2598         uhci_state_t            *uhcip,
2599         usba_pipe_handle_data_t *ph)
2600 {
2601         usb_opaque_t            curr_reqp;
2602         uhci_pipe_private_t     *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2603         usb_ep_descr_t          *ept = &pp->pp_pipe_handle->p_ep;
2604         uhci_trans_wrapper_t    *tw_tmp;
2605         uhci_trans_wrapper_t    *tw_head = pp->pp_tw_head;
2606 
2607         while (tw_head != NULL) {
2608                 tw_tmp = tw_head;
2609                 tw_head = tw_head->tw_next;
2610 
2611                 curr_reqp = tw_tmp->tw_curr_xfer_reqp;
2612                 if (curr_reqp) {
2613                         /* do this for control/bulk/intr */
2614                         if ((tw_tmp->tw_direction == PID_IN) &&
2615                             (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_INTR)) {
2616                                 uhci_deallocate_periodic_in_resource(uhcip,
2617                                     pp, tw_tmp);
2618                         } else {
2619                                 uhci_hcdi_callback(uhcip, pp,
2620                                     pp->pp_pipe_handle, tw_tmp, USB_CR_FLUSHED);
2621                         }
2622                 } /* end of curr_reqp */
2623 
2624                 if (tw_tmp->tw_claim != UHCI_MODIFY_TD_BITS_CLAIMED) {
2625                         continue;
2626                 }
2627 
2628                 while (tw_tmp->tw_hctd_head != NULL) {
2629                         uhci_delete_td(uhcip, tw_tmp->tw_hctd_head);
2630                 }
2631 
2632                 uhci_deallocate_tw(uhcip, pp, tw_tmp);
2633         }
2634 }
2635 
2636 
2637 /*
2638  * uhci_remove_qh:
2639  *      Remove the Queue Head from the Host Controller's
2640  *      appropriate QH list.
2641  */
2642 void
2643 uhci_remove_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2644 {
2645         uhci_td_t       *dummy_td;
2646 
2647         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2648 
2649         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2650             "uhci_remove_qh:");
2651 
2652         dummy_td = pp->pp_qh->td_tailp;
2653         dummy_td->flag = TD_FLAG_FREE;
2654 
2655         switch (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep)) {
2656         case USB_EP_ATTR_CONTROL:
2657                 uhci_remove_ctrl_qh(uhcip, pp);
2658                 break;
2659         case USB_EP_ATTR_BULK:
2660                 uhci_remove_bulk_qh(uhcip, pp);
2661                 break;
2662         case USB_EP_ATTR_INTR:
2663                 uhci_remove_intr_qh(uhcip, pp);
2664                 break;
2665         }
2666 }
2667 
2668 
2669 static void
2670 uhci_remove_intr_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2671 {
2672         queue_head_t   *qh = pp->pp_qh;
2673         queue_head_t   *next_lattice_qh =
2674             QH_VADDR(GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK);
2675 
2676         qh->prev_qh->link_ptr      = qh->link_ptr;
2677         next_lattice_qh->prev_qh = qh->prev_qh;
2678         qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
2679 
2680 }
2681 
2682 /*
2683  * uhci_remove_bulk_qh:
2684  *      Remove a bulk QH from the Host Controller's QH list. There may be a
2685  *      loop for bulk QHs, we must care about this while removing a bulk QH.
2686  */
2687 static void
2688 uhci_remove_bulk_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2689 {
2690         queue_head_t   *qh = pp->pp_qh;
2691         queue_head_t   *next_lattice_qh;
2692         uint32_t        paddr;
2693 
2694         paddr = (GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK);
2695         next_lattice_qh = (qh == uhcip->uhci_bulk_xfers_q_tail) ?
2696             0 : QH_VADDR(paddr);
2697 
2698         if ((qh == uhcip->uhci_bulk_xfers_q_tail) &&
2699             (qh->prev_qh == uhcip->uhci_bulk_xfers_q_head)) {
2700                 SetQH32(uhcip, qh->prev_qh->link_ptr, HC_END_OF_LIST);
2701         } else {
2702                 qh->prev_qh->link_ptr = qh->link_ptr;
2703         }
2704 
2705         if (next_lattice_qh == NULL) {
2706                 uhcip->uhci_bulk_xfers_q_tail = qh->prev_qh;
2707         } else {
2708                 next_lattice_qh->prev_qh = qh->prev_qh;
2709         }
2710 
2711         qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
2712 
2713 }
2714 
2715 
2716 static void
2717 uhci_remove_ctrl_qh(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
2718 {
2719         queue_head_t   *qh = pp->pp_qh;
2720         queue_head_t   *next_lattice_qh =
2721             QH_VADDR(GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK);
2722 
2723         qh->prev_qh->link_ptr = qh->link_ptr;
2724         if (next_lattice_qh->prev_qh != NULL) {
2725                 next_lattice_qh->prev_qh = qh->prev_qh;
2726         } else {
2727                 uhcip->uhci_ctrl_xfers_q_tail = qh->prev_qh;
2728         }
2729 
2730         qh->qh_flag = QUEUE_HEAD_FLAG_FREE;
2731 }
2732 
2733 
2734 /*
2735  * uhci_allocate_td_from_pool:
2736  *      Allocate a Transfer Descriptor (TD) from the TD buffer pool.
2737  */
2738 static uhci_td_t *
2739 uhci_allocate_td_from_pool(uhci_state_t *uhcip)
2740 {
2741         int             index;
2742         uhci_td_t       *td;
2743 
2744         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2745 
2746         /*
2747          * Search for a blank Transfer Descriptor (TD)
2748          * in the TD buffer pool.
2749          */
2750         for (index = 0; index < uhci_td_pool_size; index ++) {
2751                 if (uhcip->uhci_td_pool_addr[index].flag == TD_FLAG_FREE) {
2752                         break;
2753                 }
2754         }
2755 
2756         if (index == uhci_td_pool_size) {
2757                 USB_DPRINTF_L2(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2758                     "uhci_allocate_td_from_pool: TD exhausted");
2759 
2760                 return (NULL);
2761         }
2762 
2763         USB_DPRINTF_L4(PRINT_MASK_ALLOC, uhcip->uhci_log_hdl,
2764             "uhci_allocate_td_from_pool: Allocated %d", index);
2765 
2766         /* Create a new dummy for the end of the TD list */
2767         td = &uhcip->uhci_td_pool_addr[index];
2768 
2769         /* Mark the newly allocated TD as a dummy */
2770         td->flag =  TD_FLAG_DUMMY;
2771         td->qh_td_prev       =  NULL;
2772 
2773         return (td);
2774 }
2775 
2776 
2777 /*
2778  * uhci_insert_bulk_td:
2779  */
2780 int
2781 uhci_insert_bulk_td(
2782         uhci_state_t            *uhcip,
2783         usba_pipe_handle_data_t *ph,
2784         usb_bulk_req_t          *req,
2785         usb_flags_t             flags)
2786 {
2787         size_t                  length;
2788         uint_t                  mps;    /* MaxPacketSize */
2789         uint_t                  num_bulk_tds, i, j;
2790         uint32_t                buf_offs;
2791         uhci_td_t               *bulk_td_ptr;
2792         uhci_td_t               *current_dummy, *tmp_td;
2793         uhci_pipe_private_t     *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2794         uhci_trans_wrapper_t    *tw;
2795         uhci_bulk_isoc_xfer_t   *bulk_xfer_info;
2796         uhci_bulk_isoc_td_pool_t *td_pool_ptr;
2797 
2798         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2799             "uhci_insert_bulk_td: req: 0x%p, flags = 0x%x", (void *)req, flags);
2800 
2801         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
2802 
2803         /*
2804          * Create transfer wrapper
2805          */
2806         if ((tw = uhci_create_transfer_wrapper(uhcip, pp, req->bulk_len,
2807             flags)) == NULL) {
2808                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2809                     "uhci_insert_bulk_td: TW allocation failed");
2810 
2811                 return (USB_NO_RESOURCES);
2812         }
2813 
2814         tw->tw_bytes_xfered          = 0;
2815         tw->tw_bytes_pending         = req->bulk_len;
2816         tw->tw_handle_td             = uhci_handle_bulk_td;
2817         tw->tw_handle_callback_value = (usb_opaque_t)req->bulk_data;
2818         tw->tw_timeout_cnt           = req->bulk_timeout;
2819         tw->tw_data                  = req->bulk_data;
2820         tw->tw_curr_xfer_reqp                = (usb_opaque_t)req;
2821 
2822         /* Get the bulk pipe direction */
2823         tw->tw_direction = (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) ?
2824             PID_OUT : PID_IN;
2825 
2826         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2827             "uhci_insert_bulk_td: direction: 0x%x", tw->tw_direction);
2828 
2829         /* If the DATA OUT, copy the data into transfer buffer. */
2830         if (tw->tw_direction == PID_OUT) {
2831                 if (req->bulk_len) {
2832                         ASSERT(req->bulk_data != NULL);
2833 
2834                         /* Copy the data into the message */
2835                         ddi_rep_put8(tw->tw_accesshandle,
2836                             req->bulk_data->b_rptr,
2837                             (uint8_t *)tw->tw_buf,
2838                             req->bulk_len, DDI_DEV_AUTOINCR);
2839                 }
2840         }
2841 
2842         /* Get the max packet size.  */
2843         length = mps = pp->pp_pipe_handle->p_ep.wMaxPacketSize;
2844 
2845         /*
2846          * Calculate number of TD's to insert in the current frame interval.
2847          * Max number TD's allowed (driver implementation) is 128
2848          * in one frame interval. Once all the TD's are completed
2849          * then the remaining TD's will be inserted into the lattice
2850          * in the uhci_handle_bulk_td().
2851          */
2852         if ((tw->tw_bytes_pending / mps) >= MAX_NUM_BULK_TDS_PER_XFER) {
2853                 num_bulk_tds = MAX_NUM_BULK_TDS_PER_XFER;
2854         } else {
2855                 num_bulk_tds = (tw->tw_bytes_pending / mps);
2856 
2857                 if (tw->tw_bytes_pending % mps || tw->tw_bytes_pending == 0) {
2858                         num_bulk_tds++;
2859                         length = (tw->tw_bytes_pending % mps);
2860                 }
2861         }
2862 
2863         /*
2864          * Allocate memory for the bulk xfer information structure
2865          */
2866         if ((bulk_xfer_info = kmem_zalloc(
2867             sizeof (uhci_bulk_isoc_xfer_t), KM_NOSLEEP)) == NULL) {
2868                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2869                     "uhci_insert_bulk_td: kmem_zalloc failed");
2870 
2871                 /* Free the transfer wrapper */
2872                 uhci_deallocate_tw(uhcip, pp, tw);
2873 
2874                 return (USB_FAILURE);
2875         }
2876 
2877         /* Allocate memory for the bulk TD's */
2878         if (uhci_alloc_bulk_isoc_tds(uhcip, num_bulk_tds, bulk_xfer_info) !=
2879             USB_SUCCESS) {
2880                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2881                     "uhci_insert_bulk_td: alloc_bulk_isoc_tds failed");
2882 
2883                 kmem_free(bulk_xfer_info, sizeof (uhci_bulk_isoc_xfer_t));
2884 
2885                 /* Free the transfer wrapper */
2886                 uhci_deallocate_tw(uhcip, pp, tw);
2887 
2888                 return (USB_FAILURE);
2889         }
2890 
2891         td_pool_ptr = &bulk_xfer_info->td_pools[0];
2892         bulk_td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
2893         bulk_td_ptr[0].qh_td_prev = NULL;
2894         current_dummy = pp->pp_qh->td_tailp;
2895         buf_offs = 0;
2896         pp->pp_qh->bulk_xfer_info = bulk_xfer_info;
2897 
2898         /* Fill up all the bulk TD's */
2899         for (i = 0; i < bulk_xfer_info->num_pools; i++) {
2900                 for (j = 0; j < (td_pool_ptr->num_tds - 1); j++) {
2901                         uhci_fill_in_bulk_isoc_td(uhcip, &bulk_td_ptr[j],
2902                             &bulk_td_ptr[j+1], BULKTD_PADDR(td_pool_ptr,
2903                             &bulk_td_ptr[j+1]), ph, buf_offs, mps, tw);
2904                         buf_offs += mps;
2905                 }
2906 
2907                 /* fill in the last TD */
2908                 if (i == (bulk_xfer_info->num_pools - 1)) {
2909                         uhci_fill_in_bulk_isoc_td(uhcip, &bulk_td_ptr[j],
2910                             current_dummy, TD_PADDR(current_dummy),
2911                             ph, buf_offs, length, tw);
2912                 } else {
2913                         /* fill in the TD at the tail of a pool */
2914                         tmp_td = &bulk_td_ptr[j];
2915                         td_pool_ptr = &bulk_xfer_info->td_pools[i + 1];
2916                         bulk_td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
2917                         uhci_fill_in_bulk_isoc_td(uhcip, tmp_td,
2918                             &bulk_td_ptr[0], BULKTD_PADDR(td_pool_ptr,
2919                             &bulk_td_ptr[0]), ph, buf_offs, mps, tw);
2920                         buf_offs += mps;
2921                 }
2922         }
2923 
2924         bulk_xfer_info->num_tds      = (ushort_t)num_bulk_tds;
2925 
2926         /*
2927          * Point the end of the lattice tree to the start of the bulk xfers
2928          * queue head. This allows the HC to execute the same Queue Head/TD
2929          * in the same frame. There are some bulk devices, which NAKs after
2930          * completing each TD. As a result, the performance on such devices
2931          * is very bad.  This loop will  provide a chance to execute NAk'ed
2932          * bulk TDs again in the same frame.
2933          */
2934         if (uhcip->uhci_pending_bulk_cmds++ == 0) {
2935                 uhcip->uhci_bulk_xfers_q_tail->link_ptr =
2936                     uhcip->uhci_bulk_xfers_q_head->link_ptr;
2937                 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
2938                     "uhci_insert_bulk_td: count = %d no tds  %d",
2939                     uhcip->uhci_pending_bulk_cmds, num_bulk_tds);
2940         }
2941 
2942         /* Insert on the bulk queue head for the execution by HC */
2943         SetQH32(uhcip, pp->pp_qh->element_ptr,
2944             bulk_xfer_info->td_pools[0].cookie.dmac_address);
2945 
2946         return (USB_SUCCESS);
2947 }
2948 
2949 
2950 /*
2951  * uhci_fill_in_bulk_isoc_td
2952  *     Fills the bulk/isoc TD
2953  *
2954  * offset - different meanings for bulk and isoc TDs:
2955  *          starting offset into the TW buffer for a bulk TD
2956  *          and the index into the isoc packet list for an isoc TD
2957  */
2958 void
2959 uhci_fill_in_bulk_isoc_td(uhci_state_t *uhcip, uhci_td_t *current_td,
2960         uhci_td_t               *next_td,
2961         uint32_t                next_td_paddr,
2962         usba_pipe_handle_data_t *ph,
2963         uint_t                  offset,
2964         uint_t                  length,
2965         uhci_trans_wrapper_t    *tw)
2966 {
2967         uhci_pipe_private_t     *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
2968         usb_ep_descr_t          *ept = &pp->pp_pipe_handle->p_ep;
2969         uint32_t                buf_addr;
2970 
2971         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
2972             "uhci_fill_in_bulk_isoc_td: tw 0x%p offs 0x%x length 0x%x",
2973             (void *)tw, offset, length);
2974 
2975         bzero((char *)current_td, sizeof (uhci_td_t));
2976         SetTD32(uhcip, current_td->link_ptr, next_td_paddr | HC_DEPTH_FIRST);
2977 
2978         switch (UHCI_XFER_TYPE(ept)) {
2979         case USB_EP_ATTR_ISOCH:
2980                 if (((usb_isoc_req_t *)tw->tw_curr_xfer_reqp)->isoc_attributes
2981                     & USB_ATTRS_SHORT_XFER_OK) {
2982                         SetTD_spd(uhcip, current_td, 1);
2983                 }
2984                 break;
2985         case USB_EP_ATTR_BULK:
2986                 if (((usb_bulk_req_t *)tw->tw_curr_xfer_reqp)->bulk_attributes
2987                     & USB_ATTRS_SHORT_XFER_OK) {
2988                         SetTD_spd(uhcip, current_td, 1);
2989                 }
2990                 break;
2991         }
2992 
2993         mutex_enter(&ph->p_usba_device->usb_mutex);
2994 
2995         SetTD_c_err(uhcip, current_td, UHCI_MAX_ERR_COUNT);
2996         SetTD_status(uhcip, current_td, UHCI_TD_ACTIVE);
2997         SetTD_ioc(uhcip, current_td, INTERRUPT_ON_COMPLETION);
2998         SetTD_mlen(uhcip, current_td,
2999             (length == 0) ? ZERO_LENGTH : (length - 1));
3000         SetTD_dtogg(uhcip, current_td, pp->pp_data_toggle);
3001         SetTD_devaddr(uhcip, current_td, ph->p_usba_device->usb_addr);
3002         SetTD_endpt(uhcip, current_td, ph->p_ep.bEndpointAddress &
3003             END_POINT_ADDRESS_MASK);
3004         SetTD_PID(uhcip, current_td, tw->tw_direction);
3005 
3006         /* Get the right buffer address for the current TD */
3007         switch (UHCI_XFER_TYPE(ept)) {
3008         case USB_EP_ATTR_ISOCH:
3009                 buf_addr = tw->tw_isoc_bufs[offset].cookie.dmac_address;
3010                 break;
3011         case USB_EP_ATTR_BULK:
3012                 buf_addr = uhci_get_tw_paddr_by_offs(uhcip, offset,
3013                     length, tw);
3014                 break;
3015         }
3016         SetTD32(uhcip, current_td->buffer_address, buf_addr);
3017 
3018         /*
3019          * Adjust the data toggle.
3020          * The data toggle bit must always be 0 for isoc transfers.
3021          * And set the "iso" bit in the TD for isoc transfers.
3022          */
3023         if (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_ISOCH) {
3024                 pp->pp_data_toggle = 0;
3025                 SetTD_iso(uhcip, current_td, 1);
3026         } else {
3027                 ADJ_DATA_TOGGLE(pp);
3028                 next_td->qh_td_prev = current_td;
3029                 pp->pp_qh->td_tailp = next_td;
3030         }
3031 
3032         current_td->outst_td_next = NULL;
3033         current_td->outst_td_prev = uhcip->uhci_outst_tds_tail;
3034         if (uhcip->uhci_outst_tds_head == NULL) {
3035                 uhcip->uhci_outst_tds_head = current_td;
3036         } else {
3037                 uhcip->uhci_outst_tds_tail->outst_td_next = current_td;
3038         }
3039         uhcip->uhci_outst_tds_tail = current_td;
3040         current_td->tw = tw;
3041 
3042         if (tw->tw_hctd_head == NULL) {
3043                 ASSERT(tw->tw_hctd_tail == NULL);
3044                 tw->tw_hctd_head = current_td;
3045                 tw->tw_hctd_tail = current_td;
3046         } else {
3047                 /* Add the td to the end of the list */
3048                 tw->tw_hctd_tail->tw_td_next = current_td;
3049                 tw->tw_hctd_tail = current_td;
3050         }
3051 
3052         mutex_exit(&ph->p_usba_device->usb_mutex);
3053 }
3054 
3055 
3056 /*
3057  * uhci_alloc_bulk_isoc_tds:
3058  *      - Allocates the isoc/bulk TD pools. It will allocate one whole
3059  *        pool to store all the TDs if the system allows. Only when the
3060  *        first allocation fails, it tries to allocate several small
3061  *        pools with each pool limited in physical page size.
3062  */
3063 static int
3064 uhci_alloc_bulk_isoc_tds(
3065         uhci_state_t            *uhcip,
3066         uint_t                  num_tds,
3067         uhci_bulk_isoc_xfer_t   *info)
3068 {
3069         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3070             "uhci_alloc_bulk_isoc_tds: num_tds: 0x%x info: 0x%p",
3071             num_tds, (void *)info);
3072 
3073         info->num_pools = 1;
3074         /* allocate as a whole pool at the first time */
3075         if (uhci_alloc_memory_for_tds(uhcip, num_tds, info) !=
3076             USB_SUCCESS) {
3077                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3078                     "alloc_memory_for_tds failed: num_tds %d num_pools %d",
3079                     num_tds, info->num_pools);
3080 
3081                 /* reduce the td number per pool and alloc again */
3082                 info->num_pools = num_tds / UHCI_MAX_TD_NUM_PER_POOL;
3083                 if (num_tds % UHCI_MAX_TD_NUM_PER_POOL) {
3084                         info->num_pools++;
3085                 }
3086 
3087                 if (uhci_alloc_memory_for_tds(uhcip, num_tds, info) !=
3088                     USB_SUCCESS) {
3089                         USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3090                             "alloc_memory_for_tds failed: num_tds %d "
3091                             "num_pools %d", num_tds, info->num_pools);
3092 
3093                         return (USB_NO_RESOURCES);
3094                 }
3095         }
3096 
3097         return (USB_SUCCESS);
3098 }
3099 
3100 
3101 /*
3102  * uhci_alloc_memory_for_tds:
3103  *      - Allocates memory for the isoc/bulk td pools.
3104  */
3105 static int
3106 uhci_alloc_memory_for_tds(
3107         uhci_state_t            *uhcip,
3108         uint_t                  num_tds,
3109         uhci_bulk_isoc_xfer_t   *info)
3110 {
3111         int                     result, i, j, err;
3112         size_t                  real_length;
3113         uint_t                  ccount, num;
3114         ddi_device_acc_attr_t   dev_attr;
3115         uhci_bulk_isoc_td_pool_t *td_pool_ptr1, *td_pool_ptr2;
3116 
3117         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3118             "uhci_alloc_memory_for_tds: num_tds: 0x%x info: 0x%p "
3119             "num_pools: %u", num_tds, (void *)info, info->num_pools);
3120 
3121         /* The host controller will be little endian */
3122         dev_attr.devacc_attr_version            = DDI_DEVICE_ATTR_V0;
3123         dev_attr.devacc_attr_endian_flags       = DDI_STRUCTURE_LE_ACC;
3124         dev_attr.devacc_attr_dataorder          = DDI_STRICTORDER_ACC;
3125 
3126         /* Allocate the TD pool structures */
3127         info->td_pools = kmem_zalloc((sizeof (uhci_bulk_isoc_td_pool_t) *
3128             info->num_pools), KM_SLEEP);
3129 
3130         for (i = 0; i < info->num_pools; i++) {
3131                 if (info->num_pools == 1) {
3132                         num = num_tds;
3133                 } else if (i < (info->num_pools - 1)) {
3134                         num = UHCI_MAX_TD_NUM_PER_POOL;
3135                 } else {
3136                         num = (num_tds % UHCI_MAX_TD_NUM_PER_POOL);
3137                 }
3138 
3139                 td_pool_ptr1 = &info->td_pools[i];
3140 
3141                 /* Allocate the bulk TD pool DMA handle */
3142                 if (ddi_dma_alloc_handle(uhcip->uhci_dip,
3143                     &uhcip->uhci_dma_attr, DDI_DMA_SLEEP, 0,
3144                     &td_pool_ptr1->dma_handle) != DDI_SUCCESS) {
3145 
3146                         for (j = 0; j < i; j++) {
3147                                 td_pool_ptr2 = &info->td_pools[j];
3148                                 result = ddi_dma_unbind_handle(
3149                                     td_pool_ptr2->dma_handle);
3150                                 ASSERT(result == DDI_SUCCESS);
3151                                 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3152                                 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3153                         }
3154 
3155                         kmem_free(info->td_pools,
3156                             (sizeof (uhci_bulk_isoc_td_pool_t) *
3157                             info->num_pools));
3158 
3159                         return (USB_FAILURE);
3160                 }
3161 
3162                 /* Allocate the memory for the bulk TD pool */
3163                 if (ddi_dma_mem_alloc(td_pool_ptr1->dma_handle,
3164                     num * sizeof (uhci_td_t), &dev_attr,
3165                     DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
3166                     &td_pool_ptr1->pool_addr, &real_length,
3167                     &td_pool_ptr1->mem_handle) != DDI_SUCCESS) {
3168 
3169                         ddi_dma_free_handle(&td_pool_ptr1->dma_handle);
3170 
3171                         for (j = 0; j < i; j++) {
3172                                 td_pool_ptr2 = &info->td_pools[j];
3173                                 result = ddi_dma_unbind_handle(
3174                                     td_pool_ptr2->dma_handle);
3175                                 ASSERT(result == DDI_SUCCESS);
3176                                 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3177                                 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3178                         }
3179 
3180                         kmem_free(info->td_pools,
3181                             (sizeof (uhci_bulk_isoc_td_pool_t) *
3182                             info->num_pools));
3183 
3184                         return (USB_FAILURE);
3185                 }
3186 
3187                 /* Map the bulk TD pool into the I/O address space */
3188                 result = ddi_dma_addr_bind_handle(td_pool_ptr1->dma_handle,
3189                     NULL, (caddr_t)td_pool_ptr1->pool_addr, real_length,
3190                     DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
3191                     &td_pool_ptr1->cookie, &ccount);
3192 
3193                 /* Process the result */
3194                 err = USB_SUCCESS;
3195 
3196                 if (result != DDI_DMA_MAPPED) {
3197                         USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3198                             "uhci_allocate_memory_for_tds: Result = %d",
3199                             result);
3200                         uhci_decode_ddi_dma_addr_bind_handle_result(uhcip,
3201                             result);
3202 
3203                         err = USB_FAILURE;
3204                 }
3205 
3206                 if ((result == DDI_DMA_MAPPED) && (ccount != 1)) {
3207                         /* The cookie count should be 1 */
3208                         USB_DPRINTF_L2(PRINT_MASK_ATTA,
3209                             uhcip->uhci_log_hdl,
3210                             "uhci_allocate_memory_for_tds: "
3211                             "More than 1 cookie");
3212 
3213                         result = ddi_dma_unbind_handle(
3214                             td_pool_ptr1->dma_handle);
3215                         ASSERT(result == DDI_SUCCESS);
3216 
3217                         err = USB_FAILURE;
3218                 }
3219 
3220                 if (err == USB_FAILURE) {
3221 
3222                         ddi_dma_mem_free(&td_pool_ptr1->mem_handle);
3223                         ddi_dma_free_handle(&td_pool_ptr1->dma_handle);
3224 
3225                         for (j = 0; j < i; j++) {
3226                                 td_pool_ptr2 = &info->td_pools[j];
3227                                 result = ddi_dma_unbind_handle(
3228                                     td_pool_ptr2->dma_handle);
3229                                 ASSERT(result == DDI_SUCCESS);
3230                                 ddi_dma_mem_free(&td_pool_ptr2->mem_handle);
3231                                 ddi_dma_free_handle(&td_pool_ptr2->dma_handle);
3232                         }
3233 
3234                         kmem_free(info->td_pools,
3235                             (sizeof (uhci_bulk_isoc_td_pool_t) *
3236                             info->num_pools));
3237 
3238                         return (USB_FAILURE);
3239                 }
3240 
3241                 bzero((void *)td_pool_ptr1->pool_addr,
3242                     num * sizeof (uhci_td_t));
3243                 td_pool_ptr1->num_tds = (ushort_t)num;
3244         }
3245 
3246         return (USB_SUCCESS);
3247 }
3248 
3249 
3250 /*
3251  * uhci_handle_bulk_td:
3252  *
3253  *      Handles the completed bulk transfer descriptors
3254  */
3255 void
3256 uhci_handle_bulk_td(uhci_state_t *uhcip, uhci_td_t *td)
3257 {
3258         uint_t                  num_bulk_tds, index, td_count, j;
3259         usb_cr_t                error;
3260         uint_t                  length, bytes_xfered;
3261         ushort_t                MaxPacketSize;
3262         uint32_t                buf_offs, paddr;
3263         uhci_td_t               *bulk_td_ptr, *current_dummy, *td_head;
3264         uhci_td_t               *tmp_td;
3265         queue_head_t            *qh, *next_qh;
3266         uhci_trans_wrapper_t    *tw = td->tw;
3267         uhci_pipe_private_t     *pp = tw->tw_pipe_private;
3268         uhci_bulk_isoc_xfer_t   *bulk_xfer_info;
3269         uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3270         usba_pipe_handle_data_t *ph;
3271 
3272         USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3273             "uhci_handle_bulk_td: td = 0x%p tw = 0x%p", (void *)td, (void *)tw);
3274 
3275         /*
3276          * Update the tw_bytes_pending, and tw_bytes_xfered
3277          */
3278         bytes_xfered = ZERO_LENGTH;
3279 
3280         /*
3281          * Check whether there are any errors occurred in the xfer.
3282          * If so, update the data_toggle for the queue head and
3283          * return error to the upper layer.
3284          */
3285         if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
3286                 uhci_handle_bulk_td_errors(uhcip, td);
3287 
3288                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3289                     "uhci_handle_bulk_td: error; data toggle: 0x%x",
3290                     pp->pp_data_toggle);
3291 
3292                 return;
3293         }
3294 
3295         /*
3296          * Update the tw_bytes_pending, and tw_bytes_xfered
3297          */
3298         bytes_xfered = GetTD_alen(uhcip, td);
3299         if (bytes_xfered != ZERO_LENGTH) {
3300                 tw->tw_bytes_pending -= (bytes_xfered + 1);
3301                 tw->tw_bytes_xfered  += (bytes_xfered + 1);
3302         }
3303 
3304         /*
3305          * Get Bulk pipe information and pipe handle
3306          */
3307         bulk_xfer_info  = pp->pp_qh->bulk_xfer_info;
3308         ph = tw->tw_pipe_private->pp_pipe_handle;
3309 
3310         /*
3311          * Check whether data underrun occurred.
3312          * If so, complete the transfer
3313          * Update the data toggle bit
3314          */
3315         if (bytes_xfered != GetTD_mlen(uhcip, td)) {
3316                 bulk_xfer_info->num_tds = 1;
3317                 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3318                     "uhci_handle_bulk_td: Data underrun occured");
3319 
3320                 pp->pp_data_toggle = GetTD_dtogg(uhcip, td) == 0 ? 1 : 0;
3321         }
3322 
3323         /*
3324          * If the TD's in the current frame are completed, then check
3325          * whether we have any more bytes to xfer. If so, insert TD's.
3326          * If no more bytes needs to be transferred, then do callback to the
3327          * upper layer.
3328          * If the TD's in the current frame are not completed, then
3329          * just delete the TD from the linked lists.
3330          */
3331         USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3332             "uhci_handle_bulk_td: completed TD data toggle: 0x%x",
3333             GetTD_dtogg(uhcip, td));
3334 
3335         if (--bulk_xfer_info->num_tds == 0) {
3336                 uhci_delete_td(uhcip, td);
3337 
3338                 if ((tw->tw_bytes_pending) &&
3339                     (GetTD_mlen(uhcip, td) - GetTD_alen(uhcip, td) == 0)) {
3340 
3341                         MaxPacketSize = pp->pp_pipe_handle->p_ep.wMaxPacketSize;
3342                         length = MaxPacketSize;
3343 
3344                         qh = pp->pp_qh;
3345                         paddr = GetQH32(uhcip, qh->link_ptr) & QH_LINK_PTR_MASK;
3346                         if (GetQH32(uhcip, qh->link_ptr) !=
3347                             GetQH32(uhcip,
3348                             uhcip->uhci_bulk_xfers_q_head->link_ptr)) {
3349                                 next_qh = QH_VADDR(paddr);
3350                                 SetQH32(uhcip, qh->prev_qh->link_ptr,
3351                                     paddr|(0x2));
3352                                 next_qh->prev_qh = qh->prev_qh;
3353                                 SetQH32(uhcip, qh->link_ptr,
3354                                     GetQH32(uhcip,
3355                                     uhcip->uhci_bulk_xfers_q_head->link_ptr));
3356                                 qh->prev_qh = uhcip->uhci_bulk_xfers_q_tail;
3357                                 SetQH32(uhcip,
3358                                     uhcip->uhci_bulk_xfers_q_tail->link_ptr,
3359                                     QH_PADDR(qh) | 0x2);
3360                                 uhcip->uhci_bulk_xfers_q_tail = qh;
3361                         }
3362 
3363                         if ((tw->tw_bytes_pending / MaxPacketSize) >=
3364                             MAX_NUM_BULK_TDS_PER_XFER) {
3365                                 num_bulk_tds = MAX_NUM_BULK_TDS_PER_XFER;
3366                         } else {
3367                                 num_bulk_tds =
3368                                     (tw->tw_bytes_pending / MaxPacketSize);
3369                                 if (tw->tw_bytes_pending % MaxPacketSize) {
3370                                         num_bulk_tds++;
3371                                         length = (tw->tw_bytes_pending %
3372                                             MaxPacketSize);
3373                                 }
3374                         }
3375 
3376                         current_dummy = pp->pp_qh->td_tailp;
3377                         td_pool_ptr = &bulk_xfer_info->td_pools[0];
3378                         bulk_td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
3379                         buf_offs = tw->tw_bytes_xfered;
3380                         td_count = num_bulk_tds;
3381                         index = 0;
3382 
3383                         /* reuse the TDs to transfer more data */
3384                         while (td_count > 0) {
3385                                 for (j = 0;
3386                                     (j < (td_pool_ptr->num_tds - 1)) &&
3387                                     (td_count > 1); j++, td_count--) {
3388                                         uhci_fill_in_bulk_isoc_td(uhcip,
3389                                             &bulk_td_ptr[j], &bulk_td_ptr[j+1],
3390                                             BULKTD_PADDR(td_pool_ptr,
3391                                             &bulk_td_ptr[j+1]), ph, buf_offs,
3392                                             MaxPacketSize, tw);
3393                                         buf_offs += MaxPacketSize;
3394                                 }
3395 
3396                                 if (td_count == 1) {
3397                                         uhci_fill_in_bulk_isoc_td(uhcip,
3398                                             &bulk_td_ptr[j], current_dummy,
3399                                             TD_PADDR(current_dummy), ph,
3400                                             buf_offs, length, tw);
3401 
3402                                         break;
3403                                 } else {
3404                                         tmp_td = &bulk_td_ptr[j];
3405                                         ASSERT(index <
3406                                             (bulk_xfer_info->num_pools - 1));
3407                                         td_pool_ptr = &bulk_xfer_info->
3408                                             td_pools[index + 1];
3409                                         bulk_td_ptr = (uhci_td_t *)
3410                                             td_pool_ptr->pool_addr;
3411                                         uhci_fill_in_bulk_isoc_td(uhcip,
3412                                             tmp_td, &bulk_td_ptr[0],
3413                                             BULKTD_PADDR(td_pool_ptr,
3414                                             &bulk_td_ptr[0]), ph, buf_offs,
3415                                             MaxPacketSize, tw);
3416                                         buf_offs += MaxPacketSize;
3417                                         td_count--;
3418                                         index++;
3419                                 }
3420                         }
3421 
3422                         pp->pp_qh->bulk_xfer_info = bulk_xfer_info;
3423                         bulk_xfer_info->num_tds      = (ushort_t)num_bulk_tds;
3424                         SetQH32(uhcip, pp->pp_qh->element_ptr,
3425                             bulk_xfer_info->td_pools[0].cookie.dmac_address);
3426                 } else {
3427                         usba_pipe_handle_data_t *usb_pp = pp->pp_pipe_handle;
3428 
3429                         pp->pp_qh->bulk_xfer_info = NULL;
3430 
3431                         if (tw->tw_bytes_pending) {
3432                                 /* Update the element pointer */
3433                                 SetQH32(uhcip, pp->pp_qh->element_ptr,
3434                                     TD_PADDR(pp->pp_qh->td_tailp));
3435 
3436                                 /* Remove all the tds */
3437                                 td_head = tw->tw_hctd_head;
3438                                 while (td_head != NULL) {
3439                                         uhci_delete_td(uhcip, td_head);
3440                                         td_head = tw->tw_hctd_head;
3441                                 }
3442                         }
3443 
3444                         if (tw->tw_direction == PID_IN) {
3445                                 usb_req_attrs_t attrs = ((usb_bulk_req_t *)
3446                                     tw->tw_curr_xfer_reqp)->bulk_attributes;
3447 
3448                                 error = USB_CR_OK;
3449 
3450                                 /* Data run occurred */
3451                                 if (tw->tw_bytes_pending &&
3452                                     (!(attrs & USB_ATTRS_SHORT_XFER_OK))) {
3453                                         error = USB_CR_DATA_UNDERRUN;
3454                                 }
3455 
3456                                 uhci_sendup_td_message(uhcip, error, tw);
3457                         } else {
3458                                 uhci_do_byte_stats(uhcip, tw->tw_length,
3459                                     usb_pp->p_ep.bmAttributes,
3460                                     usb_pp->p_ep.bEndpointAddress);
3461 
3462                                 /* Data underrun occurred */
3463                                 if (tw->tw_bytes_pending) {
3464 
3465                                         tw->tw_data->b_rptr +=
3466                                             tw->tw_bytes_xfered;
3467 
3468                                         USB_DPRINTF_L2(PRINT_MASK_ATTA,
3469                                             uhcip->uhci_log_hdl,
3470                                             "uhci_handle_bulk_td: "
3471                                             "data underrun occurred");
3472 
3473                                         uhci_hcdi_callback(uhcip, pp,
3474                                             tw->tw_pipe_private->pp_pipe_handle,
3475                                             tw, USB_CR_DATA_UNDERRUN);
3476                                 } else {
3477                                         uhci_hcdi_callback(uhcip, pp,
3478                                             tw->tw_pipe_private->pp_pipe_handle,
3479                                             tw, USB_CR_OK);
3480                                 }
3481                         } /* direction */
3482 
3483                         /* Deallocate DMA memory */
3484                         uhci_deallocate_tw(uhcip, pp, tw);
3485                         for (j = 0; j < bulk_xfer_info->num_pools; j++) {
3486                                 td_pool_ptr = &bulk_xfer_info->td_pools[j];
3487                                 (void) ddi_dma_unbind_handle(
3488                                     td_pool_ptr->dma_handle);
3489                                 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
3490                                 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
3491                         }
3492                         kmem_free(bulk_xfer_info->td_pools,
3493                             (sizeof (uhci_bulk_isoc_td_pool_t) *
3494                             bulk_xfer_info->num_pools));
3495                         kmem_free(bulk_xfer_info,
3496                             sizeof (uhci_bulk_isoc_xfer_t));
3497 
3498                         /*
3499                          * When there are no pending bulk commands, point the
3500                          * end of the lattice tree to NULL. This will make sure
3501                          * that the HC control does not loop anymore and PCI
3502                          * bus is not affected.
3503                          */
3504                         if (--uhcip->uhci_pending_bulk_cmds == 0) {
3505                                 uhcip->uhci_bulk_xfers_q_tail->link_ptr =
3506                                     HC_END_OF_LIST;
3507                                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
3508                                     uhcip->uhci_log_hdl,
3509                                     "uhci_handle_bulk_td: count = %d",
3510                                     uhcip->uhci_pending_bulk_cmds);
3511                         }
3512                 }
3513         } else {
3514                 uhci_delete_td(uhcip, td);
3515         }
3516 }
3517 
3518 
3519 void
3520 uhci_handle_bulk_td_errors(uhci_state_t *uhcip, uhci_td_t *td)
3521 {
3522         usb_cr_t                usb_err;
3523         uint32_t                paddr_tail, element_ptr, paddr;
3524         uhci_td_t               *next_td;
3525         uhci_pipe_private_t     *pp;
3526         uhci_trans_wrapper_t    *tw = td->tw;
3527         usba_pipe_handle_data_t *ph;
3528         uhci_bulk_isoc_td_pool_t *td_pool_ptr = NULL;
3529 
3530         USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3531             "uhci_handle_bulk_td_errors: td = %p", (void *)td);
3532 
3533 #ifdef  DEBUG
3534         uhci_print_td(uhcip, td);
3535 #endif
3536 
3537         tw = td->tw;
3538         ph = tw->tw_pipe_private->pp_pipe_handle;
3539         pp = (uhci_pipe_private_t *)ph->p_hcd_private;
3540 
3541         /*
3542          * Find the type of error occurred and return the error
3543          * to the upper layer. And adjust the data toggle.
3544          */
3545         element_ptr = GetQH32(uhcip, pp->pp_qh->element_ptr) &
3546             QH_ELEMENT_PTR_MASK;
3547         paddr_tail = TD_PADDR(pp->pp_qh->td_tailp);
3548 
3549         /*
3550          * If a timeout occurs before a transfer has completed,
3551          * the timeout handler sets the CRC/Timeout bit and clears the Active
3552          * bit in the link_ptr for each td in the transfer.
3553          * It then waits (at least) 1 ms so that any tds the controller might
3554          * have been executing will have completed.
3555          * So at this point element_ptr will point to either:
3556          * 1) the next td for the transfer (which has not been executed,
3557          * and has the CRC/Timeout status bit set and Active bit cleared),
3558          * 2) the dummy td for this qh.
3559          * So if the element_ptr does not point to the dummy td, we know
3560          * it points to the next td that would have been executed.
3561          * That td has the data toggle we want to save.
3562          * All outstanding tds have been marked as CRC/Timeout,
3563          * so it doesn't matter which td we pass to uhci_parse_td_error
3564          * for the error status.
3565          */
3566         if (element_ptr != paddr_tail) {
3567                 paddr = (element_ptr & QH_ELEMENT_PTR_MASK);
3568                 uhci_get_bulk_td_by_paddr(uhcip, pp->pp_qh->bulk_xfer_info,
3569                     paddr, &td_pool_ptr);
3570                 next_td = BULKTD_VADDR(td_pool_ptr, paddr);
3571                 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3572                     "uhci_handle_bulk_td_errors: next td = %p",
3573                     (void *)next_td);
3574 
3575                 usb_err = uhci_parse_td_error(uhcip, pp, next_td);
3576         } else {
3577                 usb_err = uhci_parse_td_error(uhcip, pp, td);
3578         }
3579 
3580         /*
3581          * Update the link pointer.
3582          */
3583         SetQH32(uhcip, pp->pp_qh->element_ptr, TD_PADDR(pp->pp_qh->td_tailp));
3584 
3585         /*
3586          * Send up number of bytes transferred before the error condition.
3587          */
3588         if ((tw->tw_direction == PID_OUT) && tw->tw_data) {
3589                 tw->tw_data->b_rptr += tw->tw_bytes_xfered;
3590         }
3591 
3592         uhci_remove_bulk_tds_tws(uhcip, tw->tw_pipe_private, UHCI_IN_ERROR);
3593 
3594         /*
3595          * When there  are no pending bulk commands, point the end of the
3596          * lattice tree to NULL. This will make sure that the  HC control
3597          * does not loop anymore and PCI bus is not affected.
3598          */
3599         if (--uhcip->uhci_pending_bulk_cmds == 0) {
3600                 uhcip->uhci_bulk_xfers_q_tail->link_ptr = HC_END_OF_LIST;
3601                 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
3602                     "uhci_handle_bulk_td_errors: count = %d",
3603                     uhcip->uhci_pending_bulk_cmds);
3604         }
3605 
3606         uhci_hcdi_callback(uhcip, pp, ph, tw, usb_err);
3607         uhci_deallocate_tw(uhcip, pp, tw);
3608 }
3609 
3610 
3611 /*
3612  * uhci_get_bulk_td_by_paddr:
3613  *      Obtain the address of the TD pool the physical address falls in.
3614  *
3615  * td_pool_pp - pointer to the address of the TD pool containing the paddr
3616  */
3617 /* ARGSUSED */
3618 static void
3619 uhci_get_bulk_td_by_paddr(
3620         uhci_state_t                    *uhcip,
3621         uhci_bulk_isoc_xfer_t           *info,
3622         uint32_t                        paddr,
3623         uhci_bulk_isoc_td_pool_t        **td_pool_pp)
3624 {
3625         uint_t                          i = 0;
3626 
3627         while (i < info->num_pools) {
3628                 *td_pool_pp = &info->td_pools[i];
3629                 if (((*td_pool_pp)->cookie.dmac_address <= paddr) &&
3630                     (((*td_pool_pp)->cookie.dmac_address +
3631                     (*td_pool_pp)->cookie.dmac_size) > paddr)) {
3632 
3633                         break;
3634                 }
3635                 i++;
3636         }
3637 
3638         ASSERT(i < info->num_pools);
3639 }
3640 
3641 
3642 void
3643 uhci_remove_bulk_tds_tws(
3644         uhci_state_t            *uhcip,
3645         uhci_pipe_private_t     *pp,
3646         int                     what)
3647 {
3648         uint_t                  rval, i;
3649         uhci_td_t               *head;
3650         uhci_td_t               *head_next;
3651         usb_opaque_t            curr_reqp;
3652         uhci_bulk_isoc_xfer_t   *info;
3653         uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3654 
3655         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3656 
3657         if ((info = pp->pp_qh->bulk_xfer_info) == NULL) {
3658 
3659                 return;
3660         }
3661 
3662         head = uhcip->uhci_outst_tds_head;
3663 
3664         while (head) {
3665                 uhci_trans_wrapper_t *tw_tmp = head->tw;
3666                 head_next = head->outst_td_next;
3667 
3668                 if (pp->pp_qh == tw_tmp->tw_pipe_private->pp_qh) {
3669                         curr_reqp = tw_tmp->tw_curr_xfer_reqp;
3670                         if (curr_reqp &&
3671                             ((what == UHCI_IN_CLOSE) ||
3672                             (what == UHCI_IN_RESET))) {
3673                                 uhci_hcdi_callback(uhcip, pp,
3674                                     pp->pp_pipe_handle,
3675                                     tw_tmp, USB_CR_FLUSHED);
3676                         } /* end of curr_reqp */
3677 
3678                         uhci_delete_td(uhcip, head);
3679 
3680                         if (what == UHCI_IN_CLOSE || what == UHCI_IN_RESET) {
3681                                 ASSERT(info->num_tds > 0);
3682                                 if (--info->num_tds == 0) {
3683                                         uhci_deallocate_tw(uhcip, pp, tw_tmp);
3684 
3685                                         /*
3686                                          * This will make sure that the HC
3687                                          * does not loop anymore when there
3688                                          * are no pending bulk commands.
3689                                          */
3690                                         if (--uhcip->uhci_pending_bulk_cmds
3691                                             == 0) {
3692                                                 uhcip->uhci_bulk_xfers_q_tail->
3693                                                     link_ptr = HC_END_OF_LIST;
3694                                                 USB_DPRINTF_L3(PRINT_MASK_ATTA,
3695                                                     uhcip->uhci_log_hdl,
3696                                                     "uhci_remove_bulk_tds_tws:"
3697                                                     " count = %d",
3698                                                     uhcip->
3699                                                     uhci_pending_bulk_cmds);
3700                                         }
3701                                 }
3702                         }
3703                 }
3704 
3705                 head = head_next;
3706         }
3707 
3708         if (what == UHCI_IN_CLOSE || what == UHCI_IN_RESET) {
3709                 ASSERT(info->num_tds == 0);
3710         }
3711 
3712         for (i = 0; i < info->num_pools; i++) {
3713                 td_pool_ptr = &info->td_pools[i];
3714                 rval = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
3715                 ASSERT(rval == DDI_SUCCESS);
3716                 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
3717                 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
3718         }
3719         kmem_free(info->td_pools, (sizeof (uhci_bulk_isoc_td_pool_t) *
3720             info->num_pools));
3721         kmem_free(info, sizeof (uhci_bulk_isoc_xfer_t));
3722         pp->pp_qh->bulk_xfer_info = NULL;
3723 }
3724 
3725 
3726 /*
3727  * uhci_save_data_toggle ()
3728  *      Save the data toggle in the usba_device structure
3729  */
3730 void
3731 uhci_save_data_toggle(uhci_pipe_private_t *pp)
3732 {
3733         usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
3734 
3735         /* Save the data toggle in the usb devices structure. */
3736         mutex_enter(&ph->p_mutex);
3737         usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
3738             pp->pp_data_toggle);
3739         mutex_exit(&ph->p_mutex);
3740 }
3741 
3742 /*
3743  * uhci_create_isoc_transfer_wrapper:
3744  *      Create a Transaction Wrapper (TW) for isoc transfer.
3745  *      This involves the allocating of DMA resources.
3746  *
3747  *      For isoc transfers, one isoc transfer includes multiple packets
3748  *      and each packet may have a different length. So each packet is
3749  *      transfered by one TD. We only know the individual packet length
3750  *      won't exceed 1023 bytes, but we don't know exactly the lengths.
3751  *      It is hard to make one physically discontiguous DMA buffer which
3752  *      can fit in all the TDs like what can be done to the ctrl/bulk/
3753  *      intr transfers. It is also undesirable to make one physically
3754  *      contiguous DMA buffer for all the packets, since this may easily
3755  *      fail when the system is in low memory. So an individual DMA
3756  *      buffer is allocated for an individual isoc packet and each DMA
3757  *      buffer is physically contiguous. An extra structure is allocated
3758  *      to save the multiple DMA handles.
3759  */
3760 static uhci_trans_wrapper_t *
3761 uhci_create_isoc_transfer_wrapper(
3762         uhci_state_t            *uhcip,
3763         uhci_pipe_private_t     *pp,
3764         usb_isoc_req_t          *req,
3765         size_t                  length,
3766         usb_flags_t             usb_flags)
3767 {
3768         int                     result;
3769         size_t                  real_length, strtlen, xfer_size;
3770         uhci_trans_wrapper_t    *tw;
3771         ddi_device_acc_attr_t   dev_attr;
3772         ddi_dma_attr_t          dma_attr;
3773         int                     kmem_flag;
3774         int                     (*dmamem_wait)(caddr_t);
3775         uint_t                  i, j, ccount;
3776         usb_isoc_req_t          *tmp_req = req;
3777 
3778         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3779 
3780         if (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep) != USB_EP_ATTR_ISOCH) {
3781 
3782                 return (NULL);
3783         }
3784 
3785         if ((req == NULL) && (UHCI_XFER_DIR(&pp->pp_pipe_handle->p_ep) ==
3786             USB_EP_DIR_IN)) {
3787                 tmp_req = (usb_isoc_req_t *)pp->pp_client_periodic_in_reqp;
3788         }
3789 
3790         if (tmp_req == NULL) {
3791 
3792                 return (NULL);
3793         }
3794 
3795 
3796         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3797             "uhci_create_isoc_transfer_wrapper: length = 0x%lx flags = 0x%x",
3798             length, usb_flags);
3799 
3800         /* SLEEP flag should not be used in interrupt context */
3801         if (servicing_interrupt()) {
3802                 kmem_flag = KM_NOSLEEP;
3803                 dmamem_wait = DDI_DMA_DONTWAIT;
3804         } else {
3805                 kmem_flag = KM_SLEEP;
3806                 dmamem_wait = DDI_DMA_SLEEP;
3807         }
3808 
3809         /* Allocate space for the transfer wrapper */
3810         if ((tw = kmem_zalloc(sizeof (uhci_trans_wrapper_t), kmem_flag)) ==
3811             NULL) {
3812                 USB_DPRINTF_L2(PRINT_MASK_LISTS,  uhcip->uhci_log_hdl,
3813                     "uhci_create_isoc_transfer_wrapper: kmem_alloc failed");
3814 
3815                 return (NULL);
3816         }
3817 
3818         /* Allocate space for the isoc buffer handles */
3819         strtlen = sizeof (uhci_isoc_buf_t) * tmp_req->isoc_pkts_count;
3820         if ((tw->tw_isoc_bufs = kmem_zalloc(strtlen, kmem_flag)) == NULL) {
3821                 USB_DPRINTF_L2(PRINT_MASK_LISTS,  uhcip->uhci_log_hdl,
3822                     "uhci_create_isoc_transfer_wrapper: kmem_alloc "
3823                     "isoc buffer failed");
3824                 kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3825 
3826                 return (NULL);
3827         }
3828 
3829         bcopy(&uhcip->uhci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
3830         dma_attr.dma_attr_sgllen = 1;
3831 
3832         dev_attr.devacc_attr_version            = DDI_DEVICE_ATTR_V0;
3833         dev_attr.devacc_attr_endian_flags       = DDI_STRUCTURE_LE_ACC;
3834         dev_attr.devacc_attr_dataorder          = DDI_STRICTORDER_ACC;
3835 
3836         /* Store the transfer length */
3837         tw->tw_length = length;
3838 
3839         for (i = 0; i < tmp_req->isoc_pkts_count; i++) {
3840                 tw->tw_isoc_bufs[i].index = (ushort_t)i;
3841 
3842                 /* Allocate the DMA handle */
3843                 if ((result = ddi_dma_alloc_handle(uhcip->uhci_dip, &dma_attr,
3844                     dmamem_wait, 0, &tw->tw_isoc_bufs[i].dma_handle)) !=
3845                     DDI_SUCCESS) {
3846                         USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3847                             "uhci_create_isoc_transfer_wrapper: "
3848                             "Alloc handle %d failed", i);
3849 
3850                         for (j = 0; j < i; j++) {
3851                                 result = ddi_dma_unbind_handle(
3852                                     tw->tw_isoc_bufs[j].dma_handle);
3853                                 ASSERT(result == USB_SUCCESS);
3854                                 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3855                                     mem_handle);
3856                                 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3857                                     dma_handle);
3858                         }
3859                         kmem_free(tw->tw_isoc_bufs, strtlen);
3860                         kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3861 
3862                         return (NULL);
3863                 }
3864 
3865                 /* Allocate the memory */
3866                 xfer_size = tmp_req->isoc_pkt_descr[i].isoc_pkt_length;
3867                 if ((result = ddi_dma_mem_alloc(tw->tw_isoc_bufs[i].dma_handle,
3868                     xfer_size, &dev_attr, DDI_DMA_CONSISTENT, dmamem_wait,
3869                     NULL, (caddr_t *)&tw->tw_isoc_bufs[i].buf_addr,
3870                     &real_length, &tw->tw_isoc_bufs[i].mem_handle)) !=
3871                     DDI_SUCCESS) {
3872                         USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3873                             "uhci_create_isoc_transfer_wrapper: "
3874                             "dma_mem_alloc %d fail", i);
3875                         ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
3876 
3877                         for (j = 0; j < i; j++) {
3878                                 result = ddi_dma_unbind_handle(
3879                                     tw->tw_isoc_bufs[j].dma_handle);
3880                                 ASSERT(result == USB_SUCCESS);
3881                                 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3882                                     mem_handle);
3883                                 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3884                                     dma_handle);
3885                         }
3886                         kmem_free(tw->tw_isoc_bufs, strtlen);
3887                         kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3888 
3889                         return (NULL);
3890                 }
3891 
3892                 ASSERT(real_length >= xfer_size);
3893 
3894                 /* Bind the handle */
3895                 result = ddi_dma_addr_bind_handle(
3896                     tw->tw_isoc_bufs[i].dma_handle, NULL,
3897                     (caddr_t)tw->tw_isoc_bufs[i].buf_addr, real_length,
3898                     DDI_DMA_RDWR|DDI_DMA_CONSISTENT, dmamem_wait, NULL,
3899                     &tw->tw_isoc_bufs[i].cookie, &ccount);
3900 
3901                 if ((result == DDI_DMA_MAPPED) && (ccount == 1)) {
3902                         tw->tw_isoc_bufs[i].length = xfer_size;
3903 
3904                         continue;
3905                 } else {
3906                         USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3907                             "uhci_create_isoc_transfer_wrapper: "
3908                             "Bind handle %d failed", i);
3909                         if (result == DDI_DMA_MAPPED) {
3910                                 result = ddi_dma_unbind_handle(
3911                                     tw->tw_isoc_bufs[i].dma_handle);
3912                                 ASSERT(result == USB_SUCCESS);
3913                         }
3914                         ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
3915                         ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
3916 
3917                         for (j = 0; j < i; j++) {
3918                                 result = ddi_dma_unbind_handle(
3919                                     tw->tw_isoc_bufs[j].dma_handle);
3920                                 ASSERT(result == USB_SUCCESS);
3921                                 ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
3922                                     mem_handle);
3923                                 ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
3924                                     dma_handle);
3925                         }
3926                         kmem_free(tw->tw_isoc_bufs, strtlen);
3927                         kmem_free(tw, sizeof (uhci_trans_wrapper_t));
3928 
3929                         return (NULL);
3930                 }
3931         }
3932 
3933         tw->tw_ncookies = tmp_req->isoc_pkts_count;
3934         tw->tw_isoc_strtlen = strtlen;
3935 
3936         /*
3937          * Only allow one wrapper to be added at a time. Insert the
3938          * new transaction wrapper into the list for this pipe.
3939          */
3940         if (pp->pp_tw_head == NULL) {
3941                 pp->pp_tw_head = tw;
3942                 pp->pp_tw_tail = tw;
3943         } else {
3944                 pp->pp_tw_tail->tw_next = tw;
3945                 pp->pp_tw_tail = tw;
3946                 ASSERT(tw->tw_next == NULL);
3947         }
3948 
3949         /* Store a back pointer to the pipe private structure */
3950         tw->tw_pipe_private = pp;
3951 
3952         /* Store the transfer type - synchronous or asynchronous */
3953         tw->tw_flags = usb_flags;
3954 
3955         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
3956             "uhci_create_isoc_transfer_wrapper: tw = 0x%p, ncookies = %u",
3957             (void *)tw, tw->tw_ncookies);
3958 
3959         return (tw);
3960 }
3961 
3962 /*
3963  * uhci_insert_isoc_td:
3964  *      - Create transfer wrapper
3965  *      - Allocate memory for the isoc td's
3966  *      - Fill up all the TD's and submit to the HC
3967  *      - Update all the linked lists
3968  */
3969 int
3970 uhci_insert_isoc_td(
3971         uhci_state_t            *uhcip,
3972         usba_pipe_handle_data_t *ph,
3973         usb_isoc_req_t          *isoc_req,
3974         size_t                  length,
3975         usb_flags_t             flags)
3976 {
3977         int                     rval = USB_SUCCESS;
3978         int                     error;
3979         uint_t                  ddic;
3980         uint32_t                i, j, index;
3981         uint32_t                bytes_to_xfer;
3982         uint32_t                expired_frames = 0;
3983         usb_frame_number_t      start_frame, end_frame, current_frame;
3984         uhci_td_t               *td_ptr;
3985         uhci_pipe_private_t     *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
3986         uhci_trans_wrapper_t    *tw;
3987         uhci_bulk_isoc_xfer_t   *isoc_xfer_info;
3988         uhci_bulk_isoc_td_pool_t *td_pool_ptr;
3989 
3990         USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
3991             "uhci_insert_isoc_td: ph = 0x%p isoc req = %p length = %lu",
3992             (void *)ph, (void *)isoc_req, length);
3993 
3994         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
3995 
3996         /* Allocate a transfer wrapper */
3997         if ((tw = uhci_create_isoc_transfer_wrapper(uhcip, pp, isoc_req,
3998             length, flags)) == NULL) {
3999                 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4000                     "uhci_insert_isoc_td: TW allocation failed");
4001 
4002                 return (USB_NO_RESOURCES);
4003         }
4004 
4005         /* Save current isochronous request pointer */
4006         tw->tw_curr_xfer_reqp = (usb_opaque_t)isoc_req;
4007 
4008         /*
4009          * Initialize the transfer wrapper. These values are useful
4010          * for sending back the reply.
4011          */
4012         tw->tw_handle_td             = uhci_handle_isoc_td;
4013         tw->tw_handle_callback_value = NULL;
4014         tw->tw_direction = (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) ?
4015             PID_OUT : PID_IN;
4016 
4017         /*
4018          * If the transfer isoc send, then copy the data from the request
4019          * to the transfer wrapper.
4020          */
4021         if ((tw->tw_direction == PID_OUT) && length) {
4022                 uchar_t *p;
4023 
4024                 ASSERT(isoc_req->isoc_data != NULL);
4025                 p = isoc_req->isoc_data->b_rptr;
4026 
4027                 /* Copy the data into the message */
4028                 for (i = 0; i < isoc_req->isoc_pkts_count; i++) {
4029                         ddi_rep_put8(tw->tw_isoc_bufs[i].mem_handle,
4030                             p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
4031                             isoc_req->isoc_pkt_descr[i].isoc_pkt_length,
4032                             DDI_DEV_AUTOINCR);
4033                         p += isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
4034                 }
4035         }
4036 
4037         if (tw->tw_direction == PID_IN) {
4038                 if ((rval = uhci_allocate_periodic_in_resource(uhcip, pp, tw,
4039                     flags)) != USB_SUCCESS) {
4040                         USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4041                             "uhci_insert_isoc_td: isoc_req_t alloc failed");
4042                         uhci_deallocate_tw(uhcip, pp, tw);
4043 
4044                         return (rval);
4045                 }
4046 
4047                 isoc_req = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
4048         }
4049 
4050         tw->tw_isoc_req      = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
4051 
4052         /* Get the pointer to the isoc_xfer_info structure */
4053         isoc_xfer_info = (uhci_bulk_isoc_xfer_t *)&tw->tw_xfer_info;
4054         isoc_xfer_info->num_tds = isoc_req->isoc_pkts_count;
4055 
4056         /*
4057          * Allocate memory for isoc tds
4058          */
4059         if ((rval = uhci_alloc_bulk_isoc_tds(uhcip, isoc_req->isoc_pkts_count,
4060             isoc_xfer_info)) != USB_SUCCESS) {
4061                 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4062                     "uhci_alloc_bulk_isoc_td: Memory allocation failure");
4063 
4064                 if (tw->tw_direction == PID_IN) {
4065                         uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
4066                 }
4067                 uhci_deallocate_tw(uhcip, pp, tw);
4068 
4069                 return (rval);
4070         }
4071 
4072         /*
4073          * Get the isoc td pool address, buffer address and
4074          * max packet size that the device supports.
4075          */
4076         td_pool_ptr = &isoc_xfer_info->td_pools[0];
4077         td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
4078         index = 0;
4079 
4080         /*
4081          * Fill up the isoc tds
4082          */
4083         USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4084             "uhci_insert_isoc_td : isoc pkts %d", isoc_req->isoc_pkts_count);
4085 
4086         for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4087                 for (j = 0; j < td_pool_ptr->num_tds; j++) {
4088                         bytes_to_xfer =
4089                             isoc_req->isoc_pkt_descr[index].isoc_pkt_length;
4090 
4091                         uhci_fill_in_bulk_isoc_td(uhcip, &td_ptr[j],
4092                             (uhci_td_t *)NULL, HC_END_OF_LIST, ph, index,
4093                             bytes_to_xfer, tw);
4094                         td_ptr[j].isoc_pkt_index = (ushort_t)index;
4095                         index++;
4096                 }
4097 
4098                 if (i < (isoc_xfer_info->num_pools - 1)) {
4099                         td_pool_ptr = &isoc_xfer_info->td_pools[i + 1];
4100                         td_ptr = (uhci_td_t *)td_pool_ptr->pool_addr;
4101                 }
4102         }
4103 
4104         /*
4105          * Get the starting frame number.
4106          * The client drivers sets the flag USB_ATTRS_ISOC_XFER_ASAP to inform
4107          * the HCD to care of starting frame number.
4108          *
4109          * Following code is very time critical. So, perform atomic execution.
4110          */
4111         ddic = ddi_enter_critical();
4112         current_frame = uhci_get_sw_frame_number(uhcip);
4113 
4114         if (isoc_req->isoc_attributes & USB_ATTRS_ISOC_START_FRAME) {
4115                 start_frame = isoc_req->isoc_frame_no;
4116                 end_frame = start_frame + isoc_req->isoc_pkts_count;
4117 
4118                 /* Check available frames */
4119                 if ((end_frame - current_frame) < UHCI_MAX_ISOC_FRAMES) {
4120                         if (current_frame > start_frame) {
4121                                 if ((current_frame + FRNUM_OFFSET) <
4122                                     end_frame) {
4123                                         expired_frames = current_frame +
4124                                             FRNUM_OFFSET - start_frame;
4125                                         start_frame = current_frame +
4126                                             FRNUM_OFFSET;
4127                                 } else {
4128                                         rval = USB_INVALID_START_FRAME;
4129                                 }
4130                         }
4131                 } else {
4132                         rval = USB_INVALID_START_FRAME;
4133                 }
4134 
4135         } else if (isoc_req->isoc_attributes & USB_ATTRS_ISOC_XFER_ASAP) {
4136                 start_frame = pp->pp_frame_num;
4137 
4138                 if (start_frame == INVALID_FRNUM) {
4139                         start_frame = current_frame + FRNUM_OFFSET;
4140                 } else if (current_frame > start_frame) {
4141                         start_frame = current_frame + FRNUM_OFFSET;
4142                 }
4143 
4144                 end_frame = start_frame + isoc_req->isoc_pkts_count;
4145                 isoc_req->isoc_frame_no = start_frame;
4146 
4147         }
4148 
4149         if (rval != USB_SUCCESS) {
4150 
4151                 /* Exit the critical */
4152                 ddi_exit_critical(ddic);
4153 
4154                 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4155                     "uhci_insert_isoc_td: Invalid starting frame number");
4156 
4157                 if (tw->tw_direction == PID_IN) {
4158                         uhci_deallocate_periodic_in_resource(uhcip, pp, tw);
4159                 }
4160 
4161                 while (tw->tw_hctd_head) {
4162                         uhci_delete_td(uhcip, tw->tw_hctd_head);
4163                 }
4164 
4165                 for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4166                         td_pool_ptr = &isoc_xfer_info->td_pools[i];
4167                         error = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
4168                         ASSERT(error == DDI_SUCCESS);
4169                         ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4170                         ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4171                 }
4172                 kmem_free(isoc_xfer_info->td_pools,
4173                     (sizeof (uhci_bulk_isoc_td_pool_t) *
4174                     isoc_xfer_info->num_pools));
4175 
4176                 uhci_deallocate_tw(uhcip, pp, tw);
4177 
4178                 return (rval);
4179         }
4180 
4181         for (i = 0; i < expired_frames; i++) {
4182                 isoc_req->isoc_pkt_descr[i].isoc_pkt_status =
4183                     USB_CR_NOT_ACCESSED;
4184                 isoc_req->isoc_pkt_descr[i].isoc_pkt_actual_length =
4185                     isoc_req->isoc_pkt_descr[i].isoc_pkt_length;
4186                 uhci_get_isoc_td_by_index(uhcip, isoc_xfer_info, i,
4187                     &td_ptr, &td_pool_ptr);
4188                 uhci_delete_td(uhcip, td_ptr);
4189                 --isoc_xfer_info->num_tds;
4190         }
4191 
4192         /*
4193          * Add the TD's to the HC list
4194          */
4195         start_frame = (start_frame & 0x3ff);
4196         for (; i < isoc_req->isoc_pkts_count; i++) {
4197                 uhci_get_isoc_td_by_index(uhcip, isoc_xfer_info, i,
4198                     &td_ptr, &td_pool_ptr);
4199                 if (uhcip->uhci_isoc_q_tailp[start_frame]) {
4200                         td_ptr->isoc_prev =
4201                             uhcip->uhci_isoc_q_tailp[start_frame];
4202                         td_ptr->isoc_next = NULL;
4203                         td_ptr->link_ptr =
4204                             uhcip->uhci_isoc_q_tailp[start_frame]->link_ptr;
4205                         uhcip->uhci_isoc_q_tailp[start_frame]->isoc_next =
4206                             td_ptr;
4207                         SetTD32(uhcip,
4208                             uhcip->uhci_isoc_q_tailp[start_frame]->link_ptr,
4209                             ISOCTD_PADDR(td_pool_ptr, td_ptr));
4210                         uhcip->uhci_isoc_q_tailp[start_frame] = td_ptr;
4211                 } else {
4212                         uhcip->uhci_isoc_q_tailp[start_frame] = td_ptr;
4213                         td_ptr->isoc_next = NULL;
4214                         td_ptr->isoc_prev = NULL;
4215                         SetTD32(uhcip, td_ptr->link_ptr,
4216                             GetFL32(uhcip,
4217                             uhcip->uhci_frame_lst_tablep[start_frame]));
4218                         SetFL32(uhcip,
4219                             uhcip->uhci_frame_lst_tablep[start_frame],
4220                             ISOCTD_PADDR(td_pool_ptr, td_ptr));
4221                 }
4222                 td_ptr->starting_frame = (uint_t)start_frame;
4223 
4224                 if (++start_frame == NUM_FRAME_LST_ENTRIES)
4225                         start_frame = 0;
4226         }
4227 
4228         ddi_exit_critical(ddic);
4229         pp->pp_frame_num = end_frame;
4230 
4231         USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4232             "uhci_insert_isoc_td: current frame number 0x%llx, pipe frame num"
4233             " 0x%llx", (unsigned long long)current_frame,
4234             (unsigned long long)(pp->pp_frame_num));
4235 
4236         return (rval);
4237 }
4238 
4239 
4240 /*
4241  * uhci_get_isoc_td_by_index:
4242  *      Obtain the addresses of the TD pool and the TD at the index.
4243  *
4244  * tdpp - pointer to the address of the TD at the isoc packet index
4245  * td_pool_pp - pointer to the address of the TD pool containing
4246  *              the specified TD
4247  */
4248 /* ARGSUSED */
4249 static void
4250 uhci_get_isoc_td_by_index(
4251         uhci_state_t                    *uhcip,
4252         uhci_bulk_isoc_xfer_t           *info,
4253         uint_t                          index,
4254         uhci_td_t                       **tdpp,
4255         uhci_bulk_isoc_td_pool_t        **td_pool_pp)
4256 {
4257         uint_t                  i = 0, j = 0;
4258         uhci_td_t               *td_ptr;
4259 
4260         while (j < info->num_pools) {
4261                 if ((i + info->td_pools[j].num_tds) <= index) {
4262                         i += info->td_pools[j].num_tds;
4263                         j++;
4264                 } else {
4265                         i = index - i;
4266 
4267                         break;
4268                 }
4269         }
4270 
4271         ASSERT(j < info->num_pools);
4272         *td_pool_pp = &info->td_pools[j];
4273         td_ptr = (uhci_td_t *)((*td_pool_pp)->pool_addr);
4274         *tdpp = &td_ptr[i];
4275 }
4276 
4277 
4278 /*
4279  * uhci_handle_isoc_td:
4280  *      Handles the completed isoc tds
4281  */
4282 void
4283 uhci_handle_isoc_td(uhci_state_t *uhcip, uhci_td_t *td)
4284 {
4285         uint_t                  rval, i;
4286         uint32_t                pkt_index = td->isoc_pkt_index;
4287         usb_cr_t                cr;
4288         uhci_trans_wrapper_t    *tw = td->tw;
4289         usb_isoc_req_t          *isoc_req = (usb_isoc_req_t *)tw->tw_isoc_req;
4290         uhci_pipe_private_t     *pp = tw->tw_pipe_private;
4291         uhci_bulk_isoc_xfer_t   *isoc_xfer_info = &tw->tw_xfer_info;
4292         usba_pipe_handle_data_t *usb_pp;
4293         uhci_bulk_isoc_td_pool_t *td_pool_ptr;
4294 
4295         USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4296             "uhci_handle_isoc_td: td = 0x%p, pp = 0x%p, tw = 0x%p, req = 0x%p, "
4297             "index = %x", (void *)td, (void *)pp, (void *)tw, (void *)isoc_req,
4298             pkt_index);
4299 
4300         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4301 
4302         usb_pp = pp->pp_pipe_handle;
4303 
4304         /*
4305          * Check whether there are any errors occurred. If so, update error
4306          * count and return it to the upper.But never return a non zero
4307          * completion reason.
4308          */
4309         cr = USB_CR_OK;
4310         if (GetTD_status(uhcip, td) & TD_STATUS_MASK) {
4311                 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4312                     "uhci_handle_isoc_td: Error Occurred: TD Status = %x",
4313                     GetTD_status(uhcip, td));
4314                 isoc_req->isoc_error_count++;
4315         }
4316 
4317         if (isoc_req != NULL) {
4318                 isoc_req->isoc_pkt_descr[pkt_index].isoc_pkt_status = cr;
4319                 isoc_req->isoc_pkt_descr[pkt_index].isoc_pkt_actual_length =
4320                     (GetTD_alen(uhcip, td) == ZERO_LENGTH) ? 0 :
4321                     GetTD_alen(uhcip, td) + 1;
4322         }
4323 
4324         uhci_delete_isoc_td(uhcip, td);
4325 
4326         if (--isoc_xfer_info->num_tds != 0) {
4327                 USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4328                     "uhci_handle_isoc_td: Number of TDs %d",
4329                     isoc_xfer_info->num_tds);
4330 
4331                 return;
4332         }
4333 
4334         tw->tw_claim = UHCI_INTR_HDLR_CLAIMED;
4335         if (tw->tw_direction == PID_IN) {
4336                 uhci_sendup_td_message(uhcip, cr, tw);
4337 
4338                 if ((uhci_handle_isoc_receive(uhcip, pp, tw)) != USB_SUCCESS) {
4339                         USB_DPRINTF_L3(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4340                             "uhci_handle_isoc_td: Drop message");
4341                 }
4342 
4343         } else {
4344                 /* update kstats only for OUT. sendup_td_msg() does it for IN */
4345                 uhci_do_byte_stats(uhcip, tw->tw_length,
4346                     usb_pp->p_ep.bmAttributes, usb_pp->p_ep.bEndpointAddress);
4347 
4348                 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, USB_CR_OK);
4349         }
4350 
4351         for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4352                 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4353                 rval = ddi_dma_unbind_handle(td_pool_ptr->dma_handle);
4354                 ASSERT(rval == DDI_SUCCESS);
4355                 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4356                 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4357         }
4358         kmem_free(isoc_xfer_info->td_pools,
4359             (sizeof (uhci_bulk_isoc_td_pool_t) *
4360             isoc_xfer_info->num_pools));
4361         uhci_deallocate_tw(uhcip, pp, tw);
4362 }
4363 
4364 
4365 /*
4366  * uhci_handle_isoc_receive:
4367  *      - Sends the isoc data to the client
4368  *      - Inserts another isoc receive request
4369  */
4370 static int
4371 uhci_handle_isoc_receive(
4372         uhci_state_t            *uhcip,
4373         uhci_pipe_private_t     *pp,
4374         uhci_trans_wrapper_t    *tw)
4375 {
4376         USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4377             "uhci_handle_isoc_receive: tw = 0x%p", (void *)tw);
4378 
4379         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4380 
4381         /*
4382          * -- check for pipe state being polling before
4383          * inserting a new request. Check when is TD
4384          * de-allocation being done? (so we can reuse the same TD)
4385          */
4386         if (uhci_start_isoc_receive_polling(uhcip,
4387             pp->pp_pipe_handle, (usb_isoc_req_t *)tw->tw_curr_xfer_reqp,
4388             0) != USB_SUCCESS) {
4389                 USB_DPRINTF_L2(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4390                     "uhci_handle_isoc_receive: receive polling failed");
4391 
4392                 return (USB_FAILURE);
4393         }
4394 
4395         return (USB_SUCCESS);
4396 }
4397 
4398 
4399 /*
4400  * uhci_delete_isoc_td:
4401  *      - Delete from the outstanding command queue
4402  *      - Delete from the tw queue
4403  *      - Delete from the isoc queue
4404  *      - Delete from the HOST CONTROLLER list
4405  */
4406 static void
4407 uhci_delete_isoc_td(uhci_state_t *uhcip, uhci_td_t *td)
4408 {
4409         uint32_t        starting_frame = td->starting_frame;
4410 
4411         if ((td->isoc_next == NULL) && (td->isoc_prev == NULL)) {
4412                 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[starting_frame],
4413                     GetTD32(uhcip, td->link_ptr));
4414                 uhcip->uhci_isoc_q_tailp[starting_frame] = 0;
4415         } else if (td->isoc_next == NULL) {
4416                 td->isoc_prev->link_ptr = td->link_ptr;
4417                 td->isoc_prev->isoc_next = NULL;
4418                 uhcip->uhci_isoc_q_tailp[starting_frame] = td->isoc_prev;
4419         } else if (td->isoc_prev == NULL) {
4420                 td->isoc_next->isoc_prev = NULL;
4421                 SetFL32(uhcip, uhcip->uhci_frame_lst_tablep[starting_frame],
4422                     GetTD32(uhcip, td->link_ptr));
4423         } else {
4424                 td->isoc_prev->isoc_next = td->isoc_next;
4425                 td->isoc_next->isoc_prev = td->isoc_prev;
4426                 td->isoc_prev->link_ptr = td->link_ptr;
4427         }
4428 
4429         uhci_delete_td(uhcip, td);
4430 }
4431 
4432 
4433 /*
4434  * uhci_send_isoc_receive
4435  *      - Allocates usb_isoc_request
4436  *      - Updates the isoc request
4437  *      - Inserts the isoc td's into the HC processing list.
4438  */
4439 int
4440 uhci_start_isoc_receive_polling(
4441         uhci_state_t            *uhcip,
4442         usba_pipe_handle_data_t *ph,
4443         usb_isoc_req_t          *isoc_req,
4444         usb_flags_t             usb_flags)
4445 {
4446         int                     ii, error;
4447         size_t                  max_isoc_xfer_size, length, isoc_pkts_length;
4448         ushort_t                isoc_pkt_count;
4449         uhci_pipe_private_t     *pp = (uhci_pipe_private_t *)ph->p_hcd_private;
4450         usb_isoc_pkt_descr_t    *isoc_pkt_descr;
4451 
4452         USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4453             "uhci_start_isoc_receive_polling: usb_flags = %x", usb_flags);
4454 
4455         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4456 
4457         max_isoc_xfer_size = ph->p_ep.wMaxPacketSize * UHCI_MAX_ISOC_PKTS;
4458 
4459         if (isoc_req) {
4460                 isoc_pkt_descr = isoc_req->isoc_pkt_descr;
4461                 isoc_pkt_count = isoc_req->isoc_pkts_count;
4462                 isoc_pkts_length = isoc_req->isoc_pkts_length;
4463         } else {
4464                 isoc_pkt_descr = ((usb_isoc_req_t *)
4465                     pp->pp_client_periodic_in_reqp)->isoc_pkt_descr;
4466                 isoc_pkt_count = ((usb_isoc_req_t *)
4467                     pp->pp_client_periodic_in_reqp)->isoc_pkts_count;
4468                 isoc_pkts_length = ((usb_isoc_req_t *)
4469                     pp->pp_client_periodic_in_reqp)->isoc_pkts_length;
4470         }
4471 
4472         for (ii = 0, length = 0; ii < isoc_pkt_count; ii++) {
4473                 length += isoc_pkt_descr->isoc_pkt_length;
4474                 isoc_pkt_descr++;
4475         }
4476 
4477         if ((isoc_pkts_length) && (isoc_pkts_length != length)) {
4478 
4479                 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4480                     "uhci_start_isoc_receive_polling: isoc_pkts_length 0x%lx "
4481                     "is not equal to the sum of all pkt lengths 0x%lx in "
4482                     "an isoc request", isoc_pkts_length, length);
4483 
4484                 return (USB_FAILURE);
4485         }
4486 
4487         /* Check the size of isochronous request */
4488         if (length > max_isoc_xfer_size) {
4489                 USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4490                     "uhci_start_isoc_receive_polling: "
4491                     "Max isoc request size = %lx, Given isoc req size = %lx",
4492                     max_isoc_xfer_size, length);
4493 
4494                 return (USB_FAILURE);
4495         }
4496 
4497         /* Add the TD into the Host Controller's isoc list */
4498         error = uhci_insert_isoc_td(uhcip, ph, isoc_req, length, usb_flags);
4499 
4500         return (error);
4501 }
4502 
4503 
4504 /*
4505  * uhci_remove_isoc_tds_tws
4506  *      This routine scans the pipe and removes all the td's
4507  *      and transfer wrappers and deallocates the memory
4508  *      associated with those td's and tw's.
4509  */
4510 void
4511 uhci_remove_isoc_tds_tws(uhci_state_t *uhcip, uhci_pipe_private_t *pp)
4512 {
4513         uint_t                  rval, i;
4514         uhci_td_t               *tmp_td, *td_head;
4515         usb_isoc_req_t          *isoc_req;
4516         uhci_trans_wrapper_t    *tmp_tw, *tw_head;
4517         uhci_bulk_isoc_xfer_t   *isoc_xfer_info;
4518         uhci_bulk_isoc_td_pool_t *td_pool_ptr;
4519 
4520         USB_DPRINTF_L4(PRINT_MASK_ISOC, uhcip->uhci_log_hdl,
4521             "uhci_remove_isoc_tds_tws: pp = %p", (void *)pp);
4522 
4523         tw_head = pp->pp_tw_head;
4524         while (tw_head) {
4525                 tmp_tw = tw_head;
4526                 tw_head = tw_head->tw_next;
4527                 td_head = tmp_tw->tw_hctd_head;
4528                 if (tmp_tw->tw_direction == PID_IN) {
4529                         uhci_deallocate_periodic_in_resource(uhcip, pp,
4530                             tmp_tw);
4531                 } else if (tmp_tw->tw_direction == PID_OUT) {
4532                         uhci_hcdi_callback(uhcip, pp, pp->pp_pipe_handle,
4533                             tmp_tw, USB_CR_FLUSHED);
4534                 }
4535 
4536                 while (td_head) {
4537                         tmp_td = td_head;
4538                         td_head = td_head->tw_td_next;
4539                         uhci_delete_isoc_td(uhcip, tmp_td);
4540                 }
4541 
4542                 isoc_req = (usb_isoc_req_t *)tmp_tw->tw_isoc_req;
4543                 if (isoc_req) {
4544                         usb_free_isoc_req(isoc_req);
4545                 }
4546 
4547                 ASSERT(tmp_tw->tw_hctd_head == NULL);
4548 
4549                 if (tmp_tw->tw_xfer_info.td_pools) {
4550                         isoc_xfer_info =
4551                             (uhci_bulk_isoc_xfer_t *)&tmp_tw->tw_xfer_info;
4552                         for (i = 0; i < isoc_xfer_info->num_pools; i++) {
4553                                 td_pool_ptr = &isoc_xfer_info->td_pools[i];
4554                                 rval = ddi_dma_unbind_handle(
4555                                     td_pool_ptr->dma_handle);
4556                                 ASSERT(rval == DDI_SUCCESS);
4557                                 ddi_dma_mem_free(&td_pool_ptr->mem_handle);
4558                                 ddi_dma_free_handle(&td_pool_ptr->dma_handle);
4559                         }
4560                         kmem_free(isoc_xfer_info->td_pools,
4561                             (sizeof (uhci_bulk_isoc_td_pool_t) *
4562                             isoc_xfer_info->num_pools));
4563                 }
4564 
4565                 uhci_deallocate_tw(uhcip, pp, tmp_tw);
4566         }
4567 }
4568 
4569 
4570 /*
4571  * uhci_isoc_update_sw_frame_number()
4572  *      to avoid code duplication, call uhci_get_sw_frame_number()
4573  */
4574 void
4575 uhci_isoc_update_sw_frame_number(uhci_state_t *uhcip)
4576 {
4577         (void) uhci_get_sw_frame_number(uhcip);
4578 }
4579 
4580 
4581 /*
4582  * uhci_get_sw_frame_number:
4583  *      Hold the uhci_int_mutex before calling this routine.
4584  */
4585 uint64_t
4586 uhci_get_sw_frame_number(uhci_state_t *uhcip)
4587 {
4588         uint64_t sw_frnum, hw_frnum, current_frnum;
4589 
4590         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4591 
4592         sw_frnum = uhcip->uhci_sw_frnum;
4593         hw_frnum = Get_OpReg16(FRNUM);
4594 
4595         /*
4596          * Check bit 10 in the software counter and hardware frame counter.
4597          * If both are same, then don't increment the software frame counter
4598          * (Bit 10 of hw frame counter toggle for every 1024 frames)
4599          * The lower 11 bits of software counter contains the hardware frame
4600          * counter value. The MSB (bit 10) of software counter is incremented
4601          * for every 1024 frames either here or in get frame number routine.
4602          */
4603         if ((sw_frnum & UHCI_BIT_10_MASK) == (hw_frnum & UHCI_BIT_10_MASK)) {
4604                 /* The MSB of hw counter did not toggle */
4605                 current_frnum = ((sw_frnum & (SW_FRNUM_MASK)) | hw_frnum);
4606         } else {
4607                 /*
4608                  * The hw counter wrapped around. And the interrupt handler
4609                  * did not get a chance to update the sw frame counter.
4610                  * So, update the sw frame counter and return correct frame no.
4611                  */
4612                 sw_frnum >>= UHCI_SIZE_OF_HW_FRNUM - 1;
4613                 current_frnum =
4614                     ((++sw_frnum << (UHCI_SIZE_OF_HW_FRNUM - 1)) | hw_frnum);
4615         }
4616         uhcip->uhci_sw_frnum = current_frnum;
4617 
4618         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4619             "uhci_get_sw_frame_number: sw=%lld hd=%lld",
4620             (unsigned long long)(uhcip->uhci_sw_frnum),
4621             (unsigned long long)hw_frnum);
4622 
4623         return (current_frnum);
4624 }
4625 
4626 
4627 /*
4628  * uhci_cmd_timeout_hdlr:
4629  *      This routine will get called for every second. It checks for
4630  *      timed out control commands/bulk commands. Timeout any commands
4631  *      that exceeds the time out period specified by the pipe policy.
4632  */
4633 void
4634 uhci_cmd_timeout_hdlr(void *arg)
4635 {
4636         uint_t                  flag = B_FALSE;
4637         uhci_td_t               *head, *tmp_td;
4638         uhci_state_t            *uhcip = (uhci_state_t *)arg;
4639         uhci_pipe_private_t     *pp;
4640 
4641         /*
4642          * Check whether any of the control xfers are timed out.
4643          * If so, complete those commands with time out as reason.
4644          */
4645         mutex_enter(&uhcip->uhci_int_mutex);
4646         head = uhcip->uhci_outst_tds_head;
4647 
4648         while (head) {
4649                 /*
4650                  * If timeout out is zero, then dont timeout command.
4651                  */
4652                 if (head->tw->tw_timeout_cnt == 0)  {
4653                         head = head->outst_td_next;
4654                         continue;
4655                 }
4656 
4657                 if (!(head->tw->tw_flags & TW_TIMEOUT_FLAG)) {
4658                         head->tw->tw_flags |= TW_TIMEOUT_FLAG;
4659                         --head->tw->tw_timeout_cnt;
4660                 }
4661 
4662                 /* only do it for bulk and control TDs */
4663                 if ((head->tw->tw_timeout_cnt == 0) &&
4664                     (head->tw->tw_handle_td != uhci_handle_isoc_td)) {
4665 
4666                         USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl,
4667                             "Command timed out: td = %p", (void *)head);
4668 
4669                         head->tw->tw_claim = UHCI_TIMEOUT_HDLR_CLAIMED;
4670 
4671                         /*
4672                          * Check finally whether the command completed
4673                          */
4674                         if (GetTD_status(uhcip, head) & UHCI_TD_ACTIVE) {
4675                                 SetTD32(uhcip, head->link_ptr,
4676                                     GetTD32(uhcip, head->link_ptr) |
4677                                     HC_END_OF_LIST);
4678                                 pp = head->tw->tw_pipe_private;
4679                                 SetQH32(uhcip, pp->pp_qh->element_ptr,
4680                                     GetQH32(uhcip, pp->pp_qh->element_ptr) |
4681                                     HC_END_OF_LIST);
4682                         }
4683 
4684                         flag = B_TRUE;
4685                 }
4686 
4687                 head = head->outst_td_next;
4688         }
4689 
4690         if (flag) {
4691                 (void) uhci_wait_for_sof(uhcip);
4692         }
4693 
4694         head = uhcip->uhci_outst_tds_head;
4695         while (head) {
4696                 if (head->tw->tw_flags & TW_TIMEOUT_FLAG) {
4697                         head->tw->tw_flags &= ~TW_TIMEOUT_FLAG;
4698                 }
4699                 if (head->tw->tw_claim == UHCI_TIMEOUT_HDLR_CLAIMED) {
4700                         head->tw->tw_claim = UHCI_NOT_CLAIMED;
4701                         tmp_td = head->tw->tw_hctd_head;
4702                         while (tmp_td) {
4703                                 SetTD_status(uhcip, tmp_td,
4704                                     UHCI_TD_CRC_TIMEOUT);
4705                                 tmp_td = tmp_td->tw_td_next;
4706                         }
4707                 }
4708                 head = head->outst_td_next;
4709         }
4710 
4711         /*
4712          * Process the td which was completed before shifting from normal
4713          * mode to polled mode
4714          */
4715         if (uhcip->uhci_polled_flag == UHCI_POLLED_FLAG_TRUE) {
4716                 uhci_process_submitted_td_queue(uhcip);
4717                 uhcip->uhci_polled_flag = UHCI_POLLED_FLAG_FALSE;
4718         } else if (flag) {
4719                 /* Process the completed/timed out commands */
4720                 uhci_process_submitted_td_queue(uhcip);
4721         }
4722 
4723         /* Re-register the control/bulk/intr commands' timeout handler */
4724         if (uhcip->uhci_cmd_timeout_id) {
4725                 uhcip->uhci_cmd_timeout_id = timeout(uhci_cmd_timeout_hdlr,
4726                     (void *)uhcip, UHCI_ONE_SECOND);
4727         }
4728 
4729         mutex_exit(&uhcip->uhci_int_mutex);
4730 }
4731 
4732 
4733 /*
4734  * uhci_wait_for_sof:
4735  *      Wait for the start of the next frame (implying any changes made in the
4736  *      lattice have now taken effect).
4737  *      To be sure this is the case, we wait for the completion of the current
4738  *      frame (which might have already been pending), then another complete
4739  *      frame to ensure everything has taken effect.
4740  */
4741 int
4742 uhci_wait_for_sof(uhci_state_t *uhcip)
4743 {
4744         int     n, error;
4745         ushort_t    cmd_reg;
4746         usb_frame_number_t      before_frame_number, after_frame_number;
4747         clock_t rval;
4748         USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl,
4749             "uhci_wait_for_sof: uhcip = %p", (void *)uhcip);
4750 
4751         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4752 
4753         error = uhci_state_is_operational(uhcip);
4754 
4755         if (error != USB_SUCCESS) {
4756 
4757                 return (error);
4758         }
4759 
4760         before_frame_number =  uhci_get_sw_frame_number(uhcip);
4761         for (n = 0; n < MAX_SOF_WAIT_COUNT; n++) {
4762                 SetTD_ioc(uhcip, uhcip->uhci_sof_td, 1);
4763                 uhcip->uhci_cv_signal = B_TRUE;
4764 
4765                 rval = cv_reltimedwait(&uhcip->uhci_cv_SOF,
4766                     &uhcip->uhci_int_mutex, UHCI_ONE_SECOND, TR_CLOCK_TICK);
4767 
4768                 after_frame_number = uhci_get_sw_frame_number(uhcip);
4769                 if ((rval == -1) &&
4770                     (after_frame_number <= before_frame_number)) {
4771                         cmd_reg = Get_OpReg16(USBCMD);
4772                         Set_OpReg16(USBCMD, (cmd_reg | USBCMD_REG_HC_RUN));
4773                         Set_OpReg16(USBINTR, ENABLE_ALL_INTRS);
4774                         after_frame_number = uhci_get_sw_frame_number(uhcip);
4775                 }
4776                 before_frame_number = after_frame_number;
4777         }
4778 
4779         SetTD_ioc(uhcip, uhcip->uhci_sof_td, 0);
4780 
4781         return (uhcip->uhci_cv_signal ? USB_FAILURE : USB_SUCCESS);
4782 
4783 }
4784 
4785 /*
4786  * uhci_allocate_periodic_in_resource:
4787  *      Allocate interrupt/isochronous request structure for the
4788  *      interrupt/isochronous IN transfer.
4789  */
4790 int
4791 uhci_allocate_periodic_in_resource(
4792         uhci_state_t            *uhcip,
4793         uhci_pipe_private_t     *pp,
4794         uhci_trans_wrapper_t    *tw,
4795         usb_flags_t             flags)
4796 {
4797         size_t                  length = 0;
4798         usb_opaque_t            client_periodic_in_reqp;
4799         usb_intr_req_t          *cur_intr_req;
4800         usb_isoc_req_t          *curr_isoc_reqp;
4801         usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
4802 
4803         USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4804             "uhci_allocate_periodic_in_resource:\n\t"
4805             "ph = 0x%p, pp = 0x%p, tw = 0x%p, flags = 0x%x",
4806             (void *)ph, (void *)pp, (void *)tw, flags);
4807 
4808         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4809 
4810         /* Check the current periodic in request pointer */
4811         if (tw->tw_curr_xfer_reqp) {
4812                 USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4813                     "uhci_allocate_periodic_in_resource: Interrupt "
4814                     "request structure already exists: "
4815                     "allocation failed");
4816 
4817                 return (USB_SUCCESS);
4818         }
4819 
4820         /* Get the client periodic in request pointer */
4821         client_periodic_in_reqp = pp->pp_client_periodic_in_reqp;
4822 
4823         /*
4824          * If it a periodic IN request and periodic request is NULL,
4825          * allocate corresponding usb periodic IN request for the
4826          * current periodic polling request and copy the information
4827          * from the saved periodic request structure.
4828          */
4829         if (UHCI_XFER_TYPE(&ph->p_ep) == USB_EP_ATTR_INTR) {
4830                 /* Get the interrupt transfer length */
4831                 length = ((usb_intr_req_t *)client_periodic_in_reqp)->
4832                     intr_len;
4833 
4834                 cur_intr_req = usba_hcdi_dup_intr_req(ph->p_dip,
4835                     (usb_intr_req_t *)client_periodic_in_reqp, length, flags);
4836                 if (cur_intr_req == NULL) {
4837                         USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4838                             "uhci_allocate_periodic_in_resource: Interrupt "
4839                             "request structure allocation failed");
4840 
4841                         return (USB_NO_RESOURCES);
4842                 }
4843 
4844                 /* Check and save the timeout value */
4845                 tw->tw_timeout_cnt = (cur_intr_req->intr_attributes &
4846                     USB_ATTRS_ONE_XFER) ? cur_intr_req->intr_timeout: 0;
4847                 tw->tw_curr_xfer_reqp = (usb_opaque_t)cur_intr_req;
4848                 tw->tw_length = cur_intr_req->intr_len;
4849         } else {
4850                 ASSERT(client_periodic_in_reqp != NULL);
4851 
4852                 if ((curr_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip,
4853                     (usb_isoc_req_t *)client_periodic_in_reqp, flags)) ==
4854                     NULL) {
4855                         USB_DPRINTF_L2(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4856                             "uhci_allocate_periodic_in_resource: Isochronous "
4857                             "request structure allocation failed");
4858 
4859                         return (USB_NO_RESOURCES);
4860                 }
4861 
4862                 /*
4863                  * Save the client's isochronous request pointer and
4864                  * length of isochronous transfer in transfer wrapper.
4865                  * The dup'ed request is saved in pp_client_periodic_in_reqp
4866                  */
4867                 tw->tw_curr_xfer_reqp =
4868                     (usb_opaque_t)pp->pp_client_periodic_in_reqp;
4869                 pp->pp_client_periodic_in_reqp = (usb_opaque_t)curr_isoc_reqp;
4870         }
4871 
4872         mutex_enter(&ph->p_mutex);
4873         ph->p_req_count++;
4874         mutex_exit(&ph->p_mutex);
4875 
4876         return (USB_SUCCESS);
4877 }
4878 
4879 
4880 /*
4881  * uhci_deallocate_periodic_in_resource:
4882  *      Deallocate interrupt/isochronous request structure for the
4883  *      interrupt/isochronous IN transfer.
4884  */
4885 void
4886 uhci_deallocate_periodic_in_resource(
4887         uhci_state_t            *uhcip,
4888         uhci_pipe_private_t     *pp,
4889         uhci_trans_wrapper_t    *tw)
4890 {
4891         usb_opaque_t            curr_xfer_reqp;
4892         usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
4893 
4894         USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4895             "uhci_deallocate_periodic_in_resource: "
4896             "pp = 0x%p tw = 0x%p", (void *)pp, (void *)tw);
4897 
4898         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4899 
4900         curr_xfer_reqp = tw->tw_curr_xfer_reqp;
4901         if (curr_xfer_reqp) {
4902                 /*
4903                  * Reset periodic in request usb isoch
4904                  * packet request pointers to null.
4905                  */
4906                 tw->tw_curr_xfer_reqp = NULL;
4907                 tw->tw_isoc_req = NULL;
4908 
4909                 mutex_enter(&ph->p_mutex);
4910                 ph->p_req_count--;
4911                 mutex_exit(&ph->p_mutex);
4912 
4913                 /*
4914                  * Free pre-allocated interrupt or isochronous requests.
4915                  */
4916                 switch (UHCI_XFER_TYPE(&ph->p_ep)) {
4917                 case USB_EP_ATTR_INTR:
4918                         usb_free_intr_req((usb_intr_req_t *)curr_xfer_reqp);
4919                         break;
4920                 case USB_EP_ATTR_ISOCH:
4921                         usb_free_isoc_req((usb_isoc_req_t *)curr_xfer_reqp);
4922                         break;
4923                 }
4924         }
4925 }
4926 
4927 
4928 /*
4929  * uhci_hcdi_callback()
4930  *      convenience wrapper around usba_hcdi_callback()
4931  */
4932 void
4933 uhci_hcdi_callback(uhci_state_t *uhcip, uhci_pipe_private_t *pp,
4934     usba_pipe_handle_data_t *ph, uhci_trans_wrapper_t *tw, usb_cr_t cr)
4935 {
4936         usb_opaque_t    curr_xfer_reqp;
4937 
4938         USB_DPRINTF_L4(PRINT_MASK_HCDI, uhcip->uhci_log_hdl,
4939             "uhci_hcdi_callback: ph = 0x%p, tw = 0x%p, cr = 0x%x",
4940             (void *)ph, (void *)tw, cr);
4941 
4942         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4943 
4944         if (tw && tw->tw_curr_xfer_reqp) {
4945                 curr_xfer_reqp = tw->tw_curr_xfer_reqp;
4946                 tw->tw_curr_xfer_reqp = NULL;
4947                 tw->tw_isoc_req = NULL;
4948         } else {
4949                 ASSERT(pp->pp_client_periodic_in_reqp != NULL);
4950 
4951                 curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
4952                 pp->pp_client_periodic_in_reqp = NULL;
4953         }
4954 
4955         ASSERT(curr_xfer_reqp != NULL);
4956 
4957         mutex_exit(&uhcip->uhci_int_mutex);
4958         usba_hcdi_cb(ph, curr_xfer_reqp, cr);
4959         mutex_enter(&uhcip->uhci_int_mutex);
4960 }
4961 
4962 
4963 /*
4964  * uhci_state_is_operational:
4965  *
4966  * Check the Host controller state and return proper values.
4967  */
4968 int
4969 uhci_state_is_operational(uhci_state_t  *uhcip)
4970 {
4971         int     val;
4972 
4973         ASSERT(mutex_owned(&uhcip->uhci_int_mutex));
4974 
4975         switch (uhcip->uhci_hc_soft_state) {
4976         case UHCI_CTLR_INIT_STATE:
4977         case UHCI_CTLR_SUSPEND_STATE:
4978                 val = USB_FAILURE;
4979                 break;
4980         case UHCI_CTLR_OPERATIONAL_STATE:
4981                 val = USB_SUCCESS;
4982                 break;
4983         case UHCI_CTLR_ERROR_STATE:
4984                 val = USB_HC_HARDWARE_ERROR;
4985                 break;
4986         default:
4987                 val = USB_FAILURE;
4988                 break;
4989         }
4990 
4991         return (val);
4992 }
4993 
4994 
4995 #ifdef DEBUG
4996 static void
4997 uhci_print_td(uhci_state_t *uhcip, uhci_td_t *td)
4998 {
4999         uint_t  *ptr = (uint_t *)td;
5000 
5001 #ifndef lint
5002         _NOTE(NO_COMPETING_THREADS_NOW);
5003 #endif
5004         USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5005             "\tDWORD 1 0x%x\t DWORD 2 0x%x", ptr[0], ptr[1]);
5006         USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5007             "\tDWORD 3 0x%x\t DWORD 4 0x%x", ptr[2], ptr[3]);
5008         USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5009             "\tBytes xfered    = %d", td->tw->tw_bytes_xfered);
5010         USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5011             "\tBytes Pending   = %d", td->tw->tw_bytes_pending);
5012         USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5013             "Queue Head Details:");
5014         uhci_print_qh(uhcip, td->tw->tw_pipe_private->pp_qh);
5015 
5016 #ifndef lint
5017         _NOTE(COMPETING_THREADS_NOW);
5018 #endif
5019 }
5020 
5021 
5022 static void
5023 uhci_print_qh(uhci_state_t *uhcip, queue_head_t *qh)
5024 {
5025         uint_t  *ptr = (uint_t *)qh;
5026 
5027         USB_DPRINTF_L3(PRINT_MASK_DUMPING, uhcip->uhci_log_hdl,
5028             "\tLink Ptr = %x Element Ptr = %x", ptr[0], ptr[1]);
5029 }
5030 #endif