win-pvdrivers

changeset 58:70ab0938d3db

Added a 'XenShutdown' interface to allow a userspace program to listen for shutdown events
author James Harper <james.harper@bendigoit.com.au>
date Tue Dec 18 20:51:54 2007 +1100 (2007-12-18)
parents 4f37f90fc704
children d01d2a544b72
files xenpci/sources xenpci/xenpci.c xenvbd/sources xenvbd/xenvbd.c
line diff
     1.1 --- a/xenpci/sources	Sun Dec 16 17:44:31 2007 +1100
     1.2 +++ b/xenpci/sources	Tue Dec 18 20:51:54 2007 +1100
     1.3 @@ -1,7 +1,7 @@
     1.4  TARGETNAME=XENPCI
     1.5  TARGETTYPE=DRIVER
     1.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     1.7 -VERSION=0.4.0.12
     1.8 +VERSION=0.4.0.25
     1.9  KMDF_VERSION=1
    1.10  MSC_WARNING_LEVEL=/W4
    1.11  INF_NAME=xenpci
     2.1 --- a/xenpci/xenpci.c	Sun Dec 16 17:44:31 2007 +1100
     2.2 +++ b/xenpci/xenpci.c	Tue Dec 18 20:51:54 2007 +1100
     2.3 @@ -41,6 +41,8 @@ static NTSTATUS
     2.4  XenPCI_D0ExitPreInterruptsDisabled(WDFDEVICE  Device, WDF_POWER_DEVICE_STATE TargetState);
     2.5  static VOID
     2.6  XenPCI_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
     2.7 +static VOID 
     2.8 +XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
     2.9  static NTSTATUS
    2.10  XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice);
    2.11  static NTSTATUS
    2.12 @@ -75,6 +77,18 @@ static BOOLEAN AutoEnumerate;
    2.13  
    2.14  static WDFDEVICE Device;
    2.15  
    2.16 +static LIST_ENTRY ShutdownMsgList;
    2.17 +
    2.18 +typedef struct {
    2.19 +  LIST_ENTRY Entry;
    2.20 +  ULONG Ptr;
    2.21 +//  ULONG Len;
    2.22 +  UCHAR Buf[0];
    2.23 +} SHUTDOWN_MSG_ENTRY, *PSHUTDOWN_MSG_ENTRY;
    2.24 +
    2.25 +static KSPIN_LOCK ShutdownMsgLock;
    2.26 +//static KEVENT ShutdownMsgEvent;
    2.27 +
    2.28  CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptRaw;
    2.29  CM_PARTIAL_RESOURCE_DESCRIPTOR InterruptTranslated;
    2.30  
    2.31 @@ -98,6 +112,9 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
    2.32  
    2.33    KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
    2.34  
    2.35 +  InitializeListHead(&ShutdownMsgList);
    2.36 +  KeInitializeSpinLock(&ShutdownMsgLock);
    2.37 +
    2.38    RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
    2.39    InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
    2.40    status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
    2.41 @@ -192,19 +209,6 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
    2.42    return status;
    2.43  }
    2.44  
    2.45 -static void WRMSR(unsigned int msr, ULONGLONG val)
    2.46 -{
    2.47 -  ULONG lo, hi;
    2.48 -  lo = (ULONG)val;
    2.49 -  hi = (ULONG)(val >> 32);
    2.50 -  __asm  {
    2.51 -    mov ecx, msr
    2.52 -    mov eax, lo
    2.53 -    mov edx, hi
    2.54 -    wrmsr
    2.55 -  }
    2.56 -}
    2.57 -
    2.58  static int
    2.59  get_hypercall_stubs()
    2.60  {
    2.61 @@ -236,7 +240,7 @@ get_hypercall_stubs()
    2.62      //pfn = vmalloc_to_pfn((char *)hypercall_stubs + i * PAGE_SIZE);
    2.63      pfn = (ULONG)(MmGetPhysicalAddress(hypercall_stubs + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
    2.64      //KdPrint((__DRIVER_NAME " pfn = %08X\n", pfn));
    2.65 -    WRMSR(msr, ((ULONGLONG)pfn << PAGE_SHIFT) + i);
    2.66 +    __writemsr(msr, ((ULONGLONG)pfn << PAGE_SHIFT) + i);
    2.67    }
    2.68    return STATUS_SUCCESS;
    2.69  }
    2.70 @@ -305,44 +309,34 @@ set_callback_irq(ULONGLONG irq)
    2.71    return retval;
    2.72  }
    2.73  
    2.74 +WDFQUEUE ReadQueue;
    2.75 +
    2.76  static NTSTATUS
    2.77  XenPCI_AddDevice(
    2.78      IN WDFDRIVER Driver,
    2.79      IN PWDFDEVICE_INIT DeviceInit
    2.80      )
    2.81  {
    2.82 -  NTSTATUS status;
    2.83 +  NTSTATUS Status;
    2.84    WDF_CHILD_LIST_CONFIG config;
    2.85    //PXENPCI_DEVICE_DATA devData = NULL;
    2.86    WDF_OBJECT_ATTRIBUTES attributes;
    2.87    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
    2.88 -  //WDF_IO_QUEUE_CONFIG ioQConfig;
    2.89 -  WDF_INTERRUPT_CONFIG interruptConfig;
    2.90 +  WDF_IO_QUEUE_CONFIG IoQConfig;
    2.91 +  WDF_INTERRUPT_CONFIG InterruptConfig;
    2.92    PNP_BUS_INFORMATION busInfo;
    2.93    BUS_INTERFACE_STANDARD BusInterface;
    2.94 -  //WDFDEVICE Parent;
    2.95 -
    2.96 -  //PDEVICE_OBJECT pdo;
    2.97 -  //ULONG propertyAddress, length;
    2.98 +  DECLARE_CONST_UNICODE_STRING(DeviceName, L"\\Device\\XenShutdown");
    2.99 +  DECLARE_CONST_UNICODE_STRING(SymbolicName, L"\\DosDevices\\XenShutdown");
   2.100  
   2.101    UNREFERENCED_PARAMETER(Driver);
   2.102  
   2.103    KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
   2.104  
   2.105 -  // get PDO
   2.106 -  // get parent (should be PCI bus) (WdfPdoGetParent)
   2.107 -  // 
   2.108 -
   2.109    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
   2.110    WDF_CHILD_LIST_CONFIG_INIT(&config, sizeof(XENPCI_IDENTIFICATION_DESCRIPTION), XenPCI_ChildListCreateDevice);
   2.111    WdfFdoInitSetDefaultChildListConfig(DeviceInit, &config, WDF_NO_OBJECT_ATTRIBUTES);
   2.112  
   2.113 -//  WDF_FDO_EVENT_CALLBACKS_INIT(&FdoCallbacks);
   2.114 -//  FdoCallbacks.EvtDeviceFilterRemoveResourceRequirements = XenPCI_FilterRemoveResourceRequirements;
   2.115 -//  FdoCallbacks.EvtDeviceFilterAddResourceRequirements = XenPCI_FilterAddResourceRequirements;
   2.116 -//  FdoCallbacks.EvtDeviceRemoveAddedResources = XenPCI_RemoveAddedResources;
   2.117 -//  WdfFdoInitSetEventCallbacks(DeviceInit, &FdoCallbacks);
   2.118 -
   2.119    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
   2.120    pnpPowerCallbacks.EvtDevicePrepareHardware = XenPCI_PrepareHardware;
   2.121    pnpPowerCallbacks.EvtDeviceReleaseHardware = XenPCI_ReleaseHardware;
   2.122 @@ -354,48 +348,114 @@ XenPCI_AddDevice(
   2.123  
   2.124    WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
   2.125  
   2.126 +  Status = WdfDeviceInitAssignName(DeviceInit, &DeviceName);
   2.127 +  if (!NT_SUCCESS(Status))
   2.128 +  {
   2.129 +    KdPrint((__DRIVER_NAME "     WdfDeviceInitAssignName failed 0x%08x\n", Status));
   2.130 +    return Status;
   2.131 +  }
   2.132 +
   2.133    /*initialize storage for the device context*/
   2.134    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENPCI_DEVICE_DATA);
   2.135  
   2.136    /*create a device instance.*/
   2.137 -  status = WdfDeviceCreate(&DeviceInit, &attributes, &Device);  
   2.138 -  if(!NT_SUCCESS(status))
   2.139 +  Status = WdfDeviceCreate(&DeviceInit, &attributes, &Device);  
   2.140 +  if(!NT_SUCCESS(Status))
   2.141    {
   2.142 -    KdPrint((__DRIVER_NAME "     WdfDeviceCreate failed with status 0x%08x\n", status));
   2.143 -    return status;
   2.144 +    KdPrint((__DRIVER_NAME "     WdfDeviceCreate failed with Status 0x%08x\n", Status));
   2.145 +    return Status;
   2.146    }
   2.147  
   2.148    WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFilePaging, TRUE);
   2.149    WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFileHibernation, TRUE);
   2.150    WdfDeviceSetSpecialFileSupport(Device, WdfSpecialFileDump, TRUE);
   2.151  
   2.152 -  status = WdfFdoQueryForInterface(Device, &GUID_BUS_INTERFACE_STANDARD, (PINTERFACE) &BusInterface, sizeof(BUS_INTERFACE_STANDARD), 1, NULL);
   2.153 -  if(!NT_SUCCESS(status))
   2.154 +  Status = WdfFdoQueryForInterface(Device, &GUID_BUS_INTERFACE_STANDARD, (PINTERFACE) &BusInterface, sizeof(BUS_INTERFACE_STANDARD), 1, NULL);
   2.155 +  if(!NT_SUCCESS(Status))
   2.156    {
   2.157 -    KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (BusInterface) failed with status 0x%08x\n", status));
   2.158 +    KdPrint((__DRIVER_NAME "     WdfFdoQueryForInterface (BusInterface) failed with Status 0x%08x\n", Status));
   2.159    }
   2.160  
   2.161 -  //BusInterface.GetBusData(NULL, PCI_WHICHSPACE_CONFIG, buf, 
   2.162 -
   2.163 -  
   2.164    busInfo.BusTypeGuid = GUID_XENPCI_DEVCLASS;
   2.165 -  busInfo.LegacyBusType = Internal; //PNPBus;
   2.166 +  busInfo.LegacyBusType = Internal;
   2.167    busInfo.BusNumber = 0;
   2.168  
   2.169    WdfDeviceSetBusInformationForChildren(Device, &busInfo);
   2.170  
   2.171 -  WDF_INTERRUPT_CONFIG_INIT(&interruptConfig, EvtChn_Interrupt, NULL); //EvtChn_InterruptDpc);
   2.172 -  interruptConfig.EvtInterruptEnable = XenPCI_InterruptEnable;
   2.173 -  interruptConfig.EvtInterruptDisable = XenPCI_InterruptDisable;
   2.174 -  status = WdfInterruptCreate(Device, &interruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &XenInterrupt);
   2.175 -  if (!NT_SUCCESS (status))
   2.176 +  WDF_INTERRUPT_CONFIG_INIT(&InterruptConfig, EvtChn_Interrupt, NULL);
   2.177 +  InterruptConfig.EvtInterruptEnable = XenPCI_InterruptEnable;
   2.178 +  InterruptConfig.EvtInterruptDisable = XenPCI_InterruptDisable;
   2.179 +  Status = WdfInterruptCreate(Device, &InterruptConfig, WDF_NO_OBJECT_ATTRIBUTES, &XenInterrupt);
   2.180 +  if (!NT_SUCCESS (Status))
   2.181    {
   2.182 -    KdPrint((__DRIVER_NAME "WdfInterruptCreate failed 0x%08x\n", status));
   2.183 -    return status;
   2.184 +    KdPrint((__DRIVER_NAME "     WdfInterruptCreate failed 0x%08x\n", Status));
   2.185 +    return Status;
   2.186 +  }
   2.187 +
   2.188 +  Status = WdfDeviceCreateDeviceInterface(Device, (LPGUID)&GUID_XEN_IFACE_XEN, NULL);
   2.189 +  if (!NT_SUCCESS(Status))
   2.190 +  {
   2.191 +    KdPrint((__DRIVER_NAME "     WdfDeviceCreateDeviceInterface failed 0x%08x\n", Status));
   2.192 +    return Status;
   2.193 +  }
   2.194 +  WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQConfig, WdfIoQueueDispatchSequential);
   2.195 +  IoQConfig.EvtIoDefault = XenPCI_IoDefault;
   2.196 +  //IoQConfig.EvtIoRead = XenPCI_IoRead;
   2.197 +  //IoQConfig.EvtIoWrite = XenPCI_IoWrite;
   2.198 +  //IoQConfig.EvtIoDeviceControl = XenPCI_IoDeviceControl;
   2.199 +
   2.200 +  Status = WdfIoQueueCreate(Device, &IoQConfig, WDF_NO_OBJECT_ATTRIBUTES, NULL);
   2.201 +  if (!NT_SUCCESS(Status))
   2.202 +  {
   2.203 +    KdPrint((__DRIVER_NAME "     WdfIoQueueCreate failed 0x%08x\n", Status));
   2.204 +    return Status;
   2.205 +  }
   2.206 +
   2.207 +  WDF_IO_QUEUE_CONFIG_INIT(&IoQConfig, WdfIoQueueDispatchSequential);
   2.208 +  //IoQConfig.EvtIoDefault = XenPCI_IoDefault;
   2.209 +  IoQConfig.EvtIoRead = XenPCI_IoRead;
   2.210 +  //IoQConfig.EvtIoWrite = XenPCI_IoWrite;
   2.211 +  //IoQConfig.EvtIoDeviceControl = XenPCI_IoDeviceControl;
   2.212 +
   2.213 +  Status = WdfIoQueueCreate(Device, &IoQConfig, WDF_NO_OBJECT_ATTRIBUTES, &ReadQueue);
   2.214 +  if (!NT_SUCCESS(Status))
   2.215 +  {
   2.216 +    KdPrint((__DRIVER_NAME "     WdfIoQueueCreate (ReadQueue) failed 0x%08x\n", Status));
   2.217 +    switch (Status)
   2.218 +    {
   2.219 +    case STATUS_INVALID_PARAMETER:
   2.220 +      KdPrint((__DRIVER_NAME "     STATUS_INVALID_PARAMETER\n"));
   2.221 +      break;
   2.222 +    case STATUS_INFO_LENGTH_MISMATCH:
   2.223 +      KdPrint((__DRIVER_NAME "     STATUS_INFO_LENGTH_MISMATCH\n"));
   2.224 +      break;
   2.225 +    case STATUS_POWER_STATE_INVALID:
   2.226 +      KdPrint((__DRIVER_NAME "     STATUS_POWER_STATE_INVALID\n"));
   2.227 +      break;
   2.228 +    case STATUS_INSUFFICIENT_RESOURCES:
   2.229 +      KdPrint((__DRIVER_NAME "     STATUS_INSUFFICIENT_RESOURCES\n"));
   2.230 +      break;
   2.231 +    case STATUS_WDF_NO_CALLBACK:
   2.232 +      KdPrint((__DRIVER_NAME "     STATUS_WDF_NO_CALLBACK\n"));
   2.233 +      break;
   2.234 +    case STATUS_UNSUCCESSFUL:
   2.235 +      KdPrint((__DRIVER_NAME "     STATUS_UNSUCCESSFUL\n"));
   2.236 +      break;
   2.237 +    }
   2.238 +    return Status;
   2.239 +  }
   2.240 +  WdfIoQueueStopSynchronously(ReadQueue);
   2.241 +  WdfDeviceConfigureRequestDispatching(Device, ReadQueue, WdfRequestTypeRead);
   2.242 +
   2.243 +  Status = WdfDeviceCreateSymbolicLink(Device, &SymbolicName);
   2.244 +  if (!NT_SUCCESS(Status))
   2.245 +  {
   2.246 +    KdPrint((__DRIVER_NAME "     WdfDeviceCreateSymbolicLink failed 0x%08x\n", Status));
   2.247 +    return Status;
   2.248    }
   2.249  
   2.250    KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
   2.251 -  return status;
   2.252 +  return Status;
   2.253  }
   2.254  
   2.255  static NTSTATUS
   2.256 @@ -566,22 +626,6 @@ XenPCI_D0ExitPreInterruptsDisabled(WDFDE
   2.257  
   2.258    KdPrint((__DRIVER_NAME " --> D0ExitPreInterruptsDisabled\n"));
   2.259  
   2.260 -  switch (KeGetCurrentIrql())
   2.261 -  {
   2.262 -  case PASSIVE_LEVEL:
   2.263 -    KdPrint((__DRIVER_NAME "     PASSIVE_LEVEL\n"));
   2.264 -    break;
   2.265 -  case APC_LEVEL:
   2.266 -    KdPrint((__DRIVER_NAME "     APC_LEVEL\n"));
   2.267 -    break;
   2.268 -  case DISPATCH_LEVEL:
   2.269 -    KdPrint((__DRIVER_NAME "     DISPATCH_LEVEL\n"));
   2.270 -    break;
   2.271 -  default:
   2.272 -    KdPrint((__DRIVER_NAME "     %d\n", KeGetCurrentIrql()));
   2.273 -    break;
   2.274 -  }
   2.275 -
   2.276    XenBus_Stop();
   2.277  
   2.278    KdPrint((__DRIVER_NAME " <-- D0ExitPreInterruptsDisabled\n"));
   2.279 @@ -599,22 +643,6 @@ XenPCI_D0Exit(WDFDEVICE Device, WDF_POWE
   2.280  
   2.281    KdPrint((__DRIVER_NAME " --> DeviceD0Exit\n"));
   2.282  
   2.283 -  switch (KeGetCurrentIrql())
   2.284 -  {
   2.285 -  case PASSIVE_LEVEL:
   2.286 -    KdPrint((__DRIVER_NAME "     PASSIVE_LEVEL\n"));
   2.287 -    break;
   2.288 -  case APC_LEVEL:
   2.289 -    KdPrint((__DRIVER_NAME "     APC_LEVEL\n"));
   2.290 -    break;
   2.291 -  case DISPATCH_LEVEL:
   2.292 -    KdPrint((__DRIVER_NAME "     DISPATCH_LEVEL\n"));
   2.293 -    break;
   2.294 -  default:
   2.295 -    KdPrint((__DRIVER_NAME "     %d\n", KeGetCurrentIrql()));
   2.296 -    break;
   2.297 -  }
   2.298 -
   2.299    XenBus_Close();
   2.300  
   2.301    KdPrint((__DRIVER_NAME " <-- DeviceD0Exit\n"));
   2.302 @@ -637,6 +665,57 @@ XenPCI_IoDefault(
   2.303    KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
   2.304  }
   2.305  
   2.306 +
   2.307 +static VOID 
   2.308 +XenPCI_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)
   2.309 +{
   2.310 +  PSHUTDOWN_MSG_ENTRY Entry;
   2.311 +  ULONG Remaining;
   2.312 +  ULONG CopyLen;
   2.313 +  PCHAR Buffer;
   2.314 +  ULONG BufLen;
   2.315 +  KIRQL OldIrql;
   2.316 +
   2.317 +  UNREFERENCED_PARAMETER(Queue);
   2.318 +
   2.319 +  KdPrint((__DRIVER_NAME " --> IoRead\n"));
   2.320 +
   2.321 +  WdfRequestRetrieveOutputBuffer(Request, 1, &Buffer, &BufLen);
   2.322 +
   2.323 +  KeAcquireSpinLock(&ShutdownMsgLock, &OldIrql);
   2.324 +
   2.325 +  Entry = (PSHUTDOWN_MSG_ENTRY)RemoveHeadList(&ShutdownMsgList);
   2.326 +
   2.327 +  if ((PLIST_ENTRY)Entry == &ShutdownMsgList)
   2.328 +  {
   2.329 +    KdPrint((__DRIVER_NAME " <-- IoRead (Nothing in queue... xenpci is now broken)\n"));
   2.330 +    return;
   2.331 +  }
   2.332 +
   2.333 +  Remaining = strlen(Entry->Buf + Entry->Ptr);
   2.334 +  CopyLen = min(Remaining, BufLen);
   2.335 +
   2.336 +  memcpy(Buffer, Entry->Buf + Entry->Ptr, CopyLen);
   2.337 +
   2.338 +  if (Entry->Buf[Entry->Ptr] == 0)
   2.339 +  {
   2.340 +    if (IsListEmpty(&ShutdownMsgList))
   2.341 +      WdfIoQueueStop(ReadQueue, NULL, NULL);
   2.342 +  }
   2.343 +  else
   2.344 +  {    
   2.345 +    Entry->Ptr += CopyLen;
   2.346 +    InsertHeadList(&ShutdownMsgList, Entry);
   2.347 +  }
   2.348 +
   2.349 +  KeReleaseSpinLock(&ShutdownMsgLock, OldIrql);
   2.350 +
   2.351 +  WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, CopyLen);
   2.352 +
   2.353 +  KdPrint((__DRIVER_NAME " <-- IoRead\n"));
   2.354 +}
   2.355 +
   2.356 +
   2.357  static NTSTATUS
   2.358  XenPCI_InterruptEnable(WDFINTERRUPT Interrupt, WDFDEVICE AssociatedDevice)
   2.359  {
   2.360 @@ -868,9 +947,15 @@ XenPCI_XenBusWatchHandler(char *Path, PV
   2.361  static void
   2.362  XenBus_ShutdownHandler(char *Path, PVOID Data)
   2.363  {
   2.364 -  char *value;
   2.365 +  NTSTATUS Status;
   2.366 +  char *Value;
   2.367    xenbus_transaction_t xbt;
   2.368    int retry;
   2.369 +  WDFREQUEST Request;
   2.370 +  PCHAR Buffer;
   2.371 +  size_t BufLen;
   2.372 +  PCHAR Ptr;
   2.373 +  PSHUTDOWN_MSG_ENTRY Entry;
   2.374  
   2.375    UNREFERENCED_PARAMETER(Path);
   2.376    UNREFERENCED_PARAMETER(Data);
   2.377 @@ -879,16 +964,24 @@ XenBus_ShutdownHandler(char *Path, PVOID
   2.378  
   2.379    XenBus_StartTransaction(&xbt);
   2.380  
   2.381 -  XenBus_Read(XBT_NIL, SHUTDOWN_PATH, &value);
   2.382 +  XenBus_Read(XBT_NIL, SHUTDOWN_PATH, &Value);
   2.383  
   2.384 -  KdPrint((__DRIVER_NAME "     Shutdown Value = %s\n", value));
   2.385 +  KdPrint((__DRIVER_NAME "     Shutdown Value = %s\n", Value));
   2.386  
   2.387    // should check for error here... but why have we been called at all???
   2.388 -  if (value != NULL && strlen(value) != 0)
   2.389 +  if (Value != NULL && strlen(Value) != 0)
   2.390      XenBus_Write(XBT_NIL, SHUTDOWN_PATH, "");
   2.391  
   2.392    XenBus_EndTransaction(xbt, 0, &retry);
   2.393 -  
   2.394 +
   2.395 +  if (Value != NULL && strlen(Value) != 0)
   2.396 +  {
   2.397 +    Entry = (PSHUTDOWN_MSG_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, XENPCI_POOL_TAG);
   2.398 +    Entry->Ptr = 0;
   2.399 +    RtlStringCbPrintfA(Entry->Buf, sizeof(SHUTDOWN_MSG_ENTRY) + strlen(Value) + 1 + 1, "%s\n", Value);
   2.400 +    InsertTailList(&ShutdownMsgList, Entry);
   2.401 +    WdfIoQueueStart(ReadQueue);
   2.402 +  }
   2.403    KdPrint((__DRIVER_NAME " <-- XenBus_ShutdownHandler\n"));
   2.404  }
   2.405  
     3.1 --- a/xenvbd/sources	Sun Dec 16 17:44:31 2007 +1100
     3.2 +++ b/xenvbd/sources	Tue Dec 18 20:51:54 2007 +1100
     3.3 @@ -1,7 +1,7 @@
     3.4  TARGETNAME=XENVBD
     3.5  TARGETTYPE=DRIVER
     3.6  TARGETPATH=..\Target\$(DDK_TARGET_OS)
     3.7 -VERSION=0.4.0.122
     3.8 +VERSION=0.4.0.123
     3.9  KMDF_VERSION=1
    3.10  MSC_WARNING_LEVEL=/W4
    3.11  INF_NAME=xenvbd
     4.1 --- a/xenvbd/xenvbd.c	Sun Dec 16 17:44:31 2007 +1100
     4.2 +++ b/xenvbd/xenvbd.c	Tue Dec 18 20:51:54 2007 +1100
     4.3 @@ -262,6 +262,7 @@ XenVbd_HwScsiInterruptTarget(PVOID Devic
     4.4          memcpy(Srb->DataBuffer, TargetData->shadow[rep->id].Buf, BlockCount * TargetData->BytesPerSector);
     4.5  
     4.6        ScsiPortNotification(RequestComplete, DeviceData, Srb);
     4.7 +      ScsiPortNotification(NextLuRequest, DeviceData, Srb->PathId, Srb->TargetId, Srb->Lun);
     4.8  
     4.9        ADD_ID_TO_FREELIST(TargetData, rep->id);
    4.10      }
    4.11 @@ -952,23 +953,14 @@ XenVbd_HwScsiStartIo(PVOID DeviceExtensi
    4.12      case SCSIOP_READ:
    4.13      case SCSIOP_WRITE:
    4.14  //      KdPrint((__DRIVER_NAME "     Command = READ/WRITE\n"));
    4.15 -/*
    4.16 -      for (i = 0; i < 10; i++)
    4.17 -      {
    4.18 -        KdPrint((__DRIVER_NAME "     %02x: %02x\n", i, Srb->Cdb[i]));
    4.19 -      }
    4.20 -*/
    4.21 -      //KeAcquireSpinLock(&DeviceData->Lock, &KIrql);
    4.22 -
    4.23        XenVbd_PutSrbOnRing(TargetData, Srb);
    4.24        RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
    4.25        if (notify)
    4.26          DeviceData->XenDeviceData->EvtChnInterface.Notify(TargetData->EventChannel);
    4.27 -      //KeReleaseSpinLock(&DeviceData->Lock, KIrql);
    4.28 -//      Srb->SrbStatus = SRB_STATUS_SUCCESS;
    4.29 -//      ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
    4.30        if (!RING_FULL(&TargetData->Ring))
    4.31 -        ScsiPortNotification(NextRequest, DeviceExtension, NULL);
    4.32 +        ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
    4.33 +      else
    4.34 +        ScsiPortNotification(NextRequest, DeviceExtension);
    4.35        break;
    4.36      case SCSIOP_REPORT_LUNS:
    4.37        KdPrint((__DRIVER_NAME "     Command = REPORT_LUNS\n"));