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