Exemple #1
0
VOID
XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context)
{
  ULONG ActiveProcessorCount;
  ULONG i;
  highsync_info_t *highsync_info;
  KIRQL old_irql;

  UNREFERENCED_PARAMETER(context);
  FUNCTION_ENTER();

  highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG);
  RtlZeroMemory(highsync_info, sizeof(highsync_info_t));
  KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE);
  highsync_info->function0 = function0;
  highsync_info->functionN = functionN;
  highsync_info->context = context;
  highsync_info->sync_level = HIGH_LEVEL;

#if (NTDDI_VERSION >= NTDDI_WINXP)
  ActiveProcessorCount = (ULONG)KeNumberProcessors;
#else
  ActiveProcessorCount = (ULONG)*KeNumberProcessors;
#endif

  /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
  KeRaiseIrql(highsync_info->sync_level, &old_irql);

  highsync_info->do_spin = TRUE;
  for (i = 0; i < ActiveProcessorCount; i++)
  {
    if (i == 0)
      KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info);
    else
      KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info);
    KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
    KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
    KdPrint((__DRIVER_NAME "     queuing Dpc for CPU %d\n", i));
    KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
  }
  KdPrint((__DRIVER_NAME "     All Dpc's queued\n"));

  KeMemoryBarrier();
  KeLowerIrql(old_irql);

  KdPrint((__DRIVER_NAME "     Waiting for highsync_complete_event\n"));
  KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL);
#if (NTDDI_VERSION >= NTDDI_WINXP)
  KeFlushQueuedDpcs();
#else
  {
    /* just wait 1 second until all DPC's finish - not ideal but it's only for W2K */
    LARGE_INTEGER interval;
    interval.QuadPart = -1 * 1000 * 1000 * 10; /* 1 second */
    KeDelayExecutionThread(KernelMode, FALSE, &interval);
  }
#endif
  ExFreePoolWithTag(highsync_info, XENPCI_POOL_TAG);
  FUNCTION_EXIT();
}
static VOID
XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path)
{
  PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);

  FUNCTION_ENTER();
  
  FUNCTION_MSG("path = %s\n", xppdd->path);
  switch (notification_type)
  {
  case WdfSpecialFilePaging:
    FUNCTION_MSG("notification_type = Paging, flag = %d\n", is_in_notification_path);
    break;
  case WdfSpecialFileHibernation:
    xppdd->hiber_usage_kludge = is_in_notification_path;
    FUNCTION_MSG("notification_type = Hibernation, flag = %d\n", is_in_notification_path);
    break;
  case WdfSpecialFileDump:
    FUNCTION_MSG("notification_type = Dump, flag = %d\n", is_in_notification_path);
    break;
  default:
    FUNCTION_MSG("notification_type = %d, flag = %d\n", notification_type, is_in_notification_path);
    break;
  }

  FUNCTION_EXIT();
}
static VOID
XenPci_DoPatchKernel0(PVOID context) {
  patch_info_t *pi = context;
  ULONG i;
  ULONG high_level_tpr;
  ULONG patch_position_index = 0;
  ULONG potential_patch_position_index = 0;

  FUNCTION_ENTER();

  high_level_tpr = SaveTpr();
  /* we know all the other CPUs are at HIGH_LEVEL so set them all to the same as cpu 0 */
  for (i = 1; i < MAX_VIRT_CPUS; i++)
    SaveTprProcValue(i, high_level_tpr);

  /* we can't use KdPrint while patching as it may involve the TPR while we are patching it */
  for (i = 0; i < pi->length; i++) {
    if (XenPci_TestAndPatchInstruction((PUCHAR)pi->base + i)) {
      patch_positions[patch_position_index++] = (PUCHAR)pi->base + i;
    } else if (*(PULONG)((PUCHAR)pi->base + i) == LAPIC_TASKPRI) {
      potential_patch_positions[potential_patch_position_index++] = (PUCHAR)pi->base + i;
    }
  }

  for (i = 0; i < patch_position_index; i++)
    FUNCTION_MSG("Patch added at %p\n", patch_positions[i]);

  for (i = 0; i < potential_patch_position_index; i++)
    FUNCTION_MSG("Unpatch TPR address found at %p\n", potential_patch_positions[i]);

  FUNCTION_EXIT();
}
static VOID
XenBus_EvtFileCleanup(WDFFILEOBJECT file_object)
{
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfFileObjectGetDevice(file_object));
  watch_context_t *watch_context;
  KIRQL old_irql;
  PCHAR msg;

  FUNCTION_ENTER();

  KeAcquireSpinLock(&xpdid->lock, &old_irql);

  while (!IsListEmpty(&xpdid->xenbus.watch_list_head))
  {
    watch_context = (watch_context_t *)RemoveHeadList(&xpdid->xenbus.watch_list_head);
    KeReleaseSpinLock(&xpdid->lock, old_irql);
    msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_context->path, XenPci_IoWatch, watch_context);
    if (msg != NULL)
    {
      KdPrint((__DRIVER_NAME "     Error freeing watch (%s)\n", msg));
      XenPci_FreeMem(msg);
    }
    ExFreePoolWithTag(watch_context, XENPCI_POOL_TAG);
    WdfObjectDereference(file_object);
    KeAcquireSpinLock(&xpdid->lock, &old_irql);
  }

  KeReleaseSpinLock(&xpdid->lock, old_irql);
  
  FUNCTION_EXIT();
}
NDIS_STATUS
XenNet_SetInformation(
    NDIS_HANDLE adapter_context,
    NDIS_OID oid,
    PVOID information_buffer,
    ULONG information_buffer_length,
    PULONG bytes_read,
    PULONG bytes_needed) {
  NTSTATUS status;
  int i;
  
  FUNCTION_ENTER();
  for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++);

  if (!xennet_oids[i].oid) {
    FUNCTION_MSG("Unsupported OID %08x\n", oid);
    return NDIS_STATUS_NOT_SUPPORTED;
  }
  if (information_buffer_length < xennet_oids[i].min_length) {
    FUNCTION_MSG("%s Set InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length);
    *bytes_needed = xennet_oids[i].min_length;
    return NDIS_STATUS_BUFFER_TOO_SHORT;
  }
  if (!xennet_oids[i].set_routine) {
    FUNCTION_MSG("%s Set not supported\n", xennet_oids[i].oid_name);
    return NDIS_STATUS_NOT_SUPPORTED;
  }
  FUNCTION_MSG("%s\n", xennet_oids[i].oid_name);
  status = xennet_oids[i].set_routine(adapter_context, information_buffer, information_buffer_length, bytes_read, bytes_needed);
  FUNCTION_EXIT();
  return status;
}
NTSTATUS
XenBus_DeviceFileInit(WDFDEVICE device, PWDF_IO_QUEUE_CONFIG queue_config, WDFFILEOBJECT file_object)
{
  NTSTATUS status;
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  WDF_IO_QUEUE_CONFIG internal_queue_config;
  
  FUNCTION_ENTER();

  xpdid->EvtFileCleanup = XenBus_EvtFileCleanup;  
  xpdid->EvtFileClose = XenBus_EvtFileClose;
  queue_config->EvtIoRead = XenBus_EvtIoRead;
  queue_config->EvtIoWrite = XenBus_EvtIoWrite;
  // queue_config->EvtIoDeviceControl = XenBus_EvtIoDeviceControl;
  
  InitializeListHead(&xpdid->xenbus.read_list_head);
  InitializeListHead(&xpdid->xenbus.watch_list_head);
  xpdid->xenbus.len = 0;
  WDF_IO_QUEUE_CONFIG_INIT(&internal_queue_config, WdfIoQueueDispatchManual);
  
  status = WdfIoQueueCreate(device, &internal_queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdid->xenbus.io_queue);
  if (!NT_SUCCESS(status)) {
    KdPrint(("Error creating queue 0x%x\n", status));
    FUNCTION_EXIT();
    return status;
  }
  
  FUNCTION_EXIT();
  
  return status;
}
static VOID
XenBus_EvtFileClose(WDFFILEOBJECT file_object)
{
  UNREFERENCED_PARAMETER(file_object);
  FUNCTION_ENTER();
  FUNCTION_EXIT();
}
VOID
XenUsb_DeviceCallback(PVOID context, ULONG callback_type, PVOID value) {
  PXENUSB_DEVICE_DATA xudd = (PXENUSB_DEVICE_DATA)context;
  ULONG state;
  
  FUNCTION_ENTER();
  switch (callback_type) {
  case XN_DEVICE_CALLBACK_BACKEND_STATE:
    state = (ULONG)(ULONG_PTR)value;
    if (state == xudd->backend_state) {
      FUNCTION_MSG("same state %d\n", state);
      FUNCTION_EXIT();
    }
    FUNCTION_MSG("XenBusState = %d -> %d\n", xudd->backend_state, state);
    xudd->backend_state = state;
    KeSetEvent(&xudd->backend_event, 0, FALSE);
    break;
  case XN_DEVICE_CALLBACK_SUSPEND:
    FUNCTION_MSG("XN_DEVICE_CALLBACK_SUSPEND");
    XenUsb_Disconnect(xudd, TRUE);
    break;
  case XN_DEVICE_CALLBACK_RESUME:
    FUNCTION_MSG("XN_DEVICE_CALLBACK_RESUME");
    xudd->device_state = DEVICE_STATE_INITIALISING;
    XenUsb_Connect(xudd, TRUE);
    // some sort of notify to kick things off?
    break;
  }
  FUNCTION_EXIT();
}
/* called with urb ring lock held */
static VOID
PutRequestsOnRing(PXENUSB_DEVICE_DATA xudd) {
  partial_pvurb_t *partial_pvurb;
  uint16_t id;
  int notify;

  FUNCTION_ENTER();
  FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql());

  while ((partial_pvurb = (partial_pvurb_t *)RemoveHeadList((PLIST_ENTRY)&xudd->partial_pvurb_queue)) != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
    FUNCTION_MSG("partial_pvurb = %p\n", partial_pvurb);
    /* if this partial_pvurb is cancelling another we don't need to check if the cancelled partial_pvurb is on the ring - that is taken care of in HandleEvent */
    id = get_id_from_freelist(xudd->req_id_ss);
    if (id == (uint16_t)-1) {
      FUNCTION_MSG("no free ring slots\n");
      InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb->entry);
      break;
    }
    InsertTailList(&xudd->partial_pvurb_ring, &partial_pvurb->entry);
    xudd->partial_pvurbs[id] = partial_pvurb;
    partial_pvurb->req.id = id;    
    *RING_GET_REQUEST(&xudd->urb_ring, xudd->urb_ring.req_prod_pvt) = partial_pvurb->req;
    xudd->urb_ring.req_prod_pvt++;
  }
  RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xudd->urb_ring, notify);
  if (notify) {
    FUNCTION_MSG("Notifying\n");
    XnNotify(xudd->handle, xudd->event_channel);
  }
  
  FUNCTION_EXIT();
}
Exemple #10
0
static VOID
XenNet_ResumeWorkItem(PDEVICE_OBJECT device_object, PVOID context)
{
  struct xennet_info *xi = context;
  KIRQL old_irql;
  
  UNREFERENCED_PARAMETER(device_object);
  
  FUNCTION_ENTER();

  ASSERT(xi->resume_work_item);

  IoFreeWorkItem(xi->resume_work_item);
  
  XenNet_TxResumeStart(xi);
  XenNet_RxResumeStart(xi);
  XenNet_ConnectBackend(xi);
  XenNet_RxResumeEnd(xi);
  XenNet_TxResumeEnd(xi);

  KeAcquireSpinLock(&xi->resume_lock, &old_irql);
  xi->resume_work_item = NULL;
  KdPrint((__DRIVER_NAME "     *Setting suspend_resume_state_fdo = %d\n", xi->device_state->suspend_resume_state_pdo));
  xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
  KdPrint((__DRIVER_NAME "     *Notifying event channel %d\n", xi->device_state->pdo_event_channel));
  xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
  KeReleaseSpinLock(&xi->resume_lock, old_irql);

  FUNCTION_EXIT();

}
Exemple #11
0
VOID
XenNet_PnPEventNotify(
  IN NDIS_HANDLE MiniportAdapterContext,
  IN NDIS_DEVICE_PNP_EVENT PnPEvent,
  IN PVOID InformationBuffer,
  IN ULONG InformationBufferLength
  )
{
  UNREFERENCED_PARAMETER(MiniportAdapterContext);
  UNREFERENCED_PARAMETER(PnPEvent);
  UNREFERENCED_PARAMETER(InformationBuffer);
  UNREFERENCED_PARAMETER(InformationBufferLength);

  FUNCTION_ENTER();
  switch (PnPEvent)
  {
  case NdisDevicePnPEventSurpriseRemoved:
    KdPrint((__DRIVER_NAME "     NdisDevicePnPEventSurpriseRemoved\n"));
    break;
  case NdisDevicePnPEventPowerProfileChanged :
    KdPrint((__DRIVER_NAME "     NdisDevicePnPEventPowerProfileChanged\n"));
    break;
  default:
    KdPrint((__DRIVER_NAME "     %d\n", PnPEvent));
    break;
  }
  FUNCTION_EXIT();
}
Exemple #12
0
static VOID
XenPci_HighSyncCallFunction0(
  PRKDPC Dpc,
  PVOID Context,
  PVOID SystemArgument1,
  PVOID SystemArgument2)
{
  highsync_info_t *highsync_info = Context;
  ULONG ActiveProcessorCount;
  KIRQL old_irql;
  
  UNREFERENCED_PARAMETER(Dpc);
  UNREFERENCED_PARAMETER(SystemArgument1);
  UNREFERENCED_PARAMETER(SystemArgument2);

  FUNCTION_ENTER();
#if (NTDDI_VERSION >= NTDDI_WINXP)
  ActiveProcessorCount = (ULONG)KeNumberProcessors;
#else
  ActiveProcessorCount = (ULONG)*KeNumberProcessors;
#endif
  InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level);
  if (highsync_info->sync_level > DISPATCH_LEVEL)
  {
    while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount)
    {
      KeStallExecutionProcessor(1);
      KeMemoryBarrier();
    }
  }
  _disable(); //__asm cli;  
  KeRaiseIrql(highsync_info->sync_level, &old_irql);
  while (highsync_info->nr_spinning_at_sync_level < (LONG)ActiveProcessorCount - 1)
  {
    KeStallExecutionProcessor(1);
    KeMemoryBarrier();
  }
  highsync_info->function0(highsync_info->context);
  KeLowerIrql(old_irql);
  _enable(); //__asm sti;
  highsync_info->do_spin = FALSE;
  KeMemoryBarrier();  
  /* wait for all the other processors to complete spinning, just in case it matters */
  while (highsync_info->nr_spinning_at_sync_level)
  {
    KeStallExecutionProcessor(1);
    KeMemoryBarrier();
  }
  InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level);
  /* wait until nr_procs_at_dispatch_level drops to 0 indicating that nothing else requires highsync_info */
  while (highsync_info->nr_procs_at_dispatch_level)
  {
    KeStallExecutionProcessor(1);
    KeMemoryBarrier();
  }
  KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE);

  FUNCTION_EXIT();
}
VOID
XenUsb_EvtRequestCancelPvUrb(WDFREQUEST request) {
  WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request));
  PXENUSB_DEVICE_DATA xudd = GetXudd(device);
  WDF_REQUEST_PARAMETERS wrp;
  partial_pvurb_t *partial_pvurb;
  pvurb_t *pvurb;
  KIRQL old_irql;

  FUNCTION_ENTER();
  FUNCTION_MSG("cancelling request %p\n", request);

  WDF_REQUEST_PARAMETERS_INIT(&wrp);
  KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql);

  WdfRequestGetParameters(request, &wrp);
  pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1;
  FUNCTION_MSG("pvurb = %p\n", pvurb);
  ASSERT(pvurb);

  partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_queue.Flink;
  while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_queue) {
    partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
    ASSERT(!partial_pvurb->on_ring);
    FUNCTION_MSG("partial_pvurb = %p is not yet on ring\n", partial_pvurb);
    RemoveEntryList(&partial_pvurb->entry);
    ExFreePoolWithTag(partial_pvurb, XENUSB_POOL_TAG);
    pvurb->ref--;
    partial_pvurb = next_partial_pvurb;
  }
  partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_ring.Flink;
  while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_ring) {
    partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink;
    partial_pvurb_t *partial_pvurb_cancel;
    FUNCTION_MSG("partial_pvurb = %p is on ring\n", partial_pvurb);
    ASSERT(partial_pvurb->on_ring);
    partial_pvurb_cancel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb_cancel), XENUSB_POOL_TAG); /* todo - use lookaside */
    ASSERT(partial_pvurb_cancel); /* what would we do if this failed? */
    partial_pvurb_cancel->req = partial_pvurb->req;
    partial_pvurb_cancel->req.pipe = usbif_setunlink_pipe(partial_pvurb_cancel->req.pipe);
    partial_pvurb_cancel->req.u.unlink.unlink_id = partial_pvurb->req.id;
    partial_pvurb_cancel->pvurb = pvurb;
    partial_pvurb_cancel->mdl = NULL;
    partial_pvurb_cancel->other_partial_pvurb = partial_pvurb;
    partial_pvurb->other_partial_pvurb = partial_pvurb_cancel;
    partial_pvurb_cancel->on_ring = FALSE;
    pvurb->ref++;
    InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb_cancel->entry);
    partial_pvurb = next_partial_pvurb;
  }
  if (pvurb->ref) {
    PutRequestsOnRing(xudd);
    KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
  } else {
    KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql);
    WdfRequestComplete(request, STATUS_CANCELLED);
  }
  FUNCTION_EXIT();
}
static VOID
XenPci_DoPatchKernelN(PVOID context) {
  UNREFERENCED_PARAMETER(context);
  
  FUNCTION_ENTER();

  FUNCTION_EXIT();
}
VOID
XenNet_CancelOidRequest(NDIS_HANDLE adapter_context, PVOID request_id)
{
  UNREFERENCED_PARAMETER(adapter_context);
  UNREFERENCED_PARAMETER(request_id);
  FUNCTION_ENTER();
  FUNCTION_EXIT();
}
NTSTATUS
XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state) {
  NTSTATUS status = STATUS_SUCCESS;
  PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo);
  char path[128];
  
  UNREFERENCED_PARAMETER(device);
  UNREFERENCED_PARAMETER(target_state);
  
  FUNCTION_ENTER();
  FUNCTION_MSG("path = %s\n", xppdd->path);
  
  switch (target_state) {
  case WdfPowerDeviceD0:
    FUNCTION_MSG("WdfPowerDeviceD1\n");
    break;
  case WdfPowerDeviceD1:
    FUNCTION_MSG("WdfPowerDeviceD1\n");
    break;
  case WdfPowerDeviceD2:
    FUNCTION_MSG("WdfPowerDeviceD2\n");
    break;
  case WdfPowerDeviceD3:
    FUNCTION_MSG("WdfPowerDeviceD3\n");
    if (xppdd->hiber_usage_kludge) {
      FUNCTION_MSG("(but really WdfPowerDevicePrepareForHibernation)\n");
      target_state = WdfPowerDevicePrepareForHibernation;
    }
    break;
  case WdfPowerDeviceD3Final:
    FUNCTION_MSG("WdfPowerDeviceD3Final\n");
    break;
  case WdfPowerDevicePrepareForHibernation:
    FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n");
    break;  
  default:
    FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", target_state);
    break;  
  }
  
  if (target_state == WdfPowerDevicePrepareForHibernation)
  {
    FUNCTION_MSG("not powering down as we are hibernating\n");
    // should we set the backend state here so it's correct on resume???
  }
  
  /* Remove watch on backend state */
  /* even if hibernate */
  if (xppdd->device_callback) {
    FUNCTION_MSG("Removing watch %s\n", xppdd->device);
    RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
    XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
  }
  FUNCTION_EXIT();
  
  return status;
}
static NTSTATUS
XenVbd_IoCompletion_START_DEVICE(PDEVICE_OBJECT device, PIRP irp, PVOID context) {
  UNREFERENCED_PARAMETER(device);
  UNREFERENCED_PARAMETER(irp);
  FUNCTION_ENTER();
  ExFreePoolWithTag(context, XENVBD_POOL_TAG);
  FUNCTION_EXIT();
  return STATUS_SUCCESS;
}
static VOID
XenVbd_StopRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) {
  PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd;
  NTSTATUS status;
  WDFREQUEST request;
  WDF_REQUEST_SEND_OPTIONS send_options;
  IO_STACK_LOCATION stack;
  SCSI_REQUEST_BLOCK srb;
  SRB_IO_CONTROL sic;

  FUNCTION_ENTER();
  
  /* send a 'stop' down if we are suspending */
  if (suspend) {
    status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request);
    FUNCTION_MSG("WdfRequestCreate = %08x\n", status);

    RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION));
    stack.MajorFunction = IRP_MJ_SCSI;
    stack.MinorFunction = IRP_MN_SCSI_CLASS;
    stack.Parameters.Scsi.Srb = &srb;

    RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE);
    srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE;
    srb.Length = SCSI_REQUEST_BLOCK_SIZE;
    srb.PathId = 0;
    srb.TargetId = 0;
    srb.Lun = 0;
    srb.OriginalRequest = WdfRequestWdmGetIrp(request);
    srb.Function = SRB_FUNCTION_IO_CONTROL;
    srb.DataBuffer = &sic;
    
    RtlZeroMemory(&sic, sizeof(SRB_IO_CONTROL));
    sic.HeaderLength = sizeof(SRB_IO_CONTROL);
    memcpy(sic.Signature, XENVBD_CONTROL_SIG, 8);
    sic.Timeout = 60;
    sic.ControlCode = XENVBD_CONTROL_STOP;
    
    WdfRequestWdmFormatUsingStackLocation(request, &stack);
    
    WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
    if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) {
      FUNCTION_MSG("Request was _NOT_ sent\n");
    }
    #if DBG
    status = WdfRequestGetStatus(request);
    FUNCTION_MSG("Request Status = %08x\n", status);
    FUNCTION_MSG("SRB Status = %08x\n", srb.SrbStatus);
    #endif

    WdfObjectDelete(request);
  }
  
  status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing);

  FUNCTION_EXIT();
}
static VOID
XenPci_IoWatch(char *path, PVOID context)
{
  NTSTATUS status;
  watch_context_t *watch_context = context;
  WDFFILEOBJECT file_object = watch_context->file_object;
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;
  struct xsd_sockmsg *rep;
  xenbus_read_queue_item_t *list_entry;
  size_t remaining;
  WDFREQUEST request;

  FUNCTION_ENTER();
  
  KeAcquireSpinLock(&xpdid->lock, &old_irql);
  
  remaining = sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1;
  rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1, XENPCI_POOL_TAG);
  rep->type = XS_WATCH_EVENT;
  rep->req_id = 0;
  rep->tx_id = 0;
  rep->len = (ULONG)(strlen(path) + 1 + strlen(watch_context->token) + 1);
  remaining -= sizeof(struct xsd_sockmsg);
  RtlStringCbCopyA((PCHAR)(rep + 1), remaining, path);
  remaining -= strlen(path) + 1;
  RtlStringCbCopyA((PCHAR)(rep + 1) + strlen(path) + 1, remaining, watch_context->token);
  
  list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG);
  list_entry->data = rep;
  list_entry->length = sizeof(*rep) + rep->len;
  list_entry->offset = 0;
  InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry);
    
  status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &request);
  if (NT_SUCCESS(status))
  {
    WDF_REQUEST_PARAMETERS parameters;
    WDF_REQUEST_PARAMETERS_INIT(&parameters);
    WdfRequestGetParameters(request, &parameters);
    
    KdPrint((__DRIVER_NAME "     found pending read - MinorFunction = %d, length = %d\n", (ULONG)parameters.MinorFunction, (ULONG)parameters.Parameters.Read.Length));
    XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, request, parameters.Parameters.Read.Length);
    KeReleaseSpinLock(&xpdid->lock, old_irql);
    WdfRequestComplete(request, STATUS_SUCCESS);
  }
  else
  {
    KdPrint((__DRIVER_NAME "     no pending read (%08x)\n", status));
    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  
  FUNCTION_EXIT();
}
Exemple #20
0
/* Called when machine is shutting down, so just quiesce the HW and be done fast. */
VOID
XenNet_Shutdown(
  IN NDIS_HANDLE MiniportAdapterContext
  )
{
  UNREFERENCED_PARAMETER(MiniportAdapterContext);

  /* remember we are called at >= DIRQL here */
  FUNCTION_ENTER();
  FUNCTION_EXIT();
}
static NTSTATUS
XenVbd_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state) {
  PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
  NTSTATUS status;
  
  UNREFERENCED_PARAMETER(previous_state);
  // if waking from hibernate then same as suspend... maybe?
  FUNCTION_ENTER();
  status = XenVbd_Connect(&xvfd->xvdd, FALSE);
  FUNCTION_EXIT();
  return status;
}
Exemple #22
0
static VOID
XenNet_SuspendResume(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2)
{
  struct xennet_info *xi = context;
  KIRQL old_irql;
  PIO_WORKITEM resume_work_item;

  UNREFERENCED_PARAMETER(dpc);
  UNREFERENCED_PARAMETER(arg1);
  UNREFERENCED_PARAMETER(arg2);

  FUNCTION_ENTER();
  
  switch (xi->device_state->suspend_resume_state_pdo)
  {
  case SR_STATE_SUSPENDING:
    KdPrint((__DRIVER_NAME "     New state SUSPENDING\n"));
    KeAcquireSpinLock(&xi->rx_lock, &old_irql);
    if (xi->rx_id_free == NET_RX_RING_SIZE)
    {  
      xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING;
      KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
      xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
    }
    KeReleaseSpinLock(&xi->rx_lock, old_irql);
    break;
  case SR_STATE_RESUMING:
    KdPrint((__DRIVER_NAME "     New state SR_STATE_RESUMING\n"));
    /* do it like this so we don't race and double-free the work item */
    resume_work_item = IoAllocateWorkItem(xi->fdo);
    KeAcquireSpinLock(&xi->resume_lock, &old_irql);
    if (xi->resume_work_item || xi->device_state->suspend_resume_state_fdo == SR_STATE_RESUMING)
    {
      KeReleaseSpinLock(&xi->resume_lock, old_irql);
      IoFreeWorkItem(resume_work_item);
      return;
    }
    xi->resume_work_item = resume_work_item;
    KeReleaseSpinLock(&xi->resume_lock, old_irql);
    IoQueueWorkItem(xi->resume_work_item, XenNet_ResumeWorkItem, DelayedWorkQueue, xi);
    break;
  default:
    KdPrint((__DRIVER_NAME "     New state %d\n", xi->device_state->suspend_resume_state_fdo));
    xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo;
    KdPrint((__DRIVER_NAME "     Notifying event channel %d\n", xi->device_state->pdo_event_channel));
    xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel);
    break;
  }
  KeMemoryBarrier();
  
  FUNCTION_EXIT();
}
Exemple #23
0
static BOOLEAN
XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
{
  UNREFERENCED_PARAMETER(DeviceExtension);
  UNREFERENCED_PARAMETER(PathId);


  FUNCTION_ENTER();
  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  ScsiPortNotification(NextRequest, DeviceExtension);
  FUNCTION_EXIT();

  return TRUE;
}
Exemple #24
0
static BOOLEAN
XenScsi_HwScsiInitialize(PVOID DeviceExtension)
{
  PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
  UNREFERENCED_PARAMETER(DeviceExtension);

  FUNCTION_ENTER();
  xsdd->shared_paused = SHARED_PAUSED_SCSIPORT_UNPAUSED;
  ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 1 * 1000 * 1000); /* 1 second */
  
  FUNCTION_EXIT();

  return TRUE;
}
static NTSTATUS
XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp) {
  PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
  PIO_STACK_LOCATION stack;
  PCM_RESOURCE_LIST crl;
  PCM_FULL_RESOURCE_DESCRIPTOR cfrd;
  PCM_PARTIAL_RESOURCE_LIST cprl;
  PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;

  FUNCTION_ENTER();

  /*
  Pass down the xvdd area as a memory resource. This gives xenvbd the data in a known place
  and also satisifies the scsiport requirement for a memory resource
  */
  IoCopyCurrentIrpStackLocationToNext(irp);
  stack = IoGetNextIrpStackLocation(irp);

  crl = ExAllocatePoolWithTag(NonPagedPool,
          FIELD_OFFSET(CM_RESOURCE_LIST, List) +
          FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
          FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
          sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1, XENVBD_POOL_TAG);
  if (!crl) {
    // TODO: Fail this correctly
  }
  crl->Count = 1;
  cfrd = &crl->List[0];
  cfrd->InterfaceType = PNPBus;
  cfrd->BusNumber = 0;
  cprl = &cfrd->PartialResourceList;
  cprl->Version = 1;
  cprl->Revision = 1;
  cprl->Count = 1;
  prd = &cprl->PartialDescriptors[0];
  prd->Type = CmResourceTypeMemory;
  prd->ShareDisposition = CmResourceShareShared;
  prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
  prd->u.Memory.Start.QuadPart = (ULONG_PTR)&xvfd->xvdd;
  prd->u.Memory.Length = sizeof(XENVBD_DEVICE_DATA);
  stack->Parameters.StartDevice.AllocatedResources = crl;
  stack->Parameters.StartDevice.AllocatedResourcesTranslated = crl;

  IoSetCompletionRoutine(irp, XenVbd_IoCompletion_START_DEVICE, crl, TRUE, TRUE, TRUE);

  FUNCTION_EXIT();

  return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
}
Exemple #26
0
static VOID
XenPci_HighSyncCallFunctionN(
  PRKDPC Dpc,
  PVOID Context,
  PVOID SystemArgument1,
  PVOID SystemArgument2)
{
  highsync_info_t *highsync_info = Context;
  ULONG ActiveProcessorCount;
  KIRQL old_irql;
  
  UNREFERENCED_PARAMETER(Dpc);
  UNREFERENCED_PARAMETER(SystemArgument1);
  UNREFERENCED_PARAMETER(SystemArgument2);

  FUNCTION_ENTER();
  FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());

  KdPrint((__DRIVER_NAME "     CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
  InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level);
  if (highsync_info->sync_level > DISPATCH_LEVEL)
  {
#if (NTDDI_VERSION >= NTDDI_WINXP)
    ActiveProcessorCount = (ULONG)KeNumberProcessors;
#else
    ActiveProcessorCount = (ULONG)*KeNumberProcessors;
#endif
    while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount)
    {
      KeStallExecutionProcessor(1);
      KeMemoryBarrier();
    }
  }
  _disable(); //__asm cli;  
  KeRaiseIrql(highsync_info->sync_level, &old_irql);
  InterlockedIncrement(&highsync_info->nr_spinning_at_sync_level);
  while(highsync_info->do_spin)
  {
    KeStallExecutionProcessor(1);
    KeMemoryBarrier();
  }
  highsync_info->functionN(highsync_info->context);
  KeLowerIrql(old_irql);
  _enable(); //__asm sti;
  InterlockedDecrement(&highsync_info->nr_spinning_at_sync_level);
  InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level);
  FUNCTION_EXIT();
  return;
}
Exemple #27
0
/* Opposite of XenNet_Init */
VOID
XenNet_Halt(
  IN NDIS_HANDLE MiniportAdapterContext
  )
{
  struct xennet_info *xi = MiniportAdapterContext;

  FUNCTION_ENTER();
  KdPrint((__DRIVER_NAME "     IRQL = %d\n", KeGetCurrentIrql()));
  
  XenNet_D0Exit(xi);

  NdisFreeMemory(xi, 0, 0);

  FUNCTION_EXIT();
}
VOID
XenUsb_EvtChildListScanForChildren(WDFCHILDLIST child_list) {
  NTSTATUS status;
  PXENUSB_DEVICE_DATA xudd = GetXudd(WdfChildListGetDevice(child_list));
  XENUSB_PDO_IDENTIFICATION_DESCRIPTION child_description;
  CHAR path[128];
  PCHAR value;
  ULONG i;

  FUNCTION_ENTER();

  WdfChildListBeginScan(child_list);

  // hold the queue on each device and set each device to a pending state
  // read backend/num_ports
  //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/num-ports", xudd->vectors.backend_path);
  status = XnReadString(xudd->handle, XBT_NIL, path, &value);
  if (status != STATUS_SUCCESS) {
    WdfChildListEndScan(child_list);
    FUNCTION_MSG("Failed to read num-ports\n");
    return;
  }
  xudd->num_ports = (ULONG)parse_numeric_string(value);  
  XnFreeMem(xudd->handle, value);
  FUNCTION_MSG("num-ports = %d\n", xudd->num_ports);

  for (i = 0; i < 8; i++) {
    xudd->ports[i].port_number = i + 1;
    xudd->ports[i].port_type = USB_PORT_TYPE_NOT_CONNECTED;
    xudd->ports[i].port_status = 0; //1 << PORT_ENABLE;
    xudd->ports[i].port_change = 0x0000;
  }  

  /* only a single root hub is enumerated */
  WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description));

  child_description.device_number = 0; //TODO: get the proper index from parent

  status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL);
  if (!NT_SUCCESS(status)) {
    FUNCTION_MSG("WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status);
  }

  WdfChildListEndScan(child_list);
  
  FUNCTION_EXIT();
}
/* scsiport doesn't process SET_POWER correctly so we have to fudge detection of hibernate */
static NTSTATUS
XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER(WDFDEVICE device, PIRP irp) {
  PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
  PIO_STACK_LOCATION stack;
  
  FUNCTION_ENTER();
  stack = IoGetCurrentIrpStackLocation(irp);
  if (stack->Parameters.Power.Type == DevicePowerState && stack->Parameters.Power.State.DeviceState == PowerDeviceD3 && stack->Parameters.Power.ShutdownType == PowerActionHibernate) {
    FUNCTION_MSG("Going to hibernate\n");
    xvfd->hibernate_flag = TRUE;
  } else {
    xvfd->hibernate_flag = FALSE;
  }
  IoSkipCurrentIrpStackLocation(irp);
  FUNCTION_EXIT();
  return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
}
VOID
XenPci_PatchKernel(PXENPCI_DEVICE_DATA xpdd, PVOID base, ULONG length) {
  patch_info_t patch_info;
#if (NTDDI_VERSION >= NTDDI_WINXP)
  RTL_OSVERSIONINFOEXW version_info;
#endif

  FUNCTION_ENTER();

/* if we're compiled for 2000 then assume we need patching */
#if (NTDDI_VERSION >= NTDDI_WINXP)
  version_info.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);

  RtlGetVersion((PRTL_OSVERSIONINFOW)&version_info);
  if (version_info.dwMajorVersion >= 6) {
    FUNCTION_MSG("Vista or newer - no need for patch\n");
    return;
  }
  if (version_info.dwMajorVersion == 5
      && version_info.dwMinorVersion > 2) {
    FUNCTION_MSG("Windows 2003 sp2 or newer - no need for patch\n");
    return;
  }
  if (version_info.dwMajorVersion == 5
      && version_info.dwMinorVersion == 2
      && version_info.wServicePackMajor >= 2) {
    FUNCTION_MSG("Windows 2003 sp2 or newer - no need for patch\n");
    return;
  }
#endif
  if (IsMoveCr8Supported()) {
    FUNCTION_MSG("Using LOCK MOVE CR0 TPR patch\n");
    patch_method = PATCH_METHOD_LOCK_MOVE_CR0;
  } else {
    FUNCTION_MSG("Using cached TPR patch\n");
    patch_method = PATCH_METHOD_CACHED_TPR;
  }
  patch_info.base = base;
  patch_info.length = length;
    
  XenPci_HighSync(XenPci_DoPatchKernel0, XenPci_DoPatchKernelN, &patch_info);
  
  xpdd->removable = FALSE;
  
  FUNCTION_EXIT();
}