- Forgot these two files.
[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.31 2003/08/27 21:30:37 dwelch 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 #include "scsiport_int.h"
42
43 /* TYPES *********************************************************************/
44
45 #define IRP_FLAG_COMPLETE 0x00000001
46 #define IRP_FLAG_NEXT 0x00000002
47
48
49 /* GLOBALS *******************************************************************/
50
51 static NTSTATUS STDCALL
52 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
53 IN PIRP Irp);
54
55 static NTSTATUS STDCALL
56 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
57 IN PIRP Irp);
58
59 static NTSTATUS STDCALL
60 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
61 IN PIRP Irp);
62
63 static VOID STDCALL
64 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
65 IN PIRP Irp);
66
67 static IO_ALLOCATION_ACTION STDCALL
68 ScsiPortAllocateController(IN PDEVICE_OBJECT DeviceObject,
69 IN PIRP Irp,
70 IN PVOID MapRegisterBase,
71 IN PVOID Context);
72
73 static BOOLEAN STDCALL
74 ScsiPortStartPacket(IN OUT PVOID Context);
75
76 static NTSTATUS
77 ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
78 IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
79 IN ULONG PortCount,
80 IN OUT PSCSI_PORT_DEVICE_EXTENSION *RealDeviceExtension);
81
82 static VOID
83 ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
84
85 static BOOLEAN STDCALL
86 ScsiPortIsr(IN PKINTERRUPT Interrupt,
87 IN PVOID ServiceContext);
88
89 static VOID STDCALL
90 ScsiPortDpcForIsr(IN PKDPC Dpc,
91 IN PDEVICE_OBJECT DpcDeviceObject,
92 IN PIRP DpcIrp,
93 IN PVOID DpcContext);
94
95 static VOID STDCALL
96 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
97 PVOID Context);
98
99 static PSCSI_REQUEST_BLOCK
100 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
101 PSCSI_REQUEST_BLOCK OriginalSrb);
102
103 static NTSTATUS
104 ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
105 PUNICODE_STRING RegistryPath);
106
107
108 /* FUNCTIONS *****************************************************************/
109
110 /**********************************************************************
111 * NAME EXPORTED
112 * DriverEntry
113 *
114 * DESCRIPTION
115 * This function initializes the driver.
116 *
117 * RUN LEVEL
118 * PASSIVE_LEVEL
119 *
120 * ARGUMENTS
121 * DriverObject
122 * System allocated Driver Object for this driver.
123 *
124 * RegistryPath
125 * Name of registry driver service key.
126 *
127 * RETURN VALUE
128 * Status.
129 */
130
131 NTSTATUS STDCALL
132 DriverEntry(IN PDRIVER_OBJECT DriverObject,
133 IN PUNICODE_STRING RegistryPath)
134 {
135 DPRINT("ScsiPort Driver %s\n", VERSION);
136 return(STATUS_SUCCESS);
137 }
138
139
140 /**********************************************************************
141 * NAME EXPORTED
142 * ScsiDebugPrint
143 *
144 * DESCRIPTION
145 * Prints debugging messages.
146 *
147 * RUN LEVEL
148 * PASSIVE_LEVEL
149 *
150 * ARGUMENTS
151 * DebugPrintLevel
152 * Debug level of the given message.
153 *
154 * DebugMessage
155 * Pointer to printf()-compatible format string.
156 *
157 * ...
158 Additional output data (see printf()).
159 *
160 * RETURN VALUE
161 * None.
162 *
163 * @implemented
164 */
165
166 VOID
167 ScsiDebugPrint(IN ULONG DebugPrintLevel,
168 IN PCHAR DebugMessage,
169 ...)
170 {
171 char Buffer[256];
172 va_list ap;
173
174 #if 0
175 if (DebugPrintLevel > InternalDebugLevel)
176 return;
177 #endif
178
179 va_start(ap, DebugMessage);
180 vsprintf(Buffer, DebugMessage, ap);
181 va_end(ap);
182
183 DbgPrint(Buffer);
184 }
185
186
187 /*
188 * @unimplemented
189 */
190 VOID STDCALL
191 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
192 IN UCHAR PathId,
193 IN UCHAR TargetId,
194 IN UCHAR Lun,
195 IN UCHAR SrbStatus)
196 {
197 DPRINT("ScsiPortCompleteRequest()\n");
198 UNIMPLEMENTED;
199 }
200
201
202 /*
203 * @implemented
204 */
205 ULONG STDCALL
206 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
207 {
208 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
209 return(Address.u.LowPart);
210 }
211
212
213 /*
214 * @unimplemented
215 */
216 VOID STDCALL
217 ScsiPortFlushDma(IN PVOID HwDeviceExtension)
218 {
219 DPRINT("ScsiPortFlushDma()\n");
220 UNIMPLEMENTED;
221 }
222
223
224 /*
225 * @implemented
226 */
227 VOID STDCALL
228 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
229 IN PVOID MappedAddress)
230 {
231 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
232 PSCSI_PORT_DEVICE_BASE DeviceBase;
233 PLIST_ENTRY Entry;
234
235 DPRINT("ScsiPortFreeDeviceBase() called\n");
236
237 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
238 SCSI_PORT_DEVICE_EXTENSION,
239 MiniPortDeviceExtension);
240 if (IsListEmpty(&DeviceExtension->DeviceBaseListHead))
241 return;
242
243 Entry = DeviceExtension->DeviceBaseListHead.Flink;
244 while (Entry != &DeviceExtension->DeviceBaseListHead)
245 {
246 DeviceBase = CONTAINING_RECORD(Entry,
247 SCSI_PORT_DEVICE_BASE,
248 List);
249 if (DeviceBase->MappedAddress == MappedAddress)
250 {
251 MmUnmapIoSpace(DeviceBase->MappedAddress,
252 DeviceBase->NumberOfBytes);
253 RemoveEntryList(Entry);
254 ExFreePool(DeviceBase);
255
256 return;
257 }
258
259 Entry = Entry->Flink;
260 }
261 }
262
263
264 /*
265 * @implemented
266 */
267 ULONG STDCALL
268 ScsiPortGetBusData(IN PVOID DeviceExtension,
269 IN ULONG BusDataType,
270 IN ULONG SystemIoBusNumber,
271 IN ULONG SlotNumber,
272 IN PVOID Buffer,
273 IN ULONG Length)
274 {
275 return(HalGetBusData(BusDataType,
276 SystemIoBusNumber,
277 SlotNumber,
278 Buffer,
279 Length));
280 }
281
282
283 /*
284 * @implemented
285 */
286 PVOID STDCALL
287 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
288 IN INTERFACE_TYPE BusType,
289 IN ULONG SystemIoBusNumber,
290 IN SCSI_PHYSICAL_ADDRESS IoAddress,
291 IN ULONG NumberOfBytes,
292 IN BOOLEAN InIoSpace)
293 {
294 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
295 PHYSICAL_ADDRESS TranslatedAddress;
296 PSCSI_PORT_DEVICE_BASE DeviceBase;
297 ULONG AddressSpace;
298 PVOID MappedAddress;
299
300 DPRINT("ScsiPortGetDeviceBase() called\n");
301
302 AddressSpace = (ULONG)InIoSpace;
303 if (HalTranslateBusAddress(BusType,
304 SystemIoBusNumber,
305 IoAddress,
306 &AddressSpace,
307 &TranslatedAddress) == FALSE)
308 return NULL;
309
310 /* i/o space */
311 if (AddressSpace != 0)
312 return((PVOID)TranslatedAddress.u.LowPart);
313
314 MappedAddress = MmMapIoSpace(TranslatedAddress,
315 NumberOfBytes,
316 FALSE);
317
318 DeviceBase = ExAllocatePool(NonPagedPool,
319 sizeof(SCSI_PORT_DEVICE_BASE));
320 if (DeviceBase == NULL)
321 return(MappedAddress);
322
323 DeviceBase->MappedAddress = MappedAddress;
324 DeviceBase->NumberOfBytes = NumberOfBytes;
325 DeviceBase->IoAddress = IoAddress;
326 DeviceBase->SystemIoBusNumber = SystemIoBusNumber;
327
328 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
329 SCSI_PORT_DEVICE_EXTENSION,
330 MiniPortDeviceExtension);
331
332 InsertHeadList(&DeviceExtension->DeviceBaseListHead,
333 &DeviceBase->List);
334
335 return(MappedAddress);
336 }
337
338
339 /*
340 * @unimplemented
341 */
342 PVOID STDCALL
343 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
344 IN UCHAR PathId,
345 IN UCHAR TargetId,
346 IN UCHAR Lun)
347 {
348 DPRINT("ScsiPortGetLogicalUnit()\n");
349 UNIMPLEMENTED;
350 }
351
352
353 /*
354 * @unimplemented
355 */
356 SCSI_PHYSICAL_ADDRESS STDCALL
357 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
358 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
359 IN PVOID VirtualAddress,
360 OUT ULONG *Length)
361 {
362 DPRINT("ScsiPortGetPhysicalAddress()\n");
363 UNIMPLEMENTED;
364 }
365
366
367 /*
368 * @unimplemented
369 */
370 PSCSI_REQUEST_BLOCK STDCALL
371 ScsiPortGetSrb(IN PVOID DeviceExtension,
372 IN UCHAR PathId,
373 IN UCHAR TargetId,
374 IN UCHAR Lun,
375 IN LONG QueueTag)
376 {
377 DPRINT("ScsiPortGetSrb()\n");
378 UNIMPLEMENTED;
379 }
380
381
382 /*
383 * @unimplemented
384 */
385 PVOID STDCALL
386 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
387 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
388 IN ULONG NumberOfBytes)
389 {
390 DPRINT("ScsiPortGetUncachedExtension()\n");
391 UNIMPLEMENTED;
392 }
393
394
395 /*
396 * @unimplemented
397 */
398 PVOID STDCALL
399 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
400 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
401 {
402 DPRINT("ScsiPortGetVirtualAddress()\n");
403 UNIMPLEMENTED;
404 }
405
406
407 /**********************************************************************
408 * NAME EXPORTED
409 * ScsiPortInitialize
410 *
411 * DESCRIPTION
412 * Initializes SCSI port driver specific data.
413 *
414 * RUN LEVEL
415 * PASSIVE_LEVEL
416 *
417 * ARGUMENTS
418 * Argument1
419 * Pointer to the miniport driver's driver object.
420 *
421 * Argument2
422 * Pointer to the miniport driver's registry path.
423 *
424 * HwInitializationData
425 * Pointer to port driver specific configuration data.
426 *
427 * HwContext
428 Miniport driver specific context.
429 *
430 * RETURN VALUE
431 * Status.
432 *
433 * @implemented
434 */
435
436 ULONG STDCALL
437 ScsiPortInitialize(IN PVOID Argument1,
438 IN PVOID Argument2,
439 IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
440 IN PVOID HwContext)
441 {
442 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
443 PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
444 PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension;
445 PSCSI_PORT_DEVICE_EXTENSION RealDeviceExtension;
446 PCONFIGURATION_INFORMATION SystemConfig;
447 PPORT_CONFIGURATION_INFORMATION PortConfig;
448 BOOLEAN Again;
449 ULONG i;
450 ULONG Result;
451 NTSTATUS Status;
452 ULONG MaxBus;
453 PACCESS_RANGE AccessRanges;
454 ULONG ExtensionSize;
455
456 DPRINT("ScsiPortInitialize() called!\n");
457
458 if ((HwInitializationData->HwInitialize == NULL) ||
459 (HwInitializationData->HwStartIo == NULL) ||
460 (HwInitializationData->HwInterrupt == NULL) ||
461 (HwInitializationData->HwFindAdapter == NULL) ||
462 (HwInitializationData->HwResetBus == NULL))
463 return(STATUS_INVALID_PARAMETER);
464
465 DriverObject->DriverStartIo = ScsiPortStartIo;
466 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
467 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
468 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
469 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
470
471
472 SystemConfig = IoGetConfigurationInformation();
473
474 ExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
475 HwInitializationData->DeviceExtensionSize;
476 PseudoDeviceExtension = ExAllocatePool(PagedPool,
477 ExtensionSize);
478 RtlZeroMemory(PseudoDeviceExtension,
479 ExtensionSize);
480 PseudoDeviceExtension->Length = ExtensionSize;
481 PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
482 PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
483 PseudoDeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
484
485 PortConfig = &PseudoDeviceExtension->PortConfig;
486
487 PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
488 PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
489 PortConfig->InterruptMode =
490 (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
491 PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
492 PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
493 PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
494
495 PortConfig->AccessRanges =
496 ExAllocatePool(PagedPool,
497 sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
498
499 for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
500 PortConfig->InitiatorBusId[i] = 255;
501
502 PortConfig->SystemIoBusNumber = 0;
503 PortConfig->SlotNumber = 0;
504
505 MaxBus = (PortConfig->AdapterInterfaceType == PCIBus) ? 8 : 1;
506
507 DPRINT("MaxBus: %lu\n", MaxBus);
508
509 while (TRUE)
510 {
511 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
512
513 InitializeListHead(&PseudoDeviceExtension->DeviceBaseListHead);
514
515 // RtlZeroMemory(AccessRanges,
516 // sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
517
518 RtlZeroMemory(PseudoDeviceExtension->MiniPortDeviceExtension,
519 PseudoDeviceExtension->MiniPortExtensionSize);
520
521 /* Note: HwFindAdapter is called once for each bus */
522 Result = (HwInitializationData->HwFindAdapter)(&PseudoDeviceExtension->MiniPortDeviceExtension,
523 HwContext,
524 NULL, /* BusInformation */
525 NULL, /* ArgumentString */
526 &PseudoDeviceExtension->PortConfig,
527 &Again);
528 DPRINT("HwFindAdapter() result: %lu\n", Result);
529
530 if (Result == SP_RETURN_FOUND)
531 {
532 DPRINT("ScsiPortInitialize(): Found HBA!\n");
533
534 Status = ScsiPortCreatePortDevice(DriverObject,
535 PseudoDeviceExtension,
536 SystemConfig->ScsiPortCount,
537 &RealDeviceExtension);
538
539 if (!NT_SUCCESS(Status))
540 {
541 DbgPrint("ScsiPortCreatePortDevice() failed! (Status 0x%lX)\n", Status);
542
543 ExFreePool(PortConfig->AccessRanges);
544 ExFreePool(PseudoDeviceExtension);
545
546 return(Status);
547 }
548
549 /* Build the registry device map */
550 ScsiPortBuildDeviceMap(RealDeviceExtension,
551 (PUNICODE_STRING)Argument2);
552
553 /* Update the configuration info */
554 SystemConfig->AtDiskPrimaryAddressClaimed = PortConfig->AtdiskPrimaryClaimed;
555 SystemConfig->AtDiskSecondaryAddressClaimed = PortConfig->AtdiskSecondaryClaimed;
556 SystemConfig->ScsiPortCount++;
557 }
558
559 if (Again == FALSE)
560 {
561 PortConfig->SystemIoBusNumber++;
562 PortConfig->SlotNumber = 0;
563 }
564
565 DPRINT("Bus: %lu MaxBus: %lu\n", PortConfig->SystemIoBusNumber, MaxBus);
566 if (PortConfig->SystemIoBusNumber >= MaxBus)
567 {
568 DPRINT("Scanned all buses!\n");
569 break;
570 }
571 }
572
573 ExFreePool(PortConfig->AccessRanges);
574 ExFreePool(PseudoDeviceExtension);
575
576 DPRINT("ScsiPortInitialize() done!\n");
577
578 return(STATUS_SUCCESS);
579 }
580
581
582 /*
583 * @unimplemented
584 */
585 VOID STDCALL
586 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
587 IN PSCSI_REQUEST_BLOCK Srb,
588 IN ULONG LogicalAddress,
589 IN ULONG Length)
590 {
591 DPRINT("ScsiPortIoMapTransfer()\n");
592 UNIMPLEMENTED;
593 }
594
595
596 /*
597 * @unimplemented
598 */
599 VOID STDCALL
600 ScsiPortLogError(IN PVOID HwDeviceExtension,
601 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
602 IN UCHAR PathId,
603 IN UCHAR TargetId,
604 IN UCHAR Lun,
605 IN ULONG ErrorCode,
606 IN ULONG UniqueId)
607 {
608 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
609
610 DPRINT("ScsiPortLogError() called\n");
611
612 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
613 SCSI_PORT_DEVICE_EXTENSION,
614 MiniPortDeviceExtension);
615
616
617 DPRINT("ScsiPortLogError() done\n");
618 }
619
620
621 /*
622 * @implemented
623 */
624 VOID STDCALL
625 ScsiPortMoveMemory(OUT PVOID Destination,
626 IN PVOID Source,
627 IN ULONG Length)
628 {
629 RtlMoveMemory(Destination,
630 Source,
631 Length);
632 }
633
634
635 /*
636 * @implemented
637 */
638 VOID
639 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
640 IN PVOID HwDeviceExtension,
641 ...)
642 {
643 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
644
645 DPRINT("ScsiPortNotification() called\n");
646
647 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
648 SCSI_PORT_DEVICE_EXTENSION,
649 MiniPortDeviceExtension);
650
651 DPRINT("DeviceExtension %p\n", DeviceExtension);
652
653 DPRINT("Initializing = %s\n", (DeviceExtension->Initializing)?"TRUE":"FALSE");
654
655 if (DeviceExtension->Initializing == TRUE)
656 return;
657
658 switch (NotificationType)
659 {
660 case RequestComplete:
661 DPRINT("Notify: RequestComplete\n");
662 DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
663 break;
664
665 case NextRequest:
666 DPRINT("Notify: NextRequest\n");
667 DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
668 break;
669
670 default:
671 break;
672 }
673 }
674
675
676 /*
677 * @implemented
678 */
679 ULONG STDCALL
680 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
681 IN ULONG BusDataType,
682 IN ULONG SystemIoBusNumber,
683 IN ULONG SlotNumber,
684 IN PVOID Buffer,
685 IN ULONG Offset,
686 IN ULONG Length)
687 {
688 DPRINT("ScsiPortSetBusDataByOffset()\n");
689 return(HalSetBusDataByOffset(BusDataType,
690 SystemIoBusNumber,
691 SlotNumber,
692 Buffer,
693 Offset,
694 Length));
695 }
696
697
698 /*
699 * @unimplemented
700 */
701 BOOLEAN STDCALL
702 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
703 IN INTERFACE_TYPE BusType,
704 IN ULONG SystemIoBusNumber,
705 IN SCSI_PHYSICAL_ADDRESS IoAddress,
706 IN ULONG NumberOfBytes,
707 IN BOOLEAN InIoSpace)
708 {
709 DPRINT("ScsiPortValidateRange()\n");
710 return(TRUE);
711 }
712
713
714 /* INTERNAL FUNCTIONS ********************************************************/
715
716 /**********************************************************************
717 * NAME INTERNAL
718 * ScsiPortCreateClose
719 *
720 * DESCRIPTION
721 * Answer requests for Create/Close calls: a null operation.
722 *
723 * RUN LEVEL
724 * PASSIVE_LEVEL
725 *
726 * ARGUMENTS
727 * DeviceObject
728 * Pointer to a device object.
729 *
730 * Irp
731 * Pointer to an IRP.
732 *
733 * ...
734 Additional output data (see printf()).
735 *
736 * RETURN VALUE
737 * Status.
738 */
739
740 static NTSTATUS STDCALL
741 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
742 IN PIRP Irp)
743 {
744 DPRINT("ScsiPortCreateClose()\n");
745
746 Irp->IoStatus.Status = STATUS_SUCCESS;
747 Irp->IoStatus.Information = FILE_OPENED;
748
749 IoCompleteRequest(Irp, IO_NO_INCREMENT);
750
751 return(STATUS_SUCCESS);
752 }
753
754
755 /**********************************************************************
756 * NAME INTERNAL
757 * ScsiPortDispatchScsi
758 *
759 * DESCRIPTION
760 * Answer requests for SCSI calls
761 *
762 * RUN LEVEL
763 * PASSIVE_LEVEL
764 *
765 * ARGUMENTS
766 * Standard dispatch arguments
767 *
768 * RETURNS
769 * NTSTATUS
770 */
771
772 static NTSTATUS STDCALL
773 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
774 IN PIRP Irp)
775 {
776 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
777 PIO_STACK_LOCATION Stack;
778 PSCSI_REQUEST_BLOCK Srb;
779 NTSTATUS Status = STATUS_SUCCESS;
780 ULONG DataSize = 0;
781
782 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
783 DeviceObject, Irp);
784
785 DeviceExtension = DeviceObject->DeviceExtension;
786 Stack = IoGetCurrentIrpStackLocation(Irp);
787
788 Srb = Stack->Parameters.Scsi.Srb;
789 if (Srb == NULL)
790 {
791 Status = STATUS_UNSUCCESSFUL;
792
793 Irp->IoStatus.Status = Status;
794 Irp->IoStatus.Information = 0;
795
796 IoCompleteRequest(Irp, IO_NO_INCREMENT);
797
798 return(Status);
799 }
800
801 DPRINT("Srb: %p\n", Srb);
802 DPRINT("Srb->Function: %lu\n", Srb->Function);
803 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
804
805 switch (Srb->Function)
806 {
807 case SRB_FUNCTION_EXECUTE_SCSI:
808 IoStartPacket(DeviceObject, Irp, NULL, NULL);
809 return(STATUS_PENDING);
810
811 case SRB_FUNCTION_SHUTDOWN:
812 case SRB_FUNCTION_FLUSH:
813 if (DeviceExtension->PortConfig.CachesData == TRUE)
814 {
815 IoStartPacket(DeviceObject, Irp, NULL, NULL);
816 return(STATUS_PENDING);
817 }
818 break;
819
820 case SRB_FUNCTION_CLAIM_DEVICE:
821 {
822 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
823 PSCSI_INQUIRY_DATA UnitInfo;
824 PINQUIRYDATA InquiryData;
825
826 DPRINT(" SRB_FUNCTION_CLAIM_DEVICE\n");
827 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
828
829 Srb->DataBuffer = NULL;
830
831 if (DeviceExtension->PortBusInfo != NULL)
832 {
833 AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
834
835 if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
836 break;
837
838 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
839 AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
840
841 while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
842 {
843 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
844
845 if ((UnitInfo->TargetId == Srb->TargetId) &&
846 (UnitInfo->Lun == Srb->Lun) &&
847 (UnitInfo->DeviceClaimed == FALSE))
848 {
849 UnitInfo->DeviceClaimed = TRUE;
850 DPRINT("Claimed device!\n");
851
852 /* FIXME: Hack!!!!! */
853 Srb->DataBuffer = DeviceObject;
854
855 break;
856 }
857
858 if (UnitInfo->NextInquiryDataOffset == 0)
859 break;
860
861 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
862 }
863 }
864 }
865 break;
866
867 case SRB_FUNCTION_RELEASE_DEVICE:
868 {
869 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
870 PSCSI_INQUIRY_DATA UnitInfo;
871 PINQUIRYDATA InquiryData;
872
873 DPRINT(" SRB_FUNCTION_RELEASE_DEVICE\n");
874 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
875
876 if (DeviceExtension->PortBusInfo != NULL)
877 {
878 AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
879
880 if (AdapterInfo->BusData[Srb->PathId].NumberOfLogicalUnits == 0)
881 break;
882
883 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
884 AdapterInfo->BusData[Srb->PathId].InquiryDataOffset);
885
886 while (AdapterInfo->BusData[Srb->PathId].InquiryDataOffset)
887 {
888 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
889
890 if ((UnitInfo->TargetId == Srb->TargetId) &&
891 (UnitInfo->Lun == Srb->Lun) &&
892 (UnitInfo->DeviceClaimed == TRUE))
893 {
894 UnitInfo->DeviceClaimed = FALSE;
895 DPRINT("Released device!\n");
896 break;
897 }
898
899 if (UnitInfo->NextInquiryDataOffset == 0)
900 break;
901
902 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo + UnitInfo->NextInquiryDataOffset);
903 }
904 }
905 }
906 break;
907
908 default:
909 DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
910 Status = STATUS_NOT_IMPLEMENTED;
911 break;
912 }
913
914 Irp->IoStatus.Status = Status;
915 Irp->IoStatus.Information = DataSize;
916
917 IoCompleteRequest(Irp, IO_NO_INCREMENT);
918
919 return(Status);
920 }
921
922
923 /**********************************************************************
924 * NAME INTERNAL
925 * ScsiPortDeviceControl
926 *
927 * DESCRIPTION
928 * Answer requests for device control calls
929 *
930 * RUN LEVEL
931 * PASSIVE_LEVEL
932 *
933 * ARGUMENTS
934 * Standard dispatch arguments
935 *
936 * RETURNS
937 * NTSTATUS
938 */
939
940 static NTSTATUS STDCALL
941 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
942 IN PIRP Irp)
943 {
944 PIO_STACK_LOCATION Stack;
945 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
946
947 DPRINT("ScsiPortDeviceControl()\n");
948
949 Irp->IoStatus.Status = STATUS_SUCCESS;
950 Irp->IoStatus.Information = 0;
951
952
953 Stack = IoGetCurrentIrpStackLocation(Irp);
954 DeviceExtension = DeviceObject->DeviceExtension;
955
956 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
957 {
958 case IOCTL_SCSI_GET_DUMP_POINTERS:
959 {
960 PDUMP_POINTERS DumpPointers;
961 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
962 DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
963 DumpPointers->DeviceObject = DeviceObject;
964
965 Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
966 }
967 break;
968 case IOCTL_SCSI_GET_CAPABILITIES:
969 {
970 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
971
972 *((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
973 DeviceExtension->PortCapabilities;
974
975 Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
976 }
977 break;
978
979 case IOCTL_SCSI_GET_INQUIRY_DATA:
980 {
981 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
982
983 /* Copy inquiry data to the port device extension */
984 memcpy(Irp->AssociatedIrp.SystemBuffer,
985 DeviceExtension->PortBusInfo,
986 DeviceExtension->PortBusInfoSize);
987
988 DPRINT("BufferSize: %lu\n", DeviceExtension->PortBusInfoSize);
989 Irp->IoStatus.Information = DeviceExtension->PortBusInfoSize;
990 }
991 break;
992
993 default:
994 DPRINT1(" unknown ioctl code: 0x%lX\n",
995 Stack->Parameters.DeviceIoControl.IoControlCode);
996 break;
997 }
998
999 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1000
1001 return(STATUS_SUCCESS);
1002 }
1003
1004
1005 static VOID STDCALL
1006 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
1007 IN PIRP Irp)
1008 {
1009 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1010 PIO_STACK_LOCATION IrpStack;
1011 KIRQL OldIrql;
1012
1013 DPRINT("ScsiPortStartIo() called!\n");
1014
1015 DeviceExtension = DeviceObject->DeviceExtension;
1016 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1017
1018 // FIXME: implement the supported functions
1019
1020 switch (IrpStack->MajorFunction)
1021 {
1022 case IRP_MJ_SCSI:
1023 {
1024 BOOLEAN Result;
1025 PSCSI_REQUEST_BLOCK Srb;
1026 KIRQL oldIrql;
1027
1028 DPRINT("IRP_MJ_SCSI\n");
1029
1030 Srb = IrpStack->Parameters.Scsi.Srb;
1031
1032 DPRINT("DeviceExtension %p\n", DeviceExtension);
1033
1034 Irp->IoStatus.Status = STATUS_SUCCESS;
1035 Irp->IoStatus.Information = Srb->DataTransferLength;
1036
1037 DeviceExtension->CurrentIrp = Irp;
1038
1039 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
1040 ScsiPortStartPacket,
1041 DeviceExtension))
1042 {
1043 DPRINT("Synchronization failed!\n");
1044
1045 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1046 Irp->IoStatus.Information = 0;
1047 IoCompleteRequest(Irp,
1048 IO_NO_INCREMENT);
1049 IoStartNextPacket(DeviceObject,
1050 FALSE);
1051 }
1052 KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
1053 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
1054 {
1055 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
1056 IoCompleteRequest(Irp,
1057 IO_NO_INCREMENT);
1058 }
1059
1060 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
1061 {
1062 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
1063 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1064 IoStartNextPacket(DeviceObject,
1065 FALSE);
1066 }
1067 else
1068 {
1069 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1070 }
1071 }
1072 break;
1073
1074 default:
1075 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1076 Irp->IoStatus.Information = 0;
1077 IoCompleteRequest(Irp,
1078 IO_NO_INCREMENT);
1079 IoStartNextPacket(DeviceObject,
1080 FALSE);
1081 break;
1082 }
1083 DPRINT("ScsiPortStartIo() done\n");
1084 }
1085
1086
1087 static BOOLEAN STDCALL
1088 ScsiPortStartPacket(IN OUT PVOID Context)
1089 {
1090 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1091 PIO_STACK_LOCATION IrpStack;
1092 PSCSI_REQUEST_BLOCK Srb;
1093
1094 DPRINT("ScsiPortStartPacket() called\n");
1095
1096 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
1097
1098 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1099 Srb = IrpStack->Parameters.Scsi.Srb;
1100
1101 return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1102 Srb));
1103 }
1104
1105
1106 /**********************************************************************
1107 * NAME INTERNAL
1108 * ScsiPortCreatePortDevice
1109 *
1110 * DESCRIPTION
1111 * Creates and initializes a SCSI port device object.
1112 *
1113 * RUN LEVEL
1114 * PASSIVE_LEVEL
1115 *
1116 * ARGUMENTS
1117 * DriverObject
1118 * ...
1119 *
1120 * PseudoDeviceExtension
1121 * ...
1122 *
1123 * PortNumber
1124 * ...
1125 *
1126 * RETURNS
1127 * NTSTATUS
1128 */
1129
1130 static NTSTATUS
1131 ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
1132 IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
1133 IN ULONG PortNumber,
1134 IN OUT PSCSI_PORT_DEVICE_EXTENSION *RealDeviceExtension)
1135 {
1136 PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension;
1137 PIO_SCSI_CAPABILITIES PortCapabilities;
1138 PDEVICE_OBJECT PortDeviceObject;
1139 WCHAR NameBuffer[80];
1140 UNICODE_STRING DeviceName;
1141 WCHAR DosNameBuffer[80];
1142 UNICODE_STRING DosDeviceName;
1143 NTSTATUS Status;
1144 ULONG AccessRangeSize;
1145 ULONG MappedIrq;
1146 KIRQL Dirql;
1147 KAFFINITY Affinity;
1148
1149 DPRINT("ScsiPortCreatePortDevice() called\n");
1150
1151 *RealDeviceExtension = NULL;
1152
1153 MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType,
1154 PseudoDeviceExtension->PortConfig.SystemIoBusNumber,
1155 PseudoDeviceExtension->PortConfig.BusInterruptLevel,
1156 PseudoDeviceExtension->PortConfig.BusInterruptVector,
1157 &Dirql,
1158 &Affinity);
1159
1160 /* Create a unicode device name */
1161 swprintf(NameBuffer,
1162 L"\\Device\\ScsiPort%lu",
1163 PortNumber);
1164 RtlInitUnicodeString(&DeviceName,
1165 NameBuffer);
1166
1167 DPRINT("Creating device: %wZ\n", &DeviceName);
1168
1169 /* Create the port device */
1170 Status = IoCreateDevice(DriverObject,
1171 PseudoDeviceExtension->Length,
1172 &DeviceName,
1173 FILE_DEVICE_CONTROLLER,
1174 0,
1175 FALSE,
1176 &PortDeviceObject);
1177 if (!NT_SUCCESS(Status))
1178 {
1179 DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
1180 return(Status);
1181 }
1182
1183 DPRINT("Created device: %wZ\n", &DeviceName);
1184
1185 /* Set the buffering strategy here... */
1186 PortDeviceObject->Flags |= DO_DIRECT_IO;
1187 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
1188
1189 PortDeviceExtension = PortDeviceObject->DeviceExtension;
1190
1191 /* Copy pseudo device extension into the real device extension */
1192 memcpy(PortDeviceExtension,
1193 PseudoDeviceExtension,
1194 PseudoDeviceExtension->Length);
1195
1196 /* Copy access ranges */
1197 AccessRangeSize =
1198 sizeof(ACCESS_RANGE) * PseudoDeviceExtension->PortConfig.NumberOfAccessRanges;
1199 PortDeviceExtension->PortConfig.AccessRanges = ExAllocatePool(NonPagedPool,
1200 AccessRangeSize);
1201 memcpy(PortDeviceExtension->PortConfig.AccessRanges,
1202 PseudoDeviceExtension->PortConfig.AccessRanges,
1203 AccessRangeSize);
1204
1205 /* Copy device base list */
1206 if (IsListEmpty(&PseudoDeviceExtension->DeviceBaseListHead))
1207 {
1208 InitializeListHead(&PortDeviceExtension->DeviceBaseListHead);
1209 }
1210 else
1211 {
1212 PseudoDeviceExtension->DeviceBaseListHead.Flink =
1213 PortDeviceExtension->DeviceBaseListHead.Flink;
1214 PseudoDeviceExtension->DeviceBaseListHead.Blink =
1215 PortDeviceExtension->DeviceBaseListHead.Blink;
1216 PortDeviceExtension->DeviceBaseListHead.Blink->Flink =
1217 &PortDeviceExtension->DeviceBaseListHead;
1218 PortDeviceExtension->DeviceBaseListHead.Flink->Blink =
1219 &PortDeviceExtension->DeviceBaseListHead;
1220 }
1221
1222 PortDeviceExtension->DeviceObject = PortDeviceObject;
1223 PortDeviceExtension->PortNumber = PortNumber;
1224
1225 /* Initialize the spin lock in the controller extension */
1226 KeInitializeSpinLock(&PortDeviceExtension->IrpLock);
1227 KeInitializeSpinLock(&PortDeviceExtension->SpinLock);
1228
1229 /* Register an interrupt handler for this device */
1230 Status = IoConnectInterrupt(&PortDeviceExtension->Interrupt,
1231 ScsiPortIsr,
1232 PortDeviceExtension,
1233 &PortDeviceExtension->SpinLock,
1234 MappedIrq,
1235 Dirql,
1236 Dirql,
1237 PortDeviceExtension->PortConfig.InterruptMode,
1238 TRUE,
1239 Affinity,
1240 FALSE);
1241 if (!NT_SUCCESS(Status))
1242 {
1243 DbgPrint("Could not Connect Interrupt %d\n",
1244 PortDeviceExtension->PortConfig.BusInterruptVector);
1245 return(Status);
1246 }
1247
1248 /* Initialize the DPC object */
1249 IoInitializeDpcRequest(PortDeviceExtension->DeviceObject,
1250 ScsiPortDpcForIsr);
1251
1252 /* Initialize the device timer */
1253 PortDeviceExtension->TimerState = IDETimerIdle;
1254 PortDeviceExtension->TimerCount = 0;
1255 IoInitializeTimer(PortDeviceExtension->DeviceObject,
1256 ScsiPortIoTimer,
1257 PortDeviceExtension);
1258
1259 /* Initialize port capabilities */
1260 PortCapabilities = ExAllocatePool(NonPagedPool,
1261 sizeof(IO_SCSI_CAPABILITIES));
1262 PortDeviceExtension->PortCapabilities = PortCapabilities;
1263 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
1264 PortCapabilities->MaximumTransferLength =
1265 PortDeviceExtension->PortConfig.MaximumTransferLength;
1266 PortCapabilities->MaximumPhysicalPages =
1267 PortCapabilities->MaximumTransferLength / PAGE_SIZE;
1268 PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
1269 PortCapabilities->AlignmentMask =
1270 PortDeviceExtension->PortConfig.AlignmentMask;
1271 PortCapabilities->TaggedQueuing =
1272 PortDeviceExtension->PortConfig.TaggedQueuing;
1273 PortCapabilities->AdapterScansDown =
1274 PortDeviceExtension->PortConfig.AdapterScansDown;
1275 PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
1276
1277 /* Initialize inquiry data */
1278 PortDeviceExtension->PortBusInfoSize = 0;
1279 PortDeviceExtension->PortBusInfo = NULL;
1280
1281 DPRINT("DeviceExtension %p\n", PortDeviceExtension);
1282 ScsiPortInquire(PortDeviceExtension);
1283
1284
1285 /* FIXME: Copy more configuration data? */
1286
1287
1288 /* Create the dos device link */
1289 swprintf(DosNameBuffer,
1290 L"\\??\\Scsi%lu:",
1291 PortNumber);
1292 RtlInitUnicodeString(&DosDeviceName,
1293 DosNameBuffer);
1294
1295 IoCreateSymbolicLink(&DosDeviceName,
1296 &DeviceName);
1297
1298 *RealDeviceExtension = PortDeviceExtension;
1299
1300 DPRINT("ScsiPortCreatePortDevice() done\n");
1301
1302 return(STATUS_SUCCESS);
1303 }
1304
1305
1306 static VOID
1307 ScsiPortInquire(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1308 {
1309 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
1310 PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
1311 SCSI_REQUEST_BLOCK Srb;
1312 ULONG Bus;
1313 ULONG Target;
1314 ULONG UnitCount;
1315 ULONG DataSize;
1316 BOOLEAN Result;
1317
1318 DPRINT("ScsiPortInquire() called\n");
1319
1320 DeviceExtension->Initializing = TRUE;
1321
1322 /* Copy inquiry data to the port device extension */
1323 AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)ExAllocatePool(NonPagedPool, 4096);
1324 RtlZeroMemory(AdapterInfo, 4096);
1325 AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
1326
1327 UnitInfo = (PSCSI_INQUIRY_DATA)
1328 ((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
1329 (sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1)));
1330
1331 RtlZeroMemory(&Srb,
1332 sizeof(SCSI_REQUEST_BLOCK));
1333 Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
1334 Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
1335 Srb.DataTransferLength = 256;
1336 Srb.Cdb[0] = SCSIOP_INQUIRY;
1337
1338 for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++)
1339 {
1340 Srb.PathId = Bus;
1341
1342 AdapterInfo->BusData[Bus].InitiatorBusId =
1343 DeviceExtension->PortConfig.InitiatorBusId[Bus];
1344 AdapterInfo->BusData[Bus].InquiryDataOffset =
1345 (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo);
1346
1347 PrevUnit = NULL;
1348 UnitCount = 0;
1349
1350 for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
1351 {
1352 Srb.TargetId = Target;
1353 Srb.Lun = 0;
1354 Srb.SrbStatus = SRB_STATUS_SUCCESS;
1355
1356 Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1357 &Srb);
1358 DPRINT("Result: %s Srb.SrbStatus %lx\n", (Result)?"True":"False", Srb.SrbStatus);
1359
1360 if (Result == TRUE && Srb.SrbStatus == SRB_STATUS_SUCCESS)
1361 {
1362 UnitInfo->PathId = Bus;
1363 UnitInfo->TargetId = Target;
1364 UnitInfo->Lun = 0;
1365 UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
1366 memcpy(&UnitInfo->InquiryData,
1367 Srb.DataBuffer,
1368 INQUIRYDATABUFFERSIZE);
1369 if (PrevUnit != NULL)
1370 PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
1371 PrevUnit = UnitInfo;
1372 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
1373 UnitCount++;
1374 }
1375 }
1376 DPRINT("UnitCount: %lu\n", UnitCount);
1377 AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
1378 if (UnitCount == 0)
1379 AdapterInfo->BusData[Bus].InquiryDataOffset = 0;
1380 }
1381 DataSize = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
1382
1383 ExFreePool(Srb.DataBuffer);
1384
1385 DeviceExtension->Initializing = FALSE;
1386
1387 /* copy inquiry data to the port driver's device extension */
1388 DeviceExtension->PortBusInfoSize = DataSize;
1389 DeviceExtension->PortBusInfo = ExAllocatePool(NonPagedPool,
1390 DataSize);
1391 RtlCopyMemory(DeviceExtension->PortBusInfo,
1392 AdapterInfo,
1393 DataSize);
1394
1395 ExFreePool(AdapterInfo);
1396
1397 DPRINT("ScsiPortInquire() done\n");
1398 }
1399
1400
1401 static BOOLEAN STDCALL
1402 ScsiPortIsr(IN PKINTERRUPT Interrupt,
1403 IN PVOID ServiceContext)
1404 {
1405 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1406 BOOLEAN Result;
1407
1408 DPRINT("ScsiPortIsr() called!\n");
1409
1410 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
1411
1412 Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
1413 if (Result == FALSE)
1414 {
1415 return(FALSE);
1416 }
1417
1418 if (DeviceExtension->IrpFlags)
1419 {
1420 IoRequestDpc(DeviceExtension->DeviceObject,
1421 DeviceExtension->CurrentIrp,
1422 DeviceExtension);
1423 }
1424
1425 return(TRUE);
1426 }
1427
1428
1429 // ScsiPortDpcForIsr
1430 // DESCRIPTION:
1431 //
1432 // RUN LEVEL:
1433 //
1434 // ARGUMENTS:
1435 // IN PKDPC Dpc
1436 // IN PDEVICE_OBJECT DpcDeviceObject
1437 // IN PIRP DpcIrp
1438 // IN PVOID DpcContext
1439 //
1440 static VOID STDCALL
1441 ScsiPortDpcForIsr(IN PKDPC Dpc,
1442 IN PDEVICE_OBJECT DpcDeviceObject,
1443 IN PIRP DpcIrp,
1444 IN PVOID DpcContext)
1445 {
1446 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1447 PIO_STACK_LOCATION IrpStack;
1448 PSCSI_REQUEST_BLOCK Srb;
1449 KIRQL oldIrql;
1450
1451 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
1452 Dpc, DpcDeviceObject, DpcIrp, DpcContext);
1453
1454 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
1455
1456 KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
1457 if (DeviceExtension->IrpFlags)
1458 {
1459 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1460 Srb = IrpStack->Parameters.Scsi.Srb;
1461
1462 if (DeviceExtension->OriginalSrb != NULL)
1463 {
1464 DPRINT("Got sense data!\n");
1465
1466 DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
1467 DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
1468 DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
1469 DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
1470
1471 /* Copy sense data */
1472 if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
1473 {
1474 RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
1475 &DeviceExtension->InternalSenseData,
1476 sizeof(SENSE_DATA));
1477 DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
1478 }
1479
1480 /* Clear current sense data */
1481 RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
1482
1483 IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
1484 DeviceExtension->OriginalSrb = NULL;
1485 }
1486 else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
1487 (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
1488 {
1489 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
1490
1491 DeviceExtension->OriginalSrb = Srb;
1492 IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
1493 Srb);
1494 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1495 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
1496 ScsiPortStartPacket,
1497 DeviceExtension))
1498 {
1499 DPRINT1("Synchronization failed!\n");
1500
1501 DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1502 DpcIrp->IoStatus.Information = 0;
1503 IoCompleteRequest(DpcIrp,
1504 IO_NO_INCREMENT);
1505 IoStartNextPacket(DpcDeviceObject,
1506 FALSE);
1507 }
1508
1509 return;
1510 }
1511
1512 DeviceExtension->CurrentIrp = NULL;
1513
1514
1515 // DpcIrp->IoStatus.Information = 0;
1516 // DpcIrp->IoStatus.Status = STATUS_SUCCESS;
1517
1518 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
1519 {
1520 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
1521 IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
1522 }
1523
1524 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
1525 {
1526 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
1527 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1528 IoStartNextPacket(DpcDeviceObject, FALSE);
1529 }
1530 else
1531 {
1532 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1533 }
1534 }
1535 else
1536 {
1537 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1538 }
1539
1540 DPRINT("ScsiPortDpcForIsr() done\n");
1541 }
1542
1543
1544 // ScsiPortIoTimer
1545 // DESCRIPTION:
1546 // This function handles timeouts and other time delayed processing
1547 //
1548 // RUN LEVEL:
1549 //
1550 // ARGUMENTS:
1551 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
1552 // IN PVOID Context the Controller extension for the
1553 // controller the device is on
1554 //
1555 static VOID STDCALL
1556 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
1557 PVOID Context)
1558 {
1559 DPRINT1("ScsiPortIoTimer()\n");
1560 }
1561
1562
1563 static PSCSI_REQUEST_BLOCK
1564 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1565 PSCSI_REQUEST_BLOCK OriginalSrb)
1566 {
1567 PSCSI_REQUEST_BLOCK Srb;
1568 PCDB Cdb;
1569
1570 Srb = &DeviceExtension->InternalSrb;
1571
1572 RtlZeroMemory(Srb,
1573 sizeof(SCSI_REQUEST_BLOCK));
1574
1575 Srb->PathId = OriginalSrb->PathId;
1576 Srb->TargetId = OriginalSrb->TargetId;
1577 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
1578 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1579 Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
1580
1581 Srb->TimeOutValue = 4;
1582
1583 Srb->CdbLength = 6;
1584 Srb->DataBuffer = &DeviceExtension->InternalSenseData;
1585 Srb->DataTransferLength = sizeof(SENSE_DATA);
1586
1587 Cdb = (PCDB)Srb->Cdb;
1588 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
1589 Cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
1590
1591 return(Srb);
1592 }
1593
1594
1595 static VOID
1596 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1597 {
1598 DeviceExtension->OriginalSrb = NULL;
1599 }
1600
1601
1602 /**********************************************************************
1603 * NAME INTERNAL
1604 * ScsiPortBuildDeviceMap
1605 *
1606 * DESCRIPTION
1607 * Builds the registry device map of all device which are attached
1608 * to the given SCSI HBA port. The device map is located at:
1609 * \Registry\Machine\DeviceMap\Scsi
1610 *
1611 * RUN LEVEL
1612 * PASSIVE_LEVEL
1613 *
1614 * ARGUMENTS
1615 * DeviceExtension
1616 * ...
1617 *
1618 * RegistryPath
1619 * Name of registry driver service key.
1620 *
1621 * RETURNS
1622 * NTSTATUS
1623 */
1624
1625 static NTSTATUS
1626 ScsiPortBuildDeviceMap(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1627 PUNICODE_STRING RegistryPath)
1628 {
1629 OBJECT_ATTRIBUTES ObjectAttributes;
1630 UNICODE_STRING KeyName;
1631 UNICODE_STRING ValueName;
1632 WCHAR NameBuffer[64];
1633 ULONG Disposition;
1634 HANDLE ScsiKey;
1635 HANDLE ScsiPortKey;
1636 HANDLE ScsiBusKey;
1637 HANDLE ScsiInitiatorKey;
1638 HANDLE ScsiTargetKey;
1639 HANDLE ScsiLunKey;
1640 ULONG BusNumber;
1641 UCHAR CurrentTarget;
1642 PSCSI_ADAPTER_BUS_INFO AdapterInfo;
1643 PSCSI_INQUIRY_DATA UnitInfo;
1644 PINQUIRYDATA InquiryData;
1645 PWCHAR DriverName;
1646 ULONG UlongData;
1647 PWCHAR TypeName;
1648 NTSTATUS Status;
1649
1650 DPRINT("ScsiPortBuildDeviceMap() called\n");
1651
1652 if (DeviceExtension == NULL || RegistryPath == NULL)
1653 {
1654 DPRINT1("Invalid parameter\n");
1655 return(STATUS_INVALID_PARAMETER);
1656 }
1657
1658 /* Open or create the 'Scsi' subkey */
1659 RtlInitUnicodeStringFromLiteral(&KeyName,
1660 L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
1661 InitializeObjectAttributes(&ObjectAttributes,
1662 &KeyName,
1663 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
1664 0,
1665 NULL);
1666 Status = ZwCreateKey(&ScsiKey,
1667 KEY_ALL_ACCESS,
1668 &ObjectAttributes,
1669 0,
1670 NULL,
1671 REG_OPTION_VOLATILE,
1672 &Disposition);
1673 if (!NT_SUCCESS(Status))
1674 {
1675 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
1676 return(Status);
1677 }
1678
1679 /* Create new 'Scsi Port X' subkey */
1680 DPRINT("Scsi Port %lu\n",
1681 DeviceExtension->PortNumber);
1682
1683 swprintf(NameBuffer,
1684 L"Scsi Port %lu",
1685 DeviceExtension->PortNumber);
1686 RtlInitUnicodeString(&KeyName,
1687 NameBuffer);
1688 InitializeObjectAttributes(&ObjectAttributes,
1689 &KeyName,
1690 0,
1691 ScsiKey,
1692 NULL);
1693 Status = ZwCreateKey(&ScsiPortKey,
1694 KEY_ALL_ACCESS,
1695 &ObjectAttributes,
1696 0,
1697 NULL,
1698 REG_OPTION_VOLATILE,
1699 &Disposition);
1700 ZwClose(ScsiKey);
1701 if (!NT_SUCCESS(Status))
1702 {
1703 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
1704 return(Status);
1705 }
1706
1707 /*
1708 * Create port-specific values
1709 */
1710
1711 /* Set 'DMA Enabled' (REG_DWORD) value */
1712 UlongData = (ULONG)!DeviceExtension->PortCapabilities->AdapterUsesPio;
1713 DPRINT(" DMA Enabled = %s\n", (UlongData) ? "TRUE" : "FALSE");
1714 RtlInitUnicodeString(&ValueName,
1715 L"DMA Enabled");
1716 Status = ZwSetValueKey(ScsiPortKey,
1717 &ValueName,
1718 0,
1719 REG_DWORD,
1720 &UlongData,
1721 sizeof(ULONG));
1722 if (!NT_SUCCESS(Status))
1723 {
1724 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status);
1725 ZwClose(ScsiPortKey);
1726 return(Status);
1727 }
1728
1729 /* Set 'Driver' (REG_SZ) value */
1730 DriverName = wcsrchr(RegistryPath->Buffer, L'\\') + 1;
1731 RtlInitUnicodeString(&ValueName,
1732 L"Driver");
1733 Status = ZwSetValueKey(ScsiPortKey,
1734 &ValueName,
1735 0,
1736 REG_SZ,
1737 DriverName,
1738 (wcslen(DriverName) + 1) * sizeof(WCHAR));
1739 if (!NT_SUCCESS(Status))
1740 {
1741 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
1742 ZwClose(ScsiPortKey);
1743 return(Status);
1744 }
1745
1746 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
1747 UlongData = (ULONG)DeviceExtension->PortConfig.BusInterruptLevel;
1748 DPRINT(" Interrupt = %lu\n", UlongData);
1749 RtlInitUnicodeString(&ValueName,
1750 L"Interrupt");
1751 Status = ZwSetValueKey(ScsiPortKey,
1752 &ValueName,
1753 0,
1754 REG_DWORD,
1755 &UlongData,
1756 sizeof(ULONG));
1757 if (!NT_SUCCESS(Status))
1758 {
1759 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status);
1760 ZwClose(ScsiPortKey);
1761 return(Status);
1762 }
1763
1764 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
1765 UlongData = ScsiPortConvertPhysicalAddressToUlong(DeviceExtension->PortConfig.AccessRanges[0].RangeStart);
1766 DPRINT(" IOAddress = %lx\n", UlongData);
1767 RtlInitUnicodeString(&ValueName,
1768 L"IOAddress");
1769 Status = ZwSetValueKey(ScsiPortKey,
1770 &ValueName,
1771 0,
1772 REG_DWORD,
1773 &UlongData,
1774 sizeof(ULONG));
1775 if (!NT_SUCCESS(Status))
1776 {
1777 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status);
1778 ZwClose(ScsiPortKey);
1779 return(Status);
1780 }
1781
1782 /* Enumerate buses */
1783 for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig.NumberOfBuses; BusNumber++)
1784 {
1785 /* Create 'Scsi Bus X' key */
1786 DPRINT(" Scsi Bus %lu\n", BusNumber);
1787 swprintf(NameBuffer,
1788 L"Scsi Bus %lu",
1789 BusNumber);
1790 RtlInitUnicodeString(&KeyName,
1791 NameBuffer);
1792 InitializeObjectAttributes(&ObjectAttributes,
1793 &KeyName,
1794 0,
1795 ScsiPortKey,
1796 NULL);
1797 Status = ZwCreateKey(&ScsiBusKey,
1798 KEY_ALL_ACCESS,
1799 &ObjectAttributes,
1800 0,
1801 NULL,
1802 REG_OPTION_VOLATILE,
1803 &Disposition);
1804 if (!NT_SUCCESS(Status))
1805 {
1806 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
1807 ZwClose(ScsiPortKey);
1808 return(Status);
1809 }
1810
1811 /* Create 'Initiator Id X' key */
1812 DPRINT(" Initiator Id %u\n",
1813 DeviceExtension->PortConfig.InitiatorBusId[BusNumber]);
1814 swprintf(NameBuffer,
1815 L"Initiator Id %u",
1816 DeviceExtension->PortConfig.InitiatorBusId[BusNumber]);
1817 RtlInitUnicodeString(&KeyName,
1818 NameBuffer);
1819 InitializeObjectAttributes(&ObjectAttributes,
1820 &KeyName,
1821 0,
1822 ScsiBusKey,
1823 NULL);
1824 Status = ZwCreateKey(&ScsiInitiatorKey,
1825 KEY_ALL_ACCESS,
1826 &ObjectAttributes,
1827 0,
1828 NULL,
1829 REG_OPTION_VOLATILE,
1830 &Disposition);
1831 if (!NT_SUCCESS(Status))
1832 {
1833 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
1834 ZwClose(ScsiBusKey);
1835 ZwClose(ScsiPortKey);
1836 return(Status);
1837 }
1838
1839 /* FIXME: Are there any initiator values (??) */
1840
1841 ZwClose(ScsiInitiatorKey);
1842
1843
1844 /* Enumerate targets */
1845 CurrentTarget = (UCHAR)-1;
1846 ScsiTargetKey = NULL;
1847 AdapterInfo = (PSCSI_ADAPTER_BUS_INFO)DeviceExtension->PortBusInfo;
1848 if (AdapterInfo->BusData[BusNumber].NumberOfLogicalUnits != 0)
1849 {
1850 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
1851 AdapterInfo->BusData[BusNumber].InquiryDataOffset);
1852
1853 while (AdapterInfo->BusData[BusNumber].InquiryDataOffset)
1854 {
1855 if (UnitInfo->TargetId != CurrentTarget)
1856 {
1857 /* Close old target key */
1858 if (ScsiTargetKey != NULL)
1859 {
1860 ZwClose(ScsiTargetKey);
1861 ScsiTargetKey = NULL;
1862 }
1863
1864 /* Create 'Target Id X' key */
1865 DPRINT(" Target Id %u\n",
1866 UnitInfo->TargetId);
1867 swprintf(NameBuffer,
1868 L"Target Id %u",
1869 UnitInfo->TargetId);
1870 RtlInitUnicodeString(&KeyName,
1871 NameBuffer);
1872 InitializeObjectAttributes(&ObjectAttributes,
1873 &KeyName,
1874 0,
1875 ScsiBusKey,
1876 NULL);
1877 Status = ZwCreateKey(&ScsiTargetKey,
1878 KEY_ALL_ACCESS,
1879 &ObjectAttributes,
1880 0,
1881 NULL,
1882 REG_OPTION_VOLATILE,
1883 &Disposition);
1884 if (!NT_SUCCESS(Status))
1885 {
1886 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
1887 ZwClose(ScsiBusKey);
1888 ZwClose(ScsiPortKey);
1889 return(Status);
1890 }
1891
1892 CurrentTarget = UnitInfo->TargetId;
1893 }
1894
1895 /* Create 'Logical Unit Id X' key */
1896 DPRINT(" Logical Unit Id %u\n",
1897 UnitInfo->Lun);
1898 swprintf(NameBuffer,
1899 L"Logical Unit Id %u",
1900 UnitInfo->Lun);
1901 RtlInitUnicodeString(&KeyName,
1902 NameBuffer);
1903 InitializeObjectAttributes(&ObjectAttributes,
1904 &KeyName,
1905 0,
1906 ScsiTargetKey,
1907 NULL);
1908 Status = ZwCreateKey(&ScsiLunKey,
1909 KEY_ALL_ACCESS,
1910 &ObjectAttributes,
1911 0,
1912 NULL,
1913 REG_OPTION_VOLATILE,
1914 &Disposition);
1915 if (!NT_SUCCESS(Status))
1916 {
1917 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
1918 ZwClose(ScsiTargetKey);
1919 ZwClose(ScsiBusKey);
1920 ZwClose(ScsiPortKey);
1921 return(Status);
1922 }
1923
1924 /* Set values for logical unit */
1925 InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
1926
1927 /* Set 'Identifier' (REG_SZ) value */
1928 swprintf(NameBuffer,
1929 L"%.8S%.16S%.4S",
1930 InquiryData->VendorId,
1931 InquiryData->ProductId,
1932 InquiryData->ProductRevisionLevel);
1933 DPRINT(" Identifier = '%S'\n",
1934 NameBuffer);
1935 RtlInitUnicodeString(&ValueName,
1936 L"Identifier");
1937 Status = ZwSetValueKey(ScsiLunKey,
1938 &ValueName,
1939 0,
1940 REG_SZ,
1941 NameBuffer,
1942 (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
1943 if (!NT_SUCCESS(Status))
1944 {
1945 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
1946 ZwClose(ScsiLunKey);
1947 ZwClose(ScsiTargetKey);
1948 ZwClose(ScsiBusKey);
1949 ZwClose(ScsiPortKey);
1950 return(Status);
1951 }
1952
1953 /* Set 'Type' (REG_SZ) value */
1954 switch (InquiryData->DeviceType)
1955 {
1956 case 0:
1957 TypeName = L"DiskPeripheral";
1958 break;
1959 case 1:
1960 TypeName = L"TapePeripheral";
1961 break;
1962 case 2:
1963 TypeName = L"PrinterPeripheral";
1964 break;
1965 case 4:
1966 TypeName = L"WormPeripheral";
1967 break;
1968 case 5:
1969 TypeName = L"CdRomPeripheral";
1970 break;
1971 case 6:
1972 TypeName = L"ScannerPeripheral";
1973 break;
1974 case 7:
1975 TypeName = L"OpticalDiskPeripheral";
1976 break;
1977 case 8:
1978 TypeName = L"MediumChangerPeripheral";
1979 break;
1980 case 9:
1981 TypeName = L"CommunicationPeripheral";
1982 break;
1983 default:
1984 TypeName = L"OtherPeripheral";
1985 break;
1986 }
1987 DPRINT(" Type = '%S'\n", TypeName);
1988 RtlInitUnicodeString(&ValueName,
1989 L"Type");
1990 Status = ZwSetValueKey(ScsiLunKey,
1991 &ValueName,
1992 0,
1993 REG_SZ,
1994 TypeName,
1995 (wcslen(TypeName) + 1) * sizeof(WCHAR));
1996 if (!NT_SUCCESS(Status))
1997 {
1998 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
1999 ZwClose(ScsiLunKey);
2000 ZwClose(ScsiTargetKey);
2001 ZwClose(ScsiBusKey);
2002 ZwClose(ScsiPortKey);
2003 return(Status);
2004 }
2005
2006 ZwClose(ScsiLunKey);
2007
2008 if (UnitInfo->NextInquiryDataOffset == 0)
2009 break;
2010
2011 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)AdapterInfo +
2012 UnitInfo->NextInquiryDataOffset);
2013 }
2014
2015 /* Close old target key */
2016 if (ScsiTargetKey != NULL)
2017 {
2018 ZwClose(ScsiTargetKey);
2019 ScsiTargetKey = NULL;
2020 }
2021 }
2022
2023 ZwClose(ScsiBusKey);
2024 }
2025
2026 ZwClose(ScsiPortKey);
2027
2028 DPRINT("ScsiPortBuildDeviceMap() done\n");
2029
2030 return(Status);
2031 }
2032
2033 /* EOF */