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

451 lines
12 KiB
C

/****************************************************************************
* Ralink Tech Inc.
* 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.
***************************************************************************/
/****************************************************************************
Abstract:
Support multi-BSS function.
Note:
1. Call RT28xx_MBSS_Init() in init function and
call RT28xx_MBSS_Remove() in close function
2. MAC of different BSS is initialized in APStartUp()
3. BSS Index (0 ~ 15) of different rx packet is got in
4. BSS Index (0 ~ 15) of different tx packet is assigned in
5. BSS Index (0 ~ 15) of different BSS is got in APHardTransmit() by using
6. BSS Index (0 ~ 15) of IOCTL command is put in pAd->OS_Cookie->ioctl_if
7. Beacon of different BSS is enabled in APMakeAllBssBeacon() by writing 1
to the register MAC_BSSID_DW1
8. The number of MBSS can be 1, 2, 4, or 8
***************************************************************************/
#ifdef MBSS_SUPPORT
#include "rt_config.h"
/* --------------------------------- Public -------------------------------- */
/*
========================================================================
Routine Description:
Initialize Multi-BSS function.
Arguments:
pAd points to our adapter
pDevMain points to the main BSS network interface
Return Value:
None
Note:
1. Only create and initialize virtual network interfaces.
2. No main network interface here.
3. If you down ra0 and modify the BssNum of RT2860AP.dat/RT2870AP.dat,
it will not work! You must rmmod rt2860ap.ko and lsmod rt2860ap.ko again.
========================================================================
*/
VOID MBSS_Init(RTMP_ADAPTER *pAd, RTMP_OS_NETDEV_OP_HOOK *pNetDevOps)
{
#define MBSS_MAX_DEV_NUM 32
PNET_DEV pDevNew;
INT32 IdBss, MaxNumBss;
//INT status;
RTMP_OS_NETDEV_OP_HOOK netDevHook;
/* sanity check to avoid redundant virtual interfaces are created */
if (pAd->FlgMbssInit != FALSE)
return;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s --->\n", __FUNCTION__));
#endif /* RELEASE_EXCLUDE */
MaxNumBss = pAd->ApCfg.BssidNum;
if (MaxNumBss > MAX_MBSSID_NUM(pAd))
MaxNumBss = MAX_MBSSID_NUM(pAd);
if (MaxNumBss > ARRAY_SIZE(pAd->ApCfg.MBSSID))
MaxNumBss = ARRAY_SIZE(pAd->ApCfg.MBSSID);
/* first IdBss must not be 0 (BSS0), must be 1 (BSS1) */
for(IdBss=FIRST_MBSSID; IdBss<MAX_MBSSID_NUM(pAd); IdBss++)
pAd->ApCfg.MBSSID[IdBss].wdev.if_dev = NULL;
/* create virtual network interface */
for(IdBss=FIRST_MBSSID; IdBss<MaxNumBss; IdBss++)
{
struct wifi_dev *wdev;
UINT32 MC_RowID = 0, IoctlIF = 0;
char *dev_name;
#ifdef MULTIPLE_CARD_SUPPORT
MC_RowID = pAd->MC_RowID;
#endif /* MULTIPLE_CARD_SUPPORT */
#ifdef HOSTAPD_SUPPORT
IoctlIF = pAd->IoctlIF;
#endif /* HOSTAPD_SUPPORT */
BSS_STRUCT *pMbss;
dev_name = get_dev_name_prefix(pAd, INT_MBSSID);
if (!dev_name) {
DBGPRINT(RT_DEBUG_ERROR,
("%s(): Get dev name prefix fail!\n",
__func__));
break;
}
pDevNew = RtmpOSNetDevCreate(MC_RowID, &IoctlIF, INT_MBSSID, IdBss, sizeof(struct mt_dev_priv), dev_name);
#ifdef HOSTAPD_SUPPORT
pAd->IoctlIF = IoctlIF;
#endif /* HOSTAPD_SUPPORT */
if (pDevNew == NULL)
{
pAd->ApCfg.BssidNum = (UCHAR)IdBss; /* re-assign new MBSS number */
break;
}
else
{
DBGPRINT(RT_DEBUG_TRACE, ("Register MBSSID IF (%s)\n", RTMP_OS_NETDEV_GET_DEVNAME(pDevNew)));
}
pMbss = &pAd->ApCfg.MBSSID[IdBss];
wdev = &pAd->ApCfg.MBSSID[IdBss].wdev;
wdev->wdev_type = WDEV_TYPE_AP;
wdev->func_dev = &pAd->ApCfg.MBSSID[IdBss];
wdev->func_idx = (CHAR)IdBss;
wdev->sys_handle = (void *)pAd;
wdev->if_dev = pDevNew;
if (rtmp_wdev_idx_reg(pAd, wdev) < 0) {
DBGPRINT(RT_DEBUG_ERROR, ("Assign wdev idx for %s failed, free net device!\n",
RTMP_OS_NETDEV_GET_DEVNAME(pDevNew)));
RtmpOSNetDevFree(pDevNew);
break;
}
wdev->tx_pkt_allowed = ApAllowToSendPacket;
wdev->tx_pkt_handle = APSendPacket;
wdev->wdev_hard_tx = APHardTransmit;
wdev->rx_pkt_allowed = ap_rx_pkt_allow;
wdev->rx_ps_handle = ap_rx_ps_handle;
wdev->rx_pkt_foward = ap_rx_foward_handle;
RTMP_OS_NETDEV_SET_PRIV(pDevNew, pAd);
RTMP_OS_NETDEV_SET_WDEV(pDevNew, wdev);
/* init operation functions and flags */
NdisCopyMemory(&netDevHook, pNetDevOps, sizeof(netDevHook));
netDevHook.priv_flags = INT_MBSSID;
netDevHook.needProtcted = TRUE;
netDevHook.wdev = wdev;
/* Init MAC address of virtual network interface */
NdisMoveMemory(&netDevHook.devAddr[0], &wdev->bssid[0], MAC_ADDR_LEN);
/* register this device to OS */
/*status =*/ RtmpOSNetDevAttach(pAd->OpMode, pDevNew, &netDevHook);
ASSERT(pMbss);
if (pMbss) {
wdev_bcn_buf_init(pAd, &pMbss->bcn_buf);
} else {
DBGPRINT(RT_DEBUG_ERROR, ("%s():func_dev is NULL!\n", __FUNCTION__));
return;
}
}
pAd->FlgMbssInit = TRUE;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s <---\n", __FUNCTION__));
#endif /* RELEASE_EXCLUDE */
}
/*
========================================================================
Routine Description:
Remove Multi-BSS network interface.
Arguments:
pAd points to our adapter
Return Value:
None
Note:
FIRST_MBSSID = 1
Main BSS is not removed here.
========================================================================
*/
VOID MBSS_Remove(RTMP_ADAPTER *pAd)
{
struct wifi_dev *wdev;
UINT IdBss;
BSS_STRUCT *pMbss;
#ifdef RELEASE_EXCLUDE
DBGPRINT(RT_DEBUG_INFO, ("%s --->\n", __FUNCTION__));
#endif /* RELEASE_EXCLUDE */
for(IdBss=FIRST_MBSSID; IdBss<MAX_MBSSID_NUM(pAd); IdBss++)
{
wdev = &pAd->ApCfg.MBSSID[IdBss].wdev;
pMbss = &pAd->ApCfg.MBSSID[IdBss];
if (pMbss) {
wdev_bcn_buf_deinit(pAd, &pMbss->bcn_buf);
}
if (wdev->if_dev)
{
RtmpOSNetDevProtect(1);
RtmpOSNetDevDetach(wdev->if_dev);
RtmpOSNetDevProtect(0);
rtmp_wdev_idx_unreg(pAd, wdev);
RtmpOSNetDevFree(wdev->if_dev);
wdev->if_dev = NULL;
}
}
}
/*
========================================================================
Routine Description:
Get multiple bss idx.
Arguments:
pAd points to our adapter
pDev which WLAN network interface
Return Value:
0: close successfully
otherwise: close fail
Note:
========================================================================
*/
INT32 RT28xx_MBSS_IdxGet(RTMP_ADAPTER *pAd, PNET_DEV pDev)
{
INT32 BssId = -1;
INT32 IdBss;
for(IdBss=0; IdBss<pAd->ApCfg.BssidNum; IdBss++)
{
if (pAd->ApCfg.MBSSID[IdBss].wdev.if_dev == pDev)
{
BssId = IdBss;
break;
}
}
return BssId;
}
#ifdef MT_MAC
INT32 mbss_cr_enable(PNET_DEV pDev)
{
PRTMP_ADAPTER pAd;
INT BssId;
UINT32 Value = 0;
//register for sub Bssid start from 0x603000a0
UINT32 bssid_reg_base = LPON_SBTOR1;
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
BssId = RT28xx_MBSS_IdxGet(pAd, pDev);
DBGPRINT(RT_DEBUG_OFF, ("##### %s, BssId = %d\n", __func__, BssId));
if (BssId < 0)
return -1;
if (pAd->chipCap.hif_type != HIF_MT)
return 0;
if (BssId >= 1) {
//if there is any sub bssid is enable. this bit in LPON_SBTOR1 shall be 1 always.
RTMP_IO_READ32(pAd, bssid_reg_base, &Value);
Value |= SBSS_TBTT0_TSF0_EN;
RTMP_IO_WRITE32(pAd, bssid_reg_base, Value);
RTMP_IO_READ32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), &Value);
Value = 0;
Value &= ~SUB_BSSID0_TIME_OFFSET_n_MASK;
Value |= SUB_BSSID0_TIME_OFFSET_n(BssId * (20 + 4096));
/* SIFS time, 20us, and assume bcn len is 512 byte, tx by 1Mbps.*/
Value |= TBTT0_n_INT_EN;
Value |= PRE_TBTT0_n_INT_EN;
Value |= SBSS_TBTT0_TSF0_EN;
RTMP_IO_WRITE32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), Value);
/* Start Beacon Queue */
RTMP_IO_READ32(pAd, ARB_BCNQCR0, &Value);
Value |= (0x1 << (BssId+15));
RTMP_IO_WRITE32(pAd, ARB_BCNQCR0, Value);
}
return 0;
}
INT mbss_cr_disable(PNET_DEV pDev)
{
PRTMP_ADAPTER pAd;
INT BssId;
UINT32 Value;
UINT32 bssid_reg_base = LPON_SBTOR1;
UCHAR loop = 0;
BOOLEAN any_mbss_enable = FALSE;
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
BssId = RT28xx_MBSS_IdxGet(pAd, pDev);
if (BssId < 0)
return -1;
if (pAd->chipCap.hif_type != HIF_MT)
return 0;
for (loop = 1; loop < pAd->ApCfg.BssidNum; loop++) {
if (loop == BssId)
continue;//skip itself.
if (loop >= ARRAY_SIZE(pAd->ApCfg.MBSSID))
break;
if (pAd->ApCfg.MBSSID[loop].bcn_buf.bBcnSntReq == TRUE)
any_mbss_enable = TRUE;
}
if (BssId >= 1) {
RTMP_IO_READ32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), &Value);
Value = 0;
Value &= ~SUB_BSSID0_TIME_OFFSET_n_MASK;
Value |= SUB_BSSID0_TIME_OFFSET_n(BssId * (20 + 4096));
Value &= ~TBTT0_n_INT_EN;
Value &= ~PRE_TBTT0_n_INT_EN;
if (any_mbss_enable == TRUE)
Value |= SBSS_TBTT0_TSF0_EN;
else
Value &= ~SBSS_TBTT0_TSF0_EN;
RTMP_IO_WRITE32(pAd, (bssid_reg_base + (BssId - 1) * (0x4)), Value);
RTMP_IO_READ32(pAd, ARB_BCNQCR0, &Value);
Value &= ~(0x1 << (BssId+15));
RTMP_IO_WRITE32(pAd, ARB_BCNQCR0, Value);
}
return 0;
}
#endif /* MT_MAC */
/*
========================================================================
Routine Description:
Open a virtual network interface.
Arguments:
pDev which WLAN network interface
Return Value:
0: open successfully
otherwise: open fail
Note:
========================================================================
*/
INT32 MBSS_Open(PNET_DEV pDev)
{
PRTMP_ADAPTER pAd;
INT BssId;
UINT32 u4MaxMBSSIDSize;
u4MaxMBSSIDSize = sizeof(pAd->ApCfg.MBSSID)/sizeof(pAd->ApCfg.MBSSID[0]);
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
BssId = RT28xx_MBSS_IdxGet(pAd, pDev);
if (BssId < 0)
return -1;
if(BssId >= u4MaxMBSSIDSize)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): Over buffer size!\n", __FUNCTION__));
return -1;
}
pAd->ApCfg.MBSSID[BssId].bcn_buf.bBcnSntReq = TRUE;
return 0;
}
/*
========================================================================
Routine Description:
Close a virtual network interface.
Arguments:
pDev which WLAN network interface
Return Value:
0: close successfully
otherwise: close fail
Note:
========================================================================
*/
INT MBSS_Close(PNET_DEV pDev)
{
PRTMP_ADAPTER pAd;
INT BssId;
UINT32 u4MaxMBSSIDSize;
pAd = RTMP_OS_NETDEV_GET_PRIV(pDev);
BssId = RT28xx_MBSS_IdxGet(pAd, pDev);
if (BssId < 0)
return -1;
RTMP_OS_NETDEV_STOP_QUEUE(pDev);
/* kick out all stas behind the Bss */
MbssKickOutStas(pAd, BssId, REASON_DISASSOC_INACTIVE);
u4MaxMBSSIDSize = sizeof(pAd->ApCfg.MBSSID)/sizeof(pAd->ApCfg.MBSSID[0]);
if(BssId >= u4MaxMBSSIDSize)
{
DBGPRINT(RT_DEBUG_ERROR, ("%s(): Over buffer size!\n", __FUNCTION__));
return -1;
}
pAd->ApCfg.MBSSID[BssId].bcn_buf.bBcnSntReq = FALSE;
APMakeAllBssBeacon(pAd);
APUpdateAllBeaconFrame(pAd);
#ifdef MESH_SUPPORT
MeshMakeBeacon(pAd, MESH_BEACON_IDX(pAd));
MeshUpdateBeaconFrame(pAd, MESH_BEACON_IDX(pAd));
#endif /* MESH_SUPPORT */
return 0;
}
#endif /* MBSS_SUPPORT */