win-pvdrivers

view xenpci/xenpci_pdo.c @ 464:4f1c7b79948b

Updates to support a different configuration method for xenscsi
author James Harper <james.harper@bendigoit.com.au>
date Thu Nov 27 09:28:00 2008 +1100 (2008-11-27)
parents 605747e0db9c
children 7786cebdb4df
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 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
130 /* check that path == device/id/state */
131 //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
132 new_backend_state = XenPci_ReadBackendState(xppdd);
133 if (new_backend_state == XenbusStateUnknown)
134 {
135 if (xpdd->suspend_state != SUSPEND_STATE_NONE)
136 return;
137 KdPrint(("Failed to read %s, assuming closed\n", path));
138 new_backend_state = XenbusStateClosed;
139 }
141 if (xppdd->backend_state == new_backend_state)
142 {
143 KdPrint((__DRIVER_NAME " state unchanged\n"));
144 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
145 return;
146 }
148 xppdd->backend_state = new_backend_state;
150 switch (xppdd->backend_state)
151 {
152 case XenbusStateUnknown:
153 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown (%s)\n", path));
154 break;
156 case XenbusStateInitialising:
157 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising (%s)\n", path));
158 break;
160 case XenbusStateInitWait:
161 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait (%s)\n", path));
162 break;
164 case XenbusStateInitialised:
165 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised (%s)\n", path));
166 break;
168 case XenbusStateConnected:
169 KdPrint((__DRIVER_NAME " Backend State Changed to Connected (%s)\n", path));
170 break;
172 case XenbusStateClosing:
173 KdPrint((__DRIVER_NAME " Backend State Changed to Closing (%s)\n", path));
174 if (xpdd->suspend_state == SUSPEND_STATE_NONE)
175 {
176 if (xppdd->common.device_usage_paging
177 || xppdd->common.device_usage_dump
178 || xppdd->common.device_usage_hibernation)
179 {
180 KdPrint((__DRIVER_NAME " Not closing device because it is in use\n"));
181 /* in use by page file, dump file, or hiber file - can't close */
182 /* we should probably re-check if the device usage changes in the future */
183 }
184 else
185 {
186 if (xppdd->common.current_pnp_state == Started)
187 {
188 KdPrint((__DRIVER_NAME " Sending RequestDeviceEject\n"));
189 IoRequestDeviceEject(xppdd->common.pdo);
190 }
191 else
192 {
193 KdPrint((__DRIVER_NAME " Not closing device because it is not started\n"));
194 }
195 }
196 }
197 break;
199 case XenbusStateClosed:
200 KdPrint((__DRIVER_NAME " Backend State Changed to Closed (%s)\n", path));
201 break;
203 default:
204 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d (%s)\n", xppdd->backend_state, path));
205 break;
206 }
208 KeSetEvent(&xppdd->backend_state_event, 1, FALSE);
210 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
212 return;
213 }
215 struct dummy_sring {
216 RING_IDX req_prod, req_event;
217 RING_IDX rsp_prod, rsp_event;
218 uint8_t pad[48];
219 };
221 /*
222 Called at PASSIVE_LEVEL
223 Called during restore
224 */
226 static NTSTATUS
227 XenPci_ChangeFrontendState(PXENPCI_PDO_DEVICE_DATA xppdd, ULONG frontend_state_set, ULONG backend_state_response, ULONG maximum_wait_ms)
228 {
229 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
230 LARGE_INTEGER timeout;
231 ULONG remaining;
232 ULONG thiswait;
233 char path[128];
235 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
237 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->path);
238 XenBus_Printf(xpdd, XBT_NIL, path, "%d", frontend_state_set);
240 remaining = maximum_wait_ms;
242 while (xppdd->backend_state != backend_state_response)
243 {
244 thiswait = min((LONG)remaining, 1000); // 1 second or remaining time, whichever is less
245 timeout.QuadPart = (LONGLONG)-1 * thiswait * 1000 * 10;
246 if (KeWaitForSingleObject(&xppdd->backend_state_event, Executive, KernelMode, FALSE, &timeout) == STATUS_TIMEOUT)
247 {
248 remaining -= thiswait;
249 if (remaining == 0)
250 {
251 KdPrint((__DRIVER_NAME " Timed out waiting for %d!\n", backend_state_response));
252 return STATUS_UNSUCCESSFUL;
253 }
254 KdPrint((__DRIVER_NAME " Still waiting for %d (currently %d)...\n", backend_state_response, xppdd->backend_state));
255 }
256 }
257 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
258 return STATUS_SUCCESS;
259 }
261 static VOID
262 DUMP_CURRENT_PNP_STATE(PXENPCI_PDO_DEVICE_DATA xppdd)
263 {
264 switch (xppdd->common.current_pnp_state)
265 {
266 case Unknown:
267 KdPrint((__DRIVER_NAME " pnp_state = Unknown\n"));
268 break;
269 case NotStarted:
270 KdPrint((__DRIVER_NAME " pnp_state = NotStarted\n"));
271 break;
272 case Started:
273 KdPrint((__DRIVER_NAME " pnp_state = Started\n"));
274 break;
275 case StopPending:
276 KdPrint((__DRIVER_NAME " pnp_state = StopPending\n"));
277 break;
278 case Stopped:
279 KdPrint((__DRIVER_NAME " pnp_state = Stopped\n"));
280 break;
281 case RemovePending:
282 KdPrint((__DRIVER_NAME " pnp_state = RemovePending\n"));
283 break;
284 case SurpriseRemovePending:
285 KdPrint((__DRIVER_NAME " pnp_state = SurpriseRemovePending\n"));
286 break;
287 case Removed:
288 KdPrint((__DRIVER_NAME " pnp_state = Removed\n"));
289 break;
290 default:
291 KdPrint((__DRIVER_NAME " pnp_state = ???\n"));
292 break;
293 }
294 }
296 static NTSTATUS
297 XenPci_EvtChn_Bind(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
298 {
299 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
300 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
302 return EvtChn_Bind(xpdd, Port, ServiceRoutine, ServiceContext);
303 }
305 static NTSTATUS
306 XenPci_EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
307 {
308 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
309 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
311 return EvtChn_BindDpc(xpdd, Port, ServiceRoutine, ServiceContext);
312 }
314 static NTSTATUS
315 XenPci_EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
316 {
317 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
318 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
320 return EvtChn_Unbind(xpdd, Port);
321 }
323 static NTSTATUS
324 XenPci_EvtChn_Mask(PVOID Context, evtchn_port_t Port)
325 {
326 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
327 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
329 return EvtChn_Mask(xpdd, Port);
330 }
332 static NTSTATUS
333 XenPci_EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
334 {
335 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
336 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
338 return EvtChn_Unmask(xpdd, Port);
339 }
341 static NTSTATUS
342 XenPci_EvtChn_Notify(PVOID Context, evtchn_port_t Port)
343 {
344 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
345 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
347 return EvtChn_Notify(xpdd, Port);
348 }
350 static BOOLEAN
351 XenPci_EvtChn_AckEvent(PVOID context, evtchn_port_t port)
352 {
353 PXENPCI_PDO_DEVICE_DATA xppdd = context;
354 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
356 return EvtChn_AckEvent(xpdd, port);
357 }
359 static grant_ref_t
360 XenPci_GntTbl_GrantAccess(PVOID Context, domid_t domid, uint32_t frame, int readonly, grant_ref_t ref)
361 {
362 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
363 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
365 return GntTbl_GrantAccess(xpdd, domid, frame, readonly, ref);
366 }
368 static BOOLEAN
369 XenPci_GntTbl_EndAccess(PVOID Context, grant_ref_t ref, BOOLEAN keepref)
370 {
371 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
372 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
374 return GntTbl_EndAccess(xpdd, ref, keepref);
375 }
377 static VOID
378 XenPci_GntTbl_PutRef(PVOID Context, grant_ref_t ref)
379 {
380 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
381 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
383 GntTbl_PutRef(xpdd, ref);
384 }
386 static grant_ref_t
387 XenPci_GntTbl_GetRef(PVOID Context)
388 {
389 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
390 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
392 return GntTbl_GetRef(xpdd);
393 }
395 static NTSTATUS
396 XenPci_XenShutdownDevice(PVOID Context)
397 {
398 PXENPCI_PDO_DEVICE_DATA xppdd = Context;
399 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
400 PUCHAR in_ptr;
401 ULONG i;
402 UCHAR type;
403 PVOID setting;
404 PVOID value;
406 FUNCTION_ENTER();
408 if (xppdd->backend_state == XenbusStateConnected)
409 {
410 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
411 if (xppdd->backend_state == XenbusStateClosing)
412 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
413 if (xppdd->backend_state == XenbusStateClosed)
414 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
415 }
416 else
417 {
418 if (xppdd->backend_state == XenbusStateClosing)
419 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
420 }
422 if (xppdd->assigned_resources_start != NULL)
423 {
424 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
425 in_ptr = xppdd->assigned_resources_start;
426 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
427 {
428 switch (type)
429 {
430 case XEN_INIT_TYPE_RING: /* frontend ring */
431 FreePages(value);
432 break;
433 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
434 // don't know how to do this yet...
435 break;
436 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
437 EvtChn_Unbind(xpdd, PtrToUlong(value));
438 EvtChn_Close(xpdd, PtrToUlong(value));
439 break;
440 case XEN_INIT_TYPE_GRANT_ENTRIES:
441 for (i = 0; i < PtrToUlong(setting); i++)
442 GntTbl_EndAccess(xpdd, ((grant_ref_t *)value)[i], FALSE);
443 break;
444 }
445 }
446 ExFreePoolWithTag(xppdd->assigned_resources_start, XENPCI_POOL_TAG);
447 xppdd->assigned_resources_start = NULL;
448 }
450 FUNCTION_EXIT();
452 return STATUS_SUCCESS;
453 }
455 static VOID
456 XenPci_Pdo_Comm_Iface_Worker(PDEVICE_OBJECT device_object, PVOID context)
457 {
458 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
459 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
460 //char path[128];
461 char *read_value;
462 char **list_value;
463 char *err;
464 char *ptr;
465 int i;
467 UNREFERENCED_PARAMETER(context);
469 FUNCTION_ENTER();
471 switch(xppdd->comm_iface->packet_type)
472 {
473 case COMM_IFACE_CMD_XENBUS_READ:
474 KdPrint((__DRIVER_NAME " COMM_IFACE_CMD_XENBUS_READ\n"));
475 err = XenBus_Read(xpdd, XBT_NIL, xppdd->comm_iface->packet.read_req.path, &read_value);
476 if (err)
477 {
478 XenPci_FreeMem(err);
479 xppdd->comm_iface->packet_status = COMM_IFACE_STATUS_ERROR;
480 }
481 else
482 {
483 xppdd->comm_iface->packet_status = COMM_IFACE_STATUS_SUCCESS;
484 strcpy(xppdd->comm_iface->packet.read_rsp.value, read_value);
485 XenPci_FreeMem(read_value);
486 }
487 break;
488 case COMM_IFACE_CMD_XENBUS_LIST:
489 KdPrint((__DRIVER_NAME " COMM_IFACE_CMD_XENBUS_LIST\n"));
490 err = XenBus_List(xpdd, XBT_NIL, xppdd->comm_iface->packet.read_req.path, &list_value);
491 if (err)
492 {
493 XenPci_FreeMem(err);
494 xppdd->comm_iface->packet_status = COMM_IFACE_STATUS_ERROR;
495 }
496 else
497 {
498 xppdd->comm_iface->packet_status = COMM_IFACE_STATUS_SUCCESS;
499 for (ptr = xppdd->comm_iface->packet.list_rsp.values, i = 0; list_value[i]; i++)
500 {
501 strcpy(ptr, list_value[i]);
502 ptr += strlen(list_value[i]) + 1;
503 XenPci_FreeMem(list_value[i]);
504 }
505 strcpy(ptr, "");
506 XenPci_FreeMem(list_value);
507 }
508 break;
509 default:
510 KdPrint((__DRIVER_NAME " Unknown packet type = %d\n", xppdd->comm_iface->packet_type));
511 break;
512 }
513 KeMemoryBarrier();
514 xppdd->comm_iface->rsp_prod++;
515 EvtChn_Notify(xpdd, xppdd->comm_iface->fdo_event_channel);
516 FUNCTION_EXIT();
517 }
519 static DDKAPI BOOLEAN
520 XenPci_Pdo_Dpc(PKINTERRUPT interrupt, PVOID context)
521 {
522 PXENPCI_PDO_DEVICE_DATA xppdd = context;
523 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
524 PIO_WORKITEM work_item;
525 NTSTATUS status = STATUS_SUCCESS;
527 if (!xppdd->comm_iface)
528 return FALSE;
529 KeAcquireSpinLockAtDpcLevel(&xppdd->comm_iface_spinlock);
530 if (xppdd->comm_iface->req_prod == xppdd->req_cons)
531 {
532 KeReleaseSpinLockFromDpcLevel(&xppdd->comm_iface_spinlock);
533 return FALSE;
534 }
535 xppdd->req_cons = xppdd->comm_iface->req_prod;
536 KeReleaseSpinLockFromDpcLevel(&xppdd->comm_iface_spinlock);
537 work_item = IoAllocateWorkItem(xppdd->common.pdo);
538 IoQueueWorkItem(work_item, XenPci_Pdo_Comm_Iface_Worker, DelayedWorkQueue, NULL);
539 return TRUE;
540 }
542 static NTSTATUS
543 XenPci_XenConfigDevice(PVOID context);
545 static NTSTATUS
546 XenPci_XenConfigDeviceSpecifyBuffers(PVOID context, PUCHAR src, PUCHAR dst)
547 {
548 PXENPCI_PDO_DEVICE_DATA xppdd = context;
549 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
550 NTSTATUS status = STATUS_SUCCESS;
551 ULONG i;
552 char path[128];
553 PCHAR setting, value;
554 PCHAR res;
555 PVOID address;
556 UCHAR type;
557 PUCHAR in_ptr; //, in_start;
558 PUCHAR out_ptr; //, out_start;
559 XENPCI_VECTORS vectors;
560 ULONG event_channel;
561 ULONG run_type = 0;
562 PMDL ring;
563 grant_ref_t gref;
564 BOOLEAN done_xenbus_init = FALSE;
566 FUNCTION_ENTER();
568 in_ptr = src;
569 out_ptr = dst;
571 // always add vectors
572 vectors.magic = XEN_DATA_MAGIC;
573 vectors.length = sizeof(XENPCI_VECTORS);
574 vectors.context = xppdd;
575 vectors.EvtChn_Bind = XenPci_EvtChn_Bind;
576 vectors.EvtChn_BindDpc = XenPci_EvtChn_BindDpc;
577 vectors.EvtChn_Unbind = XenPci_EvtChn_Unbind;
578 vectors.EvtChn_Mask = XenPci_EvtChn_Mask;
579 vectors.EvtChn_Unmask = XenPci_EvtChn_Unmask;
580 vectors.EvtChn_Notify = XenPci_EvtChn_Notify;
581 vectors.EvtChn_AckEvent = XenPci_EvtChn_AckEvent;
582 vectors.GntTbl_GetRef = XenPci_GntTbl_GetRef;
583 vectors.GntTbl_PutRef = XenPci_GntTbl_PutRef;
584 vectors.GntTbl_GrantAccess = XenPci_GntTbl_GrantAccess;
585 vectors.GntTbl_EndAccess = XenPci_GntTbl_EndAccess;
586 vectors.XenPci_XenConfigDevice = XenPci_XenConfigDevice;
587 vectors.XenPci_XenShutdownDevice = XenPci_XenShutdownDevice;
588 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_VECTORS, NULL, &vectors);
589 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_STATE_PTR, NULL, &xppdd->device_state);
591 // first pass, possibly before state == Connected
592 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
593 {
595 if (!done_xenbus_init)
596 {
597 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
598 {
599 status = STATUS_UNSUCCESSFUL;
600 goto error;
601 }
602 done_xenbus_init = TRUE;
603 }
605 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, type, setting, value);
607 switch (type)
608 {
609 case XEN_INIT_TYPE_RUN:
610 run_type++;
611 break;
612 case XEN_INIT_TYPE_WRITE_STRING: /* frontend setting = value */
613 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_WRITE_STRING - %s = %s\n", setting, value));
614 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
615 XenBus_Printf(xpdd, XBT_NIL, path, "%s", value);
616 break;
617 case XEN_INIT_TYPE_RING: /* frontend ring */
618 /* we only allocate and do the SHARED_RING_INIT here */
619 if ((ring = AllocatePage()) != 0)
620 {
621 address = MmGetMdlVirtualAddress(ring);
622 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, address));
623 SHARED_RING_INIT((struct dummy_sring *)address);
624 if ((gref = GntTbl_GrantAccess(
625 xpdd, 0, (ULONG)*MmGetMdlPfnArray(ring), FALSE, INVALID_GRANT_REF)) != INVALID_GRANT_REF)
626 {
627 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
628 XenBus_Printf(xpdd, XBT_NIL, path, "%d", gref);
629 ADD_XEN_INIT_RSP(&out_ptr, type, setting, address);
630 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, ring);
631 // add the grant entry too so it gets freed automatically
632 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, XEN_INIT_TYPE_GRANT_ENTRIES);
633 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, 1);
634 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
635 }
636 else
637 {
638 FreePages(ring);
639 status = STATUS_UNSUCCESSFUL;
640 goto error;
641 }
642 }
643 else
644 {
645 status = STATUS_UNSUCCESSFUL;
646 goto error;
647 }
648 break;
649 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
650 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
651 if ((event_channel = EvtChn_AllocUnbound(xpdd, 0)) != 0)
652 {
653 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, event_channel));
654 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
655 XenBus_Printf(xpdd, XBT_NIL, path, "%d", event_channel);
656 ADD_XEN_INIT_RSP(&out_ptr, type, setting, UlongToPtr(event_channel));
657 ADD_XEN_INIT_RSP(&xppdd->assigned_resources_ptr, type, setting, UlongToPtr(event_channel));
658 if (type == XEN_INIT_TYPE_EVENT_CHANNEL_IRQ)
659 EvtChn_BindIrq(xpdd, event_channel, xppdd->irq_vector, path);
660 }
661 else
662 {
663 status = STATUS_UNSUCCESSFUL;
664 goto error;
665 }
666 break;
667 }
668 }
669 if (!NT_SUCCESS(status))
670 {
671 goto error;
672 }
673 // If XEN_INIT_TYPE_RUN was specified more than once then we skip XenbusStateInitialised here and go straight to XenbusStateConnected at the end
674 if (run_type == 1)
675 {
676 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialised, XenbusStateConnected, 30000) != STATUS_SUCCESS)
677 {
678 status = STATUS_UNSUCCESSFUL;
679 goto error;
680 }
681 }
683 // second pass, possibly after state == Connected
684 in_ptr = src;
685 while((type = GET_XEN_INIT_REQ(&in_ptr, (PVOID)&setting, (PVOID)&value)) != XEN_INIT_TYPE_END)
686 {
687 switch(type)
688 {
689 case XEN_INIT_TYPE_READ_STRING_BACK:
690 case XEN_INIT_TYPE_READ_STRING_FRONT:
691 if (type == XEN_INIT_TYPE_READ_STRING_FRONT)
692 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->path, setting);
693 else
694 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/%s", xppdd->backend_path, setting);
695 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
696 if (res)
697 {
698 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = <failed>\n", setting));
699 XenPci_FreeMem(res);
700 ADD_XEN_INIT_RSP(&out_ptr, type, setting, NULL);
701 }
702 else
703 {
704 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
705 ADD_XEN_INIT_RSP(&out_ptr, type, setting, value);
706 XenPci_FreeMem(value);
707 }
708 break;
709 case XEN_INIT_TYPE_VECTORS:
710 // this is always done so ignore the request
711 break;
712 case XEN_INIT_TYPE_GRANT_ENTRIES:
713 //KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
714 __ADD_XEN_INIT_UCHAR(&out_ptr, type);
715 __ADD_XEN_INIT_UCHAR(&xppdd->assigned_resources_ptr, type);
716 __ADD_XEN_INIT_ULONG(&out_ptr, PtrToUlong(value));
717 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, PtrToUlong(value));
718 for (i = 0; i < PtrToUlong(value); i++)
719 {
720 gref = GntTbl_GetRef(xpdd);
721 __ADD_XEN_INIT_ULONG(&out_ptr, gref);
722 __ADD_XEN_INIT_ULONG(&xppdd->assigned_resources_ptr, gref);
723 }
724 break;
725 case XEN_INIT_TYPE_COMM_IFACE:
726 xppdd->comm_iface = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
727 xppdd->comm_iface->magic = XEN_DATA_MAGIC;
728 xppdd->comm_iface->length = sizeof(XEN_COMM_IFACE);
729 xppdd->comm_iface->pdo_event_channel = EvtChn_AllocIpi(xpdd, 0);
730 EvtChn_BindDpc(xpdd, xppdd->comm_iface->pdo_event_channel, XenPci_Pdo_Dpc, xppdd);
731 xppdd->comm_iface->fdo_event_channel = EvtChn_AllocIpi(xpdd, 0);
732 EvtChn_BindIrq(xpdd, xppdd->comm_iface->fdo_event_channel, xppdd->irq_vector, path);
733 strcpy(xppdd->comm_iface->path, xppdd->path);
734 strcpy(xppdd->comm_iface->backend_path, xppdd->backend_path);
735 xppdd->comm_iface->req_prod = 0;
736 xppdd->comm_iface->rsp_prod = 0;
737 ADD_XEN_INIT_RSP(&out_ptr, type, NULL, xppdd->comm_iface);
738 }
739 }
740 ADD_XEN_INIT_RSP(&out_ptr, XEN_INIT_TYPE_END, NULL, NULL);
742 if (run_type)
743 {
744 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
745 {
746 status = STATUS_UNSUCCESSFUL;
747 goto error;
748 }
749 }
750 FUNCTION_EXIT();
751 return status;
753 error:
754 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
755 FUNCTION_EXIT_STATUS(status);
757 return status;
758 }
760 static NTSTATUS
761 XenPci_XenConfigDevice(PVOID context)
762 {
763 NTSTATUS status;
764 PUCHAR src, dst;
765 PXENPCI_PDO_DEVICE_DATA xppdd = context;
767 src = ExAllocatePoolWithTag(NonPagedPool, xppdd->config_page_length, XENPCI_POOL_TAG);
768 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
769 memcpy(src, dst, xppdd->config_page_length);
771 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
773 MmUnmapIoSpace(dst, xppdd->config_page_length);
774 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
776 return status;
777 }
779 static NTSTATUS
780 XenPci_GetBackendAndAddWatch(PDEVICE_OBJECT device_object)
781 {
782 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
783 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
784 char path[128];
785 PCHAR res;
786 PCHAR value;
788 /* Get backend path */
789 RtlStringCbPrintfA(path, ARRAY_SIZE(path),
790 "%s/backend", xppdd->path);
791 res = XenBus_Read(xpdd, XBT_NIL, path, &value);
792 if (res)
793 {
794 KdPrint((__DRIVER_NAME " Failed to read backend path\n"));
795 XenPci_FreeMem(res);
796 return STATUS_UNSUCCESSFUL;
797 }
798 RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value);
799 XenPci_FreeMem(value);
801 /* Add watch on backend state */
802 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
803 XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
805 return STATUS_SUCCESS;
806 }
808 NTSTATUS
809 XenPci_Pdo_Resume(PDEVICE_OBJECT device_object)
810 {
811 NTSTATUS status;
812 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
813 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
814 ULONG old_backend_state;
815 PUCHAR src, dst;
817 FUNCTION_ENTER();
819 old_backend_state = xppdd->backend_state;
821 if (xppdd->restart_on_resume)
822 {
823 status = XenPci_GetBackendAndAddWatch(device_object);
825 if (XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000) != STATUS_SUCCESS)
826 {
827 KdPrint((__DRIVER_NAME " Failed to change frontend state to Initialising\n"));
828 // this is probably an unrecoverable situation...
829 FUNCTION_ERROR_EXIT();
830 return STATUS_UNSUCCESSFUL;
831 }
832 if (xppdd->assigned_resources_ptr)
833 {
834 // reset things - feed the 'requested resources' back in
835 ADD_XEN_INIT_REQ(&xppdd->requested_resources_ptr, XEN_INIT_TYPE_END, NULL, NULL);
836 src = xppdd->requested_resources_start;
837 xppdd->requested_resources_ptr = xppdd->requested_resources_start = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
838 xppdd->assigned_resources_ptr = xppdd->assigned_resources_start;
840 dst = MmMapIoSpace(xppdd->config_page_phys, xppdd->config_page_length, MmNonCached);
842 status = XenPci_XenConfigDeviceSpecifyBuffers(xppdd, src, dst);
844 MmUnmapIoSpace(dst, xppdd->config_page_length);
845 ExFreePoolWithTag(src, XENPCI_POOL_TAG);
846 }
847 if (XenPci_ChangeFrontendState(xppdd, XenbusStateConnected, XenbusStateConnected, 30000) != STATUS_SUCCESS)
848 {
849 // this is definitely an unrecoverable situation...
850 KdPrint((__DRIVER_NAME " Failed to change frontend state to connected\n"));
851 FUNCTION_ERROR_EXIT();
852 return STATUS_UNSUCCESSFUL;
853 }
854 }
855 else
856 {
857 KdPrint((__DRIVER_NAME " Not resuming - current_pnp_state = %d, old_backend_state = %d\n", xppdd->common.current_pnp_state, old_backend_state));
858 }
859 KeMemoryBarrier();
860 xppdd->device_state.resume_state = RESUME_STATE_FRONTEND_RESUME;
861 KeMemoryBarrier();
862 EvtChn_Notify(xpdd, xpdd->suspend_evtchn);
864 FUNCTION_EXIT();
866 return STATUS_SUCCESS;
867 }
869 /* called at PASSIVE_LEVEL */
870 NTSTATUS
871 XenPci_Pdo_Suspend(PDEVICE_OBJECT device_object)
872 {
873 NTSTATUS status = STATUS_SUCCESS;
874 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
875 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
876 LARGE_INTEGER wait_time;
877 char path[128];
878 PUCHAR in_ptr;
879 UCHAR type;
880 PVOID setting;
881 PVOID value;
883 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (%s)\n", xppdd->path));
885 if (xppdd->backend_state == XenbusStateConnected)
886 {
887 xppdd->restart_on_resume = TRUE;
888 xppdd->device_state.resume_state_ack = RESUME_STATE_RUNNING;
889 KeMemoryBarrier();
890 xppdd->device_state.resume_state = RESUME_STATE_SUSPENDING;
891 KeMemoryBarrier();
892 EvtChn_Notify(xpdd, xpdd->suspend_evtchn);
893 while(xppdd->device_state.resume_state_ack != RESUME_STATE_SUSPENDING)
894 {
895 KdPrint((__DRIVER_NAME " Starting delay - resume_state = %d, resume_state_ack = %d\n", xppdd->device_state.resume_state, xppdd->device_state.resume_state_ack));
896 wait_time.QuadPart = 100 * (-1 * 10 * 1000);
897 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
898 KdPrint((__DRIVER_NAME " Done with delay\n"));
899 }
900 KdPrint((__DRIVER_NAME " resume_state acknowledged\n"));
902 XenPci_ChangeFrontendState(xppdd, XenbusStateClosing, XenbusStateClosing, 30000);
903 XenPci_ChangeFrontendState(xppdd, XenbusStateClosed, XenbusStateClosed, 30000);
904 XenPci_ChangeFrontendState(xppdd, XenbusStateInitialising, XenbusStateInitWait, 30000);
906 if (xppdd->assigned_resources_start != NULL)
907 {
908 in_ptr = xppdd->assigned_resources_ptr;
909 ADD_XEN_INIT_RSP(&in_ptr, XEN_INIT_TYPE_END, NULL, NULL);
910 in_ptr = xppdd->assigned_resources_start;
911 while((type = GET_XEN_INIT_RSP(&in_ptr, &setting, &value)) != XEN_INIT_TYPE_END)
912 {
913 switch (type)
914 {
915 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
916 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel bound to irq */
917 EvtChn_Close(xpdd, PtrToUlong(value));
918 break;
919 }
920 }
921 }
923 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
924 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
925 }
926 else
927 {
928 xppdd->restart_on_resume = FALSE;
929 }
931 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
933 return status;
934 }
936 VOID
937 XenPci_DumpPdoConfig(PDEVICE_OBJECT device_object)
938 {
939 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
941 KdPrint((__DRIVER_NAME " path = %s\n", xppdd->path));
942 KdPrint((__DRIVER_NAME " backend_path = %s\n", xppdd->backend_path));
943 KdPrint((__DRIVER_NAME " irq_number = %d\n", xppdd->irq_number));
944 KdPrint((__DRIVER_NAME " irq_level = %d\n", xppdd->irq_level));
945 KdPrint((__DRIVER_NAME " irq_vector = %x\n", xppdd->irq_vector));
946 }
948 static NTSTATUS
949 XenPci_Pnp_StartDevice(PDEVICE_OBJECT device_object, PIRP irp)
950 {
951 NTSTATUS status = STATUS_SUCCESS;
952 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
953 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
954 PIO_STACK_LOCATION stack;
955 PCM_PARTIAL_RESOURCE_LIST prl;
956 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
957 ULONG i;
958 char path[128];
960 FUNCTION_ENTER();
962 DUMP_CURRENT_PNP_STATE(xppdd);
964 stack = IoGetCurrentIrpStackLocation(irp);
966 status = XenPci_GetBackendAndAddWatch(device_object);
967 if (!NT_SUCCESS(status)) {
968 FUNCTION_ERROR_EXIT();
969 return status;
970 }
972 prl = &stack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList;
973 for (i = 0; i < prl->Count; i++)
974 {
975 prd = & prl->PartialDescriptors[i];
976 switch (prd->Type)
977 {
978 case CmResourceTypeInterrupt:
979 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt\n"));
980 KdPrint((__DRIVER_NAME " irq_number = %02x\n", prd->u.Interrupt.Vector));
981 //KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
982 xppdd->irq_number = prd->u.Interrupt.Vector;
983 //xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
984 break;
985 }
986 }
988 prl = &stack->Parameters.StartDevice.AllocatedResourcesTranslated->List[0].PartialResourceList;
989 for (i = 0; i < prl->Count; i++)
990 {
991 prd = & prl->PartialDescriptors[i];
992 switch (prd->Type)
993 {
994 case CmResourceTypeInterrupt:
995 KdPrint((__DRIVER_NAME " CmResourceTypeInterrupt\n"));
996 KdPrint((__DRIVER_NAME " irq_vector = %02x\n", prd->u.Interrupt.Vector));
997 KdPrint((__DRIVER_NAME " irq_level = %d\n", prd->u.Interrupt.Level));
998 xppdd->irq_vector = prd->u.Interrupt.Vector;
999 xppdd->irq_level = (KIRQL)prd->u.Interrupt.Level;
1000 break;
1001 case CmResourceTypeMemory:
1002 if (prd->u.Memory.Start.QuadPart)
1004 KdPrint((__DRIVER_NAME " CmResourceTypeMemory\n"));
1005 KdPrint((__DRIVER_NAME " Start = %08x, Length = %d\n", prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
1006 xppdd->config_page_phys = prd->u.Memory.Start;
1007 xppdd->config_page_length = prd->u.Memory.Length;
1008 xppdd->requested_resources_start = xppdd->requested_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1009 xppdd->assigned_resources_start = xppdd->assigned_resources_ptr = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, XENPCI_POOL_TAG);
1011 status = XenPci_XenConfigDevice(xppdd);
1012 if (!NT_SUCCESS(status))
1014 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1015 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
1016 FUNCTION_ERROR_EXIT();
1017 return status;
1022 SET_PNP_STATE(&xppdd->common, Started);
1024 FUNCTION_EXIT();
1026 return STATUS_SUCCESS;
1029 static NTSTATUS
1030 XenPci_Pnp_RemoveDevice(PDEVICE_OBJECT device_object, PIRP irp)
1032 NTSTATUS status = STATUS_SUCCESS;
1033 PXENPCI_PDO_DEVICE_DATA xppdd = device_object->DeviceExtension;
1034 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1035 char path[128];
1037 UNREFERENCED_PARAMETER(irp);
1039 FUNCTION_ENTER();
1041 DUMP_CURRENT_PNP_STATE(xppdd);
1043 if (xppdd->common.current_pnp_state != Removed)
1045 status = XenPci_XenShutdownDevice(xppdd);
1046 /* Remove watch on backend state */
1047 RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
1048 XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackEndStateHandler, xppdd);
1049 SET_PNP_STATE(&xppdd->common, Removed);
1050 IoInvalidateDeviceRelations(xppdd->bus_pdo, BusRelations);
1052 if (xppdd->reported_missing)
1054 IoDeleteDevice(xppdd->common.pdo);
1057 FUNCTION_EXIT_STATUS(status);
1059 return status;
1062 static NTSTATUS
1063 XenPci_QueryResourceRequirements(PDEVICE_OBJECT device_object, PIRP irp)
1065 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1066 PXENPCI_DEVICE_DATA xpdd = xppdd->bus_fdo->DeviceExtension;
1067 PIO_RESOURCE_REQUIREMENTS_LIST irrl;
1068 PIO_RESOURCE_DESCRIPTOR ird;
1069 ULONG length;
1071 UNREFERENCED_PARAMETER(device_object);
1073 length = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List) +
1074 FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors) +
1075 sizeof(IO_RESOURCE_DESCRIPTOR) * 1;
1076 irrl = ExAllocatePoolWithTag(NonPagedPool,
1077 length,
1078 XENPCI_POOL_TAG);
1080 irrl->ListSize = length;
1081 irrl->InterfaceType = Internal;
1082 irrl->BusNumber = 0;
1083 irrl->SlotNumber = 0;
1084 irrl->AlternativeLists = 1;
1085 irrl->List[0].Version = 1;
1086 irrl->List[0].Revision = 1;
1087 irrl->List[0].Count = 0;
1089 ird = &irrl->List[0].Descriptors[irrl->List[0].Count++];
1090 ird->Option = 0;
1091 ird->Type = CmResourceTypeInterrupt;
1092 ird->ShareDisposition = CmResourceShareShared;
1093 ird->Flags = (xpdd->irq_mode == Latched)?CM_RESOURCE_INTERRUPT_LATCHED:CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1094 ird->u.Interrupt.MinimumVector = xpdd->irq_number;
1095 ird->u.Interrupt.MaximumVector = xpdd->irq_number;
1097 irp->IoStatus.Information = (ULONG_PTR)irrl;
1098 return STATUS_SUCCESS;
1101 static NTSTATUS
1102 XenPci_Pnp_QueryTargetRelations(PDEVICE_OBJECT device_object, PIRP irp)
1104 PDEVICE_RELATIONS dr;
1105 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1107 dr = (PDEVICE_RELATIONS)ExAllocatePoolWithTag (PagedPool, sizeof(DEVICE_RELATIONS), XENPCI_POOL_TAG);
1108 dr->Count = 1;
1109 dr->Objects[0] = xppdd->common.pdo;
1110 ObReferenceObject(xppdd->common.pdo);
1111 irp->IoStatus.Information = (ULONG_PTR)dr;
1113 return STATUS_SUCCESS;
1116 static NTSTATUS
1117 XenPci_Pnp_QueryCapabilities(PDEVICE_OBJECT device_object, PIRP irp)
1119 PIO_STACK_LOCATION stack;
1120 PDEVICE_CAPABILITIES dc;
1122 UNREFERENCED_PARAMETER(device_object);
1124 stack = IoGetCurrentIrpStackLocation(irp);
1125 dc = stack->Parameters.DeviceCapabilities.Capabilities;
1126 dc->LockSupported = FALSE;
1127 dc->EjectSupported = TRUE;
1128 dc->Removable = TRUE;
1129 dc->DockDevice = FALSE;
1130 dc->UniqueID = FALSE;
1131 dc->SilentInstall = TRUE; //FALSE;
1132 dc->RawDeviceOK = FALSE;
1133 dc->SurpriseRemovalOK = TRUE;
1134 dc->HardwareDisabled = FALSE;
1135 dc->NoDisplayInUI = FALSE;
1136 dc->DeviceWake = PowerDeviceUnspecified;
1137 dc->D1Latency = 0;
1138 dc->D2Latency = 0;
1139 dc->D3Latency = 0;
1140 /* we are really supposed to get the DeviceState entries from the parent... */
1141 dc->DeviceState[PowerSystemWorking] = PowerDeviceD0;
1142 dc->DeviceState[PowerSystemSleeping1] = PowerDeviceUnspecified;
1143 dc->DeviceState[PowerSystemSleeping2] = PowerDeviceUnspecified;
1144 dc->DeviceState[PowerSystemSleeping3] = PowerDeviceUnspecified;
1145 dc->DeviceState[PowerSystemHibernate] = PowerDeviceD3;
1146 dc->DeviceState[PowerSystemShutdown] = PowerDeviceD3;
1147 return STATUS_SUCCESS;
1150 NTSTATUS
1151 XenPci_Pnp_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1153 NTSTATUS status;
1154 PIO_STACK_LOCATION stack;
1155 PXENPCI_PDO_DEVICE_DATA xppdd = (PXENPCI_PDO_DEVICE_DATA)device_object->DeviceExtension;
1156 LPWSTR buffer;
1157 WCHAR widebuf[256];
1158 unsigned int i;
1159 PPNP_BUS_INFORMATION pbi;
1160 ULONG *usage_type;
1162 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
1164 stack = IoGetCurrentIrpStackLocation(irp);
1166 switch (stack->MinorFunction)
1168 case IRP_MN_START_DEVICE:
1169 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1170 status = XenPci_Pnp_StartDevice(device_object, irp);
1171 break;
1173 case IRP_MN_QUERY_STOP_DEVICE:
1174 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1175 SET_PNP_STATE(&xppdd->common, StopPending);
1176 status = STATUS_SUCCESS;
1177 break;
1179 case IRP_MN_STOP_DEVICE:
1180 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1181 SET_PNP_STATE(&xppdd->common, Stopped);
1182 status = STATUS_SUCCESS;
1183 break;
1185 case IRP_MN_CANCEL_STOP_DEVICE:
1186 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1187 REVERT_PNP_STATE(&xppdd->common);
1188 status = STATUS_SUCCESS;
1189 break;
1191 case IRP_MN_QUERY_REMOVE_DEVICE:
1192 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1193 SET_PNP_STATE(&xppdd->common, RemovePending);
1194 status = STATUS_SUCCESS;
1195 break;
1197 case IRP_MN_REMOVE_DEVICE:
1198 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1199 status = XenPci_Pnp_RemoveDevice(device_object, irp);
1200 break;
1202 case IRP_MN_CANCEL_REMOVE_DEVICE:
1203 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE (status = %08x)\n", irp->IoStatus.Status));
1204 REVERT_PNP_STATE(&xppdd->common);
1205 status = STATUS_SUCCESS;
1206 break;
1208 case IRP_MN_SURPRISE_REMOVAL:
1209 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL (status = %08x)\n", irp->IoStatus.Status));
1210 SET_PNP_STATE(&xppdd->common, SurpriseRemovePending);
1211 status = STATUS_SUCCESS;
1212 break;
1214 case IRP_MN_DEVICE_USAGE_NOTIFICATION:
1215 KdPrint((__DRIVER_NAME " IRP_MN_DEVICE_USAGE_NOTIFICATION (status = %08x)\n", irp->IoStatus.Status));
1217 usage_type = NULL;
1218 switch (stack->Parameters.UsageNotification.Type)
1220 case DeviceUsageTypePaging:
1221 KdPrint((__DRIVER_NAME " type = DeviceUsageTypePaging\n"));
1222 usage_type = &xppdd->common.device_usage_paging;
1223 break;
1224 case DeviceUsageTypeDumpFile:
1225 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeDumpFile\n"));
1226 usage_type = &xppdd->common.device_usage_dump;
1227 break;
1228 case DeviceUsageTypeHibernation:
1229 KdPrint((__DRIVER_NAME " type = DeviceUsageTypeHibernation\n"));
1230 usage_type = &xppdd->common.device_usage_hibernation;
1231 break;
1232 default:
1233 KdPrint((__DRIVER_NAME " Unknown usage type %x\n",
1234 stack->Parameters.UsageNotification.Type));
1235 break;
1237 KdPrint((__DRIVER_NAME " inpath = %d\n", stack->Parameters.UsageNotification.InPath));
1238 if (usage_type)
1240 if (stack->Parameters.UsageNotification.InPath)
1241 (*usage_type)++;
1242 else
1243 (*usage_type)--;
1245 status = STATUS_SUCCESS;
1246 break;
1248 case IRP_MN_QUERY_ID:
1249 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_ID (status = %08x)\n", irp->IoStatus.Status));
1250 switch (stack->Parameters.QueryId.IdType)
1252 case BusQueryDeviceID: /* REG_SZ */
1253 KdPrint((__DRIVER_NAME " BusQueryDeviceID\n"));
1254 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1255 for (i = 0; i < strlen(xppdd->device); i++)
1256 widebuf[i] = xppdd->device[i];
1257 widebuf[i] = 0;
1258 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
1259 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1260 irp->IoStatus.Information = (ULONG_PTR)buffer;
1261 status = STATUS_SUCCESS;
1262 break;
1263 case BusQueryHardwareIDs: /* REG_MULTI_SZ */
1264 KdPrint((__DRIVER_NAME " BusQueryHardwareIDs\n"));
1265 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1266 for (i = 0; i < strlen(xppdd->device); i++)
1267 widebuf[i] = xppdd->device[i];
1268 widebuf[i] = 0;
1269 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
1270 for (i = 0; buffer[i] != 0; i++);
1271 buffer[i + 1] = 0;
1272 // for (i = 0; i < 256; i++)
1273 // KdPrint((__DRIVER_NAME " %04X: %04X %wc\n", i, buffer[i], buffer[i]));
1274 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1275 irp->IoStatus.Information = (ULONG_PTR)buffer;
1276 status = STATUS_SUCCESS;
1277 break;
1278 case BusQueryCompatibleIDs: /* REG_MULTI_SZ */
1279 KdPrint((__DRIVER_NAME " BusQueryCompatibleIDs\n"));
1280 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1281 for (i = 0; i < strlen(xppdd->device); i++)
1282 widebuf[i] = xppdd->device[i];
1283 widebuf[i] = 0;
1284 RtlStringCbPrintfW(buffer, 512, L"Xen\\%ws", widebuf);
1285 for (i = 0; buffer[i] != 0; i++);
1286 buffer[i + 1] = 0;
1287 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1288 irp->IoStatus.Information = (ULONG_PTR)buffer;
1289 status = STATUS_SUCCESS;
1290 break;
1291 case BusQueryInstanceID: /* REG_SZ */
1292 KdPrint((__DRIVER_NAME " BusQueryInstanceID\n"));
1293 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1294 RtlStringCbPrintfW(buffer, 512, L"%02d", xppdd->index);
1295 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1296 irp->IoStatus.Information = (ULONG_PTR)buffer;
1297 status = STATUS_SUCCESS;
1298 break;
1299 default:
1300 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryId.IdType));
1301 irp->IoStatus.Information = 0;
1302 status = STATUS_NOT_SUPPORTED;
1303 break;
1305 break;
1307 case IRP_MN_QUERY_DEVICE_TEXT:
1308 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_TEXT (status = %08x)\n", irp->IoStatus.Status));
1309 switch (stack->Parameters.QueryDeviceText.DeviceTextType)
1311 case DeviceTextDescription:
1312 KdPrint((__DRIVER_NAME " DeviceTextDescription\n"));
1313 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1314 for (i = 0; i < strlen(xppdd->device); i++)
1315 widebuf[i] = xppdd->device[i];
1316 widebuf[i] = 0;
1317 RtlStringCbPrintfW(buffer, 512, L"Xen %ws device #%d", widebuf, xppdd->index);
1318 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1319 irp->IoStatus.Information = (ULONG_PTR)buffer;
1320 status = STATUS_SUCCESS;
1321 break;
1322 case DeviceTextLocationInformation:
1323 KdPrint((__DRIVER_NAME " DeviceTextLocationInformation\n"));
1324 buffer = ExAllocatePoolWithTag(PagedPool, 512, XENPCI_POOL_TAG);
1325 RtlStringCbPrintfW(buffer, 512, L"Xen Bus");
1326 KdPrint((__DRIVER_NAME " %ls\n", buffer));
1327 irp->IoStatus.Information = (ULONG_PTR)buffer;
1328 status = STATUS_SUCCESS;
1329 break;
1330 default:
1331 KdPrint((__DRIVER_NAME " Unhandled IdType = %d\n", stack->Parameters.QueryDeviceText.DeviceTextType));
1332 irp->IoStatus.Information = 0;
1333 status = STATUS_NOT_SUPPORTED;
1334 break;
1336 break;
1338 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
1339 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCE_REQUIREMENTS (status = %08x)\n", irp->IoStatus.Status));
1340 status = XenPci_QueryResourceRequirements(device_object, irp);
1341 break;
1343 case IRP_MN_QUERY_CAPABILITIES:
1344 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_CAPABILITIES (status = %08x)\n", irp->IoStatus.Status));
1345 status = XenPci_Pnp_QueryCapabilities(device_object, irp);
1346 break;
1348 case IRP_MN_QUERY_BUS_INFORMATION:
1349 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_BUS_INFORMATION (status = %08x)\n", irp->IoStatus.Status));
1350 pbi = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), XENPCI_POOL_TAG);
1351 pbi->BusTypeGuid = GUID_BUS_TYPE_XEN;
1352 pbi->LegacyBusType = Internal;
1353 pbi->BusNumber = 0;
1354 irp->IoStatus.Information = (ULONG_PTR)pbi;
1355 status = STATUS_SUCCESS;
1356 break;
1358 case IRP_MN_QUERY_RESOURCES:
1359 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_RESOURCES (status = %08x)\n", irp->IoStatus.Status));
1360 status = irp->IoStatus.Status;
1361 #if 0
1362 crl = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, sizeof(CM_RESOURCE_LIST) - sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR), XENPCI_POOL_TAG);
1363 crl->Count = 1;
1364 crl->List[0].InterfaceType = Internal;
1365 crl->List[0].BusNumber = 0;
1366 crl->List[0].PartialResourceList.Version = 0;
1367 crl->List[0].PartialResourceList.Revision = 0;
1368 crl->List[0].PartialResourceList.Count = 0;
1369 irp->IoStatus.Information = (ULONG_PTR)crl;
1370 status = STATUS_SUCCESS;
1371 #endif
1372 break;
1374 case IRP_MN_QUERY_PNP_DEVICE_STATE:
1375 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_PNP_DEVICE_STATE (status = %08x)\n", irp->IoStatus.Status));
1376 irp->IoStatus.Information = 0;
1377 status = STATUS_SUCCESS;
1378 break;
1380 case IRP_MN_QUERY_DEVICE_RELATIONS:
1381 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_DEVICE_RELATIONS (status = %08x)\n", irp->IoStatus.Status));
1382 switch (stack->Parameters.QueryDeviceRelations.Type)
1384 case TargetDeviceRelation:
1385 KdPrint((__DRIVER_NAME " BusRelations\n"));
1386 status = XenPci_Pnp_QueryTargetRelations(device_object, irp);
1387 break;
1388 default:
1389 status = irp->IoStatus.Status;
1390 break;
1392 break;
1394 case IRP_MN_EJECT:
1395 KdPrint((__DRIVER_NAME " IRP_MN_EJECT\n"));
1396 status = STATUS_SUCCESS;
1397 break;
1399 default:
1400 //KdPrint((__DRIVER_NAME " Unhandled Minor = %d, Status = %08x\n", stack->MinorFunction, irp->IoStatus.Status));
1401 status = irp->IoStatus.Status;
1402 break;
1405 irp->IoStatus.Status = status;
1406 IoCompleteRequest(irp, IO_NO_INCREMENT);
1408 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
1410 return status;
1413 NTSTATUS
1414 XenPci_Irp_Create_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1416 NTSTATUS status;
1418 UNREFERENCED_PARAMETER(device_object);
1420 FUNCTION_ENTER();
1422 status = irp->IoStatus.Status;
1423 IoCompleteRequest(irp, IO_NO_INCREMENT);
1425 FUNCTION_EXIT();
1427 return status;
1430 NTSTATUS
1431 XenPci_Irp_Close_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1433 NTSTATUS status;
1435 UNREFERENCED_PARAMETER(device_object);
1437 FUNCTION_ENTER();
1439 status = irp->IoStatus.Status;
1440 IoCompleteRequest(irp, IO_NO_INCREMENT);
1442 FUNCTION_EXIT();
1444 return status;
1447 NTSTATUS
1448 XenPci_Irp_Read_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1450 NTSTATUS status;
1452 UNREFERENCED_PARAMETER(device_object);
1454 FUNCTION_ENTER();
1456 status = irp->IoStatus.Status;
1457 IoCompleteRequest(irp, IO_NO_INCREMENT);
1459 FUNCTION_EXIT();
1461 return status;
1464 NTSTATUS
1465 XenPci_Irp_Cleanup_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1467 NTSTATUS status;
1469 UNREFERENCED_PARAMETER(device_object);
1471 FUNCTION_ENTER();
1473 status = irp->IoStatus.Status;
1474 IoCompleteRequest(irp, IO_NO_INCREMENT);
1476 FUNCTION_EXIT();
1478 return status;
1481 DDKAPI NTSTATUS
1482 XenPci_SystemControl_Pdo(PDEVICE_OBJECT device_object, PIRP irp)
1484 NTSTATUS status;
1486 UNREFERENCED_PARAMETER(device_object);
1488 FUNCTION_ENTER();
1490 status = irp->IoStatus.Status;
1491 IoCompleteRequest(irp, IO_NO_INCREMENT);
1493 FUNCTION_EXIT();
1495 return status;