Changed the ordering for allocating the inquiry buffer and zeroing the srb in ScsiPor...
[reactos.git] / reactos / drivers / storage / scsiport / scsiport.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2001, 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: scsiport.c,v 1.17 2002/07/15 18:25:17 hbirr Exp $
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/scsiport/scsiport.c
24 * PURPOSE: SCSI port driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include "../include/srb.h"
32 #include "../include/scsi.h"
33 #include "../include/ntddscsi.h"
34
35 #define NDEBUG
36 #include <debug.h>
37
38
39 #define VERSION "0.0.1"
40
41
42 /* TYPES *********************************************************************/
43
44
45 typedef enum _SCSI_PORT_TIMER_STATES
46 {
47 IDETimerIdle,
48 IDETimerCmdWait,
49 IDETimerResetWaitForBusyNegate,
50 IDETimerResetWaitForDrdyAssert
51 } SCSI_PORT_TIMER_STATES;
52
53
54 /*
55 * SCSI_PORT_DEVICE_EXTENSION
56 *
57 * DESCRIPTION
58 * First part of the port objects device extension. The second
59 * part is the miniport-specific device extension.
60 */
61
62 typedef struct _SCSI_PORT_DEVICE_EXTENSION
63 {
64 ULONG Length;
65 ULONG MiniPortExtensionSize;
66 PORT_CONFIGURATION_INFORMATION PortConfig;
67
68 KSPIN_LOCK SpinLock;
69 PKINTERRUPT Interrupt;
70 PIRP CurrentIrp;
71 ULONG IrpFlags;
72
73 SCSI_PORT_TIMER_STATES TimerState;
74 LONG TimerCount;
75
76 BOOLEAN Initializing;
77
78 ULONG PortBusInfoSize;
79 PSCSI_ADAPTER_BUS_INFO PortBusInfo;
80
81 PIO_SCSI_CAPABILITIES PortCapabilities;
82
83 PDEVICE_OBJECT DeviceObject;
84 PCONTROLLER_OBJECT ControllerObject;
85
86 PHW_STARTIO HwStartIo;
87 PHW_INTERRUPT HwInterrupt;
88
89 PSCSI_REQUEST_BLOCK OriginalSrb;
90 SCSI_REQUEST_BLOCK InternalSrb;
91 SENSE_DATA InternalSenseData;
92
93 UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
94 } SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
95
96
97 /*
98 * SCSI_PORT_TIMER_STATES
99 *
100 * DESCRIPTION
101 * An enumeration containing the states in the timer DFA
102 */
103
104
105
106 #define IRP_FLAG_COMPLETE 0x00000001
107 #define IRP_FLAG_NEXT 0x00000002
108
109
110 /* GLOBALS *******************************************************************/
111
112 static NTSTATUS STDCALL
113 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
114 IN PIRP Irp);
115
116 static NTSTATUS STDCALL
117 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
118 IN PIRP Irp);
119
120 static NTSTATUS STDCALL
121 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
122 IN PIRP Irp);
123
124 static VOID STDCALL
125 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
126 IN PIRP Irp);
127
128 static IO_ALLOCATION_ACTION STDCALL
129 ScsiPortAllocateController(IN PDEVICE_OBJECT DeviceObject,
130 IN PIRP Irp,
131 IN PVOID MapRegisterBase,
132 IN PVOID Context);
133
134 static BOOLEAN STDCALL
135 ScsiPortStartPacket(IN OUT PVOID Context);
136
137 static NTSTATUS
138 ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
139 IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
140 IN ULONG PortCount);
141
142 static VOID
143 ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
144
145 static BOOLEAN STDCALL
146 ScsiPortIsr(IN PKINTERRUPT Interrupt,
147 IN PVOID ServiceContext);
148
149 static VOID STDCALL
150 ScsiPortDpcForIsr(IN PKDPC Dpc,
151 IN PDEVICE_OBJECT DpcDeviceObject,
152 IN PIRP DpcIrp,
153 IN PVOID DpcContext);
154
155 static VOID STDCALL
156 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
157 PVOID Context);
158
159 static PSCSI_REQUEST_BLOCK
160 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
161 PSCSI_REQUEST_BLOCK OriginalSrb);
162
163 /* FUNCTIONS *****************************************************************/
164
165 /**********************************************************************
166 * NAME EXPORTED
167 * DriverEntry
168 *
169 * DESCRIPTION
170 * This function initializes the driver.
171 *
172 * RUN LEVEL
173 * PASSIVE_LEVEL
174 *
175 * ARGUMENTS
176 * DriverObject
177 * System allocated Driver Object for this driver.
178 *
179 * RegistryPath
180 * Name of registry driver service key.
181 *
182 * RETURN VALUE
183 * Status.
184 */
185
186 NTSTATUS STDCALL
187 DriverEntry(IN PDRIVER_OBJECT DriverObject,
188 IN PUNICODE_STRING RegistryPath)
189 {
190 DPRINT("ScsiPort Driver %s\n", VERSION);
191 return(STATUS_SUCCESS);
192 }
193
194
195 /**********************************************************************
196 * NAME EXPORTED
197 * ScsiDebugPrint
198 *
199 * DESCRIPTION
200 * Prints debugging messages.
201 *
202 * RUN LEVEL
203 * PASSIVE_LEVEL
204 *
205 * ARGUMENTS
206 * DebugPrintLevel
207 * Debug level of the given message.
208 *
209 * DebugMessage
210 * Pointer to printf()-compatible format string.
211 *
212 * ...
213 Additional output data (see printf()).
214 *
215 * RETURN VALUE
216 * None.
217 */
218
219 VOID
220 ScsiDebugPrint(IN ULONG DebugPrintLevel,
221 IN PCHAR DebugMessage,
222 ...)
223 {
224 char Buffer[256];
225 va_list ap;
226
227 #if 0
228 if (DebugPrintLevel > InternalDebugLevel)
229 return;
230 #endif
231
232 va_start(ap, DebugMessage);
233 vsprintf(Buffer, DebugMessage, ap);
234 va_end(ap);
235
236 DbgPrint(Buffer);
237 }
238
239
240 VOID STDCALL
241 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
242 IN UCHAR PathId,
243 IN UCHAR TargetId,
244 IN UCHAR Lun,
245 IN UCHAR SrbStatus)
246 {
247 UNIMPLEMENTED;
248 }
249
250
251 ULONG STDCALL
252 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
253 {
254 return(Address.u.LowPart);
255 }
256
257
258 VOID STDCALL
259 ScsiPortFlushDma(IN PVOID HwDeviceExtension)
260 {
261 UNIMPLEMENTED;
262 }
263
264
265 VOID STDCALL
266 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
267 IN PVOID MappedAddress)
268 {
269 UNIMPLEMENTED;
270 }
271
272
273 ULONG STDCALL
274 ScsiPortGetBusData(IN PVOID DeviceExtension,
275 IN ULONG BusDataType,
276 IN ULONG SystemIoBusNumber,
277 IN ULONG SlotNumber,
278 IN PVOID Buffer,
279 IN ULONG Length)
280 {
281 return(HalGetBusData(BusDataType,
282 SystemIoBusNumber,
283 SlotNumber,
284 Buffer,
285 Length));
286 }
287
288
289 PVOID STDCALL
290 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
291 IN INTERFACE_TYPE BusType,
292 IN ULONG SystemIoBusNumber,
293 IN SCSI_PHYSICAL_ADDRESS IoAddress,
294 IN ULONG NumberOfBytes,
295 IN BOOLEAN InIoSpace)
296 {
297 ULONG AddressSpace;
298 PHYSICAL_ADDRESS TranslatedAddress;
299 PVOID VirtualAddress;
300 PVOID Buffer;
301 BOOLEAN rc;
302
303 AddressSpace = (ULONG)InIoSpace;
304
305 if (!HalTranslateBusAddress(BusType,
306 SystemIoBusNumber,
307 IoAddress,
308 &AddressSpace,
309 &TranslatedAddress))
310 return NULL;
311
312 /* i/o space */
313 if (AddressSpace != 0)
314 return (PVOID)TranslatedAddress.u.LowPart;
315
316 VirtualAddress = MmMapIoSpace(TranslatedAddress,
317 NumberOfBytes,
318 FALSE);
319
320 Buffer = ExAllocatePool(NonPagedPool,0x20);
321 if (Buffer == NULL)
322 return VirtualAddress;
323
324 return NULL; /* ?? */
325 }
326
327
328 PVOID STDCALL
329 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
330 IN UCHAR PathId,
331 IN UCHAR TargetId,
332 IN UCHAR Lun)
333 {
334 UNIMPLEMENTED;
335 }
336
337
338 SCSI_PHYSICAL_ADDRESS STDCALL
339 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
340 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
341 IN PVOID VirtualAddress,
342 OUT ULONG *Length)
343 {
344 UNIMPLEMENTED;
345 }
346
347
348 PSCSI_REQUEST_BLOCK STDCALL
349 ScsiPortGetSrb(IN PVOID DeviceExtension,
350 IN UCHAR PathId,
351 IN UCHAR TargetId,
352 IN UCHAR Lun,
353 IN LONG QueueTag)
354 {
355 UNIMPLEMENTED;
356 }
357
358
359 PVOID STDCALL
360 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
361 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
362 IN ULONG NumberOfBytes)
363 {
364 UNIMPLEMENTED;
365 }
366
367
368 PVOID STDCALL
369 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
370 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
371 {
372 UNIMPLEMENTED;
373 }
374
375
376 /**********************************************************************
377 * NAME EXPORTED
378 * ScsiPortInitialize
379 *
380 * DESCRIPTION
381 * Initializes SCSI port driver specific data.
382 *
383 * RUN LEVEL
384 * PASSIVE_LEVEL
385 *
386 * ARGUMENTS
387 * Argument1
388 * Pointer to the miniport driver's driver object.
389 *
390 * Argument2
391 * Pointer to the miniport driver's registry path.
392 *
393 * HwInitializationData
394 * Pointer to port driver specific configuration data.
395 *
396 * HwContext
397 Miniport driver specific context.
398 *
399 * RETURN VALUE
400 * Status.
401 */
402
403 ULONG STDCALL
404 ScsiPortInitialize(IN PVOID Argument1,
405 IN PVOID Argument2,
406 IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
407 IN PVOID HwContext)
408 {
409 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
410 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
411 PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension;
412 PCONFIGURATION_INFORMATION SystemConfig;
413 PPORT_CONFIGURATION_INFORMATION PortConfig;
414 BOOLEAN Again;
415 ULONG i;
416 ULONG Result;
417 NTSTATUS Status;
418 ULONG MaxBus;
419 PACCESS_RANGE AccessRanges;
420 ULONG ExtensionSize;
421
422 DPRINT("ScsiPortInitialize() called!\n");
423
424 if ((HwInitializationData->HwInitialize == NULL) ||
425 (HwInitializationData->HwStartIo == NULL) ||
426 (HwInitializationData->HwInterrupt == NULL) ||
427 (HwInitializationData->HwFindAdapter == NULL) ||
428 (HwInitializationData->HwResetBus == NULL))
429 return(STATUS_INVALID_PARAMETER);
430
431 DriverObject->DriverStartIo = ScsiPortStartIo;
432 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
433 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
434 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
435 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
436
437
438 SystemConfig = IoGetConfigurationInformation();
439
440 ExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
441 HwInitializationData->DeviceExtensionSize;
442 PseudoDeviceExtension = ExAllocatePool(PagedPool,
443 ExtensionSize);
444 RtlZeroMemory(PseudoDeviceExtension,
445 ExtensionSize);
446 PseudoDeviceExtension->Length = ExtensionSize;
447 PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
448 PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
449 PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
450
451 PortConfig = &PseudoDeviceExtension->PortConfig;
452
453 PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
454 PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
455 PortConfig->InterruptMode =
456 (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
457 PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
458 PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
459 PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
460
461 PortConfig->AccessRanges =
462 ExAllocatePool(PagedPool,
463 sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
464
465
466 PortConfig->SystemIoBusNumber = 0;
467 PortConfig->SlotNumber = 0;
468
469 MaxBus = (PortConfig->AdapterInterfaceType == PCIBus) ? 8 : 1;
470
471 DPRINT("MaxBus: %lu\n", MaxBus);
472
473 while (TRUE)
474 {
475 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
476
477 // RtlZeroMemory(AccessRanges,
478 // sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
479
480 RtlZeroMemory(PseudoDeviceExtension->MiniPortDeviceExtension,
481 PseudoDeviceExtension->MiniPortExtensionSize);
482
483 /* Note: HwFindAdapter is called once for each bus */
484 Result = (HwInitializationData->HwFindAdapter)(&PseudoDeviceExtension->MiniPortDeviceExtension,
485 HwContext,
486 NULL, /* BusInformation */
487 NULL, /* ArgumentString */
488 &PseudoDeviceExtension->PortConfig,
489 &Again);
490 DPRINT("HwFindAdapter() result: %lu\n", Result);
491
492 if (Result == SP_RETURN_FOUND)
493 {
494 DPRINT("ScsiPortInitialize(): Found HBA!\n");
495
496 Status = ScsiPortCreatePortDevice(DriverObject,
497 PseudoDeviceExtension,
498 SystemConfig->ScsiPortCount);
499
500 if (!NT_SUCCESS(Status))
501 {
502 DbgPrint("ScsiPortCreatePortDevice() failed! (Status 0x%lX)\n", Status);
503
504 ExFreePool(PortConfig->AccessRanges);
505 ExFreePool(PseudoDeviceExtension);
506
507 return(Status);
508 }
509
510 /* Update the configuration info */
511 SystemConfig->AtDiskPrimaryAddressClaimed = PortConfig->AtdiskPrimaryClaimed;
512 SystemConfig->AtDiskSecondaryAddressClaimed = PortConfig->AtdiskSecondaryClaimed;
513 SystemConfig->ScsiPortCount++;
514 }
515
516 if (Again == FALSE)
517 {
518 PortConfig->SystemIoBusNumber++;
519 PortConfig->SlotNumber = 0;
520 }
521
522 DPRINT("Bus: %lu MaxBus: %lu\n", PortConfig->SystemIoBusNumber, MaxBus);
523 if (PortConfig->SystemIoBusNumber >= MaxBus)
524 {
525 DPRINT("Scanned all buses!\n");
526 break;
527 }
528 }
529
530 ExFreePool(PortConfig->AccessRanges);
531 ExFreePool(PseudoDeviceExtension);
532
533 DPRINT("ScsiPortInitialize() done!\n");
534
535 return(STATUS_SUCCESS);
536 }
537
538
539 VOID STDCALL
540 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
541 IN PSCSI_REQUEST_BLOCK Srb,
542 IN ULONG LogicalAddress,
543 IN ULONG Length)
544 {
545 UNIMPLEMENTED;
546 }
547
548
549 VOID STDCALL
550 ScsiPortLogError(IN PVOID HwDeviceExtension,
551 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
552 IN UCHAR PathId,
553 IN UCHAR TargetId,
554 IN UCHAR Lun,
555 IN ULONG ErrorCode,
556 IN ULONG UniqueId)
557 {
558 UNIMPLEMENTED;
559 }
560
561
562 VOID STDCALL
563 ScsiPortMoveMemory(OUT PVOID Destination,
564 IN PVOID Source,
565 IN ULONG Length)
566 {
567 RtlMoveMemory(Destination,
568 Source,
569 Length);
570 }
571
572
573 VOID
574 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
575 IN PVOID HwDeviceExtension,
576 ...)
577 {
578 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
579
580 DPRINT("ScsiPortNotification() called\n");
581
582 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
583 SCSI_PORT_DEVICE_EXTENSION,
584 MiniPortDeviceExtension);
585
586 DPRINT("DeviceExtension %p\n", DeviceExtension);
587
588 DPRINT("Initializing = %s\n", (DeviceExtension->Initializing)?"TRUE":"FALSE");
589
590 if (DeviceExtension->Initializing == TRUE)
591 return;
592
593 switch (NotificationType)
594 {
595 case RequestComplete:
596 DPRINT("Notify: RequestComplete\n");
597 DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
598 break;
599
600 case NextRequest:
601 DPRINT("Notify: NextRequest\n");
602 DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
603 break;
604
605 default:
606 break;
607 }
608 }
609
610
611 ULONG STDCALL
612 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
613 IN ULONG BusDataType,
614 IN ULONG SystemIoBusNumber,
615 IN ULONG SlotNumber,
616 IN PVOID Buffer,
617 IN ULONG Offset,
618 IN ULONG Length)
619 {
620 return(HalSetBusDataByOffset(BusDataType,
621 SystemIoBusNumber,
622 SlotNumber,
623 Buffer,
624 Offset,
625 Length));
626 }
627
628
629 BOOLEAN STDCALL
630 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
631 IN INTERFACE_TYPE BusType,
632 IN ULONG SystemIoBusNumber,
633 IN SCSI_PHYSICAL_ADDRESS IoAddress,
634 IN ULONG NumberOfBytes,
635 IN BOOLEAN InIoSpace)
636 {
637 return(TRUE);
638 }
639
640
641 /* INTERNAL FUNCTIONS ********************************************************/
642
643 /**********************************************************************
644 * NAME INTERNAL
645 * ScsiPortCreateClose
646 *
647 * DESCRIPTION
648 * Answer requests for Create/Close calls: a null operation.
649 *
650 * RUN LEVEL
651 * PASSIVE_LEVEL
652 *
653 * ARGUMENTS
654 * DeviceObject
655 * Pointer to a device object.
656 *
657 * Irp
658 * Pointer to an IRP.
659 *
660 * ...
661 Additional output data (see printf()).
662 *
663 * RETURN VALUE
664 * Status.
665 */
666
667 static NTSTATUS STDCALL
668 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
669 IN PIRP Irp)
670 {
671 DPRINT("ScsiPortCreateClose()\n");
672
673 Irp->IoStatus.Status = STATUS_SUCCESS;
674 Irp->IoStatus.Information = FILE_OPENED;
675
676 IoCompleteRequest(Irp, IO_NO_INCREMENT);
677
678 return(STATUS_SUCCESS);
679 }
680
681
682 /**********************************************************************
683 * NAME INTERNAL
684 * ScsiPortDispatchScsi
685 *
686 * DESCRIPTION
687 * Answer requests for SCSI calls
688 *
689 * RUN LEVEL
690 * PASSIVE_LEVEL
691 *
692 * ARGUMENTS
693 * Standard dispatch arguments
694 *
695 * RETURNS
696 * NTSTATUS
697 */
698
699 static NTSTATUS STDCALL
700 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
701 IN PIRP Irp)
702 {
703 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
704 PIO_STACK_LOCATION Stack;
705 PSCSI_REQUEST_BLOCK Srb;
706 NTSTATUS Status = STATUS_SUCCESS;
707 ULONG DataSize = 0;
708
709
710 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
711 DeviceObject, Irp);
712
713 DeviceExtension = DeviceObject->DeviceExtension;
714 Stack = IoGetCurrentIrpStackLocation(Irp);
715
716
717 switch(Stack->Parameters.DeviceIoControl.IoControlCode)
718 {
719 case IOCTL_SCSI_EXECUTE_IN:
720 {
721 DPRINT(" IOCTL_SCSI_EXECUTE_IN\n");
722 }
723 break;
724
725 case IOCTL_SCSI_EXECUTE_OUT:
726 {
727 DPRINT(" IOCTL_SCSI_EXECUTE_OUT\n");
728 }
729 break;
730
731 case IOCTL_SCSI_EXECUTE_NONE:
732 {
733 DPRINT(" IOCTL_SCSI_EXECUTE_NONE\n");
734 }
735 break;
736 }
737
738 Srb = Stack->Parameters.Scsi.Srb;
739 if (Srb == NULL)
740 {
741
742 Status = STATUS_UNSUCCESSFUL;
743
744
745 Irp->IoStatus.Status = Status;
746 Irp->IoStatus.Information = 0;
747
748 IoCompleteRequest(Irp, IO_NO_INCREMENT);
749
750 return(Status);
751 }
752
753 DPRINT("Srb: %p\n", Srb);
754 DPRINT("Srb->Function: %lu\n", Srb->Function);
755 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
756
757 switch (Srb->Function)
758 {
759 case SRB_FUNCTION_EXECUTE_SCSI:
760 DPRINT(" SRB_FUNCTION_EXECUTE_SCSI\n");
761 IoStartPacket(DeviceObject, Irp, NULL, NULL);
762 DPRINT("Returning STATUS_PENDING\n");
763 return(STATUS_PENDING);
764
765 case SRB_FUNCTION_CLAIM_DEVICE:
766 {
767 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
768 PSCSI_INQUIRY_DATA UnitInfo;
769 PINQUIRYDATA InquiryData;
770
771 DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n");
772 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
773
774 Srb->DataBuffer = NULL;
775
776 if (DeviceExtension->PortBusInfo != NULL)
777 {
778 AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
779
780 if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
781 break;
782
783 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
784 AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
785
786 while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
787 {
788 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
789
790 if ((UnitInfo->TargetId == Srb->TargetId) &&
791 (UnitInfo->Lun == Srb->Lun) &&
792 (UnitInfo->DeviceClaimed == FALSE))
793 {
794 UnitInfo->DeviceClaimed = TRUE;
795 DPRINT("Claimed device!\n");
796
797 /* FIXME: Hack!!!!! */
798 Srb->DataBuffer = DeviceObject;
799
800 break;
801 }
802
803 if (UnitInfo->NextInquiryDataOffset == 0)
804 break;
805
806 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
807 }
808 }
809 }
810 break;
811
812 case SRB_FUNCTION_RELEASE_DEVICE:
813 {
814 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
815 PSCSI_INQUIRY_DATA UnitInfo;
816 PINQUIRYDATA InquiryData;
817
818 DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
819 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
820
821 if (DeviceExtension->PortBusInfo != NULL)
822 {
823 AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
824
825 if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
826 break;
827
828 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
829 AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
830
831 while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
832 {
833 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
834
835 if ((UnitInfo->TargetId == Srb->TargetId) &&
836 (UnitInfo->Lun == Srb->Lun) &&
837 (UnitInfo->DeviceClaimed == TRUE))
838 {
839 UnitInfo->DeviceClaimed = FALSE;
840 DPRINT("Released device!\n");
841 break;
842 }
843
844 if (UnitInfo->NextInquiryDataOffset == 0)
845 break;
846
847 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
848 }
849 }
850 }
851 break;
852 }
853
854 Irp->IoStatus.Status = Status;
855 Irp->IoStatus.Information = DataSize;
856
857 IoCompleteRequest(Irp, IO_NO_INCREMENT);
858
859 return(Status);
860 }
861
862
863 /**********************************************************************
864 * NAME INTERNAL
865 * ScsiPortDeviceControl
866 *
867 * DESCRIPTION
868 * Answer requests for device control calls
869 *
870 * RUN LEVEL
871 * PASSIVE_LEVEL
872 *
873 * ARGUMENTS
874 * Standard dispatch arguments
875 *
876 * RETURNS
877 * NTSTATUS
878 */
879
880 static NTSTATUS STDCALL
881 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
882 IN PIRP Irp)
883 {
884 PIO_STACK_LOCATION Stack;
885 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
886
887 DPRINT("ScsiPortDeviceControl()\n");
888
889 Irp->IoStatus.Status = STATUS_SUCCESS;
890 Irp->IoStatus.Information = 0;
891
892
893 Stack = IoGetCurrentIrpStackLocation(Irp);
894 DeviceExtension = DeviceObject->DeviceExtension;
895
896 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
897 {
898
899 case IOCTL_SCSI_GET_CAPABILITIES:
900 {
901 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
902
903 *((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
904 DeviceExtension->PortCapabilities;
905
906 Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
907 }
908 break;
909
910 case IOCTL_SCSI_GET_INQUIRY_DATA:
911 {
912 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
913
914 /* Copy inquiry data to the port device extension */
915 memcpy(Irp->AssociatedIrp.SystemBuffer,
916 DeviceExtension->PortBusInfo,
917 DeviceExtension->PortBusInfoSize);
918
919 DPRINT("BufferSize: %lu\n", DeviceExtension->PortBusInfoSize);
920 Irp->IoStatus.Information = DeviceExtension->PortBusInfoSize;
921 }
922 break;
923
924 default:
925 DPRINT1(" unknown ioctl code: 0x%lX\n",
926 Stack->Parameters.DeviceIoControl.IoControlCode);
927 break;
928 }
929
930 IoCompleteRequest(Irp, IO_NO_INCREMENT);
931
932 return(STATUS_SUCCESS);
933 }
934
935
936 static VOID STDCALL
937 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
938 IN PIRP Irp)
939 {
940 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
941 PIO_STACK_LOCATION IrpStack;
942 KIRQL OldIrql;
943
944 DPRINT("ScsiPortStartIo() called!\n");
945
946 DeviceExtension = DeviceObject->DeviceExtension;
947 IrpStack = IoGetCurrentIrpStackLocation(Irp);
948
949 // FIXME: implement the supported functions
950
951 switch (IrpStack->MajorFunction)
952 {
953 case IRP_MJ_SCSI:
954 {
955 BOOLEAN Result;
956 PSCSI_REQUEST_BLOCK Srb;
957
958 DPRINT("IRP_MJ_SCSI\n");
959
960 Srb = IrpStack->Parameters.Scsi.Srb;
961
962 DPRINT("DeviceExtension %p\n", DeviceExtension);
963
964 Irp->IoStatus.Status = STATUS_SUCCESS;
965 Irp->IoStatus.Information = Srb->DataTransferLength;
966
967 DeviceExtension->CurrentIrp = Irp;
968
969 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
970 ScsiPortStartPacket,
971 DeviceExtension))
972 {
973 DPRINT("Synchronization failed!\n");
974
975 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
976 Irp->IoStatus.Information = 0;
977 IoCompleteRequest(Irp,
978 IO_NO_INCREMENT);
979 IoStartNextPacket(DeviceObject,
980 FALSE);
981 }
982 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
983 {
984 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
985 IoCompleteRequest(Irp,
986 IO_NO_INCREMENT);
987 }
988
989 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
990 {
991 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
992 IoStartNextPacket(DeviceObject,
993 FALSE);
994 }
995 }
996 break;
997
998 default:
999 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1000 Irp->IoStatus.Information = 0;
1001 IoCompleteRequest(Irp,
1002 IO_NO_INCREMENT);
1003 IoStartNextPacket(DeviceObject,
1004 FALSE);
1005 break;
1006 }
1007 DPRINT("ScsiPortStartIo() done\n");
1008 }
1009
1010
1011 static BOOLEAN STDCALL
1012 ScsiPortStartPacket(IN OUT PVOID Context)
1013 {
1014 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1015 PIO_STACK_LOCATION IrpStack;
1016 PSCSI_REQUEST_BLOCK Srb;
1017
1018 DPRINT("ScsiPortStartPacket() called\n");
1019
1020 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
1021
1022 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1023 Srb = IrpStack->Parameters.Scsi.Srb;
1024
1025 return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1026 Srb));
1027 }
1028
1029
1030 /**********************************************************************
1031 * NAME INTERNAL
1032 * ScsiPortCreatePortDevice
1033 *
1034 * DESCRIPTION
1035 * Creates and initializes a SCSI port device object.
1036 *
1037 * RUN LEVEL
1038 * PASSIVE_LEVEL
1039 *
1040 * ARGUMENTS
1041 * DriverObject
1042 * ...
1043 *
1044 * PseudoDeviceExtension
1045 * ...
1046 *
1047 * PortNumber
1048 * ...
1049 *
1050 * RETURNS
1051 * NTSTATUS
1052 */
1053
1054 static NTSTATUS
1055 ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
1056 IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
1057 IN ULONG PortNumber)
1058 {
1059 PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension;
1060 PIO_SCSI_CAPABILITIES PortCapabilities;
1061 PDEVICE_OBJECT PortDeviceObject;
1062 WCHAR NameBuffer[80];
1063 UNICODE_STRING DeviceName;
1064 WCHAR DosNameBuffer[80];
1065 UNICODE_STRING DosDeviceName;
1066 NTSTATUS Status;
1067 ULONG AccessRangeSize;
1068
1069 #if 0
1070 ULONG MappedIrq;
1071 KIRQL Dirql;
1072 KAFFINITY Affinity;
1073 #endif
1074
1075 DPRINT("ScsiPortCreatePortDevice() called\n");
1076
1077 #if 0
1078 MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType,
1079 PseudoDeviceExtension->PortConfig.SystemIoBusNumber,
1080 0,
1081 PseudoDeviceExtension->PortConfig.BusInterruptLevel,
1082 &Dirql,
1083 &Affinity);
1084 #endif
1085
1086 /* Create a unicode device name */
1087 swprintf(NameBuffer,
1088 L"\\Device\\ScsiPort%lu",
1089 PortNumber);
1090 RtlInitUnicodeString(&DeviceName,
1091 NameBuffer);
1092
1093 DPRINT("Creating device: %wZ\n", &DeviceName);
1094
1095 /* Create the port device */
1096 Status = IoCreateDevice(DriverObject,
1097 PseudoDeviceExtension->Length,
1098 &DeviceName,
1099 FILE_DEVICE_CONTROLLER,
1100 0,
1101 FALSE,
1102 &PortDeviceObject);
1103 if (!NT_SUCCESS(Status))
1104 {
1105 DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
1106 return(Status);
1107 }
1108
1109 DPRINT("Created device: %wZ\n", &DeviceName);
1110
1111 /* Set the buffering strategy here... */
1112 PortDeviceObject->Flags |= DO_DIRECT_IO;
1113 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
1114
1115 PortDeviceExtension = PortDeviceObject->DeviceExtension;
1116
1117 /* Copy pseudo device extension into the real device extension */
1118 memcpy(PortDeviceExtension,
1119 PseudoDeviceExtension,
1120 PseudoDeviceExtension->Length);
1121
1122 /* Copy access ranges */
1123 AccessRangeSize =
1124 sizeof(ACCESS_RANGE) * PseudoDeviceExtension->PortConfig.NumberOfAccessRanges;
1125 PortDeviceExtension->PortConfig.AccessRanges = ExAllocatePool(NonPagedPool,
1126 AccessRangeSize);
1127 memcpy(PortDeviceExtension->PortConfig.AccessRanges,
1128 PseudoDeviceExtension->PortConfig.AccessRanges,
1129 AccessRangeSize);
1130
1131 PortDeviceExtension->DeviceObject = PortDeviceObject;
1132
1133
1134 /* Initialize the spin lock in the controller extension */
1135 KeInitializeSpinLock(&PortDeviceExtension->SpinLock);
1136
1137 /* Register an interrupt handler for this device */
1138 Status = IoConnectInterrupt(&PortDeviceExtension->Interrupt,
1139 ScsiPortIsr,
1140 PortDeviceExtension,
1141 &PortDeviceExtension->SpinLock,
1142 PortDeviceExtension->PortConfig.BusInterruptVector, // MappedIrq,
1143 PortDeviceExtension->PortConfig.BusInterruptLevel, // Dirql,
1144 15, //Dirql,
1145 PortDeviceExtension->PortConfig.InterruptMode,
1146 FALSE,
1147 0xFFFF, //Affinity,
1148 FALSE);
1149 if (!NT_SUCCESS(Status))
1150 {
1151 DbgPrint("Could not Connect Interrupt %d\n",
1152 PortDeviceExtension->PortConfig.BusInterruptVector);
1153 return(Status);
1154 }
1155
1156 /* Initialize the DPC object */
1157 IoInitializeDpcRequest(PortDeviceExtension->DeviceObject,
1158 ScsiPortDpcForIsr);
1159
1160 /* Initialize the device timer */
1161 PortDeviceExtension->TimerState = IDETimerIdle;
1162 PortDeviceExtension->TimerCount = 0;
1163 IoInitializeTimer(PortDeviceExtension->DeviceObject,
1164 ScsiPortIoTimer,
1165 PortDeviceExtension);
1166
1167 /* Initialize port capabilities */
1168 PortCapabilities = ExAllocatePool(NonPagedPool,
1169 sizeof(IO_SCSI_CAPABILITIES));
1170 PortDeviceExtension->PortCapabilities = PortCapabilities;
1171 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
1172 PortCapabilities->MaximumTransferLength =
1173 PortDeviceExtension->PortConfig.MaximumTransferLength;
1174 PortCapabilities->MaximumPhysicalPages =
1175 PortCapabilities->MaximumTransferLength / PAGESIZE;
1176 PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
1177 PortCapabilities->AlignmentMask =
1178 PortDeviceExtension->PortConfig.AlignmentMask;
1179 PortCapabilities->TaggedQueuing =
1180 PortDeviceExtension->PortConfig.TaggedQueuing;
1181 PortCapabilities->AdapterScansDown =
1182 PortDeviceExtension->PortConfig.AdapterScansDown;
1183 PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
1184
1185 /* Initialize inquiry data */
1186 PortDeviceExtension->PortBusInfoSize = 0;
1187 PortDeviceExtension->PortBusInfo = NULL;
1188
1189 DPRINT("DeviceExtension %p\n", PortDeviceExtension);
1190 ScsiPortInquire(PortDeviceExtension);
1191
1192
1193 /* FIXME: Copy more configuration data? */
1194
1195 /* Create the dos device link */
1196 swprintf(DosNameBuffer,
1197 L"\\??\\Scsi%lu:",
1198 PortNumber);
1199 RtlInitUnicodeString(&DosDeviceName,
1200 DosNameBuffer);
1201
1202 IoCreateSymbolicLink(&DosDeviceName,
1203 &DeviceName);
1204
1205 DPRINT("ScsiPortCreatePortDevice() done\n");
1206
1207 return(STATUS_SUCCESS);
1208 }
1209
1210
1211 static VOID
1212 ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1213 {
1214 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
1215 PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
1216 SCSI_REQUEST_BLOCK Srb;
1217 ULONG Bus;
1218 ULONG Target;
1219 ULONG UnitCount;
1220 ULONG DataSize;
1221 BOOLEAN Result;
1222
1223 DPRINT("ScsiPortInquire() called\n");
1224
1225 DeviceExtension->Initializing = TRUE;
1226
1227 /* Copy inquiry data to the port device extension */
1228 AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)ExAllocatePool(NonPagedPool, 4096);
1229 RtlZeroMemory(AdapterInfo, 4096);
1230 AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
1231
1232 UnitInfo = (PSCSI_INQUIRY_DATA)
1233 ((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
1234 (sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1)));
1235
1236 RtlZeroMemory(&Srb,
1237 sizeof(SCSI_REQUEST_BLOCK));
1238 Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
1239 Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
1240 Srb.DataTransferLength = 256;
1241 Srb.Cdb[0] = SCSIOP_INQUIRY;
1242
1243 for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++)
1244 {
1245 Srb.PathId = Bus;
1246
1247 AdapterInfo->BusData[Bus].InitiatorBusId = 0; /* ? */
1248 AdapterInfo->BusData[Bus].InquiryDataOffset =
1249 (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo);
1250
1251 PrevUnit = NULL;
1252 UnitCount = 0;
1253
1254 for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
1255 {
1256 Srb.TargetId = Target;
1257 Srb.Lun = 0;
1258 Srb.SrbStatus = SRB_STATUS_SUCCESS;
1259
1260 Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1261 &Srb);
1262 DPRINT("Result: %s Srb.SrbStatus %lx\n", (Result)?"True":"False", Srb.SrbStatus);
1263
1264 if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS)
1265 {
1266 UnitInfo->PathId = Bus;
1267 UnitInfo->TargetId = Target;
1268 UnitInfo->Lun = 0;
1269 UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
1270 memcpy(&UnitInfo->InquiryData,
1271 Srb.DataBuffer,
1272 INQUIRYDATABUFFERSIZE);
1273 if (PrevUnit != NULL)
1274 PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
1275 PrevUnit = UnitInfo;
1276 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
1277 UnitCount++;
1278 }
1279 }
1280 DPRINT("UnitCount: %lu\n", UnitCount);
1281 AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
1282 if (UnitCount == 0)
1283 AdapterInfo->BusData[Bus].InquiryDataOffset = 0;
1284 }
1285 DataSize = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
1286
1287 ExFreePool(Srb.DataBuffer);
1288
1289 DeviceExtension->Initializing = FALSE;
1290
1291 /* copy inquiry data to the port driver's device extension */
1292 DeviceExtension->PortBusInfoSize = DataSize;
1293 DeviceExtension->PortBusInfo = ExAllocatePool(NonPagedPool,
1294 DataSize);
1295 RtlCopyMemory(DeviceExtension->PortBusInfo,
1296 AdapterInfo,
1297 DataSize);
1298
1299 ExFreePool(AdapterInfo);
1300
1301 DPRINT("ScsiPortInquire() done\n");
1302 }
1303
1304
1305 static BOOLEAN STDCALL
1306 ScsiPortIsr(IN PKINTERRUPT Interrupt,
1307 IN PVOID ServiceContext)
1308 {
1309 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1310 BOOLEAN Result;
1311
1312 DPRINT("ScsiPortIsr() called!\n");
1313
1314 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
1315
1316 Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
1317 if (Result == FALSE)
1318 {
1319 return(FALSE);
1320 }
1321
1322 if (DeviceExtension->IrpFlags)
1323 {
1324 IoRequestDpc(DeviceExtension->DeviceObject,
1325 DeviceExtension->CurrentIrp,
1326 DeviceExtension);
1327 }
1328
1329 return(TRUE);
1330 }
1331
1332
1333 // ScsiPortDpcForIsr
1334 // DESCRIPTION:
1335 //
1336 // RUN LEVEL:
1337 //
1338 // ARGUMENTS:
1339 // IN PKDPC Dpc
1340 // IN PDEVICE_OBJECT DpcDeviceObject
1341 // IN PIRP DpcIrp
1342 // IN PVOID DpcContext
1343 //
1344 static VOID STDCALL
1345 ScsiPortDpcForIsr(IN PKDPC Dpc,
1346 IN PDEVICE_OBJECT DpcDeviceObject,
1347 IN PIRP DpcIrp,
1348 IN PVOID DpcContext)
1349 {
1350 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1351 PIO_STACK_LOCATION IrpStack;
1352 PSCSI_REQUEST_BLOCK Srb;
1353
1354 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
1355 Dpc, DpcDeviceObject, DpcIrp, DpcContext);
1356
1357 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
1358
1359 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1360 Srb = IrpStack->Parameters.Scsi.Srb;
1361
1362 if (DeviceExtension->OriginalSrb != NULL)
1363 {
1364 DPRINT("Got sense data!\n");
1365
1366 DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
1367 DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
1368 DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
1369 DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
1370
1371 /* Copy sense data */
1372 if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
1373 {
1374 RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
1375 &DeviceExtension->InternalSenseData,
1376 sizeof(SENSE_DATA));
1377 DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
1378 }
1379
1380 /* Clear current sense data */
1381 RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
1382
1383 IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
1384 DeviceExtension->OriginalSrb = NULL;
1385 }
1386 else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
1387 (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
1388 {
1389 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
1390
1391 DeviceExtension->OriginalSrb = Srb;
1392 IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
1393 Srb);
1394
1395 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
1396 ScsiPortStartPacket,
1397 DeviceExtension))
1398 {
1399 DPRINT("Synchronization failed!\n");
1400
1401 DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1402 DpcIrp->IoStatus.Information = 0;
1403 IoCompleteRequest(DpcIrp,
1404 IO_NO_INCREMENT);
1405 IoStartNextPacket(DpcDeviceObject,
1406 FALSE);
1407 }
1408
1409 return;
1410 }
1411
1412 DeviceExtension->CurrentIrp = NULL;
1413
1414
1415 // DpcIrp->IoStatus.Information = 0;
1416 // DpcIrp->IoStatus.Status = STATUS_SUCCESS;
1417
1418 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
1419 {
1420 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
1421 IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
1422 }
1423
1424 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
1425 {
1426 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
1427 IoStartNextPacket(DpcDeviceObject, FALSE);
1428 }
1429
1430 DPRINT("ScsiPortDpcForIsr() done\n");
1431 }
1432
1433
1434 // ScsiPortIoTimer
1435 // DESCRIPTION:
1436 // This function handles timeouts and other time delayed processing
1437 //
1438 // RUN LEVEL:
1439 //
1440 // ARGUMENTS:
1441 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
1442 // IN PVOID Context the Controller extension for the
1443 // controller the device is on
1444 //
1445 static VOID STDCALL
1446 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
1447 PVOID Context)
1448 {
1449 DPRINT1("ScsiPortIoTimer()\n");
1450 }
1451
1452
1453 static PSCSI_REQUEST_BLOCK
1454 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1455 PSCSI_REQUEST_BLOCK OriginalSrb)
1456 {
1457 PSCSI_REQUEST_BLOCK Srb;
1458 PCDB Cdb;
1459
1460 Srb = &DeviceExtension->InternalSrb;
1461
1462 RtlZeroMemory(Srb,
1463 sizeof(SCSI_REQUEST_BLOCK));
1464
1465 Srb->PathId = OriginalSrb->PathId;
1466 Srb->TargetId = OriginalSrb->TargetId;
1467 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1468 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1469 Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
1470
1471 Srb->TimeOutValue = 4;
1472
1473 Srb->CdbLength = 6;
1474 Srb->DataBuffer = &DeviceExtension->InternalSenseData;
1475 Srb->DataTransferLength = sizeof(SENSE_DATA);
1476
1477 Cdb = (PCDB)Srb->Cdb;
1478 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
1479 Cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
1480
1481 return(Srb);
1482 }
1483
1484
1485 static VOID
1486 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1487 {
1488 DeviceExtension->OriginalSrb = NULL;
1489 }
1490
1491
1492 /* EOF */