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