repository: C:/dev/kvm-guest-drivers-windows branch: master commit 70fff68250b1a33e8576c41eaf6e79c13b72730f Author: Yan Vugenfirer <yvuge...@redhat.com> Date: Wed Mar 31 17:42:35 2010 +0300
[WIN-GUEST_DRIVERS] Update viostor drivers (WinXP support, MSI support, new build scripts) Signed-off-by: Vadim Rozenfeld <vroze...@redhat.com> diff --git a/viostor/SOURCES b/viostor/SOURCES index edc46ef..5701b78 100644 --- a/viostor/SOURCES +++ b/viostor/SOURCES @@ -6,6 +6,7 @@ C_DEFINES = -DUSE_STORPORT=1 $(C_DEFINES) TARGETLIBS=$(SDK_LIB_PATH)\storport.lib !elseif "$(DDK_TARGET_OS)" == "WinLH" C_DEFINES = -DUSE_STORPORT=1 $(C_DEFINES) +C_DEFINES = -DMSI_SUPPORTED=1 $(C_DEFINES) TARGETLIBS=$(SDK_LIB_PATH)\storport.lib !elseif "$(DDK_TARGET_OS)" == "WinXP" TARGETLIBS=$(SDK_LIB_PATH)\scsiport.lib diff --git a/viostor/buildAll.bat b/viostor/buildAll.bat index 668efe7..526c368 100644 --- a/viostor/buildAll.bat +++ b/viostor/buildAll.bat @@ -1,90 +1,74 @@ -: -: Set global parameters: -: +...@echo off -: Use Windows 7 DDK -if "%DDKVER%"=="" set DDKVER=7600.16385.0 +set SYS_FILE_NAME=viostor -: By default DDK is installed under C:\WINDDK, but it can be installed in different location -if "%DDKISNTALLROOT%"=="" set DDKISNTALLROOT=C:\WINDDK\ -set BUILDROOT=%DDKISNTALLROOT%%DDKVER% -set X64ENV=x64 -if "%DDKVER%"=="6000" set X64ENV=amd64 +for %%A in (Win7 Wnet Wlh WXp) do for %%B in (32 64) do call :%%A_%%B +goto :eof -if not "%1"=="" goto parameters_here -echo no parameters specified, rebuild all -call clean.bat -call "%0" WIN7 WIN7_64 Vista Vista64 Win2003 Win200364 XP +:buildsys +call buildOne.bat %1 %2 goto :eof -:parameters_here -:nextparam -if "%1"=="" goto :eof -goto %1 -:continue -shift -goto nextparam - -:Win7 -set DDKBUILDENV= -pushd %BUILDROOT% -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% fre WIN7 -popd -build -cZg - -goto continue - -:Win7_64 -set DDKBUILDENV= -pushd %BUILDROOT% -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% %X64ENV% fre WIN7 -popd -build -cZg - -goto continue - - -:Vista -set DDKBUILDENV= -pushd %BUILDROOT% -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% fre Wlh -popd -build -cZg +:packsys +call packOne.bat %1 %2 %SYS_FILE_NAME% %3 +goto :eof -goto continue +:buildpack +call :buildsys %1 %2 +call :packsys %1 %2 %3 +set BUILD_OS= +set BUILD_ARC= +set INF_FILE_NAME= +goto :eof -:Vista64 -set DDKBUILDENV= -pushd %BUILDROOT% -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% %X64ENV% fre Wlh -popd -build -cZg +:WIN7_32 +set BUILD_OS=Win7 +set BUILD_ARC=x86 +set INF_FILE_NAME=Wlh +call :buildpack %BUILD_OS% %BUILD_ARC% %INF_FILE_NAME% +goto :eof -goto continue +:WIN7_64 +set BUILD_OS=Win7 +set BUILD_ARC=x64 +set INF_FILE_NAME=Wlh +call :buildpack %BUILD_OS% %BUILD_ARC% %INF_FILE_NAME% +goto :eof -:Win2003 -set DDKBUILDENV= -pushd %BUILDROOT% -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% fre WNET -popd -build -cZg +:WLH_32 +set BUILD_OS=Wlh +set BUILD_ARC=x86 +set INF_FILE_NAME=Wlh +call :buildpack %BUILD_OS% %BUILD_ARC% %INF_FILE_NAME% +goto :eof -goto continue +:WLH_64 +set BUILD_OS=Wlh +set BUILD_ARC=x64 +set INF_FILE_NAME=Wlh +call :buildpack %BUILD_OS% %BUILD_ARC% %INF_FILE_NAME% +goto :eof -:Win200364 -set DDKBUILDENV= -pushd %BUILDROOT% -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% %X64ENV% fre WNET -popd -build -cZg +:WNET_32 +set BUILD_OS=Wnet +set BUILD_ARC=x86 +set INF_FILE_NAME=Wnet +call :buildpack %BUILD_OS% %BUILD_ARC% %INF_FILE_NAME% +goto :eof -goto continue +:WNET_64 +set BUILD_OS=Wnet +set BUILD_ARC=x64 +set INF_FILE_NAME=Wnet +call :buildpack %BUILD_OS% %BUILD_ARC% %INF_FILE_NAME% +goto :eof -:XP -set DDKBUILDENV= -pushd %BUILDROOT% -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% fre WXP -popd -build -cZg +:WXP_32 +set BUILD_OS=WXp +set BUILD_ARC=x86 +set INF_FILE_NAME=Wxp +call :buildpack %BUILD_OS% %BUILD_ARC% %INF_FILE_NAME% +goto :eof +:WXP_64 goto :eof diff --git a/viostor/buildDDK.bat b/viostor/buildDDK.bat deleted file mode 100644 index 8c39eee..0000000 --- a/viostor/buildDDK.bat +++ /dev/null @@ -1,7 +0,0 @@ -set DDKVER=6001.18001 -set BUILDROOT=C:\WINDDK\%DDKVER% -pushd %BUILDROOT% -set X64ENV=x64 -call %BUILDROOT%\bin\setenv.bat %BUILDROOT% fre %1 %2 -popd -build -cZg diff --git a/viostor/buildOne.bat b/viostor/buildOne.bat new file mode 100644 index 0000000..8ecc35d --- /dev/null +++ b/viostor/buildOne.bat @@ -0,0 +1,13 @@ +...@echo off + +if "%DDKVER%"=="" set DDKVER=7600.16385.0 +set BUILDROOT=C:\WINDDK\%DDKVER% + +set DDKBUILDENV= +pushd %BUILDROOT% +call %BUILDROOT%\bin\setenv.bat %BUILDROOT% %2 fre %1 no_oacr +popd +build -cZg + +set DDKVER= +set BUILDROOT= \ No newline at end of file diff --git a/viostor/buildOne_bat b/viostor/buildOne_bat new file mode 100644 index 0000000..8ecc35d --- /dev/null +++ b/viostor/buildOne_bat @@ -0,0 +1,13 @@ +...@echo off + +if "%DDKVER%"=="" set DDKVER=7600.16385.0 +set BUILDROOT=C:\WINDDK\%DDKVER% + +set DDKBUILDENV= +pushd %BUILDROOT% +call %BUILDROOT%\bin\setenv.bat %BUILDROOT% %2 fre %1 no_oacr +popd +build -cZg + +set DDKVER= +set BUILDROOT= \ No newline at end of file diff --git a/viostor/clean.bat b/viostor/clean.bat index e47a389..a66b789 100644 --- a/viostor/clean.bat +++ b/viostor/clean.bat @@ -1,16 +1,15 @@ -rmdir /S /Q Debug -rmdir /S /Q Release +...@echo on + +rmdir /S /Q .\Install + rmdir /S /Q objfre_wxp_x86 rmdir /S /Q objfre_wnet_x86 rmdir /S /Q objfre_wnet_amd64 -rmdir /S /Q objfre_w2k_x86 rmdir /S /Q objfre_wlh_x86 rmdir /S /Q objfre_wlh_amd64 rmdir /S /Q objfre_win7_x86 rmdir /S /Q objfre_win7_amd64 - - del /F *.log *.wrn *.err diff --git a/viostor/packOne.bat b/viostor/packOne.bat new file mode 100644 index 0000000..8afd09a --- /dev/null +++ b/viostor/packOne.bat @@ -0,0 +1,61 @@ +...@echo off +: Param1 - Win7 | Wlh | Wnet | XP +: Param2 - x86|x64 +: Param3 - sys name +: Param3 - inf name + +if "%2"=="x64" set %%2=amd64 + +if /i "%1"=="Win7" goto :checkarch +if /i "%1"=="Wlh" goto :checkarch +if /i "%1"=="Wnet" goto :checkarch +if /i "%1"=="WXp" goto :checkarch +goto :printerr +:checkarch +if /i "%2"=="x86" goto :makeinstall +if /i "%2"=="x64" goto :makeinstall +:printerr +echo wrong parameters (1)%1 (2)%2 (3)%3 +pause +goto :eof + +:makeinstall +if "%DDKVER%"=="" set DDKVER=7600.16385.0 +set BUILDROOT=C:\WINDDK\%DDKVER% + +set INST_OS=%1 +set INST_ARC=%2 +set SYS_NAME=%3 +set INF_NAME=%4 +rem set INST_EXT=INST_ARC + +if /i "%INST_ARC%"=="x64" goto :set_x64 + +set INST_EXT=i386 +goto :startcopy + +:set_x64 +set INST_ARC=amd64 +set INST_EXT=amd64 + +:startcopy +set SYS_PATH_AND_NAME=objfre_%INST_OS%_%INST_ARC%\%INST_EXT%\%SYS_NAME%.sys +set PDB_PATH_AND_NAME=objfre_%INST_OS%_%INST_ARC%\%INST_EXT%\%SYS_NAME%.pdb +set INF_PATH_AND_NAME=%INF_NAME%.inf + +rem echo makeinstall %1 %2 %3 %4 +mkdir .\Install\%INST_OS%\%INST_ARC% +del /Q .\Install\%INST_OS%\%INST_ARC%\%FILE_NAME%.* +copy /Y %SYS_PATH_AND_NAME% .\Install\%INST_OS%\%INST_ARC% +copy /Y %PDB_PATH_AND_NAME% .\Install\%INST_OS%\%INST_ARC% +copy /Y %INF_PATH_AND_NAME% .\Install\%INST_OS%\%INST_ARC%\%SYS_NAME%.inf + +set INST_OS= +set INST_ARC= +set SYS_NAME= +set INF_NAME= +set SYS_PATH_AND_NAME= +set PDB_PATH_AND_NAME= +set INF_PATH_AND_NAME= +set DDKVER= +set BUILDROOT= \ No newline at end of file diff --git a/viostor/virtio_pci.c b/viostor/virtio_pci.c index a72b019..ffa2ed0 100644 --- a/viostor/virtio_pci.c +++ b/viostor/virtio_pci.c @@ -30,25 +30,6 @@ #include "virtio_stor.h" -VOID -VirtIODeviceDumpRegisters( - IN PVOID DeviceExtension) -{ - PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; - - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s\n", __FUNCTION__)); - - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_HOST_FEATURES] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_HOST_FEATURES)))); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_GUEST_FEATURES] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_GUEST_FEATURES)))); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_QUEUE_PFN] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN)))); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_QUEUE_NUM] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_NUM)))); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_QUEUE_SEL] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_SEL)))); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_QUEUE_NOTIFY] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_QUEUE_NOTIFY)))); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_STATUS] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_STATUS)))); - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("[VIRTIO_PCI_ISR] = %x\n", ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_ISR)))); -} - - bool VirtIODeviceGetHostFeature( IN PVOID DeviceExtension, diff --git a/viostor/virtio_pci.h b/viostor/virtio_pci.h index 3e143d4..9916759 100644 --- a/viostor/virtio_pci.h +++ b/viostor/virtio_pci.h @@ -82,10 +82,6 @@ VOID VirtIODeviceReset( IN PVOID DeviceExtension); -VOID -VirtIODeviceDumpRegisters( - IN PVOID DeviceExtension); - bool VirtIODeviceGetHostFeature( IN PVOID DeviceExtension, diff --git a/viostor/virtio_ring.c b/viostor/virtio_ring.c index 2911cef..cedb4f5 100644 --- a/viostor/virtio_ring.c +++ b/viostor/virtio_ring.c @@ -42,6 +42,63 @@ initialize_virtqueue( //#define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) #define to_vvq(_vq) (struct vring_virtqueue *)_vq +#if (NTDDI_VERSION >= NTDDI_VISTA) +/* Set up an indirect table of descriptors and add it to the queue. */ +static +int +vring_add_indirect( + IN struct vring_virtqueue *vq, + IN struct VirtIOBufferDescriptor sg[], + IN unsigned int out, + IN unsigned int in, + IN PVOID va) +{ + struct vring_desc *desc = (struct vring_desc *)va; + unsigned head; + unsigned int i; + STOR_PHYSICAL_ADDRESS addr; + ULONG len; + + addr = StorPortGetPhysicalAddress(vq->vq.DeviceExtension, NULL, desc, &len); + if (!addr.QuadPart) { + return vq->vring.num; + } + /* Transfer entries from the sg list into the indirect page */ + for (i = 0; i < out; i++) { + desc[i].flags = VRING_DESC_F_NEXT; + desc[i].addr = sg->physAddr.QuadPart; + desc[i].len = sg->ulSize; + desc[i].next = i+1; + sg++; + } + for (; i < (out + in); i++) { + desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; + desc[i].addr = sg->physAddr.QuadPart; + desc[i].len = sg->ulSize; + desc[i].next = i+1; + sg++; + } + + /* Last one doesn't continue. */ + desc[i-1].flags &= ~VRING_DESC_F_NEXT; + desc[i-1].next = 0; + + /* We're about to use a buffer */ + vq->num_free--; + + /* Use a single buffer which doesn't continue */ + head = vq->free_head; + vq->vring.desc[head].flags = VRING_DESC_F_INDIRECT; + vq->vring.desc[head].addr = addr.QuadPart; + vq->vring.desc[head].len = i * sizeof(struct vring_desc); + + /* Update free pointer */ + vq->free_head = vq->vring.desc[head].next; + + return head; +} +#endif + static int vring_add_buf( @@ -53,12 +110,28 @@ vring_add_buf( { struct vring_virtqueue *vq = to_vvq(_vq); unsigned int i, avail, head, prev; +#if (NTDDI_VERSION >= NTDDI_VISTA) + PSCSI_REQUEST_BLOCK Srb; + PRHEL_SRB_EXTENSION srbExt; + PADAPTER_EXTENSION adaptExt; + pblk_req vbr; +#endif if(data == NULL) { RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s: data is NULL!\n", __FUNCTION__) ); return -1; } - +#if (NTDDI_VERSION >= NTDDI_VISTA) + adaptExt = (PADAPTER_EXTENSION)vq->vq.DeviceExtension; + vbr = (pblk_req) data; + Srb = (PSCSI_REQUEST_BLOCK)vbr->req; + srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; + if (srbExt->addr && (out + in) > 1 && vq->num_free) { + head = vring_add_indirect(vq, sg, out, in, srbExt->addr); + if (head != vq->vring.num) + goto add_head; + } +#endif if(out + in > vq->vring.num) { RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s: out + in > vq->vring.num!\n", __FUNCTION__) ); return -1; @@ -104,7 +177,9 @@ vring_add_buf( /* Update free pointer */ vq->free_head = i; - +#if (NTDDI_VERSION >= NTDDI_VISTA) +add_head: +#endif /* Set token. */ vq->data[head] = data; @@ -118,12 +193,15 @@ vring_add_buf( RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s: Added buffer head %i to %p\n", __FUNCTION__, head, vq) ); - - return 0; +#if (NTDDI_VERSION >= NTDDI_VISTA) + if (adaptExt->indirect) + return vq->num_free ? vq->vring.num : 0; +#endif + return vq->num_free; } -static -VOID +static +VOID vring_kick_always( struct virtqueue *_vq) { @@ -174,12 +252,23 @@ detach_buf( unsigned int head) { unsigned int i; + PVOID addr; +#if (NTDDI_VERSION >= NTDDI_VISTA) + STOR_PHYSICAL_ADDRESS pa; +#endif /* Clear data ptr. */ vq->data[head] = NULL; /* Put back on free list: find end */ i = head; +#if (NTDDI_VERSION >= NTDDI_VISTA) + if (vq->vring.desc[i].flags & VRING_DESC_F_INDIRECT) { + pa.QuadPart = vq->vring.desc[i].addr; + addr = StorPortGetVirtualAddress(vq->vq.DeviceExtension, pa); + StorPortFreePool(vq->vq.DeviceExtension, addr); + } +#endif while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) { i = vq->vring.desc[i].next; vq->num_free++; @@ -233,7 +322,7 @@ vring_get_buf( unsigned int i; if (!more_used(vq)) { - RhelDbgPrint(TRACE_LEVEL_ERROR, ("No more buffers in queue: last_used_idx %d vring.used->idx %d\n", vq->last_used_idx, vq->vring.used->idx)); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("No more buffers in queue: last_used_idx %d vring.used->idx %d\n", vq->last_used_idx, vq->vring.used->idx)); return NULL; } @@ -242,14 +331,14 @@ vring_get_buf( i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id; *len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len; - RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s>>> id %d, len %d\n", __FUNCTION__, i, *len) ); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("%s>>> id %d, len %d\n", __FUNCTION__, i, *len) ); if (i >= vq->vring.num) { - RhelDbgPrint(TRACE_LEVEL_ERROR, ("id %u out of range\n", i) ); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("id %u out of range\n", i) ); return NULL; } if (!vq->data[i]) { - RhelDbgPrint(TRACE_LEVEL_ERROR, ("id %u is not a head!\n", i) ); + RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("id %u is not a head!\n", i) ); return NULL; } @@ -314,11 +403,11 @@ initialize_virtqueue( vq->num_free = num; vq->free_head = 0; for (i = 0; i < num-1; i++) - vq->vring.desc[i].next = i+1; + vq->vring.desc[i].next = (u16)(i+1); } -struct +struct virtqueue* vring_new_virtqueue( unsigned int num, @@ -327,7 +416,6 @@ vring_new_virtqueue( IN VOID (*notify)(struct virtqueue *)) { struct vring_virtqueue *vq; - unsigned int i; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s: Creating new virtqueue>>> size %d, pages %p\n", __FUNCTION__, num, pages) ); diff --git a/viostor/virtio_ring.h b/viostor/virtio_ring.h index c43f954..6992000 100644 --- a/viostor/virtio_ring.h +++ b/viostor/virtio_ring.h @@ -19,15 +19,19 @@ #include "VirtIO.h" /* This marks a buffer as continuing via the next field. */ -#define VRING_DESC_F_NEXT 1 +#define VRING_DESC_F_NEXT 1 /* This marks a buffer as write-only (otherwise read-only). */ -#define VRING_DESC_F_WRITE 2 +#define VRING_DESC_F_WRITE 2 +#define VRING_DESC_F_INDIRECT 4 /* This means don't notify other side when buffer added. */ -#define VRING_USED_F_NO_NOTIFY 1 +#define VRING_USED_F_NO_NOTIFY 1 /* This means don't interrupt guest when buffer consumed. */ -#define VRING_AVAIL_F_NO_INTERRUPT 1 +#define VRING_AVAIL_F_NO_INTERRUPT 1 +#define VIRTIO_RING_F_INDIRECT_DESC 28 + +#pragma warning(disable:4200) #pragma pack (push) #pragma pack (1) diff --git a/viostor/virtio_stor.c b/viostor/virtio_stor.c index d363909..7f9e9f1 100644 --- a/viostor/virtio_stor.c +++ b/viostor/virtio_stor.c @@ -16,7 +16,7 @@ #include "virtio_stor_utils.h" #include "virtio_stor_hw_helper.h" -ULONG RhelDbgLevel = TRACE_LEVEL_NONE; +ULONG RhelDbgLevel = TRACE_LEVEL_ERROR; BOOLEAN IsCrashDumpMode; BOOLEAN @@ -202,6 +202,11 @@ VirtIoFindAdapter( ULONG vq_sz; USHORT pageNum; + UNREFERENCED_PARAMETER( HwContext ); + UNREFERENCED_PARAMETER( BusInformation ); + UNREFERENCED_PARAMETER( ArgumentString ); + UNREFERENCED_PARAMETER( Again ); + RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; @@ -210,7 +215,6 @@ VirtIoFindAdapter( ConfigInfo->Master = TRUE; ConfigInfo->ScatterGather = TRUE; - ConfigInfo->CachesData = TRUE; ConfigInfo->DmaWidth = Width32Bits; ConfigInfo->Dma32BitAddresses = TRUE; ConfigInfo->Dma64BitAddresses = TRUE; @@ -220,7 +224,7 @@ VirtIoFindAdapter( ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex; #ifdef MSI_SUPPORTED ConfigInfo->HwMSInterruptRoutine = VirtIoMSInterruptRoutine; - ConfigInfo->InterruptSynchronizationMode=InterruptSynchronizePerMessage;//InterruptSynchronizeAll;// + ConfigInfo->InterruptSynchronizationMode=InterruptSynchronizePerMessage; #endif #else ConfigInfo->MapBuffers = TRUE; @@ -296,11 +300,14 @@ VirtIoFindAdapter( return SP_RETURN_ERROR; } + VirtIODeviceReset(DeviceExtension); ScsiPortWritePortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_SEL), (USHORT)0); if (adaptExt->dump_mode) { ScsiPortWritePortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_PFN),(USHORT)0); } + adaptExt->features = ScsiPortReadPortUlong((PULONG)(adaptExt->device_base + VIRTIO_PCI_HOST_FEATURES)); + ConfigInfo->CachesData = CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE) ? TRUE : FALSE; pageNum = ScsiPortReadPortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_QUEUE_NUM)); vr_sz = vring_size(pageNum,PAGE_SIZE); @@ -309,12 +316,20 @@ VirtIoFindAdapter( if(adaptExt->dump_mode) { ConfigInfo->NumberOfPhysicalBreaks = 8; } else { - ConfigInfo->NumberOfPhysicalBreaks = 16; + ConfigInfo->NumberOfPhysicalBreaks = MAX_PHYS_SEGMENTS + 1; } - ConfigInfo->MaximumTransferLength = ConfigInfo->NumberOfPhysicalBreaks * PAGE_SIZE; + ConfigInfo->MaximumTransferLength = 0x00FFFFFF; adaptExt->queue_depth = pageNum / ConfigInfo->NumberOfPhysicalBreaks - 1; +#if (NTDDI_VERSION >= NTDDI_VISTA) + if(!adaptExt->dump_mode) { + adaptExt->indirect = CHECKBIT(adaptExt->features, VIRTIO_RING_F_INDIRECT_DESC); + } + if(adaptExt->indirect) { + adaptExt->queue_depth <<= 1; + } +#endif RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("breaks_number = %x queue_depth = %x\n", ConfigInfo->NumberOfPhysicalBreaks, adaptExt->queue_depth)); @@ -338,8 +353,9 @@ VirtIoFindAdapter( adaptExt->virtqueue = (vring_virtqueue*)((ULONG_PTR)(adaptExt->pci_vq_info.queue) + vr_sz); InitializeListHead(&adaptExt->list_head); +#ifdef USE_STORPORT InitializeListHead(&adaptExt->complete_list); - +#endif return SP_RETURN_FOUND; } @@ -369,11 +385,12 @@ VirtIoHwInitialize( PADAPTER_EXTENSION adaptExt; u64 cap; u32 v; - struct virtio_blk_geometry vgeo; #ifdef MSI_SUPPORTED MESSAGE_INTERRUPT_INFORMATION msi_info; #endif + struct virtio_blk_geometry vgeo; + RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("%s (%d)\n", __FUNCTION__, KeGetCurrentIrql())); adaptExt = (PADAPTER_EXTENSION)DeviceExtension; @@ -411,15 +428,15 @@ VirtIoHwInitialize( return FALSE; } - if (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_BARRIER)) { + if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BARRIER)) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_BARRIER\n")); } - if (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_RO)) { + if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) { RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_RO\n")); } - if (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_SIZE_MAX)) { + if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SIZE_MAX)) { VirtIODeviceGet( DeviceExtension, FIELD_OFFSET(blk_config, size_max), &v, sizeof(v)); adaptExt->info.size_max = v; @@ -427,21 +444,21 @@ VirtIoHwInitialize( adaptExt->info.size_max = SECTOR_SIZE; } - if (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_SEG_MAX)) { + if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SEG_MAX)) { VirtIODeviceGet( DeviceExtension, 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 (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_BLK_SIZE)) { + if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BLK_SIZE)) { VirtIODeviceGet( DeviceExtension, FIELD_OFFSET(blk_config, blk_size), &v, sizeof(v)); adaptExt->info.blk_size = v; RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_BLK_SIZE = %d\n", adaptExt->info.blk_size)); } - if (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_GEOMETRY)) { + if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_GEOMETRY)) { VirtIODeviceGet( DeviceExtension, FIELD_OFFSET(blk_config, geometry), &vgeo, sizeof(vgeo)); adaptExt->info.geometry.cylinders= vgeo.cylinders; @@ -450,19 +467,32 @@ VirtIoHwInitialize( 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)); } - if (VirtIODeviceGetHostFeature(DeviceExtension, VIRTIO_BLK_F_IDENTIFY)) { - VirtIODeviceGet(DeviceExtension, FIELD_OFFSET(blk_config, identify), - &adaptExt->info.identify, VIRTIO_BLK_ID_LEN); - adaptExt->has_sn = TRUE; - RhelDbgPrint(TRACE_LEVEL_INFORMATION, ("VIRTIO_BLK_F_IDENTIFY. \n")); - } - - VirtIODeviceGet( DeviceExtension, 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( DeviceExtension, FIELD_OFFSET(blk_config, physical_block_exp), + &adaptExt->info.physical_block_exp, sizeof(adaptExt->info.physical_block_exp)); + RhelDbgPrint(TRACE_LEVEL_ERROR, ("physical_block_exp = %d\n", adaptExt->info.physical_block_exp)); + + VirtIODeviceGet( DeviceExtension, FIELD_OFFSET(blk_config, alignment_offset), + &adaptExt->info.alignment_offset, sizeof(adaptExt->info.alignment_offset)); + RhelDbgPrint(TRACE_LEVEL_ERROR, ("alignment_offset = %d\n", adaptExt->info.alignment_offset)); + + VirtIODeviceGet( DeviceExtension, FIELD_OFFSET(blk_config, min_io_size), + &adaptExt->info.min_io_size, sizeof(adaptExt->info.min_io_size)); + RhelDbgPrint(TRACE_LEVEL_ERROR, ("min_io_size = %d\n", adaptExt->info.min_io_size)); + + VirtIODeviceGet( DeviceExtension, FIELD_OFFSET(blk_config, opt_io_size), + &adaptExt->info.opt_io_size, sizeof(adaptExt->info.opt_io_size)); + RhelDbgPrint(TRACE_LEVEL_ERROR, ("opt_io_size = %d\n", adaptExt->info.opt_io_size)); + + } + + memset(&adaptExt->inquiry_data, 0, sizeof(INQUIRYDATA)); adaptExt->inquiry_data.ANSIVersion = 4; @@ -481,7 +511,6 @@ VirtIoHwInitialize( return StorPortEnablePassiveInitialization(DeviceExtension, VirtIoPassiveInitializeRoutine); } #endif - return TRUE; } @@ -504,14 +533,27 @@ VirtIoStartIo( } case SRB_FUNCTION_PNP: case SRB_FUNCTION_POWER: - case SRB_FUNCTION_SHUTDOWN: - case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_RESET_DEVICE: case SRB_FUNCTION_RESET_LOGICAL_UNIT: { Srb->SrbStatus = SRB_STATUS_SUCCESS; CompleteSRB(DeviceExtension, Srb); return TRUE; } + case SRB_FUNCTION_SHUTDOWN: + case SRB_FUNCTION_FLUSH: { + if(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE)) { + Srb->SrbStatus = SRB_STATUS_PENDING; + if(!RhelDoFlush(DeviceExtension, Srb)) { + Srb->SrbStatus = SRB_STATUS_BUSY; + CompleteSRB(DeviceExtension, Srb); + } + } else { + Srb->SrbStatus = SRB_STATUS_SUCCESS; + CompleteSRB(DeviceExtension, Srb); + } + return TRUE; + } + default: { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; CompleteSRB(DeviceExtension, Srb); @@ -530,10 +572,13 @@ VirtIoStartIo( CompleteSRB(DeviceExtension, Srb); return TRUE; } + + case SCSIOP_READ_CAPACITY16: case SCSIOP_READ_CAPACITY: { PREAD_CAPACITY_DATA readCap; PREAD_CAPACITY_DATA_EX readCapEx; u64 lastLBA; + u64 blocksize; #ifdef USE_STORPORT BOOLEAN depthSet; depthSet = StorPortSetDeviceQueueDepth(DeviceExtension, @@ -546,7 +591,8 @@ VirtIoStartIo( readCap = (PREAD_CAPACITY_DATA)Srb->DataBuffer; readCapEx = (PREAD_CAPACITY_DATA_EX)Srb->DataBuffer; - lastLBA = adaptExt->info.capacity - 1; + lastLBA = (adaptExt->info.capacity >> adaptExt->info.physical_block_exp) - 1; + blocksize = adaptExt->info.size_max * (1 << adaptExt->info.physical_block_exp); if (Srb->DataTransferLength == sizeof(READ_CAPACITY_DATA)) { if (lastLBA > 0xFFFFFFFF) { readCap->LogicalBlockAddress = (ULONG)-1; @@ -555,14 +601,14 @@ VirtIoStartIo( &lastLBA); } REVERSE_BYTES(&readCap->BytesPerBlock, - &adaptExt->info.size_max); + &blocksize); } else { ASSERT(Srb->DataTransferLength == sizeof(READ_CAPACITY_DATA_EX)); REVERSE_BYTES_QUAD(&readCapEx->LogicalBlockAddress.QuadPart, &lastLBA); - REVERSE_BYTES(&readCap->BytesPerBlock, - &adaptExt->info.size_max); + REVERSE_BYTES(&readCapEx->BytesPerBlock, + &blocksize); } Srb->SrbStatus = SRB_STATUS_SUCCESS; @@ -570,7 +616,9 @@ VirtIoStartIo( return TRUE; } case SCSIOP_READ: - case SCSIOP_WRITE: { + case SCSIOP_WRITE: + case SCSIOP_READ16: + case SCSIOP_WRITE16: { Srb->SrbStatus = SRB_STATUS_PENDING; if(!RhelDoReadWrite(DeviceExtension, Srb)) { Srb->SrbStatus = SRB_STATUS_BUSY; @@ -590,6 +638,7 @@ VirtIoStartIo( case SCSIOP_RELEASE_UNIT: case SCSIOP_RELEASE_UNIT10: case SCSIOP_VERIFY: + case SCSIOP_VERIFY16: case SCSIOP_SYNCHRONIZE_CACHE: case SCSIOP_MEDIUM_REMOVAL: { Srb->SrbStatus = SRB_STATUS_SUCCESS; @@ -622,7 +671,6 @@ VirtIoInterrupt( { pblk_req vbr; unsigned int len; - unsigned long flags; PADAPTER_EXTENSION adaptExt; BOOLEAN isInterruptServiced = FALSE; PSCSI_REQUEST_BLOCK Srb; @@ -659,6 +707,9 @@ VirtIoResetBus( IN ULONG PathId ) { + UNREFERENCED_PARAMETER( DeviceExtension ); + UNREFERENCED_PARAMETER( PathId ); + RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("<--->%s\n", __FUNCTION__)); return TRUE; } @@ -707,7 +758,7 @@ VirtIoAdapterControl( RhelDbgPrint(TRACE_LEVEL_VERBOSE, ("ScsiRestartAdapter\n")); adaptExt->pci_vq_info.vq = NULL; #ifdef MSI_SUPPORTED - if(!adaptExt->dump_mode & adaptExt->msix_vectors) { + if(!adaptExt->dump_mode && adaptExt->msix_vectors) { adaptExt->pci_vq_info.vq = VirtIODeviceFindVirtualQueue(DeviceExtension, 0, adaptExt->msix_vectors); } #endif @@ -784,7 +835,7 @@ VirtIoBuildIo( srbExt->vbr.sg[sgElement].ulSize = sgList->List[i].Length; } - srbExt->vbr.out_hdr.sector = RhelGetLba(cdb); + srbExt->vbr.out_hdr.sector = RhelGetLba(DeviceExtension, cdb); srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (struct request *)Srb; @@ -816,7 +867,6 @@ VirtIoMSInterruptRoutine ( { pblk_req vbr; unsigned int len; - unsigned long flags; PADAPTER_EXTENSION adaptExt; PSCSI_REQUEST_BLOCK Srb; @@ -889,13 +939,8 @@ RhelScsiGetInquiryData( PVPD_SERIAL_NUMBER_PAGE SerialPage; SerialPage = (PVPD_SERIAL_NUMBER_PAGE)Srb->DataBuffer; SerialPage->PageCode = VPD_SERIAL_NUMBER; - if(adaptExt->has_sn) { - SerialPage->PageLength = VIRTIO_BLK_ID_SN_BYTES; - ScsiPortMoveMemory(&SerialPage->SerialNumber[0], &adaptExt->info.identify[VIRTIO_BLK_ID_SN], VIRTIO_BLK_ID_SN_BYTES); - } else { - SerialPage->PageLength = 1; - SerialPage->SerialNumber[0] = '0'; - } + SerialPage->PageLength = 1; + SerialPage->SerialNumber[0] = '0'; Srb->DataTransferLength = sizeof(VPD_SERIAL_NUMBER_PAGE) + SerialPage->PageLength; } else if ((cdb->CDB6INQUIRY3.PageCode == VPD_DEVICE_IDENTIFIERS) && @@ -943,7 +988,10 @@ RhelScsiReportLuns( ) { UCHAR SrbStatus = SRB_STATUS_SUCCESS; - PUCHAR data = Srb->DataBuffer; + PUCHAR data = (PUCHAR)Srb->DataBuffer; + + UNREFERENCED_PARAMETER( DeviceExtension ); + data[3]=8; Srb->ScsiStatus = SCSISTAT_GOOD; Srb->SrbStatus = SrbStatus; @@ -963,6 +1011,9 @@ RhelScsiGetModeSense( PMODE_PARAMETER_HEADER header; PMODE_CACHING_PAGE cachePage; PMODE_PARAMETER_BLOCK blockDescriptor; + PADAPTER_EXTENSION adaptExt; + + adaptExt = (PADAPTER_EXTENSION)DeviceExtension; ModeSenseDataLen = Srb->DataTransferLength; @@ -987,11 +1038,11 @@ RhelScsiGetModeSense( header->ModeDataLength = sizeof(MODE_CACHING_PAGE) + 3; cachePage = (PMODE_CACHING_PAGE)header; - (ULONG_PTR)cachePage += sizeof(MODE_PARAMETER_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 = 1; + cachePage->WriteCacheEnable = CHECKBIT(adaptExt->features, VIRTIO_BLK_F_WCACHE) ? 1 : 0; Srb->DataTransferLength = sizeof(MODE_PARAMETER_HEADER) + sizeof(MODE_CACHING_PAGE); @@ -1019,7 +1070,7 @@ RhelScsiGetModeSense( header->BlockDescriptorLength = sizeof(MODE_PARAMETER_BLOCK); blockDescriptor = (PMODE_PARAMETER_BLOCK)header; - (ULONG_PTR)blockDescriptor += sizeof(MODE_PARAMETER_HEADER); + blockDescriptor = (PMODE_PARAMETER_BLOCK)((unsigned char *)(blockDescriptor) + (ULONG)sizeof(MODE_PARAMETER_HEADER)); memset(blockDescriptor, 0, sizeof(MODE_PARAMETER_HEADER)); @@ -1037,58 +1088,6 @@ RhelScsiGetModeSense( return SrbStatus; } -ULONGLONG -RhelGetLba( - PCDB Cdb - ) -{ - - EIGHT_BYTE lba; - - switch (Cdb->CDB6GENERIC.OperationCode) { - - case SCSIOP_READ: - case SCSIOP_WRITE: - case SCSIOP_WRITE_VERIFY: { - lba.AsULongLong = 0; - lba.Byte0 = Cdb->CDB10.LogicalBlockByte3; - lba.Byte1 = Cdb->CDB10.LogicalBlockByte2; - lba.Byte2 = Cdb->CDB10.LogicalBlockByte1; - lba.Byte3 = Cdb->CDB10.LogicalBlockByte0; - return lba.AsULongLong; - } - case SCSIOP_READ6: - case SCSIOP_WRITE6: { - lba.AsULongLong = 0; - lba.Byte0 = Cdb->CDB6READWRITE.LogicalBlockMsb1; - lba.Byte1 = Cdb->CDB6READWRITE.LogicalBlockMsb0; - lba.Byte2 = Cdb->CDB6READWRITE.LogicalBlockLsb; - return lba.AsULongLong; - } - case SCSIOP_READ12: - case SCSIOP_WRITE12: - case SCSIOP_WRITE_VERIFY12: { - lba.AsULongLong = 0; - REVERSE_BYTES(&lba, &Cdb->CDB12.LogicalBlock[0]); - return lba.AsULongLong; - } - case SCSIOP_READ16: - case SCSIOP_WRITE16: - case SCSIOP_WRITE_VERIFY16: { - lba.AsULongLong = 0; - REVERSE_BYTES_QUAD(&lba, &Cdb->CDB16.LogicalBlock[0]); - return lba.AsULongLong; - } - default: { - break; - } - } - - ASSERT(FALSE); - return (ULONGLONG)-1; - -} - VOID CompleteSRB( IN PVOID DeviceExtension, @@ -1115,9 +1114,13 @@ CompleteDPC( IN ULONG MessageID ) { - PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK)vbr->req; - PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; - + PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK)vbr->req; +#ifdef USE_STORPORT + PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; +#else + PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; + UNREFERENCED_PARAMETER( MessageID ); +#endif RemoveEntryList(&vbr->list_entry); #ifdef USE_STORPORT @@ -1125,15 +1128,26 @@ CompleteDPC( InsertTailList(&adaptExt->complete_list, &vbr->list_entry); StorPortIssueDpc(DeviceExtension, &adaptExt->completion_dpc, - (PVOID)MessageID, + ULongToPtr(MessageID), NULL); return; } -#endif CompleteSRB(DeviceExtension, Srb); +#else + ScsiPortNotification(RequestComplete, + DeviceExtension, + Srb); + if(srbExt->call_next) { + ScsiPortNotification(NextLuRequest, + DeviceExtension, + Srb->PathId, + Srb->TargetId, + Srb->Lun); + } +#endif } - #ifdef USE_STORPORT +#pragma warning(disable: 4100 4701) VOID CompleteDpcRoutine( IN PSTOR_DPC Dpc, @@ -1144,42 +1158,62 @@ CompleteDpcRoutine( { STOR_LOCK_HANDLE LockHandle; PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)Context; - ULONG MessageID = (ULONG)SystemArgument1; + +#ifdef MSI_SUPPORTED + ULONG MessageID = PtrToUlong(SystemArgument1); ULONG OldIrql; +#endif +#ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); } else { +#endif StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); +#ifdef MSI_SUPPORTED } +#endif + while (!IsListEmpty(&adaptExt->complete_list)) { PSCSI_REQUEST_BLOCK Srb; pblk_req vbr; vbr = (pblk_req) RemoveHeadList(&adaptExt->complete_list); Srb = (PSCSI_REQUEST_BLOCK)vbr->req; +#ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); } else { +#endif StorPortReleaseSpinLock (Context, &LockHandle); +#ifdef MSI_SUPPORTED } +#endif ScsiPortNotification(RequestComplete, Context, Srb); +#ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortAcquireMSISpinLock (Context, MessageID, &OldIrql); } else { +#endif StorPortAcquireSpinLock ( Context, InterruptLock , NULL, &LockHandle); +#ifdef MSI_SUPPORTED } +#endif } +#ifdef MSI_SUPPORTED if(adaptExt->msix_vectors) { StorPortReleaseMSISpinLock (Context, MessageID, OldIrql); } else { +#endif StorPortReleaseSpinLock (Context, &LockHandle); +#ifdef MSI_SUPPORTED } +#endif return; } #endif diff --git a/viostor/virtio_stor.h b/viostor/virtio_stor.h index 456fa0e..9c99b75 100644 --- a/viostor/virtio_stor.h +++ b/viostor/virtio_stor.h @@ -30,29 +30,29 @@ typedef struct VirtIOBufferDescriptor VIO_SG, *PVIO_SG; /* Feature bits */ -#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ -#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ -#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ -#define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */ -#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ -#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ +#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */ +#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ +#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ +#define VIRTIO_BLK_F_GEOMETRY 4 /* Legacy geometry available */ +#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */ +#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/ #define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */ -#define VIRTIO_BLK_F_IDENTIFY 8 /* ATA IDENTIFY supported */ - -#define VIRTIO_BLK_ID_LEN 256 /* length of identify u16 array */ -#define VIRTIO_BLK_ID_SN 10 /* start of char * serial# */ -#define VIRTIO_BLK_ID_SN_BYTES 20 /* length in bytes of serial# */ +#define VIRTIO_BLK_F_WCACHE 9 /* write cache enabled */ +#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */ /* These two define direction. */ -#define VIRTIO_BLK_T_IN 0 -#define VIRTIO_BLK_T_OUT 1 +#define VIRTIO_BLK_T_IN 0 +#define VIRTIO_BLK_T_OUT 1 + +#define VIRTIO_BLK_T_SCSI_CMD 2 +#define VIRTIO_BLK_T_FLUSH 4 -#define VIRTIO_BLK_S_OK 0 -#define VIRTIO_BLK_S_IOERR 1 -#define VIRTIO_BLK_S_UNSUPP 2 +#define VIRTIO_BLK_S_OK 0 +#define VIRTIO_BLK_S_IOERR 1 +#define VIRTIO_BLK_S_UNSUPP 2 #define SECTOR_SIZE 512 -#define MAX_PHYS_SEGMENTS 128 +#define MAX_PHYS_SEGMENTS 16 #define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS) #define IO_PORT_LENGTH 0x40 @@ -72,7 +72,10 @@ typedef struct virtio_blk_config { } geometry; /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */ u32 blk_size; - u16 identify[VIRTIO_BLK_ID_LEN]; + u8 physical_block_exp; + u8 alignment_offset; + u16 min_io_size; + u16 opt_io_size; }blk_config, *pblk_config; #pragma pack() @@ -99,26 +102,32 @@ typedef struct _ADAPTER_EXTENSION { vring_virtqueue* virtqueue; INQUIRYDATA inquiry_data; blk_config info; + ULONG breaks_number; + ULONG transfer_size; ULONG queue_depth; BOOLEAN dump_mode; LIST_ENTRY list_head; - LIST_ENTRY complete_list; + ULONG msix_vectors; + ULONG features; #ifdef USE_STORPORT + LIST_ENTRY complete_list; STOR_DPC completion_dpc; +#if (NTDDI_VERSION >= NTDDI_VISTA) + BOOLEAN indirect; +#endif #endif - BOOLEAN has_sn; - ULONG msix_vectors; }ADAPTER_EXTENSION, *PADAPTER_EXTENSION; typedef struct _RHEL_SRB_EXTENSION { blk_req vbr; ULONG out; ULONG in; +#ifndef USE_STORPORT + BOOLEAN call_next; +#endif +#if (NTDDI_VERSION >= NTDDI_VISTA) + PVOID addr; +#endif }RHEL_SRB_EXTENSION, *PRHEL_SRB_EXTENSION; -ULONGLONG -RhelGetLba( - PCDB Cdb - ); - #endif ___VIOSTOR__H__ diff --git a/viostor/virtio_stor_hw_helper.c b/viostor/virtio_stor_hw_helper.c index ed6abf7..ed2e5d2 100644 --- a/viostor/virtio_stor_hw_helper.c +++ b/viostor/virtio_stor_hw_helper.c @@ -13,10 +13,82 @@ * **********************************************************************/ #include "virtio_stor_hw_helper.h" +#include"virtio_stor_utils.h" #ifdef USE_STORPORT BOOLEAN -SynchronizedAccessRoutine( +SynchronizedFlushRoutine( + IN PVOID DeviceExtension, + IN PVOID Context + ) +{ + PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; + PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK) Context; + PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; + + srbExt->vbr.out_hdr.ioprio = 0; + srbExt->vbr.req = (struct request *)Srb; + srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH; + srbExt->out = 1; + srbExt->in = 1; + + if (adaptExt->pci_vq_info.vq->vq_ops->add_buf(adaptExt->pci_vq_info.vq, + &srbExt->vbr.sg[0], + srbExt->out, srbExt->in, + &srbExt->vbr) >= 0){ + InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); + adaptExt->pci_vq_info.vq->vq_ops->kick(adaptExt->pci_vq_info.vq); + return TRUE; + } + + RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortBusy\n", __FUNCTION__)); + StorPortBusy(DeviceExtension, 2); + return FALSE; +} + +BOOLEAN +RhelDoFlush(PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + return StorPortSynchronizeAccess(DeviceExtension, SynchronizedFlushRoutine, (PVOID)Srb); +} +#else +BOOLEAN +RhelDoFlush(PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb) +{ + PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; + PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; + int num_free; + + srbExt->vbr.out_hdr.ioprio = 0; + srbExt->vbr.req = (struct request *)Srb; + srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH; + srbExt->out = 1; + srbExt->in = 1; + + num_free = adaptExt->pci_vq_info.vq->vq_ops->add_buf(adaptExt->pci_vq_info.vq, + &srbExt->vbr.sg[0], + srbExt->out, srbExt->in, + &srbExt->vbr); + + if ( num_free >= 0) { + InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); + adaptExt->pci_vq_info.vq->vq_ops->kick(adaptExt->pci_vq_info.vq); + srbExt->call_next = FALSE; + if(num_free < VIRTIO_MAX_SG) { + srbExt->call_next = TRUE; + } else { + ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); + } + } + return TRUE; +} +#endif + +#ifdef USE_STORPORT +BOOLEAN +SynchronizedReadWriteRoutine( IN PVOID DeviceExtension, IN PVOID Context ) @@ -27,12 +99,14 @@ SynchronizedAccessRoutine( if (adaptExt->pci_vq_info.vq->vq_ops->add_buf(adaptExt->pci_vq_info.vq, &srbExt->vbr.sg[0], srbExt->out, srbExt->in, - &srbExt->vbr) == 0){ + &srbExt->vbr) >= 0){ InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); adaptExt->pci_vq_info.vq->vq_ops->kick(adaptExt->pci_vq_info.vq); return TRUE; } - StorPortBusy(DeviceExtension, 10); + + RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortBusy\n", __FUNCTION__)); + StorPortBusy(DeviceExtension, 5); return FALSE; } @@ -40,7 +114,29 @@ BOOLEAN RhelDoReadWrite(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { - return StorPortSynchronizeAccess(DeviceExtension, SynchronizedAccessRoutine, (PVOID)Srb); + BOOLEAN res = FALSE; + PRHEL_SRB_EXTENSION srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; +#if (NTDDI_VERSION >= NTDDI_VISTA) + NTSTATUS status = STATUS_SUCCESS; + struct vring_desc *desc = NULL; + srbExt->addr = NULL; +#endif + res = StorPortSynchronizeAccess(DeviceExtension, SynchronizedReadWriteRoutine, (PVOID)Srb); +#if (NTDDI_VERSION >= NTDDI_VISTA) + + if (!res) { + status = StorPortAllocatePool(DeviceExtension, + (srbExt->out + srbExt->in) * sizeof(struct vring_desc), + 'rdnI', (PVOID)&desc); + if (!NT_SUCCESS(status)) { + RhelDbgPrint(TRACE_LEVEL_ERROR, ("%s StorPortAllocatePool failed 0x%x\n", __FUNCTION__, status) ); + return FALSE; + } + srbExt->addr = desc; + res = StorPortSynchronizeAccess(DeviceExtension, SynchronizedReadWriteRoutine, (PVOID)Srb); + } +#endif + return res; } #else BOOLEAN @@ -54,6 +150,8 @@ RhelDoReadWrite(PVOID DeviceExtension, PVOID DataBuffer; PADAPTER_EXTENSION adaptExt; PRHEL_SRB_EXTENSION srbExt; + int num_free; + cdb = (PCDB)&Srb->Cdb[0]; srbExt = (PRHEL_SRB_EXTENSION)Srb->SrbExtension; adaptExt = (PADAPTER_EXTENSION)DeviceExtension; @@ -69,7 +167,7 @@ RhelDoReadWrite(PVOID DeviceExtension, sgElement++; } - srbExt->vbr.out_hdr.sector = RhelGetLba(cdb); + srbExt->vbr.out_hdr.sector = RhelGetLba(DeviceExtension, cdb); srbExt->vbr.out_hdr.ioprio = 0; srbExt->vbr.req = (struct request *)Srb; @@ -88,18 +186,22 @@ RhelDoReadWrite(PVOID DeviceExtension, srbExt->vbr.sg[sgElement].physAddr = ScsiPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen); srbExt->vbr.sg[sgElement].ulSize = sizeof(srbExt->vbr.status); - - - if (adaptExt->pci_vq_info.vq->vq_ops->add_buf(adaptExt->pci_vq_info.vq, + num_free = adaptExt->pci_vq_info.vq->vq_ops->add_buf(adaptExt->pci_vq_info.vq, &srbExt->vbr.sg[0], srbExt->out, srbExt->in, - &srbExt->vbr) == 0) { -//FIXME + &srbExt->vbr); + + if ( num_free >= 0) { InsertTailList(&adaptExt->list_head, &srbExt->vbr.list_entry); adaptExt->pci_vq_info.vq->vq_ops->kick(adaptExt->pci_vq_info.vq); - return TRUE; + srbExt->call_next = FALSE; + if(num_free < VIRTIO_MAX_SG) { + srbExt->call_next = TRUE; + } else { + ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); + } } - return FALSE; + return TRUE; } #endif @@ -110,10 +212,62 @@ RhelShutDown( { PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; + VirtIODeviceReset(DeviceExtension); + ScsiPortWritePortUshort((PUSHORT)(adaptExt->device_base + VIRTIO_PCI_GUEST_FEATURES), 0); if (adaptExt->pci_vq_info.vq) { adaptExt->pci_vq_info.vq->vq_ops->shutdown(adaptExt->pci_vq_info.vq); VirtIODeviceDeleteVirtualQueue(adaptExt->pci_vq_info.vq); adaptExt->pci_vq_info.vq = NULL; } - VirtIODeviceReset(DeviceExtension); +} + +ULONGLONG +RhelGetLba( + IN PVOID DeviceExtension, + IN PCDB Cdb + ) +{ + + EIGHT_BYTE lba; + PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension; + + lba.AsULongLong = 0; + + switch (Cdb->CDB6GENERIC.OperationCode) { + + case SCSIOP_READ: + case SCSIOP_WRITE: + case SCSIOP_WRITE_VERIFY: { + lba.Byte0 = Cdb->CDB10.LogicalBlockByte3; + lba.Byte1 = Cdb->CDB10.LogicalBlockByte2; + lba.Byte2 = Cdb->CDB10.LogicalBlockByte1; + lba.Byte3 = Cdb->CDB10.LogicalBlockByte0; + } + break; + case SCSIOP_READ6: + case SCSIOP_WRITE6: { + lba.Byte0 = Cdb->CDB6READWRITE.LogicalBlockMsb1; + lba.Byte1 = Cdb->CDB6READWRITE.LogicalBlockMsb0; + lba.Byte2 = Cdb->CDB6READWRITE.LogicalBlockLsb; + } + break; + case SCSIOP_READ12: + case SCSIOP_WRITE12: + case SCSIOP_WRITE_VERIFY12: { + REVERSE_BYTES(&lba, &Cdb->CDB12.LogicalBlock[0]); + } + break; + case SCSIOP_READ16: + case SCSIOP_WRITE16: + case SCSIOP_WRITE_VERIFY16: { + REVERSE_BYTES_QUAD(&lba, &Cdb->CDB16.LogicalBlock[0]); + } + break; + default: { + ASSERT(FALSE); + return (ULONGLONG)-1; + } + } + + return (lba.AsULongLong << adaptExt->info.physical_block_exp); } diff --git a/viostor/virtio_stor_hw_helper.h b/viostor/virtio_stor_hw_helper.h index c1fcafa..13c1938 100644 --- a/viostor/virtio_stor_hw_helper.h +++ b/viostor/virtio_stor_hw_helper.h @@ -35,9 +35,22 @@ RhelDoReadWrite( PSCSI_REQUEST_BLOCK Srb ); +BOOLEAN +RhelDoFlush( + IN PVOID DeviceExtension, + PSCSI_REQUEST_BLOCK Srb + ); + VOID RhelShutDown( IN PVOID DeviceExtension ); +ULONGLONG +RhelGetLba( + IN PVOID DeviceExtension, + IN PCDB Cdb + ); + + #endif ___VIOSTOR_HW_HELPER_H___ diff --git a/viostor/virtio_stor_utils.h b/viostor/virtio_stor_utils.h index 43e904c..c490341 100644 --- a/viostor/virtio_stor_utils.h +++ b/viostor/virtio_stor_utils.h @@ -23,6 +23,8 @@ #endif #include <stdarg.h> +#define CHECKBIT(value, nbit) (((value) & (1 << (nbit))) != 0) + int _cdecl _vsnprintf( diff --git a/viostor/wxp.inf b/viostor/wxp.inf new file mode 100644 index 0000000..6665149 --- /dev/null +++ b/viostor/wxp.inf @@ -0,0 +1,101 @@ +; Copyright (c) 2009, Red Hat Inc. +[Version] +Signature="$Windows NT$" +Provider=%RHEL% +ClassGUID={4D36E97B-E325-11CE-BFC1-08002BE10318} +Class=SCSIAdapter +DriverVer = 10/10/2009,5.3.0.17241 +CatalogFile=viostor.cat + +; +; Source file information +; + +[SourceDisksNames] +1 = %DiskId1%,,,"" + +[SourceDisksFiles] +viostor.sys = 1,, + +[ControlFlags] +;ExcludeFromSelect = * + +[DestinationDirs] +DefaultDestDir = 10 +viostor_Files_Driver = 12 + +; +; Driver information +; + +[Manufacturer] +%RHEL% = RHEL,NTx86,NTamd64 + +[RHEL] +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00000000 +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00020000 +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4 + +[RHEL.NTx86] +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00000000 +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00020000 +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4 + +[RHEL.NTamd64] +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00000000 +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00020000 +%RHELScsi.DeviceDesc% = rhelscsi_inst, PCI\VEN_1AF4&DEV_1001&SUBSYS_00021AF4 + +; +; General installation section +; + +[viostor_Files_Driver] +viostor.sys,,,2 + +[rhelscsi_inst] +CopyFiles=viostor_Files_Driver + +; +; Service Installation +; + +[rhelscsi_inst.Services] +AddService = viostor, 0x00000002 , rhelscsi_Service_Inst, rhelscsi_EventLog_Inst + +[rhelscsi_Service_Inst] +ServiceType = %SERVICE_KERNEL_DRIVER% +StartType = %SERVICE_BOOT_START% +ErrorControl = %SERVICE_ERROR_NORMAL% +ServiceBinary = %12%\viostor.sys +LoadOrderGroup = SCSI miniport +AddReg = pnpsafe_pci_addreg + +[rhelscsi_EventLog_Inst] +AddReg = rhelscsi_EventLog_AddReg + +[rhelscsi_EventLog_AddReg] +HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll" +HKR,,TypesSupported,%REG_DWORD%,7 + +[pnpsafe_pci_addreg] +HKR, "Parameters\PnpInterface", "5", %REG_DWORD%, 0x00000001 +HKR, "Parameters", "BusType", %REG_DWORD%, 0x00000001 + +[Strings] +; +; Localizable Strings +; +diskId1 = "Red Hat VirtIO SCSI controller Installation Disk" +RHELScsi.DeviceDesc = "Red Hat VirtIO SCSI controller" +RHEL = "Red Hat, Inc." + +; +; Non-Localizable Strings +; + +REG_EXPAND_SZ = 0x00020000 +REG_DWORD = 0x00010001 +SERVICE_KERNEL_DRIVER = 1 +SERVICE_BOOT_START = 0 +SERVICE_ERROR_NORMAL = 1 -- To unsubscribe from this list: send the line "unsubscribe kvm-commits" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html