1 /*
2 * Copyright 2013, 2018, Jérôme Duval, jerome.duval@gmail.com.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7 #include "VirtioPrivate.h"
8
9
10 device_manager_info *gDeviceManager = NULL;
11
12
13 // #pragma mark -
14
15
16 static status_t
virtio_device_init(device_node * node,void ** _device)17 virtio_device_init(device_node *node, void **_device)
18 {
19 CALLED();
20 VirtioDevice *device = new(std::nothrow) VirtioDevice(node);
21 if (device == NULL)
22 return B_NO_MEMORY;
23
24 status_t result = device->InitCheck();
25 if (result != B_OK) {
26 ERROR("failed to set up virtio device object\n");
27 delete device;
28 return result;
29 }
30
31 *_device = device;
32 return B_OK;
33 }
34
35
36 static void
virtio_device_uninit(void * _device)37 virtio_device_uninit(void *_device)
38 {
39 CALLED();
40 VirtioDevice *device = (VirtioDevice *)_device;
41 delete device;
42 }
43
44
45 static void
virtio_device_removed(void * _device)46 virtio_device_removed(void *_device)
47 {
48 CALLED();
49 //VirtioDevice *device = (VirtioDevice *)_device;
50 }
51
52
53 // #pragma mark -
54
55
56 status_t
virtio_negotiate_features(void * _device,uint64 supported,uint64 * negotiated,const char * (* get_feature_name)(uint64))57 virtio_negotiate_features(void* _device, uint64 supported,
58 uint64* negotiated, const char* (*get_feature_name)(uint64))
59 {
60 CALLED();
61 VirtioDevice *device = (VirtioDevice *)_device;
62
63 return device->NegotiateFeatures(supported, negotiated, get_feature_name);
64 }
65
66
67 status_t
virtio_clear_feature(void * _device,uint64 feature)68 virtio_clear_feature(void* _device, uint64 feature)
69 {
70 CALLED();
71 VirtioDevice *device = (VirtioDevice *)_device;
72
73 return device->ClearFeature(feature);
74 }
75
76
77 status_t
virtio_read_device_config(void * _device,uint8 offset,void * buffer,size_t bufferSize)78 virtio_read_device_config(void* _device, uint8 offset, void* buffer,
79 size_t bufferSize)
80 {
81 CALLED();
82 VirtioDevice *device = (VirtioDevice *)_device;
83
84 return device->ReadDeviceConfig(offset, buffer, bufferSize);
85 }
86
87
88 status_t
virtio_write_device_config(void * _device,uint8 offset,const void * buffer,size_t bufferSize)89 virtio_write_device_config(void* _device, uint8 offset,
90 const void* buffer, size_t bufferSize)
91 {
92 CALLED();
93 VirtioDevice *device = (VirtioDevice *)_device;
94
95 return device->WriteDeviceConfig(offset, buffer, bufferSize);
96 }
97
98
99 status_t
virtio_alloc_queues(virtio_device _device,size_t count,virtio_queue * queues,uint16 * requestedSizes)100 virtio_alloc_queues(virtio_device _device, size_t count, virtio_queue *queues,
101 uint16 *requestedSizes)
102 {
103 CALLED();
104 VirtioDevice *device = (VirtioDevice *)_device;
105 return device->AllocateQueues(count, queues, requestedSizes);
106 }
107
108
109 void
virtio_free_queues(virtio_device _device)110 virtio_free_queues(virtio_device _device)
111 {
112 CALLED();
113 VirtioDevice *device = (VirtioDevice *)_device;
114 device->FreeQueues();
115 }
116
117
118 status_t
virtio_setup_interrupt(virtio_device _device,virtio_intr_func config_handler,void * driverCookie)119 virtio_setup_interrupt(virtio_device _device, virtio_intr_func config_handler,
120 void *driverCookie)
121 {
122 CALLED();
123 VirtioDevice *device = (VirtioDevice *)_device;
124 return device->SetupInterrupt(config_handler, driverCookie);
125 }
126
127
128 status_t
virtio_free_interrupts(virtio_device _device)129 virtio_free_interrupts(virtio_device _device)
130 {
131 CALLED();
132 VirtioDevice *device = (VirtioDevice *)_device;
133 return device->FreeInterrupts();
134 }
135
136
137 status_t
virtio_queue_setup_interrupt(virtio_queue _queue,virtio_callback_func handler,void * cookie)138 virtio_queue_setup_interrupt(virtio_queue _queue, virtio_callback_func handler,
139 void *cookie)
140 {
141 CALLED();
142 VirtioQueue *queue = (VirtioQueue *)_queue;
143 return queue->SetupInterrupt(handler, cookie);
144 }
145
146
147 status_t
virtio_queue_request_v(virtio_queue _queue,const physical_entry * vector,size_t readVectorCount,size_t writtenVectorCount,void * cookie)148 virtio_queue_request_v(virtio_queue _queue, const physical_entry* vector,
149 size_t readVectorCount, size_t writtenVectorCount, void *cookie)
150 {
151 CALLED();
152 VirtioQueue *queue = (VirtioQueue *)_queue;
153 return queue->QueueRequest(vector, readVectorCount, writtenVectorCount,
154 cookie);
155 }
156
157
158 status_t
virtio_queue_request(virtio_queue _queue,const physical_entry * readEntry,const physical_entry * writtenEntry,void * cookie)159 virtio_queue_request(virtio_queue _queue, const physical_entry *readEntry,
160 const physical_entry *writtenEntry, void *cookie)
161 {
162 physical_entry entries[2];
163 if (readEntry != NULL) {
164 entries[0] = *readEntry;
165 if (writtenEntry != NULL)
166 entries[1] = *writtenEntry;
167 } else if (writtenEntry != NULL)
168 entries[0] = *writtenEntry;
169
170 return virtio_queue_request_v(_queue, entries, readEntry != NULL ? 1 : 0,
171 writtenEntry != NULL? 1 : 0, cookie);
172 }
173
174
175 bool
virtio_queue_is_full(virtio_queue _queue)176 virtio_queue_is_full(virtio_queue _queue)
177 {
178 VirtioQueue *queue = (VirtioQueue *)_queue;
179 return queue->IsFull();
180 }
181
182
183 bool
virtio_queue_is_empty(virtio_queue _queue)184 virtio_queue_is_empty(virtio_queue _queue)
185 {
186 VirtioQueue *queue = (VirtioQueue *)_queue;
187 return queue->IsEmpty();
188 }
189
190
191 uint16
virtio_queue_size(virtio_queue _queue)192 virtio_queue_size(virtio_queue _queue)
193 {
194 VirtioQueue *queue = (VirtioQueue *)_queue;
195 return queue->Size();
196 }
197
198
199 bool
virtio_queue_dequeue(virtio_queue _queue,void ** _cookie,uint32 * _usedLength)200 virtio_queue_dequeue(virtio_queue _queue, void** _cookie, uint32* _usedLength)
201 {
202 VirtioQueue *queue = (VirtioQueue *)_queue;
203 return queue->Dequeue(_cookie, _usedLength);
204 }
205
206
207 // #pragma mark -
208
209
210 status_t
virtio_added_device(device_node * parent)211 virtio_added_device(device_node *parent)
212 {
213 CALLED();
214
215 uint16 deviceType;
216 if (gDeviceManager->get_attr_uint16(parent,
217 VIRTIO_DEVICE_TYPE_ITEM, &deviceType, true) != B_OK) {
218 ERROR("device type missing\n");
219 return B_ERROR;
220 }
221
222 device_attr attributes[] = {
223 // info about device
224 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "virtio" }},
225 { VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
226 { .ui16 = deviceType }},
227 { NULL }
228 };
229
230 return gDeviceManager->register_node(parent, VIRTIO_DEVICE_MODULE_NAME,
231 attributes, NULL, NULL);
232 }
233
234
235 status_t
virtio_queue_interrupt_handler(virtio_sim sim,uint16 queue)236 virtio_queue_interrupt_handler(virtio_sim sim, uint16 queue)
237 {
238 VirtioDevice* device = (VirtioDevice*)sim;
239 return device->QueueInterrupt(queue);
240 }
241
242
243 status_t
virtio_config_interrupt_handler(virtio_sim sim)244 virtio_config_interrupt_handler(virtio_sim sim)
245 {
246 VirtioDevice* device = (VirtioDevice*)sim;
247 return device->ConfigInterrupt();
248 }
249
250
251 static status_t
std_ops(int32 op,...)252 std_ops(int32 op, ...)
253 {
254 switch (op) {
255 case B_MODULE_INIT:
256 case B_MODULE_UNINIT:
257 return B_OK;
258
259 default:
260 break;
261 }
262
263 return B_ERROR;
264 }
265
266
267 // #pragma mark -
268
269
270 virtio_device_interface virtio_device_module = {
271 {
272 {
273 VIRTIO_DEVICE_MODULE_NAME,
274 0,
275 std_ops
276 },
277
278 NULL, // supported devices
279 NULL, // register node
280 virtio_device_init,
281 virtio_device_uninit,
282 NULL, // register child devices
283 NULL, // rescan
284 virtio_device_removed,
285 NULL, // suspend
286 NULL, // resume
287 },
288
289 virtio_negotiate_features,
290 virtio_clear_feature,
291 virtio_read_device_config,
292 virtio_write_device_config,
293 virtio_alloc_queues,
294 virtio_free_queues,
295 virtio_setup_interrupt,
296 virtio_free_interrupts,
297 virtio_queue_setup_interrupt,
298 virtio_queue_request,
299 virtio_queue_request_v,
300 virtio_queue_is_full,
301 virtio_queue_is_empty,
302 virtio_queue_size,
303 virtio_queue_dequeue
304 };
305
306 virtio_for_controller_interface virtio_for_controller_module = {
307 {
308 {
309 VIRTIO_FOR_CONTROLLER_MODULE_NAME,
310 0,
311 &std_ops
312 },
313
314 NULL, // supported devices
315 virtio_added_device,
316 NULL,
317 NULL,
318 NULL
319 },
320
321 virtio_queue_interrupt_handler,
322 virtio_config_interrupt_handler
323 };
324
325
326 module_dependency module_dependencies[] = {
327 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
328 {}
329 };
330
331
332 extern struct driver_module_info sVirtioBalloonDriver;
333 extern struct driver_module_info sVirtioBalloonDeviceInterface;
334
335
336 module_info *modules[] = {
337 (module_info *)&virtio_for_controller_module,
338 (module_info *)&virtio_device_module,
339 (module_info *)&sVirtioBalloonDriver,
340 (module_info *)&sVirtioBalloonDeviceInterface,
341 NULL
342 };
343
344