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#ifndef __VIRTMMIO_H__ 16d6aed566Sopenharmony_ci#define __VIRTMMIO_H__ 17d6aed566Sopenharmony_ci 18d6aed566Sopenharmony_ci/* NOTE: Only support non-legacy device and little-endian guest. */ 19d6aed566Sopenharmony_ci 20d6aed566Sopenharmony_ci#include "stdint.h" 21d6aed566Sopenharmony_ci#include "los_reg.h" 22d6aed566Sopenharmony_ci#include "stdbool.h" 23d6aed566Sopenharmony_ci#include "los_arch_context.h" 24d6aed566Sopenharmony_ci 25d6aed566Sopenharmony_citypedef unsigned long VADDR_T; 26d6aed566Sopenharmony_citypedef unsigned long PADDR_T; 27d6aed566Sopenharmony_ci 28d6aed566Sopenharmony_ci#define IO_DEVICE_ADDR(paddr) (paddr) 29d6aed566Sopenharmony_ci#define VMM_TO_DMA_ADDR(vaddr) (vaddr) 30d6aed566Sopenharmony_ci#define DMA_TO_VMM_ADDR(vaddr) (vaddr) 31d6aed566Sopenharmony_ci#define IRQ_SPI_BASE RISCV_SYS_MAX_IRQ 32d6aed566Sopenharmony_ci 33d6aed566Sopenharmony_ci#define DSB dsb() 34d6aed566Sopenharmony_ci#define FENCE_WRITE_UINT32(value, addr) ({ DSB; *((volatile UINT32 *)((UINTPTR)(addr))) = (value); }) 35d6aed566Sopenharmony_ci 36d6aed566Sopenharmony_ciuint64_t u32_to_u64(uint32_t addr); 37d6aed566Sopenharmony_ci 38d6aed566Sopenharmony_ci#define VIRTIO_STATUS_RESET 0 39d6aed566Sopenharmony_ci#define VIRTIO_STATUS_ACK 1 40d6aed566Sopenharmony_ci#define VIRTIO_STATUS_DRIVER 2 41d6aed566Sopenharmony_ci#define VIRTIO_STATUS_DRIVER_OK 4 42d6aed566Sopenharmony_ci#define VIRTIO_STATUS_FEATURES_OK 8 43d6aed566Sopenharmony_ci#define VIRTIO_STATUS_DEVICE_NEEDS_RESET 64 44d6aed566Sopenharmony_ci#define VIRTIO_STATUS_FAILED 128 45d6aed566Sopenharmony_ci 46d6aed566Sopenharmony_ci#define VIRTIO_FEATURE_WORD0 0 47d6aed566Sopenharmony_ci#define VIRTIO_F_RING_INDIRECT_DESC (1 << 28) 48d6aed566Sopenharmony_ci#define VIRTIO_FEATURE_WORD1 1 49d6aed566Sopenharmony_ci#define VIRTIO_F_VERSION_1 (1 << 0) 50d6aed566Sopenharmony_ci 51d6aed566Sopenharmony_ci#define VIRTMMIO_REG_MAGICVALUE 0x00 52d6aed566Sopenharmony_ci#define VIRTMMIO_REG_VERSION 0x04 53d6aed566Sopenharmony_ci#define VIRTMMIO_REG_DEVICEID 0x08 54d6aed566Sopenharmony_ci#define VIRTMMIO_REG_DEVFEATURE 0x10 55d6aed566Sopenharmony_ci#define VIRTMMIO_REG_DEVFEATURESEL 0x14 56d6aed566Sopenharmony_ci#define VIRTMMIO_REG_DRVFEATURE 0x20 57d6aed566Sopenharmony_ci#define VIRTMMIO_REG_DRVFEATURESEL 0x24 58d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUESEL 0x30 59d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUENUMMAX 0x34 60d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUENUM 0x38 61d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUEREADY 0x44 62d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUENOTIFY 0x50 63d6aed566Sopenharmony_ci#define VIRTMMIO_REG_INTERRUPTSTATUS 0x60 64d6aed566Sopenharmony_ci#define VIRTMMIO_REG_INTERRUPTACK 0x64 65d6aed566Sopenharmony_ci#define VIRTMMIO_REG_STATUS 0x70 66d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUEDESCLOW 0x80 67d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUEDESCHIGH 0x84 68d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUEDRIVERLOW 0x90 69d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUEDRIVERHIGH 0x94 70d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUEDEVICELOW 0xA0 71d6aed566Sopenharmony_ci#define VIRTMMIO_REG_QUEUEDEVICEHIGH 0xA4 72d6aed566Sopenharmony_ci#define VIRTMMIO_REG_CONFIGGENERATION 0xFC 73d6aed566Sopenharmony_ci#define VIRTMMIO_REG_CONFIG 0x100 74d6aed566Sopenharmony_ci 75d6aed566Sopenharmony_ci#define VIRTQ_ALIGN_DESC 16 76d6aed566Sopenharmony_ci#define VIRTQ_ALIGN_AVAIL 2 77d6aed566Sopenharmony_ci#define VIRTQ_ALIGN_USED 4 78d6aed566Sopenharmony_ci 79d6aed566Sopenharmony_ci#define VIRTMMIO_MAGIC 0x74726976 80d6aed566Sopenharmony_ci#define VIRTMMIO_VERSION 2 81d6aed566Sopenharmony_ci#define VIRTMMIO_DEVICE_ID_NET 1 82d6aed566Sopenharmony_ci#define VIRTMMIO_DEVICE_ID_GPU 16 83d6aed566Sopenharmony_ci#define VIRTMMIO_DEVICE_ID_INPUT 18 84d6aed566Sopenharmony_ci 85d6aed566Sopenharmony_ci/* QEMU 5.2 virtio-mmio for riscv */ 86d6aed566Sopenharmony_ci#define VIRTMMIO_BASE_ADDR 0x10001000 /* see hw/riscv/virt.c virt_memmap[] */ 87d6aed566Sopenharmony_ci#define VIRTMMIO_BASE_SIZE 0x1000 /* see hw/riscv/virt.c virt_memmap[] */ 88d6aed566Sopenharmony_ci#define VIRTMMIO_BASE_IRQ 1 /* see hw/riscv/virt.h VIRTIO_IRQ */ 89d6aed566Sopenharmony_ci#define NUM_VIRTIO_TRANSPORTS 8 /* see hw/riscv/virt.h VIRTIO_COUNT */ 90d6aed566Sopenharmony_ci 91d6aed566Sopenharmony_ci#define VIRTMMIO_IRQ_NOTIFY_USED (1 << 0) 92d6aed566Sopenharmony_ci 93d6aed566Sopenharmony_cistruct VirtqDesc { 94d6aed566Sopenharmony_ci uint64_t pAddr; 95d6aed566Sopenharmony_ci uint32_t len; 96d6aed566Sopenharmony_ci#define VIRTQ_DESC_F_NEXT (1 << 0) 97d6aed566Sopenharmony_ci#define VIRTQ_DESC_F_WRITE (1 << 1) 98d6aed566Sopenharmony_ci uint16_t flag; 99d6aed566Sopenharmony_ci uint16_t next; 100d6aed566Sopenharmony_ci}; 101d6aed566Sopenharmony_ci 102d6aed566Sopenharmony_cistruct VirtqAvail { 103d6aed566Sopenharmony_ci#define VIRTQ_AVAIL_F_NO_INTERRUPT (1 << 0) 104d6aed566Sopenharmony_ci uint16_t flag; 105d6aed566Sopenharmony_ci uint16_t index; 106d6aed566Sopenharmony_ci uint16_t ring[]; 107d6aed566Sopenharmony_ci /* We do not use VIRTIO_F_EVENT_IDX, so no other member */ 108d6aed566Sopenharmony_ci}; 109d6aed566Sopenharmony_ci 110d6aed566Sopenharmony_cistruct VirtqUsedElem { 111d6aed566Sopenharmony_ci uint32_t id; /* u32 for padding purpose */ 112d6aed566Sopenharmony_ci uint32_t len; 113d6aed566Sopenharmony_ci}; 114d6aed566Sopenharmony_ci 115d6aed566Sopenharmony_cistruct VirtqUsed { 116d6aed566Sopenharmony_ci#define VIRTQ_USED_F_NO_NOTIFY (1 << 0) 117d6aed566Sopenharmony_ci uint16_t flag; 118d6aed566Sopenharmony_ci uint16_t index; 119d6aed566Sopenharmony_ci struct VirtqUsedElem ring[]; 120d6aed566Sopenharmony_ci /* We do not use VIRTIO_F_EVENT_IDX, so no other member */ 121d6aed566Sopenharmony_ci}; 122d6aed566Sopenharmony_ci 123d6aed566Sopenharmony_cistruct Virtq { 124d6aed566Sopenharmony_ci uint16_t qsz; 125d6aed566Sopenharmony_ci uint16_t last; 126d6aed566Sopenharmony_ci 127d6aed566Sopenharmony_ci struct VirtqDesc *desc; 128d6aed566Sopenharmony_ci struct VirtqAvail *avail; 129d6aed566Sopenharmony_ci struct VirtqUsed *used; 130d6aed566Sopenharmony_ci}; 131d6aed566Sopenharmony_ci 132d6aed566Sopenharmony_ci#define VIRTQ_NUM 2 133d6aed566Sopenharmony_ci 134d6aed566Sopenharmony_ci/* common virtio-mmio device structure, should be first member of specific device */ 135d6aed566Sopenharmony_cistruct VirtmmioDev { 136d6aed566Sopenharmony_ci VADDR_T base; /* I/O base address */ 137d6aed566Sopenharmony_ci#define _IRQ_MASK 0xFF /* higher bytes as registered flag */ 138d6aed566Sopenharmony_ci int irq; 139d6aed566Sopenharmony_ci struct Virtq vq[VIRTQ_NUM]; 140d6aed566Sopenharmony_ci}; 141d6aed566Sopenharmony_ci 142d6aed566Sopenharmony_ci 143d6aed566Sopenharmony_ci/* discover and fill in 'dev' if found given ID device */ 144d6aed566Sopenharmony_cibool VirtmmioDiscover(uint32_t devId, struct VirtmmioDev *dev); 145d6aed566Sopenharmony_ci 146d6aed566Sopenharmony_civoid VirtmmioInitBegin(const struct VirtmmioDev *dev); 147d6aed566Sopenharmony_ci 148d6aed566Sopenharmony_ci/* add 'supported'(default 0) according given 'features' */ 149d6aed566Sopenharmony_citypedef bool (*VirtioFeatureFn)(uint32_t features, uint32_t *supported, void *dev); 150d6aed566Sopenharmony_ci 151d6aed566Sopenharmony_ci/* negotiate 'baseDev' feature word 0 & 1 through 'f0' & 'f1'. 'dev' is passed to callbacks */ 152d6aed566Sopenharmony_cibool VirtmmioNegotiate(struct VirtmmioDev *baseDev, VirtioFeatureFn f0, VirtioFeatureFn f1, void *dev); 153d6aed566Sopenharmony_ci 154d6aed566Sopenharmony_ci/* calculate queue space of size 'qsz', conforming to alignment limits */ 155d6aed566Sopenharmony_ciunsigned VirtqSize(uint16_t qsz); 156d6aed566Sopenharmony_ci 157d6aed566Sopenharmony_ci/* config pre-allocated continuous memory as two Virtq, started at 'base' with specified queue size */ 158d6aed566Sopenharmony_ciVADDR_T VirtmmioConfigQueue(struct VirtmmioDev *dev, VADDR_T base, uint16_t qsz[], int num); 159d6aed566Sopenharmony_ci 160d6aed566Sopenharmony_cibool VirtmmioRegisterIRQ(struct VirtmmioDev *dev, HWI_PROC_FUNC handle, void *argDev, const char *devName); 161d6aed566Sopenharmony_ci 162d6aed566Sopenharmony_civoid VritmmioInitEnd(const struct VirtmmioDev *dev); 163d6aed566Sopenharmony_ci 164d6aed566Sopenharmony_civoid VirtmmioInitFailed(const struct VirtmmioDev *dev); 165d6aed566Sopenharmony_ci 166d6aed566Sopenharmony_ci#endif 167