Exemplo n.º 1
0
VOID
XenGfxGetPrivateData(XENGFX_DEVICE_EXTENSION *pXenGfxExtension)
{
    NTSTATUS Status;
    PAGED_CODE();

    pXenGfxExtension->PrivateData.Magic = XENGFX_D3D_MAGIC;
    pXenGfxExtension->PrivateData.Version = XENGFX_D3D_VERSION;

    // Read PCI values
    Status = XenGfxReadConfigSpace(pXenGfxExtension->pPhysicalDeviceObject,
                                   &(pXenGfxExtension->PrivateData.VendorId),
                                   0,
                                   2);
    if (!NT_SUCCESS(Status)) {
        TraceWarning(("XenGfxReadConfigSpace(VendorId) failed - error: 0x%x\n", Status));
        // Set a default
        pXenGfxExtension->PrivateData.VendorId = XENGFX_DEFAULT_VENDORID;
    }

    Status = XenGfxReadConfigSpace(pXenGfxExtension->pPhysicalDeviceObject,
                                   &(pXenGfxExtension->PrivateData.DeviceId),
                                   2,
                                   2);
    if (!NT_SUCCESS(Status)) {
        TraceWarning(("XenGfxReadConfigSpace(DeviceId) failed - error: 0x%x\n", Status));
        // Set a default
        pXenGfxExtension->PrivateData.DeviceId = XENGFX_DEFAULT_DEVICEID;
    }

    pXenGfxExtension->PrivateData.ApertureSize = PAGE_SIZE*pXenGfxExtension->GartPfns;
    RtlMoveMemory(&(pXenGfxExtension->PrivateData.AdapterGuid),
                  &(pXenGfxExtension->DxgkStartInfo.AdapterGuid),
                  sizeof(GUID));
}
Exemplo n.º 2
0
/* Find the path to the backend associated with @sf.  The backend path
   remains correct as long as @token remains extant.  The caller must
   XmFreeMemory() the returned string.  Returns NULL on error. */
static char *
get_backend_path(struct scsifilt *sf, SUSPEND_TOKEN token)
{
    char *res;
    char *res_nul;
    NTSTATUS stat;
    size_t s;

    UNREFERENCED_PARAMETER(token);

    stat = xenbus_read_bin(XBT_NIL, sf->frontend_path, "backend",
                           &res, &s);
    if (!NT_SUCCESS(stat)) {
        TraceWarning(("%x reading backend path.\n", stat));
        return NULL;
    }
    res_nul = XmAllocateMemory(s + 1);
    if (!res_nul) {
        TraceWarning(("Can't get %d bytes for backend path\n", s));
        XmFreeMemory(res);
        return NULL;
    }
    memcpy(res_nul, res, s);
    res_nul[s] = 0;
    XmFreeMemory(res);
    return res_nul;
}
Exemplo n.º 3
0
VOID
__XenevtchnInitIoHole(const char *module, PHYSICAL_ADDRESS base, PVOID base_va, ULONG nbytes)
{
    if (!AustereMode && io_hole_initialized) {
        TraceWarning(("IO hole already initialized by %s\n", io_hole_owner));
        return;
    }

    io_hole_start = base;
    io_hole_va_start = base_va;
    io_hole_nr_pages = MAX(IO_HOLE_MAX_PAGES, (nbytes / PAGE_SIZE));

    /* For some reason, RtlInitializeBitmap() isn't allowed to be
       called above APC level, although all the other bitmap functions
       work at any irql.  Duplicate the entire thing here. */
    io_hole_in_use.SizeOfBitMap = io_hole_nr_pages;
    io_hole_in_use.Buffer = io_hole_bitmap;

    strncpy(io_hole_owner, module, sizeof(io_hole_owner));
    io_hole_owner[sizeof(io_hole_owner) - 1] = '\0';

    io_hole_initialized = TRUE;

    TraceNotice(("%s: IO hole: [%016llx,%016llx) mapped at %p\n",
                 io_hole_owner,
                 io_hole_start.QuadPart,
                 io_hole_start.QuadPart + (io_hole_nr_pages * PAGE_SIZE),
                 io_hole_va_start));
}
Exemplo n.º 4
0
static BOOLEAN
BalloonPopulatePfnArray(
    IN  ULONG                   Requested,
    OUT PULONG                  pPopulated
    )
{
    xen_memory_reservation_t    reservation;
    LARGE_INTEGER               Start;
    LARGE_INTEGER               End;
    ULONGLONG                   TimeDelta;
    BOOLEAN                     Slow;
    ULONG                       Populated;

    XM_ASSERT(Requested <= BALLOON_PFN_ARRAY_SIZE);

    KeQuerySystemTime(&Start);

    RangeSetPopMany(&(Balloon.PfnsBalloonedOut),
                    &(Balloon.PfnArray[0]),
                    Requested);

    SET_XEN_GUEST_HANDLE(reservation.extent_start, Balloon.PfnArray);
    reservation.extent_order = 0;
    reservation.mem_flags = 0;   // unused
    reservation.domid = DOMID_SELF;
    reservation.nr_extents = Requested;

    Populated = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
    if (Populated < Requested) {
        Balloon.PartialPopulate++;

        // This should not fail as we're simply handing back part of a range we'd previously popped.
        RangeSetAddItems(&(Balloon.PfnsBalloonedOut),
                         &(Balloon.PfnArray[Populated]),
                         Requested - Populated);
    } else if (Populated > Requested) {
        XM_BUG();
    }

    RangeSetDropRseCache(&(Balloon.PfnsBalloonedOut));

    TraceVerbose(("%s: %d page(s)\n", __FUNCTION__, Populated));

    KeQuerySystemTime(&End);
    TimeDelta = (End.QuadPart - Start.QuadPart) / 10000ull;

    Slow = FALSE;
    if (TimeDelta != 0) {
        ULONGLONG   Rate;

        Rate = (ULONGLONG)(Populated * 1000) / TimeDelta;
        if (Rate < MIN_PAGES_PER_S) {
            TraceWarning(("%s: ran for more than %dms\n", __FUNCTION__, TimeDelta));
            Slow = TRUE;
        }
    }

    *pPopulated = Populated;
    return Slow;
}
Exemplo n.º 5
0
BOOLEAN
XenLowerBackendInit(
    PXEN_LOWER XenLower)
{
    PCHAR path;
    NTSTATUS status;

    // Note this is split from the XenLowerInit so it can be called on the resume
    // path in case backend values change.

    XXX_TODO("--XT-- All the backend path handling assumes dom0 is the backend, this will change for device domains")
    // XXX TODO all the backend path handling assumes dom0 is the backend. This will
    // not necessarily be true with device domains. The changes to support this go
    // beyond this module though.
    path = XenLowerReadXenstoreValue(XenLower->FrontendPath, "backend");
    if (path == NULL)
    {
        TraceError((__FUNCTION__
            ": XenLowerReadXenstoreValue() failed to return the back end path, fatal.\n"));
        return FALSE;
    }
    status = RtlStringCchCopyA(XenLower->BackendPath,
        sizeof(XenLower->BackendPath),
        path);
    XmFreeMemory(path);
    if (status != STATUS_SUCCESS)
    {
        XenLower->BackendPath[0] = 0;
        TraceError((__FUNCTION__
            ": Failed to copy back end path - status: 0x%x\n", status));
        return FALSE;
    }

    status = xenbus_read_domain_id(XBT_NIL, XenLower->FrontendPath,
        "backend-id", &XenLower->BackendDomid);
    if (!NT_SUCCESS(status))
    {
        TraceWarning((__FUNCTION__
            ": Failed to read backend id from %s (%x), setting to dom0\n",
            XenLower->FrontendPath, status));
        XenLower->BackendDomid = DOMAIN_ID_0();
    }

    // XXX TODO for now we only support a dom0 backend so check that here. Later
    // when we support a device domain for vusb, other domids will be fine.
    XXX_TODO("--XT-- For now we only support a dom0 backend so check that here");
    if (unwrap_DOMAIN_ID(XenLower->BackendDomid) != unwrap_DOMAIN_ID(DOMAIN_ID_0()))
    {
        TraceError((XENTARGET
            ": cannot connect to backend Domid: %d, only dom0 supported currently\n",
            XenLower->BackendDomid));
        return FALSE;
    }

    TraceInfo((__FUNCTION__
        ": XenLower initialized - FrontendPath: %s  BackendPath: %s BackendDomid: %d\n",
        XenLower->FrontendPath, XenLower->BackendPath, unwrap_DOMAIN_ID(XenLower->BackendDomid)));

    return TRUE;
}
Exemplo n.º 6
0
static NTSTATUS
V4vInitializeEventChannel(PDEVICE_OBJECT fdo)
{
    XENV4V_EXTENSION   *pde = V4vGetDeviceExtension(fdo);
    KLOCK_QUEUE_HANDLE  lqh;

    KeAcquireInStackQueuedSpinLock(&pde->virqLock, &lqh);

    if (!is_null_EVTCHN_PORT(pde->virqPort)) {
        KeReleaseInStackQueuedSpinLock(&lqh);
        TraceWarning(("V4V VIRQ already bound?\n"));
	    return STATUS_SUCCESS;
    }

    pde->virqPort = EvtchnBindVirq(VIRQ_V4V, V4vVirqNotifyIsr, fdo);
    if (is_null_EVTCHN_PORT(pde->virqPort)) {
        KeReleaseInStackQueuedSpinLock(&lqh);
        TraceError(("failed to bind V4V VIRQ\n"));
	    return STATUS_INSUFFICIENT_RESOURCES;
    }

    KeReleaseInStackQueuedSpinLock(&lqh);

    TraceNotice(("V4V VIRQ connected.\n"));

    return STATUS_SUCCESS;
}
Exemplo n.º 7
0
static NTSTATUS
V4vCtrlListen(XENV4V_CONTEXT *ctx, V4V_LISTEN_VALUES *lvs)
{
    LONG    val;
    ULONG32 size;

    val = InterlockedExchangeAdd(&ctx->state, 0);
    if (val != XENV4V_STATE_BOUND) {
        TraceWarning(("state not BOUND, cannot complete connect listen\n"));
        return STATUS_INVALID_DEVICE_REQUEST;
    }

    if (lvs->backlog > V4V_SOMAXCONN) {
        TraceWarning(("backlog cannot be larger than V4V_SOMAXCONN: %d\n", V4V_SOMAXCONN));
        return STATUS_INVALID_PARAMETER;
    }

    // Initialize the listener specific pieces of the context
    KeInitializeSpinLock(&ctx->u.listener.synLock);
    ctx->u.listener.synHead = NULL;
    ctx->u.listener.synTail = NULL;
    ctx->u.listener.synCount = 0;
    if (lvs->backlog == 0) {
        ctx->u.listener.backlog = V4V_SOMAXCONN;
    }
    else {
        ctx->u.listener.backlog = (LONG)lvs->backlog;
    }
    size = ctx->u.listener.backlog*sizeof(XENV4V_SYN);

    ctx->u.listener.synList = (XENV4V_SYN*)ExAllocatePoolWithTag(NonPagedPool, size, XENV4V_TAG);
    if (ctx->u.listener.synList == NULL) {
        TraceWarning(("listen failed, out of memory\n"));
        return STATUS_NO_MEMORY;
    }
    RtlZeroMemory(ctx->u.listener.synList, size);

    // Now it becomes a listener type for ever more
    InterlockedExchange(&ctx->type, XENV4V_TYPE_LISTENER);

    // After this transition the ring is ready to receive SYNs for new connections
    InterlockedExchange(&ctx->state, XENV4V_STATE_LISTENING);
    
    return STATUS_SUCCESS;
}
Exemplo n.º 8
0
static BOOLEAN NTAPI
XenGfxInitializeEdid(PXENGFX_DEVICE_EXTENSION pXenGfxExtension)
{
    UCHAR Sum = 0;
    ULONG i;
    UCHAR *pEdidBuf;
    int   notDone;
    PUCHAR edidOffset = pXenGfxExtension->pVCrtc0 + XGFX_VCRTC_EDID;
    PULONG pEdid;

    // Allocate a single page for the VCRTC0 EDID and fetch it.
    pXenGfxExtension->pEdid = XenGfxAllocateContiguousPages(1);
    if (pXenGfxExtension->pEdid == NULL) {
        TraceError(("%s Failed to allocate EDID page!\n", __FUNCTION__));
        return FALSE;
    }
    
    pEdid = (PULONG)pXenGfxExtension->pEdid;
    //Request memory
    VideoPortWriteRegisterUlong((PULONG)(pXenGfxExtension->pVCrtc0 + XGFX_VCRTC_EDID_REQUEST), 1);

    do {
        notDone = VideoPortReadRegisterUlong( (PULONG) (pXenGfxExtension->pVCrtc0 + XGFX_VCRTC_EDID_REQUEST));
    }while (notDone);

    for (i = 0; i < 4096/sizeof(ULONG); i++) {
        pEdid[i] = VideoPortReadRegisterUlong( (PULONG) (edidOffset + (i * sizeof(ULONG))));
    }

    // Check the checksum
    pEdidBuf = (UCHAR*)pXenGfxExtension->pEdid;
    for (i = 0; i < XENGFX_EDID_SIZE; i++)
        Sum += pEdidBuf[i];

    if (Sum != 0) {
        TraceWarning(("%s EDID checksum is not valid.\n", __FUNCTION__));
    }

    // The XDDM driver will not attempt to report extensions after the EDID. Clear
    // the Extension flag.
    if (pXenGfxExtension->pEdid->ExtensionFlag[0] != 0) {
        pXenGfxExtension->pEdid->ExtensionFlag[0] = 0;
        Sum = 1;
    }

    // Recalculate the checksum if needed.
    if (Sum != 0) {
        Sum = 0;
        pXenGfxExtension->pEdid->Checksum[0] = 0;
        for (i = 0; i < XENGFX_EDID_SIZE; i++)
            Sum += pEdidBuf[i];
        pXenGfxExtension->pEdid->Checksum[0] = -Sum;
    }

    return TRUE;
}
Exemplo n.º 9
0
static NTSTATUS
V4vCtrlConnect(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx, V4V_CONNECT_VALUES *cvs, PIRP irp)
{
    NTSTATUS      status = STATUS_SUCCESS;
    LONG          val;
    XENV4V_INSERT ins = {FALSE};

    val = InterlockedExchangeAdd(&ctx->state, 0);
    if (val != XENV4V_STATE_BOUND) {
        TraceWarning(("state not BOUND, cannot complete connect request\n"));
        return STATUS_INVALID_DEVICE_REQUEST;
    }

    // Any IRPs that are queued are given a sanity initialization
    V4vInitializeIrp(irp);

    // These stream related values are only set once during a single phase of transitioning
    // to a stream type.
    ctx->sdst = cvs->ringAddr;
    ctx->connId = (ULONG64)(RtlRandomEx(&pde->seed) & 0xffffffff);

    // Update the stream header in the IRPs buffer. The cvs pointer points to the IRPs actual
    // in/out buffer the IOCTL is defined to have output.
    cvs->sh.flags = V4V_SHF_SYN;
    cvs->sh.conid = (ULONG32)ctx->connId;

    // Now it becomes a connector type for ever more
    InterlockedExchange(&ctx->type, XENV4V_TYPE_CONNECTOR);

    // After this transition, we will still send a SYN datagram and get the ACK
    InterlockedExchange(&ctx->state, XENV4V_STATE_CONNECTING);

    // Start the connecting timer each time a context goes into this state.
    V4vStartConnectionTimer(pde);

    // Flag it
    irp->Tail.Overlay.DriverContext[0] = 
        (PVOID)(ULONG_PTR)(XENV4V_PEEK_STREAM|XENV4V_PEEK_WRITE|XENV4V_PEEK_SYN|XENV4V_PEEK_IOCTL);

    // Always queue it to the back and marks it pending
    status = IoCsqInsertIrpEx(&pde->csqObject, irp, NULL, &ins);
    if (NT_SUCCESS(status)) {        
        status = STATUS_PENDING;
        // Drive any write IO
        V4vProcessContextWrites(pde, ctx);
    }
    else {
        // Fail it in IOCTL routine and return go to disconnected state
        V4vStopConnectionTimer(pde, FALSE);
        InterlockedExchange(&ctx->state, XENV4V_STATE_DISCONNECTED);
    }

    return status;
}
Exemplo n.º 10
0
static NTSTATUS
V4vCtrlConnectWait(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx, V4V_WAIT_VALUES *wvs, PIRP irp)
{
    NTSTATUS      status = STATUS_SUCCESS;
    LONG          val;
    XENV4V_INSERT ins = {FALSE};

    // This is the connect wait functionality that allows a single end to end
    // stream connection. This part serves as the "listening" end.
    val = InterlockedExchangeAdd(&ctx->state, 0);
    if (val != XENV4V_STATE_BOUND) {
        TraceWarning(("state not BOUND, cannot complete connect wait request\n"));
        return STATUS_INVALID_DEVICE_REQUEST;
    }

    // Any IRPs that are queued are given a sanity initialization
    V4vInitializeIrp(irp);

    // Update the stream header in the IRPs buffer. Just clear if now, later it will
    // be used for the ACK.
    wvs->sh.flags = 0;
    wvs->sh.conid = 0;

    // Now it becomes a connector type for ever more
    InterlockedExchange(&ctx->type, XENV4V_TYPE_CONNECTOR);

    // After this transition, we will wait to get a SYN and send back the ACK
    InterlockedExchange(&ctx->state, XENV4V_STATE_WAITING);

    // Flag it
    irp->Tail.Overlay.DriverContext[0] = 
        (PVOID)(ULONG_PTR)(XENV4V_PEEK_STREAM|XENV4V_PEEK_READ|XENV4V_PEEK_SYN|XENV4V_PEEK_IOCTL);

    // Always queue it to the back and marks it pending
    status = IoCsqInsertIrpEx(&pde->csqObject, irp, NULL, &ins);
    if (NT_SUCCESS(status)) {        
        status = STATUS_PENDING;
        // Drive any read IO
        V4vProcessContextReads(pde, ctx);
    }
    else {
        // Fail it in IOCTL routine and return go to disconnected state
        InterlockedExchange(&ctx->state, XENV4V_STATE_DISCONNECTED);
    }

    return status;
}
Exemplo n.º 11
0
BOOLEAN NTAPI XenGfxVbeGetModeInfo(USHORT ModeNumber, VBE_MODE_INFO* pVbeModeInfo)
{
    const MODE_INFO_ITEM *pCurrentMode;
    BOOLEAN UsingLFB;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    if (!g_VbeInfoInitialized) {
        return FALSE;
    }

    if (pVbeModeInfo == NULL) {
        return FALSE;
    }

    RtlZeroMemory(pVbeModeInfo, sizeof(VBE_MODE_INFO));

    UsingLFB = ((ModeNumber & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER) ? TRUE : FALSE;
    ModeNumber &= 0x1ff;

    // The spinlock is not needed since this routine just reads values from the
    // local mode table or from vbe ports.

    pCurrentMode = XenGfxFindMode(ModeNumber, UsingLFB);
    if (pCurrentMode == NULL) {
        TraceWarning(("VBE mode %04x NOT FOUND??\n", ModeNumber));
        return FALSE;
    }

    TraceVerbose(("Found VBE mode 0x%04x\n", ModeNumber));
    RtlCopyMemory(pVbeModeInfo, &pCurrentMode->ModeInfo, sizeof(VBE_MODE_INFO));

    // Fix it up a bit. Setting WinFuncPtr for VBE_WINDOW_ATTRIBUTE_RELOCATABLE is probably not so useful...
    if (UsingLFB) {
        pVbeModeInfo->NumberOfBanks = 1;
    }

    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_LFB_ADDRESS_H);
    pVbeModeInfo->PhysBasePtr = READ_PORT_USHORT((USHORT*)VBE_PORT_DATA);
    pVbeModeInfo->PhysBasePtr = pVbeModeInfo->PhysBasePtr << 16;
        
    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return TRUE;
}
Exemplo n.º 12
0
//----------------------------------------------------------------------------------------------------------------------------
VOID Subsystem::Destroy()
{
  Trace0Enter("");

  m_State = 0;

  if (m_pThread)
  {
    TraceInfo(this, "Waiting for subsystem to terminate itself");
    if (!m_pThread->Wait(2000))
    {
      TraceWarning(this, "The subsystem manager timed-out whilst waiting for the subsystem to terminate.  Subsystem will be forcably terminated");
      m_pThread->Terminate();
    }

    m_pThread = 0;
  }
}
Exemplo n.º 13
0
static NTSTATUS
XenWorkItemDispatch(
    IN  struct xm_thread    *pSelf,
    IN  VOID                *Argument
    )
{
    KIRQL                   Irql;

    UNREFERENCED_PARAMETER(Argument);

    while (XmThreadWait(pSelf) >= 0) {
        Irql = acquire_irqsafe_lock(&WorkItemDispatchLock);
        while (!IsListEmpty(&PendingWorkItems)) {
            PLIST_ENTRY Head;
            XEN_WORKITEM *Item;

            Head = RemoveHeadList(&PendingWorkItems);
            Item = CurrentItem = CONTAINING_RECORD(Head, XEN_WORKITEM, List);
            release_irqsafe_lock(&WorkItemDispatchLock, Irql);

            XM_ASSERT(CurrentItem->Magic == WORKITEM_MAGIC);

            KeQuerySystemTime(&Item->Start);

            TraceVerbose(("%s: invoking '%s'\n", __FUNCTION__, CurrentItem->Name));
            CurrentItem->Work(CurrentItem->Context);

            Irql = acquire_irqsafe_lock(&WorkItemDispatchLock);
            CurrentItem = NULL;
            release_irqsafe_lock(&WorkItemDispatchLock, Irql);

            XmFreeMemory(Item);

            Irql = acquire_irqsafe_lock(&WorkItemDispatchLock);
        }
        release_irqsafe_lock(&WorkItemDispatchLock, Irql);
    }

    TraceWarning(("%s: terminating.\n", __FUNCTION__));
    return STATUS_SUCCESS;
}
Exemplo n.º 14
0
PVOID
XenevtchnAllocIoMemory(ULONG nr_bytes, PHYSICAL_ADDRESS *pa)
{
    KIRQL old_irql;
    ULONG page_nr;

    nr_bytes = (nr_bytes + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);

    old_irql = acquire_irqsafe_lock(&io_hole_lock);
    page_nr = RtlFindClearBitsAndSet(&io_hole_in_use,
                                     nr_bytes / PAGE_SIZE,
                                     0);
    release_irqsafe_lock(&io_hole_lock, old_irql);
    if (page_nr == 0xffffffff) {
        TraceWarning (("Filled the io hole!\n"));
        return NULL;
    } else {
        pa->QuadPart = io_hole_start.QuadPart + page_nr * PAGE_SIZE;
        return (PVOID)((ULONG_PTR)io_hole_va_start + page_nr * PAGE_SIZE);
    }
}
Exemplo n.º 15
0
NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT driverObject,
			PUNICODE_STRING registryPath)
{
    UNREFERENCED_PARAMETER(registryPath);	

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    PsGetVersion(&g_osMajorVersion, &g_osMinorVersion, NULL, NULL);

    if ((g_osMajorVersion < 5)||((g_osMajorVersion == 5)&&(g_osMinorVersion < 1))) {
        TraceWarning(("Windows XP or later operating systems supported!\n"));
        return STATUS_UNSUCCESSFUL;
    }

    TraceInfo(("Starting driver...\n"));

    driverObject->DriverUnload = V4vDriverUnload;
    driverObject->DriverExtension->AddDevice = V4vAddDevice;
	
    driverObject->MajorFunction[IRP_MJ_CREATE]         = V4vDispatchCreate;
    driverObject->MajorFunction[IRP_MJ_CLEANUP]        = V4vDispatchCleanup;
    driverObject->MajorFunction[IRP_MJ_CLOSE]          = V4vDispatchClose;
    driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = V4vDispatchDeviceControl;
    driverObject->MajorFunction[IRP_MJ_READ]           = V4vDispatchRead;
    driverObject->MajorFunction[IRP_MJ_WRITE]          = V4vDispatchWrite;
    driverObject->MajorFunction[IRP_MJ_PNP]            = V4vDispatchPnP;
    driverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = V4vDispatchWmi;
    driverObject->MajorFunction[IRP_MJ_POWER]          = V4vDispatchPower;
    // The rest can be handled by the system not supported routine

    TraceVerbose(("DriverEntry returning successfully\n"));

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return STATUS_SUCCESS;
}
Exemplo n.º 16
0
static NTSTATUS
XenLowerConnectBackendInternal(
    PXEN_LOWER XenLower,
    SUSPEND_TOKEN Token)
{
    NTSTATUS status = STATUS_SUCCESS;
    XENBUS_STATE state;
    xenbus_transaction_t xbt;
    PCHAR fepath;

    if (is_null_EVTCHN_PORT(XenLower->EvtchnPort))
    {
        TraceError((__FUNCTION__ ": no event channel port, this routine must be called after event channel initialization\n"));
        return STATUS_UNSUCCESSFUL;
    }

    //---------------------------Backend Wait Ready-------------------------------//
    //
    // Wait for backend to get ready for initialization.
    //

    status = xenbus_change_state(XBT_NIL,
        XenLower->FrontendPath,
        "state",
        XENBUS_STATE_INITIALISING);
    if (!NT_SUCCESS(status))
    {
        TraceWarning((__FUNCTION__
            ": Failed to change front end state to XENBUS_STATE_INITIALISING(%d) status: 0x%x\n",
            XENBUS_STATE_INITIALISING, status));
        // Go on, best effort, chin up
    }

    TraceInfo((__FUNCTION__
        ": Front end state set to XENBUS_STATE_INITIALISING(%d)\n",
        XENBUS_STATE_INITIALISING));

    state = null_XENBUS_STATE();
    for ( ; ; )
    {
        // Turns out suspend tokens are not even used.
        state = XenbusWaitForBackendStateChange(XenLower->BackendPath,
            state, NULL, Token);

        if (same_XENBUS_STATE(state, XENBUS_STATE_INITWAIT))
        {
            break;
        }

        if (same_XENBUS_STATE(state, XENBUS_STATE_CLOSING) ||
            is_null_XENBUS_STATE(state))
        {
            TraceError((__FUNCTION__ ": backend '%s' went away before we could connect to it?\n",
                XenLower->BackendPath));

            status = STATUS_UNSUCCESSFUL;
            break;
        }
    }

    if (status != STATUS_SUCCESS)
    {
        return status;
    }

    TraceInfo((__FUNCTION__
        ": Back end state went to XENBUS_STATE_INITWAIT(%d)\n",
        XENBUS_STATE_INITWAIT));
    
    //----------------------------Backend Connect---------------------------------//    

    //
    // Communicate configuration to backend.
    //

    fepath = XenLower->FrontendPath;
    do {
        xenbus_transaction_start(&xbt);
        xenbus_write_grant_ref(xbt, fepath, "ring-ref", XenLower->SringGrantRef);
        xenbus_write_evtchn_port(xbt, fepath, "event-channel", XenLower->EvtchnPort);
        xenbus_change_state(xbt, fepath, "state", XENBUS_STATE_CONNECTED);
        status = xenbus_transaction_end(xbt, 0);
    } while (status == STATUS_RETRY);

    if (status != STATUS_SUCCESS)
    {
        TraceError((__FUNCTION__ ": failed to configure xenstore frontend values.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    TraceInfo((__FUNCTION__
        ": Front end state set to XENBUS_STATE_CONNECTED(%d)\n",
        XENBUS_STATE_CONNECTED));

    //
    // Wait for backend to accept configuration and complete initialization.
    //

    state = null_XENBUS_STATE();
    for ( ; ; )
    {
        state = XenbusWaitForBackendStateChange(XenLower->BackendPath,
            state, NULL, Token);

        if (is_null_XENBUS_STATE(state) ||
            same_XENBUS_STATE(state, XENBUS_STATE_CLOSING) ||
            same_XENBUS_STATE(state, XENBUS_STATE_CLOSED))
        {

            TraceError((__FUNCTION__ ": Failed to connected '%s' <-> '%s' backend state: %d\n",
                XenLower->FrontendPath,
                XenLower->BackendPath,
                state));

            status = STATUS_UNSUCCESSFUL;
            break;
        }

        if (same_XENBUS_STATE(state, XENBUS_STATE_CONNECTED))
        {
            TraceNotice((__FUNCTION__ ": Connected '%s' <-> '%s' \n",
                XenLower->FrontendPath,
                XenLower->BackendPath));
            TraceInfo((__FUNCTION__
                ": Back end final state went to XENBUS_STATE_CONNECTED(%d)\n",
                XENBUS_STATE_CONNECTED));
            break;
        }
    }

    return status;
}
Exemplo n.º 17
0
static NTSTATUS
V4vAddDevice(PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
{
    NTSTATUS          status = STATUS_SUCCESS;
    UNICODE_STRING    deviceName;
    PDEVICE_OBJECT    fdo = NULL;
    PXENV4V_EXTENSION pde = NULL;
    LONG              val;
    BOOLEAN           symlink = FALSE;
    LARGE_INTEGER     seed;
    WCHAR            *szSddl = NULL;
    UNICODE_STRING    sddlString;
    CHAR             *szFpath = NULL;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    // We only allow one instance of this device type. If more than on pdo is created we need
    val = InterlockedCompareExchange(&g_deviceCreated, 1, 0);
    if (val != 0) {
        TraceWarning(("cannot instantiate more that one v4v device node.\n"));
        return STATUS_UNSUCCESSFUL;
    }

    do {
        // Create our device
        RtlInitUnicodeString(&deviceName, V4V_DEVICE_NAME);
        szSddl = g_win5Sddl;
        RtlInitUnicodeString(&sddlString, szSddl);

        status = 
            IoCreateDeviceSecure(driverObject,
                                 sizeof(XENV4V_EXTENSION),
                                 &deviceName,
                                 FILE_DEVICE_UNKNOWN,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &sddlString,
                                 (LPCGUID)&GUID_SD_XENV4V_CONTROL_OBJECT,
                                 &fdo);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create device object - error: 0x%x\n", status));
            fdo = NULL;
            break;
        }

        pde = (PXENV4V_EXTENSION)fdo->DeviceExtension;
        RtlZeroMemory(pde, sizeof(XENV4V_EXTENSION));
        RtlStringCchCopyW(pde->symbolicLinkText, XENV4V_SYM_NAME_LEN, V4V_SYMBOLIC_NAME);
        RtlInitUnicodeString(&pde->symbolicLink, pde->symbolicLinkText);

        // Create our symbolic link
        status = IoCreateSymbolicLink(&pde->symbolicLink, &deviceName);
        if (!NT_SUCCESS(status)) {
            TraceError(("failed to create symbolic - error: 0x%x\n", status));
            break;
        }
        symlink = TRUE;       

        // Get our xenstore path
        szFpath = xenbus_find_frontend(pdo);
        if (szFpath == NULL) {
            status = STATUS_NO_SUCH_DEVICE;
            TraceError(("failed to locate XenStore front end path\n"));
            break;
        }

        // Setup the extension
        pde->magic = XENV4V_MAGIC;
        pde->pdo = pdo;
        pde->fdo = fdo;
        IoInitializeRemoveLock(&pde->removeLock, 'v4vx', 0, 0);
        pde->frontendPath = szFpath;
        szFpath = NULL;
        pde->state = XENV4V_DEV_STOPPED; // wait for start
        pde->lastPoState = PowerSystemWorking;
        pde->virqPort = null_EVTCHN_PORT();
        KeInitializeDpc(&pde->virqDpc, V4vVirqNotifyDpc, fdo);
        KeInitializeSpinLock(&pde->virqLock);
        KeInitializeSpinLock(&pde->dpcLock);
        KeInitializeTimerEx(&pde->timer, NotificationTimer);
        KeInitializeDpc(&pde->timerDpc,
                        V4vConnectTimerDpc,
                        fdo);
        KeInitializeSpinLock(&pde->timerLock);
        pde->timerCounter = 0;
        InitializeListHead(&pde->contextList);
        KeInitializeSpinLock(&pde->contextLock);
        pde->contextCount = 0;
        InitializeListHead(&pde->ringList);
        KeInitializeSpinLock(&pde->ringLock);
        InitializeListHead(&pde->pendingIrpQueue);
        pde->pendingIrpCount = 0;
        KeInitializeSpinLock(&pde->queueLock);
        IoCsqInitializeEx(&pde->csqObject,
                          V4vCsqInsertIrpEx,
                          V4vCsqRemoveIrp,
                          V4vCsqPeekNextIrp,
                          V4vCsqAcquireLock,
                          V4vCsqReleaseLock,
                          V4vCsqCompleteCanceledIrp);
        InitializeListHead(&pde->destList);
        pde->destCount = 0;
        ExInitializeNPagedLookasideList(&pde->destLookasideList,
                                        NULL,
                                        NULL,
                                        0,
                                        sizeof(XENV4V_DESTINATION),
                                        XENV4V_TAG,
                                        0);
        KeQueryTickCount(&seed);
        pde->seed = seed.u.LowPart;

        // Now attach us to the stack
        pde->ldo = IoAttachDeviceToDeviceStack(fdo, pdo);
        if (pde->ldo == NULL) {
            TraceError(("failed to attach device to stack - error: 0x%x\n", status));
            status = STATUS_NO_SUCH_DEVICE;
            break;
        }

        // Use direct IO and let the IO manager directly map user buffers; clear the init flag
        fdo->Flags |= DO_DIRECT_IO;
        fdo->Flags &= ~DO_DEVICE_INITIALIZING;        

        // Made it here, go to connected state to be consistent
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CONNECTED);
    } while (FALSE);

    if (!NT_SUCCESS(status)) {
        if (fdo != NULL) {         
            if ((pde != NULL)&&(pde->ldo != NULL)) {
                IoDetachDevice(pde->ldo);
            }
            if (szFpath != NULL) {
                XmFreeMemory(szFpath);
            }
            if (symlink) {
                IoDeleteSymbolicLink(&pde->symbolicLink);
            }
            IoDeleteDevice(fdo);
        }
    }

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return status;
}
Exemplo n.º 18
0
NDIS_STATUS 
MiniportInitialize (
    IN  NDIS_HANDLE                        MiniportAdapterHandle,
    IN  NDIS_HANDLE                        MiniportDriverContext,
    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
    )
{
    PADAPTER adapter = NULL;
    NDIS_STATUS ndisStatus;
    PCHAR path;
    PDEVICE_OBJECT pdo;
    PCHAR xenbusPath = NULL;
    int i;

    UNREFERENCED_PARAMETER(MiniportDriverContext);
    UNREFERENCED_PARAMETER(MiniportInitParameters);

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    //
    // Wait for xenbus to come up.  SMP guests sometimes try and
    // initialise xennet and xenvbd in parallel when they come back
    // from hibernation, and that causes problems.
    //

    if (!xenbus_await_initialisation()) {
        ndisStatus = NDIS_STATUS_DEVICE_FAILED;
        goto exit;
    }

    //
    // 8021P support is disabled by default.
    // It can be turned on by specifying the appropriate PV boot option.
    //

    if (XenPVFeatureEnabled(DEBUG_NIC_8021_P)) {
        XennetMacOptions |= NDIS_MAC_OPTION_8021P_PRIORITY;
    }

    xenbus_write(XBT_NIL, "drivers/xenwnet", XENNET_VERSION);
    NdisMGetDeviceProperty(MiniportAdapterHandle,
                           &pdo,
                           NULL,
                           NULL,
                           NULL,
                           NULL);

    xenbusPath = xenbus_find_frontend(pdo);
    if (!xenbusPath) {
        ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
        goto exit;
    }

    TraceNotice(("Found '%s' frontend.\n", xenbusPath));
    adapter = XmAllocateZeroedMemory(sizeof(ADAPTER));
    if (adapter == NULL) {
        ndisStatus = NDIS_STATUS_RESOURCES;
        goto exit;
    }

    path = xenbusPath;
    xenbusPath = NULL;

    i = 0;
    do {
        ndisStatus = AdapterInitialize(adapter, MiniportAdapterHandle, path);
        if (ndisStatus != NDIS_STATUS_SUCCESS) {
            TraceWarning (("Waiting for backend...\n"));
            NdisMSleep (1000000);   // 1 sec
        }
    } while ((ndisStatus != NDIS_STATUS_SUCCESS) && (++i < 30));
    if (ndisStatus != NDIS_STATUS_SUCCESS) {
        goto exit;
    }

exit:
    if (ndisStatus != NDIS_STATUS_SUCCESS) {
        if (adapter) {
			XmFreeMemory(adapter->BackendPath);
			adapter->BackendPath = NULL;
            AdapterDelete(&adapter);
        }

        if (xenbusPath) {
            XmFreeMemory(xenbusPath);
        }
    }

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));
    return ndisStatus;
}
Exemplo n.º 19
0
/* srb is kind of half const here.  We never modify it directly, but
   it will obviously get modified when it completes. */
static void
allocate_irp_and_resubmit_srb(struct scsifilt *sf,
                              SCSI_REQUEST_BLOCK *srb_)
{
    const SCSI_REQUEST_BLOCK *const srb = srb_;
    PIRP irp;
    PIO_STACK_LOCATION isl;
    PVOID buf;
    PMDL mdl;
    PSCSI_REQUEST_BLOCK new_srb;

    irp = NULL;
    mdl = NULL;
    new_srb = NULL;

    buf = ExAllocatePoolWithTag(NonPagedPool, srb->DataTransferLength, 'ssrx');
    if (!buf)
        goto err;

    memcpy(buf, srb->DataBuffer, srb->DataTransferLength);

    new_srb = XmAllocateZeroedMemory(sizeof(*new_srb));
    if (!new_srb)
        goto err;

    new_srb->Length = sizeof(*new_srb);
    new_srb->Function = srb->Function;
    XM_ASSERT3U(new_srb->Function, ==, SRB_FUNCTION_EXECUTE_SCSI);
    new_srb->SrbFlags = srb->SrbFlags;
    new_srb->PathId = srb->PathId;
    new_srb->TargetId = srb->TargetId;
    new_srb->Lun = srb->Lun;
    new_srb->QueueTag = srb->QueueTag;
    new_srb->QueueAction = srb->QueueAction;
    new_srb->DataTransferLength = srb->DataTransferLength;
    new_srb->DataBuffer = buf;
    new_srb->OriginalRequest = (PVOID)srb;
    new_srb->CdbLength = srb->CdbLength;
    memcpy(new_srb->Cdb, srb->Cdb, srb->CdbLength);

    irp = IoAllocateIrp(2, FALSE);
    if (!irp)
        goto err;

    mdl = IoAllocateMdl(buf, new_srb->DataTransferLength, FALSE, FALSE, irp);
    if (!mdl)
        goto err;
    MmBuildMdlForNonPagedPool(mdl);

    IoSetNextIrpStackLocation(irp);
    isl = IoGetCurrentIrpStackLocation(irp);
    isl->Parameters.Scsi.Srb = new_srb;
    isl->DeviceObject = sf->fdo;
    IoSetCompletionRoutine(irp, redirect_irp_completion, NULL, TRUE, TRUE, TRUE);
    IoSetNextIrpStackLocation(irp);

    isl = IoGetCurrentIrpStackLocation(irp);
    isl->MajorFunction = IRP_MJ_SCSI;
    isl->MinorFunction = 0;
    isl->Parameters.Scsi.Srb = new_srb;
    isl->DeviceObject = sf->fdo;
    filter_process_irp(sf, irp, new_srb);

    return;

err:
    TraceWarning(("Failed to set up redirected SRB\n"));
    if (irp)
        IoFreeIrp(irp);
    if (mdl)
        IoFreeMdl(mdl);
    if (buf)
        ExFreePool(buf);
    if (new_srb)
        XmFreeMemory(new_srb);

    queue_srb_for_error(sf, (PSCSI_REQUEST_BLOCK)srb);
}
Exemplo n.º 20
0
static BOOLEAN
BalloonFreePfnArray(
    IN  ULONG       Requested,
    IN  BOOLEAN     Check,
    OUT PULONG      pFreed
    )
{
    ULONG           Index;
    ULONG           Freed;
    MDL             *Mdl;
    LARGE_INTEGER   Start;
    LARGE_INTEGER   End;
    ULONGLONG       TimeDelta;
    BOOLEAN         Slow;

    XM_ASSERT(Requested <= BALLOON_PFN_ARRAY_SIZE);

    KeQuerySystemTime(&Start);

    Freed = 0;

    if (Requested == 0)
        goto done;

    for (Index = 0; Index < Requested; Index++) {
        if (Balloon.PfnArray[Index] == 0) {
            TraceError(("%s: PFN[%d] == 0\n", __FUNCTION__, Index));
            XM_BUG();
        }
    }

    Mdl = &(Balloon.Mdl);
    Mdl->Next = NULL;
    Mdl->Size = (SHORT)(sizeof(MDL) + (sizeof(PFN_NUMBER) * Requested));
    Mdl->MdlFlags = MDL_PAGES_LOCKED;
    Mdl->Process = NULL;
    Mdl->MappedSystemVa = NULL;
    Mdl->StartVa = NULL;
    Mdl->ByteCount = Requested << PAGE_SHIFT;
    Mdl->ByteOffset = 0;

    BalloonFreePagesFromMdl(Mdl, Check);
    Freed = Requested;

    RtlZeroMemory(Balloon.PfnArray, Freed * sizeof (PFN_NUMBER));

done:
    TraceVerbose(("%s: %d page(s)\n", __FUNCTION__, Freed));

    KeQuerySystemTime(&End);
    TimeDelta = (End.QuadPart - Start.QuadPart) / 10000ull;

    Slow = FALSE;
    if (TimeDelta != 0) {
        ULONGLONG   Rate;

        Rate = (ULONGLONG)(Freed * 1000) / TimeDelta;
        if (Rate < MIN_PAGES_PER_S) {
            TraceWarning(("%s: ran for more than %dms\n", __FUNCTION__, TimeDelta));
            Slow = TRUE;
        }
    }

    *pFreed = Freed;
    return Slow;
}
Exemplo n.º 21
0
static BOOLEAN
BalloonReleasePfnArray(
    IN  ULONG                   Requested,
    OUT PULONG                  pReleased
    )
{
    xen_memory_reservation_t    reservation;
    LARGE_INTEGER               Start;
    LARGE_INTEGER               End;
    ULONGLONG                   TimeDelta;
    BOOLEAN                     Slow;
    ULONG                       Index;
    ULONG                       Registered;
    ULONG                       Released;

    XM_ASSERT(Requested <= BALLOON_PFN_ARRAY_SIZE);

    KeQuerySystemTime(&Start);

    Released = 0;

    if (Requested == 0)
        goto done;

    for (Index = 0; Index < Requested; Index++) {
        if (Balloon.PfnArray[Index] == 0) {
            TraceError(("%s: PFN[%d] == 0\n", __FUNCTION__, Index));
            XM_BUG();
        }
    }

    Registered = RangeSetAddItems(&(Balloon.PfnsBalloonedOut), 
                                  &(Balloon.PfnArray[0]),
                                  Requested);
    if (Registered < Requested) {
        TraceError(("%s: failed to register %d page(s)\n", __FUNCTION__,
                    Requested - Registered));
        if (Registered == 0)
            goto done;
    }

    SET_XEN_GUEST_HANDLE(reservation.extent_start, Balloon.PfnArray);
    reservation.extent_order = 0;
    reservation.mem_flags = 0;   // unused
    reservation.domid = DOMID_SELF;
    reservation.nr_extents = Registered;

    Released = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
    if (Released < Registered) {
        TraceWarning(("%s: partial release (%d < %d)\n", __FUNCTION__, Released, Registered));

        // This should not fail as we're removing ranges we just added
        RangeSetRemoveItems(&(Balloon.PfnsBalloonedOut),
                            &(Balloon.PfnArray[Released]),
                            Registered - Released);
    } else if (Released > Registered) {
        XM_BUG();
    }

    RtlZeroMemory(Balloon.PfnArray, Released * sizeof (PFN_NUMBER));

done:
    RangeSetDropRseCache(&(Balloon.PfnsBalloonedOut));

    TraceVerbose(("%s: %d page(s)\n", __FUNCTION__, Released));

    KeQuerySystemTime(&End);
    TimeDelta = (End.QuadPart - Start.QuadPart) / 10000ull;

    Slow = FALSE;
    if (TimeDelta != 0) {
        ULONGLONG   Rate;

        Rate = (ULONGLONG)(Released * 1000) / TimeDelta;
        if (Rate < MIN_PAGES_PER_S) {
            TraceWarning(("%s: ran for more than %dms\n", __FUNCTION__, TimeDelta));
            Slow = TRUE;
        }
    }

    *pReleased = Released;
    return Slow;
}
Exemplo n.º 22
0
static BOOLEAN
BalloonAllocatePfnArray(
    IN  ULONG       Requested,
    OUT PULONG      pAllocated
    )
{
    LARGE_INTEGER   Start;
    LARGE_INTEGER   End;
    ULONGLONG       TimeDelta;
    BOOLEAN         Slow;
    MDL             *Mdl;
    ULONG           Allocated;
    PFN_NUMBER      *Array;

    XM_ASSERT(Requested <= BALLOON_PFN_ARRAY_SIZE);

    KeQuerySystemTime(&Start);

    Allocated = 0;

    Mdl = BalloonAllocatePagesForMdl(Requested);
    if (Mdl == NULL) {
        Balloon.AllocateFail++;
        goto done;
    }

    XM_ASSERT(Mdl->ByteOffset == 0);
    XM_ASSERT((Mdl->ByteCount & (PAGE_SIZE - 1)) == 0);
    XM_ASSERT(Mdl->MdlFlags & MDL_PAGES_LOCKED);

    Allocated = Mdl->ByteCount >> PAGE_SHIFT;

    if (Allocated < Requested) {
        TraceNotice(("%s: partial allocation (%d < %d)\n", __FUNCTION__, Allocated, Requested));
        Balloon.PartialAllocate++;
    }

    Array = MmGetMdlPfnArray(Mdl);
    BalloonSortPfnArray(Array, Allocated);
    RtlCopyMemory(Balloon.PfnArray, Array, Allocated * sizeof (PFN_NUMBER));

    ExFreePool(Mdl);

done:
    TraceVerbose(("%s: %d page(s)\n", __FUNCTION__, Allocated));

    KeQuerySystemTime(&End);
    TimeDelta = (End.QuadPart - Start.QuadPart) / 10000ull;

    Slow = FALSE;
    if (TimeDelta != 0) {
        ULONGLONG   Rate;

        Rate = (ULONGLONG)(Allocated * 1000) / TimeDelta;
        if (Rate < MIN_PAGES_PER_S) {
            TraceWarning(("%s: ran for more than %dms\n", __FUNCTION__, TimeDelta));
            Slow = TRUE;
        }
    }

    *pAllocated = Allocated;
    return Slow;
}
Exemplo n.º 23
0
static NTSTATUS
V4vCtrlAccept(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx, ULONG ioc, VOID *iob, ULONG iol, PIRP irp)
{
    NTSTATUS            status = STATUS_SUCCESS;
    LONG                val;
    V4V_INIT_VALUES     init;
    FILE_OBJECT        *pfo = NULL;
    XENV4V_CONTEXT     *actx;
    XENV4V_INSERT       ins = {FALSE};
    HANDLE              fh;
    HANDLE              rxe;
    V4V_ACCEPT_PRIVATE *priv;

    val = InterlockedExchangeAdd(&ctx->state, 0);
    if (val != XENV4V_STATE_LISTENING) {
        TraceWarning(("state not LISTENING, cannot complete accept request\n"));
        return STATUS_INVALID_DEVICE_REQUEST;
    }    

    // Handle 32b/64b thunk sructures here and test input
#if defined(_WIN64)
    if (ioc == V4V_IOCTL_ACCEPT_32)
    {
        V4V_ACCEPT_VALUES_32 *avs32 = (V4V_ACCEPT_VALUES_32*)iob;

        if (iol != sizeof(V4V_ACCEPT_VALUES_32)) {
            TraceError(("invalid accept values.\n"));
            return STATUS_INVALID_PARAMETER;
        }        
        fh  = avs32->fileHandle;
        rxe = avs32->rxEvent;
        priv = (V4V_ACCEPT_PRIVATE*)((UCHAR*)avs32 + FIELD_OFFSET(V4V_ACCEPT_VALUES_32, priv));
    }
    else
#endif
    {
        V4V_ACCEPT_VALUES *avs = (V4V_ACCEPT_VALUES*)iob;

        UNREFERENCED_PARAMETER(ioc);

        if (iol != sizeof(V4V_ACCEPT_VALUES)) {
            TraceError(("invalid accept values.\n"));
            return STATUS_INVALID_PARAMETER;
        }        
        fh  = avs->fileHandle;
        rxe = avs->rxEvent;
        priv = (V4V_ACCEPT_PRIVATE*)((UCHAR*)avs + FIELD_OFFSET(V4V_ACCEPT_VALUES, priv));
    }

    // Any IRPs that are queued are given a sanity initialization
    V4vInitializeIrp(irp);

    // Get a reference to the file object for the handle
    status = ObReferenceObjectByHandle(fh,
                                       0,
                                       *IoFileObjectType,
                                       irp->RequestorMode,
                                       &pfo,
                                       NULL);
    if (!NT_SUCCESS(status)) {
        TraceError(("failed to get a reference to the accepter file object - error: 0x%x\n", status));
        return status;
    }
    actx = (XENV4V_CONTEXT*)pfo->FsContext;
    ObDereferenceObject(pfo);

    // Store the referenced acceptor context in the IOCTL buffer so we can access it at > PASSIVE later.
    V4vAddRefContext(pde, actx);
#if defined(_WIN64)
    priv->q.a = (ULONG64)actx;
#else
    priv->d.a = (ULONG32)actx;
#endif

    // Do the base initialization of the file object context
    init.rxEvent = rxe;
    init.ringLength = ctx->ringLength; // shared ring length
    status = V4vCtrlInitializeFile(actx, &init, irp);
    if (!NT_SUCCESS(status)) {
        V4vReleaseContext(pde, actx);
        TraceError(("failed to initialize the accepter file object - error: 0x%x\n", status));
        return status;
    }

    // Now initialize the accepter specific state and associate the accepter
    // with the listener context and ring.
    KeInitializeSpinLock(&actx->u.accepter.dataLock);
    actx->u.accepter.dataList = NULL;
    actx->u.accepter.dataTail = NULL;
    V4vAddRefContext(pde, ctx);
    V4vAddRefRing(pde, ctx->ringObject);
    actx->u.accepter.listenerContext = ctx;
    actx->ringObject = ctx->ringObject;

    // Now it becomes an accepter type for ever more
    InterlockedExchange(&actx->type, XENV4V_TYPE_ACCEPTER);

    // After this transition, we will wait for a SYN (may be one in the queue already).
    InterlockedExchange(&actx->state, XENV4V_STATE_ACCEPTING);

    // Flag it
    irp->Tail.Overlay.DriverContext[0] = 
        (PVOID)(ULONG_PTR)(XENV4V_PEEK_STREAM|XENV4V_PEEK_ACCEPT|XENV4V_PEEK_IOCTL);

    // Always queue it to the back and marks it pending. If it fails to be queued then
    // the user mode call will close the new handle.
    status = IoCsqInsertIrpEx(&pde->csqObject, irp, NULL, &ins);
    if (NT_SUCCESS(status)) {
        status = STATUS_PENDING;
        // Drive any accepts
        V4vDoAccepts(pde, ctx);
    }

    return status;
}
Exemplo n.º 24
0
NTSTATUS
InterruptCreate (
    _In_ WDFDEVICE Device,
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  InterruptResourceRaw,
    _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR  InterruptResourceTranslated
    )
/*++

Routine Description:

    Helper function to create device's WDFINTERRUPT object and any other 
    needed WDF resources that the interrupt needs for proper functioning.

    It assumes the first interrupt resource with which this is invoked is 
    the device interrupt, and the second is the attach/detach interrupt.

Arguments:

    Device - Wdf device object corresponding to the FDO

    InterruptResourceRaw -  Raw resource for the interrupt

    InterruptResourceTranslated - Translated resource for the interrupt

Return Value:

    Appropriate NTSTATUS value

--*/
{
    NTSTATUS Status;
    WDF_INTERRUPT_CONFIG InterruptConfig;
    PCONTROLLER_CONTEXT ControllerContext;
    WDF_OBJECT_ATTRIBUTES Attributes;
    WDFINTERRUPT* InterruptToCreate;

    TraceEntry();

    PAGED_CODE();

    ControllerContext = DeviceGetControllerContext(Device);

    WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);

    if (ControllerContext->DeviceInterrupt == NULL) {
        WDF_INTERRUPT_CONFIG_INIT(
            &InterruptConfig, 
            DeviceInterrupt_EvtInterruptIsr,
            DeviceInterrupt_EvtInterruptDpc);

        WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(
            &Attributes, 
            DEVICE_INTERRUPT_CONTEXT);

        InterruptToCreate = &ControllerContext->DeviceInterrupt;

    } else if (ControllerContext->AttachDetachInterrupt == NULL) {
        WDF_INTERRUPT_CONFIG_INIT(
            &InterruptConfig,
            DeviceInterrupt_EvtAttachDetachInterruptIsr,
            DeviceInterrupt_EvtInterruptDpc);
        InterruptConfig.CanWakeDevice = TRUE;
        InterruptConfig.PassiveHandling = TRUE;
        InterruptToCreate = &ControllerContext->AttachDetachInterrupt;

    } else {
        TraceWarning("Other interrupt resource [0X%X] is detected and is being"
                        " ignored", InterruptResourceRaw->u.Interrupt.Vector);
        Status = STATUS_SUCCESS;
        goto End;
    }
    
    InterruptConfig.InterruptRaw = InterruptResourceRaw;
    InterruptConfig.InterruptTranslated = InterruptResourceTranslated;

    Status = WdfInterruptCreate(
                 Device,
                 &InterruptConfig,
                 &Attributes,
                 InterruptToCreate);
    CHK_NT_MSG(Status, "Failed to create Device interrupt");

End:
    TraceExit();
    return Status;
}
Exemplo n.º 25
0
static NTSTATUS
V4vCtrlBind(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx, V4V_BIND_VALUES *bvs)
{
    NTSTATUS            status = STATUS_SUCCESS;
    LONG                val;
    KLOCK_QUEUE_HANDLE  lqh;
    XENV4V_RING        *robj;
    uint32_t            port;

    // Use a simple guard variable to enforce the state transition order
    val = InterlockedExchangeAdd(&ctx->state, 0);
    if (val != XENV4V_STATE_IDLE) {
        TraceWarning(("state not IDLE, cannot complete bind request\n"));
        return STATUS_INVALID_DEVICE_REQUEST;
    }

    ASSERT(ctx->ringObject == NULL);

    do {
        if ((bvs->ringId.addr.domain != V4V_DOMID_NONE)&&
            (bvs->ringId.addr.domain != DOMID_INVALID_COMPAT)) {
            TraceWarning(("failure - ring ID domain must be V4V_DOMID_NONE - value: 0x%x\n",
                         bvs->ringId.addr.domain));
            status = STATUS_INVALID_PARAMETER;
            break;
        }

        robj = V4vAllocateRing(ctx->ringLength);
        if (robj == NULL) {    
            TraceError(("failed to allocate the ring\n"));
            status = STATUS_NO_MEMORY;
            break;
        }
        robj->ring->id = bvs->ringId;

        // Have to grab this outside of lock at IRQL PASSIVE    
        port = V4vRandomPort(pde);

        // Lock this section since we access the list
        KeAcquireInStackQueuedSpinLock(&pde->ringLock, &lqh);

        if (robj->ring->id.addr.port == V4V_PORT_NONE) {
            robj->ring->id.addr.port = V4vSparePortNumber(pde, port);
        }
        else if (V4vRingIdInUse(pde, &robj->ring->id)) {
            KeReleaseInStackQueuedSpinLock(&lqh);
            TraceWarning(("ring ID already in use, cannot bind\n"));
            status = STATUS_INVALID_DEVICE_REQUEST;
            break;
        }
        
        // Now register the ring.
        status = V4vRegisterRing(robj);
        if (!NT_SUCCESS(status)) {
            KeReleaseInStackQueuedSpinLock(&lqh);
            TraceError(("failed in register ring hypercall - error: 0x%x\n", status));
            break;
        }
        robj->registered = TRUE;

        // Link it to the main list and set our pointer to it
        V4vLinkToRingList(pde, robj);
        ctx->ringObject = robj;

        KeReleaseInStackQueuedSpinLock(&lqh);

        InterlockedExchange(&ctx->type, XENV4V_TYPE_DATAGRAM);
        InterlockedExchange(&ctx->state, XENV4V_STATE_BOUND);        
    } while (FALSE);

    if (!NT_SUCCESS(status)) {
        // If it failed, undo everything - this will remove it from the list
        if (ctx->ringObject != NULL) {
            V4vReleaseRing(pde, ctx->ringObject);
        }
    }

    return status;
}
Exemplo n.º 26
0
/* We've received a csum_blank packet, but we don't want to let
   Windows see it like.  Calculate the checksum and dump it in the
   packet.  This only works for TCP and UDP on IPv4; on anything else
   it's a no-op. */
static VOID
FixupChecksum(PNDIS_PACKET packet)
{
    PNDIS_BUFFER pbuf;
    PNDIS_BUFFER pbuf_next;
    UINT bufLength;
    UINT len;
    struct ethhdr *eh;
    struct iphdr *ih;
    uint32_t csum_accumulator;
    uint32_t *ptr;
    uint16_t *csum_field;

    NdisQueryPacket(packet, NULL, NULL, &pbuf, NULL);
    NdisQueryBufferSafe(pbuf, &eh, &bufLength, NormalPagePriority);
    if (!eh || bufLength < sizeof(*eh))
        return;
    if (eh->proto != TPID_IPV4) {
        static BOOLEAN warned;
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation on non-IP ethernet prototocol %x!\n", eh->proto));
            warned = TRUE;
        }
        return;
    }
    ih = (struct iphdr *)(eh + 1);
    bufLength -= sizeof(*eh);
    if (bufLength < sizeof(*ih) ||
        bufLength < (UINT)(ih->len_version & 0x0f) * 4)
        return;
    ptr = (uint32_t *)((ULONG_PTR)ih + (ih->len_version & 0x0f)*4);
    len = ntohs(ih->tot_len) - (ih->len_version & 0x0f) * 4;

    bufLength -= (ih->len_version & 0x0f) * 4;
    if (bufLength > len)
        bufLength = len;

    if (ih->proto == IPPROTO_UDP) {
        if (bufLength < sizeof(struct udphdr))
            return;
        csum_field = &((struct udphdr *)ptr)->checksum;
    } else if (ih->proto == IPPROTO_TCP) {
        if (bufLength < sizeof(struct tcphdr))
            return;
        csum_field = &((struct tcphdr *)ptr)->checksum;
    } else {
        static BOOLEAN warned;
        /* Uh oh: don't know what this protocol is, so can't do
           checksum calculation for it. */
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation for unknown protocol %d!\n",
                          ih->proto));
            warned = TRUE;
        }
        return;
    }

    if (ih->proto == IPPROTO_TCP) {
        struct tcp_pseudo_header tph;
        uint16_t csum;

        tph.saddr = ih->src;
        tph.daddr = ih->dest;
        tph.mbz = 0;
        tph.ptcl = IPPROTO_TCP;
        tph.length = htons((uint16_t)len);

        csum_accumulator = acc_ip_csum(&tph, sizeof(tph), 0);
        csum = fold_ip_csum(csum_accumulator);

        if (*csum_field != csum)
            TraceWarning(("invlid pseudo header checksum: expected %04x, found %04x\n", csum, *csum_field));

        *csum_field = csum;
    }

    csum_accumulator = acc_ip_csum(ptr, bufLength, 0);
    len -= bufLength;

    while (len) {
        NdisGetNextBuffer(pbuf, &pbuf_next);
        if (pbuf_next == NULL)
            break;
        pbuf = pbuf_next;
        NdisQueryBufferSafe(pbuf, &ptr, &bufLength, NormalPagePriority);

        /* The buffer is already mapped into our RX buffer pool, so we
           should always be able to get a virtual address for it. */
        XM_ASSERT(ptr != NULL);

        if (bufLength > len)
            bufLength = len;

        csum_accumulator = acc_ip_csum(ptr, bufLength, csum_accumulator);
        len -= bufLength;
    }

    *csum_field = ~fold_ip_csum(csum_accumulator);
}
Exemplo n.º 27
0
// This the completion routine of the continuous reader. This can called concurrently on multiprocessor system if there are
// more than one readers configured. So make sure to protect access to global resources.
//
void HidFx2EvtUsbInterruptPipeReadComplete(
    WDFUSBPIPE  hPipe,
    WDFMEMORY   hBuffer,
    size_t      cNumBytesTransferred,
    WDFCONTEXT  pContext
   )
{
    PDEVICE_EXTENSION   pDevContext = pContext;
    BOOLEAN             fInTimerQueue;
    unsigned char       *pbSwitchState = NULL;
    unsigned char       bCurrentSwitchState = 0;
    unsigned char       bPrevSwitchState = 0;
    unsigned char       bToggledSwitch = 0;

    UNREFERENCED_PARAMETER(cNumBytesTransferred);
    UNREFERENCED_PARAMETER(hPipe);

    TraceVerbose(DBG_INIT, "(%!FUNC!) Enter\n");

    // Interrupt endpoints sends switch state when first started  or when resuming from suspend.
    // We need to ignore that data since user did not change the switch state.
    if (pDevContext->fIsPowerUpSwitchState)
    {
        pDevContext->fIsPowerUpSwitchState = FALSE;
        TraceInfo(DBG_INIT, "(%!FUNC!) Dropping interrupt message since received during powerup/resume\n");
        return;
    }


    // Make sure that there is data in the read packet. 
    // Depending on the device specification, it is possible for it to return a 0 length read in certain conditions.
    if (cNumBytesTransferred == 0)
    {
        TraceWarning(DBG_INIT, "(%!FUNC!) Zero length read occured on the Interrupt Pipe's Continuous Reader\n");
        return;
    }

    pbSwitchState = WdfMemoryGetBuffer(hBuffer, NULL);
    bCurrentSwitchState = ~(*pbSwitchState);                // switchs are inverted on hardware boards
    bCurrentSwitchState &= RADIO_SWITCH_BUTTONS_BIT_MASK;   //Mask off everything except the actual radio switch bit
    bPrevSwitchState = pDevContext->bCurrentSwitchState;

    if (bPrevSwitchState ^ bCurrentSwitchState) // make sure we toggled the radio switch
    {
        switch(pDevContext->driverMode)
        {
        // If it's a slider switch we want  0->1 and 1->0 transitions.
        case DM_SLIDER_SWITCH:
        case DM_SLIDER_SWITCH_AND_LED:
            bToggledSwitch = bCurrentSwitchState;
            // A timer is started for 10 ms everytime there is a switch toggled
            fInTimerQueue = WdfTimerStart(pDevContext->hDebounceTimer, WDF_REL_TIMEOUT_IN_MS(SWITCHPACK_DEBOUNCE_TIME));
            TraceInfo(DBG_INIT, "(%!FUNC!) Debounce Timer started. Existing -%!bool!\n", fInTimerQueue);
            break;
        //If it's a button so we only report 0->1 transitions
        case DM_BUTTON:
        case DM_BUTTON_AND_LED:
            bToggledSwitch = (bPrevSwitchState ^ bCurrentSwitchState) & bCurrentSwitchState;
            if (bToggledSwitch != 0)
            {
                // A timer is started for 10 ms everytime there is a switch toggled on
                fInTimerQueue = WdfTimerStart(pDevContext->hDebounceTimer, WDF_REL_TIMEOUT_IN_MS(SWITCHPACK_DEBOUNCE_TIME));
                TraceInfo(DBG_INIT, "(%!FUNC!) Debounce Timer started. Existing -%!bool!\n", fInTimerQueue);
            }
            break;
        // Ignore button presses if LED only
        case DM_LED_ONLY:
        default:
            break;
        }

        // Store switch state in device context
        pDevContext->bCurrentSwitchState = bCurrentSwitchState;
        pDevContext->bLatestToggledSwitch = bToggledSwitch;
    }
    else
    {
        TraceInfo(DBG_INIT, "(%!FUNC!) Not a radio switch toggle\n");
    }
    TraceInfo(DBG_INIT, "(%!FUNC!) Switch 0x%x, prevSwitch:0x%x, X0R:0x%x\n", bCurrentSwitchState, bPrevSwitchState, bToggledSwitch);

    TraceVerbose(DBG_INIT, "(%!FUNC!) Exit\n");
}
Exemplo n.º 28
0
VOID
ReceiverHandleNotification(
    IN  PRECEIVER Receiver
)
/*++
Routine Description:

    Interrupt handler for receive processing
    Put the received packets into an array and call NdisMIndicateReceivePacket
    If we run low on RFDs, allocate another one

Arguments:

    Adapter     Pointer to our adapter

Return Value:

    None
    
--*/
{
    PADAPTER        Adapter = Receiver->Common.Adapter;
    RING_IDX        prod;
    int             more_work;
    PNDIS_PACKET    PacketArray[XENNET_DEF_RFDS];
    NDIS_STATUS     PacketStatus[XENNET_DEF_RFDS];
    UINT            PacketCount;

    if (!RING_HAS_UNCONSUMED_RESPONSES(&Receiver->Common.Ring))
        return;

    NdisDprAcquireSpinLock(&Receiver->Common.Lock);
    if (Receiver->Common.Adapter->media_disconnect) {
        NdisDprReleaseSpinLock(&Receiver->Common.Lock);
        return;
    }

    if (__RING_IDX_DIFFERENCE(Receiver->Common.Ring.req_prod_pvt,
                              Receiver->Common.Ring.sring->rsp_prod) >
        NET_RX_RING_SIZE)
        TraceWarning(("Strange: rsp_prod ahead of req_prod (%d vs %d (s %d))\n",
                      Receiver->Common.Ring.sring->rsp_prod,
                      Receiver->Common.Ring.req_prod_pvt,
                      Receiver->Common.Ring.sring->req_prod));

    PacketCount = 0;

 top:
    prod = Receiver->Common.Ring.sring->rsp_prod;
    XsMemoryBarrier();
    while (!RING_IDXS_EQ(Receiver->Common.Ring.rsp_cons, prod)) {
        PNDIS_PACKET packet;
        ULONG totFrags;
        NDIS_STATUS status;

        status = ReceiverReceivePacket(Receiver, &packet, &totFrags);
        if (status != NDIS_STATUS_SUCCESS)
            continue;

        TraceProfile(("%s(%s, %p)\n", __FUNCTION__, Adapter->XenbusPrefix, packet));

        // See http://msdn.microsoft.com/en-us/library/ms797610.aspx
        if (Receiver->LowResources == 2 ||
            (Receiver->LowResources == 1 && totFrags > 1)) {
            status = NDIS_STATUS_RESOURCES;
            NDIS_SET_PACKET_STATUS(packet, status);
        }

        PacketArray[PacketCount] = packet;
        PacketStatus[PacketCount] = status;
        PacketCount++;

        if (PacketCount == XENNET_DEF_RFDS) {
            ULONG Index;

            Receiver->Common.Frames += PacketCount;
            Receiver->nRxInNdis += PacketCount;

            if (Receiver->nRxInNdis >= Receiver->nRxInNdisMax)
                Receiver->nRxInNdisMax = Receiver->nRxInNdis;

            NdisDprReleaseSpinLock(&Receiver->Common.Lock);
            NdisMIndicateReceivePacket(
                Receiver->Common.Adapter->AdapterHandle,
                PacketArray,
                PacketCount);
            NdisDprAcquireSpinLock(&Receiver->Common.Lock);

            for (Index = 0; Index < PacketCount; Index++) {
                if (PacketStatus[Index] == NDIS_STATUS_RESOURCES) {
                    ReceiverReleasePacket(Receiver, PacketArray[Index]);
                    Receiver->nRxInNdis--;
                } else {
                   XM_ASSERT(PacketStatus[Index] == NDIS_STATUS_SUCCESS);
                }
            }
            PacketCount = 0;

            ReceiverSwizzle(Receiver);
        }
    }
    RING_FINAL_CHECK_FOR_RESPONSES(&Receiver->Common.Ring, more_work);
    if (more_work)
        goto top;

    if (PacketCount != 0) {
        ULONG Index;

        Receiver->Common.Frames += PacketCount;
        Receiver->nRxInNdis += PacketCount;

        if (Receiver->nRxInNdis >= Receiver->nRxInNdisMax)
            Receiver->nRxInNdisMax = Receiver->nRxInNdis;

        NdisDprReleaseSpinLock(&Receiver->Common.Lock);
        NdisMIndicateReceivePacket(
            Receiver->Common.Adapter->AdapterHandle,
            PacketArray,
            PacketCount);
        NdisDprAcquireSpinLock(&Receiver->Common.Lock);

        for (Index = 0; Index < PacketCount; Index++) {
            if (PacketStatus[Index] == NDIS_STATUS_RESOURCES) {
                ReceiverReleasePacket(Receiver, PacketArray[Index]);
                Receiver->nRxInNdis--;
            } else {
                XM_ASSERT(PacketStatus[Index] == NDIS_STATUS_SUCCESS);
            }
        }
        PacketCount = 0;
    }

    // Swizzle unconditionally to make sure we replenish the ring even if
    // nothing was passed to NDIS.
    ReceiverSwizzle(Receiver);

    NdisDprReleaseSpinLock(&Receiver->Common.Lock);
    /* XXX Should maybe adjust size of packet pool from here. */
}
Exemplo n.º 29
0
BOOLEAN NTAPI XenGfxVbeSetMode(USHORT ModeNumber)
{
    const MODE_INFO_ITEM *pCurrentMode;
    BOOLEAN UsingLFB;
    USHORT FlagLFB, FlagNoClear;
    USHORT StrideAlign;

    TraceVerbose(("====> '%s'.\n", __FUNCTION__));

    if (!g_VbeInfoInitialized) {
        return FALSE;
    }

    ModeNumber &= 0x1FF;

    if (ModeNumber < VBE_MODE_VESA_DEFINED) {
        TraceError(("Could not set non-VBE mode!\n"));
        return FALSE;
    }

    // Get mode attributes
    UsingLFB = ((ModeNumber & VBE_MODE_LINEAR_FRAME_BUFFER) == VBE_MODE_LINEAR_FRAME_BUFFER) ? TRUE : FALSE;
    FlagLFB = (UsingLFB) ? VBE_DISPI_LFB_ENABLED : 0;
    FlagNoClear = ((ModeNumber & VBE_MODE_PRESERVE_DISPLAY_MEMORY) == VBE_MODE_PRESERVE_DISPLAY_MEMORY) ? VBE_DISPI_NOCLEARMEM : 0;

    pCurrentMode = XenGfxFindMode(ModeNumber, UsingLFB);
    if (pCurrentMode == NULL) {
        TraceWarning(("VBE mode %04x NOT FOUND (and not set)??\n", ModeNumber));
        return FALSE;
    }
    
    TraceVerbose(("Set VBE mode 0x%04x (xres=0x%04x / yres=0x%04x / bpp=0x%02x) found.\n",
                 pCurrentMode->ModeNumber, pCurrentMode->ModeInfo.XResolution,
                 pCurrentMode->ModeInfo.YResolution, pCurrentMode->ModeInfo.BitsPerPixel));

    // Need to lock here - this is going to change the mode and the state of the
    // emulated video card.
    XenGfxInt10SpinLock((UCHAR*)VGA_PORT_RANGE_BASE);

    // Disable while setting VESA modes.
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_ENABLE);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_DATA, VBE_DISPI_DISABLED);

    // N.B. don't need to worry about setting up 4 BPP modes for XenVesa

    // Set BPP, X and Y res, stride, bank
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_BPP);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_DATA, pCurrentMode->ModeInfo.BitsPerPixel);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_XRES);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_DATA, pCurrentMode->ModeInfo.XResolution);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_YRES);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_DATA, pCurrentMode->ModeInfo.YResolution);

    //New feature...
    StrideAlign = XenGfxVbeGetAlignedStride(pCurrentMode->ModeInfo.BytesPerScanLine);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_STRIDE);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_DATA, StrideAlign);

    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_BANK);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_DATA, 0);

    // Store some of the VGA port values as in the vBIOS. Note we only need to write our shadow
    // ports at this point since we switched to exclusive shadow use.
    WRITE_PORT_USHORT((USHORT*)VGA_PORT_VBE_MODE, ModeNumber);
    WRITE_PORT_USHORT((USHORT*)VGA_PORT_VIDEO_CTL, (0x60|FlagNoClear));

    // Enable new VESA mode
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_INDEX, VBE_DISPI_INDEX_ENABLE);
    WRITE_PORT_USHORT((USHORT*)VBE_PORT_DATA, VBE_DISPI_ENABLED|FlagLFB|FlagNoClear);

    XenGfxInt10SpinUnlock((UCHAR*)VGA_PORT_RANGE_BASE);

    TraceVerbose(("<==== '%s'.\n", __FUNCTION__));

    return TRUE;
}