xref: /haiku/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp (revision 52c4471a3024d2eb81fe88e2c3982b9f8daa5e56)
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, uint32 supported,
58 		uint32* negotiated, const char* (*get_feature_name)(uint32))
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, uint32 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 {
102 	CALLED();
103 	VirtioDevice *device = (VirtioDevice *)_device;
104 	return device->AllocateQueues(count, queues);
105 }
106 
107 
108 void
109 virtio_free_queues(virtio_device _device)
110 {
111 	CALLED();
112 	VirtioDevice *device = (VirtioDevice *)_device;
113 	device->FreeQueues();
114 }
115 
116 
117 status_t
118 virtio_setup_interrupt(virtio_device _device, virtio_intr_func config_handler,
119 	void *driverCookie)
120 {
121 	CALLED();
122 	VirtioDevice *device = (VirtioDevice *)_device;
123 	return device->SetupInterrupt(config_handler, driverCookie);
124 }
125 
126 
127 status_t
128 virtio_free_interrupts(virtio_device _device)
129 {
130 	CALLED();
131 	VirtioDevice *device = (VirtioDevice *)_device;
132 	return device->FreeInterrupts();
133 }
134 
135 
136 status_t
137 virtio_queue_setup_interrupt(virtio_queue _queue, virtio_callback_func handler,
138 	void *cookie)
139 {
140 	CALLED();
141 	VirtioQueue *queue = (VirtioQueue *)_queue;
142 	return queue->SetupInterrupt(handler, cookie);
143 }
144 
145 
146 status_t
147 virtio_queue_request_v(virtio_queue _queue, const physical_entry* vector,
148 		size_t readVectorCount, size_t writtenVectorCount, void *cookie)
149 {
150 	CALLED();
151 	VirtioQueue *queue = (VirtioQueue *)_queue;
152 	return queue->QueueRequest(vector, readVectorCount, writtenVectorCount,
153 		cookie);
154 }
155 
156 
157 status_t
158 virtio_queue_request(virtio_queue _queue, const physical_entry *readEntry,
159 		const physical_entry *writtenEntry, void *cookie)
160 {
161 	physical_entry entries[2];
162 	if (readEntry != NULL) {
163 		entries[0] = *readEntry;
164 		if (writtenEntry != NULL)
165 			entries[1] = *writtenEntry;
166 	} else if (writtenEntry != NULL)
167 		entries[0] = *writtenEntry;
168 
169 	return virtio_queue_request_v(_queue, entries, readEntry != NULL ? 1 : 0,
170 		writtenEntry != NULL? 1 : 0, cookie);
171 }
172 
173 
174 bool
175 virtio_queue_is_full(virtio_queue _queue)
176 {
177 	VirtioQueue *queue = (VirtioQueue *)_queue;
178 	return queue->IsFull();
179 }
180 
181 
182 bool
183 virtio_queue_is_empty(virtio_queue _queue)
184 {
185 	VirtioQueue *queue = (VirtioQueue *)_queue;
186 	return queue->IsEmpty();
187 }
188 
189 
190 uint16
191 virtio_queue_size(virtio_queue _queue)
192 {
193 	VirtioQueue *queue = (VirtioQueue *)_queue;
194 	return queue->Size();
195 }
196 
197 
198 bool
199 virtio_queue_dequeue(virtio_queue _queue, void** _cookie, uint32* _usedLength)
200 {
201 	VirtioQueue *queue = (VirtioQueue *)_queue;
202 	return queue->Dequeue(_cookie, _usedLength);
203 }
204 
205 
206 //	#pragma mark -
207 
208 
209 status_t
210 virtio_added_device(device_node *parent)
211 {
212 	CALLED();
213 
214 	uint16 deviceType;
215 	if (gDeviceManager->get_attr_uint16(parent,
216 		VIRTIO_DEVICE_TYPE_ITEM, &deviceType, true) != B_OK) {
217 		ERROR("device type missing\n");
218 		return B_ERROR;
219 	}
220 
221 	device_attr attributes[] = {
222 		// info about device
223 		{ B_DEVICE_BUS, B_STRING_TYPE, { .string = "virtio" }},
224 		{ VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
225 			{ .ui16 = deviceType }},
226 		{ NULL }
227 	};
228 
229 	return gDeviceManager->register_node(parent, VIRTIO_DEVICE_MODULE_NAME,
230 		attributes, NULL, NULL);
231 }
232 
233 
234 status_t
235 virtio_queue_interrupt_handler(virtio_sim sim, uint16 queue)
236 {
237 	VirtioDevice* device = (VirtioDevice*)sim;
238 	return device->QueueInterrupt(queue);
239 }
240 
241 
242 status_t
243 virtio_config_interrupt_handler(virtio_sim sim)
244 {
245 	VirtioDevice* device = (VirtioDevice*)sim;
246 	return device->ConfigInterrupt();
247 }
248 
249 
250 static status_t
251 std_ops(int32 op, ...)
252 {
253 	switch (op) {
254 		case B_MODULE_INIT:
255 		case B_MODULE_UNINIT:
256 			return B_OK;
257 
258 		default:
259 			break;
260 	}
261 
262 	return B_ERROR;
263 }
264 
265 
266 //	#pragma mark -
267 
268 
269 virtio_device_interface virtio_device_module = {
270 	{
271 		{
272 			VIRTIO_DEVICE_MODULE_NAME,
273 			0,
274 			std_ops
275 		},
276 
277 		NULL, // supported devices
278 		NULL, // register node
279 		virtio_device_init,
280 		virtio_device_uninit,
281 		NULL, // register child devices
282 		NULL, // rescan
283 		virtio_device_removed,
284 		NULL, // suspend
285 		NULL, // resume
286 	},
287 
288 	virtio_negotiate_features,
289 	virtio_clear_feature,
290 	virtio_read_device_config,
291 	virtio_write_device_config,
292 	virtio_alloc_queues,
293 	virtio_free_queues,
294 	virtio_setup_interrupt,
295 	virtio_free_interrupts,
296 	virtio_queue_setup_interrupt,
297 	virtio_queue_request,
298 	virtio_queue_request_v,
299 	virtio_queue_is_full,
300 	virtio_queue_is_empty,
301 	virtio_queue_size,
302 	virtio_queue_dequeue
303 };
304 
305 virtio_for_controller_interface virtio_for_controller_module = {
306 	{
307 		{
308 			VIRTIO_FOR_CONTROLLER_MODULE_NAME,
309 			0,
310 			&std_ops
311 		},
312 
313 		NULL, // supported devices
314 		virtio_added_device,
315 		NULL,
316 		NULL,
317 		NULL
318 	},
319 
320 	virtio_queue_interrupt_handler,
321 	virtio_config_interrupt_handler
322 };
323 
324 
325 module_dependency module_dependencies[] = {
326 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
327 	{}
328 };
329 
330 
331 extern struct driver_module_info sVirtioBalloonDriver;
332 extern struct driver_module_info sVirtioBalloonDeviceInterface;
333 
334 
335 module_info *modules[] = {
336 	(module_info *)&virtio_for_controller_module,
337 	(module_info *)&virtio_device_module,
338 	(module_info *)&sVirtioBalloonDriver,
339 	(module_info *)&sVirtioBalloonDeviceInterface,
340 	NULL
341 };
342 
343