Esempio n. 1
0
NTSTATUS
XenPci_ResumePdo(WDFDEVICE device) {
  PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device);
  PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd;
  PCHAR response;
  CHAR path[128];

  XenPci_GetBackendDetails(device);
  if (xppdd->device_callback) {
    FUNCTION_MSG("Resuming %s\n", xppdd->device);
    RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
    response = XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
    if (response) {
      FUNCTION_MSG("XnAddWatch - %s = %s\n", path, response);
      XenPci_FreeMem(response);
      xppdd->device_callback = NULL;
      xppdd->device_callback_context = NULL;
      FUNCTION_EXIT();
      return STATUS_UNSUCCESSFUL;
    }
    xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_RESUME, NULL);
  }
  return STATUS_SUCCESS;
}
static VOID
XenBus_EvtIoWrite(WDFQUEUE queue, WDFREQUEST request, size_t length)
{
  NTSTATUS status;
  PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfIoQueueGetDevice(queue));
  WDFFILEOBJECT file_object = WdfRequestGetFileObject(request);
  PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object);
  KIRQL old_irql;
  WDFREQUEST read_request;

  PUCHAR buffer;
  PUCHAR src_ptr;
  ULONG src_len;
  PUCHAR dst_ptr;
  ULONG copy_len;
  struct xsd_sockmsg *rep;
  xenbus_read_queue_item_t *list_entry;
  watch_context_t *watch_context;
  PCHAR watch_path;
  PCHAR watch_token;
  PCHAR msg;
  
  FUNCTION_ENTER();
  
  status = WdfRequestRetrieveInputBuffer(request, length, &buffer, NULL);
  ASSERT(NT_SUCCESS(status));
  
  src_ptr = (PUCHAR)buffer;
  src_len = (ULONG)length;
  dst_ptr = xpdid->xenbus.u.buffer + xpdid->xenbus.len;
  while (src_len != 0)
  {
    KdPrint((__DRIVER_NAME "     %d bytes of write buffer remaining\n", src_len));
    /* get a complete msg header */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg))
      continue;
    /* get a complete msg body */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      copy_len = min(sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len - xpdid->xenbus.len, src_len);
      if (!copy_len)
        continue;
      memcpy(dst_ptr, src_ptr, copy_len);
      dst_ptr += copy_len;
      src_ptr += copy_len;
      src_len -= copy_len;
      xpdid->xenbus.len += copy_len;
    }
    /* exit if we can't get that */
    if (xpdid->xenbus.len < sizeof(xpdid->xenbus.u.msg) + xpdid->xenbus.u.msg.len)
    {
      continue;
    }
    
    switch (xpdid->xenbus.u.msg.type)
    {
    case XS_WATCH:
    case XS_UNWATCH:
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      watch_context = (watch_context_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(watch_context_t), XENPCI_POOL_TAG);
      watch_path = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg));
      watch_token = (PCHAR)(xpdid->xenbus.u.buffer + sizeof(struct xsd_sockmsg) + strlen(watch_path) + 1);
      RtlStringCbCopyA(watch_context->path, ARRAY_SIZE(watch_context->path), watch_path);
      RtlStringCbCopyA(watch_context->token, ARRAY_SIZE(watch_context->path), watch_token);
      watch_context->file_object = file_object;
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        InsertTailList(&xpdid->xenbus.watch_list_head, &watch_context->entry);
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      if (xpdid->xenbus.u.msg.type == XS_WATCH)
        msg = XenBus_AddWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      else
        msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_path, XenPci_IoWatch, watch_context);
      KeAcquireSpinLock(&xpdid->lock, &old_irql);
      if (msg != NULL)
      {
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(msg) + 1, XENPCI_POOL_TAG);
        rep->type = XS_ERROR;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = (ULONG)(strlen(msg) + 0);
        RtlStringCbCopyA((PCHAR)(rep + 1), strlen(msg) + 1, msg);
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
          RemoveEntryList(&watch_context->entry);
      }
      else
      {
        if (xpdid->xenbus.u.msg.type == XS_WATCH)
        {
          WdfObjectReference(file_object);
        }
        else
        {
          RemoveEntryList(&watch_context->entry);
          WdfObjectDereference(file_object);
        }
        rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg), XENPCI_POOL_TAG);
        rep->type = xpdid->xenbus.u.msg.type;
        rep->req_id = xpdid->xenbus.u.msg.req_id;
        rep->tx_id = xpdid->xenbus.u.msg.tx_id;
        rep->len = 0;
      }
      KeReleaseSpinLock(&xpdid->lock, old_irql);
      break;
    default:
      rep = XenBus_Raw(xpdd, &xpdid->xenbus.u.msg);
      break;
    }
    xpdid->xenbus.len = 0;
    
    KeAcquireSpinLock(&xpdid->lock, &old_irql);
    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);

	// Check if someone was waiting for the answer already
	status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &read_request);
    if (NT_SUCCESS(status))
    {
		WDF_REQUEST_PARAMETERS parameters;
		KdPrint((__DRIVER_NAME "     post-write: found pending read\n"));
		WDF_REQUEST_PARAMETERS_INIT(&parameters);
		WdfRequestGetParameters(read_request, &parameters);
		XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, read_request, parameters.Parameters.Read.Length);
		WdfRequestComplete(read_request, STATUS_SUCCESS);
    }
    else
    {
		KdPrint((__DRIVER_NAME "     post-write: no pending read (%08x)\n", status));
    }

    KeReleaseSpinLock(&xpdid->lock, old_irql);
  }
  KdPrint((__DRIVER_NAME "     completing request with length %d\n", length));
  WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, length);

  FUNCTION_EXIT();
}
Esempio n. 3
0
NTSTATUS
XenPciPdo_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_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];
  
  FUNCTION_ENTER();
  FUNCTION_MSG("path = %s\n", xppdd->path);

  switch (previous_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");
      previous_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", previous_state);
    break;  
  }

  status = XenPci_GetBackendDetails(device);
  if (!NT_SUCCESS(status)) {
    WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
    FUNCTION_EXIT_STATUS(status);
    return status;
  }

  if (previous_state == WdfPowerDevicePrepareForHibernation && xppdd->device_callback) {
    FUNCTION_MSG("Restoring watch %s\n", xppdd->device);
    RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
    XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd);
  }

  if (!NT_SUCCESS(status)) {
    RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path);
    //XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateHandler, device);
    WdfDeviceSetFailed(device, WdfDeviceFailedNoRestart);
    FUNCTION_EXIT_STATUS(status);
    return status;
  }

  FUNCTION_EXIT();
  
  return status;
}