win-pvdrivers

annotate xenpci/xenpci.c @ 73:f74723639713

Corrected merge of dpc patches.
Releasing 0.5.0.0
author James Harper <james.harper@bendigoit.com.au>
date Thu Dec 20 13:07:44 2007 +1100 (2007-12-20)
parents 0d06cc4c5fc9
children b7863ede7a37
rev   line source
james@0 1 /*
james@0 2 PV Drivers for Windows Xen HVM Domains
james@0 3 Copyright (C) 2007 James Harper
james@0 4
james@0 5 This program is free software; you can redistribute it and/or
james@0 6 modify it under the terms of the GNU General Public License
james@0 7 as published by the Free Software Foundation; either version 2
james@0 8 of the License, or (at your option) any later version.
james@0 9
james@0 10 This program is distributed in the hope that it will be useful,
james@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@0 13 GNU General Public License for more details.
james@0 14
james@0 15 You should have received a copy of the GNU General Public License
james@0 16 along with this program; if not, write to the Free Software
james@0 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@0 18 */
james@0 19
james@0 20 #include "xenpci.h"
james@0 21 #include "hypercall.h"
james@0 22 #include <stdlib.h>
james@0 23
james@0 24 #define SHUTDOWN_PATH "control/shutdown"
james@4 25 #define BALLOON_PATH "memory/target"
james@0 26
james@0 27 DRIVER_INITIALIZE DriverEntry;
james@0 28 static NTSTATUS
james@0 29 XenPCI_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit);
james@0 30 static NTSTATUS
james@0 31 XenPCI_PrepareHardware(WDFDEVICE hDevice, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated);
james@0 32 static NTSTATUS
james@0 33 XenPCI_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated);
james@0 34 static NTSTATUS
james@0 35 XenPCI_D0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
james@0 36 static NTSTATUS
james@0 37 XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
james@0 38 static NTSTATUS
james@0 39 XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
james@0 40 static NTSTATUS
james@0 41 XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
james@0 42 static VOID
james@0 43 XenPCI_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
james@58 44 static VOID
james@58 45 XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
james@0 46 static NTSTATUS
james@0 47 XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
james@0 48 static NTSTATUS
james@0 49 XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
james@0 50 static NTSTATUS
james@0 51 XenPCI_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit);
james@0 52 static NTSTATUS
james@0 53 XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
james@0 54 static NTSTATUS
james@0 55 XenPCI_FilterRemoveResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
james@0 56 static NTSTATUS
james@0 57 XenPCI_FilterAddResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList);
james@0 58 static NTSTATUS
james@0 59 XenPCI_RemoveAddedResources(WDFDEVICE Device, WDFCMRESLIST ResourcesRaw, WDFCMRESLIST ResourcesTranslated);
james@0 60
james@0 61 static VOID
james@0 62 XenBus_ShutdownHandler(char *Path, PVOID Data);
james@0 63 static VOID
james@4 64 XenBus_BalloonHandler(char *Path, PVOID Data);
james@4 65 static VOID
james@0 66 XenPCI_XenBusWatchHandler(char *Path, PVOID Data);
james@0 67
james@0 68 #ifdef ALLOC_PRAGMA
james@0 69 #pragma alloc_text (INIT, DriverEntry)
james@0 70 #pragma alloc_text (PAGE, XenPCI_AddDevice)
james@0 71 #endif
james@0 72
andy@13 73 /* Global (driver-wide) variables */
james@0 74 static BOOLEAN AutoEnumerate;
james@58 75 static LIST_ENTRY ShutdownMsgList;
james@58 76
james@58 77 typedef struct {
andy@68 78 LIST_ENTRY ListEntry;
james@58 79 ULONG Ptr;
james@58 80 // ULONG Len;
andy@68 81 CHAR Buf[0];
james@58 82 } SHUTDOWN_MSG_ENTRY, *PSHUTDOWN_MSG_ENTRY;
james@58 83
james@58 84 static KSPIN_LOCK ShutdownMsgLock;
james@58 85
andy@56 86 CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw;
andy@56 87 CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated;
james@0 88
james@0 89 NTSTATUS
james@0 90 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
james@0 91 {
james@0 92 WDF_DRIVER_CONFIG config;
james@0 93 NTSTATUS status;
james@0 94 UNICODE_STRING RegKeyName;
james@0 95 UNICODE_STRING RegValueName;
james@0 96 HANDLE RegHandle;
james@0 97 OBJECT_ATTRIBUTES RegObjectAttributes;
james@0 98 char Buf[200];
james@0 99 ULONG BufLen = 200;
james@0 100 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
james@0 101 int State = 0;
james@0 102 int StartPos = 0;
james@0 103 WCHAR *SystemStartOptions;
james@0 104 size_t SystemStartOptionsLen;
james@0 105 size_t i;
james@0 106
james@6 107 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
james@0 108
james@58 109 InitializeListHead(&ShutdownMsgList);
james@58 110 KeInitializeSpinLock(&ShutdownMsgLock);
james@58 111
james@0 112 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
james@0 113 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
james@0 114 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
james@0 115 if(!NT_SUCCESS(status))
james@0 116 {
james@0 117 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
james@0 118 }
james@0 119
james@0 120 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
james@0 121 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
james@0 122 if(!NT_SUCCESS(status))
james@0 123 {
james@0 124 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
james@0 125 }
james@0 126 //KdPrint((__DRIVER_NAME " BufLen = %d\n", BufLen));
james@0 127 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
james@0 128 KdPrint((__DRIVER_NAME " Buf = %ws\n", KeyPartialValue->Data));
james@0 129 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
james@0 130
james@0 131 AutoEnumerate = FALSE;
james@0 132
james@0 133 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
james@0 134
james@0 135 for (i = 0; i <= SystemStartOptionsLen/2; i++)
james@0 136 {
james@0 137 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
james@0 138
james@0 139 switch (State)
james@0 140 {
james@0 141 case 0:
james@0 142 if (SystemStartOptions[i] == L'G')
james@0 143 {
james@0 144 StartPos = i;
james@0 145 State = 2;
james@0 146 } else if (SystemStartOptions[i] != L' ')
james@0 147 {
james@0 148 State = 1;
james@0 149 }
james@0 150 break;
james@0 151 case 1:
james@0 152 if (SystemStartOptions[i] == L' ')
james@0 153 State = 0;
james@0 154 break;
james@0 155 case 2:
james@0 156 if (SystemStartOptions[i] == L'P')
james@0 157 State = 3;
james@0 158 else
james@0 159 State = 0;
james@0 160 break;
james@0 161 case 3:
james@0 162 if (SystemStartOptions[i] == L'L')
james@0 163 State = 4;
james@0 164 else
james@0 165 State = 0;
james@0 166 break;
james@0 167 case 4:
james@0 168 if (SystemStartOptions[i] == L'P')
james@0 169 State = 5;
james@0 170 else
james@0 171 State = 0;
james@0 172 break;
james@0 173 case 5:
james@0 174 if (SystemStartOptions[i] == L'V')
james@0 175 State = 6;
james@0 176 else
james@0 177 State = 0;
james@0 178 break;
james@0 179 case 6:
james@0 180 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
james@0 181 AutoEnumerate = TRUE;
james@0 182 State = 0;
james@0 183 break;
james@0 184 }
james@0 185 }
james@0 186
james@0 187 KdPrint((__DRIVER_NAME " AutoEnumerate = %d\n", AutoEnumerate));
james@0 188
james@0 189 WDF_DRIVER_CONFIG_INIT(&config, XenPCI_AddDevice);
james@0 190 status = WdfDriverCreate(
james@0 191 DriverObject,
james@0 192 RegistryPath,
james@0 193 WDF_NO_OBJECT_ATTRIBUTES,
james@0 194 &config,
james@0 195 WDF_NO_HANDLE);
james@0 196 if(!NT_SUCCESS(status))
james@0 197 {
james@6 198 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
james@0 199 }
james@0 200
james@6 201 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
james@0 202
james@0 203 return status;
james@0 204 }
james@0 205
andy@13 206 static NTSTATUS
andy@13 207 get_hypercall_stubs(WDFDEVICE Device)
james@0 208 {
andy@16 209 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 210 DWORD32 cpuid_output[4];
james@0 211 char xensig[13];
james@0 212 ULONG i;
james@0 213 ULONG pages;
james@0 214 ULONG msr;
james@0 215
james@0 216 __cpuid(cpuid_output, 0x40000000);
james@0 217 *(ULONG*)(xensig + 0) = cpuid_output[1];
james@0 218 *(ULONG*)(xensig + 4) = cpuid_output[2];
james@0 219 *(ULONG*)(xensig + 8) = cpuid_output[3];
james@0 220 xensig[12] = '\0';
james@0 221 KdPrint((__DRIVER_NAME " Xen Signature = %s, EAX = 0x%08x\n", xensig, cpuid_output[0]));
james@0 222
james@0 223 __cpuid(cpuid_output, 0x40000002);
james@0 224 pages = cpuid_output[0];
james@0 225 msr = cpuid_output[1];
james@0 226 //KdPrint((__DRIVER_NAME " Hypercall area is %u pages.\n", pages));
james@0 227
andy@16 228 xpdd->hypercall_stubs = ExAllocatePoolWithTag(NonPagedPool, pages * PAGE_SIZE, XENPCI_POOL_TAG);
james@0 229 //KdPrint((__DRIVER_NAME " Hypercall area at %08x\n", hypercall_stubs));
james@0 230
andy@16 231 if (!xpdd->hypercall_stubs)
james@0 232 return 1;
james@0 233 for (i = 0; i < pages; i++) {
james@0 234 ULONG pfn;
james@0 235 //pfn = vmalloc_to_pfn((char *)hypercall_stubs + i * PAGE_SIZE);
andy@16 236 pfn = (ULONG)(MmGetPhysicalAddress(xpdd->hypercall_stubs + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
james@0 237 //KdPrint((__DRIVER_NAME " pfn = %08X\n", pfn));
andy@13 238 __writemsr(msr, ((ULONGLONG)pfn << PAGE_SHIFT) + i);
james@0 239 }
james@0 240 return STATUS_SUCCESS;
james@0 241 }
james@0 242
andy@13 243 PHYSICAL_ADDRESS
andy@13 244 XenPCI_AllocMMIO(WDFDEVICE Device, ULONG len)
andy@13 245 {
andy@16 246 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 247
james@0 248 PHYSICAL_ADDRESS addr;
james@0 249
andy@16 250 addr = xpdd->platform_mmio_addr;
andy@16 251 addr.QuadPart += xpdd->platform_mmio_alloc;
andy@16 252 xpdd->platform_mmio_alloc += len;
james@0 253
james@0 254 return addr;
james@0 255 }
james@0 256
james@0 257 static int
andy@13 258 init_xen_info(WDFDEVICE Device)
james@0 259 {
andy@16 260 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 261 struct xen_add_to_physmap xatp;
james@0 262 int ret;
james@0 263 PHYSICAL_ADDRESS shared_info_area_unmapped;
james@0 264
james@0 265 //setup_xen_features();
james@0 266 //KdPrint((__DRIVER_NAME " init_xen_info Hypercall area at %08x\n", hypercall_stubs));
james@0 267
andy@13 268 shared_info_area_unmapped = XenPCI_AllocMMIO(Device, PAGE_SIZE);
james@0 269 xatp.domid = DOMID_SELF;
james@0 270 xatp.idx = 0;
james@0 271 xatp.space = XENMAPSPACE_shared_info;
james@0 272 xatp.gpfn = (xen_pfn_t)(shared_info_area_unmapped.QuadPart >> PAGE_SHIFT);
andy@13 273 ret = HYPERVISOR_memory_op(Device, XENMEM_add_to_physmap, &xatp);
james@0 274 //KdPrint((__DRIVER_NAME " ret = %d\n", ret));
james@0 275
andy@16 276 xpdd->shared_info_area = MmMapIoSpace(shared_info_area_unmapped,
andy@13 277 PAGE_SIZE, MmNonCached);
james@0 278
james@0 279 return 0;
james@0 280 }
james@0 281
james@0 282 static int
andy@13 283 set_callback_irq(WDFDEVICE Device, ULONGLONG irq)
james@0 284 {
james@0 285 struct xen_hvm_param a;
james@0 286 int retval;
james@0 287
james@0 288 //KdPrint((__DRIVER_NAME " --> set_callback_irq\n"));
james@0 289 a.domid = DOMID_SELF;
james@0 290 a.index = HVM_PARAM_CALLBACK_IRQ;
james@0 291 a.value = irq;
andy@13 292 retval = HYPERVISOR_hvm_op(Device, HVMOP_set_param, &a);
james@0 293 //KdPrint((__DRIVER_NAME " HYPERVISOR_hvm_op retval = %d\n", retval));
james@0 294 //KdPrint((__DRIVER_NAME " <-- set_callback_irq\n"));
james@0 295 return retval;
james@0 296 }
james@0 297
james@58 298 WDFQUEUE ReadQueue;
james@58 299
james@0 300 static NTSTATUS
james@0 301 XenPCI_AddDevice(
james@0 302 IN WDFDRIVER Driver,
james@0 303 IN PWDFDEVICE_INIT DeviceInit
james@0 304 )
james@0 305 {
james@58 306 NTSTATUS Status;
james@0 307 WDF_CHILD_LIST_CONFIG config;
james@0 308 WDF_OBJECT_ATTRIBUTES attributes;
james@0 309 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
james@58 310 WDF_IO_QUEUE_CONFIG IoQConfig;
james@58 311 WDF_INTERRUPT_CONFIG InterruptConfig;
james@0 312 PNP_BUS_INFORMATION busInfo;
james@0 313 BUS_INTERFACE_STANDARD BusInterface;
james@58 314 DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
james@58 315 DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
andy@13 316 WDFDEVICE Device;
andy@16 317 PXENPCI_DEVICE_DATA xpdd;
james@0 318
james@0 319 UNREFERENCED_PARAMETER(Driver);
james@0 320
james@6 321 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
james@0 322
james@0 323 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
james@0 324 WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(XENPCI_IDENTIFICATION_DESCRIPTION), XenPCI_ChildListCreateDevice);
james@0 325 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
james@0 326
james@0 327 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
james@0 328 pnpPowerCallbacks.EvtDevicePrepareHardware = XenPCI_PrepareHardware;
james@0 329 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenPCI_ReleaseHardware;
james@0 330 pnpPowerCallbacks.EvtDeviceD0Entry = XenPCI_D0Entry;
andy@13 331 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled
andy@13 332 = XenPCI_D0EntryPostInterruptsEnabled;
andy@13 333 pnpPowerCallbacks.EvtDeviceD0ExitPreInterruptsDisabled
andy@13 334 = XenPCI_D0ExitPreInterruptsDisabled;
james@0 335 pnpPowerCallbacks.EvtDeviceD0Exit = XenPCI_D0Exit;
james@0 336 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
james@0 337
james@0 338 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
james@0 339
james@58 340 Status = WdfDeviceInitAssignName(DeviceInit, &DeviceName);
james@58 341 if (!NT_SUCCESS(Status))
james@58 342 {
james@58 343 KdPrint((__DRIVER_NAME " WdfDeviceInitAssignName failed 0x%08x\n", Status));
james@58 344 return Status;
james@58 345 }
james@58 346
james@0 347 /*initialize storage for the device context*/
james@0 348 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENPCI_DEVICE_DATA);
james@0 349
james@0 350 /*create a device instance.*/
james@58 351 Status = WdfDeviceCreate(&DeviceInit, &attributes, &Device);
james@58 352 if(!NT_SUCCESS(Status))
james@0 353 {
james@58 354 KdPrint((__DRIVER_NAME " WdfDeviceCreate failed with Status 0x%08x\n", Status));
james@58 355 return Status;
james@0 356 }
andy@16 357 xpdd = GetDeviceData(Device);
andy@16 358 xpdd->Device = Device;
james@0 359
james@28 360 WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFilePaging, TRUE);
james@28 361 WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFileHibernation, TRUE);
james@28 362 WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFileDump, TRUE);
james@8 363
james@58 364 Status = WdfFdoQueryForInterface(Device, &GUID_BUS_INTERFACE_STANDARD, (PINTERFACE) &BusInterface, sizeof(BUS_INTERFACE_STANDARD), 1, NULL);
james@58 365 if(!NT_SUCCESS(Status))
james@0 366 {
james@58 367 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (BusInterface) failed with Status 0x%08x\n", Status));
james@0 368 }
james@0 369
james@0 370 busInfo.BusTypeGuid = GUID_XENPCI_DEVCLASS;
james@58 371 busInfo.LegacyBusType = Internal;
james@0 372 busInfo.BusNumber = 0;
james@0 373
james@28 374 WdfDeviceSetBusInformationForChildren(Device, &busInfo);
james@0 375
james@73 376 WDF_INTERRUPT_CONFIG_INIT(&InterruptConfig, EvtChn_Interrupt, NULL); //EvtChn_InterruptDpc);
james@58 377 InterruptConfig.EvtInterruptEnable = XenPCI_InterruptEnable;
james@58 378 InterruptConfig.EvtInterruptDisable = XenPCI_InterruptDisable;
james@59 379 Status = WdfInterruptCreate(Device, &InterruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->XenInterrupt);
james@58 380 if (!NT_SUCCESS (Status))
james@0 381 {
james@58 382 KdPrint((__DRIVER_NAME " WdfInterruptCreate failed 0x%08x\n", Status));
james@58 383 return Status;
james@58 384 }
james@58 385
james@58 386 Status = WdfDeviceCreateDeviceInterface(Device, (LPGUID)&GUID_XEN_IFACE_XEN, NULL);
james@58 387 if (!NT_SUCCESS(Status))
james@58 388 {
james@58 389 KdPrint((__DRIVER_NAME " WdfDeviceCreateDeviceInterface failed 0x%08x\n", Status));
james@58 390 return Status;
james@58 391 }
james@58 392 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQConfig, WdfIoQueueDispatchSequential);
james@58 393 IoQConfig.EvtIoDefault = XenPCI_IoDefault;
james@58 394
james@58 395 Status = WdfIoQueueCreate(Device, &IoQConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL);
james@58 396 if (!NT_SUCCESS(Status))
james@58 397 {
james@58 398 KdPrint((__DRIVER_NAME " WdfIoQueueCreate failed 0x%08x\n", Status));
james@58 399 return Status;
james@58 400 }
james@58 401
james@58 402 WDF_IO_QUEUE_CONFIG_INIT(&IoQConfig, WdfIoQueueDispatchSequential);
james@58 403 IoQConfig.EvtIoRead = XenPCI_IoRead;
james@58 404
james@58 405 Status = WdfIoQueueCreate(Device, &IoQConfig, WDF_NO_OBJECT_ATTRIBUTES, &ReadQueue);
james@58 406 if (!NT_SUCCESS(Status))
james@58 407 {
james@58 408 KdPrint((__DRIVER_NAME " WdfIoQueueCreate (ReadQueue) failed 0x%08x\n", Status));
james@58 409 switch (Status)
james@58 410 {
james@58 411 case STATUS_INVALID_PARAMETER:
james@58 412 KdPrint((__DRIVER_NAME " STATUS_INVALID_PARAMETER\n"));
james@58 413 break;
james@58 414 case STATUS_INFO_LENGTH_MISMATCH:
james@58 415 KdPrint((__DRIVER_NAME " STATUS_INFO_LENGTH_MISMATCH\n"));
james@58 416 break;
james@58 417 case STATUS_POWER_STATE_INVALID:
james@58 418 KdPrint((__DRIVER_NAME " STATUS_POWER_STATE_INVALID\n"));
james@58 419 break;
james@58 420 case STATUS_INSUFFICIENT_RESOURCES:
james@58 421 KdPrint((__DRIVER_NAME " STATUS_INSUFFICIENT_RESOURCES\n"));
james@58 422 break;
james@58 423 case STATUS_WDF_NO_CALLBACK:
james@58 424 KdPrint((__DRIVER_NAME " STATUS_WDF_NO_CALLBACK\n"));
james@58 425 break;
james@58 426 case STATUS_UNSUCCESSFUL:
james@58 427 KdPrint((__DRIVER_NAME " STATUS_UNSUCCESSFUL\n"));
james@58 428 break;
james@58 429 }
james@58 430 return Status;
james@58 431 }
james@58 432 WdfIoQueueStopSynchronously(ReadQueue);
james@58 433 WdfDeviceConfigureRequestDispatching(Device, ReadQueue, WdfRequestTypeRead);
james@58 434
james@58 435 Status = WdfDeviceCreateSymbolicLink(Device, &SymbolicName);
james@58 436 if (!NT_SUCCESS(Status))
james@58 437 {
james@58 438 KdPrint((__DRIVER_NAME " WdfDeviceCreateSymbolicLink failed 0x%08x\n", Status));
james@58 439 return Status;
james@0 440 }
james@0 441
james@6 442 KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
james@58 443 return Status;
james@0 444 }
james@0 445
james@0 446 static NTSTATUS
james@0 447 XenPCI_PrepareHardware(
james@0 448 IN WDFDEVICE Device,
james@0 449 IN WDFCMRESLIST ResourceList,
james@0 450 IN WDFCMRESLIST ResourceListTranslated)
james@0 451 {
james@0 452 NTSTATUS status = STATUS_SUCCESS;
james@0 453 PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor;
andy@13 454 ULONG i;
andy@16 455 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 456
james@6 457 KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
james@0 458
james@0 459 for (i = 0; i < WdfCmResourceListGetCount(ResourceList); i++)
james@0 460 {
james@0 461 descriptor = WdfCmResourceListGetDescriptor(ResourceList, i);
james@0 462 if(!descriptor)
james@0 463 continue;
james@0 464 switch (descriptor->Type)
james@0 465 {
james@0 466 case CmResourceTypeInterrupt:
andy@16 467 xpdd->irqNumber = descriptor->u.Interrupt.Vector;
james@0 468 break;
james@0 469 }
james@0 470 }
james@0 471
james@0 472 //KdPrint((__DRIVER_NAME " GSI = %d\n", irqNumber));
james@0 473
james@0 474 //KdPrint((__DRIVER_NAME " ResourceListTranslated\n"));
james@0 475 for (i = 0; i < WdfCmResourceListGetCount(ResourceListTranslated); i++)
james@0 476 {
james@0 477 descriptor = WdfCmResourceListGetDescriptor(ResourceListTranslated, i);
james@0 478 if(!descriptor)
james@0 479 {
james@0 480 KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware (No descriptor)\n"));
james@0 481 return STATUS_DEVICE_CONFIGURATION_ERROR;
james@0 482 }
james@0 483 switch (descriptor->Type) {
james@0 484 case CmResourceTypePort:
james@0 485 //KdPrint((__DRIVER_NAME " I/O mapped CSR: (%x) Length: (%d)\n", descriptor->u.Port.Start.LowPart, descriptor->u.Port.Length));
james@0 486 break;
james@0 487 case CmResourceTypeMemory:
james@0 488 KdPrint((__DRIVER_NAME " Memory mapped CSR:(%x:%x) Length:(%d)\n", descriptor->u.Memory.Start.LowPart, descriptor->u.Memory.Start.HighPart, descriptor->u.Memory.Length));
andy@16 489 xpdd->platform_mmio_addr = descriptor->u.Memory.Start; //(ULONG)MmMapIoSpace(descriptor->u.Memory.Start, descriptor->u.Memory.Length, MmNonCached);
andy@16 490 xpdd->platform_mmio_len = descriptor->u.Memory.Length;
andy@16 491 xpdd->platform_mmio_alloc = 0;
james@0 492 break;
james@0 493 case CmResourceTypeInterrupt:
james@0 494 //KdPrint((__DRIVER_NAME " Interrupt level: 0x%0x, Vector: 0x%0x\n", descriptor->u.Interrupt.Level, descriptor->u.Interrupt.Vector));
james@48 495 memcpy(&InterruptRaw, WdfCmResourceListGetDescriptor(ResourceList, i), sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@48 496 memcpy(&InterruptTranslated, WdfCmResourceListGetDescriptor(ResourceListTranslated, i), sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@0 497 break;
james@0 498 case CmResourceTypeDevicePrivate:
james@0 499 //KdPrint((__DRIVER_NAME " Private Data: 0x%02x 0x%02x 0x%02x\n", descriptor->u.DevicePrivate.Data[0], descriptor->u.DevicePrivate.Data[1], descriptor->u.DevicePrivate.Data[2] ));
james@0 500 break;
james@0 501 default:
james@0 502 //KdPrint((__DRIVER_NAME " Unhandled resource type (0x%x)\n", descriptor->Type));
james@0 503 break;
james@0 504 }
james@0 505 }
james@0 506
andy@13 507 get_hypercall_stubs(Device);
james@0 508
andy@13 509 init_xen_info(Device);
james@0 510
andy@13 511 GntTbl_Init(Device);
james@0 512
andy@13 513 EvtChn_Init(Device);
james@0 514
andy@16 515 set_callback_irq(Device, xpdd->irqNumber);
andy@13 516
andy@13 517 XenBus_Init(Device);
james@0 518
james@0 519 //KdPrint((__DRIVER_NAME " upcall_pending = %d\n", shared_info_area->vcpu_info[0].evtchn_upcall_pending));
james@0 520
andy@16 521 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 0;
james@0 522
james@0 523 //xen_reboot_init();
james@0 524
james@6 525 KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
james@0 526
james@0 527 return status;
james@0 528 }
james@0 529
james@0 530 static NTSTATUS
james@0 531 XenPCI_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
james@0 532 {
james@0 533 UNREFERENCED_PARAMETER(Device);
james@0 534 UNREFERENCED_PARAMETER(ResourcesTranslated);
james@0 535
james@0 536 return STATUS_SUCCESS;
james@0 537 }
james@0 538
james@0 539 static NTSTATUS
james@0 540 XenPCI_D0Entry(
james@0 541 IN WDFDEVICE Device,
james@0 542 IN WDF_POWER_DEVICE_STATE PreviousState
james@0 543 )
james@0 544 {
james@0 545 NTSTATUS status = STATUS_SUCCESS;
james@0 546
james@0 547 UNREFERENCED_PARAMETER(Device);
james@0 548 UNREFERENCED_PARAMETER(PreviousState);
james@0 549
james@6 550 KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
james@0 551
james@6 552 KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
james@0 553
james@0 554 return status;
james@0 555 }
james@0 556
james@0 557 static NTSTATUS
andy@13 558 XenPCI_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
james@0 559 {
james@0 560 NTSTATUS status = STATUS_SUCCESS;
james@0 561 //OBJECT_ATTRIBUTES oa;
james@0 562 char *response;
james@0 563 char *msgTypes;
james@0 564 char **Types;
james@0 565 int i;
james@0 566 char buffer[128];
james@0 567
james@0 568 UNREFERENCED_PARAMETER(PreviousState);
james@0 569
james@6 570 KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
james@0 571
andy@13 572 XenBus_Start(Device);
james@6 573
james@6 574 KdPrint((__DRIVER_NAME " A\n"));
james@0 575
andy@13 576 response = XenBus_AddWatch(Device, XBT_NIL, SHUTDOWN_PATH, XenBus_ShutdownHandler, Device);
james@6 577 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
james@0 578
andy@13 579 response = XenBus_AddWatch(Device, XBT_NIL, BALLOON_PATH, XenBus_BalloonHandler, Device);
james@6 580 KdPrint((__DRIVER_NAME " shutdown watch response = '%s'\n", response));
james@4 581
andy@13 582 response = XenBus_AddWatch(Device, XBT_NIL, "device", XenPCI_XenBusWatchHandler, Device);
james@6 583 KdPrint((__DRIVER_NAME " device watch response = '%s'\n", response));
james@0 584
andy@13 585 msgTypes = XenBus_List(Device, XBT_NIL, "device", &Types);
james@0 586 if (!msgTypes) {
james@0 587 for (i = 0; Types[i]; i++)
james@0 588 {
james@0 589 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/%s", Types[i]);
james@0 590 //KdPrint((__DRIVER_NAME " ls device[%d] -> %s\n", i, Types[i]));
andy@13 591 XenPCI_XenBusWatchHandler(buffer, Device);
james@0 592 ExFreePoolWithTag(Types[i], XENPCI_POOL_TAG);
james@0 593 }
james@0 594 }
james@6 595 KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
james@0 596
james@0 597 return status;
james@0 598 }
james@0 599
james@0 600 static NTSTATUS
james@0 601 XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
james@0 602 {
james@0 603 NTSTATUS status = STATUS_SUCCESS;
james@0 604
james@0 605 UNREFERENCED_PARAMETER(TargetState);
james@0 606
james@35 607 KdPrint((__DRIVER_NAME " --> D0ExitPreInterruptsDisabled\n"));
james@35 608
andy@13 609 XenBus_Stop(Device);
james@0 610
james@35 611 KdPrint((__DRIVER_NAME " <-- D0ExitPreInterruptsDisabled\n"));
james@35 612
james@0 613 return status;
james@0 614 }
james@0 615
james@0 616 static NTSTATUS
james@0 617 XenPCI_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)
james@0 618 {
james@0 619 NTSTATUS status = STATUS_SUCCESS;
james@0 620
james@0 621 UNREFERENCED_PARAMETER(Device);
james@0 622 UNREFERENCED_PARAMETER(TargetState);
james@0 623
james@35 624 KdPrint((__DRIVER_NAME " --> DeviceD0Exit\n"));
james@0 625
andy@38 626 XenBus_Close(Device);
james@35 627
james@35 628 KdPrint((__DRIVER_NAME " <-- DeviceD0Exit\n"));
james@0 629
james@0 630 return status;
james@0 631 }
james@0 632
james@0 633 static VOID
james@0 634 XenPCI_IoDefault(
james@0 635 IN WDFQUEUE Queue,
james@0 636 IN WDFREQUEST Request
james@0 637 )
james@0 638 {
james@0 639 UNREFERENCED_PARAMETER(Queue);
james@0 640
james@0 641 KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
james@0 642
james@0 643 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
james@0 644
james@0 645 KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
james@0 646 }
james@0 647
james@58 648
james@58 649 static VOID
james@58 650 XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)
james@58 651 {
james@58 652 PSHUTDOWN_MSG_ENTRY Entry;
james@58 653 ULONG Remaining;
james@58 654 ULONG CopyLen;
james@58 655 PCHAR Buffer;
andy@68 656 size_t BufLen;
james@58 657 KIRQL OldIrql;
james@58 658
james@58 659 UNREFERENCED_PARAMETER(Queue);
andy@68 660 UNREFERENCED_PARAMETER(Length);
james@58 661
james@58 662 KdPrint((__DRIVER_NAME " --> IoRead\n"));
james@58 663
james@58 664 WdfRequestRetrieveOutputBuffer(Request, 1, &Buffer, &BufLen);
james@58 665
james@58 666 KeAcquireSpinLock(&ShutdownMsgLock, &OldIrql);
james@58 667
james@58 668 Entry = (PSHUTDOWN_MSG_ENTRY)RemoveHeadList(&ShutdownMsgList);
james@58 669
james@58 670 if ((PLIST_ENTRY)Entry == &ShutdownMsgList)
james@58 671 {
james@58 672 KdPrint((__DRIVER_NAME " <-- IoRead (Nothing in queue... xenpci is now broken)\n"));
james@58 673 return;
james@58 674 }
james@58 675
james@58 676 Remaining = strlen(Entry->Buf + Entry->Ptr);
james@58 677 CopyLen = min(Remaining, BufLen);
james@58 678
james@58 679 memcpy(Buffer, Entry->Buf + Entry->Ptr, CopyLen);
james@58 680
james@58 681 if (Entry->Buf[Entry->Ptr] == 0)
james@58 682 {
james@70 683 KdPrint((__DRIVER_NAME " All done... stopping queue\n"));
james@58 684 if (IsListEmpty(&ShutdownMsgList))
james@58 685 WdfIoQueueStop(ReadQueue, NULL, NULL);
james@58 686 }
james@58 687 else
james@58 688 {
james@70 689 KdPrint((__DRIVER_NAME " More to do...\n"));
james@58 690 Entry->Ptr += CopyLen;
andy@68 691 InsertHeadList(&ShutdownMsgList, &Entry->ListEntry);
james@58 692 }
james@58 693
james@58 694 KeReleaseSpinLock(&ShutdownMsgLock, OldIrql);
james@58 695
james@58 696 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, CopyLen);
james@58 697
james@58 698 KdPrint((__DRIVER_NAME " <-- IoRead\n"));
james@58 699 }
james@58 700
james@58 701
james@0 702 static NTSTATUS
james@0 703 XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
james@0 704 {
andy@16 705 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(AssociatedDevice);
james@59 706
james@0 707 UNREFERENCED_PARAMETER(Interrupt);
james@0 708
james@0 709 KdPrint((__DRIVER_NAME " --> EvtInterruptEnable\n"));
james@0 710
andy@16 711 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 0;
james@0 712
james@0 713 KdPrint((__DRIVER_NAME " <-- EvtInterruptEnable\n"));
james@0 714
james@0 715 return STATUS_SUCCESS;
james@0 716 }
james@0 717
james@0 718 static NTSTATUS
james@0 719 XenPCI_InterruptDisable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
james@0 720 {
andy@16 721 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(AssociatedDevice);
james@59 722
james@0 723 UNREFERENCED_PARAMETER(Interrupt);
james@0 724
james@0 725 //KdPrint((__DRIVER_NAME " --> EvtInterruptDisable\n"));
james@0 726
andy@16 727 xpdd->shared_info_area->vcpu_info[0].evtchn_upcall_mask = 1;
james@6 728 // should we kick off any pending interrupts here?
james@0 729
james@0 730 //KdPrint((__DRIVER_NAME " <-- EvtInterruptDisable\n"));
james@0 731
james@0 732 return STATUS_SUCCESS;
james@0 733 }
james@0 734
james@0 735 static NTSTATUS
andy@13 736 XenPCI_ChildListCreateDevice(
andy@13 737 WDFCHILDLIST ChildList,
andy@13 738 PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
andy@13 739 PWDFDEVICE_INIT ChildInit)
james@0 740 {
james@0 741 NTSTATUS status;
james@0 742 WDFDEVICE ChildDevice = NULL;
james@0 743 PXENPCI_IDENTIFICATION_DESCRIPTION XenIdentificationDesc;
james@0 744 DECLARE_UNICODE_STRING_SIZE(buffer, 20);
james@0 745 WDF_OBJECT_ATTRIBUTES PdoAttributes;
james@0 746 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
james@0 747 WDF_QUERY_INTERFACE_CONFIG qiConfig;
james@0 748 PXENPCI_XEN_DEVICE_DATA ChildDeviceData = NULL;
james@0 749
james@0 750 UNREFERENCED_PARAMETER(ChildList);
james@0 751
james@0 752 //KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
james@0 753
james@0 754 XenIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENPCI_IDENTIFICATION_DESCRIPTION, Header);
james@0 755
james@0 756 //KdPrint((__DRIVER_NAME " Type = %wZ\n", &XenIdentificationDesc->DeviceType));
james@0 757
james@0 758 //DeviceInit = WdfPdoInitAllocate(Device);
james@0 759 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_CONTROLLER);
james@0 760
james@0 761 status = RtlUnicodeStringPrintf(&buffer, L"Xen\\%wZ\0", &XenIdentificationDesc->DeviceType);
james@0 762 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
james@0 763 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
james@0 764 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
james@0 765
james@0 766 status = RtlUnicodeStringPrintf(&buffer, L"%02d", 0);
james@0 767 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
james@0 768
james@0 769 status = RtlUnicodeStringPrintf( &buffer, L"%wZ", &XenIdentificationDesc->DeviceType);
james@0 770 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
james@0 771
james@0 772 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
james@0 773
james@0 774 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, XENPCI_XEN_DEVICE_DATA);
james@0 775
james@0 776 // WDF_PDO_EVENT_CALLBACKS_INIT(&PdoCallbacks);
james@0 777 // PdoCallbacks.EvtDeviceResourceRequirementsQuery = XenPCI_DeviceResourceRequirementsQuery;
james@0 778 // WdfPdoInitSetEventCallbacks(ChildInit, &PdoCallbacks);
james@0 779
james@0 780 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
james@0 781 if (!NT_SUCCESS(status))
james@0 782 {
james@0 783 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
james@0 784 }
james@0 785
james@8 786 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
james@8 787 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
james@8 788 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
james@8 789
james@0 790 ChildDeviceData = GetXenDeviceData(ChildDevice);
james@48 791 ChildDeviceData->Magic = XEN_DATA_MAGIC;
james@48 792 ChildDeviceData->AutoEnumerate = AutoEnumerate;
james@48 793 ChildDeviceData->WatchHandler = NULL;
james@0 794 strncpy(ChildDeviceData->BasePath, XenIdentificationDesc->Path, 128);
james@48 795 memcpy(&ChildDeviceData->InterruptRaw, &InterruptRaw, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@48 796 memcpy(&ChildDeviceData->InterruptTranslated, &InterruptTranslated, sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
james@0 797
james@48 798 ChildDeviceData->EvtChnInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->EvtChnInterface);
james@48 799 ChildDeviceData->EvtChnInterface.InterfaceHeader.Version = 1;
andy@53 800 ChildDeviceData->EvtChnInterface.InterfaceHeader.Context = WdfPdoGetParent(ChildDevice);
james@48 801 ChildDeviceData->EvtChnInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@48 802 ChildDeviceData->EvtChnInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@48 803 ChildDeviceData->EvtChnInterface.Bind = EvtChn_Bind;
james@48 804 ChildDeviceData->EvtChnInterface.Unbind = EvtChn_Unbind;
james@48 805 ChildDeviceData->EvtChnInterface.Mask = EvtChn_Mask;
james@48 806 ChildDeviceData->EvtChnInterface.Unmask = EvtChn_Unmask;
james@48 807 ChildDeviceData->EvtChnInterface.Notify = EvtChn_Notify;
james@48 808 ChildDeviceData->EvtChnInterface.AllocUnbound = EvtChn_AllocUnbound;
james@73 809 ChildDeviceData->EvtChnInterface.BindDpc = EvtChn_BindDpc;
james@48 810 WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&ChildDeviceData->EvtChnInterface, &GUID_XEN_IFACE_EVTCHN, NULL);
james@0 811 status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
james@0 812 if (!NT_SUCCESS(status))
james@0 813 {
james@0 814 return status;
james@0 815 }
james@0 816
james@48 817 /*
james@48 818 ChildDeviceData->XenInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->XenInterface);
james@48 819 ChildDeviceData->XenInterface.InterfaceHeader.Version = 1;
james@48 820 ChildDeviceData->XenInterface.InterfaceHeader.Context = NULL;
james@48 821 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@48 822 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@48 823 ChildDeviceData->XenInterface.AllocMMIO = XenPCI_AllocMMIO;
james@48 824 WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&ChildDeviceData->XenInterface, &GUID_XEN_IFACE_XEN, NULL);
james@48 825 status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
james@48 826 if (!NT_SUCCESS(status)) {
james@48 827 return status;
james@48 828 }
james@48 829 */
james@48 830
james@48 831 ChildDeviceData->GntTblInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->GntTblInterface);
james@48 832 ChildDeviceData->GntTblInterface.InterfaceHeader.Version = 1;
andy@53 833 ChildDeviceData->GntTblInterface.InterfaceHeader.Context = WdfPdoGetParent(ChildDevice);
james@48 834 ChildDeviceData->GntTblInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@48 835 ChildDeviceData->GntTblInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@48 836 ChildDeviceData->GntTblInterface.GrantAccess = GntTbl_GrantAccess;
james@48 837 ChildDeviceData->GntTblInterface.EndAccess = GntTbl_EndAccess;
james@48 838 WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&ChildDeviceData->GntTblInterface, &GUID_XEN_IFACE_GNTTBL, NULL);
james@0 839 status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
james@0 840 if (!NT_SUCCESS(status)) {
james@0 841 return status;
james@0 842 }
james@0 843
james@48 844 ChildDeviceData->XenBusInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->XenBusInterface);
james@48 845 ChildDeviceData->XenBusInterface.InterfaceHeader.Version = 1;
andy@53 846 ChildDeviceData->XenBusInterface.InterfaceHeader.Context = WdfPdoGetParent(ChildDevice);
james@0 847 //XenBusInterface.InterfaceHeader.Context = ExAllocatePoolWithTag(NonPagedPool, (strlen(XenIdentificationDesc->Path) + 1), XENPCI_POOL_TAG);
james@0 848 //strcpy(XenBusInterface.InterfaceHeader.Context, XenIdentificationDesc->Path);
james@48 849 ChildDeviceData->XenBusInterface.Read = XenBus_Read;
james@48 850 ChildDeviceData->XenBusInterface.Write = XenBus_Write;
james@48 851 ChildDeviceData->XenBusInterface.Printf = XenBus_Printf;
james@48 852 ChildDeviceData->XenBusInterface.StartTransaction = XenBus_StartTransaction;
james@48 853 ChildDeviceData->XenBusInterface.EndTransaction = XenBus_EndTransaction;
james@48 854 ChildDeviceData->XenBusInterface.List = XenBus_List;
james@48 855 ChildDeviceData->XenBusInterface.AddWatch = XenBus_AddWatch;
james@48 856 ChildDeviceData->XenBusInterface.RemWatch = XenBus_RemWatch;
james@48 857 WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&ChildDeviceData->XenBusInterface, &GUID_XEN_IFACE_XENBUS, NULL);
james@0 858 status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
james@0 859 if (!NT_SUCCESS(status)) {
james@0 860 return status;
james@0 861 }
james@0 862
james@0 863 //KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice\n"));
james@0 864
james@0 865 return status;
james@0 866 }
james@0 867
james@0 868 VOID
james@0 869 XenPCI_XenBusWatchHandler(char *Path, PVOID Data)
james@0 870 {
james@0 871 XENPCI_IDENTIFICATION_DESCRIPTION description;
james@0 872 NTSTATUS status;
james@0 873 char **Bits;
james@0 874 int Count;
andy@13 875 WDFDEVICE Device = Data;
james@0 876 WDFCHILDLIST ChildList;
james@0 877 WDF_CHILD_LIST_ITERATOR ChildIterator;
james@0 878 WDFDEVICE ChildDevice;
james@0 879 PXENPCI_XEN_DEVICE_DATA ChildDeviceData;
james@0 880
james@0 881 ANSI_STRING AnsiBuf;
james@0 882
james@0 883 UNREFERENCED_PARAMETER(Data);
james@0 884
james@70 885 KdPrint((__DRIVER_NAME " --> XenBusWatchHandler\n"));
james@0 886
james@0 887 //KdPrint((__DRIVER_NAME " %s\n", Path));
james@0 888
james@28 889 ChildList = WdfFdoGetDefaultChildList(Device);
james@0 890
james@0 891 Bits = SplitString(Path, '/', 3, &Count);
james@0 892 switch (Count)
james@0 893 {
james@0 894 case 0:
james@0 895 case 1:
james@0 896 break;
james@0 897 case 2:
james@0 898 // add or update the device node
james@0 899 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
james@0 900 strncpy(description.Path, Path, 128);
james@0 901 RtlInitAnsiString(&AnsiBuf, Bits[1]);
james@0 902 //KdPrint((__DRIVER_NAME " Name = %s\n", Bits[1]));
james@0 903 RtlAnsiStringToUnicodeString(&description.DeviceType, &AnsiBuf, TRUE);
james@0 904 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(ChildList, &description.Header, NULL);
james@0 905 break;
andy@13 906 case 3:
james@0 907 WDF_CHILD_LIST_ITERATOR_INIT(&ChildIterator, WdfRetrievePresentChildren);
james@0 908 WdfChildListBeginIteration(ChildList, &ChildIterator);
andy@13 909 while (NT_SUCCESS(WdfChildListRetrieveNextDevice(ChildList, &ChildIterator, &ChildDevice, NULL)))
james@0 910 {
andy@13 911 ChildDeviceData = GetXenDeviceData(ChildDevice);
james@0 912 if (!ChildDeviceData)
andy@13 913 {
andy@13 914 KdPrint((__FUNCTION__ " No child device data, should never happen\n"));
james@0 915 continue;
andy@13 916 }
james@0 917 if (strncmp(ChildDeviceData->BasePath, Path, strlen(ChildDeviceData->BasePath)) == 0 && Path[strlen(ChildDeviceData->BasePath)] == '/')
james@0 918 {
james@0 919 //KdPrint((__DRIVER_NAME " Child Path = %s (Match - WatchHandler = %08x)\n", ChildDeviceData->BasePath, ChildDeviceData->WatchHandler));
james@0 920 if (ChildDeviceData->WatchHandler != NULL)
james@48 921 ChildDeviceData->WatchHandler(Path, ChildDeviceData->WatchContext);
james@0 922 }
james@0 923 else
james@0 924 {
james@0 925 //KdPrint((__DRIVER_NAME " Child Path = %s (No Match)\n", ChildDeviceData->BasePath));
james@0 926 }
james@0 927 }
james@0 928 WdfChildListEndIteration(ChildList, &ChildIterator);
james@0 929 break;
andy@13 930 default:
andy@13 931 KdPrint((__FUNCTION__ ": Unknown case %d\n", Count));
andy@13 932 break;
james@0 933 }
james@0 934
james@0 935 FreeSplitString(Bits, Count);
james@0 936
james@70 937 KdPrint((__DRIVER_NAME " <-- XenBusWatchHandler\n"));
james@0 938 }
james@0 939
james@0 940 static void
james@4 941 XenBus_ShutdownHandler(char *Path, PVOID Data)
james@0 942 {
andy@13 943 WDFDEVICE Device = Data;
james@58 944 char *Value;
james@0 945 xenbus_transaction_t xbt;
james@0 946 int retry;
james@58 947 PSHUTDOWN_MSG_ENTRY Entry;
james@0 948
james@0 949 UNREFERENCED_PARAMETER(Path);
james@0 950
james@4 951 KdPrint((__DRIVER_NAME " --> XenBus_ShutdownHandler\n"));
james@0 952
andy@13 953 XenBus_StartTransaction(Device, &xbt);
james@0 954
james@59 955 XenBus_Read(Device, XBT_NIL, SHUTDOWN_PATH, &Value);
james@0 956
james@59 957 if (Value != NULL && strlen(Value) != 0)
andy@13 958 XenBus_Write(Device, XBT_NIL, SHUTDOWN_PATH, "");
james@0 959
james@70 960 if (Value != NULL)
james@70 961 {
james@70 962 KdPrint((__DRIVER_NAME " Shutdown Value = %s\n", Value));
james@70 963 KdPrint((__DRIVER_NAME " strlen(...) = %d\n", strlen(Value)));
james@70 964 }
james@70 965 else
james@70 966 {
james@70 967 KdPrint((__DRIVER_NAME " Shutdown Value = <null>\n"));
james@70 968 }
james@0 969
andy@13 970 XenBus_EndTransaction(Device, xbt, 0, &retry);
james@58 971
james@58 972 if (Value != NULL && strlen(Value) != 0)
james@58 973 {
james@58 974 Entry = (PSHUTDOWN_MSG_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, XENPCI_POOL_TAG);
james@58 975 Entry->Ptr = 0;
james@58 976 RtlStringCbPrintfA(Entry->Buf, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, "%s\n", Value);
andy@68 977 InsertTailList(&ShutdownMsgList, &Entry->ListEntry);
james@58 978 WdfIoQueueStart(ReadQueue);
james@58 979 }
james@4 980 KdPrint((__DRIVER_NAME " <-- XenBus_ShutdownHandler\n"));
james@4 981 }
james@4 982
james@4 983 static VOID
james@4 984 XenBus_BalloonHandler(char *Path, PVOID Data)
james@4 985 {
andy@13 986 WDFDEVICE Device = Data;
james@4 987 char *value;
james@4 988 xenbus_transaction_t xbt;
james@4 989 int retry;
james@4 990
james@4 991 UNREFERENCED_PARAMETER(Path);
james@4 992
james@4 993 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
james@4 994
andy@13 995 XenBus_StartTransaction(Device, &xbt);
james@4 996
andy@13 997 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
james@4 998
james@4 999 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
james@4 1000
james@4 1001 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
james@4 1002 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
james@4 1003
andy@13 1004 XenBus_EndTransaction(Device, xbt, 0, &retry);
james@4 1005
james@4 1006 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
james@0 1007 }
james@0 1008
james@0 1009 /*
james@0 1010 IO_RESOURCE_DESCRIPTOR MemoryDescriptor;
james@0 1011
james@0 1012 static NTSTATUS
james@0 1013 XenPCI_FilterRemoveResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList)
james@0 1014 {
james@0 1015 NTSTATUS status;
james@0 1016 WDFIORESLIST ResourceList;
james@0 1017 PIO_RESOURCE_DESCRIPTOR Descriptor;
james@0 1018
james@0 1019 int i, j;
james@0 1020 int offset;
james@0 1021
james@0 1022 //KdPrint((__DRIVER_NAME " --> FilterRemoveResourceRequirements\n"));
james@0 1023
james@0 1024 for (i = 0; i < WdfIoResourceRequirementsListGetCount(RequirementsList); i++)
james@0 1025 {
james@0 1026 ResourceList = WdfIoResourceRequirementsListGetIoResList(RequirementsList, i);
james@0 1027 //KdPrint((__DRIVER_NAME " Resource List %d\n", i));
james@0 1028 //KdPrint((__DRIVER_NAME " %d resources in list\n", WdfIoResourceListGetCount(ResourceList)));
james@0 1029 offset = 0;
james@0 1030 for (j = 0; j < WdfIoResourceListGetCount(ResourceList); j++)
james@0 1031 {
james@0 1032 //KdPrint((__DRIVER_NAME " Resource %d\n", j));
james@0 1033 Descriptor = WdfIoResourceListGetDescriptor(ResourceList, j - offset);
james@0 1034
james@0 1035 switch (Descriptor->Type) {
james@0 1036 case CmResourceTypePort:
james@0 1037 //KdPrint((__DRIVER_NAME " Port\n"));
james@0 1038 break;
james@0 1039 case CmResourceTypeMemory:
james@0 1040 //KdPrint((__DRIVER_NAME " Memory %08X%08X - %08X%08X\n", Descriptor->u.Memory.MinimumAddress.HighPart, Descriptor->u.Memory.MinimumAddress.LowPart, Descriptor->u.Memory.MaximumAddress.HighPart, Descriptor->u.Memory.MaximumAddress.LowPart));
james@0 1041 //KdPrint((__DRIVER_NAME " Length %08X\n", Descriptor->u.Memory.Length));
james@0 1042 //KdPrint((__DRIVER_NAME " ShareDisposition %02X\n", Descriptor->ShareDisposition));
james@0 1043 //KdPrint((__DRIVER_NAME " Option %02X\n", Descriptor->Option));
james@0 1044 if (!Descriptor->Option || Descriptor->Option == IO_RESOURCE_PREFERRED) {
james@0 1045 memcpy(&MemoryDescriptor, Descriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
james@0 1046 //platform_mmio_orig_len = MemoryDescriptor.u.Memory.Length;
james@0 1047 //MemoryDescriptor.u.Memory.Length = PAGE_SIZE;
james@0 1048 MemoryDescriptor.ShareDisposition = CmResourceShareShared;
james@0 1049 }
james@0 1050 WdfIoResourceListRemove(ResourceList, j - offset);
james@0 1051 offset++;
james@0 1052 break;
james@0 1053 case CmResourceTypeInterrupt:
james@0 1054 //KdPrint((__DRIVER_NAME " Interrupt\n"));
james@0 1055 break;
james@0 1056 case CmResourceTypeDevicePrivate:
james@0 1057 //KdPrint((__DRIVER_NAME " Private\n"));
james@0 1058 break;
james@0 1059 default:
james@0 1060 //KdPrint((__DRIVER_NAME " Unknown Type (0x%x)\n", Descriptor->Type));
james@0 1061 break;
james@0 1062 }
james@0 1063 }
james@0 1064 }
james@0 1065 status = STATUS_SUCCESS;
james@0 1066
james@0 1067 KdPrint((__DRIVER_NAME " <-- FilterRemoveResourceRequirements\n"));
james@0 1068
james@0 1069 return status;
james@0 1070 }
james@0 1071
james@4 1072
james@0 1073 static NTSTATUS
james@0 1074 XenPCI_FilterAddResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList)
james@0 1075 {
james@0 1076 NTSTATUS status;
james@0 1077 WDFIORESLIST ResourceList;
james@0 1078 PIO_RESOURCE_DESCRIPTOR Descriptor;
james@0 1079
james@0 1080 int i, j;
james@0 1081
james@0 1082 KdPrint((__DRIVER_NAME " --> FilterAddResourceRequirements\n"));
james@0 1083
james@0 1084
james@0 1085 for (i = 0; i < WdfIoResourceRequirementsListGetCount(RequirementsList); i++)
james@0 1086 {
james@0 1087 ResourceList = WdfIoResourceRequirementsListGetIoResList(RequirementsList, i);
james@0 1088 //KdPrint((__DRIVER_NAME " Resource List %d\n", i));
james@0 1089 //KdPrint((__DRIVER_NAME " %d resources in list\n", WdfIoResourceListGetCount(ResourceList)));
james@0 1090 WdfIoResourceListAppendDescriptor(ResourceList, &MemoryDescriptor);
james@0 1091 //KdPrint((__DRIVER_NAME " Memory %08X%08X - %08X%08X\n", MemoryDescriptor.u.Memory.MinimumAddress.HighPart, MemoryDescriptor.u.Memory.MinimumAddress.LowPart, MemoryDescriptor.u.Memory.MaximumAddress.HighPart, MemoryDescriptor.u.Memory.MaximumAddress.LowPart));
james@0 1092 //KdPrint((__DRIVER_NAME " Length %08X\n", MemoryDescriptor.u.Memory.Length));
james@0 1093 for (j = 0; j < WdfIoResourceListGetCount(ResourceList); j++)
james@0 1094 {
james@0 1095 //KdPrint((__DRIVER_NAME " Resource %d\n", j));
james@0 1096 Descriptor = WdfIoResourceListGetDescriptor(ResourceList, j);
james@0 1097
james@0 1098 switch (Descriptor->Type) {
james@0 1099 case CmResourceTypePort:
james@0 1100 //KdPrint((__DRIVER_NAME " Port\n"));
james@0 1101 break;
james@0 1102 case CmResourceTypeMemory:
james@0 1103 //KdPrint((__DRIVER_NAME " Memory %08X%08X - %08X%08X\n", Descriptor->u.Memory.MinimumAddress.HighPart, Descriptor->u.Memory.MinimumAddress.LowPart, Descriptor->u.Memory.MaximumAddress.HighPart, Descriptor->u.Memory.MaximumAddress.LowPart));
james@0 1104 //KdPrint((__DRIVER_NAME " Length %08X\n", Descriptor->u.Memory.Length));
james@0 1105 //KdPrint((__DRIVER_NAME " ShareDisposition %02X\n", Descriptor->ShareDisposition));
james@0 1106 //Descriptor->ShareDisposition = CmResourceShareShared;
james@0 1107 //memcpy(&MemoryDescriptor, Descriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
james@0 1108 //platform_mmio_orig_len = MemoryDescriptor.u.Memory.Length;
james@0 1109 //MemoryDescriptor.u.Memory.Length = PAGE_SIZE;
james@0 1110 //WdfIoResourceListRemove(ResourceList, j);
james@0 1111 break;
james@0 1112 case CmResourceTypeInterrupt:
james@0 1113 //KdPrint((__DRIVER_NAME " Interrupt\n"));
james@0 1114 break;
james@0 1115 case CmResourceTypeDevicePrivate:
james@0 1116 //KdPrint((__DRIVER_NAME " Private\n"));
james@0 1117 break;
james@0 1118 default:
james@0 1119 //KdPrint((__DRIVER_NAME " Unknown Type (0x%x)\n", Descriptor->Type));
james@0 1120 break;
james@0 1121 }
james@0 1122 }
james@0 1123 }
james@0 1124 status = STATUS_SUCCESS;
james@0 1125
james@0 1126 //KdPrint((__DRIVER_NAME " <-- FilterAddResourceRequirements\n"));
james@0 1127
james@0 1128 return status;
james@0 1129 }
james@0 1130
james@0 1131 static NTSTATUS
james@0 1132 XenPCI_RemoveAddedResources(WDFDEVICE Device, WDFCMRESLIST ResourcesRaw, WDFCMRESLIST ResourcesTranslated)
james@0 1133 {
james@0 1134 //KdPrint((__DRIVER_NAME " --> RemoveAddedResources\n"));
james@0 1135 //KdPrint((__DRIVER_NAME " <-- RemoveAddedResources\n"));
james@0 1136
james@0 1137 return STATUS_SUCCESS;
james@0 1138 }
james@0 1139
james@0 1140 */
james@0 1141
james@0 1142 static NTSTATUS
james@0 1143 XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList)
james@0 1144 {
james@0 1145 NTSTATUS status;
james@0 1146 WDFIORESLIST resourceList;
james@0 1147 IO_RESOURCE_DESCRIPTOR descriptor;
andy@16 1148 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 1149
james@0 1150 //KdPrint((__DRIVER_NAME " --> DeviceResourceRequirementsQuery\n"));
james@0 1151
james@0 1152 status = WdfIoResourceListCreate(IoResourceRequirementsList, WDF_NO_OBJECT_ATTRIBUTES, &resourceList);
james@0 1153 if (!NT_SUCCESS(status))
james@0 1154 return status;
james@0 1155
james@0 1156 /*
james@0 1157 RtlZeroMemory(&descriptor, sizeof(descriptor));
james@0 1158
james@0 1159 descriptor.Option = 0;
james@0 1160 descriptor.Type = CmResourceTypeInterrupt;
james@0 1161 descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
james@0 1162 descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
james@0 1163 descriptor.u.Interrupt.MinimumVector = 1024;
james@0 1164 descriptor.u.Interrupt.MaximumVector = 1024+255;
james@0 1165
james@0 1166 //KdPrint((__DRIVER_NAME " MinimumVector = %d, MaximumVector = %d\n", descriptor.u.Interrupt.MinimumVector, descriptor.u.Interrupt.MaximumVector));
james@0 1167
james@0 1168 status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
james@0 1169 if (!NT_SUCCESS(status))
james@0 1170 return status;
james@0 1171 */
james@0 1172
james@0 1173 RtlZeroMemory(&descriptor, sizeof(descriptor));
james@0 1174
james@0 1175 descriptor.Option = 0;
james@0 1176 descriptor.Type = CmResourceTypeMemory;
james@0 1177 descriptor.ShareDisposition = CmResourceShareShared; //CmResourceShareDeviceExclusive;
james@0 1178 descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
james@0 1179 descriptor.u.Memory.Length = PAGE_SIZE;
james@0 1180 descriptor.u.Memory.Alignment = PAGE_SIZE;
andy@13 1181 descriptor.u.Memory.MinimumAddress.QuadPart
andy@16 1182 = xpdd->platform_mmio_addr.QuadPart + PAGE_SIZE;
andy@13 1183 descriptor.u.Memory.MaximumAddress.QuadPart
andy@16 1184 = xpdd->platform_mmio_addr.QuadPart + xpdd->platform_mmio_len - 1;
james@0 1185
james@0 1186 //KdPrint((__DRIVER_NAME " MinimumAddress = %08x, MaximumAddress = %08X\n", descriptor.u.Memory.MinimumAddress.LowPart, descriptor.u.Memory.MaximumAddress.LowPart));
james@0 1187
james@0 1188 status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
james@0 1189 if (!NT_SUCCESS(status))
james@0 1190 return status;
james@0 1191
james@0 1192 status = WdfIoResourceRequirementsListAppendIoResList(IoResourceRequirementsList, resourceList);
james@0 1193 if (!NT_SUCCESS(status))
james@0 1194 return status;
james@0 1195
james@0 1196 //KdPrint((__DRIVER_NAME " <-- DeviceResourceRequirementsQuery\n"));
james@0 1197
james@0 1198 return status;
james@0 1199 }
james@0 1200