ReactOS 0.4.15-dev-7842-g558ab78
fdo.c File Reference
#include "scsiport.h"
#include <debug.h>
Include dependency graph for fdo.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static NTSTATUS FdoSendInquiry (_In_ PDEVICE_OBJECT DeviceObject)
 
VOID FdoScanAdapter (_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension)
 
NTSTATUS FdoCallHWInitialize (_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 Calls HwInitialize routine of the miniport and sets up interrupts Should be called inside ScsiPortInitialize (for legacy drivers) or inside IRP_MN_START_DEVICE for pnp drivers.
 
NTSTATUS FdoRemoveAdapter (_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
 
NTSTATUS FdoStartAdapter (_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension)
 
static NTSTATUS FdoHandleDeviceRelations (_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension, _Inout_ PIRP Irp)
 
static NTSTATUS FdoHandleQueryCompatibleId (_Inout_ PZZWSTR *PwIds)
 
NTSTATUS FdoDispatchPnp (_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 12 of file fdo.c.

Function Documentation

◆ FdoCallHWInitialize()

NTSTATUS FdoCallHWInitialize ( _In_ PSCSI_PORT_DEVICE_EXTENSION  DeviceExtension)

Calls HwInitialize routine of the miniport and sets up interrupts Should be called inside ScsiPortInitialize (for legacy drivers) or inside IRP_MN_START_DEVICE for pnp drivers.

Parameters
[in]DeviceExtensionThe device extension
Returns
NTSTATUS of the operation

Definition at line 366 of file fdo.c.

368{
369 PPORT_CONFIGURATION_INFORMATION PortConfig = DeviceExtension->PortConfig;
372
373 /* Deal with interrupts */
374 if (DeviceExtension->HwInterrupt == NULL ||
375 (PortConfig->BusInterruptLevel == 0 && PortConfig->BusInterruptVector == 0))
376 {
377 /* No interrupts */
378 DeviceExtension->InterruptCount = 0;
379
380 DPRINT1("Interrupt Count: 0\n");
381
383
384 /* This code path will ALWAYS crash so stop it now */
385 __debugbreak();
386 }
387 else
388 {
389 BOOLEAN InterruptShareable;
391 ULONG InterruptVector[2], i, MappedIrq[2];
392 KIRQL Dirql[2], MaxDirql;
394
395 DeviceExtension->InterruptLevel[0] = PortConfig->BusInterruptLevel;
396 DeviceExtension->InterruptLevel[1] = PortConfig->BusInterruptLevel2;
397
398 InterruptVector[0] = PortConfig->BusInterruptVector;
399 InterruptVector[1] = PortConfig->BusInterruptVector2;
400
401 InterruptMode[0] = PortConfig->InterruptMode;
402 InterruptMode[1] = PortConfig->InterruptMode2;
403
404 DeviceExtension->InterruptCount =
405 (PortConfig->BusInterruptLevel2 != 0 ||
406 PortConfig->BusInterruptVector2 != 0) ? 2 : 1;
407
408 for (i = 0; i < DeviceExtension->InterruptCount; i++)
409 {
410 /* Register an interrupt handler for this device */
411 MappedIrq[i] = HalGetInterruptVector(
412 PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber,
413 DeviceExtension->InterruptLevel[i], InterruptVector[i], &Dirql[i],
414 &Affinity[i]);
415 }
416
417 if (DeviceExtension->InterruptCount == 1 || Dirql[0] > Dirql[1])
418 {
419 MaxDirql = Dirql[0];
420 }
421 else
422 {
423 MaxDirql = Dirql[1];
424 }
425
426 for (i = 0; i < DeviceExtension->InterruptCount; i++)
427 {
428 /* Determine IRQ sharability as usual */
429 if (PortConfig->AdapterInterfaceType == MicroChannel ||
431 {
432 InterruptShareable = TRUE;
433 }
434 else
435 {
436 InterruptShareable = FALSE;
437 }
438
439 Status = IoConnectInterrupt(&DeviceExtension->Interrupt[i],
441 DeviceExtension,
442 &DeviceExtension->IrqLock,
443 MappedIrq[i], Dirql[i],
444 MaxDirql,
446 InterruptShareable,
447 Affinity[i],
448 FALSE);
449
450 if (!(NT_SUCCESS(Status)))
451 {
452 DPRINT1("Could not connect interrupt %d\n", InterruptVector[i]);
453 DeviceExtension->Interrupt[i] = NULL;
454 return Status;
455 }
456 }
457 }
458
459 /* Save IoAddress (from access ranges) */
460 if (PortConfig->NumberOfAccessRanges != 0)
461 {
462 DeviceExtension->IoAddress = ((*(PortConfig->AccessRanges))[0]).RangeStart.LowPart;
463
464 DPRINT("Io Address %x\n", DeviceExtension->IoAddress);
465 }
466
467 /* Set flag that it's allowed to disconnect during this command */
468 DeviceExtension->Flags |= SCSI_PORT_DISCONNECT_ALLOWED;
469
470 /* Initialize counter of active requests (-1 means there are none) */
471 DeviceExtension->ActiveRequestCounter = -1;
472
473 /* Analyze what we have about DMA */
474 if (DeviceExtension->AdapterObject != NULL && PortConfig->Master &&
475 PortConfig->NeedPhysicalAddresses)
476 {
477 DeviceExtension->MapRegisters = TRUE;
478 }
479 else
480 {
481 DeviceExtension->MapRegisters = FALSE;
482 }
483
484 /* Call HwInitialize at DISPATCH_LEVEL */
486
488 DeviceExtension->Interrupt[0], DeviceExtension->HwInitialize,
489 DeviceExtension->MiniPortDeviceExtension))
490 {
491 DPRINT1("HwInitialize() failed!\n");
494 }
495
496 /* Check if a notification is needed */
497 if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
498 {
499 /* Call DPC right away, because we're already at DISPATCH_LEVEL */
500 ScsiPortDpcForIsr(NULL, DeviceExtension->Common.DeviceObject, NULL, NULL);
501 }
502
503 /* Lower irql back to what it was */
505
506 return STATUS_SUCCESS;
507}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define UNIMPLEMENTED
Definition: debug.h:115
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ULONG_PTR KAFFINITY
Definition: compat.h:85
NTHALAPI ULONG NTAPI HalGetInterruptVector(INTERFACE_TYPE, ULONG, ULONG, ULONG, PKIRQL, PKAFFINITY)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
@ MicroChannel
Definition: hwresource.cpp:140
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
NTSTATUS NTAPI IoConnectInterrupt(OUT PKINTERRUPT *InterruptObject, IN PKSERVICE_ROUTINE ServiceRoutine, IN PVOID ServiceContext, IN PKSPIN_LOCK SpinLock, IN ULONG Vector, IN KIRQL Irql, IN KIRQL SynchronizeIrql, IN KINTERRUPT_MODE InterruptMode, IN BOOLEAN ShareVector, IN KAFFINITY ProcessorEnableMask, IN BOOLEAN FloatingSave)
Definition: irq.c:22
BOOLEAN NTAPI KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt, IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine, IN PVOID SynchronizeContext OPTIONAL)
Definition: interrupt.c:237
#define STATUS_ADAPTER_HARDWARE_ERROR
Definition: ntstatus.h:430
#define SCSI_PORT_DISCONNECT_ALLOWED
Definition: scsiport.h:39
#define SCSI_PORT_NOTIFICATION_NEEDED
Definition: scsiport.h:31
KSERVICE_ROUTINE ScsiPortIsr
Definition: scsiport.h:459
IO_DPC_ROUTINE ScsiPortDpcForIsr
Definition: scsiport.h:451
@ LevelSensitive
Definition: miniport.h:80
enum _KINTERRUPT_MODE KINTERRUPT_MODE
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
ACCESS_RANGE(* AccessRanges)[]
Definition: srb.h:74
KINTERRUPT_MODE InterruptMode
Definition: srb.h:64
INTERFACE_TYPE AdapterInterfaceType
Definition: srb.h:59
KINTERRUPT_MODE InterruptMode2
Definition: srb.h:101
uint32_t ULONG
Definition: typedefs.h:59
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:174
_In_ PKSERVICE_ROUTINE _In_opt_ PVOID _In_opt_ PKSPIN_LOCK _In_ ULONG _In_ KIRQL _In_ KIRQL _In_ KINTERRUPT_MODE InterruptMode
Definition: iofuncs.h:806
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by ScsiPortInitialize().

◆ FdoDispatchPnp()

NTSTATUS FdoDispatchPnp ( _In_ PDEVICE_OBJECT  DeviceObject,
_Inout_ PIRP  Irp 
)

Definition at line 758 of file fdo.c.

761{
763 PSCSI_PORT_DEVICE_EXTENSION portExt = DeviceObject->DeviceExtension;
765
766 ASSERT(portExt->Common.IsFDO);
767
768 DPRINT("FDO PnP request %s\n", GetIRPMinorFunctionString(ioStack->MinorFunction));
769
770 switch (ioStack->MinorFunction)
771 {
773 {
774 // as we don't support PnP yet, this is a no-op for us
775 // (FdoStartAdapter is being called during initialization for legacy miniports)
777 // status = FdoStartAdapter(DeviceExtension);
778 break;
779 }
781 {
782 return FdoHandleDeviceRelations(portExt, Irp);
783 }
784 case IRP_MN_QUERY_ID:
785 {
786 if (ioStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
787 {
788 Irp->IoStatus.Information = 0;
789 IoForwardIrpSynchronously(portExt->Common.LowerDevice, Irp);
790 status = FdoHandleQueryCompatibleId((PZZWSTR*)&Irp->IoStatus.Information);
791 break;
792 }
793 // otherwise fall through the default case
794 }
795 default:
796 {
797 // forward irp to next device object
799 return IoCallDriver(portExt->Common.LowerDevice, Irp);
800 }
801 }
802
803 if (status != STATUS_PENDING)
804 {
805 Irp->IoStatus.Status = status;
807 }
808
809 return status;
810}
_In_ PIRP Irp
Definition: csq.h:116
FORCEINLINE PCHAR GetIRPMinorFunctionString(UCHAR MinorFunction)
Definition: driverdbg.h:13
#define ASSERT(a)
Definition: mode.c:44
_NullNull_terminated_ WCHAR * PZZWSTR
Definition: ntbasedef.h:420
#define IoCopyCurrentIrpStackLocationToNext(Irp)
Definition: ntifs_ex.h:413
#define IoCompleteRequest
Definition: irp.c:1240
BOOLEAN NTAPI IoForwardIrpSynchronously(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1625
#define IoCallDriver
Definition: irp.c:1225
#define STATUS_PENDING
Definition: ntstatus.h:82
static NTSTATUS FdoHandleDeviceRelations(_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension, _Inout_ PIRP Irp)
Definition: fdo.c:655
static NTSTATUS FdoHandleQueryCompatibleId(_Inout_ PZZWSTR *PwIds)
Definition: fdo.c:714
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:3128
Definition: ps.c:97
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2793
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MN_START_DEVICE
#define IRP_MN_QUERY_ID
#define IRP_MN_QUERY_DEVICE_RELATIONS
@ BusQueryCompatibleIDs
Definition: iotypes.h:2938

Referenced by ScsiPortDispatchPnp().

◆ FdoHandleDeviceRelations()

static NTSTATUS FdoHandleDeviceRelations ( _In_ PSCSI_PORT_DEVICE_EXTENSION  PortExtension,
_Inout_ PIRP  Irp 
)
static

Definition at line 655 of file fdo.c.

658{
660
661 // FDO always only handles bus relations
662 if (ioStack->Parameters.QueryDeviceRelations.Type == BusRelations)
663 {
664 FdoScanAdapter(PortExtension);
665 DPRINT("Found %u PD objects, FDOExt: %p\n", PortExtension->TotalLUCount, PortExtension);
666
667 // check that no filter driver has messed up this
668 ASSERT(Irp->IoStatus.Information == 0);
669
670 PDEVICE_RELATIONS deviceRelations =
672 (sizeof(DEVICE_RELATIONS) +
673 sizeof(PDEVICE_OBJECT) * (PortExtension->TotalLUCount - 1)),
675
676 if (!deviceRelations)
677 {
678 Irp->IoStatus.Information = 0;
679 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
682 }
683
684 deviceRelations->Count = 0;
685
686 for (UINT8 pathId = 0; pathId < PortExtension->NumberOfBuses; pathId++)
687 {
688 PSCSI_BUS_INFO bus = &PortExtension->Buses[pathId];
689
690 for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
691 lunEntry != &bus->LunsListHead;
692 lunEntry = lunEntry->Flink)
693 {
695 CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
696
697 deviceRelations->Objects[deviceRelations->Count++] = lunExt->Common.DeviceObject;
699 }
700 }
701
702 ASSERT(deviceRelations->Count == PortExtension->TotalLUCount);
703
704 Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
705 Irp->IoStatus.Status = STATUS_SUCCESS;
706 }
707
709 return IoCallDriver(PortExtension->Common.LowerDevice, Irp);
710}
unsigned char UINT8
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define TAG_SCSIPORT
Definition: scsiport.h:21
VOID FdoScanAdapter(_In_ PSCSI_PORT_DEVICE_EXTENSION PortExtension)
Definition: fdo.c:222
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY LunsListHead
Definition: scsiport.h:187
PDEVICE_OBJECT DeviceObject
Definition: scsiport.h:138
SCSI_PORT_COMMON_EXTENSION Common
Definition: scsiport.h:146
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
@ BusRelations
Definition: iotypes.h:2152
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by FdoDispatchPnp().

◆ FdoHandleQueryCompatibleId()

static NTSTATUS FdoHandleQueryCompatibleId ( _Inout_ PZZWSTR PwIds)
static

Definition at line 714 of file fdo.c.

716{
717 static WCHAR GenScsiAdapterId[] = L"GEN_SCSIADAPTER";
718 PWCHAR Ids = *PwIds, NewIds;
719 ULONG Length = 0;
720
721 if (Ids)
722 {
723 /* Calculate the length of existing MULTI_SZ value line by line */
724 while (*Ids)
725 {
726 Ids += wcslen(Ids) + 1;
727 }
728 Length = Ids - *PwIds;
729 Ids = *PwIds;
730 }
731
732 /* New MULTI_SZ with added identifier and finalizing zeros */
733 NewIds = ExAllocatePoolZero(PagedPool,
734 Length * sizeof(WCHAR) + sizeof(GenScsiAdapterId) + sizeof(UNICODE_NULL),
736 if (!NewIds)
737 {
739 }
740
741 if (Length)
742 {
743 RtlCopyMemory(NewIds, Ids, Length * sizeof(WCHAR));
744 }
745 RtlCopyMemory(&NewIds[Length], GenScsiAdapterId, sizeof(GenScsiAdapterId));
746
747 /* Finally replace identifiers */
748 if (Ids)
749 {
750 ExFreePool(Ids);
751 }
752 *PwIds = NewIds;
753
754 return STATUS_SUCCESS;
755}
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint16_t * PWCHAR
Definition: typedefs.h:56
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by FdoDispatchPnp().

◆ FdoRemoveAdapter()

NTSTATUS FdoRemoveAdapter ( _In_ PSCSI_PORT_DEVICE_EXTENSION  DeviceExtension)

Definition at line 510 of file fdo.c.

512{
513 IoStopTimer(DeviceExtension->Common.DeviceObject);
514
515 // release device interface
516 if (DeviceExtension->InterfaceName.Buffer)
517 {
518 IoSetDeviceInterfaceState(&DeviceExtension->InterfaceName, FALSE);
519
520 RtlFreeUnicodeString(&DeviceExtension->InterfaceName);
521 RtlInitUnicodeString(&DeviceExtension->InterfaceName, NULL);
522 }
523
524 // remove the dos device link
525 WCHAR dosNameBuffer[12];
526 UNICODE_STRING dosDeviceName;
527
528 swprintf(dosNameBuffer, L"\\??\\Scsi%lu:", DeviceExtension->PortNumber);
529 RtlInitUnicodeString(&dosDeviceName, dosNameBuffer);
530
531 IoDeleteSymbolicLink(&dosDeviceName); // don't check the result
532
533 // decrease the port count
534 if (DeviceExtension->DeviceStarted)
535 {
537 sysConfig->ScsiPortCount--;
538 }
539
540 // disconnect the interrupts
541 while (DeviceExtension->InterruptCount)
542 {
543 if (DeviceExtension->Interrupt[--DeviceExtension->InterruptCount])
544 IoDisconnectInterrupt(DeviceExtension->Interrupt[DeviceExtension->InterruptCount]);
545 }
546
547 // FIXME: delete LUNs
548 if (DeviceExtension->Buses)
549 {
550 for (UINT8 pathId = 0; pathId < DeviceExtension->NumberOfBuses; pathId++)
551 {
552 PSCSI_BUS_INFO bus = &DeviceExtension->Buses[pathId];
553 if (bus->RegistryMapKey)
554 {
555 ZwDeleteKey(bus->RegistryMapKey);
557 bus->RegistryMapKey = NULL;
558 }
559 }
560
561 ExFreePoolWithTag(DeviceExtension->Buses, TAG_SCSIPORT);
562 }
563
564 /* Free PortConfig */
565 if (DeviceExtension->PortConfig)
566 {
567 ExFreePoolWithTag(DeviceExtension->PortConfig, TAG_SCSIPORT);
568 }
569
570 /* Free common buffer (if it exists) */
571 if (DeviceExtension->SrbExtensionBuffer != NULL && DeviceExtension->CommonBufferLength != 0)
572 {
573 if (!DeviceExtension->AdapterObject)
574 {
575 ExFreePoolWithTag(DeviceExtension->SrbExtensionBuffer, TAG_SCSIPORT);
576 }
577 else
578 {
579 HalFreeCommonBuffer(DeviceExtension->AdapterObject,
580 DeviceExtension->CommonBufferLength,
581 DeviceExtension->PhysicalAddress,
582 DeviceExtension->SrbExtensionBuffer,
583 FALSE);
584 }
585 }
586
587 /* Free SRB info */
588 if (DeviceExtension->SrbInfo != NULL)
589 ExFreePoolWithTag(DeviceExtension->SrbInfo, TAG_SCSIPORT);
590
591 /* Unmap mapped addresses */
592 while (DeviceExtension->MappedAddressList != NULL)
593 {
594 MmUnmapIoSpace(DeviceExtension->MappedAddressList->MappedAddress,
595 DeviceExtension->MappedAddressList->NumberOfBytes);
596
597 PVOID ptr = DeviceExtension->MappedAddressList;
598 DeviceExtension->MappedAddressList = DeviceExtension->MappedAddressList->NextMappedAddress;
599
601 }
602
603 IoDeleteDevice(DeviceExtension->Common.DeviceObject);
604
605 return STATUS_SUCCESS;
606}
#define swprintf
Definition: precomp.h:40
VOID NTAPI HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject, IN ULONG Length, IN PHYSICAL_ADDRESS LogicalAddress, IN PVOID VirtualAddress, IN BOOLEAN CacheEnabled)
Definition: dma.c:61
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
VOID NTAPI MmUnmapIoSpace(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes)
Definition: iosup.c:193
VOID NTAPI IoStopTimer(PDEVICE_OBJECT DeviceObject)
Definition: iotimer.c:166
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PVOID ptr
Definition: dispmode.c:27
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
NTSTATUS NTAPI IoSetDeviceInterfaceState(IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
Definition: deviface.c:1311
VOID NTAPI IoDisconnectInterrupt(PKINTERRUPT InterruptObject)
Definition: irq.c:141
HANDLE RegistryMapKey
Definition: scsiport.h:191

Referenced by ScsiPortInitialize().

◆ FdoScanAdapter()

VOID FdoScanAdapter ( _In_ PSCSI_PORT_DEVICE_EXTENSION  PortExtension)

Definition at line 222 of file fdo.c.

224{
226 UINT32 totalLUNs = PortExtension->TotalLUCount;
227
228 DPRINT("FdoScanAdapter() called\n");
229
230 /* Scan all buses */
231 for (UINT8 pathId = 0; pathId < PortExtension->NumberOfBuses; pathId++)
232 {
233 DPRINT(" Scanning bus/pathID %u\n", pathId);
234
235 /* Get pointer to the scan information */
236 PSCSI_BUS_INFO currentBus = &PortExtension->Buses[pathId];
237
238 /* And send INQUIRY to every target */
239 for (UINT8 targetId = 0;
240 targetId < PortExtension->PortConfig->MaximumNumberOfTargets;
241 targetId++)
242 {
243 BOOLEAN targetFound = FALSE;
244
245 /* TODO: Support scan bottom-up */
246
247 /* Skip if it's the same address */
248 if (targetId == currentBus->BusIdentifier)
249 continue;
250
251 /* Scan all logical units */
252 for (UINT8 lun = 0; lun < PortExtension->MaxLunCount; lun++)
253 {
255
256 /* Skip invalid lun values */
257 if (lun >= PortExtension->PortConfig->MaximumNumberOfLogicalUnits)
258 continue;
259
260 // try to find an existing device
261 lunExt = GetLunByPath(PortExtension,
262 pathId,
263 targetId,
264 lun);
265
266 if (lunExt)
267 {
268 // check if the device still exists
270 if (!NT_SUCCESS(status))
271 {
272 // remove the device
274 __debugbreak();
275 }
276
278 {
279 // remove the device
281 __debugbreak();
282 }
283
284 /* Decide whether we are continuing or not */
286 continue;
287 else
288 break;
289 }
290
291 // create a new LUN device
292 PDEVICE_OBJECT lunPDO = PdoCreateLunDevice(PortExtension);
293 if (!lunPDO)
294 {
295 continue;
296 }
297
298 lunExt = lunPDO->DeviceExtension;
299
300 lunExt->PathId = pathId;
301 lunExt->TargetId = targetId;
302 lunExt->Lun = lun;
303
304 DPRINT("Add PDO to list: PDO: %p, FDOExt: %p, PDOExt: %p\n", lunPDO, PortExtension, lunExt);
305
306 /* Set flag to prevent race conditions */
308
309 /* Finally send the inquiry command */
310 status = FdoSendInquiry(lunPDO);
311
312 if (NT_SUCCESS(status))
313 {
314 /* Let's see if we really found a device */
315 PINQUIRYDATA InquiryData = &lunExt->InquiryData;
316
317 /* Check if this device is unsupported */
319 {
320 IoDeleteDevice(lunPDO);
321 continue;
322 }
323
324 /* Clear the "in scan" flag */
325 lunExt->Flags &= ~SCSI_PORT_SCAN_IN_PROGRESS;
326
327 DPRINT1("Found device of type %d at controller %d bus %d tid %d lun %d, PDO: %p\n",
328 InquiryData->DeviceType, PortExtension->PortNumber, pathId, targetId, lun, lunPDO);
329
330 InsertTailList(&currentBus->LunsListHead, &lunExt->LunEntry);
331
332 totalLUNs++;
333 currentBus->LogicalUnitsCount++;
334 targetFound = TRUE;
335 }
336 else
337 {
338 /* Decide whether we are continuing or not */
340 continue;
341 else
342 break;
343 }
344 }
345
346 if (targetFound)
347 {
348 currentBus->TargetsCount++;
349 }
350 }
351 }
352
353 PortExtension->TotalLUCount = totalLUNs;
354}
unsigned int UINT32
#define DEVICE_QUALIFIER_NOT_SUPPORTED
Definition: cdrw_hw.h:1155
#define InsertTailList(ListHead, Entry)
#define SCSI_PORT_SCAN_IN_PROGRESS
Definition: scsiport.h:51
static NTSTATUS FdoSendInquiry(_In_ PDEVICE_OBJECT DeviceObject)
Definition: fdo.c:18
PDEVICE_OBJECT PdoCreateLunDevice(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
Definition: pdo.c:18
PSCSI_PORT_LUN_EXTENSION GetLunByPath(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _In_ UCHAR PathId, _In_ UCHAR TargetId, _In_ UCHAR Lun)
Definition: pdo.c:68
PVOID DeviceExtension
Definition: env_spec_w32.h:418
UCHAR DeviceType
Definition: cdrw_hw.h:1116
UCHAR DeviceTypeQualifier
Definition: cdrw_hw.h:1117
UCHAR BusIdentifier
Definition: scsiport.h:190
UCHAR TargetsCount
Definition: scsiport.h:189
UCHAR LogicalUnitsCount
Definition: scsiport.h:188
INQUIRYDATA InquiryData
Definition: scsiport.h:158
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138

Referenced by FdoHandleDeviceRelations(), and ScsiPortInitialize().

◆ FdoSendInquiry()

static NTSTATUS FdoSendInquiry ( _In_ PDEVICE_OBJECT  DeviceObject)
static

Definition at line 18 of file fdo.c.

20{
22 PIO_STACK_LOCATION IrpStack;
24 KIRQL Irql;
25 PIRP Irp;
27 PINQUIRYDATA InquiryBuffer;
28 PSENSE_DATA SenseBuffer;
29 BOOLEAN KeepTrying = TRUE;
30 ULONG RetryCount = 0;
32 PCDB Cdb;
33
34 DPRINT("FdoSendInquiry() called\n");
35
36 PSCSI_PORT_LUN_EXTENSION LunExtension = DeviceObject->DeviceExtension;
37 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension =
38 LunExtension->Common.LowerDevice->DeviceExtension;
39
41 if (InquiryBuffer == NULL)
43
45 if (SenseBuffer == NULL)
46 {
47 ExFreePoolWithTag(InquiryBuffer, TAG_SCSIPORT);
49 }
50
51 while (KeepTrying)
52 {
53 /* Initialize event for waiting */
56 FALSE);
57
58 /* Create an IRP */
61 NULL,
62 0,
63 InquiryBuffer,
65 TRUE,
66 &Event,
68 if (Irp == NULL)
69 {
70 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
71
72 /* Quit the loop */
74 KeepTrying = FALSE;
75 continue;
76 }
77
78 /* Prepare SRB */
80
83 Srb.PathId = LunExtension->PathId;
84 Srb.TargetId = LunExtension->TargetId;
85 Srb.Lun = LunExtension->Lun;
88 Srb.TimeOutValue = 4;
89 Srb.CdbLength = 6;
90
91 Srb.SenseInfoBuffer = SenseBuffer;
93
94 Srb.DataBuffer = InquiryBuffer;
96
97 /* Attach Srb to the Irp */
98 IrpStack = IoGetNextIrpStackLocation (Irp);
99 IrpStack->Parameters.Scsi.Srb = &Srb;
100
101 /* Fill in CDB */
102 Cdb = (PCDB)Srb.Cdb;
103 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
104 Cdb->CDB6INQUIRY.LogicalUnitNumber = LunExtension->Lun;
105 Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
106
107 /* Call the driver */
109
110 /* Wait for it to complete */
111 if (Status == STATUS_PENDING)
112 {
113 DPRINT("FdoSendInquiry(): Waiting for the driver to process request...\n");
115 Executive,
117 FALSE,
118 NULL);
120 }
121
122 DPRINT("FdoSendInquiry(): Request processed by driver, status = 0x%08X\n", Status);
123
125 {
126 /* All fine, copy data over */
127 RtlCopyMemory(&LunExtension->InquiryData,
128 InquiryBuffer,
130
131 /* Quit the loop */
133 KeepTrying = FALSE;
134 continue;
135 }
136
137 DPRINT("Inquiry SRB failed with SrbStatus 0x%08X\n", Srb.SrbStatus);
138
139 /* Check if the queue is frozen */
141 {
142 /* Something weird happened, deal with it (unfreeze the queue) */
143 KeepTrying = FALSE;
144
145 DPRINT("FdoSendInquiry(): the queue is frozen at TargetId %d\n", Srb.TargetId);
146
147 /* Clear frozen flag */
148 LunExtension->Flags &= ~LUNEX_FROZEN_QUEUE;
149
150 /* Acquire the spinlock */
151 KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
152
153 /* Process the request. SpiGetNextRequestFromLun will unlock for us */
154 SpiGetNextRequestFromLun(DeviceExtension, LunExtension, &Irql);
155 }
156
157 /* Check if data overrun happened */
159 {
160 DPRINT("Data overrun at TargetId %d\n", LunExtension->TargetId);
161
162 /* Nothing dramatic, just copy data, but limiting the size */
163 RtlCopyMemory(&LunExtension->InquiryData,
164 InquiryBuffer,
167
168 /* Quit the loop */
170 KeepTrying = FALSE;
171 }
173 SenseBuffer->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST)
174 {
175 /* LUN is not valid, but some device responds there.
176 Mark it as invalid anyway */
177
178 /* Quit the loop */
180 KeepTrying = FALSE;
181 }
182 else
183 {
184 /* Retry a couple of times if no timeout happened */
185 if ((RetryCount < 2) &&
188 {
189 RetryCount++;
190 KeepTrying = TRUE;
191 }
192 else
193 {
194 /* That's all, quit the loop */
195 KeepTrying = FALSE;
196
197 /* Set status according to SRB status */
200 {
202 }
203 else
204 {
206 }
207 }
208 }
209 }
210
211 /* Free buffers */
212 ExFreePoolWithTag(InquiryBuffer, TAG_SCSIPORT);
213 ExFreePoolWithTag(SenseBuffer, TAG_SCSIPORT);
214
215 DPRINT("FdoSendInquiry() done with Status 0x%08X\n", Status);
216
217 return Status;
218}
_In_ PSCSI_REQUEST_BLOCK Srb
Definition: cdrom.h:989
#define IOCTL_SCSI_EXECUTE_IN
Definition: cdrw_hw.h:1451
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
#define SENSE_BUFFER_SIZE
Definition: cdrw_hw.h:1183
#define SCSI_SENSE_ILLEGAL_REQUEST
Definition: cdrw_hw.h:1192
union _CDB * PCDB
#define INQUIRYDATABUFFERSIZE
Definition: cdrw_hw.h:1113
_Out_ PKIRQL Irql
Definition: csq.h:179
struct _SCSI_REQUEST_BLOCK SCSI_REQUEST_BLOCK
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:315
#define SRB_STATUS_DATA_OVERRUN
Definition: srb.h:357
#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH
Definition: srb.h:360
#define SRB_STATUS_AUTOSENSE_VALID
Definition: srb.h:387
#define SRB_FLAGS_DATA_IN
Definition: srb.h:400
#define SRB_STATUS_SELECTION_TIMEOUT
Definition: srb.h:350
#define SRB_STATUS_BAD_FUNCTION
Definition: srb.h:364
#define SRB_FLAGS_DISABLE_SYNCH_TRANSFER
Definition: srb.h:397
#define SRB_STATUS(Status)
Definition: srb.h:389
#define SRB_STATUS_QUEUE_FROZEN
Definition: srb.h:386
#define SRB_STATUS_NO_DEVICE
Definition: srb.h:348
#define SRB_STATUS_SUCCESS
Definition: srb.h:341
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define NonPagedPool
Definition: env_spec_w32.h:307
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define KernelMode
Definition: asm.h:34
@ NotificationEvent
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
_In_opt_ WDFREQUEST _In_ ULONG _In_ BOOLEAN _In_ PCDB Cdb
Definition: scratch.h:159
VOID SpiGetNextRequestFromLun(_In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, _Inout_ PSCSI_PORT_LUN_EXTENSION LunExtension, _Inout_opt_ PKIRQL OldIrql)
Definition: scsi.c:342
PDEVICE_OBJECT LowerDevice
Definition: scsiport.h:139
ULONG TimeOutValue
Definition: srb.h:262
UCHAR TargetId
Definition: srb.h:254
PVOID OriginalRequest
Definition: srb.h:266
UCHAR SenseInfoBufferLength
Definition: srb.h:259
PVOID DataBuffer
Definition: srb.h:263
UCHAR PathId
Definition: srb.h:253
UCHAR CdbLength
Definition: srb.h:258
UCHAR Cdb[16]
Definition: srb.h:279
PVOID SenseInfoBuffer
Definition: srb.h:264
UCHAR Function
Definition: srb.h:250
ULONG DataTransferLength
Definition: srb.h:261
ULONG SrbFlags
Definition: srb.h:260
USHORT Length
Definition: srb.h:249
UCHAR SrbStatus
Definition: srb.h:251
UCHAR SenseKey
Definition: cdrw_hw.h:1167
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_IO_DEVICE_ERROR
Definition: udferr_usr.h:179
Definition: cdrw_hw.h:28
struct _CDB::_CDB6INQUIRY CDB6INQUIRY
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
@ Executive
Definition: ketypes.h:415

Referenced by FdoScanAdapter().

◆ FdoStartAdapter()

NTSTATUS FdoStartAdapter ( _In_ PSCSI_PORT_DEVICE_EXTENSION  PortExtension)

Definition at line 609 of file fdo.c.

611{
612 WCHAR dosNameBuffer[12];
613 UNICODE_STRING dosDeviceName;
615
616 // Start our timer
617 IoStartTimer(PortExtension->Common.DeviceObject);
618
619 // Create the dos device link
620 swprintf(dosNameBuffer, L"\\??\\Scsi%u:", PortExtension->PortNumber);
621 RtlInitUnicodeString(&dosDeviceName, dosNameBuffer);
622 status = IoCreateSymbolicLink(&dosDeviceName, &PortExtension->DeviceName);
623 if (!NT_SUCCESS(status))
624 {
625 return status;
626 }
627
628 // start building a device map
629 RegistryInitAdapterKey(PortExtension);
630
631 // increase the port count
633 sysConfig->ScsiPortCount++;
634
635 // Register and enable the device interface
636 status = IoRegisterDeviceInterface(PortExtension->Common.DeviceObject,
637 &StoragePortClassGuid,
638 NULL,
639 &PortExtension->InterfaceName);
640 DPRINT("IoRegisterDeviceInterface status: %x, InterfaceName: %wZ\n",
641 status, &PortExtension->InterfaceName);
642
643 if (NT_SUCCESS(status))
644 {
645 IoSetDeviceInterfaceState(&PortExtension->InterfaceName, TRUE);
646 }
647
648 PortExtension->DeviceStarted = TRUE;
649
650 return STATUS_SUCCESS;
651}
NTSTATUS RegistryInitAdapterKey(_Inout_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
Definition: registry.c:127
VOID NTAPI IoStartTimer(IN PDEVICE_OBJECT DeviceObject)
Definition: iotimer.c:133
NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
Definition: deviface.c:955

Referenced by ScsiPortInitialize().