1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #ifndef _SYS_USB_USBA_USBA_IMPL_H
  27 #define _SYS_USB_USBA_USBA_IMPL_H
  28 
  29 
  30 #include <sys/usb/usba.h>
  31 #include <sys/usb/usba/hcdi.h>
  32 #include <sys/usb/usba/hubdi.h>
  33 #include <sys/usb/usba/usba_private.h>
  34 #include <sys/usb/usba/usba_types.h>
  35 #include <sys/taskq.h>
  36 #include <sys/disp.h>
  37 
  38 #ifdef  __cplusplus
  39 extern "C" {
  40 #endif
  41 
  42 
  43 /*
  44  * UGEN binding values specified in <hcd>.conf files
  45  */
  46 #define USBA_UGEN_DEVICE_BINDING        1
  47 #define USBA_UGEN_INTERFACE_BINDING     2
  48 #define USBA_UGEN_INTERFACE_ASSOCIATION_BINDING         3
  49 
  50 /*
  51  * Allocating a USB address
  52  */
  53 #define USBA_MAX_ADDRESS                127
  54 #define USBA_ADDRESS_ARRAY_SIZE ((USBA_MAX_ADDRESS+8)/8)
  55 
  56 /*
  57  * async execution of usb_pipe_* functions which have a
  58  * completion callback parameter (eg. usb_pipe_close(),
  59  * usb_pipe_reset(), usb_pipe_stop_*_polling()
  60  */
  61 typedef struct usba_pipe_async_req {
  62         dev_info_t              *dip;
  63         struct usba_ph_impl     *ph_impl;
  64         usb_opaque_t            arg;
  65         usb_flags_t             usb_flags;
  66         void                    (*callback)(
  67                                         usb_pipe_handle_t       ph,
  68                                         usb_opaque_t            callback_arg,
  69                                         int                     rval,
  70                                         usb_cb_flags_t          error_code);
  71         usb_opaque_t            callback_arg;
  72         int                     (*sync_func)(dev_info_t *,
  73                                         usba_ph_impl_t *,
  74                                         struct usba_pipe_async_req *,
  75                                         usb_flags_t);
  76 } usba_pipe_async_req_t;
  77 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usba_pipe_async_req_t))
  78 
  79 /* per-pipe taskq */
  80 int     usba_async_ph_req(usba_pipe_handle_data_t *, void (*func)(void *),
  81                                                         void *, usb_flags_t);
  82 
  83 /*
  84  * usb wrapper around pm_request_power_change to allow for
  85  * non blocking behavior
  86  */
  87 typedef struct usba_pm_req {
  88         dev_info_t      *dip;
  89         int             comp;
  90         int             old_level;
  91         int             level;
  92         void            (*cb)(void *, int);
  93         void            *arg;
  94         uint_t          flags;
  95 } usba_pm_req_t;
  96 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usba_pm_req_t))
  97 
  98 
  99 /*
 100  * Request wrappers for control/bulk/interrupt and isoch pipes
 101  * These are hidden from client driver. They serve as place-holders
 102  * for doing callbacks
 103  *
 104  * Request allocation: wrapper + usb_*_req_t alloc'ed together:
 105  *
 106  *              +-----------------------+
 107  *              |       wr_queue        |               for callbacks
 108  *              +-----------------------+
 109  *              |       wr_req  |-------+       wr_req points to
 110  *              +-----------------------+       |       the req below.
 111  *              |                       |       |
 112  *              |       ....            |       |
 113  *              |       req_wrapper_t   |       |
 114  *              |                       |       |
 115  *              +-----------------------+<------+
 116  *              |                       |
 117  *              |       ....            |
 118  *              | ctrl/bulk/intr/isoch  |
 119  *              |       req_t   |
 120  *              |                       |
 121  *              |                       |
 122  *              +-----------------------+
 123  */
 124 typedef struct usba_req_wrapper {
 125         /* queueing in either a request or callback queue */
 126         usba_list_entry_t       wr_queue;
 127 
 128         /*
 129          * The request could be control/bulk/intr/isoc
 130          * See usbai.h usb_ctrl_req_t/usb_bulk_req_t
 131          * usb_intr_req_t/usb_isoc_req_t
 132          */
 133         usb_opaque_t            wr_req;
 134 
 135         /* for allocation tracking in usba_device_t */
 136         usba_list_entry_t       wr_allocated_list;
 137 
 138         /*
 139          * All reqs that are synchronous sleep on this cv
 140          * for completion notification.
 141          * In hcdi soft interrupt handler we call cv_signal()
 142          */
 143         kcondvar_t              wr_cv;
 144 
 145         /*
 146          * This goes hand-in-hand with wr_cv. It is set by the soft intr hdlr
 147          * before doing a cv_signal
 148          */
 149         boolean_t               wr_done;
 150         dev_info_t              *wr_dip;        /* owner */
 151 
 152         usb_opaque_t            wr_hcd_private; /* for HCD's use */
 153 
 154         usba_pipe_handle_data_t *wr_ph_data;    /* ptr to pipe handle */
 155 
 156         usb_cr_t                wr_cr;          /* save cr from HCDI */
 157         usb_cb_flags_t          wr_cb_flags;    /* save cb_flags */
 158         usb_flags_t             wr_usb_flags;   /* save usb flags from HCDI */
 159         usb_req_attrs_t         wr_attrs;       /* save attrs from HCDI */
 160 
 161         /* total lenght of wrapper and request */
 162         size_t                  wr_length;
 163 } usba_req_wrapper_t;
 164 
 165 _NOTE(SCHEME_PROTECTS_DATA("method", usba_req_wrapper))
 166 _NOTE(SCHEME_PROTECTS_DATA("method", usb_ctrl_req))
 167 _NOTE(SCHEME_PROTECTS_DATA("method", usb_bulk_req))
 168 _NOTE(SCHEME_PROTECTS_DATA("method", usb_intr_req))
 169 _NOTE(SCHEME_PROTECTS_DATA("method", usb_isoc_req))
 170 
 171 /* additional flag for wr_usb_flags */
 172 #define USBA_WRP_FLAGS_WAIT     0x01
 173 
 174 /* additional usb flags, not exposed to clients */
 175 #define USBA_FLAGS_PRIVILEGED   0x02    /* for default pipe operations */
 176 
 177 /* Macros to convert wrapper to different request and vice-versa */
 178 
 179 /* to get the wr->wr_req field */
 180 #define USBA_WRP2REQ(wrp)       ((wrp)->wr_req)
 181 
 182 /* to get the wrapper form the wr_req field */
 183 #define USBA_REQ2WRP(req)               (usba_req_wrapper_t *)\
 184                                 ((uintptr_t)(req) - sizeof (usba_req_wrapper_t))
 185 
 186 /* to set the the address in the wr_req field */
 187 #define USBA_SETREQ_ADDR(wrp)   ((uintptr_t)(wrp) + sizeof (*(wrp)))
 188 
 189 /* to get the 4 xfer type requests */
 190 #define USBA_WRP2CTRL_REQ(wrp)  ((usb_ctrl_req_t *)USBA_WRP2REQ((wrp)))
 191 #define USBA_WRP2INTR_REQ(wrp)  ((usb_intr_req_t *)USBA_WRP2REQ((wrp)))
 192 #define USBA_WRP2BULK_REQ(wrp)  ((usb_bulk_req_t *)USBA_WRP2REQ((wrp)))
 193 #define USBA_WRP2ISOC_REQ(wrp)  ((usb_isoc_req_t *)USBA_WRP2REQ((wrp)))
 194 
 195 /* to get pipe_handle from the wrapper */
 196 #define USBA_WRP2PH_DATA(wrp) \
 197         (usba_pipe_handle_data_t *)((wrp)->wr_ph_data)
 198 
 199 /* to get to the wr_queue from the wrapper */
 200 #define USBA_WRQUEUE2WRP(queue) (usba_req_wrapper_t *)(queue)
 201 
 202 /* to get to the wr_allocated queue from the wrapper */
 203 #define USBA_ALLOCQ2WRP(queue)  (usba_req_wrapper_t *)((uintptr_t) \
 204         (queue)  - sizeof (usba_list_entry_t) - sizeof (usb_opaque_t))
 205 
 206 
 207 /* alias for pipe handle member p_usba_private */
 208 #define p_active_cntrl_req_wrp  p_usba_private
 209 
 210 /*
 211  * This function is used to get the HCD private field maintained by USBA.
 212  * HCD calls this function.
 213  */
 214 usb_opaque_t usba_hcdi_get_ctrl_req_hcd_private(usb_ctrl_req_t *);
 215 
 216 /*
 217  * This function is used to set the HCD private field maintained by USBA.
 218  * HCD calls this function.
 219  */
 220 void    usba_hcdi_set_ctrl_req_hcd_private(usb_ctrl_req_t *, usb_opaque_t);
 221 
 222 int     usba_set_usb_address(usba_device_t *);
 223 void    usba_unset_usb_address(usba_device_t *);
 224 
 225 /*
 226  * Per Hub Data Structures
 227  */
 228 typedef  struct usba_hubdi {
 229         usba_list_entry_t hubdi_list;    /* linking in hubdi list */
 230 
 231         dev_info_t      *hubdi_dip;      /* ptr to devinfo struct */
 232 
 233         int             hubdi_flags;    /* flag options */
 234 
 235 } usba_hubdi_t;
 236 
 237 /*
 238  * usba_get_mfg_prod_sn_str:
 239  *      Return a string containing mfg, product, serial number strings.
 240  *      Remove duplicates if some strings are the same.
 241  */
 242 char    *usba_get_mfg_prod_sn_str(dev_info_t *, char *, int);
 243 
 244 /* return value when user doesn't specify configuration index */
 245 #define USBA_DEV_CONFIG_INDEX_UNDEFINED -1
 246 
 247 /*
 248  * prototypes
 249  */
 250 void    usba_usba_initialization();
 251 void    usba_usba_destroy();
 252 
 253 void    usba_usbai_register_initialization();
 254 void    usba_usbai_register_destroy();
 255 
 256 void    usba_usbai_initialization();
 257 void    usba_usbai_destroy();
 258 
 259 void    usba_hubdi_initialization();
 260 void    usba_hubdi_destroy();
 261 
 262 void    usba_devdb_initialization();
 263 void    usba_devdb_destroy();
 264 
 265 int     usba_hubdi_register(dev_info_t  *, uint_t);
 266 int     usba_hubdi_unregister(dev_info_t *);
 267 
 268 void    usba_whcdi_initialization();
 269 void    usba_whcdi_destroy();
 270 
 271 int     usba_is_root_hub(dev_info_t *dip);
 272 int     usba_is_wa(dev_info_t *dip);
 273 int     usba_is_hwa(dev_info_t *dip);
 274 
 275 usba_device_t *usba_alloc_usba_device(dev_info_t *);
 276 void    usba_free_wireless_data(usba_wireless_data_t *wireless_data);
 277 void    usba_free_usba_device(usba_device_t *usba_device_t);
 278 void    usba_clear_data_toggle(usba_device_t *usba_device);
 279 
 280 void    usba_start_next_req(usba_pipe_handle_data_t *ph);
 281 
 282 int     usba_pipe_check_handle(usba_pipe_handle_data_t *);
 283 int     usba_drain_cbs(usba_pipe_handle_data_t *, usb_cb_flags_t,
 284                         usb_cr_t);
 285 int     usba_pipe_setup_func_call(dev_info_t *,
 286                         int (*sync_func)(dev_info_t *,
 287                                 usba_ph_impl_t *, usba_pipe_async_req_t *,
 288                                 usb_flags_t),
 289                         usba_ph_impl_t *,
 290                         usb_opaque_t,
 291                         usb_flags_t,
 292                         void (*cb)(usb_pipe_handle_t, usb_opaque_t,
 293                             int, usb_cb_flags_t),
 294                         usb_opaque_t);
 295 
 296 
 297 void    usba_pipe_new_state(usba_pipe_handle_data_t *, usb_pipe_state_t);
 298 
 299 void usba_add_root_hub(dev_info_t *dip);
 300 void usba_rem_root_hub(dev_info_t *dip);
 301 
 302 /*
 303  * retrieve string descriptors for manufacturer, vendor and serial
 304  * number
 305  */
 306 void usba_get_dev_string_descrs(dev_info_t *, usba_device_t *);
 307 
 308 /*
 309  * Check if we are not in interrupt context and have
 310  * USB_FLAGS_SLEEP flags set.
 311  */
 312 #define USBA_CHECK_CONTEXT()    ASSERT(!(servicing_interrupt()))
 313 
 314 /*
 315  * USBA module Masks
 316  */
 317 #define DPRINT_MASK_USBA                0x00000001
 318 #define DPRINT_MASK_USBAI               0x00000002
 319 #define DPRINT_MASK_HUBDI               0x00000004
 320 #define DPRINT_MASK_HCDI                0x00000008
 321 #define DPRINT_MASK_HCDI_DUMPING        0x00000010
 322 #define DPRINT_MASK_HUBDI_DUMPING       0x00000020
 323 #define DPRINT_MASK_REGISTER            0x00000040
 324 #define DPRINT_MASK_DEVDB               0x00000080
 325 #define DPRINT_MASK_WHCDI               0x00000100
 326 #define DPRINT_MASK_ALL                 0xFFFFFFFF
 327 
 328 typedef struct usba_log_handle_impl {
 329         dev_info_t      *lh_dip;
 330         char            *lh_name;
 331         uint_t          *lh_errlevel;
 332         uint_t          *lh_mask;
 333         uint_t          *lh_instance_filter;
 334         uint_t          lh_flags;
 335 } usba_log_handle_impl_t;
 336 
 337 _NOTE(SCHEME_PROTECTS_DATA("USBA managed data", usba_log_handle_impl))
 338 
 339 /*
 340  * Miscellaneous definitions.
 341  */
 342 
 343 /* possible strlen of a USB driver's name */
 344 #define USBA_DRVNAME_LEN        40
 345 
 346 /* strings passed to usb_dprintfN() are this long */
 347 #define USBA_PRINT_BUF_LEN      256
 348 
 349 /*
 350  * usba_set_node_name() sets a device info node name
 351  * according to class, subclass, and protocol.
 352  * a subclass == -1 or protocol == -1 is considered a "don't care".
 353  */
 354 #define DONTCARE                ((int16_t)-1)
 355 #define FLAG_INTERFACE_NODE     0
 356 #define FLAG_DEVICE_NODE        1
 357 #define FLAG_COMBINED_NODE      2
 358 #define FLAG_INTERFACE_ASSOCIATION_NODE         3
 359 
 360 typedef struct node_name_entry {
 361         int16_t class;
 362         int16_t subclass;
 363         int16_t protocol;
 364         char    *name;
 365 } node_name_entry_t;
 366 
 367 
 368 /*
 369  * USB enumeration statistics support
 370  */
 371 
 372 /* Flags telling which stats usba_update_hotplug_stats should update */
 373 #define USBA_TOTAL_HOTPLUG_SUCCESS      0x01
 374 #define USBA_HOTPLUG_SUCCESS            0x02
 375 #define USBA_TOTAL_HOTPLUG_FAILURE      0x04
 376 #define USBA_HOTPLUG_FAILURE            0x08
 377 
 378 /*
 379  * Increment enumeration stats indicated by the flags
 380  */
 381 void    usba_update_hotplug_stats(dev_info_t *, usb_flags_t);
 382 
 383 /* Retrieve the current enumeration hotplug statistics */
 384 void    usba_get_hotplug_stats(dev_info_t *,
 385                 ulong_t *, ulong_t *, ulong_t *,
 386                 ulong_t *, uchar_t *);
 387 
 388 /* Reset the resetable hotplug stats */
 389 void    usba_reset_hotplug_stats(dev_info_t *);
 390 
 391 
 392 extern usb_log_handle_t usbai_log_handle;
 393 extern  kmutex_t usbai_mutex;
 394 
 395 void    usba_req_normal_cb(usba_req_wrapper_t *);
 396 void    usba_req_exc_cb(usba_req_wrapper_t *, usb_cr_t, usb_cb_flags_t);
 397 void    usba_do_req_exc_cb(usba_req_wrapper_t *, usb_cr_t,
 398                                                 usb_cb_flags_t);
 399 void    usba_req_set_cb_flags(usba_req_wrapper_t *, usb_cb_flags_t);
 400 
 401 /*
 402  * Creating/Destroying children (root hub, and hub children)
 403  */
 404 int     usba_create_child_devi(dev_info_t *, char *, usba_hcdi_ops_t *,
 405                 dev_info_t *, usb_port_status_t,
 406                 usba_device_t *, dev_info_t **);
 407 
 408 int     usba_destroy_child_devi(dev_info_t *, uint_t);
 409 
 410 /* utility function to map rval to a meaningful cr */
 411 usb_cr_t usba_rval2cr(int);
 412 
 413 /* various conversion functions */
 414 usb_pipe_handle_t       usba_get_dflt_pipe_handle(dev_info_t *);
 415 dev_info_t              *usba_get_dip(usb_pipe_handle_t);
 416 usb_pipe_handle_t       usba_usbdev_to_dflt_pipe_handle(usba_device_t *);
 417 usb_pipe_handle_t       usba_get_pipe_handle(usba_pipe_handle_data_t *);
 418 usba_pipe_handle_data_t *usba_get_ph_data(usb_pipe_handle_t);
 419 usb_pipe_state_t        usba_get_ph_state(usba_pipe_handle_data_t *);
 420 int                     usba_get_ph_ref_count(usba_pipe_handle_data_t *);
 421 
 422 /* increment and decrement ref_count */
 423 usba_pipe_handle_data_t *usba_hold_ph_data(usb_pipe_handle_t);
 424 void                    usba_release_ph_data(usba_ph_impl_t *);
 425 
 426 /* close all pipe and mark them persistent */
 427 void                    usba_persistent_pipe_close(usba_device_t *);
 428 
 429 /* reopen pipes that are marked persistent */
 430 int                     usba_persistent_pipe_open(usba_device_t *);
 431 
 432 /* check for leaks in hubd and usb_mid */
 433 void    usba_check_for_leaks(usba_device_t *);
 434 
 435 /* free request wrappers */
 436 void    usba_req_wrapper_free(usba_req_wrapper_t *);
 437 
 438 /* usb device capture for the specific client driver */
 439 typedef struct usb_dev_cap {
 440         dev_info_t                      *dip;
 441         usb_dev_driver_callback_t       usba_dev_driver_cb;
 442 } usb_dev_cap_t;
 443 
 444 usb_dev_cap_t usb_cap;
 445 _NOTE(SCHEME_PROTECTS_DATA("unique device capture data", usb_cap))
 446 
 447 #ifdef __cplusplus
 448 }
 449 #endif
 450 
 451 #endif /* _SYS_USB_USBA_USBA_IMPL_H */