1d6aed566Sopenharmony_ci/* 2d6aed566Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 3d6aed566Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d6aed566Sopenharmony_ci * you may not use this file except in compliance with the License. 5d6aed566Sopenharmony_ci * You may obtain a copy of the License at 6d6aed566Sopenharmony_ci * 7d6aed566Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d6aed566Sopenharmony_ci * 9d6aed566Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d6aed566Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d6aed566Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d6aed566Sopenharmony_ci * See the License for the specific language governing permissions and 13d6aed566Sopenharmony_ci * limitations under the License. 14d6aed566Sopenharmony_ci */ 15d6aed566Sopenharmony_ci 16d6aed566Sopenharmony_ci/* 17d6aed566Sopenharmony_ci * Simple virtio-net driver using HDF WIFI framework without real WIFI functions. 18d6aed566Sopenharmony_ci */ 19d6aed566Sopenharmony_ci 20d6aed566Sopenharmony_ci#include "los_hw_cpu.h" 21d6aed566Sopenharmony_ci#include "los_vm_iomap.h" 22d6aed566Sopenharmony_ci#include "los_vm_zone.h" 23d6aed566Sopenharmony_ci#include "netinet/if_ether.h" 24d6aed566Sopenharmony_ci#include "arpa/inet.h" 25d6aed566Sopenharmony_ci#include "hdf_device_desc.h" 26d6aed566Sopenharmony_ci#include "wifi/hdf_wlan_chipdriver_manager.h" 27d6aed566Sopenharmony_ci#include "wifi/wifi_mac80211_ops.h" 28d6aed566Sopenharmony_ci#include "osal.h" 29d6aed566Sopenharmony_ci#include "osal_io.h" 30d6aed566Sopenharmony_ci#include "eapol.h" 31d6aed566Sopenharmony_ci#include "virtmmio.h" 32d6aed566Sopenharmony_ci 33d6aed566Sopenharmony_ci#define HDF_LOG_TAG HDF_VIRTIO_NET 34d6aed566Sopenharmony_ci 35d6aed566Sopenharmony_ci#define VIRTIO_NET_F_MTU (1 << 3) 36d6aed566Sopenharmony_ci#define VIRTIO_NET_F_MAC (1 << 5) 37d6aed566Sopenharmony_cistruct VirtnetConfig { 38d6aed566Sopenharmony_ci uint8_t mac[6]; 39d6aed566Sopenharmony_ci uint16_t status; 40d6aed566Sopenharmony_ci uint16_t maxVirtqPairs; 41d6aed566Sopenharmony_ci uint16_t mtu; 42d6aed566Sopenharmony_ci}; 43d6aed566Sopenharmony_ci 44d6aed566Sopenharmony_ci#define VIRTMMIO_NETIF_NAME "virtnet" 45d6aed566Sopenharmony_ci#define VIRTMMIO_NETIF_DFT_GW "10.0.2.2" 46d6aed566Sopenharmony_ci#define VIRTMMIO_NETIF_DFT_MASK "255.255.255.0" 47d6aed566Sopenharmony_ci 48d6aed566Sopenharmony_ci/* This struct is actually ignored by this simple driver */ 49d6aed566Sopenharmony_cistruct VirtnetHdr { 50d6aed566Sopenharmony_ci uint8_t flag; 51d6aed566Sopenharmony_ci uint8_t gsoType; 52d6aed566Sopenharmony_ci uint16_t hdrLen; 53d6aed566Sopenharmony_ci uint16_t gsoSize; 54d6aed566Sopenharmony_ci uint16_t csumStart; 55d6aed566Sopenharmony_ci uint16_t csumOffset; 56d6aed566Sopenharmony_ci uint16_t numBuffers; 57d6aed566Sopenharmony_ci}; 58d6aed566Sopenharmony_ci 59d6aed566Sopenharmony_ci/* 60d6aed566Sopenharmony_ci * We use two queues for Tx/Rx respectively. When Tx, we record outgoing NetBuf 61d6aed566Sopenharmony_ci * and free it when QEMU done. When Rx, we use fixed buffers, then allocate & 62d6aed566Sopenharmony_ci * copy to a NetBuf, and then HDF will consume & free the NetBuf. 63d6aed566Sopenharmony_ci * Every NetBuf is a solo packet, no chaining like LWIP pbuf. So every outgoing 64d6aed566Sopenharmony_ci * packet always occupy two desc items: one for VirtnetHdr, the other for NetBuf. 65d6aed566Sopenharmony_ci * Tx/Rx queues memory layout: 66d6aed566Sopenharmony_ci * Rx queue Tx queue 67d6aed566Sopenharmony_ci * +-----------------+------------------+------------------++------+-------+------+ 68d6aed566Sopenharmony_ci * | desc: 16B align | avail: 2B align | used: 4B align || desc | avail | used | 69d6aed566Sopenharmony_ci * | 16∗(Queue Size) | 4+2∗(Queue Size) | 4+8∗(Queue Size) || | | | 70d6aed566Sopenharmony_ci * +-----------------+------------------+------------------++------+-------+------+ 71d6aed566Sopenharmony_ci */ 72d6aed566Sopenharmony_ci#define VIRTQ_RX_QSZ 16 73d6aed566Sopenharmony_ci#define VIRTQ_TX_QSZ 32 74d6aed566Sopenharmony_ci#define PER_TX_ENTRIES 2 75d6aed566Sopenharmony_ci#define PER_RXBUF_SIZE (sizeof(struct VirtnetHdr) + ETH_FRAME_LEN) 76d6aed566Sopenharmony_ci 77d6aed566Sopenharmony_cistruct VirtNetif { 78d6aed566Sopenharmony_ci struct VirtmmioDev dev; 79d6aed566Sopenharmony_ci 80d6aed566Sopenharmony_ci uint16_t tFreeHdr; /* head of Tx free desc entries list */ 81d6aed566Sopenharmony_ci uint16_t tFreeNum; 82d6aed566Sopenharmony_ci NetBuf* tbufRec[VIRTQ_TX_QSZ]; 83d6aed566Sopenharmony_ci OSAL_DECLARE_SPINLOCK(transLock); 84d6aed566Sopenharmony_ci 85d6aed566Sopenharmony_ci uint8_t rbuf[VIRTQ_RX_QSZ][PER_RXBUF_SIZE]; 86d6aed566Sopenharmony_ci 87d6aed566Sopenharmony_ci struct VirtnetHdr vnHdr; 88d6aed566Sopenharmony_ci}; 89d6aed566Sopenharmony_ci 90d6aed566Sopenharmony_cistatic inline struct VirtNetif *GetVirtnetIf(const NetDevice *netDev) 91d6aed566Sopenharmony_ci{ 92d6aed566Sopenharmony_ci return (struct VirtNetif *)GET_NET_DEV_PRIV(netDev); 93d6aed566Sopenharmony_ci} 94d6aed566Sopenharmony_ci 95d6aed566Sopenharmony_cistatic bool Feature0(uint32_t features, uint32_t *supported, void *dev) 96d6aed566Sopenharmony_ci{ 97d6aed566Sopenharmony_ci NetDevice *netDev = dev; 98d6aed566Sopenharmony_ci struct VirtNetif *nic = GetVirtnetIf(netDev); 99d6aed566Sopenharmony_ci struct VirtnetConfig *conf = (struct VirtnetConfig *)(nic->dev.base + VIRTMMIO_REG_CONFIG); 100d6aed566Sopenharmony_ci int i; 101d6aed566Sopenharmony_ci 102d6aed566Sopenharmony_ci if (features & VIRTIO_NET_F_MTU) { 103d6aed566Sopenharmony_ci if (conf->mtu > WLAN_MAX_MTU || conf->mtu < WLAN_MIN_MTU) { 104d6aed566Sopenharmony_ci HDF_LOGE("[%s]unsupported backend net MTU: %u", __func__, conf->mtu); 105d6aed566Sopenharmony_ci return false; 106d6aed566Sopenharmony_ci } 107d6aed566Sopenharmony_ci netDev->mtu = conf->mtu; 108d6aed566Sopenharmony_ci *supported |= VIRTIO_NET_F_MTU; 109d6aed566Sopenharmony_ci } else { 110d6aed566Sopenharmony_ci netDev->mtu = DEFAULT_MTU; 111d6aed566Sopenharmony_ci } 112d6aed566Sopenharmony_ci 113d6aed566Sopenharmony_ci if ((features & VIRTIO_NET_F_MAC) == 0) { 114d6aed566Sopenharmony_ci HDF_LOGE("[%s]no MAC feature found", __func__); 115d6aed566Sopenharmony_ci return false; 116d6aed566Sopenharmony_ci } 117d6aed566Sopenharmony_ci for (i = 0; i < MAC_ADDR_SIZE; i++) { 118d6aed566Sopenharmony_ci netDev->macAddr[i] = conf->mac[i]; 119d6aed566Sopenharmony_ci } 120d6aed566Sopenharmony_ci netDev->addrLen = MAC_ADDR_SIZE; 121d6aed566Sopenharmony_ci *supported |= VIRTIO_NET_F_MAC; 122d6aed566Sopenharmony_ci 123d6aed566Sopenharmony_ci return true; 124d6aed566Sopenharmony_ci} 125d6aed566Sopenharmony_ci 126d6aed566Sopenharmony_cistatic bool Feature1(uint32_t features, uint32_t *supported, void *dev) 127d6aed566Sopenharmony_ci{ 128d6aed566Sopenharmony_ci (void)dev; 129d6aed566Sopenharmony_ci if (features & VIRTIO_F_VERSION_1) { 130d6aed566Sopenharmony_ci *supported |= VIRTIO_F_VERSION_1; 131d6aed566Sopenharmony_ci } else { 132d6aed566Sopenharmony_ci HDF_LOGE("[%s]net device has no VERSION_1 feature", __func__); 133d6aed566Sopenharmony_ci return false; 134d6aed566Sopenharmony_ci } 135d6aed566Sopenharmony_ci 136d6aed566Sopenharmony_ci return true; 137d6aed566Sopenharmony_ci} 138d6aed566Sopenharmony_ci 139d6aed566Sopenharmony_cistatic int32_t InitTxFreelist(struct VirtNetif *nic) 140d6aed566Sopenharmony_ci{ 141d6aed566Sopenharmony_ci int i; 142d6aed566Sopenharmony_ci 143d6aed566Sopenharmony_ci for (i = 0; i < nic->dev.vq[1].qsz - 1; i++) { 144d6aed566Sopenharmony_ci nic->dev.vq[1].desc[i].flag = VIRTQ_DESC_F_NEXT; 145d6aed566Sopenharmony_ci nic->dev.vq[1].desc[i].next = i + 1; 146d6aed566Sopenharmony_ci } 147d6aed566Sopenharmony_ci nic->tFreeHdr = 0; 148d6aed566Sopenharmony_ci nic->tFreeNum = nic->dev.vq[1].qsz; 149d6aed566Sopenharmony_ci 150d6aed566Sopenharmony_ci return OsalSpinInit(&nic->transLock); 151d6aed566Sopenharmony_ci} 152d6aed566Sopenharmony_ci 153d6aed566Sopenharmony_cistatic void FreeTxEntry(struct VirtNetif *nic, uint16_t head) 154d6aed566Sopenharmony_ci{ 155d6aed566Sopenharmony_ci struct Virtq *q = &nic->dev.vq[1]; 156d6aed566Sopenharmony_ci uint16_t idx = q->desc[head].next; 157d6aed566Sopenharmony_ci NetBuf *nb = NULL; 158d6aed566Sopenharmony_ci 159d6aed566Sopenharmony_ci /* keep track of virt queue free entries */ 160d6aed566Sopenharmony_ci OsalSpinLock(&nic->transLock); 161d6aed566Sopenharmony_ci if (nic->tFreeNum > 0) { 162d6aed566Sopenharmony_ci q->desc[idx].next = nic->tFreeHdr; 163d6aed566Sopenharmony_ci q->desc[idx].flag = VIRTQ_DESC_F_NEXT; 164d6aed566Sopenharmony_ci } 165d6aed566Sopenharmony_ci nic->tFreeNum += PER_TX_ENTRIES; 166d6aed566Sopenharmony_ci nic->tFreeHdr = head; 167d6aed566Sopenharmony_ci nb = nic->tbufRec[idx]; 168d6aed566Sopenharmony_ci OsalSpinUnlock(&nic->transLock); 169d6aed566Sopenharmony_ci 170d6aed566Sopenharmony_ci /* We free upstream Tx NetBuf! */ 171d6aed566Sopenharmony_ci NetBufFree(nb); 172d6aed566Sopenharmony_ci} 173d6aed566Sopenharmony_ci 174d6aed566Sopenharmony_cistatic void PopulateRxBuffer(struct VirtNetif *nic) 175d6aed566Sopenharmony_ci{ 176d6aed566Sopenharmony_ci uint32_t i; 177d6aed566Sopenharmony_ci PADDR_T paddr; 178d6aed566Sopenharmony_ci struct Virtq *q = &nic->dev.vq[0]; 179d6aed566Sopenharmony_ci 180d6aed566Sopenharmony_ci for (i = 0; i < q->qsz; i++) { 181d6aed566Sopenharmony_ci paddr = VMM_TO_DMA_ADDR((VADDR_T)nic->rbuf[i]); 182d6aed566Sopenharmony_ci 183d6aed566Sopenharmony_ci q->desc[i].pAddr = paddr; 184d6aed566Sopenharmony_ci q->desc[i].len = PER_RXBUF_SIZE; 185d6aed566Sopenharmony_ci q->desc[i].flag = VIRTQ_DESC_F_WRITE; 186d6aed566Sopenharmony_ci 187d6aed566Sopenharmony_ci q->avail->ring[i] = i; 188d6aed566Sopenharmony_ci } 189d6aed566Sopenharmony_ci} 190d6aed566Sopenharmony_ci 191d6aed566Sopenharmony_cistatic int32_t ConfigQueue(struct VirtNetif *nic) 192d6aed566Sopenharmony_ci{ 193d6aed566Sopenharmony_ci VADDR_T base; 194d6aed566Sopenharmony_ci uint16_t qsz[VIRTQ_NUM]; 195d6aed566Sopenharmony_ci 196d6aed566Sopenharmony_ci base = ALIGN((VADDR_T)nic + sizeof(struct VirtNetif), VIRTQ_ALIGN_DESC); 197d6aed566Sopenharmony_ci qsz[0] = VIRTQ_RX_QSZ; 198d6aed566Sopenharmony_ci qsz[1] = VIRTQ_TX_QSZ; 199d6aed566Sopenharmony_ci if (VirtmmioConfigQueue(&nic->dev, base, qsz, VIRTQ_NUM) == 0) { 200d6aed566Sopenharmony_ci return HDF_DEV_ERR_DEV_INIT_FAIL; 201d6aed566Sopenharmony_ci } 202d6aed566Sopenharmony_ci 203d6aed566Sopenharmony_ci PopulateRxBuffer(nic); 204d6aed566Sopenharmony_ci 205d6aed566Sopenharmony_ci return InitTxFreelist(nic); 206d6aed566Sopenharmony_ci} 207d6aed566Sopenharmony_ci 208d6aed566Sopenharmony_cistatic uint16_t GetTxFreeEntry(struct VirtNetif *nic) 209d6aed566Sopenharmony_ci{ 210d6aed566Sopenharmony_ci uint32_t intSave; 211d6aed566Sopenharmony_ci uint16_t head, idx; 212d6aed566Sopenharmony_ci bool logged = false; 213d6aed566Sopenharmony_ci 214d6aed566Sopenharmony_ciRETRY: 215d6aed566Sopenharmony_ci OsalSpinLockIrqSave(&nic->transLock, &intSave); 216d6aed566Sopenharmony_ci if (PER_TX_ENTRIES > nic->tFreeNum) { 217d6aed566Sopenharmony_ci OsalSpinUnlockIrqRestore(&nic->transLock, &intSave); 218d6aed566Sopenharmony_ci if (!logged) { 219d6aed566Sopenharmony_ci HDF_LOGW("[%s]transmit queue is full", __func__); 220d6aed566Sopenharmony_ci logged = true; 221d6aed566Sopenharmony_ci } 222d6aed566Sopenharmony_ci LOS_TaskYield(); 223d6aed566Sopenharmony_ci goto RETRY; 224d6aed566Sopenharmony_ci } 225d6aed566Sopenharmony_ci 226d6aed566Sopenharmony_ci nic->tFreeNum -= PER_TX_ENTRIES; 227d6aed566Sopenharmony_ci head = nic->tFreeHdr; 228d6aed566Sopenharmony_ci idx = nic->dev.vq[1].desc[head].next; 229d6aed566Sopenharmony_ci /* new tFreeHdr may be invalid if list is empty, but tFreeNum must be valid: 0 */ 230d6aed566Sopenharmony_ci nic->tFreeHdr = nic->dev.vq[1].desc[idx].next; 231d6aed566Sopenharmony_ci OsalSpinUnlockIrqRestore(&nic->transLock, &intSave); 232d6aed566Sopenharmony_ci nic->dev.vq[1].desc[idx].flag &= ~VIRTQ_DESC_F_NEXT; 233d6aed566Sopenharmony_ci 234d6aed566Sopenharmony_ci return head; 235d6aed566Sopenharmony_ci} 236d6aed566Sopenharmony_ci 237d6aed566Sopenharmony_cistatic NetDevTxResult LowLevelOutput(NetDevice *netDev, NetBuf *p) 238d6aed566Sopenharmony_ci{ 239d6aed566Sopenharmony_ci uint16_t idx, head; 240d6aed566Sopenharmony_ci struct VirtNetif *nic = GetVirtnetIf(netDev); 241d6aed566Sopenharmony_ci struct Virtq *trans = &nic->dev.vq[1]; 242d6aed566Sopenharmony_ci 243d6aed566Sopenharmony_ci head = GetTxFreeEntry(nic); 244d6aed566Sopenharmony_ci trans->desc[head].pAddr = VMM_TO_DMA_ADDR((PADDR_T)&nic->vnHdr); 245d6aed566Sopenharmony_ci trans->desc[head].len = sizeof(struct VirtnetHdr); 246d6aed566Sopenharmony_ci idx = trans->desc[head].next; 247d6aed566Sopenharmony_ci trans->desc[idx].pAddr = LOS_PaddrQuery(NetBufGetAddress(p, E_DATA_BUF)); 248d6aed566Sopenharmony_ci trans->desc[idx].len = NetBufGetDataLen(p); 249d6aed566Sopenharmony_ci 250d6aed566Sopenharmony_ci nic->tbufRec[idx] = p; 251d6aed566Sopenharmony_ci 252d6aed566Sopenharmony_ci trans->avail->ring[trans->avail->index % trans->qsz] = head; 253d6aed566Sopenharmony_ci DSB; 254d6aed566Sopenharmony_ci trans->avail->index++; 255d6aed566Sopenharmony_ci if (trans->used->flag != VIRTQ_USED_F_NO_NOTIFY) { 256d6aed566Sopenharmony_ci OSAL_WRITEL(1, nic->dev.base + VIRTMMIO_REG_QUEUENOTIFY); 257d6aed566Sopenharmony_ci } 258d6aed566Sopenharmony_ci 259d6aed566Sopenharmony_ci return NETDEV_TX_OK; 260d6aed566Sopenharmony_ci} 261d6aed566Sopenharmony_ci 262d6aed566Sopenharmony_cistatic NetBuf *LowLevelInput(const NetDevice *netDev, const struct VirtqUsedElem *e) 263d6aed566Sopenharmony_ci{ 264d6aed566Sopenharmony_ci struct VirtNetif *nic = GetVirtnetIf(netDev); 265d6aed566Sopenharmony_ci uint16_t len; 266d6aed566Sopenharmony_ci uint8_t *payload = NULL; 267d6aed566Sopenharmony_ci NetBuf *nb = NULL; 268d6aed566Sopenharmony_ci 269d6aed566Sopenharmony_ci /* we allocate Rx NetBuf & fill in received packet */ 270d6aed566Sopenharmony_ci len = e->len - sizeof(struct VirtnetHdr); 271d6aed566Sopenharmony_ci nb = NetBufDevAlloc(netDev, len); 272d6aed566Sopenharmony_ci if (nb == NULL) { 273d6aed566Sopenharmony_ci HDF_LOGE("[%s]allocate NetBuf failed, drop 1 packet", __func__); 274d6aed566Sopenharmony_ci return NULL; 275d6aed566Sopenharmony_ci } 276d6aed566Sopenharmony_ci payload = NetBufPush(nb, E_DATA_BUF, len); /* here always succeed */ 277d6aed566Sopenharmony_ci (void)memcpy_s(payload, len, nic->rbuf[e->id] + sizeof(struct VirtnetHdr), len); 278d6aed566Sopenharmony_ci 279d6aed566Sopenharmony_ci return nb; 280d6aed566Sopenharmony_ci} 281d6aed566Sopenharmony_ci 282d6aed566Sopenharmony_cistatic void VirtnetRxHandle(NetDevice *netDev) 283d6aed566Sopenharmony_ci{ 284d6aed566Sopenharmony_ci struct VirtNetif *nic = GetVirtnetIf(netDev); 285d6aed566Sopenharmony_ci struct Virtq *q = &nic->dev.vq[0]; 286d6aed566Sopenharmony_ci NetBuf *nb = NULL; 287d6aed566Sopenharmony_ci struct VirtqUsedElem *e = NULL; 288d6aed566Sopenharmony_ci uint16_t add = 0; 289d6aed566Sopenharmony_ci 290d6aed566Sopenharmony_ci q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT; 291d6aed566Sopenharmony_ci while (1) { 292d6aed566Sopenharmony_ci if (q->last == q->used->index) { 293d6aed566Sopenharmony_ci q->avail->flag = 0; 294d6aed566Sopenharmony_ci /* recheck if new one come in between empty ring and enable interrupt */ 295d6aed566Sopenharmony_ci DSB; 296d6aed566Sopenharmony_ci if (q->last == q->used->index) { 297d6aed566Sopenharmony_ci break; 298d6aed566Sopenharmony_ci } 299d6aed566Sopenharmony_ci q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT; 300d6aed566Sopenharmony_ci } 301d6aed566Sopenharmony_ci 302d6aed566Sopenharmony_ci DSB; 303d6aed566Sopenharmony_ci e = &q->used->ring[q->last % q->qsz]; 304d6aed566Sopenharmony_ci nb = LowLevelInput(netDev, e); 305d6aed566Sopenharmony_ci if (nb && NetIfRx(netDev, nb) != 0) { /* Upstream free Rx NetBuf! */ 306d6aed566Sopenharmony_ci HDF_LOGE("[%s]NetIfRx failed, drop 1 packet", __func__); 307d6aed566Sopenharmony_ci NetBufFree(nb); 308d6aed566Sopenharmony_ci } 309d6aed566Sopenharmony_ci 310d6aed566Sopenharmony_ci /* 311d6aed566Sopenharmony_ci * Our fixed receive buffers always sit in the appropriate desc[]. 312d6aed566Sopenharmony_ci * We only need to update the available ring to QEMU. 313d6aed566Sopenharmony_ci */ 314d6aed566Sopenharmony_ci q->avail->ring[(q->avail->index + add++) % q->qsz] = e->id; 315d6aed566Sopenharmony_ci q->last++; 316d6aed566Sopenharmony_ci } 317d6aed566Sopenharmony_ci DSB; 318d6aed566Sopenharmony_ci q->avail->index += add; 319d6aed566Sopenharmony_ci 320d6aed566Sopenharmony_ci if (q->used->flag != VIRTQ_USED_F_NO_NOTIFY) { 321d6aed566Sopenharmony_ci OSAL_WRITEL(0, nic->dev.base + VIRTMMIO_REG_QUEUENOTIFY); 322d6aed566Sopenharmony_ci } 323d6aed566Sopenharmony_ci} 324d6aed566Sopenharmony_ci 325d6aed566Sopenharmony_cistatic void VirtnetTxHandle(struct VirtNetif *nic) 326d6aed566Sopenharmony_ci{ 327d6aed566Sopenharmony_ci struct Virtq *q = &nic->dev.vq[1]; 328d6aed566Sopenharmony_ci struct VirtqUsedElem *e = NULL; 329d6aed566Sopenharmony_ci 330d6aed566Sopenharmony_ci /* Bypass recheck as VirtnetRxHandle */ 331d6aed566Sopenharmony_ci q->avail->flag = VIRTQ_AVAIL_F_NO_INTERRUPT; 332d6aed566Sopenharmony_ci while (q->last != q->used->index) { 333d6aed566Sopenharmony_ci DSB; 334d6aed566Sopenharmony_ci e = &q->used->ring[q->last % q->qsz]; 335d6aed566Sopenharmony_ci FreeTxEntry(nic, e->id); 336d6aed566Sopenharmony_ci q->last++; 337d6aed566Sopenharmony_ci } 338d6aed566Sopenharmony_ci q->avail->flag = 0; 339d6aed566Sopenharmony_ci} 340d6aed566Sopenharmony_ci 341d6aed566Sopenharmony_cistatic void VirtnetIRQhandle(int swIrq, void *pDevId) 342d6aed566Sopenharmony_ci{ 343d6aed566Sopenharmony_ci (void)swIrq; 344d6aed566Sopenharmony_ci NetDevice *netDev = pDevId; 345d6aed566Sopenharmony_ci struct VirtNetif *nic = GetVirtnetIf(netDev); 346d6aed566Sopenharmony_ci 347d6aed566Sopenharmony_ci if (!(OSAL_READL(nic->dev.base + VIRTMMIO_REG_INTERRUPTSTATUS) & VIRTMMIO_IRQ_NOTIFY_USED)) { 348d6aed566Sopenharmony_ci return; 349d6aed566Sopenharmony_ci } 350d6aed566Sopenharmony_ci 351d6aed566Sopenharmony_ci VirtnetRxHandle(netDev); 352d6aed566Sopenharmony_ci 353d6aed566Sopenharmony_ci VirtnetTxHandle(nic); 354d6aed566Sopenharmony_ci 355d6aed566Sopenharmony_ci OSAL_WRITEL(VIRTMMIO_IRQ_NOTIFY_USED, nic->dev.base + VIRTMMIO_REG_INTERRUPTACK); 356d6aed566Sopenharmony_ci} 357d6aed566Sopenharmony_ci 358d6aed566Sopenharmony_ci/* 359d6aed566Sopenharmony_ci * The whole initialization is complex, here is the main point. 360d6aed566Sopenharmony_ci * -factory- FakeWifiInit/Release: alloc, set & register HdfChipDriverFactory 361d6aed566Sopenharmony_ci * -chip- FakeFactoryInitChip/Release: alloc & set HdfChipDriver 362d6aed566Sopenharmony_ci * -NetDevice- VirtNetDeviceInit/DeInit: set & add NetDevice 363d6aed566Sopenharmony_ci * -virtnet- VirtnetInit/DeInit: virtio-net driver 364d6aed566Sopenharmony_ci */ 365d6aed566Sopenharmony_ci 366d6aed566Sopenharmony_cistatic int32_t VirtnetInit(NetDevice *netDev) 367d6aed566Sopenharmony_ci{ 368d6aed566Sopenharmony_ci int32_t ret, len; 369d6aed566Sopenharmony_ci struct VirtNetif *nic = NULL; 370d6aed566Sopenharmony_ci 371d6aed566Sopenharmony_ci /* NOTE: For simplicity, alloc all these data from physical continuous memory. */ 372d6aed566Sopenharmony_ci len = sizeof(struct VirtNetif) + VirtqSize(VIRTQ_RX_QSZ) + VirtqSize(VIRTQ_TX_QSZ); 373d6aed566Sopenharmony_ci nic = LOS_DmaMemAlloc(NULL, len, sizeof(void *), DMA_CACHE); 374d6aed566Sopenharmony_ci if (nic == NULL) { 375d6aed566Sopenharmony_ci HDF_LOGE("[%s]alloc nic memory failed", __func__); 376d6aed566Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 377d6aed566Sopenharmony_ci } 378d6aed566Sopenharmony_ci memset_s(nic, len, 0, len); 379d6aed566Sopenharmony_ci GET_NET_DEV_PRIV(netDev) = nic; 380d6aed566Sopenharmony_ci 381d6aed566Sopenharmony_ci if (!VirtmmioDiscover(VIRTMMIO_DEVICE_ID_NET, &nic->dev)) { 382d6aed566Sopenharmony_ci return HDF_DEV_ERR_NO_DEVICE; 383d6aed566Sopenharmony_ci } 384d6aed566Sopenharmony_ci 385d6aed566Sopenharmony_ci VirtmmioInitBegin(&nic->dev); 386d6aed566Sopenharmony_ci 387d6aed566Sopenharmony_ci if (!VirtmmioNegotiate(&nic->dev, Feature0, Feature1, netDev)) { 388d6aed566Sopenharmony_ci ret = HDF_DEV_ERR_DEV_INIT_FAIL; 389d6aed566Sopenharmony_ci goto ERR_OUT; 390d6aed566Sopenharmony_ci } 391d6aed566Sopenharmony_ci 392d6aed566Sopenharmony_ci if ((ret = ConfigQueue(nic)) != HDF_SUCCESS) { 393d6aed566Sopenharmony_ci goto ERR_OUT; 394d6aed566Sopenharmony_ci } 395d6aed566Sopenharmony_ci 396d6aed566Sopenharmony_ci ret = OsalRegisterIrq(nic->dev.irq, OSAL_IRQF_TRIGGER_NONE, (OsalIRQHandle)VirtnetIRQhandle, 397d6aed566Sopenharmony_ci VIRTMMIO_NETIF_NAME, netDev); 398d6aed566Sopenharmony_ci if (ret != HDF_SUCCESS) { 399d6aed566Sopenharmony_ci HDF_LOGE("[%s]register IRQ failed: %d", __func__, ret); 400d6aed566Sopenharmony_ci goto ERR_OUT; 401d6aed566Sopenharmony_ci } 402d6aed566Sopenharmony_ci nic->dev.irq |= ~_IRQ_MASK; 403d6aed566Sopenharmony_ci 404d6aed566Sopenharmony_ci VritmmioInitEnd(&nic->dev); 405d6aed566Sopenharmony_ci return HDF_SUCCESS; 406d6aed566Sopenharmony_ci 407d6aed566Sopenharmony_ciERR_OUT: 408d6aed566Sopenharmony_ci VirtmmioInitFailed(&nic->dev); 409d6aed566Sopenharmony_ci return ret; 410d6aed566Sopenharmony_ci} 411d6aed566Sopenharmony_ci 412d6aed566Sopenharmony_cistatic void VirtnetDeInit(NetDevice *netDev) 413d6aed566Sopenharmony_ci{ 414d6aed566Sopenharmony_ci struct VirtNetif *nic = GetVirtnetIf(netDev); 415d6aed566Sopenharmony_ci 416d6aed566Sopenharmony_ci if (nic && (nic->dev.irq & ~_IRQ_MASK)) { 417d6aed566Sopenharmony_ci OsalUnregisterIrq(nic->dev.irq & _IRQ_MASK, netDev); 418d6aed566Sopenharmony_ci } 419d6aed566Sopenharmony_ci if (nic) { 420d6aed566Sopenharmony_ci LOS_DmaMemFree(nic); 421d6aed566Sopenharmony_ci } 422d6aed566Sopenharmony_ci GET_NET_DEV_PRIV(netDev) = NULL; 423d6aed566Sopenharmony_ci} 424d6aed566Sopenharmony_ci 425d6aed566Sopenharmony_cistatic int32_t VirtNetDeviceSetMacAddr(NetDevice *netDev, void *addr) 426d6aed566Sopenharmony_ci{ 427d6aed566Sopenharmony_ci uint8_t *p = addr; 428d6aed566Sopenharmony_ci for (int i = 0; i < netDev->addrLen; i++) { 429d6aed566Sopenharmony_ci netDev->macAddr[i] = p[i]; 430d6aed566Sopenharmony_ci } 431d6aed566Sopenharmony_ci return HDF_SUCCESS; 432d6aed566Sopenharmony_ci} 433d6aed566Sopenharmony_ci 434d6aed566Sopenharmony_cistatic struct NetDeviceInterFace g_netDevOps = { 435d6aed566Sopenharmony_ci .setMacAddr = VirtNetDeviceSetMacAddr, 436d6aed566Sopenharmony_ci /* 437d6aed566Sopenharmony_ci * Link layer packet transmission chain: 438d6aed566Sopenharmony_ci * LWIP netif->linkoutput = driverif_output, in kernel, pbuf 439d6aed566Sopenharmony_ci * KHDF netif->drv_send = LwipSend, in HDF adapter, NetBuf 440d6aed566Sopenharmony_ci * NetDevice .xmit = our driver, NetBuf 441d6aed566Sopenharmony_ci */ 442d6aed566Sopenharmony_ci .xmit = LowLevelOutput, 443d6aed566Sopenharmony_ci}; 444d6aed566Sopenharmony_ci 445d6aed566Sopenharmony_ci#define VN_RANDOM_IP_MASK 0xFF /* 255.255.255.0 subnet */ 446d6aed566Sopenharmony_ci#define VN_RANDOM_IP_SHF 24 /* network byte order */ 447d6aed566Sopenharmony_ci 448d6aed566Sopenharmony_ci/* fake WIFI have to UP interface, assign IP by hand */ 449d6aed566Sopenharmony_cistatic int32_t VirtNetDeviceInitDone(NetDevice *netDev) 450d6aed566Sopenharmony_ci{ 451d6aed566Sopenharmony_ci IpV4Addr ip, mask, gw; 452d6aed566Sopenharmony_ci uint32_t h, l; 453d6aed566Sopenharmony_ci int32_t ret; 454d6aed566Sopenharmony_ci 455d6aed566Sopenharmony_ci if ((ret = NetIfSetStatus(netDev, NETIF_UP)) != HDF_SUCCESS) { 456d6aed566Sopenharmony_ci return ret; 457d6aed566Sopenharmony_ci } 458d6aed566Sopenharmony_ci 459d6aed566Sopenharmony_ci /* odd way hope to get ~distinct~ IP for different guests */ 460d6aed566Sopenharmony_ci LOS_GetCpuCycle(&h, &l); 461d6aed566Sopenharmony_ci l &= VN_RANDOM_IP_MASK; 462d6aed566Sopenharmony_ci if (l == 0 || l == (1 << 1)) { /* avoid 10.0.2.0, 10.0.2.2 */ 463d6aed566Sopenharmony_ci l++; 464d6aed566Sopenharmony_ci } else if (l == VN_RANDOM_IP_MASK) { /* avoid 10.0.2.255 */ 465d6aed566Sopenharmony_ci l--; 466d6aed566Sopenharmony_ci } 467d6aed566Sopenharmony_ci l <<= VN_RANDOM_IP_SHF; 468d6aed566Sopenharmony_ci ip.addr = (inet_addr(VIRTMMIO_NETIF_DFT_MASK) & inet_addr(VIRTMMIO_NETIF_DFT_GW)) | l; 469d6aed566Sopenharmony_ci mask.addr = inet_addr(VIRTMMIO_NETIF_DFT_MASK); 470d6aed566Sopenharmony_ci gw.addr = inet_addr(VIRTMMIO_NETIF_DFT_GW); 471d6aed566Sopenharmony_ci return NetIfSetAddr(netDev, &ip, &mask, &gw); 472d6aed566Sopenharmony_ci} 473d6aed566Sopenharmony_ci 474d6aed566Sopenharmony_cistatic int32_t VirtNetDeviceInit(struct HdfChipDriver *chipDriver, NetDevice *netDev) 475d6aed566Sopenharmony_ci{ 476d6aed566Sopenharmony_ci (void)chipDriver; 477d6aed566Sopenharmony_ci int32_t ret; 478d6aed566Sopenharmony_ci 479d6aed566Sopenharmony_ci /* VirtnetInit also set netDev->macAddr, mtu, addrLen */ 480d6aed566Sopenharmony_ci if ((ret = VirtnetInit(netDev)) != HDF_SUCCESS) { 481d6aed566Sopenharmony_ci return ret; 482d6aed566Sopenharmony_ci } 483d6aed566Sopenharmony_ci netDev->flags = NET_DEVICE_IFF_RUNNING; 484d6aed566Sopenharmony_ci netDev->neededHeadRoom = 0; 485d6aed566Sopenharmony_ci netDev->neededTailRoom = 0; 486d6aed566Sopenharmony_ci netDev->funType.wlanType = PROTOCOL_80211_IFTYPE_STATION; 487d6aed566Sopenharmony_ci netDev->netDeviceIf = &g_netDevOps; 488d6aed566Sopenharmony_ci if ((ret = NetDeviceAdd(netDev)) != HDF_SUCCESS) { 489d6aed566Sopenharmony_ci goto ERR_OUT; 490d6aed566Sopenharmony_ci } 491d6aed566Sopenharmony_ci if ((ret = CreateEapolData(netDev)) != HDF_SUCCESS) { 492d6aed566Sopenharmony_ci goto ERR_OUT; 493d6aed566Sopenharmony_ci } 494d6aed566Sopenharmony_ci 495d6aed566Sopenharmony_ci /* everything is ready, now notify device the receive buffers */ 496d6aed566Sopenharmony_ci struct VirtNetif *nic = GetVirtnetIf(netDev); 497d6aed566Sopenharmony_ci nic->dev.vq[0].avail->index = nic->dev.vq[0].qsz; 498d6aed566Sopenharmony_ci OSAL_WRITEL(0, nic->dev.base + VIRTMMIO_REG_QUEUENOTIFY); 499d6aed566Sopenharmony_ci 500d6aed566Sopenharmony_ci return VirtNetDeviceInitDone(netDev); 501d6aed566Sopenharmony_ci 502d6aed566Sopenharmony_ciERR_OUT: 503d6aed566Sopenharmony_ci VirtnetDeInit(netDev); 504d6aed566Sopenharmony_ci return ret; 505d6aed566Sopenharmony_ci} 506d6aed566Sopenharmony_ci 507d6aed566Sopenharmony_cistatic int32_t VirtNetDeviceDeInit(struct HdfChipDriver *chipDriver, NetDevice *netDev) 508d6aed566Sopenharmony_ci{ 509d6aed566Sopenharmony_ci (void)chipDriver; 510d6aed566Sopenharmony_ci 511d6aed566Sopenharmony_ci DestroyEapolData(netDev); 512d6aed566Sopenharmony_ci 513d6aed566Sopenharmony_ci if (GetVirtnetIf(netDev)) { 514d6aed566Sopenharmony_ci VirtnetDeInit(netDev); 515d6aed566Sopenharmony_ci } 516d6aed566Sopenharmony_ci 517d6aed566Sopenharmony_ci return NetDeviceDelete(netDev); 518d6aed566Sopenharmony_ci} 519d6aed566Sopenharmony_ci 520d6aed566Sopenharmony_ci 521d6aed566Sopenharmony_ci/* 522d6aed566Sopenharmony_ci * Followings are mainly fake data & funcs to mimic a wireless card. 523d6aed566Sopenharmony_ci * 524d6aed566Sopenharmony_ci * Here is fake MAC80211 base operations. 525d6aed566Sopenharmony_ci */ 526d6aed566Sopenharmony_cistatic int32_t FakeWalSetMode(NetDevice *netDev, enum WlanWorkMode mode) 527d6aed566Sopenharmony_ci{ 528d6aed566Sopenharmony_ci (void)netDev; 529d6aed566Sopenharmony_ci if (mode != WLAN_WORKMODE_STA) { 530d6aed566Sopenharmony_ci HDF_LOGE("[%s]unsupported WLAN mode: %u", __func__, mode); 531d6aed566Sopenharmony_ci return HDF_ERR_NOT_SUPPORT; 532d6aed566Sopenharmony_ci } 533d6aed566Sopenharmony_ci return HDF_SUCCESS; 534d6aed566Sopenharmony_ci} 535d6aed566Sopenharmony_cistatic int32_t FakeWalAddKey(NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr, 536d6aed566Sopenharmony_ci struct KeyParams *params) 537d6aed566Sopenharmony_ci{ 538d6aed566Sopenharmony_ci (void)netDev; 539d6aed566Sopenharmony_ci (void)keyIndex; 540d6aed566Sopenharmony_ci (void)pairwise; 541d6aed566Sopenharmony_ci (void)macAddr; 542d6aed566Sopenharmony_ci (void)params; 543d6aed566Sopenharmony_ci return HDF_SUCCESS; 544d6aed566Sopenharmony_ci} 545d6aed566Sopenharmony_cistatic int32_t FakeWalDelKey(NetDevice *netDev, uint8_t keyIndex, bool pairwise, const uint8_t *macAddr) 546d6aed566Sopenharmony_ci{ 547d6aed566Sopenharmony_ci (void)netDev; 548d6aed566Sopenharmony_ci (void)keyIndex; 549d6aed566Sopenharmony_ci (void)pairwise; 550d6aed566Sopenharmony_ci (void)macAddr; 551d6aed566Sopenharmony_ci return HDF_SUCCESS; 552d6aed566Sopenharmony_ci} 553d6aed566Sopenharmony_cistatic int32_t FakeWalSetDefaultKey(NetDevice *netDev, uint8_t keyIndex, bool unicast, bool multicas) 554d6aed566Sopenharmony_ci{ 555d6aed566Sopenharmony_ci (void)netDev; 556d6aed566Sopenharmony_ci (void)keyIndex; 557d6aed566Sopenharmony_ci (void)unicast; 558d6aed566Sopenharmony_ci (void)multicas; 559d6aed566Sopenharmony_ci return HDF_SUCCESS; 560d6aed566Sopenharmony_ci} 561d6aed566Sopenharmony_cistatic int32_t FakeWalGetDeviceMacAddr(NetDevice *netDev, int32_t type, uint8_t *mac, uint8_t len) 562d6aed566Sopenharmony_ci{ 563d6aed566Sopenharmony_ci (void)netDev; 564d6aed566Sopenharmony_ci (void)type; 565d6aed566Sopenharmony_ci 566d6aed566Sopenharmony_ci for (int i = 0; i < len && i < netDev->addrLen; i++) { 567d6aed566Sopenharmony_ci mac[i] = netDev->macAddr[i]; 568d6aed566Sopenharmony_ci } 569d6aed566Sopenharmony_ci 570d6aed566Sopenharmony_ci return HDF_SUCCESS; 571d6aed566Sopenharmony_ci} 572d6aed566Sopenharmony_cistatic int32_t FakeWalSetMacAddr(NetDevice *netDev, uint8_t *mac, uint8_t len) 573d6aed566Sopenharmony_ci{ 574d6aed566Sopenharmony_ci (void)netDev; 575d6aed566Sopenharmony_ci 576d6aed566Sopenharmony_ci for (int i = 0; i < len && i < netDev->addrLen; i++) { 577d6aed566Sopenharmony_ci netDev->macAddr[i] = mac[i]; 578d6aed566Sopenharmony_ci } 579d6aed566Sopenharmony_ci 580d6aed566Sopenharmony_ci return HDF_SUCCESS; 581d6aed566Sopenharmony_ci} 582d6aed566Sopenharmony_cistatic int32_t FakeWalSetTxPower(NetDevice *netDev, int32_t power) 583d6aed566Sopenharmony_ci{ 584d6aed566Sopenharmony_ci (void)netDev; 585d6aed566Sopenharmony_ci (void)power; 586d6aed566Sopenharmony_ci return HDF_SUCCESS; 587d6aed566Sopenharmony_ci} 588d6aed566Sopenharmony_ci#define FAKE_MAGIC_BAND 20 589d6aed566Sopenharmony_ci#define FAKE_MAGIC_FREQ 2412 590d6aed566Sopenharmony_ci#define FAKE_MAGIC_CAPS 20 591d6aed566Sopenharmony_ci#define FAKE_MAGIC_RATE 100 592d6aed566Sopenharmony_cistatic int32_t FakeWalGetValidFreqsWithBand(NetDevice *netDev, int32_t band, int32_t *freqs, uint32_t *num) 593d6aed566Sopenharmony_ci{ 594d6aed566Sopenharmony_ci (void)netDev; 595d6aed566Sopenharmony_ci 596d6aed566Sopenharmony_ci if (band != FAKE_MAGIC_BAND) { 597d6aed566Sopenharmony_ci HDF_LOGE("[%s]unsupported WLAN band: %dMHz", __func__, band); 598d6aed566Sopenharmony_ci return HDF_ERR_NOT_SUPPORT; 599d6aed566Sopenharmony_ci } 600d6aed566Sopenharmony_ci 601d6aed566Sopenharmony_ci *freqs = FAKE_MAGIC_FREQ; /* MHz, channel 1 */ 602d6aed566Sopenharmony_ci *num = 1; 603d6aed566Sopenharmony_ci return HDF_SUCCESS; 604d6aed566Sopenharmony_ci} 605d6aed566Sopenharmony_cistruct MemAllocForWlanHwCapability { 606d6aed566Sopenharmony_ci struct WlanHwCapability cap; 607d6aed566Sopenharmony_ci struct WlanBand band; 608d6aed566Sopenharmony_ci struct WlanChannel ch; 609d6aed566Sopenharmony_ci uint16_t rate; 610d6aed566Sopenharmony_ci}; 611d6aed566Sopenharmony_cistatic void FakeWalHwCapabilityRelease(struct WlanHwCapability *self) 612d6aed566Sopenharmony_ci{ 613d6aed566Sopenharmony_ci OsalMemFree(self); 614d6aed566Sopenharmony_ci} 615d6aed566Sopenharmony_cistatic int32_t FakeWalGetHwCapability(NetDevice *netDev, struct WlanHwCapability **capability) 616d6aed566Sopenharmony_ci{ 617d6aed566Sopenharmony_ci (void)netDev; 618d6aed566Sopenharmony_ci 619d6aed566Sopenharmony_ci struct MemAllocForWlanHwCapability *p = OsalMemCalloc(sizeof(struct MemAllocForWlanHwCapability)); 620d6aed566Sopenharmony_ci if (p == NULL) { 621d6aed566Sopenharmony_ci HDF_LOGE("[%s]alloc memory failed", __func__); 622d6aed566Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 623d6aed566Sopenharmony_ci } 624d6aed566Sopenharmony_ci p->cap.Release = FakeWalHwCapabilityRelease; 625d6aed566Sopenharmony_ci p->cap.bands[0] = &p->band; 626d6aed566Sopenharmony_ci p->cap.htCapability = FAKE_MAGIC_CAPS; 627d6aed566Sopenharmony_ci p->cap.supportedRateCount = 1; 628d6aed566Sopenharmony_ci p->cap.supportedRates = &p->rate; 629d6aed566Sopenharmony_ci p->band.channelCount = 1; 630d6aed566Sopenharmony_ci p->ch.channelId = 1; 631d6aed566Sopenharmony_ci p->ch.centerFreq = FAKE_MAGIC_FREQ; 632d6aed566Sopenharmony_ci p->ch.flags = WLAN_CHANNEL_FLAG_NO_IR | WLAN_CHANNEL_FLAG_DFS_UNAVAILABLE; 633d6aed566Sopenharmony_ci p->rate = FAKE_MAGIC_RATE; 634d6aed566Sopenharmony_ci 635d6aed566Sopenharmony_ci *capability = &p->cap; 636d6aed566Sopenharmony_ci return HDF_SUCCESS; 637d6aed566Sopenharmony_ci} 638d6aed566Sopenharmony_cistatic struct HdfMac80211BaseOps g_fakeBaseOps = { 639d6aed566Sopenharmony_ci .SetMode = FakeWalSetMode, 640d6aed566Sopenharmony_ci .AddKey = FakeWalAddKey, 641d6aed566Sopenharmony_ci .DelKey = FakeWalDelKey, 642d6aed566Sopenharmony_ci .SetDefaultKey = FakeWalSetDefaultKey, 643d6aed566Sopenharmony_ci .GetDeviceMacAddr = FakeWalGetDeviceMacAddr, 644d6aed566Sopenharmony_ci .SetMacAddr = FakeWalSetMacAddr, 645d6aed566Sopenharmony_ci .SetTxPower = FakeWalSetTxPower, 646d6aed566Sopenharmony_ci .GetValidFreqsWithBand = FakeWalGetValidFreqsWithBand, 647d6aed566Sopenharmony_ci .GetHwCapability = FakeWalGetHwCapability 648d6aed566Sopenharmony_ci}; 649d6aed566Sopenharmony_ci 650d6aed566Sopenharmony_ci 651d6aed566Sopenharmony_ci/* 652d6aed566Sopenharmony_ci * Fake STA operations. 653d6aed566Sopenharmony_ci */ 654d6aed566Sopenharmony_cistatic int32_t FakeStaConnect(NetDevice *netDev, WlanConnectParams *param) 655d6aed566Sopenharmony_ci{ 656d6aed566Sopenharmony_ci (void)netDev; 657d6aed566Sopenharmony_ci (void)param; 658d6aed566Sopenharmony_ci return HDF_SUCCESS; 659d6aed566Sopenharmony_ci} 660d6aed566Sopenharmony_cistatic int32_t FakeStaDisonnect(NetDevice *netDev, uint16_t reasonCode) 661d6aed566Sopenharmony_ci{ 662d6aed566Sopenharmony_ci (void)netDev; 663d6aed566Sopenharmony_ci (void)reasonCode; 664d6aed566Sopenharmony_ci return HDF_SUCCESS; 665d6aed566Sopenharmony_ci} 666d6aed566Sopenharmony_cistatic int32_t FakeStaStartScan(NetDevice *netDev, struct WlanScanRequest *param) 667d6aed566Sopenharmony_ci{ 668d6aed566Sopenharmony_ci (void)netDev; 669d6aed566Sopenharmony_ci (void)param; 670d6aed566Sopenharmony_ci return HDF_SUCCESS; 671d6aed566Sopenharmony_ci} 672d6aed566Sopenharmony_cistatic int32_t FakeStaAbortScan(NetDevice *netDev) 673d6aed566Sopenharmony_ci{ 674d6aed566Sopenharmony_ci (void)netDev; 675d6aed566Sopenharmony_ci return HDF_SUCCESS; 676d6aed566Sopenharmony_ci} 677d6aed566Sopenharmony_cistatic int32_t FakeStaSetScanningMacAddress(NetDevice *netDev, unsigned char *mac, uint32_t len) 678d6aed566Sopenharmony_ci{ 679d6aed566Sopenharmony_ci (void)netDev; 680d6aed566Sopenharmony_ci (void)mac; 681d6aed566Sopenharmony_ci (void)len; 682d6aed566Sopenharmony_ci return HDF_SUCCESS; 683d6aed566Sopenharmony_ci} 684d6aed566Sopenharmony_cistatic struct HdfMac80211STAOps g_fakeStaOps = { 685d6aed566Sopenharmony_ci .Connect = FakeStaConnect, 686d6aed566Sopenharmony_ci .Disconnect = FakeStaDisonnect, 687d6aed566Sopenharmony_ci .StartScan = FakeStaStartScan, 688d6aed566Sopenharmony_ci .AbortScan = FakeStaAbortScan, 689d6aed566Sopenharmony_ci .SetScanningMacAddress = FakeStaSetScanningMacAddress, 690d6aed566Sopenharmony_ci}; 691d6aed566Sopenharmony_ci 692d6aed566Sopenharmony_ci 693d6aed566Sopenharmony_ci/* 694d6aed566Sopenharmony_ci * Fake factory & chip functions. 695d6aed566Sopenharmony_ci */ 696d6aed566Sopenharmony_cistatic struct HdfChipDriver *FakeFactoryInitChip(struct HdfWlanDevice *device, uint8_t ifIndex) 697d6aed566Sopenharmony_ci{ 698d6aed566Sopenharmony_ci struct HdfChipDriver *chipDriver = NULL; 699d6aed566Sopenharmony_ci if (device == NULL || ifIndex > 0) { 700d6aed566Sopenharmony_ci HDF_LOGE("[%s]HdfWlanDevice is NULL or ifIndex>0", __func__); 701d6aed566Sopenharmony_ci return NULL; 702d6aed566Sopenharmony_ci } 703d6aed566Sopenharmony_ci chipDriver = OsalMemCalloc(sizeof(struct HdfChipDriver)); 704d6aed566Sopenharmony_ci if (chipDriver == NULL) { 705d6aed566Sopenharmony_ci HDF_LOGE("[%s]alloc memory failed", __func__); 706d6aed566Sopenharmony_ci return NULL; 707d6aed566Sopenharmony_ci } 708d6aed566Sopenharmony_ci 709d6aed566Sopenharmony_ci if (strcpy_s(chipDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, VIRTMMIO_NETIF_NAME) != EOK) { 710d6aed566Sopenharmony_ci HDF_LOGE("[%s]strcpy_s failed", __func__); 711d6aed566Sopenharmony_ci OsalMemFree(chipDriver); 712d6aed566Sopenharmony_ci return NULL; 713d6aed566Sopenharmony_ci } 714d6aed566Sopenharmony_ci chipDriver->init = VirtNetDeviceInit; 715d6aed566Sopenharmony_ci chipDriver->deinit = VirtNetDeviceDeInit; 716d6aed566Sopenharmony_ci chipDriver->ops = &g_fakeBaseOps; 717d6aed566Sopenharmony_ci chipDriver->staOps = &g_fakeStaOps; 718d6aed566Sopenharmony_ci 719d6aed566Sopenharmony_ci return chipDriver; 720d6aed566Sopenharmony_ci} 721d6aed566Sopenharmony_cistatic void FakeFactoryReleaseChip(struct HdfChipDriver *chipDriver) 722d6aed566Sopenharmony_ci{ 723d6aed566Sopenharmony_ci if (chipDriver == NULL) { 724d6aed566Sopenharmony_ci return; 725d6aed566Sopenharmony_ci } 726d6aed566Sopenharmony_ci if (strcmp(chipDriver->name, VIRTMMIO_NETIF_NAME) != 0) { 727d6aed566Sopenharmony_ci HDF_LOGE("[%s]not my driver: %s", __func__, chipDriver->name); 728d6aed566Sopenharmony_ci return; 729d6aed566Sopenharmony_ci } 730d6aed566Sopenharmony_ci OsalMemFree(chipDriver); 731d6aed566Sopenharmony_ci} 732d6aed566Sopenharmony_cistatic uint8_t FakeFactoryGetMaxIFCount(struct HdfChipDriverFactory *factory) 733d6aed566Sopenharmony_ci{ 734d6aed566Sopenharmony_ci (void)factory; 735d6aed566Sopenharmony_ci return 1; 736d6aed566Sopenharmony_ci} 737d6aed566Sopenharmony_cistatic void FakeFactoryRelease(struct HdfChipDriverFactory *factory) 738d6aed566Sopenharmony_ci{ 739d6aed566Sopenharmony_ci OsalMemFree(factory); 740d6aed566Sopenharmony_ci} 741d6aed566Sopenharmony_cistatic int32_t FakeFactoryInit(void) 742d6aed566Sopenharmony_ci{ 743d6aed566Sopenharmony_ci struct HdfChipDriverManager *driverMgr = NULL; 744d6aed566Sopenharmony_ci struct HdfChipDriverFactory *tmpFactory = NULL; 745d6aed566Sopenharmony_ci int32_t ret; 746d6aed566Sopenharmony_ci 747d6aed566Sopenharmony_ci tmpFactory = OsalMemCalloc(sizeof(struct HdfChipDriverFactory)); 748d6aed566Sopenharmony_ci if (tmpFactory == NULL) { 749d6aed566Sopenharmony_ci HDF_LOGE("[%s]alloc memory failed", __func__); 750d6aed566Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 751d6aed566Sopenharmony_ci } 752d6aed566Sopenharmony_ci 753d6aed566Sopenharmony_ci driverMgr = HdfWlanGetChipDriverMgr(); 754d6aed566Sopenharmony_ci if (driverMgr == NULL || driverMgr->RegChipDriver == NULL) { 755d6aed566Sopenharmony_ci HDF_LOGE("[%s]driverMgr or its RegChipDriver is NULL!", __func__); 756d6aed566Sopenharmony_ci OsalMemFree(tmpFactory); 757d6aed566Sopenharmony_ci return HDF_FAILURE; 758d6aed566Sopenharmony_ci } 759d6aed566Sopenharmony_ci 760d6aed566Sopenharmony_ci#define VIRTMMIO_WIFI_NAME "fakewifi" /* must match wlan_chip_virtnet.hcs::driverName */ 761d6aed566Sopenharmony_ci tmpFactory->driverName = VIRTMMIO_WIFI_NAME; 762d6aed566Sopenharmony_ci tmpFactory->ReleaseFactory = FakeFactoryRelease; 763d6aed566Sopenharmony_ci tmpFactory->Build = FakeFactoryInitChip; 764d6aed566Sopenharmony_ci tmpFactory->Release = FakeFactoryReleaseChip; 765d6aed566Sopenharmony_ci tmpFactory->GetMaxIFCount = FakeFactoryGetMaxIFCount; 766d6aed566Sopenharmony_ci if ((ret = driverMgr->RegChipDriver(tmpFactory)) != HDF_SUCCESS) { 767d6aed566Sopenharmony_ci HDF_LOGE("[%s]register chip driver failed: %d", __func__, ret); 768d6aed566Sopenharmony_ci OsalMemFree(tmpFactory); 769d6aed566Sopenharmony_ci return ret; 770d6aed566Sopenharmony_ci } 771d6aed566Sopenharmony_ci 772d6aed566Sopenharmony_ci return HDF_SUCCESS; 773d6aed566Sopenharmony_ci} 774d6aed566Sopenharmony_ci 775d6aed566Sopenharmony_ci 776d6aed566Sopenharmony_ci/* 777d6aed566Sopenharmony_ci * HDF entry. 778d6aed566Sopenharmony_ci */ 779d6aed566Sopenharmony_ci 780d6aed566Sopenharmony_cistatic int32_t FakeWifiInit(struct HdfDeviceObject *device) 781d6aed566Sopenharmony_ci{ 782d6aed566Sopenharmony_ci struct VirtmmioDev dev; 783d6aed566Sopenharmony_ci 784d6aed566Sopenharmony_ci if (device == NULL) { 785d6aed566Sopenharmony_ci HDF_LOGE("[%s]device is null", __func__); 786d6aed566Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 787d6aed566Sopenharmony_ci } 788d6aed566Sopenharmony_ci 789d6aed566Sopenharmony_ci /* only when virtio-net do exist, we go on the other lots of work */ 790d6aed566Sopenharmony_ci if (!VirtmmioDiscover(VIRTMMIO_DEVICE_ID_NET, &dev)) { 791d6aed566Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 792d6aed566Sopenharmony_ci } 793d6aed566Sopenharmony_ci 794d6aed566Sopenharmony_ci return FakeFactoryInit(); 795d6aed566Sopenharmony_ci} 796d6aed566Sopenharmony_ci 797d6aed566Sopenharmony_cistatic void FakeWifiRelease(struct HdfDeviceObject *deviceObject) 798d6aed566Sopenharmony_ci{ 799d6aed566Sopenharmony_ci if (deviceObject) { 800d6aed566Sopenharmony_ci (void)ChipDriverMgrDeInit(); 801d6aed566Sopenharmony_ci } 802d6aed566Sopenharmony_ci} 803d6aed566Sopenharmony_ci 804d6aed566Sopenharmony_cistruct HdfDriverEntry g_fakeWifiEntry = { 805d6aed566Sopenharmony_ci .moduleVersion = 1, 806d6aed566Sopenharmony_ci .Init = FakeWifiInit, 807d6aed566Sopenharmony_ci .Release = FakeWifiRelease, 808d6aed566Sopenharmony_ci .moduleName = "HDF_FAKE_WIFI" 809d6aed566Sopenharmony_ci}; 810d6aed566Sopenharmony_ci 811d6aed566Sopenharmony_ciHDF_INIT(g_fakeWifiEntry); 812