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