* Always return STATUS_SUCCESS from ScsiPortInitialize if some device was found.
[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.51 2004/03/24 16:21:59 navaraf 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() unimplemented\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 BOOLEAN DeviceFound = FALSE;
661 ULONG i;
662 ULONG Result;
663 NTSTATUS Status;
664 ULONG MaxBus;
665 ULONG BusNumber;
666 PCI_SLOT_NUMBER SlotNumber;
667
668 PDEVICE_OBJECT PortDeviceObject;
669 WCHAR NameBuffer[80];
670 UNICODE_STRING DeviceName;
671 WCHAR DosNameBuffer[80];
672 UNICODE_STRING DosDeviceName;
673 PIO_SCSI_CAPABILITIES PortCapabilities;
674 ULONG MappedIrq;
675 KIRQL Dirql;
676 KAFFINITY Affinity;
677
678
679 DPRINT ("ScsiPortInitialize() called!\n");
680
681 if ((HwInitializationData->HwInitialize == NULL) ||
682 (HwInitializationData->HwStartIo == NULL) ||
683 (HwInitializationData->HwInterrupt == NULL) ||
684 (HwInitializationData->HwFindAdapter == NULL) ||
685 (HwInitializationData->HwResetBus == NULL))
686 return(STATUS_INVALID_PARAMETER);
687
688 DriverObject->DriverStartIo = ScsiPortStartIo;
689 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
690 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
691 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
692 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
693
694 SystemConfig = IoGetConfigurationInformation();
695
696 DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
697 HwInitializationData->DeviceExtensionSize;
698 PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
699 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
700
701
702 MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
703 DPRINT("MaxBus: %lu\n", MaxBus);
704
705 PortDeviceObject = NULL;
706 BusNumber = 0;
707 SlotNumber.u.AsULONG = 0;
708 while (TRUE)
709 {
710 /* Create a unicode device name */
711 swprintf (NameBuffer,
712 L"\\Device\\ScsiPort%lu",
713 SystemConfig->ScsiPortCount);
714 RtlInitUnicodeString (&DeviceName,
715 NameBuffer);
716
717 DPRINT("Creating device: %wZ\n", &DeviceName);
718
719 /* Create the port device */
720 Status = IoCreateDevice (DriverObject,
721 DeviceExtensionSize,
722 &DeviceName,
723 FILE_DEVICE_CONTROLLER,
724 0,
725 FALSE,
726 &PortDeviceObject);
727 if (!NT_SUCCESS(Status))
728 {
729 DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
730 PortDeviceObject = NULL;
731 goto ByeBye;
732 }
733
734 DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
735
736 /* Set the buffering strategy here... */
737 PortDeviceObject->Flags |= DO_DIRECT_IO;
738 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
739
740 DeviceExtension = PortDeviceObject->DeviceExtension;
741 DeviceExtension->Length = DeviceExtensionSize;
742 DeviceExtension->DeviceObject = PortDeviceObject;
743 DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
744
745 DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
746 DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
747 DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
748 DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
749 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
750
751 #if 0
752 DeviceExtension->AdapterObject = NULL;
753 DeviceExtension->MapRegisterCount = 0;
754 DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
755 DeviceExtension->VirtualAddress = NULL;
756 DeviceExtension->CommonBufferLength = 0;
757 #endif
758
759 /* Initialize the device base list */
760 InitializeListHead (&DeviceExtension->DeviceBaseListHead);
761
762 /* Initialize LUN-Extension list */
763 InitializeListHead (&DeviceExtension->LunExtensionListHead);
764
765 /* Initialize the spin lock in the controller extension */
766 KeInitializeSpinLock (&DeviceExtension->IrpLock);
767 KeInitializeSpinLock (&DeviceExtension->SpinLock);
768
769 /* Initialize the DPC object */
770 IoInitializeDpcRequest (PortDeviceObject,
771 ScsiPortDpcForIsr);
772
773 /* Initialize the device timer */
774 DeviceExtension->TimerState = IDETimerIdle;
775 DeviceExtension->TimerCount = 0;
776 IoInitializeTimer (PortDeviceObject,
777 ScsiPortIoTimer,
778 DeviceExtension);
779
780 /* Allocate and initialize port configuration info */
781 DeviceExtension->PortConfig = ExAllocatePool (NonPagedPool,
782 PortConfigSize);
783 if (DeviceExtension->PortConfig == NULL)
784 {
785 Status = STATUS_INSUFFICIENT_RESOURCES;
786 goto ByeBye;
787 }
788 RtlZeroMemory (DeviceExtension->PortConfig,
789 PortConfigSize);
790
791 PortConfig = DeviceExtension->PortConfig;
792 PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
793 PortConfig->SystemIoBusNumber = BusNumber;
794 PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
795 PortConfig->InterruptMode =
796 (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
797 PortConfig->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
798 PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
799 PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
800 PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
801 // PortConfig->DmaWidth =
802 // PortConfig->DmaSpeed =
803 // PortConfig->AlignmentMask =
804 PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
805 // PortConfig->NumberOfBuses =
806
807 for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
808 PortConfig->InitiatorBusId[i] = 255;
809
810 // PortConfig->ScatterGather =
811 // PortConfig->Master =
812 // PortConfig->CachesData =
813 // PortConfig->AdapterScansDown =
814 PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
815 PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
816 // PortConfig->Dma32BitAddresses =
817 // PortConfig->DemandMode =
818 PortConfig->MapBuffers = HwInitializationData->MapBuffers;
819 PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
820 PortConfig->TaggedQueuing = HwInitializationData->TaggedQueueing;
821 PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
822 PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
823 PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
824 // PortConfig->RealModeInitialized =
825 // PortConfig->BufferAccessScsiPortControlled =
826 PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
827 // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
828
829 PortConfig->SlotNumber = SlotNumber.u.AsULONG;
830
831 PortConfig->AccessRanges = (PACCESS_RANGE)(PortConfig + 1);
832
833 /* Search for matching PCI device */
834 if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
835 (HwInitializationData->VendorIdLength > 0) &&
836 (HwInitializationData->VendorId != NULL) &&
837 (HwInitializationData->DeviceIdLength > 0) &&
838 (HwInitializationData->DeviceId != NULL))
839 {
840 /* Get PCI device data */
841 DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
842 HwInitializationData->VendorIdLength,
843 HwInitializationData->VendorId,
844 HwInitializationData->DeviceIdLength,
845 HwInitializationData->DeviceId);
846
847 if (!SpiGetPciConfigData (HwInitializationData,
848 PortConfig,
849 BusNumber,
850 &SlotNumber))
851 {
852 Status = STATUS_UNSUCCESSFUL;
853 goto ByeBye;
854 }
855 }
856
857 /* Note: HwFindAdapter is called once for each bus */
858 Again = FALSE;
859 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
860 Result = (HwInitializationData->HwFindAdapter)(&DeviceExtension->MiniPortDeviceExtension,
861 HwContext,
862 0, /* BusInformation */
863 "", /* ArgumentString */
864 PortConfig,
865 &Again);
866 DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
867 Result, (Again) ? "True" : "False");
868
869 if (Result == SP_RETURN_FOUND)
870 {
871 DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
872
873 /* Register an interrupt handler for this device */
874 MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
875 PortConfig->SystemIoBusNumber,
876 PortConfig->BusInterruptLevel,
877 PortConfig->BusInterruptVector,
878 &Dirql,
879 &Affinity);
880 Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
881 ScsiPortIsr,
882 DeviceExtension,
883 &DeviceExtension->SpinLock,
884 MappedIrq,
885 Dirql,
886 Dirql,
887 PortConfig->InterruptMode,
888 TRUE,
889 Affinity,
890 FALSE);
891 if (!NT_SUCCESS(Status))
892 {
893 DbgPrint("Could not connect interrupt %d\n",
894 PortConfig->BusInterruptVector);
895 goto ByeBye;
896 }
897
898 if (!(HwInitializationData->HwInitialize)(&DeviceExtension->MiniPortDeviceExtension))
899 {
900 DbgPrint("HwInitialize() failed!");
901 Status = STATUS_UNSUCCESSFUL;
902 goto ByeBye;
903 }
904
905 /* Initialize port capabilities */
906 DeviceExtension->PortCapabilities = ExAllocatePool(NonPagedPool,
907 sizeof(IO_SCSI_CAPABILITIES));
908 if (DeviceExtension->PortCapabilities == NULL)
909 {
910 DbgPrint("Failed to allocate port capabilities!\n");
911 Status = STATUS_INSUFFICIENT_RESOURCES;
912 goto ByeBye;
913 }
914
915 PortCapabilities = DeviceExtension->PortCapabilities;
916 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
917 PortCapabilities->MaximumTransferLength =
918 PortConfig->MaximumTransferLength;
919 PortCapabilities->MaximumPhysicalPages =
920 PortCapabilities->MaximumTransferLength / PAGE_SIZE;
921 PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
922 PortCapabilities->AlignmentMask =
923 PortConfig->AlignmentMask;
924 PortCapabilities->TaggedQueuing =
925 PortConfig->TaggedQueuing;
926 PortCapabilities->AdapterScansDown =
927 PortConfig->AdapterScansDown;
928 PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
929
930 /* Scan the adapter for devices */
931 SpiScanAdapter (DeviceExtension);
932
933 /* Build the registry device map */
934 SpiBuildDeviceMap (DeviceExtension,
935 (PUNICODE_STRING)Argument2);
936
937 /* Create the dos device link */
938 swprintf(DosNameBuffer,
939 L"\\??\\Scsi%lu:",
940 SystemConfig->ScsiPortCount);
941 RtlInitUnicodeString(&DosDeviceName,
942 DosNameBuffer);
943 IoCreateSymbolicLink(&DosDeviceName,
944 &DeviceName);
945
946 /* Update the system configuration info */
947 if (PortConfig->AtdiskPrimaryClaimed == TRUE)
948 SystemConfig->AtDiskPrimaryAddressClaimed = TRUE;
949 if (PortConfig->AtdiskSecondaryClaimed == TRUE)
950 SystemConfig->AtDiskSecondaryAddressClaimed = TRUE;
951
952 SystemConfig->ScsiPortCount++;
953 PortDeviceObject = NULL;
954 DeviceFound = TRUE;
955 }
956 else
957 {
958 DPRINT("HwFindAdapter() Result: %lu\n", Result);
959
960 ExFreePool (PortConfig);
961 IoDeleteDevice (PortDeviceObject);
962 PortDeviceObject = NULL;
963 }
964
965 DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber, MaxBus);
966 if (BusNumber >= MaxBus)
967 {
968 DPRINT("Scanned all buses!\n");
969 Status = STATUS_SUCCESS;
970 goto ByeBye;
971 }
972
973 if (Again == FALSE)
974 {
975 BusNumber++;
976 SlotNumber.u.AsULONG = 0;
977 }
978 }
979
980 ByeBye:
981 /* Clean up the mess */
982 if (PortDeviceObject != NULL)
983 {
984 DPRINT("Delete device: %p\n", PortDeviceObject);
985
986 DeviceExtension = PortDeviceObject->DeviceExtension;
987
988 if (DeviceExtension->PortCapabilities != NULL)
989 {
990 IoDisconnectInterrupt (DeviceExtension->Interrupt);
991 ExFreePool (DeviceExtension->PortCapabilities);
992 }
993
994 if (DeviceExtension->PortConfig != NULL)
995 {
996 ExFreePool (DeviceExtension->PortConfig);
997 }
998
999 IoDeleteDevice (PortDeviceObject);
1000 }
1001
1002 DPRINT("ScsiPortInitialize() done!\n");
1003
1004 return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
1005 }
1006
1007
1008 /*
1009 * @unimplemented
1010 */
1011 VOID STDCALL
1012 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
1013 IN PSCSI_REQUEST_BLOCK Srb,
1014 IN ULONG LogicalAddress,
1015 IN ULONG Length)
1016 {
1017 DPRINT1("ScsiPortIoMapTransfer()\n");
1018 UNIMPLEMENTED;
1019 }
1020
1021
1022 /*
1023 * @unimplemented
1024 */
1025 VOID STDCALL
1026 ScsiPortLogError(IN PVOID HwDeviceExtension,
1027 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
1028 IN UCHAR PathId,
1029 IN UCHAR TargetId,
1030 IN UCHAR Lun,
1031 IN ULONG ErrorCode,
1032 IN ULONG UniqueId)
1033 {
1034 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1035
1036 DPRINT1("ScsiPortLogError() called\n");
1037
1038 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1039 SCSI_PORT_DEVICE_EXTENSION,
1040 MiniPortDeviceExtension);
1041
1042
1043 DPRINT("ScsiPortLogError() done\n");
1044 }
1045
1046
1047 /*
1048 * @implemented
1049 */
1050 VOID STDCALL
1051 ScsiPortMoveMemory(OUT PVOID Destination,
1052 IN PVOID Source,
1053 IN ULONG Length)
1054 {
1055 RtlMoveMemory(Destination,
1056 Source,
1057 Length);
1058 }
1059
1060
1061 /*
1062 * @implemented
1063 */
1064 VOID
1065 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
1066 IN PVOID HwDeviceExtension,
1067 ...)
1068 {
1069 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1070 va_list ap;
1071
1072 DPRINT("ScsiPortNotification() called\n");
1073
1074 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1075 SCSI_PORT_DEVICE_EXTENSION,
1076 MiniPortDeviceExtension);
1077
1078 DPRINT("DeviceExtension %p\n", DeviceExtension);
1079
1080 va_start(ap, HwDeviceExtension);
1081
1082 switch (NotificationType)
1083 {
1084 case RequestComplete:
1085 {
1086 PSCSI_REQUEST_BLOCK Srb;
1087
1088 Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
1089
1090 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
1091 DeviceExtension->IrpFlags |= IRP_FLAG_COMPLETE;
1092 }
1093 break;
1094
1095 case NextRequest:
1096 DPRINT("Notify: NextRequest\n");
1097 DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
1098 break;
1099
1100 case NextLuRequest:
1101 {
1102 UCHAR PathId;
1103 UCHAR TargetId;
1104 UCHAR Lun;
1105
1106 PathId = (UCHAR) va_arg (ap, int);
1107 TargetId = (UCHAR) va_arg (ap, int);
1108 Lun = (UCHAR) va_arg (ap, int);
1109
1110 DPRINT1 ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
1111 PathId, TargetId, Lun);
1112 /* FIXME: Implement it! */
1113
1114 DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
1115 // DeviceExtension->IrpFlags |= IRP_FLAG_NEXT_LU;
1116
1117 /* Hack! */
1118 DeviceExtension->IrpFlags |= IRP_FLAG_NEXT;
1119 }
1120 break;
1121
1122 case ResetDetected:
1123 DPRINT1("Notify: ResetDetected\n");
1124 /* FIXME: ??? */
1125 break;
1126
1127 default:
1128 DPRINT1 ("Unsupported notification %lu\n", NotificationType);
1129 break;
1130 }
1131
1132 va_end(ap);
1133 }
1134
1135
1136 /*
1137 * @implemented
1138 */
1139 ULONG STDCALL
1140 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
1141 IN ULONG BusDataType,
1142 IN ULONG SystemIoBusNumber,
1143 IN ULONG SlotNumber,
1144 IN PVOID Buffer,
1145 IN ULONG Offset,
1146 IN ULONG Length)
1147 {
1148 DPRINT("ScsiPortSetBusDataByOffset()\n");
1149 return(HalSetBusDataByOffset(BusDataType,
1150 SystemIoBusNumber,
1151 SlotNumber,
1152 Buffer,
1153 Offset,
1154 Length));
1155 }
1156
1157
1158 /*
1159 * @implemented
1160 */
1161 BOOLEAN STDCALL
1162 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
1163 IN INTERFACE_TYPE BusType,
1164 IN ULONG SystemIoBusNumber,
1165 IN SCSI_PHYSICAL_ADDRESS IoAddress,
1166 IN ULONG NumberOfBytes,
1167 IN BOOLEAN InIoSpace)
1168 {
1169 DPRINT("ScsiPortValidateRange()\n");
1170 return(TRUE);
1171 }
1172
1173
1174 /* INTERNAL FUNCTIONS ********************************************************/
1175
1176
1177 static BOOLEAN
1178 SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
1179 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
1180 IN ULONG BusNumber,
1181 IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
1182 {
1183 PCI_COMMON_CONFIG PciConfig;
1184 PCI_SLOT_NUMBER SlotNumber;
1185 ULONG DataSize;
1186 ULONG DeviceNumber;
1187 ULONG FunctionNumber;
1188 CHAR VendorIdString[8];
1189 CHAR DeviceIdString[8];
1190 ULONG i;
1191 ULONG RangeLength;
1192
1193 DPRINT ("SpiGetPciConfiguration() called\n");
1194
1195 if (NextSlotNumber->u.bits.FunctionNumber >= PCI_MAX_FUNCTION)
1196 {
1197 NextSlotNumber->u.bits.FunctionNumber = 0;
1198 NextSlotNumber->u.bits.DeviceNumber++;
1199 }
1200
1201 if (NextSlotNumber->u.bits.DeviceNumber >= PCI_MAX_DEVICES)
1202 {
1203 NextSlotNumber->u.bits.DeviceNumber = 0;
1204 return FALSE;
1205 }
1206
1207 for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
1208 {
1209 SlotNumber.u.bits.DeviceNumber = DeviceNumber;
1210
1211 for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
1212 {
1213 SlotNumber.u.bits.FunctionNumber = FunctionNumber;
1214
1215 DataSize = HalGetBusData (PCIConfiguration,
1216 BusNumber,
1217 SlotNumber.u.AsULONG,
1218 &PciConfig,
1219 PCI_COMMON_HDR_LENGTH);
1220 if (DataSize != PCI_COMMON_HDR_LENGTH)
1221 {
1222 if (FunctionNumber == 0)
1223 {
1224 break;
1225 }
1226 else
1227 {
1228 continue;
1229 }
1230 }
1231
1232 sprintf (VendorIdString, "%04hx", PciConfig.VendorID);
1233 sprintf (DeviceIdString, "%04hx", PciConfig.DeviceID);
1234
1235 if (!_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) &&
1236 !_strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
1237 {
1238 DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1239 PciConfig.VendorID,
1240 PciConfig.DeviceID,
1241 BusNumber,
1242 SlotNumber.u.bits.DeviceNumber,
1243 SlotNumber.u.bits.FunctionNumber);
1244
1245 PortConfig->BusInterruptLevel =
1246 PortConfig->BusInterruptVector = PciConfig.u.type0.InterruptLine;
1247 PortConfig->SlotNumber = SlotNumber.u.AsULONG;
1248
1249 /* Initialize access ranges */
1250 if (PortConfig->NumberOfAccessRanges > 0)
1251 {
1252 if (PortConfig->NumberOfAccessRanges > PCI_TYPE0_ADDRESSES)
1253 PortConfig->NumberOfAccessRanges = PCI_TYPE0_ADDRESSES;
1254
1255 for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
1256 {
1257 PortConfig->AccessRanges[i].RangeStart.QuadPart =
1258 PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK;
1259 if (PortConfig->AccessRanges[i].RangeStart.QuadPart != 0)
1260 {
1261 RangeLength = (ULONG)-1;
1262 HalSetBusDataByOffset (PCIConfiguration,
1263 BusNumber,
1264 SlotNumber.u.AsULONG,
1265 (PVOID)&RangeLength,
1266 0x10 + (i * sizeof(ULONG)),
1267 sizeof(ULONG));
1268
1269 HalGetBusDataByOffset (PCIConfiguration,
1270 BusNumber,
1271 SlotNumber.u.AsULONG,
1272 (PVOID)&RangeLength,
1273 0x10 + (i * sizeof(ULONG)),
1274 sizeof(ULONG));
1275
1276 HalSetBusDataByOffset (PCIConfiguration,
1277 BusNumber,
1278 SlotNumber.u.AsULONG,
1279 (PVOID)&PciConfig.u.type0.BaseAddresses[i],
1280 0x10 + (i * sizeof(ULONG)),
1281 sizeof(ULONG));
1282 if (RangeLength != 0)
1283 {
1284 PortConfig->AccessRanges[0].RangeLength =
1285 -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK);
1286 PortConfig->AccessRanges[i].RangeInMemory =
1287 !(PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE);
1288
1289 DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
1290 PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK,
1291 -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK),
1292 (PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE)?"FALSE":"TRUE");
1293 }
1294 }
1295 }
1296 }
1297
1298 NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
1299 NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
1300
1301 return TRUE;
1302 }
1303
1304
1305 if (FunctionNumber == 0 && !(PciConfig.HeaderType & PCI_MULTIFUNCTION))
1306 {
1307 break;
1308 }
1309 }
1310 NextSlotNumber->u.bits.FunctionNumber = 0;
1311 }
1312
1313 DPRINT ("No device found\n");
1314
1315 return FALSE;
1316 }
1317
1318
1319
1320 /**********************************************************************
1321 * NAME INTERNAL
1322 * ScsiPortCreateClose
1323 *
1324 * DESCRIPTION
1325 * Answer requests for Create/Close calls: a null operation.
1326 *
1327 * RUN LEVEL
1328 * PASSIVE_LEVEL
1329 *
1330 * ARGUMENTS
1331 * DeviceObject
1332 * Pointer to a device object.
1333 *
1334 * Irp
1335 * Pointer to an IRP.
1336 *
1337 * RETURN VALUE
1338 * Status.
1339 */
1340
1341 static NTSTATUS STDCALL
1342 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
1343 IN PIRP Irp)
1344 {
1345 DPRINT("ScsiPortCreateClose()\n");
1346
1347 Irp->IoStatus.Status = STATUS_SUCCESS;
1348 Irp->IoStatus.Information = FILE_OPENED;
1349
1350 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1351
1352 return(STATUS_SUCCESS);
1353 }
1354
1355
1356 /**********************************************************************
1357 * NAME INTERNAL
1358 * ScsiPortDispatchScsi
1359 *
1360 * DESCRIPTION
1361 * Answer requests for SCSI calls
1362 *
1363 * RUN LEVEL
1364 * PASSIVE_LEVEL
1365 *
1366 * ARGUMENTS
1367 * Standard dispatch arguments
1368 *
1369 * RETURNS
1370 * NTSTATUS
1371 */
1372
1373 static NTSTATUS STDCALL
1374 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
1375 IN PIRP Irp)
1376 {
1377 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1378 PSCSI_PORT_LUN_EXTENSION LunExtension;
1379 PIO_STACK_LOCATION Stack;
1380 PSCSI_REQUEST_BLOCK Srb;
1381 NTSTATUS Status = STATUS_SUCCESS;
1382 ULONG DataSize = 0;
1383
1384 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
1385 DeviceObject, Irp);
1386
1387 DeviceExtension = DeviceObject->DeviceExtension;
1388 Stack = IoGetCurrentIrpStackLocation(Irp);
1389
1390 Srb = Stack->Parameters.Scsi.Srb;
1391 if (Srb == NULL)
1392 {
1393 Status = STATUS_UNSUCCESSFUL;
1394
1395 Irp->IoStatus.Status = Status;
1396 Irp->IoStatus.Information = 0;
1397
1398 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1399
1400 return(Status);
1401 }
1402
1403 DPRINT("Srb: %p\n", Srb);
1404 DPRINT("Srb->Function: %lu\n", Srb->Function);
1405 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
1406
1407 LunExtension = SpiGetLunExtension(DeviceExtension,
1408 Srb->PathId,
1409 Srb->TargetId,
1410 Srb->Lun);
1411 if (LunExtension == NULL)
1412 {
1413 Status = STATUS_NO_SUCH_DEVICE;
1414
1415 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1416 Irp->IoStatus.Status = Status;
1417 Irp->IoStatus.Information = 0;
1418
1419 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1420
1421 return(Status);
1422 }
1423
1424 switch (Srb->Function)
1425 {
1426 case SRB_FUNCTION_EXECUTE_SCSI:
1427 case SRB_FUNCTION_IO_CONTROL:
1428 #ifdef USE_DEVICE_QUEUES
1429 if (Srb->SrbFlags & SRB_FLAGS_BYPASS_FROZEN_QUEUE)
1430 {
1431 IoMarkIrpPending(Irp);
1432 IoStartPacket (DeviceObject, Irp, NULL, NULL);
1433 }
1434 else
1435 {
1436 KIRQL oldIrql;
1437
1438 KeRaiseIrql (DISPATCH_LEVEL,
1439 &oldIrql);
1440
1441 if (!KeInsertByKeyDeviceQueue (&LunExtension->DeviceQueue,
1442 &Irp->Tail.Overlay.DeviceQueueEntry,
1443 Srb->QueueSortKey))
1444 {
1445 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1446 IoMarkIrpPending(Irp);
1447 IoStartPacket (DeviceObject, Irp, NULL, NULL);
1448 }
1449
1450 KeLowerIrql (oldIrql);
1451 }
1452 #else
1453 IoMarkIrpPending(Irp);
1454 IoStartPacket (DeviceObject, Irp, NULL, NULL);
1455 #endif
1456 return(STATUS_PENDING);
1457
1458 case SRB_FUNCTION_SHUTDOWN:
1459 case SRB_FUNCTION_FLUSH:
1460 if (DeviceExtension->PortConfig->CachesData == TRUE)
1461 {
1462 IoMarkIrpPending(Irp);
1463 IoStartPacket(DeviceObject, Irp, NULL, NULL);
1464 return(STATUS_PENDING);
1465 }
1466 break;
1467
1468 case SRB_FUNCTION_CLAIM_DEVICE:
1469 DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
1470
1471 /* Reference device object and keep the device object */
1472 ObReferenceObject(DeviceObject);
1473 LunExtension->DeviceObject = DeviceObject;
1474 LunExtension->DeviceClaimed = TRUE;
1475 Srb->DataBuffer = DeviceObject;
1476 break;
1477
1478 case SRB_FUNCTION_RELEASE_DEVICE:
1479 DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
1480 DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
1481 Srb->PathId, Srb->TargetId, Srb->Lun);
1482
1483 /* Dereference device object and clear the device object */
1484 ObDereferenceObject(LunExtension->DeviceObject);
1485 LunExtension->DeviceObject = NULL;
1486 LunExtension->DeviceClaimed = FALSE;
1487 break;
1488
1489 default:
1490 DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
1491 Status = STATUS_NOT_IMPLEMENTED;
1492 break;
1493 }
1494
1495 Irp->IoStatus.Status = Status;
1496 Irp->IoStatus.Information = DataSize;
1497
1498 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1499
1500 return(Status);
1501 }
1502
1503
1504 /**********************************************************************
1505 * NAME INTERNAL
1506 * ScsiPortDeviceControl
1507 *
1508 * DESCRIPTION
1509 * Answer requests for device control calls
1510 *
1511 * RUN LEVEL
1512 * PASSIVE_LEVEL
1513 *
1514 * ARGUMENTS
1515 * Standard dispatch arguments
1516 *
1517 * RETURNS
1518 * NTSTATUS
1519 */
1520
1521 static NTSTATUS STDCALL
1522 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1523 IN PIRP Irp)
1524 {
1525 PIO_STACK_LOCATION Stack;
1526 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1527
1528 DPRINT("ScsiPortDeviceControl()\n");
1529
1530 Irp->IoStatus.Status = STATUS_SUCCESS;
1531 Irp->IoStatus.Information = 0;
1532
1533
1534 Stack = IoGetCurrentIrpStackLocation(Irp);
1535 DeviceExtension = DeviceObject->DeviceExtension;
1536
1537 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
1538 {
1539 case IOCTL_SCSI_GET_DUMP_POINTERS:
1540 {
1541 PDUMP_POINTERS DumpPointers;
1542 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
1543 DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
1544 DumpPointers->DeviceObject = DeviceObject;
1545
1546 Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
1547 }
1548 break;
1549
1550 case IOCTL_SCSI_GET_CAPABILITIES:
1551 {
1552 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
1553
1554 *((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
1555 DeviceExtension->PortCapabilities;
1556
1557 Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
1558 }
1559 break;
1560
1561 case IOCTL_SCSI_GET_INQUIRY_DATA:
1562 {
1563 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
1564
1565 /* Copy inquiry data to the port device extension */
1566 Irp->IoStatus.Information =
1567 SpiGetInquiryData(DeviceExtension,
1568 Irp->AssociatedIrp.SystemBuffer);
1569 DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
1570 }
1571 break;
1572
1573 default:
1574 DPRINT1(" unknown ioctl code: 0x%lX\n",
1575 Stack->Parameters.DeviceIoControl.IoControlCode);
1576 break;
1577 }
1578
1579 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1580
1581 return(STATUS_SUCCESS);
1582 }
1583
1584
1585 static VOID STDCALL
1586 ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
1587 IN PIRP Irp)
1588 {
1589 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1590 PSCSI_PORT_LUN_EXTENSION LunExtension;
1591 PIO_STACK_LOCATION IrpStack;
1592 PSCSI_REQUEST_BLOCK Srb;
1593 KIRQL oldIrql;
1594
1595 DPRINT("ScsiPortStartIo() called!\n");
1596
1597 DeviceExtension = DeviceObject->DeviceExtension;
1598 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1599
1600 DPRINT("DeviceExtension %p\n", DeviceExtension);
1601
1602 oldIrql = KeGetCurrentIrql();
1603
1604 if (IrpStack->MajorFunction != IRP_MJ_SCSI)
1605 {
1606 DPRINT("No IRP_MJ_SCSI!\n");
1607 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
1608 Irp->IoStatus.Information = 0;
1609 IoCompleteRequest (Irp,
1610 IO_NO_INCREMENT);
1611 if (oldIrql < DISPATCH_LEVEL)
1612 {
1613 KeRaiseIrql (DISPATCH_LEVEL,
1614 &oldIrql);
1615 IoStartNextPacket (DeviceObject,
1616 FALSE);
1617 KeLowerIrql (oldIrql);
1618 }
1619 else
1620 {
1621 IoStartNextPacket (DeviceObject,
1622 FALSE);
1623 }
1624 return;
1625 }
1626
1627 Srb = IrpStack->Parameters.Scsi.Srb;
1628
1629 LunExtension = SpiGetLunExtension(DeviceExtension,
1630 Srb->PathId,
1631 Srb->TargetId,
1632 Srb->Lun);
1633 if (LunExtension == NULL)
1634 {
1635 DPRINT("Can't get LunExtension!\n");
1636 Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
1637 Irp->IoStatus.Information = 0;
1638 IoCompleteRequest (Irp,
1639 IO_NO_INCREMENT);
1640 if (oldIrql < DISPATCH_LEVEL)
1641 {
1642 KeRaiseIrql (DISPATCH_LEVEL,
1643 &oldIrql);
1644 IoStartNextPacket (DeviceObject,
1645 FALSE);
1646 KeLowerIrql (oldIrql);
1647 }
1648 else
1649 {
1650 IoStartNextPacket (DeviceObject,
1651 FALSE);
1652 }
1653 return;
1654 }
1655
1656 Irp->IoStatus.Status = STATUS_SUCCESS;
1657 Irp->IoStatus.Information = Srb->DataTransferLength;
1658
1659 DeviceExtension->CurrentIrp = Irp;
1660
1661 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
1662 ScsiPortStartPacket,
1663 DeviceExtension))
1664 {
1665 DPRINT("Synchronization failed!\n");
1666
1667 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
1668 Irp->IoStatus.Information = 0;
1669 IoCompleteRequest(Irp,
1670 IO_NO_INCREMENT);
1671 if (oldIrql < DISPATCH_LEVEL)
1672 {
1673 KeRaiseIrql (DISPATCH_LEVEL,
1674 &oldIrql);
1675 IoStartNextPacket (DeviceObject,
1676 FALSE);
1677 KeLowerIrql (oldIrql);
1678 }
1679 else
1680 {
1681 IoStartNextPacket (DeviceObject,
1682 FALSE);
1683 }
1684 }
1685
1686 KeAcquireSpinLock(&DeviceExtension->IrpLock, &oldIrql);
1687 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
1688 {
1689 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
1690 IoCompleteRequest(Irp,
1691 IO_NO_INCREMENT);
1692 }
1693
1694 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
1695 {
1696 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
1697 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
1698 IoStartNextPacket(DeviceObject,
1699 FALSE);
1700 KeLowerIrql(oldIrql);
1701 }
1702 else
1703 {
1704 KeReleaseSpinLock(&DeviceExtension->IrpLock, oldIrql);
1705 }
1706
1707 DPRINT("ScsiPortStartIo() done\n");
1708 }
1709
1710
1711 static BOOLEAN STDCALL
1712 ScsiPortStartPacket(IN OUT PVOID Context)
1713 {
1714 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1715 PIO_STACK_LOCATION IrpStack;
1716 PSCSI_REQUEST_BLOCK Srb;
1717
1718 DPRINT("ScsiPortStartPacket() called\n");
1719
1720 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)Context;
1721
1722 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
1723 Srb = IrpStack->Parameters.Scsi.Srb;
1724
1725 /* Allocte SRB extension */
1726 if (DeviceExtension->SrbExtensionSize != 0)
1727 {
1728 Srb->SrbExtension = DeviceExtension->VirtualAddress;
1729 }
1730
1731 return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1732 Srb));
1733 }
1734
1735
1736 static PSCSI_PORT_LUN_EXTENSION
1737 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1738 IN UCHAR PathId,
1739 IN UCHAR TargetId,
1740 IN UCHAR Lun)
1741 {
1742 PSCSI_PORT_LUN_EXTENSION LunExtension;
1743 ULONG LunExtensionSize;
1744
1745 DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
1746 DeviceExtension, PathId, TargetId, Lun);
1747
1748 LunExtensionSize =
1749 sizeof(SCSI_PORT_LUN_EXTENSION) + DeviceExtension->LunExtensionSize;
1750 DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
1751
1752 LunExtension = ExAllocatePool(NonPagedPool,
1753 LunExtensionSize);
1754 if (LunExtension == NULL)
1755 {
1756 return NULL;
1757 }
1758
1759 RtlZeroMemory(LunExtension,
1760 LunExtensionSize);
1761
1762 InsertTailList(&DeviceExtension->LunExtensionListHead,
1763 &LunExtension->List);
1764
1765 LunExtension->PathId = PathId;
1766 LunExtension->TargetId = TargetId;
1767 LunExtension->Lun = Lun;
1768
1769 KeInitializeDeviceQueue (&LunExtension->DeviceQueue);
1770
1771 return LunExtension;
1772 }
1773
1774
1775 static VOID
1776 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension)
1777 {
1778 DPRINT("SpiRemoveLunExtension(%p) called\n",
1779 LunExtension);
1780
1781 if (LunExtension == NULL)
1782 return;
1783
1784 RemoveEntryList (&LunExtension->List);
1785
1786
1787 /* Release LUN extersion data */
1788
1789
1790 ExFreePool (LunExtension);
1791
1792 return;
1793 }
1794
1795
1796 static PSCSI_PORT_LUN_EXTENSION
1797 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1798 IN UCHAR PathId,
1799 IN UCHAR TargetId,
1800 IN UCHAR Lun)
1801 {
1802 PSCSI_PORT_LUN_EXTENSION LunExtension;
1803 PLIST_ENTRY Entry;
1804
1805 DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
1806 DeviceExtension, PathId, TargetId, Lun);
1807
1808 if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
1809 return NULL;
1810
1811 Entry = DeviceExtension->LunExtensionListHead.Flink;
1812 while (Entry != &DeviceExtension->LunExtensionListHead)
1813 {
1814 LunExtension = CONTAINING_RECORD(Entry,
1815 SCSI_PORT_LUN_EXTENSION,
1816 List);
1817 if (LunExtension->PathId == PathId &&
1818 LunExtension->TargetId == TargetId &&
1819 LunExtension->Lun == Lun)
1820 {
1821 return LunExtension;
1822 }
1823
1824 Entry = Entry->Flink;
1825 }
1826
1827 return NULL;
1828 }
1829
1830
1831 static NTSTATUS
1832 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
1833 IN OUT PSCSI_REQUEST_BLOCK Srb)
1834 {
1835 IO_STATUS_BLOCK IoStatusBlock;
1836 PIO_STACK_LOCATION IrpStack;
1837 PKEVENT Event;
1838 PIRP Irp;
1839 NTSTATUS Status;
1840
1841 DPRINT ("SpiSendInquiry() called\n");
1842
1843 Event = ExAllocatePool (NonPagedPool,
1844 sizeof(KEVENT));
1845 if (Event == NULL)
1846 return STATUS_INSUFFICIENT_RESOURCES;
1847
1848 KeInitializeEvent (Event,
1849 NotificationEvent,
1850 FALSE);
1851
1852 Irp = IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT,
1853 DeviceObject,
1854 NULL,
1855 0,
1856 Srb->DataBuffer,
1857 Srb->DataTransferLength,
1858 TRUE,
1859 Event,
1860 &IoStatusBlock);
1861 if (Irp == NULL)
1862 {
1863 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1864 ExFreePool (Event);
1865 return STATUS_INSUFFICIENT_RESOURCES;
1866 }
1867
1868 /* Attach Srb to the Irp */
1869 IrpStack = IoGetNextIrpStackLocation (Irp);
1870 IrpStack->Parameters.Scsi.Srb = Srb;
1871 Srb->OriginalRequest = Irp;
1872
1873 /* Call the driver */
1874 Status = IoCallDriver (DeviceObject,
1875 Irp);
1876 if (Status == STATUS_PENDING)
1877 {
1878 KeWaitForSingleObject (Event,
1879 Suspended,
1880 KernelMode,
1881 FALSE,
1882 NULL);
1883 Status = IoStatusBlock.Status;
1884 }
1885
1886 ExFreePool (Event);
1887
1888 return Status;
1889 }
1890
1891
1892 static VOID
1893 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
1894 {
1895 PSCSI_PORT_LUN_EXTENSION LunExtension;
1896 SCSI_REQUEST_BLOCK Srb;
1897 PCDB Cdb;
1898 ULONG Bus;
1899 ULONG Target;
1900 ULONG Lun;
1901 NTSTATUS Status;
1902
1903 DPRINT ("SpiScanAdapter() called\n");
1904
1905 RtlZeroMemory(&Srb,
1906 sizeof(SCSI_REQUEST_BLOCK));
1907 Srb.SrbFlags = SRB_FLAGS_DATA_IN;
1908 Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
1909 Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
1910 Srb.DataTransferLength = 255; //256;
1911 Srb.CdbLength = 6;
1912
1913 Cdb = (PCDB) &Srb.Cdb;
1914
1915 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
1916 Cdb->CDB6INQUIRY.AllocationLength = 255;
1917
1918 for (Bus = 0; Bus < DeviceExtension->PortConfig->NumberOfBuses; Bus++)
1919 {
1920 Srb.PathId = Bus;
1921
1922 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
1923 {
1924 Srb.TargetId = Target;
1925
1926 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
1927 {
1928 Srb.Lun = Lun;
1929 Srb.SrbStatus = SRB_STATUS_SUCCESS;
1930
1931 Cdb->CDB6INQUIRY.LogicalUnitNumber = Lun;
1932
1933 LunExtension = SpiAllocateLunExtension (DeviceExtension,
1934 Bus,
1935 Target,
1936 Lun);
1937 if (LunExtension == NULL)
1938 {
1939 DPRINT("Failed to allocate the LUN extension!\n");
1940 ExFreePool(Srb.DataBuffer);
1941 return;
1942 }
1943
1944 Status = SpiSendInquiry (DeviceExtension->DeviceObject,
1945 &Srb);
1946 DPRINT ("Status %lx Srb.SrbStatus %x\n", Status, Srb.SrbStatus);
1947
1948 if (NT_SUCCESS(Status) &&
1949 (Srb.SrbStatus == SRB_STATUS_SUCCESS ||
1950 Srb.SrbStatus == SRB_STATUS_DATA_OVERRUN) &&
1951 ((PINQUIRYDATA)Srb.DataBuffer)->DeviceTypeQualifier == 0)
1952 {
1953 /* Copy inquiry data */
1954 RtlCopyMemory (&LunExtension->InquiryData,
1955 Srb.DataBuffer,
1956 sizeof(INQUIRYDATA));
1957 }
1958 else
1959 {
1960 SpiRemoveLunExtension (LunExtension);
1961 }
1962 }
1963 }
1964 }
1965
1966 ExFreePool(Srb.DataBuffer);
1967
1968 DPRINT ("SpiScanAdapter() done\n");
1969 }
1970
1971
1972 static ULONG
1973 SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1974 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo)
1975 {
1976 PSCSI_PORT_LUN_EXTENSION LunExtension;
1977 PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
1978 ULONG Bus;
1979 ULONG Target;
1980 ULONG Lun;
1981 ULONG UnitCount;
1982
1983 DPRINT("SpiGetInquiryData() called\n");
1984
1985 /* Copy inquiry data to the port device extension */
1986 AdapterBusInfo->NumberOfBuses = DeviceExtension->PortConfig->NumberOfBuses;
1987
1988 UnitInfo = (PSCSI_INQUIRY_DATA)
1989 ((PUCHAR)AdapterBusInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
1990 (sizeof(SCSI_BUS_DATA) * (AdapterBusInfo->NumberOfBuses - 1)));
1991
1992 for (Bus = 0; Bus < AdapterBusInfo->NumberOfBuses; Bus++)
1993 {
1994 AdapterBusInfo->BusData[Bus].InitiatorBusId =
1995 DeviceExtension->PortConfig->InitiatorBusId[Bus];
1996 AdapterBusInfo->BusData[Bus].InquiryDataOffset =
1997 (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterBusInfo);
1998
1999 PrevUnit = NULL;
2000 UnitCount = 0;
2001
2002 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
2003 {
2004 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
2005 {
2006 LunExtension = SpiGetLunExtension(DeviceExtension,
2007 Bus,
2008 Target,
2009 Lun);
2010 if (LunExtension != NULL)
2011 {
2012 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
2013 Bus, Target, Lun);
2014
2015 UnitInfo->PathId = Bus;
2016 UnitInfo->TargetId = Target;
2017 UnitInfo->Lun = Lun;
2018 UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
2019 RtlCopyMemory (&UnitInfo->InquiryData,
2020 &LunExtension->InquiryData,
2021 INQUIRYDATABUFFERSIZE);
2022 if (PrevUnit != NULL)
2023 {
2024 PrevUnit->NextInquiryDataOffset =
2025 (ULONG)((ULONG_PTR)UnitInfo-(ULONG_PTR)AdapterBusInfo);
2026 }
2027 PrevUnit = UnitInfo;
2028 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
2029 UnitCount++;
2030 }
2031 }
2032 }
2033 DPRINT("UnitCount: %lu\n", UnitCount);
2034 AdapterBusInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
2035 if (UnitCount == 0)
2036 {
2037 AdapterBusInfo->BusData[Bus].InquiryDataOffset = 0;
2038 }
2039 }
2040
2041 DPRINT("Data size: %lu\n", (ULONG)UnitInfo - (ULONG)AdapterBusInfo);
2042
2043 return (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
2044 }
2045
2046
2047 static BOOLEAN STDCALL
2048 ScsiPortIsr(IN PKINTERRUPT Interrupt,
2049 IN PVOID ServiceContext)
2050 {
2051 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2052 BOOLEAN Result;
2053
2054 DPRINT("ScsiPortIsr() called!\n");
2055
2056 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
2057
2058 Result = DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
2059 if (Result == FALSE)
2060 {
2061 return(FALSE);
2062 }
2063
2064 if (DeviceExtension->IrpFlags)
2065 {
2066 IoRequestDpc(DeviceExtension->DeviceObject,
2067 DeviceExtension->CurrentIrp,
2068 DeviceExtension);
2069 }
2070
2071 return(TRUE);
2072 }
2073
2074
2075 // ScsiPortDpcForIsr
2076 // DESCRIPTION:
2077 //
2078 // RUN LEVEL:
2079 //
2080 // ARGUMENTS:
2081 // IN PKDPC Dpc
2082 // IN PDEVICE_OBJECT DpcDeviceObject
2083 // IN PIRP DpcIrp
2084 // IN PVOID DpcContext
2085 //
2086 static VOID STDCALL
2087 ScsiPortDpcForIsr(IN PKDPC Dpc,
2088 IN PDEVICE_OBJECT DpcDeviceObject,
2089 IN PIRP DpcIrp,
2090 IN PVOID DpcContext)
2091 {
2092 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2093 PIO_STACK_LOCATION IrpStack;
2094 PSCSI_REQUEST_BLOCK Srb;
2095
2096 DPRINT("ScsiPortDpcForIsr(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
2097 Dpc, DpcDeviceObject, DpcIrp, DpcContext);
2098
2099 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
2100
2101 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->IrpLock);
2102 if (DeviceExtension->IrpFlags)
2103 {
2104 IrpStack = IoGetCurrentIrpStackLocation(DeviceExtension->CurrentIrp);
2105 Srb = IrpStack->Parameters.Scsi.Srb;
2106
2107 if (DeviceExtension->OriginalSrb != NULL)
2108 {
2109 DPRINT("Got sense data!\n");
2110
2111 DPRINT("Valid: %x\n", DeviceExtension->InternalSenseData.Valid);
2112 DPRINT("ErrorCode: %x\n", DeviceExtension->InternalSenseData.ErrorCode);
2113 DPRINT("SenseKey: %x\n", DeviceExtension->InternalSenseData.SenseKey);
2114 DPRINT("SenseCode: %x\n", DeviceExtension->InternalSenseData.AdditionalSenseCode);
2115
2116 /* Copy sense data */
2117 if (DeviceExtension->OriginalSrb->SenseInfoBufferLength != 0)
2118 {
2119 RtlCopyMemory(DeviceExtension->OriginalSrb->SenseInfoBuffer,
2120 &DeviceExtension->InternalSenseData,
2121 sizeof(SENSE_DATA));
2122 DeviceExtension->OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2123 }
2124
2125 /* Clear current sense data */
2126 RtlZeroMemory(&DeviceExtension->InternalSenseData, sizeof(SENSE_DATA));
2127
2128 IrpStack->Parameters.Scsi.Srb = DeviceExtension->OriginalSrb;
2129 ScsiPortFreeSenseRequestSrb (DeviceExtension);
2130 }
2131 else if ((SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS) &&
2132 (Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION))
2133 {
2134 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
2135
2136 DeviceExtension->OriginalSrb = Srb;
2137 IrpStack->Parameters.Scsi.Srb = ScsiPortInitSenseRequestSrb(DeviceExtension,
2138 Srb);
2139 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2140 if (!KeSynchronizeExecution(DeviceExtension->Interrupt,
2141 ScsiPortStartPacket,
2142 DeviceExtension))
2143 {
2144 DPRINT1("Synchronization failed!\n");
2145
2146 DpcIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
2147 DpcIrp->IoStatus.Information = 0;
2148 IoCompleteRequest(DpcIrp,
2149 IO_NO_INCREMENT);
2150 IoStartNextPacket(DpcDeviceObject,
2151 FALSE);
2152 }
2153
2154 return;
2155 }
2156
2157 DeviceExtension->CurrentIrp = NULL;
2158
2159 // DpcIrp->IoStatus.Information = 0;
2160 // DpcIrp->IoStatus.Status = STATUS_SUCCESS;
2161
2162 if (DeviceExtension->IrpFlags & IRP_FLAG_COMPLETE)
2163 {
2164 DeviceExtension->IrpFlags &= ~IRP_FLAG_COMPLETE;
2165 IoCompleteRequest(DpcIrp, IO_NO_INCREMENT);
2166 }
2167
2168 if (DeviceExtension->IrpFlags & IRP_FLAG_NEXT)
2169 {
2170 DeviceExtension->IrpFlags &= ~IRP_FLAG_NEXT;
2171 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2172 IoStartNextPacket(DpcDeviceObject, FALSE);
2173 }
2174 else
2175 {
2176 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2177 }
2178 }
2179 else
2180 {
2181 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->IrpLock);
2182 }
2183
2184 DPRINT("ScsiPortDpcForIsr() done\n");
2185 }
2186
2187
2188 // ScsiPortIoTimer
2189 // DESCRIPTION:
2190 // This function handles timeouts and other time delayed processing
2191 //
2192 // RUN LEVEL:
2193 //
2194 // ARGUMENTS:
2195 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
2196 // IN PVOID Context the Controller extension for the
2197 // controller the device is on
2198 //
2199 static VOID STDCALL
2200 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
2201 PVOID Context)
2202 {
2203 DPRINT1("ScsiPortIoTimer()\n");
2204 }
2205
2206
2207 static PSCSI_REQUEST_BLOCK
2208 ScsiPortInitSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2209 PSCSI_REQUEST_BLOCK OriginalSrb)
2210 {
2211 PSCSI_REQUEST_BLOCK Srb;
2212 PCDB Cdb;
2213
2214 Srb = &DeviceExtension->InternalSrb;
2215
2216 RtlZeroMemory(Srb,
2217 sizeof(SCSI_REQUEST_BLOCK));
2218
2219 Srb->PathId = OriginalSrb->PathId;
2220 Srb->TargetId = OriginalSrb->TargetId;
2221 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2222 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2223 Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2224
2225 Srb->TimeOutValue = 4;
2226
2227 Srb->CdbLength = 6;
2228 Srb->DataBuffer = &DeviceExtension->InternalSenseData;
2229 Srb->DataTransferLength = sizeof(SENSE_DATA);
2230
2231 Cdb = (PCDB)Srb->Cdb;
2232 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2233 Cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2234
2235 return(Srb);
2236 }
2237
2238
2239 static VOID
2240 ScsiPortFreeSenseRequestSrb(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
2241 {
2242 DeviceExtension->OriginalSrb = NULL;
2243 }
2244
2245
2246 /**********************************************************************
2247 * NAME INTERNAL
2248 * SpiBuildDeviceMap
2249 *
2250 * DESCRIPTION
2251 * Builds the registry device map of all device which are attached
2252 * to the given SCSI HBA port. The device map is located at:
2253 * \Registry\Machine\DeviceMap\Scsi
2254 *
2255 * RUN LEVEL
2256 * PASSIVE_LEVEL
2257 *
2258 * ARGUMENTS
2259 * DeviceExtension
2260 * ...
2261 *
2262 * RegistryPath
2263 * Name of registry driver service key.
2264 *
2265 * RETURNS
2266 * NTSTATUS
2267 */
2268
2269 static NTSTATUS
2270 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2271 PUNICODE_STRING RegistryPath)
2272 {
2273 PSCSI_PORT_LUN_EXTENSION LunExtension;
2274 OBJECT_ATTRIBUTES ObjectAttributes;
2275 UNICODE_STRING KeyName;
2276 UNICODE_STRING ValueName;
2277 WCHAR NameBuffer[64];
2278 ULONG Disposition;
2279 HANDLE ScsiKey;
2280 HANDLE ScsiPortKey = NULL;
2281 HANDLE ScsiBusKey = NULL;
2282 HANDLE ScsiInitiatorKey = NULL;
2283 HANDLE ScsiTargetKey = NULL;
2284 HANDLE ScsiLunKey = NULL;
2285 ULONG BusNumber;
2286 ULONG Target;
2287 ULONG CurrentTarget;
2288 ULONG Lun;
2289 PWCHAR DriverName;
2290 ULONG UlongData;
2291 PWCHAR TypeName;
2292 NTSTATUS Status;
2293
2294 DPRINT("SpiBuildDeviceMap() called\n");
2295
2296 if (DeviceExtension == NULL || RegistryPath == NULL)
2297 {
2298 DPRINT1("Invalid parameter\n");
2299 return(STATUS_INVALID_PARAMETER);
2300 }
2301
2302 /* Open or create the 'Scsi' subkey */
2303 RtlRosInitUnicodeStringFromLiteral(&KeyName,
2304 L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
2305 InitializeObjectAttributes(&ObjectAttributes,
2306 &KeyName,
2307 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
2308 0,
2309 NULL);
2310 Status = ZwCreateKey(&ScsiKey,
2311 KEY_ALL_ACCESS,
2312 &ObjectAttributes,
2313 0,
2314 NULL,
2315 REG_OPTION_VOLATILE,
2316 &Disposition);
2317 if (!NT_SUCCESS(Status))
2318 {
2319 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2320 return(Status);
2321 }
2322
2323 /* Create new 'Scsi Port X' subkey */
2324 DPRINT("Scsi Port %lu\n",
2325 DeviceExtension->PortNumber);
2326
2327 swprintf(NameBuffer,
2328 L"Scsi Port %lu",
2329 DeviceExtension->PortNumber);
2330 RtlInitUnicodeString(&KeyName,
2331 NameBuffer);
2332 InitializeObjectAttributes(&ObjectAttributes,
2333 &KeyName,
2334 0,
2335 ScsiKey,
2336 NULL);
2337 Status = ZwCreateKey(&ScsiPortKey,
2338 KEY_ALL_ACCESS,
2339 &ObjectAttributes,
2340 0,
2341 NULL,
2342 REG_OPTION_VOLATILE,
2343 &Disposition);
2344 ZwClose(ScsiKey);
2345 if (!NT_SUCCESS(Status))
2346 {
2347 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2348 return(Status);
2349 }
2350
2351 /*
2352 * Create port-specific values
2353 */
2354
2355 /* Set 'DMA Enabled' (REG_DWORD) value */
2356 UlongData = (ULONG)!DeviceExtension->PortCapabilities->AdapterUsesPio;
2357 DPRINT(" DMA Enabled = %s\n", (UlongData) ? "TRUE" : "FALSE");
2358 RtlInitUnicodeString(&ValueName,
2359 L"DMA Enabled");
2360 Status = ZwSetValueKey(ScsiPortKey,
2361 &ValueName,
2362 0,
2363 REG_DWORD,
2364 &UlongData,
2365 sizeof(ULONG));
2366 if (!NT_SUCCESS(Status))
2367 {
2368 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status);
2369 ZwClose(ScsiPortKey);
2370 return(Status);
2371 }
2372
2373 /* Set 'Driver' (REG_SZ) value */
2374 DriverName = wcsrchr(RegistryPath->Buffer, L'\\') + 1;
2375 RtlInitUnicodeString(&ValueName,
2376 L"Driver");
2377 Status = ZwSetValueKey(ScsiPortKey,
2378 &ValueName,
2379 0,
2380 REG_SZ,
2381 DriverName,
2382 (wcslen(DriverName) + 1) * sizeof(WCHAR));
2383 if (!NT_SUCCESS(Status))
2384 {
2385 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
2386 ZwClose(ScsiPortKey);
2387 return(Status);
2388 }
2389
2390 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
2391 UlongData = (ULONG)DeviceExtension->PortConfig->BusInterruptLevel;
2392 DPRINT(" Interrupt = %lu\n", UlongData);
2393 RtlInitUnicodeString(&ValueName,
2394 L"Interrupt");
2395 Status = ZwSetValueKey(ScsiPortKey,
2396 &ValueName,
2397 0,
2398 REG_DWORD,
2399 &UlongData,
2400 sizeof(ULONG));
2401 if (!NT_SUCCESS(Status))
2402 {
2403 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status);
2404 ZwClose(ScsiPortKey);
2405 return(Status);
2406 }
2407
2408 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
2409 UlongData = ScsiPortConvertPhysicalAddressToUlong(DeviceExtension->PortConfig->AccessRanges[0].RangeStart);
2410 DPRINT(" IOAddress = %lx\n", UlongData);
2411 RtlInitUnicodeString(&ValueName,
2412 L"IOAddress");
2413 Status = ZwSetValueKey(ScsiPortKey,
2414 &ValueName,
2415 0,
2416 REG_DWORD,
2417 &UlongData,
2418 sizeof(ULONG));
2419 if (!NT_SUCCESS(Status))
2420 {
2421 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status);
2422 ZwClose(ScsiPortKey);
2423 return(Status);
2424 }
2425
2426 /* Enumerate buses */
2427 for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
2428 {
2429 /* Create 'Scsi Bus X' key */
2430 DPRINT(" Scsi Bus %lu\n", BusNumber);
2431 swprintf(NameBuffer,
2432 L"Scsi Bus %lu",
2433 BusNumber);
2434 RtlInitUnicodeString(&KeyName,
2435 NameBuffer);
2436 InitializeObjectAttributes(&ObjectAttributes,
2437 &KeyName,
2438 0,
2439 ScsiPortKey,
2440 NULL);
2441 Status = ZwCreateKey(&ScsiBusKey,
2442 KEY_ALL_ACCESS,
2443 &ObjectAttributes,
2444 0,
2445 NULL,
2446 REG_OPTION_VOLATILE,
2447 &Disposition);
2448 if (!NT_SUCCESS(Status))
2449 {
2450 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2451 goto ByeBye;
2452 }
2453
2454 /* Create 'Initiator Id X' key */
2455 DPRINT(" Initiator Id %u\n",
2456 DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
2457 swprintf(NameBuffer,
2458 L"Initiator Id %u",
2459 (unsigned int)(UCHAR)DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
2460 RtlInitUnicodeString(&KeyName,
2461 NameBuffer);
2462 InitializeObjectAttributes(&ObjectAttributes,
2463 &KeyName,
2464 0,
2465 ScsiBusKey,
2466 NULL);
2467 Status = ZwCreateKey(&ScsiInitiatorKey,
2468 KEY_ALL_ACCESS,
2469 &ObjectAttributes,
2470 0,
2471 NULL,
2472 REG_OPTION_VOLATILE,
2473 &Disposition);
2474 if (!NT_SUCCESS(Status))
2475 {
2476 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2477 goto ByeBye;
2478 }
2479
2480 /* FIXME: Are there any initiator values (??) */
2481
2482 ZwClose(ScsiInitiatorKey);
2483 ScsiInitiatorKey = NULL;
2484
2485
2486 /* Enumerate targets */
2487 CurrentTarget = (ULONG)-1;
2488 ScsiTargetKey = NULL;
2489 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
2490 {
2491 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
2492 {
2493 LunExtension = SpiGetLunExtension(DeviceExtension,
2494 BusNumber,
2495 Target,
2496 Lun);
2497 if (LunExtension != NULL)
2498 {
2499 if (Target != CurrentTarget)
2500 {
2501 /* Close old target key */
2502 if (ScsiTargetKey != NULL)
2503 {
2504 ZwClose(ScsiTargetKey);
2505 ScsiTargetKey = NULL;
2506 }
2507
2508 /* Create 'Target Id X' key */
2509 DPRINT(" Target Id %lu\n", Target);
2510 swprintf(NameBuffer,
2511 L"Target Id %lu",
2512 Target);
2513 RtlInitUnicodeString(&KeyName,
2514 NameBuffer);
2515 InitializeObjectAttributes(&ObjectAttributes,
2516 &KeyName,
2517 0,
2518 ScsiBusKey,
2519 NULL);
2520 Status = ZwCreateKey(&ScsiTargetKey,
2521 KEY_ALL_ACCESS,
2522 &ObjectAttributes,
2523 0,
2524 NULL,
2525 REG_OPTION_VOLATILE,
2526 &Disposition);
2527 if (!NT_SUCCESS(Status))
2528 {
2529 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2530 goto ByeBye;
2531 }
2532
2533 CurrentTarget = Target;
2534 }
2535
2536 /* Create 'Logical Unit Id X' key */
2537 DPRINT(" Logical Unit Id %lu\n", Lun);
2538 swprintf(NameBuffer,
2539 L"Logical Unit Id %lu",
2540 Lun);
2541 RtlInitUnicodeString(&KeyName,
2542 NameBuffer);
2543 InitializeObjectAttributes(&ObjectAttributes,
2544 &KeyName,
2545 0,
2546 ScsiTargetKey,
2547 NULL);
2548 Status = ZwCreateKey(&ScsiLunKey,
2549 KEY_ALL_ACCESS,
2550 &ObjectAttributes,
2551 0,
2552 NULL,
2553 REG_OPTION_VOLATILE,
2554 &Disposition);
2555 if (!NT_SUCCESS(Status))
2556 {
2557 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2558 goto ByeBye;
2559 }
2560
2561 /* Set 'Identifier' (REG_SZ) value */
2562 swprintf(NameBuffer,
2563 L"%.8S%.16S%.4S",
2564 LunExtension->InquiryData.VendorId,
2565 LunExtension->InquiryData.ProductId,
2566 LunExtension->InquiryData.ProductRevisionLevel);
2567 DPRINT(" Identifier = '%S'\n", NameBuffer);
2568 RtlInitUnicodeString(&ValueName,
2569 L"Identifier");
2570 Status = ZwSetValueKey(ScsiLunKey,
2571 &ValueName,
2572 0,
2573 REG_SZ,
2574 NameBuffer,
2575 (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
2576 if (!NT_SUCCESS(Status))
2577 {
2578 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
2579 goto ByeBye;
2580 }
2581
2582 /* Set 'Type' (REG_SZ) value */
2583 switch (LunExtension->InquiryData.DeviceType)
2584 {
2585 case 0:
2586 TypeName = L"DiskPeripheral";
2587 break;
2588 case 1:
2589 TypeName = L"TapePeripheral";
2590 break;
2591 case 2:
2592 TypeName = L"PrinterPeripheral";
2593 break;
2594 case 4:
2595 TypeName = L"WormPeripheral";
2596 break;
2597 case 5:
2598 TypeName = L"CdRomPeripheral";
2599 break;
2600 case 6:
2601 TypeName = L"ScannerPeripheral";
2602 break;
2603 case 7:
2604 TypeName = L"OpticalDiskPeripheral";
2605 break;
2606 case 8:
2607 TypeName = L"MediumChangerPeripheral";
2608 break;
2609 case 9:
2610 TypeName = L"CommunicationPeripheral";
2611 break;
2612 default:
2613 TypeName = L"OtherPeripheral";
2614 break;
2615 }
2616 DPRINT(" Type = '%S'\n", TypeName);
2617 RtlInitUnicodeString(&ValueName,
2618 L"Type");
2619 Status = ZwSetValueKey(ScsiLunKey,
2620 &ValueName,
2621 0,
2622 REG_SZ,
2623 TypeName,
2624 (wcslen(TypeName) + 1) * sizeof(WCHAR));
2625 if (!NT_SUCCESS(Status))
2626 {
2627 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
2628 goto ByeBye;
2629 }
2630
2631 ZwClose(ScsiLunKey);
2632 ScsiLunKey = NULL;
2633 }
2634 }
2635
2636 /* Close old target key */
2637 if (ScsiTargetKey != NULL)
2638 {
2639 ZwClose(ScsiTargetKey);
2640 ScsiTargetKey = NULL;
2641 }
2642 }
2643
2644 ZwClose(ScsiBusKey);
2645 ScsiBusKey = NULL;
2646 }
2647
2648 ByeBye:
2649 if (ScsiLunKey != NULL)
2650 ZwClose (ScsiLunKey);
2651
2652 if (ScsiInitiatorKey != NULL)
2653 ZwClose (ScsiInitiatorKey);
2654
2655 if (ScsiTargetKey != NULL)
2656 ZwClose (ScsiTargetKey);
2657
2658 if (ScsiBusKey != NULL)
2659 ZwClose (ScsiBusKey);
2660
2661 if (ScsiPortKey != NULL)
2662 ZwClose (ScsiPortKey);
2663
2664 DPRINT("SpiBuildDeviceMap() done\n");
2665
2666 return Status;
2667 }
2668
2669 /* EOF */