kvm-guest-drivers-windows

Форк
0
/
virtio_stor_hw_helper.c 
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
#endif
39

40

41

42
#define SET_VA_PA() { ULONG len; va = adaptExt->indirect ? srbExt->desc : NULL; \
43
                      pa = va ? StorPortGetPhysicalAddress(DeviceExtension, NULL, va, &len).QuadPart : 0; \
44
                    }
45

46
#define MESSAGENUMBER_TO_QUEUE() { \
47
                    MessageId = param.MessageNumber; \
48
                    QueueNumber = MessageId - 1; \
49
                    if (QueueNumber >= adaptExt->num_queues) { \
50
                        QueueNumber %= adaptExt->num_queues; \
51
                        MessageId += 1; \
52
                    } \
53
}
54

55
BOOLEAN
56
RhelDoFlush(
57
    PVOID DeviceExtension,
58
    PSRB_TYPE Srb,
59
    BOOLEAN resend,
60
    BOOLEAN bIsr
61
    )
62
{
63
    PADAPTER_EXTENSION  adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
64
    PSRB_EXTENSION      srbExt   = SRB_EXTENSION(Srb);
65
    ULONG               fragLen = 0UL;
66
    PVOID               va = NULL;
67
    ULONGLONG           pa = 0ULL;
68

69
    ULONG               QueueNumber = 0;
70
    ULONG               MessageId = 1;
71
    ULONG               OldIrql = 0;
72
    BOOLEAN             result = FALSE;
73
    bool                notify = FALSE;
74
    STOR_LOCK_HANDLE    LockHandle = { 0 };
75
    ULONG               status = STOR_STATUS_SUCCESS;
76
    struct virtqueue    *vq = NULL;
77
    PREQUEST_LIST       element;
78

79
    SET_VA_PA();
80

81
    if (resend) {
82
        MessageId = srbExt->MessageID;
83
        QueueNumber = MessageId - 1;
84
    } else if (adaptExt->num_queues > 1) {
85
        STARTIO_PERFORMANCE_PARAMETERS param;
86
        param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);
87
        status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, &param);
88
        if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {
89
            RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",
90
                Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);
91
            MESSAGENUMBER_TO_QUEUE();
92
        }
93
        else {
94
           RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed. srb %p status 0x%x.\n",
95
                        Srb, status);
96
        }
97
    }
98

99
    if (adaptExt->reset_in_progress) {
100
        CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);
101
        return TRUE;
102
    }
103

104
    srbExt->MessageID = MessageId;
105
    vq = adaptExt->vq[QueueNumber];
106

107
    srbExt->vbr.out_hdr.sector = 0;
108
    srbExt->vbr.out_hdr.ioprio = 0;
109
    srbExt->vbr.req            = (struct request *)Srb;
110
    srbExt->vbr.out_hdr.type   = VIRTIO_BLK_T_FLUSH;
111
    srbExt->out                = 1;
112
    srbExt->in                 = 1;
113

114
    srbExt->sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen);
115
    srbExt->sg[0].length   = sizeof(srbExt->vbr.out_hdr);
116
    srbExt->sg[1].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen);
117
    srbExt->sg[1].length   = sizeof(srbExt->vbr.status);
118

119
    element = &adaptExt->processing_srbs[QueueNumber];
120
    if (!resend) {
121
        VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);
122
    }
123
    if (virtqueue_add_buf(vq,
124
                     &srbExt->sg[0],
125
                     srbExt->out, srbExt->in,
126
                     &srbExt->vbr, va, pa) >= 0) {
127
        notify = virtqueue_kick_prepare(vq);
128
        InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);
129
        element->srb_cnt++;
130
        if (!resend) {
131
            VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
132
        }
133
        result = TRUE;
134
#ifdef DBG
135
        InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);
136
#endif
137
    }
138
    else {
139
        if (!resend) {
140
            VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
141
        }
142
        RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);
143
        StorPortBusy(DeviceExtension, 2);
144
    }
145
    if (notify) {
146
        virtqueue_notify(vq);
147
    }
148

149
    return result;
150
}
151

152
BOOLEAN
153
RhelDoReadWrite(PVOID DeviceExtension,
154
                PSRB_TYPE Srb)
155
{
156
    PADAPTER_EXTENSION  adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
157
    PSRB_EXTENSION      srbExt   = SRB_EXTENSION(Srb);
158
    PVOID               va = NULL;
159
    ULONGLONG           pa = 0ULL;
160

161
    ULONG               QueueNumber = 0;
162
    ULONG               MessageId = 1;
163
    ULONG               OldIrql = 0;
164
    BOOLEAN             result = FALSE;
165
    bool                notify = FALSE;
166
    STOR_LOCK_HANDLE    LockHandle = { 0 };
167
    ULONG               status = STOR_STATUS_SUCCESS;
168
    struct virtqueue    *vq = NULL;
169
    PREQUEST_LIST       element;
170

171
    SET_VA_PA();
172

173
    if (adaptExt->num_queues > 1) {
174
        STARTIO_PERFORMANCE_PARAMETERS param;
175
        param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);
176
        status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, &param);
177
        if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {
178
            RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",
179
                Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);
180
            MESSAGENUMBER_TO_QUEUE();
181
        }
182
        else {
183
           RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed srb %p status 0x%x.\n",
184
                        Srb, status);
185
        }
186
    }
187

188
    if (adaptExt->reset_in_progress) {
189
        CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);
190
        return TRUE;
191
    }
192

193
    srbExt->MessageID = MessageId;
194
    vq = adaptExt->vq[QueueNumber];
195
    RhelDbgPrint(TRACE_LEVEL_VERBOSE, " QueueNumber 0x%x vq = %p\n", QueueNumber, vq);
196

197
    element = &adaptExt->processing_srbs[QueueNumber];
198
    VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);
199
    if (virtqueue_add_buf(vq,
200
                     &srbExt->sg[0],
201
                     srbExt->out, srbExt->in,
202
                     &srbExt->vbr, va, pa) >= 0) {
203
        notify = virtqueue_kick_prepare(vq);
204
        InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);
205
        element->srb_cnt++;
206
        VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
207
#ifdef DBG
208
        InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);
209
#endif
210
        result = TRUE;
211
    }
212
    else {
213
        VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
214
        RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);
215
        StorPortBusy(DeviceExtension, 2);
216
    }
217
    if (notify) {
218
        virtqueue_notify(vq);
219
    }
220

221
    if (adaptExt->num_queues > 1) {
222
        if (CHECKFLAG(adaptExt->perfFlags, STOR_PERF_OPTIMIZE_FOR_COMPLETION_DURING_STARTIO)) {
223
           VioStorCompleteRequest(DeviceExtension, MessageId, FALSE);
224
        }
225
    }
226
    return result;
227
}
228

229
BOOLEAN
230
RhelDoUnMap(
231
    IN PVOID DeviceExtension,
232
    IN PSRB_TYPE Srb
233
    )
234
{
235
    PADAPTER_EXTENSION  adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
236
    PSRB_EXTENSION      srbExt   = SRB_EXTENSION(Srb);
237

238
    PUNMAP_LIST_HEADER  unmapList = NULL;
239
    USHORT              blockDescrDataLength = 0;
240

241
    PVOID               srbDataBuffer = SRB_DATA_BUFFER(Srb);
242
    ULONG               srbDataBufferLength = SRB_DATA_TRANSFER_LENGTH(Srb);
243

244
    ULONG                 i = 0;
245
    PUNMAP_BLOCK_DESCRIPTOR BlockDescriptors = NULL;
246
    USHORT BlockDescrCount = 0;
247
    ULONG               fragLen = 0UL;
248
    PREQUEST_LIST       element;
249

250

251
    PVOID               va = NULL;
252
    ULONGLONG           pa = 0ULL;
253

254
    ULONG               QueueNumber = 0;
255
    ULONG               OldIrql = 0;
256
    ULONG               MessageId = 1;
257
    BOOLEAN             result = FALSE;
258
    BOOLEAN             notify = FALSE;
259
    STOR_LOCK_HANDLE    LockHandle = { 0 };
260
    ULONG               status = STOR_STATUS_SUCCESS;
261
    struct virtqueue    *vq = NULL;
262

263
    SET_VA_PA();
264

265
    unmapList = (PUNMAP_LIST_HEADER)srbDataBuffer;
266

267
    if (unmapList == NULL) {
268
        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
269
        return FALSE;
270
    }
271

272
    REVERSE_BYTES_SHORT(&blockDescrDataLength, unmapList->BlockDescrDataLength);
273

274
    if ( !(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_DISCARD)) ||
275
         (srbDataBufferLength < (ULONG)(blockDescrDataLength + 8)) ) {
276
        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
277
        return FALSE;
278
    }
279

280
    BlockDescriptors = (PUNMAP_BLOCK_DESCRIPTOR)((PCHAR)srbDataBuffer + 8);
281
    BlockDescrCount = blockDescrDataLength / sizeof(UNMAP_BLOCK_DESCRIPTOR);
282
    for (i = 0; i < BlockDescrCount; i++) {
283
        ULONGLONG       blockDescrStartingLba;
284
        ULONG           blockDescrLbaCount;
285
        REVERSE_BYTES_QUAD(&blockDescrStartingLba, BlockDescriptors[i].StartingLba);
286
        REVERSE_BYTES(&blockDescrLbaCount, BlockDescriptors[i].LbaCount);
287
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, "Count %d BlockDescrCount = %d blockDescrStartingLba = %llu blockDescrLbaCount = %lu\n",
288
                     i, BlockDescrCount, blockDescrStartingLba, blockDescrLbaCount);
289
        adaptExt->blk_discard[i].sector = blockDescrStartingLba * (adaptExt->info.blk_size / SECTOR_SIZE);
290
        adaptExt->blk_discard[i].num_sectors = blockDescrLbaCount * (adaptExt->info.blk_size / SECTOR_SIZE);
291
        adaptExt->blk_discard[i].flags = 0;
292
    }
293

294
    srbExt->vbr.out_hdr.sector = 0;
295
    srbExt->vbr.out_hdr.ioprio = 0;
296
    srbExt->vbr.req            = (struct request *)Srb;
297
    srbExt->vbr.out_hdr.type   = VIRTIO_BLK_T_DISCARD | VIRTIO_BLK_T_OUT;
298
    srbExt->out                = 2;
299
    srbExt->in                 = 1;
300

301
    srbExt->sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen);
302
    srbExt->sg[0].length   = sizeof(srbExt->vbr.out_hdr);
303
    srbExt->sg[1].physAddr = MmGetPhysicalAddress(&adaptExt->blk_discard[0]);
304
    srbExt->sg[1].length   = sizeof(blk_discard_write_zeroes) * BlockDescrCount;
305
    srbExt->sg[2].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen);
306
    srbExt->sg[2].length   = sizeof(srbExt->vbr.status);
307

308
    if (adaptExt->num_queues > 1) {
309
        STARTIO_PERFORMANCE_PARAMETERS param;
310
        param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);
311
        status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, &param);
312
        if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {
313
            RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",
314
                Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);
315
            MESSAGENUMBER_TO_QUEUE();
316
        }
317
        else {
318
           RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed srb %p status 0x%x.\n",
319
                        Srb, status);
320
        }
321
    }
322

323
    if (adaptExt->reset_in_progress) {
324
        CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);
325
        return TRUE;
326
    }
327

328
    srbExt->MessageID = MessageId;
329
    vq = adaptExt->vq[QueueNumber];
330
    RhelDbgPrint(TRACE_LEVEL_INFORMATION, " QueueNumber 0x%x vq = %p type = %d\n", QueueNumber, vq, srbExt->vbr.out_hdr.type);
331

332
    element = &adaptExt->processing_srbs[QueueNumber];
333
    VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);
334
    if (virtqueue_add_buf(vq,
335
                     &srbExt->sg[0],
336
                     srbExt->out, srbExt->in,
337
                     &srbExt->vbr, va, pa) >= 0) {
338
        notify = virtqueue_kick_prepare(vq);
339
        InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);
340
        element->srb_cnt++;
341
        VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
342
#ifdef DBG
343
        InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);
344
#endif
345
        result = TRUE;
346
    }
347
    else {
348
        VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
349
        RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);
350
        StorPortBusy(DeviceExtension, 2);
351
    }
352
    if (notify) {
353
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " %s virtqueue_notify %d.\n", __FUNCTION__,  QueueNumber);
354
        virtqueue_notify(vq);
355
    }
356
    return result;
357
}
358

359
BOOLEAN
360
RhelGetSerialNumber(
361
    IN PVOID DeviceExtension,
362
    IN PSRB_TYPE Srb
363
)
364
{
365
    ULONG               QueueNumber = 0;
366
    ULONG               OldIrql = 0;
367
    ULONG               MessageId = 1;
368
    STOR_LOCK_HANDLE    LockHandle = { 0 };
369
    struct virtqueue    *vq = NULL;
370
    PADAPTER_EXTENSION  adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
371
    PSRB_EXTENSION      srbExt   = SRB_EXTENSION(Srb);
372
    ULONG               status = STOR_STATUS_SUCCESS;
373
    PVOID               va = NULL;
374
    ULONGLONG           pa = 0ULL;
375
    BOOLEAN             result = FALSE;
376
    BOOLEAN             notify = FALSE;
377
    ULONG               fragLen = 0UL;
378
    PREQUEST_LIST       element;
379

380
    SET_VA_PA();
381

382
    RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srbExt %p.\n", srbExt);
383

384
    if (adaptExt->num_queues > 1) {
385
        STARTIO_PERFORMANCE_PARAMETERS param;
386
        param.Size = sizeof(STARTIO_PERFORMANCE_PARAMETERS);
387
        status = StorPortGetStartIoPerfParams(DeviceExtension, (PSCSI_REQUEST_BLOCK)Srb, &param);
388
        if (status == STOR_STATUS_SUCCESS && param.MessageNumber != 0) {
389
            RhelDbgPrint(TRACE_LEVEL_INFORMATION, " srb %p, QueueNumber %lu, MessageNumber %lu, ChannelNumber %lu.\n",
390
                Srb, QueueNumber, param.MessageNumber, param.ChannelNumber);
391
            MESSAGENUMBER_TO_QUEUE();
392
        }
393
        else {
394
           RhelDbgPrint(TRACE_LEVEL_ERROR, " StorPortGetStartIoPerfParams failed srb %p status 0x%x.\n",
395
                        Srb, status);
396
        }
397
    }
398
    if (adaptExt->reset_in_progress) {
399
        CompleteRequestWithStatus(DeviceExtension, Srb, SRB_STATUS_BUS_RESET);
400
        return TRUE;
401
    }
402

403
    srbExt->MessageID = MessageId;
404
    vq = adaptExt->vq[QueueNumber];
405

406
    srbExt->vbr.out_hdr.sector = 0;
407
    srbExt->vbr.out_hdr.ioprio = 0;
408
    srbExt->vbr.req            = (struct request *)Srb;
409
    srbExt->vbr.out_hdr.type   = VIRTIO_BLK_T_GET_ID | VIRTIO_BLK_T_IN;
410
    srbExt->out                = 1;
411
    srbExt->in                 = 2;
412

413
    srbExt->sg[0].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.out_hdr, &fragLen);
414
    srbExt->sg[0].length   = sizeof(srbExt->vbr.out_hdr);
415
    srbExt->sg[1].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &adaptExt->sn[0], &fragLen);
416
    srbExt->sg[1].length   = sizeof(adaptExt->sn);
417
    srbExt->sg[2].physAddr = StorPortGetPhysicalAddress(DeviceExtension, NULL, &srbExt->vbr.status, &fragLen);
418
    srbExt->sg[2].length   = sizeof(srbExt->vbr.status);
419

420
    element = &adaptExt->processing_srbs[QueueNumber];
421
    VioStorVQLock(DeviceExtension, MessageId, &LockHandle, FALSE);
422
    if (virtqueue_add_buf(vq,
423
                     &srbExt->sg[0],
424
                     srbExt->out, srbExt->in,
425
                     &srbExt->vbr, va, pa) >= 0) {
426
        notify = virtqueue_kick_prepare(vq);
427
        InsertTailList(&element->srb_list, &srbExt->vbr.list_entry);
428
        element->srb_cnt++;
429
        VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
430
        result = TRUE;
431
#ifdef DBG
432
        InterlockedIncrement((LONG volatile*)&adaptExt->inqueue_cnt);
433
#endif
434
    }
435
    else {
436
        VioStorVQUnlock(DeviceExtension, MessageId, &LockHandle, FALSE);
437
        RhelDbgPrint(TRACE_LEVEL_ERROR, " Can not add packet to queue %d.\n", QueueNumber);
438
        StorPortBusy(DeviceExtension, 2);
439
    }
440
    if (notify) {
441
        virtqueue_notify(vq);
442
    }
443

444
    return result;
445
}
446

447
VOID
448
RhelShutDown(
449
    IN PVOID DeviceExtension
450
    )
451
{
452
    ULONG index;
453
    PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
454

455
    virtio_device_reset(&adaptExt->vdev);
456
    virtio_delete_queues(&adaptExt->vdev);
457
    for (index = 0; index < adaptExt->num_queues; ++index) {
458
        adaptExt->vq[index] = NULL;
459
    }
460
    virtio_device_shutdown(&adaptExt->vdev);
461
}
462

463
ULONGLONG
464
RhelGetLba(
465
    IN PVOID DeviceExtension,
466
    IN PCDB Cdb
467
    )
468
{
469

470
    EIGHT_BYTE lba;
471
    PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
472

473
    lba.AsULongLong = 0;
474

475
    switch (Cdb->CDB6GENERIC.OperationCode) {
476

477
        case SCSIOP_READ:
478
        case SCSIOP_WRITE:
479
        case SCSIOP_READ_CAPACITY:
480
        case SCSIOP_WRITE_VERIFY:
481
        case SCSIOP_VERIFY:
482
        case SCSIOP_UNMAP:
483
        {
484
            lba.Byte0 = Cdb->CDB10.LogicalBlockByte3;
485
            lba.Byte1 = Cdb->CDB10.LogicalBlockByte2;
486
            lba.Byte2 = Cdb->CDB10.LogicalBlockByte1;
487
            lba.Byte3 = Cdb->CDB10.LogicalBlockByte0;
488
        }
489
        break;
490
        case SCSIOP_READ6:
491
        case SCSIOP_WRITE6: {
492
            lba.Byte0 = Cdb->CDB6READWRITE.LogicalBlockMsb1;
493
            lba.Byte1 = Cdb->CDB6READWRITE.LogicalBlockMsb0;
494
            lba.Byte2 = Cdb->CDB6READWRITE.LogicalBlockLsb;
495
        }
496
        break;
497
        case SCSIOP_READ12:
498
        case SCSIOP_WRITE12:
499
        case SCSIOP_WRITE_VERIFY12: {
500
            REVERSE_BYTES(&lba, &Cdb->CDB12.LogicalBlock[0]);
501
        }
502
        break;
503
        case SCSIOP_READ16:
504
        case SCSIOP_WRITE16:
505
        case SCSIOP_READ_CAPACITY16:
506
        case SCSIOP_WRITE_VERIFY16:
507
        case SCSIOP_VERIFY16: {
508
            REVERSE_BYTES_QUAD(&lba, &Cdb->CDB16.LogicalBlock[0]);
509
        }
510
        break;
511
        default: {
512
            ASSERT(FALSE);
513
            return (ULONGLONG)-1;
514
        }
515
    }
516
    return (lba.AsULongLong * (adaptExt->info.blk_size / SECTOR_SIZE));
517
}
518

519
ULONG
520
RhelGetSectors(
521
    IN PVOID DeviceExtension,
522
    IN PCDB Cdb
523
)
524
{
525
    FOUR_BYTE sector;
526
    PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
527

528
    sector.AsULong = 0UL;
529

530
    switch (Cdb->CDB6GENERIC.OperationCode) {
531

532
        case SCSIOP_READ:
533
        case SCSIOP_WRITE:
534
        case SCSIOP_READ_CAPACITY:
535
        case SCSIOP_WRITE_VERIFY:
536
        case SCSIOP_VERIFY:{
537
            sector.Byte0 = Cdb->CDB10.TransferBlocksLsb;
538
            sector.Byte1 = Cdb->CDB10.TransferBlocksMsb;
539
        }
540
        break;
541
        case SCSIOP_READ16:
542
        case SCSIOP_WRITE16:
543
        case SCSIOP_READ_CAPACITY16:
544
        case SCSIOP_WRITE_VERIFY16:
545
        case SCSIOP_VERIFY16: {
546
            REVERSE_BYTES(&sector, &Cdb->CDB16.TransferLength[0]);
547
        }
548
        break;
549
        default: {
550
            ASSERT(FALSE);
551
            return (ULONGLONG)-1;
552
        }
553
    }
554
    return (sector.AsULong * (adaptExt->info.blk_size / SECTOR_SIZE));
555
}
556

557

558
VOID
559
RhelGetDiskGeometry(
560
    IN PVOID DeviceExtension
561
)
562
{
563
    u64                cap;
564
    u32                v;
565
    struct virtio_blk_geometry vgeo;
566

567
    PADAPTER_EXTENSION adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
568
    adaptExt->features = virtio_get_features(&adaptExt->vdev);
569

570
    if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BARRIER)) {
571
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_BARRIER\n");
572
    }
573

574
    if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_RO)) {
575
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_RO\n");
576
    }
577

578
    if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SIZE_MAX)) {
579
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, size_max),
580
                          &v, sizeof(v));
581
        adaptExt->info.size_max = v;
582
    } else {
583
        adaptExt->info.size_max = PAGE_SIZE;
584
    }
585

586
    if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_SEG_MAX)) {
587
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, seg_max),
588
                          &v, sizeof(v));
589
        adaptExt->info.seg_max = v;
590
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_SEG_MAX = %d\n", adaptExt->info.seg_max);
591
    }
592

593
    if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_BLK_SIZE)) {
594
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, blk_size),
595
                          &v, sizeof(v));
596
        adaptExt->info.blk_size = v;
597
    } else {
598
        adaptExt->info.blk_size = SECTOR_SIZE;
599
    }
600
    RhelDbgPrint(TRACE_LEVEL_INFORMATION, " VIRTIO_BLK_F_BLK_SIZE = %d\n", adaptExt->info.blk_size);
601

602
    if (CHECKBIT(adaptExt->features, VIRTIO_BLK_F_GEOMETRY)) {
603
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, geometry),
604
                          &vgeo, sizeof(vgeo));
605
        adaptExt->info.geometry.cylinders= vgeo.cylinders;
606
        adaptExt->info.geometry.heads    = vgeo.heads;
607
        adaptExt->info.geometry.sectors  = vgeo.sectors;
608
        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);
609
    }
610

611
    virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, capacity),
612
                      &cap, sizeof(cap));
613
    adaptExt->info.capacity = cap;
614
    RhelDbgPrint(TRACE_LEVEL_INFORMATION, " device capacity = %08I64X\n", adaptExt->info.capacity);
615

616

617
    if(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_TOPOLOGY)) {
618
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, physical_block_exp),
619
                          &adaptExt->info.physical_block_exp, sizeof(adaptExt->info.physical_block_exp));
620
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " physical_block_exp = %d\n", adaptExt->info.physical_block_exp);
621

622
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, alignment_offset),
623
                          &adaptExt->info.alignment_offset, sizeof(adaptExt->info.alignment_offset));
624
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " alignment_offset = %d\n", adaptExt->info.alignment_offset);
625

626
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, min_io_size),
627
                          &adaptExt->info.min_io_size, sizeof(adaptExt->info.min_io_size));
628
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " min_io_size = %d\n", adaptExt->info.min_io_size);
629

630
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, opt_io_size),
631
                          &adaptExt->info.opt_io_size, sizeof(adaptExt->info.opt_io_size));
632
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " opt_io_size = %d\n", adaptExt->info.opt_io_size);
633
    }
634

635
    if(CHECKBIT(adaptExt->features, VIRTIO_BLK_F_DISCARD)) {
636
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, discard_sector_alignment),
637
                          &v, sizeof(v));
638
        if (v > 0) {
639
            v = max(v, MIN_DISCARD_SECTOR_ALIGNMENT);
640
        }
641
        adaptExt->info.discard_sector_alignment = v << SECTOR_SHIFT;
642

643
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " discard_sector_alignment = %d\n", adaptExt->info.discard_sector_alignment);
644

645
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, max_discard_sectors),
646
                          &v, sizeof(v));
647
        adaptExt->info.max_discard_sectors = v ? v : UINT_MAX;
648
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " max_discard_sectors = %d\n", adaptExt->info.max_discard_sectors);
649

650
        virtio_get_config(&adaptExt->vdev, FIELD_OFFSET(blk_config, max_discard_seg),
651
                          &v, sizeof(v));
652
        adaptExt->info.max_discard_seg = (v < MAX_DISCARD_SEGMENTS) ? v : MAX_DISCARD_SEGMENTS -1;
653
        RhelDbgPrint(TRACE_LEVEL_INFORMATION, " max_discard_seg = %d\n", adaptExt->info.max_discard_seg);
654
    }
655
}
656

657
VOID
658
VioStorVQLock(
659
    IN PVOID DeviceExtension,
660
    IN ULONG MessageID,
661
    IN OUT PSTOR_LOCK_HANDLE LockHandle,
662
    IN BOOLEAN isr
663
    )
664
{
665
    PADAPTER_EXTENSION  adaptExt;
666
    RhelDbgPrint(TRACE_LEVEL_VERBOSE, " ---> MessageID = %d isr = %d\n",  MessageID, isr);
667

668
    adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
669
    if (!isr) {
670
        if (adaptExt->msix_enabled) {
671
            if (adaptExt->num_queues > 1) {
672

673
                NT_ASSERT(MessageID > 0);
674
                NT_ASSERT(MessageID <= adaptExt->num_queues);
675
                StorPortAcquireSpinLock(DeviceExtension, DpcLock, &adaptExt->dpc[MessageID - 1], LockHandle);
676
            }
677
            else {
678
                ULONG oldIrql = 0;
679
                StorPortAcquireMSISpinLock(DeviceExtension, (adaptExt->msix_one_vector ? 0 : MessageID), &oldIrql);
680
                LockHandle->Context.OldIrql = (KIRQL)oldIrql;
681
            }
682
        }
683
        else {
684
            StorPortAcquireSpinLock(DeviceExtension, InterruptLock, NULL, LockHandle);
685
        }
686
    }
687
    RhelDbgPrint(TRACE_LEVEL_VERBOSE, " <--- MessageID = %d\n", MessageID);
688
}
689

690
VOID
691
VioStorVQUnlock(
692
    IN PVOID DeviceExtension,
693
    IN ULONG MessageID,
694
    IN PSTOR_LOCK_HANDLE LockHandle,
695
    IN BOOLEAN isr
696
    )
697
{
698
    PADAPTER_EXTENSION  adaptExt;
699
    RhelDbgPrint(TRACE_LEVEL_VERBOSE, " ---> MessageID = %d isr = %d\n", MessageID, isr);
700
    adaptExt = (PADAPTER_EXTENSION)DeviceExtension;
701

702
    if (!isr) {
703
        if (adaptExt->msix_enabled) {
704
            if (adaptExt->num_queues > 1) {
705
                StorPortReleaseSpinLock(DeviceExtension, LockHandle);
706
            }
707
            else {
708
                StorPortReleaseMSISpinLock(DeviceExtension, (adaptExt->msix_one_vector ? 0 : MessageID), LockHandle->Context.OldIrql);
709
            }
710
        }
711
        else {
712
            StorPortReleaseSpinLock(DeviceExtension, LockHandle);
713
        }
714
    }
715
    RhelDbgPrint(TRACE_LEVEL_VERBOSE, " <--- MessageID = %d\n", MessageID);
716
}
717

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.