VOID ShutDown( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; ENTER_FN(); VirtIODeviceReset(&adaptExt->vdev); StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_GUEST_FEATURES), 0); if (adaptExt->vq[0]) { adaptExt->vq[0]->vq_ops->shutdown(adaptExt->vq[0]); VirtIODeviceDeleteQueue(adaptExt->vq[0], NULL); adaptExt->vq[0] = NULL; } if (adaptExt->vq[1]) { adaptExt->vq[1]->vq_ops->shutdown(adaptExt->vq[1]); VirtIODeviceDeleteQueue(adaptExt->vq[1], NULL); adaptExt->vq[1] = NULL; } if (adaptExt->vq[2]) { adaptExt->vq[2]->vq_ops->shutdown(adaptExt->vq[2]); VirtIODeviceDeleteQueue(adaptExt->vq[2], NULL); adaptExt->vq[2] = NULL; } EXIT_FN(); }
VOID BalloonTerm( IN WDFOBJECT WdfDevice, IN BOOLEAN bFinal ) { PDEVICE_CONTEXT devCtx = GetDeviceContext(WdfDevice); PVOID p; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "--> BalloonTerm\n"); VirtIODeviceRemoveStatus(&devCtx->VDevice , VIRTIO_CONFIG_S_DRIVER_OK); if(devCtx->DefVirtQueue) { devCtx->DefVirtQueue->vq_ops->shutdown(devCtx->DefVirtQueue); if (bFinal) { VirtIODeviceDeleteQueue(devCtx->DefVirtQueue, &p); MmFreeContiguousMemory(p); devCtx->DefVirtQueue = NULL; } } if(devCtx->InfVirtQueue) { devCtx->InfVirtQueue->vq_ops->shutdown(devCtx->InfVirtQueue); if (bFinal) { VirtIODeviceDeleteQueue(devCtx->InfVirtQueue, &p); MmFreeContiguousMemory(p); devCtx->InfVirtQueue = NULL; } } if(devCtx->StatVirtQueue) { devCtx->StatVirtQueue->vq_ops->shutdown(devCtx->StatVirtQueue); if (bFinal) { VirtIODeviceDeleteQueue(devCtx->StatVirtQueue, &p); MmFreeContiguousMemory(p); devCtx->StatVirtQueue = NULL; } } if (bFinal) { VirtIODeviceReset(&devCtx->VDevice); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "<-- BalloonTerm\n"); }
VOID RhelShutDown( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; VirtIODeviceReset(&adaptExt->vdev); ScsiPortWritePortUshort((PUSHORT)(adaptExt->vdev.addr + VIRTIO_PCI_GUEST_FEATURES), 0); if (adaptExt->vq) { adaptExt->vq->vq_ops->shutdown(adaptExt->vq); VirtIODeviceDeleteQueue(adaptExt->vq, NULL); adaptExt->vq = NULL; } }
VOID ShutDown( IN PVOID DeviceExtension ) { ULONG index; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; ENTER_FN(); VirtIODeviceReset(adaptExt->pvdev); StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_GUEST_FEATURES), 0); for (index = VIRTIO_SCSI_CONTROL_QUEUE; index < adaptExt->num_queues + VIRTIO_SCSI_REQUEST_QUEUE_0; ++index) { if (adaptExt->vq[index]) { virtqueue_shutdown(adaptExt->vq[index]); VirtIODeviceDeleteQueue(adaptExt->vq[index], NULL); adaptExt->vq[index] = NULL; } } EXIT_FN(); }
NTSTATUS BalloonInit( IN WDFOBJECT WdfDevice ) { NTSTATUS status = STATUS_SUCCESS; PDEVICE_CONTEXT devCtx = GetDeviceContext(WdfDevice); 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; } if(VirtIODeviceGetHostFeature(&devCtx->VDevice, 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); if(devCtx->bServiceConnected) { VirtIODeviceEnableGuestFeature(&devCtx->VDevice, VIRTIO_BALLOON_F_STATS_VQ); } } } while(FALSE); 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; }
SCSI_ADAPTER_CONTROL_STATUS VirtIoAdapterControl( IN PVOID DeviceExtension, IN SCSI_ADAPTER_CONTROL_TYPE ControlType, IN PVOID Parameters ) { PSCSI_SUPPORTED_CONTROL_TYPE_LIST ControlTypeList; ULONG AdjustedMaxControlType; ULONG Index; PADAPTER_EXTENSION adaptExt; SCSI_ADAPTER_CONTROL_STATUS status = ScsiAdapterControlUnsuccessful; BOOLEAN SupportedConrolTypes[5] = {TRUE, TRUE, TRUE, FALSE, FALSE}; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s %d\n", __FUNCTION__, ControlType)); switch (ControlType) { case ScsiQuerySupportedControlTypes: { RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("ScsiQuerySupportedControlTypes\n")); ControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters; AdjustedMaxControlType = (ControlTypeList->MaxControlType < 5) ? ControlTypeList->MaxControlType : 5; for (Index = 0; Index < AdjustedMaxControlType; Index++) { ControlTypeList->SupportedTypeList[Index] = SupportedConrolTypes[Index]; } status = ScsiAdapterControlSuccess; break; } case ScsiStopAdapter: { RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("ScsiStopAdapter\n")); RhelShutDown(DeviceExtension); status = ScsiAdapterControlSuccess; break; } case ScsiRestartAdapter: { RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("ScsiRestartAdapter\n")); VirtIODeviceReset(&adaptExt->vdev); WriteVirtIODeviceWord(adaptExt->vdev.addr + VIRTIO_PCI_QUEUE_SEL, (USHORT)0); WriteVirtIODeviceRegister(adaptExt->vdev.addr + VIRTIO_PCI_QUEUE_PFN,(USHORT)0); adaptExt->vq = NULL; if (!VirtIoHwInitialize(DeviceExtension)) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot Initialize HW\n")); break; } status = ScsiAdapterControlSuccess; break; } default: break; } return status; }
ULONG VirtIoFindAdapter( IN PVOID DeviceExtension, IN PVOID HwContext, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, OUT PBOOLEAN Again ) { PACCESS_RANGE accessRange; PADAPTER_EXTENSION adaptExt; ULONG_PTR deviceBase; ULONG allocationSize; ULONG pageNum; #ifdef MSI_SUPPORTED PPCI_COMMON_CONFIG pPciConf = NULL; UCHAR pci_cfg_buf[256]; ULONG pci_cfg_len; #endif UNREFERENCED_PARAMETER( HwContext ); UNREFERENCED_PARAMETER( BusInformation ); UNREFERENCED_PARAMETER( ArgumentString ); UNREFERENCED_PARAMETER( Again ); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; adaptExt->dump_mode = IsCrashDumpMode; ConfigInfo->Master = TRUE; ConfigInfo->ScatterGather = TRUE; ConfigInfo->DmaWidth = Width32Bits; ConfigInfo->Dma32BitAddresses = TRUE; ConfigInfo->Dma64BitAddresses = TRUE; ConfigInfo->WmiDataProvider = FALSE; ConfigInfo->AlignmentMask = 0x3; #ifdef USE_STORPORT ConfigInfo->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS; ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; #ifdef MSI_SUPPORTED ConfigInfo->HwMSInterruptRoutine = VirtIoMSInterruptRoutine; ConfigInfo->InterruptSynchronizationMode=InterruptSynchronizePerMessage; #endif #else ConfigInfo->MapBuffers = TRUE; #endif accessRange = &(*ConfigInfo->AccessRanges)[0]; ASSERT (FALSE == accessRange->RangeInMemory) ; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("Port Resource [%08I64X-%08I64X]\n", accessRange->RangeStart.QuadPart, accessRange->RangeStart.QuadPart + accessRange->RangeLength)); if ( accessRange->RangeLength < IO_PORT_LENGTH) { LogError(DeviceExtension, SP_INTERNAL_ADAPTER_ERROR, __LINE__); RhelDbgPrint(TRACE_LEVEL_FATAL, ("Wrong access range %x bytes\n", accessRange->RangeLength)); return SP_RETURN_NOT_FOUND; } #ifndef USE_STORPORT if (!ScsiPortValidateRange(DeviceExtension, ConfigInfo->AdapterInterfaceType, ConfigInfo->SystemIoBusNumber, accessRange->RangeStart, accessRange->RangeLength, (BOOLEAN)!accessRange->RangeInMemory)) { LogError(DeviceExtension, SP_INTERNAL_ADAPTER_ERROR, __LINE__); RhelDbgPrint(TRACE_LEVEL_FATAL, ("Range validation failed %x for %x bytes\n", (*ConfigInfo->AccessRanges)[0].RangeStart.LowPart, (*ConfigInfo->AccessRanges)[0].RangeLength)); return SP_RETURN_ERROR; } #endif ConfigInfo->NumberOfBuses = 1; ConfigInfo->MaximumNumberOfTargets = 1; ConfigInfo->MaximumNumberOfLogicalUnits = 1; deviceBase = (ULONG_PTR)ScsiPortGetDeviceBase(DeviceExtension, ConfigInfo->AdapterInterfaceType, ConfigInfo->SystemIoBusNumber, accessRange->RangeStart, accessRange->RangeLength, (BOOLEAN)!accessRange->RangeInMemory); if (deviceBase == (ULONG_PTR)NULL) { LogError(DeviceExtension, SP_INTERNAL_ADAPTER_ERROR, __LINE__); RhelDbgPrint(TRACE_LEVEL_FATAL, ("Couldn't map %x for %x bytes\n", (*ConfigInfo->AccessRanges)[0].RangeStart.LowPart, (*ConfigInfo->AccessRanges)[0].RangeLength)); return SP_RETURN_ERROR; } VirtIODeviceInitialize(&adaptExt->vdev, deviceBase, sizeof(adaptExt->vdev)); VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_DRIVER); adaptExt->msix_enabled = FALSE; #ifdef MSI_SUPPORTED pci_cfg_len = StorPortGetBusData (DeviceExtension, PCIConfiguration, ConfigInfo->SystemIoBusNumber, (ULONG)ConfigInfo->SlotNumber, (PVOID)pci_cfg_buf, (ULONG)256); if (pci_cfg_len == 256) { UCHAR CapOffset; PPCI_MSIX_CAPABILITY pMsixCapOffset; pPciConf = (PPCI_COMMON_CONFIG)pci_cfg_buf; if ( (pPciConf->Status & PCI_STATUS_CAPABILITIES_LIST) == 0) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("NO CAPABILITIES_LIST\n")); } else { if ( (pPciConf->HeaderType & (~PCI_MULTIFUNCTION)) == PCI_DEVICE_TYPE ) { CapOffset = pPciConf->u.type0.CapabilitiesPtr; while (CapOffset != 0) { pMsixCapOffset = (PPCI_MSIX_CAPABILITY)(pci_cfg_buf + CapOffset); if ( pMsixCapOffset->Header.CapabilityID == PCI_CAPABILITY_ID_MSIX ) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageControl.TableSize = %d\n", pMsixCapOffset->MessageControl.TableSize)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageControl.FunctionMask = %d\n", pMsixCapOffset->MessageControl.FunctionMask)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageControl.MSIXEnable = %d\n", pMsixCapOffset->MessageControl.MSIXEnable)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageTable = %p\n", pMsixCapOffset->MessageTable)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("PBATable = %d\n", pMsixCapOffset->PBATable)); adaptExt->msix_enabled = (pMsixCapOffset->MessageControl.MSIXEnable == 1); break; } else { CapOffset = pMsixCapOffset->Header.Next; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("CapabilityID = %x, Next CapOffset = %x\n", pMsixCapOffset->Header.CapabilityID, CapOffset)); } } VirtIODeviceSetMSIXUsed(&adaptExt->vdev, adaptExt->msix_enabled); } else { RhelDbgPrint(TRACE_LEVEL_FATAL, ("NOT A PCI_DEVICE_TYPE\n")); } } } else { RhelDbgPrint(TRACE_LEVEL_FATAL, ("CANNOT READ PCI CONFIGURATION SPACE %d\n", pci_cfg_len)); } #endif VirtIODeviceReset(&adaptExt->vdev); VirtIODeviceAddStatus(&adaptExt->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE); WriteVirtIODeviceWord(adaptExt->vdev.addr + VIRTIO_PCI_QUEUE_SEL, (USHORT)0); if (adaptExt->dump_mode) { WriteVirtIODeviceWord(adaptExt->vdev.addr + VIRTIO_PCI_QUEUE_PFN, (USHORT)0); } adaptExt->features = ReadVirtIODeviceRegister(adaptExt->vdev.addr + VIRTIO_PCI_HOST_FEATURES); ConfigInfo->CachesData = CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE) ? TRUE : FALSE; if (ConfigInfo->CachesData) { u32 GuestFeatures = 0; VirtIOFeatureEnable(GuestFeatures, VIRTIO_BLK_F_WCACHE); VirtIODeviceWriteGuestFeatures(&adaptExt->vdev, GuestFeatures); } RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_WCACHE = %d\n", ConfigInfo->CachesData)); VirtIODeviceQueryQueueAllocation(&adaptExt->vdev, 0, &pageNum, &allocationSize); if(adaptExt->dump_mode) { ConfigInfo->NumberOfPhysicalBreaks = 8; } else { ConfigInfo->NumberOfPhysicalBreaks = MAX_PHYS_SEGMENTS + 1; } ConfigInfo->MaximumTransferLength = 0x00FFFFFF; adaptExt->queue_depth = pageNum / ConfigInfo->NumberOfPhysicalBreaks - 1; #if (INDIRECT_SUPPORTED) if(!adaptExt->dump_mode) { adaptExt->indirect = CHECKBIT(adaptExt->features, VIRTIO_RING_F_INDIRECT_DESC); } if(adaptExt->indirect) { adaptExt->queue_depth = pageNum; } #else adaptExt->indirect = 0; #endif RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("breaks_number = %x queue_depth = %x\n", ConfigInfo->NumberOfPhysicalBreaks, adaptExt->queue_depth)); adaptExt->uncachedExtensionVa = ScsiPortGetUncachedExtension(DeviceExtension, ConfigInfo, allocationSize); if (!adaptExt->uncachedExtensionVa) { LogError(DeviceExtension, SP_INTERNAL_ADAPTER_ERROR, __LINE__); RhelDbgPrint(TRACE_LEVEL_FATAL, ("Couldn't get uncached extension\n")); return SP_RETURN_ERROR; } InitializeListHead(&adaptExt->list_head); #ifdef USE_STORPORT InitializeListHead(&adaptExt->complete_list); #endif return SP_RETURN_FOUND; }
NTSTATUS VIOSerialEvtDevicePrepareHardware( IN WDFDEVICE Device, IN WDFCMRESLIST ResourcesRaw, IN WDFCMRESLIST ResourcesTranslated) { int nListSize = 0; PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDescriptor; WDF_INTERRUPT_INFO interruptInfo; int i = 0; PPORTS_DEVICE pContext = GetPortsDevice(Device); bool bPortFound = FALSE; NTSTATUS status = STATUS_SUCCESS; UINT nr_ports, max_queues, size_to_allocate; UNREFERENCED_PARAMETER(ResourcesRaw); PAGED_CODE(); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "<--> %s\n", __FUNCTION__); max_queues = 64; // 2 for each of max 32 ports size_to_allocate = VirtIODeviceSizeRequired((USHORT)max_queues); pContext->pIODevice = (VirtIODevice *)ExAllocatePoolWithTag( NonPagedPool, size_to_allocate, VIOSERIAL_DRIVER_MEMORY_TAG); if (NULL == pContext->pIODevice) { return STATUS_INSUFFICIENT_RESOURCES; } nListSize = WdfCmResourceListGetCount(ResourcesTranslated); for (i = 0; i < nListSize; i++) { if(pResDescriptor = WdfCmResourceListGetDescriptor(ResourcesTranslated, i)) { switch(pResDescriptor->Type) { case CmResourceTypePort : pContext->bPortMapped = (pResDescriptor->Flags & CM_RESOURCE_PORT_IO) ? FALSE : TRUE; pContext->PortBasePA = pResDescriptor->u.Port.Start; pContext->uPortLength = pResDescriptor->u.Port.Length; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "IO Port Info [%08I64X-%08I64X]\n", pResDescriptor->u.Port.Start.QuadPart, pResDescriptor->u.Port.Start.QuadPart + pResDescriptor->u.Port.Length); if (pContext->bPortMapped ) { pContext->pPortBase = MmMapIoSpace(pContext->PortBasePA, pContext->uPortLength, MmNonCached); if (!pContext->pPortBase) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "%s>>> Failed to map IO port!\n", __FUNCTION__); return STATUS_INSUFFICIENT_RESOURCES; } } else { pContext->pPortBase = (PVOID)(ULONG_PTR)pContext->PortBasePA.QuadPart; } bPortFound = TRUE; break; case CmResourceTypeInterrupt: break; } } } if(!bPortFound) { TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "%s>>> %s", __FUNCTION__, "IO port wasn't found!\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } WDF_INTERRUPT_INFO_INIT(&interruptInfo); WdfInterruptGetInfo(pContext->WdfInterrupt, &interruptInfo); VirtIODeviceInitialize(pContext->pIODevice, (ULONG_PTR)pContext->pPortBase, size_to_allocate); VirtIODeviceSetMSIXUsed(pContext->pIODevice, interruptInfo.MessageSignaled); VirtIODeviceReset(pContext->pIODevice); VirtIODeviceAddStatus(pContext->pIODevice, VIRTIO_CONFIG_S_ACKNOWLEDGE); pContext->consoleConfig.max_nr_ports = 1; if(pContext->isHostMultiport = VirtIODeviceGetHostFeature(pContext->pIODevice, VIRTIO_CONSOLE_F_MULTIPORT)) { TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "We have multiport host\n"); VirtIODeviceEnableGuestFeature(pContext->pIODevice, VIRTIO_CONSOLE_F_MULTIPORT); VirtIODeviceGet(pContext->pIODevice, FIELD_OFFSET(CONSOLE_CONFIG, max_nr_ports), &pContext->consoleConfig.max_nr_ports, sizeof(pContext->consoleConfig.max_nr_ports)); TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "VirtIOConsoleConfig->max_nr_ports %d\n", pContext->consoleConfig.max_nr_ports); if (pContext->consoleConfig.max_nr_ports > pContext->pIODevice->maxQueues / 2) { pContext->consoleConfig.max_nr_ports = pContext->pIODevice->maxQueues / 2; TraceEvents(TRACE_LEVEL_WARNING, DBG_PNP, "VirtIOConsoleConfig->max_nr_ports limited to %d\n", pContext->consoleConfig.max_nr_ports); } } if(pContext->isHostMultiport) { WDF_OBJECT_ATTRIBUTES attributes; WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = Device; status = WdfSpinLockCreate( &attributes, &pContext->CVqLock ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfSpinLockCreate failed 0x%x\n", status); return status; } } else { //FIXME // VIOSerialAddPort(Device, 0); } nr_ports = pContext->consoleConfig.max_nr_ports; pContext->in_vqs = (struct virtqueue**)ExAllocatePoolWithTag( NonPagedPool, nr_ports * sizeof(struct virtqueue*), VIOSERIAL_DRIVER_MEMORY_TAG); if(pContext->in_vqs == NULL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,"ExAllocatePoolWithTag failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } memset(pContext->in_vqs, 0, nr_ports * sizeof(struct virtqueue*)); pContext->out_vqs = (struct virtqueue**)ExAllocatePoolWithTag( NonPagedPool, nr_ports * sizeof(struct virtqueue*), VIOSERIAL_DRIVER_MEMORY_TAG ); if(pContext->out_vqs == NULL) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePoolWithTag failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } memset(pContext->out_vqs, 0, nr_ports * sizeof(struct virtqueue*)); pContext->DeviceOK = TRUE; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__); return status; }
ULONG VioScsiFindAdapter( IN PVOID DeviceExtension, IN PVOID HwContext, IN PVOID BusInformation, IN PCHAR ArgumentString, IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, IN PBOOLEAN Again ) { PADAPTER_EXTENSION adaptExt; ULONG allocationSize; ULONG pageNum; ULONG dummy; ULONG Size; #if (MSI_SUPPORTED == 1) PPCI_COMMON_CONFIG pPciConf = NULL; UCHAR pci_cfg_buf[256]; ULONG pci_cfg_len; #endif UNREFERENCED_PARAMETER( HwContext ); UNREFERENCED_PARAMETER( BusInformation ); UNREFERENCED_PARAMETER( ArgumentString ); UNREFERENCED_PARAMETER( Again ); ENTER_FN(); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; memset(adaptExt, 0, sizeof(ADAPTER_EXTENSION)); adaptExt->dump_mode = IsCrashDumpMode; ConfigInfo->Master = TRUE; ConfigInfo->ScatterGather = TRUE; ConfigInfo->DmaWidth = Width32Bits; ConfigInfo->Dma32BitAddresses = TRUE; ConfigInfo->Dma64BitAddresses = TRUE; ConfigInfo->WmiDataProvider = FALSE; ConfigInfo->AlignmentMask = 0x3; ConfigInfo->MapBuffers = STOR_MAP_NON_READ_WRITE_BUFFERS; ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; #if (MSI_SUPPORTED == 1) ConfigInfo->HwMSInterruptRoutine = VioScsiMSInterrupt; ConfigInfo->InterruptSynchronizationMode=InterruptSynchronizePerMessage; #endif if (!InitHW(DeviceExtension, ConfigInfo)) { RhelDbgPrint(TRACE_LEVEL_ERROR, ("Cannot initialize HardWare\n")); return SP_RETURN_NOT_FOUND; } #if (MSI_SUPPORTED == 1) pci_cfg_len = StorPortGetBusData (DeviceExtension, PCIConfiguration, ConfigInfo->SystemIoBusNumber, (ULONG)ConfigInfo->SlotNumber, (PVOID)pci_cfg_buf, (ULONG)256); if (pci_cfg_len == 256) { UCHAR CapOffset; PPCI_MSIX_CAPABILITY pMsixCapOffset; pPciConf = (PPCI_COMMON_CONFIG)pci_cfg_buf; if ( (pPciConf->Status & PCI_STATUS_CAPABILITIES_LIST) == 0) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("NO CAPABILITIES_LIST\n")); } else { if ( (pPciConf->HeaderType & (~PCI_MULTIFUNCTION)) == PCI_DEVICE_TYPE ) { CapOffset = pPciConf->u.type0.CapabilitiesPtr; while (CapOffset != 0) { pMsixCapOffset = (PPCI_MSIX_CAPABILITY)(pci_cfg_buf + CapOffset); if ( pMsixCapOffset->Header.CapabilityID == PCI_CAPABILITY_ID_MSIX ) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageControl.TableSize = %d\n", pMsixCapOffset->MessageControl.TableSize)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageControl.FunctionMask = %d\n", pMsixCapOffset->MessageControl.FunctionMask)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageControl.MSIXEnable = %d\n", pMsixCapOffset->MessageControl.MSIXEnable)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("MessageTable = %p\n", pMsixCapOffset->MessageTable)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("PBATable = %d\n", pMsixCapOffset->PBATable)); adaptExt->msix_enabled = (pMsixCapOffset->MessageControl.MSIXEnable == 1); } else { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("CapabilityID = %x, Next CapOffset = %x\n", pMsixCapOffset->Header.CapabilityID, CapOffset)); } CapOffset = pMsixCapOffset->Header.Next; } RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("msix_enabled = %d\n", adaptExt->msix_enabled)); VirtIODeviceSetMSIXUsed(&adaptExt->vdev, adaptExt->msix_enabled); } else { RhelDbgPrint(TRACE_LEVEL_FATAL, ("NOT A PCI_DEVICE_TYPE\n")); } } } else { RhelDbgPrint(TRACE_LEVEL_FATAL, ("CANNOT READ PCI CONFIGURATION SPACE %d\n", pci_cfg_len)); } #endif GetScsiConfig(DeviceExtension); ConfigInfo->NumberOfBuses = 1; ConfigInfo->MaximumNumberOfTargets = (UCHAR)adaptExt->scsi_config.max_target; ConfigInfo->MaximumNumberOfLogicalUnits = (UCHAR)adaptExt->scsi_config.max_lun; if(adaptExt->dump_mode) { ConfigInfo->NumberOfPhysicalBreaks = 8; } else { ConfigInfo->NumberOfPhysicalBreaks = min((MAX_PHYS_SEGMENTS + 1), adaptExt->scsi_config.seg_max); } ConfigInfo->MaximumTransferLength = 0x00FFFFFF; VirtIODeviceReset(&adaptExt->vdev); if (adaptExt->dump_mode) { StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_SEL), (USHORT)0); StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN),(USHORT)0); StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_SEL), (USHORT)1); StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN),(USHORT)0); StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_SEL), (USHORT)2); StorPortWritePortUshort(DeviceExtension, (PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN),(USHORT)0); } adaptExt->features = StorPortReadPortUlong(DeviceExtension, (PULONG)(adaptExt->device_base + VIRTIO_PCI_HOST_FEATURES)); allocationSize = 0; adaptExt->offset[0] = 0; VirtIODeviceQueryQueueAllocation(&adaptExt->vdev, 0, &pageNum, &Size); allocationSize += ROUND_TO_PAGES(Size); adaptExt->offset[1] = ROUND_TO_PAGES(Size); VirtIODeviceQueryQueueAllocation(&adaptExt->vdev, 1, &dummy, &Size); allocationSize += ROUND_TO_PAGES(Size); adaptExt->offset[2] = adaptExt->offset[1] + ROUND_TO_PAGES(Size); VirtIODeviceQueryQueueAllocation(&adaptExt->vdev, 2, &dummy, &Size); allocationSize += ROUND_TO_PAGES(Size); adaptExt->offset[3] = adaptExt->offset[2] + ROUND_TO_PAGES(Size); allocationSize += ROUND_TO_PAGES(sizeof(SRB_EXTENSION)); adaptExt->offset[4] = adaptExt->offset[3] + ROUND_TO_PAGES(sizeof(SRB_EXTENSION)); allocationSize += ROUND_TO_PAGES(sizeof(VirtIOSCSIEventNode) * 8); #if (INDIRECT_SUPPORTED == 1) if(!adaptExt->dump_mode) { adaptExt->indirect = CHECKBIT(adaptExt->features, VIRTIO_RING_F_INDIRECT_DESC); } #else adaptExt->indirect = 0; #endif if(adaptExt->indirect) { adaptExt->queue_depth = max(2, (pageNum / 4)); } else { adaptExt->queue_depth = pageNum / ConfigInfo->NumberOfPhysicalBreaks - 1; } RhelDbgPrint(TRACE_LEVEL_ERROR, ("breaks_number = %x queue_depth = %x\n", ConfigInfo->NumberOfPhysicalBreaks, adaptExt->queue_depth)); adaptExt->uncachedExtensionVa = StorPortGetUncachedExtension(DeviceExtension, ConfigInfo, allocationSize); if (!adaptExt->uncachedExtensionVa) { LogError(DeviceExtension, SP_INTERNAL_ADAPTER_ERROR, __LINE__); RhelDbgPrint(TRACE_LEVEL_FATAL, ("Can't get uncached extension\n")); return SP_RETURN_ERROR; } return SP_RETURN_FOUND; }