Added IOCTL_DISK_SET_PARTITION_INFO.
[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.18 2002/07/18 18:09:59 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 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 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
710 DeviceObject, Irp);
711
712 DeviceExtension = DeviceObject->DeviceExtension;
713 Stack = IoGetCurrentIrpStackLocation(Irp);
714
715 Srb = Stack->Parameters.Scsi.Srb;
716 if (Srb == NULL)
717 {
718 Status = STATUS_UNSUCCESSFUL;
719
720 Irp->IoStatus.Status = Status;
721 Irp->IoStatus.Information = 0;
722
723 IoCompleteRequest(Irp, IO_NO_INCREMENT);
724
725 return(Status);
726 }
727
728 DPRINT("Srb: %p\n", Srb);
729 DPRINT("Srb->Function: %lu\n", Srb->Function);
730 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
731
732 switch (Srb->Function)
733 {
734 case SRB_FUNCTION_EXECUTE_SCSI:
735 IoStartPacket(DeviceObject, Irp, NULL, NULL);
736 return(STATUS_PENDING);
737
738 case SRB_FUNCTION_SHUTDOWN:
739 case SRB_FUNCTION_FLUSH:
740 if (DeviceExtension->PortConfig.CachesData == TRUE)
741 {
742 IoStartPacket(DeviceObject, Irp, NULL, NULL);
743 return(STATUS_PENDING);
744 }
745 break;
746
747 case SRB_FUNCTION_CLAIM_DEVICE:
748 {
749 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
750 PSCSI_INQUIRY_DATA UnitInfo;
751 PINQUIRYDATA InquiryData;
752
753 DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n");
754 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
755
756 Srb->DataBuffer = NULL;
757
758 if (DeviceExtension->PortBusInfo != NULL)
759 {
760 AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
761
762 if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
763 break;
764
765 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
766 AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
767
768 while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
769 {
770 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
771
772 if ((UnitInfo->TargetId == Srb->TargetId) &&
773 (UnitInfo->Lun == Srb->Lun) &&
774 (UnitInfo->DeviceClaimed == FALSE))
775 {
776 UnitInfo->DeviceClaimed = TRUE;
777 DPRINT("Claimed device!\n");
778
779 /* FIXME: Hack!!!!! */
780 Srb->DataBuffer = DeviceObject;
781
782 break;
783 }
784
785 if (UnitInfo->NextInquiryDataOffset == 0)
786 break;
787
788 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
789 }
790 }
791 }
792 break;
793
794 case SRB_FUNCTION_RELEASE_DEVICE:
795 {
796 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
797 PSCSI_INQUIRY_DATA UnitInfo;
798 PINQUIRYDATA InquiryData;
799
800 DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
801 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
802
803 if (DeviceExtension->PortBusInfo != NULL)
804 {
805 AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
806
807 if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
808 break;
809
810 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
811 AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
812
813 while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
814 {
815 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
816
817 if ((UnitInfo->TargetId == Srb->TargetId) &&
818 (UnitInfo->Lun == Srb->Lun) &&
819 (UnitInfo->DeviceClaimed == TRUE))
820 {
821 UnitInfo->DeviceClaimed = FALSE;
822 DPRINT("Released device!\n");
823 break;
824 }
825
826 if (UnitInfo->NextInquiryDataOffset == 0)
827 break;
828
829 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
830 }
831 }
832 }
833 break;
834
835 default:
836 DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
837 Status = STATUS_NOT_IMPLEMENTED;
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 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
889
890 *((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
891 DeviceExtension->PortCapabilities;
892
893 Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
894 }
895 break;
896
897 case IOCTL_SCSI_GET_INQUIRY_DATA:
898 {
899 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
900
901 /* Copy inquiry data to the port device extension */
902 memcpy(Irp->AssociatedIrp.SystemBuffer,
903 DeviceExtension->PortBusInfo,
904 DeviceExtension->PortBusInfoSize);
905
906 DPRINT("BufferSize: %lu\n", DeviceExtension->PortBusInfoSize);
907 Irp->IoStatus.Information = DeviceExtension->PortBusInfoSize;
908 }
909 break;
910
911 default:
912 DPRINT1(" unknown ioctl code: 0x%lX\n",
913 Stack->Parameters.DeviceIoControl.IoControlCode);
914 break;
915 }
916
917 IoCompleteRequest(Irp, IO_NO_INCREMENT);
918
919 return(STATUS_SUCCESS);
920 }
921
922
923 static VOID STDCALL
924 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
925 IN PIRP Irp)
926 {
927 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
928 PIO_STACK_LOCATION IrpStack;
929 KIRQL OldIrql;
930
931 DPRINT("ScsiPortStartIo() called!\n");
932
933 DeviceExtension = DeviceObject->DeviceExtension;
934 IrpStack = IoGetCurrentIrpStackLocation(Irp);
935
936 // FIXME: implement the supported functions
937
938 switch (IrpStack->MajorFunction)
939 {
940 case IRP_MJ_SCSI:
941 {
942 BOOLEAN Result;
943 PSCSI_REQUEST_BLOCK Srb;
944
945 DPRINT("IRP_MJ_SCSI\n");
946
947 Srb = IrpStack->Parameters.Scsi.Srb;
948
949 DPRINT("DeviceExtension %p\n", DeviceExtension);
950
951 Irp->IoStatus.Status = STATUS_SUCCESS;
952 Irp->IoStatus.Information = Srb->DataTransferLength;
953
954 DeviceExtension->CurrentIrp = Irp;
955
956 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
957 ScsiPortStartPacket,
958 DeviceExtension))
959 {
960 DPRINT("Synchronization failed!\n");
961
962 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
963 Irp->IoStatus.Information = 0;
964 IoCompleteRequest(Irp,
965 IO_NO_INCREMENT);
966 IoStartNextPacket(DeviceObject,
967 FALSE);
968 }
969 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
970 {
971 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
972 IoCompleteRequest(Irp,
973 IO_NO_INCREMENT);
974 }
975
976 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
977 {
978 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
979 IoStartNextPacket(DeviceObject,
980 FALSE);
981 }
982 }
983 break;
984
985 default:
986 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
987 Irp->IoStatus.Information = 0;
988 IoCompleteRequest(Irp,
989 IO_NO_INCREMENT);
990 IoStartNextPacket(DeviceObject,
991 FALSE);
992 break;
993 }
994 DPRINT("ScsiPortStartIo() done\n");
995 }
996
997
998 static BOOLEAN STDCALL
999 ScsiPortStartPacket(IN OUT PVOID Context)
1000 {
1001 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1002 PIO_STACK_LOCATION IrpStack;
1003 PSCSI_REQUEST_BLOCK Srb;
1004
1005 DPRINT("ScsiPortStartPacket() called\n");
1006
1007 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
1008
1009 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1010 Srb = IrpStack->Parameters.Scsi.Srb;
1011
1012 return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1013 Srb));
1014 }
1015
1016
1017 /**********************************************************************
1018 * NAME INTERNAL
1019 * ScsiPortCreatePortDevice
1020 *
1021 * DESCRIPTION
1022 * Creates and initializes a SCSI port device object.
1023 *
1024 * RUN LEVEL
1025 * PASSIVE_LEVEL
1026 *
1027 * ARGUMENTS
1028 * DriverObject
1029 * ...
1030 *
1031 * PseudoDeviceExtension
1032 * ...
1033 *
1034 * PortNumber
1035 * ...
1036 *
1037 * RETURNS
1038 * NTSTATUS
1039 */
1040
1041 static NTSTATUS
1042 ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
1043 IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
1044 IN ULONG PortNumber)
1045 {
1046 PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension;
1047 PIO_SCSI_CAPABILITIES PortCapabilities;
1048 PDEVICE_OBJECT PortDeviceObject;
1049 WCHAR NameBuffer[80];
1050 UNICODE_STRING DeviceName;
1051 WCHAR DosNameBuffer[80];
1052 UNICODE_STRING DosDeviceName;
1053 NTSTATUS Status;
1054 ULONG AccessRangeSize;
1055
1056 #if 0
1057 ULONG MappedIrq;
1058 KIRQL Dirql;
1059 KAFFINITY Affinity;
1060 #endif
1061
1062 DPRINT("ScsiPortCreatePortDevice() called\n");
1063
1064 #if 0
1065 MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType,
1066 PseudoDeviceExtension->PortConfig.SystemIoBusNumber,
1067 0,
1068 PseudoDeviceExtension->PortConfig.BusInterruptLevel,
1069 &Dirql,
1070 &Affinity);
1071 #endif
1072
1073 /* Create a unicode device name */
1074 swprintf(NameBuffer,
1075 L"\\Device\\ScsiPort%lu",
1076 PortNumber);
1077 RtlInitUnicodeString(&DeviceName,
1078 NameBuffer);
1079
1080 DPRINT("Creating device: %wZ\n", &DeviceName);
1081
1082 /* Create the port device */
1083 Status = IoCreateDevice(DriverObject,
1084 PseudoDeviceExtension->Length,
1085 &DeviceName,
1086 FILE_DEVICE_CONTROLLER,
1087 0,
1088 FALSE,
1089 &PortDeviceObject);
1090 if (!NT_SUCCESS(Status))
1091 {
1092 DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
1093 return(Status);
1094 }
1095
1096 DPRINT("Created device: %wZ\n", &DeviceName);
1097
1098 /* Set the buffering strategy here... */
1099 PortDeviceObject->Flags |= DO_DIRECT_IO;
1100 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
1101
1102 PortDeviceExtension = PortDeviceObject->DeviceExtension;
1103
1104 /* Copy pseudo device extension into the real device extension */
1105 memcpy(PortDeviceExtension,
1106 PseudoDeviceExtension,
1107 PseudoDeviceExtension->Length);
1108
1109 /* Copy access ranges */
1110 AccessRangeSize =
1111 sizeof(ACCESS_RANGE) * PseudoDeviceExtension->PortConfig.NumberOfAccessRanges;
1112 PortDeviceExtension->PortConfig.AccessRanges = ExAllocatePool(NonPagedPool,
1113 AccessRangeSize);
1114 memcpy(PortDeviceExtension->PortConfig.AccessRanges,
1115 PseudoDeviceExtension->PortConfig.AccessRanges,
1116 AccessRangeSize);
1117
1118 PortDeviceExtension->DeviceObject = PortDeviceObject;
1119
1120
1121 /* Initialize the spin lock in the controller extension */
1122 KeInitializeSpinLock(&PortDeviceExtension->SpinLock);
1123
1124 /* Register an interrupt handler for this device */
1125 Status = IoConnectInterrupt(&PortDeviceExtension->Interrupt,
1126 ScsiPortIsr,
1127 PortDeviceExtension,
1128 &PortDeviceExtension->SpinLock,
1129 PortDeviceExtension->PortConfig.BusInterruptVector, // MappedIrq,
1130 PortDeviceExtension->PortConfig.BusInterruptLevel, // Dirql,
1131 15, //Dirql,
1132 PortDeviceExtension->PortConfig.InterruptMode,
1133 FALSE,
1134 0xFFFF, //Affinity,
1135 FALSE);
1136 if (!NT_SUCCESS(Status))
1137 {
1138 DbgPrint("Could not Connect Interrupt %d\n",
1139 PortDeviceExtension->PortConfig.BusInterruptVector);
1140 return(Status);
1141 }
1142
1143 /* Initialize the DPC object */
1144 IoInitializeDpcRequest(PortDeviceExtension->DeviceObject,
1145 ScsiPortDpcForIsr);
1146
1147 /* Initialize the device timer */
1148 PortDeviceExtension->TimerState = IDETimerIdle;
1149 PortDeviceExtension->TimerCount = 0;
1150 IoInitializeTimer(PortDeviceExtension->DeviceObject,
1151 ScsiPortIoTimer,
1152 PortDeviceExtension);
1153
1154 /* Initialize port capabilities */
1155 PortCapabilities = ExAllocatePool(NonPagedPool,
1156 sizeof(IO_SCSI_CAPABILITIES));
1157 PortDeviceExtension->PortCapabilities = PortCapabilities;
1158 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
1159 PortCapabilities->MaximumTransferLength =
1160 PortDeviceExtension->PortConfig.MaximumTransferLength;
1161 PortCapabilities->MaximumPhysicalPages =
1162 PortCapabilities->MaximumTransferLength / PAGESIZE;
1163 PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
1164 PortCapabilities->AlignmentMask =
1165 PortDeviceExtension->PortConfig.AlignmentMask;
1166 PortCapabilities->TaggedQueuing =
1167 PortDeviceExtension->PortConfig.TaggedQueuing;
1168 PortCapabilities->AdapterScansDown =
1169 PortDeviceExtension->PortConfig.AdapterScansDown;
1170 PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
1171
1172 /* Initialize inquiry data */
1173 PortDeviceExtension->PortBusInfoSize = 0;
1174 PortDeviceExtension->PortBusInfo = NULL;
1175
1176 DPRINT("DeviceExtension %p\n", PortDeviceExtension);
1177 ScsiPortInquire(PortDeviceExtension);
1178
1179
1180 /* FIXME: Copy more configuration data? */
1181
1182 /* Create the dos device link */
1183 swprintf(DosNameBuffer,
1184 L"\\??\\Scsi%lu:",
1185 PortNumber);
1186 RtlInitUnicodeString(&DosDeviceName,
1187 DosNameBuffer);
1188
1189 IoCreateSymbolicLink(&DosDeviceName,
1190 &DeviceName);
1191
1192 DPRINT("ScsiPortCreatePortDevice() done\n");
1193
1194 return(STATUS_SUCCESS);
1195 }
1196
1197
1198 static VOID
1199 ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1200 {
1201 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
1202 PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
1203 SCSI_REQUEST_BLOCK Srb;
1204 ULONG Bus;
1205 ULONG Target;
1206 ULONG UnitCount;
1207 ULONG DataSize;
1208 BOOLEAN Result;
1209
1210 DPRINT("ScsiPortInquire() called\n");
1211
1212 DeviceExtension->Initializing = TRUE;
1213
1214 /* Copy inquiry data to the port device extension */
1215 AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)ExAllocatePool(NonPagedPool, 4096);
1216 RtlZeroMemory(AdapterInfo, 4096);
1217 AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
1218
1219 UnitInfo = (PSCSI_INQUIRY_DATA)
1220 ((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
1221 (sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1)));
1222
1223 RtlZeroMemory(&Srb,
1224 sizeof(SCSI_REQUEST_BLOCK));
1225 Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
1226 Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
1227 Srb.DataTransferLength = 256;
1228 Srb.Cdb[0] = SCSIOP_INQUIRY;
1229
1230 for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++)
1231 {
1232 Srb.PathId = Bus;
1233
1234 AdapterInfo->BusData[Bus].InitiatorBusId = 0; /* ? */
1235 AdapterInfo->BusData[Bus].InquiryDataOffset =
1236 (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo);
1237
1238 PrevUnit = NULL;
1239 UnitCount = 0;
1240
1241 for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
1242 {
1243 Srb.TargetId = Target;
1244 Srb.Lun = 0;
1245 Srb.SrbStatus = SRB_STATUS_SUCCESS;
1246
1247 Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1248 &Srb);
1249 DPRINT("Result: %s Srb.SrbStatus %lx\n", (Result)?"True":"False", Srb.SrbStatus);
1250
1251 if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS)
1252 {
1253 UnitInfo->PathId = Bus;
1254 UnitInfo->TargetId = Target;
1255 UnitInfo->Lun = 0;
1256 UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
1257 memcpy(&UnitInfo->InquiryData,
1258 Srb.DataBuffer,
1259 INQUIRYDATABUFFERSIZE);
1260 if (PrevUnit != NULL)
1261 PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
1262 PrevUnit = UnitInfo;
1263 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
1264 UnitCount++;
1265 }
1266 }
1267 DPRINT("UnitCount: %lu\n", UnitCount);
1268 AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
1269 if (UnitCount == 0)
1270 AdapterInfo->BusData[Bus].InquiryDataOffset = 0;
1271 }
1272 DataSize = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
1273
1274 ExFreePool(Srb.DataBuffer);
1275
1276 DeviceExtension->Initializing = FALSE;
1277
1278 /* copy inquiry data to the port driver's device extension */
1279 DeviceExtension->PortBusInfoSize = DataSize;
1280 DeviceExtension->PortBusInfo = ExAllocatePool(NonPagedPool,
1281 DataSize);
1282 RtlCopyMemory(DeviceExtension->PortBusInfo,
1283 AdapterInfo,
1284 DataSize);
1285
1286 ExFreePool(AdapterInfo);
1287
1288 DPRINT("ScsiPortInquire() done\n");
1289 }
1290
1291
1292 static BOOLEAN STDCALL
1293 ScsiPortIsr(IN PKINTERRUPT Interrupt,
1294 IN PVOID ServiceContext)
1295 {
1296 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1297 BOOLEAN Result;
1298
1299 DPRINT("ScsiPortIsr() called!\n");
1300
1301 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
1302
1303 Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
1304 if (Result == FALSE)
1305 {
1306 return(FALSE);
1307 }
1308
1309 if (DeviceExtension->IrpFlags)
1310 {
1311 IoRequestDpc(DeviceExtension->DeviceObject,
1312 DeviceExtension->CurrentIrp,
1313 DeviceExtension);
1314 }
1315
1316 return(TRUE);
1317 }
1318
1319
1320 // ScsiPortDpcForIsr
1321 // DESCRIPTION:
1322 //
1323 // RUN LEVEL:
1324 //
1325 // ARGUMENTS:
1326 // IN PKDPC Dpc
1327 // IN PDEVICE_OBJECT DpcDeviceObject
1328 // IN PIRP DpcIrp
1329 // IN PVOID DpcContext
1330 //
1331 static VOID STDCALL
1332 ScsiPortDpcForIsr(IN PKDPC Dpc,
1333 IN PDEVICE_OBJECT DpcDeviceObject,
1334 IN PIRP DpcIrp,
1335 IN PVOID DpcContext)
1336 {
1337 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1338 PIO_STACK_LOCATION IrpStack;
1339 PSCSI_REQUEST_BLOCK Srb;
1340
1341 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
1342 Dpc, DpcDeviceObject, DpcIrp, DpcContext);
1343
1344 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
1345
1346 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1347 Srb = IrpStack->Parameters.Scsi.Srb;
1348
1349 if (DeviceExtension->OriginalSrb != NULL)
1350 {
1351 DPRINT("Got sense data!\n");
1352
1353 DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
1354 DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
1355 DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
1356 DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
1357
1358 /* Copy sense data */
1359 if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
1360 {
1361 RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
1362 &DeviceExtension->InternalSenseData,
1363 sizeof(SENSE_DATA));
1364 DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
1365 }
1366
1367 /* Clear current sense data */
1368 RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
1369
1370 IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
1371 DeviceExtension->OriginalSrb = NULL;
1372 }
1373 else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
1374 (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
1375 {
1376 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
1377
1378 DeviceExtension->OriginalSrb = Srb;
1379 IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
1380 Srb);
1381
1382 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
1383 ScsiPortStartPacket,
1384 DeviceExtension))
1385 {
1386 DPRINT("Synchronization failed!\n");
1387
1388 DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1389 DpcIrp->IoStatus.Information = 0;
1390 IoCompleteRequest(DpcIrp,
1391 IO_NO_INCREMENT);
1392 IoStartNextPacket(DpcDeviceObject,
1393 FALSE);
1394 }
1395
1396 return;
1397 }
1398
1399 DeviceExtension->CurrentIrp = NULL;
1400
1401
1402 // DpcIrp->IoStatus.Information = 0;
1403 // DpcIrp->IoStatus.Status = STATUS_SUCCESS;
1404
1405 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
1406 {
1407 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
1408 IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
1409 }
1410
1411 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
1412 {
1413 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
1414 IoStartNextPacket(DpcDeviceObject, FALSE);
1415 }
1416
1417 DPRINT("ScsiPortDpcForIsr() done\n");
1418 }
1419
1420
1421 // ScsiPortIoTimer
1422 // DESCRIPTION:
1423 // This function handles timeouts and other time delayed processing
1424 //
1425 // RUN LEVEL:
1426 //
1427 // ARGUMENTS:
1428 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
1429 // IN PVOID Context the Controller extension for the
1430 // controller the device is on
1431 //
1432 static VOID STDCALL
1433 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
1434 PVOID Context)
1435 {
1436 DPRINT1("ScsiPortIoTimer()\n");
1437 }
1438
1439
1440 static PSCSI_REQUEST_BLOCK
1441 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1442 PSCSI_REQUEST_BLOCK OriginalSrb)
1443 {
1444 PSCSI_REQUEST_BLOCK Srb;
1445 PCDB Cdb;
1446
1447 Srb = &DeviceExtension->InternalSrb;
1448
1449 RtlZeroMemory(Srb,
1450 sizeof(SCSI_REQUEST_BLOCK));
1451
1452 Srb->PathId = OriginalSrb->PathId;
1453 Srb->TargetId = OriginalSrb->TargetId;
1454 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1455 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1456 Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
1457
1458 Srb->TimeOutValue = 4;
1459
1460 Srb->CdbLength = 6;
1461 Srb->DataBuffer = &DeviceExtension->InternalSenseData;
1462 Srb->DataTransferLength = sizeof(SENSE_DATA);
1463
1464 Cdb = (PCDB)Srb->Cdb;
1465 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
1466 Cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
1467
1468 return(Srb);
1469 }
1470
1471
1472 static VOID
1473 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1474 {
1475 DeviceExtension->OriginalSrb = NULL;
1476 }
1477
1478
1479 /* EOF */