win-pvdrivers

view xenvbd/xenvbd.c @ 305:b4f7d75fbe24

Trying to make the devices appear more pci-like, pushing config into the inf files.
Fixed a bug which was causing crashes when multiple unaligned requests were issued concurrently
author James Harper <james.harper@bendigoit.com.au>
date Wed Jun 11 20:18:33 2008 +1000 (2008-06-11)
parents 873944504204
children 60372bd2582d
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenvbd.h"
21 #include <io/blkif.h>
22 #include <scsi.h>
23 #include <ntddscsi.h>
24 #include <ntdddisk.h>
25 #include <stdlib.h>
26 #include <xen_public.h>
27 #include <io/xenbus.h>
28 #include <io/protocols.h>
30 #pragma warning(disable: 4127)
32 DRIVER_INITIALIZE DriverEntry;
34 #ifdef ALLOC_PRAGMA
35 #pragma alloc_text (INIT, DriverEntry)
36 #endif
38 static PDRIVER_DISPATCH XenVbd_Pnp_Original;
40 static NTSTATUS
41 XenVbd_Pnp(PDEVICE_OBJECT device_object, PIRP irp)
42 {
43 PIO_STACK_LOCATION stack;
44 NTSTATUS status;
45 PCM_RESOURCE_LIST old_crl, new_crl;
46 ULONG i;
47 PCM_PARTIAL_RESOURCE_LIST prl;
48 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
49 ULONG old_length, new_length;
50 PMDL mdl;
51 PUCHAR start, ptr;
53 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
55 stack = IoGetCurrentIrpStackLocation(irp);
57 // check if the Irp is meant for us... maybe the stack->DeviceObject field?
59 switch (stack->MinorFunction)
60 {
61 case IRP_MN_START_DEVICE:
62 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE - DeviceObject = %p\n", stack->DeviceObject));
63 #if 0
64 crl = stack->Parameters.StartDevice.AllocatedResourcesTranslated;
65 prl = &crl->List[0].PartialResourceList;
66 for (i = 0; i < prl->Count; i++)
67 {
68 prd = &prl->PartialDescriptors[i];
69 if (prd->Type == CmResourceTypeMemory)
70 {
71 ptr = MmMapIoSpace(prd->u.Memory.Start, prd->u.Memory.Length, MmNonCached);
72 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL);
73 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
74 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL);
75 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL);
76 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL);
77 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_VECTORS, NULL, NULL);
78 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, UlongToPtr(GRANT_ENTRIES), NULL);
79 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
80 }
81 }
82 #endif
83 old_crl = stack->Parameters.StartDevice.AllocatedResourcesTranslated;
84 if (old_crl != NULL)
85 {
86 mdl = AllocateUncachedPage();
87 old_length = FIELD_OFFSET(CM_RESOURCE_LIST, List) +
88 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
89 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
90 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * old_crl->List[0].PartialResourceList.Count;
91 new_length = old_length + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1;
92 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENVBD_POOL_TAG);
93 memcpy(new_crl, old_crl, old_length);
94 prl = &new_crl->List[0].PartialResourceList;
95 prd = &prl->PartialDescriptors[prl->Count++];
96 prd->Type = CmResourceTypeMemory;
97 prd->ShareDisposition = CmResourceShareDeviceExclusive;
98 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE; //|CM_RESOURCE_MEMORY_PREFETCHABLE; //|CM_RESOURCE_MEMORY_CACHEABLE;
99 KdPrint((__DRIVER_NAME " PFN[0] = %p\n", MmGetMdlPfnArray(mdl)[0]));
100 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
101 prd->u.Memory.Length = PAGE_SIZE;
102 KdPrint((__DRIVER_NAME " Start = %08x:%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
103 ptr = start = MmGetMdlVirtualAddress(mdl);
104 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL);
105 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
106 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL);
107 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL);
108 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL);
109 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_VECTORS, NULL, NULL);
110 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, UlongToPtr(GRANT_ENTRIES), NULL);
111 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
113 stack->Parameters.StartDevice.AllocatedResourcesTranslated = new_crl;
115 old_crl = stack->Parameters.StartDevice.AllocatedResources;
116 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENVBD_POOL_TAG);
117 memcpy(new_crl, old_crl, old_length);
118 prl = &new_crl->List[0].PartialResourceList;
119 prd = &prl->PartialDescriptors[prl->Count++];
120 prd->Type = CmResourceTypeMemory;
121 prd->ShareDisposition = CmResourceShareDeviceExclusive;
122 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE|CM_RESOURCE_MEMORY_PREFETCHABLE|CM_RESOURCE_MEMORY_CACHEABLE;
123 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
124 prd->u.Memory.Length = PAGE_SIZE;
125 stack->Parameters.StartDevice.AllocatedResources = new_crl;
126 IoCopyCurrentIrpStackLocationToNext(irp);
127 }
128 status = XenVbd_Pnp_Original(device_object, irp);
130 break;
131 #if 0
132 case IRP_MN_QUERY_STOP_DEVICE:
133 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
134 status = XenVbd_Pnp_Original(device_object, irp);
135 break;
137 case IRP_MN_STOP_DEVICE:
138 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
139 status = XenVbd_Pnp_Original(device_object, irp);
140 break;
142 case IRP_MN_CANCEL_STOP_DEVICE:
143 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
144 status = XenVbd_Pnp_Original(device_object, irp);
145 break;
147 case IRP_MN_QUERY_REMOVE_DEVICE:
148 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
149 status = XenVbd_Pnp_Original(device_object, irp);
150 break;
152 case IRP_MN_REMOVE_DEVICE:
153 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
154 status = XenVbd_Pnp_Original(device_object, irp);
155 break;
157 case IRP_MN_CANCEL_REMOVE_DEVICE:
158 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
159 status = XenVbd_Pnp_Original(device_object, irp);
160 break;
162 case IRP_MN_SURPRISE_REMOVAL:
163 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
164 status = XenVbd_Pnp_Original(device_object, irp);
165 break;
166 #endif
168 default:
169 //KdPrint((__DRIVER_NAME " Unknown Minor = %d\n", stack->MinorFunction));
170 status = XenVbd_Pnp_Original(device_object, irp);
171 break;
172 }
174 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
176 return status;
177 }
179 NTSTATUS
180 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
181 {
182 ULONG status;
183 HW_INITIALIZATION_DATA HwInitializationData;
185 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
186 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
188 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
190 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
191 HwInitializationData.AdapterInterfaceType = Internal;
192 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
193 HwInitializationData.SpecificLuExtensionSize = 0;
194 /* SrbExtension is not always aligned to a page boundary, so we add PAGE_SIZE-1 to it to make sure we have at least UNALIGNED_DOUBLE_BUFFER_SIZE bytes of page aligned memory */
195 HwInitializationData.SrbExtensionSize = UNALIGNED_DOUBLE_BUFFER_SIZE + PAGE_SIZE - 1;
196 HwInitializationData.NumberOfAccessRanges = 1;
197 HwInitializationData.MapBuffers = TRUE;
198 HwInitializationData.NeedPhysicalAddresses = FALSE;
199 HwInitializationData.TaggedQueuing = FALSE;
200 HwInitializationData.AutoRequestSense = TRUE;
201 HwInitializationData.MultipleRequestPerLu = TRUE;
202 HwInitializationData.ReceiveEvent = FALSE;
203 HwInitializationData.VendorIdLength = 0;
204 HwInitializationData.VendorId = NULL;
205 HwInitializationData.DeviceIdLength = 0;
206 HwInitializationData.DeviceId = NULL;
208 XenVbd_FillInitCallbacks(&HwInitializationData);
210 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
212 /* DriverObject will be NULL if we are being called in dump mode */
213 if (DriverObject != NULL)
214 {
215 /* this is a bit naughty... */
216 XenVbd_Pnp_Original = DriverObject->MajorFunction[IRP_MJ_PNP];
217 DriverObject->MajorFunction[IRP_MJ_PNP] = XenVbd_Pnp;
218 }
219 else
220 XenVbd_Pnp_Original = NULL;
222 if(!NT_SUCCESS(status))
223 {
224 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
225 }
227 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
229 return status;
230 }