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