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