Files
Linux_Drivers/osdrv/extdrv/wireless/mediatek/mt7603/ap/ap_nps.c
forum_service 213c880673 add driver of tp、wiegand-gpio and wireless
Change-Id: Ie3c11d9d85cf1a05042f5690ac711856fe8b1ad7
2023-12-22 09:56:05 +08:00

484 lines
12 KiB
C

/****************************************************************************
* Ralink Tech Inc.
* 4F, No. 2 Technology 5th Rd.
* Science-based Industrial Park
* Hsin-chu, Taiwan, R.O.C.
* (c) Copyright 2002, Ralink Technology, Inc.
*
* All rights reserved. Ralink's source code is an unpublished work and the
* use of a copyright notice does not imply otherwise. This source code
* contains confidential trade secret material of Ralink Tech. Any attemp
* or participation in deciphering, decoding, reverse engineering or in any
* way altering the source code is stricitly prohibited, unless the prior
* written consent of Ralink Technology, Inc. is obtained.
****************************************************************************
Module Name:
ap_nps.c
Abstract:
IEEE 802.11v NPS SoftAP related function
Revision History:
Who When What
-------- ---------- ----------------------------------------------
Carter Chen 08-23-2013 created for 7603 AP
*/
#ifdef MT_MAC
#include "rt_config.h"
extern VOID write_tmac_info_tim(RTMP_ADAPTER *pAd, INT apidx, UCHAR *tmac_buf, HTTRANSMIT_SETTING *BeaconTransmit, ULONG frmLen);
BOOLEAN TimTransmitRequired(RTMP_ADAPTER *pAd, INT apidx, BSS_STRUCT *pMbss)
{
BOOLEAN result = FALSE;
TIM_BUF_STRUC *tim_info;
tim_info = &pMbss->tim_buf;
if (tim_info->TimBufIdx >= HW_BEACON_MAX_NUM)
return result;
if (tim_info->bTimSntReq == TRUE)
{
result = TRUE;
}
return result;
}
#ifdef MT_MAC
VOID RT28xx_UpdateTimToAsic(
IN RTMP_ADAPTER *pAd,
IN INT apidx,
IN ULONG FrameLen)
{
TIM_BUF_STRUC *tim_buf = NULL;
UCHAR *buf;
INT len;
PNDIS_PACKET *pkt = NULL;
IF_DEV_CONFIG_OPMODE_ON_AP(pAd) {
tim_buf = &pAd->ApCfg.MBSSID[apidx].tim_buf;
}
if (!tim_buf) {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): bcn_buf is NULL!\n", __FUNCTION__));
return;
}
pkt = tim_buf->TimPkt;
if (pkt) {
buf = (UCHAR *)GET_OS_PKT_DATAPTR(pkt);
len = FrameLen + pAd->chipCap.tx_hw_hdr_len;
SET_OS_PKT_LEN(pkt, len);
/* Now do hardware-depened kick out.*/
RTMP_SEM_LOCK(&pAd->BcnRingLock);
HAL_KickOutMgmtTx(pAd, Q_IDX_BCN, pkt, buf, len);
RTMP_SEM_UNLOCK(&pAd->BcnRingLock);
} else {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): TimPkt is NULL!\n", __FUNCTION__));
}
}
#if 0
VOID RT28xx_UpdateTim2ToAsic(
IN RTMP_ADAPTER *pAd,
IN INT apidx,
IN ULONG FrameLen)
{
TIM_BUF_STRUC *tim_buf = NULL;
UCHAR *buf, *hdr;
INT len;
PNDIS_PACKET *pkt = NULL;
IF_DEV_CONFIG_OPMODE_ON_AP(pAd) {
tim_buf = &pAd->ApCfg.MBSSID[apidx].tim_buf;
}
if (!tim_buf) {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): bcn_buf is NULL!\n", __FUNCTION__));
return;
}
pkt = tim_buf->TimPkt2;
if (pkt) {
buf = (UCHAR *)GET_OS_PKT_DATAPTR(pkt);
len = FrameLen + pAd->chipCap.tx_hw_hdr_len;
SET_OS_PKT_LEN(pkt, len);
/* Now do hardware-depened kick out.*/
RTMP_SEM_LOCK(&pAd->BcnRingLock);
HAL_KickOutMgmtTx(pAd, Q_IDX_BCN, pkt, buf, len);
RTMP_SEM_UNLOCK(&pAd->BcnRingLock);
} else {
DBGPRINT(RT_DEBUG_ERROR, ("%s(): TimPkt2 is NULL!\n", __FUNCTION__));
}
}
#endif
#endif /* MT_MAC */
VOID write_tmac_info_tim(RTMP_ADAPTER *pAd, INT apidx, UCHAR *tmac_buf, HTTRANSMIT_SETTING *BeaconTransmit, ULONG frmLen)
{
MAC_TX_INFO mac_info;
NdisZeroMemory((UCHAR *)&mac_info, sizeof(mac_info));
mac_info.FRAG = FALSE;
mac_info.CFACK = FALSE;
mac_info.InsTimestamp = FALSE;
mac_info.AMPDU = FALSE;
mac_info.BM = 1;
mac_info.Ack = FALSE;
mac_info.NSeq = TRUE;
mac_info.BASize = 0;
mac_info.WCID = 0;
mac_info.Length = frmLen;
mac_info.PID = PID_MGMT;
mac_info.TID = 0;
mac_info.TxRate = 0;
mac_info.Txopmode = IFS_HTTXOP;
mac_info.q_idx = Q_IDX_BCN;
mac_info.hdr_len = 24;
mac_info.bss_idx = (UCHAR)apidx;
mac_info.SpeEn = 1;
mac_info.Preamble = LONG_PREAMBLE;
write_tmac_info(pAd, tmac_buf, &mac_info, BeaconTransmit);
}
VOID APMakeBssTimFrame(RTMP_ADAPTER *pAd, INT apidx)
{
BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx];
HEADER_802_11 TimHdr;
LARGE_INTEGER FakeTimestamp;
ULONG FrameLen = 0;
UCHAR *pTimFrame, *ptr, *tmac_info;
HTTRANSMIT_SETTING TimTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at HT rate. */
//UINT8 TXWISize = pAd->chipCap.TXWISize;
UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len;
UCHAR Cat = 11;//Tim Category field
UCHAR Act = 0;//Tim Action field
UCHAR ChkBcn = 0;//Check Beacon field init from 0.
//UCHAR *pTim;
//UCHAR ID_1B, TimFirst, TimLast;
//UINT i;
if(!TimTransmitRequired(pAd, apidx, pMbss))
return;
if (pMbss->tim_buf.TimPkt == NULL) {
DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid TimPkt for MBSS[%d]\n",
__func__, apidx));
return;
}
tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->tim_buf.TimPkt);
pTimFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len);
ActHeaderInit(pAd,
&TimHdr,
BROADCAST_ADDR,
pMbss->wdev.if_addr,
pMbss->wdev.bssid);
MakeOutgoingFrame(pTimFrame, &FrameLen,
sizeof(HEADER_802_11), &TimHdr,
1, &Cat,
1, &Act,
1, &ChkBcn,
TIMESTAMP_LEN, &FakeTimestamp,
END_OF_ARGS);
TimTransmit.word = 0;
pMbss->TimIELocationInTim = (UCHAR)FrameLen;
/*
step 2 - update TIM IE
TODO: enlarge TIM bitmap to support up to 64 STAs
TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time
*/
ptr = pTimFrame + (UCHAR)FrameLen;
*ptr = IE_TIM;
*(ptr+1) = 0x0e;
*(ptr + 2) = pAd->ApCfg.DtimCount;
*(ptr + 3) = pAd->ApCfg.DtimPeriod;
*(ptr + 4) = 0xa0;
*(ptr + 5) = 0xa0;
*(ptr + 6) = 0xa0;
*(ptr + 7) = 0xa0;
*(ptr + 8) = 0xa0;
*(ptr + 9) = 0xa0;
*(ptr + 10) = 0xa0;
*(ptr + 11) = 0xa0;
*(ptr + 12) = 0xa0;
*(ptr + 13) = 0xa0;
*(ptr + 14) = 0xa0;
*(ptr + 15) = 0xa0;
// /* find the smallest AID (PS mode) */
// TimFirst = 0; /* record first TIM byte != 0x00 */
// TimLast = 0; /* record last TIM byte != 0x00 */
// pTim = pMbss->TimBitmaps;
//
// for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++)
// {
// /* get the TIM indicating PS packets for 8 stations */
// UCHAR tim_1B = pTim[ID_1B];
//
// if (ID_1B == 0)
// tim_1B &= 0xfe; /* skip bit0 bc/mc */
//
// if (tim_1B == 0)
// continue; /* find next 1B */
//
// if (TimFirst == 0)
// TimFirst = ID_1B;
//
// TimLast = ID_1B;
// }
//
// /* fill TIM content to beacon buffer */
// if (TimFirst & 0x01)
// TimFirst --; /* find the even offset byte */
//
// *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */
// *(ptr + 4) = TimFirst;
//
// for(i=TimFirst; i<=TimLast; i++)
// *(ptr + 5 + i - TimFirst) = pTim[i];
//
// /* bit0 means backlogged mcast/bcast */
// /* per spec, this bit in TIM frame shall always 0. */
// //TODO: MTK proprietary mechanism.
// //if (pAd->ApCfg.DtimCount == 0)
// //*(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01);
// *(ptr + 4) = 0;
/* adjust TIM length according to the new TIM */
FrameLen += 16;//(2 + *(ptr+1));
/* When Beacon is use CCK to send, TIM shall use OFDM to send. and it's mandatory. */
if (pAd->CommonCfg.Channel <= 14) {
TimTransmit.field.MODE = MODE_OFDM;
TimTransmit.field.MCS = MCS_RATE_6;
}
write_tmac_info_tim(pAd, apidx, tmac_info, &TimTransmit, FrameLen);
// asic_write_bcn_buf(pAd,
// tmac_info, TXWISize,
// pTimFrame, FrameLen,
// pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]);
RT28xx_UpdateTimToAsic(pAd, apidx, FrameLen);
//+++Add by shiang for debug
DBGPRINT(RT_DEBUG_OFF, ("%s(): Dump the Beacon Packet of BSS%d!\n", __FUNCTION__, apidx));
hex_dump("Initial BeaconBuf", tmac_info, FrameLen + tx_hw_hdr_len);
//---Add by shiang for debug
}
#if 0
VOID APMakeBssTimFrame2(RTMP_ADAPTER *pAd, INT apidx)
{
BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx];
HEADER_802_11 TimHdr;
LARGE_INTEGER FakeTimestamp;
ULONG FrameLen = 0;
UCHAR *pTimFrame, *ptr, *tmac_info;
HTTRANSMIT_SETTING TimTransmit = {.word = 0}; /* MGMT frame PHY rate setting when operatin at HT rate. */
UINT8 TXWISize = pAd->chipCap.TXWISize;
UINT8 tx_hw_hdr_len = pAd->chipCap.tx_hw_hdr_len;
UCHAR Cat = 11;//Tim Category field
UCHAR Act = 0;//Tim Action field
UCHAR ChkBcn = 0;//Check Beacon field init from 0.
UCHAR *pTim;
UCHAR ID_1B, TimFirst, TimLast;
UINT i;
if(!TimTransmitRequired(pAd, apidx, pMbss)) {
DBGPRINT(RT_DEBUG_OFF, ("%s, apidx = %d\n", __func__, apidx));
return;
}
if (pMbss->tim_buf.TimPkt2 == NULL) {
DBGPRINT(RT_DEBUG_ERROR, ("%s():Invalid TimPkt2 for MBSS[%d]\n",
__func__, apidx));
return;
}
tmac_info = (UCHAR *)GET_OS_PKT_DATAPTR(pMbss->tim_buf.TimPkt2);
pTimFrame = (UCHAR *)(tmac_info + tx_hw_hdr_len);
ActHeaderInit(pAd,
&TimHdr,
BROADCAST_ADDR,
pMbss->wdev.if_addr,
pMbss->wdev.bssid);
MakeOutgoingFrame(pTimFrame, &FrameLen,
sizeof(HEADER_802_11), &TimHdr,
1, &Cat,
1, &Act,
1, &ChkBcn,
TIMESTAMP_LEN, &FakeTimestamp,
END_OF_ARGS);
TimTransmit.word = 0;
pMbss->TimIELocationInTim = (UCHAR)FrameLen;
/*
step 2 - update TIM IE
TODO: enlarge TIM bitmap to support up to 64 STAs
TODO: re-measure if RT2600 TBTT interrupt happens faster than BEACON sent out time
*/
ptr = pTimFrame + (UCHAR)FrameLen;
*ptr = IE_TIM;
*(ptr+1) = 0x0e;
*(ptr + 2) = pAd->ApCfg.DtimCount;
*(ptr + 3) = pAd->ApCfg.DtimPeriod;
*(ptr + 4) = 0xb0;
*(ptr + 5) = 0xb0;
*(ptr + 6) = 0xb0;
*(ptr + 7) = 0xb0;
*(ptr + 8) = 0xb0;
*(ptr + 9) = 0xb0;
*(ptr + 10) = 0xb0;
*(ptr + 11) = 0xb0;
*(ptr + 12) = 0xb0;
*(ptr + 13) = 0xb0;
*(ptr + 14) = 0xb0;
*(ptr + 15) = 0xb0;
// /* find the smallest AID (PS mode) */
// TimFirst = 0; /* record first TIM byte != 0x00 */
// TimLast = 0; /* record last TIM byte != 0x00 */
// pTim = pMbss->TimBitmaps;
//
// for(ID_1B=0; ID_1B<WLAN_MAX_NUM_OF_TIM; ID_1B++)
// {
// /* get the TIM indicating PS packets for 8 stations */
// UCHAR tim_1B = pTim[ID_1B];
//
// if (ID_1B == 0)
// tim_1B &= 0xfe; /* skip bit0 bc/mc */
//
// if (tim_1B == 0)
// continue; /* find next 1B */
//
// if (TimFirst == 0)
// TimFirst = ID_1B;
//
// TimLast = ID_1B;
// }
//
// /* fill TIM content to beacon buffer */
// if (TimFirst & 0x01)
// TimFirst --; /* find the even offset byte */
//
// *(ptr + 1) = 3+(TimLast-TimFirst+1); /* TIM IE length */
// *(ptr + 4) = TimFirst;
//
// for(i=TimFirst; i<=TimLast; i++)
// *(ptr + 5 + i - TimFirst) = pTim[i];
//
// /* bit0 means backlogged mcast/bcast */
// /* per spec, this bit in TIM frame shall always 0. */
// //TODO: MTK proprietary mechanism.
// //if (pAd->ApCfg.DtimCount == 0)
// //*(ptr + 4) |= (pMbss->TimBitmaps[WLAN_CT_TIM_BCMC_OFFSET] & 0x01);
// *(ptr + 4) = 0;
/* adjust TIM length according to the new TIM */
FrameLen += 16;//(2 + *(ptr+1));
/* When Beacon is use CCK to send, TIM shall use OFDM to send. and it's mandatory. */
if (pAd->CommonCfg.Channel <= 14) {
TimTransmit.field.MODE = MODE_CCK;
TimTransmit.field.MCS = MCS_LONGP_RATE_1;
}
write_tmac_info_tim(pAd, apidx, tmac_info, &TimTransmit, FrameLen);
// asic_write_bcn_buf(pAd,
// tmac_info, TXWISize,
// pTimFrame, FrameLen,
// pAd->BeaconOffset[pMbss->bcn_buf.BcnBufIdx]);
RT28xx_UpdateTim2ToAsic(pAd, apidx, FrameLen);
//+++Add by shiang for debug
DBGPRINT(RT_DEBUG_OFF, ("%s(): Dump the Beacon Packet of BSS%d!\n", __FUNCTION__, apidx));
hex_dump("Initial BeaconBuf", tmac_info, FrameLen + tx_hw_hdr_len);
//---Add by shiang for debug
}
#endif
static UCHAR GetTimNum(RTMP_ADAPTER *pAd)
{
int i;
UCHAR NumTim;
TIM_BUF_STRUC *tim_info;
NumTim = 0;
for (i=0; i<pAd->ApCfg.BssidNum; i++)
{
tim_info = &pAd->ApCfg.MBSSID[i].tim_buf;
if (tim_info->bTimSntReq)
{
tim_info->TimBufIdx = NumTim;
NumTim ++;
}
}
return NumTim;
}
VOID APMakeAllTimFrame(RTMP_ADAPTER *pAd)
{
INT i;
//UCHAR NumOfTims;
/* choose the Beacon number */
/*NumOfTims =*/ GetTimNum(pAd);
for(i=0; i<pAd->ApCfg.BssidNum; i++) {
APMakeBssTimFrame(pAd, i);
// APMakeBssTimFrame2(pAd, i);//Carter, for test tttt 2 pkt purpose
}
}
INT wdev_tim_buf_init(RTMP_ADAPTER *pAd, TIM_BUF_STRUC *tim_info)
{
//bcn_info->bBcnSntReq = FALSE;
tim_info->TimBufIdx = HW_BEACON_MAX_NUM;
if (!tim_info->TimPkt) {
RTMPAllocateNdisPacket(pAd, &tim_info->TimPkt, NULL, 0, NULL, MAX_TIM_SIZE);
//NdisAllocateSpinLock(pAd, &bcn_info->bcn_lock);
} else {
DBGPRINT(RT_DEBUG_OFF, ("%s():TimPkt is allocated!\n", __func__));
}
// if (!tim_info->TimPkt2) {
// RTMPAllocateNdisPacket(pAd, &tim_info->TimPkt2, NULL, NULL, NULL, MAX_TIM_SIZE);
//NdisAllocateSpinLock(pAd, &bcn_info->bcn_lock);
// } else {
// DBGPRINT(RT_DEBUG_OFF, ("%s():TimPkt2 is allocated!\n", __func__));
//}
tim_info->bTimSntReq = TRUE;
return TRUE;
}
#endif /* MT_MAC */