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(); }
static void WriteVirtIODeviceWord(ULONG_PTR ulRegister, u16 wValue) { if (ulRegister & ~PORT_MASK) { StorPortWriteRegisterUshort(NULL, (PUSHORT)(ulRegister), (USHORT)(wValue)); } else { StorPortWritePortUshort(NULL, (PUSHORT)(ulRegister), (USHORT)(wValue)); } }
static struct virtqueue *FindVirtualQueue(PADAPTER_EXTENSION adaptExt, ULONG index, ULONG vector) { struct virtqueue *vq = NULL; if (adaptExt->uncachedExtensionVa) { ULONG len; PVOID ptr = (PVOID)((ULONG_PTR)adaptExt->uncachedExtensionVa + adaptExt->offset[index]); PHYSICAL_ADDRESS pa = StorPortGetPhysicalAddress(adaptExt, NULL, ptr, &len); if (pa.QuadPart) { vq = VirtIODevicePrepareQueue(&adaptExt->vdev, index, pa, ptr, len, NULL, FALSE); } if (vq == NULL) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> cannot create virtual queue index = %d vector = % pa = %08I64X\n", __FUNCTION__, index, vector, pa.QuadPart)); return NULL; } if (vector) { unsigned res; StorPortWritePortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_QUEUE_VECTOR),(USHORT)vector); res = StorPortReadPortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_QUEUE_VECTOR)); RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> VIRTIO_MSI_QUEUE_VECTOR vector = %d, res = 0x%x\n", __FUNCTION__, vector, res)); if(res == VIRTIO_MSI_NO_VECTOR) { VirtIODeviceDeleteQueue(vq, NULL); vq = NULL; RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> Cannot create vq vector\n", __FUNCTION__)); return NULL; } StorPortWritePortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_CONFIG_VECTOR),(USHORT)vector); res = StorPortReadPortUshort(adaptExt, (PUSHORT)(adaptExt->vdev.addr + VIRTIO_MSI_CONFIG_VECTOR)); if (res != vector) { VirtIODeviceDeleteQueue(vq, NULL); vq = NULL; RhelDbgPrint(TRACE_LEVEL_FATAL, ("%s>> Cannot set config vector\n", __FUNCTION__)); return NULL; } } } return vq; }
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(); }
void WriteVirtIODeviceWord(ULONG_PTR ulRegister, u16 wValue) { StorPortWritePortUshort(NULL, (PUSHORT)(ulRegister),(USHORT)(wValue)); }
SCSI_ADAPTER_CONTROL_STATUS VioScsiAdapterControl( 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; ENTER_FN(); 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")); ShutDown(DeviceExtension); status = ScsiAdapterControlSuccess; break; } case ScsiRestartAdapter: { RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("ScsiRestartAdapter\n")); VirtIODeviceReset(&adaptExt->vdev); 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->vq[0] = NULL; adaptExt->vq[1] = NULL; adaptExt->vq[2] = NULL; if (!VioScsiHwInitialize(DeviceExtension)) { RhelDbgPrint(TRACE_LEVEL_FATAL, ("Cannot Initialize HW\n")); break; } status = ScsiAdapterControlSuccess; break; } default: break; } EXIT_FN(); return status; }
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; }
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; }