xref: /haiku/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp (revision 9a6a20d4689307142a7ed26a1437ba47e244e73f)
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
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
37 virtio_device_uninit(void *_device)
38 {
39 	CALLED();
40 	VirtioDevice *device = (VirtioDevice *)_device;
41 	delete device;
42 }
43 
44 
45 static void
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
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
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
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
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
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
110 virtio_free_queues(virtio_device _device)
111 {
112 	CALLED();
113 	VirtioDevice *device = (VirtioDevice *)_device;
114 	device->FreeQueues();
115 }
116 
117 
118 status_t
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
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
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
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
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
176 virtio_queue_is_full(virtio_queue _queue)
177 {
178 	VirtioQueue *queue = (VirtioQueue *)_queue;
179 	return queue->IsFull();
180 }
181 
182 
183 bool
184 virtio_queue_is_empty(virtio_queue _queue)
185 {
186 	VirtioQueue *queue = (VirtioQueue *)_queue;
187 	return queue->IsEmpty();
188 }
189 
190 
191 uint16
192 virtio_queue_size(virtio_queue _queue)
193 {
194 	VirtioQueue *queue = (VirtioQueue *)_queue;
195 	return queue->Size();
196 }
197 
198 
199 bool
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
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
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
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
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