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