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 #ifdef  NOTYETNEEDED
 361                 kstat_named_init(&esp->hcdi_usb_failure,
 362                     "USB Failure", KSTAT_DATA_UINT64);
 363                 kstat_named_init(&esp->hcdi_usb_no_resources,
 364                     "No Resources", KSTAT_DATA_UINT64);
 365                 kstat_named_init(&esp->hcdi_usb_no_bandwidth,
 366                     "No Bandwidth", KSTAT_DATA_UINT64);
 367                 kstat_named_init(&esp->hcdi_usb_pipe_reserved,
 368                     "Pipe Reserved", KSTAT_DATA_UINT64);
 369                 kstat_named_init(&esp->hcdi_usb_pipe_unshareable,
 370                     "Pipe Unshareable", KSTAT_DATA_UINT64);
 371                 kstat_named_init(&esp->hcdi_usb_not_supported,
 372                     "Function Not Supported", KSTAT_DATA_UINT64);
 373                 kstat_named_init(&esp->hcdi_usb_pipe_error,
 374                     "Pipe Error", KSTAT_DATA_UINT64);
 375                 kstat_named_init(&esp->hcdi_usb_pipe_busy,
 376                     "Pipe Busy", KSTAT_DATA_UINT64);
 377 #endif
 378 
 379                 HCDI_ERROR_STATS(hcdi)->ks_private = hcdi;
 380                 HCDI_ERROR_STATS(hcdi)->ks_update = nulldev;
 381                 kstat_install(HCDI_ERROR_STATS(hcdi));
 382         }
 383 }
 384 
 385 
 386 /*
 387  * Do actual error stats
 388  */
 389 void
 390 usba_hcdi_update_error_stats(usba_hcdi_t *hcdi, usb_cr_t completion_reason)
 391 {
 392         if (HCDI_ERROR_STATS(hcdi) == NULL) {
 393 
 394                 return;
 395         }
 396 
 397         switch (completion_reason) {
 398         case USB_CR_OK:
 399                 break;
 400         case USB_CR_CRC:
 401                 HCDI_ERROR_STATS_DATA(hcdi)->cc_crc.value.ui64++;
 402                 break;
 403         case USB_CR_BITSTUFFING:
 404                 HCDI_ERROR_STATS_DATA(hcdi)->cc_bitstuffing.value.ui64++;
 405                 break;
 406         case USB_CR_DATA_TOGGLE_MM:
 407                 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_toggle_mm.value.ui64++;
 408                 break;
 409         case USB_CR_STALL:
 410                 HCDI_ERROR_STATS_DATA(hcdi)->cc_stall.value.ui64++;
 411                 break;
 412         case USB_CR_DEV_NOT_RESP:
 413                 HCDI_ERROR_STATS_DATA(hcdi)->cc_dev_not_resp.value.ui64++;
 414                 break;
 415         case USB_CR_PID_CHECKFAILURE:
 416                 HCDI_ERROR_STATS_DATA(hcdi)->cc_pid_checkfailure.value.ui64++;
 417                 break;
 418         case USB_CR_UNEXP_PID:
 419                 HCDI_ERROR_STATS_DATA(hcdi)->cc_unexp_pid.value.ui64++;
 420                 break;
 421         case USB_CR_DATA_OVERRUN:
 422                 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_overrun.value.ui64++;
 423                 break;
 424         case USB_CR_DATA_UNDERRUN:
 425                 HCDI_ERROR_STATS_DATA(hcdi)->cc_data_underrun.value.ui64++;
 426                 break;
 427         case USB_CR_BUFFER_OVERRUN:
 428                 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_overrun.value.ui64++;
 429                 break;
 430         case USB_CR_BUFFER_UNDERRUN:
 431                 HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_underrun.value.ui64++;
 432                 break;
 433         case USB_CR_TIMEOUT:
 434                 HCDI_ERROR_STATS_DATA(hcdi)->cc_timeout.value.ui64++;
 435                 break;
 436         case USB_CR_NOT_ACCESSED:
 437                 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_accessed.value.ui64++;
 438                 break;
 439         case USB_CR_NO_RESOURCES:
 440                 HCDI_ERROR_STATS_DATA(hcdi)->cc_no_resources.value.ui64++;
 441                 break;
 442         case USB_CR_UNSPECIFIED_ERR:
 443                 HCDI_ERROR_STATS_DATA(hcdi)->cc_unspecified_err.value.ui64++;
 444                 break;
 445         case USB_CR_STOPPED_POLLING:
 446                 HCDI_ERROR_STATS_DATA(hcdi)->cc_stopped_polling.value.ui64++;
 447                 break;
 448         case USB_CR_PIPE_CLOSING:
 449                 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_closing.value.ui64++;
 450                 break;
 451         case USB_CR_PIPE_RESET:
 452                 HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_reset.value.ui64++;
 453                 break;
 454         case USB_CR_NOT_SUPPORTED:
 455                 HCDI_ERROR_STATS_DATA(hcdi)->cc_not_supported.value.ui64++;
 456                 break;
 457         case USB_CR_FLUSHED:
 458                 HCDI_ERROR_STATS_DATA(hcdi)->cc_flushed.value.ui64++;
 459                 break;
 460         default:
 461                 break;
 462         }
 463 }
 464 
 465 
 466 /*
 467  * Destroy the hotplug kstats structure
 468  */
 469 static void
 470 usba_hcdi_destroy_stats(usba_hcdi_t *hcdi)
 471 {
 472         if (HCDI_HOTPLUG_STATS(hcdi)) {
 473                 kstat_delete(HCDI_HOTPLUG_STATS(hcdi));
 474                 HCDI_HOTPLUG_STATS(hcdi) = NULL;
 475         }
 476 
 477         if (HCDI_ERROR_STATS(hcdi)) {
 478                 kstat_delete(HCDI_ERROR_STATS(hcdi));
 479                 HCDI_ERROR_STATS(hcdi) = NULL;
 480         }
 481 }
 482 
 483 
 484 /*
 485  * HCD callback handling
 486  */
 487 void
 488 usba_hcdi_cb(usba_pipe_handle_data_t *ph_data,
 489         usb_opaque_t    req,
 490         usb_cr_t        completion_reason)
 491 {
 492 
 493         usba_device_t           *usba_device = ph_data->p_usba_device;
 494         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(
 495             usba_device->usb_root_hub_dip);
 496         usba_req_wrapper_t      *req_wrp = USBA_REQ2WRP(req);
 497         usb_ep_descr_t          *eptd = &ph_data->p_ep;
 498 
 499         mutex_enter(&ph_data->p_mutex);
 500 
 501 #ifdef DEBUG
 502         mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
 503 
 504         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 505             "usba_hcdi_cb: "
 506             "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d",
 507             (void *)ph_data, (void *)req, ph_data->p_ph_impl->usba_ph_state,
 508             ph_data->p_ph_impl->usba_ph_ref_count, ph_data->p_req_count,
 509             completion_reason);
 510 
 511         mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
 512 #endif
 513 
 514         /* Set the completion reason */
 515         switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
 516         case USB_EP_ATTR_CONTROL:
 517                 ((usb_ctrl_req_t *)req)->
 518                     ctrl_completion_reason = completion_reason;
 519                 break;
 520         case USB_EP_ATTR_BULK:
 521                 ((usb_bulk_req_t *)req)->
 522                     bulk_completion_reason = completion_reason;
 523                 break;
 524         case USB_EP_ATTR_INTR:
 525                 ((usb_intr_req_t *)req)->
 526                     intr_completion_reason = completion_reason;
 527                 break;
 528         case USB_EP_ATTR_ISOCH:
 529                 ((usb_isoc_req_t *)req)->
 530                     isoc_completion_reason = completion_reason;
 531                 break;
 532         }
 533 
 534         /*
 535          * exception callbacks will still go thru a taskq thread
 536          * but should occur after the soft interrupt callback
 537          * By design of periodic pipes, polling will stop on any
 538          * exception
 539          */
 540         if ((ph_data->p_spec_flag & USBA_PH_FLAG_USE_SOFT_INTR) &&
 541             (completion_reason == USB_CR_OK)) {
 542                 ph_data->p_soft_intr++;
 543                 mutex_exit(&ph_data->p_mutex);
 544 
 545                 usba_add_to_list(&hcdi->hcdi_cb_queue, &req_wrp->wr_queue);
 546 
 547                 if (ddi_intr_trigger_softint(hcdi->hcdi_softint_hdl, NULL) !=
 548                     DDI_SUCCESS)
 549                         USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 550                             "usba_hcdi_cb: ddi_intr_trigger_softint  failed");
 551 
 552                 return;
 553         }
 554 
 555         /*
 556          * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests,
 557          * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch,
 558          * so there are no conflicts.
 559          */
 560         if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
 561                 int iface;
 562 
 563                 mutex_exit(&ph_data->p_mutex);
 564                 iface = usb_get_if_number(ph_data->p_dip);
 565                 if (iface < 0) {
 566                         /* we own the device, use the first taskq */
 567                         iface = 0;
 568                 }
 569                 if (taskq_dispatch(usba_device->usb_shared_taskq[iface],
 570                     hcdi_shared_cb_thread, req_wrp, TQ_NOSLEEP) ==
 571                     NULL) {
 572                         usba_req_exc_cb(req_wrp,
 573                             USB_CR_NO_RESOURCES, USB_CB_ASYNC_REQ_FAILED);
 574                 }
 575 
 576                 return;
 577         }
 578 
 579         /* Add the callback to the pipehandles callback list */
 580         usba_add_to_list(&ph_data->p_cb_queue, &req_wrp->wr_queue);
 581 
 582         /* only dispatch if there is no thread running */
 583         if (ph_data->p_thread_id == 0) {
 584                 if (usba_async_ph_req(ph_data, hcdi_cb_thread,
 585                     ph_data, USB_FLAGS_NOSLEEP) != USB_SUCCESS) {
 586                         USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 587                             "usba_hcdi_cb: taskq_dispatch failed");
 588                         if (usba_rm_from_list(&ph_data->p_cb_queue,
 589                             &req_wrp->wr_queue) == USB_SUCCESS) {
 590                                 mutex_exit(&ph_data->p_mutex);
 591                                 usba_req_exc_cb(req_wrp,
 592                                     USB_CR_NO_RESOURCES,
 593                                     USB_CB_ASYNC_REQ_FAILED);
 594 
 595                                 return;
 596                         }
 597                 } else {
 598                         ph_data->p_thread_id = (kthread_t *)1;
 599                 }
 600         }
 601         mutex_exit(&ph_data->p_mutex);
 602 }
 603 
 604 
 605 /*
 606  * thread to perform the callbacks
 607  */
 608 static void
 609 hcdi_cb_thread(void *arg)
 610 {
 611         usba_pipe_handle_data_t *ph_data =
 612             (usba_pipe_handle_data_t *)arg;
 613         usba_ph_impl_t          *ph_impl = ph_data->p_ph_impl;
 614         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(ph_data->
 615             p_usba_device->usb_root_hub_dip);
 616         usba_req_wrapper_t      *req_wrp;
 617 
 618         mutex_enter(&ph_data->p_mutex);
 619         ASSERT(ph_data->p_thread_id == (kthread_t *)1);
 620         ph_data->p_thread_id = curthread;
 621 
 622         /*
 623          * hold the ph_data. we can't use usba_hold_ph_data() since
 624          * it will return NULL if we are closing the pipe which would
 625          * then leave all requests stuck in the cb_queue
 626          */
 627         mutex_enter(&ph_impl->usba_ph_mutex);
 628         ph_impl->usba_ph_ref_count++;
 629 
 630         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 631             "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data,
 632             ph_impl->usba_ph_ref_count);
 633 
 634         mutex_exit(&ph_impl->usba_ph_mutex);
 635 
 636         /*
 637          * wait till soft interrupt callbacks are taken care of
 638          */
 639         while (ph_data->p_soft_intr) {
 640                 mutex_exit(&ph_data->p_mutex);
 641                 delay(1);
 642                 mutex_enter(&ph_data->p_mutex);
 643         }
 644 
 645         while ((req_wrp = (usba_req_wrapper_t *)
 646             usba_rm_first_pvt_from_list(&ph_data->p_cb_queue)) != NULL) {
 647                 hcdi_do_cb(ph_data, req_wrp, hcdi);
 648         }
 649 
 650         ph_data->p_thread_id = 0;
 651         mutex_exit(&ph_data->p_mutex);
 652 
 653         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 654             "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
 655 
 656         usba_release_ph_data(ph_impl);
 657 }
 658 
 659 
 660 static void
 661 hcdi_do_cb(usba_pipe_handle_data_t *ph_data, usba_req_wrapper_t *req_wrp,
 662     usba_hcdi_t *hcdi)
 663 {
 664         usb_cr_t                completion_reason;
 665         usb_req_attrs_t         attrs = req_wrp->wr_attrs;
 666 
 667         switch (req_wrp->wr_ph_data->p_ep.bmAttributes &
 668             USB_EP_ATTR_MASK) {
 669         case USB_EP_ATTR_CONTROL:
 670                 completion_reason =
 671                     USBA_WRP2CTRL_REQ(req_wrp)->ctrl_completion_reason;
 672                 break;
 673         case USB_EP_ATTR_INTR:
 674                 completion_reason =
 675                     USBA_WRP2INTR_REQ(req_wrp)->intr_completion_reason;
 676                 break;
 677         case USB_EP_ATTR_BULK:
 678                 completion_reason =
 679                     USBA_WRP2BULK_REQ(req_wrp)->bulk_completion_reason;
 680                 break;
 681         case USB_EP_ATTR_ISOCH:
 682                 completion_reason =
 683                     USBA_WRP2ISOC_REQ(req_wrp)->isoc_completion_reason;
 684                 break;
 685         }
 686         req_wrp->wr_cr = completion_reason;
 687 
 688         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 689             "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp, completion_reason);
 690 
 691         /*
 692          * Normal callbacks:
 693          */
 694         if (completion_reason == USB_CR_OK) {
 695                 mutex_exit(&ph_data->p_mutex);
 696                 usba_req_normal_cb(req_wrp);
 697                 mutex_enter(&ph_data->p_mutex);
 698         } else {
 699                 usb_pipe_state_t pipe_state;
 700 
 701                 USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 702                     "exception callback handling: attrs=0x%x", attrs);
 703 
 704                 /*
 705                  * In exception callback handling, if we were
 706                  * not able to clear stall, we need to modify
 707                  * pipe state. Also if auto-clearing is not set
 708                  * pipe state needs to be modified.
 709                  */
 710                 pipe_state = usba_get_ph_state(ph_data);
 711 
 712                 if (!USBA_PIPE_CLOSING(pipe_state)) {
 713                         switch (completion_reason) {
 714                         case USB_CR_STOPPED_POLLING:
 715                                 if (pipe_state ==
 716                                     USB_PIPE_STATE_ACTIVE) {
 717                                         usba_pipe_new_state(ph_data,
 718                                             USB_PIPE_STATE_IDLE);
 719                                 }
 720                                 break;
 721                         case USB_CR_NOT_SUPPORTED:
 722                                 usba_pipe_new_state(ph_data,
 723                                     USB_PIPE_STATE_IDLE);
 724                                 break;
 725                         case USB_CR_PIPE_RESET:
 726                         case USB_CR_FLUSHED:
 727                                 break;
 728                         default:
 729                                 usba_pipe_new_state(ph_data,
 730                                     USB_PIPE_STATE_ERROR);
 731                                 break;
 732                         }
 733                 }
 734 
 735                 pipe_state = usba_get_ph_state(ph_data);
 736 
 737                 mutex_exit(&ph_data->p_mutex);
 738                 if (attrs & USB_ATTRS_PIPE_RESET) {
 739                         if ((completion_reason != USB_CR_PIPE_RESET) &&
 740                             (pipe_state == USB_PIPE_STATE_ERROR)) {
 741 
 742                                 hcdi_autoclearing(req_wrp);
 743                         }
 744                 }
 745 
 746                 usba_req_exc_cb(req_wrp, 0, 0);
 747                 mutex_enter(&ph_data->p_mutex);
 748         }
 749 
 750         /* Update the hcdi error kstats */
 751         if (completion_reason) {
 752                 mutex_enter(&hcdi->hcdi_mutex);
 753                 usba_hcdi_update_error_stats(hcdi, completion_reason);
 754                 mutex_exit(&hcdi->hcdi_mutex);
 755         }
 756 
 757         /*
 758          * Once the callback is finished, release the pipe handle
 759          * we start the next request first to avoid that the
 760          * pipe gets closed while starting the next request
 761          */
 762         mutex_exit(&ph_data->p_mutex);
 763         usba_start_next_req(ph_data);
 764 
 765         mutex_enter(&ph_data->p_mutex);
 766 }
 767 
 768 
 769 /*
 770  * thread to perform callbacks on the shared queue
 771  */
 772 static void
 773 hcdi_shared_cb_thread(void *arg)
 774 {
 775         usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)arg;
 776         usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data;
 777         usba_ph_impl_t          *ph_impl = ph_data->p_ph_impl;
 778         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(ph_data->
 779             p_usba_device->usb_root_hub_dip);
 780         /*
 781          * hold the ph_data. we can't use usba_hold_ph_data() since
 782          * it will return NULL if we are closing the pipe which would
 783          * then leave all requests stuck in the cb_queue
 784          */
 785         mutex_enter(&ph_impl->usba_ph_mutex);
 786         ph_impl->usba_ph_ref_count++;
 787 
 788         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 789             "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p",
 790             (void *)ph_data, ph_impl->usba_ph_ref_count, (void *)req_wrp);
 791         mutex_exit(&ph_impl->usba_ph_mutex);
 792 
 793         /* do the callback */
 794         mutex_enter(&ph_data->p_mutex);
 795         hcdi_do_cb(ph_data, req_wrp, hcdi);
 796         mutex_exit(&ph_data->p_mutex);
 797 
 798         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 799             "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
 800 
 801         usba_release_ph_data(ph_impl);
 802 }
 803 
 804 
 805 /*
 806  * soft interrupt handler
 807  */
 808 /*ARGSUSED*/
 809 static uint_t
 810 hcdi_soft_intr(caddr_t arg1, caddr_t arg2)
 811 {
 812         usba_hcdi_t             *hcdi = (void *)arg1;
 813         usba_req_wrapper_t      *req_wrp;
 814         int                     count = 0;
 815 
 816         while ((req_wrp = (usba_req_wrapper_t *)
 817             usba_rm_first_pvt_from_list(&hcdi->hcdi_cb_queue)) != NULL) {
 818                 usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data;
 819                 usba_ph_impl_t          *ph_impl = ph_data->p_ph_impl;
 820 
 821                 /* hold the pipe */
 822                 mutex_enter(&ph_impl->usba_ph_mutex);
 823                 ph_impl->usba_ph_ref_count++;
 824                 mutex_exit(&ph_impl->usba_ph_mutex);
 825 
 826                 /* do the callback */
 827                 usba_req_normal_cb(req_wrp);
 828 
 829                 /* decrement the soft interrupt count */
 830                 mutex_enter(&ph_data->p_mutex);
 831                 ph_data->p_soft_intr--;
 832                 mutex_exit(&ph_data->p_mutex);
 833 
 834                 /* release the pipe */
 835                 mutex_enter(&ph_impl->usba_ph_mutex);
 836                 ph_impl->usba_ph_ref_count--;
 837                 mutex_exit(&ph_impl->usba_ph_mutex);
 838 
 839                 count++;
 840         }
 841 
 842         return (count == 0 ? DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED);
 843 }
 844 
 845 
 846 /*
 847  * hcdi_autoclearing:
 848  *      This function is called under the taskq context. It
 849  *      resets the pipe, and clears the stall, if necessary
 850  */
 851 static void
 852 hcdi_autoclearing(usba_req_wrapper_t *req_wrp)
 853 {
 854         usb_cr_t                cr = req_wrp->wr_cr;
 855         usb_pipe_handle_t       pipe_handle, def_pipe_handle;
 856         usb_cr_t                completion_reason;
 857         usb_cb_flags_t          cb_flags;
 858         int                     rval;
 859         usba_device_t           *usba_device =
 860             req_wrp->wr_ph_data->p_usba_device;
 861         usba_hcdi_t             *hcdi = usba_hcdi_get_hcdi(
 862             usba_device->usb_root_hub_dip);
 863         usb_req_attrs_t         attrs = req_wrp->wr_attrs;
 864 
 865         USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
 866             "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp);
 867 
 868         pipe_handle = usba_get_pipe_handle(req_wrp->wr_ph_data);
 869         def_pipe_handle = usba_get_dflt_pipe_handle(req_wrp->wr_ph_data->p_dip);
 870 
 871         /*
 872          * first reset the pipe synchronously
 873          */
 874         if ((attrs & USB_ATTRS_PIPE_RESET) == USB_ATTRS_PIPE_RESET) {
 875                 usba_pipe_clear(pipe_handle);
 876                 usba_req_set_cb_flags(req_wrp, USB_CB_RESET_PIPE);
 877         }
 878 
 879         ASSERT(def_pipe_handle);
 880 
 881         /* Do not clear if this request was a usb_get_status request */
 882         if ((pipe_handle == def_pipe_handle) &&
 883             (USBA_WRP2CTRL_REQ(req_wrp)->ctrl_bRequest ==
 884             USB_REQ_GET_STATUS)) {
 885                 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
 886                     "hcdi_autoclearing: usb_get_status failed, no clearing");
 887 
 888         /* if default pipe and stall no auto clearing */
 889         } else if ((pipe_handle == def_pipe_handle) && (cr == USB_CR_STALL)) {
 890                 USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
 891                     "hcdi_autoclearing: default pipe stalled, no clearing");
 892 
 893                 usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
 894 
 895         /* else do auto clearing */
 896         } else if (((attrs & USB_ATTRS_AUTOCLEARING) ==
 897             USB_ATTRS_AUTOCLEARING) && (cr == USB_CR_STALL)) {
 898                 ushort_t status = 0;
 899 
 900                 rval = usb_get_status(req_wrp->wr_dip, def_pipe_handle,
 901                     USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_EP,
 902                     req_wrp->wr_ph_data->p_ep.bEndpointAddress,
 903                     &status, USB_FLAGS_SLEEP);
 904                 if (rval != USB_SUCCESS) {
 905                         USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
 906                             "get status (STALL) failed: rval=%d", rval);
 907 
 908                         usba_pipe_clear(def_pipe_handle);
 909                 }
 910 
 911                 if ((rval != USB_SUCCESS) ||
 912                     (status & USB_EP_HALT_STATUS)) {
 913                         usba_req_set_cb_flags(req_wrp, USB_CB_FUNCTIONAL_STALL);
 914 
 915                         if ((rval = usb_pipe_sync_ctrl_xfer(
 916                             req_wrp->wr_dip, def_pipe_handle,
 917                             USB_DEV_REQ_HOST_TO_DEV |
 918                             USB_DEV_REQ_RCPT_EP,
 919                             USB_REQ_CLEAR_FEATURE,
 920                             0,
 921                             req_wrp->wr_ph_data->p_ep.bEndpointAddress,
 922                             0,
 923                             NULL, 0,
 924                             &completion_reason,
 925                             &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
 926                                 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
 927                                     hcdi->hcdi_log_handle,
 928                                     "auto clearing (STALL) failed: "
 929                                     "rval=%d, cr=0x%x cb=0x%x",
 930                                     rval, completion_reason, cb_flags);
 931 
 932                                 usba_pipe_clear(def_pipe_handle);
 933                         } else {
 934                                 usba_req_set_cb_flags(req_wrp,
 935                                     USB_CB_STALL_CLEARED);
 936                         }
 937                 } else {
 938                         usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
 939                 }
 940         }
 941 }
 942 
 943 
 944 /*
 945  * usba_hcdi_get_req_private:
 946  *      This function is used to get the HCD private field
 947  *      maintained by USBA. HCD calls this function.
 948  *
 949  * Arguments:
 950  *      req             - pointer to usb_*_req_t
 951  *
 952  * Return Values:
 953  *      wr_hcd_private field from wrapper
 954  */
 955 usb_opaque_t
 956 usba_hcdi_get_req_private(usb_opaque_t req)
 957 {
 958         usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
 959 
 960         return (wrp->wr_hcd_private);
 961 }
 962 
 963 
 964 /*
 965  * usba_hcdi_set_req_private:
 966  *      This function is used to set the HCD private field
 967  *      maintained by USBA. HCD calls this function.
 968  *
 969  * Arguments:
 970  *      req             - pointer to usb_*_req_t
 971  *      hcd_private     - wr_hcd_private field from wrapper
 972  */
 973 void
 974 usba_hcdi_set_req_private(usb_opaque_t req,
 975                         usb_opaque_t    hcd_private)
 976 {
 977         usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
 978 
 979         wrp->wr_hcd_private = hcd_private;
 980 }
 981 
 982 
 983 /* get data toggle information for this endpoint */
 984 uchar_t
 985 usba_hcdi_get_data_toggle(usba_device_t *usba_device, uint8_t ep_addr)
 986 {
 987         uchar_t         toggle;
 988         usba_ph_impl_t  *ph_impl;
 989         int             ep_index;
 990 
 991         ep_index = usb_get_ep_index(ep_addr);
 992         mutex_enter(&usba_device->usb_mutex);
 993         ph_impl = &usba_device->usb_ph_list[ep_index];
 994         mutex_enter(&ph_impl->usba_ph_mutex);
 995         toggle = (uchar_t)(ph_impl->usba_ph_flags & USBA_PH_DATA_TOGGLE);
 996         mutex_exit(&ph_impl->usba_ph_mutex);
 997         mutex_exit(&usba_device->usb_mutex);
 998 
 999         return (toggle);
1000 }
1001 
1002 
1003 /* set data toggle information for this endpoint */
1004 void
1005 usba_hcdi_set_data_toggle(usba_device_t *usba_device, uint8_t ep_addr,
1006     uchar_t toggle)
1007 {
1008         usba_ph_impl_t  *ph_impl;
1009         int             ep_index;
1010 
1011         ep_index = usb_get_ep_index(ep_addr);
1012         mutex_enter(&usba_device->usb_mutex);
1013         ph_impl = &usba_device->usb_ph_list[ep_index];
1014         mutex_enter(&ph_impl->usba_ph_mutex);
1015         ph_impl->usba_ph_flags &= ~USBA_PH_DATA_TOGGLE;
1016         ph_impl->usba_ph_flags |= (USBA_PH_DATA_TOGGLE & toggle);
1017         mutex_exit(&ph_impl->usba_ph_mutex);
1018         mutex_exit(&usba_device->usb_mutex);
1019 }
1020 
1021 
1022 /* get pipe_handle_impl ptr for this ep */
1023 usba_pipe_handle_data_t *
1024 usba_hcdi_get_ph_data(usba_device_t *usba_device, uint8_t ep_addr)
1025 {
1026         return (usba_device->usb_ph_list[usb_get_ep_index(ep_addr)].
1027             usba_ph_data);
1028 }