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