win-pvdrivers

view xenpci/xenpci.c @ 537:2a74ac2f43bb

more big updates
dma now working under xp
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 18 22:18:23 2009 +1100 (2009-02-18)
parents 1d39de3ab8d6
children e75bb8d68370
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #define INITGUID
21 #include "xenpci.h"
22 #include <stdlib.h>
24 #define SYSRQ_PATH "control/sysrq"
25 #define SHUTDOWN_PATH "control/shutdown"
26 #define BALLOON_PATH "memory/target"
28 #pragma warning(disable : 4200) // zero-sized array
30 static NTSTATUS
31 XenPci_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init)
32 {
33 NTSTATUS status;
34 // PDEVICE_OBJECT fdo = NULL;
35 // PNP_BUS_INFORMATION busInfo;
36 // DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
37 // DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
38 WDF_CHILD_LIST_CONFIG child_list_config;
39 WDFDEVICE device;
40 PXENPCI_DEVICE_DATA xpdd;
41 UNICODE_STRING reference;
42 WDF_OBJECT_ATTRIBUTES device_attributes;
43 PNP_BUS_INFORMATION pbi;
44 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
45 WDF_INTERRUPT_CONFIG interrupt_config;
46 WDF_OBJECT_ATTRIBUTES file_attributes;
47 WDF_FILEOBJECT_CONFIG file_config;
48 WDF_IO_QUEUE_CONFIG queue_config;
50 UNREFERENCED_PARAMETER(driver);
52 FUNCTION_ENTER();
54 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
55 pnp_power_callbacks.EvtDeviceD0Entry = XenPci_EvtDeviceD0Entry;
56 pnp_power_callbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenPci_EvtDeviceD0EntryPostInterruptsEnabled;
57 pnp_power_callbacks.EvtDeviceD0Exit = XenPci_EvtDeviceD0Exit;
58 pnp_power_callbacks.EvtDeviceD0ExitPreInterruptsDisabled = XenPci_EvtDeviceD0ExitPreInterruptsDisabled;
59 pnp_power_callbacks.EvtDevicePrepareHardware = XenPci_EvtDevicePrepareHardware;
60 pnp_power_callbacks.EvtDeviceReleaseHardware = XenPci_EvtDeviceReleaseHardware;
61 pnp_power_callbacks.EvtDeviceQueryRemove = XenPci_EvtDeviceQueryRemove;
63 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
65 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_BUS_EXTENDER);
66 WdfDeviceInitSetExclusive(device_init, FALSE);
68 WDF_CHILD_LIST_CONFIG_INIT(&child_list_config, sizeof(XENPCI_PDO_IDENTIFICATION_DESCRIPTION), XenPci_EvtChildListCreateDevice);
69 child_list_config.EvtChildListScanForChildren = XenPci_EvtChildListScanForChildren;
70 WdfFdoInitSetDefaultChildListConfig(device_init, &child_list_config, WDF_NO_OBJECT_ATTRIBUTES);
72 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&file_attributes, XENPCI_DEVICE_INTERFACE_DATA);
73 WDF_FILEOBJECT_CONFIG_INIT(&file_config, XenPci_EvtDeviceFileCreate, XenPci_EvtFileClose, XenPci_EvtFileCleanup);
74 WdfDeviceInitSetFileObjectConfig(device_init, &file_config, &file_attributes);
76 WdfDeviceInitSetIoType(device_init, WdfDeviceIoBuffered);
78 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENPCI_DEVICE_DATA);
79 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
80 if (!NT_SUCCESS(status)) {
81 KdPrint(("Error creating device 0x%x\n", status));
82 return status;
83 }
85 xpdd = GetXpdd(device);
87 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
88 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
89 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
91 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queue_config, WdfIoQueueDispatchParallel);
92 queue_config.EvtIoRead = XenPci_EvtIoRead;
93 queue_config.EvtIoWrite = XenPci_EvtIoWrite;
94 status = WdfIoQueueCreate(device, &queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->io_queue);
95 if (!NT_SUCCESS(status)) {
96 KdPrint(("Error creating queue 0x%x\n", status));
97 return status;
98 }
100 WDF_INTERRUPT_CONFIG_INIT(&interrupt_config, EvtChn_EvtInterruptIsr, NULL);
101 interrupt_config.EvtInterruptEnable = EvtChn_EvtInterruptEnable;
102 interrupt_config.EvtInterruptDisable = EvtChn_EvtInterruptDisable;
104 status = WdfInterruptCreate(device, &interrupt_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdd->interrupt);
105 if (!NT_SUCCESS(status))
106 {
107 KdPrint(("Error creating interrupt 0x%x\n", status));
108 return status;
109 }
111 RtlInitUnicodeString(&reference, L"xenbus");
112 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_XENBUS, &reference);
113 if (!NT_SUCCESS(status)) {
114 KdPrint(("Error registering device interface 0x%x\n", status));
115 return status;
116 }
118 pbi.BusTypeGuid = GUID_BUS_TYPE_XEN;
119 pbi.LegacyBusType = PNPBus;
120 pbi.BusNumber = 0;
121 WdfDeviceSetBusInformationForChildren(device, &pbi);
123 xpdd->removable = TRUE;
125 FUNCTION_EXIT();
126 return status;
127 }
129 ULONG qemu_filtered;
130 ULONG qemu_filtered_by_qemu;
131 ULONG qemu_protocol_version;
132 ULONG tpr_patch_requested;
133 extern PULONG InitSafeBootMode;
135 VOID
136 XenPci_HideQemuDevices()
137 {
138 qemu_filtered_by_qemu = FALSE;
139 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) == 0x49d2)
140 {
141 qemu_protocol_version = READ_PORT_UCHAR(XEN_IOPORT_VERSION);
142 KdPrint((__DRIVER_NAME " Version = %d\n", qemu_protocol_version));
143 switch(qemu_protocol_version)
144 {
145 case 1:
146 WRITE_PORT_USHORT(XEN_IOPORT_PRODUCT, XEN_PV_PRODUCT_NUMBER);
147 WRITE_PORT_ULONG(XEN_IOPORT_BUILD, XEN_PV_PRODUCT_BUILD);
148 if (READ_PORT_USHORT(XEN_IOPORT_MAGIC) != 0x49d2)
149 {
150 KdPrint((__DRIVER_NAME " Blacklisted\n"));
151 break;
152 }
153 /* fall through */
154 case 0:
155 qemu_filtered = TRUE;
156 qemu_filtered_by_qemu = TRUE;
157 WRITE_PORT_USHORT(XEN_IOPORT_DEVICE_MASK, QEMU_UNPLUG_ALL_IDE_DISKS|QEMU_UNPLUG_ALL_NICS);
158 KdPrint((__DRIVER_NAME " Disabled qemu devices\n"));
159 break;
160 default:
161 KdPrint((__DRIVER_NAME " Unknown qemu version %d\n", qemu_protocol_version));
162 break;
163 }
164 }
165 }
167 NTSTATUS
168 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
169 {
170 NTSTATUS status = STATUS_SUCCESS;
171 WDF_DRIVER_CONFIG config;
172 WDFDRIVER driver;
173 PCONFIGURATION_INFORMATION conf_info;
174 WCHAR *SystemStartOptions;
175 UNICODE_STRING RegKeyName;
176 UNICODE_STRING RegValueName;
177 HANDLE RegHandle;
178 OBJECT_ATTRIBUTES RegObjectAttributes;
179 char Buf[300];// Sometimes bigger then 200 if system reboot from crash
180 ULONG BufLen = 300;
181 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
183 UNREFERENCED_PARAMETER(RegistryPath);
185 FUNCTION_ENTER();
187 //TestStuff();
188 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
189 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
190 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
191 if(!NT_SUCCESS(status))
192 {
193 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
194 }
196 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
197 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
198 if(!NT_SUCCESS(status))
199 {
200 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
201 }
202 else
203 ZwClose(RegHandle);
204 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
205 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
207 KdPrint((__DRIVER_NAME " SystemStartOptions = %S\n", SystemStartOptions));
209 if (wcsstr(SystemStartOptions, L"PATCHTPR"))
210 {
211 KdPrint((__DRIVER_NAME " PATCHTPR found\n"));
212 tpr_patch_requested = TRUE;
213 }
215 if (wcsstr(SystemStartOptions, L"NOGPLPV"))
216 KdPrint((__DRIVER_NAME " NOGPLPV found\n"));
217 conf_info = IoGetConfigurationInformation();
218 if ((conf_info == NULL || conf_info->DiskCount == 0)
219 && !wcsstr(SystemStartOptions, L"NOGPLPV")
220 && !*InitSafeBootMode)
221 {
222 /* see if the qemu method of disabling the PCI devices exists */
223 XenPci_HideQemuDevices();
224 /* if not, tell the filter to deny the pci devices their resources */
225 if (!qemu_filtered)
226 {
227 OBJECT_ATTRIBUTES oa;
228 UNICODE_STRING dir_name;
229 NTSTATUS status;
230 HANDLE handle;
232 KdPrint((__DRIVER_NAME " Adding DirectoryObject\n"));
233 RtlInitUnicodeString(&dir_name, L"\\NEED_GPLPV_FILTER");
234 InitializeObjectAttributes(&oa, &dir_name, OBJ_KERNEL_HANDLE, NULL, NULL);
235 status = ZwCreateDirectoryObject(&handle, DIRECTORY_CREATE_OBJECT, &oa);
236 KdPrint((__DRIVER_NAME " ZwCreateDirectoryObject = %08x\n", status));
237 if (!NT_SUCCESS(status))
238 {
239 return status;
240 }
241 qemu_filtered = TRUE;
242 }
243 }
245 if (qemu_filtered)
246 KdPrint((__DRIVER_NAME " PV Devices Active\n"));
247 else
248 KdPrint((__DRIVER_NAME " PV Devices InActive\n"));
250 WDF_DRIVER_CONFIG_INIT(&config, XenPci_EvtDeviceAdd);
251 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
253 if (!NT_SUCCESS(status)) {
254 KdPrint( ("WdfDriverCreate failed with status 0x%x\n", status));
255 }
257 FUNCTION_EXIT();
259 return status;
260 }