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