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