VOID RhelGetDiskGeometry( IN PVOID DeviceExtension ) { u64 cap; u32 v; struct virtio_blk_geometry vgeo; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; adaptExt->features = virtio_get_features(&adaptExt->vdev); if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BARRIER)) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_BARRIER\n")); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_RO\n")); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SIZE_MAX)) { virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, size_max), &v, sizeof(v)); adaptExt->info.size_max = v; } else { adaptExt->info.size_max = SECTOR_SIZE; } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SEG_MAX)) { virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, seg_max), &v, sizeof(v)); adaptExt->info.seg_max = v; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_SEG_MAX = %d\n", adaptExt->info.seg_max)); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BLK_SIZE)) { virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, blk_size), &v, sizeof(v)); adaptExt->info.blk_size = v; } else { adaptExt->info.blk_size = SECTOR_SIZE; } RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_BLK_SIZE = %d\n", adaptExt->info.blk_size)); if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_GEOMETRY)) { virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, geometry), &vgeo, sizeof(vgeo)); adaptExt->info.geometry.cylinders= vgeo.cylinders; adaptExt->info.geometry.heads = vgeo.heads; adaptExt->info.geometry.sectors = vgeo.sectors; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_GEOMETRY. cylinders = %d heads = %d sectors = %d\n", adaptExt->info.geometry.cylinders, adaptExt->info.geometry.heads, adaptExt->info.geometry.sectors)); } virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, capacity), &cap, sizeof(cap)); adaptExt->info.capacity = cap; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("capacity = %08I64X\n", adaptExt->info.capacity)); if(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_TOPOLOGY)) { virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, physical_block_exp), &adaptExt->info.physical_block_exp, sizeof(adaptExt->info.physical_block_exp)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("physical_block_exp = %d\n", adaptExt->info.physical_block_exp)); virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, alignment_offset), &adaptExt->info.alignment_offset, sizeof(adaptExt->info.alignment_offset)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("alignment_offset = %d\n", adaptExt->info.alignment_offset)); virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, min_io_size), &adaptExt->info.min_io_size, sizeof(adaptExt->info.min_io_size)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("min_io_size = %d\n", adaptExt->info.min_io_size)); virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, opt_io_size), &adaptExt->info.opt_io_size, sizeof(adaptExt->info.opt_io_size)); RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("opt_io_size = %d\n", adaptExt->info.opt_io_size)); } }
BOOLEAN VirtIoStartIo( IN PVOID DeviceExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PCDB cdb = (PCDB)&Srb->Cdb[0]; PADAPTER_EXTENSION adaptExt; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; switch (Srb->Function) { case SRB_FUNCTION_EXECUTE_SCSI: case SRB_FUNCTION_IO_CONTROL: { break; } case SRB_FUNCTION_PNP: case SRB_FUNCTION_POWER: case SRB_FUNCTION_RESET_DEVICE: case SRB_FUNCTION_RESET_LOGICAL_UNIT: { Srb->SrbStatus = SRB_STATUS_SUCCESS; CompleteSRB(DeviceExtension, Srb); return TRUE; } case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_SHUTDOWN: { Srb->SrbStatus = SRB_STATUS_PENDING; Srb->ScsiStatus = SCSISTAT_GOOD; if (!RhelDoFlush(DeviceExtension, Srb)) { Srb->SrbStatus = SRB_STATUS_ERROR; CompleteSRB(DeviceExtension, Srb); } return TRUE; } default: { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; CompleteSRB(DeviceExtension, Srb); return TRUE; } } switch (cdb->CDB6GENERIC.OperationCode) { case SCSIOP_MODE_SENSE: { Srb->SrbStatus = RhelScsiGetModeSense(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_INQUIRY: { Srb->SrbStatus = RhelScsiGetInquiryData(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_READ_CAPACITY16: case SCSIOP_READ_CAPACITY: { Srb->SrbStatus = RhelScsiGetCapacity(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_WRITE: case SCSIOP_WRITE16: { if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) { PSENSE_DATA senseBuffer = (PSENSE_DATA) Srb->SenseInfoBuffer; Srb->SrbStatus = SRB_STATUS_ERROR; Srb->ScsiStatus = SCSISTAT_CHECK_CONDITION; senseBuffer->SenseKey = SCSI_SENSE_DATA_PROTECT; senseBuffer->AdditionalSenseCode = SCSI_ADWRITE_PROTECT; CompleteSRB(DeviceExtension, Srb); return TRUE; } } case SCSIOP_READ: case SCSIOP_READ16: { Srb->SrbStatus = SRB_STATUS_PENDING; if(!RhelDoReadWrite(DeviceExtension, Srb)) { Srb->SrbStatus = SRB_STATUS_BUSY; CompleteSRB(DeviceExtension, Srb); } return TRUE; } case SCSIOP_START_STOP_UNIT: { Srb->SrbStatus = SRB_STATUS_SUCCESS; CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_REQUEST_SENSE: case SCSIOP_TEST_UNIT_READY: case SCSIOP_RESERVE_UNIT: case SCSIOP_RESERVE_UNIT10: case SCSIOP_RELEASE_UNIT: case SCSIOP_RELEASE_UNIT10: case SCSIOP_VERIFY: case SCSIOP_VERIFY16: case SCSIOP_MEDIUM_REMOVAL: { Srb->SrbStatus = SRB_STATUS_SUCCESS; Srb->ScsiStatus = SCSISTAT_GOOD; CompleteSRB(DeviceExtension, Srb); return TRUE; } case SCSIOP_SYNCHRONIZE_CACHE: case SCSIOP_SYNCHRONIZE_CACHE16: { Srb->SrbStatus = SRB_STATUS_PENDING; Srb->ScsiStatus = SCSISTAT_GOOD; if (!RhelDoFlush(DeviceExtension, Srb)) { Srb->SrbStatus = SRB_STATUS_ERROR; CompleteSRB(DeviceExtension, Srb); } return TRUE; } default: { break; } } if (cdb->CDB12.OperationCode == SCSIOP_REPORT_LUNS) { Srb->SrbStatus = RhelScsiReportLuns(DeviceExtension, Srb); CompleteSRB(DeviceExtension, Srb); return TRUE; } Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; CompleteSRB(DeviceExtension, Srb); return TRUE; }
uint8_t ckps_is_error(void) { return CHECKBIT(flags, F_ERROR) > 0; }
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; }
UCHAR RhelScsiGetModeSense( IN PVOID DeviceExtension, IN OUT PSCSI_REQUEST_BLOCK Srb ) { ULONG ModeSenseDataLen; UCHAR SrbStatus = SRB_STATUS_INVALID_LUN; PCDB cdb = (PCDB)&Srb->Cdb[0]; PMODE_PARAMETER_HEADER header; PMODE_CACHING_PAGE cachePage; PMODE_PARAMETER_BLOCK blockDescriptor; PADAPTER_EXTENSION adaptExt; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; ModeSenseDataLen = Srb->DataTransferLength; SrbStatus = SRB_STATUS_INVALID_REQUEST; if ((cdb->MODE_SENSE.PageCode == MODE_PAGE_CACHING) || (cdb->MODE_SENSE.PageCode == MODE_SENSE_RETURN_ALL)) { if (sizeof(MODE_PARAMETER_HEADER) > ModeSenseDataLen) { SrbStatus = SRB_STATUS_ERROR; return SrbStatus; } header = (PMODE_PARAMETER_HEADER)Srb->DataBuffer; memset(header, 0, sizeof(MODE_PARAMETER_HEADER)); header->DeviceSpecificParameter = MODE_DSP_FUA_SUPPORTED; if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) { header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; } ModeSenseDataLen -= sizeof(MODE_PARAMETER_HEADER); if (ModeSenseDataLen >= sizeof(MODE_CACHING_PAGE)) { header->ModeDataLength = sizeof(MODE_CACHING_PAGE) + 3; cachePage = (PMODE_CACHING_PAGE)header; cachePage = (PMODE_CACHING_PAGE)((unsigned char *)(cachePage) + (ULONG)sizeof(MODE_PARAMETER_HEADER)); memset(cachePage, 0, sizeof(MODE_CACHING_PAGE)); cachePage->PageCode = MODE_PAGE_CACHING; cachePage->PageLength = 10; cachePage->WriteCacheEnable = CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE) ? 1 : 0; Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_CACHING_PAGE); } else { Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER); } SrbStatus = SRB_STATUS_SUCCESS; } else if (cdb->MODE_SENSE.PageCode == MODE_PAGE_VENDOR_SPECIFIC) { if (sizeof(MODE_PARAMETER_HEADER) > ModeSenseDataLen) { SrbStatus = SRB_STATUS_ERROR; return SrbStatus; } header = (PMODE_PARAMETER_HEADER)Srb->DataBuffer; memset(header, 0, sizeof(MODE_PARAMETER_HEADER)); header->DeviceSpecificParameter = MODE_DSP_FUA_SUPPORTED; if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) { header->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; } ModeSenseDataLen -= sizeof(MODE_PARAMETER_HEADER); if (ModeSenseDataLen >= sizeof(MODE_PARAMETER_BLOCK)) { header->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK); blockDescriptor = (PMODE_PARAMETER_BLOCK)header; blockDescriptor = (PMODE_PARAMETER_BLOCK)((unsigned char *)(blockDescriptor) + (ULONG)sizeof(MODE_PARAMETER_HEADER)); memset(blockDescriptor, 0, sizeof(MODE_PARAMETER_BLOCK)); Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_PARAMETER_BLOCK); } else { Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER); } SrbStatus = SRB_STATUS_SUCCESS; } else { SrbStatus = SRB_STATUS_INVALID_REQUEST; } return SrbStatus; }
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; }
BOOLEAN VirtIoHwInitialize( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt; BOOLEAN ret = FALSE; ULONG guestFeatures = 0; #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 if (CHECKBIT(adaptExt->features, VIRTIO_RING_F_EVENT_IDX)) { guestFeatures |= (1ul << VIRTIO_RING_F_EVENT_IDX); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE)) { guestFeatures |= (1ul << VIRTIO_BLK_F_WCACHE); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BARRIER)) { guestFeatures |= (1ul << VIRTIO_BLK_F_BARRIER); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) { guestFeatures |= (1ul << VIRTIO_BLK_F_RO); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SIZE_MAX)) { guestFeatures |= (1ul << VIRTIO_BLK_F_SIZE_MAX); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SEG_MAX)) { guestFeatures |= (1ul << VIRTIO_BLK_F_SEG_MAX); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BLK_SIZE)) { guestFeatures |= (1ul << VIRTIO_BLK_F_BLK_SIZE); } if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_GEOMETRY)) { guestFeatures |= (1ul << VIRTIO_BLK_F_GEOMETRY); } ScsiPortWritePortUlong((PULONG)(adaptExt->vdev.addr + VIRTIO_PCI_GUEST_FEATURES), guestFeatures); 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; }