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