usbai_util.c (35f36846) usbai_util.c (d73ae94e)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
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.
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance 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/*
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/*
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident "%Z%%M% %I% %E% SMI"
28
29/*
30 * USBA: Solaris USB Architecture support
31 *
32 * Utility functions
33 */
34#define USBA_FRAMEWORK
35#include <sys/usb/usba/usba_impl.h>
36#include <sys/usb/usba/hcdi_impl.h>
37
23 * Use is subject to license terms.
24 */
25
26#pragma ident "%Z%%M% %I% %E% SMI"
27
28/*
29 * USBA: Solaris USB Architecture support
30 *
31 * Utility functions
32 */
33#define USBA_FRAMEWORK
34#include <sys/usb/usba/usba_impl.h>
35#include <sys/usb/usba/hcdi_impl.h>
36
37extern void usba_free_evdata(usba_evdata_t *);
38
38static mblk_t *usba_get_cfg_cloud(dev_info_t *, usb_pipe_handle_t, int);
39
40/* local functions */
41static int usba_sync_set_cfg(dev_info_t *, usba_ph_impl_t *,
42 usba_pipe_async_req_t *, usb_flags_t);
43static int usba_sync_set_alt_if(dev_info_t *, usba_ph_impl_t *,
44 usba_pipe_async_req_t *, usb_flags_t);
45static int usba_sync_clear_feature(dev_info_t *, usba_ph_impl_t *,

--- 764 unchanged lines hidden (view full) ---

810usb_owns_device(dev_info_t *dip)
811{
812 int interface_num = usb_get_if_number(dip);
813
814 return (interface_num < 0 ? B_TRUE : B_FALSE);
815}
816
817
39static mblk_t *usba_get_cfg_cloud(dev_info_t *, usb_pipe_handle_t, int);
40
41/* local functions */
42static int usba_sync_set_cfg(dev_info_t *, usba_ph_impl_t *,
43 usba_pipe_async_req_t *, usb_flags_t);
44static int usba_sync_set_alt_if(dev_info_t *, usba_ph_impl_t *,
45 usba_pipe_async_req_t *, usb_flags_t);
46static int usba_sync_clear_feature(dev_info_t *, usba_ph_impl_t *,

--- 764 unchanged lines hidden (view full) ---

811usb_owns_device(dev_info_t *dip)
812{
813 int interface_num = usb_get_if_number(dip);
814
815 return (interface_num < 0 ? B_TRUE : B_FALSE);
816}
817
818
819/* check whether the interface is in this interface association */
820boolean_t
821usba_check_if_in_ia(dev_info_t *dip, int n_if)
822{
823 int first_if, if_count;
824
825 first_if = usb_get_if_number(dip);
826 if_count = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
827 DDI_PROP_DONTPASS, "interface-count", -1);
828 if_count += first_if;
829
830 return ((n_if >= first_if && n_if < if_count) ? B_TRUE : B_FALSE);
831}
832
833
818uint8_t
819usba_get_ifno(dev_info_t *dip)
820{
821 int interface_num = usb_get_if_number(dip);
822
823 return (interface_num < 0 ? 0 : interface_num);
824}
825

--- 86 unchanged lines hidden (view full) ---

912 usba_pipe_handle_data_t *ph_data = usba_get_ph_data(
913 (usb_pipe_handle_t)ph_impl);
914
915 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle,
916 "usb_set_alt_if: %s, interface#=0x%x, alt#=0x%x, "
917 "uf=0x%x", ddi_node_name(dip), interface,
918 alt_number, flags);
919
834uint8_t
835usba_get_ifno(dev_info_t *dip)
836{
837 int interface_num = usb_get_if_number(dip);
838
839 return (interface_num < 0 ? 0 : interface_num);
840}
841

--- 86 unchanged lines hidden (view full) ---

928 usba_pipe_handle_data_t *ph_data = usba_get_ph_data(
929 (usb_pipe_handle_t)ph_impl);
930
931 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle,
932 "usb_set_alt_if: %s, interface#=0x%x, alt#=0x%x, "
933 "uf=0x%x", ddi_node_name(dip), interface,
934 alt_number, flags);
935
920 /* if we don't own the device, we must own the interface */
921 if (!usb_owns_device(dip) &&
936 /* if we don't own the device, we must own the interface or ia */
937 if (!usb_owns_device(dip) && !usba_check_if_in_ia(dip, interface) &&
922 (interface != usb_get_if_number(dip))) {
923 usba_release_ph_data(ph_data->p_ph_impl);
924
925 return (USB_INVALID_PERM);
926 }
927
928 /* set the alternate setting */
929 rval = usb_pipe_sync_ctrl_xfer(dip, usba_get_dflt_pipe_handle(dip),

--- 1242 unchanged lines hidden (view full) ---

2172
2173 return (NULL);
2174 } else {
2175
2176 return (allocb(size, pri));
2177 }
2178}
2179#endif
938 (interface != usb_get_if_number(dip))) {
939 usba_release_ph_data(ph_data->p_ph_impl);
940
941 return (USB_INVALID_PERM);
942 }
943
944 /* set the alternate setting */
945 rval = usb_pipe_sync_ctrl_xfer(dip, usba_get_dflt_pipe_handle(dip),

--- 1242 unchanged lines hidden (view full) ---

2188
2189 return (NULL);
2190 } else {
2191
2192 return (allocb(size, pri));
2193 }
2194}
2195#endif
2196
2197
2198/*
2199 * usb common power management for usb_mid, usb_ia and maybe other simple
2200 * drivers.
2201 */
2202
2203/*
2204 * functions to handle power transition for OS levels 0 -> 3
2205 */
2206static int
2207usb_common_pwrlvl0(dev_info_t *dip, usb_common_power_t *pm, int *dev_state)
2208{
2209 int rval;
2210
2211 switch (*dev_state) {
2212 case USB_DEV_ONLINE:
2213 /* Issue USB D3 command to the device here */
2214 rval = usb_set_device_pwrlvl3(dip);
2215 ASSERT(rval == USB_SUCCESS);
2216
2217 *dev_state = USB_DEV_PWRED_DOWN;
2218 pm->uc_current_power = USB_DEV_OS_PWR_OFF;
2219 /* FALLTHRU */
2220 case USB_DEV_DISCONNECTED:
2221 case USB_DEV_SUSPENDED:
2222 /* allow a disconnected/cpr'ed device to go to low pwr */
2223
2224 return (USB_SUCCESS);
2225 case USB_DEV_PWRED_DOWN:
2226 default:
2227 return (USB_FAILURE);
2228 }
2229}
2230
2231
2232/* ARGSUSED */
2233static int
2234usb_common_pwrlvl1(dev_info_t *dip, usb_common_power_t *pm, int *dev_state)
2235{
2236 int rval;
2237
2238 /* Issue USB D2 command to the device here */
2239 rval = usb_set_device_pwrlvl2(dip);
2240 ASSERT(rval == USB_SUCCESS);
2241
2242 return (USB_FAILURE);
2243}
2244
2245
2246/* ARGSUSED */
2247static int
2248usb_common_pwrlvl2(dev_info_t *dip, usb_common_power_t *pm, int *dev_state)
2249{
2250 int rval;
2251
2252 /* Issue USB D1 command to the device here */
2253 rval = usb_set_device_pwrlvl1(dip);
2254 ASSERT(rval == USB_SUCCESS);
2255
2256 return (USB_FAILURE);
2257}
2258
2259
2260static int
2261usb_common_pwrlvl3(dev_info_t *dip, usb_common_power_t *pm, int *dev_state)
2262{
2263 int rval;
2264
2265 switch (*dev_state) {
2266 case USB_DEV_PWRED_DOWN:
2267 /* Issue USB D0 command to the device here */
2268 rval = usb_set_device_pwrlvl0(dip);
2269 ASSERT(rval == USB_SUCCESS);
2270
2271 *dev_state = USB_DEV_ONLINE;
2272 pm->uc_current_power = USB_DEV_OS_FULL_PWR;
2273
2274 /* FALLTHRU */
2275 case USB_DEV_ONLINE:
2276 /* we are already in full power */
2277
2278 /* FALLTHRU */
2279 case USB_DEV_DISCONNECTED:
2280 case USB_DEV_SUSPENDED:
2281 /* allow a disconnected/cpr'ed device to go to low power */
2282
2283 return (USB_SUCCESS);
2284 default:
2285 USB_DPRINTF_L2(DPRINT_MASK_USBA, usbai_log_handle,
2286 "usb_common_pwrlvl3: Illegal state (%s)",
2287 usb_str_dev_state(*dev_state));
2288
2289 return (USB_FAILURE);
2290 }
2291}
2292
2293/* power management */
2294int
2295usba_common_power(dev_info_t *dip, usb_common_power_t *pm, int *dev_state,
2296 int level)
2297{
2298 int rval = DDI_FAILURE;
2299
2300 switch (level) {
2301 case USB_DEV_OS_PWR_OFF:
2302 rval = usb_common_pwrlvl0(dip, pm, dev_state);
2303 break;
2304 case USB_DEV_OS_PWR_1:
2305 rval = usb_common_pwrlvl1(dip, pm, dev_state);
2306 break;
2307 case USB_DEV_OS_PWR_2:
2308 rval = usb_common_pwrlvl2(dip, pm, dev_state);
2309 break;
2310 case USB_DEV_OS_FULL_PWR:
2311 rval = usb_common_pwrlvl3(dip, pm, dev_state);
2312 break;
2313 }
2314
2315 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
2316}
2317
2318/*
2319 * register and unregister for events from our parent for usb_mid and usb_ia
2320 * and maybe other nexus driver.
2321 *
2322 * Note: The cookie fields in usba_device structure is not used. They are
2323 * used/shared by children.
2324 */
2325void
2326usba_common_register_events(dev_info_t *dip, uint_t if_num,
2327 void (*event_cb)(dev_info_t *, ddi_eventcookie_t, void *, void *))
2328{
2329 int rval;
2330 usba_evdata_t *evdata;
2331 ddi_eventcookie_t cookie;
2332
2333 USB_DPRINTF_L4(DPRINT_MASK_USBA, usbai_log_handle,
2334 "usb_common_register_events:");
2335
2336 evdata = usba_get_evdata(dip);
2337
2338 /* get event cookie, discard level and icookie for now */
2339 rval = ddi_get_eventcookie(dip, DDI_DEVI_REMOVE_EVENT,
2340 &cookie);
2341
2342 if (rval == DDI_SUCCESS) {
2343 rval = ddi_add_event_handler(dip,
2344 cookie, event_cb, NULL, &evdata->ev_rm_cb_id);
2345
2346 if (rval != DDI_SUCCESS) {
2347
2348 goto fail;
2349 }
2350 }
2351 rval = ddi_get_eventcookie(dip, DDI_DEVI_INSERT_EVENT,
2352 &cookie);
2353 if (rval == DDI_SUCCESS) {
2354 rval = ddi_add_event_handler(dip, cookie, event_cb,
2355 NULL, &evdata->ev_ins_cb_id);
2356
2357 if (rval != DDI_SUCCESS) {
2358
2359 goto fail;
2360 }
2361 }
2362 rval = ddi_get_eventcookie(dip, USBA_PRE_SUSPEND_EVENT, &cookie);
2363 if (rval == DDI_SUCCESS) {
2364 rval = ddi_add_event_handler(dip,
2365 cookie, event_cb, NULL, &evdata->ev_suspend_cb_id);
2366
2367 if (rval != DDI_SUCCESS) {
2368
2369 goto fail;
2370 }
2371 }
2372 rval = ddi_get_eventcookie(dip, USBA_POST_RESUME_EVENT, &cookie);
2373 if (rval == DDI_SUCCESS) {
2374 rval = ddi_add_event_handler(dip, cookie, event_cb, NULL,
2375 &evdata->ev_resume_cb_id);
2376
2377 if (rval != DDI_SUCCESS) {
2378
2379 goto fail;
2380 }
2381 }
2382
2383 return;
2384
2385
2386fail:
2387 usba_common_unregister_events(dip, if_num);
2388
2389}
2390
2391void
2392usba_common_unregister_events(dev_info_t *dip, uint_t if_num)
2393{
2394 usba_evdata_t *evdata;
2395 usba_device_t *usba_device = usba_get_usba_device(dip);
2396 int i;
2397
2398 evdata = usba_get_evdata(dip);
2399
2400 if (evdata->ev_rm_cb_id != NULL) {
2401 (void) ddi_remove_event_handler(evdata->ev_rm_cb_id);
2402 evdata->ev_rm_cb_id = NULL;
2403 }
2404
2405 if (evdata->ev_ins_cb_id != NULL) {
2406 (void) ddi_remove_event_handler(evdata->ev_ins_cb_id);
2407 evdata->ev_ins_cb_id = NULL;
2408 }
2409
2410 if (evdata->ev_suspend_cb_id != NULL) {
2411 (void) ddi_remove_event_handler(evdata->ev_suspend_cb_id);
2412 evdata->ev_suspend_cb_id = NULL;
2413 }
2414
2415 if (evdata->ev_resume_cb_id != NULL) {
2416 (void) ddi_remove_event_handler(evdata->ev_resume_cb_id);
2417 evdata->ev_resume_cb_id = NULL;
2418 }
2419
2420 /* clear event data for children, required for cfgmadm unconfigure */
2421 if (usb_owns_device(dip)) {
2422 usba_free_evdata(usba_device->usb_evdata);
2423 usba_device->usb_evdata = NULL;
2424 usba_device->rm_cookie = NULL;
2425 usba_device->ins_cookie = NULL;
2426 usba_device->suspend_cookie = NULL;
2427 usba_device->resume_cookie = NULL;
2428 } else {
2429 for (i = 0; i < if_num; i++) {
2430 usba_device->usb_client_flags[usba_get_ifno(dip) + i]
2431 &= ~USBA_CLIENT_FLAG_EV_CBS;
2432 }
2433 }
2434}