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