Print this page
    
7127  remove -Wno-missing-braces from Makefile.uts
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/usb/hcd/openhci/ohci.c
          +++ new/usr/src/uts/common/io/usb/hcd/openhci/ohci.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  
  27   27  /*
  28   28   * Open Host Controller Driver (OHCI)
  29   29   *
  30   30   * The USB Open Host Controller driver is a software driver which interfaces
  31   31   * to the Universal Serial Bus layer (USBA) and the USB Open Host Controller.
  32   32   * The interface to USB Open Host Controller is defined by the OpenHCI  Host
  33   33   * Controller Interface.
  34   34   *
  35   35   * NOTE:
  36   36   *
  37   37   * Currently OHCI driver does not support the following features
  38   38   *
  39   39   * - Handle request with multiple TDs under short xfer conditions except for
  40   40   *   bulk transfers.
  41   41   */
  42   42  #include <sys/usb/hcd/openhci/ohcid.h>
  43   43  
  44   44  #include <sys/disp.h>
  45   45  #include <sys/strsun.h>
  46   46  
  47   47  /* Pointer to the state structure */
  48   48  static void *ohci_statep;
  49   49  
  50   50  int force_ohci_off = 1;
  51   51  
  52   52  /* Number of instances */
  53   53  #define OHCI_INSTS      1
  54   54  
  55   55  /* Adjustable variables for the size of the pools */
  56   56  int ohci_ed_pool_size = OHCI_ED_POOL_SIZE;
  57   57  int ohci_td_pool_size = OHCI_TD_POOL_SIZE;
  58   58  
  59   59  /*
  60   60   * Initialize the values which are used for setting up head pointers for
  61   61   * the 32ms scheduling lists which starts from the HCCA.
  62   62   */
  63   63  static uchar_t ohci_index[NUM_INTR_ED_LISTS / 2] = {0x0, 0x8, 0x4, 0xc,
  64   64                                                  0x2, 0xa, 0x6, 0xe,
  65   65                                                  0x1, 0x9, 0x5, 0xd,
  66   66                                                  0x3, 0xb, 0x7, 0xf};
  67   67  /* Debugging information */
  68   68  uint_t ohci_errmask     = (uint_t)PRINT_MASK_ALL;
  69   69  uint_t ohci_errlevel    = USB_LOG_L2;
  70   70  uint_t ohci_instance_debug = (uint_t)-1;
  71   71  
  72   72  /*
  73   73   * OHCI MSI tunable:
  74   74   *
  75   75   * By default MSI is enabled on all supported platforms.
  76   76   */
  77   77  boolean_t ohci_enable_msi = B_TRUE;
  78   78  
  79   79  /*
  80   80   * HCDI entry points
  81   81   *
  82   82   * The Host Controller Driver Interfaces (HCDI) are the software interfaces
  83   83   * between the Universal Serial Bus Driver (USBA) and the Host  Controller
  84   84   * Driver (HCD). The HCDI interfaces or entry points are subject to change.
  85   85   */
  86   86  static int      ohci_hcdi_pipe_open(
  87   87                                  usba_pipe_handle_data_t *ph,
  88   88                                  usb_flags_t             usb_flags);
  89   89  static int      ohci_hcdi_pipe_close(
  90   90                                  usba_pipe_handle_data_t *ph,
  91   91                                  usb_flags_t             usb_flags);
  92   92  static int      ohci_hcdi_pipe_reset(
  93   93                                  usba_pipe_handle_data_t *ph,
  94   94                                  usb_flags_t             usb_flags);
  95   95  static void     ohci_hcdi_pipe_reset_data_toggle(
  96   96                                  usba_pipe_handle_data_t *ph);
  97   97  static int      ohci_hcdi_pipe_ctrl_xfer(
  98   98                                  usba_pipe_handle_data_t *ph,
  99   99                                  usb_ctrl_req_t          *ctrl_reqp,
 100  100                                  usb_flags_t             usb_flags);
 101  101  static int      ohci_hcdi_bulk_transfer_size(
 102  102                                  usba_device_t           *usba_device,
 103  103                                  size_t                  *size);
 104  104  static int      ohci_hcdi_pipe_bulk_xfer(
 105  105                                  usba_pipe_handle_data_t *ph,
 106  106                                  usb_bulk_req_t          *bulk_reqp,
 107  107                                  usb_flags_t             usb_flags);
 108  108  static int      ohci_hcdi_pipe_intr_xfer(
 109  109                                  usba_pipe_handle_data_t *ph,
 110  110                                  usb_intr_req_t          *intr_req,
 111  111                                  usb_flags_t             usb_flags);
 112  112  static int      ohci_hcdi_pipe_stop_intr_polling(
 113  113                                  usba_pipe_handle_data_t *ph,
 114  114                                  usb_flags_t             usb_flags);
 115  115  static int      ohci_hcdi_get_current_frame_number(
 116  116                                  usba_device_t           *usba_device,
 117  117                                  usb_frame_number_t      *frame_number);
 118  118  static int      ohci_hcdi_get_max_isoc_pkts(
 119  119                                  usba_device_t           *usba_device,
 120  120                                  uint_t          *max_isoc_pkts_per_request);
 121  121  static int      ohci_hcdi_pipe_isoc_xfer(
 122  122                                  usba_pipe_handle_data_t *ph,
 123  123                                  usb_isoc_req_t          *isoc_reqp,
 124  124                                  usb_flags_t             usb_flags);
 125  125  static int      ohci_hcdi_pipe_stop_isoc_polling(
 126  126                                  usba_pipe_handle_data_t *ph,
 127  127                                  usb_flags_t             usb_flags);
 128  128  
 129  129  /*
 130  130   * Internal Function Prototypes
 131  131   */
 132  132  
 133  133  /* Host Controller Driver (HCD) initialization functions */
 134  134  static void     ohci_set_dma_attributes(ohci_state_t    *ohcip);
 135  135  static int      ohci_allocate_pools(ohci_state_t        *ohcip);
 136  136  static void     ohci_decode_ddi_dma_addr_bind_handle_result(
 137  137                                  ohci_state_t            *ohcip,
 138  138                                  int                     result);
 139  139  static int      ohci_map_regs(ohci_state_t              *ohcip);
 140  140  static int      ohci_register_intrs_and_init_mutex(
 141  141                                  ohci_state_t            *ohcip);
 142  142  static int      ohci_add_intrs(ohci_state_t             *ohcip,
 143  143                                  int                     intr_type);
 144  144  static int      ohci_init_ctlr(ohci_state_t             *ohcip);
 145  145  static int      ohci_init_hcca(ohci_state_t             *ohcip);
 146  146  static void     ohci_build_interrupt_lattice(
 147  147                                  ohci_state_t            *ohcip);
 148  148  static int      ohci_take_control(ohci_state_t          *ohcip);
 149  149  static usba_hcdi_ops_t *ohci_alloc_hcdi_ops(
 150  150                                  ohci_state_t            *ohcip);
 151  151  
 152  152  /* Host Controller Driver (HCD) deinitialization functions */
 153  153  static int      ohci_cleanup(ohci_state_t               *ohcip);
 154  154  static void     ohci_rem_intrs(ohci_state_t             *ohcip);
 155  155  static int      ohci_cpr_suspend(ohci_state_t           *ohcip);
 156  156  static int      ohci_cpr_resume(ohci_state_t            *ohcip);
 157  157  
 158  158  /* Bandwidth Allocation functions */
 159  159  static int      ohci_allocate_bandwidth(ohci_state_t    *ohcip,
 160  160                                  usba_pipe_handle_data_t *ph,
 161  161                                  uint_t                  *node);
 162  162  static void     ohci_deallocate_bandwidth(ohci_state_t  *ohcip,
 163  163                                  usba_pipe_handle_data_t *ph);
 164  164  static int      ohci_compute_total_bandwidth(
 165  165                                  usb_ep_descr_t          *endpoint,
 166  166                                  usb_port_status_t       port_status,
 167  167                                  uint_t                  *bandwidth);
 168  168  static int      ohci_adjust_polling_interval(
 169  169                                  ohci_state_t            *ohcip,
 170  170                                  usb_ep_descr_t          *endpoint,
 171  171                                  usb_port_status_t       port_status);
 172  172  static uint_t   ohci_lattice_height(uint_t              interval);
 173  173  static uint_t   ohci_lattice_parent(uint_t              node);
 174  174  static uint_t   ohci_leftmost_leaf(uint_t               node,
 175  175                                  uint_t                  height);
 176  176  static uint_t   ohci_hcca_intr_index(
 177  177                                  uint_t                  node);
 178  178  static uint_t   ohci_hcca_leaf_index(
 179  179                                  uint_t                  leaf);
 180  180  static uint_t   ohci_pow_2(uint_t x);
 181  181  static uint_t   ohci_log_2(uint_t x);
 182  182  
 183  183  /* Endpoint Descriptor (ED) related functions */
 184  184  static uint_t   ohci_unpack_endpoint(ohci_state_t       *ohcip,
 185  185                                  usba_pipe_handle_data_t *ph);
 186  186  static void     ohci_insert_ed(ohci_state_t             *ohcip,
 187  187                                  usba_pipe_handle_data_t *ph);
 188  188  static void     ohci_insert_ctrl_ed(
 189  189                                  ohci_state_t            *ohcip,
 190  190                                  ohci_pipe_private_t     *pp);
 191  191  static void     ohci_insert_bulk_ed(
 192  192                                  ohci_state_t            *ohcip,
 193  193                                  ohci_pipe_private_t     *pp);
 194  194  static void     ohci_insert_intr_ed(
 195  195                                  ohci_state_t            *ohcip,
 196  196                                  ohci_pipe_private_t     *pp);
 197  197  static void     ohci_insert_isoc_ed(
 198  198                                  ohci_state_t            *ohcip,
 199  199                                  ohci_pipe_private_t     *pp);
 200  200  static void     ohci_modify_sKip_bit(ohci_state_t       *ohcip,
 201  201                                  ohci_pipe_private_t     *pp,
 202  202                                  skip_bit_t              action,
 203  203                                  usb_flags_t             flag);
 204  204  static void     ohci_remove_ed(ohci_state_t             *ohcip,
 205  205                                  ohci_pipe_private_t     *pp);
 206  206  static void     ohci_remove_ctrl_ed(
 207  207                                  ohci_state_t            *ohcip,
 208  208                                  ohci_pipe_private_t     *pp);
 209  209  static void     ohci_remove_bulk_ed(
 210  210                                  ohci_state_t            *ohcip,
 211  211                                  ohci_pipe_private_t     *pp);
 212  212  static void     ohci_remove_periodic_ed(
 213  213                                  ohci_state_t            *ohcip,
 214  214                                  ohci_pipe_private_t     *pp);
 215  215  static void     ohci_insert_ed_on_reclaim_list(
 216  216                                  ohci_state_t            *ohcip,
 217  217                                  ohci_pipe_private_t     *pp);
 218  218  static void     ohci_detach_ed_from_list(
 219  219                                  ohci_state_t            *ohcip,
 220  220                                  ohci_ed_t               *ept,
 221  221                                  uint_t                  ept_type);
 222  222  static ohci_ed_t *ohci_ed_iommu_to_cpu(
 223  223                                  ohci_state_t            *ohcip,
 224  224                                  uintptr_t               addr);
 225  225  
 226  226  /* Transfer Descriptor (TD) related functions */
 227  227  static int      ohci_initialize_dummy(ohci_state_t      *ohcip,
 228  228                                  ohci_ed_t               *ept);
 229  229  static ohci_trans_wrapper_t *ohci_allocate_ctrl_resources(
 230  230                                  ohci_state_t            *ohcip,
 231  231                                  ohci_pipe_private_t     *pp,
 232  232                                  usb_ctrl_req_t          *ctrl_reqp,
 233  233                                  usb_flags_t             usb_flags);
 234  234  static void     ohci_insert_ctrl_req(
 235  235                                  ohci_state_t            *ohcip,
 236  236                                  usba_pipe_handle_data_t *ph,
 237  237                                  usb_ctrl_req_t          *ctrl_reqp,
 238  238                                  ohci_trans_wrapper_t    *tw,
 239  239                                  usb_flags_t             usb_flags);
 240  240  static ohci_trans_wrapper_t *ohci_allocate_bulk_resources(
 241  241                                  ohci_state_t            *ohcip,
 242  242                                  ohci_pipe_private_t     *pp,
 243  243                                  usb_bulk_req_t          *bulk_reqp,
 244  244                                  usb_flags_t             usb_flags);
 245  245  static void     ohci_insert_bulk_req(ohci_state_t       *ohcip,
 246  246                                  usba_pipe_handle_data_t *ph,
 247  247                                  usb_bulk_req_t          *bulk_reqp,
 248  248                                  ohci_trans_wrapper_t    *tw,
 249  249                                  usb_flags_t             flags);
 250  250  static int      ohci_start_pipe_polling(ohci_state_t    *ohcip,
 251  251                                  usba_pipe_handle_data_t *ph,
 252  252                                  usb_flags_t             flags);
 253  253  static void     ohci_set_periodic_pipe_polling(
 254  254                                  ohci_state_t            *ohcip,
 255  255                                  usba_pipe_handle_data_t *ph);
 256  256  static ohci_trans_wrapper_t *ohci_allocate_intr_resources(
 257  257                                  ohci_state_t            *ohcip,
 258  258                                  usba_pipe_handle_data_t *ph,
 259  259                                  usb_intr_req_t          *intr_reqp,
 260  260                                  usb_flags_t             usb_flags);
 261  261  static void     ohci_insert_intr_req(ohci_state_t       *ohcip,
 262  262                                  ohci_pipe_private_t     *pp,
 263  263                                  ohci_trans_wrapper_t    *tw,
 264  264                                  usb_flags_t             flags);
 265  265  static int      ohci_stop_periodic_pipe_polling(
 266  266                                  ohci_state_t            *ohcip,
 267  267                                  usba_pipe_handle_data_t *ph,
 268  268                                  usb_flags_t             flags);
 269  269  static ohci_trans_wrapper_t *ohci_allocate_isoc_resources(
 270  270                                  ohci_state_t            *ohcip,
 271  271                                  usba_pipe_handle_data_t *ph,
 272  272                                  usb_isoc_req_t          *isoc_reqp,
 273  273                                  usb_flags_t             usb_flags);
 274  274  static int      ohci_insert_isoc_req(ohci_state_t       *ohcip,
 275  275                                  ohci_pipe_private_t     *pp,
 276  276                                  ohci_trans_wrapper_t    *tw,
 277  277                                  uint_t                  flags);
 278  278  static int      ohci_insert_hc_td(ohci_state_t          *ohcip,
 279  279                                  uint_t                  hctd_ctrl,
 280  280                                  uint32_t                hctd_dma_offs,
 281  281                                  size_t                  hctd_length,
 282  282                                  uint32_t                hctd_ctrl_phase,
 283  283                                  ohci_pipe_private_t     *pp,
 284  284                                  ohci_trans_wrapper_t    *tw);
 285  285  static ohci_td_t *ohci_allocate_td_from_pool(
 286  286                                  ohci_state_t            *ohcip);
 287  287  static void     ohci_fill_in_td(ohci_state_t            *ohcip,
 288  288                                  ohci_td_t               *td,
 289  289                                  ohci_td_t               *new_dummy,
 290  290                                  uint_t                  hctd_ctrl,
 291  291                                  uint32_t                hctd_dma_offs,
 292  292                                  size_t                  hctd_length,
 293  293                                  uint32_t                hctd_ctrl_phase,
 294  294                                  ohci_pipe_private_t     *pp,
 295  295                                  ohci_trans_wrapper_t    *tw);
 296  296  static void     ohci_init_itd(
 297  297                                  ohci_state_t            *ohcip,
 298  298                                  ohci_trans_wrapper_t    *tw,
 299  299                                  uint_t                  hctd_ctrl,
 300  300                                  uint32_t                index,
 301  301                                  ohci_td_t               *td);
 302  302  static int      ohci_insert_td_with_frame_number(
 303  303                                  ohci_state_t            *ohcip,
 304  304                                  ohci_pipe_private_t     *pp,
 305  305                                  ohci_trans_wrapper_t    *tw,
 306  306                                  ohci_td_t               *current_td,
 307  307                                  ohci_td_t               *dummy_td);
 308  308  static void     ohci_insert_td_on_tw(ohci_state_t       *ohcip,
 309  309                                  ohci_trans_wrapper_t    *tw,
 310  310                                  ohci_td_t               *td);
 311  311  static void     ohci_done_list_tds(ohci_state_t         *ohcip,
 312  312                                  usba_pipe_handle_data_t *ph);
 313  313  
 314  314  /* Transfer Wrapper (TW) functions */
 315  315  static ohci_trans_wrapper_t  *ohci_create_transfer_wrapper(
 316  316                                  ohci_state_t            *ohcip,
 317  317                                  ohci_pipe_private_t     *pp,
 318  318                                  size_t                  length,
 319  319                                  uint_t                  usb_flags);
 320  320  static ohci_trans_wrapper_t  *ohci_create_isoc_transfer_wrapper(
 321  321                                  ohci_state_t            *ohcip,
 322  322                                  ohci_pipe_private_t     *pp,
 323  323                                  size_t                  length,
 324  324                                  usb_isoc_pkt_descr_t    *descr,
 325  325                                  ushort_t                pkt_count,
 326  326                                  size_t                  td_count,
 327  327                                  uint_t                  usb_flags);
 328  328  int     ohci_allocate_tds_for_tw(
 329  329                                  ohci_state_t            *ohcip,
 330  330                                  ohci_trans_wrapper_t    *tw,
 331  331                                  size_t                  td_count);
 332  332  static ohci_trans_wrapper_t  *ohci_allocate_tw_resources(
 333  333                                  ohci_state_t            *ohcip,
 334  334                                  ohci_pipe_private_t     *pp,
 335  335                                  size_t                  length,
 336  336                                  usb_flags_t             usb_flags,
 337  337                                  size_t                  td_count);
 338  338  static void     ohci_free_tw_tds_resources(
 339  339                                  ohci_state_t            *ohcip,
 340  340                                  ohci_trans_wrapper_t    *tw);
 341  341  static void     ohci_start_xfer_timer(
 342  342                                  ohci_state_t            *ohcip,
 343  343                                  ohci_pipe_private_t     *pp,
 344  344                                  ohci_trans_wrapper_t    *tw);
 345  345  static void     ohci_stop_xfer_timer(
 346  346                                  ohci_state_t            *ohcip,
 347  347                                  ohci_trans_wrapper_t    *tw,
 348  348                                  uint_t                  flag);
 349  349  static void     ohci_xfer_timeout_handler(void          *arg);
 350  350  static void     ohci_remove_tw_from_timeout_list(
 351  351                                  ohci_state_t            *ohcip,
 352  352                                  ohci_trans_wrapper_t    *tw);
 353  353  static void     ohci_start_timer(ohci_state_t           *ohcip);
 354  354  static void     ohci_free_dma_resources(ohci_state_t    *ohcip,
 355  355                                  usba_pipe_handle_data_t *ph);
 356  356  static void     ohci_free_tw(ohci_state_t               *ohcip,
 357  357                                  ohci_trans_wrapper_t    *tw);
 358  358  static int      ohci_tw_rebind_cookie(
 359  359                                  ohci_state_t            *ohcip,
 360  360                                  ohci_pipe_private_t     *pp,
 361  361                                  ohci_trans_wrapper_t    *tw);
 362  362  
 363  363  /* Interrupt Handling functions */
 364  364  static uint_t   ohci_intr(caddr_t                       arg1,
 365  365                                  caddr_t                 arg2);
 366  366  static void     ohci_handle_missed_intr(
 367  367                                  ohci_state_t            *ohcip);
 368  368  static void     ohci_handle_ue(ohci_state_t             *ohcip);
 369  369  static void     ohci_handle_endpoint_reclaimation(
 370  370                                  ohci_state_t            *ohcip);
 371  371  static void     ohci_traverse_done_list(
 372  372                                  ohci_state_t            *ohcip,
 373  373                                  ohci_td_t               *head_done_list);
 374  374  static ohci_td_t *ohci_reverse_done_list(
 375  375                                  ohci_state_t            *ohcip,
 376  376                                  ohci_td_t               *head_done_list);
 377  377  static usb_cr_t ohci_parse_error(ohci_state_t           *ohcip,
 378  378                                  ohci_td_t               *td);
 379  379  static void     ohci_parse_isoc_error(
 380  380                                  ohci_state_t            *ohcip,
 381  381                                  ohci_pipe_private_t     *pp,
 382  382                                  ohci_trans_wrapper_t    *tw,
 383  383                                  ohci_td_t               *td);
 384  384  static usb_cr_t ohci_check_for_error(
 385  385                                  ohci_state_t            *ohcip,
 386  386                                  ohci_pipe_private_t     *pp,
 387  387                                  ohci_trans_wrapper_t    *tw,
 388  388                                  ohci_td_t               *td,
 389  389                                  uint_t                  ctrl);
 390  390  static void     ohci_handle_error(
 391  391                                  ohci_state_t            *ohcip,
 392  392                                  ohci_td_t               *td,
 393  393                                  usb_cr_t                error);
 394  394  static int      ohci_cleanup_data_underrun(
 395  395                                  ohci_state_t            *ohcip,
 396  396                                  ohci_pipe_private_t     *pp,
 397  397                                  ohci_trans_wrapper_t    *tw,
 398  398                                  ohci_td_t               *td);
 399  399  static void     ohci_handle_normal_td(
 400  400                                  ohci_state_t            *ohcip,
 401  401                                  ohci_td_t               *td,
 402  402                                  ohci_trans_wrapper_t    *tw);
 403  403  static void     ohci_handle_ctrl_td(ohci_state_t        *ohcip,
 404  404                                  ohci_pipe_private_t     *pp,
 405  405                                  ohci_trans_wrapper_t    *tw,
 406  406                                  ohci_td_t               *td,
 407  407                                  void                    *);
 408  408  static void     ohci_handle_bulk_td(ohci_state_t        *ohcip,
 409  409                                  ohci_pipe_private_t     *pp,
 410  410                                  ohci_trans_wrapper_t    *tw,
 411  411                                  ohci_td_t               *td,
 412  412                                  void                    *);
 413  413  static void     ohci_handle_intr_td(ohci_state_t        *ohcip,
 414  414                                  ohci_pipe_private_t     *pp,
 415  415                                  ohci_trans_wrapper_t    *tw,
 416  416                                  ohci_td_t               *td,
 417  417                                  void                    *);
 418  418  static void     ohci_handle_one_xfer_completion(
 419  419                                  ohci_state_t            *ohcip,
 420  420                                  ohci_trans_wrapper_t    *tw);
 421  421  static void     ohci_handle_isoc_td(ohci_state_t        *ohcip,
 422  422                                  ohci_pipe_private_t     *pp,
 423  423                                  ohci_trans_wrapper_t    *tw,
 424  424                                  ohci_td_t               *td,
 425  425                                  void                    *);
 426  426  static void     ohci_sendup_td_message(
 427  427                                  ohci_state_t            *ohcip,
 428  428                                  ohci_pipe_private_t     *pp,
 429  429                                  ohci_trans_wrapper_t    *tw,
 430  430                                  ohci_td_t               *td,
 431  431                                  usb_cr_t                error);
 432  432  static int      ohci_check_done_head(
 433  433                                  ohci_state_t *ohcip,
 434  434                                  ohci_td_t               *done_head);
 435  435  
 436  436  /* Miscillaneous functions */
 437  437  static void     ohci_cpr_cleanup(
 438  438                                  ohci_state_t            *ohcip);
 439  439  static usb_req_attrs_t ohci_get_xfer_attrs(ohci_state_t *ohcip,
 440  440                                  ohci_pipe_private_t     *pp,
 441  441                                  ohci_trans_wrapper_t    *tw);
 442  442  static int      ohci_allocate_periodic_in_resource(
 443  443                                  ohci_state_t            *ohcip,
 444  444                                  ohci_pipe_private_t     *pp,
 445  445                                  ohci_trans_wrapper_t    *tw,
 446  446                                  usb_flags_t             flags);
 447  447  static int      ohci_wait_for_sof(
 448  448                                  ohci_state_t            *ohcip);
 449  449  static void     ohci_pipe_cleanup(
 450  450                                  ohci_state_t            *ohcip,
 451  451                                  usba_pipe_handle_data_t *ph);
 452  452  static void     ohci_wait_for_transfers_completion(
 453  453                                  ohci_state_t            *ohcip,
 454  454                                  ohci_pipe_private_t     *pp);
 455  455  static void     ohci_check_for_transfers_completion(
 456  456                                  ohci_state_t            *ohcip,
 457  457                                  ohci_pipe_private_t     *pp);
 458  458  static void     ohci_save_data_toggle(ohci_state_t      *ohcip,
 459  459                                  usba_pipe_handle_data_t *ph);
 460  460  static void     ohci_restore_data_toggle(ohci_state_t   *ohcip,
 461  461                                  usba_pipe_handle_data_t *ph);
 462  462  static void     ohci_deallocate_periodic_in_resource(
 463  463                                  ohci_state_t            *ohcip,
 464  464                                  ohci_pipe_private_t     *pp,
 465  465                                  ohci_trans_wrapper_t    *tw);
 466  466  static void     ohci_do_client_periodic_in_req_callback(
 467  467                                  ohci_state_t            *ohcip,
 468  468                                  ohci_pipe_private_t     *pp,
 469  469                                  usb_cr_t                completion_reason);
 470  470  static void     ohci_hcdi_callback(
 471  471                                  usba_pipe_handle_data_t *ph,
 472  472                                  ohci_trans_wrapper_t    *tw,
 473  473                                  usb_cr_t                completion_reason);
 474  474  
 475  475  /* Kstat Support */
 476  476  static void     ohci_create_stats(ohci_state_t          *ohcip);
 477  477  static void     ohci_destroy_stats(ohci_state_t         *ohcip);
 478  478  static void     ohci_do_byte_stats(
 479  479                                  ohci_state_t            *ohcip,
 480  480                                  size_t                  len,
 481  481                                  uint8_t                 attr,
 482  482                                  uint8_t                 addr);
 483  483  static void     ohci_do_intrs_stats(
 484  484                                  ohci_state_t            *ohcip,
 485  485                                  int                     val);
 486  486  static void     ohci_print_op_regs(ohci_state_t         *ohcip);
 487  487  static void     ohci_print_ed(ohci_state_t              *ohcip,
 488  488                                  ohci_ed_t               *ed);
 489  489  static void     ohci_print_td(ohci_state_t              *ohcip,
 490  490                                  ohci_td_t               *td);
 491  491  
 492  492  /* extern */
 493  493  int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level);
 494  494  
 495  495  /*
 496  496   * Device operations (dev_ops) entries function prototypes.
 497  497   *
 498  498   * We use the hub cbops since all nexus ioctl operations defined so far will
 499  499   * be executed by the root hub. The following are the Host Controller Driver
 500  500   * (HCD) entry points.
 501  501   *
 502  502   * the open/close/ioctl functions call the corresponding usba_hubdi_*
 503  503   * calls after looking up the dip thru the dev_t.
 504  504   */
 505  505  static int      ohci_open(dev_t *devp, int flags, int otyp, cred_t *credp);
 506  506  static int      ohci_close(dev_t dev, int flag, int otyp, cred_t *credp);
 507  507  static int      ohci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
 508  508                                  cred_t *credp, int *rvalp);
 509  509  
 510  510  static int      ohci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
 511  511  static int      ohci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
 512  512  static int      ohci_quiesce(dev_info_t *dip);
 513  513  
 514  514  static int      ohci_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
 515  515                                  void *arg, void **result);
 516  516  
 517  517  static struct cb_ops ohci_cb_ops = {
 518  518          ohci_open,                      /* Open */
 519  519          ohci_close,                     /* Close */
 520  520          nodev,                          /* Strategy */
 521  521          nodev,                          /* Print */
 522  522          nodev,                          /* Dump */
 523  523          nodev,                          /* Read */
 524  524          nodev,                          /* Write */
 525  525          ohci_ioctl,                     /* Ioctl */
 526  526          nodev,                          /* Devmap */
 527  527          nodev,                          /* Mmap */
 528  528          nodev,                          /* Segmap */
 529  529          nochpoll,                       /* Poll */
 530  530          ddi_prop_op,                    /* cb_prop_op */
 531  531          NULL,                           /* Streamtab */
 532  532          D_MP                            /* Driver compatibility flag */
 533  533  };
 534  534  
 535  535  static struct dev_ops ohci_ops = {
 536  536          DEVO_REV,                       /* Devo_rev */
 537  537          0,                              /* Refcnt */
 538  538          ohci_info,                      /* Info */
 539  539          nulldev,                        /* Identify */
 540  540          nulldev,                        /* Probe */
 541  541          ohci_attach,                    /* Attach */
 542  542          ohci_detach,                    /* Detach */
 543  543          nodev,                          /* Reset */
 544  544          &ohci_cb_ops,                   /* Driver operations */
 545  545          &usba_hubdi_busops,             /* Bus operations */
 546  546          usba_hubdi_root_hub_power,      /* Power */
 547  547          ohci_quiesce,                   /* Quiesce */
 548  548  };
 549  549  
  
    | ↓ open down ↓ | 549 lines elided | ↑ open up ↑ | 
 550  550  /*
 551  551   * The USBA library must be loaded for this driver.
 552  552   */
 553  553  static struct modldrv modldrv = {
 554  554          &mod_driverops,         /* Type of module. This one is a driver */
 555  555          "USB OpenHCI Driver", /* Name of the module. */
 556  556          &ohci_ops,              /* Driver ops */
 557  557  };
 558  558  
 559  559  static struct modlinkage modlinkage = {
 560      -        MODREV_1, (void *)&modldrv, NULL
      560 +        MODREV_1, { (void *)&modldrv, NULL }
 561  561  };
 562  562  
 563  563  
 564  564  int
 565  565  _init(void)
 566  566  {
 567  567          int error;
 568  568  
 569  569          /* Initialize the soft state structures */
 570  570          if ((error = ddi_soft_state_init(&ohci_statep, sizeof (ohci_state_t),
 571  571              OHCI_INSTS)) != 0) {
 572  572                  return (error);
 573  573          }
 574  574  
 575  575          /* Install the loadable module */
 576  576          if ((error = mod_install(&modlinkage)) != 0) {
 577  577                  ddi_soft_state_fini(&ohci_statep);
 578  578          }
 579  579  
 580  580          return (error);
 581  581  }
 582  582  
 583  583  
 584  584  int
 585  585  _info(struct modinfo *modinfop)
 586  586  {
 587  587          return (mod_info(&modlinkage, modinfop));
 588  588  }
 589  589  
 590  590  
 591  591  int
 592  592  _fini(void)
 593  593  {
 594  594          int error;
 595  595  
 596  596          if ((error = mod_remove(&modlinkage)) == 0) {
 597  597                  /* Release per module resources */
 598  598                  ddi_soft_state_fini(&ohci_statep);
 599  599          }
 600  600  
 601  601          return (error);
 602  602  }
 603  603  
 604  604  
 605  605  /*
 606  606   * Host Controller Driver (HCD) entry points
 607  607   */
 608  608  
 609  609  /*
 610  610   * ohci_attach:
 611  611   */
 612  612  static int
 613  613  ohci_attach(dev_info_t          *dip,
 614  614          ddi_attach_cmd_t        cmd)
 615  615  {
 616  616          int                     instance;
 617  617          ohci_state_t            *ohcip = NULL;
 618  618          usba_hcdi_register_args_t hcdi_args;
 619  619  
 620  620          switch (cmd) {
 621  621          case DDI_ATTACH:
 622  622                  break;
 623  623          case DDI_RESUME:
 624  624                  ohcip = ohci_obtain_state(dip);
 625  625  
 626  626                  return (ohci_cpr_resume(ohcip));
 627  627          default:
 628  628                  return (DDI_FAILURE);
 629  629          }
 630  630  
 631  631          /* Get the instance and create soft state */
 632  632          instance = ddi_get_instance(dip);
 633  633  
 634  634          if (ddi_soft_state_zalloc(ohci_statep, instance) != 0) {
 635  635  
 636  636                  return (DDI_FAILURE);
 637  637          }
 638  638  
 639  639          ohcip = ddi_get_soft_state(ohci_statep, instance);
 640  640          if (ohcip == NULL) {
 641  641  
 642  642                  return (DDI_FAILURE);
 643  643          }
 644  644  
 645  645          ohcip->ohci_flags = OHCI_ATTACH;
 646  646  
 647  647          ohcip->ohci_log_hdl = usb_alloc_log_hdl(dip, "ohci", &ohci_errlevel,
 648  648              &ohci_errmask, &ohci_instance_debug, 0);
 649  649  
 650  650          ohcip->ohci_flags |= OHCI_ZALLOC;
 651  651  
 652  652          /* Set host controller soft state to initilization */
 653  653          ohcip->ohci_hc_soft_state = OHCI_CTLR_INIT_STATE;
 654  654  
 655  655          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
 656  656              "ohcip = 0x%p", (void *)ohcip);
 657  657  
 658  658          /* Initialize the DMA attributes */
 659  659          ohci_set_dma_attributes(ohcip);
 660  660  
 661  661          /* Save the dip and instance */
 662  662          ohcip->ohci_dip = dip;
 663  663          ohcip->ohci_instance = instance;
 664  664  
 665  665          /* Initialize the kstat structures */
 666  666          ohci_create_stats(ohcip);
 667  667  
 668  668          /* Create the td and ed pools */
 669  669          if (ohci_allocate_pools(ohcip) != DDI_SUCCESS) {
 670  670                  (void) ohci_cleanup(ohcip);
 671  671  
 672  672                  return (DDI_FAILURE);
 673  673          }
 674  674  
 675  675          /* Map the registers */
 676  676          if (ohci_map_regs(ohcip) != DDI_SUCCESS) {
 677  677                  (void) ohci_cleanup(ohcip);
 678  678  
 679  679                  return (DDI_FAILURE);
 680  680          }
 681  681  
 682  682          /* Get the ohci chip vendor and device id */
 683  683          ohcip->ohci_vendor_id = pci_config_get16(
 684  684              ohcip->ohci_config_handle, PCI_CONF_VENID);
 685  685          ohcip->ohci_device_id = pci_config_get16(
 686  686              ohcip->ohci_config_handle, PCI_CONF_DEVID);
 687  687          ohcip->ohci_rev_id = pci_config_get8(
 688  688              ohcip->ohci_config_handle, PCI_CONF_REVID);
 689  689  
 690  690          /* Register interrupts */
 691  691          if (ohci_register_intrs_and_init_mutex(ohcip) != DDI_SUCCESS) {
 692  692                  (void) ohci_cleanup(ohcip);
 693  693  
 694  694                  return (DDI_FAILURE);
 695  695          }
 696  696  
 697  697          mutex_enter(&ohcip->ohci_int_mutex);
 698  698  
 699  699          /* Initialize the controller */
 700  700          if (ohci_init_ctlr(ohcip) != DDI_SUCCESS) {
 701  701                  mutex_exit(&ohcip->ohci_int_mutex);
 702  702                  (void) ohci_cleanup(ohcip);
 703  703  
 704  704                  return (DDI_FAILURE);
 705  705          }
 706  706  
 707  707          /*
 708  708           * At this point, the hardware wiil be okay.
 709  709           * Initialize the usba_hcdi structure
 710  710           */
 711  711          ohcip->ohci_hcdi_ops = ohci_alloc_hcdi_ops(ohcip);
 712  712  
 713  713          mutex_exit(&ohcip->ohci_int_mutex);
 714  714  
 715  715          /*
 716  716           * Make this HCD instance known to USBA
 717  717           * (dma_attr must be passed for USBA busctl's)
 718  718           */
 719  719          hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION;
 720  720          hcdi_args.usba_hcdi_register_dip = dip;
 721  721          hcdi_args.usba_hcdi_register_ops = ohcip->ohci_hcdi_ops;
 722  722          hcdi_args.usba_hcdi_register_dma_attr = &ohcip->ohci_dma_attr;
 723  723  
 724  724          /*
 725  725           * Priority and iblock_cookie are one and the same
 726  726           * (However, retaining hcdi_soft_iblock_cookie for now
 727  727           * assigning it w/ priority. In future all iblock_cookie
 728  728           * could just go)
 729  729           */
 730  730          hcdi_args.usba_hcdi_register_iblock_cookie =
 731  731              (ddi_iblock_cookie_t)(uintptr_t)ohcip->ohci_intr_pri;
 732  732  
 733  733          if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) {
 734  734                  (void) ohci_cleanup(ohcip);
 735  735  
 736  736                  return (DDI_FAILURE);
 737  737          }
 738  738          ohcip->ohci_flags |= OHCI_USBAREG;
 739  739  
 740  740          mutex_enter(&ohcip->ohci_int_mutex);
 741  741  
 742  742          if ((ohci_init_root_hub(ohcip)) != USB_SUCCESS) {
 743  743                  mutex_exit(&ohcip->ohci_int_mutex);
 744  744                  (void) ohci_cleanup(ohcip);
 745  745  
 746  746                  return (DDI_FAILURE);
 747  747          }
 748  748  
 749  749          mutex_exit(&ohcip->ohci_int_mutex);
 750  750  
 751  751          /* Finally load the root hub driver */
 752  752          if (ohci_load_root_hub_driver(ohcip) != USB_SUCCESS) {
 753  753                  (void) ohci_cleanup(ohcip);
 754  754  
 755  755                  return (DDI_FAILURE);
 756  756          }
 757  757          ohcip->ohci_flags |= OHCI_RHREG;
 758  758  
 759  759          /* Display information in the banner */
 760  760          ddi_report_dev(dip);
 761  761  
 762  762          mutex_enter(&ohcip->ohci_int_mutex);
 763  763  
 764  764          /* Reset the ohci initilization flag */
 765  765          ohcip->ohci_flags &= ~OHCI_ATTACH;
 766  766  
 767  767          /* Print the Host Control's Operational registers */
 768  768          ohci_print_op_regs(ohcip);
 769  769  
 770  770          /* For RIO we need to call pci_report_pmcap */
 771  771          if (OHCI_IS_RIO(ohcip)) {
 772  772  
 773  773                  (void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000);
 774  774          }
 775  775  
 776  776          mutex_exit(&ohcip->ohci_int_mutex);
 777  777  
 778  778          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
 779  779              "ohci_attach: dip = 0x%p done", (void *)dip);
 780  780  
 781  781          return (DDI_SUCCESS);
 782  782  }
 783  783  
 784  784  
 785  785  /*
 786  786   * ohci_detach:
 787  787   */
 788  788  int
 789  789  ohci_detach(dev_info_t          *dip,
 790  790          ddi_detach_cmd_t        cmd)
 791  791  {
 792  792          ohci_state_t            *ohcip = ohci_obtain_state(dip);
 793  793  
 794  794          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_detach:");
 795  795  
 796  796          switch (cmd) {
 797  797          case DDI_DETACH:
 798  798  
 799  799                  return (ohci_cleanup(ohcip));
 800  800  
 801  801          case DDI_SUSPEND:
 802  802  
 803  803                  return (ohci_cpr_suspend(ohcip));
 804  804          default:
 805  805  
 806  806                  return (DDI_FAILURE);
 807  807          }
 808  808  }
 809  809  
 810  810  
 811  811  /*
 812  812   * ohci_info:
 813  813   */
 814  814  /* ARGSUSED */
 815  815  static int
 816  816  ohci_info(dev_info_t            *dip,
 817  817          ddi_info_cmd_t          infocmd,
 818  818          void                    *arg,
 819  819          void                    **result)
 820  820  {
 821  821          dev_t                   dev;
 822  822          ohci_state_t            *ohcip;
 823  823          int                     instance;
 824  824          int                     error = DDI_FAILURE;
 825  825  
 826  826          switch (infocmd) {
 827  827          case DDI_INFO_DEVT2DEVINFO:
 828  828                  dev = (dev_t)arg;
 829  829                  instance = OHCI_UNIT(dev);
 830  830                  ohcip = ddi_get_soft_state(ohci_statep, instance);
 831  831                  if (ohcip != NULL) {
 832  832                          *result = (void *)ohcip->ohci_dip;
 833  833                          if (*result != NULL) {
 834  834                                  error = DDI_SUCCESS;
 835  835                          }
 836  836                  } else {
 837  837                          *result = NULL;
 838  838                  }
 839  839  
 840  840                  break;
 841  841          case DDI_INFO_DEVT2INSTANCE:
 842  842                  dev = (dev_t)arg;
 843  843                  instance = OHCI_UNIT(dev);
 844  844                  *result = (void *)(uintptr_t)instance;
 845  845                  error = DDI_SUCCESS;
 846  846                  break;
 847  847          default:
 848  848                  break;
 849  849          }
 850  850  
 851  851          return (error);
 852  852  }
 853  853  
 854  854  
 855  855  /*
 856  856   * cb_ops entry points
 857  857   */
 858  858  static dev_info_t *
 859  859  ohci_get_dip(dev_t      dev)
 860  860  {
 861  861          int             instance = OHCI_UNIT(dev);
 862  862          ohci_state_t    *ohcip = ddi_get_soft_state(ohci_statep, instance);
 863  863  
 864  864          if (ohcip) {
 865  865  
 866  866                  return (ohcip->ohci_dip);
 867  867          } else {
 868  868  
 869  869                  return (NULL);
 870  870          }
 871  871  }
 872  872  
 873  873  
 874  874  static int
 875  875  ohci_open(dev_t         *devp,
 876  876          int             flags,
 877  877          int             otyp,
 878  878          cred_t          *credp)
 879  879  {
 880  880          dev_info_t      *dip = ohci_get_dip(*devp);
 881  881  
 882  882          return (usba_hubdi_open(dip, devp, flags, otyp, credp));
 883  883  }
 884  884  
 885  885  
 886  886  static int
 887  887  ohci_close(dev_t        dev,
 888  888          int             flag,
 889  889          int             otyp,
 890  890          cred_t          *credp)
 891  891  {
 892  892          dev_info_t      *dip = ohci_get_dip(dev);
 893  893  
 894  894          return (usba_hubdi_close(dip, dev, flag, otyp, credp));
 895  895  }
 896  896  
 897  897  
 898  898  static int
 899  899  ohci_ioctl(dev_t        dev,
 900  900          int             cmd,
 901  901          intptr_t        arg,
 902  902          int             mode,
 903  903          cred_t          *credp,
 904  904          int             *rvalp)
 905  905  {
 906  906          dev_info_t      *dip = ohci_get_dip(dev);
 907  907  
 908  908          return (usba_hubdi_ioctl(dip,
 909  909              dev, cmd, arg, mode, credp, rvalp));
 910  910  }
 911  911  
 912  912  
 913  913  /*
 914  914   * Host Controller Driver (HCD) initialization functions
 915  915   */
 916  916  
 917  917  /*
 918  918   * ohci_set_dma_attributes:
 919  919   *
 920  920   * Set the limits in the DMA attributes structure. Most of the values used
 921  921   * in the  DMA limit structres are the default values as specified by  the
 922  922   * Writing PCI device drivers document.
 923  923   */
 924  924  static void
 925  925  ohci_set_dma_attributes(ohci_state_t    *ohcip)
 926  926  {
 927  927          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
 928  928              "ohci_set_dma_attributes:");
 929  929  
 930  930          /* Initialize the DMA attributes */
 931  931          ohcip->ohci_dma_attr.dma_attr_version = DMA_ATTR_V0;
 932  932          ohcip->ohci_dma_attr.dma_attr_addr_lo = 0x00000000ull;
 933  933          ohcip->ohci_dma_attr.dma_attr_addr_hi = 0xfffffffeull;
 934  934  
 935  935          /* 32 bit addressing */
 936  936          ohcip->ohci_dma_attr.dma_attr_count_max = OHCI_DMA_ATTR_COUNT_MAX;
 937  937  
 938  938          /* Byte alignment */
 939  939          ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_ALIGNMENT;
 940  940  
 941  941          /*
 942  942           * Since PCI  specification is byte alignment, the
 943  943           * burstsize field should be set to 1 for PCI devices.
 944  944           */
 945  945          ohcip->ohci_dma_attr.dma_attr_burstsizes = 0x1;
 946  946  
 947  947          ohcip->ohci_dma_attr.dma_attr_minxfer = 0x1;
 948  948          ohcip->ohci_dma_attr.dma_attr_maxxfer = OHCI_DMA_ATTR_MAX_XFER;
 949  949          ohcip->ohci_dma_attr.dma_attr_seg = 0xffffffffull;
 950  950          ohcip->ohci_dma_attr.dma_attr_sgllen = 1;
 951  951          ohcip->ohci_dma_attr.dma_attr_granular = OHCI_DMA_ATTR_GRANULAR;
 952  952          ohcip->ohci_dma_attr.dma_attr_flags = 0;
 953  953  }
 954  954  
 955  955  
 956  956  /*
 957  957   * ohci_allocate_pools:
 958  958   *
 959  959   * Allocate the system memory for the Endpoint Descriptor (ED) and for the
 960  960   * Transfer Descriptor (TD) pools. Both ED and TD structures must be aligned
 961  961   * to a 16 byte boundary.
 962  962   */
 963  963  static int
 964  964  ohci_allocate_pools(ohci_state_t        *ohcip)
 965  965  {
 966  966          ddi_device_acc_attr_t           dev_attr;
 967  967          size_t                          real_length;
 968  968          int                             result;
 969  969          uint_t                          ccount;
 970  970          int                             i;
 971  971  
 972  972          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
 973  973              "ohci_allocate_pools:");
 974  974  
 975  975          /* The host controller will be little endian */
 976  976          dev_attr.devacc_attr_version    = DDI_DEVICE_ATTR_V0;
 977  977          dev_attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
 978  978          dev_attr.devacc_attr_dataorder  = DDI_STRICTORDER_ACC;
 979  979  
 980  980          /* Byte alignment to TD alignment */
 981  981          ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_TD_ALIGNMENT;
 982  982  
 983  983          /* Allocate the TD pool DMA handle */
 984  984          if (ddi_dma_alloc_handle(ohcip->ohci_dip, &ohcip->ohci_dma_attr,
 985  985              DDI_DMA_SLEEP, 0,
 986  986              &ohcip->ohci_td_pool_dma_handle) != DDI_SUCCESS) {
 987  987  
 988  988                  return (DDI_FAILURE);
 989  989          }
 990  990  
 991  991          /* Allocate the memory for the TD pool */
 992  992          if (ddi_dma_mem_alloc(ohcip->ohci_td_pool_dma_handle,
 993  993              ohci_td_pool_size * sizeof (ohci_td_t),
 994  994              &dev_attr,
 995  995              DDI_DMA_CONSISTENT,
 996  996              DDI_DMA_SLEEP,
 997  997              0,
 998  998              (caddr_t *)&ohcip->ohci_td_pool_addr,
 999  999              &real_length,
1000 1000              &ohcip->ohci_td_pool_mem_handle)) {
1001 1001  
1002 1002                  return (DDI_FAILURE);
1003 1003          }
1004 1004  
1005 1005          /* Map the TD pool into the I/O address space */
1006 1006          result = ddi_dma_addr_bind_handle(
1007 1007              ohcip->ohci_td_pool_dma_handle,
1008 1008              NULL,
1009 1009              (caddr_t)ohcip->ohci_td_pool_addr,
1010 1010              real_length,
1011 1011              DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1012 1012              DDI_DMA_SLEEP,
1013 1013              NULL,
1014 1014              &ohcip->ohci_td_pool_cookie,
1015 1015              &ccount);
1016 1016  
1017 1017          bzero((void *)ohcip->ohci_td_pool_addr,
1018 1018              ohci_td_pool_size * sizeof (ohci_td_t));
1019 1019  
1020 1020          /* Process the result */
1021 1021          if (result == DDI_DMA_MAPPED) {
1022 1022                  /* The cookie count should be 1 */
1023 1023                  if (ccount != 1) {
1024 1024                          USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1025 1025                              "ohci_allocate_pools: More than 1 cookie");
1026 1026  
1027 1027                          return (DDI_FAILURE);
1028 1028                  }
1029 1029          } else {
1030 1030                  USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1031 1031                      "ohci_allocate_pools: Result = %d", result);
1032 1032  
1033 1033                  ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
1034 1034  
1035 1035                  return (DDI_FAILURE);
1036 1036          }
1037 1037  
1038 1038          /*
1039 1039           * DMA addresses for TD pools are bound
1040 1040           */
1041 1041          ohcip->ohci_dma_addr_bind_flag |= OHCI_TD_POOL_BOUND;
1042 1042  
1043 1043          /* Initialize the TD pool */
1044 1044          for (i = 0; i < ohci_td_pool_size; i ++) {
1045 1045                  Set_TD(ohcip->ohci_td_pool_addr[i].hctd_state, HC_TD_FREE);
1046 1046          }
1047 1047  
1048 1048          /* Byte alignment to ED alignment */
1049 1049          ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_ED_ALIGNMENT;
1050 1050  
1051 1051          /* Allocate the ED pool DMA handle */
1052 1052          if (ddi_dma_alloc_handle(ohcip->ohci_dip,
1053 1053              &ohcip->ohci_dma_attr,
1054 1054              DDI_DMA_SLEEP,
1055 1055              0,
1056 1056              &ohcip->ohci_ed_pool_dma_handle) != DDI_SUCCESS) {
1057 1057  
1058 1058                  return (DDI_FAILURE);
1059 1059          }
1060 1060  
1061 1061          /* Allocate the memory for the ED pool */
1062 1062          if (ddi_dma_mem_alloc(ohcip->ohci_ed_pool_dma_handle,
1063 1063              ohci_ed_pool_size * sizeof (ohci_ed_t),
1064 1064              &dev_attr,
1065 1065              DDI_DMA_CONSISTENT,
1066 1066              DDI_DMA_SLEEP,
1067 1067              0,
1068 1068              (caddr_t *)&ohcip->ohci_ed_pool_addr,
1069 1069              &real_length,
1070 1070              &ohcip->ohci_ed_pool_mem_handle) != DDI_SUCCESS) {
1071 1071  
1072 1072                  return (DDI_FAILURE);
1073 1073          }
1074 1074  
1075 1075          result = ddi_dma_addr_bind_handle(ohcip->ohci_ed_pool_dma_handle,
1076 1076              NULL,
1077 1077              (caddr_t)ohcip->ohci_ed_pool_addr,
1078 1078              real_length,
1079 1079              DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1080 1080              DDI_DMA_SLEEP,
1081 1081              NULL,
1082 1082              &ohcip->ohci_ed_pool_cookie,
1083 1083              &ccount);
1084 1084  
1085 1085          bzero((void *)ohcip->ohci_ed_pool_addr,
1086 1086              ohci_ed_pool_size * sizeof (ohci_ed_t));
1087 1087  
1088 1088          /* Process the result */
1089 1089          if (result == DDI_DMA_MAPPED) {
1090 1090                  /* The cookie count should be 1 */
1091 1091                  if (ccount != 1) {
1092 1092                          USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1093 1093                              "ohci_allocate_pools: More than 1 cookie");
1094 1094  
1095 1095                          return (DDI_FAILURE);
1096 1096                  }
1097 1097          } else {
1098 1098                  ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
1099 1099  
1100 1100                  return (DDI_FAILURE);
1101 1101          }
1102 1102  
1103 1103          /*
1104 1104           * DMA addresses for ED pools are bound
1105 1105           */
1106 1106          ohcip->ohci_dma_addr_bind_flag |= OHCI_ED_POOL_BOUND;
1107 1107  
1108 1108          /* Initialize the ED pool */
1109 1109          for (i = 0; i < ohci_ed_pool_size; i ++) {
1110 1110                  Set_ED(ohcip->ohci_ed_pool_addr[i].hced_state, HC_EPT_FREE);
1111 1111          }
1112 1112  
1113 1113          return (DDI_SUCCESS);
1114 1114  }
1115 1115  
1116 1116  
1117 1117  /*
1118 1118   * ohci_decode_ddi_dma_addr_bind_handle_result:
1119 1119   *
1120 1120   * Process the return values of ddi_dma_addr_bind_handle()
1121 1121   */
1122 1122  static void
1123 1123  ohci_decode_ddi_dma_addr_bind_handle_result(
1124 1124          ohci_state_t    *ohcip,
1125 1125          int             result)
1126 1126  {
1127 1127          USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
1128 1128              "ohci_decode_ddi_dma_addr_bind_handle_result:");
1129 1129  
1130 1130          switch (result) {
1131 1131          case DDI_DMA_PARTIAL_MAP:
1132 1132                  USB_DPRINTF_L2(PRINT_MASK_ALL, ohcip->ohci_log_hdl,
1133 1133                      "Partial transfers not allowed");
1134 1134                  break;
1135 1135          case DDI_DMA_INUSE:
1136 1136                  USB_DPRINTF_L2(PRINT_MASK_ALL,  ohcip->ohci_log_hdl,
1137 1137                      "Handle is in use");
1138 1138                  break;
1139 1139          case DDI_DMA_NORESOURCES:
1140 1140                  USB_DPRINTF_L2(PRINT_MASK_ALL,  ohcip->ohci_log_hdl,
1141 1141                      "No resources");
1142 1142                  break;
1143 1143          case DDI_DMA_NOMAPPING:
1144 1144                  USB_DPRINTF_L2(PRINT_MASK_ALL,  ohcip->ohci_log_hdl,
1145 1145                      "No mapping");
1146 1146                  break;
1147 1147          case DDI_DMA_TOOBIG:
1148 1148                  USB_DPRINTF_L2(PRINT_MASK_ALL,  ohcip->ohci_log_hdl,
1149 1149                      "Object is too big");
1150 1150                  break;
1151 1151          default:
1152 1152                  USB_DPRINTF_L2(PRINT_MASK_ALL,  ohcip->ohci_log_hdl,
1153 1153                      "Unknown dma error");
1154 1154          }
1155 1155  }
1156 1156  
1157 1157  
1158 1158  /*
1159 1159   * ohci_map_regs:
1160 1160   *
1161 1161   * The Host Controller (HC) contains a set of on-chip operational registers
1162 1162   * and which should be mapped into a non-cacheable portion of the  system
1163 1163   * addressable space.
1164 1164   */
1165 1165  static int
1166 1166  ohci_map_regs(ohci_state_t      *ohcip)
1167 1167  {
1168 1168          ddi_device_acc_attr_t   attr;
1169 1169          uint16_t                cmd_reg;
1170 1170  
1171 1171          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_map_regs:");
1172 1172  
1173 1173          /* The host controller will be little endian */
1174 1174          attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1175 1175          attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
1176 1176          attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1177 1177  
1178 1178          /* Map in operational registers */
1179 1179          if (ddi_regs_map_setup(ohcip->ohci_dip, 1,
1180 1180              (caddr_t *)&ohcip->ohci_regsp, 0,
1181 1181              sizeof (ohci_regs_t), &attr,
1182 1182              &ohcip->ohci_regs_handle) != DDI_SUCCESS) {
1183 1183  
1184 1184                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1185 1185                      "ohci_map_regs: Map setup error");
1186 1186  
1187 1187                  return (DDI_FAILURE);
1188 1188          }
1189 1189  
1190 1190          if (pci_config_setup(ohcip->ohci_dip,
1191 1191              &ohcip->ohci_config_handle) != DDI_SUCCESS) {
1192 1192  
1193 1193                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1194 1194                      "ohci_map_regs: Config error");
1195 1195  
1196 1196                  return (DDI_FAILURE);
1197 1197          }
1198 1198  
1199 1199          /* Make sure Memory Access Enable and Master Enable are set */
1200 1200          cmd_reg = pci_config_get16(ohcip->ohci_config_handle, PCI_CONF_COMM);
1201 1201  
1202 1202          if (!(cmd_reg & PCI_COMM_MAE)) {
1203 1203  
1204 1204                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1205 1205                      "ohci_map_regs: Memory base address access disabled");
1206 1206  
1207 1207                  return (DDI_FAILURE);
1208 1208          }
1209 1209  
1210 1210          cmd_reg |= (PCI_COMM_MAE | PCI_COMM_ME);
1211 1211  
1212 1212          pci_config_put16(ohcip->ohci_config_handle, PCI_CONF_COMM, cmd_reg);
1213 1213  
1214 1214          return (DDI_SUCCESS);
1215 1215  }
1216 1216  
1217 1217  /*
1218 1218   * The following simulated polling is for debugging purposes only.
1219 1219   * It is activated on x86 by setting usb-polling=true in GRUB or ohci.conf.
1220 1220   */
1221 1221  static int
1222 1222  ohci_is_polled(dev_info_t *dip)
1223 1223  {
1224 1224          int ret;
1225 1225          char *propval;
1226 1226  
1227 1227          if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0,
1228 1228              "usb-polling", &propval) != DDI_SUCCESS)
1229 1229  
1230 1230                  return (0);
1231 1231  
1232 1232          ret = (strcmp(propval, "true") == 0);
1233 1233          ddi_prop_free(propval);
1234 1234  
1235 1235          return (ret);
1236 1236  }
1237 1237  
1238 1238  static void
1239 1239  ohci_poll_intr(void *arg)
1240 1240  {
1241 1241          /* poll every millisecond */
1242 1242          for (;;) {
1243 1243                  (void) ohci_intr(arg, NULL);
1244 1244                  delay(drv_usectohz(1000));
1245 1245          }
1246 1246  }
1247 1247  
1248 1248  /*
1249 1249   * ohci_register_intrs_and_init_mutex:
1250 1250   *
1251 1251   * Register interrupts and initialize each mutex and condition variables
1252 1252   */
1253 1253  static int
1254 1254  ohci_register_intrs_and_init_mutex(ohci_state_t *ohcip)
1255 1255  {
1256 1256          int     intr_types;
1257 1257  
1258 1258          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1259 1259              "ohci_register_intrs_and_init_mutex:");
1260 1260  
1261 1261          /*
1262 1262           * Sometimes the OHCI controller of ULI1575 southbridge
1263 1263           * could not receive SOF intrs when enable MSI. Hence
1264 1264           * MSI is disabled for this chip.
1265 1265           */
1266 1266          if ((ohcip->ohci_vendor_id == PCI_ULI1575_VENID) &&
1267 1267              (ohcip->ohci_device_id == PCI_ULI1575_DEVID)) {
1268 1268                  ohcip->ohci_msi_enabled = B_FALSE;
1269 1269          } else {
1270 1270                  ohcip->ohci_msi_enabled = ohci_enable_msi;
1271 1271          }
1272 1272  
1273 1273          if (ohci_is_polled(ohcip->ohci_dip)) {
1274 1274                  extern pri_t maxclsyspri;
1275 1275  
1276 1276                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1277 1277                      "ohci_register_intrs_and_init_mutex: "
1278 1278                      "running in simulated polled mode");
1279 1279  
1280 1280                  (void) thread_create(NULL, 0, ohci_poll_intr, ohcip, 0, &p0,
1281 1281                      TS_RUN, maxclsyspri);
1282 1282  
1283 1283                  goto skip_intr;
1284 1284          }
1285 1285  
1286 1286          /* Get supported interrupt types */
1287 1287          if (ddi_intr_get_supported_types(ohcip->ohci_dip,
1288 1288              &intr_types) != DDI_SUCCESS) {
1289 1289                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1290 1290                      "ohci_register_intrs_and_init_mutex: "
1291 1291                      "ddi_intr_get_supported_types failed");
1292 1292  
1293 1293                  return (DDI_FAILURE);
1294 1294          }
1295 1295  
1296 1296          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1297 1297              "ohci_register_intrs_and_init_mutex: "
1298 1298              "supported interrupt types 0x%x", intr_types);
1299 1299  
1300 1300          if ((intr_types & DDI_INTR_TYPE_MSI) && ohcip->ohci_msi_enabled) {
1301 1301                  if (ohci_add_intrs(ohcip, DDI_INTR_TYPE_MSI)
1302 1302                      != DDI_SUCCESS) {
1303 1303                          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1304 1304                              "ohci_register_intrs_and_init_mutex: MSI "
1305 1305                              "registration failed, trying FIXED interrupt \n");
1306 1306                  } else {
1307 1307                          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1308 1308                              "ohci_register_intrs_and_init_mutex: "
1309 1309                              "Using MSI interrupt type\n");
1310 1310  
1311 1311                          ohcip->ohci_intr_type = DDI_INTR_TYPE_MSI;
1312 1312                          ohcip->ohci_flags |= OHCI_INTR;
1313 1313                  }
1314 1314          }
1315 1315  
1316 1316          if ((!(ohcip->ohci_flags & OHCI_INTR)) &&
1317 1317              (intr_types & DDI_INTR_TYPE_FIXED)) {
1318 1318                  if (ohci_add_intrs(ohcip, DDI_INTR_TYPE_FIXED)
1319 1319                      != DDI_SUCCESS) {
1320 1320                          USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1321 1321                              "ohci_register_intrs_and_init_mutex: "
1322 1322                              "FIXED interrupt registration failed\n");
1323 1323  
1324 1324                          return (DDI_FAILURE);
1325 1325                  }
1326 1326  
1327 1327                  USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1328 1328                      "ohci_register_intrs_and_init_mutex: "
1329 1329                      "Using FIXED interrupt type\n");
1330 1330  
1331 1331                  ohcip->ohci_intr_type = DDI_INTR_TYPE_FIXED;
1332 1332                  ohcip->ohci_flags |= OHCI_INTR;
1333 1333          }
1334 1334  
1335 1335  skip_intr:
1336 1336          /* Create prototype for SOF condition variable */
1337 1337          cv_init(&ohcip->ohci_SOF_cv, NULL, CV_DRIVER, NULL);
1338 1338  
1339 1339          /* Semaphore to serialize opens and closes */
1340 1340          sema_init(&ohcip->ohci_ocsem, 1, NULL, SEMA_DRIVER, NULL);
1341 1341  
1342 1342          return (DDI_SUCCESS);
1343 1343  }
1344 1344  
1345 1345  
1346 1346  /*
1347 1347   * ohci_add_intrs:
1348 1348   *
1349 1349   * Register FIXED or MSI interrupts.
1350 1350   */
1351 1351  static int
1352 1352  ohci_add_intrs(ohci_state_t     *ohcip,
1353 1353                  int             intr_type)
1354 1354  {
1355 1355          int     actual, avail, intr_size, count = 0;
1356 1356          int     i, flag, ret;
1357 1357  
1358 1358          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1359 1359              "ohci_add_intrs: interrupt type 0x%x", intr_type);
1360 1360  
1361 1361          /* Get number of interrupts */
1362 1362          ret = ddi_intr_get_nintrs(ohcip->ohci_dip, intr_type, &count);
1363 1363          if ((ret != DDI_SUCCESS) || (count == 0)) {
1364 1364                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1365 1365                      "ohci_add_intrs: ddi_intr_get_nintrs() failure, "
1366 1366                      "ret: %d, count: %d", ret, count);
1367 1367  
1368 1368                  return (DDI_FAILURE);
1369 1369          }
1370 1370  
1371 1371          /* Get number of available interrupts */
1372 1372          ret = ddi_intr_get_navail(ohcip->ohci_dip, intr_type, &avail);
1373 1373          if ((ret != DDI_SUCCESS) || (avail == 0)) {
1374 1374                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1375 1375                      "ohci_add_intrs: ddi_intr_get_navail() failure, "
1376 1376                      "ret: %d, count: %d", ret, count);
1377 1377  
1378 1378                  return (DDI_FAILURE);
1379 1379          }
1380 1380  
1381 1381          if (avail < count) {
1382 1382                  USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1383 1383                      "ohci_add_intrs: ohci_add_intrs: nintrs () "
1384 1384                      "returned %d, navail returned %d\n", count, avail);
1385 1385          }
1386 1386  
1387 1387          /* Allocate an array of interrupt handles */
1388 1388          intr_size = count * sizeof (ddi_intr_handle_t);
1389 1389          ohcip->ohci_htable = kmem_zalloc(intr_size, KM_SLEEP);
1390 1390  
1391 1391          flag = (intr_type == DDI_INTR_TYPE_MSI) ?
1392 1392              DDI_INTR_ALLOC_STRICT:DDI_INTR_ALLOC_NORMAL;
1393 1393  
1394 1394          /* call ddi_intr_alloc() */
1395 1395          ret = ddi_intr_alloc(ohcip->ohci_dip, ohcip->ohci_htable,
1396 1396              intr_type, 0, count, &actual, flag);
1397 1397  
1398 1398          if ((ret != DDI_SUCCESS) || (actual == 0)) {
1399 1399                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1400 1400                      "ohci_add_intrs: ddi_intr_alloc() failed %d", ret);
1401 1401  
1402 1402                  kmem_free(ohcip->ohci_htable, intr_size);
1403 1403  
1404 1404                  return (DDI_FAILURE);
1405 1405          }
1406 1406  
1407 1407          if (actual < count) {
1408 1408                  USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1409 1409                      "ohci_add_intrs: Requested: %d, Received: %d\n",
1410 1410                      count, actual);
1411 1411  
1412 1412                  for (i = 0; i < actual; i++)
1413 1413                          (void) ddi_intr_free(ohcip->ohci_htable[i]);
1414 1414  
1415 1415                  kmem_free(ohcip->ohci_htable, intr_size);
1416 1416  
1417 1417                  return (DDI_FAILURE);
1418 1418          }
1419 1419  
1420 1420          ohcip->ohci_intr_cnt = actual;
1421 1421  
1422 1422          if ((ret = ddi_intr_get_pri(ohcip->ohci_htable[0],
1423 1423              &ohcip->ohci_intr_pri)) != DDI_SUCCESS) {
1424 1424                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1425 1425                      "ohci_add_intrs: ddi_intr_get_pri() failed %d", ret);
1426 1426  
1427 1427                  for (i = 0; i < actual; i++)
1428 1428                          (void) ddi_intr_free(ohcip->ohci_htable[i]);
1429 1429  
1430 1430                  kmem_free(ohcip->ohci_htable, intr_size);
1431 1431  
1432 1432                  return (DDI_FAILURE);
1433 1433          }
1434 1434  
1435 1435          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1436 1436              "ohci_add_intrs: Supported Interrupt priority 0x%x",
1437 1437              ohcip->ohci_intr_pri);
1438 1438  
1439 1439          /* Test for high level mutex */
1440 1440          if (ohcip->ohci_intr_pri >= ddi_intr_get_hilevel_pri()) {
1441 1441                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1442 1442                      "ohci_add_intrs: Hi level interrupt not supported");
1443 1443  
1444 1444                  for (i = 0; i < actual; i++)
1445 1445                          (void) ddi_intr_free(ohcip->ohci_htable[i]);
1446 1446  
1447 1447                  kmem_free(ohcip->ohci_htable, intr_size);
1448 1448  
1449 1449                  return (DDI_FAILURE);
1450 1450          }
1451 1451  
1452 1452          /* Initialize the mutex */
1453 1453          mutex_init(&ohcip->ohci_int_mutex, NULL, MUTEX_DRIVER,
1454 1454              DDI_INTR_PRI(ohcip->ohci_intr_pri));
1455 1455  
1456 1456          /* Call ddi_intr_add_handler() */
1457 1457          for (i = 0; i < actual; i++) {
1458 1458                  if ((ret = ddi_intr_add_handler(ohcip->ohci_htable[i],
1459 1459                      ohci_intr, (caddr_t)ohcip,
1460 1460                      (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) {
1461 1461                          USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1462 1462                              "ohci_add_intrs: ddi_intr_add_handler() "
1463 1463                              "failed %d", ret);
1464 1464  
1465 1465                          for (i = 0; i < actual; i++)
1466 1466                                  (void) ddi_intr_free(ohcip->ohci_htable[i]);
1467 1467  
1468 1468                          mutex_destroy(&ohcip->ohci_int_mutex);
1469 1469                          kmem_free(ohcip->ohci_htable, intr_size);
1470 1470  
1471 1471                          return (DDI_FAILURE);
1472 1472                  }
1473 1473          }
1474 1474  
1475 1475          if ((ret = ddi_intr_get_cap(ohcip->ohci_htable[0],
1476 1476              &ohcip->ohci_intr_cap)) != DDI_SUCCESS) {
1477 1477                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1478 1478                      "ohci_add_intrs: ddi_intr_get_cap() failed %d", ret);
1479 1479  
1480 1480                  for (i = 0; i < actual; i++) {
1481 1481                          (void) ddi_intr_remove_handler(ohcip->ohci_htable[i]);
1482 1482                          (void) ddi_intr_free(ohcip->ohci_htable[i]);
1483 1483                  }
1484 1484  
1485 1485                  mutex_destroy(&ohcip->ohci_int_mutex);
1486 1486                  kmem_free(ohcip->ohci_htable, intr_size);
1487 1487  
1488 1488                  return (DDI_FAILURE);
1489 1489          }
1490 1490  
1491 1491          /* Enable all interrupts */
1492 1492          if (ohcip->ohci_intr_cap & DDI_INTR_FLAG_BLOCK) {
1493 1493                  /* Call ddi_intr_block_enable() for MSI interrupts */
1494 1494                  (void) ddi_intr_block_enable(ohcip->ohci_htable,
1495 1495                      ohcip->ohci_intr_cnt);
1496 1496          } else {
1497 1497                  /* Call ddi_intr_enable for MSI or FIXED interrupts */
1498 1498                  for (i = 0; i < ohcip->ohci_intr_cnt; i++)
1499 1499                          (void) ddi_intr_enable(ohcip->ohci_htable[i]);
1500 1500          }
1501 1501  
1502 1502          return (DDI_SUCCESS);
1503 1503  }
1504 1504  
1505 1505  
1506 1506  /*
1507 1507   * ohci_init_ctlr:
1508 1508   *
1509 1509   * Initialize the Host Controller (HC).
1510 1510   */
1511 1511  static int
1512 1512  ohci_init_ctlr(ohci_state_t     *ohcip)
1513 1513  {
1514 1514          int                     revision, curr_control, max_packet = 0;
1515 1515          clock_t                 sof_time_wait;
1516 1516          int                     retry = 0;
1517 1517          int                     ohci_frame_interval;
1518 1518  
1519 1519          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_init_ctlr:");
1520 1520  
1521 1521          if (ohci_take_control(ohcip) != DDI_SUCCESS) {
1522 1522                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1523 1523                      "ohci_init_ctlr: ohci_take_control failed\n");
1524 1524  
1525 1525                  return (DDI_FAILURE);
1526 1526          }
1527 1527  
1528 1528          /*
1529 1529           * Soft reset the host controller.
1530 1530           *
1531 1531           * On soft reset, the ohci host controller moves to the
1532 1532           * USB Suspend state in which most of the ohci operational
1533 1533           * registers are reset except stated ones. The soft reset
1534 1534           * doesn't cause a reset to the ohci root hub and even no
1535 1535           * subsequent reset signaling should be asserterd to its
1536 1536           * down stream.
1537 1537           */
1538 1538          Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
1539 1539  
1540 1540          mutex_exit(&ohcip->ohci_int_mutex);
1541 1541          /* Wait 10ms for reset to complete */
1542 1542          delay(drv_usectohz(OHCI_RESET_TIMEWAIT));
1543 1543          mutex_enter(&ohcip->ohci_int_mutex);
1544 1544  
1545 1545          /*
1546 1546           * Do hard reset the host controller.
1547 1547           *
1548 1548           * Now perform USB reset in order to reset the ohci root
1549 1549           * hub.
1550 1550           */
1551 1551          Set_OpReg(hcr_control, HCR_CONTROL_RESET);
1552 1552  
1553 1553          /*
1554 1554           * According to Section 5.1.2.3 of the specification, the
1555 1555           * host controller will go into suspend state immediately
1556 1556           * after the reset.
1557 1557           */
1558 1558  
1559 1559          /* Verify the version number */
1560 1560          revision = Get_OpReg(hcr_revision);
1561 1561  
1562 1562          if ((revision & HCR_REVISION_MASK) != HCR_REVISION_1_0) {
1563 1563  
1564 1564                  return (DDI_FAILURE);
1565 1565          }
1566 1566  
1567 1567          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1568 1568              "ohci_init_ctlr: Revision verified");
1569 1569  
1570 1570          /* hcca area need not be initialized on resume */
1571 1571          if (ohcip->ohci_hc_soft_state == OHCI_CTLR_INIT_STATE) {
1572 1572  
1573 1573                  /* Initialize the hcca area */
1574 1574                  if (ohci_init_hcca(ohcip) != DDI_SUCCESS) {
1575 1575  
1576 1576                          return (DDI_FAILURE);
1577 1577                  }
1578 1578          }
1579 1579  
1580 1580          /*
1581 1581           * Workaround for ULI1575 chipset. Following OHCI Operational Memory
1582 1582           * Registers are not cleared to their default value on reset.
1583 1583           * Explicitly set the registers to default value.
1584 1584           */
1585 1585          if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
1586 1586              ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
1587 1587                  Set_OpReg(hcr_control, HCR_CONTROL_DEFAULT);
1588 1588                  Set_OpReg(hcr_intr_enable, HCR_INT_ENABLE_DEFAULT);
1589 1589                  Set_OpReg(hcr_HCCA, HCR_HCCA_DEFAULT);
1590 1590                  Set_OpReg(hcr_ctrl_head, HCR_CONTROL_HEAD_ED_DEFAULT);
1591 1591                  Set_OpReg(hcr_bulk_head, HCR_BULK_HEAD_ED_DEFAULT);
1592 1592                  Set_OpReg(hcr_frame_interval, HCR_FRAME_INTERVAL_DEFAULT);
1593 1593                  Set_OpReg(hcr_periodic_strt, HCR_PERIODIC_START_DEFAULT);
1594 1594          }
1595 1595  
1596 1596          /* Set the HcHCCA to the physical address of the HCCA block */
1597 1597          Set_OpReg(hcr_HCCA, (uint_t)ohcip->ohci_hcca_cookie.dmac_address);
1598 1598  
1599 1599          /*
1600 1600           * Set HcInterruptEnable to enable all interrupts except Root
1601 1601           * Hub Status change and SOF interrupts.
1602 1602           */
1603 1603          Set_OpReg(hcr_intr_enable, HCR_INTR_SO | HCR_INTR_WDH |
1604 1604              HCR_INTR_RD | HCR_INTR_UE | HCR_INTR_FNO | HCR_INTR_MIE);
1605 1605  
1606 1606          /*
1607 1607           * For non-periodic transfers, reserve atleast for one low-speed
1608 1608           * device transaction. According to USB Bandwidth Analysis white
1609 1609           * paper and also as per OHCI Specification 1.0a, section 7.3.5,
1610 1610           * page 123, one low-speed transaction takes 0x628h full speed
1611 1611           * bits (197 bytes), which comes to around 13% of USB frame time.
1612 1612           *
1613 1613           * The periodic transfers will get around 87% of USB frame time.
1614 1614           */
1615 1615          Set_OpReg(hcr_periodic_strt,
1616 1616              ((PERIODIC_XFER_STARTS * BITS_PER_BYTE) - 1));
1617 1617  
1618 1618          /* Save the contents of the Frame Interval Registers */
1619 1619          ohcip->ohci_frame_interval = Get_OpReg(hcr_frame_interval);
1620 1620  
1621 1621          /*
1622 1622           * Initialize the FSLargestDataPacket value in the frame interval
1623 1623           * register. The controller compares the value of MaxPacketSize to
1624 1624           * this value to see if the entire packet may be sent out before
1625 1625           * the EOF.
1626 1626           */
1627 1627          max_packet = ((((ohcip->ohci_frame_interval -
1628 1628              MAX_OVERHEAD) * 6) / 7) << HCR_FRME_FSMPS_SHFT);
1629 1629  
1630 1630          Set_OpReg(hcr_frame_interval,
1631 1631              (max_packet | ohcip->ohci_frame_interval));
1632 1632  
1633 1633          /*
1634 1634           * Sometimes the HcFmInterval register in OHCI controller does not
1635 1635           * maintain its value after the first write. This problem is found
1636 1636           * on ULI M1575 South Bridge. To workaround the hardware problem,
1637 1637           * check the value after write and retry if the last write failed.
1638 1638           */
1639 1639          if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
1640 1640              ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
1641 1641                  ohci_frame_interval = Get_OpReg(hcr_frame_interval);
1642 1642                  while ((ohci_frame_interval != (max_packet |
1643 1643                      ohcip->ohci_frame_interval))) {
1644 1644                          if (retry >= 10) {
1645 1645                                  USB_DPRINTF_L1(PRINT_MASK_ATTA,
1646 1646                                      ohcip->ohci_log_hdl, "Failed to program"
1647 1647                                      " Frame Interval Register.");
1648 1648  
1649 1649                                  return (DDI_FAILURE);
1650 1650                          }
1651 1651                          retry++;
1652 1652                          USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1653 1653                              "ohci_init_ctlr: Failed to program Frame"
1654 1654                              " Interval Register, retry=%d", retry);
1655 1655                          Set_OpReg(hcr_frame_interval,
1656 1656                              (max_packet | ohcip->ohci_frame_interval));
1657 1657                          ohci_frame_interval = Get_OpReg(hcr_frame_interval);
1658 1658                  }
1659 1659          }
1660 1660  
1661 1661          /* Begin sending SOFs */
1662 1662          curr_control = Get_OpReg(hcr_control);
1663 1663  
1664 1664          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1665 1665              "ohci_init_ctlr: curr_control=0x%x", curr_control);
1666 1666  
1667 1667          /* Set the state to operational */
1668 1668          curr_control = (curr_control &
1669 1669              (~HCR_CONTROL_HCFS)) | HCR_CONTROL_OPERAT;
1670 1670  
1671 1671          Set_OpReg(hcr_control, curr_control);
1672 1672  
1673 1673          ASSERT((Get_OpReg(hcr_control) &
1674 1674              HCR_CONTROL_HCFS) == HCR_CONTROL_OPERAT);
1675 1675  
1676 1676          /* Set host controller soft state to operational */
1677 1677          ohcip->ohci_hc_soft_state = OHCI_CTLR_OPERATIONAL_STATE;
1678 1678  
1679 1679          /* Get the number of clock ticks to wait */
1680 1680          sof_time_wait = drv_usectohz(OHCI_MAX_SOF_TIMEWAIT * 1000000);
1681 1681  
1682 1682          /* Clear ohci_sof_flag indicating waiting for SOF interrupt */
1683 1683          ohcip->ohci_sof_flag = B_FALSE;
1684 1684  
1685 1685          /* Enable the SOF interrupt */
1686 1686          Set_OpReg(hcr_intr_enable, HCR_INTR_SOF);
1687 1687  
1688 1688          ASSERT(Get_OpReg(hcr_intr_enable) & HCR_INTR_SOF);
1689 1689  
1690 1690          (void) cv_reltimedwait(&ohcip->ohci_SOF_cv,
1691 1691              &ohcip->ohci_int_mutex, sof_time_wait, TR_CLOCK_TICK);
1692 1692  
1693 1693          /* Wait for the SOF or timeout event */
1694 1694          if (ohcip->ohci_sof_flag == B_FALSE) {
1695 1695  
1696 1696                  /* Set host controller soft state to error */
1697 1697                  ohcip->ohci_hc_soft_state = OHCI_CTLR_ERROR_STATE;
1698 1698  
1699 1699                  USB_DPRINTF_L0(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1700 1700                      "No SOF interrupts have been received, this USB OHCI host"
1701 1701                      "controller is unusable");
1702 1702                  return (DDI_FAILURE);
1703 1703          }
1704 1704  
1705 1705          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1706 1706              "ohci_init_ctlr: SOF's have started");
1707 1707  
1708 1708          return (DDI_SUCCESS);
1709 1709  }
1710 1710  
1711 1711  
1712 1712  /*
1713 1713   * ohci_init_hcca:
1714 1714   *
1715 1715   * Allocate the system memory and initialize Host Controller Communication
1716 1716   * Area (HCCA). The HCCA structure must be aligned to a 256-byte boundary.
1717 1717   */
1718 1718  static int
1719 1719  ohci_init_hcca(ohci_state_t     *ohcip)
1720 1720  {
1721 1721          ddi_device_acc_attr_t   dev_attr;
1722 1722          size_t                  real_length;
1723 1723          uint_t                  mask, ccount;
1724 1724          int                     result;
1725 1725          uintptr_t               addr;
1726 1726  
1727 1727          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
1728 1728  
1729 1729          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_init_hcca:");
1730 1730  
1731 1731          /* The host controller will be little endian */
1732 1732          dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1733 1733          dev_attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
1734 1734          dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1735 1735  
1736 1736          /* Byte alignment to HCCA alignment */
1737 1737          ohcip->ohci_dma_attr.dma_attr_align = OHCI_DMA_ATTR_HCCA_ALIGNMENT;
1738 1738  
1739 1739          /* Create space for the HCCA block */
1740 1740          if (ddi_dma_alloc_handle(ohcip->ohci_dip, &ohcip->ohci_dma_attr,
1741 1741              DDI_DMA_SLEEP,
1742 1742              0,
1743 1743              &ohcip->ohci_hcca_dma_handle)
1744 1744              != DDI_SUCCESS) {
1745 1745  
1746 1746                  return (DDI_FAILURE);
1747 1747          }
1748 1748  
1749 1749          if (ddi_dma_mem_alloc(ohcip->ohci_hcca_dma_handle,
1750 1750              2 * sizeof (ohci_hcca_t),
1751 1751              &dev_attr,
1752 1752              DDI_DMA_CONSISTENT,
1753 1753              DDI_DMA_SLEEP,
1754 1754              0,
1755 1755              (caddr_t *)&ohcip->ohci_hccap,
1756 1756              &real_length,
1757 1757              &ohcip->ohci_hcca_mem_handle)) {
1758 1758  
1759 1759                  return (DDI_FAILURE);
1760 1760          }
1761 1761  
1762 1762          bzero((void *)ohcip->ohci_hccap, real_length);
1763 1763  
1764 1764          /* Figure out the alignment requirements */
1765 1765          Set_OpReg(hcr_HCCA, 0xFFFFFFFF);
1766 1766  
1767 1767          /*
1768 1768           * Read the hcr_HCCA register until
1769 1769           * contenets are non-zero.
1770 1770           */
1771 1771          mask = Get_OpReg(hcr_HCCA);
1772 1772  
1773 1773          mutex_exit(&ohcip->ohci_int_mutex);
1774 1774          while (mask == 0) {
1775 1775                  delay(drv_usectohz(OHCI_TIMEWAIT));
1776 1776                  mask = Get_OpReg(hcr_HCCA);
1777 1777          }
1778 1778          mutex_enter(&ohcip->ohci_int_mutex);
1779 1779  
1780 1780          ASSERT(mask != 0);
1781 1781  
1782 1782          addr = (uintptr_t)ohcip->ohci_hccap;
1783 1783  
1784 1784          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1785 1785              "ohci_init_hcca: addr=0x%lx, mask=0x%x", addr, mask);
1786 1786  
1787 1787          while (addr & (~mask)) {
1788 1788                  addr++;
1789 1789          }
1790 1790  
1791 1791          ohcip->ohci_hccap = (ohci_hcca_t *)addr;
1792 1792  
1793 1793          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1794 1794              "ohci_init_hcca: Real length %lu", real_length);
1795 1795  
1796 1796          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1797 1797              "ohci_init_hcca: virtual hcca 0x%p", (void *)ohcip->ohci_hccap);
1798 1798  
1799 1799          /* Map the whole HCCA into the I/O address space */
1800 1800          result = ddi_dma_addr_bind_handle(ohcip->ohci_hcca_dma_handle,
1801 1801              NULL,
1802 1802              (caddr_t)ohcip->ohci_hccap,
1803 1803              real_length,
1804 1804              DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
1805 1805              DDI_DMA_SLEEP, NULL,
1806 1806              &ohcip->ohci_hcca_cookie,
1807 1807              &ccount);
1808 1808  
1809 1809          if (result == DDI_DMA_MAPPED) {
1810 1810                  /* The cookie count should be 1 */
1811 1811                  if (ccount != 1) {
1812 1812                          USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1813 1813                              "ohci_init_hcca: More than 1 cookie");
1814 1814  
1815 1815                          return (DDI_FAILURE);
1816 1816                  }
1817 1817          } else {
1818 1818                  ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
1819 1819  
1820 1820                  return (DDI_FAILURE);
1821 1821          }
1822 1822  
1823 1823          /*
1824 1824           * DMA addresses for HCCA are bound
1825 1825           */
1826 1826          ohcip->ohci_dma_addr_bind_flag |= OHCI_HCCA_DMA_BOUND;
1827 1827  
1828 1828          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1829 1829              "ohci_init_hcca: physical 0x%p",
1830 1830              (void *)(uintptr_t)ohcip->ohci_hcca_cookie.dmac_address);
1831 1831  
1832 1832          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1833 1833              "ohci_init_hcca: size %lu", ohcip->ohci_hcca_cookie.dmac_size);
1834 1834  
1835 1835          /* Initialize the interrupt lists */
1836 1836          ohci_build_interrupt_lattice(ohcip);
1837 1837  
1838 1838          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1839 1839              "ohci_init_hcca: End");
1840 1840  
1841 1841          return (DDI_SUCCESS);
1842 1842  }
1843 1843  
1844 1844  
1845 1845  /*
1846 1846   * ohci_build_interrupt_lattice:
1847 1847   *
1848 1848   * Construct the interrupt lattice tree using static Endpoint Descriptors
1849 1849   * (ED). This interrupt lattice tree will have total of 32 interrupt  ED
1850 1850   * lists and the Host Controller (HC) processes one interrupt ED list in
1851 1851   * every frame. The lower five bits of the current frame number indexes
1852 1852   * into an array of 32 interrupt Endpoint Descriptor lists found in the
1853 1853   * HCCA.
1854 1854   */
1855 1855  static void
1856 1856  ohci_build_interrupt_lattice(ohci_state_t       *ohcip)
1857 1857  {
1858 1858          ohci_ed_t       *list_array = ohcip->ohci_ed_pool_addr;
1859 1859          int             half_list = NUM_INTR_ED_LISTS / 2;
1860 1860          ohci_hcca_t     *hccap = ohcip->ohci_hccap;
1861 1861          uintptr_t       addr;
1862 1862          int             i;
1863 1863  
1864 1864          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1865 1865              "ohci_build_interrupt_lattice:");
1866 1866  
1867 1867          /*
1868 1868           * Reserve the first 31 Endpoint Descriptor (ED) structures
1869 1869           * in the pool as static endpoints & these are required for
1870 1870           * constructing interrupt lattice tree.
1871 1871           */
1872 1872          for (i = 0; i < NUM_STATIC_NODES; i++) {
1873 1873                  Set_ED(list_array[i].hced_ctrl, HC_EPT_sKip);
1874 1874  
1875 1875                  Set_ED(list_array[i].hced_state, HC_EPT_STATIC);
1876 1876          }
1877 1877  
1878 1878          /* Build the interrupt lattice tree */
1879 1879          for (i = 0; i < half_list - 1; i++) {
1880 1880  
1881 1881                  /*
1882 1882                   * The next  pointer in the host controller  endpoint
1883 1883                   * descriptor must contain an iommu address. Calculate
1884 1884                   * the offset into the cpu address and add this to the
1885 1885                   * starting iommu address.
1886 1886                   */
1887 1887                  addr = ohci_ed_cpu_to_iommu(ohcip, (ohci_ed_t *)&list_array[i]);
1888 1888  
1889 1889                  Set_ED(list_array[2*i + 1].hced_next, addr);
1890 1890                  Set_ED(list_array[2*i + 2].hced_next, addr);
1891 1891          }
1892 1892  
1893 1893          /*
1894 1894           * Initialize the interrupt list in the HCCA so that it points
1895 1895           * to the bottom of the tree.
1896 1896           */
1897 1897          for (i = 0; i < half_list; i++) {
1898 1898                  addr = ohci_ed_cpu_to_iommu(ohcip,
1899 1899                      (ohci_ed_t *)&list_array[half_list - 1 + ohci_index[i]]);
1900 1900  
1901 1901                  ASSERT(Get_ED(list_array[half_list - 1 +
1902 1902                      ohci_index[i]].hced_ctrl));
1903 1903  
1904 1904                  ASSERT(addr != 0);
1905 1905  
1906 1906                  Set_HCCA(hccap->HccaIntTble[i], addr);
1907 1907                  Set_HCCA(hccap->HccaIntTble[i + half_list], addr);
1908 1908          }
1909 1909  }
1910 1910  
1911 1911  
1912 1912  /*
1913 1913   * ohci_take_control:
1914 1914   *
1915 1915   * Take control of the host controller. OpenHCI allows for optional support
1916 1916   * of legacy devices through the use of System Management Mode software and
1917 1917   * system Management interrupt hardware. See section 5.1.1.3 of the OpenHCI
1918 1918   * spec for more details.
1919 1919   */
1920 1920  static int
1921 1921  ohci_take_control(ohci_state_t  *ohcip)
1922 1922  {
1923 1923  #if defined(__x86)
1924 1924          uint32_t hcr_control_val;
1925 1925          uint32_t hcr_cmd_status_val;
1926 1926          int wait;
1927 1927  #endif  /* __x86 */
1928 1928  
1929 1929          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1930 1930              "ohci_take_control:");
1931 1931  
1932 1932  #if defined(__x86)
1933 1933          /*
1934 1934           * On x86, we must tell the BIOS we want the controller,
1935 1935           * and wait for it to respond that we can have it.
1936 1936           */
1937 1937          hcr_control_val = Get_OpReg(hcr_control);
1938 1938          if ((hcr_control_val & HCR_CONTROL_IR) == 0) {
1939 1939                  USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1940 1940                      "ohci_take_control: InterruptRouting off\n");
1941 1941  
1942 1942                  return (DDI_SUCCESS);
1943 1943          }
1944 1944  
1945 1945          /* attempt the OwnershipChange request */
1946 1946          hcr_cmd_status_val = Get_OpReg(hcr_cmd_status);
1947 1947          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1948 1948              "ohci_take_control: hcr_cmd_status: 0x%x\n",
1949 1949              hcr_cmd_status_val);
1950 1950          hcr_cmd_status_val |= HCR_STATUS_OCR;
1951 1951  
1952 1952          Set_OpReg(hcr_cmd_status, hcr_cmd_status_val);
1953 1953  
1954 1954  
1955 1955          mutex_exit(&ohcip->ohci_int_mutex);
1956 1956          /* now wait for 5 seconds for InterruptRouting to go away */
1957 1957          for (wait = 0; wait < 5000; wait++) {
1958 1958                  if ((Get_OpReg(hcr_control) & HCR_CONTROL_IR) == 0)
1959 1959                          break;
1960 1960                  delay(drv_usectohz(1000));
1961 1961          }
1962 1962          mutex_enter(&ohcip->ohci_int_mutex);
1963 1963  
1964 1964          if (wait >= 5000) {
1965 1965                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1966 1966                      "ohci_take_control: couldn't take control from BIOS\n");
1967 1967  
1968 1968                  return (DDI_FAILURE);
1969 1969          }
1970 1970  #else   /* __x86 */
1971 1971          /*
1972 1972           * On Sparc, there won't be  special System Management Mode
1973 1973           * hardware for legacy devices, while the x86 platforms may
1974 1974           * have to deal with  this. This  function may be  platform
1975 1975           * specific.
1976 1976           *
1977 1977           * The interrupt routing bit should not be set.
1978 1978           */
1979 1979          if (Get_OpReg(hcr_control) & HCR_CONTROL_IR) {
1980 1980                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1981 1981                      "ohci_take_control: Routing bit set");
1982 1982  
1983 1983                  return (DDI_FAILURE);
1984 1984          }
1985 1985  #endif  /* __x86 */
1986 1986  
1987 1987          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
1988 1988              "ohci_take_control: End");
1989 1989  
1990 1990          return (DDI_SUCCESS);
1991 1991  }
1992 1992  
1993 1993  /*
1994 1994   * ohci_pm_support:
1995 1995   *      always return success since PM has been quite reliable on ohci
1996 1996   */
1997 1997  /*ARGSUSED*/
1998 1998  int
1999 1999  ohci_hcdi_pm_support(dev_info_t *dip)
2000 2000  {
2001 2001          return (USB_SUCCESS);
2002 2002  }
2003 2003  
2004 2004  /*
2005 2005   * ohci_alloc_hcdi_ops:
2006 2006   *
2007 2007   * The HCDI interfaces or entry points are the software interfaces used by
2008 2008   * the Universal Serial Bus Driver  (USBA) to  access the services of the
2009 2009   * Host Controller Driver (HCD).  During HCD initialization, inform  USBA
2010 2010   * about all available HCDI interfaces or entry points.
2011 2011   */
2012 2012  static usba_hcdi_ops_t *
2013 2013  ohci_alloc_hcdi_ops(ohci_state_t        *ohcip)
2014 2014  {
2015 2015          usba_hcdi_ops_t                 *usba_hcdi_ops;
2016 2016  
2017 2017          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2018 2018              "ohci_alloc_hcdi_ops:");
2019 2019  
2020 2020          usba_hcdi_ops = usba_alloc_hcdi_ops();
2021 2021  
2022 2022          usba_hcdi_ops->usba_hcdi_ops_version = HCDI_OPS_VERSION;
2023 2023  
2024 2024          usba_hcdi_ops->usba_hcdi_pm_support = ohci_hcdi_pm_support;
2025 2025          usba_hcdi_ops->usba_hcdi_pipe_open = ohci_hcdi_pipe_open;
2026 2026          usba_hcdi_ops->usba_hcdi_pipe_close = ohci_hcdi_pipe_close;
2027 2027  
2028 2028          usba_hcdi_ops->usba_hcdi_pipe_reset = ohci_hcdi_pipe_reset;
2029 2029          usba_hcdi_ops->usba_hcdi_pipe_reset_data_toggle =
2030 2030              ohci_hcdi_pipe_reset_data_toggle;
2031 2031  
2032 2032          usba_hcdi_ops->usba_hcdi_pipe_ctrl_xfer = ohci_hcdi_pipe_ctrl_xfer;
2033 2033          usba_hcdi_ops->usba_hcdi_pipe_bulk_xfer = ohci_hcdi_pipe_bulk_xfer;
2034 2034          usba_hcdi_ops->usba_hcdi_pipe_intr_xfer = ohci_hcdi_pipe_intr_xfer;
2035 2035          usba_hcdi_ops->usba_hcdi_pipe_isoc_xfer = ohci_hcdi_pipe_isoc_xfer;
2036 2036  
2037 2037          usba_hcdi_ops->usba_hcdi_bulk_transfer_size =
2038 2038              ohci_hcdi_bulk_transfer_size;
2039 2039  
2040 2040          usba_hcdi_ops->usba_hcdi_pipe_stop_intr_polling =
2041 2041              ohci_hcdi_pipe_stop_intr_polling;
2042 2042          usba_hcdi_ops->usba_hcdi_pipe_stop_isoc_polling =
2043 2043              ohci_hcdi_pipe_stop_isoc_polling;
2044 2044  
2045 2045          usba_hcdi_ops->usba_hcdi_get_current_frame_number =
2046 2046              ohci_hcdi_get_current_frame_number;
2047 2047          usba_hcdi_ops->usba_hcdi_get_max_isoc_pkts =
2048 2048              ohci_hcdi_get_max_isoc_pkts;
2049 2049          usba_hcdi_ops->usba_hcdi_console_input_init =
2050 2050              ohci_hcdi_polled_input_init;
2051 2051          usba_hcdi_ops->usba_hcdi_console_input_enter =
2052 2052              ohci_hcdi_polled_input_enter;
2053 2053          usba_hcdi_ops->usba_hcdi_console_read = ohci_hcdi_polled_read;
2054 2054          usba_hcdi_ops->usba_hcdi_console_input_exit =
2055 2055              ohci_hcdi_polled_input_exit;
2056 2056          usba_hcdi_ops->usba_hcdi_console_input_fini =
2057 2057              ohci_hcdi_polled_input_fini;
2058 2058  
2059 2059          usba_hcdi_ops->usba_hcdi_console_output_init =
2060 2060              ohci_hcdi_polled_output_init;
2061 2061          usba_hcdi_ops->usba_hcdi_console_output_enter =
2062 2062              ohci_hcdi_polled_output_enter;
2063 2063          usba_hcdi_ops->usba_hcdi_console_write = ohci_hcdi_polled_write;
2064 2064          usba_hcdi_ops->usba_hcdi_console_output_exit =
2065 2065              ohci_hcdi_polled_output_exit;
2066 2066          usba_hcdi_ops->usba_hcdi_console_output_fini =
2067 2067              ohci_hcdi_polled_output_fini;
2068 2068  
2069 2069          return (usba_hcdi_ops);
2070 2070  }
2071 2071  
2072 2072  
2073 2073  /*
2074 2074   * Host Controller Driver (HCD) deinitialization functions
2075 2075   */
2076 2076  
2077 2077  /*
2078 2078   * ohci_cleanup:
2079 2079   *
2080 2080   * Cleanup on attach failure or detach
2081 2081   */
2082 2082  static int
2083 2083  ohci_cleanup(ohci_state_t       *ohcip)
2084 2084  {
2085 2085          ohci_trans_wrapper_t    *tw;
2086 2086          ohci_pipe_private_t     *pp;
2087 2087          ohci_td_t               *td;
2088 2088          int                     i, state, rval;
2089 2089          int                     flags = ohcip->ohci_flags;
2090 2090  
2091 2091          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl, "ohci_cleanup:");
2092 2092  
2093 2093          if (flags & OHCI_RHREG) {
2094 2094                  /* Unload the root hub driver */
2095 2095                  if (ohci_unload_root_hub_driver(ohcip) != USB_SUCCESS) {
2096 2096  
2097 2097                          return (DDI_FAILURE);
2098 2098                  }
2099 2099          }
2100 2100  
2101 2101          if (flags & OHCI_USBAREG) {
2102 2102                  /* Unregister this HCD instance with USBA */
2103 2103                  usba_hcdi_unregister(ohcip->ohci_dip);
2104 2104          }
2105 2105  
2106 2106          if (flags & OHCI_INTR) {
2107 2107  
2108 2108                  mutex_enter(&ohcip->ohci_int_mutex);
2109 2109  
2110 2110                  /* Disable all HC ED list processing */
2111 2111                  Set_OpReg(hcr_control,
2112 2112                      (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
2113 2113                      HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
2114 2114  
2115 2115                  /* Disable all HC interrupts */
2116 2116                  Set_OpReg(hcr_intr_disable,
2117 2117                      (HCR_INTR_SO | HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE));
2118 2118  
2119 2119                  /* Wait for the next SOF */
2120 2120                  (void) ohci_wait_for_sof(ohcip);
2121 2121  
2122 2122                  /* Disable Master and SOF interrupts */
2123 2123                  Set_OpReg(hcr_intr_disable, (HCR_INTR_MIE | HCR_INTR_SOF));
2124 2124  
2125 2125                  /* Set the Host Controller Functional State to Reset */
2126 2126                  Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
2127 2127                      (~HCR_CONTROL_HCFS)) | HCR_CONTROL_RESET));
2128 2128  
2129 2129                  mutex_exit(&ohcip->ohci_int_mutex);
2130 2130                  /* Wait for sometime */
2131 2131                  delay(drv_usectohz(OHCI_TIMEWAIT));
2132 2132                  mutex_enter(&ohcip->ohci_int_mutex);
2133 2133  
2134 2134                  /*
2135 2135                   * Workaround for ULI1575 chipset. Following OHCI Operational
2136 2136                   * Memory Registers are not cleared to their default value
2137 2137                   * on reset. Explicitly set the registers to default value.
2138 2138                   */
2139 2139                  if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
2140 2140                      ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
2141 2141                          Set_OpReg(hcr_control, HCR_CONTROL_DEFAULT);
2142 2142                          Set_OpReg(hcr_intr_enable, HCR_INT_ENABLE_DEFAULT);
2143 2143                          Set_OpReg(hcr_HCCA, HCR_HCCA_DEFAULT);
2144 2144                          Set_OpReg(hcr_ctrl_head, HCR_CONTROL_HEAD_ED_DEFAULT);
2145 2145                          Set_OpReg(hcr_bulk_head, HCR_BULK_HEAD_ED_DEFAULT);
2146 2146                          Set_OpReg(hcr_frame_interval,
2147 2147                              HCR_FRAME_INTERVAL_DEFAULT);
2148 2148                          Set_OpReg(hcr_periodic_strt,
2149 2149                              HCR_PERIODIC_START_DEFAULT);
2150 2150                  }
2151 2151  
2152 2152                  mutex_exit(&ohcip->ohci_int_mutex);
2153 2153  
2154 2154                  ohci_rem_intrs(ohcip);
2155 2155          }
2156 2156  
2157 2157          /* Unmap the OHCI registers */
2158 2158          if (ohcip->ohci_regs_handle) {
2159 2159                  /* Reset the host controller */
2160 2160                  Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
2161 2161  
2162 2162                  ddi_regs_map_free(&ohcip->ohci_regs_handle);
2163 2163          }
2164 2164  
2165 2165          if (ohcip->ohci_config_handle) {
2166 2166                  pci_config_teardown(&ohcip->ohci_config_handle);
2167 2167          }
2168 2168  
2169 2169          /* Free all the buffers */
2170 2170          if (ohcip->ohci_td_pool_addr && ohcip->ohci_td_pool_mem_handle) {
2171 2171                  for (i = 0; i < ohci_td_pool_size; i ++) {
2172 2172                          td = &ohcip->ohci_td_pool_addr[i];
2173 2173                          state = Get_TD(ohcip->ohci_td_pool_addr[i].hctd_state);
2174 2174  
2175 2175                          if ((state != HC_TD_FREE) && (state != HC_TD_DUMMY) &&
2176 2176                              (td->hctd_trans_wrapper)) {
2177 2177  
2178 2178                                  mutex_enter(&ohcip->ohci_int_mutex);
2179 2179  
2180 2180                                  tw = (ohci_trans_wrapper_t *)
2181 2181                                      OHCI_LOOKUP_ID((uint32_t)
2182 2182                                      Get_TD(td->hctd_trans_wrapper));
2183 2183  
2184 2184                                  /* Obtain the pipe private structure */
2185 2185                                  pp = tw->tw_pipe_private;
2186 2186  
2187 2187                                  /* Stop the the transfer timer */
2188 2188                                  ohci_stop_xfer_timer(ohcip, tw,
2189 2189                                      OHCI_REMOVE_XFER_ALWAYS);
2190 2190  
2191 2191                                  ohci_deallocate_tw_resources(ohcip, pp, tw);
2192 2192  
2193 2193                                  mutex_exit(&ohcip->ohci_int_mutex);
2194 2194                          }
2195 2195                  }
2196 2196  
2197 2197                  /*
2198 2198                   * If OHCI_TD_POOL_BOUND flag is set, then unbind
2199 2199                   * the handle for TD pools.
2200 2200                   */
2201 2201                  if ((ohcip->ohci_dma_addr_bind_flag &
2202 2202                      OHCI_TD_POOL_BOUND) == OHCI_TD_POOL_BOUND) {
2203 2203  
2204 2204                          rval = ddi_dma_unbind_handle(
2205 2205                              ohcip->ohci_td_pool_dma_handle);
2206 2206  
2207 2207                          ASSERT(rval == DDI_SUCCESS);
2208 2208                  }
2209 2209                  ddi_dma_mem_free(&ohcip->ohci_td_pool_mem_handle);
2210 2210          }
2211 2211  
2212 2212          /* Free the TD pool */
2213 2213          if (ohcip->ohci_td_pool_dma_handle) {
2214 2214                  ddi_dma_free_handle(&ohcip->ohci_td_pool_dma_handle);
2215 2215          }
2216 2216  
2217 2217          if (ohcip->ohci_ed_pool_addr && ohcip->ohci_ed_pool_mem_handle) {
2218 2218                  /*
2219 2219                   * If OHCI_ED_POOL_BOUND flag is set, then unbind
2220 2220                   * the handle for ED pools.
2221 2221                   */
2222 2222                  if ((ohcip->ohci_dma_addr_bind_flag &
2223 2223                      OHCI_ED_POOL_BOUND) == OHCI_ED_POOL_BOUND) {
2224 2224  
2225 2225                          rval = ddi_dma_unbind_handle(
2226 2226                              ohcip->ohci_ed_pool_dma_handle);
2227 2227  
2228 2228                          ASSERT(rval == DDI_SUCCESS);
2229 2229                  }
2230 2230  
2231 2231                  ddi_dma_mem_free(&ohcip->ohci_ed_pool_mem_handle);
2232 2232          }
2233 2233  
2234 2234          /* Free the ED pool */
2235 2235          if (ohcip->ohci_ed_pool_dma_handle) {
2236 2236                  ddi_dma_free_handle(&ohcip->ohci_ed_pool_dma_handle);
2237 2237          }
2238 2238  
2239 2239          /* Free the HCCA area */
2240 2240          if (ohcip->ohci_hccap && ohcip->ohci_hcca_mem_handle) {
2241 2241                  /*
2242 2242                   * If OHCI_HCCA_DMA_BOUND flag is set, then unbind
2243 2243                   * the handle for HCCA.
2244 2244                   */
2245 2245                  if ((ohcip->ohci_dma_addr_bind_flag &
2246 2246                      OHCI_HCCA_DMA_BOUND) == OHCI_HCCA_DMA_BOUND) {
2247 2247  
2248 2248                          rval = ddi_dma_unbind_handle(
2249 2249                              ohcip->ohci_hcca_dma_handle);
2250 2250  
2251 2251                          ASSERT(rval == DDI_SUCCESS);
2252 2252                  }
2253 2253  
2254 2254                  ddi_dma_mem_free(&ohcip->ohci_hcca_mem_handle);
2255 2255          }
2256 2256  
2257 2257          if (ohcip->ohci_hcca_dma_handle) {
2258 2258                  ddi_dma_free_handle(&ohcip->ohci_hcca_dma_handle);
2259 2259          }
2260 2260  
2261 2261          if (flags & OHCI_INTR) {
2262 2262  
2263 2263                  /* Destroy the mutex */
2264 2264                  mutex_destroy(&ohcip->ohci_int_mutex);
2265 2265  
2266 2266                  /* Destroy the SOF condition varibale */
2267 2267                  cv_destroy(&ohcip->ohci_SOF_cv);
2268 2268  
2269 2269                  /* Destroy the serialize opens and closes semaphore */
2270 2270                  sema_destroy(&ohcip->ohci_ocsem);
2271 2271          }
2272 2272  
2273 2273          /* clean up kstat structs */
2274 2274          ohci_destroy_stats(ohcip);
2275 2275  
2276 2276          /* Free ohci hcdi ops */
2277 2277          if (ohcip->ohci_hcdi_ops) {
2278 2278                  usba_free_hcdi_ops(ohcip->ohci_hcdi_ops);
2279 2279          }
2280 2280  
2281 2281          if (flags & OHCI_ZALLOC) {
2282 2282  
2283 2283                  usb_free_log_hdl(ohcip->ohci_log_hdl);
2284 2284  
2285 2285                  /* Remove all properties that might have been created */
2286 2286                  ddi_prop_remove_all(ohcip->ohci_dip);
2287 2287  
2288 2288                  /* Free the soft state */
2289 2289                  ddi_soft_state_free(ohci_statep,
2290 2290                      ddi_get_instance(ohcip->ohci_dip));
2291 2291          }
2292 2292  
2293 2293          return (DDI_SUCCESS);
2294 2294  }
2295 2295  
2296 2296  
2297 2297  /*
2298 2298   * ohci_rem_intrs:
2299 2299   *
2300 2300   * Unregister FIXED or MSI interrupts
2301 2301   */
2302 2302  static void
2303 2303  ohci_rem_intrs(ohci_state_t     *ohcip)
2304 2304  {
2305 2305          int     i;
2306 2306  
2307 2307          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2308 2308              "ohci_rem_intrs: interrupt type 0x%x", ohcip->ohci_intr_type);
2309 2309  
2310 2310          /* Disable all interrupts */
2311 2311          if (ohcip->ohci_intr_cap & DDI_INTR_FLAG_BLOCK) {
2312 2312                  (void) ddi_intr_block_disable(ohcip->ohci_htable,
2313 2313                      ohcip->ohci_intr_cnt);
2314 2314          } else {
2315 2315                  for (i = 0; i < ohcip->ohci_intr_cnt; i++) {
2316 2316                          (void) ddi_intr_disable(ohcip->ohci_htable[i]);
2317 2317                  }
2318 2318          }
2319 2319  
2320 2320          /* Call ddi_intr_remove_handler() */
2321 2321          for (i = 0; i < ohcip->ohci_intr_cnt; i++) {
2322 2322                  (void) ddi_intr_remove_handler(ohcip->ohci_htable[i]);
2323 2323                  (void) ddi_intr_free(ohcip->ohci_htable[i]);
2324 2324          }
2325 2325  
2326 2326          kmem_free(ohcip->ohci_htable,
2327 2327              ohcip->ohci_intr_cnt * sizeof (ddi_intr_handle_t));
2328 2328  }
2329 2329  
2330 2330  
2331 2331  /*
2332 2332   * ohci_cpr_suspend
2333 2333   */
2334 2334  static int
2335 2335  ohci_cpr_suspend(ohci_state_t   *ohcip)
2336 2336  {
2337 2337          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2338 2338              "ohci_cpr_suspend:");
2339 2339  
2340 2340          /* Call into the root hub and suspend it */
2341 2341          if (usba_hubdi_detach(ohcip->ohci_dip, DDI_SUSPEND) != DDI_SUCCESS) {
2342 2342  
2343 2343                  return (DDI_FAILURE);
2344 2344          }
2345 2345  
2346 2346          /* Only root hub's intr pipe should be open at this time */
2347 2347          mutex_enter(&ohcip->ohci_int_mutex);
2348 2348  
2349 2349          if (ohcip->ohci_open_pipe_count > 1) {
2350 2350  
2351 2351                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2352 2352                      "ohci_cpr_suspend: fails as open pipe count = %d",
2353 2353                      ohcip->ohci_open_pipe_count);
2354 2354  
2355 2355                  mutex_exit(&ohcip->ohci_int_mutex);
2356 2356  
2357 2357                  return (DDI_FAILURE);
2358 2358          }
2359 2359  
2360 2360          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2361 2361              "ohci_cpr_suspend: Disable HC ED list processing");
2362 2362  
2363 2363          /* Disable all HC ED list processing */
2364 2364          Set_OpReg(hcr_control, (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
2365 2365              HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
2366 2366  
2367 2367          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2368 2368              "ohci_cpr_suspend: Disable HC interrupts");
2369 2369  
2370 2370          /* Disable all HC interrupts */
2371 2371          Set_OpReg(hcr_intr_disable, ~(HCR_INTR_MIE|HCR_INTR_SOF));
2372 2372  
2373 2373          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2374 2374              "ohci_cpr_suspend: Wait for the next SOF");
2375 2375  
2376 2376          /* Wait for the next SOF */
2377 2377          if (ohci_wait_for_sof(ohcip) != USB_SUCCESS) {
2378 2378  
2379 2379                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2380 2380                      "ohci_cpr_suspend: ohci host controller suspend failed");
2381 2381  
2382 2382                  mutex_exit(&ohcip->ohci_int_mutex);
2383 2383                  return (DDI_FAILURE);
2384 2384          }
2385 2385  
2386 2386          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2387 2387              "ohci_cpr_suspend: Disable Master interrupt");
2388 2388  
2389 2389          /*
2390 2390           * Disable Master interrupt so that ohci driver don't
2391 2391           * get any ohci interrupts.
2392 2392           */
2393 2393          Set_OpReg(hcr_intr_disable, HCR_INTR_MIE);
2394 2394  
2395 2395          /*
2396 2396           * Suspend the ohci host controller
2397 2397           * if usb keyboard is not connected.
2398 2398           */
2399 2399          if (ohcip->ohci_polled_kbd_count == 0 || force_ohci_off != 0) {
2400 2400                  Set_OpReg(hcr_control, HCR_CONTROL_SUSPD);
2401 2401          }
2402 2402  
2403 2403          /* Set host controller soft state to suspend */
2404 2404          ohcip->ohci_hc_soft_state = OHCI_CTLR_SUSPEND_STATE;
2405 2405  
2406 2406          mutex_exit(&ohcip->ohci_int_mutex);
2407 2407  
2408 2408          return (DDI_SUCCESS);
2409 2409  }
2410 2410  
2411 2411  
2412 2412  /*
2413 2413   * ohci_cpr_resume
2414 2414   */
2415 2415  static int
2416 2416  ohci_cpr_resume(ohci_state_t    *ohcip)
2417 2417  {
2418 2418          mutex_enter(&ohcip->ohci_int_mutex);
2419 2419  
2420 2420          USB_DPRINTF_L4(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2421 2421              "ohci_cpr_resume: Restart the controller");
2422 2422  
2423 2423          /* Cleanup ohci specific information across cpr */
2424 2424          ohci_cpr_cleanup(ohcip);
2425 2425  
2426 2426          /* Restart the controller */
2427 2427          if (ohci_init_ctlr(ohcip) != DDI_SUCCESS) {
2428 2428  
2429 2429                  USB_DPRINTF_L2(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
2430 2430                      "ohci_cpr_resume: ohci host controller resume failed ");
2431 2431  
2432 2432                  mutex_exit(&ohcip->ohci_int_mutex);
2433 2433  
2434 2434                  return (DDI_FAILURE);
2435 2435          }
2436 2436  
2437 2437          mutex_exit(&ohcip->ohci_int_mutex);
2438 2438  
2439 2439          /* Now resume the root hub */
2440 2440          if (usba_hubdi_attach(ohcip->ohci_dip, DDI_RESUME) != DDI_SUCCESS) {
2441 2441  
2442 2442                  return (DDI_FAILURE);
2443 2443          }
2444 2444  
2445 2445          return (DDI_SUCCESS);
2446 2446  }
2447 2447  
2448 2448  
2449 2449  /*
2450 2450   * HCDI entry points
2451 2451   *
2452 2452   * The Host Controller Driver Interfaces (HCDI) are the software interfaces
2453 2453   * between the Universal Serial Bus Layer (USBA) and the Host Controller
2454 2454   * Driver (HCD). The HCDI interfaces or entry points are subject to change.
2455 2455   */
2456 2456  
2457 2457  /*
2458 2458   * ohci_hcdi_pipe_open:
2459 2459   *
2460 2460   * Member of HCD Ops structure and called during client specific pipe open
2461 2461   * Add the pipe to the data structure representing the device and allocate
2462 2462   * bandwidth for the pipe if it is a interrupt or isochronous endpoint.
2463 2463   */
2464 2464  static int
2465 2465  ohci_hcdi_pipe_open(
2466 2466          usba_pipe_handle_data_t *ph,
2467 2467          usb_flags_t             flags)
2468 2468  {
2469 2469          ohci_state_t            *ohcip = ohci_obtain_state(
2470 2470              ph->p_usba_device->usb_root_hub_dip);
2471 2471          usb_ep_descr_t          *epdt = &ph->p_ep;
2472 2472          int                     rval, error = USB_SUCCESS;
2473 2473          int                     kmflag = (flags & USB_FLAGS_SLEEP) ?
2474 2474              KM_SLEEP : KM_NOSLEEP;
2475 2475          uint_t                  node = 0;
2476 2476          ohci_pipe_private_t     *pp;
2477 2477  
2478 2478          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2479 2479              "ohci_hcdi_pipe_open: addr = 0x%x, ep%d",
2480 2480              ph->p_usba_device->usb_addr,
2481 2481              epdt->bEndpointAddress & USB_EP_NUM_MASK);
2482 2482  
2483 2483          sema_p(&ohcip->ohci_ocsem);
2484 2484  
2485 2485          mutex_enter(&ohcip->ohci_int_mutex);
2486 2486          rval = ohci_state_is_operational(ohcip);
2487 2487          mutex_exit(&ohcip->ohci_int_mutex);
2488 2488  
2489 2489          if (rval != USB_SUCCESS) {
2490 2490                  sema_v(&ohcip->ohci_ocsem);
2491 2491  
2492 2492                  return (rval);
2493 2493          }
2494 2494  
2495 2495          /*
2496 2496           * Check and handle root hub pipe open.
2497 2497           */
2498 2498          if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2499 2499  
2500 2500                  mutex_enter(&ohcip->ohci_int_mutex);
2501 2501                  error = ohci_handle_root_hub_pipe_open(ph, flags);
2502 2502                  mutex_exit(&ohcip->ohci_int_mutex);
2503 2503                  sema_v(&ohcip->ohci_ocsem);
2504 2504  
2505 2505                  return (error);
2506 2506          }
2507 2507  
2508 2508          /*
2509 2509           * Opening of other pipes excluding root hub pipe are
2510 2510           * handled below. Check whether pipe is already opened.
2511 2511           */
2512 2512          if (ph->p_hcd_private) {
2513 2513                  USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2514 2514                      "ohci_hcdi_pipe_open: Pipe is already opened");
2515 2515  
2516 2516                  sema_v(&ohcip->ohci_ocsem);
2517 2517  
2518 2518                  return (USB_FAILURE);
2519 2519          }
2520 2520  
2521 2521          /*
2522 2522           * A portion of the bandwidth is reserved for the non-periodic
2523 2523           * transfers, i.e control and bulk transfers in each of one
2524 2524           * millisecond frame period & usually it will be 10% of frame
2525 2525           * period. Hence there is no need to check for the available
2526 2526           * bandwidth before adding the control or bulk endpoints.
2527 2527           *
2528 2528           * There is a need to check for the available bandwidth before
2529 2529           * adding the periodic transfers, i.e interrupt & isochronous,
2530 2530           * since all these periodic transfers are guaranteed transfers.
2531 2531           * Usually 90% of the total frame time is reserved for periodic
2532 2532           * transfers.
2533 2533           */
2534 2534          if (OHCI_PERIODIC_ENDPOINT(epdt)) {
2535 2535  
2536 2536                  mutex_enter(&ohcip->ohci_int_mutex);
2537 2537                  mutex_enter(&ph->p_mutex);
2538 2538  
2539 2539                  error = ohci_allocate_bandwidth(ohcip, ph, &node);
2540 2540  
2541 2541                  if (error != USB_SUCCESS) {
2542 2542  
2543 2543                          USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2544 2544                              "ohci_hcdi_pipe_open: Bandwidth allocation failed");
2545 2545  
2546 2546                          mutex_exit(&ph->p_mutex);
2547 2547                          mutex_exit(&ohcip->ohci_int_mutex);
2548 2548                          sema_v(&ohcip->ohci_ocsem);
2549 2549  
2550 2550                          return (error);
2551 2551                  }
2552 2552  
2553 2553                  mutex_exit(&ph->p_mutex);
2554 2554                  mutex_exit(&ohcip->ohci_int_mutex);
2555 2555          }
2556 2556  
2557 2557          /* Create the HCD pipe private structure */
2558 2558          pp = kmem_zalloc(sizeof (ohci_pipe_private_t), kmflag);
2559 2559  
2560 2560          /*
2561 2561           * Return failure if ohci pipe private
2562 2562           * structure allocation fails.
2563 2563           */
2564 2564          if (pp == NULL) {
2565 2565  
2566 2566                  mutex_enter(&ohcip->ohci_int_mutex);
2567 2567  
2568 2568                  /* Deallocate bandwidth */
2569 2569                  if (OHCI_PERIODIC_ENDPOINT(epdt)) {
2570 2570  
2571 2571                          mutex_enter(&ph->p_mutex);
2572 2572                          ohci_deallocate_bandwidth(ohcip, ph);
2573 2573                          mutex_exit(&ph->p_mutex);
2574 2574                  }
2575 2575  
2576 2576                  mutex_exit(&ohcip->ohci_int_mutex);
2577 2577                  sema_v(&ohcip->ohci_ocsem);
2578 2578  
2579 2579                  return (USB_NO_RESOURCES);
2580 2580          }
2581 2581  
2582 2582          mutex_enter(&ohcip->ohci_int_mutex);
2583 2583  
2584 2584          /* Store the node in the interrupt lattice */
2585 2585          pp->pp_node = node;
2586 2586  
2587 2587          /* Create prototype for xfer completion condition variable */
2588 2588          cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL);
2589 2589  
2590 2590          /* Set the state of pipe as idle */
2591 2591          pp->pp_state = OHCI_PIPE_STATE_IDLE;
2592 2592  
2593 2593          /* Store a pointer to the pipe handle */
2594 2594          pp->pp_pipe_handle = ph;
2595 2595  
2596 2596          mutex_enter(&ph->p_mutex);
2597 2597  
2598 2598          /* Store the pointer in the pipe handle */
2599 2599          ph->p_hcd_private = (usb_opaque_t)pp;
2600 2600  
2601 2601          /* Store a copy of the pipe policy */
2602 2602          bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
2603 2603  
2604 2604          mutex_exit(&ph->p_mutex);
2605 2605  
2606 2606          /* Allocate the host controller endpoint descriptor */
2607 2607          pp->pp_ept = ohci_alloc_hc_ed(ohcip, ph);
2608 2608  
2609 2609          if (pp->pp_ept == NULL) {
2610 2610                  USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2611 2611                      "ohci_hcdi_pipe_open: ED allocation failed");
2612 2612  
2613 2613                  mutex_enter(&ph->p_mutex);
2614 2614  
2615 2615                  /* Deallocate bandwidth */
2616 2616                  if (OHCI_PERIODIC_ENDPOINT(epdt)) {
2617 2617  
2618 2618                          ohci_deallocate_bandwidth(ohcip, ph);
2619 2619                  }
2620 2620  
2621 2621                  /* Destroy the xfer completion condition varibale */
2622 2622                  cv_destroy(&pp->pp_xfer_cmpl_cv);
2623 2623  
2624 2624                  /*
2625 2625                   * Deallocate the hcd private portion
2626 2626                   * of the pipe handle.
2627 2627                   */
2628 2628                  kmem_free(ph->p_hcd_private, sizeof (ohci_pipe_private_t));
2629 2629  
2630 2630                  /*
2631 2631                   * Set the private structure in the
2632 2632                   * pipe handle equal to NULL.
2633 2633                   */
2634 2634                  ph->p_hcd_private = NULL;
2635 2635                  mutex_exit(&ph->p_mutex);
2636 2636  
2637 2637                  mutex_exit(&ohcip->ohci_int_mutex);
2638 2638                  sema_v(&ohcip->ohci_ocsem);
2639 2639  
2640 2640                  return (USB_NO_RESOURCES);
2641 2641          }
2642 2642  
2643 2643          /* Restore the data toggle information */
2644 2644          ohci_restore_data_toggle(ohcip, ph);
2645 2645  
2646 2646          /*
2647 2647           * Insert the endpoint onto the host controller's
2648 2648           * appropriate endpoint list. The host controller
2649 2649           * will not schedule this endpoint and will not have
2650 2650           * any TD's to process.
2651 2651           */
2652 2652          ohci_insert_ed(ohcip, ph);
2653 2653  
2654 2654          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2655 2655              "ohci_hcdi_pipe_open: ph = 0x%p", (void *)ph);
2656 2656  
2657 2657          ohcip->ohci_open_pipe_count++;
2658 2658  
2659 2659          mutex_exit(&ohcip->ohci_int_mutex);
2660 2660  
2661 2661          sema_v(&ohcip->ohci_ocsem);
2662 2662  
2663 2663          return (USB_SUCCESS);
2664 2664  }
2665 2665  
2666 2666  
2667 2667  /*
2668 2668   * ohci_hcdi_pipe_close:
2669 2669   *
2670 2670   * Member of HCD Ops structure and called during the client  specific pipe
2671 2671   * close. Remove the pipe and the data structure representing the device.
2672 2672   * Deallocate  bandwidth for the pipe if it is a interrupt or isochronous
2673 2673   * endpoint.
2674 2674   */
2675 2675  /* ARGSUSED */
2676 2676  static int
2677 2677  ohci_hcdi_pipe_close(
2678 2678          usba_pipe_handle_data_t *ph,
2679 2679          usb_flags_t             flags)
2680 2680  {
2681 2681          ohci_state_t            *ohcip = ohci_obtain_state(
2682 2682              ph->p_usba_device->usb_root_hub_dip);
2683 2683          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2684 2684          usb_ep_descr_t          *eptd = &ph->p_ep;
2685 2685          int                     error = USB_SUCCESS;
2686 2686  
2687 2687          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2688 2688              "ohci_hcdi_pipe_close: addr = 0x%x, ep%d",
2689 2689              ph->p_usba_device->usb_addr,
2690 2690              eptd->bEndpointAddress & USB_EP_NUM_MASK);
2691 2691  
2692 2692          sema_p(&ohcip->ohci_ocsem);
2693 2693  
2694 2694          /* Check and handle root hub pipe close */
2695 2695          if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2696 2696  
2697 2697                  mutex_enter(&ohcip->ohci_int_mutex);
2698 2698                  error = ohci_handle_root_hub_pipe_close(ph);
2699 2699                  mutex_exit(&ohcip->ohci_int_mutex);
2700 2700                  sema_v(&ohcip->ohci_ocsem);
2701 2701  
2702 2702                  return (error);
2703 2703          }
2704 2704  
2705 2705          ASSERT(ph->p_hcd_private != NULL);
2706 2706  
2707 2707          mutex_enter(&ohcip->ohci_int_mutex);
2708 2708  
2709 2709          /* Set pipe state to pipe close */
2710 2710          pp->pp_state = OHCI_PIPE_STATE_CLOSE;
2711 2711  
2712 2712          ohci_pipe_cleanup(ohcip, ph);
2713 2713  
2714 2714          /*
2715 2715           * Remove the endoint descriptor from Host
2716 2716           * Controller's appropriate endpoint list.
2717 2717           */
2718 2718          ohci_remove_ed(ohcip, pp);
2719 2719  
2720 2720          /* Deallocate bandwidth */
2721 2721          if (OHCI_PERIODIC_ENDPOINT(eptd)) {
2722 2722  
2723 2723                  mutex_enter(&ph->p_mutex);
2724 2724                  ohci_deallocate_bandwidth(ohcip, ph);
2725 2725                  mutex_exit(&ph->p_mutex);
2726 2726          }
2727 2727  
2728 2728          mutex_enter(&ph->p_mutex);
2729 2729  
2730 2730          /* Destroy the xfer completion condition varibale */
2731 2731          cv_destroy(&pp->pp_xfer_cmpl_cv);
2732 2732  
2733 2733          /*
2734 2734           * Deallocate the hcd private portion
2735 2735           * of the pipe handle.
2736 2736           */
2737 2737          kmem_free(ph->p_hcd_private, sizeof (ohci_pipe_private_t));
2738 2738          ph->p_hcd_private = NULL;
2739 2739  
2740 2740          mutex_exit(&ph->p_mutex);
2741 2741  
2742 2742          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2743 2743              "ohci_hcdi_pipe_close: ph = 0x%p", (void *)ph);
2744 2744  
2745 2745          ohcip->ohci_open_pipe_count--;
2746 2746  
2747 2747          mutex_exit(&ohcip->ohci_int_mutex);
2748 2748          sema_v(&ohcip->ohci_ocsem);
2749 2749  
2750 2750          return (error);
2751 2751  }
2752 2752  
2753 2753  
2754 2754  /*
2755 2755   * ohci_hcdi_pipe_reset:
2756 2756   */
2757 2757  /* ARGSUSED */
2758 2758  static int
2759 2759  ohci_hcdi_pipe_reset(
2760 2760          usba_pipe_handle_data_t *ph,
2761 2761          usb_flags_t             usb_flags)
2762 2762  {
2763 2763          ohci_state_t            *ohcip = ohci_obtain_state(
2764 2764              ph->p_usba_device->usb_root_hub_dip);
2765 2765          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2766 2766          int                     error = USB_SUCCESS;
2767 2767  
2768 2768          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2769 2769              "ohci_hcdi_pipe_reset: ph = 0x%p ", (void *)ph);
2770 2770  
2771 2771          /*
2772 2772           * Check and handle root hub pipe reset.
2773 2773           */
2774 2774          if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2775 2775  
2776 2776                  error = ohci_handle_root_hub_pipe_reset(ph, usb_flags);
2777 2777                  return (error);
2778 2778          }
2779 2779  
2780 2780          mutex_enter(&ohcip->ohci_int_mutex);
2781 2781  
2782 2782          /* Set pipe state to pipe reset */
2783 2783          pp->pp_state = OHCI_PIPE_STATE_RESET;
2784 2784  
2785 2785          ohci_pipe_cleanup(ohcip, ph);
2786 2786  
2787 2787          mutex_exit(&ohcip->ohci_int_mutex);
2788 2788  
2789 2789          return (error);
2790 2790  }
2791 2791  
2792 2792  /*
2793 2793   * ohci_hcdi_pipe_reset_data_toggle:
2794 2794   */
2795 2795  void
2796 2796  ohci_hcdi_pipe_reset_data_toggle(
2797 2797          usba_pipe_handle_data_t *ph)
2798 2798  {
2799 2799          ohci_state_t            *ohcip = ohci_obtain_state(
2800 2800              ph->p_usba_device->usb_root_hub_dip);
2801 2801          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2802 2802  
2803 2803          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2804 2804              "ohci_hcdi_pipe_reset_data_toggle:");
2805 2805  
2806 2806          mutex_enter(&ohcip->ohci_int_mutex);
2807 2807  
2808 2808          mutex_enter(&ph->p_mutex);
2809 2809          usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
2810 2810              DATA0);
2811 2811          mutex_exit(&ph->p_mutex);
2812 2812  
2813 2813          Set_ED(pp->pp_ept->hced_headp,
2814 2814              Get_ED(pp->pp_ept->hced_headp) & (~HC_EPT_Carry));
2815 2815          mutex_exit(&ohcip->ohci_int_mutex);
2816 2816  
2817 2817  }
2818 2818  
2819 2819  /*
2820 2820   * ohci_hcdi_pipe_ctrl_xfer:
2821 2821   */
2822 2822  static int
2823 2823  ohci_hcdi_pipe_ctrl_xfer(
2824 2824          usba_pipe_handle_data_t *ph,
2825 2825          usb_ctrl_req_t          *ctrl_reqp,
2826 2826          usb_flags_t             usb_flags)
2827 2827  {
2828 2828          ohci_state_t            *ohcip = ohci_obtain_state(
2829 2829              ph->p_usba_device->usb_root_hub_dip);
2830 2830          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2831 2831          int                     rval;
2832 2832          int                     error = USB_SUCCESS;
2833 2833          ohci_trans_wrapper_t    *tw;
2834 2834  
2835 2835          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2836 2836              "ohci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
2837 2837              (void *)ph, (void *)ctrl_reqp, usb_flags);
2838 2838  
2839 2839          mutex_enter(&ohcip->ohci_int_mutex);
2840 2840          rval = ohci_state_is_operational(ohcip);
2841 2841          mutex_exit(&ohcip->ohci_int_mutex);
2842 2842  
2843 2843          if (rval != USB_SUCCESS) {
2844 2844  
2845 2845                  return (rval);
2846 2846          }
2847 2847  
2848 2848          /*
2849 2849           * Check and handle root hub control request.
2850 2850           */
2851 2851          if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
2852 2852  
2853 2853                  error = ohci_handle_root_hub_request(ohcip, ph, ctrl_reqp);
2854 2854  
2855 2855                  return (error);
2856 2856          }
2857 2857  
2858 2858          mutex_enter(&ohcip->ohci_int_mutex);
2859 2859  
2860 2860          /*
2861 2861           *  Check whether pipe is in halted state.
2862 2862           */
2863 2863          if (pp->pp_state == OHCI_PIPE_STATE_ERROR) {
2864 2864  
2865 2865                  USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2866 2866                      "ohci_hcdi_pipe_ctrl_xfer:"
2867 2867                      "Pipe is in error state, need pipe reset to continue");
2868 2868  
2869 2869                  mutex_exit(&ohcip->ohci_int_mutex);
2870 2870  
2871 2871                  return (USB_FAILURE);
2872 2872          }
2873 2873  
2874 2874          /* Allocate a transfer wrapper */
2875 2875          if ((tw = ohci_allocate_ctrl_resources(ohcip, pp, ctrl_reqp,
2876 2876              usb_flags)) == NULL) {
2877 2877  
2878 2878                  error = USB_NO_RESOURCES;
2879 2879          } else {
2880 2880                  /* Insert the td's on the endpoint */
2881 2881                  ohci_insert_ctrl_req(ohcip, ph, ctrl_reqp, tw, usb_flags);
2882 2882          }
2883 2883  
2884 2884          mutex_exit(&ohcip->ohci_int_mutex);
2885 2885  
2886 2886          return (error);
2887 2887  }
2888 2888  
2889 2889  
2890 2890  /*
2891 2891   * ohci_hcdi_bulk_transfer_size:
2892 2892   *
2893 2893   * Return maximum bulk transfer size
2894 2894   */
2895 2895  
2896 2896  /* ARGSUSED */
2897 2897  static int
2898 2898  ohci_hcdi_bulk_transfer_size(
2899 2899          usba_device_t   *usba_device,
2900 2900          size_t          *size)
2901 2901  {
2902 2902          ohci_state_t    *ohcip = ohci_obtain_state(
2903 2903              usba_device->usb_root_hub_dip);
2904 2904          int             rval;
2905 2905  
2906 2906          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2907 2907              "ohci_hcdi_bulk_transfer_size:");
2908 2908  
2909 2909          mutex_enter(&ohcip->ohci_int_mutex);
2910 2910          rval = ohci_state_is_operational(ohcip);
2911 2911          mutex_exit(&ohcip->ohci_int_mutex);
2912 2912  
2913 2913          if (rval != USB_SUCCESS) {
2914 2914  
2915 2915                  return (rval);
2916 2916          }
2917 2917  
2918 2918          *size = OHCI_MAX_BULK_XFER_SIZE;
2919 2919  
2920 2920          return (USB_SUCCESS);
2921 2921  }
2922 2922  
2923 2923  
2924 2924  /*
2925 2925   * ohci_hcdi_pipe_bulk_xfer:
2926 2926   */
2927 2927  static int
2928 2928  ohci_hcdi_pipe_bulk_xfer(
2929 2929          usba_pipe_handle_data_t *ph,
2930 2930          usb_bulk_req_t          *bulk_reqp,
2931 2931          usb_flags_t             usb_flags)
2932 2932  {
2933 2933          ohci_state_t            *ohcip = ohci_obtain_state(
2934 2934              ph->p_usba_device->usb_root_hub_dip);
2935 2935          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
2936 2936          int                     rval, error = USB_SUCCESS;
2937 2937          ohci_trans_wrapper_t    *tw;
2938 2938  
2939 2939          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2940 2940              "ohci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
2941 2941              (void *)ph, (void *)bulk_reqp, usb_flags);
2942 2942  
2943 2943          mutex_enter(&ohcip->ohci_int_mutex);
2944 2944          rval = ohci_state_is_operational(ohcip);
2945 2945  
2946 2946          if (rval != USB_SUCCESS) {
2947 2947                  mutex_exit(&ohcip->ohci_int_mutex);
2948 2948  
2949 2949                  return (rval);
2950 2950          }
2951 2951  
2952 2952          /*
2953 2953           *  Check whether pipe is in halted state.
2954 2954           */
2955 2955          if (pp->pp_state == OHCI_PIPE_STATE_ERROR) {
2956 2956  
2957 2957                  USB_DPRINTF_L2(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2958 2958                      "ohci_hcdi_pipe_bulk_xfer:"
2959 2959                      "Pipe is in error state, need pipe reset to continue");
2960 2960  
2961 2961                  mutex_exit(&ohcip->ohci_int_mutex);
2962 2962  
2963 2963                  return (USB_FAILURE);
2964 2964          }
2965 2965  
2966 2966          /* Allocate a transfer wrapper */
2967 2967          if ((tw = ohci_allocate_bulk_resources(ohcip, pp, bulk_reqp,
2968 2968              usb_flags)) == NULL) {
2969 2969  
2970 2970                  error = USB_NO_RESOURCES;
2971 2971          } else {
2972 2972                  /* Add the TD into the Host Controller's bulk list */
2973 2973                  ohci_insert_bulk_req(ohcip, ph, bulk_reqp, tw, usb_flags);
2974 2974          }
2975 2975  
2976 2976          mutex_exit(&ohcip->ohci_int_mutex);
2977 2977  
2978 2978          return (error);
2979 2979  }
2980 2980  
2981 2981  
2982 2982  /*
2983 2983   * ohci_hcdi_pipe_intr_xfer:
2984 2984   */
2985 2985  static int
2986 2986  ohci_hcdi_pipe_intr_xfer(
2987 2987          usba_pipe_handle_data_t *ph,
2988 2988          usb_intr_req_t          *intr_reqp,
2989 2989          usb_flags_t             usb_flags)
2990 2990  {
2991 2991          ohci_state_t            *ohcip = ohci_obtain_state(
2992 2992              ph->p_usba_device->usb_root_hub_dip);
2993 2993          int                     pipe_dir, rval, error = USB_SUCCESS;
2994 2994          ohci_trans_wrapper_t    *tw;
2995 2995  
2996 2996          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
2997 2997              "ohci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
2998 2998              (void *)ph, (void *)intr_reqp, usb_flags);
2999 2999  
3000 3000          mutex_enter(&ohcip->ohci_int_mutex);
3001 3001          rval = ohci_state_is_operational(ohcip);
3002 3002  
3003 3003          if (rval != USB_SUCCESS) {
3004 3004                  mutex_exit(&ohcip->ohci_int_mutex);
3005 3005  
3006 3006                  return (rval);
3007 3007          }
3008 3008  
3009 3009          /* Get the pipe direction */
3010 3010          pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
3011 3011  
3012 3012          if (pipe_dir == USB_EP_DIR_IN) {
3013 3013                  error = ohci_start_periodic_pipe_polling(ohcip, ph,
3014 3014                      (usb_opaque_t)intr_reqp, usb_flags);
3015 3015          } else {
3016 3016                  /* Allocate transaction resources */
3017 3017                  if ((tw = ohci_allocate_intr_resources(ohcip, ph,
3018 3018                      intr_reqp, usb_flags)) == NULL) {
3019 3019                          error = USB_NO_RESOURCES;
3020 3020                  } else {
3021 3021                          ohci_insert_intr_req(ohcip,
3022 3022                              (ohci_pipe_private_t *)ph->p_hcd_private,
3023 3023                              tw, usb_flags);
3024 3024                  }
3025 3025          }
3026 3026  
3027 3027          mutex_exit(&ohcip->ohci_int_mutex);
3028 3028  
3029 3029          return (error);
3030 3030  }
3031 3031  
3032 3032  
3033 3033  /*
3034 3034   * ohci_hcdi_pipe_stop_intr_polling()
3035 3035   */
3036 3036  static int
3037 3037  ohci_hcdi_pipe_stop_intr_polling(
3038 3038          usba_pipe_handle_data_t *ph,
3039 3039          usb_flags_t             flags)
3040 3040  {
3041 3041          ohci_state_t            *ohcip = ohci_obtain_state(
3042 3042              ph->p_usba_device->usb_root_hub_dip);
3043 3043          int                     error = USB_SUCCESS;
3044 3044  
3045 3045          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3046 3046              "ohci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x",
3047 3047              (void *)ph, flags);
3048 3048  
3049 3049          mutex_enter(&ohcip->ohci_int_mutex);
3050 3050  
3051 3051          error = ohci_stop_periodic_pipe_polling(ohcip, ph, flags);
3052 3052  
3053 3053          mutex_exit(&ohcip->ohci_int_mutex);
3054 3054  
3055 3055          return (error);
3056 3056  }
3057 3057  
3058 3058  
3059 3059  /*
3060 3060   * ohci_hcdi_get_current_frame_number:
3061 3061   *
3062 3062   * Get the current usb frame number.
3063 3063   * Return whether the request is handled successfully.
3064 3064   */
3065 3065  static int
3066 3066  ohci_hcdi_get_current_frame_number(
3067 3067          usba_device_t           *usba_device,
3068 3068          usb_frame_number_t      *frame_number)
3069 3069  {
3070 3070          ohci_state_t            *ohcip = ohci_obtain_state(
3071 3071              usba_device->usb_root_hub_dip);
3072 3072          int                     rval;
3073 3073  
3074 3074          ohcip = ohci_obtain_state(usba_device->usb_root_hub_dip);
3075 3075  
3076 3076          mutex_enter(&ohcip->ohci_int_mutex);
3077 3077          rval = ohci_state_is_operational(ohcip);
3078 3078  
3079 3079          if (rval != USB_SUCCESS) {
3080 3080                  mutex_exit(&ohcip->ohci_int_mutex);
3081 3081  
3082 3082                  return (rval);
3083 3083          }
3084 3084  
3085 3085          *frame_number = ohci_get_current_frame_number(ohcip);
3086 3086  
3087 3087          mutex_exit(&ohcip->ohci_int_mutex);
3088 3088  
3089 3089          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3090 3090              "ohci_hcdi_get_current_frame_number:"
3091 3091              "Current frame number 0x%llx", (unsigned long long)(*frame_number));
3092 3092  
3093 3093          return (rval);
3094 3094  }
3095 3095  
3096 3096  
3097 3097  /*
3098 3098   * ohci_hcdi_get_max_isoc_pkts:
3099 3099   *
3100 3100   * Get maximum isochronous packets per usb isochronous request.
3101 3101   * Return whether the request is handled successfully.
3102 3102   */
3103 3103  static int
3104 3104  ohci_hcdi_get_max_isoc_pkts(
3105 3105          usba_device_t   *usba_device,
3106 3106          uint_t          *max_isoc_pkts_per_request)
3107 3107  {
3108 3108          ohci_state_t            *ohcip = ohci_obtain_state(
3109 3109              usba_device->usb_root_hub_dip);
3110 3110          int                     rval;
3111 3111  
3112 3112          mutex_enter(&ohcip->ohci_int_mutex);
3113 3113          rval = ohci_state_is_operational(ohcip);
3114 3114          mutex_exit(&ohcip->ohci_int_mutex);
3115 3115  
3116 3116          if (rval != USB_SUCCESS) {
3117 3117  
3118 3118                  return (rval);
3119 3119          }
3120 3120  
3121 3121          *max_isoc_pkts_per_request = OHCI_MAX_ISOC_PKTS_PER_XFER;
3122 3122  
3123 3123          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3124 3124              "ohci_hcdi_get_max_isoc_pkts: maximum isochronous"
3125 3125              "packets per usb isochronous request = 0x%x",
3126 3126              *max_isoc_pkts_per_request);
3127 3127  
3128 3128          return (rval);
3129 3129  }
3130 3130  
3131 3131  
3132 3132  /*
3133 3133   * ohci_hcdi_pipe_isoc_xfer:
3134 3134   */
3135 3135  static int
3136 3136  ohci_hcdi_pipe_isoc_xfer(
3137 3137          usba_pipe_handle_data_t *ph,
3138 3138          usb_isoc_req_t          *isoc_reqp,
3139 3139          usb_flags_t             usb_flags)
3140 3140  {
3141 3141          ohci_state_t            *ohcip = ohci_obtain_state(
3142 3142              ph->p_usba_device->usb_root_hub_dip);
3143 3143          int                     error = USB_SUCCESS;
3144 3144          int                     pipe_dir, rval;
3145 3145          ohci_trans_wrapper_t    *tw;
3146 3146  
3147 3147          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3148 3148              "ohci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
3149 3149              (void *)ph, (void *)isoc_reqp, usb_flags);
3150 3150  
3151 3151          mutex_enter(&ohcip->ohci_int_mutex);
3152 3152          rval = ohci_state_is_operational(ohcip);
3153 3153  
3154 3154          if (rval != USB_SUCCESS) {
3155 3155                  mutex_exit(&ohcip->ohci_int_mutex);
3156 3156  
3157 3157                  return (rval);
3158 3158          }
3159 3159  
3160 3160          /* Get the isochronous pipe direction */
3161 3161          pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
3162 3162  
3163 3163          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3164 3164              "ohci_hcdi_pipe_isoc_xfer: isoc_reqp = 0x%p, uf = 0x%x",
3165 3165              (void *)isoc_reqp, usb_flags);
3166 3166  
3167 3167          if (pipe_dir == USB_EP_DIR_IN) {
3168 3168                  error = ohci_start_periodic_pipe_polling(ohcip, ph,
3169 3169                      (usb_opaque_t)isoc_reqp, usb_flags);
3170 3170          } else {
3171 3171                  /* Allocate transaction resources */
3172 3172                  if ((tw = ohci_allocate_isoc_resources(ohcip, ph,
3173 3173                      isoc_reqp, usb_flags)) == NULL) {
3174 3174                          error = USB_NO_RESOURCES;
3175 3175                  } else {
3176 3176                          error = ohci_insert_isoc_req(ohcip,
3177 3177                              (ohci_pipe_private_t *)ph->p_hcd_private,
3178 3178                              tw, usb_flags);
3179 3179                  }
3180 3180          }
3181 3181  
3182 3182          mutex_exit(&ohcip->ohci_int_mutex);
3183 3183  
3184 3184          return (error);
3185 3185  }
3186 3186  
3187 3187  
3188 3188  /*
3189 3189   * ohci_hcdi_pipe_stop_isoc_polling()
3190 3190   */
3191 3191  static int
3192 3192  ohci_hcdi_pipe_stop_isoc_polling(
3193 3193          usba_pipe_handle_data_t *ph,
3194 3194          usb_flags_t             flags)
3195 3195  {
3196 3196          ohci_state_t            *ohcip = ohci_obtain_state(
3197 3197              ph->p_usba_device->usb_root_hub_dip);
3198 3198          int                     rval, error = USB_SUCCESS;
3199 3199  
3200 3200          USB_DPRINTF_L4(PRINT_MASK_HCDI, ohcip->ohci_log_hdl,
3201 3201              "ohci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x",
3202 3202              (void *)ph, flags);
3203 3203  
3204 3204          mutex_enter(&ohcip->ohci_int_mutex);
3205 3205          rval = ohci_state_is_operational(ohcip);
3206 3206  
3207 3207          if (rval != USB_SUCCESS) {
3208 3208                  mutex_exit(&ohcip->ohci_int_mutex);
3209 3209                  return (rval);
3210 3210          }
3211 3211  
3212 3212          error = ohci_stop_periodic_pipe_polling(ohcip, ph, flags);
3213 3213  
3214 3214          mutex_exit(&ohcip->ohci_int_mutex);
3215 3215          return (error);
3216 3216  }
3217 3217  
3218 3218  
3219 3219  /*
3220 3220   * Bandwidth Allocation functions
3221 3221   */
3222 3222  
3223 3223  /*
3224 3224   * ohci_allocate_bandwidth:
3225 3225   *
3226 3226   * Figure out whether or not this interval may be supported. Return the index
3227 3227   * into the  lattice if it can be supported.  Return allocation failure if it
3228 3228   * can not be supported.
3229 3229   *
3230 3230   * The lattice structure looks like this with the bottom leaf actually
3231 3231   * being an array.  There is a total of 63 nodes in this tree.  The lattice tree
3232 3232   * itself is 0 based, while the bottom leaf array is 0 based.  The 0 bucket in
3233 3233   * the bottom leaf array is used to store the smalled allocated bandwidth of all
3234 3234   * the leaves.
3235 3235   *
3236 3236   *      0
3237 3237   *    1   2
3238 3238   *   3 4 5 6
3239 3239   *   ...
3240 3240   *  (32 33 ... 62 63)     <-- last row does not exist in lattice, but an array
3241 3241   *   0 1 2 3 ... 30 31
3242 3242   *
3243 3243   * We keep track of the bandwidth that each leaf uses.  First we search for the
3244 3244   * first leaf with the smallest used bandwidth.  Based on that leaf we find the
3245 3245   * parent node of that leaf based on the interval time.
3246 3246   *
3247 3247   * From the parent node, we find all the leafs of that subtree and update the
3248 3248   * additional bandwidth needed.  In order to balance the load the leaves are not
3249 3249   * executed directly from left to right, but scattered.  For a better picture
3250 3250   * refer to Section 3.3.2 in the OpenHCI 1.0 spec, there should be a figure
3251 3251   * showing the Interrupt ED Structure.
3252 3252   */
3253 3253  static int
3254 3254  ohci_allocate_bandwidth(
3255 3255          ohci_state_t            *ohcip,
3256 3256          usba_pipe_handle_data_t *ph,
3257 3257          uint_t                  *node)
3258 3258  {
3259 3259          int                     interval, error, i;
3260 3260          uint_t                  min, min_index, height;
3261 3261          uint_t                  leftmost, list, bandwidth;
3262 3262          usb_ep_descr_t          *endpoint = &ph->p_ep;
3263 3263  
3264 3264          /* This routine is protected by the ohci_int_mutex */
3265 3265          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3266 3266  
3267 3267          /*
3268 3268           * Calculate the length in bytes of a transaction on this
3269 3269           * periodic endpoint.
3270 3270           */
3271 3271          mutex_enter(&ph->p_usba_device->usb_mutex);
3272 3272          error = ohci_compute_total_bandwidth(
3273 3273              endpoint, ph->p_usba_device->usb_port_status, &bandwidth);
3274 3274          mutex_exit(&ph->p_usba_device->usb_mutex);
3275 3275  
3276 3276          /*
3277 3277           * If length is zero, then, it means endpoint maximum packet
3278 3278           * supported is zero.  In that case, return failure without
3279 3279           * allocating any bandwidth.
3280 3280           */
3281 3281          if (error != USB_SUCCESS) {
3282 3282                  USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3283 3283                      "ohci_allocate_bandwidth: Periodic endpoint with "
3284 3284                      "zero endpoint maximum packet size is not supported");
3285 3285  
3286 3286                  return (USB_NOT_SUPPORTED);
3287 3287          }
3288 3288  
3289 3289          /*
3290 3290           * If the length in bytes plus the allocated bandwidth exceeds
3291 3291           * the maximum, return bandwidth allocation failure.
3292 3292           */
3293 3293          if ((ohcip->ohci_periodic_minimum_bandwidth + bandwidth) >
3294 3294              (MAX_PERIODIC_BANDWIDTH)) {
3295 3295  
3296 3296                  USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3297 3297                      "ohci_allocate_bandwidth: Reached maximum "
3298 3298                      "bandwidth value and cannot allocate bandwidth "
3299 3299                      "for a given periodic endpoint");
3300 3300  
3301 3301                  return (USB_NO_BANDWIDTH);
3302 3302          }
3303 3303  
3304 3304          /* Adjust polling interval to be a power of 2 */
3305 3305          mutex_enter(&ph->p_usba_device->usb_mutex);
3306 3306          interval = ohci_adjust_polling_interval(ohcip,
3307 3307              endpoint, ph->p_usba_device->usb_port_status);
3308 3308          mutex_exit(&ph->p_usba_device->usb_mutex);
3309 3309  
3310 3310          /*
3311 3311           * If this interval can't be supported,
3312 3312           * return allocation failure.
3313 3313           */
3314 3314          if (interval == USB_FAILURE) {
3315 3315  
3316 3316                  return (USB_FAILURE);
3317 3317          }
3318 3318  
3319 3319          USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3320 3320              "The new interval is %d", interval);
3321 3321  
3322 3322          /* Find the leaf with the smallest allocated bandwidth */
3323 3323          min_index = 0;
3324 3324          min = ohcip->ohci_periodic_bandwidth[0];
3325 3325  
3326 3326          for (i = 1; i < NUM_INTR_ED_LISTS; i++) {
3327 3327                  if (ohcip->ohci_periodic_bandwidth[i] < min) {
3328 3328                          min_index = i;
3329 3329                          min = ohcip->ohci_periodic_bandwidth[i];
3330 3330                  }
3331 3331          }
3332 3332  
3333 3333          USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3334 3334              "The leaf %d for minimal bandwidth %d", min_index, min);
3335 3335  
3336 3336          /* Adjust min for the lattice */
3337 3337          min_index = min_index + NUM_INTR_ED_LISTS - 1;
3338 3338  
3339 3339          /*
3340 3340           * Find the index into the lattice given the
3341 3341           * leaf with the smallest allocated bandwidth.
3342 3342           */
3343 3343          height = ohci_lattice_height(interval);
3344 3344  
3345 3345          USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3346 3346              "The height is %d", height);
3347 3347  
3348 3348          *node = min_index;
3349 3349  
3350 3350          for (i = 0; i < height; i++) {
3351 3351                  *node = ohci_lattice_parent(*node);
3352 3352          }
3353 3353  
3354 3354          USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3355 3355              "Real node is %d", *node);
3356 3356  
3357 3357          /*
3358 3358           * Find the leftmost leaf in the subtree
3359 3359           * specified by the node.
3360 3360           */
3361 3361          leftmost = ohci_leftmost_leaf(*node, height);
3362 3362  
3363 3363          USB_DPRINTF_L4(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3364 3364              "Leftmost %d", leftmost);
3365 3365  
3366 3366          for (i = 0; i < (NUM_INTR_ED_LISTS/interval); i++) {
3367 3367                  list = ohci_hcca_leaf_index(leftmost + i);
3368 3368                  if ((ohcip->ohci_periodic_bandwidth[list] +
3369 3369                      bandwidth) > MAX_PERIODIC_BANDWIDTH) {
3370 3370  
3371 3371                          USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3372 3372                              "ohci_allocate_bandwidth: Reached maximum "
3373 3373                              "bandwidth value and cannot allocate bandwidth "
3374 3374                              "for periodic endpoint");
3375 3375  
3376 3376                          return (USB_NO_BANDWIDTH);
3377 3377                  }
3378 3378          }
3379 3379  
3380 3380          /*
3381 3381           * All the leaves for this node must be updated with the bandwidth.
3382 3382           */
3383 3383          for (i = 0; i < (NUM_INTR_ED_LISTS/interval); i++) {
3384 3384                  list = ohci_hcca_leaf_index(leftmost + i);
3385 3385                  ohcip->ohci_periodic_bandwidth[list] += bandwidth;
3386 3386          }
3387 3387  
3388 3388          /* Find the leaf with the smallest allocated bandwidth */
3389 3389          min_index = 0;
3390 3390          min = ohcip->ohci_periodic_bandwidth[0];
3391 3391  
3392 3392          for (i = 1; i < NUM_INTR_ED_LISTS; i++) {
3393 3393                  if (ohcip->ohci_periodic_bandwidth[i] < min) {
3394 3394                          min_index = i;
3395 3395                          min = ohcip->ohci_periodic_bandwidth[i];
3396 3396                  }
3397 3397          }
3398 3398  
3399 3399          /* Save the minimum for later use */
3400 3400          ohcip->ohci_periodic_minimum_bandwidth = min;
3401 3401  
3402 3402          return (USB_SUCCESS);
3403 3403  }
3404 3404  
3405 3405  
3406 3406  /*
3407 3407   * ohci_deallocate_bandwidth:
3408 3408   *
3409 3409   * Deallocate bandwidth for the given node in the lattice and the length
3410 3410   * of transfer.
3411 3411   */
3412 3412  static void
3413 3413  ohci_deallocate_bandwidth(
3414 3414          ohci_state_t            *ohcip,
3415 3415          usba_pipe_handle_data_t *ph)
3416 3416  {
3417 3417          uint_t                  min, node, bandwidth;
3418 3418          uint_t                  height, leftmost, list;
3419 3419          int                     i, interval;
3420 3420          usb_ep_descr_t          *endpoint = &ph->p_ep;
3421 3421          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
3422 3422  
3423 3423          /* This routine is protected by the ohci_int_mutex */
3424 3424          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3425 3425  
3426 3426          /* Obtain the length */
3427 3427          mutex_enter(&ph->p_usba_device->usb_mutex);
3428 3428          (void) ohci_compute_total_bandwidth(
3429 3429              endpoint, ph->p_usba_device->usb_port_status, &bandwidth);
3430 3430          mutex_exit(&ph->p_usba_device->usb_mutex);
3431 3431  
3432 3432          /* Obtain the node */
3433 3433          node = pp->pp_node;
3434 3434  
3435 3435          /* Adjust polling interval to be a power of 2 */
3436 3436          mutex_enter(&ph->p_usba_device->usb_mutex);
3437 3437          interval = ohci_adjust_polling_interval(ohcip,
3438 3438              endpoint, ph->p_usba_device->usb_port_status);
3439 3439          mutex_exit(&ph->p_usba_device->usb_mutex);
3440 3440  
3441 3441          /* Find the height in the tree */
3442 3442          height = ohci_lattice_height(interval);
3443 3443  
3444 3444          /*
3445 3445           * Find the leftmost leaf in the subtree specified by the node
3446 3446           */
3447 3447          leftmost = ohci_leftmost_leaf(node, height);
3448 3448  
3449 3449          /* Delete the bandwith from the appropriate lists */
3450 3450          for (i = 0; i < (NUM_INTR_ED_LISTS/interval); i++) {
3451 3451                  list = ohci_hcca_leaf_index(leftmost + i);
3452 3452                  ohcip->ohci_periodic_bandwidth[list] -= bandwidth;
3453 3453          }
3454 3454  
3455 3455          min = ohcip->ohci_periodic_bandwidth[0];
3456 3456  
3457 3457          /* Recompute the minimum */
3458 3458          for (i = 1; i < NUM_INTR_ED_LISTS; i++) {
3459 3459                  if (ohcip->ohci_periodic_bandwidth[i] < min) {
3460 3460                          min = ohcip->ohci_periodic_bandwidth[i];
3461 3461                  }
3462 3462          }
3463 3463  
3464 3464          /* Save the minimum for later use */
3465 3465          ohcip->ohci_periodic_minimum_bandwidth = min;
3466 3466  }
3467 3467  
3468 3468  
3469 3469  /*
3470 3470   * ohci_compute_total_bandwidth:
3471 3471   *
3472 3472   * Given a periodic endpoint (interrupt or isochronous) determine the total
3473 3473   * bandwidth for one transaction. The OpenHCI host controller traverses the
3474 3474   * endpoint descriptor lists on a first-come-first-serve basis. When the HC
3475 3475   * services an endpoint, only a single transaction attempt is made. The  HC
3476 3476   * moves to the next Endpoint Descriptor after the first transaction attempt
3477 3477   * rather than finishing the entire Transfer Descriptor. Therefore, when  a
3478 3478   * Transfer Descriptor is inserted into the lattice, we will only count the
3479 3479   * number of bytes for one transaction.
3480 3480   *
3481 3481   * The following are the formulas used for  calculating bandwidth in  terms
3482 3482   * bytes and it is for the single USB full speed and low speed  transaction
3483 3483   * respectively. The protocol overheads will be different for each of  type
3484 3484   * of USB transfer and all these formulas & protocol overheads are  derived
3485 3485   * from the 5.9.3 section of USB Specification & with the help of Bandwidth
3486 3486   * Analysis white paper which is posted on the USB  developer forum.
3487 3487   *
3488 3488   * Full-Speed:
3489 3489   *              Protocol overhead  + ((MaxPacketSize * 7)/6 )  + Host_Delay
3490 3490   *
3491 3491   * Low-Speed:
3492 3492   *              Protocol overhead  + Hub LS overhead +
3493 3493   *                (Low-Speed clock * ((MaxPacketSize * 7)/6 )) + Host_Delay
3494 3494   */
3495 3495  static int
3496 3496  ohci_compute_total_bandwidth(
3497 3497          usb_ep_descr_t          *endpoint,
3498 3498          usb_port_status_t       port_status,
3499 3499          uint_t                  *bandwidth)
3500 3500  {
3501 3501          ushort_t                maxpacketsize = endpoint->wMaxPacketSize;
3502 3502  
3503 3503          /*
3504 3504           * If endpoint maximum packet is zero, then return immediately.
3505 3505           */
3506 3506          if (maxpacketsize == 0) {
3507 3507  
3508 3508                  return (USB_NOT_SUPPORTED);
3509 3509          }
3510 3510  
3511 3511          /* Add Host Controller specific delay to required bandwidth */
3512 3512          *bandwidth = HOST_CONTROLLER_DELAY;
3513 3513  
3514 3514          /* Add bit-stuffing overhead */
3515 3515          maxpacketsize = (ushort_t)((maxpacketsize * 7) / 6);
3516 3516  
3517 3517          /* Low Speed interrupt transaction */
3518 3518          if (port_status == USBA_LOW_SPEED_DEV) {
3519 3519                  /* Low Speed interrupt transaction */
3520 3520                  *bandwidth += (LOW_SPEED_PROTO_OVERHEAD +
3521 3521                      HUB_LOW_SPEED_PROTO_OVERHEAD +
3522 3522                      (LOW_SPEED_CLOCK * maxpacketsize));
3523 3523          } else {
3524 3524                  /* Full Speed transaction */
3525 3525                  *bandwidth += maxpacketsize;
3526 3526  
3527 3527                  if ((endpoint->bmAttributes &
3528 3528                      USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) {
3529 3529                          /* Full Speed interrupt transaction */
3530 3530                          *bandwidth += FS_NON_ISOC_PROTO_OVERHEAD;
3531 3531                  } else {
3532 3532                          /* Isochronous and input transaction */
3533 3533                          if ((endpoint->bEndpointAddress &
3534 3534                              USB_EP_DIR_MASK) == USB_EP_DIR_IN) {
3535 3535                                  *bandwidth += FS_ISOC_INPUT_PROTO_OVERHEAD;
3536 3536                          } else {
3537 3537                                  /* Isochronous and output transaction */
3538 3538                                  *bandwidth += FS_ISOC_OUTPUT_PROTO_OVERHEAD;
3539 3539                          }
3540 3540                  }
3541 3541          }
3542 3542  
3543 3543          return (USB_SUCCESS);
3544 3544  }
3545 3545  
3546 3546  
3547 3547  /*
3548 3548   * ohci_adjust_polling_interval:
3549 3549   */
3550 3550  static int
3551 3551  ohci_adjust_polling_interval(
3552 3552          ohci_state_t            *ohcip,
3553 3553          usb_ep_descr_t          *endpoint,
3554 3554          usb_port_status_t       port_status)
3555 3555  {
3556 3556          uint_t                  interval;
3557 3557          int                     i = 0;
3558 3558  
3559 3559          /*
3560 3560           * Get the polling interval from the endpoint descriptor
3561 3561           */
3562 3562          interval = endpoint->bInterval;
3563 3563  
3564 3564          /*
3565 3565           * The bInterval value in the endpoint descriptor can range
3566 3566           * from 1 to 255ms. The interrupt lattice has 32 leaf nodes,
3567 3567           * and the host controller cycles through these nodes every
3568 3568           * 32ms. The longest polling  interval that the  controller
3569 3569           * supports is 32ms.
3570 3570           */
3571 3571  
3572 3572          /*
3573 3573           * Return an error if the polling interval is less than 1ms
3574 3574           * and greater than 255ms
3575 3575           */
3576 3576          if ((interval < MIN_POLL_INTERVAL) ||
3577 3577              (interval > MAX_POLL_INTERVAL)) {
3578 3578  
3579 3579                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3580 3580                      "ohci_adjust_polling_interval: "
3581 3581                      "Endpoint's poll interval must be between %d and %d ms",
3582 3582                      MIN_POLL_INTERVAL, MAX_POLL_INTERVAL);
3583 3583  
3584 3584                  return (USB_FAILURE);
3585 3585          }
3586 3586  
3587 3587          /*
3588 3588           * According USB Specifications, a  full-speed endpoint can
3589 3589           * specify a desired polling interval 1ms to 255ms and a low
3590 3590           * speed  endpoints are limited to  specifying only 10ms to
3591 3591           * 255ms. But some old keyboards & mice uses polling interval
3592 3592           * of 8ms. For compatibility  purpose, we are using polling
3593 3593           * interval between 8ms & 255ms for low speed endpoints. But
3594 3594           * ohci driver will reject the any low speed endpoints which
3595 3595           * request polling interval less than 8ms.
3596 3596           */
3597 3597          if ((port_status == USBA_LOW_SPEED_DEV) &&
3598 3598              (interval < MIN_LOW_SPEED_POLL_INTERVAL)) {
3599 3599  
3600 3600                  USB_DPRINTF_L2(PRINT_MASK_BW, ohcip->ohci_log_hdl,
3601 3601                      "ohci_adjust_polling_interval: "
3602 3602                      "Low speed endpoint's poll interval of %d ms "
3603 3603                      "is below threshold.  Rounding up to %d ms",
3604 3604                      interval, MIN_LOW_SPEED_POLL_INTERVAL);
3605 3605  
3606 3606                  interval = MIN_LOW_SPEED_POLL_INTERVAL;
3607 3607          }
3608 3608  
3609 3609          /*
3610 3610           * If polling interval is greater than 32ms,
3611 3611           * adjust polling interval equal to 32ms.
3612 3612           */
3613 3613          if (interval > NUM_INTR_ED_LISTS) {
3614 3614                  interval = NUM_INTR_ED_LISTS;
3615 3615          }
3616 3616  
3617 3617          /*
3618 3618           * Find the nearest power of 2 that'sless
3619 3619           * than interval.
3620 3620           */
3621 3621          while ((ohci_pow_2(i)) <= interval) {
3622 3622                  i++;
3623 3623          }
3624 3624  
3625 3625          return (ohci_pow_2((i - 1)));
3626 3626  }
3627 3627  
3628 3628  
3629 3629  /*
3630 3630   * ohci_lattice_height:
3631 3631   *
3632 3632   * Given the requested bandwidth, find the height in the tree at which the
3633 3633   * nodes for this bandwidth fall.  The height is measured as the number of
3634 3634   * nodes from the leaf to the level specified by bandwidth The root of the
3635 3635   * tree is at height TREE_HEIGHT.
3636 3636   */
3637 3637  static uint_t
3638 3638  ohci_lattice_height(uint_t interval)
3639 3639  {
3640 3640          return (TREE_HEIGHT - (ohci_log_2(interval)));
3641 3641  }
3642 3642  
3643 3643  
3644 3644  /*
3645 3645   * ohci_lattice_parent:
3646 3646   */
3647 3647  static uint_t
3648 3648  ohci_lattice_parent(uint_t node)
3649 3649  {
3650 3650          if ((node % 2) == 0) {
3651 3651                  return ((node/2) - 1);
3652 3652          } else {
3653 3653                  return ((node + 1)/2 - 1);
3654 3654          }
3655 3655  }
3656 3656  
3657 3657  
3658 3658  /*
3659 3659   * ohci_leftmost_leaf:
3660 3660   *
3661 3661   * Find the leftmost leaf in the subtree specified by the node. Height refers
3662 3662   * to number of nodes from the bottom of the tree to the node,  including the
3663 3663   * node.
3664 3664   *
3665 3665   * The formula for a zero based tree is:
3666 3666   *     2^H * Node + 2^H - 1
3667 3667   * The leaf of the tree is an array, convert the number for the array.
3668 3668   *     Subtract the size of nodes not in the array
3669 3669   *     2^H * Node + 2^H - 1 - (NUM_INTR_ED_LIST - 1) =
3670 3670   *     2^H * Node + 2^H - NUM_INTR_ED_LIST =
3671 3671   *     2^H * (Node + 1) - NUM_INTR_ED_LIST
3672 3672   *         0
3673 3673   *       1   2
3674 3674   *      0 1 2 3
3675 3675   */
3676 3676  static uint_t
3677 3677  ohci_leftmost_leaf(
3678 3678          uint_t  node,
3679 3679          uint_t  height)
3680 3680  {
3681 3681          return ((ohci_pow_2(height) * (node + 1)) - NUM_INTR_ED_LISTS);
3682 3682  }
3683 3683  
3684 3684  /*
3685 3685   * ohci_hcca_intr_index:
3686 3686   *
3687 3687   * Given a node in the lattice, find the index for the hcca interrupt table
3688 3688   */
3689 3689  static uint_t
3690 3690  ohci_hcca_intr_index(uint_t node)
3691 3691  {
3692 3692          /*
3693 3693           * Adjust the node to the array representing
3694 3694           * the bottom of the tree.
3695 3695           */
3696 3696          node = node - NUM_STATIC_NODES;
3697 3697  
3698 3698          if ((node % 2) == 0) {
3699 3699                  return (ohci_index[node / 2]);
3700 3700          } else {
3701 3701                  return (ohci_index[node / 2] + (NUM_INTR_ED_LISTS / 2));
3702 3702          }
3703 3703  }
3704 3704  
3705 3705  /*
3706 3706   * ohci_hcca_leaf_index:
3707 3707   *
3708 3708   * Given a node in the bottom leaf array of the lattice, find the index
3709 3709   * for the hcca interrupt table
3710 3710   */
3711 3711  static uint_t
3712 3712  ohci_hcca_leaf_index(uint_t leaf)
3713 3713  {
3714 3714          if ((leaf % 2) == 0) {
3715 3715                  return (ohci_index[leaf / 2]);
3716 3716          } else {
3717 3717                  return (ohci_index[leaf / 2] + (NUM_INTR_ED_LISTS / 2));
3718 3718          }
3719 3719  }
3720 3720  
3721 3721  /*
3722 3722   * ohci_pow_2:
3723 3723   *
3724 3724   * Compute 2 to the power
3725 3725   */
3726 3726  static uint_t
3727 3727  ohci_pow_2(uint_t x)
3728 3728  {
3729 3729          if (x == 0) {
3730 3730                  return (1);
3731 3731          } else {
3732 3732                  return (2 << (x - 1));
3733 3733          }
3734 3734  }
3735 3735  
3736 3736  
3737 3737  /*
3738 3738   * ohci_log_2:
3739 3739   *
3740 3740   * Compute log base 2 of x
3741 3741   */
3742 3742  static uint_t
3743 3743  ohci_log_2(uint_t x)
3744 3744  {
3745 3745          int i = 0;
3746 3746  
3747 3747          while (x != 1) {
3748 3748                  x = x >> 1;
3749 3749                  i++;
3750 3750          }
3751 3751  
3752 3752          return (i);
3753 3753  }
3754 3754  
3755 3755  
3756 3756  /*
3757 3757   * Endpoint Descriptor (ED) manipulations functions
3758 3758   */
3759 3759  
3760 3760  /*
3761 3761   * ohci_alloc_hc_ed:
3762 3762   * NOTE: This function is also called from POLLED MODE.
3763 3763   *
3764 3764   * Allocate an endpoint descriptor (ED)
3765 3765   */
3766 3766  ohci_ed_t *
3767 3767  ohci_alloc_hc_ed(
3768 3768          ohci_state_t            *ohcip,
3769 3769          usba_pipe_handle_data_t *ph)
3770 3770  {
3771 3771          int                     i, state;
3772 3772          ohci_ed_t               *hc_ed;
3773 3773  
3774 3774          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3775 3775              "ohci_alloc_hc_ed: ph = 0x%p", (void *)ph);
3776 3776  
3777 3777          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3778 3778  
3779 3779          /*
3780 3780           * The first 31 endpoints in the Endpoint Descriptor (ED)
3781 3781           * buffer pool are reserved for building interrupt lattice
3782 3782           * tree. Search for a blank endpoint descriptor in the ED
3783 3783           * buffer pool.
3784 3784           */
3785 3785          for (i = NUM_STATIC_NODES; i < ohci_ed_pool_size; i ++) {
3786 3786                  state = Get_ED(ohcip->ohci_ed_pool_addr[i].hced_state);
3787 3787  
3788 3788                  if (state == HC_EPT_FREE) {
3789 3789                          break;
3790 3790                  }
3791 3791          }
3792 3792  
3793 3793          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3794 3794              "ohci_alloc_hc_ed: Allocated %d", i);
3795 3795  
3796 3796          if (i == ohci_ed_pool_size) {
3797 3797                  USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3798 3798                      "ohci_alloc_hc_ed: ED exhausted");
3799 3799  
3800 3800                  return (NULL);
3801 3801          } else {
3802 3802  
3803 3803                  hc_ed = &ohcip->ohci_ed_pool_addr[i];
3804 3804  
3805 3805                  USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
3806 3806                      "ohci_alloc_hc_ed: Allocated address 0x%p", (void *)hc_ed);
3807 3807  
3808 3808                  ohci_print_ed(ohcip, hc_ed);
3809 3809  
3810 3810                  /* Unpack the endpoint descriptor into a control field */
3811 3811                  if (ph) {
3812 3812                          if ((ohci_initialize_dummy(ohcip,
3813 3813                              hc_ed)) == USB_NO_RESOURCES) {
3814 3814                                  bzero((void *)hc_ed, sizeof (ohci_ed_t));
3815 3815                                  Set_ED(hc_ed->hced_state, HC_EPT_FREE);
3816 3816                                  return (NULL);
3817 3817                          }
3818 3818  
3819 3819                          Set_ED(hc_ed->hced_prev, NULL);
3820 3820                          Set_ED(hc_ed->hced_next, NULL);
3821 3821  
3822 3822                          /* Change ED's state Active */
3823 3823                          Set_ED(hc_ed->hced_state, HC_EPT_ACTIVE);
3824 3824  
3825 3825                          Set_ED(hc_ed->hced_ctrl,
3826 3826                              ohci_unpack_endpoint(ohcip, ph));
3827 3827                  } else {
3828 3828                          Set_ED(hc_ed->hced_ctrl, HC_EPT_sKip);
3829 3829  
3830 3830                          /* Change ED's state Static */
3831 3831                          Set_ED(hc_ed->hced_state, HC_EPT_STATIC);
3832 3832                  }
3833 3833  
3834 3834                  return (hc_ed);
3835 3835          }
3836 3836  }
3837 3837  
3838 3838  
3839 3839  /*
3840 3840   * ohci_unpack_endpoint:
3841 3841   *
3842 3842   * Unpack the information in the pipe handle and create the first byte
3843 3843   * of the Host Controller's (HC) Endpoint Descriptor (ED).
3844 3844   */
3845 3845  static uint_t
3846 3846  ohci_unpack_endpoint(
3847 3847          ohci_state_t            *ohcip,
3848 3848          usba_pipe_handle_data_t *ph)
3849 3849  {
3850 3850          usb_ep_descr_t          *endpoint = &ph->p_ep;
3851 3851          uint_t                  maxpacketsize, addr, ctrl = 0;
3852 3852  
3853 3853          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3854 3854              "ohci_unpack_endpoint:");
3855 3855  
3856 3856          ctrl = ph->p_usba_device->usb_addr;
3857 3857  
3858 3858          addr = endpoint->bEndpointAddress;
3859 3859  
3860 3860          /* Assign the endpoint's address */
3861 3861          ctrl = ctrl | ((addr & USB_EP_NUM_MASK) << HC_EPT_EP_SHFT);
3862 3862  
3863 3863          /*
3864 3864           * Assign the direction. If the endpoint is a control endpoint,
3865 3865           * the direction is assigned by the Transfer Descriptor (TD).
3866 3866           */
3867 3867          if ((endpoint->bmAttributes &
3868 3868              USB_EP_ATTR_MASK) != USB_EP_ATTR_CONTROL) {
3869 3869                  if (addr & USB_EP_DIR_MASK) {
3870 3870                          /* The direction is IN */
3871 3871                          ctrl = ctrl | HC_EPT_DF_IN;
3872 3872                  } else {
3873 3873                          /* The direction is OUT */
3874 3874                          ctrl = ctrl | HC_EPT_DF_OUT;
3875 3875                  }
3876 3876          }
3877 3877  
3878 3878          /* Assign the speed */
3879 3879          mutex_enter(&ph->p_usba_device->usb_mutex);
3880 3880          if (ph->p_usba_device->usb_port_status == USBA_LOW_SPEED_DEV) {
3881 3881                  ctrl = ctrl | HC_EPT_Speed;
3882 3882          }
3883 3883          mutex_exit(&ph->p_usba_device->usb_mutex);
3884 3884  
3885 3885          /* Assign the format */
3886 3886          if ((endpoint->bmAttributes &
3887 3887              USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
3888 3888                  ctrl = ctrl | HC_EPT_Format;
3889 3889          }
3890 3890  
3891 3891          maxpacketsize = endpoint->wMaxPacketSize;
3892 3892          maxpacketsize = maxpacketsize << HC_EPT_MAXPKTSZ;
3893 3893          ctrl = ctrl | (maxpacketsize & HC_EPT_MPS);
3894 3894  
3895 3895          return (ctrl);
3896 3896  }
3897 3897  
3898 3898  
3899 3899  /*
3900 3900   * ohci_insert_ed:
3901 3901   *
3902 3902   * Add the Endpoint Descriptor (ED) into the Host Controller's
3903 3903   * (HC) appropriate endpoint list.
3904 3904   */
3905 3905  static void
3906 3906  ohci_insert_ed(
3907 3907          ohci_state_t            *ohcip,
3908 3908          usba_pipe_handle_data_t *ph)
3909 3909  {
3910 3910          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
3911 3911  
3912 3912          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3913 3913              "ohci_insert_ed:");
3914 3914  
3915 3915          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3916 3916  
3917 3917          switch (ph->p_ep.bmAttributes & USB_EP_ATTR_MASK) {
3918 3918          case USB_EP_ATTR_CONTROL:
3919 3919                  ohci_insert_ctrl_ed(ohcip, pp);
3920 3920                  break;
3921 3921          case USB_EP_ATTR_BULK:
3922 3922                  ohci_insert_bulk_ed(ohcip, pp);
3923 3923                  break;
3924 3924          case USB_EP_ATTR_INTR:
3925 3925                  ohci_insert_intr_ed(ohcip, pp);
3926 3926                  break;
3927 3927          case USB_EP_ATTR_ISOCH:
3928 3928                  ohci_insert_isoc_ed(ohcip, pp);
3929 3929                  break;
3930 3930          }
3931 3931  }
3932 3932  
3933 3933  
3934 3934  /*
3935 3935   * ohci_insert_ctrl_ed:
3936 3936   *
3937 3937   * Insert a control endpoint into the Host Controller's (HC)
3938 3938   * control endpoint list.
3939 3939   */
3940 3940  static void
3941 3941  ohci_insert_ctrl_ed(
3942 3942          ohci_state_t            *ohcip,
3943 3943          ohci_pipe_private_t     *pp)
3944 3944  {
3945 3945          ohci_ed_t       *ept = pp->pp_ept;
3946 3946          ohci_ed_t       *prev_ept;
3947 3947  
3948 3948          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3949 3949              "ohci_insert_ctrl_ed:");
3950 3950  
3951 3951          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3952 3952  
3953 3953          /* Obtain a ptr to the head of the list */
3954 3954          if (Get_OpReg(hcr_ctrl_head)) {
3955 3955                  prev_ept = ohci_ed_iommu_to_cpu(ohcip,
3956 3956                      Get_OpReg(hcr_ctrl_head));
3957 3957  
3958 3958                  /* Set up the backwards pointer */
3959 3959                  Set_ED(prev_ept->hced_prev, ohci_ed_cpu_to_iommu(ohcip, ept));
3960 3960          }
3961 3961  
3962 3962          /* The new endpoint points to the head of the list */
3963 3963          Set_ED(ept->hced_next, Get_OpReg(hcr_ctrl_head));
3964 3964  
3965 3965          /* Set the head ptr to the new endpoint */
3966 3966          Set_OpReg(hcr_ctrl_head, ohci_ed_cpu_to_iommu(ohcip, ept));
3967 3967  
3968 3968          /*
3969 3969           * Enable Control list processing if control open
3970 3970           * pipe count is zero.
3971 3971           */
3972 3972          if (!ohcip->ohci_open_ctrl_pipe_count) {
3973 3973                  /* Start Control list processing */
3974 3974                  Set_OpReg(hcr_control,
3975 3975                      (Get_OpReg(hcr_control) | HCR_CONTROL_CLE));
3976 3976          }
3977 3977  
3978 3978          ohcip->ohci_open_ctrl_pipe_count++;
3979 3979  }
3980 3980  
3981 3981  
3982 3982  /*
3983 3983   * ohci_insert_bulk_ed:
3984 3984   *
3985 3985   * Insert a bulk endpoint into the Host Controller's (HC) bulk endpoint list.
3986 3986   */
3987 3987  static void
3988 3988  ohci_insert_bulk_ed(
3989 3989          ohci_state_t            *ohcip,
3990 3990          ohci_pipe_private_t     *pp)
3991 3991  {
3992 3992          ohci_ed_t               *ept = pp->pp_ept;
3993 3993          ohci_ed_t               *prev_ept;
3994 3994  
3995 3995          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
3996 3996              "ohci_insert_bulk_ed:");
3997 3997  
3998 3998          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
3999 3999  
4000 4000          /* Obtain a ptr to the head of the Bulk list */
4001 4001          if (Get_OpReg(hcr_bulk_head)) {
4002 4002                  prev_ept = ohci_ed_iommu_to_cpu(ohcip,
4003 4003                      Get_OpReg(hcr_bulk_head));
4004 4004  
4005 4005                  /* Set up the backwards pointer */
4006 4006                  Set_ED(prev_ept->hced_prev, ohci_ed_cpu_to_iommu(ohcip, ept));
4007 4007          }
4008 4008  
4009 4009          /* The new endpoint points to the head of the Bulk list */
4010 4010          Set_ED(ept->hced_next, Get_OpReg(hcr_bulk_head));
4011 4011  
4012 4012          /* Set the Bulk head ptr to the new endpoint */
4013 4013          Set_OpReg(hcr_bulk_head, ohci_ed_cpu_to_iommu(ohcip, ept));
4014 4014  
4015 4015          /*
4016 4016           * Enable Bulk list processing if bulk open pipe
4017 4017           * count is zero.
4018 4018           */
4019 4019          if (!ohcip->ohci_open_bulk_pipe_count) {
4020 4020                  /* Start Bulk list processing */
4021 4021                  Set_OpReg(hcr_control,
4022 4022                      (Get_OpReg(hcr_control) | HCR_CONTROL_BLE));
4023 4023          }
4024 4024  
4025 4025          ohcip->ohci_open_bulk_pipe_count++;
4026 4026  }
4027 4027  
4028 4028  
4029 4029  /*
4030 4030   * ohci_insert_intr_ed:
4031 4031   *
4032 4032   * Insert a interrupt endpoint into the Host Controller's (HC) interrupt
4033 4033   * lattice tree.
4034 4034   */
4035 4035  static void
4036 4036  ohci_insert_intr_ed(
4037 4037          ohci_state_t            *ohcip,
4038 4038          ohci_pipe_private_t     *pp)
4039 4039  {
4040 4040          ohci_ed_t               *ept = pp->pp_ept;
4041 4041          ohci_ed_t               *next_lattice_ept, *lattice_ept;
4042 4042          uint_t                  node;
4043 4043  
4044 4044          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4045 4045  
4046 4046          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4047 4047              "ohci_insert_intr_ed:");
4048 4048  
4049 4049          /*
4050 4050           * The appropriate node was found
4051 4051           * during the opening of the pipe.
4052 4052           */
4053 4053          node = pp->pp_node;
4054 4054  
4055 4055          if (node >= NUM_STATIC_NODES) {
4056 4056                  /* Get the hcca interrupt table index */
4057 4057                  node = ohci_hcca_intr_index(node);
4058 4058  
4059 4059                  /* Get the first endpoint on the list */
4060 4060                  next_lattice_ept = ohci_ed_iommu_to_cpu(ohcip,
4061 4061                      Get_HCCA(ohcip->ohci_hccap->HccaIntTble[node]));
4062 4062  
4063 4063                  /* Update this endpoint to point to it */
4064 4064                  Set_ED(ept->hced_next,
4065 4065                      ohci_ed_cpu_to_iommu(ohcip, next_lattice_ept));
4066 4066  
4067 4067                  /* Put this endpoint at the head of the list */
4068 4068                  Set_HCCA(ohcip->ohci_hccap->HccaIntTble[node],
4069 4069                      ohci_ed_cpu_to_iommu(ohcip, ept));
4070 4070  
4071 4071                  /* The previous pointer is NULL */
4072 4072                  Set_ED(ept->hced_prev, NULL);
4073 4073  
4074 4074                  /* Update the previous pointer of ept->hced_next */
4075 4075                  if (Get_ED(next_lattice_ept->hced_state) != HC_EPT_STATIC) {
4076 4076                          Set_ED(next_lattice_ept->hced_prev,
4077 4077                              ohci_ed_cpu_to_iommu(ohcip, ept));
4078 4078                  }
4079 4079          } else {
4080 4080                  /* Find the lattice endpoint */
4081 4081                  lattice_ept = &ohcip->ohci_ed_pool_addr[node];
4082 4082  
4083 4083                  /* Find the next lattice endpoint */
4084 4084                  next_lattice_ept = ohci_ed_iommu_to_cpu(
4085 4085                      ohcip, Get_ED(lattice_ept->hced_next));
4086 4086  
4087 4087                  /*
4088 4088                   * Update this endpoint to point to the next one in the
4089 4089                   * lattice.
4090 4090                   */
4091 4091                  Set_ED(ept->hced_next, Get_ED(lattice_ept->hced_next));
4092 4092  
4093 4093                  /* Insert this endpoint into the lattice */
4094 4094                  Set_ED(lattice_ept->hced_next,
4095 4095                      ohci_ed_cpu_to_iommu(ohcip, ept));
4096 4096  
4097 4097                  /* Update the previous pointer */
4098 4098                  Set_ED(ept->hced_prev,
4099 4099                      ohci_ed_cpu_to_iommu(ohcip, lattice_ept));
4100 4100  
4101 4101                  /* Update the previous pointer of ept->hced_next */
4102 4102                  if ((next_lattice_ept) &&
4103 4103                      (Get_ED(next_lattice_ept->hced_state) != HC_EPT_STATIC)) {
4104 4104  
4105 4105                          Set_ED(next_lattice_ept->hced_prev,
4106 4106                              ohci_ed_cpu_to_iommu(ohcip, ept));
4107 4107                  }
4108 4108          }
4109 4109  
4110 4110          /*
4111 4111           * Enable periodic list processing if periodic (interrupt
4112 4112           * and isochronous) open pipe count is zero.
4113 4113           */
4114 4114          if (!ohcip->ohci_open_periodic_pipe_count) {
4115 4115                  ASSERT(!ohcip->ohci_open_isoch_pipe_count);
4116 4116  
4117 4117                  Set_OpReg(hcr_control,
4118 4118                      (Get_OpReg(hcr_control) | HCR_CONTROL_PLE));
4119 4119          }
4120 4120  
4121 4121          ohcip->ohci_open_periodic_pipe_count++;
4122 4122  }
4123 4123  
4124 4124  
4125 4125  /*
4126 4126   * ohci_insert_isoc_ed:
4127 4127   *
4128 4128   * Insert a isochronous endpoint into the Host Controller's (HC) interrupt
4129 4129   * lattice tree. A isochronous endpoint will be inserted at the end of the
4130 4130   * 1ms interrupt endpoint list.
4131 4131   */
4132 4132  static void
4133 4133  ohci_insert_isoc_ed(
4134 4134          ohci_state_t            *ohcip,
4135 4135          ohci_pipe_private_t     *pp)
4136 4136  {
4137 4137          ohci_ed_t               *next_lattice_ept, *lattice_ept;
4138 4138          ohci_ed_t               *ept = pp->pp_ept;
4139 4139          uint_t                  node;
4140 4140  
4141 4141          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4142 4142  
4143 4143          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4144 4144              "ohci_insert_isoc_ed:");
4145 4145  
4146 4146          /*
4147 4147           * The appropriate node was found during the opening of the pipe.
4148 4148           * This  node must be root of the interrupt lattice tree.
4149 4149           */
4150 4150          node = pp->pp_node;
4151 4151  
4152 4152          ASSERT(node == 0);
4153 4153  
4154 4154          /* Find the 1ms interrupt lattice endpoint */
4155 4155          lattice_ept = &ohcip->ohci_ed_pool_addr[node];
4156 4156  
4157 4157          /* Find the next lattice endpoint */
4158 4158          next_lattice_ept = ohci_ed_iommu_to_cpu(
4159 4159              ohcip, Get_ED(lattice_ept->hced_next));
4160 4160  
4161 4161          while (next_lattice_ept) {
4162 4162                  lattice_ept = next_lattice_ept;
4163 4163  
4164 4164                  /* Find the next lattice endpoint */
4165 4165                  next_lattice_ept = ohci_ed_iommu_to_cpu(
4166 4166                      ohcip, Get_ED(lattice_ept->hced_next));
4167 4167          }
4168 4168  
4169 4169          /* The next pointer is NULL */
4170 4170          Set_ED(ept->hced_next, NULL);
4171 4171  
4172 4172          /* Update the previous pointer */
4173 4173          Set_ED(ept->hced_prev, ohci_ed_cpu_to_iommu(ohcip, lattice_ept));
4174 4174  
4175 4175          /* Insert this endpoint into the lattice */
4176 4176          Set_ED(lattice_ept->hced_next, ohci_ed_cpu_to_iommu(ohcip, ept));
4177 4177  
4178 4178          /*
4179 4179           * Enable periodic and isoch lists processing if isoch
4180 4180           * open pipe count is zero.
4181 4181           */
4182 4182          if (!ohcip->ohci_open_isoch_pipe_count) {
4183 4183  
4184 4184                  Set_OpReg(hcr_control, (Get_OpReg(hcr_control) |
4185 4185                      HCR_CONTROL_PLE | HCR_CONTROL_IE));
4186 4186          }
4187 4187  
4188 4188          ohcip->ohci_open_periodic_pipe_count++;
4189 4189          ohcip->ohci_open_isoch_pipe_count++;
4190 4190  }
4191 4191  
4192 4192  
4193 4193  /*
4194 4194   * ohci_modify_sKip_bit:
4195 4195   *
4196 4196   * Modify the sKip bit on the Host Controller (HC) Endpoint Descriptor (ED).
4197 4197   */
4198 4198  static void
4199 4199  ohci_modify_sKip_bit(
4200 4200          ohci_state_t            *ohcip,
4201 4201          ohci_pipe_private_t     *pp,
4202 4202          skip_bit_t              action,
4203 4203          usb_flags_t             flag)
4204 4204  {
4205 4205          ohci_ed_t               *ept = pp->pp_ept;
4206 4206  
4207 4207          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4208 4208              "ohci_modify_sKip_bit: action = 0x%x flag = 0x%x",
4209 4209              action, flag);
4210 4210  
4211 4211          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4212 4212  
4213 4213          if (action == CLEAR_sKip) {
4214 4214                  /*
4215 4215                   * If the skip bit is to be cleared, just clear it.
4216 4216                   * there shouldn't be any race condition problems.
4217 4217                   * If the host controller reads the bit before the
4218 4218                   * driver has a chance to set the bit, the bit will
4219 4219                   * be reread on the next frame.
4220 4220                   */
4221 4221                  Set_ED(ept->hced_ctrl, (Get_ED(ept->hced_ctrl) & ~HC_EPT_sKip));
4222 4222          } else {
4223 4223                  /* Sync ED and TD pool */
4224 4224                  if (flag & OHCI_FLAGS_DMA_SYNC) {
4225 4225                          Sync_ED_TD_Pool(ohcip);
4226 4226                  }
4227 4227  
4228 4228                  /* Check Halt or Skip bit is already set */
4229 4229                  if ((Get_ED(ept->hced_headp) & HC_EPT_Halt) ||
4230 4230                      (Get_ED(ept->hced_ctrl) & HC_EPT_sKip)) {
4231 4231  
4232 4232                          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4233 4233                              "ohci_modify_sKip_bit: "
4234 4234                              "Halt or Skip bit is already set");
4235 4235                  } else {
4236 4236                          /*
4237 4237                           * The action is to set the skip bit.  In order to
4238 4238                           * be sure that the HCD has seen the sKip bit, wait
4239 4239                           * for the next start of frame.
4240 4240                           */
4241 4241                          Set_ED(ept->hced_ctrl,
4242 4242                              (Get_ED(ept->hced_ctrl) | HC_EPT_sKip));
4243 4243  
4244 4244                          if (flag & OHCI_FLAGS_SLEEP) {
4245 4245                                  /* Wait for the next SOF */
4246 4246                                  (void) ohci_wait_for_sof(ohcip);
4247 4247  
4248 4248                                  /* Sync ED and TD pool */
4249 4249                                  if (flag & OHCI_FLAGS_DMA_SYNC) {
4250 4250                                          Sync_ED_TD_Pool(ohcip);
4251 4251                                  }
4252 4252                          }
4253 4253                  }
4254 4254          }
4255 4255  }
4256 4256  
4257 4257  
4258 4258  /*
4259 4259   * ohci_remove_ed:
4260 4260   *
4261 4261   * Remove the Endpoint Descriptor (ED) from the Host Controller's appropriate
4262 4262   * endpoint list.
4263 4263   */
4264 4264  static void
4265 4265  ohci_remove_ed(
4266 4266          ohci_state_t            *ohcip,
4267 4267          ohci_pipe_private_t     *pp)
4268 4268  {
4269 4269          uchar_t                 attributes;
4270 4270  
4271 4271          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4272 4272  
4273 4273          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4274 4274              "ohci_remove_ed:");
4275 4275  
4276 4276          attributes = pp->pp_pipe_handle->p_ep.bmAttributes & USB_EP_ATTR_MASK;
4277 4277  
4278 4278          switch (attributes) {
4279 4279          case USB_EP_ATTR_CONTROL:
4280 4280                  ohci_remove_ctrl_ed(ohcip, pp);
4281 4281                  break;
4282 4282          case USB_EP_ATTR_BULK:
4283 4283                  ohci_remove_bulk_ed(ohcip, pp);
4284 4284                  break;
4285 4285          case USB_EP_ATTR_INTR:
4286 4286          case USB_EP_ATTR_ISOCH:
4287 4287                  ohci_remove_periodic_ed(ohcip, pp);
4288 4288                  break;
4289 4289          }
4290 4290  }
4291 4291  
4292 4292  
4293 4293  /*
4294 4294   * ohci_remove_ctrl_ed:
4295 4295   *
4296 4296   * Remove a control Endpoint Descriptor (ED) from the Host Controller's (HC)
4297 4297   * control endpoint list.
4298 4298   */
4299 4299  static void
4300 4300  ohci_remove_ctrl_ed(
4301 4301          ohci_state_t            *ohcip,
4302 4302          ohci_pipe_private_t     *pp)
4303 4303  {
4304 4304          ohci_ed_t               *ept = pp->pp_ept; /* ept to be removed */
4305 4305  
4306 4306          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4307 4307              "ohci_remove_ctrl_ed:");
4308 4308  
4309 4309          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4310 4310  
4311 4311          /* The control list should already be stopped */
4312 4312          ASSERT(!(Get_OpReg(hcr_control) & HCR_CONTROL_CLE));
4313 4313  
4314 4314          ohcip->ohci_open_ctrl_pipe_count--;
4315 4315  
4316 4316          /* Detach the endpoint from the list that it's on */
4317 4317          ohci_detach_ed_from_list(ohcip, ept, USB_EP_ATTR_CONTROL);
4318 4318  
4319 4319          /*
4320 4320           * If next endpoint pointed by endpoint to be removed is not NULL
4321 4321           * then set current control pointer to the next endpoint pointed by
4322 4322           * endpoint to be removed. Otherwise set current control pointer to
4323 4323           * the beginning of the control list.
4324 4324           */
4325 4325          if (Get_ED(ept->hced_next)) {
4326 4326                  Set_OpReg(hcr_ctrl_curr, Get_ED(ept->hced_next));
4327 4327          } else {
4328 4328                  Set_OpReg(hcr_ctrl_curr, Get_OpReg(hcr_ctrl_head));
4329 4329          }
4330 4330  
4331 4331          if (ohcip->ohci_open_ctrl_pipe_count) {
4332 4332                  ASSERT(Get_OpReg(hcr_ctrl_head));
4333 4333  
4334 4334                  /* Reenable the control list */
4335 4335                  Set_OpReg(hcr_control,
4336 4336                      (Get_OpReg(hcr_control) | HCR_CONTROL_CLE));
4337 4337          }
4338 4338  
4339 4339          ohci_insert_ed_on_reclaim_list(ohcip, pp);
4340 4340  }
4341 4341  
4342 4342  
4343 4343  /*
4344 4344   * ohci_remove_bulk_ed:
4345 4345   *
4346 4346   * Remove free the  bulk Endpoint Descriptor (ED) from the Host Controller's
4347 4347   * (HC) bulk endpoint list.
4348 4348   */
4349 4349  static void
4350 4350  ohci_remove_bulk_ed(
4351 4351          ohci_state_t            *ohcip,
4352 4352          ohci_pipe_private_t     *pp)
4353 4353  {
4354 4354          ohci_ed_t               *ept = pp->pp_ept;      /* ept to be removed */
4355 4355  
4356 4356          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4357 4357              "ohci_remove_bulk_ed:");
4358 4358  
4359 4359          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4360 4360  
4361 4361          /* The bulk list should already be stopped */
4362 4362          ASSERT(!(Get_OpReg(hcr_control) & HCR_CONTROL_BLE));
4363 4363  
4364 4364          ohcip->ohci_open_bulk_pipe_count--;
4365 4365  
4366 4366          /* Detach the endpoint from the bulk list */
4367 4367          ohci_detach_ed_from_list(ohcip, ept, USB_EP_ATTR_BULK);
4368 4368  
4369 4369          /*
4370 4370           * If next endpoint pointed by endpoint to be removed is not NULL
4371 4371           * then set current bulk pointer to the next endpoint pointed by
4372 4372           * endpoint to be removed. Otherwise set current bulk pointer to
4373 4373           * the beginning of the bulk list.
4374 4374           */
4375 4375          if (Get_ED(ept->hced_next)) {
4376 4376                  Set_OpReg(hcr_bulk_curr, Get_ED(ept->hced_next));
4377 4377          } else {
4378 4378                  Set_OpReg(hcr_bulk_curr, Get_OpReg(hcr_bulk_head));
4379 4379          }
4380 4380  
4381 4381          if (ohcip->ohci_open_bulk_pipe_count) {
4382 4382                  ASSERT(Get_OpReg(hcr_bulk_head));
4383 4383  
4384 4384                  /* Re-enable the bulk list */
4385 4385                  Set_OpReg(hcr_control,
4386 4386                      (Get_OpReg(hcr_control) | HCR_CONTROL_BLE));
4387 4387          }
4388 4388  
4389 4389          ohci_insert_ed_on_reclaim_list(ohcip, pp);
4390 4390  }
4391 4391  
4392 4392  
4393 4393  /*
4394 4394   * ohci_remove_periodic_ed:
4395 4395   *
4396 4396   * Set up an periodic endpoint to be removed from the Host Controller's (HC)
4397 4397   * interrupt lattice tree. The Endpoint Descriptor (ED) will be freed in the
4398 4398   * interrupt handler.
4399 4399   */
4400 4400  static void
4401 4401  ohci_remove_periodic_ed(
4402 4402          ohci_state_t            *ohcip,
4403 4403          ohci_pipe_private_t     *pp)
4404 4404  {
4405 4405          ohci_ed_t               *ept = pp->pp_ept;      /* ept to be removed */
4406 4406          uint_t                  ept_type;
4407 4407  
4408 4408          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4409 4409              "ohci_remove_periodic_ed:");
4410 4410  
4411 4411          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4412 4412  
4413 4413          ASSERT((Get_ED(ept->hced_tailp) & HC_EPT_TD_TAIL) ==
4414 4414              (Get_ED(ept->hced_headp) & HC_EPT_TD_HEAD));
4415 4415  
4416 4416          ohcip->ohci_open_periodic_pipe_count--;
4417 4417  
4418 4418          ept_type = pp->pp_pipe_handle->
4419 4419              p_ep.bmAttributes & USB_EP_ATTR_MASK;
4420 4420  
4421 4421          if (ept_type == USB_EP_ATTR_ISOCH) {
4422 4422                  ohcip->ohci_open_isoch_pipe_count--;
4423 4423          }
4424 4424  
4425 4425          /* Store the node number */
4426 4426          Set_ED(ept->hced_node, pp->pp_node);
4427 4427  
4428 4428          /* Remove the endpoint from interrupt lattice tree */
4429 4429          ohci_detach_ed_from_list(ohcip, ept, ept_type);
4430 4430  
4431 4431          /*
4432 4432           * Disable isoch list processing if isoch open pipe count
4433 4433           * is zero.
4434 4434           */
4435 4435          if (!ohcip->ohci_open_isoch_pipe_count) {
4436 4436                  Set_OpReg(hcr_control,
4437 4437                      (Get_OpReg(hcr_control) & ~(HCR_CONTROL_IE)));
4438 4438          }
4439 4439  
4440 4440          /*
4441 4441           * Disable periodic list processing if periodic (interrupt
4442 4442           * and isochrous) open pipe count is zero.
4443 4443           */
4444 4444          if (!ohcip->ohci_open_periodic_pipe_count) {
4445 4445                  ASSERT(!ohcip->ohci_open_isoch_pipe_count);
4446 4446  
4447 4447                  Set_OpReg(hcr_control,
4448 4448                      (Get_OpReg(hcr_control) & ~(HCR_CONTROL_PLE)));
4449 4449          }
4450 4450  
4451 4451          ohci_insert_ed_on_reclaim_list(ohcip, pp);
4452 4452  }
4453 4453  
4454 4454  
4455 4455  /*
4456 4456   * ohci_detach_ed_from_list:
4457 4457   *
4458 4458   * Remove the Endpoint Descriptor (ED) from the appropriate Host Controller's
4459 4459   * (HC) endpoint list.
4460 4460   */
4461 4461  static void
4462 4462  ohci_detach_ed_from_list(
4463 4463          ohci_state_t    *ohcip,
4464 4464          ohci_ed_t       *ept,
4465 4465          uint_t          ept_type)
4466 4466  {
4467 4467          ohci_ed_t       *prev_ept;      /* Previous endpoint */
4468 4468          ohci_ed_t       *next_ept;      /* Endpoint after one to be removed */
4469 4469          uint_t          node;
4470 4470  
4471 4471          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4472 4472              "ohci_detach_ed_from_list:");
4473 4473  
4474 4474          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4475 4475  
4476 4476          prev_ept = ohci_ed_iommu_to_cpu(ohcip, Get_ED(ept->hced_prev));
4477 4477          next_ept = ohci_ed_iommu_to_cpu(ohcip, Get_ED(ept->hced_next));
4478 4478  
4479 4479          /*
4480 4480           * If there is no previous endpoint, then this
4481 4481           * endpoint is at the head of the endpoint list.
4482 4482           */
4483 4483          if (prev_ept == NULL) {
4484 4484                  if (next_ept) {
4485 4485                          /*
4486 4486                           * If this endpoint is the first element of the
4487 4487                           * list and there is more  than one endpoint on
4488 4488                           * the list then perform specific actions based
4489 4489                           * on the type of endpoint list.
4490 4490                           */
4491 4491                          switch (ept_type) {
4492 4492                          case USB_EP_ATTR_CONTROL:
4493 4493                                  /* Set the head of list to next ept */
4494 4494                                  Set_OpReg(hcr_ctrl_head,
4495 4495                                      Get_ED(ept->hced_next));
4496 4496  
4497 4497                                  /* Clear prev ptr of  next endpoint */
4498 4498                                  Set_ED(next_ept->hced_prev,  NULL);
4499 4499                                  break;
4500 4500                          case USB_EP_ATTR_BULK:
4501 4501                                  /* Set the head of list to next ept */
4502 4502                                  Set_OpReg(hcr_bulk_head,
4503 4503                                      Get_ED(ept->hced_next));
4504 4504  
4505 4505                                  /* Clear prev ptr of  next endpoint */
4506 4506                                  Set_ED(next_ept->hced_prev, NULL);
4507 4507                                  break;
4508 4508                          case USB_EP_ATTR_INTR:
4509 4509                                  /*
4510 4510                                   * HCCA area should point
4511 4511                                   * directly to this ept.
4512 4512                                   */
4513 4513                                  ASSERT(Get_ED(ept->hced_node) >=
4514 4514                                      NUM_STATIC_NODES);
4515 4515  
4516 4516                                  /* Get the hcca interrupt table index */
4517 4517                                  node = ohci_hcca_intr_index(
4518 4518                                      Get_ED(ept->hced_node));
4519 4519  
4520 4520                                  /*
4521 4521                                   * Delete the ept from the
4522 4522                                   * bottom of the tree.
4523 4523                                   */
4524 4524                                  Set_HCCA(ohcip->ohci_hccap->
4525 4525                                      HccaIntTble[node], Get_ED(ept->hced_next));
4526 4526  
4527 4527                                  /*
4528 4528                                   * Update the previous pointer
4529 4529                                   * of ept->hced_next
4530 4530                                   */
4531 4531                                  if (Get_ED(next_ept->hced_state) !=
4532 4532                                      HC_EPT_STATIC) {
4533 4533  
4534 4534                                          Set_ED(next_ept->hced_prev, NULL);
4535 4535                                  }
4536 4536  
4537 4537                                  break;
4538 4538                          case USB_EP_ATTR_ISOCH:
4539 4539                          default:
4540 4540                                  break;
4541 4541                          }
4542 4542                  } else {
4543 4543                          /*
4544 4544                           * If there was only one element on the list
4545 4545                           * perform specific actions based on the type
4546 4546                           * of the list.
4547 4547                           */
4548 4548                          switch (ept_type) {
4549 4549                          case USB_EP_ATTR_CONTROL:
4550 4550                                  /* Set the head to NULL */
4551 4551                                  Set_OpReg(hcr_ctrl_head, NULL);
4552 4552                                  break;
4553 4553                          case USB_EP_ATTR_BULK:
4554 4554                                  /* Set the head to NULL */
4555 4555                                  Set_OpReg(hcr_bulk_head, NULL);
4556 4556                                  break;
4557 4557                          case USB_EP_ATTR_INTR:
4558 4558                          case USB_EP_ATTR_ISOCH:
4559 4559                          default:
4560 4560                                  break;
4561 4561                          }
4562 4562                  }
4563 4563          } else {
4564 4564                  /* The previous ept points to the next one */
4565 4565                  Set_ED(prev_ept->hced_next, Get_ED(ept->hced_next));
4566 4566  
4567 4567                  /*
4568 4568                   * Set the previous ptr of the next_ept to prev_ept
4569 4569                   * if this isn't the last endpoint on the list
4570 4570                   */
4571 4571                  if ((next_ept) &&
4572 4572                      (Get_ED(next_ept->hced_state) != HC_EPT_STATIC)) {
4573 4573  
4574 4574                          /* Set the previous ptr of the next one */
4575 4575                          Set_ED(next_ept->hced_prev, Get_ED(ept->hced_prev));
4576 4576                  }
4577 4577          }
4578 4578  }
4579 4579  
4580 4580  
4581 4581  /*
4582 4582   * ohci_insert_ed_on_reclaim_list:
4583 4583   *
4584 4584   * Insert Endpoint onto the reclaim list
4585 4585   */
4586 4586  static void
4587 4587  ohci_insert_ed_on_reclaim_list(
4588 4588          ohci_state_t            *ohcip,
4589 4589          ohci_pipe_private_t     *pp)
4590 4590  {
4591 4591          ohci_ed_t               *ept = pp->pp_ept; /* ept to be removed */
4592 4592          ohci_ed_t               *next_ept, *prev_ept;
4593 4593          usb_frame_number_t      frame_number;
4594 4594  
4595 4595          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4596 4596  
4597 4597          /*
4598 4598           * Read current usb frame number and add appropriate number of
4599 4599           * usb frames needs to wait before reclaiming current endpoint.
4600 4600           */
4601 4601          frame_number =
4602 4602              ohci_get_current_frame_number(ohcip) + MAX_SOF_WAIT_COUNT;
4603 4603  
4604 4604          /* Store 32bit ID */
4605 4605          Set_ED(ept->hced_reclaim_frame,
4606 4606              ((uint32_t)(OHCI_GET_ID((void *)(uintptr_t)frame_number))));
4607 4607  
4608 4608          /* Insert the endpoint onto the reclaimation list */
4609 4609          if (ohcip->ohci_reclaim_list) {
4610 4610                  next_ept = ohcip->ohci_reclaim_list;
4611 4611  
4612 4612                  while (next_ept) {
4613 4613                          prev_ept = next_ept;
4614 4614                          next_ept = ohci_ed_iommu_to_cpu(ohcip,
4615 4615                              Get_ED(next_ept->hced_reclaim_next));
4616 4616                  }
4617 4617  
4618 4618                  Set_ED(prev_ept->hced_reclaim_next,
4619 4619                      ohci_ed_cpu_to_iommu(ohcip, ept));
4620 4620          } else {
4621 4621                  ohcip->ohci_reclaim_list = ept;
4622 4622          }
4623 4623  
4624 4624          ASSERT(Get_ED(ept->hced_reclaim_next) == NULL);
4625 4625  
4626 4626          /* Enable the SOF interrupt */
4627 4627          Set_OpReg(hcr_intr_enable, HCR_INTR_SOF);
4628 4628  }
4629 4629  
4630 4630  
4631 4631  /*
4632 4632   * ohci_deallocate_ed:
4633 4633   * NOTE: This function is also called from POLLED MODE.
4634 4634   *
4635 4635   * Deallocate a Host Controller's (HC) Endpoint Descriptor (ED).
4636 4636   */
4637 4637  void
4638 4638  ohci_deallocate_ed(
4639 4639          ohci_state_t    *ohcip,
4640 4640          ohci_ed_t       *old_ed)
4641 4641  {
4642 4642          ohci_td_t       *dummy_td;
4643 4643  
4644 4644          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4645 4645              "ohci_deallocate_ed:");
4646 4646  
4647 4647          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4648 4648  
4649 4649          dummy_td = ohci_td_iommu_to_cpu(ohcip, Get_ED(old_ed->hced_headp));
4650 4650  
4651 4651          if (dummy_td) {
4652 4652  
4653 4653                  ASSERT(Get_TD(dummy_td->hctd_state) == HC_TD_DUMMY);
4654 4654                  ohci_deallocate_td(ohcip, dummy_td);
4655 4655          }
4656 4656  
4657 4657          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4658 4658              "ohci_deallocate_ed: Deallocated 0x%p", (void *)old_ed);
4659 4659  
4660 4660          bzero((void *)old_ed, sizeof (ohci_ed_t));
4661 4661          Set_ED(old_ed->hced_state, HC_EPT_FREE);
4662 4662  }
4663 4663  
4664 4664  
4665 4665  /*
4666 4666   * ohci_ed_cpu_to_iommu:
4667 4667   * NOTE: This function is also called from POLLED MODE.
4668 4668   *
4669 4669   * This function converts for the given Endpoint Descriptor (ED) CPU address
4670 4670   * to IO address.
4671 4671   */
4672 4672  uint32_t
4673 4673  ohci_ed_cpu_to_iommu(
4674 4674          ohci_state_t    *ohcip,
4675 4675          ohci_ed_t       *addr)
4676 4676  {
4677 4677          uint32_t        ed;
4678 4678  
4679 4679          ed = (uint32_t)ohcip->ohci_ed_pool_cookie.dmac_address +
4680 4680              (uint32_t)((uintptr_t)addr - (uintptr_t)(ohcip->ohci_ed_pool_addr));
4681 4681  
4682 4682          ASSERT(ed >= ohcip->ohci_ed_pool_cookie.dmac_address);
4683 4683          ASSERT(ed <= ohcip->ohci_ed_pool_cookie.dmac_address +
4684 4684              sizeof (ohci_ed_t) * ohci_ed_pool_size);
4685 4685  
4686 4686          return (ed);
4687 4687  }
4688 4688  
4689 4689  
4690 4690  /*
4691 4691   * ohci_ed_iommu_to_cpu:
4692 4692   *
4693 4693   * This function converts for the given Endpoint Descriptor (ED) IO address
4694 4694   * to CPU address.
4695 4695   */
4696 4696  static ohci_ed_t *
4697 4697  ohci_ed_iommu_to_cpu(
4698 4698          ohci_state_t    *ohcip,
4699 4699          uintptr_t       addr)
4700 4700  {
4701 4701          ohci_ed_t       *ed;
4702 4702  
4703 4703          if (addr == NULL) {
4704 4704  
4705 4705                  return (NULL);
4706 4706          }
4707 4707  
4708 4708          ed = (ohci_ed_t *)((uintptr_t)
4709 4709              (addr - ohcip->ohci_ed_pool_cookie.dmac_address) +
4710 4710              (uintptr_t)ohcip->ohci_ed_pool_addr);
4711 4711  
4712 4712          ASSERT(ed >= ohcip->ohci_ed_pool_addr);
4713 4713          ASSERT((uintptr_t)ed <= (uintptr_t)ohcip->ohci_ed_pool_addr +
4714 4714              (uintptr_t)(sizeof (ohci_ed_t) * ohci_ed_pool_size));
4715 4715  
4716 4716          return (ed);
4717 4717  }
4718 4718  
4719 4719  
4720 4720  /*
4721 4721   * Transfer Descriptor manipulations functions
4722 4722   */
4723 4723  
4724 4724  /*
4725 4725   * ohci_initialize_dummy:
4726 4726   *
4727 4727   * An Endpoint Descriptor (ED) has a  dummy Transfer Descriptor (TD) on the
4728 4728   * end of its TD list. Initially, both the head and tail pointers of the ED
4729 4729   * point to the dummy TD.
4730 4730   */
4731 4731  static int
4732 4732  ohci_initialize_dummy(
4733 4733          ohci_state_t    *ohcip,
4734 4734          ohci_ed_t       *ept)
4735 4735  {
4736 4736          ohci_td_t *dummy;
4737 4737  
4738 4738          /* Obtain a  dummy TD */
4739 4739          dummy = ohci_allocate_td_from_pool(ohcip);
4740 4740  
4741 4741          if (dummy == NULL) {
4742 4742                  return (USB_NO_RESOURCES);
4743 4743          }
4744 4744  
4745 4745          /*
4746 4746           * Both the head and tail pointers of an ED point
4747 4747           * to this new dummy TD.
4748 4748           */
4749 4749          Set_ED(ept->hced_headp, (ohci_td_cpu_to_iommu(ohcip, dummy)));
4750 4750          Set_ED(ept->hced_tailp, (ohci_td_cpu_to_iommu(ohcip, dummy)));
4751 4751  
4752 4752          return (USB_SUCCESS);
4753 4753  }
4754 4754  
4755 4755  /*
4756 4756   * ohci_allocate_ctrl_resources:
4757 4757   *
4758 4758   * Calculates the number of tds necessary for a ctrl transfer, and allocates
4759 4759   * all the resources necessary.
4760 4760   *
4761 4761   * Returns NULL if there is insufficient resources otherwise TW.
4762 4762   */
4763 4763  static ohci_trans_wrapper_t *
4764 4764  ohci_allocate_ctrl_resources(
4765 4765          ohci_state_t            *ohcip,
4766 4766          ohci_pipe_private_t     *pp,
4767 4767          usb_ctrl_req_t          *ctrl_reqp,
4768 4768          usb_flags_t             usb_flags)
4769 4769  {
4770 4770          size_t                  td_count = 2;
4771 4771          size_t                  ctrl_buf_size;
4772 4772          ohci_trans_wrapper_t    *tw;
4773 4773  
4774 4774          /* Add one more td for data phase */
4775 4775          if (ctrl_reqp->ctrl_wLength) {
4776 4776                  td_count++;
4777 4777          }
4778 4778  
4779 4779          /*
4780 4780           * If we have a control data phase, the data buffer starts
4781 4781           * on the next 4K page boundary. So the TW buffer is allocated
4782 4782           * to be larger than required. The buffer in the range of
4783 4783           * [SETUP_SIZE, OHCI_MAX_TD_BUF_SIZE) is just for padding
4784 4784           * and not to be transferred.
4785 4785           */
4786 4786          if (ctrl_reqp->ctrl_wLength) {
4787 4787                  ctrl_buf_size = OHCI_MAX_TD_BUF_SIZE +
4788 4788                      ctrl_reqp->ctrl_wLength;
4789 4789          } else {
4790 4790                  ctrl_buf_size = SETUP_SIZE;
4791 4791          }
4792 4792  
4793 4793          tw = ohci_allocate_tw_resources(ohcip, pp, ctrl_buf_size,
4794 4794              usb_flags, td_count);
4795 4795  
4796 4796          return (tw);
4797 4797  }
4798 4798  
4799 4799  /*
4800 4800   * ohci_insert_ctrl_req:
4801 4801   *
4802 4802   * Create a Transfer Descriptor (TD) and a data buffer for a control endpoint.
4803 4803   */
4804 4804  /* ARGSUSED */
4805 4805  static void
4806 4806  ohci_insert_ctrl_req(
4807 4807          ohci_state_t            *ohcip,
4808 4808          usba_pipe_handle_data_t *ph,
4809 4809          usb_ctrl_req_t          *ctrl_reqp,
4810 4810          ohci_trans_wrapper_t    *tw,
4811 4811          usb_flags_t             usb_flags)
4812 4812  {
4813 4813          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
4814 4814          uchar_t                 bmRequestType = ctrl_reqp->ctrl_bmRequestType;
4815 4815          uchar_t                 bRequest = ctrl_reqp->ctrl_bRequest;
4816 4816          uint16_t                wValue = ctrl_reqp->ctrl_wValue;
4817 4817          uint16_t                wIndex = ctrl_reqp->ctrl_wIndex;
4818 4818          uint16_t                wLength = ctrl_reqp->ctrl_wLength;
4819 4819          mblk_t                  *data = ctrl_reqp->ctrl_data;
4820 4820          uint32_t                ctrl = 0;
4821 4821          int                     sdata;
4822 4822  
4823 4823          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4824 4824              "ohci_insert_ctrl_req:");
4825 4825  
4826 4826          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
4827 4827  
4828 4828          /*
4829 4829           * Save current control request pointer and timeout values
4830 4830           * in transfer wrapper.
4831 4831           */
4832 4832          tw->tw_curr_xfer_reqp = (usb_opaque_t)ctrl_reqp;
4833 4833          tw->tw_timeout = ctrl_reqp->ctrl_timeout ?
4834 4834              ctrl_reqp->ctrl_timeout : OHCI_DEFAULT_XFER_TIMEOUT;
4835 4835  
4836 4836          /*
4837 4837           * Initialize the callback and any callback data for when
4838 4838           * the td completes.
4839 4839           */
4840 4840          tw->tw_handle_td = ohci_handle_ctrl_td;
4841 4841          tw->tw_handle_callback_value = NULL;
4842 4842  
4843 4843          /* Create the first four bytes of the setup packet */
4844 4844          sdata = (bmRequestType << 24) | (bRequest << 16) |
4845 4845              (((wValue >> 8) | (wValue << 8)) & 0x0000FFFF);
4846 4846  
4847 4847          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4848 4848              "ohci_create_setup_pkt: sdata = 0x%x", sdata);
4849 4849  
4850 4850          ddi_put32(tw->tw_accesshandle, (uint_t *)tw->tw_buf, sdata);
4851 4851  
4852 4852          /* Create the second four bytes */
4853 4853          sdata = (uint32_t)(((((wIndex >> 8) |
4854 4854              (wIndex << 8)) << 16) & 0xFFFF0000) |
4855 4855              (((wLength >> 8) | (wLength << 8)) & 0x0000FFFF));
4856 4856  
4857 4857          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4858 4858              "ohci_create_setup_pkt: sdata = 0x%x", sdata);
4859 4859  
4860 4860          ddi_put32(tw->tw_accesshandle,
4861 4861              (uint_t *)((uintptr_t)tw->tw_buf + sizeof (uint_t)), sdata);
4862 4862  
4863 4863          ctrl = HC_TD_SETUP|HC_TD_MS_DT|HC_TD_DT_0|HC_TD_6I;
4864 4864  
4865 4865          /*
4866 4866           * The TD's are placed on the ED one at a time.
4867 4867           * Once this TD is placed on the done list, the
4868 4868           * data or status phase TD will be enqueued.
4869 4869           */
4870 4870          (void) ohci_insert_hc_td(ohcip, ctrl, 0, SETUP_SIZE,
4871 4871              OHCI_CTRL_SETUP_PHASE, pp, tw);
4872 4872  
4873 4873          USB_DPRINTF_L3(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
4874 4874              "Create_setup: pp 0x%p", (void *)pp);
4875 4875  
4876 4876          /*
4877 4877           * If this control transfer has a data phase, record the
4878 4878           * direction. If the data phase is an OUT transaction,
4879 4879           * copy the data into the buffer of the transfer wrapper.
4880 4880           */
4881 4881          if (wLength != 0) {
4882 4882                  /* There is a data stage.  Find the direction */
4883 4883                  if (bmRequestType & USB_DEV_REQ_DEV_TO_HOST) {
4884 4884                          tw->tw_direction = HC_TD_IN;
4885 4885                  } else {
4886 4886                          tw->tw_direction = HC_TD_OUT;
4887 4887  
4888 4888                          /* Copy the data into the message */
4889 4889                          ddi_rep_put8(tw->tw_accesshandle, data->b_rptr,
4890 4890                              (uint8_t *)(tw->tw_buf + OHCI_MAX_TD_BUF_SIZE),
4891 4891                              wLength, DDI_DEV_AUTOINCR);
4892 4892  
4893 4893                  }
4894 4894  
4895 4895                  ctrl = (ctrl_reqp->ctrl_attributes & USB_ATTRS_SHORT_XFER_OK) ?
4896 4896                      HC_TD_R : 0;
4897 4897  
4898 4898                  /*
4899 4899                   * There is a data stage.
4900 4900                   * Find the direction.
4901 4901                   */
4902 4902                  if (tw->tw_direction == HC_TD_IN) {
4903 4903                          ctrl = ctrl|HC_TD_IN|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_6I;
4904 4904                  } else {
4905 4905                          ctrl = ctrl|HC_TD_OUT|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_6I;
4906 4906                  }
4907 4907  
4908 4908                  /*
4909 4909                   * Create the TD.  If this is an OUT transaction,
4910 4910                   * the data is already in the buffer of the TW.
4911 4911                   */
4912 4912                  (void) ohci_insert_hc_td(ohcip, ctrl, OHCI_MAX_TD_BUF_SIZE,
4913 4913                      wLength, OHCI_CTRL_DATA_PHASE, pp, tw);
4914 4914  
4915 4915                  /*
4916 4916                   * The direction of the STATUS TD depends on
4917 4917                   * the direction of the transfer.
4918 4918                   */
4919 4919                  if (tw->tw_direction == HC_TD_IN) {
4920 4920                          ctrl = HC_TD_OUT|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_1I;
4921 4921                  } else {
4922 4922                          ctrl = HC_TD_IN|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_1I;
4923 4923                  }
4924 4924          } else {
4925 4925                  ctrl = HC_TD_IN|HC_TD_MS_DT|HC_TD_DT_1|HC_TD_1I;
4926 4926          }
4927 4927  
4928 4928          /* Status stage */
4929 4929          (void) ohci_insert_hc_td(ohcip, ctrl, 0,
4930 4930              0, OHCI_CTRL_STATUS_PHASE, pp, tw);
4931 4931  
4932 4932          /* Indicate that the control list is filled */
4933 4933          Set_OpReg(hcr_cmd_status, HCR_STATUS_CLF);
4934 4934  
4935 4935          /* Start the timer for this control transfer */
4936 4936          ohci_start_xfer_timer(ohcip, pp, tw);
4937 4937  }
4938 4938  
4939 4939  /*
4940 4940   * ohci_allocate_bulk_resources:
4941 4941   *
4942 4942   * Calculates the number of tds necessary for a ctrl transfer, and allocates
4943 4943   * all the resources necessary.
4944 4944   *
4945 4945   * Returns NULL if there is insufficient resources otherwise TW.
4946 4946   */
4947 4947  static ohci_trans_wrapper_t *
4948 4948  ohci_allocate_bulk_resources(
4949 4949          ohci_state_t            *ohcip,
4950 4950          ohci_pipe_private_t     *pp,
4951 4951          usb_bulk_req_t          *bulk_reqp,
4952 4952          usb_flags_t             usb_flags)
4953 4953  {
4954 4954          size_t                  td_count = 0;
4955 4955          ohci_trans_wrapper_t    *tw;
4956 4956  
4957 4957          /* Check the size of bulk request */
4958 4958          if (bulk_reqp->bulk_len > OHCI_MAX_BULK_XFER_SIZE) {
4959 4959  
4960 4960                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
4961 4961                      "ohci_allocate_bulk_resources: Bulk request size 0x%x is "
4962 4962                      "more than 0x%x", bulk_reqp->bulk_len,
4963 4963                      OHCI_MAX_BULK_XFER_SIZE);
4964 4964  
4965 4965                  return (NULL);
4966 4966          }
4967 4967  
4968 4968          /* Get the required bulk packet size */
4969 4969          td_count = bulk_reqp->bulk_len / OHCI_MAX_TD_XFER_SIZE;
4970 4970          if (bulk_reqp->bulk_len % OHCI_MAX_TD_XFER_SIZE ||
4971 4971              bulk_reqp->bulk_len == 0) {
4972 4972                  td_count++;
4973 4973          }
4974 4974  
4975 4975          tw = ohci_allocate_tw_resources(ohcip, pp, bulk_reqp->bulk_len,
4976 4976              usb_flags, td_count);
4977 4977  
4978 4978          return (tw);
4979 4979  }
4980 4980  
4981 4981  /*
4982 4982   * ohci_insert_bulk_req:
4983 4983   *
4984 4984   * Create a Transfer Descriptor (TD) and a data buffer for a bulk
4985 4985   * endpoint.
4986 4986   */
4987 4987  /* ARGSUSED */
4988 4988  static void
4989 4989  ohci_insert_bulk_req(
4990 4990          ohci_state_t            *ohcip,
4991 4991          usba_pipe_handle_data_t *ph,
4992 4992          usb_bulk_req_t          *bulk_reqp,
4993 4993          ohci_trans_wrapper_t    *tw,
4994 4994          usb_flags_t             flags)
4995 4995  {
4996 4996          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
4997 4997          uint_t                  bulk_pkt_size, count;
4998 4998          size_t                  residue = 0, len = 0;
4999 4999          uint32_t                ctrl = 0;
5000 5000          int                     pipe_dir;
5001 5001  
5002 5002          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5003 5003              "ohci_insert_bulk_req: bulk_reqp = 0x%p flags = 0x%x",
5004 5004              (void *)bulk_reqp, flags);
5005 5005  
5006 5006          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5007 5007  
5008 5008          /* Get the bulk pipe direction */
5009 5009          pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
5010 5010  
5011 5011          /* Get the required bulk packet size */
5012 5012          bulk_pkt_size = min(bulk_reqp->bulk_len, OHCI_MAX_TD_XFER_SIZE);
5013 5013  
5014 5014          if (bulk_pkt_size)
5015 5015                  residue = tw->tw_length % bulk_pkt_size;
5016 5016  
5017 5017          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5018 5018              "ohci_insert_bulk_req: bulk_pkt_size = %d", bulk_pkt_size);
5019 5019  
5020 5020          /*
5021 5021           * Save current bulk request pointer and timeout values
5022 5022           * in transfer wrapper.
5023 5023           */
5024 5024          tw->tw_curr_xfer_reqp = (usb_opaque_t)bulk_reqp;
5025 5025          tw->tw_timeout = bulk_reqp->bulk_timeout;
5026 5026  
5027 5027          /*
5028 5028           * Initialize the callback and any callback
5029 5029           * data required when the td completes.
5030 5030           */
5031 5031          tw->tw_handle_td = ohci_handle_bulk_td;
5032 5032          tw->tw_handle_callback_value = NULL;
5033 5033  
5034 5034          tw->tw_direction =
5035 5035              (pipe_dir == USB_EP_DIR_OUT) ? HC_TD_OUT : HC_TD_IN;
5036 5036  
5037 5037          if (tw->tw_direction == HC_TD_OUT && bulk_reqp->bulk_len) {
5038 5038  
5039 5039                  ASSERT(bulk_reqp->bulk_data != NULL);
5040 5040  
5041 5041                  /* Copy the data into the message */
5042 5042                  ddi_rep_put8(tw->tw_accesshandle,
5043 5043                      bulk_reqp->bulk_data->b_rptr, (uint8_t *)tw->tw_buf,
5044 5044                      bulk_reqp->bulk_len, DDI_DEV_AUTOINCR);
5045 5045          }
5046 5046  
5047 5047          ctrl = tw->tw_direction|HC_TD_DT_0|HC_TD_6I;
5048 5048  
5049 5049          /* Insert all the bulk TDs */
5050 5050          for (count = 0; count < tw->tw_num_tds; count++) {
5051 5051  
5052 5052                  /* Check for last td */
5053 5053                  if (count == (tw->tw_num_tds - 1)) {
5054 5054  
5055 5055                          ctrl = ((ctrl & ~HC_TD_DI) | HC_TD_1I);
5056 5056  
5057 5057                          /* Check for inserting residue data */
5058 5058                          if (residue) {
5059 5059                                  bulk_pkt_size = (uint_t)residue;
5060 5060                          }
5061 5061  
5062 5062                          /*
5063 5063                           * Only set the round bit on the last TD, to ensure
5064 5064                           * the controller will always HALT the ED in case of
5065 5065                           * a short transfer.
5066 5066                           */
5067 5067                          if (bulk_reqp->bulk_attributes &
5068 5068                              USB_ATTRS_SHORT_XFER_OK) {
5069 5069                                  ctrl |= HC_TD_R;
5070 5070                          }
5071 5071                  }
5072 5072  
5073 5073                  /* Insert the TD onto the endpoint */
5074 5074                  (void) ohci_insert_hc_td(ohcip, ctrl, len,
5075 5075                      bulk_pkt_size, 0, pp, tw);
5076 5076  
5077 5077                  len = len + bulk_pkt_size;
5078 5078          }
5079 5079  
5080 5080          /* Indicate that the bulk list is filled */
5081 5081          Set_OpReg(hcr_cmd_status, HCR_STATUS_BLF);
5082 5082  
5083 5083          /* Start the timer for this bulk transfer */
5084 5084          ohci_start_xfer_timer(ohcip, pp, tw);
5085 5085  }
5086 5086  
5087 5087  
5088 5088  /*
5089 5089   * ohci_start_periodic_pipe_polling:
5090 5090   * NOTE: This function is also called from POLLED MODE.
5091 5091   */
5092 5092  int
5093 5093  ohci_start_periodic_pipe_polling(
5094 5094          ohci_state_t            *ohcip,
5095 5095          usba_pipe_handle_data_t *ph,
5096 5096          usb_opaque_t            periodic_in_reqp,
5097 5097          usb_flags_t             flags)
5098 5098  {
5099 5099          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5100 5100          usb_ep_descr_t          *eptd = &ph->p_ep;
5101 5101          int                     error = USB_SUCCESS;
5102 5102  
5103 5103          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5104 5104              "ohci_start_periodic_pipe_polling: ep%d",
5105 5105              ph->p_ep.bEndpointAddress & USB_EP_NUM_MASK);
5106 5106  
5107 5107          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5108 5108  
5109 5109          /*
5110 5110           * Check and handle start polling on root hub interrupt pipe.
5111 5111           */
5112 5112          if ((ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) &&
5113 5113              ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
5114 5114              USB_EP_ATTR_INTR)) {
5115 5115  
5116 5116                  error = ohci_handle_root_hub_pipe_start_intr_polling(ph,
5117 5117                      (usb_intr_req_t *)periodic_in_reqp, flags);
5118 5118  
5119 5119                  return (error);
5120 5120          }
5121 5121  
5122 5122          switch (pp->pp_state) {
5123 5123          case OHCI_PIPE_STATE_IDLE:
5124 5124                  /* Save the Original client's Periodic IN request */
5125 5125                  pp->pp_client_periodic_in_reqp = periodic_in_reqp;
5126 5126  
5127 5127                  /*
5128 5128                   * This pipe is uninitialized or if a valid TD is
5129 5129                   * not found then insert a TD on the interrupt or
5130 5130                   * isochronous IN endpoint.
5131 5131                   */
5132 5132                  error = ohci_start_pipe_polling(ohcip, ph, flags);
5133 5133  
5134 5134                  if (error != USB_SUCCESS) {
5135 5135                          USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5136 5136                              "ohci_start_periodic_pipe_polling: "
5137 5137                              "Start polling failed");
5138 5138  
5139 5139                          pp->pp_client_periodic_in_reqp = NULL;
5140 5140  
5141 5141                          return (error);
5142 5142                  }
5143 5143  
5144 5144                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
5145 5145                      "ohci_start_periodic_pipe_polling: PP = 0x%p", (void *)pp);
5146 5146  
5147 5147                  ASSERT((pp->pp_tw_head != NULL) && (pp->pp_tw_tail != NULL));
5148 5148  
5149 5149                  break;
5150 5150          case OHCI_PIPE_STATE_ACTIVE:
5151 5151                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5152 5152                      "ohci_start_periodic_pipe_polling: "
5153 5153                      "Polling is already in progress");
5154 5154  
5155 5155                  error = USB_FAILURE;
5156 5156                  break;
5157 5157          case OHCI_PIPE_STATE_ERROR:
5158 5158                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5159 5159                      "ohci_start_periodic_pipe_polling: "
5160 5160                      "Pipe is halted and perform reset before restart polling");
5161 5161  
5162 5162                  error = USB_FAILURE;
5163 5163                  break;
5164 5164          default:
5165 5165                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5166 5166                      "ohci_start_periodic_pipe_polling: Undefined state");
5167 5167  
5168 5168                  error = USB_FAILURE;
5169 5169                  break;
5170 5170          }
5171 5171  
5172 5172          return (error);
5173 5173  }
5174 5174  
5175 5175  
5176 5176  /*
5177 5177   * ohci_start_pipe_polling:
5178 5178   *
5179 5179   * Insert the number of periodic requests corresponding to polling
5180 5180   * interval as calculated during pipe open.
5181 5181   */
5182 5182  static int
5183 5183  ohci_start_pipe_polling(
5184 5184          ohci_state_t            *ohcip,
5185 5185          usba_pipe_handle_data_t *ph,
5186 5186          usb_flags_t             flags)
5187 5187  {
5188 5188          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5189 5189          usb_ep_descr_t          *eptd = &ph->p_ep;
5190 5190          ohci_trans_wrapper_t    *tw_list, *tw;
5191 5191          int                     i, total_tws;
5192 5192          int                     error = USB_SUCCESS;
5193 5193  
5194 5194          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5195 5195              "ohci_start_pipe_polling:");
5196 5196  
5197 5197          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5198 5198  
5199 5199          /*
5200 5200           * For the start polling, pp_max_periodic_req_cnt will be zero
5201 5201           * and for the restart polling request, it will be non zero.
5202 5202           *
5203 5203           * In case of start polling request, find out number of requests
5204 5204           * required for the Interrupt IN endpoints corresponding to the
5205 5205           * endpoint polling interval. For Isochronous IN endpoints, it is
5206 5206           * always fixed since its polling interval will be one ms.
5207 5207           */
5208 5208          if (pp->pp_max_periodic_req_cnt == 0) {
5209 5209  
5210 5210                  ohci_set_periodic_pipe_polling(ohcip, ph);
5211 5211          }
5212 5212  
5213 5213          ASSERT(pp->pp_max_periodic_req_cnt != 0);
5214 5214  
5215 5215          /* Allocate all the necessary resources for the IN transfer */
5216 5216          tw_list = NULL;
5217 5217          total_tws = pp->pp_max_periodic_req_cnt - pp->pp_cur_periodic_req_cnt;
5218 5218          for (i = 0; i < total_tws; i++) {
5219 5219                  switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
5220 5220                  case USB_EP_ATTR_INTR:
5221 5221                          tw = ohci_allocate_intr_resources(
5222 5222                              ohcip, ph, NULL, flags);
5223 5223                          break;
5224 5224                  case USB_EP_ATTR_ISOCH:
5225 5225                          tw = ohci_allocate_isoc_resources(
5226 5226                              ohcip, ph, NULL, flags);
5227 5227                          break;
5228 5228                  }
5229 5229                  if (tw == NULL) {
5230 5230                          error = USB_NO_RESOURCES;
5231 5231                          /* There are not enough resources, deallocate the TWs */
5232 5232                          tw = tw_list;
5233 5233                          while (tw != NULL) {
5234 5234                                  tw_list = tw->tw_next;
5235 5235                                  ohci_deallocate_periodic_in_resource(
5236 5236                                      ohcip, pp, tw);
5237 5237                                  ohci_deallocate_tw_resources(ohcip, pp, tw);
5238 5238                                  tw = tw_list;
5239 5239                          }
5240 5240                          return (error);
5241 5241                  } else {
5242 5242                          if (tw_list == NULL) {
5243 5243                                  tw_list = tw;
5244 5244                          }
5245 5245                  }
5246 5246          }
5247 5247  
5248 5248          i = 0;
5249 5249          while (pp->pp_cur_periodic_req_cnt < pp->pp_max_periodic_req_cnt) {
5250 5250  
5251 5251                  USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5252 5252                      "ohci_start_pipe_polling: max = %d curr = %d tw = %p:",
5253 5253                      pp->pp_max_periodic_req_cnt, pp->pp_cur_periodic_req_cnt,
5254 5254                      (void *)tw_list);
5255 5255  
5256 5256                  tw = tw_list;
5257 5257                  tw_list = tw->tw_next;
5258 5258  
5259 5259                  switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
5260 5260                  case USB_EP_ATTR_INTR:
5261 5261                          ohci_insert_intr_req(ohcip, pp, tw, flags);
5262 5262                          break;
5263 5263                  case USB_EP_ATTR_ISOCH:
5264 5264                          error = ohci_insert_isoc_req(ohcip, pp, tw, flags);
5265 5265                          break;
5266 5266                  }
5267 5267                  if (error == USB_SUCCESS) {
5268 5268                          pp->pp_cur_periodic_req_cnt++;
5269 5269                  } else {
5270 5270                          /*
5271 5271                           * Deallocate the remaining tw
5272 5272                           * The current tw should have already been deallocated
5273 5273                           */
5274 5274                          tw = tw_list;
5275 5275                          while (tw != NULL) {
5276 5276                                  tw_list = tw->tw_next;
5277 5277                                  ohci_deallocate_periodic_in_resource(
5278 5278                                      ohcip, pp, tw);
5279 5279                                  ohci_deallocate_tw_resources(ohcip, pp, tw);
5280 5280                                  tw = tw_list;
5281 5281                          }
5282 5282                          /*
5283 5283                           * If this is the first req return an error.
5284 5284                           * Otherwise return success.
5285 5285                           */
5286 5286                          if (i != 0) {
5287 5287                                  error = USB_SUCCESS;
5288 5288                          }
5289 5289  
5290 5290                          break;
5291 5291                  }
5292 5292                  i++;
5293 5293          }
5294 5294  
5295 5295          return (error);
5296 5296  }
5297 5297  
5298 5298  
5299 5299  /*
5300 5300   * ohci_set_periodic_pipe_polling:
5301 5301   *
5302 5302   * Calculate the number of periodic requests needed corresponding to the
5303 5303   * interrupt/isochronous IN endpoints polling interval. Table below gives
5304 5304   * the number of periodic requests needed for the interrupt/isochronous
5305 5305   * IN endpoints according to endpoint polling interval.
5306 5306   *
5307 5307   * Polling interval             Number of periodic requests
5308 5308   *
5309 5309   * 1ms                          4
5310 5310   * 2ms                          2
5311 5311   * 4ms to 32ms                  1
5312 5312   */
5313 5313  static void
5314 5314  ohci_set_periodic_pipe_polling(
5315 5315          ohci_state_t            *ohcip,
5316 5316          usba_pipe_handle_data_t *ph)
5317 5317  {
5318 5318          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5319 5319          usb_ep_descr_t          *endpoint = &ph->p_ep;
5320 5320          uchar_t                 ep_attr = endpoint->bmAttributes;
5321 5321          uint_t                  interval;
5322 5322  
5323 5323          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5324 5324              "ohci_set_periodic_pipe_polling:");
5325 5325  
5326 5326          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5327 5327  
5328 5328          pp->pp_cur_periodic_req_cnt = 0;
5329 5329  
5330 5330          /*
5331 5331           * Check usb flag whether USB_FLAGS_ONE_TIME_POLL flag is
5332 5332           * set and if so, set pp->pp_max_periodic_req_cnt to one.
5333 5333           */
5334 5334          if (((ep_attr & USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) &&
5335 5335              (pp->pp_client_periodic_in_reqp)) {
5336 5336                  usb_intr_req_t *intr_reqp =
5337 5337                      (usb_intr_req_t *)pp->pp_client_periodic_in_reqp;
5338 5338  
5339 5339                  if (intr_reqp->intr_attributes &
5340 5340                      USB_ATTRS_ONE_XFER) {
5341 5341  
5342 5342                          pp->pp_max_periodic_req_cnt = INTR_XMS_REQS;
5343 5343  
5344 5344                          return;
5345 5345                  }
5346 5346          }
5347 5347  
5348 5348          mutex_enter(&ph->p_usba_device->usb_mutex);
5349 5349  
5350 5350          /*
5351 5351           * The ohci_adjust_polling_interval function will not fail
5352 5352           * at this instance since bandwidth allocation is already
5353 5353           * done. Here we are getting only the periodic interval.
5354 5354           */
5355 5355          interval = ohci_adjust_polling_interval(ohcip, endpoint,
5356 5356              ph->p_usba_device->usb_port_status);
5357 5357  
5358 5358          mutex_exit(&ph->p_usba_device->usb_mutex);
5359 5359  
5360 5360          switch (interval) {
5361 5361          case INTR_1MS_POLL:
5362 5362                  pp->pp_max_periodic_req_cnt = INTR_1MS_REQS;
5363 5363                  break;
5364 5364          case INTR_2MS_POLL:
5365 5365                  pp->pp_max_periodic_req_cnt = INTR_2MS_REQS;
5366 5366                  break;
5367 5367          default:
5368 5368                  pp->pp_max_periodic_req_cnt = INTR_XMS_REQS;
5369 5369                  break;
5370 5370          }
5371 5371  
5372 5372          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5373 5373              "ohci_set_periodic_pipe_polling: Max periodic requests = %d",
5374 5374              pp->pp_max_periodic_req_cnt);
5375 5375  }
5376 5376  
5377 5377  /*
5378 5378   * ohci_allocate_intr_resources:
5379 5379   *
5380 5380   * Calculates the number of tds necessary for a intr transfer, and allocates
5381 5381   * all the necessary resources.
5382 5382   *
5383 5383   * Returns NULL if there is insufficient resources otherwise TW.
5384 5384   */
5385 5385  static ohci_trans_wrapper_t *
5386 5386  ohci_allocate_intr_resources(
5387 5387          ohci_state_t            *ohcip,
5388 5388          usba_pipe_handle_data_t *ph,
5389 5389          usb_intr_req_t          *intr_reqp,
5390 5390          usb_flags_t             flags)
5391 5391  {
5392 5392          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5393 5393          int                     pipe_dir;
5394 5394          size_t                  td_count = 1;
5395 5395          size_t                  tw_length;
5396 5396          ohci_trans_wrapper_t    *tw;
5397 5397  
5398 5398          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5399 5399              "ohci_allocate_intr_resources:");
5400 5400  
5401 5401          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5402 5402  
5403 5403          pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
5404 5404  
5405 5405          /* Get the length of interrupt transfer & alloc data */
5406 5406          if (intr_reqp) {
5407 5407                  tw_length = intr_reqp->intr_len;
5408 5408          } else {
5409 5409                  ASSERT(pipe_dir == USB_EP_DIR_IN);
5410 5410                  tw_length = (pp->pp_client_periodic_in_reqp) ?
5411 5411                      (((usb_intr_req_t *)pp->
5412 5412                      pp_client_periodic_in_reqp)->intr_len) :
5413 5413                      ph->p_ep.wMaxPacketSize;
5414 5414          }
5415 5415  
5416 5416          /* Check the size of interrupt request */
5417 5417          if (tw_length > OHCI_MAX_TD_XFER_SIZE) {
5418 5418  
5419 5419                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5420 5420                      "ohci_allocate_intr_resources: Intr request size 0x%lx is "
5421 5421                      "more than 0x%x", tw_length, OHCI_MAX_TD_XFER_SIZE);
5422 5422  
5423 5423                  return (NULL);
5424 5424          }
5425 5425  
5426 5426          if ((tw = ohci_allocate_tw_resources(ohcip, pp, tw_length,
5427 5427              flags, td_count)) == NULL) {
5428 5428  
5429 5429                  return (NULL);
5430 5430          }
5431 5431  
5432 5432          if (pipe_dir == USB_EP_DIR_IN) {
5433 5433                  if (ohci_allocate_periodic_in_resource(ohcip, pp, tw, flags) !=
5434 5434                      USB_SUCCESS) {
5435 5435  
5436 5436                          ohci_deallocate_tw_resources(ohcip, pp, tw);
5437 5437                          return (NULL);
5438 5438                  }
5439 5439                  tw->tw_direction = HC_TD_IN;
5440 5440          } else {
5441 5441                  if (tw_length) {
5442 5442                          ASSERT(intr_reqp->intr_data != NULL);
5443 5443  
5444 5444                          /* Copy the data into the message */
5445 5445                          ddi_rep_put8(tw->tw_accesshandle,
5446 5446                              intr_reqp->intr_data->b_rptr, (uint8_t *)tw->tw_buf,
5447 5447                              intr_reqp->intr_len, DDI_DEV_AUTOINCR);
5448 5448                  }
5449 5449  
5450 5450                  tw->tw_curr_xfer_reqp = (usb_opaque_t)intr_reqp;
5451 5451                  tw->tw_direction = HC_TD_OUT;
5452 5452          }
5453 5453  
5454 5454          if (intr_reqp) {
5455 5455                  tw->tw_timeout = intr_reqp->intr_timeout;
5456 5456          }
5457 5457  
5458 5458          /*
5459 5459           * Initialize the callback and any callback
5460 5460           * data required when the td completes.
5461 5461           */
5462 5462          tw->tw_handle_td = ohci_handle_intr_td;
5463 5463          tw->tw_handle_callback_value = NULL;
5464 5464  
5465 5465          return (tw);
5466 5466  }
5467 5467  
5468 5468  /*
5469 5469   * ohci_insert_intr_req:
5470 5470   *
5471 5471   * Insert an Interrupt request into the Host Controller's periodic list.
5472 5472   */
5473 5473  /* ARGSUSED */
5474 5474  static void
5475 5475  ohci_insert_intr_req(
5476 5476          ohci_state_t            *ohcip,
5477 5477          ohci_pipe_private_t     *pp,
5478 5478          ohci_trans_wrapper_t    *tw,
5479 5479          usb_flags_t             flags)
5480 5480  {
5481 5481          usb_intr_req_t          *curr_intr_reqp = NULL;
5482 5482          uint_t                  ctrl = 0;
5483 5483  
5484 5484          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5485 5485  
5486 5486          ASSERT(tw->tw_curr_xfer_reqp != NULL);
5487 5487  
5488 5488          /* Get the current interrupt request pointer */
5489 5489          curr_intr_reqp = (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
5490 5490  
5491 5491          ctrl = tw->tw_direction | HC_TD_DT_0 | HC_TD_1I;
5492 5492  
5493 5493          if (curr_intr_reqp->intr_attributes & USB_ATTRS_SHORT_XFER_OK) {
5494 5494                  ctrl |= HC_TD_R;
5495 5495          }
5496 5496  
5497 5497          /* Insert another interrupt TD */
5498 5498          (void) ohci_insert_hc_td(ohcip, ctrl, 0, tw->tw_length, 0, pp, tw);
5499 5499  
5500 5500          /* Start the timer for this Interrupt transfer */
5501 5501          ohci_start_xfer_timer(ohcip, pp, tw);
5502 5502  }
5503 5503  
5504 5504  
5505 5505  /*
5506 5506   * ohci_stop_periodic_pipe_polling:
5507 5507   */
5508 5508  /* ARGSUSED */
5509 5509  static int
5510 5510  ohci_stop_periodic_pipe_polling(
5511 5511          ohci_state_t            *ohcip,
5512 5512          usba_pipe_handle_data_t *ph,
5513 5513          usb_flags_t             flags)
5514 5514  {
5515 5515          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5516 5516          usb_ep_descr_t          *eptd = &ph->p_ep;
5517 5517  
5518 5518          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5519 5519              "ohci_stop_periodic_pipe_polling: Flags = 0x%x", flags);
5520 5520  
5521 5521          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5522 5522  
5523 5523          /*
5524 5524           * Check and handle stop polling on root hub interrupt pipe.
5525 5525           */
5526 5526          if ((ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) &&
5527 5527              ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
5528 5528              USB_EP_ATTR_INTR)) {
5529 5529  
5530 5530                  ohci_handle_root_hub_pipe_stop_intr_polling(
5531 5531                      ph, flags);
5532 5532                  return (USB_SUCCESS);
5533 5533          }
5534 5534  
5535 5535          if (pp->pp_state != OHCI_PIPE_STATE_ACTIVE) {
5536 5536  
5537 5537                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5538 5538                      "ohci_stop_periodic_pipe_polling: Polling already stopped");
5539 5539  
5540 5540                  return (USB_SUCCESS);
5541 5541          }
5542 5542  
5543 5543          /* Set pipe state to pipe stop polling */
5544 5544          pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
5545 5545  
5546 5546          ohci_pipe_cleanup(ohcip, ph);
5547 5547  
5548 5548          return (USB_SUCCESS);
5549 5549  }
5550 5550  
5551 5551  /*
5552 5552   * ohci_allocate_isoc_resources:
5553 5553   *
5554 5554   * Calculates the number of tds necessary for a intr transfer, and allocates
5555 5555   * all the necessary resources.
5556 5556   *
5557 5557   * Returns NULL if there is insufficient resources otherwise TW.
5558 5558   */
5559 5559  static ohci_trans_wrapper_t *
5560 5560  ohci_allocate_isoc_resources(
5561 5561          ohci_state_t            *ohcip,
5562 5562          usba_pipe_handle_data_t *ph,
5563 5563          usb_isoc_req_t          *isoc_reqp,
5564 5564          usb_flags_t             flags)
5565 5565  {
5566 5566          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
5567 5567          int                     pipe_dir;
5568 5568          uint_t                  max_pkt_size = ph->p_ep.wMaxPacketSize;
5569 5569          uint_t                  max_isoc_xfer_size;
5570 5570          usb_isoc_pkt_descr_t    *isoc_pkt_descr, *start_isoc_pkt_descr;
5571 5571          ushort_t                isoc_pkt_count;
5572 5572          size_t                  count, td_count;
5573 5573          size_t                  tw_length;
5574 5574          size_t                  isoc_pkts_length;
5575 5575          ohci_trans_wrapper_t    *tw;
5576 5576  
5577 5577  
5578 5578          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5579 5579              "ohci_allocate_isoc_resources: flags = ox%x", flags);
5580 5580  
5581 5581          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5582 5582  
5583 5583          /*
5584 5584           *  Check whether pipe is in halted state.
5585 5585           */
5586 5586          if (pp->pp_state == OHCI_PIPE_STATE_ERROR) {
5587 5587                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5588 5588                      "ohci_allocate_isoc_resources:"
5589 5589                      "Pipe is in error state, need pipe reset to continue");
5590 5590  
5591 5591                  return (NULL);
5592 5592          }
5593 5593  
5594 5594          pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
5595 5595  
5596 5596          /* Calculate the maximum isochronous transfer size */
5597 5597          max_isoc_xfer_size = OHCI_MAX_ISOC_PKTS_PER_XFER * max_pkt_size;
5598 5598  
5599 5599          if (isoc_reqp) {
5600 5600                  isoc_pkt_descr = isoc_reqp->isoc_pkt_descr;
5601 5601                  isoc_pkt_count = isoc_reqp->isoc_pkts_count;
5602 5602                  isoc_pkts_length = isoc_reqp->isoc_pkts_length;
5603 5603          } else {
5604 5604                  isoc_pkt_descr = ((usb_isoc_req_t *)
5605 5605                      pp->pp_client_periodic_in_reqp)->isoc_pkt_descr;
5606 5606  
5607 5607                  isoc_pkt_count = ((usb_isoc_req_t *)
5608 5608                      pp->pp_client_periodic_in_reqp)->isoc_pkts_count;
5609 5609  
5610 5610                  isoc_pkts_length = ((usb_isoc_req_t *)
5611 5611                      pp->pp_client_periodic_in_reqp)->isoc_pkts_length;
5612 5612          }
5613 5613  
5614 5614          start_isoc_pkt_descr = isoc_pkt_descr;
5615 5615  
5616 5616          /*
5617 5617           * For isochronous IN pipe, get value of number of isochronous
5618 5618           * packets per usb isochronous request
5619 5619           */
5620 5620          if (pipe_dir == USB_EP_DIR_IN) {
5621 5621                  for (count = 0, tw_length = 0;
5622 5622                      count < isoc_pkt_count; count++) {
5623 5623                          tw_length += isoc_pkt_descr->isoc_pkt_length;
5624 5624                          isoc_pkt_descr++;
5625 5625                  }
5626 5626  
5627 5627                  if ((isoc_pkts_length) && (isoc_pkts_length != tw_length)) {
5628 5628  
5629 5629                          USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5630 5630                              "ohci_allocate_isoc_resources: "
5631 5631                              "isoc_pkts_length 0x%lx is not equal to the sum of "
5632 5632                              "all pkt lengths 0x%lx in an isoc request",
5633 5633                              isoc_pkts_length, tw_length);
5634 5634  
5635 5635                          return (NULL);
5636 5636                  }
5637 5637  
5638 5638          } else {
5639 5639                  ASSERT(isoc_reqp != NULL);
5640 5640                  tw_length = MBLKL(isoc_reqp->isoc_data);
5641 5641          }
5642 5642  
5643 5643          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5644 5644              "ohci_allocate_isoc_resources: length = 0x%lx", tw_length);
5645 5645  
5646 5646          /* Check the size of isochronous request */
5647 5647          if (tw_length > max_isoc_xfer_size) {
5648 5648  
5649 5649                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5650 5650                      "ohci_allocate_isoc_resources: Maximum isoc request"
5651 5651                      "size 0x%x Given isoc request size 0x%lx",
5652 5652                      max_isoc_xfer_size, tw_length);
5653 5653  
5654 5654                  return (NULL);
5655 5655          }
5656 5656  
5657 5657          /*
5658 5658           * Each isochronous TD can hold data upto eight isochronous
5659 5659           * data packets. Calculate the number of isochronous TDs needs
5660 5660           * to be insert to complete current isochronous request.
5661 5661           */
5662 5662          td_count = isoc_pkt_count / OHCI_ISOC_PKTS_PER_TD;
5663 5663  
5664 5664          if (isoc_pkt_count % OHCI_ISOC_PKTS_PER_TD) {
5665 5665                  td_count++;
5666 5666          }
5667 5667  
5668 5668          tw = ohci_create_isoc_transfer_wrapper(ohcip, pp, tw_length,
5669 5669              start_isoc_pkt_descr, isoc_pkt_count, td_count, flags);
5670 5670  
5671 5671          if (tw == NULL) {
5672 5672                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5673 5673                      "ohci_create_isoc_transfer_wrapper: "
5674 5674                      "Unable to allocate TW");
5675 5675  
5676 5676                  return (NULL);
5677 5677          }
5678 5678  
5679 5679          if (ohci_allocate_tds_for_tw(ohcip, tw, td_count) ==
5680 5680              USB_SUCCESS) {
5681 5681                  tw->tw_num_tds = (uint_t)td_count;
5682 5682          } else {
5683 5683                  ohci_deallocate_tw_resources(ohcip, pp, tw);
5684 5684  
5685 5685                  return (NULL);
5686 5686          }
5687 5687  
5688 5688          if (pipe_dir == USB_EP_DIR_IN) {
5689 5689                  if (ohci_allocate_periodic_in_resource(ohcip, pp, tw, flags) !=
5690 5690                      USB_SUCCESS) {
5691 5691  
5692 5692                          ohci_deallocate_tw_resources(ohcip, pp, tw);
5693 5693                          return (NULL);
5694 5694                  }
5695 5695                  tw->tw_direction = HC_TD_IN;
5696 5696          } else {
5697 5697                  if (tw->tw_length) {
5698 5698                          uchar_t *p;
5699 5699                          int i;
5700 5700  
5701 5701                          ASSERT(isoc_reqp->isoc_data != NULL);
5702 5702                          p = isoc_reqp->isoc_data->b_rptr;
5703 5703  
5704 5704                          /* Copy the data into the message */
5705 5705                          for (i = 0; i < td_count; i++) {
5706 5706                                  ddi_rep_put8(
5707 5707                                      tw->tw_isoc_bufs[i].mem_handle, p,
5708 5708                                      (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
5709 5709                                      tw->tw_isoc_bufs[i].length,
5710 5710                                      DDI_DEV_AUTOINCR);
5711 5711                                  p += tw->tw_isoc_bufs[i].length;
5712 5712                          }
5713 5713                  }
5714 5714                  tw->tw_curr_xfer_reqp = (usb_opaque_t)isoc_reqp;
5715 5715                  tw->tw_direction = HC_TD_OUT;
5716 5716          }
5717 5717  
5718 5718          /*
5719 5719           * Initialize the callback and any callback
5720 5720           * data required when the td completes.
5721 5721           */
5722 5722          tw->tw_handle_td = ohci_handle_isoc_td;
5723 5723          tw->tw_handle_callback_value = NULL;
5724 5724  
5725 5725          return (tw);
5726 5726  }
5727 5727  
5728 5728  /*
5729 5729   * ohci_insert_isoc_req:
5730 5730   *
5731 5731   * Insert an isochronous request into the Host Controller's
5732 5732   * isochronous list.  If there is an error is will appropriately
5733 5733   * deallocate the unused resources.
5734 5734   */
5735 5735  static int
5736 5736  ohci_insert_isoc_req(
5737 5737          ohci_state_t            *ohcip,
5738 5738          ohci_pipe_private_t     *pp,
5739 5739          ohci_trans_wrapper_t    *tw,
5740 5740          uint_t                  flags)
5741 5741  {
5742 5742          size_t                  curr_isoc_xfer_offset, curr_isoc_xfer_len;
5743 5743          uint_t                  isoc_pkts, residue, count;
5744 5744          uint_t                  i, ctrl, frame_count;
5745 5745          uint_t                  error = USB_SUCCESS;
5746 5746          usb_isoc_req_t          *curr_isoc_reqp;
5747 5747          usb_isoc_pkt_descr_t    *curr_isoc_pkt_descr;
5748 5748  
5749 5749          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5750 5750              "ohci_insert_isoc_req: flags = 0x%x", flags);
5751 5751  
5752 5752          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5753 5753  
5754 5754          /*
5755 5755           * Get the current isochronous request and packet
5756 5756           * descriptor pointers.
5757 5757           */
5758 5758          curr_isoc_reqp = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
5759 5759          curr_isoc_pkt_descr = curr_isoc_reqp->isoc_pkt_descr;
5760 5760  
5761 5761          ASSERT(curr_isoc_reqp != NULL);
5762 5762          ASSERT(curr_isoc_reqp->isoc_pkt_descr != NULL);
5763 5763  
5764 5764          /*
5765 5765           * Save address of first usb isochronous packet descriptor.
5766 5766           */
5767 5767          tw->tw_curr_isoc_pktp = curr_isoc_reqp->isoc_pkt_descr;
5768 5768  
5769 5769          /* Insert all the isochronous TDs */
5770 5770          for (count = 0, curr_isoc_xfer_offset = 0,
5771 5771              isoc_pkts = 0; count < tw->tw_num_tds; count++) {
5772 5772  
5773 5773                  residue = curr_isoc_reqp->isoc_pkts_count - isoc_pkts;
5774 5774  
5775 5775                  /* Check for inserting residue data */
5776 5776                  if ((count == (tw->tw_num_tds - 1)) &&
5777 5777                      (residue < OHCI_ISOC_PKTS_PER_TD)) {
5778 5778                          frame_count = residue;
5779 5779                  } else {
5780 5780                          frame_count = OHCI_ISOC_PKTS_PER_TD;
5781 5781                  }
5782 5782  
5783 5783                  curr_isoc_pkt_descr = tw->tw_curr_isoc_pktp;
5784 5784  
5785 5785                  /*
5786 5786                   * Calculate length of isochronous transfer
5787 5787                   * for the current TD.
5788 5788                   */
5789 5789                  for (i = 0, curr_isoc_xfer_len = 0;
5790 5790                      i < frame_count; i++, curr_isoc_pkt_descr++) {
5791 5791                          curr_isoc_xfer_len +=
5792 5792                              curr_isoc_pkt_descr->isoc_pkt_length;
5793 5793                  }
5794 5794  
5795 5795                  /*
5796 5796                   * Programm td control field by checking whether this
5797 5797                   * is last td.
5798 5798                   */
5799 5799                  if (count == (tw->tw_num_tds - 1)) {
5800 5800                          ctrl = ((((frame_count - 1) << HC_ITD_FC_SHIFT) &
5801 5801                              HC_ITD_FC) | HC_TD_DT_0 | HC_TD_0I);
5802 5802                  } else {
5803 5803                          ctrl = ((((frame_count - 1) << HC_ITD_FC_SHIFT) &
5804 5804                              HC_ITD_FC) | HC_TD_DT_0 | HC_TD_6I);
5805 5805                  }
5806 5806  
5807 5807                  /* Insert the TD into the endpoint */
5808 5808                  if ((error = ohci_insert_hc_td(ohcip, ctrl, count,
5809 5809                      curr_isoc_xfer_len, 0, pp, tw)) !=
5810 5810                      USB_SUCCESS) {
5811 5811                          tw->tw_num_tds = count;
5812 5812                          tw->tw_length  = curr_isoc_xfer_offset;
5813 5813                          break;
5814 5814                  }
5815 5815  
5816 5816                  isoc_pkts += frame_count;
5817 5817                  tw->tw_curr_isoc_pktp += frame_count;
5818 5818                  curr_isoc_xfer_offset += curr_isoc_xfer_len;
5819 5819          }
5820 5820  
5821 5821          if (error != USB_SUCCESS) {
5822 5822                  /* Free periodic in resources */
5823 5823                  if (tw->tw_direction == USB_EP_DIR_IN) {
5824 5824                          ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
5825 5825                  }
5826 5826  
5827 5827                  /* Free all resources if IN or if count == 0(for both IN/OUT) */
5828 5828                  if (tw->tw_direction == USB_EP_DIR_IN || count == 0) {
5829 5829  
5830 5830                          ohci_deallocate_tw_resources(ohcip, pp, tw);
5831 5831  
5832 5832                          if (pp->pp_cur_periodic_req_cnt) {
5833 5833                                  /*
5834 5834                                   * Set pipe state to stop polling and
5835 5835                                   * error to no resource. Don't insert
5836 5836                                   * any more isochronous polling requests.
5837 5837                                   */
5838 5838                                  pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
5839 5839                                  pp->pp_error = error;
5840 5840                          } else {
5841 5841                                  /* Set periodic in pipe state to idle */
5842 5842                                  pp->pp_state = OHCI_PIPE_STATE_IDLE;
5843 5843                          }
5844 5844                  }
5845 5845          } else {
5846 5846  
5847 5847                  /*
5848 5848                   * Reset back to the address of first usb isochronous
5849 5849                   * packet descriptor.
5850 5850                   */
5851 5851                  tw->tw_curr_isoc_pktp = curr_isoc_reqp->isoc_pkt_descr;
5852 5852  
5853 5853                  /* Reset the CONTINUE flag */
5854 5854                  pp->pp_flag &= ~OHCI_ISOC_XFER_CONTINUE;
5855 5855          }
5856 5856  
5857 5857          return (error);
5858 5858  }
5859 5859  
5860 5860  
5861 5861  /*
5862 5862   * ohci_insert_hc_td:
5863 5863   *
5864 5864   * Insert a Transfer Descriptor (TD) on an Endpoint Descriptor (ED).
5865 5865   * Always returns USB_SUCCESS, except for ISOCH.
5866 5866   */
5867 5867  static int
5868 5868  ohci_insert_hc_td(
5869 5869          ohci_state_t            *ohcip,
5870 5870          uint_t                  hctd_ctrl,
5871 5871          uint32_t                hctd_dma_offs,
5872 5872          size_t                  hctd_length,
5873 5873          uint32_t                hctd_ctrl_phase,
5874 5874          ohci_pipe_private_t     *pp,
5875 5875          ohci_trans_wrapper_t    *tw)
5876 5876  {
5877 5877          ohci_td_t               *new_dummy;
5878 5878          ohci_td_t               *cpu_current_dummy;
5879 5879          ohci_ed_t               *ept = pp->pp_ept;
5880 5880          int                     error;
5881 5881  
5882 5882          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5883 5883  
5884 5884          /* Retrieve preallocated td from the TW */
5885 5885          new_dummy = tw->tw_hctd_free_list;
5886 5886  
5887 5887          ASSERT(new_dummy != NULL);
5888 5888  
5889 5889          tw->tw_hctd_free_list = ohci_td_iommu_to_cpu(ohcip,
5890 5890              Get_TD(new_dummy->hctd_tw_next_td));
5891 5891          Set_TD(new_dummy->hctd_tw_next_td, NULL);
5892 5892  
5893 5893          /* Fill in the current dummy */
5894 5894          cpu_current_dummy = (ohci_td_t *)
5895 5895              (ohci_td_iommu_to_cpu(ohcip, Get_ED(ept->hced_tailp)));
5896 5896  
5897 5897          /*
5898 5898           * Fill in the current dummy td and
5899 5899           * add the new dummy to the end.
5900 5900           */
5901 5901          ohci_fill_in_td(ohcip, cpu_current_dummy, new_dummy,
5902 5902              hctd_ctrl, hctd_dma_offs, hctd_length, hctd_ctrl_phase, pp, tw);
5903 5903  
5904 5904          /*
5905 5905           * If this is an isochronous TD, first write proper
5906 5906           * starting usb frame number in which this TD must
5907 5907           * can be processed. After writing the frame number
5908 5908           * insert this TD into the ED's list.
5909 5909           */
5910 5910          if ((pp->pp_pipe_handle->p_ep.bmAttributes &
5911 5911              USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
5912 5912  
5913 5913                  error = ohci_insert_td_with_frame_number(
5914 5914                      ohcip, pp, tw, cpu_current_dummy, new_dummy);
5915 5915  
5916 5916                  if (error != USB_SUCCESS) {
5917 5917                          /* Reset the current dummy back to a dummy */
5918 5918                          bzero((char *)cpu_current_dummy, sizeof (ohci_td_t));
5919 5919                          Set_TD(cpu_current_dummy->hctd_state, HC_TD_DUMMY);
5920 5920  
5921 5921                          /* return the new dummy back to the free list */
5922 5922                          bzero((char *)new_dummy, sizeof (ohci_td_t));
5923 5923                          Set_TD(new_dummy->hctd_state, HC_TD_DUMMY);
5924 5924                          if (tw->tw_hctd_free_list != NULL) {
5925 5925                                  Set_TD(new_dummy->hctd_tw_next_td,
5926 5926                                      ohci_td_cpu_to_iommu(ohcip,
5927 5927                                      tw->tw_hctd_free_list));
5928 5928                          }
5929 5929                          tw->tw_hctd_free_list = new_dummy;
5930 5930  
5931 5931                          return (error);
5932 5932                  }
5933 5933          } else {
5934 5934                  /*
5935 5935                   * For control, bulk and interrupt TD, just
5936 5936                   * add the new dummy to the ED's list. When
5937 5937                   * this occurs, the Host Controller ill see
5938 5938                   * the newly filled in dummy TD.
5939 5939                   */
5940 5940                  Set_ED(ept->hced_tailp,
5941 5941                      (ohci_td_cpu_to_iommu(ohcip, new_dummy)));
5942 5942          }
5943 5943  
5944 5944          /* Insert this td onto the tw */
5945 5945          ohci_insert_td_on_tw(ohcip, tw, cpu_current_dummy);
5946 5946  
5947 5947          return (USB_SUCCESS);
5948 5948  }
5949 5949  
5950 5950  
5951 5951  /*
5952 5952   * ohci_allocate_td_from_pool:
5953 5953   *
5954 5954   * Allocate a Transfer Descriptor (TD) from the TD buffer pool.
5955 5955   */
5956 5956  static ohci_td_t *
5957 5957  ohci_allocate_td_from_pool(ohci_state_t *ohcip)
5958 5958  {
5959 5959          int                             i, state;
5960 5960          ohci_td_t                       *td;
5961 5961  
5962 5962          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
5963 5963  
5964 5964          /*
5965 5965           * Search for a blank Transfer Descriptor (TD)
5966 5966           * in the TD buffer pool.
5967 5967           */
5968 5968          for (i = 0; i < ohci_td_pool_size; i ++) {
5969 5969                  state = Get_TD(ohcip->ohci_td_pool_addr[i].hctd_state);
5970 5970                  if (state == HC_TD_FREE) {
5971 5971                          break;
5972 5972                  }
5973 5973          }
5974 5974  
5975 5975          if (i >= ohci_td_pool_size) {
5976 5976                  USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
5977 5977                      "ohci_allocate_td_from_pool: TD exhausted");
5978 5978  
5979 5979                  return (NULL);
5980 5980          }
5981 5981  
5982 5982          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
5983 5983              "ohci_allocate_td_from_pool: Allocated %d", i);
5984 5984  
5985 5985          /* Create a new dummy for the end of the TD list */
5986 5986          td = &ohcip->ohci_td_pool_addr[i];
5987 5987  
5988 5988          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
5989 5989              "ohci_allocate_td_from_pool: td 0x%p", (void *)td);
5990 5990  
5991 5991          /* Mark the newly allocated TD as a dummy */
5992 5992          Set_TD(td->hctd_state, HC_TD_DUMMY);
5993 5993  
5994 5994          return (td);
5995 5995  }
5996 5996  
5997 5997  /*
5998 5998   * ohci_fill_in_td:
5999 5999   *
6000 6000   * Fill in the fields of a Transfer Descriptor (TD).
6001 6001   *
6002 6002   * hctd_dma_offs - different meanings for non-isoc and isoc TDs:
6003 6003   *          starting offset into the TW buffer for a non-isoc TD
6004 6004   *          and the index into the isoc TD list for an isoc TD.
6005 6005   *          For non-isoc TDs, the starting offset should be 4k
6006 6006   *          aligned and the TDs in one transfer must be filled in
6007 6007   *          increasing order.
6008 6008   */
6009 6009  static void
6010 6010  ohci_fill_in_td(
6011 6011          ohci_state_t            *ohcip,
6012 6012          ohci_td_t               *td,
6013 6013          ohci_td_t               *new_dummy,
6014 6014          uint_t                  hctd_ctrl,
6015 6015          uint32_t                hctd_dma_offs,
6016 6016          size_t                  hctd_length,
6017 6017          uint32_t                hctd_ctrl_phase,
6018 6018          ohci_pipe_private_t     *pp,
6019 6019          ohci_trans_wrapper_t    *tw)
6020 6020  {
6021 6021          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6022 6022              "ohci_fill_in_td: td 0x%p bufoffs 0x%x len 0x%lx",
6023 6023              (void *)td, hctd_dma_offs, hctd_length);
6024 6024  
6025 6025          /* Assert that the td to be filled in is a dummy */
6026 6026          ASSERT(Get_TD(td->hctd_state) == HC_TD_DUMMY);
6027 6027  
6028 6028          /* Change TD's state Active */
6029 6029          Set_TD(td->hctd_state, HC_TD_ACTIVE);
6030 6030  
6031 6031          /* Update the TD special fields */
6032 6032          if ((pp->pp_pipe_handle->p_ep.bmAttributes &
6033 6033              USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
6034 6034                  ohci_init_itd(ohcip, tw, hctd_ctrl, hctd_dma_offs, td);
6035 6035          } else {
6036 6036                  /* Update the dummy with control information */
6037 6037                  Set_TD(td->hctd_ctrl, (hctd_ctrl | HC_TD_CC_NA));
6038 6038  
6039 6039                  ohci_init_td(ohcip, tw, hctd_dma_offs, hctd_length, td);
6040 6040          }
6041 6041  
6042 6042          /* The current dummy now points to the new dummy */
6043 6043          Set_TD(td->hctd_next_td, (ohci_td_cpu_to_iommu(ohcip, new_dummy)));
6044 6044  
6045 6045          /*
6046 6046           * For Control transfer, hctd_ctrl_phase is a valid field.
6047 6047           */
6048 6048          if (hctd_ctrl_phase) {
6049 6049                  Set_TD(td->hctd_ctrl_phase, hctd_ctrl_phase);
6050 6050          }
6051 6051  
6052 6052          /* Print the td */
6053 6053          ohci_print_td(ohcip, td);
6054 6054  
6055 6055          /* Fill in the wrapper portion of the TD */
6056 6056  
6057 6057          /* Set the transfer wrapper */
6058 6058          ASSERT(tw != NULL);
6059 6059          ASSERT(tw->tw_id != NULL);
6060 6060  
6061 6061          Set_TD(td->hctd_trans_wrapper, (uint32_t)tw->tw_id);
6062 6062          Set_TD(td->hctd_tw_next_td, NULL);
6063 6063  }
6064 6064  
6065 6065  
6066 6066  /*
6067 6067   * ohci_init_td:
6068 6068   *
6069 6069   * Initialize the buffer address portion of non-isoc Transfer
6070 6070   * Descriptor (TD).
6071 6071   */
6072 6072  void
6073 6073  ohci_init_td(
6074 6074          ohci_state_t            *ohcip,
6075 6075          ohci_trans_wrapper_t    *tw,
6076 6076          uint32_t                hctd_dma_offs,
6077 6077          size_t                  hctd_length,
6078 6078          ohci_td_t               *td)
6079 6079  {
6080 6080          uint32_t        page_addr, start_addr = 0, end_addr = 0;
6081 6081          size_t          buf_len = hctd_length;
6082 6082          int             rem_len, i;
6083 6083  
6084 6084          /*
6085 6085           * TDs must be filled in increasing DMA offset order.
6086 6086           * tw_dma_offs is initialized to be 0 at TW creation and
6087 6087           * is only increased in this function.
6088 6088           */
6089 6089          ASSERT(buf_len == 0 || hctd_dma_offs >= tw->tw_dma_offs);
6090 6090  
6091 6091          Set_TD(td->hctd_xfer_offs, hctd_dma_offs);
6092 6092          Set_TD(td->hctd_xfer_len, buf_len);
6093 6093  
6094 6094          /* Computing the starting buffer address and end buffer address */
6095 6095          for (i = 0; (i < 2) && (buf_len > 0); i++) {
6096 6096                  /* Advance to the next DMA cookie if necessary */
6097 6097                  if ((tw->tw_dma_offs + tw->tw_cookie.dmac_size) <=
6098 6098                      hctd_dma_offs) {
6099 6099                          /*
6100 6100                           * tw_dma_offs always points to the starting offset
6101 6101                           * of a cookie
6102 6102                           */
6103 6103                          tw->tw_dma_offs += tw->tw_cookie.dmac_size;
6104 6104                          ddi_dma_nextcookie(tw->tw_dmahandle, &tw->tw_cookie);
6105 6105                          tw->tw_cookie_idx++;
6106 6106                          ASSERT(tw->tw_cookie_idx < tw->tw_ncookies);
6107 6107                  }
6108 6108  
6109 6109                  ASSERT((tw->tw_dma_offs + tw->tw_cookie.dmac_size) >
6110 6110                      hctd_dma_offs);
6111 6111  
6112 6112                  /*
6113 6113                   * Counting the remained buffer length to be filled in
6114 6114                   * the TD for current DMA cookie
6115 6115                   */
6116 6116                  rem_len = (tw->tw_dma_offs + tw->tw_cookie.dmac_size) -
6117 6117                      hctd_dma_offs;
6118 6118  
6119 6119                  /* Get the beginning address of the buffer */
6120 6120                  page_addr = (hctd_dma_offs - tw->tw_dma_offs) +
6121 6121                      tw->tw_cookie.dmac_address;
6122 6122                  ASSERT((page_addr % OHCI_4K_ALIGN) == 0);
6123 6123  
6124 6124                  if (i == 0) {
6125 6125                          start_addr = page_addr;
6126 6126                  }
6127 6127  
6128 6128                  USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6129 6129                      "ohci_init_td: page_addr 0x%x dmac_size "
6130 6130                      "0x%lx idx %d", page_addr, tw->tw_cookie.dmac_size,
6131 6131                      tw->tw_cookie_idx);
6132 6132  
6133 6133                  if (buf_len <= OHCI_MAX_TD_BUF_SIZE) {
6134 6134                          ASSERT(buf_len <= rem_len);
6135 6135                          end_addr = page_addr + buf_len - 1;
6136 6136                          buf_len = 0;
6137 6137                          break;
6138 6138                  } else {
6139 6139                          ASSERT(rem_len >= OHCI_MAX_TD_BUF_SIZE);
6140 6140                          buf_len -= OHCI_MAX_TD_BUF_SIZE;
6141 6141                          hctd_dma_offs += OHCI_MAX_TD_BUF_SIZE;
6142 6142                  }
6143 6143          }
6144 6144  
6145 6145          ASSERT(buf_len == 0);
6146 6146  
6147 6147          Set_TD(td->hctd_cbp, start_addr);
6148 6148          Set_TD(td->hctd_buf_end, end_addr);
6149 6149  }
6150 6150  
6151 6151  
6152 6152  /*
6153 6153   * ohci_init_itd:
6154 6154   *
6155 6155   * Initialize the buffer address portion of isoc Transfer Descriptor (TD).
6156 6156   */
6157 6157  static void
6158 6158  ohci_init_itd(
6159 6159          ohci_state_t            *ohcip,
6160 6160          ohci_trans_wrapper_t    *tw,
6161 6161          uint_t                  hctd_ctrl,
6162 6162          uint32_t                index,
6163 6163          ohci_td_t               *td)
6164 6164  {
6165 6165          uint32_t                start_addr, end_addr, offset, offset_addr;
6166 6166          ohci_isoc_buf_t         *bufp;
6167 6167          size_t                  buf_len;
6168 6168          uint_t                  buf, fc, toggle, flag;
6169 6169          usb_isoc_pkt_descr_t    *temp_pkt_descr;
6170 6170          int                     i;
6171 6171  
6172 6172          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6173 6173  
6174 6174          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6175 6175              "ohci_init_itd: ctrl = 0x%x", hctd_ctrl);
6176 6176  
6177 6177          /*
6178 6178           * Write control information except starting
6179 6179           * usb frame number.
6180 6180           */
6181 6181          Set_TD(td->hctd_ctrl, (hctd_ctrl | HC_TD_CC_NA));
6182 6182  
6183 6183          bufp = &tw->tw_isoc_bufs[index];
6184 6184          Set_TD(td->hctd_xfer_offs, index);
6185 6185          Set_TD(td->hctd_xfer_len, bufp->length);
6186 6186  
6187 6187          start_addr = bufp->cookie.dmac_address;
6188 6188          ASSERT((start_addr % OHCI_4K_ALIGN) == 0);
6189 6189  
6190 6190          buf_len = bufp->length;
6191 6191          if (bufp->ncookies == OHCI_DMA_ATTR_TD_SGLLEN) {
6192 6192                  buf_len = bufp->length - bufp->cookie.dmac_size;
6193 6193                  ddi_dma_nextcookie(bufp->dma_handle, &bufp->cookie);
6194 6194          }
6195 6195          end_addr = bufp->cookie.dmac_address + buf_len - 1;
6196 6196  
6197 6197          /*
6198 6198           * For an isochronous transfer, the hctd_cbp contains,
6199 6199           * the 4k page, and not the actual start of the buffer.
6200 6200           */
6201 6201          Set_TD(td->hctd_cbp, ((uint32_t)start_addr & HC_ITD_PAGE_MASK));
6202 6202          Set_TD(td->hctd_buf_end, end_addr);
6203 6203  
6204 6204          fc = (hctd_ctrl & HC_ITD_FC) >> HC_ITD_FC_SHIFT;
6205 6205          toggle = 0;
6206 6206          buf = start_addr;
6207 6207  
6208 6208          /*
6209 6209           * Get the address of first isochronous data packet
6210 6210           * for the current isochronous TD.
6211 6211           */
6212 6212          temp_pkt_descr =  tw->tw_curr_isoc_pktp;
6213 6213  
6214 6214          /* The offsets are actually offsets into the page */
6215 6215          for (i = 0; i <= fc; i++) {
6216 6216                  offset_addr = (uint32_t)((buf &
6217 6217                      HC_ITD_OFFSET_ADDR) | (HC_ITD_OFFSET_CC));
6218 6218  
6219 6219                  flag =  ((start_addr &
6220 6220                      HC_ITD_PAGE_MASK) ^ (buf & HC_ITD_PAGE_MASK));
6221 6221  
6222 6222                  if (flag) {
6223 6223                          offset_addr |= HC_ITD_4KBOUNDARY_CROSS;
6224 6224                  }
6225 6225  
6226 6226                  if (toggle) {
6227 6227                          offset = (uint32_t)((offset_addr <<
6228 6228                              HC_ITD_OFFSET_SHIFT) & HC_ITD_ODD_OFFSET);
6229 6229  
6230 6230                          Set_TD(td->hctd_offsets[i / 2],
6231 6231                              Get_TD(td->hctd_offsets[i / 2]) | offset);
6232 6232                          toggle = 0;
6233 6233                  } else {
6234 6234                          offset = (uint32_t)(offset_addr & HC_ITD_EVEN_OFFSET);
6235 6235  
6236 6236                          Set_TD(td->hctd_offsets[i / 2],
6237 6237                              Get_TD(td->hctd_offsets[i / 2]) | offset);
6238 6238                          toggle = 1;
6239 6239                  }
6240 6240  
6241 6241                  buf = (uint32_t)(buf + temp_pkt_descr->isoc_pkt_length);
6242 6242                  temp_pkt_descr++;
6243 6243          }
6244 6244  }
6245 6245  
6246 6246  
6247 6247  /*
6248 6248   * ohci_insert_td_with_frame_number:
6249 6249   *
6250 6250   * Insert current isochronous TD into the ED's list. with proper
6251 6251   * usb frame number in which this TD can be processed.
6252 6252   */
6253 6253  static int
6254 6254  ohci_insert_td_with_frame_number(
6255 6255          ohci_state_t            *ohcip,
6256 6256          ohci_pipe_private_t     *pp,
6257 6257          ohci_trans_wrapper_t    *tw,
6258 6258          ohci_td_t               *current_td,
6259 6259          ohci_td_t               *dummy_td)
6260 6260  {
6261 6261          usb_isoc_req_t          *isoc_reqp =
6262 6262              (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
6263 6263          usb_frame_number_t      current_frame_number, start_frame_number;
6264 6264          uint_t                  ddic, ctrl, isoc_pkts;
6265 6265          ohci_ed_t               *ept = pp->pp_ept;
6266 6266  
6267 6267          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6268 6268              "ohci_insert_td_with_frame_number:"
6269 6269              "isoc flags 0x%x", isoc_reqp->isoc_attributes);
6270 6270  
6271 6271          /* Get the TD ctrl information */
6272 6272          isoc_pkts = ((Get_TD(current_td->hctd_ctrl) &
6273 6273              HC_ITD_FC) >> HC_ITD_FC_SHIFT) + 1;
6274 6274  
6275 6275          /*
6276 6276           * Enter critical, while programming the usb frame number
6277 6277           * and inserting current isochronous TD into the ED's list.
6278 6278           */
6279 6279          ddic = ddi_enter_critical();
6280 6280  
6281 6281          /* Get the current frame number */
6282 6282          current_frame_number = ohci_get_current_frame_number(ohcip);
6283 6283  
6284 6284          /* Check the given isochronous flags */
6285 6285          switch (isoc_reqp->isoc_attributes &
6286 6286              (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) {
6287 6287          case USB_ATTRS_ISOC_START_FRAME:
6288 6288                  /* Starting frame number is specified */
6289 6289                  if (pp->pp_flag & OHCI_ISOC_XFER_CONTINUE) {
6290 6290                          /* Get the starting usb frame number */
6291 6291                          start_frame_number = pp->pp_next_frame_number;
6292 6292                  } else {
6293 6293                          /* Check for the Starting usb frame number */
6294 6294                          if ((isoc_reqp->isoc_frame_no == 0) ||
6295 6295                              ((isoc_reqp->isoc_frame_no +
6296 6296                              isoc_reqp->isoc_pkts_count) <
6297 6297                              current_frame_number)) {
6298 6298  
6299 6299                                  /* Exit the critical */
6300 6300                                  ddi_exit_critical(ddic);
6301 6301  
6302 6302                                  USB_DPRINTF_L2(PRINT_MASK_LISTS,
6303 6303                                      ohcip->ohci_log_hdl,
6304 6304                                      "ohci_insert_td_with_frame_number:"
6305 6305                                      "Invalid starting frame number");
6306 6306  
6307 6307                                  return (USB_INVALID_START_FRAME);
6308 6308                          }
6309 6309  
6310 6310                          /* Get the starting usb frame number */
6311 6311                          start_frame_number = isoc_reqp->isoc_frame_no;
6312 6312  
6313 6313                          pp->pp_next_frame_number = 0;
6314 6314                  }
6315 6315                  break;
6316 6316          case USB_ATTRS_ISOC_XFER_ASAP:
6317 6317                  /* ohci has to specify starting frame number */
6318 6318                  if ((pp->pp_next_frame_number) &&
6319 6319                      (pp->pp_next_frame_number > current_frame_number)) {
6320 6320                          /*
6321 6321                           * Get the next usb frame number.
6322 6322                           */
6323 6323                          start_frame_number = pp->pp_next_frame_number;
6324 6324                  } else {
6325 6325                          /*
6326 6326                           * Add appropriate offset to the current usb
6327 6327                           * frame number and use it as a starting frame
6328 6328                           * number.
6329 6329                           */
6330 6330                          start_frame_number =
6331 6331                              current_frame_number + OHCI_FRAME_OFFSET;
6332 6332                  }
6333 6333  
6334 6334                  if (!(pp->pp_flag & OHCI_ISOC_XFER_CONTINUE)) {
6335 6335                          isoc_reqp->isoc_frame_no = start_frame_number;
6336 6336                  }
6337 6337                  break;
6338 6338          default:
6339 6339                  /* Exit the critical */
6340 6340                  ddi_exit_critical(ddic);
6341 6341  
6342 6342                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6343 6343                      "ohci_insert_td_with_frame_number: Either starting "
6344 6344                      "frame number or ASAP flags are not set, attrs = 0x%x",
6345 6345                      isoc_reqp->isoc_attributes);
6346 6346  
6347 6347                  return (USB_NO_FRAME_NUMBER);
6348 6348          }
6349 6349  
6350 6350          /* Get the TD ctrl information */
6351 6351          ctrl = Get_TD(current_td->hctd_ctrl) & (~(HC_ITD_SF));
6352 6352  
6353 6353          /* Set the frame number field */
6354 6354          Set_TD(current_td->hctd_ctrl, ctrl | (start_frame_number & HC_ITD_SF));
6355 6355  
6356 6356          /*
6357 6357           * Add the new dummy to the ED's list. When this occurs,
6358 6358           * the Host Controller will see newly filled in dummy TD.
6359 6359           */
6360 6360          Set_ED(ept->hced_tailp, (ohci_td_cpu_to_iommu(ohcip, dummy_td)));
6361 6361  
6362 6362          /* Exit the critical */
6363 6363          ddi_exit_critical(ddic);
6364 6364  
6365 6365          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6366 6366              "ohci_insert_td_with_frame_number:"
6367 6367              "current frame number 0x%llx start frame number 0x%llx",
6368 6368              (unsigned long long)current_frame_number,
6369 6369              (unsigned long long)start_frame_number);
6370 6370  
6371 6371          /*
6372 6372           * Increment this saved frame number by current number
6373 6373           * of data packets needs to be transfer.
6374 6374           */
6375 6375          pp->pp_next_frame_number = start_frame_number + isoc_pkts;
6376 6376  
6377 6377          /*
6378 6378           * Set OHCI_ISOC_XFER_CONTINUE flag in order to send other
6379 6379           * isochronous packets,  part of the current isoch request
6380 6380           * in the subsequent frames.
6381 6381           */
6382 6382          pp->pp_flag |= OHCI_ISOC_XFER_CONTINUE;
6383 6383  
6384 6384          return (USB_SUCCESS);
6385 6385  }
6386 6386  
6387 6387  
6388 6388  /*
6389 6389   * ohci_insert_td_on_tw:
6390 6390   *
6391 6391   * The transfer wrapper keeps a list of all Transfer Descriptors (TD) that
6392 6392   * are allocated for this transfer. Insert a TD  onto this list. The  list
6393 6393   * of TD's does not include the dummy TD that is at the end of the list of
6394 6394   * TD's for the endpoint.
6395 6395   */
6396 6396  static void
6397 6397  ohci_insert_td_on_tw(
6398 6398          ohci_state_t            *ohcip,
6399 6399          ohci_trans_wrapper_t    *tw,
6400 6400          ohci_td_t               *td)
6401 6401  {
6402 6402          /*
6403 6403           * Set the next pointer to NULL because
6404 6404           * this is the last TD on list.
6405 6405           */
6406 6406          Set_TD(td->hctd_tw_next_td, NULL);
6407 6407  
6408 6408          if (tw->tw_hctd_head == NULL) {
6409 6409                  ASSERT(tw->tw_hctd_tail == NULL);
6410 6410                  tw->tw_hctd_head = td;
6411 6411                  tw->tw_hctd_tail = td;
6412 6412          } else {
6413 6413                  ohci_td_t *dummy = (ohci_td_t *)tw->tw_hctd_tail;
6414 6414  
6415 6415                  ASSERT(dummy != NULL);
6416 6416                  ASSERT(dummy != td);
6417 6417                  ASSERT(Get_TD(td->hctd_state) != HC_TD_DUMMY);
6418 6418  
6419 6419                  /* Add the td to the end of the list */
6420 6420                  Set_TD(dummy->hctd_tw_next_td,
6421 6421                      ohci_td_cpu_to_iommu(ohcip, td));
6422 6422  
6423 6423                  tw->tw_hctd_tail = td;
6424 6424  
6425 6425                  ASSERT(Get_TD(td->hctd_tw_next_td) == NULL);
6426 6426          }
6427 6427  }
6428 6428  
6429 6429  
6430 6430  /*
6431 6431   * ohci_traverse_tds:
6432 6432   * NOTE: This function is also called from POLLED MODE.
6433 6433   *
6434 6434   * Traverse the list of TD's for an endpoint.  Since the endpoint is marked
6435 6435   * as sKipped,  the Host Controller (HC) is no longer accessing these TD's.
6436 6436   * Remove all the TD's that are attached to the endpoint.
6437 6437   */
6438 6438  void
6439 6439  ohci_traverse_tds(
6440 6440          ohci_state_t            *ohcip,
6441 6441          usba_pipe_handle_data_t *ph)
6442 6442  {
6443 6443          ohci_trans_wrapper_t    *tw;
6444 6444          ohci_ed_t               *ept;
6445 6445          ohci_pipe_private_t     *pp;
6446 6446          uint32_t                addr;
6447 6447          ohci_td_t               *tailp, *headp, *next;
6448 6448  
6449 6449          pp = (ohci_pipe_private_t *)ph->p_hcd_private;
6450 6450          ept = pp->pp_ept;
6451 6451  
6452 6452          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6453 6453              "ohci_traverse_tds: ph = 0x%p ept = 0x%p",
6454 6454              (void *)ph, (void *)ept);
6455 6455  
6456 6456          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6457 6457  
6458 6458          addr = Get_ED(ept->hced_headp) & (uint32_t)HC_EPT_TD_HEAD;
6459 6459  
6460 6460          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6461 6461              "ohci_traverse_tds: addr (head) = 0x%x", addr);
6462 6462  
6463 6463          headp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip, addr));
6464 6464  
6465 6465          addr = Get_ED(ept->hced_tailp) & (uint32_t)HC_EPT_TD_TAIL;
6466 6466  
6467 6467          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6468 6468              "ohci_traverse_tds: addr (tail) = 0x%x", addr);
6469 6469  
6470 6470          tailp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip, addr));
6471 6471  
6472 6472          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6473 6473              "ohci_traverse_tds: cpu head = 0x%p cpu tail = 0x%p",
6474 6474              (void *)headp, (void *)tailp);
6475 6475  
6476 6476          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6477 6477              "ohci_traverse_tds: iommu head = 0x%x iommu tail = 0x%x",
6478 6478              ohci_td_cpu_to_iommu(ohcip, headp),
6479 6479              ohci_td_cpu_to_iommu(ohcip, tailp));
6480 6480  
6481 6481          /*
6482 6482           * Traverse the list of TD's that are currently on the endpoint.
6483 6483           * These TD's have not been processed and will not be processed
6484 6484           * because the endpoint processing is stopped.
6485 6485           */
6486 6486          while (headp != tailp) {
6487 6487                  next = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
6488 6488                      (Get_TD(headp->hctd_next_td) & HC_EPT_TD_TAIL)));
6489 6489  
6490 6490                  tw = (ohci_trans_wrapper_t *)OHCI_LOOKUP_ID(
6491 6491                      (uint32_t)Get_TD(headp->hctd_trans_wrapper));
6492 6492  
6493 6493                  /* Stop the the transfer timer */
6494 6494                  ohci_stop_xfer_timer(ohcip, tw, OHCI_REMOVE_XFER_ALWAYS);
6495 6495  
6496 6496                  ohci_deallocate_td(ohcip, headp);
6497 6497                  headp = next;
6498 6498          }
6499 6499  
6500 6500          /* Both head and tail pointers must be same */
6501 6501          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6502 6502              "ohci_traverse_tds: head = 0x%p tail = 0x%p",
6503 6503              (void *)headp, (void *)tailp);
6504 6504  
6505 6505          /* Update the pointer in the endpoint descriptor */
6506 6506          Set_ED(ept->hced_headp, (ohci_td_cpu_to_iommu(ohcip, headp)));
6507 6507  
6508 6508          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6509 6509              "ohci_traverse_tds: new head = 0x%x",
6510 6510              (ohci_td_cpu_to_iommu(ohcip, headp)));
6511 6511  
6512 6512          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6513 6513              "ohci_traverse_tds: tailp = 0x%x headp = 0x%x",
6514 6514              (Get_ED(ept->hced_tailp) & HC_EPT_TD_TAIL),
6515 6515              (Get_ED(ept->hced_headp) & HC_EPT_TD_HEAD));
6516 6516  
6517 6517          ASSERT((Get_ED(ept->hced_tailp) & HC_EPT_TD_TAIL) ==
6518 6518              (Get_ED(ept->hced_headp) & HC_EPT_TD_HEAD));
6519 6519  }
6520 6520  
6521 6521  
6522 6522  /*
6523 6523   * ohci_done_list_tds:
6524 6524   *
6525 6525   * There may be TD's on the done list that have not been processed yet. Walk
6526 6526   * through these TD's and mark them as RECLAIM. All the mappings for the  TD
6527 6527   * will be torn down, so the interrupt handle is alerted of this fact through
6528 6528   * the RECLAIM flag.
6529 6529   */
6530 6530  static void
6531 6531  ohci_done_list_tds(
6532 6532          ohci_state_t            *ohcip,
6533 6533          usba_pipe_handle_data_t *ph)
6534 6534  {
6535 6535          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
6536 6536          ohci_trans_wrapper_t    *head_tw = pp->pp_tw_head;
6537 6537          ohci_trans_wrapper_t    *next_tw;
6538 6538          ohci_td_t               *head_td, *next_td;
6539 6539  
6540 6540          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6541 6541  
6542 6542          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6543 6543              "ohci_done_list_tds:");
6544 6544  
6545 6545          /* Process the transfer wrappers for this pipe */
6546 6546          next_tw = head_tw;
6547 6547          while (next_tw) {
6548 6548                  head_td = (ohci_td_t *)next_tw->tw_hctd_head;
6549 6549                  next_td = head_td;
6550 6550  
6551 6551                  if (head_td) {
6552 6552                          /*
6553 6553                           * Walk through each TD for this transfer
6554 6554                           * wrapper. If a TD still exists, then it
6555 6555                           * is currently on the done list.
6556 6556                           */
6557 6557                          while (next_td) {
6558 6558  
6559 6559                                  /* To free TD, set TD state to RECLAIM */
6560 6560                                  Set_TD(next_td->hctd_state, HC_TD_RECLAIM);
6561 6561  
6562 6562                                  Set_TD(next_td->hctd_trans_wrapper, NULL);
6563 6563  
6564 6564                                  next_td = ohci_td_iommu_to_cpu(ohcip,
6565 6565                                      Get_TD(next_td->hctd_tw_next_td));
6566 6566                          }
6567 6567                  }
6568 6568  
6569 6569                  /* Stop the the transfer timer */
6570 6570                  ohci_stop_xfer_timer(ohcip, next_tw, OHCI_REMOVE_XFER_ALWAYS);
6571 6571  
6572 6572                  next_tw = next_tw->tw_next;
6573 6573          }
6574 6574  }
6575 6575  
6576 6576  
6577 6577  /*
6578 6578   * Remove old_td from tw and update the links.
6579 6579   */
6580 6580  void
6581 6581  ohci_unlink_td_from_tw(
6582 6582          ohci_state_t            *ohcip,
6583 6583          ohci_td_t               *old_td,
6584 6584          ohci_trans_wrapper_t    *tw)
6585 6585  {
6586 6586          ohci_td_t *next, *head, *tail;
6587 6587  
6588 6588          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6589 6589              "ohci_unlink_td_from_tw: ohcip = 0x%p, old_td = 0x%p, tw = 0x%p",
6590 6590              (void *)ohcip, (void *)old_td, (void *)tw);
6591 6591  
6592 6592          if (old_td == NULL || tw == NULL) {
6593 6593  
6594 6594                  return;
6595 6595          }
6596 6596  
6597 6597          head = tw->tw_hctd_head;
6598 6598          tail = tw->tw_hctd_tail;
6599 6599  
6600 6600          if (head == NULL) {
6601 6601  
6602 6602                  return;
6603 6603          }
6604 6604  
6605 6605          /* if this old_td is on head */
6606 6606          if (old_td == head) {
6607 6607                  if (old_td == tail) {
6608 6608                          tw->tw_hctd_head = NULL;
6609 6609                          tw->tw_hctd_tail = NULL;
6610 6610                  } else {
6611 6611                          tw->tw_hctd_head = ohci_td_iommu_to_cpu(ohcip,
6612 6612                              Get_TD(head->hctd_tw_next_td));
6613 6613                  }
6614 6614  
6615 6615                  return;
6616 6616          }
6617 6617  
6618 6618          /* find this old_td's position in the tw */
6619 6619          next = ohci_td_iommu_to_cpu(ohcip, Get_TD(head->hctd_tw_next_td));
6620 6620          while (next && (old_td != next)) {
6621 6621                  head = next;
6622 6622                  next = ohci_td_iommu_to_cpu(ohcip,
6623 6623                      Get_TD(next->hctd_tw_next_td));
6624 6624          }
6625 6625  
6626 6626          /* unlink the found old_td from the tw */
6627 6627          if (old_td == next) {
6628 6628                  Set_TD(head->hctd_tw_next_td, Get_TD(next->hctd_tw_next_td));
6629 6629                  if (old_td == tail) {
6630 6630                          tw->tw_hctd_tail = head;
6631 6631                  }
6632 6632          }
6633 6633  }
6634 6634  
6635 6635  
6636 6636  /*
6637 6637   * ohci_deallocate_td:
6638 6638   * NOTE: This function is also called from POLLED MODE.
6639 6639   *
6640 6640   * Deallocate a Host Controller's (HC) Transfer Descriptor (TD).
6641 6641   */
6642 6642  void
6643 6643  ohci_deallocate_td(
6644 6644          ohci_state_t    *ohcip,
6645 6645          ohci_td_t       *old_td)
6646 6646  {
6647 6647          ohci_trans_wrapper_t    *tw;
6648 6648  
6649 6649          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6650 6650              "ohci_deallocate_td: old_td = 0x%p", (void *)old_td);
6651 6651  
6652 6652          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6653 6653  
6654 6654          /*
6655 6655           * Obtain the transaction wrapper and tw will be
6656 6656           * NULL for the dummy and for the reclaim TD's.
6657 6657           */
6658 6658          if ((Get_TD(old_td->hctd_state) == HC_TD_DUMMY) ||
6659 6659              (Get_TD(old_td->hctd_state) == HC_TD_RECLAIM)) {
6660 6660                  tw = (ohci_trans_wrapper_t *)((uintptr_t)
6661 6661                      Get_TD(old_td->hctd_trans_wrapper));
6662 6662                  ASSERT(tw == NULL);
6663 6663          } else {
6664 6664                  tw = (ohci_trans_wrapper_t *)
6665 6665                      OHCI_LOOKUP_ID((uint32_t)
6666 6666                      Get_TD(old_td->hctd_trans_wrapper));
6667 6667                  ASSERT(tw != NULL);
6668 6668          }
6669 6669  
6670 6670          /*
6671 6671           * If this TD should be reclaimed, don't try to access its
6672 6672           * transfer wrapper.
6673 6673           */
6674 6674          if ((Get_TD(old_td->hctd_state) != HC_TD_RECLAIM) && tw) {
6675 6675  
6676 6676                  ohci_unlink_td_from_tw(ohcip, old_td, tw);
6677 6677          }
6678 6678  
6679 6679          bzero((void *)old_td, sizeof (ohci_td_t));
6680 6680          Set_TD(old_td->hctd_state, HC_TD_FREE);
6681 6681  
6682 6682          USB_DPRINTF_L3(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6683 6683              "ohci_deallocate_td: td 0x%p", (void *)old_td);
6684 6684  }
6685 6685  
6686 6686  
6687 6687  /*
6688 6688   * ohci_td_cpu_to_iommu:
6689 6689   * NOTE: This function is also called from POLLED MODE.
6690 6690   *
6691 6691   * This function converts for the given Transfer Descriptor (TD) CPU address
6692 6692   * to IO address.
6693 6693   */
6694 6694  uint32_t
6695 6695  ohci_td_cpu_to_iommu(
6696 6696          ohci_state_t    *ohcip,
6697 6697          ohci_td_t       *addr)
6698 6698  {
6699 6699          uint32_t        td;
6700 6700  
6701 6701          td  = (uint32_t)ohcip->ohci_td_pool_cookie.dmac_address +
6702 6702              (uint32_t)((uintptr_t)addr - (uintptr_t)(ohcip->ohci_td_pool_addr));
6703 6703  
6704 6704          ASSERT((ohcip->ohci_td_pool_cookie.dmac_address +
6705 6705              (uint32_t) (sizeof (ohci_td_t) *
6706 6706              (addr - ohcip->ohci_td_pool_addr))) ==
6707 6707              (ohcip->ohci_td_pool_cookie.dmac_address +
6708 6708              (uint32_t)((uintptr_t)addr - (uintptr_t)
6709 6709              (ohcip->ohci_td_pool_addr))));
6710 6710  
6711 6711          ASSERT(td >= ohcip->ohci_td_pool_cookie.dmac_address);
6712 6712          ASSERT(td <= ohcip->ohci_td_pool_cookie.dmac_address +
6713 6713              sizeof (ohci_td_t) * ohci_td_pool_size);
6714 6714  
6715 6715          return (td);
6716 6716  }
6717 6717  
6718 6718  
6719 6719  /*
6720 6720   * ohci_td_iommu_to_cpu:
6721 6721   * NOTE: This function is also called from POLLED MODE.
6722 6722   *
6723 6723   * This function converts for the given Transfer Descriptor (TD) IO address
6724 6724   * to CPU address.
6725 6725   */
6726 6726  ohci_td_t *
6727 6727  ohci_td_iommu_to_cpu(
6728 6728          ohci_state_t    *ohcip,
6729 6729          uintptr_t       addr)
6730 6730  {
6731 6731          ohci_td_t       *td;
6732 6732  
6733 6733          if (addr == NULL) {
6734 6734  
6735 6735                  return (NULL);
6736 6736          }
6737 6737  
6738 6738          td = (ohci_td_t *)((uintptr_t)
6739 6739              (addr - ohcip->ohci_td_pool_cookie.dmac_address) +
6740 6740              (uintptr_t)ohcip->ohci_td_pool_addr);
6741 6741  
6742 6742          ASSERT(td >= ohcip->ohci_td_pool_addr);
6743 6743          ASSERT((uintptr_t)td <= (uintptr_t)ohcip->ohci_td_pool_addr +
6744 6744              (uintptr_t)(sizeof (ohci_td_t) * ohci_td_pool_size));
6745 6745  
6746 6746          return (td);
6747 6747  }
6748 6748  
6749 6749  /*
6750 6750   * ohci_allocate_tds_for_tw:
6751 6751   *
6752 6752   * Allocate n Transfer Descriptors (TD) from the TD buffer pool and places it
6753 6753   * into the TW.
6754 6754   *
6755 6755   * Returns USB_NO_RESOURCES if it was not able to allocate all the requested TD
6756 6756   * otherwise USB_SUCCESS.
6757 6757   */
6758 6758  int
6759 6759  ohci_allocate_tds_for_tw(
6760 6760          ohci_state_t            *ohcip,
6761 6761          ohci_trans_wrapper_t    *tw,
6762 6762          size_t                  td_count)
6763 6763  {
6764 6764          ohci_td_t               *td;
6765 6765          uint32_t                td_addr;
6766 6766          int                     i;
6767 6767          int                     error = USB_SUCCESS;
6768 6768  
6769 6769          for (i = 0; i < td_count; i++) {
6770 6770                  td = ohci_allocate_td_from_pool(ohcip);
6771 6771                  if (td == NULL) {
6772 6772                          error = USB_NO_RESOURCES;
6773 6773                          USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6774 6774                              "ohci_allocate_tds_for_tw: "
6775 6775                              "Unable to allocate %lu TDs",
6776 6776                              td_count);
6777 6777                          break;
6778 6778                  }
6779 6779                  if (tw->tw_hctd_free_list != NULL) {
6780 6780                          td_addr = ohci_td_cpu_to_iommu(ohcip,
6781 6781                              tw->tw_hctd_free_list);
6782 6782                          Set_TD(td->hctd_tw_next_td, td_addr);
6783 6783                  }
6784 6784                  tw->tw_hctd_free_list = td;
6785 6785          }
6786 6786  
6787 6787          return (error);
6788 6788  }
6789 6789  
6790 6790  /*
6791 6791   * ohci_allocate_tw_resources:
6792 6792   *
6793 6793   * Allocate a Transaction Wrapper (TW) and n Transfer Descriptors (TD)
6794 6794   * from the TD buffer pool and places it into the TW.  It does an all
6795 6795   * or nothing transaction.
6796 6796   *
6797 6797   * Returns NULL if there is insufficient resources otherwise TW.
6798 6798   */
6799 6799  static ohci_trans_wrapper_t *
6800 6800  ohci_allocate_tw_resources(
6801 6801          ohci_state_t            *ohcip,
6802 6802          ohci_pipe_private_t     *pp,
6803 6803          size_t                  tw_length,
6804 6804          usb_flags_t             usb_flags,
6805 6805          size_t                  td_count)
6806 6806  {
6807 6807          ohci_trans_wrapper_t    *tw;
6808 6808  
6809 6809          tw = ohci_create_transfer_wrapper(ohcip, pp, tw_length, usb_flags);
6810 6810  
6811 6811          if (tw == NULL) {
6812 6812                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
6813 6813                      "ohci_allocate_tw_resources: Unable to allocate TW");
6814 6814          } else {
6815 6815                  if (ohci_allocate_tds_for_tw(ohcip, tw, td_count) ==
6816 6816                      USB_SUCCESS) {
6817 6817                          tw->tw_num_tds = (uint_t)td_count;
6818 6818                  } else {
6819 6819                          ohci_deallocate_tw_resources(ohcip, pp, tw);
6820 6820                          tw = NULL;
6821 6821                  }
6822 6822          }
6823 6823  
6824 6824          return (tw);
6825 6825  }
6826 6826  
6827 6827  /*
6828 6828   * ohci_free_tw_tds_resources:
6829 6829   *
6830 6830   * Free all allocated resources for Transaction Wrapper (TW).
6831 6831   * Does not free the TW itself.
6832 6832   */
6833 6833  static void
6834 6834  ohci_free_tw_tds_resources(
6835 6835          ohci_state_t            *ohcip,
6836 6836          ohci_trans_wrapper_t    *tw)
6837 6837  {
6838 6838          ohci_td_t               *td;
6839 6839          ohci_td_t               *temp_td;
6840 6840  
6841 6841          td = tw->tw_hctd_free_list;
6842 6842          while (td != NULL) {
6843 6843                  /* Save the pointer to the next td before destroying it */
6844 6844                  temp_td = ohci_td_iommu_to_cpu(ohcip,
6845 6845                      Get_TD(td->hctd_tw_next_td));
6846 6846                  ohci_deallocate_td(ohcip, td);
6847 6847                  td = temp_td;
6848 6848          }
6849 6849          tw->tw_hctd_free_list = NULL;
6850 6850  }
6851 6851  
6852 6852  
6853 6853  /*
6854 6854   * Transfer Wrapper functions
6855 6855   *
6856 6856   * ohci_create_transfer_wrapper:
6857 6857   *
6858 6858   * Create a Transaction Wrapper (TW) for non-isoc transfer types
6859 6859   * and this involves the allocating of DMA resources.
6860 6860   */
6861 6861  static ohci_trans_wrapper_t *
6862 6862  ohci_create_transfer_wrapper(
6863 6863          ohci_state_t            *ohcip,
6864 6864          ohci_pipe_private_t     *pp,
6865 6865          size_t                  length,
6866 6866          uint_t                  usb_flags)
6867 6867  {
6868 6868          ddi_device_acc_attr_t   dev_attr;
6869 6869          int                     result;
6870 6870          size_t                  real_length;
6871 6871          ohci_trans_wrapper_t    *tw;
6872 6872          ddi_dma_attr_t          dma_attr;
6873 6873          int                     kmem_flag;
6874 6874          int                     (*dmamem_wait)(caddr_t);
6875 6875          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
6876 6876  
6877 6877          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6878 6878              "ohci_create_transfer_wrapper: length = 0x%lx flags = 0x%x",
6879 6879              length, usb_flags);
6880 6880  
6881 6881          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
6882 6882  
6883 6883          /* isochronous pipe should not call into this function */
6884 6884          if ((ph->p_ep.bmAttributes & USB_EP_ATTR_MASK) ==
6885 6885              USB_EP_ATTR_ISOCH) {
6886 6886  
6887 6887                  return (NULL);
6888 6888          }
6889 6889  
6890 6890          /* SLEEP flag should not be used while holding mutex */
6891 6891          kmem_flag = KM_NOSLEEP;
6892 6892          dmamem_wait = DDI_DMA_DONTWAIT;
6893 6893  
6894 6894          /* Allocate space for the transfer wrapper */
6895 6895          tw = kmem_zalloc(sizeof (ohci_trans_wrapper_t), kmem_flag);
6896 6896  
6897 6897          if (tw == NULL) {
6898 6898                  USB_DPRINTF_L2(PRINT_MASK_ALLOC,  ohcip->ohci_log_hdl,
6899 6899                      "ohci_create_transfer_wrapper: kmem_zalloc failed");
6900 6900  
6901 6901                  return (NULL);
6902 6902          }
6903 6903  
6904 6904          /* zero-length packet doesn't need to allocate dma memory */
6905 6905          if (length == 0) {
6906 6906  
6907 6907                  goto dmadone;
6908 6908          }
6909 6909  
6910 6910          /* allow sg lists for transfer wrapper dma memory */
6911 6911          bcopy(&ohcip->ohci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
6912 6912          dma_attr.dma_attr_sgllen = OHCI_DMA_ATTR_TW_SGLLEN;
6913 6913          dma_attr.dma_attr_align = OHCI_DMA_ATTR_ALIGNMENT;
6914 6914  
6915 6915          /* Allocate the DMA handle */
6916 6916          result = ddi_dma_alloc_handle(ohcip->ohci_dip,
6917 6917              &dma_attr, dmamem_wait, 0, &tw->tw_dmahandle);
6918 6918  
6919 6919          if (result != DDI_SUCCESS) {
6920 6920                  USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6921 6921                      "ohci_create_transfer_wrapper: Alloc handle failed");
6922 6922  
6923 6923                  kmem_free(tw, sizeof (ohci_trans_wrapper_t));
6924 6924  
6925 6925                  return (NULL);
6926 6926          }
6927 6927  
6928 6928          dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
6929 6929  
6930 6930          /* The host controller will be little endian */
6931 6931          dev_attr.devacc_attr_endian_flags  = DDI_STRUCTURE_BE_ACC;
6932 6932          dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
6933 6933  
6934 6934          /* Allocate the memory */
6935 6935          result = ddi_dma_mem_alloc(tw->tw_dmahandle, length,
6936 6936              &dev_attr, DDI_DMA_CONSISTENT, dmamem_wait, NULL,
6937 6937              (caddr_t *)&tw->tw_buf, &real_length, &tw->tw_accesshandle);
6938 6938  
6939 6939          if (result != DDI_SUCCESS) {
6940 6940                  USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6941 6941                      "ohci_create_transfer_wrapper: dma_mem_alloc fail");
6942 6942  
6943 6943                  ddi_dma_free_handle(&tw->tw_dmahandle);
6944 6944                  kmem_free(tw, sizeof (ohci_trans_wrapper_t));
6945 6945  
6946 6946                  return (NULL);
6947 6947          }
6948 6948  
6949 6949          ASSERT(real_length >= length);
6950 6950  
6951 6951          /* Bind the handle */
6952 6952          result = ddi_dma_addr_bind_handle(tw->tw_dmahandle, NULL,
6953 6953              (caddr_t)tw->tw_buf, real_length, DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
6954 6954              dmamem_wait, NULL, &tw->tw_cookie, &tw->tw_ncookies);
6955 6955  
6956 6956          if (result != DDI_DMA_MAPPED) {
6957 6957                  ohci_decode_ddi_dma_addr_bind_handle_result(ohcip, result);
6958 6958  
6959 6959                  ddi_dma_mem_free(&tw->tw_accesshandle);
6960 6960                  ddi_dma_free_handle(&tw->tw_dmahandle);
6961 6961                  kmem_free(tw, sizeof (ohci_trans_wrapper_t));
6962 6962  
6963 6963                  return (NULL);
6964 6964          }
6965 6965  
6966 6966          tw->tw_cookie_idx = 0;
6967 6967          tw->tw_dma_offs = 0;
6968 6968  
6969 6969  dmadone:
6970 6970          /*
6971 6971           * Only allow one wrapper to be added at a time. Insert the
6972 6972           * new transaction wrapper into the list for this pipe.
6973 6973           */
6974 6974          if (pp->pp_tw_head == NULL) {
6975 6975                  pp->pp_tw_head = tw;
6976 6976                  pp->pp_tw_tail = tw;
6977 6977          } else {
6978 6978                  pp->pp_tw_tail->tw_next = tw;
6979 6979                  pp->pp_tw_tail = tw;
6980 6980          }
6981 6981  
6982 6982          /* Store the transfer length */
6983 6983          tw->tw_length = length;
6984 6984  
6985 6985          /* Store a back pointer to the pipe private structure */
6986 6986          tw->tw_pipe_private = pp;
6987 6987  
6988 6988          /* Store the transfer type - synchronous or asynchronous */
6989 6989          tw->tw_flags = usb_flags;
6990 6990  
6991 6991          /* Get and Store 32bit ID */
6992 6992          tw->tw_id = OHCI_GET_ID((void *)tw);
6993 6993  
6994 6994          ASSERT(tw->tw_id != NULL);
6995 6995  
6996 6996          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
6997 6997              "ohci_create_transfer_wrapper: tw = 0x%p, ncookies = %u",
6998 6998              (void *)tw, tw->tw_ncookies);
6999 6999  
7000 7000          return (tw);
7001 7001  }
7002 7002  
7003 7003  
7004 7004  /*
7005 7005   * Transfer Wrapper functions
7006 7006   *
7007 7007   * ohci_create_isoc_transfer_wrapper:
7008 7008   *
7009 7009   * Create a Transaction Wrapper (TW) for isoc transfer
7010 7010   * and this involves the allocating of DMA resources.
7011 7011   */
7012 7012  static ohci_trans_wrapper_t *
7013 7013  ohci_create_isoc_transfer_wrapper(
7014 7014          ohci_state_t            *ohcip,
7015 7015          ohci_pipe_private_t     *pp,
7016 7016          size_t                  length,
7017 7017          usb_isoc_pkt_descr_t    *descr,
7018 7018          ushort_t                pkt_count,
7019 7019          size_t                  td_count,
7020 7020          uint_t                  usb_flags)
7021 7021  {
7022 7022          ddi_device_acc_attr_t   dev_attr;
7023 7023          int                     result;
7024 7024          size_t                  real_length, xfer_size;
7025 7025          uint_t                  ccount;
7026 7026          ohci_trans_wrapper_t    *tw;
7027 7027          ddi_dma_attr_t          dma_attr;
7028 7028          int                     kmem_flag;
7029 7029          uint_t                  i, j, frame_count, residue;
7030 7030          int                     (*dmamem_wait)(caddr_t);
7031 7031          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
7032 7032          usb_isoc_pkt_descr_t    *isoc_pkt_descr = descr;
7033 7033  
7034 7034          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7035 7035              "ohci_create_isoc_transfer_wrapper: length = 0x%lx flags = 0x%x",
7036 7036              length, usb_flags);
7037 7037  
7038 7038          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7039 7039  
7040 7040          /* non-isochronous pipe should not call into this function */
7041 7041          if ((ph->p_ep.bmAttributes & USB_EP_ATTR_MASK) !=
7042 7042              USB_EP_ATTR_ISOCH) {
7043 7043  
7044 7044                  return (NULL);
7045 7045          }
7046 7046  
7047 7047          /* SLEEP flag should not be used in interrupt context */
7048 7048          if (servicing_interrupt()) {
7049 7049                  kmem_flag = KM_NOSLEEP;
7050 7050                  dmamem_wait = DDI_DMA_DONTWAIT;
7051 7051          } else {
7052 7052                  kmem_flag = KM_SLEEP;
7053 7053                  dmamem_wait = DDI_DMA_SLEEP;
7054 7054          }
7055 7055  
7056 7056          /* Allocate space for the transfer wrapper */
7057 7057          tw = kmem_zalloc(sizeof (ohci_trans_wrapper_t), kmem_flag);
7058 7058  
7059 7059          if (tw == NULL) {
7060 7060                  USB_DPRINTF_L2(PRINT_MASK_ALLOC,  ohcip->ohci_log_hdl,
7061 7061                      "ohci_create_transfer_wrapper: kmem_zalloc failed");
7062 7062  
7063 7063                  return (NULL);
7064 7064          }
7065 7065  
7066 7066          /* Allocate space for the isoc buffer handles */
7067 7067          tw->tw_isoc_strtlen = sizeof (ohci_isoc_buf_t) * td_count;
7068 7068          if ((tw->tw_isoc_bufs = kmem_zalloc(tw->tw_isoc_strtlen,
7069 7069              kmem_flag)) == NULL) {
7070 7070                  USB_DPRINTF_L2(PRINT_MASK_LISTS,  ohcip->ohci_log_hdl,
7071 7071                      "ohci_create_isoc_transfer_wrapper: kmem_alloc "
7072 7072                      "isoc buffer failed");
7073 7073                  kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7074 7074  
7075 7075                  return (NULL);
7076 7076          }
7077 7077  
7078 7078          /* allow sg lists for transfer wrapper dma memory */
7079 7079          bcopy(&ohcip->ohci_dma_attr, &dma_attr, sizeof (ddi_dma_attr_t));
7080 7080          dma_attr.dma_attr_sgllen = OHCI_DMA_ATTR_TD_SGLLEN;
7081 7081          dma_attr.dma_attr_align = OHCI_DMA_ATTR_ALIGNMENT;
7082 7082  
7083 7083          dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
7084 7084  
7085 7085          /* The host controller will be little endian */
7086 7086          dev_attr.devacc_attr_endian_flags  = DDI_STRUCTURE_BE_ACC;
7087 7087          dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
7088 7088  
7089 7089          residue = pkt_count % OHCI_ISOC_PKTS_PER_TD;
7090 7090  
7091 7091          for (i = 0; i < td_count; i++) {
7092 7092                  tw->tw_isoc_bufs[i].index = i;
7093 7093  
7094 7094                  if ((i == (td_count - 1)) && (residue != 0)) {
7095 7095                          frame_count = residue;
7096 7096                  } else {
7097 7097                          frame_count = OHCI_ISOC_PKTS_PER_TD;
7098 7098                  }
7099 7099  
7100 7100                  /* Allocate the DMA handle */
7101 7101                  result = ddi_dma_alloc_handle(ohcip->ohci_dip, &dma_attr,
7102 7102                      dmamem_wait, 0, &tw->tw_isoc_bufs[i].dma_handle);
7103 7103  
7104 7104                  if (result != DDI_SUCCESS) {
7105 7105                          USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7106 7106                              "ohci_create_isoc_transfer_wrapper: "
7107 7107                              "Alloc handle failed");
7108 7108  
7109 7109                          for (j = 0; j < i; j++) {
7110 7110                                  result = ddi_dma_unbind_handle(
7111 7111                                      tw->tw_isoc_bufs[j].dma_handle);
7112 7112                                  ASSERT(result == USB_SUCCESS);
7113 7113                                  ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
7114 7114                                      mem_handle);
7115 7115                                  ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
7116 7116                                      dma_handle);
7117 7117                          }
7118 7118                          kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7119 7119                          kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7120 7120  
7121 7121                          return (NULL);
7122 7122                  }
7123 7123  
7124 7124                  /* Compute the memory length */
7125 7125                  for (xfer_size = 0, j = 0; j < frame_count; j++) {
7126 7126                          ASSERT(isoc_pkt_descr != NULL);
7127 7127                          xfer_size += isoc_pkt_descr->isoc_pkt_length;
7128 7128                          isoc_pkt_descr++;
7129 7129                  }
7130 7130  
7131 7131                  /* Allocate the memory */
7132 7132                  result = ddi_dma_mem_alloc(tw->tw_isoc_bufs[i].dma_handle,
7133 7133                      xfer_size, &dev_attr, DDI_DMA_CONSISTENT, dmamem_wait,
7134 7134                      NULL, (caddr_t *)&tw->tw_isoc_bufs[i].buf_addr,
7135 7135                      &real_length, &tw->tw_isoc_bufs[i].mem_handle);
7136 7136  
7137 7137                  if (result != DDI_SUCCESS) {
7138 7138                          USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7139 7139                              "ohci_create_isoc_transfer_wrapper: "
7140 7140                              "dma_mem_alloc %d fail", i);
7141 7141                          ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
7142 7142  
7143 7143                          for (j = 0; j < i; j++) {
7144 7144                                  result = ddi_dma_unbind_handle(
7145 7145                                      tw->tw_isoc_bufs[j].dma_handle);
7146 7146                                  ASSERT(result == USB_SUCCESS);
7147 7147                                  ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
7148 7148                                      mem_handle);
7149 7149                                  ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
7150 7150                                      dma_handle);
7151 7151                          }
7152 7152                          kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7153 7153                          kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7154 7154  
7155 7155                          return (NULL);
7156 7156                  }
7157 7157  
7158 7158                  ASSERT(real_length >= xfer_size);
7159 7159  
7160 7160                  /* Bind the handle */
7161 7161                  result = ddi_dma_addr_bind_handle(
7162 7162                      tw->tw_isoc_bufs[i].dma_handle, NULL,
7163 7163                      (caddr_t)tw->tw_isoc_bufs[i].buf_addr, real_length,
7164 7164                      DDI_DMA_RDWR|DDI_DMA_CONSISTENT, dmamem_wait, NULL,
7165 7165                      &tw->tw_isoc_bufs[i].cookie, &ccount);
7166 7166  
7167 7167                  if ((result == DDI_DMA_MAPPED) &&
7168 7168                      (ccount <= OHCI_DMA_ATTR_TD_SGLLEN)) {
7169 7169                          tw->tw_isoc_bufs[i].length = xfer_size;
7170 7170                          tw->tw_isoc_bufs[i].ncookies = ccount;
7171 7171  
7172 7172                          continue;
7173 7173                  } else {
7174 7174                          USB_DPRINTF_L2(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7175 7175                              "ohci_create_isoc_transfer_wrapper: "
7176 7176                              "Bind handle %d failed", i);
7177 7177                          if (result == DDI_DMA_MAPPED) {
7178 7178                                  result = ddi_dma_unbind_handle(
7179 7179                                      tw->tw_isoc_bufs[i].dma_handle);
7180 7180                                  ASSERT(result == USB_SUCCESS);
7181 7181                          }
7182 7182                          ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
7183 7183                          ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
7184 7184  
7185 7185                          for (j = 0; j < i; j++) {
7186 7186                                  result = ddi_dma_unbind_handle(
7187 7187                                      tw->tw_isoc_bufs[j].dma_handle);
7188 7188                                  ASSERT(result == USB_SUCCESS);
7189 7189                                  ddi_dma_mem_free(&tw->tw_isoc_bufs[j].
7190 7190                                      mem_handle);
7191 7191                                  ddi_dma_free_handle(&tw->tw_isoc_bufs[j].
7192 7192                                      dma_handle);
7193 7193                          }
7194 7194                          kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7195 7195                          kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7196 7196  
7197 7197                          return (NULL);
7198 7198                  }
7199 7199          }
7200 7200  
7201 7201          /*
7202 7202           * Only allow one wrapper to be added at a time. Insert the
7203 7203           * new transaction wrapper into the list for this pipe.
7204 7204           */
7205 7205          if (pp->pp_tw_head == NULL) {
7206 7206                  pp->pp_tw_head = tw;
7207 7207                  pp->pp_tw_tail = tw;
7208 7208          } else {
7209 7209                  pp->pp_tw_tail->tw_next = tw;
7210 7210                  pp->pp_tw_tail = tw;
7211 7211          }
7212 7212  
7213 7213          /* Store the transfer length */
7214 7214          tw->tw_length = length;
7215 7215  
7216 7216          /* Store the td numbers */
7217 7217          tw->tw_ncookies = (uint_t)td_count;
7218 7218  
7219 7219          /* Store a back pointer to the pipe private structure */
7220 7220          tw->tw_pipe_private = pp;
7221 7221  
7222 7222          /* Store the transfer type - synchronous or asynchronous */
7223 7223          tw->tw_flags = usb_flags;
7224 7224  
7225 7225          /* Get and Store 32bit ID */
7226 7226          tw->tw_id = OHCI_GET_ID((void *)tw);
7227 7227  
7228 7228          ASSERT(tw->tw_id != NULL);
7229 7229  
7230 7230          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7231 7231              "ohci_create_isoc_transfer_wrapper: tw = 0x%p", (void *)tw);
7232 7232  
7233 7233          return (tw);
7234 7234  }
7235 7235  
7236 7236  
7237 7237  /*
7238 7238   * ohci_start_xfer_timer:
7239 7239   *
7240 7240   * Start the timer for the control, bulk and for one time interrupt
7241 7241   * transfers.
7242 7242   */
7243 7243  /* ARGSUSED */
7244 7244  static void
7245 7245  ohci_start_xfer_timer(
7246 7246          ohci_state_t            *ohcip,
7247 7247          ohci_pipe_private_t     *pp,
7248 7248          ohci_trans_wrapper_t    *tw)
7249 7249  {
7250 7250          USB_DPRINTF_L3(PRINT_MASK_LISTS,  ohcip->ohci_log_hdl,
7251 7251              "ohci_start_xfer_timer: tw = 0x%p", (void *)tw);
7252 7252  
7253 7253          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7254 7254  
7255 7255          /*
7256 7256           * The timeout handling is done only for control, bulk and for
7257 7257           * one time Interrupt transfers.
7258 7258           *
7259 7259           * NOTE: If timeout is zero; Assume infinite timeout and don't
7260 7260           * insert this transfer on the timeout list.
7261 7261           */
7262 7262          if (tw->tw_timeout) {
7263 7263                  /*
7264 7264                   * Increase timeout value by one second and this extra one
7265 7265                   * second is used to halt the endpoint if given transfer
7266 7266                   * times out.
7267 7267                   */
7268 7268                  tw->tw_timeout++;
7269 7269  
7270 7270                  /*
7271 7271                   * Add this transfer wrapper into the transfer timeout list.
7272 7272                   */
7273 7273                  if (ohcip->ohci_timeout_list) {
7274 7274                          tw->tw_timeout_next = ohcip->ohci_timeout_list;
7275 7275                  }
7276 7276  
7277 7277                  ohcip->ohci_timeout_list = tw;
7278 7278                  ohci_start_timer(ohcip);
7279 7279          }
7280 7280  }
7281 7281  
7282 7282  
7283 7283  /*
7284 7284   * ohci_stop_xfer_timer:
7285 7285   *
7286 7286   * Start the timer for the control, bulk and for one time interrupt
7287 7287   * transfers.
7288 7288   */
7289 7289  void
7290 7290  ohci_stop_xfer_timer(
7291 7291          ohci_state_t            *ohcip,
7292 7292          ohci_trans_wrapper_t    *tw,
7293 7293          uint_t                  flag)
7294 7294  {
7295 7295          timeout_id_t            timer_id;
7296 7296  
7297 7297          USB_DPRINTF_L3(PRINT_MASK_LISTS,  ohcip->ohci_log_hdl,
7298 7298              "ohci_stop_xfer_timer: tw = 0x%p", (void *)tw);
7299 7299  
7300 7300          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7301 7301  
7302 7302          /*
7303 7303           * The timeout handling is done only for control, bulk
7304 7304           * and for one time Interrupt transfers.
7305 7305           */
7306 7306          if (ohcip->ohci_timeout_list == NULL) {
7307 7307                  return;
7308 7308          }
7309 7309  
7310 7310          switch (flag) {
7311 7311          case OHCI_REMOVE_XFER_IFLAST:
7312 7312                  if (tw->tw_hctd_head != tw->tw_hctd_tail) {
7313 7313                          break;
7314 7314                  }
7315 7315                  /* FALLTHRU */
7316 7316          case OHCI_REMOVE_XFER_ALWAYS:
7317 7317                  ohci_remove_tw_from_timeout_list(ohcip, tw);
7318 7318  
7319 7319                  if ((ohcip->ohci_timeout_list == NULL) &&
7320 7320                      (ohcip->ohci_timer_id)) {
7321 7321  
7322 7322                          timer_id = ohcip->ohci_timer_id;
7323 7323  
7324 7324                          /* Reset the timer id to zero */
7325 7325                          ohcip->ohci_timer_id = 0;
7326 7326  
7327 7327                          mutex_exit(&ohcip->ohci_int_mutex);
7328 7328  
7329 7329                          (void) untimeout(timer_id);
7330 7330  
7331 7331                          mutex_enter(&ohcip->ohci_int_mutex);
7332 7332                  }
7333 7333                  break;
7334 7334          default:
7335 7335                  break;
7336 7336          }
7337 7337  }
7338 7338  
7339 7339  
7340 7340  /*
7341 7341   * ohci_xfer_timeout_handler:
7342 7342   *
7343 7343   * Control or bulk transfer timeout handler.
7344 7344   */
7345 7345  static void
7346 7346  ohci_xfer_timeout_handler(void *arg)
7347 7347  {
7348 7348          ohci_state_t            *ohcip = (ohci_state_t *)arg;
7349 7349          ohci_trans_wrapper_t    *exp_xfer_list_head = NULL;
7350 7350          ohci_trans_wrapper_t    *exp_xfer_list_tail = NULL;
7351 7351          ohci_trans_wrapper_t    *tw, *next;
7352 7352          ohci_td_t               *td;
7353 7353          usb_flags_t             flags;
7354 7354  
7355 7355          USB_DPRINTF_L3(PRINT_MASK_LISTS,  ohcip->ohci_log_hdl,
7356 7356              "ohci_xfer_timeout_handler: ohcip = 0x%p", (void *)ohcip);
7357 7357  
7358 7358          mutex_enter(&ohcip->ohci_int_mutex);
7359 7359  
7360 7360          /* Set the required flags */
7361 7361          flags = OHCI_FLAGS_NOSLEEP | OHCI_FLAGS_DMA_SYNC;
7362 7362  
7363 7363          /*
7364 7364           * Check whether still timeout handler is valid.
7365 7365           */
7366 7366          if (ohcip->ohci_timer_id) {
7367 7367  
7368 7368                  /* Reset the timer id to zero */
7369 7369                  ohcip->ohci_timer_id = 0;
7370 7370          } else {
7371 7371                  mutex_exit(&ohcip->ohci_int_mutex);
7372 7372  
7373 7373                  return;
7374 7374          }
7375 7375  
7376 7376          /* Get the transfer timeout list head */
7377 7377          tw = ohcip->ohci_timeout_list;
7378 7378  
7379 7379          /*
7380 7380           * Process ohci timeout list and look whether the timer
7381 7381           * has expired for any transfers. Create a temporary list
7382 7382           * of expired transfers and process them later.
7383 7383           */
7384 7384          while (tw) {
7385 7385                  /* Get the transfer on the timeout list */
7386 7386                  next = tw->tw_timeout_next;
7387 7387  
7388 7388                  tw->tw_timeout--;
7389 7389  
7390 7390                  /*
7391 7391                   * Set the sKip bit to stop all transactions on
7392 7392                   * this pipe
7393 7393                   */
7394 7394                  if (tw->tw_timeout == 1) {
7395 7395                          ohci_modify_sKip_bit(ohcip,
7396 7396                              tw->tw_pipe_private, SET_sKip, flags);
7397 7397  
7398 7398                          /* Reset dma sync flag */
7399 7399                          flags &= ~OHCI_FLAGS_DMA_SYNC;
7400 7400                  }
7401 7401  
7402 7402                  /* Remove tw from the timeout list */
7403 7403                  if (tw->tw_timeout == 0) {
7404 7404  
7405 7405                          ohci_remove_tw_from_timeout_list(ohcip, tw);
7406 7406  
7407 7407                          /* Add tw to the end of expire list */
7408 7408                          if (exp_xfer_list_head) {
7409 7409                                  exp_xfer_list_tail->tw_timeout_next = tw;
7410 7410                          } else {
7411 7411                                  exp_xfer_list_head = tw;
7412 7412                          }
7413 7413                          exp_xfer_list_tail = tw;
7414 7414                          tw->tw_timeout_next = NULL;
7415 7415                  }
7416 7416  
7417 7417                  tw = next;
7418 7418          }
7419 7419  
7420 7420          /* Get the expired transfer timeout list head */
7421 7421          tw = exp_xfer_list_head;
7422 7422  
7423 7423          if (tw && (flags & OHCI_FLAGS_DMA_SYNC)) {
7424 7424                  /* Sync ED and TD pool */
7425 7425                  Sync_ED_TD_Pool(ohcip);
7426 7426          }
7427 7427  
7428 7428          /*
7429 7429           * Process the expired transfers by notifing the corrsponding
7430 7430           * client driver through the exception callback.
7431 7431           */
7432 7432          while (tw) {
7433 7433                  /* Get the transfer on the expired transfer timeout list */
7434 7434                  next = tw->tw_timeout_next;
7435 7435  
7436 7436                  td = tw->tw_hctd_head;
7437 7437  
7438 7438                  while (td) {
7439 7439                          /* Set TD state to TIMEOUT */
7440 7440                          Set_TD(td->hctd_state, HC_TD_TIMEOUT);
7441 7441  
7442 7442                          /* Get the next TD from the wrapper */
7443 7443                          td = ohci_td_iommu_to_cpu(ohcip,
7444 7444                              Get_TD(td->hctd_tw_next_td));
7445 7445                  }
7446 7446  
7447 7447                  ohci_handle_error(ohcip, tw->tw_hctd_head, USB_CR_TIMEOUT);
7448 7448  
7449 7449                  tw = next;
7450 7450          }
7451 7451  
7452 7452          ohci_start_timer(ohcip);
7453 7453          mutex_exit(&ohcip->ohci_int_mutex);
7454 7454  }
7455 7455  
7456 7456  
7457 7457  /*
7458 7458   * ohci_remove_tw_from_timeout_list:
7459 7459   *
7460 7460   * Remove Control or bulk transfer from the timeout list.
7461 7461   */
7462 7462  static void
7463 7463  ohci_remove_tw_from_timeout_list(
7464 7464          ohci_state_t            *ohcip,
7465 7465          ohci_trans_wrapper_t    *tw)
7466 7466  {
7467 7467          ohci_trans_wrapper_t    *prev, *next;
7468 7468  
7469 7469          USB_DPRINTF_L3(PRINT_MASK_LISTS,  ohcip->ohci_log_hdl,
7470 7470              "ohci_remove_tw_from_timeout_list: tw = 0x%p", (void *)tw);
7471 7471  
7472 7472          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7473 7473  
7474 7474          if (ohcip->ohci_timeout_list == tw) {
7475 7475                  ohcip->ohci_timeout_list = tw->tw_timeout_next;
7476 7476          } else {
7477 7477                  prev = ohcip->ohci_timeout_list;
7478 7478                  next = prev->tw_timeout_next;
7479 7479  
7480 7480                  while (next && (next != tw)) {
7481 7481                          prev = next;
7482 7482                          next = next->tw_timeout_next;
7483 7483                  }
7484 7484  
7485 7485                  if (next == tw) {
7486 7486                          prev->tw_timeout_next = next->tw_timeout_next;
7487 7487                  }
7488 7488          }
7489 7489  
7490 7490          /* Reset the xfer timeout */
7491 7491          tw->tw_timeout_next = NULL;
7492 7492  }
7493 7493  
7494 7494  
7495 7495  /*
7496 7496   * ohci_start_timer:
7497 7497   *
7498 7498   * Start the ohci timer
7499 7499   */
7500 7500  static void
7501 7501  ohci_start_timer(ohci_state_t   *ohcip)
7502 7502  {
7503 7503          USB_DPRINTF_L3(PRINT_MASK_LISTS,  ohcip->ohci_log_hdl,
7504 7504              "ohci_start_timer: ohcip = 0x%p", (void *)ohcip);
7505 7505  
7506 7506          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7507 7507  
7508 7508          /*
7509 7509           * Start the global timer only if currently timer is not
7510 7510           * running and if there are any transfers on the timeout
7511 7511           * list. This timer will be per USB Host Controller.
7512 7512           */
7513 7513          if ((!ohcip->ohci_timer_id) && (ohcip->ohci_timeout_list)) {
7514 7514                  ohcip->ohci_timer_id = timeout(ohci_xfer_timeout_handler,
7515 7515                      (void *)ohcip, drv_usectohz(1000000));
7516 7516          }
7517 7517  }
7518 7518  
7519 7519  
7520 7520  /*
7521 7521   * ohci_deallocate_tw_resources:
7522 7522   * NOTE: This function is also called from POLLED MODE.
7523 7523   *
7524 7524   * Deallocate of a Transaction Wrapper (TW) and this involves the freeing of
7525 7525   * of DMA resources.
7526 7526   */
7527 7527  void
7528 7528  ohci_deallocate_tw_resources(
7529 7529          ohci_state_t            *ohcip,
7530 7530          ohci_pipe_private_t     *pp,
7531 7531          ohci_trans_wrapper_t    *tw)
7532 7532  {
7533 7533          ohci_trans_wrapper_t    *prev, *next;
7534 7534  
7535 7535          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7536 7536              "ohci_deallocate_tw_resources: tw = 0x%p", (void *)tw);
7537 7537  
7538 7538          /*
7539 7539           * If the transfer wrapper has no Host Controller (HC)
7540 7540           * Transfer Descriptors (TD) associated with it,  then
7541 7541           * remove the transfer wrapper.
7542 7542           */
7543 7543          if (tw->tw_hctd_head) {
7544 7544                  ASSERT(tw->tw_hctd_tail != NULL);
7545 7545  
7546 7546                  return;
7547 7547          }
7548 7548  
7549 7549          ASSERT(tw->tw_hctd_tail == NULL);
7550 7550  
7551 7551          /* Make sure we return all the unused td's to the pool as well */
7552 7552          ohci_free_tw_tds_resources(ohcip, tw);
7553 7553  
7554 7554          /*
7555 7555           * If pp->pp_tw_head and pp->pp_tw_tail are pointing to
7556 7556           * given TW then set the head and  tail  equal to NULL.
7557 7557           * Otherwise search for this TW in the linked TW's list
7558 7558           * and then remove this TW from the list.
7559 7559           */
7560 7560          if (pp->pp_tw_head == tw) {
7561 7561                  if (pp->pp_tw_tail == tw) {
7562 7562                          pp->pp_tw_head = NULL;
7563 7563                          pp->pp_tw_tail = NULL;
7564 7564                  } else {
7565 7565                          pp->pp_tw_head = tw->tw_next;
7566 7566                  }
7567 7567          } else {
7568 7568                  prev = pp->pp_tw_head;
7569 7569                  next = prev->tw_next;
7570 7570  
7571 7571                  while (next && (next != tw)) {
7572 7572                          prev = next;
7573 7573                          next = next->tw_next;
7574 7574                  }
7575 7575  
7576 7576                  if (next == tw) {
7577 7577                          prev->tw_next = next->tw_next;
7578 7578  
7579 7579                          if (pp->pp_tw_tail == tw) {
7580 7580                                  pp->pp_tw_tail = prev;
7581 7581                          }
7582 7582                  }
7583 7583          }
7584 7584  
7585 7585          ohci_free_tw(ohcip, tw);
7586 7586  }
7587 7587  
7588 7588  
7589 7589  /*
7590 7590   * ohci_free_dma_resources:
7591 7591   *
7592 7592   * Free dma resources of a Transfer Wrapper (TW) and also free the TW.
7593 7593   */
7594 7594  static void
7595 7595  ohci_free_dma_resources(
7596 7596          ohci_state_t            *ohcip,
7597 7597          usba_pipe_handle_data_t *ph)
7598 7598  {
7599 7599          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
7600 7600          ohci_trans_wrapper_t    *head_tw = pp->pp_tw_head;
7601 7601          ohci_trans_wrapper_t    *next_tw, *tw;
7602 7602  
7603 7603          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7604 7604              "ohci_free_dma_resources: ph = 0x%p", (void *)ph);
7605 7605  
7606 7606          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7607 7607  
7608 7608          /* Process the Transfer Wrappers */
7609 7609          next_tw = head_tw;
7610 7610          while (next_tw) {
7611 7611                  tw = next_tw;
7612 7612                  next_tw = tw->tw_next;
7613 7613  
7614 7614                  USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7615 7615                      "ohci_free_dma_resources: Free TW = 0x%p", (void *)tw);
7616 7616  
7617 7617                  ohci_free_tw(ohcip, tw);
7618 7618          }
7619 7619  
7620 7620          /* Adjust the head and tail pointers */
7621 7621          pp->pp_tw_head = NULL;
7622 7622          pp->pp_tw_tail = NULL;
7623 7623  }
7624 7624  
7625 7625  
7626 7626  /*
7627 7627   * ohci_free_tw:
7628 7628   *
7629 7629   * Free the Transfer Wrapper (TW).
7630 7630   */
7631 7631  static void
7632 7632  ohci_free_tw(
7633 7633          ohci_state_t            *ohcip,
7634 7634          ohci_trans_wrapper_t    *tw)
7635 7635  {
7636 7636          int                     rval, i;
7637 7637  
7638 7638          USB_DPRINTF_L4(PRINT_MASK_ALLOC, ohcip->ohci_log_hdl,
7639 7639              "ohci_free_tw: tw = 0x%p", (void *)tw);
7640 7640  
7641 7641          ASSERT(tw != NULL);
7642 7642          ASSERT(tw->tw_id != NULL);
7643 7643  
7644 7644          /* Free 32bit ID */
7645 7645          OHCI_FREE_ID((uint32_t)tw->tw_id);
7646 7646  
7647 7647          if (tw->tw_isoc_strtlen > 0) {
7648 7648                  ASSERT(tw->tw_isoc_bufs != NULL);
7649 7649                  for (i = 0; i < tw->tw_ncookies; i++) {
7650 7650                          if (tw->tw_isoc_bufs[i].ncookies > 0) {
7651 7651                                  rval = ddi_dma_unbind_handle(
7652 7652                                      tw->tw_isoc_bufs[i].dma_handle);
7653 7653                                  ASSERT(rval == USB_SUCCESS);
7654 7654                          }
7655 7655                          ddi_dma_mem_free(&tw->tw_isoc_bufs[i].mem_handle);
7656 7656                          ddi_dma_free_handle(&tw->tw_isoc_bufs[i].dma_handle);
7657 7657                  }
7658 7658                  kmem_free(tw->tw_isoc_bufs, tw->tw_isoc_strtlen);
7659 7659          } else if (tw->tw_dmahandle != NULL) {
7660 7660                  if (tw->tw_ncookies > 0) {
7661 7661                          rval = ddi_dma_unbind_handle(tw->tw_dmahandle);
7662 7662                          ASSERT(rval == DDI_SUCCESS);
7663 7663                  }
7664 7664                  ddi_dma_mem_free(&tw->tw_accesshandle);
7665 7665                  ddi_dma_free_handle(&tw->tw_dmahandle);
7666 7666          }
7667 7667  
7668 7668          /* Free transfer wrapper */
7669 7669          kmem_free(tw, sizeof (ohci_trans_wrapper_t));
7670 7670  }
7671 7671  
7672 7672  
7673 7673  /*
7674 7674   * Interrupt Handling functions
7675 7675   */
7676 7676  
7677 7677  /*
7678 7678   * ohci_intr:
7679 7679   *
7680 7680   * OpenHCI (OHCI) interrupt handling routine.
7681 7681   */
7682 7682  static uint_t
7683 7683  ohci_intr(caddr_t arg1, caddr_t arg2)
7684 7684  {
7685 7685          ohci_state_t            *ohcip = (ohci_state_t *)arg1;
7686 7686          uint_t                  intr;
7687 7687          ohci_td_t               *done_head = NULL;
7688 7688          ohci_save_intr_sts_t    *ohci_intr_sts = &ohcip->ohci_save_intr_sts;
7689 7689  
7690 7690          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7691 7691              "ohci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p",
7692 7692              (void *)arg1, (void *)arg2);
7693 7693  
7694 7694          mutex_enter(&ohcip->ohci_int_mutex);
7695 7695  
7696 7696          /* Any interrupt is not handled for the suspended device. */
7697 7697          if (ohcip->ohci_hc_soft_state == OHCI_CTLR_SUSPEND_STATE) {
7698 7698                  mutex_exit(&ohcip->ohci_int_mutex);
7699 7699  
7700 7700                  return (DDI_INTR_UNCLAIMED);
7701 7701          }
7702 7702  
7703 7703          /*
7704 7704           * Suppose if we switched to the polled mode from the normal
7705 7705           * mode when interrupt handler is executing then we  need to
7706 7706           * save the interrupt status information in the  polled mode
7707 7707           * to  avoid race conditions. The following flag will be set
7708 7708           * and reset on entering & exiting of ohci interrupt handler
7709 7709           * respectively.  This flag will be used in the  polled mode
7710 7710           * to check whether the interrupt handler was running when we
7711 7711           * switched to the polled mode from the normal mode.
7712 7712           */
7713 7713          ohci_intr_sts->ohci_intr_flag = OHCI_INTR_HANDLING;
7714 7714  
7715 7715          /* Temporarily turn off interrupts */
7716 7716          Set_OpReg(hcr_intr_disable, HCR_INTR_MIE);
7717 7717  
7718 7718          /*
7719 7719           * Handle any missed ohci interrupt especially WriteDoneHead
7720 7720           * and SOF interrupts because of previous polled mode switch.
7721 7721           */
7722 7722          ohci_handle_missed_intr(ohcip);
7723 7723  
7724 7724          /*
7725 7725           * Now process the actual ohci interrupt events  that caused
7726 7726           * invocation of this ohci interrupt handler.
7727 7727           */
7728 7728  
7729 7729          /*
7730 7730           * Updating the WriteDoneHead interrupt:
7731 7731           *
7732 7732           * (a) Host Controller
7733 7733           *
7734 7734           *      - First Host controller (HC) checks  whether WDH bit
7735 7735           *        in the interrupt status register is cleared.
7736 7736           *
7737 7737           *      - If WDH bit is cleared then HC writes new done head
7738 7738           *        list information into the HCCA done head field.
7739 7739           *
7740 7740           *      - Set WDH bit in the interrupt status register.
7741 7741           *
7742 7742           * (b) Host Controller Driver (HCD)
7743 7743           *
7744 7744           *      - First read the interrupt status register. The HCCA
7745 7745           *        done head and WDH bit may be set or may not be set
7746 7746           *        while reading the interrupt status register.
7747 7747           *
7748 7748           *      - Read the  HCCA done head list. By this time may be
7749 7749           *        HC has updated HCCA done head and  WDH bit in ohci
7750 7750           *        interrupt status register.
7751 7751           *
7752 7752           *      - If done head is non-null and if WDH bit is not set
7753 7753           *        then Host Controller has updated HCCA  done head &
7754 7754           *        WDH bit in the interrupt stats register in between
7755 7755           *        reading the interrupt status register & HCCA  done
7756 7756           *        head. In that case, definitely WDH bit will be set
7757 7757           *        in the interrupt status register & driver can take
7758 7758           *        it for granted.
7759 7759           *
7760 7760           * Now read the Interrupt Status & Interrupt enable register
7761 7761           * to determine the exact interrupt events.
7762 7762           */
7763 7763          intr = ohci_intr_sts->ohci_curr_intr_sts =
7764 7764              (Get_OpReg(hcr_intr_status) & Get_OpReg(hcr_intr_enable));
7765 7765  
7766 7766          if (ohcip->ohci_hccap) {
7767 7767                  /* Sync HCCA area */
7768 7768                  Sync_HCCA(ohcip);
7769 7769  
7770 7770                  /* Read and Save the HCCA DoneHead value */
7771 7771                  done_head = ohci_intr_sts->ohci_curr_done_lst =
7772 7772                      (ohci_td_t *)(uintptr_t)
7773 7773                      (Get_HCCA(ohcip->ohci_hccap->HccaDoneHead) &
7774 7774                      HCCA_DONE_HEAD_MASK);
7775 7775  
7776 7776                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7777 7777                      "ohci_intr: Done head! 0x%p", (void *)done_head);
7778 7778          }
7779 7779  
7780 7780          /* Update kstat values */
7781 7781          ohci_do_intrs_stats(ohcip, intr);
7782 7782  
7783 7783          /*
7784 7784           * Look at the HccaDoneHead, if it is a non-zero valid address,
7785 7785           * a done list update interrupt is indicated. Otherwise, this
7786 7786           * intr bit is cleared.
7787 7787           */
7788 7788          if (ohci_check_done_head(ohcip, done_head) == USB_SUCCESS) {
7789 7789  
7790 7790                  /* Set the WriteDoneHead bit in the interrupt events */
7791 7791                  intr |= HCR_INTR_WDH;
7792 7792          } else {
7793 7793  
7794 7794                  /* Clear the WriteDoneHead bit */
7795 7795                  intr &= ~HCR_INTR_WDH;
7796 7796          }
7797 7797  
7798 7798          /*
7799 7799           * We could have gotten a spurious interrupts. If so, do not
7800 7800           * claim it.  This is quite  possible on some  architectures
7801 7801           * where more than one PCI slots share the IRQs.  If so, the
7802 7802           * associated driver's interrupt routine may get called even
7803 7803           * if the interrupt is not meant for them.
7804 7804           *
7805 7805           * By unclaiming the interrupt, the other driver gets chance
7806 7806           * to service its interrupt.
7807 7807           */
7808 7808          if (!intr) {
7809 7809  
7810 7810                  /* Reset the interrupt handler flag */
7811 7811                  ohci_intr_sts->ohci_intr_flag &= ~OHCI_INTR_HANDLING;
7812 7812  
7813 7813                  Set_OpReg(hcr_intr_enable, HCR_INTR_MIE);
7814 7814                  mutex_exit(&ohcip->ohci_int_mutex);
7815 7815                  return (DDI_INTR_UNCLAIMED);
7816 7816          }
7817 7817  
7818 7818          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7819 7819              "Interrupt status 0x%x", intr);
7820 7820  
7821 7821          /*
7822 7822           * Check for Frame Number Overflow.
7823 7823           */
7824 7824          if (intr & HCR_INTR_FNO) {
7825 7825                  USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7826 7826                      "ohci_intr: Frame Number Overflow");
7827 7827  
7828 7828                  ohci_handle_frame_number_overflow(ohcip);
7829 7829          }
7830 7830  
7831 7831          if (intr & HCR_INTR_SOF) {
7832 7832                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7833 7833                      "ohci_intr: Start of Frame");
7834 7834  
7835 7835                  /* Set ohci_sof_flag indicating SOF interrupt occurred */
7836 7836                  ohcip->ohci_sof_flag = B_TRUE;
7837 7837  
7838 7838                  /* Disabel SOF interrupt */
7839 7839                  Set_OpReg(hcr_intr_disable, HCR_INTR_SOF);
7840 7840  
7841 7841                  /*
7842 7842                   * Call cv_broadcast on every SOF interrupt to wakeup
7843 7843                   * all the threads that are waiting the SOF.  Calling
7844 7844                   * cv_broadcast on every SOF has no effect even if no
7845 7845                   * threads are waiting for the SOF.
7846 7846                   */
7847 7847                  cv_broadcast(&ohcip->ohci_SOF_cv);
7848 7848          }
7849 7849  
7850 7850          if (intr & HCR_INTR_SO) {
7851 7851                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7852 7852                      "ohci_intr: Schedule overrun");
7853 7853  
7854 7854                  ohcip->ohci_so_error++;
7855 7855          }
7856 7856  
7857 7857          if ((intr & HCR_INTR_WDH) && (done_head)) {
7858 7858                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7859 7859                      "ohci_intr: Done Head");
7860 7860  
7861 7861                  /*
7862 7862                   * Currently if we are processing one  WriteDoneHead
7863 7863                   * interrupt  and also if we  switched to the polled
7864 7864                   * mode at least once  during this time,  then there
7865 7865                   * may be chance that  Host Controller generates one
7866 7866                   * more Write DoneHead or Start of Frame  interrupts
7867 7867                   * for the normal since the polled code clears WDH &
7868 7868                   * SOF interrupt bits before returning to the normal
7869 7869                   * mode. Under this condition, we must not clear the
7870 7870                   * HCCA done head field & also we must not clear WDH
7871 7871                   * interrupt bit in the interrupt  status register.
7872 7872                   */
7873 7873                  if (done_head == (ohci_td_t *)(uintptr_t)
7874 7874                      (Get_HCCA(ohcip->ohci_hccap->HccaDoneHead) &
7875 7875                      HCCA_DONE_HEAD_MASK)) {
7876 7876  
7877 7877                          /* Reset the done head to NULL */
7878 7878                          Set_HCCA(ohcip->ohci_hccap->HccaDoneHead, NULL);
7879 7879                  } else {
7880 7880                          intr &= ~HCR_INTR_WDH;
7881 7881                  }
7882 7882  
7883 7883                  /* Clear the current done head field */
7884 7884                  ohci_intr_sts->ohci_curr_done_lst = NULL;
7885 7885  
7886 7886                  ohci_traverse_done_list(ohcip, done_head);
7887 7887          }
7888 7888  
7889 7889          /* Process endpoint reclaimation list */
7890 7890          if (ohcip->ohci_reclaim_list) {
7891 7891                  ohci_handle_endpoint_reclaimation(ohcip);
7892 7892          }
7893 7893  
7894 7894          if (intr & HCR_INTR_RD) {
7895 7895                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7896 7896                      "ohci_intr: Resume Detected");
7897 7897          }
7898 7898  
7899 7899          if (intr & HCR_INTR_RHSC) {
7900 7900                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7901 7901                      "ohci_intr: Root hub status change");
7902 7902          }
7903 7903  
7904 7904          if (intr & HCR_INTR_OC) {
7905 7905                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7906 7906                      "ohci_intr: Change ownership");
7907 7907  
7908 7908          }
7909 7909  
7910 7910          if (intr & HCR_INTR_UE) {
7911 7911                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7912 7912                      "ohci_intr: Unrecoverable error");
7913 7913  
7914 7914                  ohci_handle_ue(ohcip);
7915 7915          }
7916 7916  
7917 7917          /* Acknowledge the interrupt */
7918 7918          Set_OpReg(hcr_intr_status, intr);
7919 7919  
7920 7920          /* Clear the current interrupt event field */
7921 7921          ohci_intr_sts->ohci_curr_intr_sts = 0;
7922 7922  
7923 7923          /*
7924 7924           * Reset the following flag indicating exiting the interrupt
7925 7925           * handler and this flag will be used in the polled  mode to
7926 7926           * do some extra processing.
7927 7927           */
7928 7928          ohci_intr_sts->ohci_intr_flag &= ~OHCI_INTR_HANDLING;
7929 7929  
7930 7930          Set_OpReg(hcr_intr_enable, HCR_INTR_MIE);
7931 7931  
7932 7932          /*
7933 7933           * Read interrupt status register to make sure that any PIO
7934 7934           * store to clear the ISR has made it on the PCI bus before
7935 7935           * returning from its interrupt handler.
7936 7936           */
7937 7937          (void) Get_OpReg(hcr_intr_status);
7938 7938  
7939 7939          mutex_exit(&ohcip->ohci_int_mutex);
7940 7940  
7941 7941          USB_DPRINTF_L3(PRINT_MASK_INTR,  ohcip->ohci_log_hdl,
7942 7942              "Interrupt handling completed");
7943 7943  
7944 7944          return (DDI_INTR_CLAIMED);
7945 7945  }
7946 7946  
7947 7947  /*
7948 7948   * Check whether done_head is a valid td point address.
7949 7949   * It should be non-zero, 16-byte aligned, and fall in ohci_td_pool.
7950 7950   */
7951 7951  static int
7952 7952  ohci_check_done_head(ohci_state_t *ohcip, ohci_td_t *done_head)
7953 7953  {
7954 7954          uintptr_t lower, upper, headp;
7955 7955          lower = ohcip->ohci_td_pool_cookie.dmac_address;
7956 7956          upper = lower + ohcip->ohci_td_pool_cookie.dmac_size;
7957 7957          headp = (uintptr_t)done_head;
7958 7958  
7959 7959          if (headp && !(headp & ~HCCA_DONE_HEAD_MASK) &&
7960 7960              (headp >= lower) && (headp < upper)) {
7961 7961  
7962 7962                  return (USB_SUCCESS);
7963 7963          } else {
7964 7964  
7965 7965                  return (USB_FAILURE);
7966 7966          }
7967 7967  }
7968 7968  
7969 7969  /*
7970 7970   * ohci_handle_missed_intr:
7971 7971   *
7972 7972   * Handle any ohci missed interrupts because of polled mode switch.
7973 7973   */
7974 7974  static void
7975 7975  ohci_handle_missed_intr(ohci_state_t    *ohcip)
7976 7976  {
7977 7977          ohci_save_intr_sts_t            *ohci_intr_sts =
7978 7978              &ohcip->ohci_save_intr_sts;
7979 7979          ohci_td_t                       *done_head;
7980 7980          uint_t                          intr;
7981 7981  
7982 7982          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
7983 7983  
7984 7984          /*
7985 7985           * Check whether we have  missed any ohci interrupts because
7986 7986           * of the polled mode switch during  previous ohci interrupt
7987 7987           * handler execution. Only  Write Done Head & SOF interrupts
7988 7988           * saved in the polled mode. First process  these interrupts
7989 7989           * before processing actual interrupts that caused invocation
7990 7990           * of ohci interrupt handler.
7991 7991           */
7992 7992          if (!ohci_intr_sts->ohci_missed_intr_sts) {
7993 7993                  /* No interrupts are missed, simply return */
7994 7994  
7995 7995                  return;
7996 7996          }
7997 7997  
7998 7998          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
7999 7999              "ohci_handle_missed_intr: Handle ohci missed interrupts");
8000 8000  
8001 8001          /*
8002 8002           * The functionality and importance of critical code section
8003 8003           * in the normal mode ohci  interrupt handler & its usage in
8004 8004           * the polled mode is explained below.
8005 8005           *
8006 8006           * (a) Normal mode:
8007 8007           *
8008 8008           *      - Set the flag  indicating that  processing critical
8009 8009           *        code in ohci interrupt handler.
8010 8010           *
8011 8011           *      - Process the missed ohci interrupts by  copying the
8012 8012           *        miised interrupt events and done  head list fields
8013 8013           *        information to the critical interrupt event & done
8014 8014           *        list fields.
8015 8015           *
8016 8016           *      - Reset the missed ohci interrupt events & done head
8017 8017           *        list fields so that the new missed interrupt event
8018 8018           *        and done head list information can be saved.
8019 8019           *
8020 8020           *      - All above steps will be executed  with in critical
8021 8021           *        section of the  interrupt handler.Then ohci missed
8022 8022           *        interrupt handler will be called to service missed
8023 8023           *        ohci interrupts.
8024 8024           *
8025 8025           * (b) Polled mode:
8026 8026           *
8027 8027           *      - On entering the polled code,it checks for critical
8028 8028           *        section code execution within the normal mode ohci
8029 8029           *        interrupt handler.
8030 8030           *
8031 8031           *      - If the critical section code is executing in normal
8032 8032           *        mode ohci interrupt handler and if copying of ohci
8033 8033           *        missed interrupt events & done head list fields to
8034 8034           *        the critical fields is finished then save the "any
8035 8035           *        missed interrupt events & done head list"  because
8036 8036           *        of current polled mode switch into "critical missed
8037 8037           *        interrupt events & done list fields" instead actual
8038 8038           *        missed events and done list fields.
8039 8039           *
8040 8040           *      - Otherwise save "any missed interrupt events & done
8041 8041           *        list" because of this  current polled  mode switch
8042 8042           *        in the actual missed  interrupt events & done head
8043 8043           *        list fields.
8044 8044           */
8045 8045  
8046 8046          /*
8047 8047           * Set flag indicating that  interrupt handler is processing
8048 8048           * critical interrupt code,  so that polled mode code checks
8049 8049           * for this condition & will do extra processing as explained
8050 8050           * above in order to aviod the race conditions.
8051 8051           */
8052 8052          ohci_intr_sts->ohci_intr_flag |= OHCI_INTR_CRITICAL;
8053 8053          ohci_intr_sts->ohci_critical_intr_sts |=
8054 8054              ohci_intr_sts->ohci_missed_intr_sts;
8055 8055  
8056 8056          if (ohci_intr_sts->ohci_missed_done_lst) {
8057 8057  
8058 8058                  ohci_intr_sts->ohci_critical_done_lst =
8059 8059                      ohci_intr_sts->ohci_missed_done_lst;
8060 8060          }
8061 8061  
8062 8062          ohci_intr_sts->ohci_missed_intr_sts = 0;
8063 8063          ohci_intr_sts->ohci_missed_done_lst = NULL;
8064 8064          ohci_intr_sts->ohci_intr_flag &= ~OHCI_INTR_CRITICAL;
8065 8065  
8066 8066          intr = ohci_intr_sts->ohci_critical_intr_sts;
8067 8067          done_head = ohci_intr_sts->ohci_critical_done_lst;
8068 8068  
8069 8069          if (intr & HCR_INTR_SOF) {
8070 8070                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8071 8071                      "ohci_handle_missed_intr: Start of Frame");
8072 8072  
8073 8073                  /*
8074 8074                   * Call cv_broadcast on every SOF interrupt to wakeup
8075 8075                   * all the threads that are waiting the SOF.  Calling
8076 8076                   * cv_broadcast on every SOF has no effect even if no
8077 8077                   * threads are waiting for the SOF.
8078 8078                   */
8079 8079                  cv_broadcast(&ohcip->ohci_SOF_cv);
8080 8080          }
8081 8081  
8082 8082          if ((intr & HCR_INTR_WDH) && (done_head)) {
8083 8083                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8084 8084                      "ohci_handle_missed_intr: Done Head");
8085 8085  
8086 8086                  /* Clear the critical done head field */
8087 8087                  ohci_intr_sts->ohci_critical_done_lst = NULL;
8088 8088  
8089 8089                  ohci_traverse_done_list(ohcip, done_head);
8090 8090          }
8091 8091  
8092 8092          /* Clear the critical interrupt event field */
8093 8093          ohci_intr_sts->ohci_critical_intr_sts = 0;
8094 8094  }
8095 8095  
8096 8096  
8097 8097  /*
8098 8098   * ohci_handle_ue:
8099 8099   *
8100 8100   * Handling of Unrecoverable Error interrupt (UE).
8101 8101   */
8102 8102  static void
8103 8103  ohci_handle_ue(ohci_state_t     *ohcip)
8104 8104  {
8105 8105          usb_frame_number_t      before_frame_number, after_frame_number;
8106 8106  
8107 8107          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8108 8108  
8109 8109          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8110 8110              "ohci_handle_ue: Handling of UE interrupt");
8111 8111  
8112 8112          /*
8113 8113           * First check whether current UE error occured due to USB or
8114 8114           * due to some other subsystem. This can be verified by reading
8115 8115           * usb frame numbers before & after a delay of few milliseconds.
8116 8116           * If usb frame number read after delay is greater than the one
8117 8117           * read before delay, then, USB subsystem is fine. In this case,
8118 8118           * disable UE error interrupt and return without shutdowning the
8119 8119           * USB subsystem.
8120 8120           *
8121 8121           * Otherwise, if usb frame number read after delay is less than
8122 8122           * or equal to one read before the delay, then, current UE error
8123 8123           * occured from USB susbsystem. In this case,go ahead with actual
8124 8124           * UE error recovery procedure.
8125 8125           *
8126 8126           * Get the current usb frame number before waiting for few
8127 8127           * milliseconds.
8128 8128           */
8129 8129          before_frame_number = ohci_get_current_frame_number(ohcip);
8130 8130  
8131 8131          /* Wait for few milliseconds */
8132 8132          drv_usecwait(OHCI_TIMEWAIT);
8133 8133  
8134 8134          /*
8135 8135           * Get the current usb frame number after waiting for
8136 8136           * milliseconds.
8137 8137           */
8138 8138          after_frame_number = ohci_get_current_frame_number(ohcip);
8139 8139  
8140 8140          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8141 8141              "ohci_handle_ue: Before Frm No 0x%llx After Frm No 0x%llx",
8142 8142              (unsigned long long)before_frame_number,
8143 8143              (unsigned long long)after_frame_number);
8144 8144  
8145 8145          if (after_frame_number > before_frame_number) {
8146 8146  
8147 8147                  /* Disable UE interrupt */
8148 8148                  Set_OpReg(hcr_intr_disable, HCR_INTR_UE);
8149 8149  
8150 8150                  return;
8151 8151          }
8152 8152  
8153 8153          /*
8154 8154           * This UE is due to USB hardware error. Reset ohci controller
8155 8155           * and reprogram to bring it back to functional state.
8156 8156           */
8157 8157          if ((ohci_do_soft_reset(ohcip)) != USB_SUCCESS) {
8158 8158                  USB_DPRINTF_L0(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8159 8159                      "Unrecoverable USB Hardware Error");
8160 8160  
8161 8161                  /* Disable UE interrupt */
8162 8162                  Set_OpReg(hcr_intr_disable, HCR_INTR_UE);
8163 8163  
8164 8164                  /* Set host controller soft state to error */
8165 8165                  ohcip->ohci_hc_soft_state = OHCI_CTLR_ERROR_STATE;
8166 8166          }
8167 8167  }
8168 8168  
8169 8169  
8170 8170  /*
8171 8171   * ohci_handle_frame_number_overflow:
8172 8172   *
8173 8173   * Update software based usb frame number part on every frame number
8174 8174   * overflow interrupt.
8175 8175   *
8176 8176   * NOTE: This function is also called from POLLED MODE.
8177 8177   *
8178 8178   * Refer ohci spec 1.0a, section 5.3, page 81 for more details.
8179 8179   */
8180 8180  void
8181 8181  ohci_handle_frame_number_overflow(ohci_state_t *ohcip)
8182 8182  {
8183 8183          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8184 8184              "ohci_handle_frame_number_overflow:");
8185 8185  
8186 8186          ohcip->ohci_fno += (0x10000 -
8187 8187              (((Get_HCCA(ohcip->ohci_hccap->HccaFrameNo) &
8188 8188              0xFFFF) ^ ohcip->ohci_fno) & 0x8000));
8189 8189  
8190 8190          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8191 8191              "ohci_handle_frame_number_overflow:"
8192 8192              "Frame Number Higher Part 0x%llx\n",
8193 8193              (unsigned long long)(ohcip->ohci_fno));
8194 8194  }
8195 8195  
8196 8196  
8197 8197  /*
8198 8198   * ohci_handle_endpoint_reclaimation:
8199 8199   *
8200 8200   * Reclamation of Host Controller (HC) Endpoint Descriptors (ED).
8201 8201   */
8202 8202  static void
8203 8203  ohci_handle_endpoint_reclaimation(ohci_state_t  *ohcip)
8204 8204  {
8205 8205          usb_frame_number_t      current_frame_number;
8206 8206          usb_frame_number_t      endpoint_frame_number;
8207 8207          ohci_ed_t               *reclaim_ed;
8208 8208  
8209 8209          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8210 8210              "ohci_handle_endpoint_reclaimation:");
8211 8211  
8212 8212          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8213 8213  
8214 8214          current_frame_number = ohci_get_current_frame_number(ohcip);
8215 8215  
8216 8216          /*
8217 8217           * Deallocate all Endpoint Descriptors (ED) which are on the
8218 8218           * reclaimation list. These ED's are already removed from the
8219 8219           * interrupt lattice tree.
8220 8220           */
8221 8221          while (ohcip->ohci_reclaim_list) {
8222 8222                  reclaim_ed = ohcip->ohci_reclaim_list;
8223 8223  
8224 8224                  endpoint_frame_number = (usb_frame_number_t)(uintptr_t)
8225 8225                      (OHCI_LOOKUP_ID(Get_ED(reclaim_ed->hced_reclaim_frame)));
8226 8226  
8227 8227                  USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8228 8228                      "ohci_handle_endpoint_reclaimation:"
8229 8229                      "current frame number 0x%llx endpoint frame number 0x%llx",
8230 8230                      (unsigned long long)current_frame_number,
8231 8231                      (unsigned long long)endpoint_frame_number);
8232 8232  
8233 8233                  /*
8234 8234                   * Deallocate current endpoint only if endpoint's usb frame
8235 8235                   * number is less than or equal to current usb frame number.
8236 8236                   *
8237 8237                   * If endpoint's usb frame number is greater than the current
8238 8238                   * usb frame number, ignore rest of the endpoints in the list
8239 8239                   * since rest of the endpoints are inserted into the reclaim
8240 8240                   * list later than the current reclaim endpoint.
8241 8241                   */
8242 8242                  if (endpoint_frame_number > current_frame_number) {
8243 8243                          break;
8244 8244                  }
8245 8245  
8246 8246                  /* Get the next endpoint from the rec. list */
8247 8247                  ohcip->ohci_reclaim_list = ohci_ed_iommu_to_cpu(ohcip,
8248 8248                      Get_ED(reclaim_ed->hced_reclaim_next));
8249 8249  
8250 8250                  /* Free 32bit ID */
8251 8251                  OHCI_FREE_ID((uint32_t)Get_ED(reclaim_ed->hced_reclaim_frame));
8252 8252  
8253 8253                  /* Deallocate the endpoint */
8254 8254                  ohci_deallocate_ed(ohcip, reclaim_ed);
8255 8255          }
8256 8256  }
8257 8257  
8258 8258  
8259 8259  /*
8260 8260   * ohci_traverse_done_list:
8261 8261   */
8262 8262  static void
8263 8263  ohci_traverse_done_list(
8264 8264          ohci_state_t            *ohcip,
8265 8265          ohci_td_t               *head_done_list)
8266 8266  {
8267 8267          uint_t                  state;          /* TD state */
8268 8268          ohci_td_t               *td, *old_td;   /* TD pointers */
8269 8269          usb_cr_t                error;          /* Error from TD */
8270 8270          ohci_trans_wrapper_t    *tw = NULL;     /* Transfer wrapper */
8271 8271          ohci_pipe_private_t     *pp = NULL;     /* Pipe private field */
8272 8272  
8273 8273          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8274 8274              "ohci_traverse_done_list:");
8275 8275  
8276 8276          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8277 8277  
8278 8278          /* Sync ED and TD pool */
8279 8279          Sync_ED_TD_Pool(ohcip);
8280 8280  
8281 8281          /* Reverse the done list */
8282 8282          td = ohci_reverse_done_list(ohcip, head_done_list);
8283 8283  
8284 8284          /* Traverse the list of transfer descriptors */
8285 8285          while (td) {
8286 8286                  /* Check for TD state */
8287 8287                  state = Get_TD(td->hctd_state);
8288 8288  
8289 8289                  USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8290 8290                      "ohci_traverse_done_list:\n\t"
8291 8291                      "td = 0x%p  state = 0x%x", (void *)td, state);
8292 8292  
8293 8293                  /*
8294 8294                   * Obtain the  transfer wrapper only  if the TD is
8295 8295                   * not marked as RECLAIM.
8296 8296                   *
8297 8297                   * A TD that is marked as  RECLAIM has had its DMA
8298 8298                   * mappings, ED, TD and pipe private structure are
8299 8299                   * ripped down. Just deallocate this TD.
8300 8300                   */
8301 8301                  if (state != HC_TD_RECLAIM) {
8302 8302  
8303 8303                          tw = (ohci_trans_wrapper_t *)OHCI_LOOKUP_ID(
8304 8304                              (uint32_t)Get_TD(td->hctd_trans_wrapper));
8305 8305  
8306 8306                          ASSERT(tw != NULL);
8307 8307  
8308 8308                          pp = tw->tw_pipe_private;
8309 8309  
8310 8310                          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8311 8311                              "ohci_traverse_done_list: PP = 0x%p TW = 0x%p",
8312 8312                              (void *)pp, (void *)tw);
8313 8313                  }
8314 8314  
8315 8315                  /*
8316 8316                   * Don't process the TD if its  state is marked as
8317 8317                   * either RECLAIM or TIMEOUT.
8318 8318                   *
8319 8319                   * A TD that is marked as TIMEOUT has already been
8320 8320                   * processed by TD timeout handler & client driver
8321 8321                   * has been informed through exception callback.
8322 8322                   */
8323 8323                  if ((state != HC_TD_RECLAIM) && (state != HC_TD_TIMEOUT)) {
8324 8324  
8325 8325                          /* Look at the error status */
8326 8326                          error = ohci_parse_error(ohcip, td);
8327 8327  
8328 8328                          if (error == USB_CR_OK) {
8329 8329                                  ohci_handle_normal_td(ohcip, td, tw);
8330 8330                          } else {
8331 8331                                  /* handle the error condition */
8332 8332                                  ohci_handle_error(ohcip, td, error);
8333 8333                          }
8334 8334                  } else {
8335 8335                          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8336 8336                              "ohci_traverse_done_list: TD State = %d", state);
8337 8337                  }
8338 8338  
8339 8339                  /*
8340 8340                   * Save a pointer to the current transfer descriptor
8341 8341                   */
8342 8342                  old_td = td;
8343 8343  
8344 8344                  td = ohci_td_iommu_to_cpu(ohcip, Get_TD(td->hctd_next_td));
8345 8345  
8346 8346                  /* Deallocate this transfer descriptor */
8347 8347                  ohci_deallocate_td(ohcip, old_td);
8348 8348  
8349 8349                  /*
8350 8350                   * Deallocate the transfer wrapper if there are no more
8351 8351                   * TD's for the transfer wrapper. ohci_deallocate_tw_resources()
8352 8352                   * will  not deallocate the tw for a periodic  endpoint
8353 8353                   * since it will always have a TD attached to it.
8354 8354                   *
8355 8355                   * Do not deallocate the TW if it is a isoc or intr pipe in.
8356 8356                   * The tw's are reused.
8357 8357                   *
8358 8358                   * An TD that is marked as reclaim doesn't have a  pipe
8359 8359                   * or a TW associated with it anymore so don't call this
8360 8360                   * function.
8361 8361                   */
8362 8362                  if (state != HC_TD_RECLAIM) {
8363 8363                          ASSERT(tw != NULL);
8364 8364                          ohci_deallocate_tw_resources(ohcip, pp, tw);
8365 8365                  }
8366 8366          }
8367 8367  }
8368 8368  
8369 8369  
8370 8370  /*
8371 8371   * ohci_reverse_done_list:
8372 8372   *
8373 8373   * Reverse the order of the Transfer Descriptor (TD) Done List.
8374 8374   */
8375 8375  static ohci_td_t *
8376 8376  ohci_reverse_done_list(
8377 8377          ohci_state_t    *ohcip,
8378 8378          ohci_td_t       *head_done_list)
8379 8379  {
8380 8380          ohci_td_t       *cpu_new_tail, *cpu_new_head, *cpu_save;
8381 8381  
8382 8382          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8383 8383              "ohci_reverse_done_list:");
8384 8384  
8385 8385          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8386 8386          ASSERT(head_done_list != NULL);
8387 8387  
8388 8388          /* At first, both the tail and head pointers point to the same elem */
8389 8389          cpu_new_tail = cpu_new_head =
8390 8390              ohci_td_iommu_to_cpu(ohcip, (uintptr_t)head_done_list);
8391 8391  
8392 8392          /* See if the list has only one element */
8393 8393          if (Get_TD(cpu_new_head->hctd_next_td) == NULL) {
8394 8394  
8395 8395                  return (cpu_new_head);
8396 8396          }
8397 8397  
8398 8398          /* Advance the head pointer */
8399 8399          cpu_new_head = (ohci_td_t *)
8400 8400              ohci_td_iommu_to_cpu(ohcip, Get_TD(cpu_new_head->hctd_next_td));
8401 8401  
8402 8402          /* The new tail now points to nothing */
8403 8403          Set_TD(cpu_new_tail->hctd_next_td, NULL);
8404 8404  
8405 8405          cpu_save = (ohci_td_t *)
8406 8406              ohci_td_iommu_to_cpu(ohcip, Get_TD(cpu_new_head->hctd_next_td));
8407 8407  
8408 8408          /* Reverse the list and store the pointers as CPU addresses */
8409 8409          while (cpu_save) {
8410 8410                  Set_TD(cpu_new_head->hctd_next_td,
8411 8411                      ohci_td_cpu_to_iommu(ohcip, cpu_new_tail));
8412 8412  
8413 8413                  cpu_new_tail = cpu_new_head;
8414 8414                  cpu_new_head = cpu_save;
8415 8415  
8416 8416                  cpu_save = (ohci_td_t *)
8417 8417                      ohci_td_iommu_to_cpu(ohcip,
8418 8418                      Get_TD(cpu_new_head->hctd_next_td));
8419 8419          }
8420 8420  
8421 8421          Set_TD(cpu_new_head->hctd_next_td,
8422 8422              ohci_td_cpu_to_iommu(ohcip, cpu_new_tail));
8423 8423  
8424 8424          return (cpu_new_head);
8425 8425  }
8426 8426  
8427 8427  
8428 8428  /*
8429 8429   * ohci_parse_error:
8430 8430   *
8431 8431   * Parse the result for any errors.
8432 8432   */
8433 8433  static usb_cr_t
8434 8434  ohci_parse_error(
8435 8435          ohci_state_t            *ohcip,
8436 8436          ohci_td_t               *td)
8437 8437  {
8438 8438          uint_t                  ctrl;
8439 8439          usb_ep_descr_t          *eptd;
8440 8440          ohci_trans_wrapper_t    *tw;
8441 8441          ohci_pipe_private_t     *pp;
8442 8442          uint_t                  flag;
8443 8443          usb_cr_t                error;
8444 8444  
8445 8445          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8446 8446              "ohci_parse_error:");
8447 8447  
8448 8448          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8449 8449  
8450 8450          ASSERT(td != NULL);
8451 8451  
8452 8452          /* Obtain the transfer wrapper from the TD */
8453 8453          tw = (ohci_trans_wrapper_t *)
8454 8454              OHCI_LOOKUP_ID((uint32_t)Get_TD(td->hctd_trans_wrapper));
8455 8455  
8456 8456          ASSERT(tw != NULL);
8457 8457  
8458 8458          /* Obtain the pipe private structure */
8459 8459          pp = tw->tw_pipe_private;
8460 8460  
8461 8461          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8462 8462              "ohci_parse_error: PP 0x%p TW 0x%p", (void *)pp, (void *)tw);
8463 8463  
8464 8464          eptd = &pp->pp_pipe_handle->p_ep;
8465 8465  
8466 8466          ctrl = (uint_t)Get_TD(td->hctd_ctrl) & (uint32_t)HC_TD_CC;
8467 8467  
8468 8468          /*
8469 8469           * Check the condition code of completed TD and report errors
8470 8470           * if any. This checking will be done both for the general and
8471 8471           * the isochronous TDs.
8472 8472           */
8473 8473          if ((error = ohci_check_for_error(ohcip, pp, tw, td, ctrl)) !=
8474 8474              USB_CR_OK) {
8475 8475                  flag = OHCI_REMOVE_XFER_ALWAYS;
8476 8476          } else {
8477 8477                  flag  = OHCI_REMOVE_XFER_IFLAST;
8478 8478          }
8479 8479  
8480 8480          /* Stop the the transfer timer */
8481 8481          ohci_stop_xfer_timer(ohcip, tw, flag);
8482 8482  
8483 8483          /*
8484 8484           * The isochronous endpoint needs additional error checking
8485 8485           * and special processing.
8486 8486           */
8487 8487          if ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
8488 8488              USB_EP_ATTR_ISOCH) {
8489 8489  
8490 8490                  ohci_parse_isoc_error(ohcip, pp, tw, td);
8491 8491  
8492 8492                  /* always reset error */
8493 8493                  error = USB_CR_OK;
8494 8494          }
8495 8495  
8496 8496          return (error);
8497 8497  }
8498 8498  
8499 8499  
8500 8500  /*
8501 8501   * ohci_parse_isoc_error:
8502 8502   *
8503 8503   * Check for any errors in the isochronous data packets. Also fillup
8504 8504   * the status for each of the isochrnous data packets.
8505 8505   */
8506 8506  void
8507 8507  ohci_parse_isoc_error(
8508 8508          ohci_state_t            *ohcip,
8509 8509          ohci_pipe_private_t     *pp,
8510 8510          ohci_trans_wrapper_t    *tw,
8511 8511          ohci_td_t               *td)
8512 8512  {
8513 8513          usb_isoc_req_t          *isoc_reqp;
8514 8514          usb_isoc_pkt_descr_t    *isoc_pkt_descr;
8515 8515          uint_t                  toggle = 0, fc, ctrl, psw;
8516 8516          int                     i;
8517 8517  
8518 8518          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8519 8519              "ohci_parse_isoc_error: td 0x%p", (void *)td);
8520 8520  
8521 8521          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8522 8522  
8523 8523          fc = ((uint_t)Get_TD(td->hctd_ctrl) &
8524 8524              HC_ITD_FC) >> HC_ITD_FC_SHIFT;
8525 8525  
8526 8526          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
8527 8527              "ohci_parse_isoc_error: frame count %d", fc);
8528 8528  
8529 8529          /*
8530 8530           * Get the address of current usb isochronous request
8531 8531           * and array of packet descriptors.
8532 8532           */
8533 8533          isoc_reqp = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
8534 8534          isoc_pkt_descr = isoc_reqp->isoc_pkt_descr;
8535 8535          isoc_pkt_descr += tw->tw_pkt_idx;
8536 8536  
8537 8537          for (i = 0; i <= fc; i++) {
8538 8538  
8539 8539                  psw = Get_TD(td->hctd_offsets[i / 2]);
8540 8540  
8541 8541                  if (toggle) {
8542 8542                          ctrl = psw & HC_ITD_ODD_OFFSET;
8543 8543                          toggle = 0;
8544 8544                  } else {
8545 8545                          ctrl =  (psw & HC_ITD_EVEN_OFFSET) <<
8546 8546                              HC_ITD_OFFSET_SHIFT;
8547 8547                          toggle = 1;
8548 8548                  }
8549 8549  
8550 8550                  isoc_pkt_descr->isoc_pkt_actual_length =
8551 8551                      (ctrl >> HC_ITD_OFFSET_SHIFT) & HC_ITD_OFFSET_ADDR;
8552 8552  
8553 8553                  ctrl = (uint_t)(ctrl & (uint32_t)HC_TD_CC);
8554 8554  
8555 8555                  /* Write the status of isoc data packet */
8556 8556                  isoc_pkt_descr->isoc_pkt_status =
8557 8557                      ohci_check_for_error(ohcip, pp, tw, td, ctrl);
8558 8558  
8559 8559                  if (isoc_pkt_descr->isoc_pkt_status) {
8560 8560                          /* Increment isoc data packet error count */
8561 8561                          isoc_reqp->isoc_error_count++;
8562 8562                  }
8563 8563  
8564 8564                  /*
8565 8565                   * Get the address of next isoc data packet descriptor.
8566 8566                   */
8567 8567                  isoc_pkt_descr++;
8568 8568          }
8569 8569          tw->tw_pkt_idx = tw->tw_pkt_idx + fc + 1;
8570 8570  
8571 8571          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
8572 8572              "ohci_parse_isoc_error: tw_pkt_idx %d", tw->tw_pkt_idx);
8573 8573  
8574 8574  }
8575 8575  
8576 8576  
8577 8577  /*
8578 8578   * ohci_check_for_error:
8579 8579   *
8580 8580   * Check for any errors.
8581 8581   */
8582 8582  static usb_cr_t
8583 8583  ohci_check_for_error(
8584 8584          ohci_state_t            *ohcip,
8585 8585          ohci_pipe_private_t     *pp,
8586 8586          ohci_trans_wrapper_t    *tw,
8587 8587          ohci_td_t               *td,
8588 8588          uint_t                  ctrl)
8589 8589  {
8590 8590          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
8591 8591          uchar_t                 ep_attrs = ph->p_ep.bmAttributes;
8592 8592          usb_cr_t                error = USB_CR_OK;
8593 8593          usb_req_attrs_t         xfer_attrs;
8594 8594  
8595 8595          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8596 8596              "ohci_check_for_error: td = 0x%p ctrl = 0x%x",
8597 8597              (void *)td, ctrl);
8598 8598  
8599 8599          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8600 8600  
8601 8601          switch (ctrl) {
8602 8602          case HC_TD_CC_NO_E:
8603 8603                  USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8604 8604                      "ohci_check_for_error: No Error");
8605 8605                  error = USB_CR_OK;
8606 8606                  break;
8607 8607          case HC_TD_CC_CRC:
8608 8608                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8609 8609                      "ohci_check_for_error: CRC error");
8610 8610                  error = USB_CR_CRC;
8611 8611                  break;
8612 8612          case HC_TD_CC_BS:
8613 8613                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8614 8614                      "ohci_check_for_error: Bit stuffing");
8615 8615                  error = USB_CR_BITSTUFFING;
8616 8616                  break;
8617 8617          case HC_TD_CC_DTM:
8618 8618                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8619 8619                      "ohci_check_for_error: Data Toggle Mismatch");
8620 8620                  error = USB_CR_DATA_TOGGLE_MM;
8621 8621                  break;
8622 8622          case HC_TD_CC_STALL:
8623 8623                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8624 8624                      "ohci_check_for_error: Stall");
8625 8625                  error = USB_CR_STALL;
8626 8626                  break;
8627 8627          case HC_TD_CC_DNR:
8628 8628                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8629 8629                      "ohci_check_for_error: Device not responding");
8630 8630                  error = USB_CR_DEV_NOT_RESP;
8631 8631                  break;
8632 8632          case HC_TD_CC_PCF:
8633 8633                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8634 8634                      "ohci_check_for_error: PID check failure");
8635 8635                  error = USB_CR_PID_CHECKFAILURE;
8636 8636                  break;
8637 8637          case HC_TD_CC_UPID:
8638 8638                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8639 8639                      "ohci_check_for_error: Unexpected PID");
8640 8640                  error = USB_CR_UNEXP_PID;
8641 8641                  break;
8642 8642          case HC_TD_CC_DO:
8643 8643                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8644 8644                      "ohci_check_for_error: Data overrrun");
8645 8645                  error = USB_CR_DATA_OVERRUN;
8646 8646                  break;
8647 8647          case HC_TD_CC_DU:
8648 8648                  /*
8649 8649                   * Check whether short packets are acceptable.
8650 8650                   * If so don't report error to client drivers
8651 8651                   * and restart the endpoint. Otherwise report
8652 8652                   * data underrun error to client driver.
8653 8653                   */
8654 8654                  xfer_attrs = ohci_get_xfer_attrs(ohcip, pp, tw);
8655 8655  
8656 8656                  if (xfer_attrs & USB_ATTRS_SHORT_XFER_OK) {
8657 8657                          error = USB_CR_OK;
8658 8658                          if ((ep_attrs & USB_EP_ATTR_MASK) !=
8659 8659                              USB_EP_ATTR_ISOCH) {
8660 8660                                  /*
8661 8661                                   * Cleanup the remaining resources that may have
8662 8662                                   * been allocated for this transfer.
8663 8663                                   */
8664 8664                                  if (ohci_cleanup_data_underrun(ohcip, pp, tw,
8665 8665                                      td) == USB_SUCCESS) {
8666 8666                                          /* Clear the halt bit */
8667 8667                                          Set_ED(pp->pp_ept->hced_headp,
8668 8668                                              (Get_ED(pp->pp_ept->hced_headp) &
8669 8669                                              ~HC_EPT_Halt));
8670 8670                                  } else {
8671 8671                                          error = USB_CR_UNSPECIFIED_ERR;
8672 8672                                  }
8673 8673                          }
8674 8674                  } else {
8675 8675                          USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8676 8676                              "ohci_check_for_error: Data underrun");
8677 8677  
8678 8678                          error = USB_CR_DATA_UNDERRUN;
8679 8679                  }
8680 8680  
8681 8681                  break;
8682 8682          case HC_TD_CC_BO:
8683 8683                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8684 8684                      "ohci_check_for_error: Buffer overrun");
8685 8685                  error = USB_CR_BUFFER_OVERRUN;
8686 8686                  break;
8687 8687          case HC_TD_CC_BU:
8688 8688                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8689 8689                      "ohci_check_for_error: Buffer underrun");
8690 8690                  error = USB_CR_BUFFER_UNDERRUN;
8691 8691                  break;
8692 8692          case HC_TD_CC_NA:
8693 8693          default:
8694 8694                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8695 8695                      "ohci_check_for_error: Not accessed");
8696 8696                  error = USB_CR_NOT_ACCESSED;
8697 8697                  break;
8698 8698          }
8699 8699  
8700 8700          if (error) {
8701 8701                  uint_t hced_ctrl =  Get_ED(pp->pp_ept->hced_ctrl);
8702 8702  
8703 8703                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8704 8704                      "ohci_check_for_error: Error %d Device address %d "
8705 8705                      "Endpoint number %d", error, (hced_ctrl & HC_EPT_FUNC),
8706 8706                      ((hced_ctrl & HC_EPT_EP) >> HC_EPT_EP_SHFT));
8707 8707          }
8708 8708  
8709 8709          return (error);
8710 8710  }
8711 8711  
8712 8712  
8713 8713  /*
8714 8714   * ohci_handle_error:
8715 8715   *
8716 8716   * Inform USBA about occured transaction errors by calling the USBA callback
8717 8717   * routine.
8718 8718   */
8719 8719  static void
8720 8720  ohci_handle_error(
8721 8721          ohci_state_t            *ohcip,
8722 8722          ohci_td_t               *td,
8723 8723          usb_cr_t                error)
8724 8724  {
8725 8725          ohci_trans_wrapper_t    *tw;
8726 8726          usba_pipe_handle_data_t *ph;
8727 8727          ohci_pipe_private_t     *pp;
8728 8728          mblk_t                  *mp = NULL;
8729 8729          size_t                  length = 0;
8730 8730          uchar_t                 attributes;
8731 8731          usb_intr_req_t          *curr_intr_reqp;
8732 8732  
8733 8733          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8734 8734              "ohci_handle_error: error = 0x%x", error);
8735 8735  
8736 8736          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8737 8737  
8738 8738          ASSERT(td != NULL);
8739 8739  
8740 8740          /* Print the values in the td */
8741 8741          ohci_print_td(ohcip, td);
8742 8742  
8743 8743          /* Obtain the transfer wrapper from the TD */
8744 8744          tw = (ohci_trans_wrapper_t *)
8745 8745              OHCI_LOOKUP_ID((uint32_t)Get_TD(td->hctd_trans_wrapper));
8746 8746  
8747 8747          ASSERT(tw != NULL);
8748 8748  
8749 8749          /* Obtain the pipe private structure */
8750 8750          pp = tw->tw_pipe_private;
8751 8751  
8752 8752          ph = tw->tw_pipe_private->pp_pipe_handle;
8753 8753          attributes = ph->p_ep.bmAttributes & USB_EP_ATTR_MASK;
8754 8754  
8755 8755          /*
8756 8756           * Special error handling
8757 8757           */
8758 8758          if (tw->tw_direction == HC_TD_IN) {
8759 8759  
8760 8760                  switch (attributes) {
8761 8761                  case USB_EP_ATTR_CONTROL:
8762 8762                          if (((ph->p_ep.bmAttributes &
8763 8763                              USB_EP_ATTR_MASK) ==
8764 8764                              USB_EP_ATTR_CONTROL) &&
8765 8765                              (Get_TD(td->hctd_ctrl_phase) ==
8766 8766                              OHCI_CTRL_SETUP_PHASE)) {
8767 8767  
8768 8768                                  break;
8769 8769                          }
8770 8770                          /* FALLTHROUGH */
8771 8771                  case USB_EP_ATTR_BULK:
8772 8772                          /*
8773 8773                           * Call ohci_sendup_td_message
8774 8774                           * to send message to upstream.
8775 8775                           */
8776 8776                          ohci_sendup_td_message(ohcip, pp, tw, td, error);
8777 8777  
8778 8778                          return;
8779 8779                  case USB_EP_ATTR_INTR:
8780 8780                          curr_intr_reqp =
8781 8781                              (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
8782 8782  
8783 8783                          if (curr_intr_reqp->intr_attributes &
8784 8784                              USB_ATTRS_ONE_XFER) {
8785 8785  
8786 8786                                  ohci_handle_one_xfer_completion(ohcip, tw);
8787 8787                          }
8788 8788  
8789 8789                          /* Decrement periodic in request count */
8790 8790                          pp->pp_cur_periodic_req_cnt--;
8791 8791                          break;
8792 8792                  case USB_EP_ATTR_ISOCH:
8793 8793                  default:
8794 8794                          break;
8795 8795                  }
8796 8796          } else {
8797 8797                  switch (attributes) {
8798 8798                  case USB_EP_ATTR_BULK:
8799 8799                  case USB_EP_ATTR_INTR:
8800 8800                          /*
8801 8801                           * If "CurrentBufferPointer" of Transfer
8802 8802                           * Descriptor (TD) is not equal to zero,
8803 8803                           * then we sent less data  to the device
8804 8804                           * than requested by client. In that case,
8805 8805                           * return the mblk after updating the
8806 8806                           * data->r_ptr.
8807 8807                           */
8808 8808                          if (Get_TD(td->hctd_cbp)) {
8809 8809                                  usb_opaque_t xfer_reqp = tw->tw_curr_xfer_reqp;
8810 8810                                  size_t residue;
8811 8811  
8812 8812                                  residue = ohci_get_td_residue(ohcip, td);
8813 8813                                  length = Get_TD(td->hctd_xfer_offs) +
8814 8814                                      Get_TD(td->hctd_xfer_len) - residue;
8815 8815  
8816 8816                                  USB_DPRINTF_L2(PRINT_MASK_INTR,
8817 8817                                      ohcip->ohci_log_hdl,
8818 8818                                      "ohci_handle_error: requested data %lu "
8819 8819                                      "sent data %lu", tw->tw_length, length);
8820 8820  
8821 8821                                  if (attributes == USB_EP_ATTR_BULK) {
8822 8822                                          mp = (mblk_t *)((usb_bulk_req_t *)
8823 8823                                              (xfer_reqp))->bulk_data;
8824 8824                                  } else {
8825 8825                                          mp = (mblk_t *)((usb_intr_req_t *)
8826 8826                                              (xfer_reqp))->intr_data;
8827 8827                                  }
8828 8828  
8829 8829                                  /* Increment the read pointer */
8830 8830                                  mp->b_rptr = mp->b_rptr + length;
8831 8831                          }
8832 8832                          break;
8833 8833                  default:
8834 8834                          break;
8835 8835                  }
8836 8836          }
8837 8837  
8838 8838          /*
8839 8839           * Callback the client with the
8840 8840           * failure reason.
8841 8841           */
8842 8842          ohci_hcdi_callback(ph, tw, error);
8843 8843  
8844 8844          /* Check anybody is waiting for transfers completion event */
8845 8845          ohci_check_for_transfers_completion(ohcip, pp);
8846 8846  }
8847 8847  
8848 8848  /*
8849 8849   * ohci_cleanup_data_underrun:
8850 8850   *
8851 8851   * Cleans up resources when a short xfer occurs
8852 8852   */
8853 8853  static int
8854 8854  ohci_cleanup_data_underrun(
8855 8855          ohci_state_t            *ohcip,
8856 8856          ohci_pipe_private_t     *pp,
8857 8857          ohci_trans_wrapper_t    *tw,
8858 8858          ohci_td_t               *td)
8859 8859  {
8860 8860          ohci_td_t               *next_td;
8861 8861          ohci_td_t               *last_td;
8862 8862          ohci_td_t               *temp_td;
8863 8863          uint32_t                last_td_addr;
8864 8864          uint_t                  hced_head;
8865 8865  
8866 8866          USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8867 8867              "ohci_cleanup_data_underrun: td 0x%p, tw 0x%p",
8868 8868              (void *)td, (void *)tw);
8869 8869  
8870 8870          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8871 8871          ASSERT(tw->tw_hctd_head == td);
8872 8872  
8873 8873          /* Check if this TD is the last td in the tw */
8874 8874          last_td = tw->tw_hctd_tail;
8875 8875          if (td == last_td) {
8876 8876                  /* There is no need for cleanup */
8877 8877                  return (USB_SUCCESS);
8878 8878          }
8879 8879  
8880 8880          /*
8881 8881           * Make sure the ED is halted before we change any td's.
8882 8882           * If for some reason it is not halted, return error to client
8883 8883           * driver so they can reset the port.
8884 8884           */
8885 8885          hced_head = Get_ED(pp->pp_ept->hced_headp);
8886 8886          if (!(hced_head & HC_EPT_Halt)) {
8887 8887                  uint_t hced_ctrl = Get_ED(pp->pp_ept->hced_ctrl);
8888 8888  
8889 8889                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8890 8890                      "ohci_cleanup_data_underrun: Unable to clean up a short "
8891 8891                      "xfer error.  Client might send/receive irrelevant data."
8892 8892                      " Device address %d Endpoint number %d",
8893 8893                      (hced_ctrl & HC_EPT_FUNC),
8894 8894                      ((hced_ctrl & HC_EPT_EP) >> HC_EPT_EP_SHFT));
8895 8895  
8896 8896                  Set_ED(pp->pp_ept->hced_headp, hced_head | HC_EPT_Halt);
8897 8897  
8898 8898                  return (USB_FAILURE);
8899 8899          }
8900 8900  
8901 8901          /*
8902 8902           * Get the address of the first td of the next transfer (tw).
8903 8903           * This td, may currently be a dummy td, but when a new request
8904 8904           * arrives, it will be transformed into a regular td.
8905 8905           */
8906 8906          last_td_addr = Get_TD(last_td->hctd_next_td);
8907 8907          /* Set ED head to this last td */
8908 8908          Set_ED(pp->pp_ept->hced_headp,
8909 8909              (last_td_addr & HC_EPT_TD_HEAD) |
8910 8910              (hced_head & ~HC_EPT_TD_HEAD));
8911 8911  
8912 8912          /*
8913 8913           * Start removing all the unused TD's from the TW,
8914 8914           * but keep the first one.
8915 8915           */
8916 8916          tw->tw_hctd_tail = td;
8917 8917  
8918 8918          /*
8919 8919           * Get the last_td, the next td in the tw list.
8920 8920           * Afterwards completely disassociate the current td from other tds
8921 8921           */
8922 8922          next_td = (ohci_td_t *)ohci_td_iommu_to_cpu(ohcip,
8923 8923              Get_TD(td->hctd_tw_next_td));
8924 8924          Set_TD(td->hctd_tw_next_td, NULL);
8925 8925  
8926 8926          /*
8927 8927           * Iterate down the tw list and deallocate them
8928 8928           */
8929 8929          while (next_td != NULL) {
8930 8930                  tw->tw_num_tds--;
8931 8931                  /* Disassociate this td from it's TW and set to RECLAIM */
8932 8932                  Set_TD(next_td->hctd_trans_wrapper, NULL);
8933 8933                  Set_TD(next_td->hctd_state, HC_TD_RECLAIM);
8934 8934  
8935 8935                  temp_td = next_td;
8936 8936  
8937 8937                  next_td = (ohci_td_t *)ohci_td_iommu_to_cpu(ohcip,
8938 8938                      Get_TD(next_td->hctd_tw_next_td));
8939 8939  
8940 8940                  ohci_deallocate_td(ohcip, temp_td);
8941 8941          }
8942 8942  
8943 8943          ASSERT(tw->tw_num_tds == 1);
8944 8944  
8945 8945          return (USB_SUCCESS);
8946 8946  }
8947 8947  
8948 8948  /*
8949 8949   * ohci_handle_normal_td:
8950 8950   */
8951 8951  static void
8952 8952  ohci_handle_normal_td(
8953 8953          ohci_state_t            *ohcip,
8954 8954          ohci_td_t               *td,
8955 8955          ohci_trans_wrapper_t    *tw)
8956 8956  {
8957 8957          ohci_pipe_private_t     *pp;    /* Pipe private field */
8958 8958  
8959 8959          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8960 8960              "ohci_handle_normal_td:");
8961 8961  
8962 8962          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8963 8963          ASSERT(tw != NULL);
8964 8964  
8965 8965          /* Obtain the pipe private structure */
8966 8966          pp = tw->tw_pipe_private;
8967 8967  
8968 8968          (*tw->tw_handle_td)(ohcip, pp, tw,
8969 8969              td, tw->tw_handle_callback_value);
8970 8970  
8971 8971          /* Check anybody is waiting for transfers completion event */
8972 8972          ohci_check_for_transfers_completion(ohcip, pp);
8973 8973  }
8974 8974  
8975 8975  
8976 8976  /*
8977 8977   * ohci_handle_ctrl_td:
8978 8978   *
8979 8979   * Handle a control Transfer Descriptor (TD).
8980 8980   */
8981 8981  /* ARGSUSED */
8982 8982  static void
8983 8983  ohci_handle_ctrl_td(
8984 8984          ohci_state_t            *ohcip,
8985 8985          ohci_pipe_private_t     *pp,
8986 8986          ohci_trans_wrapper_t    *tw,
8987 8987          ohci_td_t               *td,
8988 8988          void                    *tw_handle_callback_value)
8989 8989  {
8990 8990          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
8991 8991  
8992 8992          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
8993 8993              "ohci_handle_ctrl_td: pp = 0x%p tw = 0x%p td = 0x%p state = 0x%x",
8994 8994              (void *)pp, (void *)tw, (void *)td, Get_TD(td->hctd_ctrl_phase));
8995 8995  
8996 8996          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
8997 8997  
8998 8998          /*
8999 8999           * Check which control transfer phase got completed.
9000 9000           */
9001 9001          tw->tw_num_tds--;
9002 9002          switch (Get_TD(td->hctd_ctrl_phase)) {
9003 9003          case OHCI_CTRL_SETUP_PHASE:
9004 9004                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9005 9005                      "Setup complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
9006 9006  
9007 9007                  break;
9008 9008          case OHCI_CTRL_DATA_PHASE:
9009 9009                  /*
9010 9010                   * If "CurrentBufferPointer" of Transfer Descriptor (TD)
9011 9011                   * is not equal to zero, then we received less data from
9012 9012                   * the device than requested by us. In that case, get the
9013 9013                   * actual received data size.
9014 9014                   */
9015 9015                  if (Get_TD(td->hctd_cbp)) {
9016 9016                          size_t                  length, residue;
9017 9017  
9018 9018                          residue = ohci_get_td_residue(ohcip, td);
9019 9019                          length = Get_TD(td->hctd_xfer_offs) +
9020 9020                              Get_TD(td->hctd_xfer_len) - residue;
9021 9021  
9022 9022                          USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9023 9023                              "ohci_handle_ctrl_qtd: requested data %lu "
9024 9024                              "received data %lu", tw->tw_length, length);
9025 9025  
9026 9026                          /* Save actual received data length */
9027 9027                          tw->tw_length = length;
9028 9028                  }
9029 9029  
9030 9030                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9031 9031                      "Data complete: pp 0x%p td 0x%p",
9032 9032                      (void *)pp, (void *)td);
9033 9033  
9034 9034                  break;
9035 9035          case OHCI_CTRL_STATUS_PHASE:
9036 9036                  if ((tw->tw_length != 0) &&
9037 9037                      (tw->tw_direction == HC_TD_IN)) {
9038 9038  
9039 9039                          /*
9040 9040                           * Call ohci_sendup_td_message
9041 9041                           * to send message to upstream.
9042 9042                           */
9043 9043                          ohci_sendup_td_message(ohcip,
9044 9044                              pp, tw, td, USB_CR_OK);
9045 9045                  } else {
9046 9046                          ohci_do_byte_stats(ohcip,
9047 9047                              tw->tw_length - OHCI_MAX_TD_BUF_SIZE,
9048 9048                              ph->p_ep.bmAttributes,
9049 9049                              ph->p_ep.bEndpointAddress);
9050 9050  
9051 9051                          ohci_hcdi_callback(ph, tw, USB_CR_OK);
9052 9052                  }
9053 9053  
9054 9054                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9055 9055                      "Status complete: pp 0x%p td 0x%p", (void *)pp, (void *)td);
9056 9056  
9057 9057                  break;
9058 9058          }
9059 9059  }
9060 9060  
9061 9061  
9062 9062  /*
9063 9063   * ohci_handle_bulk_td:
9064 9064   *
9065 9065   * Handle a bulk Transfer Descriptor (TD).
9066 9066   */
9067 9067  /* ARGSUSED */
9068 9068  static void
9069 9069  ohci_handle_bulk_td(
9070 9070          ohci_state_t            *ohcip,
9071 9071          ohci_pipe_private_t     *pp,
9072 9072          ohci_trans_wrapper_t    *tw,
9073 9073          ohci_td_t               *td,
9074 9074          void                    *tw_handle_callback_value)
9075 9075  {
9076 9076          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9077 9077          usb_ep_descr_t          *eptd = &ph->p_ep;
9078 9078  
9079 9079          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9080 9080              "ohci_handle_bulk_td:");
9081 9081  
9082 9082          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9083 9083  
9084 9084          /*
9085 9085           * Decrement the TDs counter and check whether all the bulk
9086 9086           * data has been send or received. If TDs counter reaches
9087 9087           * zero then inform client driver about completion current
9088 9088           * bulk request. Other wise wait for completion of other bulk
9089 9089           * TDs or transactions on this pipe.
9090 9090           */
9091 9091          if (--tw->tw_num_tds != 0) {
9092 9092  
9093 9093                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9094 9094                      "ohci_handle_bulk_td: Number of TDs %d", tw->tw_num_tds);
9095 9095  
9096 9096                  return;
9097 9097          }
9098 9098  
9099 9099          /*
9100 9100           * If this is a bulk in pipe, return the data to the client.
9101 9101           * For a bulk out pipe, there is no need to do anything.
9102 9102           */
9103 9103          if ((eptd->bEndpointAddress &
9104 9104              USB_EP_DIR_MASK) == USB_EP_DIR_OUT) {
9105 9105  
9106 9106                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9107 9107                      "ohci_handle_bulk_td: Bulk out pipe");
9108 9108  
9109 9109                  ohci_do_byte_stats(ohcip, tw->tw_length,
9110 9110                      eptd->bmAttributes, eptd->bEndpointAddress);
9111 9111  
9112 9112                  /* Do the callback */
9113 9113                  ohci_hcdi_callback(ph, tw, USB_CR_OK);
9114 9114  
9115 9115                  return;
9116 9116          }
9117 9117  
9118 9118          /* Call ohci_sendup_td_message to send message to upstream */
9119 9119          ohci_sendup_td_message(ohcip, pp, tw, td, USB_CR_OK);
9120 9120  }
9121 9121  
9122 9122  
9123 9123  /*
9124 9124   * ohci_handle_intr_td:
9125 9125   *
9126 9126   * Handle a interrupt Transfer Descriptor (TD).
9127 9127   */
9128 9128  /* ARGSUSED */
9129 9129  static void
9130 9130  ohci_handle_intr_td(
9131 9131          ohci_state_t            *ohcip,
9132 9132          ohci_pipe_private_t     *pp,
9133 9133          ohci_trans_wrapper_t    *tw,
9134 9134          ohci_td_t               *td,
9135 9135          void                    *tw_handle_callback_value)
9136 9136  {
9137 9137          usb_intr_req_t          *curr_intr_reqp =
9138 9138              (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
9139 9139          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9140 9140          usb_ep_descr_t          *eptd = &ph->p_ep;
9141 9141          usb_req_attrs_t         attrs;
9142 9142          int                     error = USB_SUCCESS;
9143 9143  
9144 9144          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9145 9145              "ohci_handle_intr_td: pp=0x%p tw=0x%p td=0x%p"
9146 9146              "intr_reqp=0%p data=0x%p", (void *)pp, (void *)tw, (void *)td,
9147 9147              (void *)curr_intr_reqp, (void *)curr_intr_reqp->intr_data);
9148 9148  
9149 9149          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9150 9150  
9151 9151          /* Get the interrupt xfer attributes */
9152 9152          attrs = curr_intr_reqp->intr_attributes;
9153 9153  
9154 9154          /*
9155 9155           * For a Interrupt OUT pipe, we just callback and we are done
9156 9156           */
9157 9157          if ((eptd->bEndpointAddress & USB_EP_DIR_MASK) == USB_EP_DIR_OUT) {
9158 9158  
9159 9159                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9160 9160                      "ohci_handle_intr_td: Intr out pipe, intr_reqp=0x%p,"
9161 9161                      "data=0x%p", (void *)curr_intr_reqp,
9162 9162                      (void *)curr_intr_reqp->intr_data);
9163 9163  
9164 9164                  ohci_do_byte_stats(ohcip, tw->tw_length,
9165 9165                      eptd->bmAttributes, eptd->bEndpointAddress);
9166 9166  
9167 9167                  /* Do the callback */
9168 9168                  ohci_hcdi_callback(ph, tw, USB_CR_OK);
9169 9169  
9170 9170                  return;
9171 9171          }
9172 9172  
9173 9173          /* Decrement number of interrupt request count */
9174 9174          pp->pp_cur_periodic_req_cnt--;
9175 9175  
9176 9176          /*
9177 9177           * Check usb flag whether USB_FLAGS_ONE_XFER flag is set
9178 9178           * and if so, free duplicate request.
9179 9179           */
9180 9180          if (attrs & USB_ATTRS_ONE_XFER) {
9181 9181                  ohci_handle_one_xfer_completion(ohcip, tw);
9182 9182          }
9183 9183  
9184 9184          /* Call ohci_sendup_td_message to callback into client */
9185 9185          ohci_sendup_td_message(ohcip, pp, tw, td, USB_CR_OK);
9186 9186  
9187 9187          /*
9188 9188           * If interrupt pipe state is still active, insert next Interrupt
9189 9189           * request into the Host Controller's Interrupt list.  Otherwise
9190 9190           * you are done.
9191 9191           */
9192 9192          if (pp->pp_state != OHCI_PIPE_STATE_ACTIVE) {
9193 9193                  return;
9194 9194          }
9195 9195  
9196 9196          if ((error = ohci_allocate_periodic_in_resource(ohcip, pp, tw, 0)) ==
9197 9197              USB_SUCCESS) {
9198 9198                  curr_intr_reqp = (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
9199 9199  
9200 9200                  ASSERT(curr_intr_reqp != NULL);
9201 9201  
9202 9202                  tw->tw_num_tds = 1;
9203 9203  
9204 9204                  if (ohci_tw_rebind_cookie(ohcip, pp, tw) != USB_SUCCESS) {
9205 9205                          ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9206 9206                          error = USB_FAILURE;
9207 9207                  } else if (ohci_allocate_tds_for_tw(ohcip, tw,
9208 9208                      tw->tw_num_tds) != USB_SUCCESS) {
9209 9209                          ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9210 9210                          error = USB_FAILURE;
9211 9211                  }
9212 9212          }
9213 9213  
9214 9214          if (error != USB_SUCCESS) {
9215 9215                  /*
9216 9216                   * Set pipe state to stop polling and error to no
9217 9217                   * resource. Don't insert any more interrupt polling
9218 9218                   * requests.
9219 9219                   */
9220 9220                  pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
9221 9221                  pp->pp_error = USB_CR_NO_RESOURCES;
9222 9222          } else {
9223 9223                  ohci_insert_intr_req(ohcip, pp, tw, 0);
9224 9224  
9225 9225                  /* Increment number of interrupt request count */
9226 9226                  pp->pp_cur_periodic_req_cnt++;
9227 9227  
9228 9228                  ASSERT(pp->pp_cur_periodic_req_cnt ==
9229 9229                      pp->pp_max_periodic_req_cnt);
9230 9230          }
9231 9231  }
9232 9232  
9233 9233  
9234 9234  /*
9235 9235   * ohci_handle_one_xfer_completion:
9236 9236   */
9237 9237  static void
9238 9238  ohci_handle_one_xfer_completion(
9239 9239          ohci_state_t            *ohcip,
9240 9240          ohci_trans_wrapper_t    *tw)
9241 9241  {
9242 9242          usba_pipe_handle_data_t *ph = tw->tw_pipe_private->pp_pipe_handle;
9243 9243          ohci_pipe_private_t     *pp = tw->tw_pipe_private;
9244 9244          usb_intr_req_t          *curr_intr_reqp =
9245 9245              (usb_intr_req_t *)tw->tw_curr_xfer_reqp;
9246 9246  
9247 9247          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9248 9248              "ohci_handle_one_xfer_completion: tw = 0x%p", (void *)tw);
9249 9249  
9250 9250          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9251 9251          ASSERT(curr_intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER);
9252 9252  
9253 9253          pp->pp_state = OHCI_PIPE_STATE_IDLE;
9254 9254  
9255 9255          /*
9256 9256           * For one xfer, we need to copy back data ptr
9257 9257           * and free current request
9258 9258           */
9259 9259          ((usb_intr_req_t *)(pp->pp_client_periodic_in_reqp))->
9260 9260              intr_data = ((usb_intr_req_t *)
9261 9261              (tw->tw_curr_xfer_reqp))->intr_data;
9262 9262  
9263 9263          ((usb_intr_req_t *)tw->tw_curr_xfer_reqp)->intr_data = NULL;
9264 9264  
9265 9265          /* Now free duplicate current request */
9266 9266          usb_free_intr_req((usb_intr_req_t *)tw-> tw_curr_xfer_reqp);
9267 9267  
9268 9268          mutex_enter(&ph->p_mutex);
9269 9269          ph->p_req_count--;
9270 9270          mutex_exit(&ph->p_mutex);
9271 9271  
9272 9272          /* Make client's request the current request */
9273 9273          tw->tw_curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
9274 9274          pp->pp_client_periodic_in_reqp = NULL;
9275 9275  }
9276 9276  
9277 9277  
9278 9278  /*
9279 9279   * ohci_handle_isoc_td:
9280 9280   *
9281 9281   * Handle an isochronous Transfer Descriptor (TD).
9282 9282   */
9283 9283  /* ARGSUSED */
9284 9284  static void
9285 9285  ohci_handle_isoc_td(
9286 9286          ohci_state_t            *ohcip,
9287 9287          ohci_pipe_private_t     *pp,
9288 9288          ohci_trans_wrapper_t    *tw,
9289 9289          ohci_td_t               *td,
9290 9290          void                    *tw_handle_callback_value)
9291 9291  {
9292 9292          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9293 9293          usb_ep_descr_t          *eptd = &ph->p_ep;
9294 9294          usb_isoc_req_t          *curr_isoc_reqp =
9295 9295              (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
9296 9296          int                     error = USB_SUCCESS;
9297 9297  
9298 9298          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9299 9299              "ohci_handle_isoc_td: pp=0x%p tw=0x%p td=0x%p"
9300 9300              "isoc_reqp=0%p data=0x%p", (void *)pp, (void *)tw, (void *)td,
9301 9301              (void *)curr_isoc_reqp, (void *)curr_isoc_reqp->isoc_data);
9302 9302  
9303 9303          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9304 9304  
9305 9305          /*
9306 9306           * Decrement the TDs counter and check whether all the isoc
9307 9307           * data has been send or received. If TDs counter reaches
9308 9308           * zero then inform client driver about completion current
9309 9309           * isoc request. Otherwise wait for completion of other isoc
9310 9310           * TDs or transactions on this pipe.
9311 9311           */
9312 9312          if (--tw->tw_num_tds != 0) {
9313 9313  
9314 9314                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9315 9315                      "ohci_handle_isoc_td: Number of TDs %d", tw->tw_num_tds);
9316 9316  
9317 9317                  return;
9318 9318          }
9319 9319  
9320 9320          /*
9321 9321           * If this is a isoc in pipe, return the data to the client.
9322 9322           * For a isoc out pipe, there is no need to do anything.
9323 9323           */
9324 9324          if ((eptd->bEndpointAddress & USB_EP_DIR_MASK) == USB_EP_DIR_OUT) {
9325 9325                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9326 9326                      "ohci_handle_isoc_td: Isoc out pipe, isoc_reqp=0x%p,"
9327 9327                      "data=0x%p", (void *)curr_isoc_reqp,
9328 9328                      (void *)curr_isoc_reqp->isoc_data);
9329 9329  
9330 9330                  ohci_do_byte_stats(ohcip, tw->tw_length,
9331 9331                      eptd->bmAttributes, eptd->bEndpointAddress);
9332 9332  
9333 9333                  /* Do the callback */
9334 9334                  ohci_hcdi_callback(ph, tw, USB_CR_OK);
9335 9335  
9336 9336                  return;
9337 9337          }
9338 9338  
9339 9339          /* Decrement number of IN isochronous request count */
9340 9340          pp->pp_cur_periodic_req_cnt--;
9341 9341  
9342 9342          /* Call ohci_sendup_td_message to send message to upstream */
9343 9343          ohci_sendup_td_message(ohcip, pp, tw, td, USB_CR_OK);
9344 9344  
9345 9345          /*
9346 9346           * If isochronous pipe state is still active, insert next isochronous
9347 9347           * request into the Host Controller's isochronous list.
9348 9348           */
9349 9349          if (pp->pp_state != OHCI_PIPE_STATE_ACTIVE) {
9350 9350                  return;
9351 9351          }
9352 9352  
9353 9353          if ((error = ohci_allocate_periodic_in_resource(ohcip, pp, tw, 0)) ==
9354 9354              USB_SUCCESS) {
9355 9355                  curr_isoc_reqp = (usb_isoc_req_t *)tw->tw_curr_xfer_reqp;
9356 9356  
9357 9357                  ASSERT(curr_isoc_reqp != NULL);
9358 9358  
9359 9359                  tw->tw_num_tds =
9360 9360                      curr_isoc_reqp->isoc_pkts_count / OHCI_ISOC_PKTS_PER_TD;
9361 9361                  if (curr_isoc_reqp->isoc_pkts_count % OHCI_ISOC_PKTS_PER_TD) {
9362 9362                          tw->tw_num_tds++;
9363 9363                  }
9364 9364  
9365 9365                  if (ohci_tw_rebind_cookie(ohcip, pp, tw) != USB_SUCCESS) {
9366 9366                          ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9367 9367                          error = USB_FAILURE;
9368 9368                  } else if (ohci_allocate_tds_for_tw(ohcip, tw,
9369 9369                      tw->tw_num_tds) != USB_SUCCESS) {
9370 9370                          ohci_deallocate_periodic_in_resource(ohcip, pp, tw);
9371 9371                          error = USB_FAILURE;
9372 9372                  }
9373 9373          }
9374 9374  
9375 9375          if (error != USB_SUCCESS ||
9376 9376              ohci_insert_isoc_req(ohcip, pp, tw, 0) != USB_SUCCESS) {
9377 9377                  /*
9378 9378                   * Set pipe state to stop polling and error to no
9379 9379                   * resource. Don't insert any more isoch polling
9380 9380                   * requests.
9381 9381                   */
9382 9382                  pp->pp_state = OHCI_PIPE_STATE_STOP_POLLING;
9383 9383                  pp->pp_error = USB_CR_NO_RESOURCES;
9384 9384  
9385 9385          } else {
9386 9386                  /* Increment number of IN isochronous request count */
9387 9387                  pp->pp_cur_periodic_req_cnt++;
9388 9388  
9389 9389                  ASSERT(pp->pp_cur_periodic_req_cnt ==
9390 9390                      pp->pp_max_periodic_req_cnt);
9391 9391          }
9392 9392  }
9393 9393  
9394 9394  
9395 9395  /*
9396 9396   * ohci_tw_rebind_cookie:
9397 9397   *
9398 9398   * If the cookie associated with a DMA buffer has been walked, the cookie
9399 9399   * is not usable any longer. To reuse the DMA buffer, the DMA handle needs
9400 9400   * to rebind for cookies.
9401 9401   */
9402 9402  static int
9403 9403  ohci_tw_rebind_cookie(
9404 9404          ohci_state_t            *ohcip,
9405 9405          ohci_pipe_private_t     *pp,
9406 9406          ohci_trans_wrapper_t    *tw)
9407 9407  {
9408 9408          usb_ep_descr_t          *eptd = &pp->pp_pipe_handle->p_ep;
9409 9409          int                     rval, i;
9410 9410          uint_t                  ccount;
9411 9411  
9412 9412          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9413 9413              "ohci_tw_rebind_cookie:");
9414 9414  
9415 9415          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9416 9416  
9417 9417          if ((eptd->bmAttributes & USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH) {
9418 9418                  ASSERT(tw->tw_num_tds == tw->tw_ncookies);
9419 9419  
9420 9420                  for (i = 0; i < tw->tw_num_tds; i++) {
9421 9421                          if (tw->tw_isoc_bufs[i].ncookies == 1) {
9422 9422  
9423 9423                                  /*
9424 9424                                   * no need to rebind when there is
9425 9425                                   * only one cookie in a buffer
9426 9426                                   */
9427 9427                                  continue;
9428 9428                          }
9429 9429  
9430 9430                          /* unbind the DMA handle before rebinding */
9431 9431                          rval = ddi_dma_unbind_handle(
9432 9432                              tw->tw_isoc_bufs[i].dma_handle);
9433 9433                          ASSERT(rval == USB_SUCCESS);
9434 9434                          tw->tw_isoc_bufs[i].ncookies = 0;
9435 9435  
9436 9436                          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9437 9437                              "rebind dma_handle %d", i);
9438 9438  
9439 9439                          /* rebind the handle to get cookies */
9440 9440                          rval = ddi_dma_addr_bind_handle(
9441 9441                              tw->tw_isoc_bufs[i].dma_handle, NULL,
9442 9442                              (caddr_t)tw->tw_isoc_bufs[i].buf_addr,
9443 9443                              tw->tw_isoc_bufs[i].length,
9444 9444                              DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
9445 9445                              DDI_DMA_DONTWAIT, NULL,
9446 9446                              &tw->tw_isoc_bufs[i].cookie, &ccount);
9447 9447  
9448 9448                          if ((rval == DDI_DMA_MAPPED) &&
9449 9449                              (ccount <= OHCI_DMA_ATTR_TD_SGLLEN)) {
9450 9450                                  tw->tw_isoc_bufs[i].ncookies = ccount;
9451 9451                          } else {
9452 9452  
9453 9453                                  return (USB_NO_RESOURCES);
9454 9454                          }
9455 9455                  }
9456 9456          } else {
9457 9457                  if (tw->tw_cookie_idx != 0) {
9458 9458                          /* unbind the DMA handle before rebinding */
9459 9459                          rval = ddi_dma_unbind_handle(tw->tw_dmahandle);
9460 9460                          ASSERT(rval == DDI_SUCCESS);
9461 9461                          tw->tw_ncookies = 0;
9462 9462  
9463 9463                          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9464 9464                              "rebind dma_handle");
9465 9465  
9466 9466                          /* rebind the handle to get cookies */
9467 9467                          rval = ddi_dma_addr_bind_handle(
9468 9468                              tw->tw_dmahandle, NULL,
9469 9469                              (caddr_t)tw->tw_buf, tw->tw_length,
9470 9470                              DDI_DMA_RDWR|DDI_DMA_CONSISTENT,
9471 9471                              DDI_DMA_DONTWAIT, NULL,
9472 9472                              &tw->tw_cookie, &ccount);
9473 9473  
9474 9474                          if (rval == DDI_DMA_MAPPED) {
9475 9475                                  tw->tw_ncookies = ccount;
9476 9476                                  tw->tw_dma_offs = 0;
9477 9477                                  tw->tw_cookie_idx = 0;
9478 9478                          } else {
9479 9479  
9480 9480                                  return (USB_NO_RESOURCES);
9481 9481                          }
9482 9482                  }
9483 9483          }
9484 9484  
9485 9485          return (USB_SUCCESS);
9486 9486  }
9487 9487  
9488 9488  
9489 9489  /*
9490 9490   * ohci_sendup_td_message:
9491 9491   *      copy data, if necessary and do callback
9492 9492   */
9493 9493  static void
9494 9494  ohci_sendup_td_message(
9495 9495          ohci_state_t            *ohcip,
9496 9496          ohci_pipe_private_t     *pp,
9497 9497          ohci_trans_wrapper_t    *tw,
9498 9498          ohci_td_t               *td,
9499 9499          usb_cr_t                error)
9500 9500  {
9501 9501          usb_ep_descr_t          *eptd = &pp->pp_pipe_handle->p_ep;
9502 9502          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
9503 9503          size_t                  length = 0, skip_len = 0, residue;
9504 9504          mblk_t                  *mp;
9505 9505          uchar_t                 *buf;
9506 9506          usb_opaque_t            curr_xfer_reqp = tw->tw_curr_xfer_reqp;
9507 9507  
9508 9508          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9509 9509  
9510 9510          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9511 9511              "ohci_sendup_td_message:");
9512 9512  
9513 9513          ASSERT(tw != NULL);
9514 9514  
9515 9515          length = tw->tw_length;
9516 9516  
9517 9517          switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
9518 9518          case USB_EP_ATTR_CONTROL:
9519 9519                  /*
9520 9520                   * Get the correct length, adjust it for the setup size
9521 9521                   * which is not part of the data length in control end
9522 9522                   * points.  Update tw->tw_length for future references.
9523 9523                   */
9524 9524                  if (((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_wLength) {
9525 9525                          tw->tw_length = length = length - OHCI_MAX_TD_BUF_SIZE;
9526 9526                  } else {
9527 9527                          tw->tw_length = length = length - SETUP_SIZE;
9528 9528                  }
9529 9529  
9530 9530                  /* Set the length of the buffer to skip */
9531 9531                  skip_len = OHCI_MAX_TD_BUF_SIZE;
9532 9532  
9533 9533                  if (Get_TD(td->hctd_ctrl_phase) != OHCI_CTRL_DATA_PHASE) {
9534 9534                          break;
9535 9535                  }
9536 9536                  /* FALLTHRU */
9537 9537          case USB_EP_ATTR_BULK:
9538 9538          case USB_EP_ATTR_INTR:
9539 9539                  /*
9540 9540                   * If error is "data overrun", do not check for the
9541 9541                   * "CurrentBufferPointer"  and return whatever data
9542 9542                   * received to the client driver.
9543 9543                   */
9544 9544                  if (error == USB_CR_DATA_OVERRUN) {
9545 9545                          break;
9546 9546                  }
9547 9547  
9548 9548                  /*
9549 9549                   * If "CurrentBufferPointer" of Transfer Descriptor
9550 9550                   * (TD) is not equal to zero, then we received less
9551 9551                   * data from the device than requested by us. In that
9552 9552                   * case, get the actual received data size.
9553 9553                   */
9554 9554                  if (Get_TD(td->hctd_cbp)) {
9555 9555                          residue = ohci_get_td_residue(ohcip, td);
9556 9556                          length = Get_TD(td->hctd_xfer_offs) +
9557 9557                              Get_TD(td->hctd_xfer_len) - residue - skip_len;
9558 9558  
9559 9559                          USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9560 9560                              "ohci_sendup_qtd_message: requested data %lu "
9561 9561                              "received data %lu", tw->tw_length, length);
9562 9562                  }
9563 9563  
9564 9564                  break;
9565 9565          case USB_EP_ATTR_ISOCH:
9566 9566          default:
9567 9567                  break;
9568 9568          }
9569 9569  
9570 9570          /* Copy the data into the mblk_t */
9571 9571          buf = (uchar_t *)tw->tw_buf + skip_len;
9572 9572  
9573 9573          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9574 9574              "ohci_sendup_qtd_message: length %lu error %d", length, error);
9575 9575  
9576 9576          /* Get the message block */
9577 9577          switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
9578 9578          case USB_EP_ATTR_CONTROL:
9579 9579                  mp = ((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_data;
9580 9580                  break;
9581 9581          case USB_EP_ATTR_BULK:
9582 9582                  mp = ((usb_bulk_req_t *)curr_xfer_reqp)->bulk_data;
9583 9583                  break;
9584 9584          case USB_EP_ATTR_INTR:
9585 9585                  mp = ((usb_intr_req_t *)curr_xfer_reqp)->intr_data;
9586 9586                  break;
9587 9587          case USB_EP_ATTR_ISOCH:
9588 9588                  mp = ((usb_isoc_req_t *)curr_xfer_reqp)->isoc_data;
9589 9589                  break;
9590 9590          }
9591 9591  
9592 9592          ASSERT(mp != NULL);
9593 9593  
9594 9594          if (length) {
9595 9595                  int i;
9596 9596                  uchar_t *p = mp->b_rptr;
9597 9597  
9598 9598                  /*
9599 9599                   * Update kstat byte counts
9600 9600                   * The control endpoints don't have direction bits so in
9601 9601                   * order for control stats to be counted correctly an in
9602 9602                   * bit must be faked on a control read.
9603 9603                   */
9604 9604                  if ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
9605 9605                      USB_EP_ATTR_CONTROL) {
9606 9606                          ohci_do_byte_stats(ohcip, length,
9607 9607                              eptd->bmAttributes, USB_EP_DIR_IN);
9608 9608                  } else {
9609 9609                          ohci_do_byte_stats(ohcip, length,
9610 9610                              eptd->bmAttributes, eptd->bEndpointAddress);
9611 9611                  }
9612 9612  
9613 9613                  if ((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
9614 9614                      USB_EP_ATTR_ISOCH) {
9615 9615                          for (i = 0; i < tw->tw_ncookies; i++) {
9616 9616                                  Sync_IO_Buffer(
9617 9617                                      tw->tw_isoc_bufs[i].dma_handle,
9618 9618                                      tw->tw_isoc_bufs[i].length);
9619 9619  
9620 9620                                  ddi_rep_get8(tw->tw_isoc_bufs[i].mem_handle,
9621 9621                                      p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr,
9622 9622                                      tw->tw_isoc_bufs[i].length,
9623 9623                                      DDI_DEV_AUTOINCR);
9624 9624                                  p += tw->tw_isoc_bufs[i].length;
9625 9625                          }
9626 9626                          tw->tw_pkt_idx = 0;
9627 9627                  } else {
9628 9628                          /* Sync IO buffer */
9629 9629                          Sync_IO_Buffer(tw->tw_dmahandle, (skip_len + length));
9630 9630  
9631 9631                          /* Copy the data into the message */
9632 9632                          ddi_rep_get8(tw->tw_accesshandle,
9633 9633                              mp->b_rptr, buf, length, DDI_DEV_AUTOINCR);
9634 9634                  }
9635 9635  
9636 9636                  /* Increment the write pointer */
9637 9637                  mp->b_wptr = mp->b_wptr + length;
9638 9638          } else {
9639 9639                  USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9640 9640                      "ohci_sendup_td_message: Zero length packet");
9641 9641          }
9642 9642  
9643 9643          ohci_hcdi_callback(ph, tw, error);
9644 9644  }
9645 9645  
9646 9646  
9647 9647  /*
9648 9648   * ohci_get_td_residue:
9649 9649   *
9650 9650   * Calculate the bytes not transfered by the TD
9651 9651   */
9652 9652  size_t
9653 9653  ohci_get_td_residue(
9654 9654          ohci_state_t    *ohcip,
9655 9655          ohci_td_t       *td)
9656 9656  {
9657 9657          uint32_t        buf_addr, end_addr;
9658 9658          size_t          residue;
9659 9659  
9660 9660          buf_addr = Get_TD(td->hctd_cbp);
9661 9661          end_addr = Get_TD(td->hctd_buf_end);
9662 9662  
9663 9663          if ((buf_addr & 0xfffff000) ==
9664 9664              (end_addr & 0xfffff000)) {
9665 9665                  residue = end_addr - buf_addr + 1;
9666 9666          } else {
9667 9667                  residue = OHCI_MAX_TD_BUF_SIZE -
9668 9668                      (buf_addr & 0x00000fff) +
9669 9669                      (end_addr & 0x00000fff) + 1;
9670 9670          }
9671 9671  
9672 9672          return (residue);
9673 9673  }
9674 9674  
9675 9675  
9676 9676  /*
9677 9677   * Miscellaneous functions
9678 9678   */
9679 9679  
9680 9680  /*
9681 9681   * ohci_obtain_state:
9682 9682   * NOTE: This function is also called from POLLED MODE.
9683 9683   */
9684 9684  ohci_state_t *
9685 9685  ohci_obtain_state(dev_info_t    *dip)
9686 9686  {
9687 9687          int                     instance = ddi_get_instance(dip);
9688 9688          ohci_state_t            *state = ddi_get_soft_state(
9689 9689              ohci_statep, instance);
9690 9690  
9691 9691          ASSERT(state != NULL);
9692 9692  
9693 9693          return (state);
9694 9694  }
9695 9695  
9696 9696  
9697 9697  /*
9698 9698   * ohci_state_is_operational:
9699 9699   *
9700 9700   * Check the Host controller state and return proper values.
9701 9701   */
9702 9702  int
9703 9703  ohci_state_is_operational(ohci_state_t  *ohcip)
9704 9704  {
9705 9705          int                             val;
9706 9706  
9707 9707          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9708 9708  
9709 9709          switch (ohcip->ohci_hc_soft_state) {
9710 9710          case OHCI_CTLR_INIT_STATE:
9711 9711          case OHCI_CTLR_SUSPEND_STATE:
9712 9712                  val = USB_FAILURE;
9713 9713                  break;
9714 9714          case OHCI_CTLR_OPERATIONAL_STATE:
9715 9715                  val = USB_SUCCESS;
9716 9716                  break;
9717 9717          case OHCI_CTLR_ERROR_STATE:
9718 9718                  val = USB_HC_HARDWARE_ERROR;
9719 9719                  break;
9720 9720          default:
9721 9721                  val = USB_FAILURE;
9722 9722                  break;
9723 9723          }
9724 9724  
9725 9725          return (val);
9726 9726  }
9727 9727  
9728 9728  
9729 9729  /*
9730 9730   * ohci_do_soft_reset
9731 9731   *
9732 9732   * Do soft reset of ohci host controller.
9733 9733   */
9734 9734  int
9735 9735  ohci_do_soft_reset(ohci_state_t *ohcip)
9736 9736  {
9737 9737          usb_frame_number_t      before_frame_number, after_frame_number;
9738 9738          timeout_id_t            xfer_timer_id, rh_timer_id;
9739 9739          ohci_regs_t             *ohci_save_regs;
9740 9740          ohci_td_t               *done_head;
9741 9741  
9742 9742          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9743 9743  
9744 9744          /* Increment host controller error count */
9745 9745          ohcip->ohci_hc_error++;
9746 9746  
9747 9747          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9748 9748              "ohci_do_soft_reset:"
9749 9749              "Reset ohci host controller 0x%x", ohcip->ohci_hc_error);
9750 9750  
9751 9751          /*
9752 9752           * Allocate space for saving current Host Controller
9753 9753           * registers. Don't do any recovery if allocation
9754 9754           * fails.
9755 9755           */
9756 9756          ohci_save_regs = (ohci_regs_t *)
9757 9757              kmem_zalloc(sizeof (ohci_regs_t), KM_NOSLEEP);
9758 9758  
9759 9759          if (ohci_save_regs == NULL) {
9760 9760                  USB_DPRINTF_L2(PRINT_MASK_INTR,  ohcip->ohci_log_hdl,
9761 9761                      "ohci_do_soft_reset: kmem_zalloc failed");
9762 9762  
9763 9763                  return (USB_FAILURE);
9764 9764          }
9765 9765  
9766 9766          /* Save current ohci registers */
9767 9767          ohci_save_regs->hcr_control = Get_OpReg(hcr_control);
9768 9768          ohci_save_regs->hcr_cmd_status = Get_OpReg(hcr_cmd_status);
9769 9769          ohci_save_regs->hcr_intr_enable = Get_OpReg(hcr_intr_enable);
9770 9770          ohci_save_regs->hcr_periodic_strt = Get_OpReg(hcr_periodic_strt);
9771 9771          ohci_save_regs->hcr_frame_interval = Get_OpReg(hcr_frame_interval);
9772 9772          ohci_save_regs->hcr_HCCA = Get_OpReg(hcr_HCCA);
9773 9773          ohci_save_regs->hcr_bulk_head = Get_OpReg(hcr_bulk_head);
9774 9774          ohci_save_regs->hcr_ctrl_head = Get_OpReg(hcr_ctrl_head);
9775 9775  
9776 9776          USB_DPRINTF_L4(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9777 9777              "ohci_do_soft_reset: Save reg = 0x%p", (void *)ohci_save_regs);
9778 9778  
9779 9779          /* Disable all list processing and interrupts */
9780 9780          Set_OpReg(hcr_control, (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
9781 9781              HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
9782 9782  
9783 9783          Set_OpReg(hcr_intr_disable, HCR_INTR_SO |
9784 9784              HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE |
9785 9785              HCR_INTR_FNO | HCR_INTR_SOF | HCR_INTR_MIE);
9786 9786  
9787 9787          /* Wait for few milliseconds */
9788 9788          drv_usecwait(OHCI_TIMEWAIT);
9789 9789  
9790 9790          /* Root hub interrupt pipe timeout id */
9791 9791          rh_timer_id = ohcip->ohci_root_hub.rh_intr_pipe_timer_id;
9792 9792  
9793 9793          /* Stop the root hub interrupt timer */
9794 9794          if (rh_timer_id) {
9795 9795                  ohcip->ohci_root_hub.rh_intr_pipe_timer_id = 0;
9796 9796                  ohcip->ohci_root_hub.rh_intr_pipe_state =
9797 9797                      OHCI_PIPE_STATE_IDLE;
9798 9798  
9799 9799                  mutex_exit(&ohcip->ohci_int_mutex);
9800 9800                  (void) untimeout(rh_timer_id);
9801 9801                  mutex_enter(&ohcip->ohci_int_mutex);
9802 9802          }
9803 9803  
9804 9804          /* Transfer timeout id */
9805 9805          xfer_timer_id = ohcip->ohci_timer_id;
9806 9806  
9807 9807          /* Stop the global transfer timer */
9808 9808          if (xfer_timer_id) {
9809 9809                  ohcip->ohci_timer_id = 0;
9810 9810                  mutex_exit(&ohcip->ohci_int_mutex);
9811 9811                  (void) untimeout(xfer_timer_id);
9812 9812                  mutex_enter(&ohcip->ohci_int_mutex);
9813 9813          }
9814 9814  
9815 9815          /* Process any pending HCCA DoneHead */
9816 9816          done_head = (ohci_td_t *)(uintptr_t)
9817 9817              (Get_HCCA(ohcip->ohci_hccap->HccaDoneHead) & HCCA_DONE_HEAD_MASK);
9818 9818  
9819 9819          if (ohci_check_done_head(ohcip, done_head) == USB_SUCCESS) {
9820 9820                  /* Reset the done head to NULL */
9821 9821                  Set_HCCA(ohcip->ohci_hccap->HccaDoneHead, NULL);
9822 9822  
9823 9823                  ohci_traverse_done_list(ohcip, done_head);
9824 9824          }
9825 9825  
9826 9826          /* Process any pending hcr_done_head value */
9827 9827          done_head = (ohci_td_t *)(uintptr_t)
9828 9828              (Get_OpReg(hcr_done_head) & HCCA_DONE_HEAD_MASK);
9829 9829          if (ohci_check_done_head(ohcip, done_head) == USB_SUCCESS) {
9830 9830  
9831 9831                  ohci_traverse_done_list(ohcip, done_head);
9832 9832          }
9833 9833  
9834 9834          /* Do soft reset of ohci host controller */
9835 9835          Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
9836 9836  
9837 9837          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9838 9838              "ohci_do_soft_reset: Reset in progress");
9839 9839  
9840 9840          /* Wait for reset to complete */
9841 9841          drv_usecwait(OHCI_RESET_TIMEWAIT);
9842 9842  
9843 9843          /* Reset HCCA HcFrameNumber */
9844 9844          Set_HCCA(ohcip->ohci_hccap->HccaFrameNo, 0x00000000);
9845 9845  
9846 9846          /*
9847 9847           * Restore previous saved HC register value
9848 9848           * into the current HC registers.
9849 9849           */
9850 9850          Set_OpReg(hcr_periodic_strt, (uint32_t)
9851 9851              ohci_save_regs->hcr_periodic_strt);
9852 9852  
9853 9853          Set_OpReg(hcr_frame_interval, (uint32_t)
9854 9854              ohci_save_regs->hcr_frame_interval);
9855 9855  
9856 9856          Set_OpReg(hcr_done_head, 0x0);
9857 9857  
9858 9858          Set_OpReg(hcr_bulk_curr, 0x0);
9859 9859  
9860 9860          Set_OpReg(hcr_bulk_head, (uint32_t)
9861 9861              ohci_save_regs->hcr_bulk_head);
9862 9862  
9863 9863          Set_OpReg(hcr_ctrl_curr, 0x0);
9864 9864  
9865 9865          Set_OpReg(hcr_ctrl_head, (uint32_t)
9866 9866              ohci_save_regs->hcr_ctrl_head);
9867 9867  
9868 9868          Set_OpReg(hcr_periodic_curr, 0x0);
9869 9869  
9870 9870          Set_OpReg(hcr_HCCA, (uint32_t)
9871 9871              ohci_save_regs->hcr_HCCA);
9872 9872  
9873 9873          Set_OpReg(hcr_intr_status, 0x0);
9874 9874  
9875 9875          /*
9876 9876           * Set HcInterruptEnable to enable all interrupts except
9877 9877           * Root Hub Status change interrupt.
9878 9878           */
9879 9879          Set_OpReg(hcr_intr_enable,
9880 9880              HCR_INTR_SO | HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE |
9881 9881              HCR_INTR_FNO | HCR_INTR_SOF | HCR_INTR_MIE);
9882 9882  
9883 9883          /* Start Control and Bulk list processing */
9884 9884          Set_OpReg(hcr_cmd_status, (HCR_STATUS_CLF | HCR_STATUS_BLF));
9885 9885  
9886 9886          /*
9887 9887           * Start up Control, Bulk, Periodic and Isochronous lists
9888 9888           * processing.
9889 9889           */
9890 9890          Set_OpReg(hcr_control, (uint32_t)
9891 9891              (ohci_save_regs->hcr_control & (~HCR_CONTROL_HCFS)));
9892 9892  
9893 9893          /*
9894 9894           * Deallocate the space that allocated for saving
9895 9895           * HC registers.
9896 9896           */
9897 9897          kmem_free((void *) ohci_save_regs, sizeof (ohci_regs_t));
9898 9898  
9899 9899          /* Resume the host controller */
9900 9900          Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
9901 9901              (~HCR_CONTROL_HCFS)) | HCR_CONTROL_RESUME));
9902 9902  
9903 9903          /* Wait for resume to complete */
9904 9904          drv_usecwait(OHCI_RESUME_TIMEWAIT);
9905 9905  
9906 9906          /* Set the Host Controller Functional State to Operational */
9907 9907          Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
9908 9908              (~HCR_CONTROL_HCFS)) | HCR_CONTROL_OPERAT));
9909 9909  
9910 9910          /* Wait 10ms for HC to start sending SOF */
9911 9911          drv_usecwait(OHCI_TIMEWAIT);
9912 9912  
9913 9913          /*
9914 9914           * Get the current usb frame number before waiting for few
9915 9915           * milliseconds.
9916 9916           */
9917 9917          before_frame_number = ohci_get_current_frame_number(ohcip);
9918 9918  
9919 9919          /* Wait for few milliseconds */
9920 9920          drv_usecwait(OHCI_TIMEWAIT);
9921 9921  
9922 9922          /*
9923 9923           * Get the current usb frame number after waiting for few
9924 9924           * milliseconds.
9925 9925           */
9926 9926          after_frame_number = ohci_get_current_frame_number(ohcip);
9927 9927  
9928 9928          USB_DPRINTF_L3(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9929 9929              "ohci_do_soft_reset: Before Frm No 0x%llx After Frm No 0x%llx",
9930 9930              (unsigned long long)before_frame_number,
9931 9931              (unsigned long long)after_frame_number);
9932 9932  
9933 9933          if (after_frame_number <= before_frame_number) {
9934 9934  
9935 9935                  USB_DPRINTF_L2(PRINT_MASK_INTR, ohcip->ohci_log_hdl,
9936 9936                      "ohci_do_soft_reset: Soft reset failed");
9937 9937  
9938 9938                  return (USB_FAILURE);
9939 9939          }
9940 9940  
9941 9941          /* Start the timer for the root hub interrupt pipe polling */
9942 9942          if (rh_timer_id) {
9943 9943                  ohcip->ohci_root_hub.rh_intr_pipe_timer_id =
9944 9944                      timeout(ohci_handle_root_hub_status_change,
9945 9945                      (void *)ohcip, drv_usectohz(OHCI_RH_POLL_TIME));
9946 9946  
9947 9947                  ohcip->ohci_root_hub.
9948 9948                      rh_intr_pipe_state = OHCI_PIPE_STATE_ACTIVE;
9949 9949          }
9950 9950  
9951 9951          /* Start the global timer */
9952 9952          if (xfer_timer_id) {
9953 9953                  ohcip->ohci_timer_id = timeout(ohci_xfer_timeout_handler,
9954 9954                      (void *)ohcip, drv_usectohz(1000000));
9955 9955          }
9956 9956  
9957 9957          return (USB_SUCCESS);
9958 9958  }
9959 9959  
9960 9960  
9961 9961  /*
9962 9962   * ohci_get_current_frame_number:
9963 9963   *
9964 9964   * Get the current software based usb frame number.
9965 9965   */
9966 9966  usb_frame_number_t
9967 9967  ohci_get_current_frame_number(ohci_state_t *ohcip)
9968 9968  {
9969 9969          usb_frame_number_t      usb_frame_number;
9970 9970          usb_frame_number_t      ohci_fno, frame_number;
9971 9971          ohci_save_intr_sts_t    *ohci_intr_sts =
9972 9972              &ohcip->ohci_save_intr_sts;
9973 9973  
9974 9974          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
9975 9975  
9976 9976          /*
9977 9977           * Sync HCCA area only if this function
9978 9978           * is invoked in non interrupt context.
9979 9979           */
9980 9980          if (!(ohci_intr_sts->ohci_intr_flag &
9981 9981              OHCI_INTR_HANDLING)) {
9982 9982  
9983 9983                  /* Sync HCCA area */
9984 9984                  Sync_HCCA(ohcip);
9985 9985          }
9986 9986  
9987 9987          ohci_fno = ohcip->ohci_fno;
9988 9988          frame_number = Get_HCCA(ohcip->ohci_hccap->HccaFrameNo);
9989 9989  
9990 9990          /*
9991 9991           * Calculate current software based usb frame number.
9992 9992           *
9993 9993           * This code accounts for the fact that frame number is
9994 9994           * updated by the Host Controller before the ohci driver
9995 9995           * gets an FrameNumberOverflow (FNO) interrupt that will
9996 9996           * adjust Frame higher part.
9997 9997           *
9998 9998           * Refer ohci specification 1.0a, section 5.4, page 86.
9999 9999           */
10000 10000          usb_frame_number = ((frame_number & 0x7FFF) | ohci_fno) +
10001 10001              (((frame_number & 0xFFFF) ^ ohci_fno) & 0x8000);
10002 10002  
10003 10003          return (usb_frame_number);
10004 10004  }
10005 10005  
10006 10006  
10007 10007  /*
10008 10008   * ohci_cpr_cleanup:
10009 10009   *
10010 10010   * Cleanup ohci state and other ohci specific informations across
10011 10011   * Check Point Resume (CPR).
10012 10012   */
10013 10013  static  void
10014 10014  ohci_cpr_cleanup(ohci_state_t *ohcip)
10015 10015  {
10016 10016          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10017 10017  
10018 10018          /* Reset software part of usb frame number */
10019 10019          ohcip->ohci_fno = 0;
10020 10020  
10021 10021          /* Reset Schedule Overrrun Error Counter */
10022 10022          ohcip->ohci_so_error = 0;
10023 10023  
10024 10024          /* Reset HCCA HcFrameNumber */
10025 10025          Set_HCCA(ohcip->ohci_hccap->HccaFrameNo, 0x00000000);
10026 10026  }
10027 10027  
10028 10028  
10029 10029  /*
10030 10030   * ohci_get_xfer_attrs:
10031 10031   *
10032 10032   * Get the attributes of a particular xfer.
10033 10033   */
10034 10034  static usb_req_attrs_t
10035 10035  ohci_get_xfer_attrs(
10036 10036          ohci_state_t            *ohcip,
10037 10037          ohci_pipe_private_t     *pp,
10038 10038          ohci_trans_wrapper_t    *tw)
10039 10039  {
10040 10040          usb_ep_descr_t          *eptd = &pp->pp_pipe_handle->p_ep;
10041 10041          usb_req_attrs_t         attrs = 0;
10042 10042  
10043 10043          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10044 10044              "ohci_get_xfer_attrs:");
10045 10045  
10046 10046          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10047 10047  
10048 10048          switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
10049 10049          case USB_EP_ATTR_CONTROL:
10050 10050                  attrs = ((usb_ctrl_req_t *)
10051 10051                      tw->tw_curr_xfer_reqp)->ctrl_attributes;
10052 10052                  break;
10053 10053          case USB_EP_ATTR_BULK:
10054 10054                  attrs = ((usb_bulk_req_t *)
10055 10055                      tw->tw_curr_xfer_reqp)->bulk_attributes;
10056 10056                  break;
10057 10057          case USB_EP_ATTR_INTR:
10058 10058                  attrs = ((usb_intr_req_t *)
10059 10059                      tw->tw_curr_xfer_reqp)->intr_attributes;
10060 10060                  break;
10061 10061          case USB_EP_ATTR_ISOCH:
10062 10062                  attrs = ((usb_isoc_req_t *)
10063 10063                      tw->tw_curr_xfer_reqp)->isoc_attributes;
10064 10064                  break;
10065 10065          }
10066 10066  
10067 10067          return (attrs);
10068 10068  }
10069 10069  
10070 10070  
10071 10071  /*
10072 10072   * ohci_allocate_periodic_in_resource
10073 10073   *
10074 10074   * Allocate interrupt/isochronous request structure for the
10075 10075   * interrupt/isochronous IN transfer.
10076 10076   */
10077 10077  static int
10078 10078  ohci_allocate_periodic_in_resource(
10079 10079          ohci_state_t            *ohcip,
10080 10080          ohci_pipe_private_t     *pp,
10081 10081          ohci_trans_wrapper_t    *tw,
10082 10082          usb_flags_t             flags)
10083 10083  {
10084 10084          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10085 10085          uchar_t                 ep_attr = ph->p_ep.bmAttributes;
10086 10086          usb_intr_req_t          *curr_intr_reqp;
10087 10087          usb_isoc_req_t          *curr_isoc_reqp;
10088 10088          usb_opaque_t            client_periodic_in_reqp;
10089 10089          size_t                  length = 0;
10090 10090  
10091 10091          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10092 10092              "ohci_allocate_periodic_in_resource:"
10093 10093              "pp = 0x%p tw = 0x%p flags = 0x%x", (void *)pp, (void *)tw, flags);
10094 10094  
10095 10095          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10096 10096          ASSERT(tw->tw_curr_xfer_reqp == NULL);
10097 10097  
10098 10098          /* Get the client periodic in request pointer */
10099 10099          client_periodic_in_reqp = pp->pp_client_periodic_in_reqp;
10100 10100  
10101 10101          /*
10102 10102           * If it a periodic IN request and periodic request is NULL,
10103 10103           * allocate corresponding usb periodic IN request for the
10104 10104           * current periodic polling request and copy the information
10105 10105           * from the saved periodic request structure.
10106 10106           */
10107 10107          if ((ep_attr & USB_EP_ATTR_MASK) == USB_EP_ATTR_INTR) {
10108 10108  
10109 10109                  if (client_periodic_in_reqp) {
10110 10110  
10111 10111                          /* Get the interrupt transfer length */
10112 10112                          length = ((usb_intr_req_t *)
10113 10113                              client_periodic_in_reqp)->intr_len;
10114 10114  
10115 10115                          curr_intr_reqp = usba_hcdi_dup_intr_req(
10116 10116                              ph->p_dip, (usb_intr_req_t *)
10117 10117                              client_periodic_in_reqp, length, flags);
10118 10118                  } else {
10119 10119                          curr_intr_reqp = usb_alloc_intr_req(
10120 10120                              ph->p_dip, length, flags);
10121 10121                  }
10122 10122  
10123 10123                  if (curr_intr_reqp == NULL) {
10124 10124  
10125 10125                          USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10126 10126                              "ohci_allocate_periodic_in_resource: Interrupt "
10127 10127                              "request structure allocation failed");
10128 10128  
10129 10129                          return (USB_NO_RESOURCES);
10130 10130                  }
10131 10131  
10132 10132                  if (client_periodic_in_reqp == NULL) {
10133 10133                          /* For polled mode */
10134 10134                          curr_intr_reqp->
10135 10135                              intr_attributes = USB_ATTRS_SHORT_XFER_OK;
10136 10136                          curr_intr_reqp->
10137 10137                              intr_len = ph->p_ep.wMaxPacketSize;
10138 10138                  } else {
10139 10139                          /* Check and save the timeout value */
10140 10140                          tw->tw_timeout = (curr_intr_reqp->intr_attributes &
10141 10141                              USB_ATTRS_ONE_XFER) ?
10142 10142                              curr_intr_reqp->intr_timeout: 0;
10143 10143                  }
10144 10144  
10145 10145                  tw->tw_curr_xfer_reqp = (usb_opaque_t)curr_intr_reqp;
10146 10146                  tw->tw_length = curr_intr_reqp->intr_len;
10147 10147          } else {
10148 10148                  ASSERT(client_periodic_in_reqp != NULL);
10149 10149  
10150 10150                  curr_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip,
10151 10151                      (usb_isoc_req_t *)client_periodic_in_reqp, flags);
10152 10152  
10153 10153                  if (curr_isoc_reqp == NULL) {
10154 10154  
10155 10155                          USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10156 10156                              "ohci_allocate_periodic_in_resource: Isochronous"
10157 10157                              "request structure allocation failed");
10158 10158  
10159 10159                          return (USB_NO_RESOURCES);
10160 10160                  }
10161 10161  
10162 10162                  /*
10163 10163                   * Save the client's isochronous request pointer and
10164 10164                   * length of isochronous transfer in transfer wrapper.
10165 10165                   * The dup'ed request is saved in pp_client_periodic_in_reqp
10166 10166                   */
10167 10167                  tw->tw_curr_xfer_reqp =
10168 10168                      (usb_opaque_t)pp->pp_client_periodic_in_reqp;
10169 10169                  pp->pp_client_periodic_in_reqp = (usb_opaque_t)curr_isoc_reqp;
10170 10170          }
10171 10171  
10172 10172          mutex_enter(&ph->p_mutex);
10173 10173          ph->p_req_count++;
10174 10174          mutex_exit(&ph->p_mutex);
10175 10175  
10176 10176          pp->pp_state = OHCI_PIPE_STATE_ACTIVE;
10177 10177  
10178 10178          return (USB_SUCCESS);
10179 10179  }
10180 10180  
10181 10181  
10182 10182  /*
10183 10183   * ohci_wait_for_sof:
10184 10184   *
10185 10185   * Wait for couple of SOF interrupts
10186 10186   */
10187 10187  static int
10188 10188  ohci_wait_for_sof(ohci_state_t  *ohcip)
10189 10189  {
10190 10190          usb_frame_number_t      before_frame_number, after_frame_number;
10191 10191          clock_t                 sof_time_wait;
10192 10192          int                     rval, sof_wait_count;
10193 10193  
10194 10194          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10195 10195              "ohci_wait_for_sof");
10196 10196  
10197 10197          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10198 10198  
10199 10199          rval = ohci_state_is_operational(ohcip);
10200 10200  
10201 10201          if (rval != USB_SUCCESS) {
10202 10202  
10203 10203                  return (rval);
10204 10204          }
10205 10205  
10206 10206          /* Get the number of clock ticks to wait */
10207 10207          sof_time_wait = drv_usectohz(OHCI_MAX_SOF_TIMEWAIT * 1000000);
10208 10208  
10209 10209          sof_wait_count = 0;
10210 10210  
10211 10211          /*
10212 10212           * Get the current usb frame number before waiting for the
10213 10213           * SOF interrupt event.
10214 10214           */
10215 10215          before_frame_number = ohci_get_current_frame_number(ohcip);
10216 10216  
10217 10217          while (sof_wait_count < MAX_SOF_WAIT_COUNT) {
10218 10218                  /* Enable the SOF interrupt */
10219 10219                  Set_OpReg(hcr_intr_enable, HCR_INTR_SOF);
10220 10220  
10221 10221                  ASSERT(Get_OpReg(hcr_intr_enable) & HCR_INTR_SOF);
10222 10222  
10223 10223                  /* Wait for the SOF or timeout event */
10224 10224                  rval = cv_reltimedwait(&ohcip->ohci_SOF_cv,
10225 10225                      &ohcip->ohci_int_mutex, sof_time_wait, TR_CLOCK_TICK);
10226 10226  
10227 10227                  /*
10228 10228                   * Get the current usb frame number after woken up either
10229 10229                   * from SOF interrupt or timer expired event.
10230 10230                   */
10231 10231                  after_frame_number = ohci_get_current_frame_number(ohcip);
10232 10232  
10233 10233                  USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10234 10234                      "ohci_wait_for_sof: before 0x%llx, after 0x%llx",
10235 10235                      (unsigned long long)before_frame_number,
10236 10236                      (unsigned long long)after_frame_number);
10237 10237  
10238 10238                  /*
10239 10239                   * Return failure, if we are woken up becuase of timer expired
10240 10240                   * event and if usb frame number has not been changed.
10241 10241                   */
10242 10242                  if ((rval == -1) &&
10243 10243                      (after_frame_number <= before_frame_number)) {
10244 10244  
10245 10245                          if ((ohci_do_soft_reset(ohcip)) != USB_SUCCESS) {
10246 10246  
10247 10247                                  USB_DPRINTF_L0(PRINT_MASK_LISTS,
10248 10248                                      ohcip->ohci_log_hdl, "No SOF interrupts");
10249 10249  
10250 10250                                  /* Set host controller soft state to error */
10251 10251                                  ohcip->ohci_hc_soft_state =
10252 10252                                      OHCI_CTLR_ERROR_STATE;
10253 10253  
10254 10254                                  return (USB_FAILURE);
10255 10255                          }
10256 10256  
10257 10257                          /* Get new usb frame number */
10258 10258                          after_frame_number = before_frame_number =
10259 10259                              ohci_get_current_frame_number(ohcip);
10260 10260                  }
10261 10261  
10262 10262                  ASSERT(after_frame_number >= before_frame_number);
10263 10263  
10264 10264                  before_frame_number = after_frame_number;
10265 10265                  sof_wait_count++;
10266 10266          }
10267 10267  
10268 10268          return (USB_SUCCESS);
10269 10269  }
10270 10270  
10271 10271  
10272 10272  /*
10273 10273   * ohci_pipe_cleanup
10274 10274   *
10275 10275   * Cleanup ohci pipe.
10276 10276   */
10277 10277  static void
10278 10278  ohci_pipe_cleanup(
10279 10279          ohci_state_t            *ohcip,
10280 10280          usba_pipe_handle_data_t *ph)
10281 10281  {
10282 10282          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10283 10283          usb_ep_descr_t          *eptd = &ph->p_ep;
10284 10284          usb_cr_t                completion_reason;
10285 10285          uint_t                  pipe_state = pp->pp_state;
10286 10286          uint_t                  bit = 0;
10287 10287  
10288 10288          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10289 10289              "ohci_pipe_cleanup: ph = 0x%p", (void *)ph);
10290 10290  
10291 10291          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10292 10292  
10293 10293          switch (pipe_state) {
10294 10294          case OHCI_PIPE_STATE_CLOSE:
10295 10295                  if (OHCI_NON_PERIODIC_ENDPOINT(eptd)) {
10296 10296  
10297 10297                          bit = ((eptd->bmAttributes &
10298 10298                              USB_EP_ATTR_MASK) == USB_EP_ATTR_CONTROL) ?
10299 10299                              HCR_CONTROL_CLE: HCR_CONTROL_BLE;
10300 10300  
10301 10301                          Set_OpReg(hcr_control,
10302 10302                              (Get_OpReg(hcr_control) & ~(bit)));
10303 10303  
10304 10304                          /* Wait for the next SOF */
10305 10305                          (void) ohci_wait_for_sof(ohcip);
10306 10306  
10307 10307                          break;
10308 10308                  }
10309 10309                  /* FALLTHROUGH */
10310 10310          case OHCI_PIPE_STATE_RESET:
10311 10311          case OHCI_PIPE_STATE_STOP_POLLING:
10312 10312                  /*
10313 10313                   * Set the sKip bit to stop all transactions on
10314 10314                   * this pipe
10315 10315                   */
10316 10316                  ohci_modify_sKip_bit(ohcip, pp, SET_sKip,
10317 10317                      OHCI_FLAGS_SLEEP | OHCI_FLAGS_DMA_SYNC);
10318 10318  
10319 10319                  break;
10320 10320          default:
10321 10321                  return;
10322 10322          }
10323 10323  
10324 10324          /*
10325 10325           * Wait for processing all completed transfers and
10326 10326           * to send results to upstream.
10327 10327           */
10328 10328          ohci_wait_for_transfers_completion(ohcip, pp);
10329 10329  
10330 10330          /* Save the data toggle information */
10331 10331          ohci_save_data_toggle(ohcip, ph);
10332 10332  
10333 10333          /*
10334 10334           * Traverse the list of TD's on this endpoint and
10335 10335           * these TD's have outstanding transfer requests.
10336 10336           * Since the list processing is stopped, these tds
10337 10337           * can be deallocated.
10338 10338           */
10339 10339          ohci_traverse_tds(ohcip, ph);
10340 10340  
10341 10341          /*
10342 10342           * If all of the endpoint's TD's have been deallocated,
10343 10343           * then the DMA mappings can be torn down. If not there
10344 10344           * are some TD's on the  done list that have not been
10345 10345           * processed. Tag these TD's  so that they are thrown
10346 10346           * away when the done list is processed.
10347 10347           */
10348 10348          ohci_done_list_tds(ohcip, ph);
10349 10349  
10350 10350          /* Do callbacks for all unfinished requests */
10351 10351          ohci_handle_outstanding_requests(ohcip, pp);
10352 10352  
10353 10353          /* Free DMA resources */
10354 10354          ohci_free_dma_resources(ohcip, ph);
10355 10355  
10356 10356          switch (pipe_state) {
10357 10357          case OHCI_PIPE_STATE_CLOSE:
10358 10358                  completion_reason = USB_CR_PIPE_CLOSING;
10359 10359                  break;
10360 10360          case OHCI_PIPE_STATE_RESET:
10361 10361          case OHCI_PIPE_STATE_STOP_POLLING:
10362 10362                  /* Set completion reason */
10363 10363                  completion_reason = (pipe_state ==
10364 10364                      OHCI_PIPE_STATE_RESET) ?
10365 10365                      USB_CR_PIPE_RESET: USB_CR_STOPPED_POLLING;
10366 10366  
10367 10367                  /* Restore the data toggle information */
10368 10368                  ohci_restore_data_toggle(ohcip, ph);
10369 10369  
10370 10370                  /*
10371 10371                   * Clear the sKip bit to restart all the
10372 10372                   * transactions on this pipe.
10373 10373                   */
10374 10374                  ohci_modify_sKip_bit(ohcip, pp,
10375 10375                      CLEAR_sKip, OHCI_FLAGS_NOSLEEP);
10376 10376  
10377 10377                  /* Set pipe state to idle */
10378 10378                  pp->pp_state = OHCI_PIPE_STATE_IDLE;
10379 10379  
10380 10380                  break;
10381 10381          }
10382 10382  
10383 10383          ASSERT((Get_ED(pp->pp_ept->hced_tailp) & HC_EPT_TD_TAIL) ==
10384 10384              (Get_ED(pp->pp_ept->hced_headp) & HC_EPT_TD_HEAD));
10385 10385  
10386 10386          ASSERT((pp->pp_tw_head == NULL) && (pp->pp_tw_tail == NULL));
10387 10387  
10388 10388          /*
10389 10389           * Do the callback for the original client
10390 10390           * periodic IN request.
10391 10391           */
10392 10392          if ((OHCI_PERIODIC_ENDPOINT(eptd)) &&
10393 10393              ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) ==
10394 10394              USB_EP_DIR_IN)) {
10395 10395  
10396 10396                  ohci_do_client_periodic_in_req_callback(
10397 10397                      ohcip, pp, completion_reason);
10398 10398          }
10399 10399  }
10400 10400  
10401 10401  
10402 10402  /*
10403 10403   * ohci_wait_for_transfers_completion:
10404 10404   *
10405 10405   * Wait for processing all completed transfers and to send results
10406 10406   * to upstream.
10407 10407   */
10408 10408  static void
10409 10409  ohci_wait_for_transfers_completion(
10410 10410          ohci_state_t            *ohcip,
10411 10411          ohci_pipe_private_t     *pp)
10412 10412  {
10413 10413          ohci_trans_wrapper_t    *head_tw = pp->pp_tw_head;
10414 10414          ohci_trans_wrapper_t    *next_tw;
10415 10415          ohci_td_t               *tailp, *headp, *nextp;
10416 10416          ohci_td_t               *head_td, *next_td;
10417 10417          ohci_ed_t               *ept = pp->pp_ept;
10418 10418          int                     rval;
10419 10419  
10420 10420          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10421 10421              "ohci_wait_for_transfers_completion: pp = 0x%p", (void *)pp);
10422 10422  
10423 10423          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10424 10424  
10425 10425          headp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10426 10426              Get_ED(ept->hced_headp) & (uint32_t)HC_EPT_TD_HEAD));
10427 10427  
10428 10428          tailp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10429 10429              Get_ED(ept->hced_tailp) & (uint32_t)HC_EPT_TD_TAIL));
10430 10430  
10431 10431          rval = ohci_state_is_operational(ohcip);
10432 10432  
10433 10433          if (rval != USB_SUCCESS) {
10434 10434  
10435 10435                  return;
10436 10436          }
10437 10437  
10438 10438          pp->pp_count_done_tds = 0;
10439 10439  
10440 10440          /* Process the transfer wrappers for this pipe */
10441 10441          next_tw = head_tw;
10442 10442          while (next_tw) {
10443 10443                  head_td = (ohci_td_t *)next_tw->tw_hctd_head;
10444 10444                  next_td = head_td;
10445 10445  
10446 10446                  if (head_td) {
10447 10447                          /*
10448 10448                           * Walk through each TD for this transfer
10449 10449                           * wrapper. If a TD still exists, then it
10450 10450                           * is currently on the done list.
10451 10451                           */
10452 10452                          while (next_td) {
10453 10453  
10454 10454                                  nextp = headp;
10455 10455  
10456 10456                                  while (nextp != tailp) {
10457 10457  
10458 10458                                          /* TD is on the ED */
10459 10459                                          if (nextp == next_td) {
10460 10460                                                  break;
10461 10461                                          }
10462 10462  
10463 10463                                          nextp = (ohci_td_t *)
10464 10464                                              (ohci_td_iommu_to_cpu(ohcip,
10465 10465                                              (Get_TD(nextp->hctd_next_td) &
10466 10466                                              HC_EPT_TD_TAIL)));
10467 10467                                  }
10468 10468  
10469 10469                                  if (nextp == tailp) {
10470 10470                                          pp->pp_count_done_tds++;
10471 10471                                  }
10472 10472  
10473 10473                                  next_td = ohci_td_iommu_to_cpu(ohcip,
10474 10474                                      Get_TD(next_td->hctd_tw_next_td));
10475 10475                          }
10476 10476                  }
10477 10477  
10478 10478                  next_tw = next_tw->tw_next;
10479 10479          }
10480 10480  
10481 10481          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10482 10482              "ohci_wait_for_transfers_completion: count_done_tds = 0x%x",
10483 10483              pp->pp_count_done_tds);
10484 10484  
10485 10485          if (!pp->pp_count_done_tds) {
10486 10486  
10487 10487                  return;
10488 10488          }
10489 10489  
10490 10490          (void) cv_reltimedwait(&pp->pp_xfer_cmpl_cv, &ohcip->ohci_int_mutex,
10491 10491              drv_usectohz(OHCI_XFER_CMPL_TIMEWAIT * 1000000), TR_CLOCK_TICK);
10492 10492  
10493 10493          if (pp->pp_count_done_tds) {
10494 10494  
10495 10495                  USB_DPRINTF_L2(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10496 10496                      "ohci_wait_for_transfers_completion: No transfers "
10497 10497                      "completion confirmation received for 0x%x requests",
10498 10498                      pp->pp_count_done_tds);
10499 10499          }
10500 10500  }
10501 10501  
10502 10502  
10503 10503  /*
10504 10504   * ohci_check_for_transfers_completion:
10505 10505   *
10506 10506   * Check whether anybody is waiting for transfers completion event. If so, send
10507 10507   * this event and also stop initiating any new transfers on this pipe.
10508 10508   */
10509 10509  static void
10510 10510  ohci_check_for_transfers_completion(
10511 10511          ohci_state_t            *ohcip,
10512 10512          ohci_pipe_private_t     *pp)
10513 10513  {
10514 10514          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10515 10515              "ohci_check_for_transfers_completion: pp = 0x%p", (void *)pp);
10516 10516  
10517 10517          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10518 10518  
10519 10519          if ((pp->pp_state == OHCI_PIPE_STATE_STOP_POLLING) &&
10520 10520              (pp->pp_error == USB_CR_NO_RESOURCES) &&
10521 10521              (pp->pp_cur_periodic_req_cnt == 0)) {
10522 10522  
10523 10523                  /* Reset pipe error to zero */
10524 10524                  pp->pp_error = 0;
10525 10525  
10526 10526                  /* Do callback for original request */
10527 10527                  ohci_do_client_periodic_in_req_callback(
10528 10528                      ohcip, pp, USB_CR_NO_RESOURCES);
10529 10529          }
10530 10530  
10531 10531          if (pp->pp_count_done_tds) {
10532 10532  
10533 10533                  USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10534 10534                      "ohci_check_for_transfers_completion:"
10535 10535                      "count_done_tds = 0x%x", pp->pp_count_done_tds);
10536 10536  
10537 10537                  /* Decrement the done td count */
10538 10538                  pp->pp_count_done_tds--;
10539 10539  
10540 10540                  if (!pp->pp_count_done_tds) {
10541 10541                          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10542 10542                              "ohci_check_for_transfers_completion:"
10543 10543                              "Sent transfers completion event pp = 0x%p",
10544 10544                              (void *)pp);
10545 10545  
10546 10546                          /* Send the transfer completion signal */
10547 10547                          cv_signal(&pp->pp_xfer_cmpl_cv);
10548 10548                  }
10549 10549          }
10550 10550  }
10551 10551  
10552 10552  
10553 10553  /*
10554 10554   * ohci_save_data_toggle:
10555 10555   *
10556 10556   * Save the data toggle information.
10557 10557   */
10558 10558  static void
10559 10559  ohci_save_data_toggle(
10560 10560          ohci_state_t            *ohcip,
10561 10561          usba_pipe_handle_data_t *ph)
10562 10562  {
10563 10563          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10564 10564          usb_ep_descr_t          *eptd = &ph->p_ep;
10565 10565          uint_t                  data_toggle;
10566 10566          usb_cr_t                error = pp->pp_error;
10567 10567          ohci_ed_t               *ed = pp->pp_ept;
10568 10568          ohci_td_t               *headp, *tailp;
10569 10569  
10570 10570          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10571 10571              "ohci_save_data_toggle: ph = 0x%p", (void *)ph);
10572 10572  
10573 10573          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10574 10574  
10575 10575          /* Reset the pipe error value */
10576 10576          pp->pp_error = USB_CR_OK;
10577 10577  
10578 10578          /* Return immediately if it is a control or isoc pipe */
10579 10579          if (((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
10580 10580              USB_EP_ATTR_CONTROL) || ((eptd->bmAttributes &
10581 10581              USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH)) {
10582 10582  
10583 10583                  return;
10584 10584          }
10585 10585  
10586 10586          headp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10587 10587              Get_ED(ed->hced_headp) & (uint32_t)HC_EPT_TD_HEAD));
10588 10588  
10589 10589          tailp = (ohci_td_t *)(ohci_td_iommu_to_cpu(ohcip,
10590 10590              Get_ED(ed->hced_tailp) & (uint32_t)HC_EPT_TD_TAIL));
10591 10591  
10592 10592          /*
10593 10593           * Retrieve the data toggle information either from the endpoint
10594 10594           * (ED) or from the transfer descriptor (TD) depending on the
10595 10595           * situation.
10596 10596           */
10597 10597          if ((Get_ED(ed->hced_headp) & HC_EPT_Halt) || (headp == tailp)) {
10598 10598  
10599 10599                  /* Get the data toggle information from the endpoint */
10600 10600                  data_toggle = (Get_ED(ed->hced_headp) &
10601 10601                      HC_EPT_Carry)? DATA1:DATA0;
10602 10602          } else {
10603 10603                  /*
10604 10604                   * Retrieve the data toggle information depending on the
10605 10605                   * master data toggle information saved in  the transfer
10606 10606                   * descriptor (TD) at the head of the endpoint (ED).
10607 10607                   *
10608 10608                   * Check for master data toggle information .
10609 10609                   */
10610 10610                  if (Get_TD(headp->hctd_ctrl) & HC_TD_MS_DT) {
10611 10611                          /* Get the data toggle information from td */
10612 10612                          data_toggle = (Get_TD(headp->hctd_ctrl) &
10613 10613                              HC_TD_DT_1) ? DATA1:DATA0;
10614 10614                  } else {
10615 10615                          /* Get the data toggle information from the endpoint */
10616 10616                          data_toggle = (Get_ED(ed->hced_headp) &
10617 10617                              HC_EPT_Carry)? DATA1:DATA0;
10618 10618                  }
10619 10619          }
10620 10620  
10621 10621          /*
10622 10622           * If error is STALL, then, set
10623 10623           * data toggle to zero.
10624 10624           */
10625 10625          if (error == USB_CR_STALL) {
10626 10626                  data_toggle = DATA0;
10627 10627          }
10628 10628  
10629 10629          /*
10630 10630           * Save the data toggle information
10631 10631           * in the usb device structure.
10632 10632           */
10633 10633          mutex_enter(&ph->p_mutex);
10634 10634          usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
10635 10635              data_toggle);
10636 10636          mutex_exit(&ph->p_mutex);
10637 10637  }
10638 10638  
10639 10639  
10640 10640  /*
10641 10641   * ohci_restore_data_toggle:
10642 10642   *
10643 10643   * Restore the data toggle information.
10644 10644   */
10645 10645  static void
10646 10646  ohci_restore_data_toggle(
10647 10647          ohci_state_t            *ohcip,
10648 10648          usba_pipe_handle_data_t *ph)
10649 10649  {
10650 10650          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10651 10651          usb_ep_descr_t          *eptd = &ph->p_ep;
10652 10652          uint_t                  data_toggle = 0;
10653 10653  
10654 10654          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10655 10655              "ohci_restore_data_toggle: ph = 0x%p", (void *)ph);
10656 10656  
10657 10657          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10658 10658  
10659 10659          /*
10660 10660           * Return immediately if it is a control or isoc pipe.
10661 10661           */
10662 10662          if (((eptd->bmAttributes & USB_EP_ATTR_MASK) ==
10663 10663              USB_EP_ATTR_CONTROL) || ((eptd->bmAttributes &
10664 10664              USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH)) {
10665 10665  
10666 10666                  return;
10667 10667          }
10668 10668  
10669 10669          mutex_enter(&ph->p_mutex);
10670 10670  
10671 10671          data_toggle = usba_hcdi_get_data_toggle(ph->p_usba_device,
10672 10672              ph->p_ep.bEndpointAddress);
10673 10673          usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress,
10674 10674              0);
10675 10675  
10676 10676          mutex_exit(&ph->p_mutex);
10677 10677  
10678 10678          /*
10679 10679           * Restore the data toggle bit depending on the
10680 10680           * previous data toggle information.
10681 10681           */
10682 10682          if (data_toggle) {
10683 10683                  Set_ED(pp->pp_ept->hced_headp,
10684 10684                      Get_ED(pp->pp_ept->hced_headp) | HC_EPT_Carry);
10685 10685          } else {
10686 10686                  Set_ED(pp->pp_ept->hced_headp,
10687 10687                      Get_ED(pp->pp_ept->hced_headp) & (~HC_EPT_Carry));
10688 10688          }
10689 10689  }
10690 10690  
10691 10691  
10692 10692  /*
10693 10693   * ohci_handle_outstanding_requests
10694 10694   * NOTE: This function is also called from POLLED MODE.
10695 10695   *
10696 10696   * Deallocate interrupt/isochronous request structure for the
10697 10697   * interrupt/isochronous IN transfer. Do the callbacks for all
10698 10698   * unfinished requests.
10699 10699   */
10700 10700  void
10701 10701  ohci_handle_outstanding_requests(
10702 10702          ohci_state_t            *ohcip,
10703 10703          ohci_pipe_private_t     *pp)
10704 10704  {
10705 10705          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10706 10706          usb_ep_descr_t  *eptd = &ph->p_ep;
10707 10707          ohci_trans_wrapper_t    *curr_tw;
10708 10708          ohci_trans_wrapper_t    *next_tw;
10709 10709          usb_opaque_t            curr_xfer_reqp;
10710 10710  
10711 10711          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10712 10712              "ohci_handle_outstanding_requests: pp = 0x%p", (void *)pp);
10713 10713  
10714 10714          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10715 10715  
10716 10716          /*
10717 10717           * Deallocate all the pre-allocated interrupt requests
10718 10718           */
10719 10719          next_tw = pp->pp_tw_head;
10720 10720  
10721 10721          while (next_tw) {
10722 10722                  curr_tw = next_tw;
10723 10723                  next_tw = curr_tw->tw_next;
10724 10724  
10725 10725                  curr_xfer_reqp = curr_tw->tw_curr_xfer_reqp;
10726 10726  
10727 10727                  /* Deallocate current interrupt request */
10728 10728                  if (curr_xfer_reqp) {
10729 10729  
10730 10730                          if ((OHCI_PERIODIC_ENDPOINT(eptd)) &&
10731 10731                              (curr_tw->tw_direction == HC_TD_IN)) {
10732 10732  
10733 10733                                  /* Decrement periodic in request count */
10734 10734                                  pp->pp_cur_periodic_req_cnt--;
10735 10735  
10736 10736                                  ohci_deallocate_periodic_in_resource(
10737 10737                                      ohcip, pp, curr_tw);
10738 10738                          } else {
10739 10739                                  ohci_hcdi_callback(ph,
10740 10740                                      curr_tw, USB_CR_FLUSHED);
10741 10741                          }
10742 10742                  }
10743 10743          }
10744 10744  }
10745 10745  
10746 10746  
10747 10747  /*
10748 10748   * ohci_deallocate_periodic_in_resource
10749 10749   *
10750 10750   * Deallocate interrupt/isochronous request structure for the
10751 10751   * interrupt/isochronous IN transfer.
10752 10752   */
10753 10753  static void
10754 10754  ohci_deallocate_periodic_in_resource(
10755 10755          ohci_state_t            *ohcip,
10756 10756          ohci_pipe_private_t     *pp,
10757 10757          ohci_trans_wrapper_t    *tw)
10758 10758  {
10759 10759          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10760 10760          uchar_t                 ep_attr = ph->p_ep.bmAttributes;
10761 10761          usb_opaque_t            curr_xfer_reqp;
10762 10762  
10763 10763          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10764 10764              "ohci_deallocate_periodic_in_resource: "
10765 10765              "pp = 0x%p tw = 0x%p", (void *)pp, (void *)tw);
10766 10766  
10767 10767          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10768 10768  
10769 10769          curr_xfer_reqp = tw->tw_curr_xfer_reqp;
10770 10770  
10771 10771          /* Check the current periodic in request pointer */
10772 10772          if (curr_xfer_reqp) {
10773 10773                  /*
10774 10774                   * Reset periodic in request usb isoch
10775 10775                   * packet request pointers to null.
10776 10776                   */
10777 10777                  tw->tw_curr_xfer_reqp = NULL;
10778 10778                  tw->tw_curr_isoc_pktp = NULL;
10779 10779  
10780 10780                  mutex_enter(&ph->p_mutex);
10781 10781                  ph->p_req_count--;
10782 10782                  mutex_exit(&ph->p_mutex);
10783 10783  
10784 10784                  /*
10785 10785                   * Free pre-allocated interrupt
10786 10786                   * or isochronous requests.
10787 10787                   */
10788 10788                  switch (ep_attr & USB_EP_ATTR_MASK) {
10789 10789                  case USB_EP_ATTR_INTR:
10790 10790                          usb_free_intr_req(
10791 10791                              (usb_intr_req_t *)curr_xfer_reqp);
10792 10792                          break;
10793 10793                  case USB_EP_ATTR_ISOCH:
10794 10794                          usb_free_isoc_req(
10795 10795                              (usb_isoc_req_t *)curr_xfer_reqp);
10796 10796                          break;
10797 10797                  }
10798 10798          }
10799 10799  }
10800 10800  
10801 10801  
10802 10802  /*
10803 10803   * ohci_do_client_periodic_in_req_callback
10804 10804   *
10805 10805   * Do callback for the original client periodic IN request.
10806 10806   */
10807 10807  static void
10808 10808  ohci_do_client_periodic_in_req_callback(
10809 10809          ohci_state_t            *ohcip,
10810 10810          ohci_pipe_private_t     *pp,
10811 10811          usb_cr_t                completion_reason)
10812 10812  {
10813 10813          usba_pipe_handle_data_t *ph = pp->pp_pipe_handle;
10814 10814  
10815 10815          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10816 10816              "ohci_do_client_periodic_in_req_callback: "
10817 10817              "pp = 0x%p cc = 0x%x", (void *)pp, completion_reason);
10818 10818  
10819 10819          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10820 10820  
10821 10821          /*
10822 10822           * Check for Interrupt/Isochronous IN, whether we need to do
10823 10823           * callback for the original client's periodic IN request.
10824 10824           */
10825 10825          if (pp->pp_client_periodic_in_reqp) {
10826 10826                  ASSERT(pp->pp_cur_periodic_req_cnt == 0);
10827 10827                  ohci_hcdi_callback(ph, NULL, completion_reason);
10828 10828          }
10829 10829  }
10830 10830  
10831 10831  
10832 10832  /*
10833 10833   * ohci_hcdi_callback()
10834 10834   *
10835 10835   * Convenience wrapper around usba_hcdi_cb() other than root hub.
10836 10836   */
10837 10837  static void
10838 10838  ohci_hcdi_callback(
10839 10839          usba_pipe_handle_data_t *ph,
10840 10840          ohci_trans_wrapper_t    *tw,
10841 10841          usb_cr_t                completion_reason)
10842 10842  {
10843 10843          ohci_state_t            *ohcip = ohci_obtain_state(
10844 10844              ph->p_usba_device->usb_root_hub_dip);
10845 10845          uchar_t                 attributes = ph->p_ep.bmAttributes &
10846 10846              USB_EP_ATTR_MASK;
10847 10847          ohci_pipe_private_t     *pp = (ohci_pipe_private_t *)ph->p_hcd_private;
10848 10848          usb_opaque_t            curr_xfer_reqp;
10849 10849          uint_t                  pipe_state = 0;
10850 10850  
10851 10851          USB_DPRINTF_L4(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
10852 10852              "ohci_hcdi_callback: ph = 0x%p, tw = 0x%p, cr = 0x%x",
10853 10853              (void *)ph, (void *)tw, completion_reason);
10854 10854  
10855 10855          ASSERT(mutex_owned(&ohcip->ohci_int_mutex));
10856 10856  
10857 10857          /* Set the pipe state as per completion reason */
10858 10858          switch (completion_reason) {
10859 10859          case USB_CR_OK:
10860 10860                  pipe_state = pp->pp_state;
10861 10861                  break;
10862 10862          case USB_CR_NO_RESOURCES:
10863 10863          case USB_CR_NOT_SUPPORTED:
10864 10864          case USB_CR_STOPPED_POLLING:
10865 10865          case USB_CR_PIPE_RESET:
10866 10866                  pipe_state = OHCI_PIPE_STATE_IDLE;
10867 10867                  break;
10868 10868          case USB_CR_PIPE_CLOSING:
10869 10869                  break;
10870 10870          default:
10871 10871                  /*
10872 10872                   * Set the pipe state to error
10873 10873                   * except for the isoc pipe.
10874 10874                   */
10875 10875                  if (attributes != USB_EP_ATTR_ISOCH) {
10876 10876                          pipe_state = OHCI_PIPE_STATE_ERROR;
10877 10877                          pp->pp_error = completion_reason;
10878 10878                  }
10879 10879                  break;
10880 10880  
10881 10881          }
10882 10882  
10883 10883          pp->pp_state = pipe_state;
10884 10884  
10885 10885          if (tw && tw->tw_curr_xfer_reqp) {
10886 10886                  curr_xfer_reqp = tw->tw_curr_xfer_reqp;
10887 10887                  tw->tw_curr_xfer_reqp = NULL;
10888 10888                  tw->tw_curr_isoc_pktp = NULL;
10889 10889          } else {
10890 10890                  ASSERT(pp->pp_client_periodic_in_reqp != NULL);
10891 10891  
10892 10892                  curr_xfer_reqp = pp->pp_client_periodic_in_reqp;
10893 10893                  pp->pp_client_periodic_in_reqp = NULL;
10894 10894          }
10895 10895  
10896 10896          ASSERT(curr_xfer_reqp != NULL);
10897 10897  
10898 10898          mutex_exit(&ohcip->ohci_int_mutex);
10899 10899  
10900 10900          usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason);
10901 10901  
10902 10902          mutex_enter(&ohcip->ohci_int_mutex);
10903 10903  }
10904 10904  
10905 10905  
10906 10906  /*
10907 10907   * ohci kstat functions
10908 10908   */
10909 10909  
10910 10910  /*
10911 10911   * ohci_create_stats:
10912 10912   *
10913 10913   * Allocate and initialize the ohci kstat structures
10914 10914   */
10915 10915  static void
10916 10916  ohci_create_stats(ohci_state_t  *ohcip)
10917 10917  {
10918 10918          char                    kstatname[KSTAT_STRLEN];
10919 10919          const char              *dname = ddi_driver_name(ohcip->ohci_dip);
10920 10920          char                    *usbtypes[USB_N_COUNT_KSTATS] =
10921 10921              {"ctrl", "isoch", "bulk", "intr"};
10922 10922          uint_t                  instance = ohcip->ohci_instance;
10923 10923          ohci_intrs_stats_t      *isp;
10924 10924          int                     i;
10925 10925  
10926 10926          if (OHCI_INTRS_STATS(ohcip) == NULL) {
10927 10927                  (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,intrs",
10928 10928                      dname, instance);
10929 10929                  OHCI_INTRS_STATS(ohcip) = kstat_create("usba", instance,
10930 10930                      kstatname, "usb_interrupts", KSTAT_TYPE_NAMED,
10931 10931                      sizeof (ohci_intrs_stats_t) / sizeof (kstat_named_t),
10932 10932                      KSTAT_FLAG_PERSISTENT);
10933 10933  
10934 10934                  if (OHCI_INTRS_STATS(ohcip)) {
10935 10935                          isp = OHCI_INTRS_STATS_DATA(ohcip);
10936 10936                          kstat_named_init(&isp->ohci_hcr_intr_total,
10937 10937                              "Interrupts Total", KSTAT_DATA_UINT64);
10938 10938                          kstat_named_init(&isp->ohci_hcr_intr_not_claimed,
10939 10939                              "Not Claimed", KSTAT_DATA_UINT64);
10940 10940                          kstat_named_init(&isp->ohci_hcr_intr_so,
10941 10941                              "Schedule Overruns", KSTAT_DATA_UINT64);
10942 10942                          kstat_named_init(&isp->ohci_hcr_intr_wdh,
10943 10943                              "Writeback Done Head", KSTAT_DATA_UINT64);
10944 10944                          kstat_named_init(&isp->ohci_hcr_intr_sof,
10945 10945                              "Start Of Frame", KSTAT_DATA_UINT64);
10946 10946                          kstat_named_init(&isp->ohci_hcr_intr_rd,
10947 10947                              "Resume Detected", KSTAT_DATA_UINT64);
10948 10948                          kstat_named_init(&isp->ohci_hcr_intr_ue,
10949 10949                              "Unrecoverable Error", KSTAT_DATA_UINT64);
10950 10950                          kstat_named_init(&isp->ohci_hcr_intr_fno,
10951 10951                              "Frame No. Overflow", KSTAT_DATA_UINT64);
10952 10952                          kstat_named_init(&isp->ohci_hcr_intr_rhsc,
10953 10953                              "Root Hub Status Change", KSTAT_DATA_UINT64);
10954 10954                          kstat_named_init(&isp->ohci_hcr_intr_oc,
10955 10955                              "Change In Ownership", KSTAT_DATA_UINT64);
10956 10956  
10957 10957                          OHCI_INTRS_STATS(ohcip)->ks_private = ohcip;
10958 10958                          OHCI_INTRS_STATS(ohcip)->ks_update = nulldev;
10959 10959                          kstat_install(OHCI_INTRS_STATS(ohcip));
10960 10960                  }
10961 10961          }
10962 10962  
10963 10963          if (OHCI_TOTAL_STATS(ohcip) == NULL) {
10964 10964                  (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,total",
10965 10965                      dname, instance);
10966 10966                  OHCI_TOTAL_STATS(ohcip) = kstat_create("usba", instance,
10967 10967                      kstatname, "usb_byte_count", KSTAT_TYPE_IO, 1,
10968 10968                      KSTAT_FLAG_PERSISTENT);
10969 10969  
10970 10970                  if (OHCI_TOTAL_STATS(ohcip)) {
10971 10971                          kstat_install(OHCI_TOTAL_STATS(ohcip));
10972 10972                  }
10973 10973          }
10974 10974  
10975 10975          for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
10976 10976                  if (ohcip->ohci_count_stats[i] == NULL) {
10977 10977                          (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,%s",
10978 10978                              dname, instance, usbtypes[i]);
10979 10979                          ohcip->ohci_count_stats[i] = kstat_create("usba",
10980 10980                              instance, kstatname, "usb_byte_count",
10981 10981                              KSTAT_TYPE_IO, 1, KSTAT_FLAG_PERSISTENT);
10982 10982  
10983 10983                          if (ohcip->ohci_count_stats[i]) {
10984 10984                                  kstat_install(ohcip->ohci_count_stats[i]);
10985 10985                          }
10986 10986                  }
10987 10987          }
10988 10988  }
10989 10989  
10990 10990  
10991 10991  /*
10992 10992   * ohci_destroy_stats:
10993 10993   *
10994 10994   * Clean up ohci kstat structures
10995 10995   */
10996 10996  static void
10997 10997  ohci_destroy_stats(ohci_state_t *ohcip)
10998 10998  {
10999 10999          int     i;
11000 11000  
11001 11001          if (OHCI_INTRS_STATS(ohcip)) {
11002 11002                  kstat_delete(OHCI_INTRS_STATS(ohcip));
11003 11003                  OHCI_INTRS_STATS(ohcip) = NULL;
11004 11004          }
11005 11005  
11006 11006          if (OHCI_TOTAL_STATS(ohcip)) {
11007 11007                  kstat_delete(OHCI_TOTAL_STATS(ohcip));
11008 11008                  OHCI_TOTAL_STATS(ohcip) = NULL;
11009 11009          }
11010 11010  
11011 11011          for (i = 0; i < USB_N_COUNT_KSTATS; i++) {
11012 11012                  if (ohcip->ohci_count_stats[i]) {
11013 11013                          kstat_delete(ohcip->ohci_count_stats[i]);
11014 11014                          ohcip->ohci_count_stats[i] = NULL;
11015 11015                  }
11016 11016          }
11017 11017  }
11018 11018  
11019 11019  
11020 11020  /*
11021 11021   * ohci_do_intrs_stats:
11022 11022   *
11023 11023   * ohci status information
11024 11024   */
11025 11025  static void
11026 11026  ohci_do_intrs_stats(
11027 11027          ohci_state_t    *ohcip,
11028 11028          int             val)
11029 11029  {
11030 11030          if (OHCI_INTRS_STATS(ohcip)) {
11031 11031                  OHCI_INTRS_STATS_DATA(ohcip)->ohci_hcr_intr_total.value.ui64++;
11032 11032                  switch (val) {
11033 11033                          case HCR_INTR_SO:
11034 11034                                  OHCI_INTRS_STATS_DATA(ohcip)->
11035 11035                                      ohci_hcr_intr_so.value.ui64++;
11036 11036                                  break;
11037 11037                          case HCR_INTR_WDH:
11038 11038                                  OHCI_INTRS_STATS_DATA(ohcip)->
11039 11039                                      ohci_hcr_intr_wdh.value.ui64++;
11040 11040                                  break;
11041 11041                          case HCR_INTR_SOF:
11042 11042                                  OHCI_INTRS_STATS_DATA(ohcip)->
11043 11043                                      ohci_hcr_intr_sof.value.ui64++;
11044 11044                                  break;
11045 11045                          case HCR_INTR_RD:
11046 11046                                  OHCI_INTRS_STATS_DATA(ohcip)->
11047 11047                                      ohci_hcr_intr_rd.value.ui64++;
11048 11048                                  break;
11049 11049                          case HCR_INTR_UE:
11050 11050                                  OHCI_INTRS_STATS_DATA(ohcip)->
11051 11051                                      ohci_hcr_intr_ue.value.ui64++;
11052 11052                                  break;
11053 11053                          case HCR_INTR_FNO:
11054 11054                                  OHCI_INTRS_STATS_DATA(ohcip)->
11055 11055                                      ohci_hcr_intr_fno.value.ui64++;
11056 11056                                  break;
11057 11057                          case HCR_INTR_RHSC:
11058 11058                                  OHCI_INTRS_STATS_DATA(ohcip)->
11059 11059                                      ohci_hcr_intr_rhsc.value.ui64++;
11060 11060                                  break;
11061 11061                          case HCR_INTR_OC:
11062 11062                                  OHCI_INTRS_STATS_DATA(ohcip)->
11063 11063                                      ohci_hcr_intr_oc.value.ui64++;
11064 11064                                  break;
11065 11065                          default:
11066 11066                                  OHCI_INTRS_STATS_DATA(ohcip)->
11067 11067                                      ohci_hcr_intr_not_claimed.value.ui64++;
11068 11068                                  break;
11069 11069                  }
11070 11070          }
11071 11071  }
11072 11072  
11073 11073  
11074 11074  /*
11075 11075   * ohci_do_byte_stats:
11076 11076   *
11077 11077   * ohci data xfer information
11078 11078   */
11079 11079  static void
11080 11080  ohci_do_byte_stats(
11081 11081          ohci_state_t    *ohcip,
11082 11082          size_t          len,
11083 11083          uint8_t         attr,
11084 11084          uint8_t         addr)
11085 11085  {
11086 11086          uint8_t         type = attr & USB_EP_ATTR_MASK;
11087 11087          uint8_t         dir = addr & USB_EP_DIR_MASK;
11088 11088  
11089 11089          if (dir == USB_EP_DIR_IN) {
11090 11090                  OHCI_TOTAL_STATS_DATA(ohcip)->reads++;
11091 11091                  OHCI_TOTAL_STATS_DATA(ohcip)->nread += len;
11092 11092                  switch (type) {
11093 11093                          case USB_EP_ATTR_CONTROL:
11094 11094                                  OHCI_CTRL_STATS(ohcip)->reads++;
11095 11095                                  OHCI_CTRL_STATS(ohcip)->nread += len;
11096 11096                                  break;
11097 11097                          case USB_EP_ATTR_BULK:
11098 11098                                  OHCI_BULK_STATS(ohcip)->reads++;
11099 11099                                  OHCI_BULK_STATS(ohcip)->nread += len;
11100 11100                                  break;
11101 11101                          case USB_EP_ATTR_INTR:
11102 11102                                  OHCI_INTR_STATS(ohcip)->reads++;
11103 11103                                  OHCI_INTR_STATS(ohcip)->nread += len;
11104 11104                                  break;
11105 11105                          case USB_EP_ATTR_ISOCH:
11106 11106                                  OHCI_ISOC_STATS(ohcip)->reads++;
11107 11107                                  OHCI_ISOC_STATS(ohcip)->nread += len;
11108 11108                                  break;
11109 11109                  }
11110 11110          } else if (dir == USB_EP_DIR_OUT) {
11111 11111                  OHCI_TOTAL_STATS_DATA(ohcip)->writes++;
11112 11112                  OHCI_TOTAL_STATS_DATA(ohcip)->nwritten += len;
11113 11113                  switch (type) {
11114 11114                          case USB_EP_ATTR_CONTROL:
11115 11115                                  OHCI_CTRL_STATS(ohcip)->writes++;
11116 11116                                  OHCI_CTRL_STATS(ohcip)->nwritten += len;
11117 11117                                  break;
11118 11118                          case USB_EP_ATTR_BULK:
11119 11119                                  OHCI_BULK_STATS(ohcip)->writes++;
11120 11120                                  OHCI_BULK_STATS(ohcip)->nwritten += len;
11121 11121                                  break;
11122 11122                          case USB_EP_ATTR_INTR:
11123 11123                                  OHCI_INTR_STATS(ohcip)->writes++;
11124 11124                                  OHCI_INTR_STATS(ohcip)->nwritten += len;
11125 11125                                  break;
11126 11126                          case USB_EP_ATTR_ISOCH:
11127 11127                                  OHCI_ISOC_STATS(ohcip)->writes++;
11128 11128                                  OHCI_ISOC_STATS(ohcip)->nwritten += len;
11129 11129                                  break;
11130 11130                  }
11131 11131          }
11132 11132  }
11133 11133  
11134 11134  
11135 11135  /*
11136 11136   * ohci_print_op_regs:
11137 11137   *
11138 11138   * Print Host Controller's (HC) Operational registers.
11139 11139   */
11140 11140  static void
11141 11141  ohci_print_op_regs(ohci_state_t *ohcip)
11142 11142  {
11143 11143          uint_t                  i;
11144 11144  
11145 11145          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11146 11146              "\n\tOHCI%d Operational Registers\n",
11147 11147              ddi_get_instance(ohcip->ohci_dip));
11148 11148  
11149 11149          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11150 11150              "\thcr_revision: 0x%x \t\thcr_control: 0x%x",
11151 11151              Get_OpReg(hcr_revision), Get_OpReg(hcr_control));
11152 11152          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11153 11153              "\thcr_cmd_status: 0x%x \t\thcr_intr_enable: 0x%x",
11154 11154              Get_OpReg(hcr_cmd_status), Get_OpReg(hcr_intr_enable));
11155 11155          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11156 11156              "\thcr_intr_disable: 0x%x \thcr_HCCA: 0x%x",
11157 11157              Get_OpReg(hcr_intr_disable), Get_OpReg(hcr_HCCA));
11158 11158          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11159 11159              "\thcr_periodic_curr: 0x%x \t\thcr_ctrl_head: 0x%x",
11160 11160              Get_OpReg(hcr_periodic_curr), Get_OpReg(hcr_ctrl_head));
11161 11161          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11162 11162              "\thcr_ctrl_curr: 0x%x  \t\thcr_bulk_head: 0x%x",
11163 11163              Get_OpReg(hcr_ctrl_curr), Get_OpReg(hcr_bulk_head));
11164 11164          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11165 11165              "\thcr_bulk_curr: 0x%x \t\thcr_done_head: 0x%x",
11166 11166              Get_OpReg(hcr_bulk_curr), Get_OpReg(hcr_done_head));
11167 11167          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11168 11168              "\thcr_frame_interval: 0x%x "
11169 11169              "\thcr_frame_remaining: 0x%x", Get_OpReg(hcr_frame_interval),
11170 11170              Get_OpReg(hcr_frame_remaining));
11171 11171          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11172 11172              "\thcr_frame_number: 0x%x  \thcr_periodic_strt: 0x%x",
11173 11173              Get_OpReg(hcr_frame_number), Get_OpReg(hcr_periodic_strt));
11174 11174          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11175 11175              "\thcr_transfer_ls: 0x%x \t\thcr_rh_descriptorA: 0x%x",
11176 11176              Get_OpReg(hcr_transfer_ls), Get_OpReg(hcr_rh_descriptorA));
11177 11177          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11178 11178              "\thcr_rh_descriptorB: 0x%x \thcr_rh_status: 0x%x",
11179 11179              Get_OpReg(hcr_rh_descriptorB), Get_OpReg(hcr_rh_status));
11180 11180  
11181 11181          USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11182 11182              "\tRoot hub port status");
11183 11183  
11184 11184          for (i = 0; i < (Get_OpReg(hcr_rh_descriptorA) & HCR_RHA_NDP); i++) {
11185 11185                  USB_DPRINTF_L3(PRINT_MASK_ATTA, ohcip->ohci_log_hdl,
11186 11186                      "\thcr_rh_portstatus 0x%x: 0x%x ", i,
11187 11187                      Get_OpReg(hcr_rh_portstatus[i]));
11188 11188          }
11189 11189  }
11190 11190  
11191 11191  
11192 11192  /*
11193 11193   * ohci_print_ed:
11194 11194   */
11195 11195  static void
11196 11196  ohci_print_ed(
11197 11197          ohci_state_t    *ohcip,
11198 11198          ohci_ed_t       *ed)
11199 11199  {
11200 11200          uint_t          ctrl = Get_ED(ed->hced_ctrl);
11201 11201  
11202 11202          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11203 11203              "ohci_print_ed: ed = 0x%p", (void *)ed);
11204 11204  
11205 11205          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11206 11206              "\thced_ctrl: 0x%x %s", ctrl,
11207 11207              ((Get_ED(ed->hced_headp) & HC_EPT_Halt) ? "halted": ""));
11208 11208          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11209 11209              "\ttoggle carry: 0x%x", Get_ED(ed->hced_headp) & HC_EPT_Carry);
11210 11210  
11211 11211          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11212 11212              "\tctrl: 0x%x", Get_ED(ed->hced_ctrl));
11213 11213          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11214 11214              "\ttailp: 0x%x", Get_ED(ed->hced_tailp));
11215 11215          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11216 11216              "\theadp: 0x%x", Get_ED(ed->hced_headp));
11217 11217          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11218 11218              "\tnext: 0x%x", Get_ED(ed->hced_next));
11219 11219          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11220 11220              "\tprev: 0x%x", Get_ED(ed->hced_prev));
11221 11221          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11222 11222              "\tnode: 0x%x", Get_ED(ed->hced_node));
11223 11223          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11224 11224              "\treclaim_next: 0x%x", Get_ED(ed->hced_reclaim_next));
11225 11225          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11226 11226              "\treclaim_frame: 0x%x", Get_ED(ed->hced_reclaim_frame));
11227 11227          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11228 11228              "\tstate: 0x%x", Get_ED(ed->hced_state));
11229 11229  }
11230 11230  
11231 11231  
11232 11232  /*
11233 11233   * ohci_print_td:
11234 11234   */
11235 11235  static void
11236 11236  ohci_print_td(
11237 11237          ohci_state_t    *ohcip,
11238 11238          ohci_td_t       *td)
11239 11239  {
11240 11240          uint_t          i;
11241 11241          uint_t          ctrl = Get_TD(td->hctd_ctrl);
11242 11242  
11243 11243          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11244 11244              "ohci_print_td: td = 0x%p", (void *)td);
11245 11245  
11246 11246          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11247 11247              "\tPID: 0x%x ", ctrl & HC_TD_PID);
11248 11248          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11249 11249              "\tDelay Intr: 0x%x ", ctrl & HC_TD_DI);
11250 11250          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11251 11251              "\tData Toggle: 0x%x ", ctrl & HC_TD_DT);
11252 11252          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11253 11253              "\tError Count: 0x%x ", ctrl & HC_TD_EC);
11254 11254  
11255 11255          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11256 11256              "\tctrl: 0x%x ", Get_TD(td->hctd_ctrl));
11257 11257          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11258 11258              "\tcbp: 0x%x ", Get_TD(td->hctd_cbp));
11259 11259          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11260 11260              "\tnext_td: 0x%x ", Get_TD(td->hctd_next_td));
11261 11261          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11262 11262              "\tbuf_end: 0x%x ", Get_TD(td->hctd_buf_end));
11263 11263  
11264 11264          for (i = 0; i < 4; i++) {
11265 11265                  USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11266 11266                      "\toffset[%d]: 0x%x ", i, Get_TD(td->hctd_offsets[i]));
11267 11267          }
11268 11268  
11269 11269          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11270 11270              "\ttrans_wrapper: 0x%x ", Get_TD(td->hctd_trans_wrapper));
11271 11271          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11272 11272              "\tstate: 0x%x ", Get_TD(td->hctd_state));
11273 11273          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11274 11274              "\ttw_next_td: 0x%x ", Get_TD(td->hctd_tw_next_td));
11275 11275          USB_DPRINTF_L3(PRINT_MASK_LISTS, ohcip->ohci_log_hdl,
11276 11276              "\tctrl_phase: 0x%x ", Get_TD(td->hctd_ctrl_phase));
11277 11277  }
11278 11278  
11279 11279  /*
11280 11280   * quiesce(9E) entry point.
11281 11281   *
11282 11282   * This function is called when the system is single-threaded at high
11283 11283   * PIL with preemption disabled. Therefore, this function must not be
11284 11284   * blocked.
11285 11285   *
11286 11286   * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
11287 11287   * DDI_FAILURE indicates an error condition and should almost never happen.
11288 11288   *
11289 11289   * define as a wrapper for sparc, or warlock will complain.
11290 11290   */
11291 11291  #ifdef  __sparc
11292 11292  int
11293 11293  ohci_quiesce(dev_info_t *dip)
11294 11294  {
11295 11295          return (ddi_quiesce_not_supported(dip));
11296 11296  }
11297 11297  #else
11298 11298  int
11299 11299  ohci_quiesce(dev_info_t *dip)
11300 11300  {
11301 11301          ohci_state_t    *ohcip = ohci_obtain_state(dip);
11302 11302  
11303 11303          if (ohcip == NULL)
11304 11304                  return (DDI_FAILURE);
11305 11305  
11306 11306  #ifndef lint
11307 11307          _NOTE(NO_COMPETING_THREADS_NOW);
11308 11308  #endif
11309 11309  
11310 11310          if (ohcip->ohci_flags & OHCI_INTR) {
11311 11311  
11312 11312                  /* Disable all HC ED list processing */
11313 11313                  Set_OpReg(hcr_control,
11314 11314                      (Get_OpReg(hcr_control) & ~(HCR_CONTROL_CLE |
11315 11315                      HCR_CONTROL_BLE | HCR_CONTROL_PLE | HCR_CONTROL_IE)));
11316 11316  
11317 11317                  /* Disable all HC interrupts */
11318 11318                  Set_OpReg(hcr_intr_disable,
11319 11319                      (HCR_INTR_SO | HCR_INTR_WDH | HCR_INTR_RD | HCR_INTR_UE));
11320 11320  
11321 11321                  /* Disable Master and SOF interrupts */
11322 11322                  Set_OpReg(hcr_intr_disable, (HCR_INTR_MIE | HCR_INTR_SOF));
11323 11323  
11324 11324                  /* Set the Host Controller Functional State to Reset */
11325 11325                  Set_OpReg(hcr_control, ((Get_OpReg(hcr_control) &
11326 11326                      (~HCR_CONTROL_HCFS)) | HCR_CONTROL_RESET));
11327 11327  
11328 11328                  /*
11329 11329                   * Workaround for ULI1575 chipset. Following OHCI Operational
11330 11330                   * Memory Registers are not cleared to their default value
11331 11331                   * on reset. Explicitly set the registers to default value.
11332 11332                   */
11333 11333                  if (ohcip->ohci_vendor_id == PCI_ULI1575_VENID &&
11334 11334                      ohcip->ohci_device_id == PCI_ULI1575_DEVID) {
11335 11335                          Set_OpReg(hcr_control, HCR_CONTROL_DEFAULT);
11336 11336                          Set_OpReg(hcr_intr_enable, HCR_INT_ENABLE_DEFAULT);
11337 11337                          Set_OpReg(hcr_HCCA, HCR_HCCA_DEFAULT);
11338 11338                          Set_OpReg(hcr_ctrl_head, HCR_CONTROL_HEAD_ED_DEFAULT);
11339 11339                          Set_OpReg(hcr_bulk_head, HCR_BULK_HEAD_ED_DEFAULT);
11340 11340                          Set_OpReg(hcr_frame_interval,
11341 11341                              HCR_FRAME_INTERVAL_DEFAULT);
11342 11342                          Set_OpReg(hcr_periodic_strt,
11343 11343                              HCR_PERIODIC_START_DEFAULT);
11344 11344                  }
11345 11345  
11346 11346                  ohcip->ohci_hc_soft_state = OHCI_CTLR_SUSPEND_STATE;
11347 11347          }
11348 11348  
11349 11349          /* Unmap the OHCI registers */
11350 11350          if (ohcip->ohci_regs_handle) {
11351 11351                  /* Reset the host controller */
11352 11352                  Set_OpReg(hcr_cmd_status, HCR_STATUS_RESET);
11353 11353          }
11354 11354  
11355 11355  #ifndef lint
11356 11356          _NOTE(COMPETING_THREADS_NOW);
11357 11357  #endif
11358 11358          return (DDI_SUCCESS);
11359 11359  }
11360 11360  #endif  /* __sparc */
  
    | ↓ open down ↓ | 10790 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX