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(); }
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; }
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(); }
NDIS_STATUS XenNet_SetOID_GEN_CURRENT_PACKET_FILTER(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) { struct xennet_info *xi = context; PULONG data = information_buffer; UNREFERENCED_PARAMETER(information_buffer_length); *bytes_needed = sizeof(ULONG64); if (*data & NDIS_PACKET_TYPE_DIRECTED) FUNCTION_MSG("NDIS_PACKET_TYPE_DIRECTED\n"); if (*data & NDIS_PACKET_TYPE_MULTICAST) FUNCTION_MSG("NDIS_PACKET_TYPE_MULTICAST\n"); if (*data & NDIS_PACKET_TYPE_ALL_MULTICAST) FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_MULTICAST\n"); if (*data & NDIS_PACKET_TYPE_BROADCAST) FUNCTION_MSG("NDIS_PACKET_TYPE_BROADCAST\n"); if (*data & NDIS_PACKET_TYPE_PROMISCUOUS) FUNCTION_MSG("NDIS_PACKET_TYPE_PROMISCUOUS\n"); if (*data & NDIS_PACKET_TYPE_ALL_FUNCTIONAL) FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_FUNCTIONAL (not supported)\n"); if (*data & NDIS_PACKET_TYPE_ALL_LOCAL) FUNCTION_MSG("NDIS_PACKET_TYPE_ALL_LOCAL (not supported)\n"); if (*data & NDIS_PACKET_TYPE_FUNCTIONAL) FUNCTION_MSG("NDIS_PACKET_TYPE_FUNCTIONAL (not supported)\n"); if (*data & NDIS_PACKET_TYPE_GROUP) FUNCTION_MSG("NDIS_PACKET_TYPE_GROUP (not supported)\n"); if (*data & ~SUPPORTED_PACKET_FILTERS) { FUNCTION_MSG("returning NDIS_STATUS_NOT_SUPPORTED\n"); return NDIS_STATUS_NOT_SUPPORTED; } xi->packet_filter = *(ULONG *)data; *bytes_read = sizeof(ULONG); return NDIS_STATUS_SUCCESS; }
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(); }
NDIS_STATUS XenNet_QueryInformation( IN NDIS_HANDLE adapter_context, IN NDIS_OID oid, IN PVOID information_buffer, IN ULONG information_buffer_length, OUT PULONG bytes_written, OUT PULONG bytes_needed) { NTSTATUS status; int i; 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 Query 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].query_routine) { FUNCTION_MSG("%s Query 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].query_routine(adapter_context, information_buffer, information_buffer_length, bytes_written, bytes_needed); return status; }
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 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 XenVbd_SendEvent(WDFDEVICE device) { PXENVBD_FILTER_DATA xvfd = GetXvfd(device); NTSTATUS status; WDFREQUEST request; WDF_REQUEST_SEND_OPTIONS send_options; IO_STACK_LOCATION stack; PUCHAR buf; PSCSI_REQUEST_BLOCK srb; PSRB_IO_CONTROL sic; status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request); if (status != STATUS_SUCCESS) { FUNCTION_MSG("WdfRequestCreate failed %08x\n", status); /* this is bad - event will be dropped */ return; } buf = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL) + sizeof(LARGE_INTEGER), XENVBD_POOL_TAG); RtlZeroMemory(buf, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL)); srb = (PSCSI_REQUEST_BLOCK)(buf); sic = (PSRB_IO_CONTROL)(buf + sizeof(SCSI_REQUEST_BLOCK)); srb->Length = sizeof(SCSI_REQUEST_BLOCK); srb->SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE; srb->PathId = 0; srb->TargetId = 0; srb->Lun = 0; srb->OriginalRequest = WdfRequestWdmGetIrp(request); srb->Function = SRB_FUNCTION_IO_CONTROL; srb->DataBuffer = sic; srb->DataTransferLength = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL); srb->TimeOutValue = (ULONG)-1; sic->HeaderLength = sizeof(SRB_IO_CONTROL); memcpy(sic->Signature, XENVBD_CONTROL_SIG, 8); sic->Timeout = (ULONG)-1; sic->ControlCode = XENVBD_CONTROL_EVENT; KeQuerySystemTime((PLARGE_INTEGER)((PUCHAR)buf + sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL))); RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION)); stack.MajorFunction = IRP_MJ_SCSI; stack.MinorFunction = IRP_MN_SCSI_CLASS; stack.Parameters.Scsi.Srb = srb; WdfRequestWdmFormatUsingStackLocation(request, &stack); WdfRequestSetCompletionRoutine(request, XenVbd_SendEventComplete, buf); WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, 0); //WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE); if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) { FUNCTION_MSG("Error sending request\n"); } }
static NTSTATUS XenUsb_CompleteXenbusInit(PXENUSB_DEVICE_DATA xudd) { PUCHAR ptr; USHORT type; PCHAR setting, value, value2; ULONG i; ptr = xudd->config_page; while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END) { switch(type) { case XEN_INIT_TYPE_RING: /* frontend ring */ FUNCTION_MSG("XEN_INIT_TYPE_RING - %s = %p\n", setting, value); if (strcmp(setting, "urb-ring-ref") == 0) { xudd->urb_sring = (usbif_urb_sring_t *)value; FRONT_RING_INIT(&xudd->urb_ring, xudd->urb_sring, PAGE_SIZE); } if (strcmp(setting, "conn-ring-ref") == 0) { xudd->conn_sring = (usbif_conn_sring_t *)value; FRONT_RING_INIT(&xudd->conn_ring, xudd->conn_sring, PAGE_SIZE); } break; case XEN_INIT_TYPE_EVENT_CHANNEL_DPC: /* frontend event channel */ FUNCTION_MSG("XEN_INIT_TYPE_EVENT_CHANNEL_DPC - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF); if (strcmp(setting, "event-channel") == 0) { xudd->event_channel = PtrToUlong(value); } break; case XEN_INIT_TYPE_READ_STRING_BACK: case XEN_INIT_TYPE_READ_STRING_FRONT: FUNCTION_MSG("XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value); break; default: FUNCTION_MSG("XEN_INIT_TYPE_%d\n", type); break; } } if (xudd->urb_sring == NULL || xudd->conn_sring == NULL || xudd->event_channel == 0) { FUNCTION_MSG("Missing settings\n"); FUNCTION_EXIT(); return STATUS_BAD_INITIAL_PC; } stack_new(&xudd->req_id_ss, REQ_ID_COUNT); for (i = 0; i < REQ_ID_COUNT; i++) { put_id_on_freelist(xudd->req_id_ss, (uint16_t)i); } return STATUS_SUCCESS; }
NDIS_STATUS XenNet_QueryOID_GEN_SUPPORTED_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_written, PULONG bytes_needed) { PNDIS_OID supported_oids; int i; UNREFERENCED_PARAMETER(context); UNREFERENCED_PARAMETER(information_buffer); UNREFERENCED_PARAMETER(information_buffer_length); UNREFERENCED_PARAMETER(bytes_written); UNREFERENCED_PARAMETER(bytes_needed); for (i = 0; xennet_oids[i].oid; i++); if (information_buffer_length < sizeof(NDIS_OID) * i) { *bytes_needed = sizeof(NDIS_OID) * i; return NDIS_STATUS_BUFFER_TOO_SHORT; } supported_oids = information_buffer; for (i = 0; xennet_oids[i].oid; i++) { supported_oids[i] = xennet_oids[i].oid; FUNCTION_MSG("Supporting %08x (%s) %s %d bytes\n", xennet_oids[i].oid, xennet_oids[i].oid_name, (xennet_oids[i].query_routine?(xennet_oids[i].set_routine?"get/set":"get only"):(xennet_oids[i].set_routine?"set only":"none")), xennet_oids[i].min_length); } return STATUS_SUCCESS; }
NDIS_STATUS XenNet_SetOID_802_3_MULTICAST_LIST(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) { struct xennet_info *xi = context; UCHAR *multicast_list; int i; UNREFERENCED_PARAMETER(bytes_read); UNREFERENCED_PARAMETER(bytes_needed); if (information_buffer_length > MULTICAST_LIST_MAX_SIZE * 6) { return NDIS_STATUS_MULTICAST_FULL; } if (information_buffer_length % 6 != 0) { return NDIS_STATUS_MULTICAST_FULL; } multicast_list = information_buffer; for (i = 0; i < (int)information_buffer_length / 6; i++) { if (!(multicast_list[i * 6 + 0] & 0x01)) { FUNCTION_MSG("Address %d (%02x:%02x:%02x:%02x:%02x:%02x) is not a multicast address\n", i, (ULONG)multicast_list[i * 6 + 0], (ULONG)multicast_list[i * 6 + 1], (ULONG)multicast_list[i * 6 + 2], (ULONG)multicast_list[i * 6 + 3], (ULONG)multicast_list[i * 6 + 4], (ULONG)multicast_list[i * 6 + 5]); /* the docs say that we should return NDIS_STATUS_MULTICAST_FULL if we get an invalid multicast address but I'm not sure if that's the case... */ } } memcpy(xi->multicast_list, multicast_list, information_buffer_length); xi->multicast_list_size = information_buffer_length / 6; return NDIS_STATUS_SUCCESS; }
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(); }
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(); }
NDIS_STATUS XenNet_SetOID_OFFLOAD_ENCAPSULATION(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) { struct xennet_info *xi = context; PNDIS_OFFLOAD_ENCAPSULATION noe = (PNDIS_OFFLOAD_ENCAPSULATION)information_buffer; UNREFERENCED_PARAMETER(bytes_needed); UNREFERENCED_PARAMETER(information_buffer_length); /* mostly assume that NDIS vets the settings for us */ if (noe->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3) { FUNCTION_MSG("Unknown Encapsulation Type %d\n", noe->IPv4.EncapsulationType); return NDIS_STATUS_NOT_SUPPORTED; } switch(noe->IPv4.Enabled) { case NDIS_OFFLOAD_SET_ON: FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_ON\n"); xi->current_csum_supported = xi->backend_csum_supported && xi->frontend_csum_supported; xi->current_gso_value = min(xi->backend_csum_supported, xi->frontend_csum_supported); break; case NDIS_OFFLOAD_SET_OFF: FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_SET_OFF\n"); xi->current_csum_supported = FALSE; xi->current_gso_value = 0; break; case NDIS_OFFLOAD_SET_NO_CHANGE: FUNCTION_MSG(" IPv4.Enabled = NDIS_OFFLOAD_NO_CHANGE\n"); break; } FUNCTION_MSG(" IPv4.HeaderSize = %d\n", noe->IPv4.HeaderSize); FUNCTION_MSG(" IPv6.EncapsulationType = %d\n", noe->IPv6.EncapsulationType); switch(noe->IPv6.Enabled) { case NDIS_OFFLOAD_SET_ON: FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_ON (this is an error)\n"); break; case NDIS_OFFLOAD_SET_OFF: FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_SET_OFF\n"); break; case NDIS_OFFLOAD_SET_NO_CHANGE: FUNCTION_MSG(" IPv6.Enabled = NDIS_OFFLOAD_NO_CHANGE\n"); break; } *bytes_read = sizeof(NDIS_OFFLOAD_ENCAPSULATION); FUNCTION_MSG(" IPv6.HeaderSize = %d\n", noe->IPv6.HeaderSize); return NDIS_STATUS_SUCCESS; }
NTSTATUS XenPci_SuspendPdo(WDFDEVICE device) { PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device); PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd; PCHAR response; CHAR path[128]; if (xppdd->device_callback) { FUNCTION_MSG("Suspending %s\n", xppdd->device); xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_SUSPEND, NULL); RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path); response = XenBus_RemWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd); if (response) { FUNCTION_MSG("XnRemWatch - %s = %s\n", path, response); XenPci_FreeMem(response); } } return STATUS_SUCCESS; }
NDIS_STATUS XenNet_SetOID_GEN_CURRENT_LOOKAHEAD(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) { struct xennet_info *xi = context; PULONG data = information_buffer; UNREFERENCED_PARAMETER(information_buffer_length); UNREFERENCED_PARAMETER(bytes_read); UNREFERENCED_PARAMETER(bytes_needed); xi->current_lookahead = *(ULONG *)data; FUNCTION_MSG("Set OID_GEN_CURRENT_LOOKAHEAD %d (%p)\n", xi->current_lookahead, xi); return NDIS_STATUS_SUCCESS; }
NTSTATUS XenUsb_Disconnect(PVOID context, BOOLEAN suspend) { PXENUSB_DEVICE_DATA xudd = (PXENUSB_DEVICE_DATA)context; //PFN_NUMBER pfn; NTSTATUS status; if (xudd->device_state != DEVICE_STATE_ACTIVE && xudd->device_state != DEVICE_STATE_INACTIVE) { FUNCTION_MSG("state not DEVICE_STATE_(IN)ACTIVE, is %d instead\n", xudd->device_state); FUNCTION_EXIT(); return STATUS_SUCCESS; } if (xudd->device_state != DEVICE_STATE_INACTIVE) { xudd->device_state = DEVICE_STATE_DISCONNECTING; status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing); while (xudd->backend_state != XenbusStateClosing && xudd->backend_state != XenbusStateClosed) { FUNCTION_MSG("Waiting for XenbusStateClosing/Closed\n"); KeWaitForSingleObject(&xudd->backend_event, Executive, KernelMode, FALSE, NULL); } status = XnWriteInt32(xudd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosed); while (xudd->backend_state != XenbusStateClosed) { FUNCTION_MSG("Waiting for XenbusStateClosed\n"); KeWaitForSingleObject(&xudd->backend_event, Executive, KernelMode, FALSE, NULL); } XnUnbindEvent(xudd->handle, xudd->event_channel); #if NTDDI_VERSION < WINXP KeFlushQueuedDpcs(); #endif XnEndAccess(xudd->handle, xudd->conn_sring_gref, FALSE, XENUSB_POOL_TAG); ExFreePoolWithTag(xudd->conn_sring, XENUSB_POOL_TAG); XnEndAccess(xudd->handle, xudd->urb_sring_gref, FALSE, XENUSB_POOL_TAG); ExFreePoolWithTag(xudd->urb_sring, XENUSB_POOL_TAG); } if (!suspend) { XnCloseDevice(xudd->handle); } xudd->device_state = DEVICE_STATE_DISCONNECTED; return STATUS_SUCCESS; }
NDIS_STATUS XenNet_SetOID_GEN_MACHINE_NAME(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) { UNICODE_STRING name; UNREFERENCED_PARAMETER(context); UNREFERENCED_PARAMETER(bytes_read); UNREFERENCED_PARAMETER(bytes_needed); name.Length = (USHORT)information_buffer_length; name.MaximumLength = (USHORT)information_buffer_length; name.Buffer = information_buffer; FUNCTION_MSG("name = %wZ\n", &name); return NDIS_STATUS_SUCCESS; }
static VOID XenVbd_SendEventComplete(WDFREQUEST request, WDFIOTARGET target, PWDF_REQUEST_COMPLETION_PARAMS params, WDFCONTEXT context) { WDFDEVICE device = WdfIoTargetGetDevice(target); PXENVBD_FILTER_DATA xvfd = GetXvfd(device); NTSTATUS status; PSCSI_REQUEST_BLOCK srb = context; LARGE_INTEGER systemtime; ULONGLONG elapsed; UNREFERENCED_PARAMETER(params); UNREFERENCED_PARAMETER(context); status = WdfRequestGetStatus(request); if (status != 0 || srb->SrbStatus != SRB_STATUS_SUCCESS) { FUNCTION_MSG("Request Status = %08x, SRB Status = %08x\n", status, srb->SrbStatus); } KeQuerySystemTime(&systemtime); elapsed = systemtime.QuadPart - ((PLARGE_INTEGER)((PUCHAR)context + sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL)))->QuadPart; elapsed = elapsed / 10000; // now in ms if (elapsed > 1000) { FUNCTION_MSG("Event took %d ms\n", (ULONG)elapsed); } ExFreePoolWithTag(context, XENVBD_POOL_TAG); WdfObjectDelete(request); for (;;) { if (InterlockedCompareExchange(&xvfd->event_state, 0, 1) == 1) { /* no pending event, and we cleared outstanding flag */ break; } if (InterlockedCompareExchange(&xvfd->event_state, 1, 2) == 2) { /* there was a pending event, and we set the flag back to outstanding */ //FUNCTION_MSG("sending pended event\n"); XenVbd_SendEvent(device); break; } /* event_state changed while we were looking at it, go round again */ } }
static NTSTATUS XenPci_GetBackendDetails(WDFDEVICE device) { PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device); PXENPCI_DEVICE_DATA xpdd = GetXpdd(xppdd->wdf_device_bus_fdo); char path[128]; PCHAR res; PCHAR value; FUNCTION_ENTER(); /* Get backend path */ RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/backend", xppdd->path); res = XenBus_Read(xpdd, XBT_NIL, path, &value); if (res) { FUNCTION_MSG("Failed to read backend path\n"); XenPci_FreeMem(res); return STATUS_UNSUCCESSFUL; } RtlStringCbCopyA(xppdd->backend_path, ARRAY_SIZE(xppdd->backend_path), value); XenPci_FreeMem(value); /* Get backend id */ RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/backend-id", xppdd->path); res = XenBus_Read(xpdd, XBT_NIL, path, &value); if (res) { FUNCTION_MSG("Failed to read backend id\n"); XenPci_FreeMem(res); return STATUS_UNSUCCESSFUL; } xppdd->backend_id = (domid_t)atoi(value); XenPci_FreeMem(value); FUNCTION_EXIT(); return STATUS_SUCCESS; }
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; }
NTSTATUS XenPci_ResumePdo(WDFDEVICE device) { PXENPCI_PDO_DEVICE_DATA xppdd = GetXppdd(device); PXENPCI_DEVICE_DATA xpdd = xppdd->xpdd; PCHAR response; CHAR path[128]; XenPci_GetBackendDetails(device); if (xppdd->device_callback) { FUNCTION_MSG("Resuming %s\n", xppdd->device); RtlStringCbPrintfA(path, ARRAY_SIZE(path), "%s/state", xppdd->backend_path); response = XenBus_AddWatch(xpdd, XBT_NIL, path, XenPci_BackendStateCallback, xppdd); if (response) { FUNCTION_MSG("XnAddWatch - %s = %s\n", path, response); XenPci_FreeMem(response); xppdd->device_callback = NULL; xppdd->device_callback_context = NULL; FUNCTION_EXIT(); return STATUS_UNSUCCESSFUL; } xppdd->device_callback(xppdd->device_callback_context, XN_DEVICE_CALLBACK_RESUME, NULL); } return STATUS_SUCCESS; }
static VOID XenUsb_EvtIoInternalDeviceControl( WDFQUEUE queue, WDFREQUEST request, size_t output_buffer_length, size_t input_buffer_length, ULONG io_control_code) { WDFDEVICE device = WdfIoQueueGetDevice(queue); PXENUSB_DEVICE_DATA xudd = GetXudd(device); //WDF_REQUEST_PARAMETERS wrp; //pvusb_urb_t *urb; UNREFERENCED_PARAMETER(input_buffer_length); UNREFERENCED_PARAMETER(output_buffer_length); FUNCTION_ENTER(); //WDF_REQUEST_PARAMETERS_INIT(&wrp); //WdfRequestGetParameters(request, &wrp); switch(io_control_code) { case IOCTL_INTERNAL_PVUSB_SUBMIT_URB: FUNCTION_MSG("IOCTL_INTERNAL_PVUSB_SUBMIT_URB\n"); //urb = (pvusb_urb_t *)wrp.Parameters.Others.Arg1; //FUNCTION_MSG("urb = %p\n", urb); WdfRequestForwardToIoQueue(request, xudd->pvurb_queue); break; default: FUNCTION_MSG("Unknown IOCTL %08x\n", io_control_code); WdfRequestComplete(request, WdfRequestGetStatus(request)); break; } 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); }
NDIS_STATUS XenNet_SetOID_GEN_NETWORK_LAYER_ADDRESSES(NDIS_HANDLE context, PVOID information_buffer, ULONG information_buffer_length, PULONG bytes_read, PULONG bytes_needed) { PNETWORK_ADDRESS_LIST nal = information_buffer; PNETWORK_ADDRESS na; PNETWORK_ADDRESS_IP ip; int i; UNREFERENCED_PARAMETER(context); UNREFERENCED_PARAMETER(bytes_read); UNREFERENCED_PARAMETER(bytes_needed); FUNCTION_MSG("AddressType = %d\n", nal->AddressType); FUNCTION_MSG("AddressCount = %d\n", nal->AddressCount); if (nal->AddressCount == 0) { // remove addresses of AddressType type } else { na = nal->Address; for (i = 0; i < nal->AddressCount; i++) { if ((ULONG_PTR)na - (ULONG_PTR)nal + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength > information_buffer_length) { FUNCTION_MSG("Out of bounds\n"); return NDIS_STATUS_INVALID_DATA; } switch(na->AddressType) { case NDIS_PROTOCOL_ID_TCP_IP: FUNCTION_MSG("Address[%d].Type = NDIS_PROTOCOL_ID_TCP_IP\n", i); FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength); if (na->AddressLength != NETWORK_ADDRESS_LENGTH_IP) { FUNCTION_MSG("Length is invalid\n"); break; } ip = (PNETWORK_ADDRESS_IP)na->Address; FUNCTION_MSG("Address[%d].in_addr = %d.%d.%d.%d\n", i, ip->in_addr & 0xff, (ip->in_addr >> 8) & 0xff, (ip->in_addr >> 16) & 0xff, (ip->in_addr >> 24) & 0xff); break; default: FUNCTION_MSG("Address[%d].Type = %d\n", i, na->AddressType); FUNCTION_MSG("Address[%d].Length = %d\n", i, na->AddressLength); break; } na = (PNETWORK_ADDRESS)((PUCHAR)na + FIELD_OFFSET(NETWORK_ADDRESS, Address) + na->AddressLength); } } return NDIS_STATUS_SUCCESS; }
static VOID XenUsb_EvtIoDefault( WDFQUEUE queue, WDFREQUEST request) { NTSTATUS status; WDF_REQUEST_PARAMETERS parameters; FUNCTION_ENTER(); UNREFERENCED_PARAMETER(queue); status = STATUS_BAD_INITIAL_PC; WDF_REQUEST_PARAMETERS_INIT(¶meters); WdfRequestGetParameters(request, ¶meters); switch (parameters.Type) { case WdfRequestTypeCreate: FUNCTION_MSG("WdfRequestTypeCreate\n"); break; case WdfRequestTypeClose: FUNCTION_MSG("WdfRequestTypeClose\n"); break; case WdfRequestTypeRead: FUNCTION_MSG("WdfRequestTypeRead\n"); break; case WdfRequestTypeWrite: FUNCTION_MSG("WdfRequestTypeWrite\n"); break; case WdfRequestTypeDeviceControl: FUNCTION_MSG("WdfRequestTypeDeviceControl\n"); break; case WdfRequestTypeDeviceControlInternal: FUNCTION_MSG("WdfRequestTypeDeviceControlInternal\n"); break; default: FUNCTION_MSG("Unknown type %x\n", parameters.Type); break; } WdfRequestComplete(request, status); FUNCTION_EXIT(); }
static NTSTATUS XenVbd_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state) { PXENVBD_FILTER_DATA xvfd = GetXvfd(device); NTSTATUS status = STATUS_SUCCESS; FUNCTION_ENTER(); 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 (xvfd->hibernate_flag) { 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) { status = XenVbd_Disconnect(&xvfd->xvdd, FALSE); } FUNCTION_EXIT(); return status; }
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { NTSTATUS status; WDF_DRIVER_CONFIG config; WDFDRIVER driver; UNREFERENCED_PARAMETER(RegistryPath); FUNCTION_ENTER(); WDF_DRIVER_CONFIG_INIT(&config, XenVbd_EvtDeviceAdd); status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver); if (!NT_SUCCESS(status)) { FUNCTION_MSG("WdfDriverCreate failed with status 0x%x\n", status); FUNCTION_EXIT(); return status; } FUNCTION_EXIT(); return status; }