xref: /haiku/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp (revision 225b6382637a7346d5378ee45a6581b4e2616055)
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* configCookie)
100 {
101 	CALLED();
102 	VirtioDevice *device = (VirtioDevice *)cookie;
103 	return device->SetupInterrupt(config_handler, configCookie);
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 //	#pragma mark -
138 
139 
140 status_t
141 virtio_added_device(device_node *parent)
142 {
143 	CALLED();
144 
145 	uint16 deviceType;
146 	if (gDeviceManager->get_attr_uint16(parent,
147 		VIRTIO_DEVICE_TYPE_ITEM, &deviceType, true) != B_OK) {
148 		ERROR("device type missing\n");
149 		return B_ERROR;
150 	}
151 
152 	device_attr attributes[] = {
153 		// info about device
154 		{ B_DEVICE_BUS, B_STRING_TYPE, { string: "virtio" }},
155 		{ VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE,
156 			{ ui16: deviceType }},
157 		{ NULL }
158 	};
159 
160 	return gDeviceManager->register_node(parent, VIRTIO_DEVICE_MODULE_NAME,
161 		attributes, NULL, NULL);
162 }
163 
164 
165 status_t
166 virtio_queue_interrupt_handler(virtio_sim sim, uint16 queue)
167 {
168 	VirtioDevice* device = (VirtioDevice*)sim;
169 	return device->QueueInterrupt(queue);
170 }
171 
172 
173 status_t
174 virtio_config_interrupt_handler(virtio_sim sim)
175 {
176 	VirtioDevice* device = (VirtioDevice*)sim;
177 	return device->ConfigInterrupt();
178 }
179 
180 
181 static status_t
182 std_ops(int32 op, ...)
183 {
184 	switch (op) {
185 		case B_MODULE_INIT:
186 		case B_MODULE_UNINIT:
187 			return B_OK;
188 
189 		default:
190 			break;
191 	}
192 
193 	return B_ERROR;
194 }
195 
196 
197 //	#pragma mark -
198 
199 
200 virtio_device_interface virtio_device_module = {
201 	{
202 		{
203 			VIRTIO_DEVICE_MODULE_NAME,
204 			0,
205 			std_ops
206 		},
207 
208 		NULL, // supported devices
209 		NULL, // register node
210 		virtio_device_init,
211 		virtio_device_uninit,
212 		NULL, // register child devices
213 		NULL, // rescan
214 		virtio_device_removed,
215 		NULL, // suspend
216 		NULL, // resume
217 	},
218 
219 	virtio_negociate_features,
220 	virtio_read_device_config,
221 	virtio_write_device_config,
222 	virtio_alloc_queues,
223 	virtio_setup_interrupt,
224 	virtio_queue_request,
225 	virtio_queue_request_v
226 };
227 
228 virtio_for_controller_interface virtio_for_controller_module = {
229 	{
230 		{
231 			VIRTIO_FOR_CONTROLLER_MODULE_NAME,
232 			0,
233 			&std_ops
234 		},
235 
236 		NULL, // supported devices
237 		virtio_added_device,
238 		NULL,
239 		NULL,
240 		NULL
241 	},
242 
243 	virtio_queue_interrupt_handler,
244 	virtio_config_interrupt_handler
245 };
246 
247 
248 module_dependency module_dependencies[] = {
249 	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
250 	{}
251 };
252 
253 module_info *modules[] = {
254 	(module_info *)&virtio_for_controller_module,
255 	(module_info *)&virtio_device_module,
256 	NULL
257 };
258 
259