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