win-pvdrivers

annotate xenvbd/xenvbd.c @ 74:06b4321b7068

Created a common AllocagePages routine in xen_windows.h
Updated xennet and xenvbd to use it.
Updated xennet's method of getting the virtual address from the Mdl
author James Harper <james.harper@bendigoit.com.au>
date Thu Dec 20 21:37:20 2007 +1100 (2007-12-20)
parents f74723639713
children b7863ede7a37
rev   line source
james@0 1 #include "xenvbd.h"
james@0 2 #include <io/blkif.h>
james@0 3 #include <scsi.h>
james@0 4 #include <ntddscsi.h>
james@0 5 #include <ntdddisk.h>
james@0 6 #include <stdlib.h>
james@0 7 #include <xen_public.h>
james@0 8 #include <io/xenbus.h>
james@0 9
james@0 10 #define wmb() KeMemoryBarrier()
james@0 11 #define mb() KeMemoryBarrier()
james@0 12
james@48 13 #define BUF_PAGES_PER_SRB 11
james@48 14
james@0 15 DRIVER_INITIALIZE DriverEntry;
james@0 16
james@48 17 static ULONG
james@48 18 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again);
james@48 19 static BOOLEAN
james@48 20 XenVbd_HwScsiInitialize(PVOID DeviceExtension);
james@48 21 static BOOLEAN
james@48 22 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb);
james@48 23 static BOOLEAN
james@48 24 XenVbd_HwScsiInterrupt(PVOID DeviceExtension);
james@48 25 static BOOLEAN
james@48 26 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId);
james@48 27 static BOOLEAN
james@48 28 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState);
james@48 29 static SCSI_ADAPTER_CONTROL_STATUS
james@48 30 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters);
james@0 31
james@0 32 #ifdef ALLOC_PRAGMA
james@0 33 #pragma alloc_text (INIT, DriverEntry)
james@0 34 #endif
james@0 35
james@0 36 static BOOLEAN AutoEnumerate;
james@0 37
james@0 38 NTSTATUS
james@0 39 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
james@0 40 {
james@48 41 ULONG Status;
james@48 42 HW_INITIALIZATION_DATA HwInitializationData;
james@0 43
james@0 44 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
james@0 45
james@48 46 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
james@0 47
james@48 48 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
james@48 49 HwInitializationData.AdapterInterfaceType = Internal; //PNPBus;
james@48 50 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
james@48 51 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
james@48 52 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
james@48 53 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
james@48 54 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
james@48 55 HwInitializationData.HwDmaStarted = NULL;
james@48 56 HwInitializationData.HwAdapterState = NULL;
james@48 57 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
james@48 58 HwInitializationData.SpecificLuExtensionSize = 0;
james@48 59 HwInitializationData.SrbExtensionSize = 0;
james@48 60 HwInitializationData.NumberOfAccessRanges = 1;
james@0 61
james@48 62 //HwInitializationData.MapBuffers = FALSE;
james@48 63 HwInitializationData.MapBuffers = TRUE;
james@0 64
james@48 65 HwInitializationData.NeedPhysicalAddresses = FALSE;
james@48 66 // HwInitializationData.NeedPhysicalAddresses = TRUE;
james@0 67
james@48 68 HwInitializationData.TaggedQueuing = TRUE; //FALSE;
james@48 69 HwInitializationData.AutoRequestSense = FALSE;
james@48 70 HwInitializationData.MultipleRequestPerLu = FALSE;
james@48 71 HwInitializationData.ReceiveEvent = FALSE; // check this
james@48 72 HwInitializationData.VendorIdLength = 0;
james@48 73 HwInitializationData.VendorId = NULL;
james@48 74 HwInitializationData.DeviceIdLength = 0;
james@48 75 HwInitializationData.DeviceId = NULL;
james@48 76 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
james@0 77
james@48 78 Status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
james@48 79
james@48 80 if(!NT_SUCCESS(Status))
james@0 81 {
james@48 82 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", Status));
james@0 83 }
james@0 84
james@0 85 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
james@0 86
james@48 87 return Status;
james@0 88 }
james@0 89
james@48 90 static ULONG
james@48 91 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
james@48 92 {
james@48 93 ULONG Status = SP_RETURN_FOUND;
james@48 94 ULONG i;
james@48 95 PACCESS_RANGE AccessRange;
james@48 96 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@48 97
james@49 98 KeInitializeSpinLock(&DeviceData->Lock);
james@48 99 KdPrint((__DRIVER_NAME " --> HwScsiFindAdapter\n"));
james@48 100 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@48 101
james@48 102 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
james@48 103 KdPrint((__DRIVER_NAME " BusInterruptVector = %d\n", ConfigInfo->BusInterruptVector));
james@48 104
james@48 105 KdPrint((__DRIVER_NAME " AccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
james@48 106
james@48 107 for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++)
james@48 108 {
james@48 109 AccessRange = &(*(ConfigInfo->AccessRanges))[i];
james@48 110 KdPrint((__DRIVER_NAME " AccessRange %2d: RangeStart = %08x, RangeLength = %08x, RangeInMemory = %d\n", i, AccessRange->RangeStart.LowPart, AccessRange->RangeLength, AccessRange->RangeInMemory));
james@48 111 switch (i)
james@48 112 {
james@48 113 case 0:
james@48 114 DeviceData->XenDeviceData = (PXENPCI_XEN_DEVICE_DATA)AccessRange->RangeStart.QuadPart;
james@48 115 KdPrint((__DRIVER_NAME " Mapped to virtual address %08x\n", DeviceData->XenDeviceData));
james@48 116 KdPrint((__DRIVER_NAME " Magic = %08x\n", DeviceData->XenDeviceData->Magic));
james@48 117 if (DeviceData->XenDeviceData->Magic == XEN_DATA_MAGIC)
james@48 118 {
james@48 119 }
james@48 120 break;
james@48 121 default:
james@48 122 break;
james@48 123 }
james@48 124 }
james@48 125
james@48 126 ConfigInfo->NumberOfBuses = SCSI_BUSES;
james@48 127 ConfigInfo->MaximumTransferLength = BUF_PAGES_PER_SRB * PAGE_SIZE;
james@48 128 ConfigInfo->NumberOfPhysicalBreaks = BUF_PAGES_PER_SRB - 1; //11 - 1;
james@48 129 ConfigInfo->ScatterGather = TRUE;
james@48 130 ConfigInfo->Master = FALSE;
james@48 131 ConfigInfo->AlignmentMask = 0;
james@48 132 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
james@48 133 ConfigInfo->MaximumNumberOfTargets = SCSI_TARGETS_PER_BUS;
james@48 134 //ConfigInfo->TaggedQueueing = TRUE;
james@48 135
james@48 136 *Again = FALSE;
james@48 137
james@48 138 KdPrint((__DRIVER_NAME " <-- HwScsiFindAdapter\n"));
james@48 139
james@48 140 return Status;
james@48 141 }
james@48 142
james@48 143 static __inline uint64_t
james@48 144 GET_ID_FROM_FREELIST(PXENVBD_TARGET_DATA TargetData)
james@48 145 {
james@48 146 uint64_t free;
james@48 147 free = TargetData->shadow_free;
james@48 148 TargetData->shadow_free = TargetData->shadow[free].req.id;
james@48 149 TargetData->shadow[free].req.id = 0x0fffffee; /* debug */
james@48 150 return free;
james@48 151 }
james@48 152
james@48 153 static __inline VOID
james@48 154 ADD_ID_TO_FREELIST(PXENVBD_TARGET_DATA TargetData, uint64_t Id)
james@48 155 {
james@48 156 TargetData->shadow[Id].req.id = TargetData->shadow_free;
james@48 157 TargetData->shadow[Id].Srb = NULL;
james@48 158 TargetData->shadow_free = Id;
james@48 159 }
james@48 160
james@48 161 //static HANDLE XenVbd_ScsiPortThreadHandle;
james@48 162 //static KEVENT XenVbd_ScsiPortThreadEvent;
james@48 163
james@0 164 static VOID
james@48 165 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID DeviceExtension)
james@0 166 {
james@48 167 PXENVBD_TARGET_DATA TargetData = (PXENVBD_TARGET_DATA)DeviceExtension;
james@48 168
james@73 169 // KdPrint((__DRIVER_NAME " --> Interrupt\n"));
james@73 170
james@48 171 TargetData->PendingInterrupt = TRUE;
james@73 172
james@73 173 // KdPrint((__DRIVER_NAME " <-- Interrupt\n"));
james@48 174 return;
james@48 175 }
james@48 176
james@48 177 static VOID
james@48 178 XenVbd_HwScsiInterruptTarget(PVOID DeviceExtension)
james@48 179 {
james@48 180 PXENVBD_TARGET_DATA TargetData = (PXENVBD_TARGET_DATA)DeviceExtension;
james@48 181 PSCSI_REQUEST_BLOCK Srb;
james@0 182 RING_IDX i, rp;
james@0 183 int j;
james@0 184 blkif_response_t *rep;
james@0 185 char *DataBuffer;
james@0 186 int more_to_do;
james@0 187 int BlockCount;
james@48 188 KIRQL Irql;
james@8 189 int notify;
james@48 190 KAPC_STATE ApcState;
james@48 191 PIRP Irp;
james@48 192 PXENVBD_DEVICE_DATA DeviceData;
james@0 193
james@48 194 // KdPrint((__DRIVER_NAME " --> HwScsiInterruptTarget\n"));
james@0 195
james@48 196 DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
james@0 197 more_to_do = TRUE;
james@0 198
james@0 199 while (more_to_do)
james@0 200 {
james@48 201 rp = TargetData->Ring.sring->rsp_prod;
james@0 202 KeMemoryBarrier();
james@48 203 for (i = TargetData->Ring.rsp_cons; i != rp; i++)
james@0 204 {
james@48 205 rep = RING_GET_RESPONSE(&TargetData->Ring, i);
james@48 206 Srb = TargetData->shadow[rep->id].Srb;
james@49 207 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
james@48 208
james@49 209 if (rep->status == BLKIF_RSP_OKAY)
james@49 210 Srb->SrbStatus = SRB_STATUS_SUCCESS;
james@49 211 else
james@0 212 {
james@48 213 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
james@49 214 if (Srb->Cdb[0] == SCSIOP_READ)
james@49 215 KdPrint((__DRIVER_NAME " Operation = Read\n"));
james@49 216 else
james@49 217 KdPrint((__DRIVER_NAME " Operation = Write\n"));
james@49 218 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", TargetData->shadow[rep->id].req.sector_number, BlockCount));
james@49 219 Srb->SrbStatus = SRB_STATUS_ERROR;
james@0 220 }
james@48 221 for (j = 0; j < TargetData->shadow[rep->id].req.nr_segments; j++)
andy@56 222 DeviceData->XenDeviceData->GntTblInterface.EndAccess(
andy@56 223 DeviceData->XenDeviceData->GntTblInterface.InterfaceHeader.Context,
andy@56 224 TargetData->shadow[rep->id].req.seg[j].gref);
james@48 225 if (Srb->Cdb[0] == SCSIOP_READ)
james@48 226 memcpy(Srb->DataBuffer, TargetData->shadow[rep->id].Buf, BlockCount * TargetData->BytesPerSector);
james@48 227
james@48 228 ScsiPortNotification(RequestComplete, DeviceData, Srb);
james@58 229 ScsiPortNotification(NextLuRequest, DeviceData, Srb->PathId, Srb->TargetId, Srb->Lun);
james@0 230
james@48 231 ADD_ID_TO_FREELIST(TargetData, rep->id);
james@0 232 }
james@0 233
james@48 234 TargetData->Ring.rsp_cons = i;
james@48 235 if (i != TargetData->Ring.req_prod_pvt)
james@0 236 {
james@48 237 RING_FINAL_CHECK_FOR_RESPONSES(&TargetData->Ring, more_to_do);
james@0 238 }
james@0 239 else
james@0 240 {
james@48 241 TargetData->Ring.sring->rsp_event = i + 1;
james@0 242 more_to_do = FALSE;
james@0 243 }
james@0 244 }
james@0 245
james@48 246 // KdPrint((__DRIVER_NAME " <-- HwScsiInterruptTarget\n"));
james@4 247
james@48 248 return FALSE;
james@0 249 }
james@0 250
james@0 251 static BOOLEAN
james@48 252 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
james@0 253 {
james@48 254 PXENVBD_DEVICE_DATA DeviceData;
james@48 255 PXENVBD_TARGET_DATA TargetData;
james@48 256 int i, j;
james@0 257
james@48 258 // KdPrint((__DRIVER_NAME " --> HwScsiInterrupt\n"));
james@0 259
james@48 260 DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@0 261
james@48 262 KeMemoryBarrier();
james@48 263 for (i = 0; i < SCSI_BUSES; i++)
james@48 264 {
james@48 265 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
james@48 266 {
james@48 267 TargetData = &DeviceData->BusData[i].TargetData[j];
james@48 268 if (TargetData->PendingInterrupt)
james@48 269 XenVbd_HwScsiInterruptTarget(TargetData);
james@48 270 TargetData->PendingInterrupt = FALSE;
james@48 271 }
james@48 272 }
james@48 273 // KdPrint((__DRIVER_NAME " <-- HwScsiInterrupt\n"));
andy@56 274
andy@56 275 return TRUE;
james@0 276 }
james@0 277
james@0 278 static VOID
james@0 279 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
james@0 280 {
james@48 281 PXENVBD_TARGET_DATA TargetData;
james@48 282 PXENVBD_DEVICE_DATA DeviceData;
james@0 283 char TmpPath[128];
james@0 284 char *Value;
james@0 285 int NewState;
james@0 286 PMDL Mdl;
james@0 287 grant_ref_t ref;
james@0 288 blkif_sring_t *SharedRing;
james@0 289 ULONG PFN;
james@48 290 //XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
james@48 291 KIRQL OldIrql;
james@0 292 NTSTATUS status;
james@48 293 int i;
james@0 294
james@48 295 KdPrint((__DRIVER_NAME " --> BackEndStateHandler\n"));
james@49 296 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@0 297
james@48 298 TargetData = (PXENVBD_TARGET_DATA)Data;
james@48 299 DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
james@48 300
andy@56 301 DeviceData->XenDeviceData->XenBusInterface.Read(
andy@56 302 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
andy@56 303 XBT_NIL, Path, &Value);
james@0 304
james@0 305 NewState = atoi(Value);
james@0 306 switch (NewState)
james@0 307 {
james@0 308 case XenbusStateUnknown:
james@0 309 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
james@0 310 break;
james@0 311
james@0 312 case XenbusStateInitialising:
james@0 313 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
james@0 314 break;
james@0 315
james@0 316 case XenbusStateInitWait:
james@0 317 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
james@0 318
andy@56 319 TargetData->EventChannel = DeviceData->XenDeviceData->EvtChnInterface.AllocUnbound(
andy@56 320 DeviceData->XenDeviceData->EvtChnInterface.InterfaceHeader.Context, 0);
andy@56 321 DeviceData->XenDeviceData->EvtChnInterface.Bind(
andy@56 322 DeviceData->XenDeviceData->EvtChnInterface.InterfaceHeader.Context,
andy@56 323 TargetData->EventChannel, XenVbd_Interrupt, TargetData);
james@0 324 Mdl = AllocatePage();
james@0 325 PFN = *MmGetMdlPfnArray(Mdl);
james@0 326 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
james@0 327 SHARED_RING_INIT(SharedRing);
james@48 328 FRONT_RING_INIT(&TargetData->Ring, SharedRing, PAGE_SIZE);
andy@56 329 ref = DeviceData->XenDeviceData->GntTblInterface.GrantAccess(
andy@56 330 DeviceData->XenDeviceData->GntTblInterface.InterfaceHeader.Context,
andy@56 331 0, PFN, FALSE);
james@0 332
james@48 333 TargetData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
james@48 334
james@48 335 memset(TargetData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
james@48 336 for (i = 0; i < BLK_RING_SIZE; i++)
james@48 337 {
james@48 338 TargetData->shadow[i].req.id = i + 1;
james@48 339 TargetData->shadow[i].Mdl = AllocatePages(BUF_PAGES_PER_SRB); // stupid that we have to do this!
james@48 340 TargetData->shadow[i].Buf = MmGetMdlVirtualAddress(TargetData->shadow[i].Mdl);
james@48 341 }
james@48 342 TargetData->shadow_free = 0;
james@48 343 TargetData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
james@48 344
james@48 345 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
james@48 346 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
james@66 347 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", ref);
james@48 348
james@48 349 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
james@0 350 RtlStringCbCatA(TmpPath, 128, "/event-channel");
james@66 351 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", TargetData->EventChannel);
james@0 352
james@48 353 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
james@0 354 RtlStringCbCatA(TmpPath, 128, "/state");
james@66 355 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
james@0 356
james@0 357 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
james@0 358 break;
james@0 359
james@0 360 case XenbusStateInitialised:
james@0 361 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
james@0 362 break;
james@0 363
james@0 364 case XenbusStateConnected:
james@0 365 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
james@0 366
james@48 367 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
james@9 368 RtlStringCbCatA(TmpPath, 128, "/device-type");
andy@56 369 DeviceData->XenDeviceData->XenBusInterface.Read(
andy@56 370 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
andy@56 371 XBT_NIL, TmpPath, &Value);
james@9 372 if (strcmp(Value, "disk") == 0)
james@9 373 {
james@9 374 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
james@48 375 TargetData->DeviceType = XENVBD_DEVICETYPE_DISK;
james@9 376 }
james@9 377 else if (strcmp(Value, "cdrom") == 0)
james@9 378 {
james@9 379 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
james@48 380 TargetData->DeviceType = XENVBD_DEVICETYPE_CDROM;
james@9 381 }
james@9 382 else
james@9 383 {
james@9 384 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
james@48 385 TargetData->DeviceType = XENVBD_DEVICETYPE_UNKNOWN;
james@9 386 }
james@9 387
james@48 388 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
james@9 389 RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
andy@56 390 DeviceData->XenDeviceData->XenBusInterface.Read(
andy@56 391 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
andy@56 392 XBT_NIL, TmpPath, &Value);
james@9 393 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
andy@13 394 ExFreePool(Value);
james@0 395
james@48 396 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
james@0 397 RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
andy@56 398 DeviceData->XenDeviceData->XenBusInterface.Read(
andy@56 399 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
andy@56 400 XBT_NIL, TmpPath, &Value);
james@9 401 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
andy@13 402 ExFreePool(Value);
james@0 403
james@48 404 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
james@0 405 RtlStringCbCatA(TmpPath, 128, "/sector-size");
andy@56 406 DeviceData->XenDeviceData->XenBusInterface.Read(
andy@56 407 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
andy@56 408 XBT_NIL, TmpPath, &Value);
james@0 409 // should complain if Value == NULL
james@48 410 TargetData->BytesPerSector = atoi(Value);
james@0 411
james@48 412 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", TargetData->BytesPerSector));
james@0 413
james@48 414 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
james@0 415 RtlStringCbCatA(TmpPath, 128, "/sectors");
andy@56 416 DeviceData->XenDeviceData->XenBusInterface.Read(
andy@56 417 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
andy@56 418 XBT_NIL, TmpPath, &Value);
james@0 419 // should complain if Value == NULL
james@48 420 TargetData->TotalSectors = (ULONGLONG)atol(Value);
james@0 421
james@48 422 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", TargetData->TotalSectors));
james@0 423
james@0 424 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
james@48 425 TargetData->Geometry.MediaType = FixedMedia;
james@48 426 TargetData->Geometry.BytesPerSector = TargetData->BytesPerSector;
james@48 427 TargetData->Geometry.SectorsPerTrack = 63;
james@48 428 TargetData->Geometry.TracksPerCylinder = 255;
james@48 429 TargetData->Geometry.Cylinders.QuadPart = TargetData->TotalSectors / TargetData->Geometry.SectorsPerTrack / TargetData->Geometry.TracksPerCylinder;
james@48 430 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", TargetData->Geometry.Cylinders.LowPart, TargetData->Geometry.TracksPerCylinder, TargetData->Geometry.SectorsPerTrack));
james@48 431
james@48 432 // now ask windows to rescan the scsi bus...
james@48 433 DeviceData->BusChangePending = 1;
james@0 434
james@48 435 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
james@0 436 RtlStringCbCatA(TmpPath, 128, "/state");
james@66 437 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateConnected);
james@0 438
james@0 439 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
james@48 440 InterlockedIncrement(&DeviceData->EnumeratedDevices);
james@48 441 KdPrint((__DRIVER_NAME " Added a device, notifying\n"));
james@48 442 KeSetEvent(&DeviceData->WaitDevicesEvent, 1, FALSE);
james@0 443
james@0 444 break;
james@0 445
james@0 446 case XenbusStateClosing:
james@0 447 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
james@0 448 break;
james@0 449
james@0 450 case XenbusStateClosed:
james@0 451 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
james@0 452 break;
james@0 453
james@0 454 default:
james@0 455 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
james@0 456 break;
james@0 457 }
james@48 458
james@48 459 KdPrint((__DRIVER_NAME " <-- BackEndStateHandler\n"));
james@0 460 }
james@0 461
james@0 462 static VOID
james@48 463 XenVbd_WatchHandler(char *Path, PVOID DeviceExtension)
james@0 464 {
james@48 465 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@0 466 char **Bits;
james@0 467 int Count;
james@0 468 char TmpPath[128];
james@0 469 char *Value;
james@49 470 int CurrentBus, CurrentTarget;
james@49 471 PXENVBD_TARGET_DATA TargetData, VacantTarget;
james@49 472 KIRQL OldIrql;
james@48 473 int i, j;
james@0 474
james@48 475 KdPrint((__DRIVER_NAME " --> WatchHandler (DeviceData = %08x)\n", DeviceData));
james@0 476
james@48 477 KdPrint((__DRIVER_NAME " Path = %s\n", Path));
james@0 478
james@0 479 Bits = SplitString(Path, '/', 4, &Count);
james@0 480 switch (Count)
andy@56 481 {
james@0 482 case 0:
james@0 483 case 1:
james@0 484 case 2:
james@0 485 break; // should never happen
james@0 486 case 3:
james@0 487 break;
james@0 488 case 4:
james@0 489 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
james@0 490 break;
andy@56 491
james@49 492 KeAcquireSpinLock(&DeviceData->Lock, &OldIrql);
andy@56 493
james@49 494 for (VacantTarget = NULL,i = 0; i < SCSI_BUSES * SCSI_TARGETS_PER_BUS; i++)
james@0 495 {
james@49 496 CurrentBus = i / SCSI_TARGETS_PER_BUS;
james@49 497 CurrentTarget = i % SCSI_TARGETS_PER_BUS;
james@49 498 if (CurrentTarget == 7) // don't use 7 - it would be for the controller
james@49 499 continue;
james@49 500 TargetData = &DeviceData->BusData[CurrentBus].TargetData[CurrentTarget];
james@49 501 if (TargetData->Present && strncmp(TargetData->Path, Path, strlen(TargetData->Path)) == 0 && Path[strlen(TargetData->Path)] == '/')
james@49 502 break; // already exists
james@49 503 else if (!TargetData->Present && VacantTarget == NULL)
james@49 504 VacantTarget = TargetData;
james@49 505 }
james@49 506 if (i == SCSI_BUSES * SCSI_TARGETS_PER_BUS && VacantTarget != NULL)
james@49 507 {
james@49 508 VacantTarget->Present = 1;
james@49 509 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
andy@56 510
james@49 511 RtlStringCbCopyA(VacantTarget->Path, 128, Bits[0]);
james@49 512 RtlStringCbCatA(VacantTarget->Path, 128, "/");
james@49 513 RtlStringCbCatA(VacantTarget->Path, 128, Bits[1]);
james@49 514 RtlStringCbCatA(VacantTarget->Path, 128, "/");
james@49 515 RtlStringCbCatA(VacantTarget->Path, 128, Bits[2]);
james@48 516
james@49 517 VacantTarget->DeviceIndex = atoi(Bits[2]);
james@48 518
james@49 519 RtlStringCbCopyA(TmpPath, 128, VacantTarget->Path);
james@49 520 RtlStringCbCatA(TmpPath, 128, "/backend");
james@59 521 DeviceData->XenDeviceData->XenBusInterface.Read(
james@59 522 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
james@59 523 XBT_NIL, TmpPath, &Value);
james@49 524 if (Value == NULL)
james@49 525 KdPrint((__DRIVER_NAME " Read Failed\n"));
james@49 526 else
james@49 527 RtlStringCbCopyA(VacantTarget->BackendPath, 128, Value);
james@49 528 RtlStringCbCopyA(TmpPath, 128, VacantTarget->BackendPath);
james@49 529 RtlStringCbCatA(TmpPath, 128, "/state");
james@48 530
james@59 531 DeviceData->XenDeviceData->XenBusInterface.AddWatch(
james@59 532 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
james@59 533 XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, VacantTarget);
james@0 534 }
james@49 535 else
james@49 536 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
james@0 537 break;
james@0 538 }
james@0 539
james@0 540 FreeSplitString(Bits, Count);
james@0 541
james@48 542 KdPrint((__DRIVER_NAME " <-- WatchHandler\n"));
james@0 543
james@0 544 return;
james@0 545 }
james@0 546
james@48 547 static VOID
james@48 548 XenVbd_CheckBusChangedTimer(PVOID DeviceExtension)
james@0 549 {
james@48 550 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@9 551
james@48 552 if (DeviceData->BusChangePending)
james@48 553 {
james@48 554 ScsiPortNotification(BusChangeDetected, DeviceData, 0);
james@48 555 DeviceData->BusChangePending = 0;
james@9 556 }
james@48 557 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
james@48 558 }
james@47 559
james@48 560 static BOOLEAN
james@48 561 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
james@48 562 {
james@48 563 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@48 564 unsigned int i, j;
james@48 565 NTSTATUS Status;
james@48 566 char **VbdDevices;
james@48 567 char *msg;
james@48 568 char buffer[128];
james@48 569 LARGE_INTEGER WaitTimeout;
james@47 570
james@48 571 KdPrint((__DRIVER_NAME " --> HwScsiInitialize\n"));
james@48 572 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@8 573
james@48 574 for (i = 0; i < SCSI_BUSES; i++)
james@0 575 {
james@48 576 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
james@48 577 {
james@48 578 DeviceData->BusData[i].TargetData[j].Present = 0;
james@48 579 DeviceData->BusData[i].TargetData[j].DeviceData = DeviceData;
james@48 580 }
james@0 581 }
james@0 582
james@48 583 DeviceData->XenDeviceData->WatchContext = DeviceExtension;
james@48 584 KeMemoryBarrier();
james@48 585 DeviceData->XenDeviceData->WatchHandler = XenVbd_WatchHandler;
james@0 586
james@48 587 KeInitializeEvent(&DeviceData->WaitDevicesEvent, SynchronizationEvent, FALSE);
james@48 588 DeviceData->EnumeratedDevices = 0;
james@48 589 if (DeviceData->XenDeviceData->AutoEnumerate)
james@0 590 {
andy@56 591 msg = DeviceData->XenDeviceData->XenBusInterface.List(
andy@56 592 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
andy@56 593 XBT_NIL, "device/vbd", &VbdDevices);
james@48 594 if (!msg) {
james@48 595 for (i = 0; VbdDevices[i]; i++)
james@48 596 {
james@48 597 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
james@48 598 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
james@48 599 XenVbd_WatchHandler(buffer, DeviceData);
james@49 600 // WaitTimeout.QuadPart = -600000000;
james@49 601 KeWaitForSingleObject(&DeviceData->WaitDevicesEvent, Executive, KernelMode, FALSE, NULL);
james@49 602 KdPrint((__DRIVER_NAME " %d devices enumerated\n", DeviceData->EnumeratedDevices));
james@49 603 }
james@49 604 }
james@49 605 /*
james@49 606 for (i = 0; VbdDevices[i]; i++)
james@49 607 {
james@49 608 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
james@49 609 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
james@49 610 XenVbd_WatchHandler(buffer, DeviceData);
james@48 611 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
james@48 612 }
james@48 613 KdPrint((__DRIVER_NAME " Waiting for %d devices to be enumerated\n", i));
james@48 614 while (DeviceData->EnumeratedDevices < i)
james@48 615 {
james@48 616 WaitTimeout.QuadPart = -600000000;
james@48 617 if (KeWaitForSingleObject(&DeviceData->WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
james@48 618 {
james@48 619 KdPrint((__DRIVER_NAME " Wait timed out\n"));
james@48 620 break;
james@48 621 }
james@48 622 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", DeviceData->EnumeratedDevices, i));
james@48 623 }
james@48 624 }
james@49 625 */
james@48 626 ScsiPortNotification(BusChangeDetected, DeviceData, 0);
james@48 627 DeviceData->BusChangePending = 0;
james@0 628 }
james@48 629 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
james@8 630
james@48 631 KdPrint((__DRIVER_NAME " <-- HwScsiInitialize\n"));
james@0 632
james@48 633 return TRUE;
james@8 634 }
james@8 635
james@8 636 static ULONG
james@48 637 XenVbd_FillModePage(PXENVBD_DEVICE_DATA DeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
james@8 638 {
james@8 639 PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
james@8 640
james@8 641 switch (PageCode)
james@0 642 {
james@48 643 /*
james@8 644 case MODE_PAGE_RIGID_GEOMETRY:
james@48 645 if (DeviceData->ScsiData->DeviceType == XENVBD_DEVICETYPE_CDROM)
james@9 646 {
james@8 647 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
james@48 648 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
james@48 649 return 1;
james@8 650 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
james@8 651 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
james@8 652 ModeRigidGeometry->PageCode = PageCode;
james@8 653 ModeRigidGeometry->PageSavable = 0;
james@8 654 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
james@48 655 ModeRigidGeometry->NumberOfCylinders[0] = (DeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
james@48 656 ModeRigidGeometry->NumberOfCylinders[1] = (DeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
james@48 657 ModeRigidGeometry->NumberOfCylinders[2] = (DeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
james@48 658 ModeRigidGeometry->NumberOfHeads = DeviceData->Geometry.TracksPerCylinder;
james@8 659 //ModeRigidGeometry->LandZoneCyclinder = 0;
james@8 660 ModeRigidGeometry->RoataionRate[0] = 0x05;
james@8 661 ModeRigidGeometry->RoataionRate[0] = 0x39;
james@48 662 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
james@9 663 }
james@8 664 break;
james@48 665 */
james@8 666 case MODE_PAGE_FAULT_REPORTING:
james@8 667 break;
james@8 668 default:
james@8 669 break;
james@0 670 }
james@8 671 return 0;
james@0 672 }
james@0 673
james@48 674 // Call with device lock held
james@48 675 static VOID
james@48 676 XenVbd_PutSrbOnRing(PXENVBD_TARGET_DATA TargetData, PSCSI_REQUEST_BLOCK Srb)
james@29 677 {
james@48 678 //PUCHAR DataBuffer;
james@48 679 blkif_request_t *req;
james@48 680 int i;
james@48 681 int j;
james@48 682 int BlockCount;
james@48 683 int sect_offset;
james@48 684 PVOID CurrentVirtual;
james@48 685 ULONG CurrentLength;
james@48 686 ULONG SegmentLength;
james@48 687 SCSI_PHYSICAL_ADDRESS PageAddress;
james@48 688 int Iterations;
james@48 689 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
james@29 690
james@48 691 // can use SRB_STATUS_BUSY to push the SRB back to windows...
james@29 692
james@48 693 // KdPrint((__DRIVER_NAME " --> PutSrbOnRing\n"));
james@35 694
james@48 695 if (RING_FULL(&TargetData->Ring))
james@29 696 {
james@48 697 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
james@48 698 // TODO: Fail badly here
james@29 699 }
james@29 700
james@48 701 req = RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt);
james@29 702
james@48 703 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
james@48 704 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
james@48 705
james@48 706 req->id = GET_ID_FROM_FREELIST(TargetData);
james@48 707
james@48 708 if (req->id == 0x0fffffff)
james@48 709 {
james@48 710 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutSrbOnRing\n"));
james@48 711 }
james@48 712
james@48 713 req->handle = 0;
james@48 714 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
james@48 715 TargetData->shadow[req->id].Srb = Srb;
james@48 716
james@48 717 // KdPrint((__DRIVER_NAME " DataBuffer = %08X\n", Srb->DataBuffer));
james@48 718 // KdPrint((__DRIVER_NAME " BlockCount = %08X\n", BlockCount));
james@48 719
james@48 720 req->nr_segments = (BlockCount * TargetData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE;
james@48 721 // KdPrint((__DRIVER_NAME " req->nr_segments = %08X\n", req->nr_segments));
james@48 722
james@48 723 for (i = 0; i < req->nr_segments; i++)
james@48 724 {
andy@56 725 req->seg[i].gref = DeviceData->XenDeviceData->GntTblInterface.GrantAccess(
andy@56 726 DeviceData->XenDeviceData->GntTblInterface.InterfaceHeader.Context,
andy@56 727 0, MmGetMdlPfnArray(TargetData->shadow[req->id].Mdl)[i], FALSE);
james@48 728 req->seg[i].first_sect = 0;
james@48 729 if (i == req->nr_segments - 1)
james@48 730 req->seg[i].last_sect = (BlockCount - 1) % (PAGE_SIZE / TargetData->BytesPerSector);
james@48 731 else
james@48 732 req->seg[i].last_sect = PAGE_SIZE / TargetData->BytesPerSector - 1;
james@48 733 // KdPrint((__DRIVER_NAME " Page %d, first_sect = %d, last_sect = %d\n", i, req->seg[i].first_sect, req->seg[i].last_sect));
james@48 734 }
james@48 735 if (Srb->Cdb[0] == SCSIOP_WRITE)
james@48 736 memcpy(TargetData->shadow[req->id].Buf, Srb->DataBuffer, BlockCount * TargetData->BytesPerSector);
james@48 737 TargetData->shadow[req->id].req = *req;
james@48 738 TargetData->Ring.req_prod_pvt++;
james@48 739
james@48 740 // KdPrint((__DRIVER_NAME " <-- PutSrbOnRing\n"));
james@29 741 }
james@29 742
james@48 743 static BOOLEAN
james@48 744 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
james@9 745 {
james@48 746 PUCHAR DataBuffer;
james@48 747 PCDB cdb;
james@48 748 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
james@48 749 PXENVBD_TARGET_DATA TargetData;
james@48 750 unsigned int i;
james@48 751 KIRQL KIrql;
james@48 752 int notify;
james@48 753 SCSI_PHYSICAL_ADDRESS ScsiPhysicalAddress;
james@48 754 ULONG Length;
james@9 755
james@48 756 // KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
james@48 757 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@0 758
james@48 759 if (Srb->PathId >= SCSI_BUSES || Srb->TargetId >= SCSI_TARGETS_PER_BUS)
james@48 760 {
james@48 761 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
james@48 762 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 763 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@48 764 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
james@48 765 return TRUE;
james@48 766 }
james@0 767
james@48 768 TargetData = &DeviceData->BusData[Srb->PathId].TargetData[Srb->TargetId];
james@9 769
james@48 770 if (!TargetData->Present)
james@48 771 {
james@48 772 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
james@48 773 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 774 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@48 775 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Not Present)\n"));
james@48 776 return TRUE;
james@48 777 }
james@0 778
james@0 779 switch (Srb->Function)
james@0 780 {
james@0 781 case SRB_FUNCTION_EXECUTE_SCSI:
james@8 782 cdb = (PCDB)Srb->Cdb;
james@48 783 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
james@48 784 switch(cdb->CDB6GENERIC.OperationCode)
james@9 785 {
james@0 786 case SCSIOP_TEST_UNIT_READY:
james@70 787 // KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
james@0 788 Srb->SrbStatus = SRB_STATUS_SUCCESS;
james@0 789 Srb->ScsiStatus = 0;
james@48 790 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 791 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 792 break;
james@0 793 case SCSIOP_INQUIRY:
james@8 794 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
james@8 795 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
james@48 796 KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
james@48 797 KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
james@48 798 // KdPrint((__DRIVER_NAME " PhysicalAddress.LowPart = %08x\n", ScsiPortGetPhysicalAddress(DeviceData, Srb, Srb->DataBuffer, &Length).LowPart));
james@48 799 // DataBuffer = ScsiPortGetVirtualAddress(DeviceData, ScsiPortGetPhysicalAddress(DeviceData, Srb, Srb->DataBuffer, &Length));
james@48 800 // KdPrint((__DRIVER_NAME " (Databuffer = %08x)\n", DataBuffer));
james@48 801 // break;
james@48 802 DataBuffer = Srb->DataBuffer;
james@48 803 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
james@48 804 Srb->SrbStatus = SRB_STATUS_SUCCESS;
james@48 805 switch (TargetData->DeviceType)
james@0 806 {
james@48 807 case XENVBD_DEVICETYPE_DISK:
james@48 808 if ((Srb->Cdb[1] & 1) == 0)
james@48 809 {
james@48 810 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
james@48 811 DataBuffer[1] = 0x00; // not removable
james@48 812 DataBuffer[3] = 32;
james@48 813 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
james@48 814 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
james@48 815 memcpy(DataBuffer + 32, "0000", 4); // product revision level
james@48 816 }
james@48 817 else
james@48 818 {
james@48 819 switch (Srb->Cdb[2])
james@48 820 {
james@48 821 case 0x00:
james@48 822 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
james@48 823 DataBuffer[1] = 0x00;
james@48 824 DataBuffer[2] = 0x00;
james@48 825 DataBuffer[3] = 2;
james@48 826 DataBuffer[4] = 0x00;
james@48 827 DataBuffer[5] = 0x80;
james@48 828 break;
james@48 829 case 0x80:
james@48 830 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
james@48 831 DataBuffer[1] = 0x80;
james@48 832 DataBuffer[2] = 0x00;
james@48 833 DataBuffer[3] = 8;
james@48 834 DataBuffer[4] = 0x31;
james@48 835 DataBuffer[5] = 0x32;
james@48 836 DataBuffer[6] = 0x33;
james@48 837 DataBuffer[7] = 0x34;
james@48 838 DataBuffer[8] = 0x35;
james@48 839 DataBuffer[9] = 0x36;
james@48 840 DataBuffer[10] = 0x37;
james@48 841 DataBuffer[11] = 0x38;
james@48 842 break;
james@48 843 default:
james@48 844 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
james@48 845 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@48 846 break;
james@48 847 }
james@48 848 }
james@48 849 break;
james@48 850 case XENVBD_DEVICETYPE_CDROM:
james@48 851 if ((Srb->Cdb[1] & 1) == 0)
james@48 852 {
james@48 853 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
james@48 854 DataBuffer[1] = 0x01; // removable
james@48 855 DataBuffer[3] = 32;
james@48 856 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
james@48 857 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
james@48 858 memcpy(DataBuffer + 32, "0000", 4); // product revision level
james@48 859 }
james@48 860 else
james@48 861 {
james@48 862 switch (Srb->Cdb[2])
james@48 863 {
james@48 864 case 0x00:
james@48 865 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
james@48 866 DataBuffer[1] = 0x00;
james@48 867 DataBuffer[2] = 0x00;
james@48 868 DataBuffer[3] = 2;
james@48 869 DataBuffer[4] = 0x00;
james@48 870 DataBuffer[5] = 0x80;
james@48 871 break;
james@48 872 case 0x80:
james@48 873 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
james@48 874 DataBuffer[1] = 0x80;
james@48 875 DataBuffer[2] = 0x00;
james@48 876 DataBuffer[3] = 8;
james@48 877 DataBuffer[4] = 0x31;
james@48 878 DataBuffer[5] = 0x32;
james@48 879 DataBuffer[6] = 0x33;
james@48 880 DataBuffer[7] = 0x34;
james@48 881 DataBuffer[8] = 0x35;
james@48 882 DataBuffer[9] = 0x36;
james@48 883 DataBuffer[10] = 0x37;
james@48 884 DataBuffer[11] = 0x38;
james@48 885 break;
james@48 886 default:
james@48 887 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
james@48 888 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@48 889 break;
james@48 890 }
james@48 891 }
james@48 892 break;
james@48 893 default:
james@48 894 KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", TargetData->DeviceType));
james@48 895 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@48 896 break;
james@0 897 }
james@48 898 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 899 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 900 break;
james@0 901 case SCSIOP_READ_CAPACITY:
james@48 902 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
james@48 903 DataBuffer = Srb->DataBuffer;
james@47 904 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
james@49 905 DataBuffer[0] = (unsigned char)((TargetData->TotalSectors - 1) >> 24) & 0xff;
james@49 906 DataBuffer[1] = (unsigned char)((TargetData->TotalSectors - 1) >> 16) & 0xff;
james@49 907 DataBuffer[2] = (unsigned char)((TargetData->TotalSectors - 1) >> 8) & 0xff;
james@49 908 DataBuffer[3] = (unsigned char)((TargetData->TotalSectors - 1) >> 0) & 0xff;
james@48 909 DataBuffer[4] = (unsigned char)(TargetData->BytesPerSector >> 24) & 0xff;
james@48 910 DataBuffer[5] = (unsigned char)(TargetData->BytesPerSector >> 16) & 0xff;
james@48 911 DataBuffer[6] = (unsigned char)(TargetData->BytesPerSector >> 8) & 0xff;
james@48 912 DataBuffer[7] = (unsigned char)(TargetData->BytesPerSector >> 0) & 0xff;
james@0 913 Srb->ScsiStatus = 0;
james@0 914 Srb->SrbStatus = SRB_STATUS_SUCCESS;
james@48 915 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 916 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 917 break;
james@0 918 case SCSIOP_MODE_SENSE:
james@48 919 KdPrint((__DRIVER_NAME " Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", Srb->Cdb[1] & 0x10, Srb->Cdb[2] & 0xC0, Srb->Cdb[2] & 0x3F));
james@8 920 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
james@8 921
james@48 922 Srb->ScsiStatus = 0;
james@48 923 Srb->SrbStatus = SRB_STATUS_SUCCESS;
james@48 924 Srb->DataTransferLength = 0;
james@48 925 DataBuffer = Srb->DataBuffer;
james@29 926 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
james@48 927 switch(cdb->MODE_SENSE.PageCode)
james@0 928 {
james@8 929 case MODE_SENSE_RETURN_ALL:
james@8 930 //Ptr = (UCHAR *)Srb->DataBuffer;
james@8 931 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
james@8 932 {
james@48 933 if (XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength))
james@48 934 {
james@48 935 break;
james@48 936 }
james@8 937 }
james@8 938 break;
james@0 939 default:
james@48 940 XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength);
james@8 941 break;
james@0 942 }
james@48 943 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 944 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 945 break;
james@0 946 case SCSIOP_READ:
james@0 947 case SCSIOP_WRITE:
james@48 948 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
james@48 949 XenVbd_PutSrbOnRing(TargetData, Srb);
james@48 950 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
james@48 951 if (notify)
andy@56 952 DeviceData->XenDeviceData->EvtChnInterface.Notify(
andy@56 953 DeviceData->XenDeviceData->EvtChnInterface.InterfaceHeader.Context,
andy@56 954 TargetData->EventChannel);
james@48 955 if (!RING_FULL(&TargetData->Ring))
james@58 956 ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
james@58 957 else
james@58 958 ScsiPortNotification(NextRequest, DeviceExtension);
james@0 959 break;
james@48 960 case SCSIOP_REPORT_LUNS:
james@48 961 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
james@48 962 Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
james@48 963 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 964 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@47 965 break;
james@29 966 case SCSIOP_READ_TOC:
james@48 967 DataBuffer = Srb->DataBuffer;
james@48 968 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
james@29 969 /*
james@29 970 #define READ_TOC_FORMAT_TOC 0x00
james@29 971 #define READ_TOC_FORMAT_SESSION 0x01
james@29 972 #define READ_TOC_FORMAT_FULL_TOC 0x02
james@29 973 #define READ_TOC_FORMAT_PMA 0x03
james@29 974 #define READ_TOC_FORMAT_ATIP 0x04
james@29 975 */
james@29 976 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
james@29 977 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
james@29 978 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
james@29 979 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
james@29 980 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
james@29 981 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
james@29 982 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
james@29 983 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
james@29 984 switch (cdb->READ_TOC.Format2)
james@29 985 {
james@29 986 case READ_TOC_FORMAT_TOC:
james@29 987 DataBuffer[0] = 0; // length MSB
james@29 988 DataBuffer[1] = 10; // length LSB
james@29 989 DataBuffer[2] = 1; // First Track
james@29 990 DataBuffer[3] = 1; // Last Track
james@29 991 DataBuffer[4] = 0; // Reserved
james@29 992 DataBuffer[5] = 0x14; // current position data + uninterrupted data
james@29 993 DataBuffer[6] = 1; // last complete track
james@29 994 DataBuffer[7] = 0; // reserved
james@29 995 DataBuffer[8] = 0; // MSB Block
james@29 996 DataBuffer[9] = 0;
james@29 997 DataBuffer[10] = 0;
james@29 998 DataBuffer[11] = 0; // LSB Block
james@29 999 Srb->SrbStatus = SRB_STATUS_SUCCESS;
james@29 1000 break;
james@29 1001 case READ_TOC_FORMAT_SESSION:
james@29 1002 case READ_TOC_FORMAT_FULL_TOC:
james@29 1003 case READ_TOC_FORMAT_PMA:
james@29 1004 case READ_TOC_FORMAT_ATIP:
james@29 1005 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@29 1006 break;
james@29 1007 }
james@48 1008 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 1009 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@29 1010 break;
james@0 1011 default:
james@9 1012 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
james@29 1013 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@48 1014 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 1015 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 1016 break;
james@0 1017 }
james@0 1018 break;
james@0 1019 case SRB_FUNCTION_CLAIM_DEVICE:
james@48 1020 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
james@48 1021 // ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
james@48 1022 // Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
james@0 1023 Srb->SrbStatus = SRB_STATUS_SUCCESS;
james@48 1024 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 1025 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 1026 break;
james@0 1027 case SRB_FUNCTION_IO_CONTROL:
james@47 1028 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
james@0 1029 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@48 1030 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 1031 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 1032 break;
james@0 1033 case SRB_FUNCTION_FLUSH:
james@47 1034 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
james@48 1035 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@48 1036 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 1037 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 1038 break;
james@0 1039 default:
james@0 1040 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
james@48 1041 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
james@48 1042 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
james@48 1043 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
james@0 1044 break;
james@0 1045 }
james@0 1046
james@48 1047 // KdPrint((__DRIVER_NAME " <-- HwScsiStartIo\n"));
james@0 1048
james@48 1049 return TRUE;
james@0 1050 }
james@48 1051
james@48 1052 static BOOLEAN
james@48 1053 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
james@48 1054 {
james@48 1055 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
james@48 1056 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@48 1057
james@48 1058 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
james@48 1059
james@48 1060 return TRUE;
james@48 1061 }
james@48 1062
james@48 1063
james@48 1064 static BOOLEAN
james@48 1065 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
james@48 1066 {
james@48 1067 KdPrint((__DRIVER_NAME " --> HwScsiAdapterState\n"));
james@48 1068 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@48 1069
james@48 1070 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterState\n"));
james@48 1071
james@48 1072 return TRUE;
james@48 1073 }
james@48 1074
james@48 1075 static SCSI_ADAPTER_CONTROL_STATUS
james@48 1076 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
james@48 1077 {
james@48 1078 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
james@48 1079 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
james@48 1080
james@48 1081 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
james@48 1082 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
james@48 1083
james@48 1084 switch (ControlType)
james@48 1085 {
james@48 1086 case ScsiQuerySupportedControlTypes:
james@48 1087 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
james@48 1088 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
james@48 1089 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
james@48 1090 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
james@48 1091 break;
james@48 1092 case ScsiStopAdapter:
james@48 1093 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
james@48 1094 break;
james@48 1095 case ScsiRestartAdapter:
james@48 1096 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
james@48 1097 break;
james@48 1098 case ScsiSetBootConfig:
james@48 1099 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
james@48 1100 break;
james@48 1101 case ScsiSetRunningConfig:
james@48 1102 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
james@48 1103 break;
james@48 1104 default:
james@48 1105 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
james@48 1106 break;
james@48 1107 }
james@48 1108
james@48 1109 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
james@48 1110
james@48 1111 return Status;
james@48 1112 }