Staging: hv: add the Hyper-V virtual storage driver
[deliverable/linux.git] / drivers / staging / hv / StorVsc.c
CommitLineData
bef4a34a
HJ
1/*
2 *
3 * Copyright (c) 2009, Microsoft Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * Authors:
19 * Haiyang Zhang <haiyangz@microsoft.com>
20 * Hank Janssen <hjanssen@microsoft.com>
21 *
22 */
23
24
25#include "logging.h"
26
27#include "StorVscApi.h"
28#include "VmbusPacketFormat.h"
29#include "vstorage.h"
30
31
32//
33// #defines
34//
35
36//
37// Data types
38//
39
40typedef struct _STORVSC_REQUEST_EXTENSION {
41 //LIST_ENTRY ListEntry;
42
43 STORVSC_REQUEST *Request;
44 DEVICE_OBJECT *Device;
45
46 // Synchronize the request/response if needed
47 HANDLE WaitEvent;
48
49 VSTOR_PACKET VStorPacket;
50} STORVSC_REQUEST_EXTENSION;
51
52
53// A storvsc device is a device object that contains a vmbus channel
54typedef struct _STORVSC_DEVICE{
55 DEVICE_OBJECT *Device;
56
57 int RefCount; // 0 indicates the device is being destroyed
58
59 int NumOutstandingRequests;
60
61 // Each unique Port/Path/Target represents 1 channel ie scsi controller. In reality, the pathid, targetid is always 0
62 // and the port is set by us
63 ULONG PortNumber;
64 UCHAR PathId;
65 UCHAR TargetId;
66
67 //LIST_ENTRY OutstandingRequestList;
68 //HANDLE OutstandingRequestLock;
69
70 // Used for vsc/vsp channel reset process
71 STORVSC_REQUEST_EXTENSION InitRequest;
72
73 STORVSC_REQUEST_EXTENSION ResetRequest;
74
75} STORVSC_DEVICE;
76
77
78//
79// Globals
80//
81static const char* gDriverName="storvsc";
82
83//{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}
84static const GUID gStorVscDeviceType={
85 .Data = {0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f}
86};
87
88//
89// Internal routines
90//
91static int
92StorVscOnDeviceAdd(
93 DEVICE_OBJECT *Device,
94 void *AdditionalInfo
95 );
96
97static int
98StorVscOnDeviceRemove(
99 DEVICE_OBJECT *Device
100 );
101
102static int
103StorVscOnIORequest(
104 DEVICE_OBJECT *Device,
105 STORVSC_REQUEST *Request
106 );
107
108static int
109StorVscOnHostReset(
110 DEVICE_OBJECT *Device
111 );
112
113static void
114StorVscOnCleanup(
115 DRIVER_OBJECT *Device
116 );
117
118static void
119StorVscOnChannelCallback(
120 PVOID Context
121 );
122
123static void
124StorVscOnIOCompletion(
125 DEVICE_OBJECT *Device,
126 VSTOR_PACKET *VStorPacket,
127 STORVSC_REQUEST_EXTENSION *RequestExt
128 );
129
130static void
131StorVscOnReceive(
132 DEVICE_OBJECT *Device,
133 VSTOR_PACKET *VStorPacket,
134 STORVSC_REQUEST_EXTENSION *RequestExt
135 );
136
137static int
138StorVscConnectToVsp(
139 DEVICE_OBJECT *Device
140 );
141
142static inline STORVSC_DEVICE* AllocStorDevice(DEVICE_OBJECT *Device)
143{
144 STORVSC_DEVICE *storDevice;
145
146 storDevice = MemAllocZeroed(sizeof(STORVSC_DEVICE));
147 if (!storDevice)
148 return NULL;
149
150 // Set to 2 to allow both inbound and outbound traffics
151 // (ie GetStorDevice() and MustGetStorDevice()) to proceed.
152 InterlockedCompareExchange(&storDevice->RefCount, 2, 0);
153
154 storDevice->Device = Device;
155 Device->Extension = storDevice;
156
157 return storDevice;
158}
159
160static inline void FreeStorDevice(STORVSC_DEVICE *Device)
161{
162 ASSERT(Device->RefCount == 0);
163 MemFree(Device);
164}
165
166// Get the stordevice object iff exists and its refcount > 1
167static inline STORVSC_DEVICE* GetStorDevice(DEVICE_OBJECT *Device)
168{
169 STORVSC_DEVICE *storDevice;
170
171 storDevice = (STORVSC_DEVICE*)Device->Extension;
172 if (storDevice && storDevice->RefCount > 1)
173 {
174 InterlockedIncrement(&storDevice->RefCount);
175 }
176 else
177 {
178 storDevice = NULL;
179 }
180
181 return storDevice;
182}
183
184// Get the stordevice object iff exists and its refcount > 0
185static inline STORVSC_DEVICE* MustGetStorDevice(DEVICE_OBJECT *Device)
186{
187 STORVSC_DEVICE *storDevice;
188
189 storDevice = (STORVSC_DEVICE*)Device->Extension;
190 if (storDevice && storDevice->RefCount)
191 {
192 InterlockedIncrement(&storDevice->RefCount);
193 }
194 else
195 {
196 storDevice = NULL;
197 }
198
199 return storDevice;
200}
201
202static inline void PutStorDevice(DEVICE_OBJECT *Device)
203{
204 STORVSC_DEVICE *storDevice;
205
206 storDevice = (STORVSC_DEVICE*)Device->Extension;
207 ASSERT(storDevice);
208
209 InterlockedDecrement(&storDevice->RefCount);
210 ASSERT(storDevice->RefCount);
211}
212
213// Drop ref count to 1 to effectively disable GetStorDevice()
214static inline STORVSC_DEVICE* ReleaseStorDevice(DEVICE_OBJECT *Device)
215{
216 STORVSC_DEVICE *storDevice;
217
218 storDevice = (STORVSC_DEVICE*)Device->Extension;
219 ASSERT(storDevice);
220
221 // Busy wait until the ref drop to 2, then set it to 1
222 while (InterlockedCompareExchange(&storDevice->RefCount, 1, 2) != 2)
223 {
224 Sleep(100);
225 }
226
227 return storDevice;
228}
229
230// Drop ref count to 0. No one can use StorDevice object.
231static inline STORVSC_DEVICE* FinalReleaseStorDevice(DEVICE_OBJECT *Device)
232{
233 STORVSC_DEVICE *storDevice;
234
235 storDevice = (STORVSC_DEVICE*)Device->Extension;
236 ASSERT(storDevice);
237
238 // Busy wait until the ref drop to 1, then set it to 0
239 while (InterlockedCompareExchange(&storDevice->RefCount, 0, 1) != 1)
240 {
241 Sleep(100);
242 }
243
244 Device->Extension = NULL;
245 return storDevice;
246}
247
248/*++;
249
250
251Name:
252 StorVscInitialize()
253
254Description:
255 Main entry point
256
257--*/
258int
259StorVscInitialize(
260 DRIVER_OBJECT *Driver
261 )
262{
263 STORVSC_DRIVER_OBJECT* storDriver = (STORVSC_DRIVER_OBJECT*)Driver;
264 int ret=0;
265
266 DPRINT_ENTER(STORVSC);
267
268 DPRINT_DBG(STORVSC, "sizeof(STORVSC_REQUEST)=%d sizeof(STORVSC_REQUEST_EXTENSION)=%d sizeof(VSTOR_PACKET)=%d, sizeof(VMSCSI_REQUEST)=%d",
269 sizeof(STORVSC_REQUEST), sizeof(STORVSC_REQUEST_EXTENSION), sizeof(VSTOR_PACKET), sizeof(VMSCSI_REQUEST));
270
271 // Make sure we are at least 2 pages since 1 page is used for control
272 ASSERT(storDriver->RingBufferSize >= (PAGE_SIZE << 1));
273
274 Driver->name = gDriverName;
275 memcpy(&Driver->deviceType, &gStorVscDeviceType, sizeof(GUID));
276
277 storDriver->RequestExtSize = sizeof(STORVSC_REQUEST_EXTENSION);
278
279 // Divide the ring buffer data size (which is 1 page less than the ring buffer size since that page is reserved for the ring buffer indices)
280 // by the max request size (which is VMBUS_CHANNEL_PACKET_MULITPAGE_BUFFER + VSTOR_PACKET + UINT64)
281 storDriver->MaxOutstandingRequestsPerChannel =
282 ((storDriver->RingBufferSize - PAGE_SIZE) / ALIGN_UP(MAX_MULTIPAGE_BUFFER_PACKET + sizeof(VSTOR_PACKET) + sizeof(UINT64),sizeof(UINT64)));
283
284 DPRINT_INFO(STORVSC, "max io %u, currently %u\n", storDriver->MaxOutstandingRequestsPerChannel, STORVSC_MAX_IO_REQUESTS);
285
286 // Setup the dispatch table
287 storDriver->Base.OnDeviceAdd = StorVscOnDeviceAdd;
288 storDriver->Base.OnDeviceRemove = StorVscOnDeviceRemove;
289 storDriver->Base.OnCleanup = StorVscOnCleanup;
290
291 storDriver->OnIORequest = StorVscOnIORequest;
292 storDriver->OnHostReset = StorVscOnHostReset;
293
294 DPRINT_EXIT(STORVSC);
295
296 return ret;
297}
298
299/*++
300
301Name:
302 StorVscOnDeviceAdd()
303
304Description:
305 Callback when the device belonging to this driver is added
306
307--*/
308int
309StorVscOnDeviceAdd(
310 DEVICE_OBJECT *Device,
311 void *AdditionalInfo
312 )
313{
314 int ret=0;
315 STORVSC_DEVICE *storDevice;
316 //VMSTORAGE_CHANNEL_PROPERTIES *props;
317 STORVSC_DEVICE_INFO *deviceInfo = (STORVSC_DEVICE_INFO*)AdditionalInfo;
318
319 DPRINT_ENTER(STORVSC);
320
321 storDevice = AllocStorDevice(Device);
322 if (!storDevice)
323 {
324 ret = -1;
325 goto Cleanup;
326 }
327
328 // Save the channel properties to our storvsc channel
329 //props = (VMSTORAGE_CHANNEL_PROPERTIES*) channel->offerMsg.Offer.u.Standard.UserDefined;
330
331 // FIXME:
332 // If we support more than 1 scsi channel, we need to set the port number here
333 // to the scsi channel but how do we get the scsi channel prior to the bus scan
334 /*storChannel->PortNumber = 0;
335 storChannel->PathId = props->PathId;
336 storChannel->TargetId = props->TargetId;*/
337
338 storDevice->PortNumber = deviceInfo->PortNumber;
339 // Send it back up
340 ret = StorVscConnectToVsp(Device);
341
342 //deviceInfo->PortNumber = storDevice->PortNumber;
343 deviceInfo->PathId = storDevice->PathId;
344 deviceInfo->TargetId = storDevice->TargetId;
345
346 DPRINT_DBG(STORVSC, "assigned port %u, path %u target %u\n", storDevice->PortNumber, storDevice->PathId, storDevice->TargetId);
347
348Cleanup:
349 DPRINT_EXIT(STORVSC);
350
351 return ret;
352}
353
354static int StorVscChannelInit(DEVICE_OBJECT *Device)
355{
356 int ret=0;
357 STORVSC_DEVICE *storDevice;
358 STORVSC_REQUEST_EXTENSION *request;
359 VSTOR_PACKET *vstorPacket;
360
361 storDevice = GetStorDevice(Device);
362 if (!storDevice)
363 {
364 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
365 DPRINT_EXIT(STORVSC);
366 return -1;
367 }
368
369 request = &storDevice->InitRequest;
370 vstorPacket = &request->VStorPacket;
371
372 // Now, initiate the vsc/vsp initialization protocol on the open channel
373
374 memset(request, sizeof(STORVSC_REQUEST_EXTENSION), 0);
375 request->WaitEvent = WaitEventCreate();
376
377 vstorPacket->Operation = VStorOperationBeginInitialization;
378 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
379
380 /*SpinlockAcquire(gDriverExt.packetListLock);
381 INSERT_TAIL_LIST(&gDriverExt.packetList, &packet->listEntry.entry);
382 SpinlockRelease(gDriverExt.packetListLock);*/
383
384 DPRINT_INFO(STORVSC, "BEGIN_INITIALIZATION_OPERATION...");
385
386 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
387 vstorPacket,
388 sizeof(VSTOR_PACKET),
389 (ULONG_PTR)request,
390 VmbusPacketTypeDataInBand,
391 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
392 if ( ret != 0)
393 {
394 DPRINT_ERR(STORVSC, "unable to send BEGIN_INITIALIZATION_OPERATION");
395 goto Cleanup;
396 }
397
398 WaitEventWait(request->WaitEvent);
399
400 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
401 {
402 DPRINT_ERR(STORVSC, "BEGIN_INITIALIZATION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
403 goto Cleanup;
404 }
405
406 DPRINT_INFO(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION...");
407
408 // reuse the packet for version range supported
409 memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
410 vstorPacket->Operation = VStorOperationQueryProtocolVersion;
411 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
412
413 vstorPacket->Version.MajorMinor = VMSTOR_PROTOCOL_VERSION_CURRENT;
414 FILL_VMSTOR_REVISION(vstorPacket->Version.Revision);
415
416 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
417 vstorPacket,
418 sizeof(VSTOR_PACKET),
419 (ULONG_PTR)request,
420 VmbusPacketTypeDataInBand,
421 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
422 if ( ret != 0)
423 {
424 DPRINT_ERR(STORVSC, "unable to send BEGIN_INITIALIZATION_OPERATION");
425 goto Cleanup;
426 }
427
428 WaitEventWait(request->WaitEvent);
429
430 // TODO: Check returned version
431 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
432 {
433 DPRINT_ERR(STORVSC, "QUERY_PROTOCOL_VERSION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
434 goto Cleanup;
435 }
436
437 // Query channel properties
438 DPRINT_INFO(STORVSC, "QUERY_PROPERTIES_OPERATION...");
439
440 memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
441 vstorPacket->Operation = VStorOperationQueryProperties;
442 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
443 vstorPacket->StorageChannelProperties.PortNumber = storDevice->PortNumber;
444
445 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
446 vstorPacket,
447 sizeof(VSTOR_PACKET),
448 (ULONG_PTR)request,
449 VmbusPacketTypeDataInBand,
450 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
451
452 if ( ret != 0)
453 {
454 DPRINT_ERR(STORVSC, "unable to send QUERY_PROPERTIES_OPERATION");
455 goto Cleanup;
456 }
457
458 WaitEventWait(request->WaitEvent);
459
460 // TODO: Check returned version
461 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
462 {
463 DPRINT_ERR(STORVSC, "QUERY_PROPERTIES_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
464 goto Cleanup;
465 }
466
467 //storDevice->PortNumber = vstorPacket->StorageChannelProperties.PortNumber;
468 storDevice->PathId = vstorPacket->StorageChannelProperties.PathId;
469 storDevice->TargetId = vstorPacket->StorageChannelProperties.TargetId;
470
471 DPRINT_DBG(STORVSC, "channel flag 0x%x, max xfer len 0x%x", vstorPacket->StorageChannelProperties.Flags, vstorPacket->StorageChannelProperties.MaxTransferBytes);
472
473 DPRINT_INFO(STORVSC, "END_INITIALIZATION_OPERATION...");
474
475 memset(vstorPacket, sizeof(VSTOR_PACKET), 0);
476 vstorPacket->Operation = VStorOperationEndInitialization;
477 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
478
479 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
480 vstorPacket,
481 sizeof(VSTOR_PACKET),
482 (ULONG_PTR)request,
483 VmbusPacketTypeDataInBand,
484 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
485
486 if ( ret != 0)
487 {
488 DPRINT_ERR(STORVSC, "unable to send END_INITIALIZATION_OPERATION");
489 goto Cleanup;
490 }
491
492 WaitEventWait(request->WaitEvent);
493
494 if (vstorPacket->Operation != VStorOperationCompleteIo || vstorPacket->Status != 0)
495 {
496 DPRINT_ERR(STORVSC, "END_INITIALIZATION_OPERATION failed (op %d status 0x%x)", vstorPacket->Operation, vstorPacket->Status);
497 goto Cleanup;
498 }
499
500 DPRINT_INFO(STORVSC, "**** storage channel up and running!! ****");
501
502Cleanup:
503 if (request->WaitEvent)
504 {
505 WaitEventClose(request->WaitEvent);
506 request->WaitEvent = NULL;
507 }
508
509 PutStorDevice(Device);
510
511 DPRINT_EXIT(STORVSC);
512 return ret;
513}
514
515
516int
517StorVscConnectToVsp(
518 DEVICE_OBJECT *Device
519 )
520{
521 int ret=0;
522 VMSTORAGE_CHANNEL_PROPERTIES props;
523
524 STORVSC_DRIVER_OBJECT *storDriver = (STORVSC_DRIVER_OBJECT*) Device->Driver;;
525
526 memset(&props, sizeof(VMSTORAGE_CHANNEL_PROPERTIES), 0);
527
528 // Open the channel
529 ret = Device->Driver->VmbusChannelInterface.Open(Device,
530 storDriver->RingBufferSize,
531 storDriver->RingBufferSize,
532 (PVOID)&props,
533 sizeof(VMSTORAGE_CHANNEL_PROPERTIES),
534 StorVscOnChannelCallback,
535 Device
536 );
537
538 DPRINT_DBG(STORVSC, "storage props: path id %d, tgt id %d, max xfer %d", props.PathId, props.TargetId, props.MaxTransferBytes);
539
540 if (ret != 0)
541 {
542 DPRINT_ERR(STORVSC, "unable to open channel: %d", ret);
543 return -1;
544 }
545
546 ret = StorVscChannelInit(Device);
547
548 return ret;
549}
550
551
552/*++
553
554Name:
555 StorVscOnDeviceRemove()
556
557Description:
558 Callback when the our device is being removed
559
560--*/
561int
562StorVscOnDeviceRemove(
563 DEVICE_OBJECT *Device
564 )
565{
566 STORVSC_DEVICE *storDevice;
567 int ret=0;
568
569 DPRINT_ENTER(STORVSC);
570
571 DPRINT_INFO(STORVSC, "disabling storage device (%p)...", Device->Extension);
572
573 storDevice = ReleaseStorDevice(Device);
574
575 // At this point, all outbound traffic should be disable. We only allow inbound traffic (responses) to proceed
576 // so that outstanding requests can be completed.
577 while (storDevice->NumOutstandingRequests)
578 {
579 DPRINT_INFO(STORVSC, "waiting for %d requests to complete...", storDevice->NumOutstandingRequests);
580
581 Sleep(100);
582 }
583
584 DPRINT_INFO(STORVSC, "removing storage device (%p)...", Device->Extension);
585
586 storDevice = FinalReleaseStorDevice(Device);
587
588 DPRINT_INFO(STORVSC, "storage device (%p) safe to remove", storDevice);
589
590 // Close the channel
591 Device->Driver->VmbusChannelInterface.Close(Device);
592
593 FreeStorDevice(storDevice);
594
595 DPRINT_EXIT(STORVSC);
596 return ret;
597}
598
599
600//static void
601//StorVscOnTargetRescan(
602// void *Context
603// )
604//{
605// DEVICE_OBJECT *device=(DEVICE_OBJECT*)Context;
606// STORVSC_DRIVER_OBJECT *storDriver;
607//
608// DPRINT_ENTER(STORVSC);
609//
610// storDriver = (STORVSC_DRIVER_OBJECT*) device->Driver;
611// storDriver->OnHostRescan(device);
612//
613// DPRINT_EXIT(STORVSC);
614//}
615
616int
617StorVscOnHostReset(
618 DEVICE_OBJECT *Device
619 )
620{
621 int ret=0;
622
623 STORVSC_DEVICE *storDevice;
624 STORVSC_REQUEST_EXTENSION *request;
625 VSTOR_PACKET *vstorPacket;
626
627 DPRINT_ENTER(STORVSC);
628
629 DPRINT_INFO(STORVSC, "resetting host adapter...");
630
631 storDevice = GetStorDevice(Device);
632 if (!storDevice)
633 {
634 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
635 DPRINT_EXIT(STORVSC);
636 return -1;
637 }
638
639 request = &storDevice->ResetRequest;
640 vstorPacket = &request->VStorPacket;
641
642 request->WaitEvent = WaitEventCreate();
643
644 vstorPacket->Operation = VStorOperationResetBus;
645 vstorPacket->Flags = REQUEST_COMPLETION_FLAG;
646 vstorPacket->VmSrb.PathId = storDevice->PathId;
647
648 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
649 vstorPacket,
650 sizeof(VSTOR_PACKET),
651 (ULONG_PTR)&storDevice->ResetRequest,
652 VmbusPacketTypeDataInBand,
653 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
654 if (ret != 0)
655 {
656 DPRINT_ERR(STORVSC, "Unable to send reset packet %p ret %d", vstorPacket, ret);
657 goto Cleanup;
658 }
659
660 // FIXME: Add a timeout
661 WaitEventWait(request->WaitEvent);
662
663 WaitEventClose(request->WaitEvent);
664 DPRINT_INFO(STORVSC, "host adapter reset completed");
665
666 // At this point, all outstanding requests in the adapter should have been flushed out and return to us
667
668Cleanup:
669 PutStorDevice(Device);
670 DPRINT_EXIT(STORVSC);
671 return ret;
672}
673
674/*++
675
676Name:
677 StorVscOnIORequest()
678
679Description:
680 Callback to initiate an I/O request
681
682--*/
683int
684StorVscOnIORequest(
685 DEVICE_OBJECT *Device,
686 STORVSC_REQUEST *Request
687 )
688{
689 STORVSC_DEVICE *storDevice;
690 STORVSC_REQUEST_EXTENSION* requestExtension = (STORVSC_REQUEST_EXTENSION*) Request->Extension;
691 VSTOR_PACKET* vstorPacket =&requestExtension->VStorPacket;
692 int ret=0;
693
694 DPRINT_ENTER(STORVSC);
695
696 storDevice = GetStorDevice(Device);
697
698 DPRINT_DBG(STORVSC, "enter - Device %p, DeviceExt %p, Request %p, Extension %p",
699 Device, storDevice, Request, requestExtension);
700
701 DPRINT_DBG(STORVSC, "req %p len %d bus %d, target %d, lun %d cdblen %d",
702 Request, Request->DataBuffer.Length, Request->Bus, Request->TargetId, Request->LunId, Request->CdbLen);
703
704 if (!storDevice)
705 {
706 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
707 DPRINT_EXIT(STORVSC);
708 return -2;
709 }
710
711 //PrintBytes(Request->Cdb, Request->CdbLen);
712
713 requestExtension->Request = Request;
714 requestExtension->Device = Device;
715
716 memset(vstorPacket, 0 , sizeof(VSTOR_PACKET));
717
718 vstorPacket->Flags |= REQUEST_COMPLETION_FLAG;
719
720 vstorPacket->VmSrb.Length = sizeof(VMSCSI_REQUEST);
721
722 vstorPacket->VmSrb.PortNumber = Request->Host;
723 vstorPacket->VmSrb.PathId = Request->Bus;
724 vstorPacket->VmSrb.TargetId = Request->TargetId;
725 vstorPacket->VmSrb.Lun = Request->LunId;
726
727 vstorPacket->VmSrb.SenseInfoLength = SENSE_BUFFER_SIZE;
728
729 // Copy over the scsi command descriptor block
730 vstorPacket->VmSrb.CdbLength = Request->CdbLen;
731 memcpy(&vstorPacket->VmSrb.Cdb, Request->Cdb, Request->CdbLen);
732
733 vstorPacket->VmSrb.DataIn = Request->Type;
734 vstorPacket->VmSrb.DataTransferLength = Request->DataBuffer.Length;
735
736 vstorPacket->Operation = VStorOperationExecuteSRB;
737
738 DPRINT_DBG(STORVSC, "srb - len %d port %d, path %d, target %d, lun %d senselen %d cdblen %d",
739 vstorPacket->VmSrb.Length,
740 vstorPacket->VmSrb.PortNumber,
741 vstorPacket->VmSrb.PathId,
742 vstorPacket->VmSrb.TargetId,
743 vstorPacket->VmSrb.Lun,
744 vstorPacket->VmSrb.SenseInfoLength,
745 vstorPacket->VmSrb.CdbLength);
746
747 if (requestExtension->Request->DataBuffer.Length)
748 {
749 ret = Device->Driver->VmbusChannelInterface.SendPacketMultiPageBuffer(Device,
750 &requestExtension->Request->DataBuffer,
751 vstorPacket,
752 sizeof(VSTOR_PACKET),
753 (ULONG_PTR)requestExtension);
754 }
755 else
756 {
757 ret = Device->Driver->VmbusChannelInterface.SendPacket(Device,
758 vstorPacket,
759 sizeof(VSTOR_PACKET),
760 (ULONG_PTR)requestExtension,
761 VmbusPacketTypeDataInBand,
762 VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
763 }
764
765 if (ret != 0)
766 {
767 DPRINT_DBG(STORVSC, "Unable to send packet %p ret %d", vstorPacket, ret);
768 }
769
770 InterlockedIncrement(&storDevice->NumOutstandingRequests);
771
772 PutStorDevice(Device);
773
774 DPRINT_EXIT(STORVSC);
775 return ret;
776}
777
778/*++
779
780Name:
781 StorVscOnCleanup()
782
783Description:
784 Perform any cleanup when the driver is removed
785
786--*/
787void
788StorVscOnCleanup(
789 DRIVER_OBJECT *Driver
790 )
791{
792 DPRINT_ENTER(STORVSC);
793 DPRINT_EXIT(STORVSC);
794}
795
796
797static void
798StorVscOnIOCompletion(
799 DEVICE_OBJECT *Device,
800 VSTOR_PACKET *VStorPacket,
801 STORVSC_REQUEST_EXTENSION *RequestExt
802 )
803{
804 STORVSC_REQUEST *request;
805 STORVSC_DEVICE *storDevice;
806
807 DPRINT_ENTER(STORVSC);
808
809 storDevice = MustGetStorDevice(Device);
810 if (!storDevice)
811 {
812 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
813 DPRINT_EXIT(STORVSC);
814 return;
815 }
816
817 DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION - request extension %p completed bytes xfer %u",
818 RequestExt, VStorPacket->VmSrb.DataTransferLength);
819
820 ASSERT(RequestExt != NULL);
821 ASSERT(RequestExt->Request != NULL);
822
823 request = RequestExt->Request;
824
825 ASSERT(request->OnIOCompletion != NULL);
826
827 // Copy over the status...etc
828 request->Status = VStorPacket->VmSrb.ScsiStatus;
829
830 if (request->Status != 0 || VStorPacket->VmSrb.SrbStatus != 1)
831 {
832 DPRINT_WARN(STORVSC, "cmd 0x%x scsi status 0x%x srb status 0x%x\n",
833 request->Cdb[0],
834 VStorPacket->VmSrb.ScsiStatus,
835 VStorPacket->VmSrb.SrbStatus);
836 }
837
838 if ((request->Status & 0xFF) == 0x02) // CHECK_CONDITION
839 {
840 if (VStorPacket->VmSrb.SrbStatus & 0x80) // autosense data available
841 {
842 DPRINT_WARN(STORVSC, "storvsc pkt %p autosense data valid - len %d\n",
843 RequestExt, VStorPacket->VmSrb.SenseInfoLength);
844
845 ASSERT(VStorPacket->VmSrb.SenseInfoLength <= request->SenseBufferSize);
846 memcpy(request->SenseBuffer,
847 VStorPacket->VmSrb.SenseData,
848 VStorPacket->VmSrb.SenseInfoLength);
849
850 request->SenseBufferSize = VStorPacket->VmSrb.SenseInfoLength;
851 }
852 }
853
854 // TODO:
855 request->BytesXfer = VStorPacket->VmSrb.DataTransferLength;
856
857 request->OnIOCompletion(request);
858
859 InterlockedDecrement(&storDevice->NumOutstandingRequests);
860
861 PutStorDevice(Device);
862
863 DPRINT_EXIT(STORVSC);
864}
865
866
867static void
868StorVscOnReceive(
869 DEVICE_OBJECT *Device,
870 VSTOR_PACKET *VStorPacket,
871 STORVSC_REQUEST_EXTENSION *RequestExt
872 )
873{
874 switch(VStorPacket->Operation)
875 {
876 case VStorOperationCompleteIo:
877
878 DPRINT_DBG(STORVSC, "IO_COMPLETE_OPERATION");
879 StorVscOnIOCompletion(Device, VStorPacket, RequestExt);
880 break;
881
882 //case ENUMERATE_DEVICE_OPERATION:
883
884 // DPRINT_INFO(STORVSC, "ENUMERATE_DEVICE_OPERATION");
885
886 // StorVscOnTargetRescan(Device);
887 // break;
888
889 case VStorOperationRemoveDevice:
890
891 DPRINT_INFO(STORVSC, "REMOVE_DEVICE_OPERATION");
892 // TODO:
893 break;
894
895 default:
896 DPRINT_INFO(STORVSC, "Unknown operation received - %d", VStorPacket->Operation);
897 break;
898 }
899}
900
901void
902StorVscOnChannelCallback(
903 PVOID Context
904 )
905{
906 int ret=0;
907 DEVICE_OBJECT *device = (DEVICE_OBJECT*)Context;
908 STORVSC_DEVICE *storDevice;
909 UINT32 bytesRecvd;
910 UINT64 requestId;
911 UCHAR packet[ALIGN_UP(sizeof(VSTOR_PACKET),8)];
912 STORVSC_REQUEST_EXTENSION *request;
913
914 DPRINT_ENTER(STORVSC);
915
916 ASSERT(device);
917
918 storDevice = MustGetStorDevice(device);
919 if (!storDevice)
920 {
921 DPRINT_ERR(STORVSC, "unable to get stor device...device being destroyed?");
922 DPRINT_EXIT(STORVSC);
923 return;
924 }
925
926 do
927 {
928 ret = device->Driver->VmbusChannelInterface.RecvPacket(device,
929 packet,
930 ALIGN_UP(sizeof(VSTOR_PACKET),8),
931 &bytesRecvd,
932 &requestId);
933 if (ret == 0 && bytesRecvd > 0)
934 {
935 DPRINT_DBG(STORVSC, "receive %d bytes - tid %llx", bytesRecvd, requestId);
936
937 //ASSERT(bytesRecvd == sizeof(VSTOR_PACKET));
938
939 request = (STORVSC_REQUEST_EXTENSION*)(ULONG_PTR)requestId;
940 ASSERT(request);
941
942 //if (vstorPacket.Flags & SYNTHETIC_FLAG)
943 if ((request == &storDevice->InitRequest) || (request == &storDevice->ResetRequest))
944 {
945 //DPRINT_INFO(STORVSC, "reset completion - operation %u status %u", vstorPacket.Operation, vstorPacket.Status);
946
947 memcpy(&request->VStorPacket, packet, sizeof(VSTOR_PACKET));
948
949 WaitEventSet(request->WaitEvent);
950 }
951 else
952 {
953 StorVscOnReceive(device, (VSTOR_PACKET*)packet, request);
954 }
955 }
956 else
957 {
958 //DPRINT_DBG(STORVSC, "nothing else to read...");
959 break;
960 }
961 } while (1);
962
963 PutStorDevice(device);
964
965 DPRINT_EXIT(STORVSC);
966 return;
967}
This page took 0.082585 seconds and 5 git commands to generate.