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