Example #1
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;
}
Example #2
0
static NTSTATUS
redirect_irp_completion(PDEVICE_OBJECT dev_obj, PIRP irp, PVOID ctxt)
{
    IO_STACK_LOCATION *const isl = IoGetCurrentIrpStackLocation(irp);
    struct scsifilt *const sf = get_scsifilt(dev_obj);
    SCSI_REQUEST_BLOCK *const new_srb = isl->Parameters.Scsi.Srb;
    SCSI_REQUEST_BLOCK *const srb = new_srb->OriginalRequest;
    MDL *const mdl = irp->MdlAddress;
    void *const buf = new_srb->DataBuffer;

    UNREFERENCED_PARAMETER(ctxt);

    srb->SrbStatus = new_srb->SrbStatus;
    srb->ScsiStatus = new_srb->ScsiStatus;
    memcpy(srb->DataBuffer, buf, srb->DataTransferLength);

    IoFreeIrp(irp);
    IoFreeMdl(mdl);
    ExFreePool(buf);
    XmFreeMemory(new_srb);

    queue_srb_for_completion(sf, srb);

    return STATUS_MORE_PROCESSING_REQUIRED;
}
Example #3
0
ULONG
XenLowerInterfaceVersion(
    PXEN_LOWER XenLower)
{
    NTSTATUS status;
    PCHAR vstr;
    int version;

	vstr = XenLowerReadXenstoreValue(XenLower->BackendPath, "version");
    if (vstr == NULL)
    {
        TraceError((__FUNCTION__\
            ": XenLowerReadXenstoreValue() failed to return the vusb version.\n"));
        return 0;
    }

    sscanf_s(vstr, "%d", &version);
    XmFreeMemory(vstr);

    // Need to now write the version we support to the frontend
    status = xenbus_printf(XBT_NIL, XenLower->FrontendPath,
        "version", "%d", XEN_LOWER_INTERFACE_VERSION);
    if (!NT_SUCCESS(status))
    {
        TraceError((__FUNCTION__\
            ": xenbus_printf(frontend/version) failed.\n"));
        return 0;
    }

    TraceInfo((__FUNCTION__
        ": Read backend version: %d  -  Wrote frontend version: %d\n",
        version, XEN_LOWER_INTERFACE_VERSION));

    return (ULONG)version;
}
Example #4
0
/* Write a grant ref and ec port to xenstore in a transaction for whatever
 * your pThing is. Also some non-transaction read/write stuff.
 */
static NTSTATUS
GrantAndEventChannelInATransaction(CHAR *pFrontendPath, struct THING *pThing)
{
    NTSTATUS Status;
    CHAR *pMyData;
    xenbus_transaction_t Xbt;
    
    do {
        xenbus_transaction_start(&Xbt);
        xenbus_write_grant_ref(Xbt, pFrontendPath, "ring-ref",
                               pThing->RingGrantRef);

        xenbus_write_evtchn_port(Xbt, pFrontendPath, "event-channel",
                                 pThing->EvtchnPort);

        Status = xenbus_transaction_end(Xbt, 0);

    } while (Status == STATUS_RETRY);

    if (Status != STATUS_SUCCESS) {
        DbgPrint("Failed to end transaction, 0x%08x.\n", Status);
        /* Handle failure */
    }

    /* A write and read w/o a transaction */
    xenbus_write(XBT_NIL, "drivers/mydriver", "1.2.3.4");

    Status = xenbus_read(XBT_NIL, "drivers/mydriver/mydata", &pMyData);
    if (NT_SUCCESS(Status)) {
        DbgPrint("Read MyData: %s\n", pMyData);
        XmFreeMemory(pMyData);
    }

    /* ... */
}
Example #5
0
struct xm_thread *
XmSpawnThread(NTSTATUS (*cb)(struct xm_thread *xt, void *d), void *d)
{
    struct xm_thread *work;
    NTSTATUS stat;
    HANDLE tmpHandle;

    work = XmAllocateMemory(sizeof(*work));
    if (!work) return NULL;
    work->exit = FALSE;
    KeInitializeEvent(&work->event, NotificationEvent, FALSE);
    work->cb = cb;
    work->data = d;
    stat = PsCreateSystemThread(&tmpHandle, THREAD_ALL_ACCESS, NULL,
                                INVALID_HANDLE_VALUE, NULL, xm_thread_func,
                                work);
    if (!NT_SUCCESS(stat)) {
        XmFreeMemory(work);
        return NULL;
    }
    stat = ObReferenceObjectByHandle(tmpHandle, SYNCHRONIZE, NULL,
                                     KernelMode, &work->thread,
                                     NULL);
    ZwClose(tmpHandle);
    if (!NT_SUCCESS(stat)) {
        /* We can't reliably kill the thread in this case, and
           therefore can't release memory.  Instruct it to exit soon
           and hope for the best. */
        work->exit = TRUE;
        KeSetEvent(&work->event, IO_NO_INCREMENT, FALSE);
        return NULL;
    }

    return work;
}
Example #6
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;
}
Example #7
0
static PCHAR
XenLowerReadXenstoreValue(
    PCHAR Path,
    PCHAR Value)
{
    ULONG plen, vlen;
    PCHAR path;
    PCHAR res = NULL;
    NTSTATUS status;

    plen = (ULONG)strlen(Path);
    vlen = (ULONG)strlen(Value);
    path = (PCHAR)XmAllocateMemory(plen + vlen + 2);
    if (path == NULL)
    {
        return NULL;
    }

    memcpy(path, Path, plen);
    path[plen] = '/';
    memcpy(path + plen + 1, Value, vlen + 1);
    status = xenbus_read(XBT_NIL, path, &res);
    XmFreeMemory(path);
    if (!NT_SUCCESS(status))
    {
        return NULL;
    }

    return res;
}
Example #8
0
void
XmKillThread(struct xm_thread *t)
{
    if (!t)
        return;
    TraceDebug (("Killing thread %p.\n", t));
    XM_ASSERT(KeGetCurrentThread() != t->thread);
    t->exit = TRUE;
    KeSetEvent(&t->event, IO_NO_INCREMENT, FALSE);
    KeWaitForSingleObject(t->thread, Executive, KernelMode, FALSE,
                          NULL);
    ObDereferenceObject(t->thread);
    XmFreeMemory(t);
}
Example #9
0
BOOLEAN
XenLowerInit(
    PXEN_LOWER XenLower,
    PVOID XenUpper,
    PDEVICE_OBJECT Pdo)
{
    PCHAR path;
    NTSTATUS status;

    XenLower->XenUpper = XenUpper;
    XenLower->Pdo = Pdo;

    //
    // 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())
    {
        TraceError((__FUNCTION__ ": xenbus_await_initialisation() failed?\n"));
        return FALSE;
    }

    path = xenbus_find_frontend(Pdo);
    if (path == NULL)
    {
        TraceError((__FUNCTION__
            ": xenbus_find_frontend() failed to return the front end path, fatal.\n"));
        return FALSE;
    }
    status = RtlStringCchCopyA(XenLower->FrontendPath,
        sizeof(XenLower->FrontendPath),
        path);
    XmFreeMemory(path);
    if (status != STATUS_SUCCESS)
    {
        XenLower->FrontendPath[0] = 0;
        TraceError((__FUNCTION__ ": Failed to copy front end path - status: 0x%x\n", status));
        return FALSE;
    }

    return TRUE;
}
Example #10
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;
}
Example #11
0
BOOLEAN
XenLowerGetOnline(
    PVOID Context)
{
    PXEN_LOWER XenLower = (PXEN_LOWER)Context;
    PCHAR sstr;
    int state;

    sstr = XenLowerReadXenstoreValue(XenLower->BackendPath, "online");
    if (sstr == NULL)
    {
        TraceError((__FUNCTION__
            ": XenLowerReadXenstoreValue() failed to return the back end state.\n"));
        return FALSE;
    }

    sscanf_s(sstr, "%d", &state);
    XmFreeMemory(sstr);

    return (state == 1);
}
Example #12
0
ULONG
XenLowerGetBackendState(
    PVOID Context)
{
    PXEN_LOWER XenLower = (PXEN_LOWER)Context;
    PCHAR sstr;
    int state;

    sstr = XenLowerReadXenstoreValue(XenLower->BackendPath, "state");
    if (sstr == NULL)
    {
        TraceError((__FUNCTION__
            ": XenLowerReadXenstoreValue() failed to return the back end state.\n"));
        return XenbusStateUnknown;
    }

    sscanf_s(sstr, "%d", &state);
    XmFreeMemory(sstr);

    return (ULONG)state;
}
Example #13
0
static NTSTATUS NTAPI
V4vDispatchPnP(PDEVICE_OBJECT fdo, PIRP irp)
{
    NTSTATUS           status = STATUS_SUCCESS;
    PIO_STACK_LOCATION isl = IoGetCurrentIrpStackLocation(irp);
    PXENV4V_EXTENSION  pde = V4vGetDeviceExtension(fdo);
    KEVENT             kev;

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

    TraceVerbose((" =PnP= 0x%x\n", isl->MinorFunction));

    status = IoAcquireRemoveLock(&pde->removeLock, irp);
    if (!NT_SUCCESS(status)) {
        TraceError(("failed to acquire IO lock - error: 0x%x\n", status));
        return V4vSimpleCompleteIrp(irp, status);
    }

    switch (isl->MinorFunction) {
    case IRP_MN_START_DEVICE:
        KeInitializeEvent(&kev, NotificationEvent, FALSE);
        // Send the start down and wait for it to complete
        IoCopyCurrentIrpStackLocationToNext(irp);
        IoSetCompletionRoutine(irp, V4vStartDeviceIoCompletion, &kev, TRUE, TRUE, TRUE);
        status = IoCallDriver(pde->ldo, irp);
        if (status == STATUS_PENDING) {
            // Wait for everything underneath us to complete
            TraceVerbose(("Device start waiting for lower device.\n"));
            KeWaitForSingleObject(&kev, Executive, KernelMode, FALSE, NULL);
            TraceVerbose(("Device start wait finished.\n"));
        }

        status = irp->IoStatus.Status;
        if (!NT_SUCCESS(status)) {
            TraceError(("Failed to start lower drivers: %x.\n", status));
            IoCompleteRequest(irp, IO_NO_INCREMENT);
            break;
        }

        status = STATUS_SUCCESS;

        // Connect our interrupt (ec).
        status = V4vInitializeEventChannel(fdo);
        if (NT_SUCCESS(status)) {
            InterlockedExchange(&pde->state, XENV4V_DEV_STARTED);
        }
        else {
            TraceError(("failed to initialize event channel - error: 0x%x\n", status));
        }

        irp->IoStatus.Status = status;
        IoCompleteRequest(irp, IO_NO_INCREMENT);
        break;
    case IRP_MN_STOP_DEVICE:
        // Stop our device's IO processing
        V4vStopDevice(fdo, pde);

        // Pass it down
        irp->IoStatus.Status = STATUS_SUCCESS;
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);
        break;        
    case IRP_MN_REMOVE_DEVICE:
        // Stop our device's IO processing
        V4vStopDevice(fdo, pde);

        // Cleanup anything here that locks for IO
        IoReleaseRemoveLockAndWait(&pde->removeLock, irp);

        // Pass it down first
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);

        // Then detach and cleanup our device
        xenbus_change_state(XBT_NIL, pde->frontendPath, "state", XENBUS_STATE_CLOSED);
        IoDetachDevice(pde->ldo);
        ExDeleteNPagedLookasideList(&pde->destLookasideList);
        XmFreeMemory(pde->frontendPath);
        IoDeleteSymbolicLink(&pde->symbolicLink);
        IoDeleteDevice(fdo);
        InterlockedAnd(&g_deviceCreated, 0);
        return status;
    default:
        // Pass it down
        TraceVerbose(("IRP_MJ_PNP MinorFunction %d passed down\n", isl->MinorFunction));
        IoSkipCurrentIrpStackLocation(irp);
        status = IoCallDriver(pde->ldo, irp);
    };

    // Everybody but REMOVE
    IoReleaseRemoveLock(&pde->removeLock, irp); 

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

    return status;
}
Example #14
0
/* We've bound the scsifilt instance to a xenvbd instance, and we've
   disconnected xenvbd from the shared ring.  Connect scsifilt. */
NTSTATUS
connect_scsifilt_with_token(struct scsifilt *sf, SUSPEND_TOKEN token)
{
    XENBUS_STATE state;
    blkif_sring_t *ring_shared;
    NTSTATUS status;
    KIRQL irql;

    if (sf->backend_path != NULL) {
        TraceVerbose(("Releasing old backend path (%p)\n", sf->backend_path));

        XmFreeMemory(sf->backend_path);
        sf->backend_path = NULL;
    }

    if (sf->ring_shared != NULL) {
        TraceVerbose(("Releasing old shared ring (%p)\n", sf->ring_shared));

        XmFreeMemory(sf->ring_shared);
        sf->ring_shared = NULL;
        sf->ring.sring = NULL;
    }

    find_backend_handle(sf);

    status = STATUS_UNSUCCESSFUL;
    sf->backend_path = get_backend_path(sf, token);
    if (sf->backend_path == NULL)
        goto fail1;

    sf->target_resume(sf->target_id, token);

    if (sf->stopped) {
        sf->target_start(sf->target_id, sf->backend_path, token);
        sf->stopped = FALSE;
    }

    state = XenbusWaitForBackendStateChange(sf->backend_path,
                                            null_XENBUS_STATE(),
                                            NULL,
                                            token);
    if (!same_XENBUS_STATE(state, XENBUS_STATE_INITWAIT))
        goto fail2;

    probe_backend_capabilities(sf);

    status = STATUS_NO_MEMORY;
    ring_shared = XmAllocateZeroedMemory(PAGE_SIZE << sf->ring_order);
    if (ring_shared == NULL)
        goto fail3;

    KeAcquireSpinLock(&sf->ring_lock, &irql);
    sf->ring_shared = ring_shared;
    SHARED_RING_INIT(sf->ring_shared);
    FRONT_RING_INIT(&sf->ring, sf->ring_shared, PAGE_SIZE << sf->ring_order);
    KeReleaseSpinLock(&sf->ring_lock, irql);

    grant_ring(sf);

    status = open_evtchn(sf);
    if (!NT_SUCCESS(status))
        goto fail4;

    do {
        xenbus_transaction_t xbt;

        xenbus_transaction_start(&xbt);

        xenbus_write_evtchn_port(xbt,
                                 sf->frontend_path,
                                 "event-channel",
                                 sf->evtchn_port);

        if (sf->single_page) {
            XM_ASSERT3U(sf->ring_order, ==, 0);

            TraceNotice(("%s: using single page handshake\n", sf->frontend_path));

            /* single page handshake */
            xenbus_write_grant_ref(xbt,
                                   sf->frontend_path,
                                   "ring-ref",
                                   sf->ring_gref[0]);
        } else {
            int i;

            TraceNotice(("%s: using multi-page handshake\n", sf->frontend_path));

            xenbus_printf(xbt, sf->frontend_path, "ring-page-order", "%u",
                          sf->ring_order);

            for (i = 0; i < (1 << sf->ring_order); i++) {
                char buffer[10];

                Xmsnprintf(buffer, sizeof(buffer), "ring-ref%1u", i);
                xenbus_write_grant_ref(xbt, sf->frontend_path, buffer,
                                       sf->ring_gref[i]);
            }
        }

        xenbus_printf(xbt, sf->frontend_path, "protocol", "x86_32-abi");
        xenbus_write_feature_flag(xbt, sf->frontend_path, "feature-surprise-remove",
                                  TRUE);
        xenbus_write_feature_flag(xbt, sf->frontend_path, "feature-online-resize",
                                  TRUE);
        xenbus_change_state(xbt, sf->frontend_path, "state",
                            XENBUS_STATE_INITIALISED);

        status = xenbus_transaction_end(xbt, 0);
    } while (status == STATUS_RETRY);
Example #15
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);
}
Example #16
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;
}
Example #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;
}