VOID GetScsiConfig( IN PVOID DeviceExtension ) { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; ENTER_FN(); adaptExt->features = StorPortReadPortUlong(DeviceExtension, (PULONG)(adaptExt->device_base + VIRTIO_PCI_HOST_FEATURES)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, seg_max), &adaptExt->scsi_config.seg_max, sizeof(adaptExt->scsi_config.seg_max)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, num_queues), &adaptExt->scsi_config.num_queues, sizeof(adaptExt->scsi_config.num_queues)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, max_sectors), &adaptExt->scsi_config.max_sectors, sizeof(adaptExt->scsi_config.max_sectors)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, cmd_per_lun), &adaptExt->scsi_config.cmd_per_lun, sizeof(adaptExt->scsi_config.cmd_per_lun)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, event_info_size), &adaptExt->scsi_config.event_info_size, sizeof(adaptExt->scsi_config.event_info_size)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, sense_size), &adaptExt->scsi_config.sense_size, sizeof(adaptExt->scsi_config.sense_size)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, cdb_size), &adaptExt->scsi_config.cdb_size, sizeof(adaptExt->scsi_config.cdb_size)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, max_channel), &adaptExt->scsi_config.max_channel, sizeof(adaptExt->scsi_config.max_channel)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, max_target), &adaptExt->scsi_config.max_target, sizeof(adaptExt->scsi_config.max_target)); VirtIODeviceGet( &adaptExt->vdev, FIELD_OFFSET(VirtIOSCSIConfig, max_lun), &adaptExt->scsi_config.max_lun, sizeof(adaptExt->scsi_config.max_lun)); EXIT_FN(); }
LONGLONG BalloonGetSize( IN WDFOBJECT WdfDevice ) { PDEVICE_CONTEXT devCtx = GetDeviceContext(WdfDevice); u32 v; VirtIODeviceGet(&devCtx->VDevice, FIELD_OFFSET(VIRTIO_BALLOON_CONFIG, num_pages), &v, sizeof(v)); return (LONGLONG)v - devCtx->num_pages; }
VOID RhelGetDiskGeometry( IN PVOID DeviceExtension ) { u64 cap; u32 v; struct virtio_blk_geometry vgeo; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; adaptExt->features = ScsiPortReadPortUlong((PULONG)(adaptExt->vdev.addr + VIRTIO_PCI_HOST_FEATURES)); 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)) { VirtIODeviceGet( &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)) { VirtIODeviceGet(&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)) { VirtIODeviceGet( &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)) { VirtIODeviceGet( &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)); } VirtIODeviceGet( &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)) { VirtIODeviceGet( &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)); VirtIODeviceGet( &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)); VirtIODeviceGet( &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)); VirtIODeviceGet( &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)); } }
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; }