19430SRaymond.Chen@Sun.COM /*
29430SRaymond.Chen@Sun.COM * CDDL HEADER START
39430SRaymond.Chen@Sun.COM *
49430SRaymond.Chen@Sun.COM * The contents of this file are subject to the terms of the
59430SRaymond.Chen@Sun.COM * Common Development and Distribution License (the "License").
69430SRaymond.Chen@Sun.COM * You may not use this file except in compliance with the License.
79430SRaymond.Chen@Sun.COM *
89430SRaymond.Chen@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99430SRaymond.Chen@Sun.COM * or http://www.opensolaris.org/os/licensing.
109430SRaymond.Chen@Sun.COM * See the License for the specific language governing permissions
119430SRaymond.Chen@Sun.COM * and limitations under the License.
129430SRaymond.Chen@Sun.COM *
139430SRaymond.Chen@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
149430SRaymond.Chen@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159430SRaymond.Chen@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
169430SRaymond.Chen@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
179430SRaymond.Chen@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
189430SRaymond.Chen@Sun.COM *
199430SRaymond.Chen@Sun.COM * CDDL HEADER END
209430SRaymond.Chen@Sun.COM */
219430SRaymond.Chen@Sun.COM /*
229430SRaymond.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
239430SRaymond.Chen@Sun.COM * Use is subject to license terms.
249430SRaymond.Chen@Sun.COM */
259430SRaymond.Chen@Sun.COM
269430SRaymond.Chen@Sun.COM /*
279430SRaymond.Chen@Sun.COM * UWB radio controller driver interfaces
289430SRaymond.Chen@Sun.COM */
299430SRaymond.Chen@Sun.COM #include <sys/uwb/uwba/uwba.h>
309430SRaymond.Chen@Sun.COM #include <sys/sunndi.h>
319430SRaymond.Chen@Sun.COM #include <sys/ddi.h>
329430SRaymond.Chen@Sun.COM
339430SRaymond.Chen@Sun.COM
349430SRaymond.Chen@Sun.COM /*
359430SRaymond.Chen@Sun.COM * The following is a list of functions which handles the rccb command
369430SRaymond.Chen@Sun.COM * for uwb model, each rccb command has a related handler. Not all the
379430SRaymond.Chen@Sun.COM * rccb command is supportted, the below uwb_rccb_handler_tbl lists
389430SRaymond.Chen@Sun.COM * the supported handler
399430SRaymond.Chen@Sun.COM */
409430SRaymond.Chen@Sun.COM static int uwb_do_cmd_rccb(uwb_dev_handle_t, uwb_rccb_cmd_t *);
419430SRaymond.Chen@Sun.COM static int uwb_do_cmd_scan(uwb_dev_handle_t, uwb_rccb_cmd_t *);
429430SRaymond.Chen@Sun.COM static int uwb_do_cmd_start_beacon(uwb_dev_handle_t,
439430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t *);
449430SRaymond.Chen@Sun.COM static int uwb_do_cmd_dev_addr_mgmt(uwb_dev_handle_t, uwb_rccb_cmd_t *);
459430SRaymond.Chen@Sun.COM
469430SRaymond.Chen@Sun.COM
479430SRaymond.Chen@Sun.COM static int uwb_process_rccb_cmd_private(uwb_dev_handle_t,
489430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t *, uwb_cmd_result_t *);
499430SRaymond.Chen@Sun.COM
509430SRaymond.Chen@Sun.COM static int uwb_send_rccb_cmd(uwb_dev_handle_t, uwb_rccb_cmd_t *);
519430SRaymond.Chen@Sun.COM static int uwb_check_rccb_cmd(uwb_dev_handle_t, uwb_rccb_cmd_t *);
529430SRaymond.Chen@Sun.COM static int uwb_check_dev_state(uwba_dev_t *, uwb_rccb_cmd_t *);
539430SRaymond.Chen@Sun.COM static void uwb_set_dev_state(uwba_dev_t *, uwb_rccb_cmd_t *);
549430SRaymond.Chen@Sun.COM
559430SRaymond.Chen@Sun.COM static int uwb_wait_cmd_result(uwb_dev_handle_t);
569430SRaymond.Chen@Sun.COM static void uwb_free_cmd_result(uwb_dev_handle_t);
579430SRaymond.Chen@Sun.COM
589430SRaymond.Chen@Sun.COM static int uwb_rccb_cmd_enter(uwba_dev_t *);
599430SRaymond.Chen@Sun.COM static void uwb_rccb_cmd_leave(uwba_dev_t *);
609430SRaymond.Chen@Sun.COM
619430SRaymond.Chen@Sun.COM static int uwb_do_ioctl_rccb_cmd(uwb_dev_handle_t,
629430SRaymond.Chen@Sun.COM uint16_t, intptr_t, int);
639430SRaymond.Chen@Sun.COM
649430SRaymond.Chen@Sun.COM static uwb_notif_wrapper_t *uwb_get_notification(uwb_dev_handle_t,
659430SRaymond.Chen@Sun.COM intptr_t, int);
669430SRaymond.Chen@Sun.COM static void uwb_free_notification(uwb_notif_wrapper_t *);
679430SRaymond.Chen@Sun.COM /*
689430SRaymond.Chen@Sun.COM *
699430SRaymond.Chen@Sun.COM * This is all the rccb command handler supported and not supported in
709430SRaymond.Chen@Sun.COM * current version. rccb handler table map
719430SRaymond.Chen@Sun.COM */
729430SRaymond.Chen@Sun.COM static uwb_rccb_handler_t uwb_rccb_handler_tbl [] = {
739430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* CHANNEL_CHANGE */
749430SRaymond.Chen@Sun.COM uwb_do_cmd_dev_addr_mgmt, /* DEV_ADDR_MGMT */
759430SRaymond.Chen@Sun.COM uwb_do_cmd_rccb, /* GET_IE */
769430SRaymond.Chen@Sun.COM uwb_do_cmd_rccb, /* RESET */
779430SRaymond.Chen@Sun.COM uwb_do_cmd_scan, /* SCAN */
789430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* SET_BEACON_FILTER */
799430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* SET_DRP_IE */
809430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* SET_IE */
819430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* SET_NOTIFICATION_FILTER */
829430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* SET_TX_POWER */
839430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* SLEEP */
849430SRaymond.Chen@Sun.COM uwb_do_cmd_start_beacon, /* START_BEACON */
859430SRaymond.Chen@Sun.COM uwb_do_cmd_rccb, /* STOP_BEACON */
869430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER, /* BP_MERGE */
879430SRaymond.Chen@Sun.COM UWB_RCCB_NULL_HANDLER /* SEND_COMMAND_FRAME */
889430SRaymond.Chen@Sun.COM };
899430SRaymond.Chen@Sun.COM
909430SRaymond.Chen@Sun.COM /*
919430SRaymond.Chen@Sun.COM * This table recode different size of the rccb command data block
929430SRaymond.Chen@Sun.COM * For those rccb command not supported, it is zero
939430SRaymond.Chen@Sun.COM */
949430SRaymond.Chen@Sun.COM static uint8_t uwb_rccb_size_tbl [] = {
959430SRaymond.Chen@Sun.COM 0, /* CHANNEL_CHANGE */
969430SRaymond.Chen@Sun.COM sizeof (uwb_rccb_dev_addr_mgmt_t), /* DEV_ADDR_MGMT */
979430SRaymond.Chen@Sun.COM sizeof (uwb_rccb_cmd_t), /* GET_IE */
989430SRaymond.Chen@Sun.COM sizeof (uwb_rccb_cmd_t), /* RESET */
999430SRaymond.Chen@Sun.COM sizeof (uwb_rccb_scan_t), /* SCAN */
1009430SRaymond.Chen@Sun.COM 0, /* SET_BEACON_FILTER */
1019430SRaymond.Chen@Sun.COM 0, /* SET_DRP_IE */
1029430SRaymond.Chen@Sun.COM 0, /* SET_IE */
1039430SRaymond.Chen@Sun.COM 0, /* SET_NOTIFICATION_FILTER */
1049430SRaymond.Chen@Sun.COM 0, /* SET_TX_POWER */
1059430SRaymond.Chen@Sun.COM 0, /* SLEEP */
1069430SRaymond.Chen@Sun.COM sizeof (uwb_rccb_start_beacon_t), /* START_BEACON */
1079430SRaymond.Chen@Sun.COM sizeof (uwb_rccb_cmd_t), /* STOP_BEACON */
1089430SRaymond.Chen@Sun.COM 0, /* BP_MERGE */
1099430SRaymond.Chen@Sun.COM 0 /* SEND_COMMAND_FRAME */
1109430SRaymond.Chen@Sun.COM };
1119430SRaymond.Chen@Sun.COM _NOTE(SCHEME_PROTECTS_DATA("unique per call", uwba_dev::send_cmd))
1129430SRaymond.Chen@Sun.COM _NOTE(SCHEME_PROTECTS_DATA("unique per call", uwb_rceb_get_ie))
1139430SRaymond.Chen@Sun.COM _NOTE(SCHEME_PROTECTS_DATA("unique per call", uwb_rceb_result_code))
1149430SRaymond.Chen@Sun.COM
1159430SRaymond.Chen@Sun.COM /*
1169430SRaymond.Chen@Sun.COM * Called by radio controller driver's attach() to register the device to uwba.
1179430SRaymond.Chen@Sun.COM * Including alloc and init the uwb_dev_handle
1189430SRaymond.Chen@Sun.COM */
1199430SRaymond.Chen@Sun.COM void
uwb_dev_attach(dev_info_t * dip,uwb_dev_handle_t * uwb_dev_handle,uint_t rcd_intr_pri,int (* send_cmd)(uwb_dev_handle_t uwb_dev_hdl,mblk_t * data,uint16_t data_len))1209430SRaymond.Chen@Sun.COM uwb_dev_attach(dev_info_t *dip, uwb_dev_handle_t *uwb_dev_handle,
1219430SRaymond.Chen@Sun.COM uint_t rcd_intr_pri, int (*send_cmd)(uwb_dev_handle_t uwb_dev_hdl,
1229430SRaymond.Chen@Sun.COM mblk_t *data, uint16_t data_len))
1239430SRaymond.Chen@Sun.COM {
1249430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev;
1259430SRaymond.Chen@Sun.COM
1269430SRaymond.Chen@Sun.COM uwba_alloc_uwb_dev(dip, &uwba_dev, rcd_intr_pri);
1279430SRaymond.Chen@Sun.COM
1289430SRaymond.Chen@Sun.COM uwba_init_ctxt_id(uwba_dev);
1299430SRaymond.Chen@Sun.COM uwba_dev->send_cmd = send_cmd;
1309430SRaymond.Chen@Sun.COM
1319430SRaymond.Chen@Sun.COM uwba_dev_add_to_list(uwba_dev);
1329430SRaymond.Chen@Sun.COM
1339430SRaymond.Chen@Sun.COM *uwb_dev_handle = (uwb_dev_handle_t)uwba_dev;
1349430SRaymond.Chen@Sun.COM
1359430SRaymond.Chen@Sun.COM }
1369430SRaymond.Chen@Sun.COM
1379430SRaymond.Chen@Sun.COM /*
1389430SRaymond.Chen@Sun.COM * Called by radio controller driver's dettach() to unregister the device from
1399430SRaymond.Chen@Sun.COM * uwba. Including dealloc and fnit the uwb_dev_handle
1409430SRaymond.Chen@Sun.COM */
1419430SRaymond.Chen@Sun.COM void
uwb_dev_detach(uwb_dev_handle_t uwb_dev_hdl)1429430SRaymond.Chen@Sun.COM uwb_dev_detach(uwb_dev_handle_t uwb_dev_hdl)
1439430SRaymond.Chen@Sun.COM {
1449430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
1459430SRaymond.Chen@Sun.COM
1469430SRaymond.Chen@Sun.COM uwba_dev_rm_from_list(uwba_dev);
1479430SRaymond.Chen@Sun.COM uwba_fini_ctxt_id(uwba_dev);
1489430SRaymond.Chen@Sun.COM uwba_free_uwb_dev(uwba_dev);
1499430SRaymond.Chen@Sun.COM }
1509430SRaymond.Chen@Sun.COM
1519430SRaymond.Chen@Sun.COM /*
1529430SRaymond.Chen@Sun.COM * Called by the radio controler to the dip from a uwb_dev_handle
1539430SRaymond.Chen@Sun.COM */
1549430SRaymond.Chen@Sun.COM dev_info_t *
uwb_get_dip(uwb_dev_handle_t uwb_dev_hdl)1559430SRaymond.Chen@Sun.COM uwb_get_dip(uwb_dev_handle_t uwb_dev_hdl)
1569430SRaymond.Chen@Sun.COM {
1579430SRaymond.Chen@Sun.COM if (uwb_dev_hdl) {
1589430SRaymond.Chen@Sun.COM
1599430SRaymond.Chen@Sun.COM return (((uwba_dev_t *)uwb_dev_hdl)->dip);
1609430SRaymond.Chen@Sun.COM }
1619430SRaymond.Chen@Sun.COM
1629430SRaymond.Chen@Sun.COM return (NULL);
1639430SRaymond.Chen@Sun.COM }
1649430SRaymond.Chen@Sun.COM
1659430SRaymond.Chen@Sun.COM /*
1669430SRaymond.Chen@Sun.COM * Called by host controller or radio controller, this function set the
1679430SRaymond.Chen@Sun.COM * ddi_no_autodetach to for the hwarc dip. Radio controller interface
1689430SRaymond.Chen@Sun.COM * should alway be detached after the host controller detachment.
1699430SRaymond.Chen@Sun.COM * So it should be called while the hwahc is attaching
1709430SRaymond.Chen@Sun.COM * dip- a hwahc dip or a hwarc dip
1719430SRaymond.Chen@Sun.COM */
1729430SRaymond.Chen@Sun.COM int
uwb_dev_online(dev_info_t * dip)1739430SRaymond.Chen@Sun.COM uwb_dev_online(dev_info_t *dip)
1749430SRaymond.Chen@Sun.COM {
1759430SRaymond.Chen@Sun.COM dev_info_t *pdip, *child_dip;
1769430SRaymond.Chen@Sun.COM int rval = UWB_FAILURE;
1779430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = NULL;
1789430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
1799430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
1809430SRaymond.Chen@Sun.COM if (uwb_dev_hdl != NULL) {
1819430SRaymond.Chen@Sun.COM (void) ddi_prop_update_int(DDI_DEV_T_NONE, uwba_dev->dip,
1829430SRaymond.Chen@Sun.COM DDI_NO_AUTODETACH, 1);
1839430SRaymond.Chen@Sun.COM
1849430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
1859430SRaymond.Chen@Sun.COM }
1869430SRaymond.Chen@Sun.COM
1879430SRaymond.Chen@Sun.COM pdip = ddi_get_parent(dip);
1889430SRaymond.Chen@Sun.COM child_dip = ddi_get_child(pdip);
1899430SRaymond.Chen@Sun.COM while (child_dip != NULL) {
1909430SRaymond.Chen@Sun.COM if (child_dip != dip) {
1919430SRaymond.Chen@Sun.COM /* Force the dip online */
1929430SRaymond.Chen@Sun.COM if (ndi_devi_online(child_dip, NDI_ONLINE_ATTACH) !=
1939430SRaymond.Chen@Sun.COM NDI_SUCCESS) {
1949430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
1959430SRaymond.Chen@Sun.COM "fail to online dip = %p, node_name = %s",
1969430SRaymond.Chen@Sun.COM dip, ddi_node_name(child_dip));
1979430SRaymond.Chen@Sun.COM }
1989430SRaymond.Chen@Sun.COM
1999430SRaymond.Chen@Sun.COM /*
2009430SRaymond.Chen@Sun.COM * Update the dip properties if it is a radio
2019430SRaymond.Chen@Sun.COM * controller node
2029430SRaymond.Chen@Sun.COM */
2039430SRaymond.Chen@Sun.COM if (strcmp(ddi_node_name(child_dip), "hwa-radio") ==
2049430SRaymond.Chen@Sun.COM 0) {
2059430SRaymond.Chen@Sun.COM (void) ddi_prop_update_int(DDI_DEV_T_NONE,
2069430SRaymond.Chen@Sun.COM child_dip, DDI_NO_AUTODETACH, 1);
2079430SRaymond.Chen@Sun.COM rval = UWB_SUCCESS;
2089430SRaymond.Chen@Sun.COM break;
2099430SRaymond.Chen@Sun.COM }
2109430SRaymond.Chen@Sun.COM }
2119430SRaymond.Chen@Sun.COM
2129430SRaymond.Chen@Sun.COM child_dip = ddi_get_next_sibling(child_dip);
2139430SRaymond.Chen@Sun.COM }
2149430SRaymond.Chen@Sun.COM
2159430SRaymond.Chen@Sun.COM return (rval);
2169430SRaymond.Chen@Sun.COM
2179430SRaymond.Chen@Sun.COM }
2189430SRaymond.Chen@Sun.COM
2199430SRaymond.Chen@Sun.COM /*
2209430SRaymond.Chen@Sun.COM * Called by hwahc when detaching.
2219430SRaymond.Chen@Sun.COM * The hwarc should be detached after the hwahc. So it should only be
2229430SRaymond.Chen@Sun.COM * called when hwahc is detaching.
2239430SRaymond.Chen@Sun.COM */
2249430SRaymond.Chen@Sun.COM int
uwb_dev_offline(dev_info_t * dip)2259430SRaymond.Chen@Sun.COM uwb_dev_offline(dev_info_t *dip)
2269430SRaymond.Chen@Sun.COM {
2279430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = NULL;
2289430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
2299430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
2309430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
2319430SRaymond.Chen@Sun.COM "uwb_dev_offline::no dev for dip:0x%p", dip);
2329430SRaymond.Chen@Sun.COM
2339430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
2349430SRaymond.Chen@Sun.COM }
2359430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
2369430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
2379430SRaymond.Chen@Sun.COM " uwb_dev_offline dip = 0x%p", dip);
2389430SRaymond.Chen@Sun.COM (void) ddi_prop_update_int(DDI_DEV_T_NONE, uwba_dev->dip,
2399430SRaymond.Chen@Sun.COM DDI_NO_AUTODETACH, 0);
2409430SRaymond.Chen@Sun.COM
2419430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
2429430SRaymond.Chen@Sun.COM
2439430SRaymond.Chen@Sun.COM }
2449430SRaymond.Chen@Sun.COM /*
2459430SRaymond.Chen@Sun.COM * Called by hwarc when disconnect or suspend.
2469430SRaymond.Chen@Sun.COM * Stop beacon. In addition, uwb will save the current channel
2479430SRaymond.Chen@Sun.COM * and dev state.
2489430SRaymond.Chen@Sun.COM */
2499430SRaymond.Chen@Sun.COM int
uwb_dev_disconnect(dev_info_t * dip)2509430SRaymond.Chen@Sun.COM uwb_dev_disconnect(dev_info_t *dip)
2519430SRaymond.Chen@Sun.COM {
2529430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = NULL;
2539430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
2549430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
2559430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
2569430SRaymond.Chen@Sun.COM "uwb_dev_offline::no dev for dip:0x%p", dip);
2579430SRaymond.Chen@Sun.COM
2589430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
2599430SRaymond.Chen@Sun.COM }
2609430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
2619430SRaymond.Chen@Sun.COM
2629430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
2639430SRaymond.Chen@Sun.COM uint8_t channel = uwba_dev->channel;
2649430SRaymond.Chen@Sun.COM uint8_t state = uwba_dev->dev_state;
2659430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
2669430SRaymond.Chen@Sun.COM
2679430SRaymond.Chen@Sun.COM
2689430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
2699430SRaymond.Chen@Sun.COM " uwb_dev_disconnect dip = 0x%p, channel=%d, state=%d",
2709430SRaymond.Chen@Sun.COM dip, channel, state);
2719430SRaymond.Chen@Sun.COM
2729430SRaymond.Chen@Sun.COM if (state == UWB_STATE_BEACON) {
273*10912SRaymond.Chen@Sun.COM (void) uwb_stop_beacon(dip);
2749430SRaymond.Chen@Sun.COM }
2759430SRaymond.Chen@Sun.COM
2769430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
2779430SRaymond.Chen@Sun.COM uwba_dev->channel = channel;
2789430SRaymond.Chen@Sun.COM uwba_dev->dev_state = state;
2799430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
2809430SRaymond.Chen@Sun.COM
2819430SRaymond.Chen@Sun.COM
2829430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
2839430SRaymond.Chen@Sun.COM
2849430SRaymond.Chen@Sun.COM }
2859430SRaymond.Chen@Sun.COM
2869430SRaymond.Chen@Sun.COM /*
2879430SRaymond.Chen@Sun.COM * Called by hwarc when reconnect or resume.
2889430SRaymond.Chen@Sun.COM * Start beacon and set the dev address whchi is saved
2899430SRaymond.Chen@Sun.COM * in disconnect or suspend.
2909430SRaymond.Chen@Sun.COM */
2919430SRaymond.Chen@Sun.COM int
uwb_dev_reconnect(dev_info_t * dip)2929430SRaymond.Chen@Sun.COM uwb_dev_reconnect(dev_info_t *dip)
2939430SRaymond.Chen@Sun.COM {
2949430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = NULL;
2959430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
2969430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
2979430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
2989430SRaymond.Chen@Sun.COM "uwb_dev_offline::no dev for dip:0x%p", dip);
2999430SRaymond.Chen@Sun.COM
3009430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
3019430SRaymond.Chen@Sun.COM }
3029430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
3039430SRaymond.Chen@Sun.COM
3049430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
3059430SRaymond.Chen@Sun.COM uint8_t channel = uwba_dev->channel;
3069430SRaymond.Chen@Sun.COM uint8_t state = uwba_dev->dev_state;
3079430SRaymond.Chen@Sun.COM uwba_dev->dev_state = UWB_STATE_IDLE;
3089430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
3099430SRaymond.Chen@Sun.COM
3109430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
3119430SRaymond.Chen@Sun.COM " uwb_dev_reconnect dip = 0x%p, channel= %d, state = %d",
3129430SRaymond.Chen@Sun.COM dip, channel, state);
3139430SRaymond.Chen@Sun.COM
3149430SRaymond.Chen@Sun.COM
315*10912SRaymond.Chen@Sun.COM (void) uwb_set_dev_addr(dip, uwba_dev->dev_addr);
3169430SRaymond.Chen@Sun.COM
3179430SRaymond.Chen@Sun.COM if (state == UWB_STATE_BEACON) {
318*10912SRaymond.Chen@Sun.COM (void) uwb_start_beacon(dip, uwba_dev->channel);
3199430SRaymond.Chen@Sun.COM }
3209430SRaymond.Chen@Sun.COM
3219430SRaymond.Chen@Sun.COM
3229430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
3239430SRaymond.Chen@Sun.COM
3249430SRaymond.Chen@Sun.COM }
3259430SRaymond.Chen@Sun.COM
3269430SRaymond.Chen@Sun.COM
3279430SRaymond.Chen@Sun.COM
3289430SRaymond.Chen@Sun.COM /*
3299430SRaymond.Chen@Sun.COM * This is a common interface for other models to send a
3309430SRaymond.Chen@Sun.COM * rccb command to the radio controller
3319430SRaymond.Chen@Sun.COM */
3329430SRaymond.Chen@Sun.COM int
uwb_process_rccb_cmd(dev_info_t * dip,uwb_rccb_cmd_t * rccb_cmd,uwb_cmd_result_t * cmd_result)3339430SRaymond.Chen@Sun.COM uwb_process_rccb_cmd(dev_info_t *dip, uwb_rccb_cmd_t *rccb_cmd,
3349430SRaymond.Chen@Sun.COM uwb_cmd_result_t *cmd_result)
3359430SRaymond.Chen@Sun.COM {
3369430SRaymond.Chen@Sun.COM int rval = UWB_SUCCESS;
3379430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
3389430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
3399430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
3409430SRaymond.Chen@Sun.COM "uwb_process_rccb_cmd::no dev for dip:0x%p", dip);
3419430SRaymond.Chen@Sun.COM
3429430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
3439430SRaymond.Chen@Sun.COM }
3449430SRaymond.Chen@Sun.COM
3459430SRaymond.Chen@Sun.COM /* check if it is a valid rccb command */
3469430SRaymond.Chen@Sun.COM if (uwb_check_rccb_cmd(uwb_dev_hdl, rccb_cmd) != UWB_SUCCESS) {
3479430SRaymond.Chen@Sun.COM
3489430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
3499430SRaymond.Chen@Sun.COM }
3509430SRaymond.Chen@Sun.COM
3519430SRaymond.Chen@Sun.COM rval = uwb_process_rccb_cmd_private(uwb_dev_hdl, rccb_cmd, cmd_result);
3529430SRaymond.Chen@Sun.COM
3539430SRaymond.Chen@Sun.COM return (rval);
3549430SRaymond.Chen@Sun.COM }
3559430SRaymond.Chen@Sun.COM
3569430SRaymond.Chen@Sun.COM /*
3579430SRaymond.Chen@Sun.COM * Find a free chanel by scaning the supported channels
3589430SRaymond.Chen@Sun.COM */
3599430SRaymond.Chen@Sun.COM uint8_t
uwb_allocate_channel(dev_info_t * dip)3609430SRaymond.Chen@Sun.COM uwb_allocate_channel(dev_info_t *dip)
3619430SRaymond.Chen@Sun.COM {
3629430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
3639430SRaymond.Chen@Sun.COM uint8_t channel = 0;
3649430SRaymond.Chen@Sun.COM if (!uwb_dev_hdl) {
3659430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
3669430SRaymond.Chen@Sun.COM "uwb_send_rccb_cmd: uwba dev not found");
3679430SRaymond.Chen@Sun.COM goto done;
3689430SRaymond.Chen@Sun.COM }
3699430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
3709430SRaymond.Chen@Sun.COM "uwb_allocate_channel: enter");
3719430SRaymond.Chen@Sun.COM channel = uwba_allocate_channel(uwb_dev_hdl);
3729430SRaymond.Chen@Sun.COM done:
3739430SRaymond.Chen@Sun.COM return (channel);
3749430SRaymond.Chen@Sun.COM }
3759430SRaymond.Chen@Sun.COM /* scan a channel and wait for a while to get beacon info */
3769430SRaymond.Chen@Sun.COM int
uwb_scan_channel(uwb_dev_handle_t uwb_dev_hdl,uint8_t channel)3779430SRaymond.Chen@Sun.COM uwb_scan_channel(uwb_dev_handle_t uwb_dev_hdl, uint8_t channel)
3789430SRaymond.Chen@Sun.COM {
3799430SRaymond.Chen@Sun.COM
3809430SRaymond.Chen@Sun.COM uwb_rccb_scan_t rccb_cmd;
3819430SRaymond.Chen@Sun.COM
3829430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
3839430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
3849430SRaymond.Chen@Sun.COM
3859430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_SCAN;
3869430SRaymond.Chen@Sun.COM rccb_cmd.bScanState = UWB_RC_SCAN_ONLY;
3879430SRaymond.Chen@Sun.COM rccb_cmd.wStartTime = 0;
3889430SRaymond.Chen@Sun.COM rccb_cmd.bChannelNumber = channel;
3899430SRaymond.Chen@Sun.COM
3909430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
3919430SRaymond.Chen@Sun.COM "uwb_scan_channel: channel = %d", channel);
3929430SRaymond.Chen@Sun.COM /* Scan a specific channel */
3939430SRaymond.Chen@Sun.COM
3949430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
3959430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, NULL) != 0) {
3969430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
3979430SRaymond.Chen@Sun.COM "uwb_scan_channel: process cmd failed");
3989430SRaymond.Chen@Sun.COM
3999430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
4009430SRaymond.Chen@Sun.COM }
4019430SRaymond.Chen@Sun.COM
4029430SRaymond.Chen@Sun.COM /* wait for beacon info */
4039430SRaymond.Chen@Sun.COM delay(drv_usectohz(300000));
4049430SRaymond.Chen@Sun.COM
4059430SRaymond.Chen@Sun.COM /* stop scan in the channel */
4069430SRaymond.Chen@Sun.COM rccb_cmd.bScanState = UWB_RC_SCAN_DISABLED;
4079430SRaymond.Chen@Sun.COM
4089430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
4099430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)NULL) != 0) {
4109430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
4119430SRaymond.Chen@Sun.COM "uwb_scan_channel: process cmd failed, channel = %d",
4129430SRaymond.Chen@Sun.COM channel);
4139430SRaymond.Chen@Sun.COM
4149430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
4159430SRaymond.Chen@Sun.COM }
4169430SRaymond.Chen@Sun.COM
4179430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
4189430SRaymond.Chen@Sun.COM }
4199430SRaymond.Chen@Sun.COM
4209430SRaymond.Chen@Sun.COM /* Stop beacon common interface */
4219430SRaymond.Chen@Sun.COM int
uwb_stop_beacon(dev_info_t * dip)4229430SRaymond.Chen@Sun.COM uwb_stop_beacon(dev_info_t *dip)
4239430SRaymond.Chen@Sun.COM {
4249430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t rccb_cmd;
4259430SRaymond.Chen@Sun.COM uwb_rceb_result_code_t ret;
4269430SRaymond.Chen@Sun.COM
4279430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
4289430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
4299430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
4309430SRaymond.Chen@Sun.COM "uwb_stop_beacon::no dev for dip:0x%p", dip);
4319430SRaymond.Chen@Sun.COM
4329430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
4339430SRaymond.Chen@Sun.COM }
4349430SRaymond.Chen@Sun.COM
4359430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
4369430SRaymond.Chen@Sun.COM "uwb_stop_beacon: enter");
4379430SRaymond.Chen@Sun.COM
4389430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
4399430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
4409430SRaymond.Chen@Sun.COM
4419430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_STOP_BEACON;
4429430SRaymond.Chen@Sun.COM
4439430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
4449430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)&ret) != 0) {
4459430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
4469430SRaymond.Chen@Sun.COM "uwb_stop_beacon: process cmd failed");
4479430SRaymond.Chen@Sun.COM
4489430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
4499430SRaymond.Chen@Sun.COM }
4509430SRaymond.Chen@Sun.COM
4519430SRaymond.Chen@Sun.COM if (ret.bResultCode != 0) {
4529430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
4539430SRaymond.Chen@Sun.COM "uwb_stop_beacon: bResultCode =%d", ret.bResultCode);
4549430SRaymond.Chen@Sun.COM
4559430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
4569430SRaymond.Chen@Sun.COM }
4579430SRaymond.Chen@Sun.COM
4589430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
4599430SRaymond.Chen@Sun.COM }
4609430SRaymond.Chen@Sun.COM
4619430SRaymond.Chen@Sun.COM /*
4629430SRaymond.Chen@Sun.COM * Start beacon common interface
4639430SRaymond.Chen@Sun.COM * start beaconing on specified channel
4649430SRaymond.Chen@Sun.COM */
4659430SRaymond.Chen@Sun.COM int
uwb_start_beacon(dev_info_t * dip,uint8_t channel)4669430SRaymond.Chen@Sun.COM uwb_start_beacon(dev_info_t *dip, uint8_t channel)
4679430SRaymond.Chen@Sun.COM {
4689430SRaymond.Chen@Sun.COM uwb_rccb_start_beacon_t rccb_cmd;
4699430SRaymond.Chen@Sun.COM uwb_rceb_result_code_t ret;
4709430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
4719430SRaymond.Chen@Sun.COM
4729430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
4739430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
4749430SRaymond.Chen@Sun.COM "uwb_start_beacon::no dev for dip:0x%p, channel = %d",
4759430SRaymond.Chen@Sun.COM dip, channel);
4769430SRaymond.Chen@Sun.COM
4779430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
4789430SRaymond.Chen@Sun.COM }
4799430SRaymond.Chen@Sun.COM
4809430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
4819430SRaymond.Chen@Sun.COM "uwb_start_beacon: channel = %d", channel);
4829430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
4839430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
4849430SRaymond.Chen@Sun.COM
4859430SRaymond.Chen@Sun.COM
4869430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_START_BEACON;
4879430SRaymond.Chen@Sun.COM /* todo: this needs to be fixed later */
4889430SRaymond.Chen@Sun.COM rccb_cmd.wBPSTOffset = 0;
4899430SRaymond.Chen@Sun.COM rccb_cmd.bChannelNumber = channel;
4909430SRaymond.Chen@Sun.COM
4919430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
4929430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)&ret) != 0) {
4939430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
4949430SRaymond.Chen@Sun.COM "uwb_start_beacon: process cmd failed"
4959430SRaymond.Chen@Sun.COM "channel = %d", channel);
4969430SRaymond.Chen@Sun.COM
4979430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
4989430SRaymond.Chen@Sun.COM }
4999430SRaymond.Chen@Sun.COM
5009430SRaymond.Chen@Sun.COM
5019430SRaymond.Chen@Sun.COM if (ret.bResultCode != 0) {
5029430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
5039430SRaymond.Chen@Sun.COM "uwb_start_beacon: bResultCode =%d", ret.bResultCode);
5049430SRaymond.Chen@Sun.COM
5059430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
5069430SRaymond.Chen@Sun.COM }
5079430SRaymond.Chen@Sun.COM
5089430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
5099430SRaymond.Chen@Sun.COM }
5109430SRaymond.Chen@Sun.COM
5119430SRaymond.Chen@Sun.COM /* Get the mac address of the radion controller */
5129430SRaymond.Chen@Sun.COM int
uwb_get_mac_addr(dev_info_t * dip,uint8_t * mac_addr)5139430SRaymond.Chen@Sun.COM uwb_get_mac_addr(dev_info_t *dip, uint8_t *mac_addr)
5149430SRaymond.Chen@Sun.COM {
5159430SRaymond.Chen@Sun.COM uwb_rccb_dev_addr_mgmt_t rccb_cmd;
5169430SRaymond.Chen@Sun.COM uwb_rceb_dev_addr_mgmt_t ret;
5179430SRaymond.Chen@Sun.COM
5189430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
5199430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
5209430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
5219430SRaymond.Chen@Sun.COM "uwb_get_mac_addr::no dev for dip:0x%p", dip);
5229430SRaymond.Chen@Sun.COM
5239430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
5249430SRaymond.Chen@Sun.COM }
5259430SRaymond.Chen@Sun.COM
5269430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
5279430SRaymond.Chen@Sun.COM "uwb_get_mac_addr: enter");
5289430SRaymond.Chen@Sun.COM
5299430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
5309430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
5319430SRaymond.Chen@Sun.COM
5329430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_DEV_ADDR_MGMT;
5339430SRaymond.Chen@Sun.COM rccb_cmd.bmOperationType = 2; /* get MAC. XXX: should use Macro */
5349430SRaymond.Chen@Sun.COM
5359430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
5369430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)&ret) != 0) {
5379430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
5389430SRaymond.Chen@Sun.COM "uwb_get_mac_addr: process cmd failed");
5399430SRaymond.Chen@Sun.COM
5409430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
5419430SRaymond.Chen@Sun.COM }
5429430SRaymond.Chen@Sun.COM
5439430SRaymond.Chen@Sun.COM
5449430SRaymond.Chen@Sun.COM if (ret.bResultCode != 0) {
5459430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
5469430SRaymond.Chen@Sun.COM "uwb_get_mac_addr: bResultCode =%d", ret.bResultCode);
5479430SRaymond.Chen@Sun.COM
5489430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
5499430SRaymond.Chen@Sun.COM }
5509430SRaymond.Chen@Sun.COM (void) memcpy(mac_addr, ret.baAddr, 6);
5519430SRaymond.Chen@Sun.COM
5529430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
5539430SRaymond.Chen@Sun.COM }
5549430SRaymond.Chen@Sun.COM
5559430SRaymond.Chen@Sun.COM /* Get the device address of the radion controller */
5569430SRaymond.Chen@Sun.COM int
uwb_get_dev_addr(dev_info_t * dip,uint16_t * dev_addr)5579430SRaymond.Chen@Sun.COM uwb_get_dev_addr(dev_info_t *dip, uint16_t *dev_addr)
5589430SRaymond.Chen@Sun.COM {
5599430SRaymond.Chen@Sun.COM uwb_rccb_dev_addr_mgmt_t rccb_cmd;
5609430SRaymond.Chen@Sun.COM uwb_rceb_dev_addr_mgmt_t ret;
5619430SRaymond.Chen@Sun.COM
5629430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
5639430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
5649430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
5659430SRaymond.Chen@Sun.COM "uwb_get_dev_addr::no dev for dip:0x%p", dip);
5669430SRaymond.Chen@Sun.COM
5679430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
5689430SRaymond.Chen@Sun.COM }
5699430SRaymond.Chen@Sun.COM
5709430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
5719430SRaymond.Chen@Sun.COM "uwb_get_dev_addr: enter");
5729430SRaymond.Chen@Sun.COM
5739430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
5749430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
5759430SRaymond.Chen@Sun.COM
5769430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_DEV_ADDR_MGMT;
5779430SRaymond.Chen@Sun.COM rccb_cmd.bmOperationType = 0; /* get 16-bit dev addr */
5789430SRaymond.Chen@Sun.COM
5799430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
5809430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)&ret) != 0) {
5819430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
5829430SRaymond.Chen@Sun.COM "uwb_get_dev_addr: process cmd failed");
5839430SRaymond.Chen@Sun.COM
5849430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
5859430SRaymond.Chen@Sun.COM }
5869430SRaymond.Chen@Sun.COM if (ret.bResultCode != 0) {
5879430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
5889430SRaymond.Chen@Sun.COM "uwb_get_dev_addr: bResultCode =%d", ret.bResultCode);
5899430SRaymond.Chen@Sun.COM
5909430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
5919430SRaymond.Chen@Sun.COM }
5929430SRaymond.Chen@Sun.COM *dev_addr = ret.baAddr[0] | (ret.baAddr[1] << 8);
5939430SRaymond.Chen@Sun.COM
5949430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
5959430SRaymond.Chen@Sun.COM }
5969430SRaymond.Chen@Sun.COM
5979430SRaymond.Chen@Sun.COM /* Set the device address of the radion controller */
5989430SRaymond.Chen@Sun.COM int
uwb_set_dev_addr(dev_info_t * dip,uint16_t dev_addr)5999430SRaymond.Chen@Sun.COM uwb_set_dev_addr(dev_info_t *dip, uint16_t dev_addr)
6009430SRaymond.Chen@Sun.COM {
6019430SRaymond.Chen@Sun.COM uwb_rccb_dev_addr_mgmt_t rccb_cmd;
6029430SRaymond.Chen@Sun.COM uwb_rceb_dev_addr_mgmt_t ret;
6039430SRaymond.Chen@Sun.COM
6049430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
6059430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
6069430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
6079430SRaymond.Chen@Sun.COM "uwb_set_dev_addr::no dev for dip:0x%p, dev_addr=%d",
6089430SRaymond.Chen@Sun.COM dip, dev_addr);
6099430SRaymond.Chen@Sun.COM
6109430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
6119430SRaymond.Chen@Sun.COM }
6129430SRaymond.Chen@Sun.COM
6139430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
6149430SRaymond.Chen@Sun.COM "uwb_set_dev_addr: dev_addr = %d", dev_addr);
6159430SRaymond.Chen@Sun.COM
6169430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
6179430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
6189430SRaymond.Chen@Sun.COM
6199430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_DEV_ADDR_MGMT;
6209430SRaymond.Chen@Sun.COM rccb_cmd.bmOperationType = 1; /* set 16-bit dev addr */
6219430SRaymond.Chen@Sun.COM rccb_cmd.baAddr[0] = dev_addr & 0xff;
6229430SRaymond.Chen@Sun.COM rccb_cmd.baAddr[1] = (dev_addr >> 8) & 0xff;
6239430SRaymond.Chen@Sun.COM
6249430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
6259430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)&ret) != 0) {
6269430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
6279430SRaymond.Chen@Sun.COM "uwb_set_dev_addr: process cmd failed"
6289430SRaymond.Chen@Sun.COM "dev_addr=%d", dev_addr);
6299430SRaymond.Chen@Sun.COM
6309430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
6319430SRaymond.Chen@Sun.COM }
6329430SRaymond.Chen@Sun.COM
6339430SRaymond.Chen@Sun.COM
6349430SRaymond.Chen@Sun.COM if (ret.bResultCode != 0) {
6359430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
6369430SRaymond.Chen@Sun.COM "uwb_set_dev_addr: bResultCode =%d", ret.bResultCode);
6379430SRaymond.Chen@Sun.COM
6389430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
6399430SRaymond.Chen@Sun.COM }
6409430SRaymond.Chen@Sun.COM
6419430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
6429430SRaymond.Chen@Sun.COM }
6439430SRaymond.Chen@Sun.COM
6449430SRaymond.Chen@Sun.COM /*
6459430SRaymond.Chen@Sun.COM * Reset the radio controller.
6469430SRaymond.Chen@Sun.COM * This is called when the radio controller is attached.
6479430SRaymond.Chen@Sun.COM * Notice:Radio controller should not be reset when it
6489430SRaymond.Chen@Sun.COM * is beaconing or scaning.
6499430SRaymond.Chen@Sun.COM */
6509430SRaymond.Chen@Sun.COM int
uwb_reset_dev(dev_info_t * dip)6519430SRaymond.Chen@Sun.COM uwb_reset_dev(dev_info_t *dip)
6529430SRaymond.Chen@Sun.COM {
6539430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t rccb_cmd;
6549430SRaymond.Chen@Sun.COM uwb_rceb_result_code_t ret;
6559430SRaymond.Chen@Sun.COM
6569430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
6579430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
6589430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
6599430SRaymond.Chen@Sun.COM "uwb_reset_dev:no dev for dip:0x%p", dip);
6609430SRaymond.Chen@Sun.COM
6619430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
6629430SRaymond.Chen@Sun.COM }
6639430SRaymond.Chen@Sun.COM
6649430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
6659430SRaymond.Chen@Sun.COM "uwb_reset_dev: enter");
6669430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
6679430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
6689430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_RESET;
6699430SRaymond.Chen@Sun.COM
6709430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
6719430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)&ret) != 0) {
6729430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
6739430SRaymond.Chen@Sun.COM "uwb_reset_dev: process cmd failed");
6749430SRaymond.Chen@Sun.COM
6759430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
6769430SRaymond.Chen@Sun.COM }
6779430SRaymond.Chen@Sun.COM if (ret.bResultCode != 0) {
6789430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
6799430SRaymond.Chen@Sun.COM "uwb_reset_dev: bResultCode =%d", ret.bResultCode);
6809430SRaymond.Chen@Sun.COM
6819430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
6829430SRaymond.Chen@Sun.COM }
6839430SRaymond.Chen@Sun.COM
6849430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
6859430SRaymond.Chen@Sun.COM }
6869430SRaymond.Chen@Sun.COM
6879430SRaymond.Chen@Sun.COM /*
6889430SRaymond.Chen@Sun.COM * Called while attaching.
6899430SRaymond.Chen@Sun.COM * The physical capabilities is initialized.
6909430SRaymond.Chen@Sun.COM * Only the supported channels is used in current version
6919430SRaymond.Chen@Sun.COM */
6929430SRaymond.Chen@Sun.COM int
uwb_init_phy(dev_info_t * dip)6939430SRaymond.Chen@Sun.COM uwb_init_phy(dev_info_t *dip)
6949430SRaymond.Chen@Sun.COM {
6959430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t rccb_cmd;
6969430SRaymond.Chen@Sun.COM
6979430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl = uwba_dev_search(dip);
6989430SRaymond.Chen@Sun.COM if (uwb_dev_hdl == NULL) {
6999430SRaymond.Chen@Sun.COM uwba_log(NULL, UWBA_LOG_LOG,
7009430SRaymond.Chen@Sun.COM "uwb_init_phy::no dev for dip:0x%p", dip);
7019430SRaymond.Chen@Sun.COM
7029430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
7039430SRaymond.Chen@Sun.COM }
7049430SRaymond.Chen@Sun.COM
7059430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_DEBUG,
7069430SRaymond.Chen@Sun.COM "uwb_init_phy: enter");
7079430SRaymond.Chen@Sun.COM bzero(&rccb_cmd, sizeof (rccb_cmd));
7089430SRaymond.Chen@Sun.COM rccb_cmd.rccb.bCommandType = UWB_CE_TYPE_GENERAL;
7099430SRaymond.Chen@Sun.COM rccb_cmd.rccb.wCommand = UWB_CE_GET_IE;
7109430SRaymond.Chen@Sun.COM
7119430SRaymond.Chen@Sun.COM if (uwb_process_rccb_cmd_private(uwb_dev_hdl,
7129430SRaymond.Chen@Sun.COM (uwb_rccb_cmd_t *)&rccb_cmd, (uwb_cmd_result_t *)NULL) != 0) {
7139430SRaymond.Chen@Sun.COM uwba_log((uwba_dev_t *)uwb_dev_hdl, UWBA_LOG_LOG,
7149430SRaymond.Chen@Sun.COM "uwb_init_phy: process cmd failed");
7159430SRaymond.Chen@Sun.COM
7169430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
7179430SRaymond.Chen@Sun.COM }
7189430SRaymond.Chen@Sun.COM /* todo: rceb result is handled in event notification */
7199430SRaymond.Chen@Sun.COM
7209430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
7219430SRaymond.Chen@Sun.COM }
7229430SRaymond.Chen@Sun.COM
7239430SRaymond.Chen@Sun.COM
7249430SRaymond.Chen@Sun.COM /* Get a notif from the list head. That notif is dis-linked from the list. */
7259430SRaymond.Chen@Sun.COM static uwb_notif_wrapper_t *
uwb_get_notif_head(uwb_dev_handle_t uwb_dev_hdl)7269430SRaymond.Chen@Sun.COM uwb_get_notif_head(uwb_dev_handle_t uwb_dev_hdl)
7279430SRaymond.Chen@Sun.COM {
7289430SRaymond.Chen@Sun.COM uwb_notif_wrapper_t *nw = NULL;
7299430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
7309430SRaymond.Chen@Sun.COM
7319430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
7329430SRaymond.Chen@Sun.COM
7339430SRaymond.Chen@Sun.COM if (!list_is_empty(&uwba_dev->notif_list)) {
7349430SRaymond.Chen@Sun.COM nw = list_head(&uwba_dev->notif_list);
7359430SRaymond.Chen@Sun.COM if (nw != NULL) {
7369430SRaymond.Chen@Sun.COM
7379430SRaymond.Chen@Sun.COM /*
7389430SRaymond.Chen@Sun.COM * unlink a notification wrapper's structure from the
7399430SRaymond.Chen@Sun.COM * list
7409430SRaymond.Chen@Sun.COM */
7419430SRaymond.Chen@Sun.COM list_remove(&(uwba_dev->notif_list), nw);
7429430SRaymond.Chen@Sun.COM }
7439430SRaymond.Chen@Sun.COM }
7449430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
7459430SRaymond.Chen@Sun.COM
7469430SRaymond.Chen@Sun.COM return (nw);
7479430SRaymond.Chen@Sun.COM }
7489430SRaymond.Chen@Sun.COM
7499430SRaymond.Chen@Sun.COM /*
7509430SRaymond.Chen@Sun.COM * UWB ioctls
7519430SRaymond.Chen@Sun.COM * UWB_COMMAND --- Send a rccb command to the radio controller
7529430SRaymond.Chen@Sun.COM * UWB_GET_NOTIFICATION -- Get the uwb notifications. Not used
7539430SRaymond.Chen@Sun.COM */
7549430SRaymond.Chen@Sun.COM int
uwb_do_ioctl(uwb_dev_handle_t uwb_dev_hdl,int cmd,intptr_t arg,int mode)7559430SRaymond.Chen@Sun.COM uwb_do_ioctl(uwb_dev_handle_t uwb_dev_hdl,
7569430SRaymond.Chen@Sun.COM int cmd, intptr_t arg, int mode)
7579430SRaymond.Chen@Sun.COM {
7589430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
7599430SRaymond.Chen@Sun.COM int rv = 0;
7609430SRaymond.Chen@Sun.COM
7619430SRaymond.Chen@Sun.COM switch (cmd) {
7629430SRaymond.Chen@Sun.COM case UWB_COMMAND: /* Issue commands to UWB Radio Controller */
7639430SRaymond.Chen@Sun.COM {
7649430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t rccb_cmd;
7659430SRaymond.Chen@Sun.COM if (ddi_copyin((caddr_t)arg, &rccb_cmd,
7669430SRaymond.Chen@Sun.COM sizeof (rccb_cmd), mode)) {
7679430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
7689430SRaymond.Chen@Sun.COM "uwb_do_ioctl: ddi_copyin fail");
7699430SRaymond.Chen@Sun.COM
7709430SRaymond.Chen@Sun.COM rv = EFAULT;
7719430SRaymond.Chen@Sun.COM break;
7729430SRaymond.Chen@Sun.COM }
7739430SRaymond.Chen@Sun.COM if (uwb_check_rccb_cmd(uwb_dev_hdl, &rccb_cmd) != UWB_SUCCESS) {
7749430SRaymond.Chen@Sun.COM
7759430SRaymond.Chen@Sun.COM rv = EINVAL;
7769430SRaymond.Chen@Sun.COM break;
7779430SRaymond.Chen@Sun.COM }
7789430SRaymond.Chen@Sun.COM if (uwb_do_ioctl_rccb_cmd(uwb_dev_hdl, rccb_cmd.rccb.wCommand,
7799430SRaymond.Chen@Sun.COM arg, mode)
7809430SRaymond.Chen@Sun.COM != UWB_SUCCESS) {
7819430SRaymond.Chen@Sun.COM
7829430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
7839430SRaymond.Chen@Sun.COM "uwb_do_ioctl: uwb_do_ioctl_rccb_cmd failed");
7849430SRaymond.Chen@Sun.COM rv = EIO;
7859430SRaymond.Chen@Sun.COM }
7869430SRaymond.Chen@Sun.COM
7879430SRaymond.Chen@Sun.COM break;
7889430SRaymond.Chen@Sun.COM }
7899430SRaymond.Chen@Sun.COM case UWB_GET_NOTIFICATION:
7909430SRaymond.Chen@Sun.COM {
7919430SRaymond.Chen@Sun.COM uwb_notif_wrapper_t *nw;
7929430SRaymond.Chen@Sun.COM
7939430SRaymond.Chen@Sun.COM nw = uwb_get_notification(uwb_dev_hdl, arg, mode);
7949430SRaymond.Chen@Sun.COM
7959430SRaymond.Chen@Sun.COM if (nw && nw->notif) {
7969430SRaymond.Chen@Sun.COM /* Copy the notification to userland application */
7979430SRaymond.Chen@Sun.COM if (ddi_copyout(nw->notif,
7989430SRaymond.Chen@Sun.COM (caddr_t)&(((uwb_notif_get_t *)arg)->notif),
7999430SRaymond.Chen@Sun.COM nw->length, mode)) { /* todo: 32bit/64bit */
8009430SRaymond.Chen@Sun.COM
8019430SRaymond.Chen@Sun.COM rv = EFAULT;
8029430SRaymond.Chen@Sun.COM }
8039430SRaymond.Chen@Sun.COM /* release the notif and the wrapper. */
8049430SRaymond.Chen@Sun.COM uwb_free_notification(nw);
8059430SRaymond.Chen@Sun.COM } else {
8069430SRaymond.Chen@Sun.COM rv = EIO;
8079430SRaymond.Chen@Sun.COM }
8089430SRaymond.Chen@Sun.COM
8099430SRaymond.Chen@Sun.COM break;
8109430SRaymond.Chen@Sun.COM }
8119430SRaymond.Chen@Sun.COM default:
8129430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
8139430SRaymond.Chen@Sun.COM "uwb_do_ioctl: not a valid cmd value, cmd=%x", cmd);
8149430SRaymond.Chen@Sun.COM rv = EINVAL;
8159430SRaymond.Chen@Sun.COM }
8169430SRaymond.Chen@Sun.COM
8179430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
8189430SRaymond.Chen@Sun.COM "uwb_do_ioctl: exit, rv=%d", rv);
8199430SRaymond.Chen@Sun.COM
8209430SRaymond.Chen@Sun.COM return (rv);
8219430SRaymond.Chen@Sun.COM }
8229430SRaymond.Chen@Sun.COM
8239430SRaymond.Chen@Sun.COM
8249430SRaymond.Chen@Sun.COM /*
8259430SRaymond.Chen@Sun.COM * Parse all the standard events, including command results and notifications.
8269430SRaymond.Chen@Sun.COM * If a unknown event, return UWB_NOT_SUPPORTED. The specific client radio
8279430SRaymond.Chen@Sun.COM * controllers might has the knowledge to parse the vendor specific
8289430SRaymond.Chen@Sun.COM * events/notifications.
8299430SRaymond.Chen@Sun.COM */
8309430SRaymond.Chen@Sun.COM int
uwb_parse_evt_notif(uint8_t * data,int data_len,uwb_dev_handle_t uwb_dev_hdl)8319430SRaymond.Chen@Sun.COM uwb_parse_evt_notif(uint8_t *data, int data_len,
8329430SRaymond.Chen@Sun.COM uwb_dev_handle_t uwb_dev_hdl)
8339430SRaymond.Chen@Sun.COM {
8349430SRaymond.Chen@Sun.COM uint16_t evt_code, evt_size;
8359430SRaymond.Chen@Sun.COM void *evt_struct;
8369430SRaymond.Chen@Sun.COM uwb_rceb_head_t *rceb;
8379430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev;
8389430SRaymond.Chen@Sun.COM uint8_t *spec_data; /* the raw event data excluding rceb. */
8399430SRaymond.Chen@Sun.COM int spec_data_len, offset;
8409430SRaymond.Chen@Sun.COM int rval = UWB_SUCCESS;
8419430SRaymond.Chen@Sun.COM
8429430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
8439430SRaymond.Chen@Sun.COM
8449430SRaymond.Chen@Sun.COM /* Get evt/notif code */
8459430SRaymond.Chen@Sun.COM if ((evt_code = uwba_get_evt_code(data, data_len)) ==
8469430SRaymond.Chen@Sun.COM UWB_INVALID_EVT_CODE) {
8479430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
8489430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: invalid evt_code");
8499430SRaymond.Chen@Sun.COM
8509430SRaymond.Chen@Sun.COM return (UWB_INVALID_EVT_CODE);
8519430SRaymond.Chen@Sun.COM }
8529430SRaymond.Chen@Sun.COM
8539430SRaymond.Chen@Sun.COM if ((evt_size = uwba_get_evt_size(data, data_len, evt_code)) ==
8549430SRaymond.Chen@Sun.COM UWB_INVALID_EVT_SIZE) {
8559430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
8569430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: invalid evt_size. evt_code=%d",
8579430SRaymond.Chen@Sun.COM evt_code);
8589430SRaymond.Chen@Sun.COM
8599430SRaymond.Chen@Sun.COM return (UWB_INVALID_EVT_SIZE);
8609430SRaymond.Chen@Sun.COM }
8619430SRaymond.Chen@Sun.COM evt_struct = kmem_alloc(evt_size, KM_NOSLEEP);
8629430SRaymond.Chen@Sun.COM if (evt_struct == NULL) {
8639430SRaymond.Chen@Sun.COM
8649430SRaymond.Chen@Sun.COM return (UWB_NO_RESOURCES);
8659430SRaymond.Chen@Sun.COM }
8669430SRaymond.Chen@Sun.COM
8679430SRaymond.Chen@Sun.COM /* parse rceb and get the data offset just after the rceb struct. */
8689430SRaymond.Chen@Sun.COM if ((offset = uwba_parse_rceb(data, data_len, evt_struct, evt_size))
8699430SRaymond.Chen@Sun.COM == UWB_PARSE_ERROR) {
8709430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
8719430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: uwba_parse_rceb failed");
8729430SRaymond.Chen@Sun.COM kmem_free(evt_struct, evt_size);
8739430SRaymond.Chen@Sun.COM
8749430SRaymond.Chen@Sun.COM return (UWB_PARSE_ERROR);
8759430SRaymond.Chen@Sun.COM }
8769430SRaymond.Chen@Sun.COM rceb = (uwb_rceb_head_t *)evt_struct;
8779430SRaymond.Chen@Sun.COM if (rceb->bEventContext > 0 &&
8789430SRaymond.Chen@Sun.COM rceb->bEventContext != uwba_dev->ctxt_id) {
8799430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
8809430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: cmd result's ctxt_id is "
8819430SRaymond.Chen@Sun.COM "not matching cmd's ctxt_id,"
8829430SRaymond.Chen@Sun.COM " result ctxt_id=%d, cmd ctxt_id=%d",
8839430SRaymond.Chen@Sun.COM rceb->bEventContext, uwba_dev->ctxt_id);
8849430SRaymond.Chen@Sun.COM }
8859430SRaymond.Chen@Sun.COM
8869430SRaymond.Chen@Sun.COM /* the data after rceb head are evt specific data */
8879430SRaymond.Chen@Sun.COM spec_data = data + offset;
8889430SRaymond.Chen@Sun.COM spec_data_len = data_len - offset;
8899430SRaymond.Chen@Sun.COM
8909430SRaymond.Chen@Sun.COM switch (evt_code) {
8919430SRaymond.Chen@Sun.COM case UWB_CE_CHANNEL_CHANGE:
8929430SRaymond.Chen@Sun.COM case UWB_CE_RESET:
8939430SRaymond.Chen@Sun.COM case UWB_CE_SCAN:
8949430SRaymond.Chen@Sun.COM case UWB_CE_SET_BEACON_FILTER:
8959430SRaymond.Chen@Sun.COM case UWB_CE_SET_NOTIFICATION_FILTER:
8969430SRaymond.Chen@Sun.COM case UWB_CE_SET_TX_POWER:
8979430SRaymond.Chen@Sun.COM case UWB_CE_SLEEP:
8989430SRaymond.Chen@Sun.COM case UWB_CE_START_BEACON:
8999430SRaymond.Chen@Sun.COM case UWB_CE_STOP_BEACON:
9009430SRaymond.Chen@Sun.COM case UWB_CE_BP_MERGE:
9019430SRaymond.Chen@Sun.COM case UWB_CE_SEND_COMMAND_FRAME:
9029430SRaymond.Chen@Sun.COM case UWB_CE_SET_ASIE_NOTIFICATION:
9039430SRaymond.Chen@Sun.COM /* All the above cmd results have only result code. */
9049430SRaymond.Chen@Sun.COM ((uwb_rceb_result_code_t *)evt_struct)->bResultCode =
9059430SRaymond.Chen@Sun.COM *spec_data;
9069430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
9079430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: msg = %s, bResultCode = %d ",
9089430SRaymond.Chen@Sun.COM uwba_event_msg(evt_code), *spec_data);
9099430SRaymond.Chen@Sun.COM
9109430SRaymond.Chen@Sun.COM break;
9119430SRaymond.Chen@Sun.COM case UWB_CE_DEV_ADDR_MGMT:
9129430SRaymond.Chen@Sun.COM rval = uwba_parse_dev_addr_mgmt(spec_data, spec_data_len,
9139430SRaymond.Chen@Sun.COM (uwb_rceb_dev_addr_mgmt_t *)evt_struct);
9149430SRaymond.Chen@Sun.COM
9159430SRaymond.Chen@Sun.COM break;
9169430SRaymond.Chen@Sun.COM case UWB_CE_GET_IE:
9179430SRaymond.Chen@Sun.COM rval = uwba_parse_get_ie(uwb_dev_hdl, spec_data, spec_data_len,
9189430SRaymond.Chen@Sun.COM (uwb_rceb_get_ie_t *)evt_struct);
9199430SRaymond.Chen@Sun.COM
9209430SRaymond.Chen@Sun.COM break;
9219430SRaymond.Chen@Sun.COM case UWB_NOTIF_BEACON_RECEIVED:
9229430SRaymond.Chen@Sun.COM rval = uwba_parse_beacon_rcv(uwb_dev_hdl, spec_data,
9239430SRaymond.Chen@Sun.COM spec_data_len, (uwb_rceb_beacon_t *)evt_struct);
9249430SRaymond.Chen@Sun.COM break;
9259430SRaymond.Chen@Sun.COM case UWB_NOTIF_BPOIE_CHANGE:
9269430SRaymond.Chen@Sun.COM rval = uwba_parse_bpoie_chg(uwb_dev_hdl, spec_data,
9279430SRaymond.Chen@Sun.COM spec_data_len, (uwb_rceb_bpoie_change_t *)evt_struct);
9289430SRaymond.Chen@Sun.COM break;
9299430SRaymond.Chen@Sun.COM
9309430SRaymond.Chen@Sun.COM case UWB_NOTIF_BEACON_SIZE_CHANGE:
9319430SRaymond.Chen@Sun.COM case UWB_CE_SET_DRP_IE:
9329430SRaymond.Chen@Sun.COM case UWB_CE_SET_IE:
9339430SRaymond.Chen@Sun.COM case UWB_NOTIF_IE_RECEIVED:
9349430SRaymond.Chen@Sun.COM case UWB_NOTIF_BP_SLOT_CHANGE:
9359430SRaymond.Chen@Sun.COM case UWB_NOTIF_BP_SWITCH_IE_RECEIVED:
9369430SRaymond.Chen@Sun.COM case UWB_NOTIF_DEV_ADDR_CONFLICT:
9379430SRaymond.Chen@Sun.COM case UWB_NOTIF_DRP_AVAILABILITY_CHANGE:
9389430SRaymond.Chen@Sun.COM case UWB_NOTIF_DRP:
9399430SRaymond.Chen@Sun.COM case UWB_NOTIF_BP_SWITCH_STATUS:
9409430SRaymond.Chen@Sun.COM case UWB_NOTIF_CMD_FRAME_RCV:
9419430SRaymond.Chen@Sun.COM case UWB_NOTIF_CHANNEL_CHANGE_IE_RCV:
9429430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
9439430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: %s not supported",
9449430SRaymond.Chen@Sun.COM uwba_event_msg(evt_code));
9459430SRaymond.Chen@Sun.COM break;
9469430SRaymond.Chen@Sun.COM
9479430SRaymond.Chen@Sun.COM default: /* unkonwn events or notifications */
9489430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
9499430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: unkonwn events or notifications,"
9509430SRaymond.Chen@Sun.COM " evt_code=%d", evt_code);
9519430SRaymond.Chen@Sun.COM break;
9529430SRaymond.Chen@Sun.COM }
9539430SRaymond.Chen@Sun.COM
9549430SRaymond.Chen@Sun.COM if (rval != UWB_SUCCESS) {
9559430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
9569430SRaymond.Chen@Sun.COM "uwb_parse_evt_notif: fail, rval = %d", rval);
9579430SRaymond.Chen@Sun.COM
9589430SRaymond.Chen@Sun.COM kmem_free(evt_struct, evt_size);
9599430SRaymond.Chen@Sun.COM
9609430SRaymond.Chen@Sun.COM return (rval);
9619430SRaymond.Chen@Sun.COM }
9629430SRaymond.Chen@Sun.COM
9639430SRaymond.Chen@Sun.COM /*
9649430SRaymond.Chen@Sun.COM * By now, parse complete. Go on notify the waiting cmd thread or add
9659430SRaymond.Chen@Sun.COM * notification to list
9669430SRaymond.Chen@Sun.COM */
9679430SRaymond.Chen@Sun.COM if (evt_code > UWB_NOTIF_RESERVED) {
9689430SRaymond.Chen@Sun.COM /* If this event is a cmd result */
9699430SRaymond.Chen@Sun.COM uwba_put_cmd_result(uwba_dev, evt_struct, evt_size);
9709430SRaymond.Chen@Sun.COM } else {
9719430SRaymond.Chen@Sun.COM
9729430SRaymond.Chen@Sun.COM /* If this event is a notification */
9739430SRaymond.Chen@Sun.COM rval = uwba_add_notif_to_list(uwba_dev, evt_struct, evt_size);
9749430SRaymond.Chen@Sun.COM }
9759430SRaymond.Chen@Sun.COM
9769430SRaymond.Chen@Sun.COM return (rval);
9779430SRaymond.Chen@Sun.COM }
9789430SRaymond.Chen@Sun.COM
9799430SRaymond.Chen@Sun.COM
9809430SRaymond.Chen@Sun.COM /*
9819430SRaymond.Chen@Sun.COM * Send command to device. This function is shared by those commands whose cmd
9829430SRaymond.Chen@Sun.COM * data have rccb only.
9839430SRaymond.Chen@Sun.COM */
9849430SRaymond.Chen@Sun.COM static int
uwb_do_cmd_rccb(uwb_dev_handle_t uwb_dev_hdl,uwb_rccb_cmd_t * rccb_cmd)9859430SRaymond.Chen@Sun.COM uwb_do_cmd_rccb(uwb_dev_handle_t uwb_dev_hdl, uwb_rccb_cmd_t *rccb_cmd)
9869430SRaymond.Chen@Sun.COM {
9879430SRaymond.Chen@Sun.COM /* reset cmd has no extra bytes, just rccb */
9889430SRaymond.Chen@Sun.COM mblk_t *data;
9899430SRaymond.Chen@Sun.COM uint16_t data_len;
9909430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev;
9919430SRaymond.Chen@Sun.COM int rval = UWB_SUCCESS;
9929430SRaymond.Chen@Sun.COM
9939430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
9949430SRaymond.Chen@Sun.COM
9959430SRaymond.Chen@Sun.COM /* size of rccb. Reset cmd has no data other than rccb head */
9969430SRaymond.Chen@Sun.COM data_len = UWB_RAW_RCCB_HEAD_SIZE;
9979430SRaymond.Chen@Sun.COM
9989430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
9999430SRaymond.Chen@Sun.COM "uwb_do_cmd_rccb: wLength=%d", data_len);
10009430SRaymond.Chen@Sun.COM
10019430SRaymond.Chen@Sun.COM /* Data block */
10029430SRaymond.Chen@Sun.COM if ((data = allocb(data_len, BPRI_HI)) == NULL) {
10039430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
10049430SRaymond.Chen@Sun.COM "uwb_do_cmd_rccb: allocb failed");
10059430SRaymond.Chen@Sun.COM
10069430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
10079430SRaymond.Chen@Sun.COM }
10089430SRaymond.Chen@Sun.COM
10099430SRaymond.Chen@Sun.COM uwba_fill_rccb_head(uwba_dev, rccb_cmd->rccb.wCommand, data);
10109430SRaymond.Chen@Sun.COM data->b_wptr += data_len;
10119430SRaymond.Chen@Sun.COM
10129430SRaymond.Chen@Sun.COM /* record the current cmd rccb to the uwb dev handle. */
10139430SRaymond.Chen@Sun.COM uwba_copy_rccb(rccb_cmd, &(uwba_dev->curr_rccb));
10149430SRaymond.Chen@Sun.COM uwba_dev->curr_rccb.rccb.bCommandContext = data->b_rptr[3];
10159430SRaymond.Chen@Sun.COM
10169430SRaymond.Chen@Sun.COM /*
10179430SRaymond.Chen@Sun.COM * data will be freed by radio client driver after the cmd is sent to
10189430SRaymond.Chen@Sun.COM * device
10199430SRaymond.Chen@Sun.COM */
10209430SRaymond.Chen@Sun.COM rval = uwba_dev->send_cmd(uwb_dev_hdl, data, data_len);
10219430SRaymond.Chen@Sun.COM if (rval != UWB_SUCCESS) {
10229430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
10239430SRaymond.Chen@Sun.COM "uwb_do_cmd_rccb: send cmd fail ");
10249430SRaymond.Chen@Sun.COM
10259430SRaymond.Chen@Sun.COM return (rval);
10269430SRaymond.Chen@Sun.COM }
10279430SRaymond.Chen@Sun.COM
10289430SRaymond.Chen@Sun.COM return (rval);
10299430SRaymond.Chen@Sun.COM }
10309430SRaymond.Chen@Sun.COM
10319430SRaymond.Chen@Sun.COM /* Dev addr management rccb cmd handler */
10329430SRaymond.Chen@Sun.COM static int
uwb_do_cmd_dev_addr_mgmt(uwb_dev_handle_t uwb_dev_hdl,uwb_rccb_cmd_t * rccb_cmd)10339430SRaymond.Chen@Sun.COM uwb_do_cmd_dev_addr_mgmt(uwb_dev_handle_t uwb_dev_hdl,
10349430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t *rccb_cmd)
10359430SRaymond.Chen@Sun.COM {
10369430SRaymond.Chen@Sun.COM mblk_t *data;
10379430SRaymond.Chen@Sun.COM uint16_t data_len;
10389430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev;
10399430SRaymond.Chen@Sun.COM int i, rval = UWB_SUCCESS;
10409430SRaymond.Chen@Sun.COM uwb_rccb_dev_addr_mgmt_t *rccb_dev_addr =
10419430SRaymond.Chen@Sun.COM (uwb_rccb_dev_addr_mgmt_t *)rccb_cmd;
10429430SRaymond.Chen@Sun.COM
10439430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
10449430SRaymond.Chen@Sun.COM /* size of device address mgmt RCCB */
10459430SRaymond.Chen@Sun.COM data_len = UWB_RAW_RCCB_HEAD_SIZE + 7;
10469430SRaymond.Chen@Sun.COM
10479430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
10489430SRaymond.Chen@Sun.COM "uwb_do_cmd_dev_addr_mgmt: wLength=%d, type=%x",
10499430SRaymond.Chen@Sun.COM data_len, rccb_dev_addr->bmOperationType);
10509430SRaymond.Chen@Sun.COM
10519430SRaymond.Chen@Sun.COM /* Data block */
10529430SRaymond.Chen@Sun.COM if ((data = allocb(data_len, BPRI_HI)) == NULL) {
10539430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
10549430SRaymond.Chen@Sun.COM "uwb_do_cmd_dev_addr_mgmt: allocb failed");
10559430SRaymond.Chen@Sun.COM
10569430SRaymond.Chen@Sun.COM return (UWB_NO_RESOURCES);
10579430SRaymond.Chen@Sun.COM }
10589430SRaymond.Chen@Sun.COM
10599430SRaymond.Chen@Sun.COM uwba_fill_rccb_head(uwba_dev, rccb_dev_addr->rccb.wCommand, data);
10609430SRaymond.Chen@Sun.COM data->b_rptr[4] = rccb_dev_addr->bmOperationType;
10619430SRaymond.Chen@Sun.COM for (i = 0; i < 6; i++) {
10629430SRaymond.Chen@Sun.COM data->b_rptr[5 + i] = rccb_dev_addr->baAddr[i];
10639430SRaymond.Chen@Sun.COM }
10649430SRaymond.Chen@Sun.COM data->b_wptr += data_len;
10659430SRaymond.Chen@Sun.COM
10669430SRaymond.Chen@Sun.COM /* record the current cmd rccb to the uwb dev handle. */
10679430SRaymond.Chen@Sun.COM uwba_copy_rccb((uwb_rccb_cmd_t *)rccb_dev_addr, &(uwba_dev->curr_rccb));
10689430SRaymond.Chen@Sun.COM uwba_dev->curr_rccb.rccb.bCommandContext = data->b_rptr[3];
10699430SRaymond.Chen@Sun.COM
10709430SRaymond.Chen@Sun.COM if ((rval = uwba_dev->send_cmd(uwb_dev_hdl, data, data_len))
10719430SRaymond.Chen@Sun.COM != UWB_SUCCESS) {
10729430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
10739430SRaymond.Chen@Sun.COM "uwb_do_cmd_dev_addr_mgmt: fail ");
10749430SRaymond.Chen@Sun.COM
10759430SRaymond.Chen@Sun.COM return (rval);
10769430SRaymond.Chen@Sun.COM }
10779430SRaymond.Chen@Sun.COM
10789430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
10799430SRaymond.Chen@Sun.COM "uwb_do_cmd_dev_addr_mgmt: success.");
10809430SRaymond.Chen@Sun.COM
10819430SRaymond.Chen@Sun.COM return (rval);
10829430SRaymond.Chen@Sun.COM }
10839430SRaymond.Chen@Sun.COM
10849430SRaymond.Chen@Sun.COM /* Scan rccb cmd handler */
10859430SRaymond.Chen@Sun.COM static int
uwb_do_cmd_scan(uwb_dev_handle_t uwb_dev_hdl,uwb_rccb_cmd_t * rccb_cmd)10869430SRaymond.Chen@Sun.COM uwb_do_cmd_scan(uwb_dev_handle_t uwb_dev_hdl, uwb_rccb_cmd_t *rccb_cmd)
10879430SRaymond.Chen@Sun.COM {
10889430SRaymond.Chen@Sun.COM mblk_t *data;
10899430SRaymond.Chen@Sun.COM uint16_t data_len;
10909430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev;
10919430SRaymond.Chen@Sun.COM int rval = UWB_SUCCESS;
10929430SRaymond.Chen@Sun.COM uwb_rccb_scan_t *rccb_scan = (uwb_rccb_scan_t *)rccb_cmd;
10939430SRaymond.Chen@Sun.COM
10949430SRaymond.Chen@Sun.COM uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
10959430SRaymond.Chen@Sun.COM data_len = UWB_RAW_RCCB_HEAD_SIZE + 4; /* size of scan RCCB */
10969430SRaymond.Chen@Sun.COM
10979430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
10989430SRaymond.Chen@Sun.COM "uwb_do_cmd_scan: wLength=%d", data_len);
10999430SRaymond.Chen@Sun.COM
11009430SRaymond.Chen@Sun.COM /* Data block */
11019430SRaymond.Chen@Sun.COM if ((data = allocb(data_len, BPRI_HI)) == NULL) {
11029430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
11039430SRaymond.Chen@Sun.COM "uwb_do_cmd_scan: allocb failed");
11049430SRaymond.Chen@Sun.COM
11059430SRaymond.Chen@Sun.COM return (UWB_NO_RESOURCES);
11069430SRaymond.Chen@Sun.COM }
11079430SRaymond.Chen@Sun.COM
11089430SRaymond.Chen@Sun.COM uwba_fill_rccb_head(uwba_dev, rccb_scan->rccb.wCommand, data);
11099430SRaymond.Chen@Sun.COM data->b_rptr[4] = rccb_scan->bChannelNumber;
11109430SRaymond.Chen@Sun.COM data->b_rptr[5] = rccb_scan->bScanState;
11119430SRaymond.Chen@Sun.COM UINT16_TO_LE(rccb_scan->wStartTime, 6, data->b_rptr);
11129430SRaymond.Chen@Sun.COM data->b_wptr += data_len;
11139430SRaymond.Chen@Sun.COM
11149430SRaymond.Chen@Sun.COM /* record the current cmd rccb to the uwb dev handle. */
11159430SRaymond.Chen@Sun.COM uwba_copy_rccb((uwb_rccb_cmd_t *)rccb_scan, &(uwba_dev->curr_rccb));
11169430SRaymond.Chen@Sun.COM uwba_dev->curr_rccb.rccb.bCommandContext = data->b_rptr[3];
11179430SRaymond.Chen@Sun.COM
11189430SRaymond.Chen@Sun.COM if ((rval = uwba_dev->send_cmd(uwb_dev_hdl, data, data_len))
11199430SRaymond.Chen@Sun.COM != UWB_SUCCESS) {
11209430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
11219430SRaymond.Chen@Sun.COM "uwb_send_rccb_cmd: fail ");
11229430SRaymond.Chen@Sun.COM
11239430SRaymond.Chen@Sun.COM return (rval);
11249430SRaymond.Chen@Sun.COM }
11259430SRaymond.Chen@Sun.COM
11269430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
11279430SRaymond.Chen@Sun.COM "uwb_do_cmd_scan: success.");
11289430SRaymond.Chen@Sun.COM
11299430SRaymond.Chen@Sun.COM return (rval);
11309430SRaymond.Chen@Sun.COM }
11319430SRaymond.Chen@Sun.COM
11329430SRaymond.Chen@Sun.COM /* Start beacon rccb handler */
11339430SRaymond.Chen@Sun.COM static int
uwb_do_cmd_start_beacon(uwb_dev_handle_t uwb_dev_hdl,uwb_rccb_cmd_t * rccb_cmd)11349430SRaymond.Chen@Sun.COM uwb_do_cmd_start_beacon(uwb_dev_handle_t uwb_dev_hdl,
11359430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t *rccb_cmd)
11369430SRaymond.Chen@Sun.COM {
11379430SRaymond.Chen@Sun.COM mblk_t *data;
11389430SRaymond.Chen@Sun.COM uint16_t data_len;
11399430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
11409430SRaymond.Chen@Sun.COM int rval = UWB_SUCCESS;
11419430SRaymond.Chen@Sun.COM uwba_client_dev_t *client = NULL;
11429430SRaymond.Chen@Sun.COM uwb_rccb_start_beacon_t *rccb_startbc =
11439430SRaymond.Chen@Sun.COM (uwb_rccb_start_beacon_t *)rccb_cmd;
11449430SRaymond.Chen@Sun.COM
11459430SRaymond.Chen@Sun.COM if (client = uwba_find_cdev_by_channel(uwba_dev,
11469430SRaymond.Chen@Sun.COM rccb_startbc->bChannelNumber)) {
11479430SRaymond.Chen@Sun.COM rccb_startbc->wBPSTOffset = client->wBPSTOffset;
11489430SRaymond.Chen@Sun.COM }
11499430SRaymond.Chen@Sun.COM
11509430SRaymond.Chen@Sun.COM data_len = UWB_RAW_RCCB_HEAD_SIZE + 3; /* size of start beacon RCCB */
11519430SRaymond.Chen@Sun.COM
11529430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
11539430SRaymond.Chen@Sun.COM "uwb_do_cmd_start_beacon: channel= %d , BPSTOffset = %d",
11549430SRaymond.Chen@Sun.COM rccb_startbc->bChannelNumber, rccb_startbc->wBPSTOffset);
11559430SRaymond.Chen@Sun.COM /* Data block */
11569430SRaymond.Chen@Sun.COM if ((data = allocb(data_len, BPRI_HI)) == NULL) {
11579430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
11589430SRaymond.Chen@Sun.COM "uwb_do_cmd_start_beacon: allocb failed");
11599430SRaymond.Chen@Sun.COM
11609430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
11619430SRaymond.Chen@Sun.COM }
11629430SRaymond.Chen@Sun.COM
11639430SRaymond.Chen@Sun.COM uwba_fill_rccb_head(uwba_dev, rccb_startbc->rccb.wCommand, data);
11649430SRaymond.Chen@Sun.COM UINT16_TO_LE(rccb_startbc->wBPSTOffset, 4, data->b_rptr);
11659430SRaymond.Chen@Sun.COM data->b_rptr[6] = rccb_startbc->bChannelNumber;
11669430SRaymond.Chen@Sun.COM data->b_wptr += data_len;
11679430SRaymond.Chen@Sun.COM
11689430SRaymond.Chen@Sun.COM /* record the current cmd rccb to the uwb dev handle. */
11699430SRaymond.Chen@Sun.COM uwba_copy_rccb((uwb_rccb_cmd_t *)rccb_startbc, &(uwba_dev->curr_rccb));
11709430SRaymond.Chen@Sun.COM uwba_dev->curr_rccb.rccb.bCommandContext = data->b_rptr[3];
11719430SRaymond.Chen@Sun.COM if ((rval = uwba_dev->send_cmd(uwb_dev_hdl, data, data_len))
11729430SRaymond.Chen@Sun.COM != UWB_SUCCESS) {
11739430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
11749430SRaymond.Chen@Sun.COM "uwb_do_cmd_start_beacon: send_cmd failed, channel = %d,"
11759430SRaymond.Chen@Sun.COM "wBPSTOffset = %d", rccb_startbc->bChannelNumber,
11769430SRaymond.Chen@Sun.COM rccb_startbc->wBPSTOffset);
11779430SRaymond.Chen@Sun.COM
11789430SRaymond.Chen@Sun.COM return (rval);
11799430SRaymond.Chen@Sun.COM }
11809430SRaymond.Chen@Sun.COM
11819430SRaymond.Chen@Sun.COM return (rval);
11829430SRaymond.Chen@Sun.COM }
11839430SRaymond.Chen@Sun.COM
11849430SRaymond.Chen@Sun.COM /* Send rccb cmd and get the rceb result */
11859430SRaymond.Chen@Sun.COM static int
uwb_process_rccb_cmd_private(uwb_dev_handle_t uwb_dev_hdl,uwb_rccb_cmd_t * rccb_cmd,uwb_cmd_result_t * cmd_result)11869430SRaymond.Chen@Sun.COM uwb_process_rccb_cmd_private(uwb_dev_handle_t uwb_dev_hdl,
11879430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t *rccb_cmd, uwb_cmd_result_t *cmd_result)
11889430SRaymond.Chen@Sun.COM {
11899430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
11909430SRaymond.Chen@Sun.COM int rval = UWB_SUCCESS;
11919430SRaymond.Chen@Sun.COM
11929430SRaymond.Chen@Sun.COM if (uwb_check_dev_state(uwba_dev, rccb_cmd) != UWB_SUCCESS) {
11939430SRaymond.Chen@Sun.COM
11949430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
11959430SRaymond.Chen@Sun.COM "uwb_process_rccb_cmd_private: illegal dev_state:%d",
11969430SRaymond.Chen@Sun.COM uwba_dev->dev_state);
11979430SRaymond.Chen@Sun.COM
11989430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
11999430SRaymond.Chen@Sun.COM }
12009430SRaymond.Chen@Sun.COM
12019430SRaymond.Chen@Sun.COM
12029430SRaymond.Chen@Sun.COM
12039430SRaymond.Chen@Sun.COM if (uwb_rccb_cmd_enter(uwba_dev) != UWB_SUCCESS) {
12049430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
12059430SRaymond.Chen@Sun.COM "uwb_process_rccb_cmd_private: fail to enter"
12069430SRaymond.Chen@Sun.COM "wCommand = %d, %s ", rccb_cmd->rccb.wCommand,
12079430SRaymond.Chen@Sun.COM uwba_event_msg(rccb_cmd->rccb.wCommand));
12089430SRaymond.Chen@Sun.COM
12099430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
12109430SRaymond.Chen@Sun.COM }
12119430SRaymond.Chen@Sun.COM
12129430SRaymond.Chen@Sun.COM if ((rval = uwb_send_rccb_cmd(uwb_dev_hdl, rccb_cmd)) != UWB_SUCCESS) {
12139430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
12149430SRaymond.Chen@Sun.COM "uwb_process_rccb_cmd_private: fail to send"
12159430SRaymond.Chen@Sun.COM "wCommand = %d, %s ", rccb_cmd->rccb.wCommand,
12169430SRaymond.Chen@Sun.COM uwba_event_msg(rccb_cmd->rccb.wCommand));
12179430SRaymond.Chen@Sun.COM goto cleanup;
12189430SRaymond.Chen@Sun.COM }
12199430SRaymond.Chen@Sun.COM
12209430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
12219430SRaymond.Chen@Sun.COM /* Copy the command result to application */
12229430SRaymond.Chen@Sun.COM if (cmd_result) {
12239430SRaymond.Chen@Sun.COM bcopy(uwba_dev->cmd_result_wrap.cmd_result, cmd_result,
12249430SRaymond.Chen@Sun.COM uwba_dev->cmd_result_wrap.length);
12259430SRaymond.Chen@Sun.COM }
12269430SRaymond.Chen@Sun.COM /* release the command result (event) block. */
12279430SRaymond.Chen@Sun.COM uwb_free_cmd_result(uwb_dev_hdl);
12289430SRaymond.Chen@Sun.COM
12299430SRaymond.Chen@Sun.COM uwb_set_dev_state(uwba_dev, rccb_cmd);
12309430SRaymond.Chen@Sun.COM
12319430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
12329430SRaymond.Chen@Sun.COM
12339430SRaymond.Chen@Sun.COM cleanup:
12349430SRaymond.Chen@Sun.COM uwb_rccb_cmd_leave(uwba_dev);
12359430SRaymond.Chen@Sun.COM
12369430SRaymond.Chen@Sun.COM return (rval);
12379430SRaymond.Chen@Sun.COM }
12389430SRaymond.Chen@Sun.COM
12399430SRaymond.Chen@Sun.COM /* Call rccb handler to send a rccb cmd */
12409430SRaymond.Chen@Sun.COM static int
uwb_send_rccb_cmd(uwb_dev_handle_t uwb_dev_hdl,uwb_rccb_cmd_t * rccb_cmd)12419430SRaymond.Chen@Sun.COM uwb_send_rccb_cmd(uwb_dev_handle_t uwb_dev_hdl, uwb_rccb_cmd_t *rccb_cmd)
12429430SRaymond.Chen@Sun.COM {
12439430SRaymond.Chen@Sun.COM int rccb_index = rccb_cmd->rccb.wCommand - UWB_CE_CHANNEL_CHANGE;
12449430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
12459430SRaymond.Chen@Sun.COM ASSERT(rccb_cmd->rccb.bCommandType == UWB_CE_TYPE_GENERAL);
12469430SRaymond.Chen@Sun.COM
12479430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
12489430SRaymond.Chen@Sun.COM if (uwb_rccb_handler_tbl[rccb_index](uwb_dev_hdl, rccb_cmd)
12499430SRaymond.Chen@Sun.COM != UWB_SUCCESS) {
12509430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
12519430SRaymond.Chen@Sun.COM "uwb_send_rccb_cmd: uwb_send_rccb_cmd failed");
12529430SRaymond.Chen@Sun.COM goto failure;
12539430SRaymond.Chen@Sun.COM
12549430SRaymond.Chen@Sun.COM }
12559430SRaymond.Chen@Sun.COM if (uwb_wait_cmd_result(uwb_dev_hdl) != UWB_SUCCESS) {
12569430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
12579430SRaymond.Chen@Sun.COM "uwb_send_rccb_cmd: fail to get cmd result ");
12589430SRaymond.Chen@Sun.COM goto failure;
12599430SRaymond.Chen@Sun.COM }
12609430SRaymond.Chen@Sun.COM
12619430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
12629430SRaymond.Chen@Sun.COM
12639430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
12649430SRaymond.Chen@Sun.COM failure:
12659430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
12669430SRaymond.Chen@Sun.COM
12679430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
12689430SRaymond.Chen@Sun.COM
12699430SRaymond.Chen@Sun.COM }
12709430SRaymond.Chen@Sun.COM /* Check a rccb cmd */
12719430SRaymond.Chen@Sun.COM static int
uwb_check_rccb_cmd(uwb_dev_handle_t uwb_dev_hdl,uwb_rccb_cmd_t * rccb_cmd)12729430SRaymond.Chen@Sun.COM uwb_check_rccb_cmd(uwb_dev_handle_t uwb_dev_hdl, uwb_rccb_cmd_t *rccb_cmd)
12739430SRaymond.Chen@Sun.COM {
12749430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
12759430SRaymond.Chen@Sun.COM int rccb_index = rccb_cmd->rccb.wCommand - UWB_CE_CHANNEL_CHANGE;
12769430SRaymond.Chen@Sun.COM
12779430SRaymond.Chen@Sun.COM if (rccb_cmd->rccb.bCommandType != UWB_CE_TYPE_GENERAL) {
12789430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
12799430SRaymond.Chen@Sun.COM "uwb_check_rccb_cmd: invalid bCommandType = %d",
12809430SRaymond.Chen@Sun.COM rccb_cmd->rccb.bCommandType);
12819430SRaymond.Chen@Sun.COM
12829430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
12839430SRaymond.Chen@Sun.COM }
12849430SRaymond.Chen@Sun.COM if ((rccb_cmd->rccb.wCommand < UWB_CE_CHANNEL_CHANGE) ||
12859430SRaymond.Chen@Sun.COM (rccb_cmd->rccb.wCommand > UWB_CE_SET_ASIE_NOTIFICATION)) {
12869430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
12879430SRaymond.Chen@Sun.COM "uwb_check_rccb_cmd: invalid wCommand = %d",
12889430SRaymond.Chen@Sun.COM rccb_cmd->rccb.wCommand);
12899430SRaymond.Chen@Sun.COM
12909430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
12919430SRaymond.Chen@Sun.COM }
12929430SRaymond.Chen@Sun.COM if (uwb_rccb_handler_tbl[rccb_index] == UWB_RCCB_NULL_HANDLER) {
12939430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
12949430SRaymond.Chen@Sun.COM "uwb_send_rccb_cmd: unsupportted wCommand = %d",
12959430SRaymond.Chen@Sun.COM rccb_cmd->rccb.wCommand);
12969430SRaymond.Chen@Sun.COM
12979430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
12989430SRaymond.Chen@Sun.COM }
12999430SRaymond.Chen@Sun.COM
13009430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
13019430SRaymond.Chen@Sun.COM }
13029430SRaymond.Chen@Sun.COM
13039430SRaymond.Chen@Sun.COM /* Check the current dev state */
13049430SRaymond.Chen@Sun.COM static int
uwb_check_dev_state(uwba_dev_t * uwba_dev,uwb_rccb_cmd_t * rccb_cmd)13059430SRaymond.Chen@Sun.COM uwb_check_dev_state(uwba_dev_t *uwba_dev, uwb_rccb_cmd_t *rccb_cmd) {
13069430SRaymond.Chen@Sun.COM uint8_t state = uwba_dev->dev_state;
13079430SRaymond.Chen@Sun.COM
13089430SRaymond.Chen@Sun.COM switch (rccb_cmd->rccb.wCommand) {
13099430SRaymond.Chen@Sun.COM case UWB_CE_SCAN:
13109430SRaymond.Chen@Sun.COM if (((uwb_rccb_scan_t *)rccb_cmd)->bScanState
13119430SRaymond.Chen@Sun.COM == UWB_RC_SCAN_DISABLED) {
13129430SRaymond.Chen@Sun.COM if (state == UWB_STATE_SCAN) {
13139430SRaymond.Chen@Sun.COM
13149430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
13159430SRaymond.Chen@Sun.COM }
13169430SRaymond.Chen@Sun.COM } else {
13179430SRaymond.Chen@Sun.COM
13189430SRaymond.Chen@Sun.COM if (state == UWB_STATE_IDLE) {
13199430SRaymond.Chen@Sun.COM
13209430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
13219430SRaymond.Chen@Sun.COM }
13229430SRaymond.Chen@Sun.COM }
13239430SRaymond.Chen@Sun.COM break;
13249430SRaymond.Chen@Sun.COM
13259430SRaymond.Chen@Sun.COM case UWB_CE_START_BEACON:
13269430SRaymond.Chen@Sun.COM case UWB_CE_RESET:
13279430SRaymond.Chen@Sun.COM if (state == UWB_STATE_IDLE) {
13289430SRaymond.Chen@Sun.COM
13299430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
13309430SRaymond.Chen@Sun.COM }
13319430SRaymond.Chen@Sun.COM break;
13329430SRaymond.Chen@Sun.COM
13339430SRaymond.Chen@Sun.COM case UWB_CE_STOP_BEACON:
13349430SRaymond.Chen@Sun.COM if (state == UWB_STATE_BEACON) {
13359430SRaymond.Chen@Sun.COM
13369430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
13379430SRaymond.Chen@Sun.COM }
13389430SRaymond.Chen@Sun.COM break;
13399430SRaymond.Chen@Sun.COM
13409430SRaymond.Chen@Sun.COM default:
13419430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
13429430SRaymond.Chen@Sun.COM }
13439430SRaymond.Chen@Sun.COM
13449430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
13459430SRaymond.Chen@Sun.COM }
13469430SRaymond.Chen@Sun.COM /* Set the uwb dev state */
13479430SRaymond.Chen@Sun.COM static void
uwb_set_dev_state(uwba_dev_t * uwba_dev,uwb_rccb_cmd_t * rccb_cmd)13489430SRaymond.Chen@Sun.COM uwb_set_dev_state(uwba_dev_t *uwba_dev, uwb_rccb_cmd_t *rccb_cmd) {
13499430SRaymond.Chen@Sun.COM switch (rccb_cmd->rccb.wCommand) {
13509430SRaymond.Chen@Sun.COM case UWB_CE_SCAN:
13519430SRaymond.Chen@Sun.COM {
13529430SRaymond.Chen@Sun.COM uwb_rccb_scan_t *cmd =
13539430SRaymond.Chen@Sun.COM (uwb_rccb_scan_t *)rccb_cmd;
13549430SRaymond.Chen@Sun.COM if (cmd->bScanState == UWB_RC_SCAN_DISABLED) {
13559430SRaymond.Chen@Sun.COM
13569430SRaymond.Chen@Sun.COM uwba_dev->dev_state = UWB_STATE_IDLE;
13579430SRaymond.Chen@Sun.COM } else {
13589430SRaymond.Chen@Sun.COM
13599430SRaymond.Chen@Sun.COM uwba_dev->dev_state = UWB_STATE_SCAN;
13609430SRaymond.Chen@Sun.COM uwba_dev->channel = cmd->bChannelNumber;
13619430SRaymond.Chen@Sun.COM }
13629430SRaymond.Chen@Sun.COM }
13639430SRaymond.Chen@Sun.COM break;
13649430SRaymond.Chen@Sun.COM
13659430SRaymond.Chen@Sun.COM case UWB_CE_START_BEACON:
13669430SRaymond.Chen@Sun.COM {
13679430SRaymond.Chen@Sun.COM uwb_rccb_start_beacon_t *cmd =
13689430SRaymond.Chen@Sun.COM (uwb_rccb_start_beacon_t *)rccb_cmd;
13699430SRaymond.Chen@Sun.COM uwba_dev->dev_state = UWB_STATE_BEACON;
13709430SRaymond.Chen@Sun.COM uwba_dev->channel = cmd->bChannelNumber;
13719430SRaymond.Chen@Sun.COM }
13729430SRaymond.Chen@Sun.COM break;
13739430SRaymond.Chen@Sun.COM
13749430SRaymond.Chen@Sun.COM case UWB_CE_STOP_BEACON:
13759430SRaymond.Chen@Sun.COM case UWB_CE_RESET:
13769430SRaymond.Chen@Sun.COM
13779430SRaymond.Chen@Sun.COM uwba_dev->dev_state = UWB_STATE_IDLE;
13789430SRaymond.Chen@Sun.COM break;
13799430SRaymond.Chen@Sun.COM case UWB_CE_DEV_ADDR_MGMT:
13809430SRaymond.Chen@Sun.COM {
13819430SRaymond.Chen@Sun.COM uwb_rccb_dev_addr_mgmt_t *cmd =
13829430SRaymond.Chen@Sun.COM (uwb_rccb_dev_addr_mgmt_t *)rccb_cmd;
13839430SRaymond.Chen@Sun.COM if (cmd->bmOperationType == 1)
13849430SRaymond.Chen@Sun.COM {
13859430SRaymond.Chen@Sun.COM uwba_dev->dev_addr = cmd->baAddr[1];
13869430SRaymond.Chen@Sun.COM uwba_dev->dev_addr =
13879430SRaymond.Chen@Sun.COM uwba_dev->dev_addr <<8;
13889430SRaymond.Chen@Sun.COM uwba_dev->dev_addr =
13899430SRaymond.Chen@Sun.COM uwba_dev->dev_addr | cmd->baAddr[0];
13909430SRaymond.Chen@Sun.COM }
13919430SRaymond.Chen@Sun.COM }
13929430SRaymond.Chen@Sun.COM break;
13939430SRaymond.Chen@Sun.COM
13949430SRaymond.Chen@Sun.COM default:
13959430SRaymond.Chen@Sun.COM break;
13969430SRaymond.Chen@Sun.COM }
13979430SRaymond.Chen@Sun.COM
13989430SRaymond.Chen@Sun.COM }
13999430SRaymond.Chen@Sun.COM
14009430SRaymond.Chen@Sun.COM /* Handle rccb cmd for ioctl */
14019430SRaymond.Chen@Sun.COM static int
uwb_do_ioctl_rccb_cmd(uwb_dev_handle_t uwb_dev_hdl,uint16_t wCommand,intptr_t arg,int mode)14029430SRaymond.Chen@Sun.COM uwb_do_ioctl_rccb_cmd(uwb_dev_handle_t uwb_dev_hdl, uint16_t wCommand,
14039430SRaymond.Chen@Sun.COM intptr_t arg, int mode)
14049430SRaymond.Chen@Sun.COM {
14059430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
14069430SRaymond.Chen@Sun.COM int rv = UWB_FAILURE;
14079430SRaymond.Chen@Sun.COM
14089430SRaymond.Chen@Sun.COM int rccb_size = uwb_rccb_size_tbl[wCommand - UWB_CE_CHANNEL_CHANGE];
14099430SRaymond.Chen@Sun.COM uwb_rccb_cmd_t *rccb_cmd = NULL;
14109430SRaymond.Chen@Sun.COM
14119430SRaymond.Chen@Sun.COM if (uwb_rccb_cmd_enter(uwba_dev) != UWB_SUCCESS) {
14129430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
14139430SRaymond.Chen@Sun.COM "uwb_do_ioctl_rccb_cmd: enter cmd fail");
14149430SRaymond.Chen@Sun.COM
14159430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
14169430SRaymond.Chen@Sun.COM }
14179430SRaymond.Chen@Sun.COM rccb_cmd = kmem_alloc(rccb_size, KM_NOSLEEP);
14189430SRaymond.Chen@Sun.COM if (ddi_copyin((caddr_t)arg, rccb_cmd, rccb_size, mode)) {
14199430SRaymond.Chen@Sun.COM
14209430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
14219430SRaymond.Chen@Sun.COM "uwb_do_ioctl_rccb_cmd: ddi_copyin fail");
14229430SRaymond.Chen@Sun.COM
14239430SRaymond.Chen@Sun.COM goto cleanup;
14249430SRaymond.Chen@Sun.COM }
14259430SRaymond.Chen@Sun.COM
14269430SRaymond.Chen@Sun.COM if (uwb_check_dev_state(uwba_dev, rccb_cmd) != UWB_SUCCESS) {
14279430SRaymond.Chen@Sun.COM
14289430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
14299430SRaymond.Chen@Sun.COM "uwb_check_dev_state: illegal dev_state:%d",
14309430SRaymond.Chen@Sun.COM uwba_dev->dev_state);
14319430SRaymond.Chen@Sun.COM
14329430SRaymond.Chen@Sun.COM goto cleanup;
14339430SRaymond.Chen@Sun.COM }
14349430SRaymond.Chen@Sun.COM
14359430SRaymond.Chen@Sun.COM
14369430SRaymond.Chen@Sun.COM if ((uwb_send_rccb_cmd(uwb_dev_hdl, rccb_cmd)) != UWB_SUCCESS) {
14379430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
14389430SRaymond.Chen@Sun.COM "uwb_do_ioctl_rccb_cmd: fail to send wCommand = %d ",
14399430SRaymond.Chen@Sun.COM rccb_cmd->rccb.wCommand);
14409430SRaymond.Chen@Sun.COM
14419430SRaymond.Chen@Sun.COM goto cleanup;
14429430SRaymond.Chen@Sun.COM }
14439430SRaymond.Chen@Sun.COM
14449430SRaymond.Chen@Sun.COM /* Copy the command result to application */
14459430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
14469430SRaymond.Chen@Sun.COM if (ddi_copyout(uwba_dev->cmd_result_wrap.cmd_result, (caddr_t)arg,
14479430SRaymond.Chen@Sun.COM uwba_dev->cmd_result_wrap.length, mode)) {
14489430SRaymond.Chen@Sun.COM
14499430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_LOG,
14509430SRaymond.Chen@Sun.COM "uwb_do_ioctl_rccb_cmd: ddi_copyout fail");
14519430SRaymond.Chen@Sun.COM } else {
14529430SRaymond.Chen@Sun.COM rv = UWB_SUCCESS;
14539430SRaymond.Chen@Sun.COM }
14549430SRaymond.Chen@Sun.COM
14559430SRaymond.Chen@Sun.COM /* release the command result (event) block. */
14569430SRaymond.Chen@Sun.COM uwb_free_cmd_result(uwb_dev_hdl);
14579430SRaymond.Chen@Sun.COM
14589430SRaymond.Chen@Sun.COM uwb_set_dev_state(uwba_dev, rccb_cmd);
14599430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
14609430SRaymond.Chen@Sun.COM
14619430SRaymond.Chen@Sun.COM cleanup:
14629430SRaymond.Chen@Sun.COM uwb_rccb_cmd_leave(uwba_dev);
14639430SRaymond.Chen@Sun.COM kmem_free(rccb_cmd, rccb_size);
14649430SRaymond.Chen@Sun.COM
14659430SRaymond.Chen@Sun.COM return (rv);
14669430SRaymond.Chen@Sun.COM }
14679430SRaymond.Chen@Sun.COM
14689430SRaymond.Chen@Sun.COM /*
14699430SRaymond.Chen@Sun.COM * alloc evt block according to cmd code; alloc context id;
14709430SRaymond.Chen@Sun.COM * link the evt block to uwb_dev_hdl
14719430SRaymond.Chen@Sun.COM */
14729430SRaymond.Chen@Sun.COM static int
uwb_wait_cmd_result(uwb_dev_handle_t uwb_dev_hdl)14739430SRaymond.Chen@Sun.COM uwb_wait_cmd_result(uwb_dev_handle_t uwb_dev_hdl)
14749430SRaymond.Chen@Sun.COM {
14759430SRaymond.Chen@Sun.COM int rval = UWB_SUCCESS;
14769430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
14779430SRaymond.Chen@Sun.COM
14789430SRaymond.Chen@Sun.COM ASSERT(mutex_owned(&uwba_dev->dev_mutex));
14799430SRaymond.Chen@Sun.COM
14809430SRaymond.Chen@Sun.COM while (uwba_dev->cmd_result_wrap.cmd_result == NULL) {
14819430SRaymond.Chen@Sun.COM
14829430SRaymond.Chen@Sun.COM if (cv_timedwait_sig(&uwba_dev->cmd_result_cv,
14839430SRaymond.Chen@Sun.COM &uwba_dev->dev_mutex, UWB_CMD_TIMEOUT) <= 0) {
14849430SRaymond.Chen@Sun.COM
14859430SRaymond.Chen@Sun.COM /* no cmd result is received and cv is signaled */
14869430SRaymond.Chen@Sun.COM rval = UWB_FAILURE;
14879430SRaymond.Chen@Sun.COM
14889430SRaymond.Chen@Sun.COM return (rval);
14899430SRaymond.Chen@Sun.COM }
14909430SRaymond.Chen@Sun.COM uwba_log(uwba_dev, UWBA_LOG_DEBUG,
14919430SRaymond.Chen@Sun.COM "uwb_wait_cmd_result: wait for cmd complete end, "
14929430SRaymond.Chen@Sun.COM "cv_signal received.");
14939430SRaymond.Chen@Sun.COM }
14949430SRaymond.Chen@Sun.COM ASSERT(uwba_dev->cmd_result_wrap.cmd_result != NULL);
14959430SRaymond.Chen@Sun.COM
14969430SRaymond.Chen@Sun.COM return (rval);
14979430SRaymond.Chen@Sun.COM }
14989430SRaymond.Chen@Sun.COM
14999430SRaymond.Chen@Sun.COM static void
uwb_free_cmd_result(uwb_dev_handle_t uwb_dev_hdl)15009430SRaymond.Chen@Sun.COM uwb_free_cmd_result(uwb_dev_handle_t uwb_dev_hdl)
15019430SRaymond.Chen@Sun.COM {
15029430SRaymond.Chen@Sun.COM uwba_dev_t *uwba_dev = (uwba_dev_t *)uwb_dev_hdl;
15039430SRaymond.Chen@Sun.COM
15049430SRaymond.Chen@Sun.COM
15059430SRaymond.Chen@Sun.COM ASSERT(mutex_owned(&uwba_dev->dev_mutex));
15069430SRaymond.Chen@Sun.COM
15079430SRaymond.Chen@Sun.COM kmem_free(uwba_dev->cmd_result_wrap.cmd_result,
15089430SRaymond.Chen@Sun.COM uwba_dev->cmd_result_wrap.length);
15099430SRaymond.Chen@Sun.COM uwba_dev->cmd_result_wrap.cmd_result = NULL;
15109430SRaymond.Chen@Sun.COM uwba_dev->cmd_result_wrap.length = 0;
15119430SRaymond.Chen@Sun.COM uwba_free_ctxt_id(uwba_dev, uwba_dev->ctxt_id);
15129430SRaymond.Chen@Sun.COM }
15139430SRaymond.Chen@Sun.COM
15149430SRaymond.Chen@Sun.COM /* Get notif for ioctl */
15159430SRaymond.Chen@Sun.COM static uwb_notif_wrapper_t *
uwb_get_notification(uwb_dev_handle_t uwb_dev_hdl,intptr_t arg,int mode)15169430SRaymond.Chen@Sun.COM uwb_get_notification(uwb_dev_handle_t uwb_dev_hdl,
15179430SRaymond.Chen@Sun.COM intptr_t arg, int mode)
15189430SRaymond.Chen@Sun.COM {
15199430SRaymond.Chen@Sun.COM uwb_notif_wrapper_t *notif;
15209430SRaymond.Chen@Sun.COM uwb_notif_get_t ng;
15219430SRaymond.Chen@Sun.COM
15229430SRaymond.Chen@Sun.COM
15239430SRaymond.Chen@Sun.COM if (ddi_copyin((caddr_t)arg, &ng, sizeof (ng), mode)) {
15249430SRaymond.Chen@Sun.COM
15259430SRaymond.Chen@Sun.COM return (NULL);
15269430SRaymond.Chen@Sun.COM }
15279430SRaymond.Chen@Sun.COM if (ng.notif.rceb.bEventType != UWB_CE_TYPE_GENERAL) {
15289430SRaymond.Chen@Sun.COM
15299430SRaymond.Chen@Sun.COM return (NULL);
15309430SRaymond.Chen@Sun.COM }
15319430SRaymond.Chen@Sun.COM
15329430SRaymond.Chen@Sun.COM notif = uwb_get_notif_head(uwb_dev_hdl);
15339430SRaymond.Chen@Sun.COM
15349430SRaymond.Chen@Sun.COM return (notif);
15359430SRaymond.Chen@Sun.COM }
15369430SRaymond.Chen@Sun.COM /* Free a notif from notificatin list */
15379430SRaymond.Chen@Sun.COM static void
uwb_free_notification(uwb_notif_wrapper_t * nw)15389430SRaymond.Chen@Sun.COM uwb_free_notification(uwb_notif_wrapper_t *nw)
15399430SRaymond.Chen@Sun.COM {
15409430SRaymond.Chen@Sun.COM ASSERT(nw->notif);
15419430SRaymond.Chen@Sun.COM
15429430SRaymond.Chen@Sun.COM kmem_free(nw->notif, nw->length);
15439430SRaymond.Chen@Sun.COM kmem_free(nw, sizeof (uwb_notif_wrapper_t));
15449430SRaymond.Chen@Sun.COM }
15459430SRaymond.Chen@Sun.COM /* uwb rccb cmd handler lock */
15469430SRaymond.Chen@Sun.COM static int
uwb_rccb_cmd_enter(uwba_dev_t * uwba_dev)15479430SRaymond.Chen@Sun.COM uwb_rccb_cmd_enter(uwba_dev_t *uwba_dev)
15489430SRaymond.Chen@Sun.COM {
15499430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
15509430SRaymond.Chen@Sun.COM while (uwba_dev->cmd_busy == B_TRUE) {
15519430SRaymond.Chen@Sun.COM if (cv_wait_sig(&uwba_dev->cmd_handler_cv,
15529430SRaymond.Chen@Sun.COM &uwba_dev->dev_mutex) <= 0) {
15539430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
15549430SRaymond.Chen@Sun.COM
15559430SRaymond.Chen@Sun.COM return (UWB_FAILURE);
15569430SRaymond.Chen@Sun.COM }
15579430SRaymond.Chen@Sun.COM }
15589430SRaymond.Chen@Sun.COM uwba_dev->cmd_busy = B_TRUE;
15599430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
15609430SRaymond.Chen@Sun.COM
15619430SRaymond.Chen@Sun.COM return (UWB_SUCCESS);
15629430SRaymond.Chen@Sun.COM }
15639430SRaymond.Chen@Sun.COM /* uwb rccb cmd handler unlock */
15649430SRaymond.Chen@Sun.COM static void
uwb_rccb_cmd_leave(uwba_dev_t * uwba_dev)15659430SRaymond.Chen@Sun.COM uwb_rccb_cmd_leave(uwba_dev_t *uwba_dev)
15669430SRaymond.Chen@Sun.COM {
15679430SRaymond.Chen@Sun.COM mutex_enter(&uwba_dev->dev_mutex);
15689430SRaymond.Chen@Sun.COM uwba_dev->cmd_busy = B_FALSE;
15699430SRaymond.Chen@Sun.COM cv_signal(&uwba_dev->cmd_handler_cv);
15709430SRaymond.Chen@Sun.COM mutex_exit(&uwba_dev->dev_mutex);
15719430SRaymond.Chen@Sun.COM }
1572