VOID XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context) { ULONG ActiveProcessorCount; ULONG i; highsync_info_t *highsync_info; KIRQL old_irql; UNREFERENCED_PARAMETER(context); FUNCTION_ENTER(); highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG); RtlZeroMemory(highsync_info, sizeof(highsync_info_t)); KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE); highsync_info->function0 = function0; highsync_info->functionN = functionN; highsync_info->context = context; highsync_info->sync_level = HIGH_LEVEL; #if (NTDDI_VERSION >= NTDDI_WINXP) ActiveProcessorCount = (ULONG)KeNumberProcessors; #else ActiveProcessorCount = (ULONG)*KeNumberProcessors; #endif /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */ KeRaiseIrql(highsync_info->sync_level, &old_irql); highsync_info->do_spin = TRUE; for (i = 0; i < ActiveProcessorCount; i++) { if (i == 0) KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info); else KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info); KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i); KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance); KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i)); KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL); } KdPrint((__DRIVER_NAME " All Dpc's queued\n")); KeMemoryBarrier(); KeLowerIrql(old_irql); KdPrint((__DRIVER_NAME " Waiting for highsync_complete_event\n")); KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL); #if (NTDDI_VERSION >= NTDDI_WINXP) KeFlushQueuedDpcs(); #else { /* just wait 1 second until all DPC's finish - not ideal but it's only for W2K */ LARGE_INTEGER interval; interval.QuadPart = -1 * 1000 * 1000 * 10; /* 1 second */ KeDelayExecutionThread(KernelMode, FALSE, &interval); } #endif ExFreePoolWithTag(highsync_info, XENPCI_POOL_TAG); FUNCTION_EXIT(); }
static VOID XenPciPdo_EvtDeviceUsageNotification(WDFDEVICE device, WDF_SPECIAL_FILE_TYPE notification_type, BOOLEAN is_in_notification_path) { PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device); FUNCTION_ENTER(); FUNCTION_MSG("path = %s\n", xppdd->path); switch (notification_type) { case WdfSpecialFilePaging: FUNCTION_MSG("notification_type = Paging, flag = %d\n", is_in_notification_path); break; case WdfSpecialFileHibernation: xppdd->hiber_usage_kludge = is_in_notification_path; FUNCTION_MSG("notification_type = Hibernation, flag = %d\n", is_in_notification_path); break; case WdfSpecialFileDump: FUNCTION_MSG("notification_type = Dump, flag = %d\n", is_in_notification_path); break; default: FUNCTION_MSG("notification_type = %d, flag = %d\n", notification_type, is_in_notification_path); break; } FUNCTION_EXIT(); }
static VOID XenPci_DoPatchKernel0(PVOID context) { patch_info_t *pi = context; ULONG i; ULONG high_level_tpr; ULONG patch_position_index = 0; ULONG potential_patch_position_index = 0; FUNCTION_ENTER(); high_level_tpr = SaveTpr(); /* we know all the other CPUs are at HIGH_LEVEL so set them all to the same as cpu 0 */ for (i = 1; i < MAX_VIRT_CPUS; i++) SaveTprProcValue(i, high_level_tpr); /* we can't use KdPrint while patching as it may involve the TPR while we are patching it */ for (i = 0; i < pi->length; i++) { if (XenPci_TestAndPatchInstruction((PUCHAR)pi->base + i)) { patch_positions[patch_position_index++] = (PUCHAR)pi->base + i; } else if (*(PULONG)((PUCHAR)pi->base + i) == LAPIC_TASKPRI) { potential_patch_positions[potential_patch_position_index++] = (PUCHAR)pi->base + i; } } for (i = 0; i < patch_position_index; i++) FUNCTION_MSG("Patch added at %p\n", patch_positions[i]); for (i = 0; i < potential_patch_position_index; i++) FUNCTION_MSG("Unpatch TPR address found at %p\n", potential_patch_positions[i]); FUNCTION_EXIT(); }
static VOID XenBus_EvtFileCleanup(WDFFILEOBJECT file_object) { PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object); PXENPCI_DEVICE_DATA xpdd = GetXpdd(WdfFileObjectGetDevice(file_object)); watch_context_t *watch_context; KIRQL old_irql; PCHAR msg; FUNCTION_ENTER(); KeAcquireSpinLock(&xpdid->lock, &old_irql); while (!IsListEmpty(&xpdid->xenbus.watch_list_head)) { watch_context = (watch_context_t *)RemoveHeadList(&xpdid->xenbus.watch_list_head); KeReleaseSpinLock(&xpdid->lock, old_irql); msg = XenBus_RemWatch(xpdd, XBT_NIL, watch_context->path, XenPci_IoWatch, watch_context); if (msg != NULL) { KdPrint((__DRIVER_NAME " Error freeing watch (%s)\n", msg)); XenPci_FreeMem(msg); } ExFreePoolWithTag(watch_context, XENPCI_POOL_TAG); WdfObjectDereference(file_object); KeAcquireSpinLock(&xpdid->lock, &old_irql); } KeReleaseSpinLock(&xpdid->lock, old_irql); FUNCTION_EXIT(); }
NDIS_STATUS XenNet_SetInformation( NDIS_HANDLE adapter_context, NDIS_OID oid, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) { NTSTATUS status; int i; FUNCTION_ENTER(); for (i = 0; xennet_oids[i].oid && xennet_oids[i].oid != oid; i++); if (!xennet_oids[i].oid) { FUNCTION_MSG("Unsupported OID %08x\n", oid); return NDIS_STATUS_NOT_SUPPORTED; } if (information_buffer_length < xennet_oids[i].min_length) { FUNCTION_MSG("%s Set InformationBufferLength %d < min_length %d\n", xennet_oids[i].oid_name, information_buffer_length, xennet_oids[i].min_length); *bytes_needed = xennet_oids[i].min_length; return NDIS_STATUS_BUFFER_TOO_SHORT; } if (!xennet_oids[i].set_routine) { FUNCTION_MSG("%s Set not supported\n", xennet_oids[i].oid_name); return NDIS_STATUS_NOT_SUPPORTED; } FUNCTION_MSG("%s\n", xennet_oids[i].oid_name); status = xennet_oids[i].set_routine(adapter_context, information_buffer, information_buffer_length, bytes_read, bytes_needed); FUNCTION_EXIT(); return status; }
NTSTATUS XenBus_DeviceFileInit(WDFDEVICE device, PWDF_IO_QUEUE_CONFIG queue_config, WDFFILEOBJECT file_object) { NTSTATUS status; PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object); WDF_IO_QUEUE_CONFIG internal_queue_config; FUNCTION_ENTER(); xpdid->EvtFileCleanup = XenBus_EvtFileCleanup; xpdid->EvtFileClose = XenBus_EvtFileClose; queue_config->EvtIoRead = XenBus_EvtIoRead; queue_config->EvtIoWrite = XenBus_EvtIoWrite; // queue_config->EvtIoDeviceControl = XenBus_EvtIoDeviceControl; InitializeListHead(&xpdid->xenbus.read_list_head); InitializeListHead(&xpdid->xenbus.watch_list_head); xpdid->xenbus.len = 0; WDF_IO_QUEUE_CONFIG_INIT(&internal_queue_config, WdfIoQueueDispatchManual); status = WdfIoQueueCreate(device, &internal_queue_config, WDF_NO_OBJECT_ATTRIBUTES, &xpdid->xenbus.io_queue); if (!NT_SUCCESS(status)) { KdPrint(("Error creating queue 0x%x\n", status)); FUNCTION_EXIT(); return status; } FUNCTION_EXIT(); return status; }
static VOID XenBus_EvtFileClose(WDFFILEOBJECT file_object) { UNREFERENCED_PARAMETER(file_object); FUNCTION_ENTER(); FUNCTION_EXIT(); }
VOID XenUsb_DeviceCallback(PVOID context, ULONG callback_type, PVOID value) { PXENUSB_DEVICE_DATA xudd = (PXENUSB_DEVICE_DATA)context; ULONG state; FUNCTION_ENTER(); switch (callback_type) { case XN_DEVICE_CALLBACK_BACKEND_STATE: state = (ULONG)(ULONG_PTR)value; if (state == xudd->backend_state) { FUNCTION_MSG("same state %d\n", state); FUNCTION_EXIT(); } FUNCTION_MSG("XenBusState = %d -> %d\n", xudd->backend_state, state); xudd->backend_state = state; KeSetEvent(&xudd->backend_event, 0, FALSE); break; case XN_DEVICE_CALLBACK_SUSPEND: FUNCTION_MSG("XN_DEVICE_CALLBACK_SUSPEND"); XenUsb_Disconnect(xudd, TRUE); break; case XN_DEVICE_CALLBACK_RESUME: FUNCTION_MSG("XN_DEVICE_CALLBACK_RESUME"); xudd->device_state = DEVICE_STATE_INITIALISING; XenUsb_Connect(xudd, TRUE); // some sort of notify to kick things off? break; } FUNCTION_EXIT(); }
/* called with urb ring lock held */ static VOID PutRequestsOnRing(PXENUSB_DEVICE_DATA xudd) { partial_pvurb_t *partial_pvurb; uint16_t id; int notify; FUNCTION_ENTER(); FUNCTION_MSG("IRQL = %d\n", KeGetCurrentIrql()); while ((partial_pvurb = (partial_pvurb_t *)RemoveHeadList((PLIST_ENTRY)&xudd->partial_pvurb_queue)) != (partial_pvurb_t *)&xudd->partial_pvurb_queue) { FUNCTION_MSG("partial_pvurb = %p\n", partial_pvurb); /* if this partial_pvurb is cancelling another we don't need to check if the cancelled partial_pvurb is on the ring - that is taken care of in HandleEvent */ id = get_id_from_freelist(xudd->req_id_ss); if (id == (uint16_t)-1) { FUNCTION_MSG("no free ring slots\n"); InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb->entry); break; } InsertTailList(&xudd->partial_pvurb_ring, &partial_pvurb->entry); xudd->partial_pvurbs[id] = partial_pvurb; partial_pvurb->req.id = id; *RING_GET_REQUEST(&xudd->urb_ring, xudd->urb_ring.req_prod_pvt) = partial_pvurb->req; xudd->urb_ring.req_prod_pvt++; } RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xudd->urb_ring, notify); if (notify) { FUNCTION_MSG("Notifying\n"); XnNotify(xudd->handle, xudd->event_channel); } FUNCTION_EXIT(); }
static VOID XenNet_ResumeWorkItem(PDEVICE_OBJECT device_object, PVOID context) { struct xennet_info *xi = context; KIRQL old_irql; UNREFERENCED_PARAMETER(device_object); FUNCTION_ENTER(); ASSERT(xi->resume_work_item); IoFreeWorkItem(xi->resume_work_item); XenNet_TxResumeStart(xi); XenNet_RxResumeStart(xi); XenNet_ConnectBackend(xi); XenNet_RxResumeEnd(xi); XenNet_TxResumeEnd(xi); KeAcquireSpinLock(&xi->resume_lock, &old_irql); xi->resume_work_item = NULL; KdPrint((__DRIVER_NAME " *Setting suspend_resume_state_fdo = %d\n", xi->device_state->suspend_resume_state_pdo)); xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo; KdPrint((__DRIVER_NAME " *Notifying event channel %d\n", xi->device_state->pdo_event_channel)); xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel); KeReleaseSpinLock(&xi->resume_lock, old_irql); FUNCTION_EXIT(); }
VOID XenNet_PnPEventNotify( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_DEVICE_PNP_EVENT PnPEvent, IN PVOID InformationBuffer, IN ULONG InformationBufferLength ) { UNREFERENCED_PARAMETER(MiniportAdapterContext); UNREFERENCED_PARAMETER(PnPEvent); UNREFERENCED_PARAMETER(InformationBuffer); UNREFERENCED_PARAMETER(InformationBufferLength); FUNCTION_ENTER(); switch (PnPEvent) { case NdisDevicePnPEventSurpriseRemoved: KdPrint((__DRIVER_NAME " NdisDevicePnPEventSurpriseRemoved\n")); break; case NdisDevicePnPEventPowerProfileChanged : KdPrint((__DRIVER_NAME " NdisDevicePnPEventPowerProfileChanged\n")); break; default: KdPrint((__DRIVER_NAME " %d\n", PnPEvent)); break; } FUNCTION_EXIT(); }
static VOID XenPci_HighSyncCallFunction0( PRKDPC Dpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2) { highsync_info_t *highsync_info = Context; ULONG ActiveProcessorCount; KIRQL old_irql; UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); FUNCTION_ENTER(); #if (NTDDI_VERSION >= NTDDI_WINXP) ActiveProcessorCount = (ULONG)KeNumberProcessors; #else ActiveProcessorCount = (ULONG)*KeNumberProcessors; #endif InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level); if (highsync_info->sync_level > DISPATCH_LEVEL) { while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } } _disable(); //__asm cli; KeRaiseIrql(highsync_info->sync_level, &old_irql); while (highsync_info->nr_spinning_at_sync_level < (LONG)ActiveProcessorCount - 1) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } highsync_info->function0(highsync_info->context); KeLowerIrql(old_irql); _enable(); //__asm sti; highsync_info->do_spin = FALSE; KeMemoryBarrier(); /* wait for all the other processors to complete spinning, just in case it matters */ while (highsync_info->nr_spinning_at_sync_level) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level); /* wait until nr_procs_at_dispatch_level drops to 0 indicating that nothing else requires highsync_info */ while (highsync_info->nr_procs_at_dispatch_level) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE); FUNCTION_EXIT(); }
VOID XenUsb_EvtRequestCancelPvUrb(WDFREQUEST request) { WDFDEVICE device = WdfIoQueueGetDevice(WdfRequestGetIoQueue(request)); PXENUSB_DEVICE_DATA xudd = GetXudd(device); WDF_REQUEST_PARAMETERS wrp; partial_pvurb_t *partial_pvurb; pvurb_t *pvurb; KIRQL old_irql; FUNCTION_ENTER(); FUNCTION_MSG("cancelling request %p\n", request); WDF_REQUEST_PARAMETERS_INIT(&wrp); KeAcquireSpinLock(&xudd->urb_ring_lock, &old_irql); WdfRequestGetParameters(request, &wrp); pvurb = (pvurb_t *)wrp.Parameters.Others.Arg1; FUNCTION_MSG("pvurb = %p\n", pvurb); ASSERT(pvurb); partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_queue.Flink; while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_queue) { partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink; ASSERT(!partial_pvurb->on_ring); FUNCTION_MSG("partial_pvurb = %p is not yet on ring\n", partial_pvurb); RemoveEntryList(&partial_pvurb->entry); ExFreePoolWithTag(partial_pvurb, XENUSB_POOL_TAG); pvurb->ref--; partial_pvurb = next_partial_pvurb; } partial_pvurb = (partial_pvurb_t *)xudd->partial_pvurb_ring.Flink; while (partial_pvurb != (partial_pvurb_t *)&xudd->partial_pvurb_ring) { partial_pvurb_t *next_partial_pvurb = (partial_pvurb_t *)partial_pvurb->entry.Flink; partial_pvurb_t *partial_pvurb_cancel; FUNCTION_MSG("partial_pvurb = %p is on ring\n", partial_pvurb); ASSERT(partial_pvurb->on_ring); partial_pvurb_cancel = ExAllocatePoolWithTag(NonPagedPool, sizeof(*partial_pvurb_cancel), XENUSB_POOL_TAG); /* todo - use lookaside */ ASSERT(partial_pvurb_cancel); /* what would we do if this failed? */ partial_pvurb_cancel->req = partial_pvurb->req; partial_pvurb_cancel->req.pipe = usbif_setunlink_pipe(partial_pvurb_cancel->req.pipe); partial_pvurb_cancel->req.u.unlink.unlink_id = partial_pvurb->req.id; partial_pvurb_cancel->pvurb = pvurb; partial_pvurb_cancel->mdl = NULL; partial_pvurb_cancel->other_partial_pvurb = partial_pvurb; partial_pvurb->other_partial_pvurb = partial_pvurb_cancel; partial_pvurb_cancel->on_ring = FALSE; pvurb->ref++; InsertHeadList(&xudd->partial_pvurb_queue, &partial_pvurb_cancel->entry); partial_pvurb = next_partial_pvurb; } if (pvurb->ref) { PutRequestsOnRing(xudd); KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql); } else { KeReleaseSpinLock(&xudd->urb_ring_lock, old_irql); WdfRequestComplete(request, STATUS_CANCELLED); } FUNCTION_EXIT(); }
static VOID XenPci_DoPatchKernelN(PVOID context) { UNREFERENCED_PARAMETER(context); FUNCTION_ENTER(); FUNCTION_EXIT(); }
VOID XenNet_CancelOidRequest(NDIS_HANDLE adapter_context, PVOID request_id) { UNREFERENCED_PARAMETER(adapter_context); UNREFERENCED_PARAMETER(request_id); FUNCTION_ENTER(); FUNCTION_EXIT(); }
NTSTATUS XenPciPdo_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state) { NTSTATUS status = STATUS_SUCCESS; PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device); PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo); char path[128]; UNREFERENCED_PARAMETER(device); UNREFERENCED_PARAMETER(target_state); FUNCTION_ENTER(); FUNCTION_MSG("path = %s\n", xppdd->path); switch (target_state) { case WdfPowerDeviceD0: FUNCTION_MSG("WdfPowerDeviceD1\n"); break; case WdfPowerDeviceD1: FUNCTION_MSG("WdfPowerDeviceD1\n"); break; case WdfPowerDeviceD2: FUNCTION_MSG("WdfPowerDeviceD2\n"); break; case WdfPowerDeviceD3: FUNCTION_MSG("WdfPowerDeviceD3\n"); if (xppdd->hiber_usage_kludge) { FUNCTION_MSG("(but really WdfPowerDevicePrepareForHibernation)\n"); target_state = WdfPowerDevicePrepareForHibernation; } break; case WdfPowerDeviceD3Final: FUNCTION_MSG("WdfPowerDeviceD3Final\n"); break; case WdfPowerDevicePrepareForHibernation: FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n"); break; default: FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", target_state); break; } if (target_state == WdfPowerDevicePrepareForHibernation) { FUNCTION_MSG("not powering down as we are hibernating\n"); // should we set the backend state here so it's correct on resume??? } /* Remove watch on backend state */ /* even if hibernate */ if (xppdd->device_callback) { FUNCTION_MSG("Removing watch %s\n", xppdd->device); RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path); XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd); } FUNCTION_EXIT(); return status; }
static NTSTATUS XenVbd_IoCompletion_START_DEVICE(PDEVICE_OBJECT device, PIRP irp, PVOID context) { UNREFERENCED_PARAMETER(device); UNREFERENCED_PARAMETER(irp); FUNCTION_ENTER(); ExFreePoolWithTag(context, XENVBD_POOL_TAG); FUNCTION_EXIT(); return STATUS_SUCCESS; }
static VOID XenVbd_StopRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) { PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd; NTSTATUS status; WDFREQUEST request; WDF_REQUEST_SEND_OPTIONS send_options; IO_STACK_LOCATION stack; SCSI_REQUEST_BLOCK srb; SRB_IO_CONTROL sic; FUNCTION_ENTER(); /* send a 'stop' down if we are suspending */ if (suspend) { status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request); FUNCTION_MSG("WdfRequestCreate = %08x\n", status); RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION)); stack.MajorFunction = IRP_MJ_SCSI; stack.MinorFunction = IRP_MN_SCSI_CLASS; stack.Parameters.Scsi.Srb = &srb; RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE); srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; srb.Length = SCSI_REQUEST_BLOCK_SIZE; srb.PathId = 0; srb.TargetId = 0; srb.Lun = 0; srb.OriginalRequest = WdfRequestWdmGetIrp(request); srb.Function = SRB_FUNCTION_IO_CONTROL; srb.DataBuffer = &sic; RtlZeroMemory(&sic, sizeof(SRB_IO_CONTROL)); sic.HeaderLength = sizeof(SRB_IO_CONTROL); memcpy(sic.Signature, XENVBD_CONTROL_SIG, 8); sic.Timeout = 60; sic.ControlCode = XENVBD_CONTROL_STOP; WdfRequestWdmFormatUsingStackLocation(request, &stack); WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS); if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { FUNCTION_MSG("Request was _NOT_ sent\n"); } #if DBG status = WdfRequestGetStatus(request); FUNCTION_MSG("Request Status = %08x\n", status); FUNCTION_MSG("SRB Status = %08x\n", srb.SrbStatus); #endif WdfObjectDelete(request); } status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing); FUNCTION_EXIT(); }
static VOID XenPci_IoWatch(char *path, PVOID context) { NTSTATUS status; watch_context_t *watch_context = context; WDFFILEOBJECT file_object = watch_context->file_object; PXENPCI_DEVICE_INTERFACE_DATA xpdid = GetXpdid(file_object); KIRQL old_irql; struct xsd_sockmsg *rep; xenbus_read_queue_item_t *list_entry; size_t remaining; WDFREQUEST request; FUNCTION_ENTER(); KeAcquireSpinLock(&xpdid->lock, &old_irql); remaining = sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1; rep = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct xsd_sockmsg) + strlen(path) + 1 + strlen(watch_context->token) + 1, XENPCI_POOL_TAG); rep->type = XS_WATCH_EVENT; rep->req_id = 0; rep->tx_id = 0; rep->len = (ULONG)(strlen(path) + 1 + strlen(watch_context->token) + 1); remaining -= sizeof(struct xsd_sockmsg); RtlStringCbCopyA((PCHAR)(rep + 1), remaining, path); remaining -= strlen(path) + 1; RtlStringCbCopyA((PCHAR)(rep + 1) + strlen(path) + 1, remaining, watch_context->token); list_entry = (xenbus_read_queue_item_t *)ExAllocatePoolWithTag(NonPagedPool, sizeof(xenbus_read_queue_item_t), XENPCI_POOL_TAG); list_entry->data = rep; list_entry->length = sizeof(*rep) + rep->len; list_entry->offset = 0; InsertTailList(&xpdid->xenbus.read_list_head, (PLIST_ENTRY)list_entry); status = WdfIoQueueRetrieveNextRequest(xpdid->xenbus.io_queue, &request); if (NT_SUCCESS(status)) { WDF_REQUEST_PARAMETERS parameters; WDF_REQUEST_PARAMETERS_INIT(¶meters); WdfRequestGetParameters(request, ¶meters); KdPrint((__DRIVER_NAME " found pending read - MinorFunction = %d, length = %d\n", (ULONG)parameters.MinorFunction, (ULONG)parameters.Parameters.Read.Length)); XenBus_ProcessReadRequest(xpdid->xenbus.io_queue, request, parameters.Parameters.Read.Length); KeReleaseSpinLock(&xpdid->lock, old_irql); WdfRequestComplete(request, STATUS_SUCCESS); } else { KdPrint((__DRIVER_NAME " no pending read (%08x)\n", status)); KeReleaseSpinLock(&xpdid->lock, old_irql); } FUNCTION_EXIT(); }
/* Called when machine is shutting down, so just quiesce the HW and be done fast. */ VOID XenNet_Shutdown( IN NDIS_HANDLE MiniportAdapterContext ) { UNREFERENCED_PARAMETER(MiniportAdapterContext); /* remember we are called at >= DIRQL here */ FUNCTION_ENTER(); FUNCTION_EXIT(); }
static NTSTATUS XenVbd_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state) { PXENVBD_FILTER_DATA xvfd = GetXvfd(device); NTSTATUS status; UNREFERENCED_PARAMETER(previous_state); // if waking from hibernate then same as suspend... maybe? FUNCTION_ENTER(); status = XenVbd_Connect(&xvfd->xvdd, FALSE); FUNCTION_EXIT(); return status; }
static VOID XenNet_SuspendResume(PKDPC dpc, PVOID context, PVOID arg1, PVOID arg2) { struct xennet_info *xi = context; KIRQL old_irql; PIO_WORKITEM resume_work_item; UNREFERENCED_PARAMETER(dpc); UNREFERENCED_PARAMETER(arg1); UNREFERENCED_PARAMETER(arg2); FUNCTION_ENTER(); switch (xi->device_state->suspend_resume_state_pdo) { case SR_STATE_SUSPENDING: KdPrint((__DRIVER_NAME " New state SUSPENDING\n")); KeAcquireSpinLock(&xi->rx_lock, &old_irql); if (xi->rx_id_free == NET_RX_RING_SIZE) { xi->device_state->suspend_resume_state_fdo = SR_STATE_SUSPENDING; KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xi->device_state->pdo_event_channel)); xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel); } KeReleaseSpinLock(&xi->rx_lock, old_irql); break; case SR_STATE_RESUMING: KdPrint((__DRIVER_NAME " New state SR_STATE_RESUMING\n")); /* do it like this so we don't race and double-free the work item */ resume_work_item = IoAllocateWorkItem(xi->fdo); KeAcquireSpinLock(&xi->resume_lock, &old_irql); if (xi->resume_work_item || xi->device_state->suspend_resume_state_fdo == SR_STATE_RESUMING) { KeReleaseSpinLock(&xi->resume_lock, old_irql); IoFreeWorkItem(resume_work_item); return; } xi->resume_work_item = resume_work_item; KeReleaseSpinLock(&xi->resume_lock, old_irql); IoQueueWorkItem(xi->resume_work_item, XenNet_ResumeWorkItem, DelayedWorkQueue, xi); break; default: KdPrint((__DRIVER_NAME " New state %d\n", xi->device_state->suspend_resume_state_fdo)); xi->device_state->suspend_resume_state_fdo = xi->device_state->suspend_resume_state_pdo; KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xi->device_state->pdo_event_channel)); xi->vectors.EvtChn_Notify(xi->vectors.context, xi->device_state->pdo_event_channel); break; } KeMemoryBarrier(); FUNCTION_EXIT(); }
static BOOLEAN XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId) { UNREFERENCED_PARAMETER(DeviceExtension); UNREFERENCED_PARAMETER(PathId); FUNCTION_ENTER(); KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql())); ScsiPortNotification(NextRequest, DeviceExtension); FUNCTION_EXIT(); return TRUE; }
static BOOLEAN XenScsi_HwScsiInitialize(PVOID DeviceExtension) { PXENSCSI_DEVICE_DATA xsdd = DeviceExtension; UNREFERENCED_PARAMETER(DeviceExtension); FUNCTION_ENTER(); xsdd->shared_paused = SHARED_PAUSED_SCSIPORT_UNPAUSED; ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 1 * 1000 * 1000); /* 1 second */ FUNCTION_EXIT(); return TRUE; }
static NTSTATUS XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp) { PXENVBD_FILTER_DATA xvfd = GetXvfd(device); PIO_STACK_LOCATION stack; PCM_RESOURCE_LIST crl; PCM_FULL_RESOURCE_DESCRIPTOR cfrd; PCM_PARTIAL_RESOURCE_LIST cprl; PCM_PARTIAL_RESOURCE_DESCRIPTOR prd; FUNCTION_ENTER(); /* Pass down the xvdd area as a memory resource. This gives xenvbd the data in a known place and also satisifies the scsiport requirement for a memory resource */ IoCopyCurrentIrpStackLocationToNext(irp); stack = IoGetNextIrpStackLocation(irp); crl = ExAllocatePoolWithTag(NonPagedPool, FIELD_OFFSET(CM_RESOURCE_LIST, List) + FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) + FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1, XENVBD_POOL_TAG); if (!crl) { // TODO: Fail this correctly } crl->Count = 1; cfrd = &crl->List[0]; cfrd->InterfaceType = PNPBus; cfrd->BusNumber = 0; cprl = &cfrd->PartialResourceList; cprl->Version = 1; cprl->Revision = 1; cprl->Count = 1; prd = &cprl->PartialDescriptors[0]; prd->Type = CmResourceTypeMemory; prd->ShareDisposition = CmResourceShareShared; prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE; prd->u.Memory.Start.QuadPart = (ULONG_PTR)&xvfd->xvdd; prd->u.Memory.Length = sizeof(XENVBD_DEVICE_DATA); stack->Parameters.StartDevice.AllocatedResources = crl; stack->Parameters.StartDevice.AllocatedResourcesTranslated = crl; IoSetCompletionRoutine(irp, XenVbd_IoCompletion_START_DEVICE, crl, TRUE, TRUE, TRUE); FUNCTION_EXIT(); return WdfDeviceWdmDispatchPreprocessedIrp(device, irp); }
static VOID XenPci_HighSyncCallFunctionN( PRKDPC Dpc, PVOID Context, PVOID SystemArgument1, PVOID SystemArgument2) { highsync_info_t *highsync_info = Context; ULONG ActiveProcessorCount; KIRQL old_irql; UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); FUNCTION_ENTER(); FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber()); KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber())); InterlockedIncrement(&highsync_info->nr_procs_at_dispatch_level); if (highsync_info->sync_level > DISPATCH_LEVEL) { #if (NTDDI_VERSION >= NTDDI_WINXP) ActiveProcessorCount = (ULONG)KeNumberProcessors; #else ActiveProcessorCount = (ULONG)*KeNumberProcessors; #endif while (highsync_info->nr_procs_at_dispatch_level < (LONG)ActiveProcessorCount) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } } _disable(); //__asm cli; KeRaiseIrql(highsync_info->sync_level, &old_irql); InterlockedIncrement(&highsync_info->nr_spinning_at_sync_level); while(highsync_info->do_spin) { KeStallExecutionProcessor(1); KeMemoryBarrier(); } highsync_info->functionN(highsync_info->context); KeLowerIrql(old_irql); _enable(); //__asm sti; InterlockedDecrement(&highsync_info->nr_spinning_at_sync_level); InterlockedDecrement(&highsync_info->nr_procs_at_dispatch_level); FUNCTION_EXIT(); return; }
/* Opposite of XenNet_Init */ VOID XenNet_Halt( IN NDIS_HANDLE MiniportAdapterContext ) { struct xennet_info *xi = MiniportAdapterContext; FUNCTION_ENTER(); KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql())); XenNet_D0Exit(xi); NdisFreeMemory(xi, 0, 0); FUNCTION_EXIT(); }
VOID XenUsb_EvtChildListScanForChildren(WDFCHILDLIST child_list) { NTSTATUS status; PXENUSB_DEVICE_DATA xudd = GetXudd(WdfChildListGetDevice(child_list)); XENUSB_PDO_IDENTIFICATION_DESCRIPTION child_description; CHAR path[128]; PCHAR value; ULONG i; FUNCTION_ENTER(); WdfChildListBeginScan(child_list); // hold the queue on each device and set each device to a pending state // read backend/num_ports //RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/num-ports", xudd->vectors.backend_path); status = XnReadString(xudd->handle, XBT_NIL, path, &value); if (status != STATUS_SUCCESS) { WdfChildListEndScan(child_list); FUNCTION_MSG("Failed to read num-ports\n"); return; } xudd->num_ports = (ULONG)parse_numeric_string(value); XnFreeMem(xudd->handle, value); FUNCTION_MSG("num-ports = %d\n", xudd->num_ports); for (i = 0; i < 8; i++) { xudd->ports[i].port_number = i + 1; xudd->ports[i].port_type = USB_PORT_TYPE_NOT_CONNECTED; xudd->ports[i].port_status = 0; //1 << PORT_ENABLE; xudd->ports[i].port_change = 0x0000; } /* only a single root hub is enumerated */ WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&child_description.header, sizeof(child_description)); child_description.device_number = 0; //TODO: get the proper index from parent status = WdfChildListAddOrUpdateChildDescriptionAsPresent(child_list, &child_description.header, NULL); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfChildListAddOrUpdateChildDescriptionAsPresent failed with status 0x%08x\n", status); } WdfChildListEndScan(child_list); FUNCTION_EXIT(); }
/* scsiport doesn't process SET_POWER correctly so we have to fudge detection of hibernate */ static NTSTATUS XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER(WDFDEVICE device, PIRP irp) { PXENVBD_FILTER_DATA xvfd = GetXvfd(device); PIO_STACK_LOCATION stack; FUNCTION_ENTER(); stack = IoGetCurrentIrpStackLocation(irp); if (stack->Parameters.Power.Type == DevicePowerState && stack->Parameters.Power.State.DeviceState == PowerDeviceD3 && stack->Parameters.Power.ShutdownType == PowerActionHibernate) { FUNCTION_MSG("Going to hibernate\n"); xvfd->hibernate_flag = TRUE; } else { xvfd->hibernate_flag = FALSE; } IoSkipCurrentIrpStackLocation(irp); FUNCTION_EXIT(); return WdfDeviceWdmDispatchPreprocessedIrp(device, irp); }
VOID XenPci_PatchKernel(PXENPCI_DEVICE_DATA xpdd, PVOID base, ULONG length) { patch_info_t patch_info; #if (NTDDI_VERSION >= NTDDI_WINXP) RTL_OSVERSIONINFOEXW version_info; #endif FUNCTION_ENTER(); /* if we're compiled for 2000 then assume we need patching */ #if (NTDDI_VERSION >= NTDDI_WINXP) version_info.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW); RtlGetVersion((PRTL_OSVERSIONINFOW)&version_info); if (version_info.dwMajorVersion >= 6) { FUNCTION_MSG("Vista or newer - no need for patch\n"); return; } if (version_info.dwMajorVersion == 5 && version_info.dwMinorVersion > 2) { FUNCTION_MSG("Windows 2003 sp2 or newer - no need for patch\n"); return; } if (version_info.dwMajorVersion == 5 && version_info.dwMinorVersion == 2 && version_info.wServicePackMajor >= 2) { FUNCTION_MSG("Windows 2003 sp2 or newer - no need for patch\n"); return; } #endif if (IsMoveCr8Supported()) { FUNCTION_MSG("Using LOCK MOVE CR0 TPR patch\n"); patch_method = PATCH_METHOD_LOCK_MOVE_CR0; } else { FUNCTION_MSG("Using cached TPR patch\n"); patch_method = PATCH_METHOD_CACHED_TPR; } patch_info.base = base; patch_info.length = length; XenPci_HighSync(XenPci_DoPatchKernel0, XenPci_DoPatchKernelN, &patch_info); xpdd->removable = FALSE; FUNCTION_EXIT(); }