1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * USBA: Solaris USB Architecture support
  28  *
  29  * hcdi.c contains the code for client driver callbacks.  A host controller
  30  * driver registers/unregisters with usba through usba_hcdi_register/unregister.
  31  *
  32  * When the transfer has finished, the host controller driver will call into
  33  * usba with the result.  The call is usba_hcdi_cb().
  34  *
  35  * The callback queue is maintained in FIFO order.  usba_hcdi_cb
  36  * adds to the queue, and hcdi_cb_thread takes the callbacks off the queue
  37  * and executes them.
  38  */
  39 #define USBA_FRAMEWORK
  40 #include <sys/usb/usba/usba_impl.h>
  41 #include <sys/usb/usba/hcdi_impl.h>
  42 #include <sys/kstat.h>
  43 #include <sys/ddi_impldefs.h>
  44 
  45 /* function prototypes, XXXX use hcdi_ prefix?  */
  46 static void usba_hcdi_create_stats(usba_hcdi_t *, int);
  47 static void usba_hcdi_update_error_stats(usba_hcdi_t *, usb_cr_t);
  48 static void usba_hcdi_destroy_stats(usba_hcdi_t *);
  49 
  50 /* internal functions */
  51 static uint_t hcdi_soft_intr(caddr_t arg1, caddr_t arg2);
  52 
  53 static void hcdi_cb_thread(void *);
  54 static void hcdi_shared_cb_thread(void *);
  55 static void hcdi_do_cb(usba_pipe_handle_data_t *, usba_req_wrapper_t *,
  56                                                         usba_hcdi_t *);
  57 static void hcdi_autoclearing(usba_req_wrapper_t *);
  58 
  59 /* private function from USBAI */
  60 void    usba_pipe_clear(usb_pipe_handle_t);
  61 
  62 /* for debug messages */
  63 uint_t  hcdi_errmask    = (uint_t)DPRINT_MASK_ALL;
  64 uint_t  hcdi_errlevel   = USB_LOG_L4;
  65 uint_t  hcdi_instance_debug = (uint_t)-1;
  66 
  67 void
  68 usba_hcdi_initialization()
  69 {
  70 }
  71 
  72 
  73 void
  74 usba_hcdi_destroy()
  75 {
  76 }
  77 
  78 
  79 /*
  80  * store hcdi structure in the dip
  81  */
  82 void
  83 usba_hcdi_set_hcdi(dev_info_t *dip, usba_hcdi_t *hcdi)
  84 {
  85         ddi_set_driver_private(dip, hcdi);
  86 }
  87 
  88 
  89 /*
  90  * retrieve hcdi structure from the dip
  91  */
  92 usba_hcdi_t *
  93 usba_hcdi_get_hcdi(dev_info_t *dip)
  94 {
  95         return (ddi_get_driver_private(dip));
  96 }
  97 
  98 /*
  99  * Called by an HCD to attach an instance of the driver
 100  *      make this instance known to USBA
 101  *      the HCD should initialize usba_hcdi structure prior
 102  *      to calling this interface
 103  */
 104 int
 105 usba_hcdi_register(usba_hcdi_register_args_t *args, uint_t flags)
 106 {
 107         char            *datap;
 108         uint_t          soft_prip;
 109         usba_hcdi_t     *hcdi = kmem_zalloc(sizeof (usba_hcdi_t), KM_SLEEP);
 110 
 111         if (args->usba_hcdi_register_version != HCDI_REGISTER_VERS_0) {
 112                 kmem_free(hcdi, sizeof (usba_hcdi_t));
 113 
 114                 return (USB_FAILURE);
 115         }
 116 
 117         hcdi->hcdi_dip = args->usba_hcdi_register_dip;
 118 
 119         /*
 120          * Create a log_handle
 121          */
 122         hcdi->hcdi_log_handle = usb_alloc_log_hdl(hcdi->hcdi_dip, NULL,
 123             &hcdi_errlevel, &hcdi_errmask, &hcdi_instance_debug,
 124             0);
 125 
 126         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 127             "usba_hcdi_register: %s", ddi_node_name(hcdi->hcdi_dip));
 128 
 129         /*
 130          * Initialize the mutex.  Use the iblock cookie passed in
 131          * by the host controller driver.
 132          */
 133         mutex_init(&hcdi->hcdi_mutex, NULL, MUTEX_DRIVER,
 134             args->usba_hcdi_register_iblock_cookie);
 135 
 136         /* add soft interrupt */
 137         if (ddi_intr_add_softint(hcdi->hcdi_dip, &hcdi->hcdi_softint_hdl,
 138             DDI_INTR_SOFTPRI_MAX, hcdi_soft_intr, (caddr_t)hcdi) !=
 139             DDI_SUCCESS) {
 140                 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 141                     "usba_hcd_register: add soft interrupt failed");
 142                 mutex_destroy(&hcdi->hcdi_mutex);
 143                 usb_free_log_hdl(hcdi->hcdi_log_handle);
 144                 kmem_free(hcdi, sizeof (usba_hcdi_t));
 145 
 146                 return (USB_FAILURE);
 147         }
 148 
 149         if (ddi_intr_get_softint_pri(hcdi->hcdi_softint_hdl, &soft_prip) !=
 150             DDI_SUCCESS) {
 151                 USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 152                     "usba_hcd_register: get soft interrupt priority failed");
 153                 (void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl);
 154                 mutex_destroy(&hcdi->hcdi_mutex);
 155                 usb_free_log_hdl(hcdi->hcdi_log_handle);
 156                 kmem_free(hcdi, sizeof (usba_hcdi_t));
 157 
 158                 return (USB_FAILURE);
 159         }
 160 
 161         /*
 162          * Priority and iblock_cookie are one and the same
 163          * (However, retaining hcdi_soft_iblock_cookie for now
 164          * assigning it w/ priority. In future all iblock_cookie
 165          * could just go)
 166          */
 167         hcdi->hcdi_soft_iblock_cookie =
 168             (ddi_iblock_cookie_t)(uintptr_t)soft_prip;
 169 
 170         usba_init_list(&hcdi->hcdi_cb_queue, NULL, NULL);
 171 
 172         hcdi->hcdi_dma_attr  = args->usba_hcdi_register_dma_attr;
 173         hcdi->hcdi_flags     = flags;
 174         hcdi->hcdi_ops               = args->usba_hcdi_register_ops;
 175         hcdi->hcdi_iblock_cookie = args->usba_hcdi_register_iblock_cookie;
 176         usba_hcdi_create_stats(hcdi, ddi_get_instance(hcdi->hcdi_dip));
 177 
 178         hcdi->hcdi_min_xfer  = hcdi->hcdi_dma_attr->dma_attr_minxfer;
 179         hcdi->hcdi_min_burst_size =
 180             (1<<(ddi_ffs(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1));
 181         hcdi->hcdi_max_burst_size =
 182             (1<<(ddi_fls(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1));
 183 
 184         usba_hcdi_set_hcdi(hcdi->hcdi_dip, hcdi);
 185 
 186         if (ddi_prop_lookup_string(DDI_DEV_T_ANY,
 187             hcdi->hcdi_dip,
 188             DDI_PROP_DONTPASS, "ugen-default-binding", &datap) ==
 189             DDI_PROP_SUCCESS) {
 190                 if (strcmp(datap, "device") == 0) {
 191                         hcdi->hcdi_ugen_default_binding =
 192                             USBA_UGEN_DEVICE_BINDING;
 193                 } else if (strcmp(datap, "interface") == 0) {
 194                         hcdi->hcdi_ugen_default_binding =
 195                             USBA_UGEN_INTERFACE_BINDING;
 196                 } else if (strcmp(datap, "interface-association") == 0) {
 197                         hcdi->hcdi_ugen_default_binding =
 198                             USBA_UGEN_INTERFACE_ASSOCIATION_BINDING;
 199                 } else {
 200                         USB_DPRINTF_L2(DPRINT_MASK_HCDI,
 201                             hcdi->hcdi_log_handle,
 202                             "illegal value (%s) for "
 203                             "ugen_default_binding property",
 204                             datap);
 205                 }
 206                 ddi_prop_free(datap);
 207         }
 208 
 209         return (USB_SUCCESS);
 210 }
 211 
 212 
 213 /*
 214  * Called by an HCD to detach an instance of the driver
 215  */
 216 /*ARGSUSED*/
 217 void
 218 usba_hcdi_unregister(dev_info_t *dip)
 219 {
 220         usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip);
 221 
 222         if (hcdi) {
 223                 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 224                     "usba_hcdi_unregister: %s", ddi_node_name(dip));
 225 
 226                 usba_hcdi_set_hcdi(dip, NULL);
 227 
 228                 mutex_destroy(&hcdi->hcdi_mutex);
 229                 usba_hcdi_destroy_stats(hcdi);
 230                 usb_free_log_hdl(hcdi->hcdi_log_handle);
 231 
 232                 /* Destroy the soft interrupt */
 233                 (void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl);
 234                 kmem_free(hcdi, sizeof (usba_hcdi_t));
 235         }
 236 }
 237 
 238 
 239 /*
 240  * alloc usba_hcdi_ops structure
 241  *      called from the HCD attach routine
 242  */
 243 usba_hcdi_ops_t *
 244 usba_alloc_hcdi_ops()
 245 {
 246         usba_hcdi_ops_t *usba_hcdi_ops;
 247 
 248         usba_hcdi_ops = kmem_zalloc(sizeof (usba_hcdi_ops_t), KM_SLEEP);
 249 
 250         return (usba_hcdi_ops);
 251 }
 252 
 253 
 254 /*
 255  * dealloc usba_hcdi_ops structure
 256  */
 257 void
 258 usba_free_hcdi_ops(usba_hcdi_ops_t *hcdi_ops)
 259 {
 260         if (hcdi_ops) {
 261                 kmem_free(hcdi_ops, sizeof (usba_hcdi_ops_t));
 262         }
 263 }
 264 
 265 
 266 /*
 267  * Allocate the hotplug kstats structure
 268  */
 269 void
 270 usba_hcdi_create_stats(usba_hcdi_t *hcdi, int instance)
 271 {
 272         char                    kstatname[KSTAT_STRLEN];
 273         const char              *dname = ddi_driver_name(hcdi->hcdi_dip);
 274         hcdi_hotplug_stats_t    *hsp;
 275         hcdi_error_stats_t      *esp;
 276 
 277         if (HCDI_HOTPLUG_STATS(hcdi) == NULL) {
 278                 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,hotplug",
 279                     dname, instance);
 280                 HCDI_HOTPLUG_STATS(hcdi) = kstat_create("usba", instance,
 281                     kstatname, "usb_hotplug", KSTAT_TYPE_NAMED,
 282                     sizeof (hcdi_hotplug_stats_t) / sizeof (kstat_named_t),
 283                     KSTAT_FLAG_PERSISTENT);
 284 
 285                 if (HCDI_HOTPLUG_STATS(hcdi) == NULL) {
 286 
 287                         return;
 288                 }
 289 
 290                 hsp = HCDI_HOTPLUG_STATS_DATA(hcdi);
 291                 kstat_named_init(&hsp->hcdi_hotplug_total_success,
 292                     "Total Hotplug Successes", KSTAT_DATA_UINT64);
 293                 kstat_named_init(&hsp->hcdi_hotplug_success,
 294                     "Hotplug Successes", KSTAT_DATA_UINT64);
 295                 kstat_named_init(&hsp->hcdi_hotplug_total_failure,
 296                     "Hotplug Total Failures", KSTAT_DATA_UINT64);
 297                 kstat_named_init(&hsp->hcdi_hotplug_failure,
 298                     "Hotplug Failures", KSTAT_DATA_UINT64);
 299                 kstat_named_init(&hsp->hcdi_device_count,
 300                     "Device Count", KSTAT_DATA_UINT64);
 301 
 302                 HCDI_HOTPLUG_STATS(hcdi)->ks_private = hcdi;
 303                 HCDI_HOTPLUG_STATS(hcdi)->ks_update = nulldev;
 304                 kstat_install(HCDI_HOTPLUG_STATS(hcdi));
 305         }
 306 
 307         if (HCDI_ERROR_STATS(hcdi) == NULL) {
 308                 (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,error",
 309                     dname, instance);
 310                 HCDI_ERROR_STATS(hcdi) = kstat_create("usba", instance,
 311                     kstatname, "usb_errors", KSTAT_TYPE_NAMED,
 312                     sizeof (hcdi_error_stats_t) / sizeof (kstat_named_t),
 313                     KSTAT_FLAG_PERSISTENT);
 314 
 315                 if (HCDI_ERROR_STATS(hcdi) == NULL) {
 316 
 317                         return;
 318                 }
 319 
 320                 esp = HCDI_ERROR_STATS_DATA(hcdi);
 321                 kstat_named_init(&esp->cc_crc, "CRC Errors", KSTAT_DATA_UINT64);
 322                 kstat_named_init(&esp->cc_bitstuffing,
 323                     "Bit Stuffing Violations", KSTAT_DATA_UINT64);
 324                 kstat_named_init(&esp->cc_data_toggle_mm,
 325                     "Data Toggle PID Errors", KSTAT_DATA_UINT64);
 326                 kstat_named_init(&esp->cc_stall,
 327                     "Endpoint Stalls", KSTAT_DATA_UINT64);
 328                 kstat_named_init(&esp->cc_dev_not_resp,
 329                     "Device Not Responding", KSTAT_DATA_UINT64);
 330                 kstat_named_init(&esp->cc_pid_checkfailure,
 331                     "PID Check Bit Errors", KSTAT_DATA_UINT64);
 332                 kstat_named_init(&esp->cc_unexp_pid,
 333                     "Invalid PID Errors", KSTAT_DATA_UINT64);
 334                 kstat_named_init(&esp->cc_data_overrun,
 335                     "Data Overruns", KSTAT_DATA_UINT64);
 336                 kstat_named_init(&esp->cc_data_underrun,
 337                     "Data Underruns", KSTAT_DATA_UINT64);
 338                 kstat_named_init(&esp->cc_buffer_overrun,
 339                     "Buffer Overruns", KSTAT_DATA_UINT64);
 340                 kstat_named_init(&esp->cc_buffer_underrun,
 341                     "Buffer Underruns", KSTAT_DATA_UINT64);
 342                 kstat_named_init(&esp->cc_timeout,
 343                     "Command Timed Out", KSTAT_DATA_UINT64);
 344                 kstat_named_init(&esp->cc_not_accessed,
 345                     "Not Accessed By Hardware", KSTAT_DATA_UINT64);
 346                 kstat_named_init(&esp->cc_no_resources,
 347                     "No Resources", KSTAT_DATA_UINT64);
 348                 kstat_named_init(&esp->cc_unspecified_err,
 349                     "Unspecified Error", KSTAT_DATA_UINT64);
 350                 kstat_named_init(&esp->cc_stopped_polling,
 351                     "Stopped Polling", KSTAT_DATA_UINT64);
 352                 kstat_named_init(&esp->cc_pipe_closing,
 353                     "Pipe Closing", KSTAT_DATA_UINT64);
 354                 kstat_named_init(&esp->cc_pipe_reset,
 355                     "Pipe Reset", KSTAT_DATA_UINT64);
 356                 kstat_named_init(&esp->cc_not_supported,
 357                     "Command Not Supported", KSTAT_DATA_UINT64);
 358                 kstat_named_init(&esp->cc_flushed,
 359                     "Request Flushed", KSTAT_DATA_UINT64);
 360 
 361                 HCDI_ERROR_STATS(hcdi)->ks_private = hcdi;
 362                 HCDI_ERROR_STATS(hcdi)->ks_update = nulldev;
 363                 kstat_install(HCDI_ERROR_STATS(hcdi));
 364         }
 365 }
 366 
 367 
 368 /*
 369  * Do actual error stats
 370  */
 371 void
 372 usba_hcdi_update_error_stats(usba_hcdi_t *hcdi, usb_cr_t completion_reason)
 373 {
 374         if (HCDI_ERROR_STATS(hcdi) == NULL) {
 375 
 376                 return;
 377         }
 378 
 379         switch (completion_reason) {
 380         case USB_CR_OK:
 381                 break;
 382         case USB_CR_CRC:
 383                 HCDI_ERROR_STATS_DATA(hcdi)->cc_crc.value.ui64++;
 384                 break;
 385         case USB_CR_BITSTUFFING:
 386                 HCDI_ERROR_STATS_DATA(hcdi)->cc_bitstuffing.value.ui64++;
 387                 break;
 388         case USB_CR_DATA_TOGGLE_MM:
 389                 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_toggle_mm.value.ui64++;
 390                 break;
 391         case USB_CR_STALL:
 392                 HCDI_ERROR_STATS_DATA(hcdi)->cc_stall.value.ui64++;
 393                 break;
 394         case USB_CR_DEV_NOT_RESP:
 395                 HCDI_ERROR_STATS_DATA(hcdi)->cc_dev_not_resp.value.ui64++;
 396                 break;
 397         case USB_CR_PID_CHECKFAILURE:
 398                 HCDI_ERROR_STATS_DATA(hcdi)->cc_pid_checkfailure.value.ui64++;
 399                 break;
 400         case USB_CR_UNEXP_PID:
 401                 HCDI_ERROR_STATS_DATA(hcdi)->cc_unexp_pid.value.ui64++;
 402                 break;
 403         case USB_CR_DATA_OVERRUN:
 404                 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_overrun.value.ui64++;
 405                 break;
 406         case USB_CR_DATA_UNDERRUN:
 407                 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_underrun.value.ui64++;
 408                 break;
 409         case USB_CR_BUFFER_OVERRUN:
 410                 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_overrun.value.ui64++;
 411                 break;
 412         case USB_CR_BUFFER_UNDERRUN:
 413                 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_underrun.value.ui64++;
 414                 break;
 415         case USB_CR_TIMEOUT:
 416                 HCDI_ERROR_STATS_DATA(hcdi)->cc_timeout.value.ui64++;
 417                 break;
 418         case USB_CR_NOT_ACCESSED:
 419                 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_accessed.value.ui64++;
 420                 break;
 421         case USB_CR_NO_RESOURCES:
 422                 HCDI_ERROR_STATS_DATA(hcdi)->cc_no_resources.value.ui64++;
 423                 break;
 424         case USB_CR_UNSPECIFIED_ERR:
 425                 HCDI_ERROR_STATS_DATA(hcdi)->cc_unspecified_err.value.ui64++;
 426                 break;
 427         case USB_CR_STOPPED_POLLING:
 428                 HCDI_ERROR_STATS_DATA(hcdi)->cc_stopped_polling.value.ui64++;
 429                 break;
 430         case USB_CR_PIPE_CLOSING:
 431                 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_closing.value.ui64++;
 432                 break;
 433         case USB_CR_PIPE_RESET:
 434                 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_reset.value.ui64++;
 435                 break;
 436         case USB_CR_NOT_SUPPORTED:
 437                 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_supported.value.ui64++;
 438                 break;
 439         case USB_CR_FLUSHED:
 440                 HCDI_ERROR_STATS_DATA(hcdi)->cc_flushed.value.ui64++;
 441                 break;
 442         default:
 443                 break;
 444         }
 445 }
 446 
 447 
 448 /*
 449  * Destroy the hotplug kstats structure
 450  */
 451 static void
 452 usba_hcdi_destroy_stats(usba_hcdi_t *hcdi)
 453 {
 454         if (HCDI_HOTPLUG_STATS(hcdi)) {
 455                 kstat_delete(HCDI_HOTPLUG_STATS(hcdi));
 456                 HCDI_HOTPLUG_STATS(hcdi) = NULL;
 457         }
 458 
 459         if (HCDI_ERROR_STATS(hcdi)) {
 460                 kstat_delete(HCDI_ERROR_STATS(hcdi));
 461                 HCDI_ERROR_STATS(hcdi) = NULL;
 462         }
 463 }
 464 
 465 
 466 /*
 467  * HCD callback handling
 468  */
 469 void
 470 usba_hcdi_cb(usba_pipe_handle_data_t *ph_data,
 471         usb_opaque_t    req,
 472         usb_cr_t        completion_reason)
 473 {
 474 
 475         usba_device_t           *usba_device = ph_data->p_usba_device;
 476         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(
 477             usba_device->usb_root_hub_dip);
 478         usba_req_wrapper_t      *req_wrp = USBA_REQ2WRP(req);
 479         usb_ep_descr_t          *eptd = &ph_data->p_ep;
 480 
 481         mutex_enter(&ph_data->p_mutex);
 482 
 483 #ifdef DEBUG
 484         mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
 485 
 486         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 487             "usba_hcdi_cb: "
 488             "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d",
 489             (void *)ph_data, (void *)req, ph_data->p_ph_impl->usba_ph_state,
 490             ph_data->p_ph_impl->usba_ph_ref_count, ph_data->p_req_count,
 491             completion_reason);
 492 
 493         mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
 494 #endif
 495 
 496         /* Set the completion reason */
 497         switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
 498         case USB_EP_ATTR_CONTROL:
 499                 ((usb_ctrl_req_t *)req)->
 500                     ctrl_completion_reason = completion_reason;
 501                 break;
 502         case USB_EP_ATTR_BULK:
 503                 ((usb_bulk_req_t *)req)->
 504                     bulk_completion_reason = completion_reason;
 505                 break;
 506         case USB_EP_ATTR_INTR:
 507                 ((usb_intr_req_t *)req)->
 508                     intr_completion_reason = completion_reason;
 509                 break;
 510         case USB_EP_ATTR_ISOCH:
 511                 ((usb_isoc_req_t *)req)->
 512                     isoc_completion_reason = completion_reason;
 513                 break;
 514         }
 515 
 516         /*
 517          * exception callbacks will still go thru a taskq thread
 518          * but should occur after the soft interrupt callback
 519          * By design of periodic pipes, polling will stop on any
 520          * exception
 521          */
 522         if ((ph_data->p_spec_flag & USBA_PH_FLAG_USE_SOFT_INTR) &&
 523             (completion_reason == USB_CR_OK)) {
 524                 ph_data->p_soft_intr++;
 525                 mutex_exit(&ph_data->p_mutex);
 526 
 527                 usba_add_to_list(&hcdi->hcdi_cb_queue, &req_wrp->wr_queue);
 528 
 529                 if (ddi_intr_trigger_softint(hcdi->hcdi_softint_hdl, NULL) !=
 530                     DDI_SUCCESS)
 531                         USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 532                             "usba_hcdi_cb: ddi_intr_trigger_softint  failed");
 533 
 534                 return;
 535         }
 536 
 537         /*
 538          * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests,
 539          * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch,
 540          * so there are no conflicts.
 541          */
 542         if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
 543                 int iface;
 544 
 545                 mutex_exit(&ph_data->p_mutex);
 546                 iface = usb_get_if_number(ph_data->p_dip);
 547                 if (iface < 0) {
 548                         /* we own the device, use the first taskq */
 549                         iface = 0;
 550                 }
 551                 if (taskq_dispatch(usba_device->usb_shared_taskq[iface],
 552                     hcdi_shared_cb_thread, req_wrp, TQ_NOSLEEP) ==
 553                     NULL) {
 554                         usba_req_exc_cb(req_wrp,
 555                             USB_CR_NO_RESOURCES, USB_CB_ASYNC_REQ_FAILED);
 556                 }
 557 
 558                 return;
 559         }
 560 
 561         /* Add the callback to the pipehandles callback list */
 562         usba_add_to_list(&ph_data->p_cb_queue, &req_wrp->wr_queue);
 563 
 564         /* only dispatch if there is no thread running */
 565         if (ph_data->p_thread_id == 0) {
 566                 if (usba_async_ph_req(ph_data, hcdi_cb_thread,
 567                     ph_data, USB_FLAGS_NOSLEEP) != USB_SUCCESS) {
 568                         USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 569                             "usba_hcdi_cb: taskq_dispatch failed");
 570                         if (usba_rm_from_list(&ph_data->p_cb_queue,
 571                             &req_wrp->wr_queue) == USB_SUCCESS) {
 572                                 mutex_exit(&ph_data->p_mutex);
 573                                 usba_req_exc_cb(req_wrp,
 574                                     USB_CR_NO_RESOURCES,
 575                                     USB_CB_ASYNC_REQ_FAILED);
 576 
 577                                 return;
 578                         }
 579                 } else {
 580                         ph_data->p_thread_id = (kthread_t *)1;
 581                 }
 582         }
 583         mutex_exit(&ph_data->p_mutex);
 584 }
 585 
 586 
 587 /*
 588  * thread to perform the callbacks
 589  */
 590 static void
 591 hcdi_cb_thread(void *arg)
 592 {
 593         usba_pipe_handle_data_t *ph_data =
 594             (usba_pipe_handle_data_t *)arg;
 595         usba_ph_impl_t          *ph_impl = ph_data->p_ph_impl;
 596         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(ph_data->
 597             p_usba_device->usb_root_hub_dip);
 598         usba_req_wrapper_t      *req_wrp;
 599 
 600         mutex_enter(&ph_data->p_mutex);
 601         ASSERT(ph_data->p_thread_id == (kthread_t *)1);
 602         ph_data->p_thread_id = curthread;
 603 
 604         /*
 605          * hold the ph_data. we can't use usba_hold_ph_data() since
 606          * it will return NULL if we are closing the pipe which would
 607          * then leave all requests stuck in the cb_queue
 608          */
 609         mutex_enter(&ph_impl->usba_ph_mutex);
 610         ph_impl->usba_ph_ref_count++;
 611 
 612         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 613             "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data,
 614             ph_impl->usba_ph_ref_count);
 615 
 616         mutex_exit(&ph_impl->usba_ph_mutex);
 617 
 618         /*
 619          * wait till soft interrupt callbacks are taken care of
 620          */
 621         while (ph_data->p_soft_intr) {
 622                 mutex_exit(&ph_data->p_mutex);
 623                 delay(1);
 624                 mutex_enter(&ph_data->p_mutex);
 625         }
 626 
 627         while ((req_wrp = (usba_req_wrapper_t *)
 628             usba_rm_first_pvt_from_list(&ph_data->p_cb_queue)) != NULL) {
 629                 hcdi_do_cb(ph_data, req_wrp, hcdi);
 630         }
 631 
 632         ph_data->p_thread_id = 0;
 633         mutex_exit(&ph_data->p_mutex);
 634 
 635         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 636             "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
 637 
 638         usba_release_ph_data(ph_impl);
 639 }
 640 
 641 
 642 static void
 643 hcdi_do_cb(usba_pipe_handle_data_t *ph_data, usba_req_wrapper_t *req_wrp,
 644     usba_hcdi_t *hcdi)
 645 {
 646         usb_cr_t                completion_reason;
 647         usb_req_attrs_t         attrs = req_wrp->wr_attrs;
 648 
 649         switch (req_wrp->wr_ph_data->p_ep.bmAttributes &
 650             USB_EP_ATTR_MASK) {
 651         case USB_EP_ATTR_CONTROL:
 652                 completion_reason =
 653                     USBA_WRP2CTRL_REQ(req_wrp)->ctrl_completion_reason;
 654                 break;
 655         case USB_EP_ATTR_INTR:
 656                 completion_reason =
 657                     USBA_WRP2INTR_REQ(req_wrp)->intr_completion_reason;
 658                 break;
 659         case USB_EP_ATTR_BULK:
 660                 completion_reason =
 661                     USBA_WRP2BULK_REQ(req_wrp)->bulk_completion_reason;
 662                 break;
 663         case USB_EP_ATTR_ISOCH:
 664                 completion_reason =
 665                     USBA_WRP2ISOC_REQ(req_wrp)->isoc_completion_reason;
 666                 break;
 667         }
 668         req_wrp->wr_cr = completion_reason;
 669 
 670         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 671             "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp, completion_reason);
 672 
 673         /*
 674          * Normal callbacks:
 675          */
 676         if (completion_reason == USB_CR_OK) {
 677                 mutex_exit(&ph_data->p_mutex);
 678                 usba_req_normal_cb(req_wrp);
 679                 mutex_enter(&ph_data->p_mutex);
 680         } else {
 681                 usb_pipe_state_t pipe_state;
 682 
 683                 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 684                     "exception callback handling: attrs=0x%x", attrs);
 685 
 686                 /*
 687                  * In exception callback handling, if we were
 688                  * not able to clear stall, we need to modify
 689                  * pipe state. Also if auto-clearing is not set
 690                  * pipe state needs to be modified.
 691                  */
 692                 pipe_state = usba_get_ph_state(ph_data);
 693 
 694                 if (!USBA_PIPE_CLOSING(pipe_state)) {
 695                         switch (completion_reason) {
 696                         case USB_CR_STOPPED_POLLING:
 697                                 if (pipe_state ==
 698                                     USB_PIPE_STATE_ACTIVE) {
 699                                         usba_pipe_new_state(ph_data,
 700                                             USB_PIPE_STATE_IDLE);
 701                                 }
 702                                 break;
 703                         case USB_CR_NOT_SUPPORTED:
 704                                 usba_pipe_new_state(ph_data,
 705                                     USB_PIPE_STATE_IDLE);
 706                                 break;
 707                         case USB_CR_PIPE_RESET:
 708                         case USB_CR_FLUSHED:
 709                                 break;
 710                         default:
 711                                 usba_pipe_new_state(ph_data,
 712                                     USB_PIPE_STATE_ERROR);
 713                                 break;
 714                         }
 715                 }
 716 
 717                 pipe_state = usba_get_ph_state(ph_data);
 718 
 719                 mutex_exit(&ph_data->p_mutex);
 720                 if (attrs & USB_ATTRS_PIPE_RESET) {
 721                         if ((completion_reason != USB_CR_PIPE_RESET) &&
 722                             (pipe_state == USB_PIPE_STATE_ERROR)) {
 723 
 724                                 hcdi_autoclearing(req_wrp);
 725                         }
 726                 }
 727 
 728                 usba_req_exc_cb(req_wrp, 0, 0);
 729                 mutex_enter(&ph_data->p_mutex);
 730         }
 731 
 732         /* Update the hcdi error kstats */
 733         if (completion_reason) {
 734                 mutex_enter(&hcdi->hcdi_mutex);
 735                 usba_hcdi_update_error_stats(hcdi, completion_reason);
 736                 mutex_exit(&hcdi->hcdi_mutex);
 737         }
 738 
 739         /*
 740          * Once the callback is finished, release the pipe handle
 741          * we start the next request first to avoid that the
 742          * pipe gets closed while starting the next request
 743          */
 744         mutex_exit(&ph_data->p_mutex);
 745         usba_start_next_req(ph_data);
 746 
 747         mutex_enter(&ph_data->p_mutex);
 748 }
 749 
 750 
 751 /*
 752  * thread to perform callbacks on the shared queue
 753  */
 754 static void
 755 hcdi_shared_cb_thread(void *arg)
 756 {
 757         usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)arg;
 758         usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data;
 759         usba_ph_impl_t          *ph_impl = ph_data->p_ph_impl;
 760         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(ph_data->
 761             p_usba_device->usb_root_hub_dip);
 762         /*
 763          * hold the ph_data. we can't use usba_hold_ph_data() since
 764          * it will return NULL if we are closing the pipe which would
 765          * then leave all requests stuck in the cb_queue
 766          */
 767         mutex_enter(&ph_impl->usba_ph_mutex);
 768         ph_impl->usba_ph_ref_count++;
 769 
 770         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 771             "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p",
 772             (void *)ph_data, ph_impl->usba_ph_ref_count, (void *)req_wrp);
 773         mutex_exit(&ph_impl->usba_ph_mutex);
 774 
 775         /* do the callback */
 776         mutex_enter(&ph_data->p_mutex);
 777         hcdi_do_cb(ph_data, req_wrp, hcdi);
 778         mutex_exit(&ph_data->p_mutex);
 779 
 780         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 781             "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
 782 
 783         usba_release_ph_data(ph_impl);
 784 }
 785 
 786 
 787 /*
 788  * soft interrupt handler
 789  */
 790 /*ARGSUSED*/
 791 static uint_t
 792 hcdi_soft_intr(caddr_t arg1, caddr_t arg2)
 793 {
 794         usba_hcdi_t             *hcdi = (void *)arg1;
 795         usba_req_wrapper_t      *req_wrp;
 796         int                     count = 0;
 797 
 798         while ((req_wrp = (usba_req_wrapper_t *)
 799             usba_rm_first_pvt_from_list(&hcdi->hcdi_cb_queue)) != NULL) {
 800                 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data;
 801                 usba_ph_impl_t          *ph_impl = ph_data->p_ph_impl;
 802 
 803                 /* hold the pipe */
 804                 mutex_enter(&ph_impl->usba_ph_mutex);
 805                 ph_impl->usba_ph_ref_count++;
 806                 mutex_exit(&ph_impl->usba_ph_mutex);
 807 
 808                 /* do the callback */
 809                 usba_req_normal_cb(req_wrp);
 810 
 811                 /* decrement the soft interrupt count */
 812                 mutex_enter(&ph_data->p_mutex);
 813                 ph_data->p_soft_intr--;
 814                 mutex_exit(&ph_data->p_mutex);
 815 
 816                 /* release the pipe */
 817                 mutex_enter(&ph_impl->usba_ph_mutex);
 818                 ph_impl->usba_ph_ref_count--;
 819                 mutex_exit(&ph_impl->usba_ph_mutex);
 820 
 821                 count++;
 822         }
 823 
 824         return (count == 0 ? DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED);
 825 }
 826 
 827 
 828 /*
 829  * hcdi_autoclearing:
 830  *      This function is called under the taskq context. It
 831  *      resets the pipe, and clears the stall, if necessary
 832  */
 833 static void
 834 hcdi_autoclearing(usba_req_wrapper_t *req_wrp)
 835 {
 836         usb_cr_t                cr = req_wrp->wr_cr;
 837         usb_pipe_handle_t       pipe_handle, def_pipe_handle;
 838         usb_cr_t                completion_reason;
 839         usb_cb_flags_t          cb_flags;
 840         int                     rval;
 841         usba_device_t           *usba_device =
 842             req_wrp->wr_ph_data->p_usba_device;
 843         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(
 844             usba_device->usb_root_hub_dip);
 845         usb_req_attrs_t         attrs = req_wrp->wr_attrs;
 846 
 847         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 848             "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp);
 849 
 850         pipe_handle = usba_get_pipe_handle(req_wrp->wr_ph_data);
 851         def_pipe_handle = usba_get_dflt_pipe_handle(req_wrp->wr_ph_data->p_dip);
 852 
 853         /*
 854          * first reset the pipe synchronously
 855          */
 856         if ((attrs & USB_ATTRS_PIPE_RESET) == USB_ATTRS_PIPE_RESET) {
 857                 usba_pipe_clear(pipe_handle);
 858                 usba_req_set_cb_flags(req_wrp, USB_CB_RESET_PIPE);
 859         }
 860 
 861         ASSERT(def_pipe_handle);
 862 
 863         /* Do not clear if this request was a usb_get_status request */
 864         if ((pipe_handle == def_pipe_handle) &&
 865             (USBA_WRP2CTRL_REQ(req_wrp)->ctrl_bRequest ==
 866             USB_REQ_GET_STATUS)) {
 867                 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
 868                     "hcdi_autoclearing: usb_get_status failed, no clearing");
 869 
 870         /* if default pipe and stall no auto clearing */
 871         } else if ((pipe_handle == def_pipe_handle) && (cr == USB_CR_STALL)) {
 872                 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
 873                     "hcdi_autoclearing: default pipe stalled, no clearing");
 874 
 875                 usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
 876 
 877         /* else do auto clearing */
 878         } else if (((attrs & USB_ATTRS_AUTOCLEARING) ==
 879             USB_ATTRS_AUTOCLEARING) && (cr == USB_CR_STALL)) {
 880                 ushort_t status = 0;
 881 
 882                 rval = usb_get_status(req_wrp->wr_dip, def_pipe_handle,
 883                     USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_EP,
 884                     req_wrp->wr_ph_data->p_ep.bEndpointAddress,
 885                     &status, USB_FLAGS_SLEEP);
 886                 if (rval != USB_SUCCESS) {
 887                         USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
 888                             "get status (STALL) failed: rval=%d", rval);
 889 
 890                         usba_pipe_clear(def_pipe_handle);
 891                 }
 892 
 893                 if ((rval != USB_SUCCESS) ||
 894                     (status & USB_EP_HALT_STATUS)) {
 895                         usba_req_set_cb_flags(req_wrp, USB_CB_FUNCTIONAL_STALL);
 896 
 897                         if ((rval = usb_pipe_sync_ctrl_xfer(
 898                             req_wrp->wr_dip, def_pipe_handle,
 899                             USB_DEV_REQ_HOST_TO_DEV |
 900                             USB_DEV_REQ_RCPT_EP,
 901                             USB_REQ_CLEAR_FEATURE,
 902                             0,
 903                             req_wrp->wr_ph_data->p_ep.bEndpointAddress,
 904                             0,
 905                             NULL, 0,
 906                             &completion_reason,
 907                             &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
 908                                 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
 909                                     hcdi->hcdi_log_handle,
 910                                     "auto clearing (STALL) failed: "
 911                                     "rval=%d, cr=0x%x cb=0x%x",
 912                                     rval, completion_reason, cb_flags);
 913 
 914                                 usba_pipe_clear(def_pipe_handle);
 915                         } else {
 916                                 usba_req_set_cb_flags(req_wrp,
 917                                     USB_CB_STALL_CLEARED);
 918                         }
 919                 } else {
 920                         usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
 921                 }
 922         }
 923 }
 924 
 925 
 926 /*
 927  * usba_hcdi_get_req_private:
 928  *      This function is used to get the HCD private field
 929  *      maintained by USBA. HCD calls this function.
 930  *
 931  * Arguments:
 932  *      req             - pointer to usb_*_req_t
 933  *
 934  * Return Values:
 935  *      wr_hcd_private field from wrapper
 936  */
 937 usb_opaque_t
 938 usba_hcdi_get_req_private(usb_opaque_t req)
 939 {
 940         usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
 941 
 942         return (wrp->wr_hcd_private);
 943 }
 944 
 945 
 946 /*
 947  * usba_hcdi_set_req_private:
 948  *      This function is used to set the HCD private field
 949  *      maintained by USBA. HCD calls this function.
 950  *
 951  * Arguments:
 952  *      req             - pointer to usb_*_req_t
 953  *      hcd_private     - wr_hcd_private field from wrapper
 954  */
 955 void
 956 usba_hcdi_set_req_private(usb_opaque_t req,
 957                         usb_opaque_t    hcd_private)
 958 {
 959         usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
 960 
 961         wrp->wr_hcd_private = hcd_private;
 962 }
 963 
 964 
 965 /* get data toggle information for this endpoint */
 966 uchar_t
 967 usba_hcdi_get_data_toggle(usba_device_t *usba_device, uint8_t ep_addr)
 968 {
 969         uchar_t         toggle;
 970         usba_ph_impl_t  *ph_impl;
 971         int             ep_index;
 972 
 973         ep_index = usb_get_ep_index(ep_addr);
 974         mutex_enter(&usba_device->usb_mutex);
 975         ph_impl = &usba_device->usb_ph_list[ep_index];
 976         mutex_enter(&ph_impl->usba_ph_mutex);
 977         toggle = (uchar_t)(ph_impl->usba_ph_flags & USBA_PH_DATA_TOGGLE);
 978         mutex_exit(&ph_impl->usba_ph_mutex);
 979         mutex_exit(&usba_device->usb_mutex);
 980 
 981         return (toggle);
 982 }
 983 
 984 
 985 /* set data toggle information for this endpoint */
 986 void
 987 usba_hcdi_set_data_toggle(usba_device_t *usba_device, uint8_t ep_addr,
 988     uchar_t toggle)
 989 {
 990         usba_ph_impl_t  *ph_impl;
 991         int             ep_index;
 992 
 993         ep_index = usb_get_ep_index(ep_addr);
 994         mutex_enter(&usba_device->usb_mutex);
 995         ph_impl = &usba_device->usb_ph_list[ep_index];
 996         mutex_enter(&ph_impl->usba_ph_mutex);
 997         ph_impl->usba_ph_flags &= ~USBA_PH_DATA_TOGGLE;
 998         ph_impl->usba_ph_flags |= (USBA_PH_DATA_TOGGLE & toggle);
 999         mutex_exit(&ph_impl->usba_ph_mutex);
1000         mutex_exit(&usba_device->usb_mutex);
1001 }
1002 
1003 
1004 /* get pipe_handle_impl ptr for this ep */
1005 usba_pipe_handle_data_t *
1006 usba_hcdi_get_ph_data(usba_device_t *usba_device, uint8_t ep_addr)
1007 {
1008         return (usba_device->usb_ph_list[usb_get_ep_index(ep_addr)].
1009             usba_ph_data);
1010 }