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 #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 /* 239 * usba_get_mfg_prod_sn_str: 240 * Return a string containing mfg, product, serial number strings. 241 * Remove duplicates if some strings are the same. 242 */ 243 char *usba_get_mfg_prod_sn_str(dev_info_t *, char *, int); 244 245 /* return value when user doesn't specify configuration index */ 246 #define USBA_DEV_CONFIG_INDEX_UNDEFINED -1 247 248 /* 249 * prototypes 250 */ 251 void usba_usba_initialization(); 252 void usba_usba_destroy(); 253 254 void usba_usbai_register_initialization(); 255 void usba_usbai_register_destroy(); 256 257 void usba_usbai_initialization(); 258 void usba_usbai_destroy(); 259 260 void usba_hubdi_initialization(); 261 void usba_hubdi_destroy(); 262 263 void usba_devdb_initialization(); 264 void usba_devdb_destroy(); 265 266 int usba_is_root_hub(dev_info_t *dip); 267 268 usba_device_t *usba_alloc_usba_device(dev_info_t *); 269 void usba_free_usba_device(usba_device_t *usba_device_t); 270 void usba_clear_data_toggle(usba_device_t *usba_device); 271 272 void usba_start_next_req(usba_pipe_handle_data_t *ph); 273 274 int usba_pipe_check_handle(usba_pipe_handle_data_t *); 275 int usba_drain_cbs(usba_pipe_handle_data_t *, usb_cb_flags_t, 276 usb_cr_t); 277 int usba_pipe_setup_func_call(dev_info_t *, 278 int (*sync_func)(dev_info_t *, 279 usba_ph_impl_t *, usba_pipe_async_req_t *, 280 usb_flags_t), 281 usba_ph_impl_t *, 282 usb_opaque_t, 283 usb_flags_t, 284 void (*cb)(usb_pipe_handle_t, usb_opaque_t, 285 int, usb_cb_flags_t), 286 usb_opaque_t); 287 288 289 void usba_pipe_new_state(usba_pipe_handle_data_t *, usb_pipe_state_t); 290 291 292 /* 293 * retrieve string descriptors for manufacturer, vendor and serial 294 * number 295 */ 296 void usba_get_dev_string_descrs(dev_info_t *, usba_device_t *); 297 298 /* 299 * Check if we are not in interrupt context and have 300 * USB_FLAGS_SLEEP flags set. 301 */ 302 #define USBA_CHECK_CONTEXT() ASSERT(!(servicing_interrupt())) 303 304 /* 305 * USBA module Masks 306 */ 307 #define DPRINT_MASK_USBA 0x00000001 308 #define DPRINT_MASK_USBAI 0x00000002 309 #define DPRINT_MASK_HUBDI 0x00000004 310 #define DPRINT_MASK_HCDI 0x00000008 311 #define DPRINT_MASK_HCDI_DUMPING 0x00000010 312 #define DPRINT_MASK_HUBDI_DUMPING 0x00000020 313 #define DPRINT_MASK_REGISTER 0x00000040 314 #define DPRINT_MASK_DEVDB 0x00000080 315 #define DPRINT_MASK_ALL 0xFFFFFFFF 316 317 typedef struct usba_log_handle_impl { 318 dev_info_t *lh_dip; 319 char *lh_name; 320 uint_t *lh_errlevel; 321 uint_t *lh_mask; 322 uint_t *lh_instance_filter; 323 uint_t lh_flags; 324 } usba_log_handle_impl_t; 325 326 _NOTE(SCHEME_PROTECTS_DATA("USBA managed data", usba_log_handle_impl)) 327 328 /* 329 * Miscellaneous definitions. 330 */ 331 332 /* possible strlen of a USB driver's name */ 333 #define USBA_DRVNAME_LEN 40 334 335 /* strings passed to usb_dprintfN() are this long */ 336 #define USBA_PRINT_BUF_LEN 256 337 338 /* 339 * usba_set_node_name() sets a device info node name 340 * according to class, subclass, and protocol. 341 * a subclass == -1 or protocol == -1 is considered a "don't care". 342 */ 343 #define DONTCARE ((int16_t)-1) 344 #define FLAG_INTERFACE_NODE 0 345 #define FLAG_DEVICE_NODE 1 346 #define FLAG_COMBINED_NODE 2 347 #define FLAG_INTERFACE_ASSOCIATION_NODE 3 348 349 typedef struct node_name_entry { 350 int16_t class; 351 int16_t subclass; 352 int16_t protocol; 353 char *name; 354 } node_name_entry_t; 355 356 357 /* 358 * USB enumeration statistics support 359 */ 360 361 /* Flags telling which stats usba_update_hotplug_stats should update */ 362 #define USBA_TOTAL_HOTPLUG_SUCCESS 0x01 363 #define USBA_HOTPLUG_SUCCESS 0x02 364 #define USBA_TOTAL_HOTPLUG_FAILURE 0x04 365 #define USBA_HOTPLUG_FAILURE 0x08 366 367 /* 368 * Increment enumeration stats indicated by the flags 369 */ 370 void usba_update_hotplug_stats(dev_info_t *, usb_flags_t); 371 372 /* Retrieve the current enumeration hotplug statistics */ 373 void usba_get_hotplug_stats(dev_info_t *, 374 ulong_t *, ulong_t *, ulong_t *, 375 ulong_t *, uchar_t *); 376 377 /* Reset the resetable hotplug stats */ 378 void usba_reset_hotplug_stats(dev_info_t *); 379 380 381 extern usb_log_handle_t usbai_log_handle; 382 extern kmutex_t usbai_mutex; 383 384 void usba_req_normal_cb(usba_req_wrapper_t *); 385 void usba_req_exc_cb(usba_req_wrapper_t *, usb_cr_t, usb_cb_flags_t); 386 void usba_do_req_exc_cb(usba_req_wrapper_t *, usb_cr_t, 387 usb_cb_flags_t); 388 void usba_req_set_cb_flags(usba_req_wrapper_t *, usb_cb_flags_t); 389 390 /* 391 * Creating/Destroying children (root hub, and hub children) 392 */ 393 int usba_create_child_devi(dev_info_t *, char *, usba_hcdi_ops_t *, 394 dev_info_t *, usb_port_status_t, 395 usba_device_t *, dev_info_t **); 396 397 int usba_destroy_child_devi(dev_info_t *, uint_t); 398 399 /* utility function to map rval to a meaningful cr */ 400 usb_cr_t usba_rval2cr(int); 401 402 /* various conversion functions */ 403 usb_pipe_handle_t usba_get_dflt_pipe_handle(dev_info_t *); 404 dev_info_t *usba_get_dip(usb_pipe_handle_t); 405 usb_pipe_handle_t usba_usbdev_to_dflt_pipe_handle(usba_device_t *); 406 usb_pipe_handle_t usba_get_pipe_handle(usba_pipe_handle_data_t *); 407 usba_pipe_handle_data_t *usba_get_ph_data(usb_pipe_handle_t); 408 usb_pipe_state_t usba_get_ph_state(usba_pipe_handle_data_t *); 409 int usba_get_ph_ref_count(usba_pipe_handle_data_t *); 410 411 /* increment and decrement ref_count */ 412 usba_pipe_handle_data_t *usba_hold_ph_data(usb_pipe_handle_t); 413 void usba_release_ph_data(usba_ph_impl_t *); 414 415 /* close all pipe and mark them persistent */ 416 void usba_persistent_pipe_close(usba_device_t *); 417 418 /* reopen pipes that are marked persistent */ 419 int usba_persistent_pipe_open(usba_device_t *); 420 421 /* check for leaks in hubd and usb_mid */ 422 void usba_check_for_leaks(usba_device_t *); 423 424 /* free request wrappers */ 425 void usba_req_wrapper_free(usba_req_wrapper_t *); 426 427 #ifdef __cplusplus 428 } 429 #endif 430 431 #endif /* _SYS_USB_USBA_USBA_IMPL_H */ 432