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