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