xref: /device/qemu/drivers/virtio/virtnet.c (revision d6aed566)
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