NTSTATUS BalloonInit( IN WDFOBJECT WdfDevice ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_CONTEXT devCtx = GetDeviceContext(WdfDevice); u32 hostFeatures; u32 guestFeatures; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> BalloonInit\n"); VirtIODeviceReset(&devCtx->VDevice); VirtIODeviceAddStatus(&devCtx->VDevice, VIRTIO_CONFIG_S_ACKNOWLEDGE); VirtIODeviceAddStatus(&devCtx->VDevice, VIRTIO_CONFIG_S_DRIVER); do { if (!devCtx->InfVirtQueue) { devCtx->InfVirtQueue = FindVirtualQueue(&devCtx->VDevice, 0); } else { VirtIODeviceRenewQueue(devCtx->InfVirtQueue); } if (!devCtx->InfVirtQueue) { status = STATUS_INSUFFICIENT_RESOURCES; break; } if (!devCtx->DefVirtQueue) { devCtx->DefVirtQueue = FindVirtualQueue(&devCtx->VDevice, 1); } else { VirtIODeviceRenewQueue(devCtx->DefVirtQueue); } if (!devCtx->DefVirtQueue) { status = STATUS_INSUFFICIENT_RESOURCES; break; } guestFeatures = 0; hostFeatures = VirtIODeviceReadHostFeatures(&devCtx->VDevice); if(VirtIOIsFeatureEnabled(hostFeatures, VIRTIO_BALLOON_F_STATS_VQ)) { BOOLEAN bNeedBuffer = FALSE; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> VIRTIO_BALLOON_F_STATS_VQ\n"); if(!devCtx->StatVirtQueue) { devCtx->StatVirtQueue = FindVirtualQueue(&devCtx->VDevice, 2); bNeedBuffer = TRUE; } else { VirtIODeviceRenewQueue(devCtx->StatVirtQueue); } if(!devCtx->StatVirtQueue) { status = STATUS_INSUFFICIENT_RESOURCES; break; } if (bNeedBuffer) { VIO_SG sg; sg.physAddr = MmGetPhysicalAddress(devCtx->MemStats); sg.ulSize = sizeof (BALLOON_STAT) * VIRTIO_BALLOON_S_NR; if(devCtx->StatVirtQueue->vq_ops->add_buf(devCtx->StatVirtQueue, &sg, 1, 0, devCtx, NULL, 0) < 0) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "<-> %s :: Cannot add buffer\n", __FUNCTION__); } } devCtx->StatVirtQueue->vq_ops->kick(devCtx->StatVirtQueue); VirtIOFeatureEnable(guestFeatures, VIRTIO_BALLOON_F_STATS_VQ); } } while(FALSE); VirtIODeviceWriteGuestFeatures(&devCtx->VDevice, guestFeatures); if(NT_SUCCESS(status)) { VirtIODeviceAddStatus(&devCtx->VDevice, VIRTIO_CONFIG_S_DRIVER_OK); } else { VirtIODeviceAddStatus(&devCtx->VDevice, VIRTIO_CONFIG_S_FAILED); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- BalloonInit\n"); return status; }
static NTSTATUS VIOSerialInitAllQueues( IN WDFOBJECT Device) { NTSTATUS status = STATUS_SUCCESS; PPORTS_DEVICE pContext = GetPortsDevice(Device); UINT nr_ports, i, j; USHORT ControlVector, QueuesVector; WDF_INTERRUPT_INFO info; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "--> %s\n", __FUNCTION__); WDF_INTERRUPT_INFO_INIT(&info); WdfInterruptGetInfo(pContext->WdfInterrupt, &info); ControlVector = info.MessageSignaled ? 0 : VIRTIO_MSI_NO_VECTOR; WDF_INTERRUPT_INFO_INIT(&info); WdfInterruptGetInfo(pContext->QueuesInterrupt, &info); QueuesVector = (ControlVector != VIRTIO_MSI_NO_VECTOR) ? (info.Vector ? 1 : 0) : VIRTIO_MSI_NO_VECTOR; nr_ports = pContext->consoleConfig.max_nr_ports; if(pContext->isHostMultiport) { nr_ports++; } for(i = 0, j = 0; i < nr_ports; i++) { if(i == 1) // Control Port { if (pContext->c_ivq) VirtIODeviceRenewQueue(pContext->c_ivq); else pContext->c_ivq = FindVirtualQueue(pContext->pIODevice, 2, ControlVector); if (pContext->c_ovq) VirtIODeviceRenewQueue(pContext->c_ovq); else pContext->c_ovq = FindVirtualQueue(pContext->pIODevice, 3, ControlVector); } else { if (pContext->in_vqs[j]) VirtIODeviceRenewQueue(pContext->in_vqs[j]); else pContext->in_vqs[j] = FindVirtualQueue(pContext->pIODevice, i * 2, QueuesVector); if (pContext->out_vqs[j]) VirtIODeviceRenewQueue(pContext->out_vqs[j]); else pContext->out_vqs[j] = FindVirtualQueue(pContext->pIODevice, (i * 2) + 1, QueuesVector); ++j; } } if (pContext->isHostMultiport && (pContext->c_ovq == NULL)) { status = STATUS_NOT_FOUND; } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "<-- %s\n", __FUNCTION__); return status; }
BOOLEAN VirtIoHwInitialize( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt; BOOLEAN ret = FALSE; #ifdef MSI_SUPPORTED MESSAGE_INTERRUPT_INFORMATION msi_info; #endif RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; adaptExt->msix_vectors = 0; #ifdef MSI_SUPPORTED while(StorPortGetMSIInfo(DeviceExtension, adaptExt->msix_vectors, &msi_info) == STOR_STATUS_SUCCESS) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageId = %x\n", msi_info.MessageId)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageData = %x\n", msi_info.MessageData)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptVector = %x\n", msi_info.InterruptVector)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptLevel = %x\n", msi_info.InterruptLevel)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptMode = %s\n", msi_info.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched")); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageAddress = %p\n\n", msi_info.MessageAddress)); ++adaptExt->msix_vectors; } if(!adaptExt->dump_mode && (adaptExt->msix_vectors > 1)) { adaptExt->vq = FindVirtualQueue(adaptExt, 0, adaptExt->msix_vectors - 1); } #endif if(!adaptExt->vq) { adaptExt->vq = FindVirtualQueue(adaptExt, 0, 0); } if (!adaptExt->vq) { LogError(DeviceExtension, SP_INTERNAL_ADAPTER_ERROR, __LINE__); RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find snd virtual queue\n")); VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_FAILED); return ret; } RhelGetDiskGeometry(DeviceExtension); memset(&adaptExt->inquiry_data, 0, sizeof(INQUIRYDATA)); adaptExt->inquiry_data.ANSIVersion = 4; adaptExt->inquiry_data.ResponseDataFormat = 2; adaptExt->inquiry_data.CommandQueue = 1; adaptExt->inquiry_data.DeviceType = DIRECT_ACCESS_DEVICE; adaptExt->inquiry_data.Wide32Bit = 1; adaptExt->inquiry_data.AdditionalLength = 91; ScsiPortMoveMemory(&adaptExt->inquiry_data.VendorId, "Red Hat ", sizeof("Red Hat ")); ScsiPortMoveMemory(&adaptExt->inquiry_data.ProductId, "VirtIO", sizeof("VirtIO")); ScsiPortMoveMemory(&adaptExt->inquiry_data.ProductRevisionLevel, "0001", sizeof("0001")); ScsiPortMoveMemory(&adaptExt->inquiry_data.VendorSpecific, "0001", sizeof("0001")); if(!adaptExt->dump_mode && !adaptExt->sn_ok) { RhelGetSerialNumber(DeviceExtension); } ret = TRUE; #ifdef USE_STORPORT if(!adaptExt->dump_mode && !adaptExt->dpc_ok) { ret = StorPortEnablePassiveInitialization(DeviceExtension, VirtIoPassiveInitializeRoutine); } #endif if (ret) { VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_DRIVER_OK); } else { VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_FAILED); } return ret; }
BOOLEAN VioScsiHwInitialize( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; PVOID ptr = adaptExt->uncachedExtensionVa; ULONG i; #if (MSI_SUPPORTED == 1) MESSAGE_INTERRUPT_INFORMATION msi_info; #endif ENTER_FN(); adaptExt->msix_vectors = 0; #if (MSI_SUPPORTED == 1) while(StorPortGetMSIInfo(DeviceExtension, adaptExt->msix_vectors, &msi_info) == STOR_STATUS_SUCCESS) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageId = %x\n", msi_info.MessageId)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageData = %x\n", msi_info.MessageData)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptVector = %x\n", msi_info.InterruptVector)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptLevel = %x\n", msi_info.InterruptLevel)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("InterruptMode = %s\n", msi_info.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched")); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageAddress = %p\n\n", msi_info.MessageAddress)); ++adaptExt->msix_vectors; } if(!adaptExt->dump_mode && (adaptExt->msix_vectors > 1)) { adaptExt->vq[0] = FindVirtualQueue(adaptExt, 0, 1); } if(!adaptExt->dump_mode && (adaptExt->msix_vectors > 2)) { adaptExt->vq[1] = FindVirtualQueue(adaptExt, 1, 2); } if(!adaptExt->dump_mode && (adaptExt->msix_vectors > 3)) { adaptExt->vq[2] = FindVirtualQueue(adaptExt, 2, 3); } #endif if (!adaptExt->vq[0]) { adaptExt->vq[0] = FindVirtualQueue(adaptExt, 0, 0); } if (!adaptExt->vq[0]) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find virtual queue 0\n")); return FALSE; } if (!adaptExt->vq[1]) { adaptExt->vq[1] = FindVirtualQueue(adaptExt, 1, 0); } if (!adaptExt->vq[1]) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find virtual queue 1\n")); return FALSE; } if (!adaptExt->vq[2]) { adaptExt->vq[2] = FindVirtualQueue(adaptExt, 2, 0); } if (!adaptExt->vq[2]) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot find virtual queue 2\n")); return FALSE; } adaptExt->tmf_cmd.SrbExtension = (PSRB_EXTENSION)((ULONG_PTR)adaptExt->uncachedExtensionVa + adaptExt->offset[3]); adaptExt->events = (PVirtIOSCSIEventNode)((ULONG_PTR)adaptExt->uncachedExtensionVa + adaptExt->offset[4]); if (!adaptExt->dump_mode && CHECKBIT(adaptExt->features, VIRTIO_SCSI_F_HOTPLUG)) { PVirtIOSCSIEventNode events = adaptExt->events; for (i = 0; i < 8; i++) { if (!KickEvent(DeviceExtension, (PVOID)(&events[i]))) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("Can't add event %d\n", i)); } } } StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_GUEST_FEATURES), (USHORT)((1 << VIRTIO_SCSI_F_HOTPLUG) | (1 << VIRTIO_SCSI_F_CHANGE))); StorPortWritePortUchar(DeviceExtension, (PUCHAR)(adaptExt->device_base + VIRTIO_PCI_STATUS), (UCHAR)VIRTIO_CONFIG_S_DRIVER_OK); EXIT_FN(); return TRUE; }