-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvirtio.c
124 lines (112 loc) · 2.79 KB
/
virtio.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "virtio.h"
struct rv32_virtio *virtio_init(u8 *disk)
{
struct rv32_virtio *vio = malloc(sizeof(struct rv32_virtio));
memset(vio, 0, sizeof(struct rv32_virtio));
vio->config[1] = 0x00;
vio->config[2] = 0x01;
vio->disk = disk;
vio->q_notify = -1;
return vio;
}
bool virtio_is_interrupting(struct rv32_virtio *virtio)
{
if (virtio->q_notify != -1) {
virtio->isr |= 1;
virtio->q_notify = -1;
return true;
}
return false;
}
exception_t read_virtio(struct rv32_virtio *virtio,
u32 addr,
u32 size,
u32 *result)
{
if (addr >= VIRTIO_CONFIG) {
int index = addr - VIRTIO_CONFIG;
if (index >= 8)
return LOAD_ACCESS_FAULT;
*result = virtio->config[index];
return OK;
}
if (size != 32)
return LOAD_ACCESS_FAULT;
switch (addr) {
case VIRTIO_MAGIC:
*result = 0x74726976;
break;
case VIRTIO_VERSION:
*result = 0x1;
break;
case VIRTIO_DEVICE_ID:
*result = 0x2;
break;
case VIRTIO_VENDOR_ID:
*result = 0x554d4551;
break;
case VIRTIO_DEVICE_FEATURES:
*result = 0; // 1 << 28;
break;
case VIRTIO_DRIVER_FEATURES:
*result = virtio->driver_features;
break;
case VIRTIO_QUEUE_NUM_MAX:
*result = VIRTIO_DESC_NUM;
break;
case VIRTIO_QUEUE_PFN:
*result = virtio->q_pfn;
break;
case VIRTIO_INTERRUPT_STATUS:
*result = virtio->isr;
break;
case VIRTIO_STATUS:
*result = virtio->status;
break;
default:
*result = 0;
}
return OK;
}
exception_t write_virtio(struct rv32_virtio *virtio,
u32 addr,
u32 size,
u32 value)
{
if (addr >= VIRTIO_CONFIG) {
int index = addr - VIRTIO_CONFIG;
if (index >= 8)
return LOAD_ACCESS_FAULT;
virtio->config[index] = (value >> (index * 8)) & 0xff;
return OK;
}
if (size != 32)
return STORE_AMO_ACCESS_FAULT;
switch (addr) {
case VIRTIO_DEVICE_FEATURES:
virtio->driver_features = value;
break;
case VIRTIO_GUEST_PAGE_SIZE:
virtio->page_size = value;
break;
case VIRTIO_QUEUE_SEL:
virtio->q_sel = value;
break;
case VIRTIO_QUEUE_NUM:
virtio->q_num = value;
break;
case VIRTIO_QUEUE_PFN:
virtio->q_pfn = value;
break;
case VIRTIO_QUEUE_NOTIFY:
virtio->q_notify = value;
break;
case VIRTIO_INTERRUPT_ACK:
virtio->isr &= ~(value & 0xff);
break;
case VIRTIO_STATUS:
virtio->status = value;
break;
}
return OK;
}