mirror of
https://github.com/cccriscv/mini-riscv-os.git
synced 2025-11-16 12:34:33 +00:00
117 lines
4.4 KiB
C
117 lines
4.4 KiB
C
/*
|
||
* References:
|
||
* 1. https://github.com/ianchen0119/xv6-riscv/blob/riscv/kernel/virtio.h
|
||
* 2. https://github.com/sgmarz/osblog/blob/master/risc_v/src/virtio.rs
|
||
*/
|
||
#define VIRTIO_MMIO_BASE 0x10001000
|
||
/* OFFSET */
|
||
#define VIRTIO_MMIO_MAGIC_VALUE 0x000 // Magic value must be 0x74726976
|
||
#define VIRTIO_MMIO_VERSION 0x004 // Version: 1 (Legacy)
|
||
/*
|
||
* Device ID:
|
||
* 1 (Network Device)
|
||
* 2 (Block Device)
|
||
* 4 (Random number generator Device)
|
||
* 16 (GPU Device)
|
||
* 18 (Input Device)
|
||
*/
|
||
#define VIRTIO_MMIO_DEVICE_ID 0x008
|
||
#define VIRTIO_MMIO_DEVICE_FEATURES 0x010
|
||
#define VIRTIO_MMIO_DRIVER_FEATURES 0x020
|
||
#define VIRTIO_MMIO_GUEST_PAGE_SIZE 0x028 // page size for PFN, write-only
|
||
#define VIRTIO_MMIO_QUEUE_SEL 0x030 // select queue, write-only
|
||
#define VIRTIO_MMIO_QUEUE_NUM_MAX 0x034 // max size of current queue, read-only
|
||
#define VIRTIO_MMIO_QUEUE_NUM 0x038 // size of current queue, write-only
|
||
#define VIRTIO_MMIO_QUEUE_ALIGN 0x03c // used ring alignment, write-only
|
||
#define VIRTIO_MMIO_QUEUE_PFN 0x040 // physical page number for queue, read/write
|
||
#define VIRTIO_MMIO_QUEUE_READY 0x044 // ready bit
|
||
#define VIRTIO_MMIO_QUEUE_NOTIFY 0x050 // write-only
|
||
#define VIRTIO_MMIO_INTERRUPT_STATUS 0x060 // read-only
|
||
#define VIRTIO_MMIO_INTERRUPT_ACK 0x064 // write-only
|
||
#define VIRTIO_MMIO_STATUS 0x070 // read/write
|
||
|
||
// status register bits, from qemu virtio_config.h
|
||
#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
|
||
#define VIRTIO_CONFIG_S_DRIVER 2
|
||
#define VIRTIO_CONFIG_S_DRIVER_OK 4
|
||
#define VIRTIO_CONFIG_S_FEATURES_OK 8
|
||
|
||
// device feature bits
|
||
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
|
||
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
|
||
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
|
||
#define VIRTIO_BLK_F_MQ 12 /* support more than one vq */
|
||
#define VIRTIO_F_ANY_LAYOUT 27
|
||
#define VIRTIO_RING_F_INDIRECT_DESC 28
|
||
#define VIRTIO_RING_F_EVENT_IDX 29
|
||
|
||
// this many virtio descriptors.
|
||
#define NUM 8
|
||
|
||
// æ<><C3A6>述符包å<E280A6>«é€™äº›è¨Šæ<C5A0>¯: 地å<C2B0>€ï¼Œåœ°å<C2B0>€é•·åº¦ï¼ŒæŸ<C3A6>些標誌和其他信æ<C2A1>¯ã€‚ä½¿ç”¨æ¤æ<C2A4><C3A6>述符,我們å<E28098>¯ä»¥å°‡è¨å‚™æŒ‡å<E280A1>‘ RAM ä¸ä»»ä½•ç·©è¡<C3A8>å<EFBFBD>€çš„å…§å˜åœ°å<C2B0>€ã€‚
|
||
typedef struct virtq_desc
|
||
{
|
||
/*
|
||
* addr: 我們å<E28098>¯ä»¥åœ¨ 64-bit å…§å˜åœ°å<C2B0>€å…§çš„任何ä½<C3A4>置告訴è¨å‚™å˜å„²ä½<C3A4>置。
|
||
* len: 讓 Device 知é<C2A5>“有多少內å˜å<CB9C>¯ç”¨ã€‚
|
||
* flags: 用於控制 descriptor 。
|
||
* next: 告訴 Device 下一個æ<E280B9><C3A6>述符的 Index 。如果指定了 VIRTQ_DESC_F_NEXT, Device 僅讀å<E282AC>–è©²å—æ®µã€‚å<E2809A>¦å‰‡ç„¡æ•ˆã€‚
|
||
*/
|
||
uint64_t addr;
|
||
uint32_t len;
|
||
uint16_t flags;
|
||
uint16_t next;
|
||
} virtq_desc_t;
|
||
#define VRING_DESC_F_NEXT 1 // chained with another descriptor
|
||
#define VRING_DESC_F_WRITE 2 // device writes (vs read)
|
||
|
||
/*
|
||
* ç”¨ä¾†å˜æ”¾ descriptor 的索引,當 Device 收到通知時,它會檢查 AvailableRing 確èª<C3A8>需è¦<C3A8>讀å<E282AC>–哪些 Descriptor 。
|
||
* 注æ„<C3A6>: Descriptor å’Œ AvailableRing 都å˜å„²åœ¨ RAM ä¸ã€‚
|
||
*/
|
||
typedef struct virtq_avail
|
||
{
|
||
uint16_t flags; // always zero
|
||
uint16_t idx; // driver will write ring[idx] next
|
||
uint16_t ring[NUM]; // descriptor numbers of chain heads
|
||
uint16_t unused;
|
||
} virtq_avail_t;
|
||
|
||
/*
|
||
* 當內部的 Index 與 UsedRing çš„ Index 相ç‰ï¼Œä»£è¡¨æ‰€æœ‰è³‡æ–™éƒ½å·²ç¶“被讀å<E282AC>–,這個 Device 是唯一需è¦<C3A8>被寫進 Index 的。
|
||
*/
|
||
|
||
typedef struct virtq_used_elem
|
||
{
|
||
uint32_t id; // index of start of completed descriptor chain
|
||
uint32_t len;
|
||
} virtq_used_elem_t;
|
||
|
||
/*
|
||
* Device å<>¯ä»¥ä½¿ç”¨ UsedRing å<>‘ OS 發é€<C3A9>訊æ<C5A0>¯ã€‚
|
||
* Device 通常使用它來告知 OS 它已完æˆ<C3A6>å…ˆå‰<C3A5>通知的請求。
|
||
* AvailableRing 與 UsedRing é<>žå¸¸ç›¸ä¼¼ï¼Œå·®ç•°åœ¨æ–¼: OS 需è¦<C3A8>查看 UsedRing 得知哪個 Descriptor 已經被æœ<C3A6>務。
|
||
*/
|
||
|
||
typedef struct virtq_used
|
||
{
|
||
uint16_t flags; // always zero
|
||
uint16_t idx; // device increments when it adds a ring[] entry
|
||
struct virtq_used_elem ring[NUM];
|
||
} virtq_used_t;
|
||
|
||
// these are specific to virtio block devices, e.g. disks,
|
||
// described in Section 5.2 of the spec.
|
||
|
||
#define VIRTIO_BLK_T_IN 0 // read the disk
|
||
#define VIRTIO_BLK_T_OUT 1 // write the disk
|
||
|
||
// the format of the first descriptor in a disk request.
|
||
// to be followed by two more descriptors containing
|
||
// the block, and a one-byte status.
|
||
typedef struct virtio_blk_req
|
||
{
|
||
uint32_t type; // VIRTIO_BLK_T_IN or ..._OUT
|
||
uint32_t reserved; // å°‡ Header 擴充到 16-byte ,並將 64-bit sector 移到æ£ç¢ºçš„ä½<C3A4>置。
|
||
uint64_t sector;
|
||
} virtio_blk_req_t; |