2c283af483f86c50550547902c71a84ea8b8cf95
[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.50 2004/03/23 12:30:15 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 #include <rosrtl/string.h>
35
36 #define NDEBUG
37 #include <debug.h>
38
39
40 #define VERSION "0.0.1"
41
42 #include "scsiport_int.h"
43
44 /* #define USE_DEVICE_QUEUES */
45
46 /* TYPES *********************************************************************/
47
48 #define IRP_FLAG_COMPLETE 0x00000001
49 #define IRP_FLAG_NEXT 0x00000002
50 #define IRP_FLAG_NEXT_LU 0x00000004
51
52
53 /* GLOBALS *******************************************************************/
54
55 static BOOLEAN
56 SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
57 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
58 IN ULONG BusNumber,
59 IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
60
61 static NTSTATUS STDCALL
62 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
63 IN PIRP Irp);
64
65 static NTSTATUS STDCALL
66 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
67 IN PIRP Irp);
68
69 static NTSTATUS STDCALL
70 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
71 IN PIRP Irp);
72
73 static VOID STDCALL
74 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
75 IN PIRP Irp);
76
77 static BOOLEAN STDCALL
78 ScsiPortStartPacket(IN OUT PVOID Context);
79
80
81 static PSCSI_PORT_LUN_EXTENSION
82 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
83 IN UCHAR PathId,
84 IN UCHAR TargetId,
85 IN UCHAR Lun);
86
87 static VOID
88 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension);
89
90 static PSCSI_PORT_LUN_EXTENSION
91 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
92 IN UCHAR PathId,
93 IN UCHAR TargetId,
94 IN UCHAR Lun);
95
96 static NTSTATUS
97 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
98 IN OUT PSCSI_REQUEST_BLOCK Srb);
99
100 static VOID
101 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
102
103 static ULONG
104 SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
105 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo);
106
107 static BOOLEAN STDCALL
108 ScsiPortIsr(IN PKINTERRUPT Interrupt,
109 IN PVOID ServiceContext);
110
111 static VOID STDCALL
112 ScsiPortDpcForIsr(IN PKDPC Dpc,
113 IN PDEVICE_OBJECT DpcDeviceObject,
114 IN PIRP DpcIrp,
115 IN PVOID DpcContext);
116
117 static VOID STDCALL
118 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
119 PVOID Context);
120
121 static PSCSI_REQUEST_BLOCK
122 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
123 PSCSI_REQUEST_BLOCK OriginalSrb);
124
125 static VOID
126 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
127
128 static NTSTATUS
129 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
130 PUNICODE_STRING RegistryPath);
131
132
133 /* FUNCTIONS *****************************************************************/
134
135 /**********************************************************************
136 * NAME EXPORTED
137 * DriverEntry
138 *
139 * DESCRIPTION
140 * This function initializes the driver.
141 *
142 * RUN LEVEL
143 * PASSIVE_LEVEL
144 *
145 * ARGUMENTS
146 * DriverObject
147 * System allocated Driver Object for this driver.
148 *
149 * RegistryPath
150 * Name of registry driver service key.
151 *
152 * RETURN VALUE
153 * Status.
154 */
155
156 NTSTATUS STDCALL
157 DriverEntry(IN PDRIVER_OBJECT DriverObject,
158 IN PUNICODE_STRING RegistryPath)
159 {
160 DPRINT("ScsiPort Driver %s\n", VERSION);
161 return(STATUS_SUCCESS);
162 }
163
164
165 /**********************************************************************
166 * NAME EXPORTED
167 * ScsiDebugPrint
168 *
169 * DESCRIPTION
170 * Prints debugging messages.
171 *
172 * RUN LEVEL
173 * PASSIVE_LEVEL
174 *
175 * ARGUMENTS
176 * DebugPrintLevel
177 * Debug level of the given message.
178 *
179 * DebugMessage
180 * Pointer to printf()-compatible format string.
181 *
182 * ...
183 Additional output data (see printf()).
184 *
185 * RETURN VALUE
186 * None.
187 *
188 * @implemented
189 */
190
191 VOID
192 ScsiDebugPrint(IN ULONG DebugPrintLevel,
193 IN PCHAR DebugMessage,
194 ...)
195 {
196 char Buffer[256];
197 va_list ap;
198
199 #if 0
200 if (DebugPrintLevel > InternalDebugLevel)
201 return;
202 #endif
203
204 va_start(ap, DebugMessage);
205 vsprintf(Buffer, DebugMessage, ap);
206 va_end(ap);
207
208 DbgPrint(Buffer);
209 }
210
211
212 /*
213 * @unimplemented
214 */
215 VOID STDCALL
216 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
217 IN UCHAR PathId,
218 IN UCHAR TargetId,
219 IN UCHAR Lun,
220 IN UCHAR SrbStatus)
221 {
222 DPRINT("ScsiPortCompleteRequest()\n");
223 UNIMPLEMENTED;
224 }
225
226
227 /*
228 * @implemented
229 */
230 ULONG STDCALL
231 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
232 {
233 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
234 return(Address.u.LowPart);
235 }
236
237
238 /*
239 * @unimplemented
240 */
241 VOID STDCALL
242 ScsiPortFlushDma(IN PVOID HwDeviceExtension)
243 {
244 DPRINT("ScsiPortFlushDma()\n");
245 UNIMPLEMENTED;
246 }
247
248
249 /*
250 * @implemented
251 */
252 VOID STDCALL
253 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
254 IN PVOID MappedAddress)
255 {
256 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
257 PSCSI_PORT_DEVICE_BASE DeviceBase;
258 PLIST_ENTRY Entry;
259
260 DPRINT("ScsiPortFreeDeviceBase() called\n");
261
262 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
263 SCSI_PORT_DEVICE_EXTENSION,
264 MiniPortDeviceExtension);
265 if (IsListEmpty(&DeviceExtension->DeviceBaseListHead))
266 return;
267
268 Entry = DeviceExtension->DeviceBaseListHead.Flink;
269 while (Entry != &DeviceExtension->DeviceBaseListHead)
270 {
271 DeviceBase = CONTAINING_RECORD(Entry,
272 SCSI_PORT_DEVICE_BASE,
273 List);
274 if (DeviceBase->MappedAddress == MappedAddress)
275 {
276 MmUnmapIoSpace(DeviceBase->MappedAddress,
277 DeviceBase->NumberOfBytes);
278 RemoveEntryList(Entry);
279 ExFreePool(DeviceBase);
280
281 return;
282 }
283
284 Entry = Entry->Flink;
285 }
286 }
287
288
289 /*
290 * @implemented
291 */
292 ULONG STDCALL
293 ScsiPortGetBusData(IN PVOID DeviceExtension,
294 IN ULONG BusDataType,
295 IN ULONG SystemIoBusNumber,
296 IN ULONG SlotNumber,
297 IN PVOID Buffer,
298 IN ULONG Length)
299 {
300 return(HalGetBusData(BusDataType,
301 SystemIoBusNumber,
302 SlotNumber,
303 Buffer,
304 Length));
305 }
306
307
308 /*
309 * @implemented
310 */
311 PVOID STDCALL
312 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
313 IN INTERFACE_TYPE BusType,
314 IN ULONG SystemIoBusNumber,
315 IN SCSI_PHYSICAL_ADDRESS IoAddress,
316 IN ULONG NumberOfBytes,
317 IN BOOLEAN InIoSpace)
318 {
319 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
320 PHYSICAL_ADDRESS TranslatedAddress;
321 PSCSI_PORT_DEVICE_BASE DeviceBase;
322 ULONG AddressSpace;
323 PVOID MappedAddress;
324
325 DPRINT ("ScsiPortGetDeviceBase() called\n");
326
327 AddressSpace = (ULONG)InIoSpace;
328 if (HalTranslateBusAddress(BusType,
329 SystemIoBusNumber,
330 IoAddress,
331 &AddressSpace,
332 &TranslatedAddress) == FALSE)
333 return NULL;
334
335 /* i/o space */
336 if (AddressSpace != 0)
337 return((PVOID)TranslatedAddress.u.LowPart);
338
339 MappedAddress = MmMapIoSpace(TranslatedAddress,
340 NumberOfBytes,
341 FALSE);
342
343 DeviceBase = ExAllocatePool(NonPagedPool,
344 sizeof(SCSI_PORT_DEVICE_BASE));
345 if (DeviceBase == NULL)
346 return(MappedAddress);
347
348 DeviceBase->MappedAddress = MappedAddress;
349 DeviceBase->NumberOfBytes = NumberOfBytes;
350 DeviceBase->IoAddress = IoAddress;
351 DeviceBase->SystemIoBusNumber = SystemIoBusNumber;
352
353 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
354 SCSI_PORT_DEVICE_EXTENSION,
355 MiniPortDeviceExtension);
356
357 InsertHeadList(&DeviceExtension->DeviceBaseListHead,
358 &DeviceBase->List);
359
360 return(MappedAddress);
361 }
362
363
364 /*
365 * @implemented
366 */
367 PVOID STDCALL
368 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
369 IN UCHAR PathId,
370 IN UCHAR TargetId,
371 IN UCHAR Lun)
372 {
373 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
374 PSCSI_PORT_LUN_EXTENSION LunExtension;
375 PLIST_ENTRY Entry;
376
377 DPRINT("ScsiPortGetLogicalUnit() called\n");
378
379 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
380 SCSI_PORT_DEVICE_EXTENSION,
381 MiniPortDeviceExtension);
382 if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
383 return NULL;
384
385 Entry = DeviceExtension->LunExtensionListHead.Flink;
386 while (Entry != &DeviceExtension->LunExtensionListHead)
387 {
388 LunExtension = CONTAINING_RECORD(Entry,
389 SCSI_PORT_LUN_EXTENSION,
390 List);
391 if (LunExtension->PathId == PathId &&
392 LunExtension->TargetId == TargetId &&
393 LunExtension->Lun == Lun)
394 {
395 return (PVOID)&LunExtension->MiniportLunExtension;
396 }
397
398 Entry = Entry->Flink;
399 }
400
401 return NULL;
402 }
403
404
405 /*
406 * @unimplemented
407 */
408 SCSI_PHYSICAL_ADDRESS STDCALL
409 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
410 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
411 IN PVOID VirtualAddress,
412 OUT ULONG *Length)
413 {
414 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
415 SCSI_PHYSICAL_ADDRESS PhysicalAddress;
416 SCSI_PHYSICAL_ADDRESS NextPhysicalAddress;
417 ULONG BufferLength = 0;
418 ULONG Offset;
419 PVOID EndAddress;
420
421 DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
422 HwDeviceExtension, Srb, VirtualAddress, Length);
423
424 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
425 SCSI_PORT_DEVICE_EXTENSION,
426 MiniPortDeviceExtension);
427
428 *Length = 0;
429
430 if (Srb == NULL)
431 {
432 if ((ULONG_PTR)DeviceExtension->VirtualAddress > (ULONG_PTR)VirtualAddress)
433 {
434 PhysicalAddress.QuadPart = 0ULL;
435 return PhysicalAddress;
436 }
437
438 Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
439 if (Offset >= DeviceExtension->CommonBufferLength)
440 {
441 PhysicalAddress.QuadPart = 0ULL;
442 return PhysicalAddress;
443 }
444
445 PhysicalAddress.QuadPart =
446 DeviceExtension->PhysicalAddress.QuadPart + (ULONGLONG)Offset;
447 BufferLength = DeviceExtension->CommonBufferLength - Offset;
448 }
449 else
450 {
451 EndAddress = Srb->DataBuffer + Srb->DataTransferLength;
452 if (VirtualAddress == NULL)
453 {
454 VirtualAddress = Srb->DataBuffer;
455 }
456 else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
457 {
458 PhysicalAddress.QuadPart = 0LL;
459 return PhysicalAddress;
460 }
461
462 PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
463 if (PhysicalAddress.QuadPart == 0LL)
464 {
465 return PhysicalAddress;
466 }
467
468 Offset = (ULONG_PTR)VirtualAddress & (PAGE_SIZE - 1);
469 #if 1
470 /*
471 * FIXME:
472 * MmGetPhysicalAddress doesn't return the offset within the page.
473 * We must set the correct offset.
474 */
475 PhysicalAddress.u.LowPart = (PhysicalAddress.u.LowPart & ~(PAGE_SIZE - 1)) + Offset;
476 #endif
477 BufferLength += PAGE_SIZE - Offset;
478 while (VirtualAddress + BufferLength < EndAddress)
479 {
480 NextPhysicalAddress = MmGetPhysicalAddress(VirtualAddress + BufferLength);
481 if (PhysicalAddress.QuadPart + (ULONGLONG)BufferLength != NextPhysicalAddress.QuadPart)
482 {
483 break;
484 }
485 BufferLength += PAGE_SIZE;
486 }
487 if (VirtualAddress + BufferLength >= EndAddress)
488 {
489 BufferLength = EndAddress - VirtualAddress;
490 }
491 }
492
493 *Length = BufferLength;
494
495 return PhysicalAddress;
496 }
497
498
499 /*
500 * @unimplemented
501 */
502 PSCSI_REQUEST_BLOCK STDCALL
503 ScsiPortGetSrb(IN PVOID DeviceExtension,
504 IN UCHAR PathId,
505 IN UCHAR TargetId,
506 IN UCHAR Lun,
507 IN LONG QueueTag)
508 {
509 DPRINT1("ScsiPortGetSrb()\n");
510 UNIMPLEMENTED;
511 return NULL;
512 }
513
514
515 /*
516 * @implemented
517 */
518 PVOID STDCALL
519 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
520 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
521 IN ULONG NumberOfBytes)
522 {
523 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
524 DEVICE_DESCRIPTION DeviceDescription;
525
526 DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
527 HwDeviceExtension, ConfigInfo, NumberOfBytes);
528
529 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
530 SCSI_PORT_DEVICE_EXTENSION,
531 MiniPortDeviceExtension);
532
533 /* Check for allocated common DMA buffer */
534 if (DeviceExtension->VirtualAddress != NULL)
535 {
536 DPRINT1("The HBA has already got a common DMA buffer!\n");
537 return NULL;
538 }
539
540 /* Check for DMA adapter object */
541 if (DeviceExtension->AdapterObject == NULL)
542 {
543 /* Initialize DMA adapter description */
544 RtlZeroMemory(&DeviceDescription,
545 sizeof(DEVICE_DESCRIPTION));
546 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
547 DeviceDescription.Master = ConfigInfo->Master;
548 DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
549 DeviceDescription.DemandMode = ConfigInfo->DemandMode;
550 DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
551 DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
552 DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
553 DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
554 DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
555 DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
556 DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
557 DeviceDescription.DmaPort = ConfigInfo->DmaPort;
558
559 /* Get a DMA adapter object */
560 DeviceExtension->AdapterObject = HalGetAdapter(&DeviceDescription,
561 &DeviceExtension->MapRegisterCount);
562 if (DeviceExtension->AdapterObject == NULL)
563 {
564 DPRINT1("HalGetAdapter() failed\n");
565 return NULL;
566 }
567 }
568
569 /* Allocate a common DMA buffer */
570 DeviceExtension->CommonBufferLength =
571 NumberOfBytes + DeviceExtension->SrbExtensionSize;
572 DeviceExtension->VirtualAddress =
573 HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
574 DeviceExtension->CommonBufferLength,
575 &DeviceExtension->PhysicalAddress,
576 FALSE);
577 if (DeviceExtension->VirtualAddress == NULL)
578 {
579 DPRINT1("HalAllocateCommonBuffer() failed!\n");
580 DeviceExtension->CommonBufferLength = 0;
581 return NULL;
582 }
583
584 return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
585 DeviceExtension->SrbExtensionSize);
586 }
587
588
589 /*
590 * @implemented
591 */
592 PVOID STDCALL
593 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
594 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
595 {
596 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
597 ULONG Offset;
598
599 DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
600 HwDeviceExtension, PhysicalAddress.QuadPart);
601
602 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
603 SCSI_PORT_DEVICE_EXTENSION,
604 MiniPortDeviceExtension);
605
606 if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
607 return NULL;
608
609 Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
610 if (Offset >= DeviceExtension->CommonBufferLength)
611 return NULL;
612
613 return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + Offset);
614 }
615
616
617 /**********************************************************************
618 * NAME EXPORTED
619 * ScsiPortInitialize
620 *
621 * DESCRIPTION
622 * Initializes SCSI port driver specific data.
623 *
624 * RUN LEVEL
625 * PASSIVE_LEVEL
626 *
627 * ARGUMENTS
628 * Argument1
629 * Pointer to the miniport driver's driver object.
630 *
631 * Argument2
632 * Pointer to the miniport driver's registry path.
633 *
634 * HwInitializationData
635 * Pointer to port driver specific configuration data.
636 *
637 * HwContext
638 Miniport driver specific context.
639 *
640 * RETURN VALUE
641 * Status.
642 *
643 * @implemented
644 */
645
646 ULONG STDCALL
647 ScsiPortInitialize(IN PVOID Argument1,
648 IN PVOID Argument2,
649 IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
650 IN PVOID HwContext)
651 {
652 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
653 // PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
654 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
655 PCONFIGURATION_INFORMATION SystemConfig;
656 PPORT_CONFIGURATION_INFORMATION PortConfig;
657 ULONG DeviceExtensionSize;
658 ULONG PortConfigSize;
659 BOOLEAN Again;
660 ULONG i;
661 ULONG Result;
662 NTSTATUS Status;
663 ULONG MaxBus;
664 ULONG BusNumber;
665 PCI_SLOT_NUMBER SlotNumber;
666
667 PDEVICE_OBJECT PortDeviceObject;
668 WCHAR NameBuffer[80];
669 UNICODE_STRING DeviceName;
670 WCHAR DosNameBuffer[80];
671 UNICODE_STRING DosDeviceName;
672 PIO_SCSI_CAPABILITIES PortCapabilities;
673 ULONG MappedIrq;
674 KIRQL Dirql;
675 KAFFINITY Affinity;
676
677
678 DPRINT ("ScsiPortInitialize() called!\n");
679
680 if ((HwInitializationData->HwInitialize == NULL) ||
681 (HwInitializationData->HwStartIo == NULL) ||
682 (HwInitializationData->HwInterrupt == NULL) ||
683 (HwInitializationData->HwFindAdapter == NULL) ||
684 (HwInitializationData->HwResetBus == NULL))
685 return(STATUS_INVALID_PARAMETER);
686
687 DriverObject->DriverStartIo = ScsiPortStartIo;
688 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
689 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
690 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
691 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
692
693 SystemConfig = IoGetConfigurationInformation();
694
695 DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
696 HwInitializationData->DeviceExtensionSize;
697 PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
698 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
699
700
701 MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
702 DPRINT("MaxBus: %lu\n", MaxBus);
703
704 PortDeviceObject = NULL;
705 BusNumber = 0;
706 SlotNumber.u.AsULONG = 0;
707 while (TRUE)
708 {
709 /* Create a unicode device name */
710 swprintf (NameBuffer,
711 L"\\Device\\ScsiPort%lu",
712 SystemConfig->ScsiPortCount);
713 RtlInitUnicodeString (&DeviceName,
714 NameBuffer);
715
716 DPRINT("Creating device: %wZ\n", &DeviceName);
717
718 /* Create the port device */
719 Status = IoCreateDevice (DriverObject,
720 DeviceExtensionSize,
721 &DeviceName,
722 FILE_DEVICE_CONTROLLER,
723 0,
724 FALSE,
725 &PortDeviceObject);
726 if (!NT_SUCCESS(Status))
727 {
728 DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
729 PortDeviceObject = NULL;
730 goto ByeBye;
731 }
732
733 DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
734
735 /* Set the buffering strategy here... */
736 PortDeviceObject->Flags |= DO_DIRECT_IO;
737 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
738
739 DeviceExtension = PortDeviceObject->DeviceExtension;
740 DeviceExtension->Length = DeviceExtensionSize;
741 DeviceExtension->DeviceObject = PortDeviceObject;
742 DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
743
744 DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
745 DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
746 DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
747 DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
748 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
749
750 #if 0
751 DeviceExtension->AdapterObject = NULL;
752 DeviceExtension->MapRegisterCount = 0;
753 DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
754 DeviceExtension->VirtualAddress = NULL;
755 DeviceExtension->CommonBufferLength = 0;
756 #endif
757
758 /* Initialize the device base list */
759 InitializeListHead (&DeviceExtension->DeviceBaseListHead);
760
761 /* Initialize LUN-Extension list */
762 InitializeListHead (&DeviceExtension->LunExtensionListHead);
763
764 /* Initialize the spin lock in the controller extension */
765 KeInitializeSpinLock (&DeviceExtension->IrpLock);
766 KeInitializeSpinLock (&DeviceExtension->SpinLock);
767
768 /* Initialize the DPC object */
769 IoInitializeDpcRequest (PortDeviceObject,
770 ScsiPortDpcForIsr);
771
772 /* Initialize the device timer */
773 DeviceExtension->TimerState = IDETimerIdle;
774 DeviceExtension->TimerCount = 0;
775 IoInitializeTimer (PortDeviceObject,
776 ScsiPortIoTimer,
777 DeviceExtension);
778
779 /* Allocate and initialize port configuration info */
780 DeviceExtension->PortConfig = ExAllocatePool (NonPagedPool,
781 PortConfigSize);
782 if (DeviceExtension->PortConfig == NULL)
783 {
784 Status = STATUS_INSUFFICIENT_RESOURCES;
785 goto ByeBye;
786 }
787 RtlZeroMemory (DeviceExtension->PortConfig,
788 PortConfigSize);
789
790 PortConfig = DeviceExtension->PortConfig;
791 PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
792 PortConfig->SystemIoBusNumber = BusNumber;
793 PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
794 PortConfig->InterruptMode =
795 (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
796 PortConfig->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
797 PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
798 PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
799 PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
800 // PortConfig->DmaWidth =
801 // PortConfig->DmaSpeed =
802 // PortConfig->AlignmentMask =
803 PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
804 // PortConfig->NumberOfBuses =
805
806 for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
807 PortConfig->InitiatorBusId[i] = 255;
808
809 // PortConfig->ScatterGather =
810 // PortConfig->Master =
811 // PortConfig->CachesData =
812 // PortConfig->AdapterScansDown =
813 PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
814 PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
815 // PortConfig->Dma32BitAddresses =
816 // PortConfig->DemandMode =
817 PortConfig->MapBuffers = HwInitializationData->MapBuffers;
818 PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
819 PortConfig->TaggedQueuing = HwInitializationData->TaggedQueueing;
820 PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
821 PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
822 PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
823 // PortConfig->RealModeInitialized =
824 // PortConfig->BufferAccessScsiPortControlled =
825 PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
826 // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
827
828 PortConfig->SlotNumber = SlotNumber.u.AsULONG;
829
830 PortConfig->AccessRanges = (PACCESS_RANGE)(PortConfig + 1);
831
832 /* Search for matching PCI device */
833 if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
834 (HwInitializationData->VendorIdLength > 0) &&
835 (HwInitializationData->VendorId != NULL) &&
836 (HwInitializationData->DeviceIdLength > 0) &&
837 (HwInitializationData->DeviceId != NULL))
838 {
839 /* Get PCI device data */
840 DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
841 HwInitializationData->VendorIdLength,
842 HwInitializationData->VendorId,
843 HwInitializationData->DeviceIdLength,
844 HwInitializationData->DeviceId);
845
846 if (!SpiGetPciConfigData (HwInitializationData,
847 PortConfig,
848 BusNumber,
849 &SlotNumber))
850 {
851 Status = STATUS_UNSUCCESSFUL;
852 goto ByeBye;
853 }
854 }
855
856 /* Note: HwFindAdapter is called once for each bus */
857 Again = FALSE;
858 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
859 Result = (HwInitializationData->HwFindAdapter)(&DeviceExtension->MiniPortDeviceExtension,
860 HwContext,
861 0, /* BusInformation */
862 "", /* ArgumentString */
863 PortConfig,
864 &Again);
865 DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
866 Result, (Again) ? "True" : "False");
867
868 if (Result == SP_RETURN_FOUND)
869 {
870 DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
871
872 /* Register an interrupt handler for this device */
873 MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
874 PortConfig->SystemIoBusNumber,
875 PortConfig->BusInterruptLevel,
876 PortConfig->BusInterruptVector,
877 &Dirql,
878 &Affinity);
879 Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
880 ScsiPortIsr,
881 DeviceExtension,
882 &DeviceExtension->SpinLock,
883 MappedIrq,
884 Dirql,
885 Dirql,
886 PortConfig->InterruptMode,
887 TRUE,
888 Affinity,
889 FALSE);
890 if (!NT_SUCCESS(Status))
891 {
892 DbgPrint("Could not connect interrupt %d\n",
893 PortConfig->BusInterruptVector);
894 goto ByeBye;
895 }
896
897 if (!(HwInitializationData->HwInitialize)(&DeviceExtension->MiniPortDeviceExtension))
898 {
899 DbgPrint("HwInitialize() failed!");
900 Status = STATUS_UNSUCCESSFUL;
901 goto ByeBye;
902 }
903
904 /* Initialize port capabilities */
905 DeviceExtension->PortCapabilities = ExAllocatePool(NonPagedPool,
906 sizeof(IO_SCSI_CAPABILITIES));
907 if (DeviceExtension->PortCapabilities == NULL)
908 {
909 DbgPrint("Failed to allocate port capabilities!\n");
910 Status = STATUS_INSUFFICIENT_RESOURCES;
911 goto ByeBye;
912 }
913
914 PortCapabilities = DeviceExtension->PortCapabilities;
915 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
916 PortCapabilities->MaximumTransferLength =
917 PortConfig->MaximumTransferLength;
918 PortCapabilities->MaximumPhysicalPages =
919 PortCapabilities->MaximumTransferLength / PAGE_SIZE;
920 PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
921 PortCapabilities->AlignmentMask =
922 PortConfig->AlignmentMask;
923 PortCapabilities->TaggedQueuing =
924 PortConfig->TaggedQueuing;
925 PortCapabilities->AdapterScansDown =
926 PortConfig->AdapterScansDown;
927 PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
928
929 /* Scan the adapter for devices */
930 SpiScanAdapter (DeviceExtension);
931
932 /* Build the registry device map */
933 SpiBuildDeviceMap (DeviceExtension,
934 (PUNICODE_STRING)Argument2);
935
936 /* Create the dos device link */
937 swprintf(DosNameBuffer,
938 L"\\??\\Scsi%lu:",
939 SystemConfig->ScsiPortCount);
940 RtlInitUnicodeString(&DosDeviceName,
941 DosNameBuffer);
942 IoCreateSymbolicLink(&DosDeviceName,
943 &DeviceName);
944
945 /* Update the system configuration info */
946 if (PortConfig->AtdiskPrimaryClaimed == TRUE)
947 SystemConfig->AtDiskPrimaryAddressClaimed = TRUE;
948 if (PortConfig->AtdiskSecondaryClaimed == TRUE)
949 SystemConfig->AtDiskSecondaryAddressClaimed = TRUE;
950
951 SystemConfig->ScsiPortCount++;
952 PortDeviceObject = NULL;
953 }
954 else
955 {
956 DPRINT("HwFindAdapter() Result: %lu\n", Result);
957
958 ExFreePool (PortConfig);
959 IoDeleteDevice (PortDeviceObject);
960 PortDeviceObject = NULL;
961 }
962
963 DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber, MaxBus);
964 if (BusNumber >= MaxBus)
965 {
966 DPRINT("Scanned all buses!\n");
967 Status = STATUS_SUCCESS;
968 goto ByeBye;
969 }
970
971 if (Again == FALSE)
972 {
973 BusNumber++;
974 SlotNumber.u.AsULONG = 0;
975 }
976 }
977
978 ByeBye:
979 /* Clean up the mess */
980 if (PortDeviceObject != NULL)
981 {
982 DPRINT("Delete device: %p\n", PortDeviceObject);
983
984 DeviceExtension = PortDeviceObject->DeviceExtension;
985
986 if (DeviceExtension->PortCapabilities != NULL)
987 {
988 IoDisconnectInterrupt (DeviceExtension->Interrupt);
989 ExFreePool (DeviceExtension->PortCapabilities);
990 }
991
992 if (DeviceExtension->PortConfig != NULL)
993 {
994 ExFreePool (DeviceExtension->PortConfig);
995 }
996
997 IoDeleteDevice (PortDeviceObject);
998 }
999
1000 DPRINT("ScsiPortInitialize() done!\n");
1001
1002 return Status;
1003 }
1004
1005
1006 /*
1007 * @unimplemented
1008 */
1009 VOID STDCALL
1010 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
1011 IN PSCSI_REQUEST_BLOCK Srb,
1012 IN ULONG LogicalAddress,
1013 IN ULONG Length)
1014 {
1015 DPRINT1("ScsiPortIoMapTransfer()\n");
1016 UNIMPLEMENTED;
1017 }
1018
1019
1020 /*
1021 * @unimplemented
1022 */
1023 VOID STDCALL
1024 ScsiPortLogError(IN PVOID HwDeviceExtension,
1025 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
1026 IN UCHAR PathId,
1027 IN UCHAR TargetId,
1028 IN UCHAR Lun,
1029 IN ULONG ErrorCode,
1030 IN ULONG UniqueId)
1031 {
1032 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1033
1034 DPRINT1("ScsiPortLogError() called\n");
1035
1036 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1037 SCSI_PORT_DEVICE_EXTENSION,
1038 MiniPortDeviceExtension);
1039
1040
1041 DPRINT("ScsiPortLogError() done\n");
1042 }
1043
1044
1045 /*
1046 * @implemented
1047 */
1048 VOID STDCALL
1049 ScsiPortMoveMemory(OUT PVOID Destination,
1050 IN PVOID Source,
1051 IN ULONG Length)
1052 {
1053 RtlMoveMemory(Destination,
1054 Source,
1055 Length);
1056 }
1057
1058
1059 /*
1060 * @implemented
1061 */
1062 VOID
1063 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
1064 IN PVOID HwDeviceExtension,
1065 ...)
1066 {
1067 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1068 va_list ap;
1069
1070 DPRINT("ScsiPortNotification() called\n");
1071
1072 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1073 SCSI_PORT_DEVICE_EXTENSION,
1074 MiniPortDeviceExtension);
1075
1076 DPRINT("DeviceExtension %p\n", DeviceExtension);
1077
1078 va_start(ap, HwDeviceExtension);
1079
1080 switch (NotificationType)
1081 {
1082 case RequestComplete:
1083 {
1084 PSCSI_REQUEST_BLOCK Srb;
1085
1086 Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
1087
1088 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
1089 DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
1090 }
1091 break;
1092
1093 case NextRequest:
1094 DPRINT("Notify: NextRequest\n");
1095 DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
1096 break;
1097
1098 case NextLuRequest:
1099 {
1100 UCHAR PathId;
1101 UCHAR TargetId;
1102 UCHAR Lun;
1103
1104 PathId = (UCHAR) va_arg (ap, int);
1105 TargetId = (UCHAR) va_arg (ap, int);
1106 Lun = (UCHAR) va_arg (ap, int);
1107
1108 DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
1109 PathId, TargetId, Lun);
1110 /* FIXME: Implement it! */
1111
1112 // DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
1113
1114 /* Hack! */
1115 DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
1116 }
1117 break;
1118
1119 case ResetDetected:
1120 DPRINT1("Notify: ResetDetected\n");
1121 /* FIXME: ??? */
1122 break;
1123
1124 default:
1125 DPRINT1 ("Unsupported notification %lu\n", NotificationType);
1126 break;
1127 }
1128
1129 va_end(ap);
1130 }
1131
1132
1133 /*
1134 * @implemented
1135 */
1136 ULONG STDCALL
1137 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
1138 IN ULONG BusDataType,
1139 IN ULONG SystemIoBusNumber,
1140 IN ULONG SlotNumber,
1141 IN PVOID Buffer,
1142 IN ULONG Offset,
1143 IN ULONG Length)
1144 {
1145 DPRINT("ScsiPortSetBusDataByOffset()\n");
1146 return(HalSetBusDataByOffset(BusDataType,
1147 SystemIoBusNumber,
1148 SlotNumber,
1149 Buffer,
1150 Offset,
1151 Length));
1152 }
1153
1154
1155 /*
1156 * @implemented
1157 */
1158 BOOLEAN STDCALL
1159 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
1160 IN INTERFACE_TYPE BusType,
1161 IN ULONG SystemIoBusNumber,
1162 IN SCSI_PHYSICAL_ADDRESS IoAddress,
1163 IN ULONG NumberOfBytes,
1164 IN BOOLEAN InIoSpace)
1165 {
1166 DPRINT("ScsiPortValidateRange()\n");
1167 return(TRUE);
1168 }
1169
1170
1171 /* INTERNAL FUNCTIONS ********************************************************/
1172
1173
1174 static BOOLEAN
1175 SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
1176 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
1177 IN ULONG BusNumber,
1178 IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
1179 {
1180 PCI_COMMON_CONFIG PciConfig;
1181 PCI_SLOT_NUMBER SlotNumber;
1182 ULONG DataSize;
1183 ULONG DeviceNumber;
1184 ULONG FunctionNumber;
1185 CHAR VendorIdString[8];
1186 CHAR DeviceIdString[8];
1187 ULONG i;
1188 ULONG RangeLength;
1189
1190 DPRINT ("SpiGetPciConfiguration() called\n");
1191
1192 if (NextSlotNumber->u.bits.FunctionNumber >= PCI_MAX_FUNCTION)
1193 {
1194 NextSlotNumber->u.bits.FunctionNumber = 0;
1195 NextSlotNumber->u.bits.DeviceNumber++;
1196 }
1197
1198 if (NextSlotNumber->u.bits.DeviceNumber >= PCI_MAX_DEVICES)
1199 {
1200 NextSlotNumber->u.bits.DeviceNumber = 0;
1201 return FALSE;
1202 }
1203
1204 for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
1205 {
1206 SlotNumber.u.bits.DeviceNumber = DeviceNumber;
1207
1208 for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
1209 {
1210 SlotNumber.u.bits.FunctionNumber = FunctionNumber;
1211
1212 DataSize = HalGetBusData (PCIConfiguration,
1213 BusNumber,
1214 SlotNumber.u.AsULONG,
1215 &PciConfig,
1216 PCI_COMMON_HDR_LENGTH);
1217 if (DataSize != PCI_COMMON_HDR_LENGTH)
1218 {
1219 if (FunctionNumber == 0)
1220 {
1221 break;
1222 }
1223 else
1224 {
1225 continue;
1226 }
1227 }
1228
1229 sprintf (VendorIdString, "%04hx", PciConfig.VendorID);
1230 sprintf (DeviceIdString, "%04hx", PciConfig.DeviceID);
1231
1232 if (!_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) &&
1233 !_strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
1234 {
1235 DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1236 PciConfig.VendorID,
1237 PciConfig.DeviceID,
1238 BusNumber,
1239 SlotNumber.u.bits.DeviceNumber,
1240 SlotNumber.u.bits.FunctionNumber);
1241
1242 PortConfig->BusInterruptLevel =
1243 PortConfig->BusInterruptVector = PciConfig.u.type0.InterruptLine;
1244 PortConfig->SlotNumber = SlotNumber.u.AsULONG;
1245
1246 /* Initialize access ranges */
1247 if (PortConfig->NumberOfAccessRanges > 0)
1248 {
1249 if (PortConfig->NumberOfAccessRanges > PCI_TYPE0_ADDRESSES)
1250 PortConfig->NumberOfAccessRanges = PCI_TYPE0_ADDRESSES;
1251
1252 for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
1253 {
1254 PortConfig->AccessRanges[i].RangeStart.QuadPart =
1255 PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK;
1256 if (PortConfig->AccessRanges[i].RangeStart.QuadPart != 0)
1257 {
1258 RangeLength = (ULONG)-1;
1259 HalSetBusDataByOffset (PCIConfiguration,
1260 BusNumber,
1261 SlotNumber.u.AsULONG,
1262 (PVOID)&RangeLength,
1263 0x10 + (i * sizeof(ULONG)),
1264 sizeof(ULONG));
1265
1266 HalGetBusDataByOffset (PCIConfiguration,
1267 BusNumber,
1268 SlotNumber.u.AsULONG,
1269 (PVOID)&RangeLength,
1270 0x10 + (i * sizeof(ULONG)),
1271 sizeof(ULONG));
1272
1273 HalSetBusDataByOffset (PCIConfiguration,
1274 BusNumber,
1275 SlotNumber.u.AsULONG,
1276 (PVOID)&PciConfig.u.type0.BaseAddresses[i],
1277 0x10 + (i * sizeof(ULONG)),
1278 sizeof(ULONG));
1279 if (RangeLength != 0)
1280 {
1281 PortConfig->AccessRanges[0].RangeLength =
1282 -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK);
1283 PortConfig->AccessRanges[i].RangeInMemory =
1284 !(PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE);
1285
1286 DPRINT1("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
1287 PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK,
1288 -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK),
1289 (PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE)?"FALSE":"TRUE");
1290 }
1291 }
1292 }
1293 }
1294
1295 NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
1296 NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
1297
1298 return TRUE;
1299 }
1300
1301
1302 if (FunctionNumber == 0 && !(PciConfig.HeaderType & PCI_MULTIFUNCTION))
1303 {
1304 break;
1305 }
1306 }
1307 NextSlotNumber->u.bits.FunctionNumber = 0;
1308 }
1309
1310 DPRINT ("No device found\n");
1311
1312 return FALSE;
1313 }
1314
1315
1316
1317 /**********************************************************************
1318 * NAME INTERNAL
1319 * ScsiPortCreateClose
1320 *
1321 * DESCRIPTION
1322 * Answer requests for Create/Close calls: a null operation.
1323 *
1324 * RUN LEVEL
1325 * PASSIVE_LEVEL
1326 *
1327 * ARGUMENTS
1328 * DeviceObject
1329 * Pointer to a device object.
1330 *
1331 * Irp
1332 * Pointer to an IRP.
1333 *
1334 * RETURN VALUE
1335 * Status.
1336 */
1337
1338 static NTSTATUS STDCALL
1339 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
1340 IN PIRP Irp)
1341 {
1342 DPRINT("ScsiPortCreateClose()\n");
1343
1344 Irp->IoStatus.Status = STATUS_SUCCESS;
1345 Irp->IoStatus.Information = FILE_OPENED;
1346
1347 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1348
1349 return(STATUS_SUCCESS);
1350 }
1351
1352
1353 /**********************************************************************
1354 * NAME INTERNAL
1355 * ScsiPortDispatchScsi
1356 *
1357 * DESCRIPTION
1358 * Answer requests for SCSI calls
1359 *
1360 * RUN LEVEL
1361 * PASSIVE_LEVEL
1362 *
1363 * ARGUMENTS
1364 * Standard dispatch arguments
1365 *
1366 * RETURNS
1367 * NTSTATUS
1368 */
1369
1370 static NTSTATUS STDCALL
1371 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
1372 IN PIRP Irp)
1373 {
1374 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1375 PSCSI_PORT_LUN_EXTENSION LunExtension;
1376 PIO_STACK_LOCATION Stack;
1377 PSCSI_REQUEST_BLOCK Srb;
1378 NTSTATUS Status = STATUS_SUCCESS;
1379 ULONG DataSize = 0;
1380
1381 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
1382 DeviceObject, Irp);
1383
1384 DeviceExtension = DeviceObject->DeviceExtension;
1385 Stack = IoGetCurrentIrpStackLocation(Irp);
1386
1387 Srb = Stack->Parameters.Scsi.Srb;
1388 if (Srb == NULL)
1389 {
1390 Status = STATUS_UNSUCCESSFUL;
1391
1392 Irp->IoStatus.Status = Status;
1393 Irp->IoStatus.Information = 0;
1394
1395 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1396
1397 return(Status);
1398 }
1399
1400 DPRINT("Srb: %p\n", Srb);
1401 DPRINT("Srb->Function: %lu\n", Srb->Function);
1402 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
1403
1404 LunExtension = SpiGetLunExtension(DeviceExtension,
1405 Srb->PathId,
1406 Srb->TargetId,
1407 Srb->Lun);
1408 if (LunExtension == NULL)
1409 {
1410 Status = STATUS_NO_SUCH_DEVICE;
1411
1412 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1413 Irp->IoStatus.Status = Status;
1414 Irp->IoStatus.Information = 0;
1415
1416 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1417
1418 return(Status);
1419 }
1420
1421 switch (Srb->Function)
1422 {
1423 case SRB_FUNCTION_EXECUTE_SCSI:
1424 case SRB_FUNCTION_IO_CONTROL:
1425 #ifdef USE_DEVICE_QUEUES
1426 if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
1427 {
1428 IoMarkIrpPending(Irp);
1429 IoStartPacket (DeviceObject, Irp, NULL, NULL);
1430 }
1431 else
1432 {
1433 KIRQL oldIrql;
1434
1435 KeRaiseIrql (DISPATCH_LEVEL,
1436 &oldIrql);
1437
1438 if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue,
1439 &Irp->Tail.Overlay.DeviceQueueEntry,
1440 Srb->QueueSortKey))
1441 {
1442 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1443 IoMarkIrpPending(Irp);
1444 IoStartPacket (DeviceObject, Irp, NULL, NULL);
1445 }
1446
1447 KeLowerIrql (oldIrql);
1448 }
1449 #else
1450 IoMarkIrpPending(Irp);
1451 IoStartPacket (DeviceObject, Irp, NULL, NULL);
1452 #endif
1453 return(STATUS_PENDING);
1454
1455 case SRB_FUNCTION_SHUTDOWN:
1456 case SRB_FUNCTION_FLUSH:
1457 if (DeviceExtension->PortConfig->CachesData == TRUE)
1458 {
1459 IoMarkIrpPending(Irp);
1460 IoStartPacket(DeviceObject, Irp, NULL, NULL);
1461 return(STATUS_PENDING);
1462 }
1463 break;
1464
1465 case SRB_FUNCTION_CLAIM_DEVICE:
1466 DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
1467
1468 /* Reference device object and keep the device object */
1469 ObReferenceObject(DeviceObject);
1470 LunExtension->DeviceObject = DeviceObject;
1471 LunExtension->DeviceClaimed = TRUE;
1472 Srb->DataBuffer = DeviceObject;
1473 break;
1474
1475 case SRB_FUNCTION_RELEASE_DEVICE:
1476 DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
1477 DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
1478 Srb->PathId, Srb->TargetId, Srb->Lun);
1479
1480 /* Dereference device object and clear the device object */
1481 ObDereferenceObject(LunExtension->DeviceObject);
1482 LunExtension->DeviceObject = NULL;
1483 LunExtension->DeviceClaimed = FALSE;
1484 break;
1485
1486 default:
1487 DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
1488 Status = STATUS_NOT_IMPLEMENTED;
1489 break;
1490 }
1491
1492 Irp->IoStatus.Status = Status;
1493 Irp->IoStatus.Information = DataSize;
1494
1495 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1496
1497 return(Status);
1498 }
1499
1500
1501 /**********************************************************************
1502 * NAME INTERNAL
1503 * ScsiPortDeviceControl
1504 *
1505 * DESCRIPTION
1506 * Answer requests for device control calls
1507 *
1508 * RUN LEVEL
1509 * PASSIVE_LEVEL
1510 *
1511 * ARGUMENTS
1512 * Standard dispatch arguments
1513 *
1514 * RETURNS
1515 * NTSTATUS
1516 */
1517
1518 static NTSTATUS STDCALL
1519 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1520 IN PIRP Irp)
1521 {
1522 PIO_STACK_LOCATION Stack;
1523 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1524
1525 DPRINT("ScsiPortDeviceControl()\n");
1526
1527 Irp->IoStatus.Status = STATUS_SUCCESS;
1528 Irp->IoStatus.Information = 0;
1529
1530
1531 Stack = IoGetCurrentIrpStackLocation(Irp);
1532 DeviceExtension = DeviceObject->DeviceExtension;
1533
1534 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
1535 {
1536 case IOCTL_SCSI_GET_DUMP_POINTERS:
1537 {
1538 PDUMP_POINTERS DumpPointers;
1539 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
1540 DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
1541 DumpPointers->DeviceObject = DeviceObject;
1542
1543 Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
1544 }
1545 break;
1546
1547 case IOCTL_SCSI_GET_CAPABILITIES:
1548 {
1549 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
1550
1551 *((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
1552 DeviceExtension->PortCapabilities;
1553
1554 Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
1555 }
1556 break;
1557
1558 case IOCTL_SCSI_GET_INQUIRY_DATA:
1559 {
1560 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
1561
1562 /* Copy inquiry data to the port device extension */
1563 Irp->IoStatus.Information =
1564 SpiGetInquiryData(DeviceExtension,
1565 Irp->AssociatedIrp.SystemBuffer);
1566 DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
1567 }
1568 break;
1569
1570 default:
1571 DPRINT1(" unknown ioctl code: 0x%lX\n",
1572 Stack->Parameters.DeviceIoControl.IoControlCode);
1573 break;
1574 }
1575
1576 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1577
1578 return(STATUS_SUCCESS);
1579 }
1580
1581
1582 static VOID STDCALL
1583 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
1584 IN PIRP Irp)
1585 {
1586 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1587 PSCSI_PORT_LUN_EXTENSION LunExtension;
1588 PIO_STACK_LOCATION IrpStack;
1589 PSCSI_REQUEST_BLOCK Srb;
1590 KIRQL oldIrql;
1591
1592 DPRINT("ScsiPortStartIo() called!\n");
1593
1594 DeviceExtension = DeviceObject->DeviceExtension;
1595 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1596
1597 DPRINT("DeviceExtension %p\n", DeviceExtension);
1598
1599 oldIrql = KeGetCurrentIrql();
1600
1601 if (IrpStack->MajorFunction != IRP_MJ_SCSI)
1602 {
1603 DPRINT("No IRP_MJ_SCSI!\n");
1604 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1605 Irp->IoStatus.Information = 0;
1606 IoCompleteRequest (Irp,
1607 IO_NO_INCREMENT);
1608 if (oldIrql < DISPATCH_LEVEL)
1609 {
1610 KeRaiseIrql (DISPATCH_LEVEL,
1611 &oldIrql);
1612 IoStartNextPacket (DeviceObject,
1613 FALSE);
1614 KeLowerIrql (oldIrql);
1615 }
1616 else
1617 {
1618 IoStartNextPacket (DeviceObject,
1619 FALSE);
1620 }
1621 return;
1622 }
1623
1624 Srb = IrpStack->Parameters.Scsi.Srb;
1625
1626 LunExtension = SpiGetLunExtension(DeviceExtension,
1627 Srb->PathId,
1628 Srb->TargetId,
1629 Srb->Lun);
1630 if (LunExtension == NULL)
1631 {
1632 DPRINT("Can't get LunExtension!\n");
1633 Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
1634 Irp->IoStatus.Information = 0;
1635 IoCompleteRequest (Irp,
1636 IO_NO_INCREMENT);
1637 if (oldIrql < DISPATCH_LEVEL)
1638 {
1639 KeRaiseIrql (DISPATCH_LEVEL,
1640 &oldIrql);
1641 IoStartNextPacket (DeviceObject,
1642 FALSE);
1643 KeLowerIrql (oldIrql);
1644 }
1645 else
1646 {
1647 IoStartNextPacket (DeviceObject,
1648 FALSE);
1649 }
1650 return;
1651 }
1652
1653 Irp->IoStatus.Status = STATUS_SUCCESS;
1654 Irp->IoStatus.Information = Srb->DataTransferLength;
1655
1656 /* Allocte SRB extension */
1657 if (DeviceExtension->SrbExtensionSize != 0)
1658 {
1659 Srb->SrbExtension = DeviceExtension->VirtualAddress;
1660 }
1661
1662 DeviceExtension->CurrentIrp = Irp;
1663
1664 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
1665 ScsiPortStartPacket,
1666 DeviceExtension))
1667 {
1668 DPRINT("Synchronization failed!\n");
1669
1670 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1671 Irp->IoStatus.Information = 0;
1672 IoCompleteRequest(Irp,
1673 IO_NO_INCREMENT);
1674 if (oldIrql < DISPATCH_LEVEL)
1675 {
1676 KeRaiseIrql (DISPATCH_LEVEL,
1677 &oldIrql);
1678 IoStartNextPacket (DeviceObject,
1679 FALSE);
1680 KeLowerIrql (oldIrql);
1681 }
1682 else
1683 {
1684 IoStartNextPacket (DeviceObject,
1685 FALSE);
1686 }
1687 }
1688
1689 KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
1690 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
1691 {
1692 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
1693 IoCompleteRequest(Irp,
1694 IO_NO_INCREMENT);
1695 }
1696
1697 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
1698 {
1699 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
1700 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
1701 IoStartNextPacket(DeviceObject,
1702 FALSE);
1703 KeLowerIrql(oldIrql);
1704 }
1705 else
1706 {
1707 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1708 }
1709
1710 DPRINT("ScsiPortStartIo() done\n");
1711 }
1712
1713
1714 static BOOLEAN STDCALL
1715 ScsiPortStartPacket(IN OUT PVOID Context)
1716 {
1717 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1718 PIO_STACK_LOCATION IrpStack;
1719 PSCSI_REQUEST_BLOCK Srb;
1720
1721 DPRINT("ScsiPortStartPacket() called\n");
1722
1723 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
1724
1725 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1726 Srb = IrpStack->Parameters.Scsi.Srb;
1727
1728 return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1729 Srb));
1730 }
1731
1732
1733 static PSCSI_PORT_LUN_EXTENSION
1734 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1735 IN UCHAR PathId,
1736 IN UCHAR TargetId,
1737 IN UCHAR Lun)
1738 {
1739 PSCSI_PORT_LUN_EXTENSION LunExtension;
1740 ULONG LunExtensionSize;
1741
1742 DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
1743 DeviceExtension, PathId, TargetId, Lun);
1744
1745 LunExtensionSize =
1746 sizeof(SCSI_PORT_LUN_EXTENSION) + DeviceExtension->LunExtensionSize;
1747 DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
1748
1749 LunExtension = ExAllocatePool(NonPagedPool,
1750 LunExtensionSize);
1751 if (LunExtension == NULL)
1752 {
1753 return NULL;
1754 }
1755
1756 RtlZeroMemory(LunExtension,
1757 LunExtensionSize);
1758
1759 InsertTailList(&DeviceExtension->LunExtensionListHead,
1760 &LunExtension->List);
1761
1762 LunExtension->PathId = PathId;
1763 LunExtension->TargetId = TargetId;
1764 LunExtension->Lun = Lun;
1765
1766 KeInitializeDeviceQueue (&LunExtension->DeviceQueue);
1767
1768 return LunExtension;
1769 }
1770
1771
1772 static VOID
1773 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension)
1774 {
1775 DPRINT("SpiRemoveLunExtension(%p) called\n",
1776 LunExtension);
1777
1778 if (LunExtension == NULL)
1779 return;
1780
1781 RemoveEntryList (&LunExtension->List);
1782
1783
1784 /* Release LUN extersion data */
1785
1786
1787 ExFreePool (LunExtension);
1788
1789 return;
1790 }
1791
1792
1793 static PSCSI_PORT_LUN_EXTENSION
1794 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1795 IN UCHAR PathId,
1796 IN UCHAR TargetId,
1797 IN UCHAR Lun)
1798 {
1799 PSCSI_PORT_LUN_EXTENSION LunExtension;
1800 PLIST_ENTRY Entry;
1801
1802 DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
1803 DeviceExtension, PathId, TargetId, Lun);
1804
1805 if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
1806 return NULL;
1807
1808 Entry = DeviceExtension->LunExtensionListHead.Flink;
1809 while (Entry != &DeviceExtension->LunExtensionListHead)
1810 {
1811 LunExtension = CONTAINING_RECORD(Entry,
1812 SCSI_PORT_LUN_EXTENSION,
1813 List);
1814 if (LunExtension->PathId == PathId &&
1815 LunExtension->TargetId == TargetId &&
1816 LunExtension->Lun == Lun)
1817 {
1818 return LunExtension;
1819 }
1820
1821 Entry = Entry->Flink;
1822 }
1823
1824 return NULL;
1825 }
1826
1827
1828 static NTSTATUS
1829 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
1830 IN OUT PSCSI_REQUEST_BLOCK Srb)
1831 {
1832 IO_STATUS_BLOCK IoStatusBlock;
1833 PIO_STACK_LOCATION IrpStack;
1834 PKEVENT Event;
1835 PIRP Irp;
1836 NTSTATUS Status;
1837
1838 DPRINT ("SpiSendInquiry() called\n");
1839
1840 Event = ExAllocatePool (NonPagedPool,
1841 sizeof(KEVENT));
1842 if (Event == NULL)
1843 return STATUS_INSUFFICIENT_RESOURCES;
1844
1845 KeInitializeEvent (Event,
1846 NotificationEvent,
1847 FALSE);
1848
1849 Irp = IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT,
1850 DeviceObject,
1851 NULL,
1852 0,
1853 Srb->DataBuffer,
1854 Srb->DataTransferLength,
1855 TRUE,
1856 Event,
1857 &IoStatusBlock);
1858 if (Irp == NULL)
1859 {
1860 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1861 ExFreePool (Event);
1862 return STATUS_INSUFFICIENT_RESOURCES;
1863 }
1864
1865 /* Attach Srb to the Irp */
1866 IrpStack = IoGetNextIrpStackLocation (Irp);
1867 IrpStack->Parameters.Scsi.Srb = Srb;
1868 Srb->OriginalRequest = Irp;
1869
1870 /* Call the driver */
1871 Status = IoCallDriver (DeviceObject,
1872 Irp);
1873 if (Status == STATUS_PENDING)
1874 {
1875 KeWaitForSingleObject (Event,
1876 Suspended,
1877 KernelMode,
1878 FALSE,
1879 NULL);
1880 Status = IoStatusBlock.Status;
1881 }
1882
1883 ExFreePool (Event);
1884
1885 return Status;
1886 }
1887
1888
1889 static VOID
1890 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1891 {
1892 PSCSI_PORT_LUN_EXTENSION LunExtension;
1893 SCSI_REQUEST_BLOCK Srb;
1894 PCDB Cdb;
1895 ULONG Bus;
1896 ULONG Target;
1897 ULONG Lun;
1898 NTSTATUS Status;
1899
1900 DPRINT ("SpiScanAdapter() called\n");
1901
1902 RtlZeroMemory(&Srb,
1903 sizeof(SCSI_REQUEST_BLOCK));
1904 Srb.SrbFlags = SRB_FLAGS_DATA_IN;
1905 Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
1906 Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
1907 Srb.DataTransferLength = 255; //256;
1908 Srb.CdbLength = 6;
1909
1910 Cdb = (PCDB) &Srb.Cdb;
1911
1912 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
1913 Cdb->CDB6INQUIRY.AllocationLength = 255;
1914
1915 for (Bus = 0; Bus < DeviceExtension->PortConfig->NumberOfBuses; Bus++)
1916 {
1917 Srb.PathId = Bus;
1918
1919 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
1920 {
1921 Srb.TargetId = Target;
1922
1923 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
1924 {
1925 Srb.Lun = Lun;
1926 Srb.SrbStatus = SRB_STATUS_SUCCESS;
1927
1928 Cdb->CDB6INQUIRY.LogicalUnitNumber = Lun;
1929
1930 LunExtension = SpiAllocateLunExtension (DeviceExtension,
1931 Bus,
1932 Target,
1933 Lun);
1934 if (LunExtension == NULL)
1935 {
1936 DPRINT("Failed to allocate the LUN extension!\n");
1937 ExFreePool(Srb.DataBuffer);
1938 return;
1939 }
1940
1941 Status = SpiSendInquiry (DeviceExtension->DeviceObject,
1942 &Srb);
1943 DPRINT ("Status %lx Srb.SrbStatus %x\n", Status, Srb.SrbStatus);
1944
1945 if (NT_SUCCESS(Status) &&
1946 (Srb.SrbStatus == SRB_STATUS_SUCCESS ||
1947 Srb.SrbStatus == SRB_STATUS_DATA_OVERRUN) &&
1948 ((PINQUIRYDATA)Srb.DataBuffer)->DeviceTypeQualifier == 0)
1949 {
1950 /* Copy inquiry data */
1951 RtlCopyMemory (&LunExtension->InquiryData,
1952 Srb.DataBuffer,
1953 sizeof(INQUIRYDATA));
1954 }
1955 else
1956 {
1957 SpiRemoveLunExtension (LunExtension);
1958 }
1959 }
1960 }
1961 }
1962
1963 ExFreePool(Srb.DataBuffer);
1964
1965 DPRINT ("SpiScanAdapter() done\n");
1966 }
1967
1968
1969 static ULONG
1970 SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1971 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo)
1972 {
1973 PSCSI_PORT_LUN_EXTENSION LunExtension;
1974 PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
1975 ULONG Bus;
1976 ULONG Target;
1977 ULONG Lun;
1978 ULONG UnitCount;
1979
1980 DPRINT("SpiGetInquiryData() called\n");
1981
1982 /* Copy inquiry data to the port device extension */
1983 AdapterBusInfo->NumberOfBuses = DeviceExtension->PortConfig->NumberOfBuses;
1984
1985 UnitInfo = (PSCSI_INQUIRY_DATA)
1986 ((PUCHAR)AdapterBusInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
1987 (sizeof(SCSI_BUS_DATA) * (AdapterBusInfo->NumberOfBuses - 1)));
1988
1989 for (Bus = 0; Bus < AdapterBusInfo->NumberOfBuses; Bus++)
1990 {
1991 AdapterBusInfo->BusData[Bus].InitiatorBusId =
1992 DeviceExtension->PortConfig->InitiatorBusId[Bus];
1993 AdapterBusInfo->BusData[Bus].InquiryDataOffset =
1994 (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterBusInfo);
1995
1996 PrevUnit = NULL;
1997 UnitCount = 0;
1998
1999 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
2000 {
2001 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
2002 {
2003 LunExtension = SpiGetLunExtension(DeviceExtension,
2004 Bus,
2005 Target,
2006 Lun);
2007 if (LunExtension != NULL)
2008 {
2009 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
2010 Bus, Target, Lun);
2011
2012 UnitInfo->PathId = Bus;
2013 UnitInfo->TargetId = Target;
2014 UnitInfo->Lun = Lun;
2015 UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
2016 RtlCopyMemory (&UnitInfo->InquiryData,
2017 &LunExtension->InquiryData,
2018 INQUIRYDATABUFFERSIZE);
2019 if (PrevUnit != NULL)
2020 {
2021 PrevUnit->NextInquiryDataOffset =
2022 (ULONG)((ULONG_PTR)UnitInfo-(ULONG_PTR)AdapterBusInfo);
2023 }
2024 PrevUnit = UnitInfo;
2025 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
2026 UnitCount++;
2027 }
2028 }
2029 }
2030 DPRINT("UnitCount: %lu\n", UnitCount);
2031 AdapterBusInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
2032 if (UnitCount == 0)
2033 {
2034 AdapterBusInfo->BusData[Bus].InquiryDataOffset = 0;
2035 }
2036 }
2037
2038 DPRINT("Data size: %lu\n", (ULONG)UnitInfo - (ULONG)AdapterBusInfo);
2039
2040 return (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
2041 }
2042
2043
2044 static BOOLEAN STDCALL
2045 ScsiPortIsr(IN PKINTERRUPT Interrupt,
2046 IN PVOID ServiceContext)
2047 {
2048 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2049 BOOLEAN Result;
2050
2051 DPRINT("ScsiPortIsr() called!\n");
2052
2053 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
2054
2055 Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
2056 if (Result == FALSE)
2057 {
2058 return(FALSE);
2059 }
2060
2061 if (DeviceExtension->IrpFlags)
2062 {
2063 IoRequestDpc(DeviceExtension->DeviceObject,
2064 DeviceExtension->CurrentIrp,
2065 DeviceExtension);
2066 }
2067
2068 return(TRUE);
2069 }
2070
2071
2072 // ScsiPortDpcForIsr
2073 // DESCRIPTION:
2074 //
2075 // RUN LEVEL:
2076 //
2077 // ARGUMENTS:
2078 // IN PKDPC Dpc
2079 // IN PDEVICE_OBJECT DpcDeviceObject
2080 // IN PIRP DpcIrp
2081 // IN PVOID DpcContext
2082 //
2083 static VOID STDCALL
2084 ScsiPortDpcForIsr(IN PKDPC Dpc,
2085 IN PDEVICE_OBJECT DpcDeviceObject,
2086 IN PIRP DpcIrp,
2087 IN PVOID DpcContext)
2088 {
2089 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2090 PIO_STACK_LOCATION IrpStack;
2091 PSCSI_REQUEST_BLOCK Srb;
2092
2093 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
2094 Dpc, DpcDeviceObject, DpcIrp, DpcContext);
2095
2096 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
2097
2098 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
2099 if (DeviceExtension->IrpFlags)
2100 {
2101 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
2102 Srb = IrpStack->Parameters.Scsi.Srb;
2103
2104 if (DeviceExtension->OriginalSrb != NULL)
2105 {
2106 DPRINT("Got sense data!\n");
2107
2108 DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
2109 DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
2110 DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
2111 DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
2112
2113 /* Copy sense data */
2114 if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
2115 {
2116 RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
2117 &DeviceExtension->InternalSenseData,
2118 sizeof(SENSE_DATA));
2119 DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2120 }
2121
2122 /* Clear current sense data */
2123 RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
2124
2125 IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
2126 ScsiPortFreeSenseRequestSrb (DeviceExtension);
2127 }
2128 else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
2129 (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
2130 {
2131 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
2132
2133 DeviceExtension->OriginalSrb = Srb;
2134 IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
2135 Srb);
2136 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2137 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
2138 ScsiPortStartPacket,
2139 DeviceExtension))
2140 {
2141 DPRINT1("Synchronization failed!\n");
2142
2143 DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
2144 DpcIrp->IoStatus.Information = 0;
2145 IoCompleteRequest(DpcIrp,
2146 IO_NO_INCREMENT);
2147 IoStartNextPacket(DpcDeviceObject,
2148 FALSE);
2149 }
2150
2151 return;
2152 }
2153
2154 DeviceExtension->CurrentIrp = NULL;
2155
2156 // DpcIrp->IoStatus.Information = 0;
2157 // DpcIrp->IoStatus.Status = STATUS_SUCCESS;
2158
2159 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
2160 {
2161 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
2162 IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
2163 }
2164
2165 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
2166 {
2167 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
2168 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2169 IoStartNextPacket(DpcDeviceObject, FALSE);
2170 }
2171 else
2172 {
2173 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2174 }
2175 }
2176 else
2177 {
2178 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2179 }
2180
2181 DPRINT("ScsiPortDpcForIsr() done\n");
2182 }
2183
2184
2185 // ScsiPortIoTimer
2186 // DESCRIPTION:
2187 // This function handles timeouts and other time delayed processing
2188 //
2189 // RUN LEVEL:
2190 //
2191 // ARGUMENTS:
2192 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
2193 // IN PVOID Context the Controller extension for the
2194 // controller the device is on
2195 //
2196 static VOID STDCALL
2197 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
2198 PVOID Context)
2199 {
2200 DPRINT1("ScsiPortIoTimer()\n");
2201 }
2202
2203
2204 static PSCSI_REQUEST_BLOCK
2205 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2206 PSCSI_REQUEST_BLOCK OriginalSrb)
2207 {
2208 PSCSI_REQUEST_BLOCK Srb;
2209 PCDB Cdb;
2210
2211 Srb = &DeviceExtension->InternalSrb;
2212
2213 RtlZeroMemory(Srb,
2214 sizeof(SCSI_REQUEST_BLOCK));
2215
2216 Srb->PathId = OriginalSrb->PathId;
2217 Srb->TargetId = OriginalSrb->TargetId;
2218 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2219 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2220 Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2221
2222 Srb->TimeOutValue = 4;
2223
2224 Srb->CdbLength = 6;
2225 Srb->DataBuffer = &DeviceExtension->InternalSenseData;
2226 Srb->DataTransferLength = sizeof(SENSE_DATA);
2227
2228 Cdb = (PCDB)Srb->Cdb;
2229 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2230 Cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2231
2232 return(Srb);
2233 }
2234
2235
2236 static VOID
2237 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
2238 {
2239 DeviceExtension->OriginalSrb = NULL;
2240 }
2241
2242
2243 /**********************************************************************
2244 * NAME INTERNAL
2245 * SpiBuildDeviceMap
2246 *
2247 * DESCRIPTION
2248 * Builds the registry device map of all device which are attached
2249 * to the given SCSI HBA port. The device map is located at:
2250 * \Registry\Machine\DeviceMap\Scsi
2251 *
2252 * RUN LEVEL
2253 * PASSIVE_LEVEL
2254 *
2255 * ARGUMENTS
2256 * DeviceExtension
2257 * ...
2258 *
2259 * RegistryPath
2260 * Name of registry driver service key.
2261 *
2262 * RETURNS
2263 * NTSTATUS
2264 */
2265
2266 static NTSTATUS
2267 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2268 PUNICODE_STRING RegistryPath)
2269 {
2270 PSCSI_PORT_LUN_EXTENSION LunExtension;
2271 OBJECT_ATTRIBUTES ObjectAttributes;
2272 UNICODE_STRING KeyName;
2273 UNICODE_STRING ValueName;
2274 WCHAR NameBuffer[64];
2275 ULONG Disposition;
2276 HANDLE ScsiKey;
2277 HANDLE ScsiPortKey = NULL;
2278 HANDLE ScsiBusKey = NULL;
2279 HANDLE ScsiInitiatorKey = NULL;
2280 HANDLE ScsiTargetKey = NULL;
2281 HANDLE ScsiLunKey = NULL;
2282 ULONG BusNumber;
2283 ULONG Target;
2284 ULONG CurrentTarget;
2285 ULONG Lun;
2286 PWCHAR DriverName;
2287 ULONG UlongData;
2288 PWCHAR TypeName;
2289 NTSTATUS Status;
2290
2291 DPRINT("SpiBuildDeviceMap() called\n");
2292
2293 if (DeviceExtension == NULL || RegistryPath == NULL)
2294 {
2295 DPRINT1("Invalid parameter\n");
2296 return(STATUS_INVALID_PARAMETER);
2297 }
2298
2299 /* Open or create the 'Scsi' subkey */
2300 RtlRosInitUnicodeStringFromLiteral(&KeyName,
2301 L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
2302 InitializeObjectAttributes(&ObjectAttributes,
2303 &KeyName,
2304 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
2305 0,
2306 NULL);
2307 Status = ZwCreateKey(&ScsiKey,
2308 KEY_ALL_ACCESS,
2309 &ObjectAttributes,
2310 0,
2311 NULL,
2312 REG_OPTION_VOLATILE,
2313 &Disposition);
2314 if (!NT_SUCCESS(Status))
2315 {
2316 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2317 return(Status);
2318 }
2319
2320 /* Create new 'Scsi Port X' subkey */
2321 DPRINT("Scsi Port %lu\n",
2322 DeviceExtension->PortNumber);
2323
2324 swprintf(NameBuffer,
2325 L"Scsi Port %lu",
2326 DeviceExtension->PortNumber);
2327 RtlInitUnicodeString(&KeyName,
2328 NameBuffer);
2329 InitializeObjectAttributes(&ObjectAttributes,
2330 &KeyName,
2331 0,
2332 ScsiKey,
2333 NULL);
2334 Status = ZwCreateKey(&ScsiPortKey,
2335 KEY_ALL_ACCESS,
2336 &ObjectAttributes,
2337 0,
2338 NULL,
2339 REG_OPTION_VOLATILE,
2340 &Disposition);
2341 ZwClose(ScsiKey);
2342 if (!NT_SUCCESS(Status))
2343 {
2344 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2345 return(Status);
2346 }
2347
2348 /*
2349 * Create port-specific values
2350 */
2351
2352 /* Set 'DMA Enabled' (REG_DWORD) value */
2353 UlongData = (ULONG)!DeviceExtension->PortCapabilities->AdapterUsesPio;
2354 DPRINT(" DMA Enabled = %s\n", (UlongData) ? "TRUE" : "FALSE");
2355 RtlInitUnicodeString(&ValueName,
2356 L"DMA Enabled");
2357 Status = ZwSetValueKey(ScsiPortKey,
2358 &ValueName,
2359 0,
2360 REG_DWORD,
2361 &UlongData,
2362 sizeof(ULONG));
2363 if (!NT_SUCCESS(Status))
2364 {
2365 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status);
2366 ZwClose(ScsiPortKey);
2367 return(Status);
2368 }
2369
2370 /* Set 'Driver' (REG_SZ) value */
2371 DriverName = wcsrchr(RegistryPath->Buffer, L'\\') + 1;
2372 RtlInitUnicodeString(&ValueName,
2373 L"Driver");
2374 Status = ZwSetValueKey(ScsiPortKey,
2375 &ValueName,
2376 0,
2377 REG_SZ,
2378 DriverName,
2379 (wcslen(DriverName) + 1) * sizeof(WCHAR));
2380 if (!NT_SUCCESS(Status))
2381 {
2382 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
2383 ZwClose(ScsiPortKey);
2384 return(Status);
2385 }
2386
2387 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
2388 UlongData = (ULONG)DeviceExtension->PortConfig->BusInterruptLevel;
2389 DPRINT(" Interrupt = %lu\n", UlongData);
2390 RtlInitUnicodeString(&ValueName,
2391 L"Interrupt");
2392 Status = ZwSetValueKey(ScsiPortKey,
2393 &ValueName,
2394 0,
2395 REG_DWORD,
2396 &UlongData,
2397 sizeof(ULONG));
2398 if (!NT_SUCCESS(Status))
2399 {
2400 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status);
2401 ZwClose(ScsiPortKey);
2402 return(Status);
2403 }
2404
2405 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
2406 UlongData = ScsiPortConvertPhysicalAddressToUlong(DeviceExtension->PortConfig->AccessRanges[0].RangeStart);
2407 DPRINT(" IOAddress = %lx\n", UlongData);
2408 RtlInitUnicodeString(&ValueName,
2409 L"IOAddress");
2410 Status = ZwSetValueKey(ScsiPortKey,
2411 &ValueName,
2412 0,
2413 REG_DWORD,
2414 &UlongData,
2415 sizeof(ULONG));
2416 if (!NT_SUCCESS(Status))
2417 {
2418 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status);
2419 ZwClose(ScsiPortKey);
2420 return(Status);
2421 }
2422
2423 /* Enumerate buses */
2424 for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
2425 {
2426 /* Create 'Scsi Bus X' key */
2427 DPRINT(" Scsi Bus %lu\n", BusNumber);
2428 swprintf(NameBuffer,
2429 L"Scsi Bus %lu",
2430 BusNumber);
2431 RtlInitUnicodeString(&KeyName,
2432 NameBuffer);
2433 InitializeObjectAttributes(&ObjectAttributes,
2434 &KeyName,
2435 0,
2436 ScsiPortKey,
2437 NULL);
2438 Status = ZwCreateKey(&ScsiBusKey,
2439 KEY_ALL_ACCESS,
2440 &ObjectAttributes,
2441 0,
2442 NULL,
2443 REG_OPTION_VOLATILE,
2444 &Disposition);
2445 if (!NT_SUCCESS(Status))
2446 {
2447 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2448 goto ByeBye;
2449 }
2450
2451 /* Create 'Initiator Id X' key */
2452 DPRINT(" Initiator Id %u\n",
2453 DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
2454 swprintf(NameBuffer,
2455 L"Initiator Id %u",
2456 (unsigned int)(UCHAR)DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
2457 RtlInitUnicodeString(&KeyName,
2458 NameBuffer);
2459 InitializeObjectAttributes(&ObjectAttributes,
2460 &KeyName,
2461 0,
2462 ScsiBusKey,
2463 NULL);
2464 Status = ZwCreateKey(&ScsiInitiatorKey,
2465 KEY_ALL_ACCESS,
2466 &ObjectAttributes,
2467 0,
2468 NULL,
2469 REG_OPTION_VOLATILE,
2470 &Disposition);
2471 if (!NT_SUCCESS(Status))
2472 {
2473 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2474 goto ByeBye;
2475 }
2476
2477 /* FIXME: Are there any initiator values (??) */
2478
2479 ZwClose(ScsiInitiatorKey);
2480 ScsiInitiatorKey = NULL;
2481
2482
2483 /* Enumerate targets */
2484 CurrentTarget = (ULONG)-1;
2485 ScsiTargetKey = NULL;
2486 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
2487 {
2488 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
2489 {
2490 LunExtension = SpiGetLunExtension(DeviceExtension,
2491 BusNumber,
2492 Target,
2493 Lun);
2494 if (LunExtension != NULL)
2495 {
2496 if (Target != CurrentTarget)
2497 {
2498 /* Close old target key */
2499 if (ScsiTargetKey != NULL)
2500 {
2501 ZwClose(ScsiTargetKey);
2502 ScsiTargetKey = NULL;
2503 }
2504
2505 /* Create 'Target Id X' key */
2506 DPRINT(" Target Id %lu\n", Target);
2507 swprintf(NameBuffer,
2508 L"Target Id %lu",
2509 Target);
2510 RtlInitUnicodeString(&KeyName,
2511 NameBuffer);
2512 InitializeObjectAttributes(&ObjectAttributes,
2513 &KeyName,
2514 0,
2515 ScsiBusKey,
2516 NULL);
2517 Status = ZwCreateKey(&ScsiTargetKey,
2518 KEY_ALL_ACCESS,
2519 &ObjectAttributes,
2520 0,
2521 NULL,
2522 REG_OPTION_VOLATILE,
2523 &Disposition);
2524 if (!NT_SUCCESS(Status))
2525 {
2526 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2527 goto ByeBye;
2528 }
2529
2530 CurrentTarget = Target;
2531 }
2532
2533 /* Create 'Logical Unit Id X' key */
2534 DPRINT(" Logical Unit Id %lu\n", Lun);
2535 swprintf(NameBuffer,
2536 L"Logical Unit Id %lu",
2537 Lun);
2538 RtlInitUnicodeString(&KeyName,
2539 NameBuffer);
2540 InitializeObjectAttributes(&ObjectAttributes,
2541 &KeyName,
2542 0,
2543 ScsiTargetKey,
2544 NULL);
2545 Status = ZwCreateKey(&ScsiLunKey,
2546 KEY_ALL_ACCESS,
2547 &ObjectAttributes,
2548 0,
2549 NULL,
2550 REG_OPTION_VOLATILE,
2551 &Disposition);
2552 if (!NT_SUCCESS(Status))
2553 {
2554 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2555 goto ByeBye;
2556 }
2557
2558 /* Set 'Identifier' (REG_SZ) value */
2559 swprintf(NameBuffer,
2560 L"%.8S%.16S%.4S",
2561 LunExtension->InquiryData.VendorId,
2562 LunExtension->InquiryData.ProductId,
2563 LunExtension->InquiryData.ProductRevisionLevel);
2564 DPRINT(" Identifier = '%S'\n", NameBuffer);
2565 RtlInitUnicodeString(&ValueName,
2566 L"Identifier");
2567 Status = ZwSetValueKey(ScsiLunKey,
2568 &ValueName,
2569 0,
2570 REG_SZ,
2571 NameBuffer,
2572 (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
2573 if (!NT_SUCCESS(Status))
2574 {
2575 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
2576 goto ByeBye;
2577 }
2578
2579 /* Set 'Type' (REG_SZ) value */
2580 switch (LunExtension->InquiryData.DeviceType)
2581 {
2582 case 0:
2583 TypeName = L"DiskPeripheral";
2584 break;
2585 case 1:
2586 TypeName = L"TapePeripheral";
2587 break;
2588 case 2:
2589 TypeName = L"PrinterPeripheral";
2590 break;
2591 case 4:
2592 TypeName = L"WormPeripheral";
2593 break;
2594 case 5:
2595 TypeName = L"CdRomPeripheral";
2596 break;
2597 case 6:
2598 TypeName = L"ScannerPeripheral";
2599 break;
2600 case 7:
2601 TypeName = L"OpticalDiskPeripheral";
2602 break;
2603 case 8:
2604 TypeName = L"MediumChangerPeripheral";
2605 break;
2606 case 9:
2607 TypeName = L"CommunicationPeripheral";
2608 break;
2609 default:
2610 TypeName = L"OtherPeripheral";
2611 break;
2612 }
2613 DPRINT(" Type = '%S'\n", TypeName);
2614 RtlInitUnicodeString(&ValueName,
2615 L"Type");
2616 Status = ZwSetValueKey(ScsiLunKey,
2617 &ValueName,
2618 0,
2619 REG_SZ,
2620 TypeName,
2621 (wcslen(TypeName) + 1) * sizeof(WCHAR));
2622 if (!NT_SUCCESS(Status))
2623 {
2624 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
2625 goto ByeBye;
2626 }
2627
2628 ZwClose(ScsiLunKey);
2629 ScsiLunKey = NULL;
2630 }
2631 }
2632
2633 /* Close old target key */
2634 if (ScsiTargetKey != NULL)
2635 {
2636 ZwClose(ScsiTargetKey);
2637 ScsiTargetKey = NULL;
2638 }
2639 }
2640
2641 ZwClose(ScsiBusKey);
2642 ScsiBusKey = NULL;
2643 }
2644
2645 ByeBye:
2646 if (ScsiLunKey != NULL)
2647 ZwClose (ScsiLunKey);
2648
2649 if (ScsiInitiatorKey != NULL)
2650 ZwClose (ScsiInitiatorKey);
2651
2652 if (ScsiTargetKey != NULL)
2653 ZwClose (ScsiTargetKey);
2654
2655 if (ScsiBusKey != NULL)
2656 ZwClose (ScsiBusKey);
2657
2658 if (ScsiPortKey != NULL)
2659 ZwClose (ScsiPortKey);
2660
2661 DPRINT("SpiBuildDeviceMap() done\n");
2662
2663 return Status;
2664 }
2665
2666 /* EOF */