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