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