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_HUBDVAR_H 27#define _SYS_USB_HUBDVAR_H 28 29 30#ifdef __cplusplus 31extern "C" { 32#endif 33 34#include <sys/sunndi.h> 35#include <sys/ndi_impldefs.h> 36#include <sys/usb/usba/usba_types.h> 37#include <sys/callb.h> 38 39/* 40 * HUB USB device state management : 41 * 42 * CHILD PWRLVL---1>--------+ 43 * ^ | 44 * 8 | 45 * | | 46 * 9 | 47 * v | 48 * PWRED_DWN---<3----4>--ONLINE---<2-----1>-DISCONNECTED 49 * | | ^ | | 50 * | | 10 | | 51 * | | | | | 52 * | | RECOVER-<2-------+ | 53 * | | ^ | 54 * | 5 6 | 55 * | | | | 56 * | v | | 57 * +----5>----------SUSPENDED----<5----7>----+ 58 * 59 * 1 = Device Unplug 60 * 2 = Original Device reconnected and after hub driver restores its own 61 * device state. 62 * 3 = Device idles for time T & transitions to low power state 63 * 4 = Remote wakeup by device OR Application kicking off IO to device 64 * 5 = Notification to save state prior to DDI_SUSPEND 65 * 6 = Notification to restore state after DDI_RESUME with correct device 66 * and after hub driver restores its own device state. 67 * 7 = Notification to restore state after DDI_RESUME with device 68 * disconnected or a wrong device 69 * 8 = Hub detect child doing remote wakeup and request the PM 70 * framework to bring it to full power 71 * 9 = PM framework has compeleted call power entry point of the child 72 * and bus ctls of hub 73 * 10 = Restoring states of its children i.e. set addrs & config. 74 * 75 */ 76 77#define HUBD_INITIAL_SOFT_SPACE 4 78 79typedef struct hub_power_struct { 80 void *hubp_hubd; /* points back to hubd_t */ 81 82 uint8_t hubp_wakeup_enabled; /* remote wakeup enabled? */ 83 84 /* this is the bit mask of the power states that device has */ 85 uint8_t hubp_pwr_states; 86 87 int hubp_busy_pm; /* device busy accounting */ 88 89 /* wakeup and power transition capabilities of an interface */ 90 uint8_t hubp_pm_capabilities; 91 92 uint8_t hubp_current_power; /* current power level */ 93 94 time_t hubp_time_at_full_power; /* timestamp 0->3 */ 95 96 uint8_t hubp_min_pm_threshold; /* in seconds */ 97 98 /* power state of all children are tracked here */ 99 uint8_t *hubp_child_pwrstate; 100 101 /* pm-components properties are stored here */ 102 char *hubp_pmcomp[5]; 103 104 usba_cfg_pwr_descr_t hubp_confpwr_descr; /* config pwr descr */ 105} hub_power_t; 106 107/* warlock directives, stable data */ 108_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_hubd)) 109_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_wakeup_enabled)) 110_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_pwr_states)) 111_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_time_at_full_power)) 112_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_min_pm_threshold)) 113_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_pm_capabilities)) 114_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_pmcomp)) 115_NOTE(DATA_READABLE_WITHOUT_LOCK(hub_power_t::hubp_confpwr_descr)) 116 117 118#define HUBD_APID_NAMELEN 32 /* max len in cfgadm display */ 119 120/* 121 * hubd cpr data structure used for callback before kernel threads are 122 * suspended 123 */ 124typedef struct hubd_cpr { 125 callb_cpr_t cpr; /* for cpr related info */ 126 struct hubd *statep; /* ohci soft state struct */ 127 kmutex_t lockp; 128} hubd_cpr_t; 129 130_NOTE(DATA_READABLE_WITHOUT_LOCK(hubd_cpr_t::cpr)) 131_NOTE(DATA_READABLE_WITHOUT_LOCK(hubd_cpr_t::statep)) 132 133 134/* 135 * soft state information for this hubd 136 */ 137typedef struct hubd { 138 int h_instance; 139 uint_t h_init_state; 140 uint_t h_dev_state; 141 int8_t h_bus_ctls; 142 int8_t h_bus_pwr; 143 hub_power_t *h_hubpm; /* pointer to power struct */ 144 dev_info_t *h_dip; 145 146 /* 147 * mutex to protect softstate and hw regs 148 */ 149 kmutex_t h_mutex; 150 151 /* 152 * save the usba_device pointer 153 */ 154 usba_device_t *h_usba_device; 155 156 int h_softstate; 157 158 /* 159 * default pipe handle 160 */ 161 usb_pipe_handle_t h_default_pipe; 162 163 /* 164 * pipe handle for ep1 165 */ 166 usb_pipe_handle_t h_ep1_ph; 167 usb_ep_descr_t h_ep1_descr; 168 usb_pipe_policy_t h_pipe_policy; 169 uint_t h_intr_pipe_state; 170 171 /* 172 * root hub descriptor 173 */ 174 struct usb_hub_descr h_hub_descr; 175 176 /* 177 * hotplug handling 178 */ 179 uint_t h_hotplug_thread; 180 181 /* 182 * h_children_dips is a array for holding 183 * each child dip indexed by port 184 * h_usba_devices is the corresponding usba_device 185 */ 186 dev_info_t **h_children_dips; 187 size_t h_cd_list_length; 188 usba_device_t **h_usba_devices; 189 190 /* change reported by hub, limited to 31 ports */ 191 usb_port_mask_t h_port_change; 192 193 /* waiting for reset completion callback */ 194 usb_port_mask_t h_port_reset_wait; 195 196 /* track transitions of child on each port */ 197 uint16_t h_port_state[MAX_PORTS + 1]; 198 199 /* track reset state of each port */ 200 boolean_t h_reset_port[MAX_PORTS + 1]; 201 202 /* track event registration of children */ 203 uint8_t h_child_events[MAX_PORTS + 1]; 204 205 kcondvar_t h_cv_reset_port; 206 kcondvar_t h_cv_hotplug_dev; 207 uint_t h_intr_completion_reason; 208 usb_log_handle_t h_log_handle; /* for logging msgs */ 209 210 ndi_event_hdl_t h_ndi_event_hdl; 211 hubd_cpr_t *h_cpr_cb; 212 213 /* 214 * Hotplug event statistics since hub was attached 215 */ 216 ulong_t h_total_hotplug_success; 217 ulong_t h_total_hotplug_failure; 218 219 /* for minor node */ 220 char *h_ancestry_str; 221 222 /* registration data */ 223 usb_client_dev_data_t *h_dev_data; 224 225 /* for deathrow implementation */ 226 boolean_t h_cleanup_enabled; 227 boolean_t h_cleanup_needed; 228 boolean_t h_cleanup_active; 229 230 /* 231 * for power budget support 232 * h_pwr_limit and h_pwr_left are expressed 233 * in 2mA units 234 */ 235 boolean_t h_local_pwr_capable; 236 boolean_t h_local_pwr_on; 237 uint16_t h_pwr_limit; /* per port pwr limit */ 238 int16_t h_pwr_left; /* limit on the whole hub */ 239 240 /* 241 * conf file override to power budget property 242 * if 1, power budget is disabled 243 */ 244 boolean_t h_ignore_pwr_budget; 245 246 /* for HWA to cleanup child, NULL for normal hubs */ 247 int (*h_cleanup_child)(dev_info_t *); 248} hubd_t; 249 250_NOTE(MUTEX_PROTECTS_DATA(hubd::h_mutex, hubd)) 251_NOTE(MUTEX_PROTECTS_DATA(hubd::h_mutex, hub_power_t)) 252_NOTE(DATA_READABLE_WITHOUT_LOCK(hubd::h_default_pipe 253 hubd::h_usba_device 254 hubd::h_dev_data 255 hubd::h_ndi_event_hdl 256 hubd::h_cpr_cb 257 hubd::h_log_handle 258 hubd::h_ep1_ph 259 hubd::h_instance 260 hubd::h_hubpm 261 hubd::h_dip 262 hubd::h_ignore_pwr_budget 263 hubd::h_hub_descr 264 hubd::h_cleanup_child 265)) 266 267_NOTE(SCHEME_PROTECTS_DATA("stable data", usb_ep_descr)) 268 269/* 270 * hubd hotplug thread argument data structure 271 */ 272typedef struct hubd_hotplug_arg { 273 hubd_t *hubd; 274 275 /* 276 * flag to indicate if a hotplug thread is started 277 * during hubd attach time, if true, it means the 278 * connected devices need to be enumerated regardless 279 * of the connect status change bit 280 */ 281 boolean_t hotplug_during_attach; 282} hubd_hotplug_arg_t; 283 284/* 285 * hubd reset thread argument data structure 286 */ 287typedef struct hubd_reset_arg { 288 hubd_t *hubd; 289 /* The port needs to be reset */ 290 uint16_t reset_port; 291} hubd_reset_arg_t; 292 293_NOTE(SCHEME_PROTECTS_DATA("unshared", hubd_hotplug_arg)) 294_NOTE(SCHEME_PROTECTS_DATA("unshared", hubd_reset_arg)) 295 296#define HUBD_UNIT(dev) (getminor((dev))) 297#define HUBD_MUTEX(hubd) (&((hubd)->h_mutex)) 298#define HUBD_SS_ISOPEN 0x0001 299#define HUBD_ACK_ALL_CHANGES PORT_CHANGE_MASK 300 301/* init state */ 302#define HUBD_LOCKS_DONE 0x0001 303#define HUBD_HUBDI_REGISTERED 0x0002 304#define HUBD_MINOR_NODE_CREATED 0x0004 305#define HUBD_CHILDREN_CREATED 0x0008 306#define HUBD_EVENTS_REGISTERED 0x0020 307 308/* 309 * port flags : These are essentially extensions of Port Status Field Bits 310 * as in USB 2.0 spec Table 11-21 and #defined in hubd.h file. We make use 311 * of the unused bits (5-7,13-15) here to track states of the hub's child. 312 */ 313#define HUBD_CHILD_ATTACHING 0x0020 314#define HUBD_CHILD_DETACHING 0x0040 315#define HUBD_CHILD_PWRLVL_CHNG 0x0080 316#define HUBD_CHILD_RAISE_POWER 0x2000 317#define HUBD_CHILD_ZAP 0x4000 318 319/* Tracking events registered by children */ 320#define HUBD_CHILD_EVENT_DISCONNECT 0x01 321#define HUBD_CHILD_EVENT_PRESUSPEND 0x02 322 323/* This dev state is used exclusively by hub to change port suspend/resume */ 324#define USB_DEV_HUB_CHILD_PWRLVL 0x80 325#define USB_DEV_HUB_STATE_RECOVER 0x81 326 327/* 328 * hubd interrupt pipe management : 329 * 330 * Following are the states of the interrupt pipe 331 * 332 * IDLE: 333 * initial state and after closing of the interrupt pipe 334 * 335 * OPENING: 336 * Set when the pipe is being opened 337 * 338 * ACTIVE: 339 * Set when the pipe has been opened in hubd_open_intr_pipe. This is 340 * typically after a hub has got enumerated and initialized. 341 * 342 * CLOSING : 343 * Set when the pipe is closed by calling hubd_close_intr_pipe(). This is 344 * typically called on hub disconnect via hubd_cleanup. 345 */ 346#define HUBD_INTR_PIPE_IDLE 0 347#define HUBD_INTR_PIPE_OPENING 1 348#define HUBD_INTR_PIPE_ACTIVE 2 349#define HUBD_INTR_PIPE_STOPPED 3 350#define HUBD_INTR_PIPE_CLOSING 4 351 352 353/* request structure for putting dips on deathrow list */ 354typedef struct hubd_offline_req { 355 usba_list_entry_t or_queue; /* DO NOT MOVE! */ 356 hubd_t *or_hubd; 357 usb_port_t or_port; 358 dev_info_t *or_dip; 359 uint_t or_flag; 360} hubd_offline_req_t; 361 362_NOTE(SCHEME_PROTECTS_DATA("unshared", hubd_offline_req)) 363 364 365/* 366 * cfgadm state values 367 */ 368#define HUBD_CFGADM_NORMAL 0 /* normal state */ 369#define HUBD_CFGADM_DISCONNECTED 1 /* logically disconnected */ 370#define HUBD_CFGADM_UNCONFIGURED 2 /* port is unconfigured */ 371#define HUBD_CFGADM_EMPTY 3 /* port is empty */ 372#define HUBD_CFGADM_STILL_REFERENCED 4 /* ndi_devi_offline failed */ 373#define HUBD_CFGADM_CONFIGURED 5 /* port is configured */ 374 375/* 376 * Debug printing 377 * Masks 378 */ 379#define DPRINT_MASK_ATTA 0x00000001 380#define DPRINT_MASK_CBOPS 0x00000002 381#define DPRINT_MASK_CALLBACK 0x00000004 382#define DPRINT_MASK_PORT 0x00000008 383#define DPRINT_MASK_HUB 0x00000010 384#define DPRINT_MASK_HOTPLUG 0x00000020 385#define DPRINT_MASK_EVENTS 0x00000040 386#define DPRINT_MASK_PM 0x00000080 387#define DPRINT_MASK_ALL 0xFFFFFFFF 388 389 390/* status length used in getting hub status */ 391#define GET_STATUS_LENGTH 0x04 /* length of get status req */ 392 393/* flag for hubd_start_polling */ 394#define HUBD_ALWAYS_START_POLLING 1 395 396/* enumeration timeout */ 397#define HUBDI_ENUM_TIMEOUT 1 /* 1 second */ 398 399/* power budget unit in mA */ 400#define USB_PWR_UNIT_LOAD 100 401 402/* power values in 100mA units */ 403#define USB_HIGH_PWR_VALUE 5 404#define USB_LOW_PWR_VALUE 1 405 406/* 407 * According to section 9.6.3 of USB 2.0 spec, 408 * bMaxPower in the device configuration descriptor 409 * is expressed in 2mA units 410 */ 411#define USB_CFG_DESCR_PWR_UNIT 2 412 413/* variables shared with wire adapter class drivers */ 414extern uint_t hubd_errlevel; 415extern uint_t hubd_errmask; 416extern uint_t hubd_instance_debug; 417 418/* common interfaces for hub and wire adapter class devices */ 419hubd_t *hubd_get_soft_state(dev_info_t *); 420void hubd_get_ancestry_str(hubd_t *); 421int hubd_get_all_device_config_cloud(hubd_t *, dev_info_t *, 422 usba_device_t *); 423int hubd_select_device_configuration(hubd_t *, usb_port_t, 424 dev_info_t *, usba_device_t *); 425dev_info_t *hubd_ready_device(hubd_t *, dev_info_t *, usba_device_t *, 426 uint_t); 427void hubd_schedule_cleanup(dev_info_t *); 428 429#ifdef __cplusplus 430} 431#endif 432 433#endif /* _SYS_USB_HUBDVAR_H */ 434