kvm-guest-drivers-windows
716 строк · 26.3 Кб
1/*
2* This file contains various virtio queue related routines.
3*
4* Copyright (c) 2008-2017 Red Hat, Inc.
5*
6* Author(s):
7* Vadim Rozenfeld <vrozenfe@redhat.com>
8*
9* Redistribution and use in source and binary forms, with or without
10* modification, are permitted provided that the following conditions
11* are met :
12* 1. Redistributions of source code must retain the above copyright
13* notice, this list of conditions and the following disclaimer.
14* 2. Redistributions in binary form must reproduce the above copyright
15* notice, this list of conditions and the following disclaimer in the
16* documentation and / or other materials provided with the distribution.
17* 3. Neither the names of the copyright holders nor the names of their contributors
18* may be used to endorse or promote products derived from this software
19* without specific prior written permission.
20* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23* ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30* SUCH DAMAGE.
31*/
32#include "virtio_stor_hw_helper.h"33#include"virtio_stor_utils.h"34#include <limits.h>35
36#if defined(EVENT_TRACING)37#include "virtio_stor_hw_helper.tmh"38#endif39
40
41
42#define SET_VA_PA() { ULONG len; va = adaptExt->indirect ? srbExt->desc : NULL; \43pa = va ? StorPortGetPhysicalAddress(DeviceExtension, NULL, va, &len).QuadPart : 0; \44}45
46#define MESSAGENUMBER_TO_QUEUE() { \47MessageId = param.MessageNumber; \48QueueNumber = MessageId - 1; \49if (QueueNumber >= adaptExt->num_queues) { \50QueueNumber %= adaptExt->num_queues; \51MessageId += 1; \52} \53}
54
55BOOLEAN
56RhelDoFlush(57PVOID DeviceExtension,58PSRB_TYPE Srb,59BOOLEAN resend,60BOOLEAN bIsr
61)62{
63PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;64PSRB_EXTENSION srbExt = SRB_EXTENSION(Srb);65ULONG fragLen = 0UL;66PVOID va = NULL;67ULONGLONG pa = 0ULL;68
69ULONG QueueNumber = 0;70ULONG MessageId = 1;71ULONG OldIrql = 0;72BOOLEAN result = FALSE;73bool notify = FALSE;74STOR_LOCK_HANDLE LockHandle = { 0 };75ULONG status = STOR_STATUS_SUCCESS;76struct virtqueue *vq = NULL;77PREQUEST_LIST element;78
79SET_VA_PA();80
81if (resend) {82MessageId = srbExt->MessageID;83QueueNumber = MessageId - 1;84} else if (adaptExt->num_queues > 1) {85STARTIO_PERFORMANCE_PARAMETERS param;86param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);87status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, ¶m);88if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {89RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",90Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);91MESSAGENUMBER_TO_QUEUE();92}93else {94RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed. srb %p status 0x%x.\n",95Srb, status);96}97}98
99if (adaptExt->reset_in_progress) {100CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);101return TRUE;102}103
104srbExt->MessageID = MessageId;105vq = adaptExt->vq[QueueNumber];106
107srbExt->vbr.out_hdr.sector = 0;108srbExt->vbr.out_hdr.ioprio = 0;109srbExt->vbr.req = (struct request *)Srb;110srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_FLUSH;111srbExt->out = 1;112srbExt->in = 1;113
114srbExt->sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen);115srbExt->sg[0].length = sizeof(srbExt->vbr.out_hdr);116srbExt->sg[1].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen);117srbExt->sg[1].length = sizeof(srbExt->vbr.status);118
119element = &adaptExt->processing_srbs[QueueNumber];120if (!resend) {121VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);122}123if (virtqueue_add_buf(vq,124&srbExt->sg[0],125srbExt->out, srbExt->in,126&srbExt->vbr, va, pa) >= 0) {127notify = virtqueue_kick_prepare(vq);128InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);129element->srb_cnt++;130if (!resend) {131VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);132}133result = TRUE;134#ifdef DBG135InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);136#endif137}138else {139if (!resend) {140VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);141}142RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);143StorPortBusy(DeviceExtension, 2);144}145if (notify) {146virtqueue_notify(vq);147}148
149return result;150}
151
152BOOLEAN
153RhelDoReadWrite(PVOID DeviceExtension,154PSRB_TYPE Srb)155{
156PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;157PSRB_EXTENSION srbExt = SRB_EXTENSION(Srb);158PVOID va = NULL;159ULONGLONG pa = 0ULL;160
161ULONG QueueNumber = 0;162ULONG MessageId = 1;163ULONG OldIrql = 0;164BOOLEAN result = FALSE;165bool notify = FALSE;166STOR_LOCK_HANDLE LockHandle = { 0 };167ULONG status = STOR_STATUS_SUCCESS;168struct virtqueue *vq = NULL;169PREQUEST_LIST element;170
171SET_VA_PA();172
173if (adaptExt->num_queues > 1) {174STARTIO_PERFORMANCE_PARAMETERS param;175param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);176status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, ¶m);177if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {178RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",179Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);180MESSAGENUMBER_TO_QUEUE();181}182else {183RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed srb %p status 0x%x.\n",184Srb, status);185}186}187
188if (adaptExt->reset_in_progress) {189CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);190return TRUE;191}192
193srbExt->MessageID = MessageId;194vq = adaptExt->vq[QueueNumber];195RhelDbgPrint(TRACE_LEVEL_VERBOSE, " QueueNumber 0x%x vq = %p\n", QueueNumber, vq);196
197element = &adaptExt->processing_srbs[QueueNumber];198VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);199if (virtqueue_add_buf(vq,200&srbExt->sg[0],201srbExt->out, srbExt->in,202&srbExt->vbr, va, pa) >= 0) {203notify = virtqueue_kick_prepare(vq);204InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);205element->srb_cnt++;206VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);207#ifdef DBG208InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);209#endif210result = TRUE;211}212else {213VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);214RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);215StorPortBusy(DeviceExtension, 2);216}217if (notify) {218virtqueue_notify(vq);219}220
221if (adaptExt->num_queues > 1) {222if (CHECKFLAG(adaptExt->perfFlags, STOR_PERF_OPTIMIZE_FOR_COMPLETION_DURING_STARTIO)) {223VioStorCompleteRequest(DeviceExtension, MessageId, FALSE);224}225}226return result;227}
228
229BOOLEAN
230RhelDoUnMap(231IN PVOID DeviceExtension,232IN PSRB_TYPE Srb
233)234{
235PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;236PSRB_EXTENSION srbExt = SRB_EXTENSION(Srb);237
238PUNMAP_LIST_HEADER unmapList = NULL;239USHORT blockDescrDataLength = 0;240
241PVOID srbDataBuffer = SRB_DATA_BUFFER(Srb);242ULONG srbDataBufferLength = SRB_DATA_TRANSFER_LENGTH(Srb);243
244ULONG i = 0;245PUNMAP_BLOCK_DESCRIPTOR BlockDescriptors = NULL;246USHORT BlockDescrCount = 0;247ULONG fragLen = 0UL;248PREQUEST_LIST element;249
250
251PVOID va = NULL;252ULONGLONG pa = 0ULL;253
254ULONG QueueNumber = 0;255ULONG OldIrql = 0;256ULONG MessageId = 1;257BOOLEAN result = FALSE;258BOOLEAN notify = FALSE;259STOR_LOCK_HANDLE LockHandle = { 0 };260ULONG status = STOR_STATUS_SUCCESS;261struct virtqueue *vq = NULL;262
263SET_VA_PA();264
265unmapList = (PUNMAP_LIST_HEADER)srbDataBuffer;266
267if (unmapList == NULL) {268Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;269return FALSE;270}271
272REVERSE_BYTES_SHORT(&blockDescrDataLength, unmapList->BlockDescrDataLength);273
274if ( !(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_DISCARD)) ||275(srbDataBufferLength < (ULONG)(blockDescrDataLength + 8)) ) {276Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;277return FALSE;278}279
280BlockDescriptors = (PUNMAP_BLOCK_DESCRIPTOR)((PCHAR)srbDataBuffer + 8);281BlockDescrCount = blockDescrDataLength / sizeof(UNMAP_BLOCK_DESCRIPTOR);282for (i = 0; i < BlockDescrCount; i++) {283ULONGLONG blockDescrStartingLba;284ULONG blockDescrLbaCount;285REVERSE_BYTES_QUAD(&blockDescrStartingLba, BlockDescriptors[i].StartingLba);286REVERSE_BYTES(&blockDescrLbaCount, BlockDescriptors[i].LbaCount);287RhelDbgPrint(TRACE_LEVEL_INFORMATION, "Count %d BlockDescrCount = %d blockDescrStartingLba = %llu blockDescrLbaCount = %lu\n",288i, BlockDescrCount, blockDescrStartingLba, blockDescrLbaCount);289adaptExt->blk_discard[i].sector = blockDescrStartingLba * (adaptExt->info.blk_size / SECTOR_SIZE);290adaptExt->blk_discard[i].num_sectors = blockDescrLbaCount * (adaptExt->info.blk_size / SECTOR_SIZE);291adaptExt->blk_discard[i].flags = 0;292}293
294srbExt->vbr.out_hdr.sector = 0;295srbExt->vbr.out_hdr.ioprio = 0;296srbExt->vbr.req = (struct request *)Srb;297srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_DISCARD | VIRTIO_BLK_T_OUT;298srbExt->out = 2;299srbExt->in = 1;300
301srbExt->sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen);302srbExt->sg[0].length = sizeof(srbExt->vbr.out_hdr);303srbExt->sg[1].physAddr = MmGetPhysicalAddress(&adaptExt->blk_discard[0]);304srbExt->sg[1].length = sizeof(blk_discard_write_zeroes) * BlockDescrCount;305srbExt->sg[2].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen);306srbExt->sg[2].length = sizeof(srbExt->vbr.status);307
308if (adaptExt->num_queues > 1) {309STARTIO_PERFORMANCE_PARAMETERS param;310param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);311status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, ¶m);312if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {313RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",314Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);315MESSAGENUMBER_TO_QUEUE();316}317else {318RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed srb %p status 0x%x.\n",319Srb, status);320}321}322
323if (adaptExt->reset_in_progress) {324CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);325return TRUE;326}327
328srbExt->MessageID = MessageId;329vq = adaptExt->vq[QueueNumber];330RhelDbgPrint(TRACE_LEVEL_INFORMATION, " QueueNumber 0x%x vq = %p type = %d\n", QueueNumber, vq, srbExt->vbr.out_hdr.type);331
332element = &adaptExt->processing_srbs[QueueNumber];333VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);334if (virtqueue_add_buf(vq,335&srbExt->sg[0],336srbExt->out, srbExt->in,337&srbExt->vbr, va, pa) >= 0) {338notify = virtqueue_kick_prepare(vq);339InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);340element->srb_cnt++;341VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);342#ifdef DBG343InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);344#endif345result = TRUE;346}347else {348VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);349RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);350StorPortBusy(DeviceExtension, 2);351}352if (notify) {353RhelDbgPrint(TRACE_LEVEL_INFORMATION, " %s virtqueue_notify %d.\n", __FUNCTION__, QueueNumber);354virtqueue_notify(vq);355}356return result;357}
358
359BOOLEAN
360RhelGetSerialNumber(361IN PVOID DeviceExtension,362IN PSRB_TYPE Srb
363)
364{
365ULONG QueueNumber = 0;366ULONG OldIrql = 0;367ULONG MessageId = 1;368STOR_LOCK_HANDLE LockHandle = { 0 };369struct virtqueue *vq = NULL;370PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;371PSRB_EXTENSION srbExt = SRB_EXTENSION(Srb);372ULONG status = STOR_STATUS_SUCCESS;373PVOID va = NULL;374ULONGLONG pa = 0ULL;375BOOLEAN result = FALSE;376BOOLEAN notify = FALSE;377ULONG fragLen = 0UL;378PREQUEST_LIST element;379
380SET_VA_PA();381
382RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srbExt %p.\n", srbExt);383
384if (adaptExt->num_queues > 1) {385STARTIO_PERFORMANCE_PARAMETERS param;386param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);387status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, ¶m);388if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {389RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",390Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);391MESSAGENUMBER_TO_QUEUE();392}393else {394RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed srb %p status 0x%x.\n",395Srb, status);396}397}398if (adaptExt->reset_in_progress) {399CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);400return TRUE;401}402
403srbExt->MessageID = MessageId;404vq = adaptExt->vq[QueueNumber];405
406srbExt->vbr.out_hdr.sector = 0;407srbExt->vbr.out_hdr.ioprio = 0;408srbExt->vbr.req = (struct request *)Srb;409srbExt->vbr.out_hdr.type = VIRTIO_BLK_T_GET_ID | VIRTIO_BLK_T_IN;410srbExt->out = 1;411srbExt->in = 2;412
413srbExt->sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen);414srbExt->sg[0].length = sizeof(srbExt->vbr.out_hdr);415srbExt->sg[1].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &adaptExt->sn[0], &fragLen);416srbExt->sg[1].length = sizeof(adaptExt->sn);417srbExt->sg[2].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen);418srbExt->sg[2].length = sizeof(srbExt->vbr.status);419
420element = &adaptExt->processing_srbs[QueueNumber];421VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);422if (virtqueue_add_buf(vq,423&srbExt->sg[0],424srbExt->out, srbExt->in,425&srbExt->vbr, va, pa) >= 0) {426notify = virtqueue_kick_prepare(vq);427InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);428element->srb_cnt++;429VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);430result = TRUE;431#ifdef DBG432InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);433#endif434}435else {436VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);437RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);438StorPortBusy(DeviceExtension, 2);439}440if (notify) {441virtqueue_notify(vq);442}443
444return result;445}
446
447VOID
448RhelShutDown(449IN PVOID DeviceExtension
450)451{
452ULONG index;453PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;454
455virtio_device_reset(&adaptExt->vdev);456virtio_delete_queues(&adaptExt->vdev);457for (index = 0; index < adaptExt->num_queues; ++index) {458adaptExt->vq[index] = NULL;459}460virtio_device_shutdown(&adaptExt->vdev);461}
462
463ULONGLONG
464RhelGetLba(465IN PVOID DeviceExtension,466IN PCDB Cdb
467)468{
469
470EIGHT_BYTE lba;471PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;472
473lba.AsULongLong = 0;474
475switch (Cdb->CDB6GENERIC.OperationCode) {476
477case SCSIOP_READ:478case SCSIOP_WRITE:479case SCSIOP_READ_CAPACITY:480case SCSIOP_WRITE_VERIFY:481case SCSIOP_VERIFY:482case SCSIOP_UNMAP:483{484lba.Byte0 = Cdb->CDB10.LogicalBlockByte3;485lba.Byte1 = Cdb->CDB10.LogicalBlockByte2;486lba.Byte2 = Cdb->CDB10.LogicalBlockByte1;487lba.Byte3 = Cdb->CDB10.LogicalBlockByte0;488}489break;490case SCSIOP_READ6:491case SCSIOP_WRITE6: {492lba.Byte0 = Cdb->CDB6READWRITE.LogicalBlockMsb1;493lba.Byte1 = Cdb->CDB6READWRITE.LogicalBlockMsb0;494lba.Byte2 = Cdb->CDB6READWRITE.LogicalBlockLsb;495}496break;497case SCSIOP_READ12:498case SCSIOP_WRITE12:499case SCSIOP_WRITE_VERIFY12: {500REVERSE_BYTES(&lba, &Cdb->CDB12.LogicalBlock[0]);501}502break;503case SCSIOP_READ16:504case SCSIOP_WRITE16:505case SCSIOP_READ_CAPACITY16:506case SCSIOP_WRITE_VERIFY16:507case SCSIOP_VERIFY16: {508REVERSE_BYTES_QUAD(&lba, &Cdb->CDB16.LogicalBlock[0]);509}510break;511default: {512ASSERT(FALSE);513return (ULONGLONG)-1;514}515}516return (lba.AsULongLong * (adaptExt->info.blk_size / SECTOR_SIZE));517}
518
519ULONG
520RhelGetSectors(521IN PVOID DeviceExtension,522IN PCDB Cdb
523)
524{
525FOUR_BYTE sector;526PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;527
528sector.AsULong = 0UL;529
530switch (Cdb->CDB6GENERIC.OperationCode) {531
532case SCSIOP_READ:533case SCSIOP_WRITE:534case SCSIOP_READ_CAPACITY:535case SCSIOP_WRITE_VERIFY:536case SCSIOP_VERIFY:{537sector.Byte0 = Cdb->CDB10.TransferBlocksLsb;538sector.Byte1 = Cdb->CDB10.TransferBlocksMsb;539}540break;541case SCSIOP_READ16:542case SCSIOP_WRITE16:543case SCSIOP_READ_CAPACITY16:544case SCSIOP_WRITE_VERIFY16:545case SCSIOP_VERIFY16: {546REVERSE_BYTES(§or, &Cdb->CDB16.TransferLength[0]);547}548break;549default: {550ASSERT(FALSE);551return (ULONGLONG)-1;552}553}554return (sector.AsULong * (adaptExt->info.blk_size / SECTOR_SIZE));555}
556
557
558VOID
559RhelGetDiskGeometry(560IN PVOID DeviceExtension
561)
562{
563u64 cap;564u32 v;565struct virtio_blk_geometry vgeo;566
567PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;568adaptExt->features = virtio_get_features(&adaptExt->vdev);569
570if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BARRIER)) {571RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_BARRIER\n");572}573
574if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) {575RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_RO\n");576}577
578if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SIZE_MAX)) {579virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, size_max),580&v, sizeof(v));581adaptExt->info.size_max = v;582} else {583adaptExt->info.size_max = PAGE_SIZE;584}585
586if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SEG_MAX)) {587virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, seg_max),588&v, sizeof(v));589adaptExt->info.seg_max = v;590RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_SEG_MAX = %d\n", adaptExt->info.seg_max);591}592
593if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BLK_SIZE)) {594virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, blk_size),595&v, sizeof(v));596adaptExt->info.blk_size = v;597} else {598adaptExt->info.blk_size = SECTOR_SIZE;599}600RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_BLK_SIZE = %d\n", adaptExt->info.blk_size);601
602if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_GEOMETRY)) {603virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, geometry),604&vgeo, sizeof(vgeo));605adaptExt->info.geometry.cylinders= vgeo.cylinders;606adaptExt->info.geometry.heads = vgeo.heads;607adaptExt->info.geometry.sectors = vgeo.sectors;608RhelDbgPrint(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);609}610
611virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, capacity),612&cap, sizeof(cap));613adaptExt->info.capacity = cap;614RhelDbgPrint(TRACE_LEVEL_INFORMATION, " device capacity = %08I64X\n", adaptExt->info.capacity);615
616
617if(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_TOPOLOGY)) {618virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, physical_block_exp),619&adaptExt->info.physical_block_exp, sizeof(adaptExt->info.physical_block_exp));620RhelDbgPrint(TRACE_LEVEL_INFORMATION, " physical_block_exp = %d\n", adaptExt->info.physical_block_exp);621
622virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, alignment_offset),623&adaptExt->info.alignment_offset, sizeof(adaptExt->info.alignment_offset));624RhelDbgPrint(TRACE_LEVEL_INFORMATION, " alignment_offset = %d\n", adaptExt->info.alignment_offset);625
626virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, min_io_size),627&adaptExt->info.min_io_size, sizeof(adaptExt->info.min_io_size));628RhelDbgPrint(TRACE_LEVEL_INFORMATION, " min_io_size = %d\n", adaptExt->info.min_io_size);629
630virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, opt_io_size),631&adaptExt->info.opt_io_size, sizeof(adaptExt->info.opt_io_size));632RhelDbgPrint(TRACE_LEVEL_INFORMATION, " opt_io_size = %d\n", adaptExt->info.opt_io_size);633}634
635if(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_DISCARD)) {636virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, discard_sector_alignment),637&v, sizeof(v));638if (v > 0) {639v = max(v, MIN_DISCARD_SECTOR_ALIGNMENT);640}641adaptExt->info.discard_sector_alignment = v << SECTOR_SHIFT;642
643RhelDbgPrint(TRACE_LEVEL_INFORMATION, " discard_sector_alignment = %d\n", adaptExt->info.discard_sector_alignment);644
645virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, max_discard_sectors),646&v, sizeof(v));647adaptExt->info.max_discard_sectors = v ? v : UINT_MAX;648RhelDbgPrint(TRACE_LEVEL_INFORMATION, " max_discard_sectors = %d\n", adaptExt->info.max_discard_sectors);649
650virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, max_discard_seg),651&v, sizeof(v));652adaptExt->info.max_discard_seg = (v < MAX_DISCARD_SEGMENTS) ? v : MAX_DISCARD_SEGMENTS -1;653RhelDbgPrint(TRACE_LEVEL_INFORMATION, " max_discard_seg = %d\n", adaptExt->info.max_discard_seg);654}655}
656
657VOID
658VioStorVQLock(659IN PVOID DeviceExtension,660IN ULONG MessageID,661IN OUT PSTOR_LOCK_HANDLE LockHandle,662IN BOOLEAN isr
663)664{
665PADAPTER_EXTENSION adaptExt;666RhelDbgPrint(TRACE_LEVEL_VERBOSE, " ---> MessageID = %d isr = %d\n", MessageID, isr);667
668adaptExt = (PADAPTER_EXTENSION)DeviceExtension;669if (!isr) {670if (adaptExt->msix_enabled) {671if (adaptExt->num_queues > 1) {672
673NT_ASSERT(MessageID > 0);674NT_ASSERT(MessageID <= adaptExt->num_queues);675StorPortAcquireSpinLock(DeviceExtension, DpcLock, &adaptExt->dpc[MessageID - 1], LockHandle);676}677else {678ULONG oldIrql = 0;679StorPortAcquireMSISpinLock(DeviceExtension, (adaptExt->msix_one_vector ? 0 : MessageID), &oldIrql);680LockHandle->Context.OldIrql = (KIRQL)oldIrql;681}682}683else {684StorPortAcquireSpinLock(DeviceExtension, InterruptLock, NULL, LockHandle);685}686}687RhelDbgPrint(TRACE_LEVEL_VERBOSE, " <--- MessageID = %d\n", MessageID);688}
689
690VOID
691VioStorVQUnlock(692IN PVOID DeviceExtension,693IN ULONG MessageID,694IN PSTOR_LOCK_HANDLE LockHandle,695IN BOOLEAN isr
696)697{
698PADAPTER_EXTENSION adaptExt;699RhelDbgPrint(TRACE_LEVEL_VERBOSE, " ---> MessageID = %d isr = %d\n", MessageID, isr);700adaptExt = (PADAPTER_EXTENSION)DeviceExtension;701
702if (!isr) {703if (adaptExt->msix_enabled) {704if (adaptExt->num_queues > 1) {705StorPortReleaseSpinLock(DeviceExtension, LockHandle);706}707else {708StorPortReleaseMSISpinLock(DeviceExtension, (adaptExt->msix_one_vector ? 0 : MessageID), LockHandle->Context.OldIrql);709}710}711else {712StorPortReleaseSpinLock(DeviceExtension, LockHandle);713}714}715RhelDbgPrint(TRACE_LEVEL_VERBOSE, " <--- MessageID = %d\n", MessageID);716}
717