📄 wmi.c
字号:
A_STATUS
wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
A_BOOL set)
{
void *osbuf;
WMI_SET_PMKID_CMD *cmd;
if (bssid == NULL) {
return A_EINVAL;
}
if ((set == TRUE) && (pmkId == NULL)) {
return A_EINVAL;
}
osbuf = a_netbuf_alloc(sizeof(*cmd));
if (osbuf == NULL) {
return A_NO_MEMORY;
}
a_netbuf_put(osbuf, sizeof(*cmd));
cmd = (WMI_SET_PMKID_CMD *)(a_netbuf_to_data(osbuf));
A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
if (set == TRUE) {
A_MEMCPY(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
cmd->enable = PMKID_ENABLE;
} else {
A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
cmd->enable = PMKID_DISABLE;
}
return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
}
A_STATUS
wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en)
{
void *osbuf;
WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
osbuf = a_netbuf_alloc(sizeof(*cmd));
if (osbuf == NULL) {
return A_NO_MEMORY;
}
a_netbuf_put(osbuf, sizeof(*cmd));
cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(a_netbuf_to_data(osbuf));
cmd->cm_en = (en == TRUE)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
NO_SYNC_WMIFLAG));
}
A_STATUS
wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, int endPoint)
{
WMI_DATA_HDR *dtHdr;
AR_DEBUG_ASSERT(endPoint != WMI_CONTROL_MBOX);
AR_DEBUG_ASSERT(osbuf != NULL);
if (a_netbuf_push(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
return A_NO_MEMORY;
}
dtHdr = (WMI_DATA_HDR *)a_netbuf_to_data(osbuf);
#ifndef AR6K_FIRMWARE_1_0
dtHdr->rssi = 0;
#else
dtHdr->reserved1 = 0;
#endif
WMI_DATA_HDR_SET_MSG_TYPE( dtHdr, SYNC_MSGTYPE);
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi sync pkt sent on mbox %d\n", endPoint);
return (ar6000_control_tx(wmip->wmi_devt, osbuf, endPoint));
}
static A_STATUS
wmi_sync_point(struct wmi_t *wmip)
{
void *cmd_osbuf, *be_osbuf, *pri_osbuf[WMI_MAX_NUM_PRI_STREAMS];
A_UINT8 i;
A_STATUS status;
WMI_DEBUG_PRINTF(ATH_LOG_INF,"wmi_sync_point\n");
/*
* We allocate all network buffers needed so we will be able to
* send all required frames.
*/
cmd_osbuf = a_netbuf_alloc(0); /* no payload */
if (cmd_osbuf == NULL) {
return A_NO_MEMORY;
}
be_osbuf = a_netbuf_alloc(0); /* no payload */
if (be_osbuf == NULL) {
a_netbuf_free(cmd_osbuf);
return A_NO_MEMORY;
}
for (i = 0; i < wmip->wmi_numQoSStream; i++) {
pri_osbuf[i] = a_netbuf_alloc(0); /* no payload */
if (pri_osbuf[i] == NULL) {
A_UINT8 j;
a_netbuf_free(be_osbuf);
a_netbuf_free(cmd_osbuf);
/* free previously allocated bufs */
for (j = 0; j < i; j++) {
a_netbuf_free(pri_osbuf[j]);
}
return A_NO_MEMORY;
}
}
/*
* Send sync cmd followed by sync data messages on all endpoints being
* used
*/
status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
NO_SYNC_WMIFLAG);
if (status == A_OK) {
status = wmi_dataSync_send(wmip, be_osbuf, WMI_BEST_EFFORT_MBOX);
}
if (status == A_OK) {
A_UINT8 priIndex = 0;
for (i = 0; i < wmip->wmi_numQoSStream; i++) {
while (priIndex < WMI_MAX_NUM_PRI_STREAMS &&
(!wmip->wmi_priority[priIndex].inUse)) {
priIndex++;
}
if (priIndex >= WMI_MAX_NUM_PRI_STREAMS) {
break;
}
status = wmi_dataSync_send(wmip, pri_osbuf[i], wmip->wmi_priority[priIndex].mbox);
if (status != A_OK) {
break;
}
priIndex++;
}
}
return (status);
}
A_STATUS
wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
{
void *osbuf;
WMI_CREATE_PSTREAM_CMD *cmd;
#ifndef AR6K_FIRMWARE_1_0
/* Validate all the parameters. */
if( !((params->userPriority < 8) &&
(params->trafficDirection == BIDIR_TRAFFIC ||
params->trafficDirection == UPLINK_TRAFFIC ||
params->trafficDirection == DNLINK_TRAFFIC ) &&
(params->userPriority <= 0x7) &&
(params->trafficClass != WMM_AC_BE) &&
(params->trafficType == TRAFFIC_TYPE_APERIODIC ||
params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
(params->voicePSCapability == DISABLE_FOR_THIS_AC ||
params->voicePSCapability == ENABLE_FOR_THIS_AC ||
params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
(params->tsid < 15)) )
{
return A_EINVAL;
}
#endif
if (params->trafficDirection == BIDIR_TRAFFIC) {
if (wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][params->trafficClass]
|| wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][params->trafficClass]
|| wmip->wmi_cpstreamCmdInProgress) {
WMI_DEBUG_PRINTF(ATH_LOG_ERR,"create %d too busy !\n",params->trafficClass);
return A_EBUSY;
}
wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][params->trafficClass] = TRUE;
wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][params->trafficClass] = TRUE;
} else {
if (wmip->wmi_pstreamCmdInProgress[params->trafficDirection][params->trafficClass]
|| wmip->wmi_cpstreamCmdInProgress) {
WMI_DEBUG_PRINTF(ATH_LOG_ERR,"create %d too busy !\n",params->trafficClass);
return A_EBUSY;
}
wmip->wmi_pstreamCmdInProgress[params->trafficDirection][params->trafficClass] = TRUE;
}
osbuf = a_netbuf_alloc(sizeof(*cmd));
if (osbuf == NULL) {
return A_NO_MEMORY;
}
wmip->wmi_cpstreamCmdInProgress = TRUE;
a_netbuf_put(osbuf, sizeof(*cmd));
WMI_DEBUG_PRINTF(ATH_LOG_INF,"Sending create_pstream_cmd: ac=%d, rxQ=%d, dir=%d\n",
params->trafficClass, params->rxQueueNum, params->trafficDirection);
cmd = (WMI_CREATE_PSTREAM_CMD *)(a_netbuf_to_data(osbuf));
A_MEMZERO(cmd, sizeof(*cmd));
A_MEMCPY(cmd, params, sizeof(*cmd));
if (params->rxQueueNum == 0xFF) {
if(wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][params->trafficClass] != WMI_NOT_MAPPED)
cmd->rxQueueNum = wmip->wmi_trafficClassMap[DNLINK_TRAFFIC][params->trafficClass];
else
cmd->rxQueueNum = wmip->wmi_olderPriRxMbox;
} else {
cmd->rxQueueNum = params->rxQueueNum;
}
/* mike: should be SYNC_BEFORE_WMIFLAG */
return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
NO_SYNC_WMIFLAG));
}
A_STATUS
wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 txQueueNumber, A_UINT8 rxQueueNumber, A_UINT8 dir)
{
void *osbuf;
WMI_DELETE_PSTREAM_CMD *cmd;
A_STATUS status;
A_UINT8 class;
osbuf = a_netbuf_alloc(sizeof(*cmd));
if (osbuf == NULL) {
return A_NO_MEMORY;
}
if (dir == BIDIR_TRAFFIC) {
class = wmip->wmi_mboxMap[UPLINK_TRAFFIC][txQueueNumber].trafficClass;
if (wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][class]
|| wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][class]) {
return A_EBUSY;
}
wmip->wmi_pstreamCmdInProgress[UPLINK_TRAFFIC][class] = TRUE;
wmip->wmi_pstreamCmdInProgress[DNLINK_TRAFFIC][class] = TRUE;
} else {
if (dir == UPLINK_TRAFFIC) {
class = wmip->wmi_mboxMap[UPLINK_TRAFFIC][txQueueNumber].trafficClass;
} else {
class = wmip->wmi_mboxMap[DNLINK_TRAFFIC][rxQueueNumber].trafficClass;
}
if (wmip->wmi_pstreamCmdInProgress[dir][class]) {
return A_EBUSY;
}
wmip->wmi_pstreamCmdInProgress[dir][class] = TRUE;
}
a_netbuf_put(osbuf, sizeof(*cmd));
cmd = (WMI_DELETE_PSTREAM_CMD *)(a_netbuf_to_data(osbuf));
A_MEMZERO(cmd, sizeof(*cmd));
cmd->txQueueNumber = txQueueNumber;
cmd->rxQueueNumber = rxQueueNumber;
cmd->trafficDirection = dir;
cmd->trafficClass = class;
WMI_DEBUG_PRINTF(ATH_LOG_INF,"Sending delete_pstream_cmd: txQ=%d, rxQ=%d, dir=%d\n",
txQueueNumber, rxQueueNumber, dir);
status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
(dir == UPLINK_TRAFFIC || dir == BIDIR_TRAFFIC) ? SYNC_BEFORE_WMIFLAG : NO_SYNC_WMIFLAG));
if (class != WMM_AC_BE) {
/* Update internal states */
if (dir == UPLINK_TRAFFIC || dir == BIDIR_TRAFFIC) {
wmip->wmi_numQoSStream--;
ar6000_set_numdataendpts(wmip->wmi_devt, wmip->wmi_numQoSStream+1);
wmip->wmi_priority[wmip->wmi_mboxMap[UPLINK_TRAFFIC][txQueueNumber].priorityNum].inUse = 0;
wmip->wmi_trafficClassMap[UPLINK_TRAFFIC][class] = WMI_NOT_MAPPED;
wmip->wmi_mboxMap[UPLINK_TRAFFIC][txQueueNumber].priorityNum = WMI_NOT_MAPPED;
wmip->wmi_mboxMap[UPLINK_TRAFFIC][txQueueNumber].trafficClass = WMM_AC_BE;
}
}
return status;
}
/*
* used to set the bit rate. rate is in Kbps. If rate == -1
* then auto selection is used.
*/
A_STATUS
wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 rate)
{
void *osbuf;
WMI_BIT_RATE_CMD *cmd;
A_INT8 i;
if (rate != -1) {
for (i=0;;i++) {
if (wmi_rateTable[i] == 0) {
return A_EINVAL;
}
if (wmi_rateTable[i] == rate) {
break;
}
}
} else {
i = -1;
}
osbuf = a_netbuf_alloc(sizeof(*cmd));
if (osbuf == NULL) {
return A_NO_MEMORY;
}
a_netbuf_put(osbuf, sizeof(*cmd));
cmd = (WMI_BIT_RATE_CMD *)(a_netbuf_to_data(osbuf));
A_MEMZERO(cmd, sizeof(*cmd));
cmd->rateIndex = i;
return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
}
A_STATUS
wmi_get_bitrate_cmd(struct wmi_t *wmip)
{
void *osbuf;
osbuf = a_netbuf_alloc(0); /* no payload */
if (osbuf == NULL) {
return A_NO_MEMORY;
}
return (wmi_cmd_send(wmip, osbuf, WMI_GET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
}
A_STATUS
wmi_get_channelList_cmd(struct wmi_t *wmip)
{
void *osbuf;
osbuf = a_netbuf_alloc(0); /* no payload */
if (osbuf == NULL) {
return A_NO_MEMORY;
}
return (wmi_cmd_send(wmip, osbuf, WMI_GET_CHANNEL_LIST_CMDID,
NO_SYNC_WMIFLAG));
}
/*
* used to generate a wmi sey channel Parameters cmd.
* mode should always be specified and corresponds to the phy mode of the
* wlan.
* numChan should alway sbe specified. If zero indicates that all available
* channels should be used.
* channelList is an array of channel frequencies (in Mhz) which the radio
* should limit its operation to. It should be NULL if numChan == 0. Size of
* array should correspond to numChan entries.
*/
A_STATUS
wmi_set_channelParams_cmd(struct wmi_t *wmip, WMI_PHY_MODE mode, A_INT8 numChan,
A_UINT16 *channelList)
{
void *osbuf;
WMI_CHANNEL_PARAMS_CMD *cmd;
A_INT8 size;
if ((mode <= WMI_MIN_PHY_MODE) || (mode >= WMI_MAX_PHY_MODE)) {
return A_EINVAL;
}
size = sizeof (*cmd);
if (numChan) {
if (numChan > WMI_MAX_CHANNELS) {
return A_EINVAL;
}
size += sizeof(A_UINT16) * (numChan - 1);
}
osbuf = a_netbuf_alloc(size);
if (osbuf == NULL) {
return A_NO_MEMORY;
}
a_netbuf_put(osbuf, size);
cmd = (WMI_CHANNEL_PARAMS_CMD *)(a_netbuf_to_data(osbuf));
A_MEMZERO(cmd, size);
cmd->phyMode = mode;
cmd->numChannels = numChan;
A_MEMCPY(cmd->channelList, channelList, numChan * sizeof(A_UINT16));
return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
NO_SYNC_WMIFLAG));
}
A_STATUS
wmi_set_link_threshold_params(struct wmi_t *wmip,
A_UINT8 highThreshold_upperVal,
A_UINT8 highThreshold_lowerVal,
A_UINT8 lowThreshold_upperVal,
A_UINT8 lowThreshold_lowerVal,
A_UINT32 pollTime)
{
void *osbuf;
A_INT8 size;
WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
/* These values are in ascending order */
if( highThreshold_upperVal <= highThreshold_lowerVal ||
lowThreshold_upperVal <= lowThreshold_lowerVal ||
highThreshold_lowerVal <= lowThreshold_upperVal)
return A_EINVAL;
size = sizeof (*cmd);
osbuf = a_netbuf_alloc(size);
if (osbuf == NULL) {
return A_NO_MEMORY;
}
a_netbuf_put(osbuf, size);
cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(a_netbuf_to_data(osbuf));
A_MEMZERO(cmd, size);
cmd->highThreshold_upperVal = highThreshold_upperVal;
cmd->highThreshold_lowerVal = highThreshold_lowerVal;
cmd->lowThreshold_upperVal = lowThreshold_upperVal;
cmd->lowThreshold_lowerVal = lowThreshold_lowerV
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -