win-pvdrivers

view xenscsi/xenscsi.c @ 283:3c65d6c6453f

Fixed a sense problem with xenscsi. scsi passthrough now working properly.
author James Harper <james.harper@bendigoit.com.au>
date Tue May 27 22:46:06 2008 +1000 (2008-05-27)
parents 874c3640830e
children a55d72ac422f
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 "xenscsi.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 static ULONG
35 XenScsi_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again);
36 static BOOLEAN
37 XenScsi_HwScsiInitialize(PVOID DeviceExtension);
38 static BOOLEAN
39 XenScsi_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb);
40 static BOOLEAN
41 XenScsi_HwScsiInterrupt(PVOID DeviceExtension);
42 static BOOLEAN
43 XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId);
44 static BOOLEAN
45 XenScsi_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState);
46 static SCSI_ADAPTER_CONTROL_STATUS
47 XenScsi_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters);
49 #ifdef ALLOC_PRAGMA
50 #pragma alloc_text (INIT, DriverEntry)
51 #endif
53 static PDRIVER_DISPATCH XenScsi_Pnp_Original;
55 static NTSTATUS
56 XenScsi_Pnp(PDEVICE_OBJECT device_object, PIRP irp)
57 {
58 PIO_STACK_LOCATION stack;
59 NTSTATUS status;
60 PCM_RESOURCE_LIST old_crl, new_crl;
61 PCM_PARTIAL_RESOURCE_LIST prl;
62 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
63 ULONG old_length, new_length;
64 PMDL mdl;
65 PUCHAR start, ptr;
67 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
69 stack = IoGetCurrentIrpStackLocation(irp);
71 // check if the Irp is meant for us... maybe the stack->DeviceObject field?
73 switch (stack->MinorFunction)
74 {
75 case IRP_MN_START_DEVICE:
76 KdPrint((__DRIVER_NAME " IRP_MN_START_DEVICE - DeviceObject = %p\n", stack->DeviceObject));
77 old_crl = stack->Parameters.StartDevice.AllocatedResourcesTranslated;
78 if (old_crl != NULL)
79 {
80 mdl = AllocateUncachedPage();
81 old_length = FIELD_OFFSET(CM_RESOURCE_LIST, List) +
82 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
83 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
84 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * old_crl->List[0].PartialResourceList.Count;
85 new_length = old_length + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1;
86 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENSCSI_POOL_TAG);
87 memcpy(new_crl, old_crl, old_length);
88 prl = &new_crl->List[0].PartialResourceList;
89 prd = &prl->PartialDescriptors[prl->Count++];
90 prd->Type = CmResourceTypeMemory;
91 prd->ShareDisposition = CmResourceShareDeviceExclusive;
92 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE|CM_RESOURCE_MEMORY_PREFETCHABLE|CM_RESOURCE_MEMORY_CACHEABLE;
93 KdPrint((__DRIVER_NAME " PFN[0] = %p\n", MmGetMdlPfnArray(mdl)[0]));
94 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
95 prd->u.Memory.Length = PAGE_SIZE;
96 KdPrint((__DRIVER_NAME " Start = %08x:%08x, Length = %d\n", prd->u.Memory.Start.HighPart, prd->u.Memory.Start.LowPart, prd->u.Memory.Length));
97 ptr = start = MmGetMdlVirtualAddress(mdl);
98 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL);
99 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL);
100 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "b-dev", NULL);
101 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_VECTORS, NULL, NULL);
102 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, UlongToPtr(GRANT_ENTRIES), NULL);
103 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL);
105 stack->Parameters.StartDevice.AllocatedResourcesTranslated = new_crl;
107 old_crl = stack->Parameters.StartDevice.AllocatedResources;
108 new_crl = ExAllocatePoolWithTag(PagedPool, new_length, XENSCSI_POOL_TAG);
109 memcpy(new_crl, old_crl, old_length);
110 prl = &new_crl->List[0].PartialResourceList;
111 prd = &prl->PartialDescriptors[prl->Count++];
112 prd->Type = CmResourceTypeMemory;
113 prd->ShareDisposition = CmResourceShareDeviceExclusive;
114 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE|CM_RESOURCE_MEMORY_PREFETCHABLE|CM_RESOURCE_MEMORY_CACHEABLE;
115 prd->u.Memory.Start.QuadPart = MmGetMdlPfnArray(mdl)[0] << PAGE_SHIFT;
116 prd->u.Memory.Length = PAGE_SIZE;
117 stack->Parameters.StartDevice.AllocatedResources = new_crl;
118 IoCopyCurrentIrpStackLocationToNext(irp);
119 }
120 else
121 {
122 KdPrint((__DRIVER_NAME " AllocatedResource == NULL\n"));
123 }
124 status = XenScsi_Pnp_Original(device_object, irp);
126 break;
128 case IRP_MN_QUERY_STOP_DEVICE:
129 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_STOP_DEVICE\n"));
130 status = XenScsi_Pnp_Original(device_object, irp);
131 break;
133 case IRP_MN_STOP_DEVICE:
134 KdPrint((__DRIVER_NAME " IRP_MN_STOP_DEVICE\n"));
135 status = XenScsi_Pnp_Original(device_object, irp);
136 break;
138 case IRP_MN_CANCEL_STOP_DEVICE:
139 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_STOP_DEVICE\n"));
140 status = XenScsi_Pnp_Original(device_object, irp);
141 break;
143 case IRP_MN_QUERY_REMOVE_DEVICE:
144 KdPrint((__DRIVER_NAME " IRP_MN_QUERY_REMOVE_DEVICE\n"));
145 status = XenScsi_Pnp_Original(device_object, irp);
146 break;
148 case IRP_MN_REMOVE_DEVICE:
149 KdPrint((__DRIVER_NAME " IRP_MN_REMOVE_DEVICE\n"));
150 status = XenScsi_Pnp_Original(device_object, irp);
151 break;
153 case IRP_MN_CANCEL_REMOVE_DEVICE:
154 KdPrint((__DRIVER_NAME " IRP_MN_CANCEL_REMOVE_DEVICE\n"));
155 status = XenScsi_Pnp_Original(device_object, irp);
156 break;
158 case IRP_MN_SURPRISE_REMOVAL:
159 KdPrint((__DRIVER_NAME " IRP_MN_SURPRISE_REMOVAL\n"));
160 status = XenScsi_Pnp_Original(device_object, irp);
161 break;
163 default:
164 KdPrint((__DRIVER_NAME " Unknown Minor = %d\n", stack->MinorFunction));
165 status = XenScsi_Pnp_Original(device_object, irp);
166 break;
167 }
169 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__"\n"));
171 return status;
172 }
174 NTSTATUS
175 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
176 {
177 ULONG Status;
178 HW_INITIALIZATION_DATA HwInitializationData;
180 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
181 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
183 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
185 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
186 HwInitializationData.AdapterInterfaceType = Internal;
187 HwInitializationData.HwDmaStarted = NULL;
188 HwInitializationData.DeviceExtensionSize = sizeof(XENSCSI_DEVICE_DATA);
189 HwInitializationData.SpecificLuExtensionSize = 0;
190 HwInitializationData.SrbExtensionSize = 0;
191 HwInitializationData.NumberOfAccessRanges = 1;
192 HwInitializationData.MapBuffers = TRUE;
193 HwInitializationData.NeedPhysicalAddresses = FALSE;
194 HwInitializationData.TaggedQueuing = TRUE;
195 HwInitializationData.AutoRequestSense = TRUE;
196 HwInitializationData.MultipleRequestPerLu = TRUE;
197 HwInitializationData.ReceiveEvent = FALSE;
198 HwInitializationData.VendorIdLength = 0;
199 HwInitializationData.VendorId = NULL;
200 HwInitializationData.DeviceIdLength = 0;
201 HwInitializationData.DeviceId = NULL;
203 XenScsi_FillInitCallbacks(&HwInitializationData);
205 Status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
207 /* this is a bit naughty... */
208 XenScsi_Pnp_Original = DriverObject->MajorFunction[IRP_MJ_PNP];
209 DriverObject->MajorFunction[IRP_MJ_PNP] = XenScsi_Pnp;
211 if(!NT_SUCCESS(Status))
212 {
213 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", Status));
214 }
216 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
218 return Status;
219 }