win-pvdrivers

view xenpci/xenpci_pdo.c @ 497:312a41f82b8f

Updated to support the proposed patches to qemu from Steven Smith on ~20081216
author James Harper <james.harper@bendigoit.com.au>
date Fri Dec 19 22:08:17 2008 +1100 (2008-12-19)
parents a6e3f76419c3
children cb0b2da68686
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
21 #include <stdlib.h>
22 #include <io/ring.h>
24 #pragma warning(disable : 4200) // zero-sized array
25 #pragma warning(disable: 4127) // conditional expression is constant
27 NTSTATUS
28 XenPci_Power_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
29 {
30 NTSTATUS status;
31 PIO_STACK_LOCATION stack;
32 POWER_STATE_TYPE power_type;
33 POWER_STATE power_state;
34 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
35 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
37 UNREFERENCED_PARAMETER(device_object);
39 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
41 stack = IoGetCurrentIrpStackLocation(irp);
42 power_type = stack->Parameters.Power.Type;
43 power_state = stack->Parameters.Power.State;
45 switch (stack->MinorFunction)
46 {
47 case IRP_MN_POWER_SEQUENCE:
48 //KdPrint((__DRIVER_NAME " IRP_MN_POWER_SEQUENCE\n"));
49 status = STATUS_NOT_SUPPORTED;
50 break;
51 case IRP_MN_QUERY_POWER:
52 //KdPrint((__DRIVER_NAME " IRP_MN_QUERY_POWER\n"));
53 status = STATUS_SUCCESS;
54 break;
55 case IRP_MN_SET_POWER:
56 //KdPrint((__DRIVER_NAME " IRP_MN_SET_POWER\n"));
57 switch (power_type) {
58 case DevicePowerState:
59 PoSetPowerState(device_object, power_type, power_state);
60 status = STATUS_SUCCESS;
61 break;
62 case SystemPowerState:
63 status = STATUS_SUCCESS;
64 break;
65 default:
66 status = STATUS_NOT_SUPPORTED;
67 break;
68 }
69 break;
70 case IRP_MN_WAIT_WAKE:
71 //KdPrint((__DRIVER_NAME " IRP_MN_WAIT_WAKE\n"));
72 status = STATUS_NOT_SUPPORTED;
73 break;
74 default:
75 //KdPrint((__DRIVER_NAME " Unknown IRP_MN_%d\n", stack->MinorFunction));
76 status = STATUS_NOT_SUPPORTED;
77 break;
78 }
79 if (status != STATUS_NOT_SUPPORTED) {
80 irp->IoStatus.Status = status;
81 }
83 PoStartNextPowerIrp(irp);
84 status = irp->IoStatus.Status;
85 IoCompleteRequest(irp, IO_NO_INCREMENT);
87 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
89 return status;
90 }
92 /*
93 Called at PASSIVE_LEVEL(?)
94 Called during restore
95 */
97 static ULONG
98 XenPci_ReadBackendState(PXENPCI_PDO_DEVICE_DATA xppdd)
99 {
100 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
101 char path[128];
102 char *value;
103 char *err;
104 ULONG backend_state;
106 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
107 err = XenBus_Read(xpdd, XBT_NIL, path, &value);
108 if (err)
109 {
110 XenPci_FreeMem(err);
111 return XenbusStateUnknown;
112 }
113 else
114 {
115 backend_state = atoi(value);
116 XenPci_FreeMem(value);
117 return backend_state;
118 }
119 }
121 static VOID
122 XenPci_BackEndStateHandler(char *path, PVOID context)
123 {
124 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)context;
125 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
126 ULONG new_backend_state;
128 #if !DBG
129 UNREFERENCED_PARAMETER(path);
130 #endif
132 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
134 /* check that path == device/id/state */
135 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
136 new_backend_state = XenPci_ReadBackendState(xppdd);
137 if (new_backend_state == XenbusStateUnknown)
138 {
139 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
140 return;
141 KdPrint(("Failed to read %s, assuming closed\n", path));
142 new_backend_state = XenbusStateClosed;
143 }
145 if (xppdd->backend_state == new_backend_state)
146 {
147 KdPrint((__DRIVER_NAME " state unchanged\n"));
148 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
149 return;
150 }
152 xppdd->backend_state = new_backend_state;
154 switch (xppdd->backend_state)
155 {
156 case XenbusStateUnknown:
157 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
158 break;
160 case XenbusStateInitialising:
161 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
162 break;
164 case XenbusStateInitWait:
165 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
166 break;
168 case XenbusStateInitialised:
169 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
170 break;
172 case XenbusStateConnected:
173 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
174 break;
176 case XenbusStateClosing:
177 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
178 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
179 {
180 if (xppdd->common.device_usage_paging
181 || xppdd->common.device_usage_dump
182 || xppdd->common.device_usage_hibernation)
183 {
184 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
185 /* in use by page file, dump file, or hiber file - can't close */
186 /* we should probably re-check if the device usage changes in the future */
187 }
188 else
189 {
190 if (xppdd->common.current_pnp_state == Started)
191 {
192 KdPrint((__DRIVER_NAME " Sending RequestDeviceEject\n"));
193 IoRequestDeviceEject(xppdd->common.pdo);
194 }
195 else
196 {
197 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
198 }
199 }
200 }
201 break;
203 case XenbusStateClosed:
204 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
205 break;
207 default:
208 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
209 break;
210 }
212 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
214 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
216 return;
217 }
219 struct dummy_sring {
220 RING_IDX req_prod, req_event;
221 RING_IDX rsp_prod, rsp_event;
222 uint8_t pad[48];
223 };
225 /*
226 Called at PASSIVE_LEVEL
227 Called during restore
228 */
230 static NTSTATUS
231 XenPci_ChangeFrontendState(PXENPCI_PDO_DEVICE_DATA xppdd, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
232 {
233 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
234 LARGE_INTEGER timeout;
235 ULONG remaining;
236 ULONG thiswait;
237 char path[128];
239 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
241 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
242 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
244 remaining = maximum_wait_ms;
246 while (xppdd->backend_state != backend_state_response)
247 {
248 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
249 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
250 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
251 {
252 remaining -= thiswait;
253 if (remaining == 0)
254 {
255 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
256 return STATUS_UNSUCCESSFUL;
257 }
258 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
259 }
260 }
261 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
262 return STATUS_SUCCESS;
263 }
265 static VOID
266 DUMP_CURRENT_PNP_STATE(PXENPCI_PDO_DEVICE_DATA xppdd)
267 {
268 switch (xppdd->common.current_pnp_state)
269 {
270 case Unknown:
271 KdPrint((__DRIVER_NAME " pnp_state = Unknown\n"));
272 break;
273 case NotStarted:
274 KdPrint((__DRIVER_NAME " pnp_state = NotStarted\n"));
275 break;
276 case Started:
277 KdPrint((__DRIVER_NAME " pnp_state = Started\n"));
278 break;
279 case StopPending:
280 KdPrint((__DRIVER_NAME " pnp_state = StopPending\n"));
281 break;
282 case Stopped:
283 KdPrint((__DRIVER_NAME " pnp_state = Stopped\n"));
284 break;
285 case RemovePending:
286 KdPrint((__DRIVER_NAME " pnp_state = RemovePending\n"));
287 break;
288 case SurpriseRemovePending:
289 KdPrint((__DRIVER_NAME " pnp_state = SurpriseRemovePending\n"));
290 break;
291 case Removed:
292 KdPrint((__DRIVER_NAME " pnp_state = Removed\n"));
293 break;
294 default:
295 KdPrint((__DRIVER_NAME " pnp_state = ???\n"));
296 break;
297 }
298 }
300 static NTSTATUS
301 XenPci_EvtChn_Bind(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
302 {
303 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
304 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
306 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
307 }
309 static NTSTATUS
310 XenPci_EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
311 {
312 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
313 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
315 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
316 }
318 static NTSTATUS
319 XenPci_EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
320 {
321 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
322 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
324 return EvtChn_Unbind(xpdd, Port);
325 }
327 static NTSTATUS
328 XenPci_EvtChn_Mask(PVOID Context, evtchn_port_t Port)
329 {
330 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
331 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
333 return EvtChn_Mask(xpdd, Port);
334 }
336 static NTSTATUS
337 XenPci_EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
338 {
339 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
340 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
342 return EvtChn_Unmask(xpdd, Port);
343 }
345 static NTSTATUS
346 XenPci_EvtChn_Notify(PVOID Context, evtchn_port_t Port)
347 {
348 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
349 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
351 return EvtChn_Notify(xpdd, Port);
352 }
354 static BOOLEAN
355 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
356 {
357 PXENPCI_PDO_DEVICE_DATA xppdd = context;
358 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
360 return EvtChn_AckEvent(xpdd, port);
361 }
363 static grant_ref_t
364 XenPci_GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
365 {
366 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
367 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
369 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
370 }
372 static BOOLEAN
373 XenPci_GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref)
374 {
375 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
376 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
378 return GntTbl_EndAccess(xpdd, ref, keepref);
379 }
381 static VOID
382 XenPci_GntTbl_PutRef(PVOID Context, grant_ref_t ref)
383 {
384 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
385 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
387 GntTbl_PutRef(xpdd, ref);
388 }
390 static grant_ref_t
391 XenPci_GntTbl_GetRef(PVOID Context)
392 {
393 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
394 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
396 return GntTbl_GetRef(xpdd);
397 }
399 PCHAR
400 XenPci_XenBus_Read(PVOID Context, xenbus_transaction_t xbt, const char *path, char **value)
401 {
402 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
403 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
404 return XenBus_Read(xpdd, xbt, path, value);
405 }
407 PCHAR
408 XenPci_XenBus_Write(PVOID Context, xenbus_transaction_t xbt, const char *path, const char *value)
409 {
410 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
411 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
412 return XenBus_Write(xpdd, xbt, path, value);
413 }
415 PCHAR
416 XenPci_XenBus_Printf(PVOID Context, xenbus_transaction_t xbt, const char *path, const char *fmt, ...)
417 {
418 //PXENPCI_PDO_DEVICE_DATA xppdd = Context;
419 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
420 //return XenBus_Printf(xpdd, xbt, path, value);
421 UNREFERENCED_PARAMETER(Context);
422 UNREFERENCED_PARAMETER(xbt);
423 UNREFERENCED_PARAMETER(path);
424 UNREFERENCED_PARAMETER(fmt);
425 return NULL;
426 }
428 PCHAR
429 XenPci_XenBus_StartTransaction(PVOID Context, xenbus_transaction_t *xbt)
430 {
431 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
432 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
433 return XenBus_StartTransaction(xpdd, xbt);
434 }
436 PCHAR
437 XenPci_XenBus_EndTransaction(PVOID Context, xenbus_transaction_t xbt, int abort, int *retry)
438 {
439 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
440 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
441 return XenBus_EndTransaction(xpdd, xbt, abort, retry);
442 }
444 PCHAR
445 XenPci_XenBus_List(PVOID Context, xenbus_transaction_t xbt, const char *prefix, char ***contents)
446 {
447 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
448 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
449 return XenBus_List(xpdd, xbt, prefix, contents);
450 }
452 PCHAR
453 XenPci_XenBus_AddWatch(PVOID Context, xenbus_transaction_t xbt, const char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
454 {
455 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
456 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
457 PCHAR retval;
459 FUNCTION_ENTER();
460 retval = XenBus_AddWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
461 if (retval == NULL)
462 {
463 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = NULL\n", path));
464 }
465 else
466 {
467 KdPrint((__DRIVER_NAME " XenPci_XenBus_AddWatch - %s = %s\n", path, retval));
468 }
469 FUNCTION_EXIT();
470 return retval;
471 }
473 PCHAR
474 XenPci_XenBus_RemWatch(PVOID Context, xenbus_transaction_t xbt, const char *path, PXENBUS_WATCH_CALLBACK ServiceRoutine, PVOID ServiceContext)
475 {
476 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
477 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
478 return XenBus_RemWatch(xpdd, xbt, path, ServiceRoutine, ServiceContext);
479 }
481 static NTSTATUS
482 XenPci_XenShutdownDevice(PVOID Context)
483 {
484 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
485 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
486 PUCHAR in_ptr;
487 ULONG i;
488 UCHAR type;
489 PVOID setting;
490 PVOID value;
492 FUNCTION_ENTER();
494 if (xppdd->backend_state == XenbusStateConnected)
495 {
496 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
497 if (xppdd->backend_state == XenbusStateClosing)
498 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
499 if (xppdd->backend_state == XenbusStateClosed)
500 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
501 }
502 else
503 {
504 if (xppdd->backend_state == XenbusStateClosing)
505 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
506 }
508 if (xppdd->assigned_resources_start != NULL)
509 {
510 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
511 in_ptr = xppdd->assigned_resources_start;
512 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
513 {
514 switch (type)
515 {
516 case XEN_INIT_TYPE_RING: /* frontend ring */
517 FreePages(value);
518 break;
519 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
520 // don't know how to do this yet...
521 break;
522 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
523 EvtChn_Unbind(xpdd, PtrToUlong(value));
524 EvtChn_Close(xpdd, PtrToUlong(value));
525 break;
526 case XEN_INIT_TYPE_GRANT_ENTRIES:
527 for (i = 0; i < PtrToUlong(setting); i++)
528 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
529 break;
530 }
531 }
532 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
533 xppdd->assigned_resources_start = NULL;
534 }
536 FUNCTION_EXIT();
538 return STATUS_SUCCESS;
539 }
541 static NTSTATUS
542 XenPci_XenConfigDevice(PVOID context);
544 static NTSTATUS
545 XenPci_XenConfigDeviceSpecifyBuffers(PVOID context, PUCHAR src, PUCHAR dst)
546 {
547 PXENPCI_PDO_DEVICE_DATA xppdd = context;
548 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
549 NTSTATUS status = STATUS_SUCCESS;
550 ULONG i;
551 char path[128];
552 PCHAR setting, value;
553 PCHAR res;
554 PVOID address;
555 UCHAR type;
556 PUCHAR in_ptr; //, in_start;
557 PUCHAR out_ptr; //, out_start;
558 XENPCI_VECTORS vectors;
559 ULONG event_channel;
560 ULONG run_type = 0;
561 PMDL ring;
562 grant_ref_t gref;
563 BOOLEAN done_xenbus_init = FALSE;
565 FUNCTION_ENTER();
567 in_ptr = src;
568 out_ptr = dst;
570 // always add vectors
571 vectors.magic = XEN_DATA_MAGIC;
572 vectors.length = sizeof(XENPCI_VECTORS);
573 vectors.context = xppdd;
574 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
575 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
576 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
577 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
578 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
579 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
580 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
581 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
582 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
583 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
584 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
585 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
586 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
587 strncpy(vectors.path, xppdd->path, 128);
588 strncpy(vectors.backend_path, xppdd->backend_path, 128);
589 vectors.pdo_event_channel = xpdd->pdo_event_channel;
590 vectors.XenBus_Read = XenPci_XenBus_Read;
591 vectors.XenBus_Write = XenPci_XenBus_Write;
592 vectors.XenBus_Printf = XenPci_XenBus_Printf;
593 vectors.XenBus_StartTransaction = XenPci_XenBus_StartTransaction;
594 vectors.XenBus_EndTransaction = XenPci_XenBus_EndTransaction;
595 vectors.XenBus_List = XenPci_XenBus_List;
596 vectors.XenBus_AddWatch = XenPci_XenBus_AddWatch;
597 vectors.XenBus_RemWatch = XenPci_XenBus_RemWatch;
599 if (qemu_filtered)
600 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_ACTIVE, NULL, NULL);
602 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION, NULL, UlongToPtr(qemu_protocol_version));
604 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors);
605 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state);
607 // first pass, possibly before state == Connected
608 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
609 {
611 if (!done_xenbus_init)
612 {
613 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
614 {
615 status = STATUS_UNSUCCESSFUL;
616 goto error;
617 }
618 done_xenbus_init = TRUE;
619 }
621 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value);
623 switch (type)
624 {
625 case XEN_INIT_TYPE_RUN:
626 run_type++;
627 break;
628 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
629 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
630 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
631 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
632 break;
633 case XEN_INIT_TYPE_RING: /* frontend ring */
634 /* we only allocate and do the SHARED_RING_INIT here */
635 if ((ring = AllocatePage()) != 0)
636 {
637 address = MmGetMdlVirtualAddress(ring);
638 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
639 SHARED_RING_INIT((struct dummy_sring *)address);
640 if ((gref = GntTbl_GrantAccess(
641 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
642 {
643 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
644 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
645 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address);
646 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring);
647 // add the grant entry too so it gets freed automatically
648 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
649 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
650 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
651 }
652 else
653 {
654 FreePages(ring);
655 status = STATUS_UNSUCCESSFUL;
656 goto error;
657 }
658 }
659 else
660 {
661 status = STATUS_UNSUCCESSFUL;
662 goto error;
663 }
664 break;
665 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
666 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
667 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
668 {
669 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
670 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
671 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
672 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel));
673 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel));
674 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
675 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
676 }
677 else
678 {
679 status = STATUS_UNSUCCESSFUL;
680 goto error;
681 }
682 break;
683 }
684 }
685 if (!NT_SUCCESS(status))
686 {
687 goto error;
688 }
689 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
690 if (run_type == 1)
691 {
692 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
693 {
694 status = STATUS_UNSUCCESSFUL;
695 goto error;
696 }
697 }
699 // second pass, possibly after state == Connected
700 in_ptr = src;
701 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
702 {
703 switch(type)
704 {
705 case XEN_INIT_TYPE_READ_STRING_BACK:
706 case XEN_INIT_TYPE_READ_STRING_FRONT:
707 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
708 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
709 else
710 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
711 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
712 if (res)
713 {
714 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
715 XenPci_FreeMem(res);
716 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL);
717 }
718 else
719 {
720 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
721 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value);
722 XenPci_FreeMem(value);
723 }
724 break;
725 case XEN_INIT_TYPE_VECTORS:
726 // this is always done so ignore the request
727 break;
728 case XEN_INIT_TYPE_GRANT_ENTRIES:
729 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
730 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
731 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
732 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
733 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
734 for (i = 0; i < PtrToUlong(value); i++)
735 {
736 gref = GntTbl_GetRef(xpdd);
737 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
738 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
739 }
740 break;
741 }
742 }
743 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL);
745 if (run_type)
746 {
747 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
748 {
749 status = STATUS_UNSUCCESSFUL;
750 goto error;
751 }
752 }
753 FUNCTION_EXIT();
754 return status;
756 error:
757 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
758 FUNCTION_EXIT_STATUS(status);
760 return status;
761 }
763 static NTSTATUS
764 XenPci_XenConfigDevice(PVOID context)
765 {
766 NTSTATUS status;
767 PUCHAR src, dst;
768 PXENPCI_PDO_DEVICE_DATA xppdd = context;
770 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
771 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
772 memcpy(src, dst, xppdd->config_page_length);
774 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
776 MmUnmapIoSpace(dst, xppdd->config_page_length);
777 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
779 return status;
780 }
782 static NTSTATUS
783 XenPci_GetBackendAndAddWatch(PDEVICE_OBJECT device_object)
784 {
785 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
786 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
787 char path[128];
788 PCHAR res;
789 PCHAR value;
791 /* Get backend path */
792 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
793 "%s/backend", xppdd->path);
794 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
795 if (res)
796 {
797 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
798 XenPci_FreeMem(res);
799 return STATUS_UNSUCCESSFUL;
800 }
801 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
802 XenPci_FreeMem(value);
804 /* Add watch on backend state */
805 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
806 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
808 return STATUS_SUCCESS;
809 }
811 NTSTATUS
812 XenPci_Pdo_Resume(PDEVICE_OBJECT device_object)
813 {
814 NTSTATUS status;
815 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
816 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
817 ULONG old_backend_state;
818 PUCHAR src, dst;
820 FUNCTION_ENTER();
822 old_backend_state = xppdd->backend_state;
824 if (xppdd->restart_on_resume)
825 {
826 status = XenPci_GetBackendAndAddWatch(device_object);
828 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
829 {
830 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
831 // this is probably an unrecoverable situation...
832 FUNCTION_ERROR_EXIT();
833 return STATUS_UNSUCCESSFUL;
834 }
835 if (xppdd->assigned_resources_ptr)
836 {
837 // reset things - feed the 'requested resources' back in
838 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
839 src = xppdd->requested_resources_start;
840 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);;
841 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
843 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
845 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
847 MmUnmapIoSpace(dst, xppdd->config_page_length);
848 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
849 }
850 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
851 {
852 // this is definitely an unrecoverable situation...
853 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
854 FUNCTION_ERROR_EXIT();
855 return STATUS_UNSUCCESSFUL;
856 }
857 }
858 else
859 {
860 KdPrint((__DRIVER_NAME " Not resuming - current_pnp_state = %d, old_backend_state = %d\n", xppdd->common.current_pnp_state, old_backend_state));
861 }
862 KeMemoryBarrier();
863 xppdd->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
864 KeMemoryBarrier();
865 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
867 FUNCTION_EXIT();
869 return STATUS_SUCCESS;
870 }
872 /* called at PASSIVE_LEVEL */
873 NTSTATUS
874 XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object)
875 {
876 NTSTATUS status = STATUS_SUCCESS;
877 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
878 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
879 LARGE_INTEGER wait_time;
880 char path[128];
881 PUCHAR in_ptr;
882 UCHAR type;
883 PVOID setting;
884 PVOID value;
886 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
888 if (xppdd->backend_state == XenbusStateConnected)
889 {
890 xppdd->restart_on_resume = TRUE;
891 xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
892 KeMemoryBarrier();
893 xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
894 KeMemoryBarrier();
895 EvtChn_Notify(xpdd, xpdd->pdo_event_channel);
896 while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
897 {
898 KdPrint((__DRIVER_NAME " Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
899 wait_time.QuadPart = 100 * (-1 * 10 * 1000);
900 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
901 KdPrint((__DRIVER_NAME " Done with delay\n"));
902 }
903 KdPrint((__DRIVER_NAME " resume_state acknowledged\n"));
905 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
906 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
907 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
909 if (xppdd->assigned_resources_start != NULL)
910 {
911 in_ptr = xppdd->assigned_resources_ptr;
912 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL);
913 in_ptr = xppdd->assigned_resources_start;
914 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
915 {
916 switch (type)
917 {
918 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
919 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
920 EvtChn_Close(xpdd, PtrToUlong(value));
921 break;
922 }
923 }
924 }
926 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
927 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
928 }
929 else
930 {
931 xppdd->restart_on_resume = FALSE;
932 }
934 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
936 return status;
937 }
939 VOID
940 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object)
941 {
942 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
944 #if !DBG
945 UNREFERENCED_PARAMETER(xppdd);
946 #endif
948 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
949 KdPrint((__DRIVER_NAME " backend_path = %s\n", xppdd->backend_path));
950 KdPrint((__DRIVER_NAME " irq_number = %d\n", xppdd->irq_number));
951 KdPrint((__DRIVER_NAME " irq_level = %d\n", xppdd->irq_level));
952 KdPrint((__DRIVER_NAME " irq_vector = %x\n", xppdd->irq_vector));
953 }
955 static PMDL
956 XenConfig_MakeConfigPage(PDEVICE_OBJECT device_object)
957 {
958 //PXENCONFIG_DEVICE_DATA xcdd = (PXENCONFIG_DEVICE_DATA)device_object->DeviceExtension;
959 //PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
960 //PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
961 PMDL mdl;
962 PUCHAR ptr;
963 PDEVICE_OBJECT curr;
964 PDRIVER_OBJECT fdo_driver_object;
965 PUCHAR fdo_driver_extension;
967 mdl = AllocateUncachedPage();
968 ptr = MmGetMdlVirtualAddress(mdl);
969 curr = IoGetAttachedDeviceReference(device_object);
970 while (curr != NULL)
971 {
972 fdo_driver_object = curr->DriverObject;
973 KdPrint((__DRIVER_NAME " fdo_driver_object = %p\n", fdo_driver_object));
974 if (fdo_driver_object)
975 {
976 fdo_driver_extension = IoGetDriverObjectExtension(fdo_driver_object, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC));
977 KdPrint((__DRIVER_NAME " fdo_driver_extension = %p\n", fdo_driver_extension));
978 if (fdo_driver_extension)
979 {
980 memcpy(ptr, fdo_driver_extension, PAGE_SIZE);
981 break;
982 }
983 }
984 curr = IoGetLowerDeviceObject(curr);
985 }
986 return mdl;
987 }
989 static NTSTATUS
990 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
991 {
992 NTSTATUS status = STATUS_SUCCESS;
993 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
994 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
995 PIO_STACK_LOCATION stack;
996 PCM_PARTIAL_RESOURCE_LIST prl;
997 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
998 ULONG i;
999 char path[128];
1000 PMDL mdl;
1002 FUNCTION_ENTER();
1003 KdPrint((__DRIVER_NAME " %s\n", xppdd->path));
1005 DUMP_CURRENT_PNP_STATE(xppdd);
1007 stack = IoGetCurrentIrpStackLocation(irp);
1009 status = XenPci_GetBackendAndAddWatch(device_object);
1010 if (!NT_SUCCESS(status)) {
1011 FUNCTION_ERROR_EXIT();
1012 return status;
1015 mdl = XenConfig_MakeConfigPage(device_object);
1017 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
1018 for (i = 0; i < prl->Count; i++)
1020 prd = & prl->PartialDescriptors[i];
1021 switch (prd->Type)
1023 case CmResourceTypeInterrupt:
1024 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt\n"));
1025 KdPrint((__DRIVER_NAME " irq_number = %02x\n", prd->u.Interrupt.Vector));
1026 //KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
1027 xppdd->irq_number = prd->u.Interrupt.Vector;
1028 //xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
1029 break;
1030 case CmResourceTypeMemory:
1031 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart && prd->u.Memory.Length == 0)
1033 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
1034 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
1036 break;
1040 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
1041 for (i = 0; i < prl->Count; i++)
1043 prd = & prl->PartialDescriptors[i];
1044 switch (prd->Type)
1046 case CmResourceTypeInterrupt:
1047 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt (%d)\n", i));
1048 KdPrint((__DRIVER_NAME " irq_vector = %02x\n", prd->u.Interrupt.Vector));
1049 KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
1050 xppdd->irq_vector = prd->u.Interrupt.Vector;
1051 xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
1052 break;
1053 case CmResourceTypeMemory:
1054 KdPrint((__DRIVER_NAME " CmResourceTypeMemory (%d)\n", i));
1055 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1056 if (prd->u.Memory.Start.QuadPart == xpdd->platform_mmio_addr.QuadPart)
1058 if (prd->u.Memory.Length == 0)
1060 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
1061 prd->u.Memory.Length = MmGetMdlByteCount(mdl);
1062 KdPrint((__DRIVER_NAME " New Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1064 xppdd->config_page_phys = prd->u.Memory.Start;
1065 xppdd->config_page_length = prd->u.Memory.Length;
1066 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1067 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1069 status = XenPci_XenConfigDevice(xppdd);
1070 if (!NT_SUCCESS(status))
1072 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1073 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
1074 FUNCTION_ERROR_EXIT();
1075 return status;
1078 break;
1082 SET_PNP_STATE(&xppdd->common, Started);
1084 FUNCTION_EXIT();
1086 return STATUS_SUCCESS;
1089 static NTSTATUS
1090 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
1092 NTSTATUS status = STATUS_SUCCESS;
1093 PXENPCI_PDO_DEVICE_DATA xppdd = device_object->DeviceExtension;
1094 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1095 char path[128];
1097 UNREFERENCED_PARAMETER(irp);
1099 FUNCTION_ENTER();
1101 DUMP_CURRENT_PNP_STATE(xppdd);
1103 if (xppdd->common.current_pnp_state != Removed)
1105 status = XenPci_XenShutdownDevice(xppdd);
1106 /* Remove watch on backend state */
1107 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1108 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
1109 SET_PNP_STATE(&xppdd->common, Removed);
1110 IoInvalidateDeviceRelations(xppdd->bus_pdo, BusRelations);
1112 if (xppdd->reported_missing)
1114 IoDeleteDevice(xppdd->common.pdo);
1117 FUNCTION_EXIT_STATUS(status);
1119 return status;
1122 static NTSTATUS
1123 XenPci_QueryResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
1125 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1126 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1127 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
1128 PIO_RESOURCE_DESCRIPTOR ird;
1129 ULONG length;
1131 UNREFERENCED_PARAMETER(device_object);
1133 length = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
1134 FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) +
1135 sizeof(IO_RESOURCE_DESCRIPTOR) * 2;
1136 irrl = ExAllocatePoolWithTag(NonPagedPool,
1137 length,
1138 XENPCI_POOL_TAG);
1140 irrl->ListSize = length;
1141 irrl->InterfaceType = Internal;
1142 irrl->BusNumber = 0;
1143 irrl->SlotNumber = 0;
1144 irrl->AlternativeLists = 1;
1145 irrl->List[0].Version = 1;
1146 irrl->List[0].Revision = 1;
1147 irrl->List[0].Count = 0;
1149 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
1150 ird->Option = 0;
1151 ird->Type = CmResourceTypeInterrupt;
1152 ird->ShareDisposition = CmResourceShareShared;
1153 ird->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1154 ird->u.Interrupt.MinimumVector = xpdd->irq_number;
1155 ird->u.Interrupt.MaximumVector = xpdd->irq_number;
1157 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
1158 ird->Option = 0;
1159 ird->Type = CmResourceTypeMemory;
1160 ird->ShareDisposition = CmResourceShareShared;
1161 ird->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
1162 ird->u.Memory.MinimumAddress = xpdd->platform_mmio_addr;
1163 ird->u.Memory.MaximumAddress = xpdd->platform_mmio_addr;
1164 ird->u.Memory.Length = 0;
1165 ird->u.Memory.Alignment = PAGE_SIZE;
1167 irp->IoStatus.Information = (ULONG_PTR)irrl;
1168 return STATUS_SUCCESS;
1171 static NTSTATUS
1172 XenPci_Pnp_QueryTargetRelations(PDEVICE_OBJECT device_object, PIRP irp)
1174 PDEVICE_RELATIONS dr;
1175 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1177 dr = (PDEVICE_RELATIONS)ExAllocatePoolWithTag (PagedPool, sizeof(DEVICE_RELATIONS), XENPCI_POOL_TAG);
1178 dr->Count = 1;
1179 dr->Objects[0] = xppdd->common.pdo;
1180 ObReferenceObject(xppdd->common.pdo);
1181 irp->IoStatus.Information = (ULONG_PTR)dr;
1183 return STATUS_SUCCESS;
1186 static NTSTATUS
1187 XenPci_Pnp_QueryCapabilities(PDEVICE_OBJECT device_object, PIRP irp)
1189 PIO_STACK_LOCATION stack;
1190 PDEVICE_CAPABILITIES dc;
1192 UNREFERENCED_PARAMETER(device_object);
1194 stack = IoGetCurrentIrpStackLocation(irp);
1195 dc = stack->Parameters.DeviceCapabilities.Capabilities;
1196 dc->LockSupported = FALSE;
1197 dc->EjectSupported = TRUE;
1198 dc->Removable = TRUE;
1199 dc->DockDevice = FALSE;
1200 dc->UniqueID = FALSE;
1201 dc->SilentInstall = TRUE; //FALSE;
1202 dc->RawDeviceOK = FALSE;
1203 dc->SurpriseRemovalOK = TRUE;
1204 dc->HardwareDisabled = FALSE;
1205 dc->NoDisplayInUI = FALSE;
1206 dc->DeviceWake = PowerDeviceUnspecified;
1207 dc->D1Latency = 0;
1208 dc->D2Latency = 0;
1209 dc->D3Latency = 0;
1210 /* we are really supposed to get the DeviceState entries from the parent... */
1211 dc->DeviceState[PowerSystemWorking] = PowerDeviceD0;
1212 dc->DeviceState[PowerSystemSleeping1] = PowerDeviceUnspecified;
1213 dc->DeviceState[PowerSystemSleeping2] = PowerDeviceUnspecified;
1214 dc->DeviceState[PowerSystemSleeping3] = PowerDeviceUnspecified;
1215 dc->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1216 dc->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1217 return STATUS_SUCCESS;
1220 NTSTATUS
1221 XenPci_Pnp_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1223 NTSTATUS status;
1224 PIO_STACK_LOCATION stack;
1225 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1226 LPWSTR buffer;
1227 WCHAR widebuf[256];
1228 unsigned int i;
1229 PPNP_BUS_INFORMATION pbi;
1230 ULONG *usage_type;
1232 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1234 stack = IoGetCurrentIrpStackLocation(irp);
1236 switch (stack->MinorFunction)
1238 case IRP_MN_START_DEVICE:
1239 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1240 status = XenPci_Pnp_StartDevice(device_object, irp);
1241 break;
1243 case IRP_MN_QUERY_STOP_DEVICE:
1244 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1245 SET_PNP_STATE(&xppdd->common, StopPending);
1246 status = STATUS_SUCCESS;
1247 break;
1249 case IRP_MN_STOP_DEVICE:
1250 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1251 SET_PNP_STATE(&xppdd->common, Stopped);
1252 status = STATUS_SUCCESS;
1253 break;
1255 case IRP_MN_CANCEL_STOP_DEVICE:
1256 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1257 REVERT_PNP_STATE(&xppdd->common);
1258 status = STATUS_SUCCESS;
1259 break;
1261 case IRP_MN_QUERY_REMOVE_DEVICE:
1262 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1263 SET_PNP_STATE(&xppdd->common, RemovePending);
1264 status = STATUS_SUCCESS;
1265 break;
1267 case IRP_MN_REMOVE_DEVICE:
1268 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1269 status = XenPci_Pnp_RemoveDevice(device_object, irp);
1270 break;
1272 case IRP_MN_CANCEL_REMOVE_DEVICE:
1273 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1274 REVERT_PNP_STATE(&xppdd->common);
1275 status = STATUS_SUCCESS;
1276 break;
1278 case IRP_MN_SURPRISE_REMOVAL:
1279 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL (status = %08x)\n", irp->IoStatus.Status));
1280 SET_PNP_STATE(&xppdd->common, SurpriseRemovePending);
1281 status = STATUS_SUCCESS;
1282 break;
1284 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1285 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION (status = %08x)\n", irp->IoStatus.Status));
1287 usage_type = NULL;
1288 switch (stack->Parameters.UsageNotification.Type)
1290 case DeviceUsageTypePaging:
1291 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging\n"));
1292 usage_type = &xppdd->common.device_usage_paging;
1293 break;
1294 case DeviceUsageTypeDumpFile:
1295 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile\n"));
1296 usage_type = &xppdd->common.device_usage_dump;
1297 break;
1298 case DeviceUsageTypeHibernation:
1299 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation\n"));
1300 usage_type = &xppdd->common.device_usage_hibernation;
1301 break;
1302 default:
1303 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
1304 stack->Parameters.UsageNotification.Type));
1305 break;
1307 KdPrint((__DRIVER_NAME " inpath = %d\n", stack->Parameters.UsageNotification.InPath));
1308 if (usage_type)
1310 if (stack->Parameters.UsageNotification.InPath)
1311 (*usage_type)++;
1312 else
1313 (*usage_type)--;
1315 status = STATUS_SUCCESS;
1316 break;
1318 case IRP_MN_QUERY_ID:
1319 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_ID (status = %08x)\n", irp->IoStatus.Status));
1320 switch (stack->Parameters.QueryId.IdType)
1322 case BusQueryDeviceID: /* REG_SZ */
1323 KdPrint((__DRIVER_NAME " BusQueryDeviceID\n"));
1324 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1325 for (i = 0; i < strlen(xppdd->device); i++)
1326 widebuf[i] = xppdd->device[i];
1327 widebuf[i] = 0;
1328 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
1329 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1330 irp->IoStatus.Information = (ULONG_PTR)buffer;
1331 status = STATUS_SUCCESS;
1332 break;
1333 case BusQueryHardwareIDs: /* REG_MULTI_SZ */
1334 KdPrint((__DRIVER_NAME " BusQueryHardwareIDs\n"));
1335 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1336 for (i = 0; i < strlen(xppdd->device); i++)
1337 widebuf[i] = xppdd->device[i];
1338 widebuf[i] = 0;
1339 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
1340 for (i = 0; buffer[i] != 0; i++);
1341 buffer[i + 1] = 0;
1342 // for (i = 0; i < 256; i++)
1343 // KdPrint((__DRIVER_NAME " %04X: %04X %wc\n", i, buffer[i], buffer[i]));
1344 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1345 irp->IoStatus.Information = (ULONG_PTR)buffer;
1346 status = STATUS_SUCCESS;
1347 break;
1348 case BusQueryCompatibleIDs: /* REG_MULTI_SZ */
1349 KdPrint((__DRIVER_NAME " BusQueryCompatibleIDs\n"));
1350 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1351 for (i = 0; i < strlen(xppdd->device); i++)
1352 widebuf[i] = xppdd->device[i];
1353 widebuf[i] = 0;
1354 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
1355 for (i = 0; buffer[i] != 0; i++);
1356 buffer[i + 1] = 0;
1357 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1358 irp->IoStatus.Information = (ULONG_PTR)buffer;
1359 status = STATUS_SUCCESS;
1360 break;
1361 case BusQueryInstanceID: /* REG_SZ */
1362 KdPrint((__DRIVER_NAME " BusQueryInstanceID\n"));
1363 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1364 RtlStringCbPrintfW(buffer, 512, L"%02d", xppdd->index);
1365 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1366 irp->IoStatus.Information = (ULONG_PTR)buffer;
1367 status = STATUS_SUCCESS;
1368 break;
1369 default:
1370 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryId.IdType));
1371 irp->IoStatus.Information = 0;
1372 status = STATUS_NOT_SUPPORTED;
1373 break;
1375 break;
1377 case IRP_MN_QUERY_DEVICE_TEXT:
1378 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_TEXT (status = %08x)\n", irp->IoStatus.Status));
1379 switch (stack->Parameters.QueryDeviceText.DeviceTextType)
1381 case DeviceTextDescription:
1382 KdPrint((__DRIVER_NAME " DeviceTextDescription\n"));
1383 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1384 for (i = 0; i < strlen(xppdd->device); i++)
1385 widebuf[i] = xppdd->device[i];
1386 widebuf[i] = 0;
1387 RtlStringCbPrintfW(buffer, 512, L"Xen %ws device #%d", widebuf, xppdd->index);
1388 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1389 irp->IoStatus.Information = (ULONG_PTR)buffer;
1390 status = STATUS_SUCCESS;
1391 break;
1392 case DeviceTextLocationInformation:
1393 KdPrint((__DRIVER_NAME " DeviceTextLocationInformation\n"));
1394 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1395 RtlStringCbPrintfW(buffer, 512, L"Xen Bus");
1396 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1397 irp->IoStatus.Information = (ULONG_PTR)buffer;
1398 status = STATUS_SUCCESS;
1399 break;
1400 default:
1401 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryDeviceText.DeviceTextType));
1402 irp->IoStatus.Information = 0;
1403 status = STATUS_NOT_SUPPORTED;
1404 break;
1406 break;
1408 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1409 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCE_REQUIREMENTS (status = %08x)\n", irp->IoStatus.Status));
1410 status = XenPci_QueryResourceRequirements(device_object, irp);
1411 break;
1413 case IRP_MN_QUERY_CAPABILITIES:
1414 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_CAPABILITIES (status = %08x)\n", irp->IoStatus.Status));
1415 status = XenPci_Pnp_QueryCapabilities(device_object, irp);
1416 break;
1418 case IRP_MN_QUERY_BUS_INFORMATION:
1419 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_BUS_INFORMATION (status = %08x)\n", irp->IoStatus.Status));
1420 pbi = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), XENPCI_POOL_TAG);
1421 pbi->BusTypeGuid = GUID_BUS_TYPE_XEN;
1422 pbi->LegacyBusType = Internal;
1423 pbi->BusNumber = 0;
1424 irp->IoStatus.Information = (ULONG_PTR)pbi;
1425 status = STATUS_SUCCESS;
1426 break;
1428 case IRP_MN_QUERY_RESOURCES:
1429 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCES (status = %08x)\n", irp->IoStatus.Status));
1430 status = irp->IoStatus.Status;
1431 #if 0
1432 crl = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR), XENPCI_POOL_TAG);
1433 crl->Count = 1;
1434 crl->List[0].InterfaceType = Internal;
1435 crl->List[0].BusNumber = 0;
1436 crl->List[0].PartialResourceList.Version = 0;
1437 crl->List[0].PartialResourceList.Revision = 0;
1438 crl->List[0].PartialResourceList.Count = 0;
1439 irp->IoStatus.Information = (ULONG_PTR)crl;
1440 status = STATUS_SUCCESS;
1441 #endif
1442 break;
1444 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1445 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE (status = %08x)\n", irp->IoStatus.Status));
1446 irp->IoStatus.Information = 0;
1447 status = STATUS_SUCCESS;
1448 break;
1450 case IRP_MN_QUERY_DEVICE_RELATIONS:
1451 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS (status = %08x)\n", irp->IoStatus.Status));
1452 switch (stack->Parameters.QueryDeviceRelations.Type)
1454 case TargetDeviceRelation:
1455 KdPrint((__DRIVER_NAME " BusRelations\n"));
1456 status = XenPci_Pnp_QueryTargetRelations(device_object, irp);
1457 break;
1458 default:
1459 status = irp->IoStatus.Status;
1460 break;
1462 break;
1464 case IRP_MN_EJECT:
1465 KdPrint((__DRIVER_NAME " IRP_MN_EJECT\n"));
1466 status = STATUS_SUCCESS;
1467 break;
1469 default:
1470 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d, Status = %08x\n", stack->MinorFunction, irp->IoStatus.Status));
1471 status = irp->IoStatus.Status;
1472 break;
1475 irp->IoStatus.Status = status;
1476 IoCompleteRequest(irp, IO_NO_INCREMENT);
1478 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1480 return status;
1483 NTSTATUS
1484 XenPci_Irp_Create_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1486 NTSTATUS status;
1488 UNREFERENCED_PARAMETER(device_object);
1490 FUNCTION_ENTER();
1492 status = irp->IoStatus.Status;
1493 IoCompleteRequest(irp, IO_NO_INCREMENT);
1495 FUNCTION_EXIT();
1497 return status;
1500 NTSTATUS
1501 XenPci_Irp_Close_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1503 NTSTATUS status;
1505 UNREFERENCED_PARAMETER(device_object);
1507 FUNCTION_ENTER();
1509 status = irp->IoStatus.Status;
1510 IoCompleteRequest(irp, IO_NO_INCREMENT);
1512 FUNCTION_EXIT();
1514 return status;
1517 NTSTATUS
1518 XenPci_Irp_Read_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1520 NTSTATUS status;
1522 UNREFERENCED_PARAMETER(device_object);
1524 FUNCTION_ENTER();
1526 status = irp->IoStatus.Status;
1527 IoCompleteRequest(irp, IO_NO_INCREMENT);
1529 FUNCTION_EXIT();
1531 return status;
1534 NTSTATUS
1535 XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1537 NTSTATUS status;
1539 UNREFERENCED_PARAMETER(device_object);
1541 FUNCTION_ENTER();
1543 status = irp->IoStatus.Status;
1544 IoCompleteRequest(irp, IO_NO_INCREMENT);
1546 FUNCTION_EXIT();
1548 return status;
1551 DDKAPI NTSTATUS
1552 XenPci_SystemControl_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1554 NTSTATUS status;
1556 UNREFERENCED_PARAMETER(device_object);
1558 FUNCTION_ENTER();
1560 status = irp->IoStatus.Status;
1561 IoCompleteRequest(irp, IO_NO_INCREMENT);
1563 FUNCTION_EXIT();
1565 return status;