win-pvdrivers

annotate xenpci/xenpci.c @ 75:b7863ede7a37

Created a 'xenenum' driver for when the device driver should attach to xen\???\xxx rather than xen\xxx
author James Harper <james.harper@bendigoit.com.au>
date Thu Dec 27 20:49:42 2007 +1100 (2007-12-27)
parents f74723639713
children dfa772949c6e
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@75 386 Status = WdfDeviceCreateDeviceInterface(Device, (LPGUID)&GUID_XEN_IFACE, 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->XenInterface.InterfaceHeader.Size = sizeof(ChildDeviceData->XenInterface);
james@48 799 ChildDeviceData->XenInterface.InterfaceHeader.Version = 1;
james@75 800 ChildDeviceData->XenInterface.InterfaceHeader.Context = WdfPdoGetParent(ChildDevice);
james@48 801 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
james@48 802 ChildDeviceData->XenInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;
james@48 803
james@75 804 ChildDeviceData->XenInterface.AllocMMIO = XenPCI_AllocMMIO;
james@0 805
james@75 806 ChildDeviceData->XenInterface.EvtChn_Bind = EvtChn_Bind;
james@75 807 ChildDeviceData->XenInterface.EvtChn_Unbind = EvtChn_Unbind;
james@75 808 ChildDeviceData->XenInterface.EvtChn_Mask = EvtChn_Mask;
james@75 809 ChildDeviceData->XenInterface.EvtChn_Unmask = EvtChn_Unmask;
james@75 810 ChildDeviceData->XenInterface.EvtChn_Notify = EvtChn_Notify;
james@75 811 ChildDeviceData->XenInterface.EvtChn_AllocUnbound = EvtChn_AllocUnbound;
james@75 812 ChildDeviceData->XenInterface.EvtChn_BindDpc = EvtChn_BindDpc;
james@75 813
james@75 814 ChildDeviceData->XenInterface.GntTbl_GrantAccess = GntTbl_GrantAccess;
james@75 815 ChildDeviceData->XenInterface.GntTbl_EndAccess = GntTbl_EndAccess;
james@75 816
james@75 817 ChildDeviceData->XenInterface.XenBus_Read = XenBus_Read;
james@75 818 ChildDeviceData->XenInterface.XenBus_Write = XenBus_Write;
james@75 819 ChildDeviceData->XenInterface.XenBus_Printf = XenBus_Printf;
james@75 820 ChildDeviceData->XenInterface.XenBus_StartTransaction = XenBus_StartTransaction;
james@75 821 ChildDeviceData->XenInterface.XenBus_EndTransaction = XenBus_EndTransaction;
james@75 822 ChildDeviceData->XenInterface.XenBus_List = XenBus_List;
james@75 823 ChildDeviceData->XenInterface.XenBus_AddWatch = XenBus_AddWatch;
james@75 824 ChildDeviceData->XenInterface.XenBus_RemWatch = XenBus_RemWatch;
james@75 825
james@75 826 WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig, (PINTERFACE)&ChildDeviceData->XenInterface, &GUID_XEN_IFACE, NULL);
james@0 827 status = WdfDeviceAddQueryInterface(ChildDevice, &qiConfig);
james@0 828 if (!NT_SUCCESS(status)) {
james@0 829 return status;
james@0 830 }
james@0 831
james@0 832 //KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice\n"));
james@0 833
james@0 834 return status;
james@0 835 }
james@0 836
james@0 837 VOID
james@0 838 XenPCI_XenBusWatchHandler(char *Path, PVOID Data)
james@0 839 {
james@0 840 XENPCI_IDENTIFICATION_DESCRIPTION description;
james@0 841 NTSTATUS status;
james@0 842 char **Bits;
james@0 843 int Count;
andy@13 844 WDFDEVICE Device = Data;
james@0 845 WDFCHILDLIST ChildList;
james@0 846 WDF_CHILD_LIST_ITERATOR ChildIterator;
james@0 847 WDFDEVICE ChildDevice;
james@0 848 PXENPCI_XEN_DEVICE_DATA ChildDeviceData;
james@0 849
james@0 850 ANSI_STRING AnsiBuf;
james@0 851
james@0 852 UNREFERENCED_PARAMETER(Data);
james@0 853
james@70 854 KdPrint((__DRIVER_NAME " --> XenBusWatchHandler\n"));
james@0 855
james@0 856 //KdPrint((__DRIVER_NAME " %s\n", Path));
james@0 857
james@28 858 ChildList = WdfFdoGetDefaultChildList(Device);
james@0 859
james@0 860 Bits = SplitString(Path, '/', 3, &Count);
james@0 861 switch (Count)
james@0 862 {
james@0 863 case 0:
james@0 864 case 1:
james@0 865 break;
james@0 866 case 2:
james@0 867 // add or update the device node
james@0 868 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&description.Header, sizeof(description));
james@0 869 strncpy(description.Path, Path, 128);
james@0 870 RtlInitAnsiString(&AnsiBuf, Bits[1]);
james@0 871 //KdPrint((__DRIVER_NAME " Name = %s\n", Bits[1]));
james@0 872 RtlAnsiStringToUnicodeString(&description.DeviceType, &AnsiBuf, TRUE);
james@0 873 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(ChildList, &description.Header, NULL);
james@0 874 break;
andy@13 875 case 3:
james@0 876 WDF_CHILD_LIST_ITERATOR_INIT(&ChildIterator, WdfRetrievePresentChildren);
james@0 877 WdfChildListBeginIteration(ChildList, &ChildIterator);
andy@13 878 while (NT_SUCCESS(WdfChildListRetrieveNextDevice(ChildList, &ChildIterator, &ChildDevice, NULL)))
james@0 879 {
andy@13 880 ChildDeviceData = GetXenDeviceData(ChildDevice);
james@0 881 if (!ChildDeviceData)
andy@13 882 {
andy@13 883 KdPrint((__FUNCTION__ " No child device data, should never happen\n"));
james@0 884 continue;
andy@13 885 }
james@0 886 if (strncmp(ChildDeviceData->BasePath, Path, strlen(ChildDeviceData->BasePath)) == 0 && Path[strlen(ChildDeviceData->BasePath)] == '/')
james@0 887 {
james@0 888 //KdPrint((__DRIVER_NAME " Child Path = %s (Match - WatchHandler = %08x)\n", ChildDeviceData->BasePath, ChildDeviceData->WatchHandler));
james@0 889 if (ChildDeviceData->WatchHandler != NULL)
james@48 890 ChildDeviceData->WatchHandler(Path, ChildDeviceData->WatchContext);
james@0 891 }
james@0 892 else
james@0 893 {
james@0 894 //KdPrint((__DRIVER_NAME " Child Path = %s (No Match)\n", ChildDeviceData->BasePath));
james@0 895 }
james@0 896 }
james@0 897 WdfChildListEndIteration(ChildList, &ChildIterator);
james@0 898 break;
andy@13 899 default:
andy@13 900 KdPrint((__FUNCTION__ ": Unknown case %d\n", Count));
andy@13 901 break;
james@0 902 }
james@0 903
james@0 904 FreeSplitString(Bits, Count);
james@0 905
james@70 906 KdPrint((__DRIVER_NAME " <-- XenBusWatchHandler\n"));
james@0 907 }
james@0 908
james@0 909 static void
james@4 910 XenBus_ShutdownHandler(char *Path, PVOID Data)
james@0 911 {
andy@13 912 WDFDEVICE Device = Data;
james@58 913 char *Value;
james@0 914 xenbus_transaction_t xbt;
james@0 915 int retry;
james@58 916 PSHUTDOWN_MSG_ENTRY Entry;
james@0 917
james@0 918 UNREFERENCED_PARAMETER(Path);
james@0 919
james@4 920 KdPrint((__DRIVER_NAME " --> XenBus_ShutdownHandler\n"));
james@0 921
andy@13 922 XenBus_StartTransaction(Device, &xbt);
james@0 923
james@59 924 XenBus_Read(Device, XBT_NIL, SHUTDOWN_PATH, &Value);
james@0 925
james@59 926 if (Value != NULL && strlen(Value) != 0)
andy@13 927 XenBus_Write(Device, XBT_NIL, SHUTDOWN_PATH, "");
james@0 928
james@70 929 if (Value != NULL)
james@70 930 {
james@70 931 KdPrint((__DRIVER_NAME " Shutdown Value = %s\n", Value));
james@70 932 KdPrint((__DRIVER_NAME " strlen(...) = %d\n", strlen(Value)));
james@70 933 }
james@70 934 else
james@70 935 {
james@70 936 KdPrint((__DRIVER_NAME " Shutdown Value = <null>\n"));
james@70 937 }
james@0 938
andy@13 939 XenBus_EndTransaction(Device, xbt, 0, &retry);
james@58 940
james@58 941 if (Value != NULL && strlen(Value) != 0)
james@58 942 {
james@58 943 Entry = (PSHUTDOWN_MSG_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, XENPCI_POOL_TAG);
james@58 944 Entry->Ptr = 0;
james@58 945 RtlStringCbPrintfA(Entry->Buf, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, "%s\n", Value);
andy@68 946 InsertTailList(&ShutdownMsgList, &Entry->ListEntry);
james@58 947 WdfIoQueueStart(ReadQueue);
james@58 948 }
james@4 949 KdPrint((__DRIVER_NAME " <-- XenBus_ShutdownHandler\n"));
james@4 950 }
james@4 951
james@4 952 static VOID
james@4 953 XenBus_BalloonHandler(char *Path, PVOID Data)
james@4 954 {
andy@13 955 WDFDEVICE Device = Data;
james@4 956 char *value;
james@4 957 xenbus_transaction_t xbt;
james@4 958 int retry;
james@4 959
james@4 960 UNREFERENCED_PARAMETER(Path);
james@4 961
james@4 962 KdPrint((__DRIVER_NAME " --> XenBus_BalloonHandler\n"));
james@4 963
andy@13 964 XenBus_StartTransaction(Device, &xbt);
james@4 965
andy@13 966 XenBus_Read(Device, XBT_NIL, BALLOON_PATH, &value);
james@4 967
james@4 968 KdPrint((__DRIVER_NAME " Balloon Value = %s\n", value));
james@4 969
james@4 970 // use the memory_op(unsigned int op, void *arg) hypercall to adjust this
james@4 971 // use XENMEM_increase_reservation and XENMEM_decrease_reservation
james@4 972
andy@13 973 XenBus_EndTransaction(Device, xbt, 0, &retry);
james@4 974
james@4 975 KdPrint((__DRIVER_NAME " <-- XenBus_BalloonHandler\n"));
james@0 976 }
james@0 977
james@0 978 /*
james@0 979 IO_RESOURCE_DESCRIPTOR MemoryDescriptor;
james@0 980
james@0 981 static NTSTATUS
james@0 982 XenPCI_FilterRemoveResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList)
james@0 983 {
james@0 984 NTSTATUS status;
james@0 985 WDFIORESLIST ResourceList;
james@0 986 PIO_RESOURCE_DESCRIPTOR Descriptor;
james@0 987
james@0 988 int i, j;
james@0 989 int offset;
james@0 990
james@0 991 //KdPrint((__DRIVER_NAME " --> FilterRemoveResourceRequirements\n"));
james@0 992
james@0 993 for (i = 0; i < WdfIoResourceRequirementsListGetCount(RequirementsList); i++)
james@0 994 {
james@0 995 ResourceList = WdfIoResourceRequirementsListGetIoResList(RequirementsList, i);
james@0 996 //KdPrint((__DRIVER_NAME " Resource List %d\n", i));
james@0 997 //KdPrint((__DRIVER_NAME " %d resources in list\n", WdfIoResourceListGetCount(ResourceList)));
james@0 998 offset = 0;
james@0 999 for (j = 0; j < WdfIoResourceListGetCount(ResourceList); j++)
james@0 1000 {
james@0 1001 //KdPrint((__DRIVER_NAME " Resource %d\n", j));
james@0 1002 Descriptor = WdfIoResourceListGetDescriptor(ResourceList, j - offset);
james@0 1003
james@0 1004 switch (Descriptor->Type) {
james@0 1005 case CmResourceTypePort:
james@0 1006 //KdPrint((__DRIVER_NAME " Port\n"));
james@0 1007 break;
james@0 1008 case CmResourceTypeMemory:
james@0 1009 //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 1010 //KdPrint((__DRIVER_NAME " Length %08X\n", Descriptor->u.Memory.Length));
james@0 1011 //KdPrint((__DRIVER_NAME " ShareDisposition %02X\n", Descriptor->ShareDisposition));
james@0 1012 //KdPrint((__DRIVER_NAME " Option %02X\n", Descriptor->Option));
james@0 1013 if (!Descriptor->Option || Descriptor->Option == IO_RESOURCE_PREFERRED) {
james@0 1014 memcpy(&MemoryDescriptor, Descriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
james@0 1015 //platform_mmio_orig_len = MemoryDescriptor.u.Memory.Length;
james@0 1016 //MemoryDescriptor.u.Memory.Length = PAGE_SIZE;
james@0 1017 MemoryDescriptor.ShareDisposition = CmResourceShareShared;
james@0 1018 }
james@0 1019 WdfIoResourceListRemove(ResourceList, j - offset);
james@0 1020 offset++;
james@0 1021 break;
james@0 1022 case CmResourceTypeInterrupt:
james@0 1023 //KdPrint((__DRIVER_NAME " Interrupt\n"));
james@0 1024 break;
james@0 1025 case CmResourceTypeDevicePrivate:
james@0 1026 //KdPrint((__DRIVER_NAME " Private\n"));
james@0 1027 break;
james@0 1028 default:
james@0 1029 //KdPrint((__DRIVER_NAME " Unknown Type (0x%x)\n", Descriptor->Type));
james@0 1030 break;
james@0 1031 }
james@0 1032 }
james@0 1033 }
james@0 1034 status = STATUS_SUCCESS;
james@0 1035
james@0 1036 KdPrint((__DRIVER_NAME " <-- FilterRemoveResourceRequirements\n"));
james@0 1037
james@0 1038 return status;
james@0 1039 }
james@0 1040
james@4 1041
james@0 1042 static NTSTATUS
james@0 1043 XenPCI_FilterAddResourceRequirements(WDFDEVICE Device, WDFIORESREQLIST RequirementsList)
james@0 1044 {
james@0 1045 NTSTATUS status;
james@0 1046 WDFIORESLIST ResourceList;
james@0 1047 PIO_RESOURCE_DESCRIPTOR Descriptor;
james@0 1048
james@0 1049 int i, j;
james@0 1050
james@0 1051 KdPrint((__DRIVER_NAME " --> FilterAddResourceRequirements\n"));
james@0 1052
james@0 1053
james@0 1054 for (i = 0; i < WdfIoResourceRequirementsListGetCount(RequirementsList); i++)
james@0 1055 {
james@0 1056 ResourceList = WdfIoResourceRequirementsListGetIoResList(RequirementsList, i);
james@0 1057 //KdPrint((__DRIVER_NAME " Resource List %d\n", i));
james@0 1058 //KdPrint((__DRIVER_NAME " %d resources in list\n", WdfIoResourceListGetCount(ResourceList)));
james@0 1059 WdfIoResourceListAppendDescriptor(ResourceList, &MemoryDescriptor);
james@0 1060 //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 1061 //KdPrint((__DRIVER_NAME " Length %08X\n", MemoryDescriptor.u.Memory.Length));
james@0 1062 for (j = 0; j < WdfIoResourceListGetCount(ResourceList); j++)
james@0 1063 {
james@0 1064 //KdPrint((__DRIVER_NAME " Resource %d\n", j));
james@0 1065 Descriptor = WdfIoResourceListGetDescriptor(ResourceList, j);
james@0 1066
james@0 1067 switch (Descriptor->Type) {
james@0 1068 case CmResourceTypePort:
james@0 1069 //KdPrint((__DRIVER_NAME " Port\n"));
james@0 1070 break;
james@0 1071 case CmResourceTypeMemory:
james@0 1072 //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 1073 //KdPrint((__DRIVER_NAME " Length %08X\n", Descriptor->u.Memory.Length));
james@0 1074 //KdPrint((__DRIVER_NAME " ShareDisposition %02X\n", Descriptor->ShareDisposition));
james@0 1075 //Descriptor->ShareDisposition = CmResourceShareShared;
james@0 1076 //memcpy(&MemoryDescriptor, Descriptor, sizeof(IO_RESOURCE_DESCRIPTOR));
james@0 1077 //platform_mmio_orig_len = MemoryDescriptor.u.Memory.Length;
james@0 1078 //MemoryDescriptor.u.Memory.Length = PAGE_SIZE;
james@0 1079 //WdfIoResourceListRemove(ResourceList, j);
james@0 1080 break;
james@0 1081 case CmResourceTypeInterrupt:
james@0 1082 //KdPrint((__DRIVER_NAME " Interrupt\n"));
james@0 1083 break;
james@0 1084 case CmResourceTypeDevicePrivate:
james@0 1085 //KdPrint((__DRIVER_NAME " Private\n"));
james@0 1086 break;
james@0 1087 default:
james@0 1088 //KdPrint((__DRIVER_NAME " Unknown Type (0x%x)\n", Descriptor->Type));
james@0 1089 break;
james@0 1090 }
james@0 1091 }
james@0 1092 }
james@0 1093 status = STATUS_SUCCESS;
james@0 1094
james@0 1095 //KdPrint((__DRIVER_NAME " <-- FilterAddResourceRequirements\n"));
james@0 1096
james@0 1097 return status;
james@0 1098 }
james@0 1099
james@0 1100 static NTSTATUS
james@0 1101 XenPCI_RemoveAddedResources(WDFDEVICE Device, WDFCMRESLIST ResourcesRaw, WDFCMRESLIST ResourcesTranslated)
james@0 1102 {
james@0 1103 //KdPrint((__DRIVER_NAME " --> RemoveAddedResources\n"));
james@0 1104 //KdPrint((__DRIVER_NAME " <-- RemoveAddedResources\n"));
james@0 1105
james@0 1106 return STATUS_SUCCESS;
james@0 1107 }
james@0 1108
james@0 1109 */
james@0 1110
james@0 1111 static NTSTATUS
james@0 1112 XenPCI_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList)
james@0 1113 {
james@0 1114 NTSTATUS status;
james@0 1115 WDFIORESLIST resourceList;
james@0 1116 IO_RESOURCE_DESCRIPTOR descriptor;
andy@16 1117 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
james@0 1118
james@0 1119 //KdPrint((__DRIVER_NAME " --> DeviceResourceRequirementsQuery\n"));
james@0 1120
james@0 1121 status = WdfIoResourceListCreate(IoResourceRequirementsList, WDF_NO_OBJECT_ATTRIBUTES, &resourceList);
james@0 1122 if (!NT_SUCCESS(status))
james@0 1123 return status;
james@0 1124
james@0 1125 /*
james@0 1126 RtlZeroMemory(&descriptor, sizeof(descriptor));
james@0 1127
james@0 1128 descriptor.Option = 0;
james@0 1129 descriptor.Type = CmResourceTypeInterrupt;
james@0 1130 descriptor.ShareDisposition = CmResourceShareDeviceExclusive;
james@0 1131 descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
james@0 1132 descriptor.u.Interrupt.MinimumVector = 1024;
james@0 1133 descriptor.u.Interrupt.MaximumVector = 1024+255;
james@0 1134
james@0 1135 //KdPrint((__DRIVER_NAME " MinimumVector = %d, MaximumVector = %d\n", descriptor.u.Interrupt.MinimumVector, descriptor.u.Interrupt.MaximumVector));
james@0 1136
james@0 1137 status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
james@0 1138 if (!NT_SUCCESS(status))
james@0 1139 return status;
james@0 1140 */
james@0 1141
james@0 1142 RtlZeroMemory(&descriptor, sizeof(descriptor));
james@0 1143
james@0 1144 descriptor.Option = 0;
james@0 1145 descriptor.Type = CmResourceTypeMemory;
james@0 1146 descriptor.ShareDisposition = CmResourceShareShared; //CmResourceShareDeviceExclusive;
james@0 1147 descriptor.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
james@0 1148 descriptor.u.Memory.Length = PAGE_SIZE;
james@0 1149 descriptor.u.Memory.Alignment = PAGE_SIZE;
andy@13 1150 descriptor.u.Memory.MinimumAddress.QuadPart
andy@16 1151 = xpdd->platform_mmio_addr.QuadPart + PAGE_SIZE;
andy@13 1152 descriptor.u.Memory.MaximumAddress.QuadPart
andy@16 1153 = xpdd->platform_mmio_addr.QuadPart + xpdd->platform_mmio_len - 1;
james@0 1154
james@0 1155 //KdPrint((__DRIVER_NAME " MinimumAddress = %08x, MaximumAddress = %08X\n", descriptor.u.Memory.MinimumAddress.LowPart, descriptor.u.Memory.MaximumAddress.LowPart));
james@0 1156
james@0 1157 status = WdfIoResourceListAppendDescriptor(resourceList, &descriptor);
james@0 1158 if (!NT_SUCCESS(status))
james@0 1159 return status;
james@0 1160
james@0 1161 status = WdfIoResourceRequirementsListAppendIoResList(IoResourceRequirementsList, resourceList);
james@0 1162 if (!NT_SUCCESS(status))
james@0 1163 return status;
james@0 1164
james@0 1165 //KdPrint((__DRIVER_NAME " <-- DeviceResourceRequirementsQuery\n"));
james@0 1166
james@0 1167 return status;
james@0 1168 }
james@0 1169