win-pvdrivers

view xenpci/xenpci_export.c @ 1099:27bd2a5a4704

License change from GPL to BSD
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 13 13:38:31 2014 +1100 (2014-03-13)
parents 5be1f70687ad
children
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
4 Copyright (c) 2014, James Harper
5 All rights reserved.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 * Neither the name of James Harper nor the
15 names of its contributors may be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL JAMES HARPER BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
30 #include "xenpci.h"
31 #include <aux_klib.h>
33 ULONG
34 XnGetVersion() {
35 return 1;
36 }
38 VOID
39 XenPci_BackendStateCallback(char *path, PVOID context) {
40 PXENPCI_PDO_DEVICE_DATA xppdd = context;
41 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
42 PCHAR err;
43 PCHAR value;
44 ULONG backend_state;
45 ULONG frontend_state;
47 FUNCTION_ENTER();
48 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
49 FUNCTION_MSG("Read path=%s\n", path);
50 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
51 if (err) {
52 FUNCTION_MSG("Error %s\n", err);
53 XenPci_FreeMem(err);
54 /* this is pretty catastrophic... */
55 /* maybe call the callback with an unknown or something... or just ignore? */
56 FUNCTION_EXIT();
57 return;
58 }
59 FUNCTION_MSG("Read value=%s\n", value);
60 backend_state = atoi(value);
61 XenPci_FreeMem(value);
62 if (backend_state == XenbusStateClosing) {
63 /* check to see if transition to closing was initiated by backend */
64 CHAR frontend_state_path[128];
65 FUNCTION_MSG("backend path is closing. checking frontend path\n");
66 RtlStringCbCopyA(frontend_state_path, ARRAY_SIZE(frontend_state_path), xppdd->path);
67 RtlStringCbCatA(frontend_state_path, ARRAY_SIZE(frontend_state_path), "/state");
68 err = XenBus_Read(xpdd, XBT_NIL, frontend_state_path, &value);
69 if (err) {
70 FUNCTION_MSG("Error %s\n", err);
71 XenPci_FreeMem(err);
72 FUNCTION_EXIT();
73 return;
74 }
75 FUNCTION_MSG("Read value=%s\n", value);
76 frontend_state = atoi(value);
77 XenPci_FreeMem(value);
78 if (frontend_state == XenbusStateConnected) {
79 FUNCTION_MSG("initiated by backend. Requesting eject\n");
80 /* frontend is still connected. disconnection was initiated by backend */
81 WdfPdoRequestEject(xppdd->wdf_device);
82 }
83 }
84 xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_BACKEND_STATE, (PVOID)(ULONG_PTR)backend_state);
85 FUNCTION_EXIT();
86 }
88 XN_HANDLE
89 XnOpenDevice(PDEVICE_OBJECT pdo, PXN_DEVICE_CALLBACK callback, PVOID context) {
90 WDFDEVICE device;
91 PXENPCI_PDO_DEVICE_DATA xppdd;
92 PXENPCI_DEVICE_DATA xpdd;
93 PCHAR response;
94 CHAR path[128];
96 FUNCTION_ENTER();
97 device = WdfWdmDeviceGetWdfDeviceHandle(pdo);
98 if (!device) {
99 FUNCTION_MSG("Failed to get WDFDEVICE for %p\n", pdo);
100 return NULL;
101 }
102 xppdd = GetXppdd(device);
103 xpdd = xppdd->xpdd;
104 xppdd->device_callback = callback;
105 xppdd->device_callback_context = context;
106 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
107 response = XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
108 if (response) {
109 FUNCTION_MSG("XnAddWatch - %s = %s\n", path, response);
110 XenPci_FreeMem(response);
111 xppdd->device_callback = NULL;
112 xppdd->device_callback_context = NULL;
113 FUNCTION_EXIT();
114 return NULL;
115 }
117 FUNCTION_EXIT();
118 return xppdd;
119 }
121 VOID
122 XnCloseDevice(XN_HANDLE handle) {
123 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
124 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
125 PCHAR response;
126 CHAR path[128];
128 FUNCTION_ENTER();
129 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
130 response = XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
131 if (response) {
132 FUNCTION_MSG("XnRemWatch - %s = %s\n", path, response);
133 XenPci_FreeMem(response);
134 }
135 xppdd->device_callback = NULL;
136 xppdd->device_callback_context = NULL;
137 FUNCTION_EXIT();
138 return;
139 }
141 NTSTATUS
142 XnBindEvent(XN_HANDLE handle, evtchn_port_t *port, PXN_EVENT_CALLBACK callback, PVOID context) {
143 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
144 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
145 *port = EvtChn_AllocUnbound(xpdd, xppdd->backend_id);
146 return EvtChn_Bind(xpdd, *port, callback, context, EVT_ACTION_FLAGS_DEFAULT);
147 }
149 NTSTATUS
150 XnUnbindEvent(XN_HANDLE handle, evtchn_port_t port) {
151 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
152 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
153 EvtChn_Unbind(xpdd, port);
154 EvtChn_Close(xpdd, port);
155 return STATUS_SUCCESS;
156 }
158 grant_ref_t
159 XnGrantAccess(XN_HANDLE handle, uint32_t frame, int readonly, grant_ref_t ref, ULONG tag) {
160 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
161 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
162 return GntTbl_GrantAccess(xpdd, xppdd->backend_id, frame, readonly, ref, tag);
163 }
165 BOOLEAN
166 XnEndAccess(XN_HANDLE handle, grant_ref_t ref, BOOLEAN keepref, ULONG tag) {
167 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
168 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
169 return GntTbl_EndAccess(xpdd, ref, keepref, tag);
170 }
172 grant_ref_t
173 XnAllocateGrant(XN_HANDLE handle, ULONG tag) {
174 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
175 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
176 return GntTbl_GetRef(xpdd, tag);
177 }
179 VOID
180 XnFreeGrant(XN_HANDLE handle, grant_ref_t ref, ULONG tag) {
181 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
182 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
183 GntTbl_PutRef(xpdd, ref, tag);
184 }
186 /* result must be freed with XnFreeMem() */
187 NTSTATUS
188 XnReadString(XN_HANDLE handle, ULONG base, PCHAR path, PCHAR *value) {
189 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
190 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
191 PCHAR response;
192 CHAR full_path[1024];
194 switch(base) {
195 case XN_BASE_FRONTEND:
196 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->path);
197 break;
198 case XN_BASE_BACKEND:
199 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->backend_path);
200 break;
201 case XN_BASE_GLOBAL:
202 full_path[0] = 0;
203 }
204 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), "/");
205 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), path);
207 response = XenBus_Read(xpdd, XBT_NIL, full_path, value);
208 if (response) {
209 FUNCTION_MSG("Error reading %s - %s\n", full_path, response);
210 XenPci_FreeMem(response);
211 return STATUS_UNSUCCESSFUL;
212 }
213 return STATUS_SUCCESS;
214 }
216 NTSTATUS
217 XnWriteString(XN_HANDLE handle, ULONG base, PCHAR path, PCHAR value) {
218 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
219 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
220 PCHAR response;
221 CHAR full_path[1024];
223 switch(base) {
224 case XN_BASE_FRONTEND:
225 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->path);
226 break;
227 case XN_BASE_BACKEND:
228 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->backend_path);
229 break;
230 case XN_BASE_GLOBAL:
231 full_path[0] = 0;
232 }
233 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), "/");
234 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), path);
236 //FUNCTION_MSG("XnWriteString(%s, %s)\n", full_path, value);
237 response = XenBus_Write(xpdd, XBT_NIL, full_path, value);
238 if (response) {
239 FUNCTION_MSG("XnWriteString - %s = %s\n", full_path, response);
240 XenPci_FreeMem(response);
241 FUNCTION_EXIT();
242 return STATUS_UNSUCCESSFUL;
243 }
244 return STATUS_SUCCESS;
245 }
247 NTSTATUS
248 XnReadInt32(XN_HANDLE handle, ULONG base, PCHAR path, ULONG *value) {
249 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
250 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
251 CHAR full_path[1024];
252 PCHAR response;
253 PCHAR string_value;
255 switch(base) {
256 case XN_BASE_FRONTEND:
257 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->path);
258 break;
259 case XN_BASE_BACKEND:
260 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->backend_path);
261 break;
262 case XN_BASE_GLOBAL:
263 full_path[0] = 0;
264 }
265 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), "/");
266 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), path);
268 response = XenBus_Read(xpdd, XBT_NIL, full_path, &string_value);
269 if (response) {
270 FUNCTION_MSG("XnReadInt - %s = %s\n", full_path, response);
271 XenPci_FreeMem(response);
272 FUNCTION_EXIT();
273 return STATUS_UNSUCCESSFUL;
274 }
275 *value = atoi(string_value);
276 return STATUS_SUCCESS;
277 }
279 NTSTATUS
280 XnWriteInt32(XN_HANDLE handle, ULONG base, PCHAR path, ULONG value) {
281 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
282 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
283 CHAR full_path[1024];
284 PCHAR response;
286 switch(base) {
287 case XN_BASE_FRONTEND:
288 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->path);
289 break;
290 case XN_BASE_BACKEND:
291 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->backend_path);
292 break;
293 case XN_BASE_GLOBAL:
294 full_path[0] = 0;
295 }
296 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), "/");
297 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), path);
299 //FUNCTION_MSG("XnWriteInt32(%s, %d)\n", full_path, value);
300 response = XenBus_Printf(xpdd, XBT_NIL, full_path, "%d", value);
301 if (response) {
302 FUNCTION_MSG("XnWriteInt - %s = %s\n", full_path, response);
303 XenPci_FreeMem(response);
304 FUNCTION_EXIT();
305 return STATUS_UNSUCCESSFUL;
306 }
307 return STATUS_SUCCESS;
308 }
310 NTSTATUS
311 XnReadInt64(XN_HANDLE handle, ULONG base, PCHAR path, ULONGLONG *value) {
312 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
313 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
314 CHAR full_path[1024];
315 PCHAR response;
316 PCHAR string_value;
317 PCHAR ptr;
319 switch(base) {
320 case XN_BASE_FRONTEND:
321 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->path);
322 break;
323 case XN_BASE_BACKEND:
324 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->backend_path);
325 break;
326 case XN_BASE_GLOBAL:
327 full_path[0] = 0;
328 }
329 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), "/");
330 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), path);
332 response = XenBus_Read(xpdd, XBT_NIL, full_path, &string_value);
333 if (response) {
334 FUNCTION_MSG("XnReadInt - %s = %s\n", full_path, response);
335 XenPci_FreeMem(response);
336 FUNCTION_EXIT();
337 return STATUS_UNSUCCESSFUL;
338 }
339 *value = 0;
340 for (ptr = string_value; *ptr && *ptr >= '0' && *ptr <= '9'; ptr++) {
341 *value *= 10;
342 *value += (*ptr) - '0';
343 }
344 return STATUS_SUCCESS;
345 }
347 NTSTATUS
348 XnWriteInt64(XN_HANDLE handle, ULONG base, PCHAR path, ULONGLONG value) {
349 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
350 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
351 CHAR full_path[1024];
352 PCHAR response;
354 switch(base) {
355 case XN_BASE_FRONTEND:
356 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->path);
357 break;
358 case XN_BASE_BACKEND:
359 RtlStringCbCopyA(full_path, ARRAY_SIZE(full_path), xppdd->backend_path);
360 break;
361 case XN_BASE_GLOBAL:
362 full_path[0] = 0;
363 }
364 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), "/");
365 RtlStringCbCatA(full_path, ARRAY_SIZE(full_path), path);
367 response = XenBus_Printf(xpdd, XBT_NIL, full_path, "%I64d", value);
368 if (response) {
369 FUNCTION_MSG("XnWriteInt - %s = %s\n", full_path, response);
370 XenPci_FreeMem(response);
371 FUNCTION_EXIT();
372 return STATUS_UNSUCCESSFUL;
373 }
374 return STATUS_SUCCESS;
375 }
377 NTSTATUS
378 XnNotify(XN_HANDLE handle, evtchn_port_t port) {
379 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
380 PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
381 return EvtChn_Notify(xpdd, port);
382 }
384 /* called at PASSIVE_LEVEL */
385 VOID
386 XnGetValue(XN_HANDLE handle, ULONG value_type, PVOID value) {
387 PXENPCI_PDO_DEVICE_DATA xppdd = handle;
388 //PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
389 DECLARE_UNICODE_STRING_SIZE(my_device_name, 128);
390 ULONG i;
392 switch (value_type) {
393 case XN_VALUE_TYPE_QEMU_HIDE_FLAGS:
394 *(PULONG)value = (ULONG)qemu_hide_flags_value;
395 break;
396 case XN_VALUE_TYPE_QEMU_FILTER:
397 *(PULONG)value = FALSE;
398 RtlUnicodeStringPrintf(&my_device_name, L"#%S#", xppdd->device);
399 for (i = 0; i < WdfCollectionGetCount(qemu_hide_devices); i++) {
400 WDFSTRING wdf_string = WdfCollectionGetItem(qemu_hide_devices, i);
401 UNICODE_STRING hide_device_name;
402 WdfStringGetUnicodeString(wdf_string, &hide_device_name);
403 if (RtlCompareUnicodeString(&hide_device_name, &my_device_name, TRUE) != 0) {
404 *(PULONG)value = TRUE;
405 break;
406 }
407 }
408 break;
409 default:
410 FUNCTION_MSG("GetValue unknown type %d\n", value_type);
411 break;
412 }
413 }
415 PVOID
416 XnGetHypercallStubs() {
417 return hypercall_stubs;
418 }
420 VOID
421 XnSetHypercallStubs(PVOID _hypercall_stubs) {
422 hypercall_stubs = _hypercall_stubs;
423 }
425 NTSTATUS
426 XnDebugPrint(PCHAR format, ...) {
427 NTSTATUS status;
428 va_list args;
430 va_start(args, format);
431 status = XenPci_DebugPrintV(format, args);
432 va_end(args);
434 return status;
435 }
437 VOID
438 XnPrintDump() {
439 KBUGCHECK_DATA bugcheck_data;
441 bugcheck_data.BugCheckDataSize = sizeof(bugcheck_data);
442 AuxKlibGetBugCheckData(&bugcheck_data);
443 if (bugcheck_data.BugCheckCode != 0) {
444 /* use XnDebugPrint so this gets printed even not in debug mode */
445 XnDebugPrint("Bug check 0x%08x (0x%p, 0x%p, 0x%p, 0x%p)\n", bugcheck_data.BugCheckCode, bugcheck_data.Parameter1, bugcheck_data.Parameter2, bugcheck_data.Parameter3, bugcheck_data.Parameter4);
446 }
447 }
449 ULONG
450 XnTmemOp(struct tmem_op *tmem_op) {
451 return HYPERVISOR_tmem_op(tmem_op);