mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 02:34:53 +00:00
[CLASSPNP]: Add Windows Server 2003 DDK ClassPNP sample, under the license and terms of the Windows Server 2003 DDK.
[CDROM]: Add Windows Server 2003 DDK Cdrom Sample, under the license and terms of the Windows Server 2003 DDK. They both build and run fine, but PCIIDE(x) must be completed/enabled, and atapi must be rewritten to be WDM-compliant. svn path=/trunk/; revision=49171
This commit is contained in:
parent
8047296236
commit
73c1c7f232
7136
reactos/drivers/storage/class/cdrom_new/cdrom.c
Normal file
7136
reactos/drivers/storage/class/cdrom_new/cdrom.c
Normal file
File diff suppressed because it is too large
Load diff
823
reactos/drivers/storage/class/cdrom_new/cdrom.h
Normal file
823
reactos/drivers/storage/class/cdrom_new/cdrom.h
Normal file
|
@ -0,0 +1,823 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
cdromp.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Private header file for cdrom.sys. This contains private
|
||||||
|
structure and function declarations as well as constant
|
||||||
|
values which do not need to be exported.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#ifndef __CDROMP_H__
|
||||||
|
#define __CDROMP_H__
|
||||||
|
|
||||||
|
#include "ntddmmc.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
extern CLASSPNP_SCAN_FOR_SPECIAL_INFO CdromHackItems[];
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CdromDebugError = 0, // always printed
|
||||||
|
CdromDebugWarning = 1, // set bit 0x00000001 in nt!kd_cdrom_mask
|
||||||
|
CdromDebugTrace = 2, // set bit 0x00000002 in nt!kd_cdrom_mask
|
||||||
|
CdromDebugInfo = 3, // set bit 0x00000004 in nt!kd_cdrom_mask
|
||||||
|
#if 0
|
||||||
|
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||||
|
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||||
|
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||||
|
CdromDebug = z, // set bit 0x00000000 in nt!kd_cdrom_mask
|
||||||
|
#endif
|
||||||
|
CdromDebugFeatures = 32 // set bit 0x80000000 in nt!kd_cdrom_mask
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CDROM_GET_CONFIGURATION_TIMEOUT (0x4)
|
||||||
|
|
||||||
|
#define CDROM_HACK_DEC_RRD (0x00000001)
|
||||||
|
#define CDROM_HACK_FUJITSU_FMCD_10x (0x00000002)
|
||||||
|
#define CDROM_HACK_HITACHI_1750 (0x00000004)
|
||||||
|
#define CDROM_HACK_HITACHI_GD_2000 (0x00000008)
|
||||||
|
#define CDROM_HACK_TOSHIBA_SD_W1101 (0x00000010)
|
||||||
|
#define CDROM_HACK_TOSHIBA_XM_3xx (0x00000020)
|
||||||
|
#define CDROM_HACK_NEC_CDDA (0x00000040)
|
||||||
|
#define CDROM_HACK_PLEXTOR_CDDA (0x00000080)
|
||||||
|
#define CDROM_HACK_BAD_GET_CONFIG_SUPPORT (0x00000100)
|
||||||
|
#define CDROM_HACK_FORCE_READ_CD_DETECTION (0x00000200)
|
||||||
|
#define CDROM_HACK_READ_CD_SUPPORTED (0x00000400)
|
||||||
|
#define CDROM_HACK_LOCKED_PAGES (0x80000000) // not a valid flag to save
|
||||||
|
|
||||||
|
#define CDROM_HACK_VALID_FLAGS (0x000007ff)
|
||||||
|
#define CDROM_HACK_INVALID_FLAGS (~CDROM_HACK_VALID_FLAGS)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _XA_CONTEXT {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer to the device object.
|
||||||
|
//
|
||||||
|
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer to the original request when
|
||||||
|
// a mode select must be sent.
|
||||||
|
//
|
||||||
|
|
||||||
|
PIRP OriginalRequest;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer to the mode select srb.
|
||||||
|
//
|
||||||
|
|
||||||
|
PSCSI_REQUEST_BLOCK Srb;
|
||||||
|
} XA_CONTEXT, *PXA_CONTEXT;
|
||||||
|
|
||||||
|
typedef struct _ERROR_RECOVERY_DATA {
|
||||||
|
MODE_PARAMETER_HEADER Header;
|
||||||
|
MODE_PARAMETER_BLOCK BlockDescriptor;
|
||||||
|
MODE_READ_RECOVERY_PAGE ReadRecoveryPage;
|
||||||
|
} ERROR_RECOVERY_DATA, *PERROR_RECOVERY_DATA;
|
||||||
|
|
||||||
|
typedef struct _ERROR_RECOVERY_DATA10 {
|
||||||
|
MODE_PARAMETER_HEADER10 Header10;
|
||||||
|
MODE_PARAMETER_BLOCK BlockDescriptor10;
|
||||||
|
MODE_READ_RECOVERY_PAGE ReadRecoveryPage10;
|
||||||
|
} ERROR_RECOVERY_DATA10, *PERROR_RECOVERY_DATA10;
|
||||||
|
|
||||||
|
//
|
||||||
|
// CdRom specific addition to device extension.
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _CDROM_DRIVER_EXTENSION {
|
||||||
|
ULONG InterlockedCdRomCounter;
|
||||||
|
PVOID Reserved[3];
|
||||||
|
} CDROM_DRIVER_EXTENSION, *PCDROM_DRIVER_EXTENSION;
|
||||||
|
|
||||||
|
#define CdromMmcUpdateComplete 0
|
||||||
|
#define CdromMmcUpdateRequired 1
|
||||||
|
#define CdromMmcUpdateStarted 2
|
||||||
|
|
||||||
|
typedef struct _CDROM_MMC_EXTENSION {
|
||||||
|
|
||||||
|
ULONG IsMmc; // allow quick checks
|
||||||
|
ULONG WriteAllowed;
|
||||||
|
|
||||||
|
LONG UpdateState;
|
||||||
|
|
||||||
|
SLIST_HEADER DelayedIrps; // irps delayed due to
|
||||||
|
KSPIN_LOCK DelayedLock; // lock for delayed irps
|
||||||
|
|
||||||
|
PIO_WORKITEM CapabilitiesWorkItem;
|
||||||
|
PIRP CapabilitiesIrp;
|
||||||
|
PMDL CapabilitiesMdl;
|
||||||
|
PGET_CONFIGURATION_HEADER CapabilitiesBuffer;
|
||||||
|
ULONG CapabilitiesBufferSize;
|
||||||
|
KEVENT CapabilitiesEvent;
|
||||||
|
SCSI_REQUEST_BLOCK CapabilitiesSrb;
|
||||||
|
|
||||||
|
} CDROM_MMC_EXTENSION, *PCDROM_MMC_EXTENSION;
|
||||||
|
|
||||||
|
|
||||||
|
#define CDROM_DRIVER_EXTENSION_ID CdRomAddDevice
|
||||||
|
|
||||||
|
typedef struct _CDROM_DATA {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer to the cdrom driver extension
|
||||||
|
//
|
||||||
|
|
||||||
|
PCDROM_DRIVER_EXTENSION DriverExtension;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// These bits allow detection of when to requery the
|
||||||
|
// drive's capabilities.
|
||||||
|
//
|
||||||
|
|
||||||
|
CDROM_MMC_EXTENSION Mmc;
|
||||||
|
|
||||||
|
//
|
||||||
|
// hack flags for ScanForSpecial routines
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG_PTR HackFlags;
|
||||||
|
|
||||||
|
//
|
||||||
|
// the error handling routines need to be per-device,
|
||||||
|
// not per-driver....
|
||||||
|
//
|
||||||
|
|
||||||
|
PCLASS_ERROR ErrorHandler;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicates whether an audio play operation
|
||||||
|
// is currently being performed.
|
||||||
|
// Only thing this does is prevent reads and
|
||||||
|
// toc requests while playing audio.
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN PlayActive;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicates whether the blocksize used for user data
|
||||||
|
// is 2048 or 2352.
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN RawAccess;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicates that this is a DEC RRD cdrom.
|
||||||
|
// This drive requires software to fix responses
|
||||||
|
// from the faulty firmware
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN IsDecRrd;
|
||||||
|
|
||||||
|
//
|
||||||
|
// This points to an irp which needs to be delayed for a bit before a
|
||||||
|
// retry can be attempted. The interval counter is set by the deferring
|
||||||
|
// routine and will be decremented to zero in the tick handler. Once
|
||||||
|
// the counter goes to zero the irp will be issued again.
|
||||||
|
// DelayedRetryResend controls whether the irp is resent to the lower
|
||||||
|
// driver (TRUE) or reissued into the startio routine (FALSE)
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN DelayedRetryResend;
|
||||||
|
|
||||||
|
PIRP DelayedRetryIrp;
|
||||||
|
|
||||||
|
ULONG DelayedRetryInterval;
|
||||||
|
|
||||||
|
KSPIN_LOCK DelayedRetrySpinLock;
|
||||||
|
|
||||||
|
//
|
||||||
|
// indicate we need to pick a default dvd region
|
||||||
|
// for the user if we can
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG PickDvdRegion;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The interface strings registered for this device.
|
||||||
|
//
|
||||||
|
|
||||||
|
UNICODE_STRING CdromInterfaceString;
|
||||||
|
UNICODE_STRING VolumeInterfaceString;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The well known name link for this device.
|
||||||
|
//
|
||||||
|
|
||||||
|
UNICODE_STRING WellKnownName;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicates whether 6 or 10 bytes mode sense/select
|
||||||
|
// should be used
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG XAFlags;
|
||||||
|
|
||||||
|
//
|
||||||
|
// keep track of what type of DVD device we are
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN DvdRpc0Device;
|
||||||
|
BOOLEAN DvdRpc0LicenseFailure;
|
||||||
|
UCHAR Rpc0SystemRegion; // bitmask, one means prevent play
|
||||||
|
UCHAR Rpc0SystemRegionResetCount;
|
||||||
|
|
||||||
|
ULONG Rpc0RetryRegistryCallback; // one until initial region choosen
|
||||||
|
|
||||||
|
KMUTEX Rpc0RegionMutex;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Storage for the error recovery page. This is used
|
||||||
|
// as an easy method to switch block sizes.
|
||||||
|
//
|
||||||
|
// NOTE - doubly unnamed structs just aren't very clean looking code - this
|
||||||
|
// should get cleaned up at some point in the future.
|
||||||
|
//
|
||||||
|
|
||||||
|
union {
|
||||||
|
ERROR_RECOVERY_DATA;
|
||||||
|
ERROR_RECOVERY_DATA10;
|
||||||
|
};
|
||||||
|
|
||||||
|
} CDROM_DATA, *PCDROM_DATA;
|
||||||
|
|
||||||
|
#define DEVICE_EXTENSION_SIZE sizeof(FUNCTIONAL_DEVICE_EXTENSION) + sizeof(CDROM_DATA)
|
||||||
|
#define SCSI_CDROM_TIMEOUT 10
|
||||||
|
#define SCSI_CHANGER_BONUS_TIMEOUT 10
|
||||||
|
#define HITACHI_MODE_DATA_SIZE 12
|
||||||
|
#define MODE_DATA_SIZE 64
|
||||||
|
#define RAW_SECTOR_SIZE 2352
|
||||||
|
#define COOKED_SECTOR_SIZE 2048
|
||||||
|
#define CDROM_SRB_LIST_SIZE 4
|
||||||
|
|
||||||
|
#define PLAY_ACTIVE(x) (((PCDROM_DATA)(x->CommonExtension.DriverData))->PlayActive)
|
||||||
|
|
||||||
|
#define MSF_TO_LBA(Minutes,Seconds,Frames) \
|
||||||
|
(ULONG)((60 * 75 * (Minutes)) + (75 * (Seconds)) + ((Frames) - 150))
|
||||||
|
|
||||||
|
#define LBA_TO_MSF(Lba,Minutes,Seconds,Frames) \
|
||||||
|
{ \
|
||||||
|
(Minutes) = (UCHAR)(Lba / (60 * 75)); \
|
||||||
|
(Seconds) = (UCHAR)((Lba % (60 * 75)) / 75); \
|
||||||
|
(Frames) = (UCHAR)((Lba % (60 * 75)) % 75); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define flags for XA, CDDA, and Mode Select/Sense
|
||||||
|
//
|
||||||
|
|
||||||
|
#define XA_USE_6_BYTE 0x01
|
||||||
|
#define XA_USE_10_BYTE 0x02
|
||||||
|
|
||||||
|
#define XA_NOT_SUPPORTED 0x10
|
||||||
|
#define XA_USE_READ_CD 0x20
|
||||||
|
#define XA_PLEXTOR_CDDA 0x40
|
||||||
|
#define XA_NEC_CDDA 0x80
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sector types for READ_CD
|
||||||
|
//
|
||||||
|
|
||||||
|
#define ANY_SECTOR 0
|
||||||
|
#define CD_DA_SECTOR 1
|
||||||
|
#define YELLOW_MODE1_SECTOR 2
|
||||||
|
#define YELLOW_MODE2_SECTOR 3
|
||||||
|
#define FORM2_MODE1_SECTOR 4
|
||||||
|
#define FORM2_MODE2_SECTOR 5
|
||||||
|
|
||||||
|
#define MAX_COPY_PROTECT_AGID 4
|
||||||
|
|
||||||
|
#ifdef ExAllocatePool
|
||||||
|
#undef ExAllocatePool
|
||||||
|
#define ExAllocatePool #assert(FALSE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CDROM_TAG_GET_CONFIG 'cCcS' // "ScCc" - ioctl GET_CONFIGURATION
|
||||||
|
#define CDROM_TAG_DC_EVENT 'ECcS' // "ScCE" - device control synch event
|
||||||
|
#define CDROM_TAG_FEATURE 'FCcS' // "ScCF" - allocated by CdRomGetConfiguration(), free'd by caller
|
||||||
|
#define CDROM_TAG_DISK_GEOM 'GCcS' // "ScCG" - disk geometry buffer
|
||||||
|
#define CDROM_TAG_HITACHI_ERROR 'HCcS' // "ScCH" - hitachi error buffer
|
||||||
|
#define CDROM_TAG_SENSE_INFO 'ICcS' // "ScCI" - sense info buffers
|
||||||
|
#define CDROM_TAG_POWER_IRP 'iCcS' // "ScCi" - irp for power request
|
||||||
|
#define CDROM_TAG_SRB 'SCcS' // "ScCS" - srb allocation
|
||||||
|
#define CDROM_TAG_STRINGS 'sCcS' // "ScCs" - assorted string data
|
||||||
|
#define CDROM_TAG_MODE_DATA 'MCcS' // "ScCM" - mode data buffer
|
||||||
|
#define CDROM_TAG_READ_CAP 'PCcS' // "ScCP" - read capacity buffer
|
||||||
|
#define CDROM_TAG_PLAY_ACTIVE 'pCcS' // "ScCp" - play active checks
|
||||||
|
#define CDROM_TAG_SUB_Q 'QCcS' // "ScCQ" - read sub q buffer
|
||||||
|
#define CDROM_TAG_RAW 'RCcS' // "ScCR" - raw mode read buffer
|
||||||
|
#define CDROM_TAG_TOC 'TCcS' // "ScCT" - read toc buffer
|
||||||
|
#define CDROM_TAG_TOSHIBA_ERROR 'tCcS' // "ScCt" - toshiba error buffer
|
||||||
|
#define CDROM_TAG_DEC_ERROR 'dCcS' // "ScCt" - DEC error buffer
|
||||||
|
#define CDROM_TAG_UPDATE_CAP 'UCcS' // "ScCU" - update capacity path
|
||||||
|
#define CDROM_TAG_VOLUME 'VCcS' // "ScCV" - volume control buffer
|
||||||
|
#define CDROM_TAG_VOLUME_INT 'vCcS' // "ScCv" - volume control buffer
|
||||||
|
|
||||||
|
#define DVD_TAG_READ_STRUCTURE 'SVcS' // "ScVS" - used for dvd structure reads
|
||||||
|
#define DVD_TAG_READ_KEY 'kVcS' // "ScVk" - read buffer for dvd key
|
||||||
|
#define DVD_TAG_SEND_KEY 'KVcS' // "ScVK" - write buffer for dvd key
|
||||||
|
#define DVD_TAG_RPC2_CHECK 'sVcS' // "ScVs" - read buffer for dvd/rpc2 check
|
||||||
|
#define DVD_TAG_DVD_REGION 'tVcS' // "ScVt" - read buffer for rpc2 check
|
||||||
|
#define DVD_TAG_SECURITY 'XVcS' // "ScVX" - security descriptor
|
||||||
|
|
||||||
|
|
||||||
|
#define CDROM_SUBKEY_NAME (L"CdRom") // store new settings here
|
||||||
|
#define CDROM_READ_CD_NAME (L"ReadCD") // READ_CD support previously detected
|
||||||
|
#define CDROM_NON_MMC_DRIVE_NAME (L"NonMmc") // MMC commands hang
|
||||||
|
//
|
||||||
|
// DVD Registry Value Names for RPC0 Device
|
||||||
|
//
|
||||||
|
#define DVD_DEFAULT_REGION (L"DefaultDvdRegion") // this is init. by the dvd class installer
|
||||||
|
#define DVD_CURRENT_REGION (L"DvdR")
|
||||||
|
#define DVD_REGION_RESET_COUNT (L"DvdRCnt")
|
||||||
|
#define DVD_MAX_REGION_RESET_COUNT 2
|
||||||
|
#define DVD_MAX_REGION 8
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define BAIL_OUT(Irp) \
|
||||||
|
DebugPrint((2, "Cdrom: [%p] Bailing with status " \
|
||||||
|
" %lx at line %x file %s\n", \
|
||||||
|
(Irp), (Irp)->IoStatus.Status, \
|
||||||
|
__LINE__, __FILE__))
|
||||||
|
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This routine grabs an extra remove lock using a local variable
|
||||||
|
for a unique tag. It then completes the irp in question, and
|
||||||
|
the just-acquired removelock guarantees that it is still safe
|
||||||
|
to call IoStartNextPacket(). When that finishes, we release
|
||||||
|
the newly acquired RemoveLock and return.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - the device object for the StartIo queue
|
||||||
|
Irp - the request we are completing
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
This is implemented as an inline function to allow the compiler
|
||||||
|
to optimize this as either a function call or as actual inline code.
|
||||||
|
|
||||||
|
This routine will not work with IoXxxRemoveLock() calls, as the
|
||||||
|
behavior is different. ClassXxxRemoveLock() calls succeed until
|
||||||
|
the remove has completed, while IoXxxRemoveLock() calls fail as
|
||||||
|
soon as the call to IoReleaseRemoveLockAndWait() has been called.
|
||||||
|
The Class version allows this routine to work in a safe manner.
|
||||||
|
|
||||||
|
replaces the following two lines:
|
||||||
|
IoStartNextPacket(DeviceObject, FALSE);
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
and raises irql as needed to call IoStartNextPacket()
|
||||||
|
|
||||||
|
--*/
|
||||||
|
static inline
|
||||||
|
VOID
|
||||||
|
CdRomCompleteIrpAndStartNextPacketSafely(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UCHAR uniqueAddress;
|
||||||
|
KIRQL oldIrql = KeGetCurrentIrql();
|
||||||
|
|
||||||
|
ClassAcquireRemoveLock(DeviceObject, (PIRP)&uniqueAddress);
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
ClassCompleteRequest(DeviceObject, Irp, IO_CD_ROM_INCREMENT);
|
||||||
|
|
||||||
|
if (oldIrql > DISPATCH_LEVEL) {
|
||||||
|
ASSERT(!"Cannot call IoStartNextPacket at raised IRQL!");
|
||||||
|
} else if (oldIrql < DISPATCH_LEVEL) {
|
||||||
|
KeRaiseIrqlToDpcLevel();
|
||||||
|
} else { // (oldIrql == DISPATCH_LEVEL)
|
||||||
|
NOTHING;
|
||||||
|
}
|
||||||
|
|
||||||
|
IoStartNextPacket(DeviceObject, FALSE);
|
||||||
|
|
||||||
|
if (oldIrql > DISPATCH_LEVEL) {
|
||||||
|
ASSERT(!"Cannot call IoStartNextPacket at raised IRQL!");
|
||||||
|
} else if (oldIrql < DISPATCH_LEVEL) {
|
||||||
|
KeLowerIrql(oldIrql);
|
||||||
|
} else { // (oldIrql == DISPATCH_LEVEL)
|
||||||
|
NOTHING;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, (PIRP)&uniqueAddress);
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomDeviceControlDvdReadStructure(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP OriginalIrp,
|
||||||
|
IN PIRP NewIrp,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomDeviceControlDvdEndSession(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP OriginalIrp,
|
||||||
|
IN PIRP NewIrp,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomDeviceControlDvdStartSessionReadKey(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP OriginalIrp,
|
||||||
|
IN PIRP NewIrp,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomDeviceControlDvdSendKey(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP OriginalIrp,
|
||||||
|
IN PIRP NewIrp,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DriverEntry(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomUnload(
|
||||||
|
IN PDRIVER_OBJECT DriverObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomAddDevice(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PDEVICE_OBJECT Pdo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomOpenClose(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomReadWriteVerification(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomSwitchMode(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN ULONG SectorSize,
|
||||||
|
IN PIRP OriginalRequest
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomDeviceControlDispatch(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomDeviceControlCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomSetVolumeIntermediateCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomSwitchModeCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomXACompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomClassIoctlCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomStartIo(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomTickHandler(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomUpdateCapacity(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN PIRP IrpToComplete,
|
||||||
|
IN OPTIONAL PKEVENT IoctlEvent
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomCreateDeviceObject(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PDEVICE_OBJECT Pdo
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ScanForSpecialHandler(
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
ULONG_PTR HackFlags
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ScanForSpecial(
|
||||||
|
PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
CdRomIsPlayActive(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomErrorHandler(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
NTSTATUS *Status,
|
||||||
|
BOOLEAN *Retry
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HitachiProcessErrorGD2000(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
NTSTATUS *Status,
|
||||||
|
BOOLEAN *Retry
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HitachiProcessError(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
NTSTATUS *Status,
|
||||||
|
BOOLEAN *Retry
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ToshibaProcessError(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
NTSTATUS *Status,
|
||||||
|
BOOLEAN *Retry
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ToshibaProcessErrorCompletion(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomCreateNamedEvent(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION DeviceExtension,
|
||||||
|
IN ULONG DeviceNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomInitDevice(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomStartDevice(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomStopDevice(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN UCHAR Type
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomRemoveDevice(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN UCHAR Type
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomDvdEndAllSessionsCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomDvdReadDiskKeyCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
DEVICE_TYPE
|
||||||
|
CdRomGetDeviceType(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomCreateWellKnownName(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomDeleteWellKnownName(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomGetDeviceParameter (
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PWSTR ParameterName,
|
||||||
|
IN OUT PULONG ParameterValue
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomSetDeviceParameter (
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PWSTR ParameterName,
|
||||||
|
IN ULONG ParameterValue
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomPickDvdRegion (
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomRetryRequest(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN ULONG Delay,
|
||||||
|
IN BOOLEAN ResendIrp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomRerunRequest(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN OPTIONAL PIRP Irp,
|
||||||
|
IN BOOLEAN ResendIrp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomGetRpc0Settings(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomSetRpc0Settings(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN UCHAR NewRegion
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomShutdownFlush(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomIsDeviceMmcDevice(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
OUT PBOOLEAN IsMmc
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomMmcErrorHandler(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
OUT PNTSTATUS Status,
|
||||||
|
OUT PBOOLEAN Retry
|
||||||
|
);
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
CdRomFindFeaturePage(
|
||||||
|
IN PGET_CONFIGURATION_HEADER FeatureBuffer,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN FEATURE_NUMBER Feature
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomGetConfiguration(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
OUT PGET_CONFIGURATION_HEADER *Buffer,
|
||||||
|
OUT PULONG BytesReturned,
|
||||||
|
IN FEATURE_NUMBER StartingFeature,
|
||||||
|
IN ULONG RequestedType
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomUpdateMmcDriveCapabilities(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PVOID Context // RESERVED == NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomFindProfileInProfiles(
|
||||||
|
IN PFEATURE_DATA_PROFILE_LIST ProfileHeader,
|
||||||
|
IN FEATURE_PROFILE_TYPE ProfileToFind,
|
||||||
|
OUT PBOOLEAN Exists
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomAllocateMmcResources(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomDeAllocateMmcResources(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdromFakePartitionInfo(
|
||||||
|
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRomInterpretReadCapacity(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PREAD_CAPACITY_DATA ReadCapacityBuffer
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomShutdownFlushCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PIRP Context
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
CdRompFlushDelayedList(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PCDROM_MMC_EXTENSION MmcData,
|
||||||
|
IN NTSTATUS Status,
|
||||||
|
IN BOOLEAN CalledFromWorkItem
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif // __CDROMP_H__
|
||||||
|
|
||||||
|
|
344
reactos/drivers/storage/class/cdrom_new/cdrom.inf
Normal file
344
reactos/drivers/storage/class/cdrom_new/cdrom.inf
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
;
|
||||||
|
; cdrom.inf -- INF file for installing CDROM drives
|
||||||
|
;
|
||||||
|
; Copyright (c) 1993-1997, Microsoft Corporation
|
||||||
|
|
||||||
|
[Version]
|
||||||
|
Signature="$WINDOWS NT$"
|
||||||
|
Class=CDROM
|
||||||
|
ClassGuid={4D36E965-E325-11CE-BFC1-08002BE10318}
|
||||||
|
Provider=%DDK_SAMPLE%
|
||||||
|
DriverVer=03/15/2001,5.1.2462.0
|
||||||
|
CatalogFile=ddk_sample.cat
|
||||||
|
|
||||||
|
[cdaudio_copyfiles]
|
||||||
|
cdaudio.sys
|
||||||
|
|
||||||
|
[changer_copyfiles]
|
||||||
|
changer.sys
|
||||||
|
|
||||||
|
[cdrom_copyfiles]
|
||||||
|
cdrom.sys
|
||||||
|
redbook.sys
|
||||||
|
|
||||||
|
[storprop_copyfiles]
|
||||||
|
storprop.dll
|
||||||
|
|
||||||
|
[DestinationDirs]
|
||||||
|
cdrom_copyfiles = 12
|
||||||
|
cdaudio_copyfiles = 12
|
||||||
|
changer_copyfiles = 12
|
||||||
|
storprop_copyfiles = 11
|
||||||
|
|
||||||
|
[Manufacturer]
|
||||||
|
%ATAPI_CHGR% = atapi_chgr
|
||||||
|
%CHINON% = chinon_cdrom
|
||||||
|
%DENON% = denon_cdrom
|
||||||
|
%FUJITSU% = fujitsu_cdrom
|
||||||
|
%HITACHI% = hitachi_cdrom
|
||||||
|
%HP% = hp_cdrom
|
||||||
|
%MITSUMI% = mitsumi_cdrom
|
||||||
|
%NEC% = nec_cdrom
|
||||||
|
%OTI% = oti_cdrom
|
||||||
|
%PIONEER% = pioneer_cdrom
|
||||||
|
%WEARNES% = wearnes_cdrom
|
||||||
|
%GenManufacturer% = cdrom_device
|
||||||
|
|
||||||
|
[atapi_chgr]
|
||||||
|
%NecChanger_devdesc% = changer_install,IDE\CdRomNEC_CD-ROM_DRIVE:251____________________
|
||||||
|
%NecChanger_devdesc% = changer_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:251
|
||||||
|
%NecChanger_devdesc% = changer_install,IDE\CdRomNEC_CD-ROM_DRIVE:253____________________
|
||||||
|
%NecChanger_devdesc% = changer_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:253
|
||||||
|
%NecChanger_devdesc% = changer_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:252
|
||||||
|
%AlpsChanger_devdesc% = changer_install,IDE\CdRomALPS_DC544______________________________
|
||||||
|
%TorisanChanger_devdesc% = changer_install,IDE\CdRomTORiSAN_CD-ROM_CDR-C3G__________________
|
||||||
|
%TorisanChanger_devdesc% = changer_install,SCSI\CdRomTORiSAN_CD-ROM_CDR-C3G__
|
||||||
|
%TorisanChanger_devdesc% = changer_install,IDE\CdRomTORiSAN_CD-ROM_CDR_C36__________________
|
||||||
|
%PanasonicChanger_devdesc% = changer_install,IDE\CdRomMATSHITA_RD-DRC001-M____________________
|
||||||
|
%PanasonicChanger_devdesc% = changer_install,IDE\CdRomMATSHITA_RD-DRC002-S____________________
|
||||||
|
%PanasonicChanger_devdesc% = changer_install,SCSI\CdRomNAKAMICHMJ-5.16_________
|
||||||
|
|
||||||
|
[fujitsu_cdrom]
|
||||||
|
%fujitsu_devdesc% = cdaudio_install,SCSI\CdRomFUJITSU_
|
||||||
|
|
||||||
|
[chinon_cdrom]
|
||||||
|
%chinon_devdesc% = cdaudio_install,SCSI\CdRomCHINON__
|
||||||
|
|
||||||
|
[denon_cdrom]
|
||||||
|
%denon_devdesc% = cdaudio_install,SCSI\CdRomDENON___
|
||||||
|
|
||||||
|
[hp_cdrom]
|
||||||
|
%hp_devdesc% = cdaudio_install,SCSI\CdRomHP______C4324/C4325_____
|
||||||
|
|
||||||
|
[hitachi_cdrom]
|
||||||
|
%hitachi_devdesc% = cdaudio_install,SCSI\CdRomHITACHI_CDR-3650/1650S__
|
||||||
|
%hitachi_devdesc% = cdaudio_install,SCSI\CdRomHITACHI_CDR-1750S_______
|
||||||
|
|
||||||
|
[mitsumi_cdrom]
|
||||||
|
%Mitsumi_cdrom_devdesc% = mitsumi_install,IDE\CdRomMITSUMI_CD-ROM________!A________________
|
||||||
|
|
||||||
|
[nec_cdrom]
|
||||||
|
%NecMultispin_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:38_
|
||||||
|
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE_4_M
|
||||||
|
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:80_
|
||||||
|
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:82_
|
||||||
|
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:83_
|
||||||
|
%NecIntersect_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:84_
|
||||||
|
%NecMultispin_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:841
|
||||||
|
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:400
|
||||||
|
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:401
|
||||||
|
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:500
|
||||||
|
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:501
|
||||||
|
%NecOem_devdesc% = cdaudio_install,SCSI\CdRomNEC_____CD-ROM_DRIVE:900
|
||||||
|
|
||||||
|
[oti_cdrom]
|
||||||
|
%oti_devdesc% = cdaudio_install,IDE\CdRomOTI_DOLPHIN_8001_IDE____________________
|
||||||
|
|
||||||
|
[pioneer_cdrom]
|
||||||
|
%pioneer_devdesc% = cdaudio_install,SCSI\CdRomPIONEER_CD-ROM_DRM-600__
|
||||||
|
%pioneer_devdesc% = cdaudio_install,SCSI\CdRomPIONEER_CD-ROM_DRM-600x_
|
||||||
|
|
||||||
|
[wearnes_cdrom]
|
||||||
|
%wearnes_devdesc% = cdaudio_install,IDE\CdRomWEARNES_
|
||||||
|
|
||||||
|
|
||||||
|
[cdrom_device]
|
||||||
|
;;
|
||||||
|
;; if none of the above matched, then only cdrom.sys is required for this drive
|
||||||
|
;;
|
||||||
|
%gencdrom_devdesc% = cdrom_install,SCSI\WormPIONEER_CD-WO_DR-R504X__
|
||||||
|
%gencdrom_devdesc% = cdrom_install,SCSI\WormSONY____CD-R___CDU920S__
|
||||||
|
%gencdrom_devdesc% = cdrom_install,SCSI\WormSONY____CD-R___CDU948S__
|
||||||
|
%gencdrom_devdesc% = cdrom_install,GenCdRom
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Use to add filter drivers for the device
|
||||||
|
;;
|
||||||
|
|
||||||
|
[cdaudio_addreg]
|
||||||
|
HKR,,"UpperFilters",0x00010008,"cdaudio"
|
||||||
|
|
||||||
|
[changer_addreg]
|
||||||
|
HKR,,"UpperFilters",0x00010008,"changer"
|
||||||
|
|
||||||
|
[mitsumi_addreg]
|
||||||
|
HKR,,"FriendlyName",,%Mitsumi_Generic_FriendlyName%
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; more addreg sections
|
||||||
|
;;
|
||||||
|
|
||||||
|
[dvd_property_provider_AddReg]
|
||||||
|
HKR,,EnumPropPages32,,"storprop.dll,DvdPropPageProvider"
|
||||||
|
|
||||||
|
[autorun_addreg]
|
||||||
|
;;
|
||||||
|
;; The AutoRunAlwaysDisable key is only for use when the hardware cannot
|
||||||
|
;; accepts TEST_UNIT_READY commands. Disabling 'AutoRun' or including
|
||||||
|
;; devices in this list will prevent removable media services from being
|
||||||
|
;; able to properly handle these devices.
|
||||||
|
;;
|
||||||
|
HKLM,"System\CurrentControlSet\Services\cdrom","AutoRun",0x00010003,1
|
||||||
|
HKLM,"System\CurrentControlSet\Services\cdrom","AutoRunAlwaysDisable",\
|
||||||
|
0x00010000,\
|
||||||
|
"NEC MBR-7 ", \
|
||||||
|
"NEC MBR-7.4 ", \
|
||||||
|
"PIONEER CHANGR DRM-1804X", \
|
||||||
|
"PIONEER CD-ROM DRM-6324X", \
|
||||||
|
"PIONEER CD-ROM DRM-624X ", \
|
||||||
|
"TORiSAN CD-ROM CDR_C36"
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Use to disable synchronous transfers to this device. Sync transfers will
|
||||||
|
;; always be turned off by default in this INF for any cdrom-type device
|
||||||
|
;;
|
||||||
|
[nosync_addreg]
|
||||||
|
HKR,,"DefaultRequestFlags",0x00010001,8
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Installation section for cdaudio. Sets cdrom as the service and adds
|
||||||
|
;; cdaudio as an upper filter
|
||||||
|
;;
|
||||||
|
|
||||||
|
[cdaudio_install]
|
||||||
|
CopyFiles=cdaudio_copyfiles,cdrom_copyfiles,storprop_copyfiles
|
||||||
|
AddReg=dvd_property_provider_AddReg
|
||||||
|
|
||||||
|
[cdaudio_install.HW]
|
||||||
|
AddReg=nosync_addreg,cdaudio_addreg
|
||||||
|
|
||||||
|
[cdaudio_install.Services]
|
||||||
|
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||||
|
AddService=cdaudio,,cdaudio_ServiceInstallSection
|
||||||
|
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Installation section for changer
|
||||||
|
;;
|
||||||
|
|
||||||
|
[changer_install]
|
||||||
|
CopyFiles=changer_copyfiles,cdrom_copyfiles,storprop_copyfiles
|
||||||
|
AddReg=dvd_property_provider_AddReg
|
||||||
|
|
||||||
|
[changer_install.HW]
|
||||||
|
AddReg=changer_addreg
|
||||||
|
|
||||||
|
[changer_install.Services]
|
||||||
|
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||||
|
AddService=changer,,changer_ServiceInstallSection
|
||||||
|
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Installation section for mitsumi.
|
||||||
|
;;
|
||||||
|
|
||||||
|
[mitsumi_install]
|
||||||
|
CopyFiles=cdrom_copyfiles,storprop_copyfiles
|
||||||
|
AddReg=dvd_property_provider_AddReg
|
||||||
|
|
||||||
|
[mitsumi_install.HW]
|
||||||
|
AddReg=nosync_addreg,mitsumi_addreg
|
||||||
|
|
||||||
|
[mitsumi_install.Services]
|
||||||
|
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||||
|
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Installation section for generic cdrom.
|
||||||
|
;;
|
||||||
|
|
||||||
|
[cdrom_install]
|
||||||
|
CopyFiles=cdrom_copyfiles,storprop_copyfiles
|
||||||
|
AddReg=dvd_property_provider_AddReg
|
||||||
|
|
||||||
|
[cdrom_install.HW]
|
||||||
|
AddReg=nosync_addreg
|
||||||
|
|
||||||
|
[cdrom_install.Services]
|
||||||
|
AddService=cdrom,0x00000002,cdrom_ServiceInstallSection
|
||||||
|
AddService=redbook,,redbook_ServiceInstallSection,redbook_InstallEventLogSection
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Service install sections for cdrom and cdaudio
|
||||||
|
;;
|
||||||
|
|
||||||
|
[cdrom_ServiceInstallSection]
|
||||||
|
DisplayName = %cdrom_ServiceDesc%
|
||||||
|
ServiceType = 1
|
||||||
|
StartType = 1
|
||||||
|
ErrorControl = 1
|
||||||
|
ServiceBinary = %12%\cdrom.sys
|
||||||
|
LoadOrderGroup = SCSI CDROM Class
|
||||||
|
AddReg=autorun_addreg
|
||||||
|
|
||||||
|
[cdaudio_ServiceInstallSection]
|
||||||
|
DisplayName = %cdaudio_ServiceDesc%
|
||||||
|
ServiceType = 1
|
||||||
|
StartType = 1
|
||||||
|
ErrorControl = 1
|
||||||
|
ServiceBinary = %12%\cdaudio.sys
|
||||||
|
LoadOrderGroup = Pnp Filter
|
||||||
|
|
||||||
|
[changer_ServiceInstallSection]
|
||||||
|
DisplayName = %changer_ServiceDesc%
|
||||||
|
ServiceType = 1
|
||||||
|
StartType = 1
|
||||||
|
ErrorControl = 1
|
||||||
|
ServiceBinary = %12%\changer.sys
|
||||||
|
LoadOrderGroup = Pnp Filter
|
||||||
|
|
||||||
|
[redbook_ServiceInstallSection]
|
||||||
|
DisplayName = %redbook_ServiceDesc%
|
||||||
|
ServiceType = 1
|
||||||
|
StartType = 1
|
||||||
|
ErrorControl = 1
|
||||||
|
ServiceBinary = %12%\redbook.sys
|
||||||
|
LoadOrderGroup = Pnp Filter
|
||||||
|
|
||||||
|
[redbook_InstallEventLogSection]
|
||||||
|
AddReg = redbook_EventLog_addreg
|
||||||
|
|
||||||
|
[redbook_EventLog_addreg]
|
||||||
|
HKR,,"EventMessageFile",0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\redbook.sys"
|
||||||
|
HKR,,"TypesSupported",0x00010001,7
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[Strings]
|
||||||
|
DDK_SAMPLE="DDK Sample Provider"
|
||||||
|
CDClassName = "DVD/CD-ROM drives"
|
||||||
|
|
||||||
|
;; Manufacturer specific strings
|
||||||
|
ATAPI_CHGR = "Atapi 2.5 Changer Devices"
|
||||||
|
CHINON = "Chinon"
|
||||||
|
DENON = "Denon"
|
||||||
|
FUJITSU = "Fujitsu"
|
||||||
|
HITACHI = "Hitachi"
|
||||||
|
HP = "Hewlett Packard"
|
||||||
|
MITSUMI = "Mitsumi"
|
||||||
|
NEC = "NEC"
|
||||||
|
OTI = "OTI"
|
||||||
|
PIONEER = "Pioneer"
|
||||||
|
WEARNES = "Wearnes"
|
||||||
|
GenManufacturer = "(Standard CD-ROM drives)"
|
||||||
|
|
||||||
|
;; Descriptions for enumerated brands and models
|
||||||
|
AlpsChanger_devdesc = "Alps CD-ROM Changer"
|
||||||
|
chinon_devdesc = "Chinon CD-ROM Drive"
|
||||||
|
denon_devdesc = "Denon CD-ROM Drive"
|
||||||
|
fujitsu_devdesc = "Fujitsu CD-ROM Drive"
|
||||||
|
hp_devdesc = "Hewlett Packard CD-ROM Drive"
|
||||||
|
hitachi_devdesc = "Hitachi CD-ROM Drive"
|
||||||
|
Mitsumi_cdrom_devdesc = "Mitsumi CD-ROM Drive"
|
||||||
|
NecChanger_devdesc = "NEC CD-ROM Changer"
|
||||||
|
NecIntersect_devdesc = "NEC Intersect CD-ROM Drive"
|
||||||
|
NecMultispin_devdesc = "NEC Multispin CD-ROM Drive"
|
||||||
|
NecOem_devdesc = "NEC CD-ROM Drive"
|
||||||
|
oti_devdesc = "OTI CD-ROM Drive"
|
||||||
|
PanasonicChanger_devdesc = "Panasonic CD-ROM Changer"
|
||||||
|
pioneer_devdesc = "Pioneer CD-ROM Drive"
|
||||||
|
TorisanChanger_devdesc = "Torisan CD-ROM Changer"
|
||||||
|
wearnes_devdesc = "Wearnes CD-ROM Drive"
|
||||||
|
gencdrom_devdesc = "CD-ROM Drive"
|
||||||
|
|
||||||
|
;; Mitsumi Friendly name explictly listed
|
||||||
|
Mitsumi_Generic_FriendlyName = "Mitsumi CD-ROM Drive"
|
||||||
|
|
||||||
|
;; Service descriptions
|
||||||
|
cdrom_ServiceDesc = "CD-ROM Driver"
|
||||||
|
cdaudio_ServiceDesc = "CD-Audio Filter Driver"
|
||||||
|
changer_ServiceDesc = "CD-Changer Filter Driver"
|
||||||
|
redbook_ServiceDesc = "Digital CD Audio Playback Filter Driver"
|
||||||
|
|
||||||
|
|
20
reactos/drivers/storage/class/cdrom_new/cdrom_new.rbuild
Normal file
20
reactos/drivers/storage/class/cdrom_new/cdrom_new.rbuild
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
|
||||||
|
<module name="cdrom_new" type="kernelmodedriver" installbase="system32/drivers" installname="cdrom_new.sys">
|
||||||
|
<bootstrap installbase="$(CDOUTPUT)" />
|
||||||
|
<library>ntoskrnl</library>
|
||||||
|
<library>hal</library>
|
||||||
|
<library>classpnp</library>
|
||||||
|
<include base="cdrom_new">../inc</include>
|
||||||
|
<group compilerset="gcc">
|
||||||
|
<compilerflag>-mrtd</compilerflag>
|
||||||
|
<compilerflag>-fno-builtin</compilerflag>
|
||||||
|
<compilerflag>-w</compilerflag>
|
||||||
|
</group>
|
||||||
|
<file>cdrom.c</file>
|
||||||
|
<file>data.c</file>
|
||||||
|
<file>ioctl.c</file>
|
||||||
|
<file>mmc.c</file>
|
||||||
|
<file>scsicdrm.rc</file>
|
||||||
|
<file>sec.c</file>
|
||||||
|
</module>
|
99
reactos/drivers/storage/class/cdrom_new/data.c
Normal file
99
reactos/drivers/storage/class/cdrom_new/data.c
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "ntddk.h"
|
||||||
|
#include "classpnp.h"
|
||||||
|
#include "trace.h"
|
||||||
|
|
||||||
|
#ifdef ALLOC_DATA_PRAGMA
|
||||||
|
#pragma data_seg("PAGE")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
#define CDROM_HACK_DEC_RRD (0x00000001)
|
||||||
|
#define CDROM_HACK_FUJITSU_FMCD_10x (0x00000002)
|
||||||
|
#define CDROM_HACK_HITACHI_1750 (0x00000004)
|
||||||
|
#define CDROM_HACK_HITACHI_GD_2000 (0x00000008)
|
||||||
|
#define CDROM_HACK_TOSHIBA_SD_W1101 (0x00000010)
|
||||||
|
#define CDROM_HACK_TOSHIBA_XM_3xx (0x00000020)
|
||||||
|
#define CDROM_HACK_NEC_CDDA (0x00000040)
|
||||||
|
#define CDROM_HACK_PLEXTOR_CDDA (0x00000080)
|
||||||
|
#define CDROM_HACK_BAD_GET_CONFIG_SUPPORT (0x00000100)
|
||||||
|
#define CDROM_HACK_FORCE_READ_CD_DETECTION (0x00000200)
|
||||||
|
#define CDROM_HACK_READ_CD_SUPPORTED (0x00000400)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
CLASSPNP_SCAN_FOR_SPECIAL_INFO CdromHackItems[] = {
|
||||||
|
// digital put out drives using 512 byte block sizes,
|
||||||
|
// and needed us to send a mode page to set the sector
|
||||||
|
// size back to 2048.
|
||||||
|
{ "DEC" , "RRD" , NULL, 0x0001 },
|
||||||
|
// these fujitsu drives take longer than ten seconds to
|
||||||
|
// timeout commands when audio discs are placed in them
|
||||||
|
{ "FUJITSU" , "FMCD-101" , NULL, 0x0002 },
|
||||||
|
{ "FUJITSU" , "FMCD-102" , NULL, 0x0002 },
|
||||||
|
// these hitachi drives don't work properly in PIO mode
|
||||||
|
{ "HITACHI ", "CDR-1750S" , NULL, 0x0004 },
|
||||||
|
{ "HITACHI ", "CDR-3650/1650S" , NULL, 0x0004 },
|
||||||
|
// this particular gem doesn't automatcially spin up
|
||||||
|
// on some media access commands.
|
||||||
|
{ "" , "HITACHI GD-2000" , NULL, 0x0008 },
|
||||||
|
{ "" , "HITACHI DVD-ROM GD-2000" , NULL, 0x0008 },
|
||||||
|
// this particular drive doesn't support DVD playback.
|
||||||
|
// just print an error message in CHK builds.
|
||||||
|
{ "TOSHIBA ", "SD-W1101 DVD-RAM" , NULL, 0x0010 },
|
||||||
|
// not sure what this device's issue was. seems to
|
||||||
|
// require mode selects at various times.
|
||||||
|
{ "TOSHIBA ", "CD-ROM XM-3" , NULL, 0x0020 },
|
||||||
|
// NEC defined a "READ_CD" type command before there was
|
||||||
|
// a standard, so fall back on this as an option.
|
||||||
|
{ "NEC" , "" , NULL, 0x0040 },
|
||||||
|
// plextor defined a "READ_CD" type command before there was
|
||||||
|
// a standard, so fall back on this as an option.
|
||||||
|
{ "PLEXTOR ", "" , NULL, 0x0080 },
|
||||||
|
// this drive times out and sometimes disappears from the bus
|
||||||
|
// when send GET_CONFIGURATION commands. don't send them.
|
||||||
|
{ "" , "LG DVD-ROM DRD-840B" , NULL, 0x0100 },
|
||||||
|
{ "" , "SAMSUNG DVD-ROM SD-608" , NULL, 0x0300 },
|
||||||
|
// these drives should have supported READ_CD, but at least
|
||||||
|
// some firmware revisions did not. force READ_CD detection.
|
||||||
|
{ "" , "SAMSUNG DVD-ROM SD-" , NULL, 0x2000 },
|
||||||
|
// the mitsumi drive below doesn't follow the block-only spec,
|
||||||
|
// and we end up hanging when sending it commands it doesn't
|
||||||
|
// understand. this causes complications later, also.
|
||||||
|
{ "MITSUMI ", "CR-4802TE " , NULL, 0x0100 },
|
||||||
|
// some drives return various funky errors (such as 3/2/0 NO_SEEK_COMPLETE)
|
||||||
|
// during the detection of READ_CD support, resulting in iffy detection.
|
||||||
|
// since they probably don't support mode switching, which is really old
|
||||||
|
// legacy stuff anyways, the ability to read digitally is lost when
|
||||||
|
// these drives return unexpected error codes. note: MMC compliant drives
|
||||||
|
// are presumed to support READ_CD, as are DVD drives, and anything
|
||||||
|
// connected to a bus type other than IDE or SCSI, and therefore don't
|
||||||
|
// need to be here.
|
||||||
|
{ "YAMAHA ", "CRW8424S " , NULL, 0x0400 },
|
||||||
|
// and finally, a place to finish the list. :)
|
||||||
|
{ NULL , NULL , NULL, 0x0000 }
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ALLOC_DATA_PRAGMA
|
||||||
|
#pragma data_seg()
|
||||||
|
#endif
|
||||||
|
|
4054
reactos/drivers/storage/class/cdrom_new/ioctl.c
Normal file
4054
reactos/drivers/storage/class/cdrom_new/ioctl.c
Normal file
File diff suppressed because it is too large
Load diff
1422
reactos/drivers/storage/class/cdrom_new/mmc.c
Normal file
1422
reactos/drivers/storage/class/cdrom_new/mmc.c
Normal file
File diff suppressed because it is too large
Load diff
23
reactos/drivers/storage/class/cdrom_new/scsicdrm.rc
Normal file
23
reactos/drivers/storage/class/cdrom_new/scsicdrm.rc
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//+-------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Microsoft Windows
|
||||||
|
//
|
||||||
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||||
|
//
|
||||||
|
// File: scsicdrm.rc
|
||||||
|
//
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <ntverp.h>
|
||||||
|
|
||||||
|
#define VER_FILETYPE VFT_DRV
|
||||||
|
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
|
||||||
|
#define VER_FILEDESCRIPTION_STR "SCSI CD-ROM Driver"
|
||||||
|
#define VER_INTERNALNAME_STR "cdrom.sys"
|
||||||
|
#define VER_ORIGINALFILENAME_STR "cdrom.sys"
|
||||||
|
#define VER_LANGNEUTRAL
|
||||||
|
|
||||||
|
#include "common.ver"
|
||||||
|
|
38
reactos/drivers/storage/class/cdrom_new/sec.c
Normal file
38
reactos/drivers/storage/class/cdrom_new/sec.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*--
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1999
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "sec.h"
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomGetRpc0Settings(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
|
||||||
|
PCDROM_DATA cddata = (PCDROM_DATA)(commonExtension->DriverData);
|
||||||
|
|
||||||
|
cddata->Rpc0SystemRegion = (UCHAR)(~1); // region one
|
||||||
|
cddata->Rpc0SystemRegionResetCount = 0; // no resets
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
CdRomSetRpc0Settings(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN UCHAR NewRegion
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
11
reactos/drivers/storage/class/cdrom_new/sec.h
Normal file
11
reactos/drivers/storage/class/cdrom_new/sec.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*--
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1999
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ntddk.h"
|
||||||
|
#include "classpnp.h"
|
||||||
|
#include "cdrom.h"
|
||||||
|
|
32
reactos/drivers/storage/class/cdrom_new/sources
Normal file
32
reactos/drivers/storage/class/cdrom_new/sources
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
!IF 0
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
sources.
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
TARGETNAME=cdrom
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=DRIVER
|
||||||
|
|
||||||
|
TARGETLIBS=\
|
||||||
|
$(DDK_LIB_PATH)\classpnp.lib \
|
||||||
|
$(DDK_LIB_PATH)\ntoskrnl.lib
|
||||||
|
|
||||||
|
INCLUDES=..\inc;..\..\inc
|
||||||
|
|
||||||
|
SOURCES=\
|
||||||
|
data.c \
|
||||||
|
cdrom.c \
|
||||||
|
ioctl.c \
|
||||||
|
mmc.c \
|
||||||
|
scsicdrm.rc \
|
||||||
|
sec.c
|
||||||
|
|
||||||
|
RUN_WPP=$(SOURCES)\
|
||||||
|
-km\
|
||||||
|
-func:TraceLog((LEVEL,MSG,...))
|
||||||
|
|
53
reactos/drivers/storage/class/cdrom_new/trace.h
Normal file
53
reactos/drivers/storage/class/cdrom_new/trace.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
WPP_DEFINE_CONTROL_GUID specifies the GUID used for this filter.
|
||||||
|
*** REPLACE THE GUID WITH YOUR OWN UNIQUE ID ***
|
||||||
|
WPP_DEFINE_BIT allows setting debug bit masks to selectively print.
|
||||||
|
|
||||||
|
everything else can revert to the default?
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define TraceLogger(x, ...) DbgPrint(__VA_ARGS__)
|
||||||
|
#define TraceLog(x) TraceLogger x
|
||||||
|
#define WPP_INIT_TRACING(x, y)
|
||||||
|
#define WPP_CLEANUP(x)
|
||||||
|
|
||||||
|
#define WPP_CONTROL_GUIDS \
|
||||||
|
WPP_DEFINE_CONTROL_GUID(Cdrom,(58db8e03,0537,45cb,b29b,597f6cbebbfd), \
|
||||||
|
WPP_DEFINE_BIT(CdromDebugError) /* bit 0 = 0x00000001 */ \
|
||||||
|
WPP_DEFINE_BIT(CdromDebugWarning) /* bit 1 = 0x00000002 */ \
|
||||||
|
WPP_DEFINE_BIT(CdromDebugTrace) /* bit 2 = 0x00000004 */ \
|
||||||
|
WPP_DEFINE_BIT(CdromDebugInfo) /* bit 3 = 0x00000008 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD04) /* bit 4 = 0x00000010 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD05) /* bit 5 = 0x00000020 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD06) /* bit 6 = 0x00000040 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD07) /* bit 7 = 0x00000080 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD08) /* bit 8 = 0x00000100 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD09) /* bit 9 = 0x00000200 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD10) /* bit 10 = 0x00000400 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD11) /* bit 11 = 0x00000800 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD12) /* bit 12 = 0x00001000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD13) /* bit 13 = 0x00002000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD14) /* bit 14 = 0x00004000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD15) /* bit 15 = 0x00008000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD16) /* bit 16 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD17) /* bit 17 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD18) /* bit 18 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD19) /* bit 19 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD20) /* bit 20 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD21) /* bit 21 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD22) /* bit 22 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD23) /* bit 23 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD24) /* bit 24 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD25) /* bit 25 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD26) /* bit 26 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD27) /* bit 27 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD28) /* bit 28 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(FilterDebugD29) /* bit 29 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(CdromSecError) /* bit 30 = 0x00000000 */ \
|
||||||
|
WPP_DEFINE_BIT(CdromSecInfo) /* bit 31 = 0x00000000 */ \
|
||||||
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
<directory name="cdrom">
|
<directory name="cdrom">
|
||||||
<xi:include href="cdrom/cdrom.rbuild" />
|
<xi:include href="cdrom/cdrom.rbuild" />
|
||||||
</directory>
|
</directory>
|
||||||
|
<directory name="cdrom_new">
|
||||||
|
<xi:include href="cdrom_new/cdrom_new.rbuild" />
|
||||||
|
</directory>
|
||||||
<directory name="class2">
|
<directory name="class2">
|
||||||
<xi:include href="class2/class2.rbuild" />
|
<xi:include href="class2/class2.rbuild" />
|
||||||
</directory>
|
</directory>
|
||||||
|
|
3611
reactos/drivers/storage/classpnp/autorun.c
Normal file
3611
reactos/drivers/storage/classpnp/autorun.c
Normal file
File diff suppressed because it is too large
Load diff
9182
reactos/drivers/storage/classpnp/class.c
Normal file
9182
reactos/drivers/storage/classpnp/class.c
Normal file
File diff suppressed because it is too large
Load diff
61
reactos/drivers/storage/classpnp/class.def
Normal file
61
reactos/drivers/storage/classpnp/class.def
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
NAME CLASSPNP.SYS
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
ClassInitialize@12
|
||||||
|
ClassInitializeEx@12
|
||||||
|
ClassGetDescriptor@12
|
||||||
|
ClassReadDriveCapacity@4
|
||||||
|
ClassReleaseQueue@4
|
||||||
|
ClassAsynchronousCompletion@12
|
||||||
|
ClassSplitRequest@12
|
||||||
|
ClassDeviceControl@8
|
||||||
|
ClassIoComplete@12
|
||||||
|
ClassIoCompleteAssociated@12
|
||||||
|
ClassInterpretSenseInfo@28
|
||||||
|
ClassSendDeviceIoControlSynchronous@28
|
||||||
|
ClassSendIrpSynchronous@8
|
||||||
|
ClassForwardIrpSynchronous@8
|
||||||
|
ClassSendSrbSynchronous@20
|
||||||
|
ClassSendSrbAsynchronous@24
|
||||||
|
ClassBuildRequest@8
|
||||||
|
ClassModeSense@16
|
||||||
|
ClassFindModePage@16
|
||||||
|
ClassClaimDevice@8
|
||||||
|
ClassInternalIoControl@8
|
||||||
|
ClassCreateDeviceObject@20
|
||||||
|
ClassRemoveDevice@8
|
||||||
|
ClassInitializeSrbLookasideList@8
|
||||||
|
ClassDeleteSrbLookasideList@4
|
||||||
|
ClassQueryTimeOutRegistryValue@4
|
||||||
|
ClassInvalidateBusRelations@4
|
||||||
|
ClassMarkChildrenMissing@4
|
||||||
|
ClassMarkChildMissing@8
|
||||||
|
ClassDebugPrint
|
||||||
|
ClassGetDriverExtension@4
|
||||||
|
ClassCompleteRequest@12
|
||||||
|
ClassReleaseRemoveLock@8
|
||||||
|
ClassAcquireRemoveLockEx@16
|
||||||
|
ClassUpdateInformationInRegistry@20
|
||||||
|
ClassWmiCompleteRequest@20
|
||||||
|
ClassWmiFireEvent@20
|
||||||
|
ClassGetVpb@4
|
||||||
|
ClassSetFailurePredictionPoll@12
|
||||||
|
ClassNotifyFailurePredicted@32
|
||||||
|
ClassInitializeTestUnitPolling@8
|
||||||
|
ClassSignalCompletion@12
|
||||||
|
ClassSendStartUnit@4
|
||||||
|
ClassSetMediaChangeState@12
|
||||||
|
ClassResetMediaChangeTimer@4
|
||||||
|
ClassCheckMediaState@4
|
||||||
|
ClassInitializeMediaChangeDetection@8
|
||||||
|
ClassCleanupMediaChangeDetection@4
|
||||||
|
ClassEnableMediaChangeDetection@4
|
||||||
|
ClassDisableMediaChangeDetection@4
|
||||||
|
ClassSpinDownPowerHandler@8
|
||||||
|
ClassStopUnitPowerHandler@8
|
||||||
|
ClassAcquireChildLock@4
|
||||||
|
ClassReleaseChildLock@4
|
||||||
|
ClassScanForSpecial@12
|
||||||
|
ClassSetDeviceParameter@16
|
||||||
|
ClassGetDeviceParameter@16
|
||||||
|
|
23
reactos/drivers/storage/classpnp/class.rc
Normal file
23
reactos/drivers/storage/classpnp/class.rc
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//+-------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Microsoft Windows
|
||||||
|
//
|
||||||
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||||
|
//
|
||||||
|
// File: class.rc
|
||||||
|
//
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <ntverp.h>
|
||||||
|
|
||||||
|
#define VER_FILETYPE VFT_DRV
|
||||||
|
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
|
||||||
|
#define VER_FILEDESCRIPTION_STR "SCSI Class System Dll"
|
||||||
|
#define VER_INTERNALNAME_STR "Classpnp.sys"
|
||||||
|
#define VER_ORIGINALFILENAME_STR "Classpnp.sys"
|
||||||
|
#define VER_LANGNEUTRAL
|
||||||
|
|
||||||
|
#include "common.ver"
|
||||||
|
|
907
reactos/drivers/storage/classpnp/classp.h
Normal file
907
reactos/drivers/storage/classpnp/classp.h
Normal file
|
@ -0,0 +1,907 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
classp.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Private header file for classpnp.sys modules. This contains private
|
||||||
|
structure and function declarations as well as constant values which do
|
||||||
|
not need to be exported.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <ntddk.h>
|
||||||
|
|
||||||
|
#include <scsi.h>
|
||||||
|
#include <wmidata.h>
|
||||||
|
#include <classpnp.h>
|
||||||
|
|
||||||
|
#if CLASS_INIT_GUID
|
||||||
|
#include <initguid.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <mountdev.h>
|
||||||
|
#include <ioevent.h>
|
||||||
|
#include <pseh/pseh2.h>
|
||||||
|
|
||||||
|
extern CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[];
|
||||||
|
|
||||||
|
extern GUID ClassGuidQueryRegInfoEx;
|
||||||
|
|
||||||
|
|
||||||
|
#define CLASSP_REG_SUBKEY_NAME (L"Classpnp")
|
||||||
|
|
||||||
|
#define CLASSP_REG_HACK_VALUE_NAME (L"HackMask")
|
||||||
|
#define CLASSP_REG_MMC_DETECTION_VALUE_NAME (L"MMCDetectionState")
|
||||||
|
#define CLASSP_REG_WRITE_CACHE_VALUE_NAME (L"WriteCacheEnableOverride")
|
||||||
|
#define CLASSP_REG_PERF_RESTORE_VALUE_NAME (L"RestorePerfAtCount")
|
||||||
|
#define CLASSP_REG_REMOVAL_POLICY_VALUE_NAME (L"UserRemovalPolicy")
|
||||||
|
|
||||||
|
#define CLASS_PERF_RESTORE_MINIMUM (0x10)
|
||||||
|
#define CLASS_ERROR_LEVEL_1 (0x4)
|
||||||
|
#define CLASS_ERROR_LEVEL_2 (0x8)
|
||||||
|
|
||||||
|
#define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
|
||||||
|
#define FDO_HACK_GESN_IS_BAD (0x00000002)
|
||||||
|
#define FDO_HACK_NO_SYNC_CACHE (0x00000004)
|
||||||
|
|
||||||
|
#define FDO_HACK_VALID_FLAGS (0x00000007)
|
||||||
|
#define FDO_HACK_INVALID_FLAGS (~FDO_HACK_VALID_FLAGS)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lots of retries of synchronized SCSI commands that devices may not
|
||||||
|
* even support really slows down the system (especially while booting).
|
||||||
|
* (Even GetDriveCapacity may be failed on purpose if an external disk is powered off).
|
||||||
|
* If a disk cannot return a small initialization buffer at startup
|
||||||
|
* in two attempts (with delay interval) then we cannot expect it to return
|
||||||
|
* data consistently with four retries.
|
||||||
|
* So don't set the retry counts as high here as for data SRBs.
|
||||||
|
*
|
||||||
|
* If we find that these requests are failing consecutively,
|
||||||
|
* despite the retry interval, on otherwise reliable media,
|
||||||
|
* then we should either increase the retry interval for
|
||||||
|
* that failure or (by all means) increase these retry counts as appropriate.
|
||||||
|
*/
|
||||||
|
#define NUM_LOCKMEDIAREMOVAL_RETRIES 1
|
||||||
|
#define NUM_MODESENSE_RETRIES 1
|
||||||
|
#define NUM_DRIVECAPACITY_RETRIES 1
|
||||||
|
|
||||||
|
|
||||||
|
#define CLASS_FILE_OBJECT_EXTENSION_KEY 'eteP'
|
||||||
|
#define CLASSP_VOLUME_VERIFY_CHECKED 0x34
|
||||||
|
|
||||||
|
#define CLASS_TAG_PRIVATE_DATA 'CPcS'
|
||||||
|
#define CLASS_TAG_PRIVATE_DATA_FDO 'FPcS'
|
||||||
|
#define CLASS_TAG_PRIVATE_DATA_PDO 'PPcS'
|
||||||
|
|
||||||
|
struct _MEDIA_CHANGE_DETECTION_INFO {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mutex to synchronize enable/disable requests and media state changes
|
||||||
|
//
|
||||||
|
|
||||||
|
KMUTEX MediaChangeMutex;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The current state of the media (present, not present, unknown)
|
||||||
|
// protected by MediaChangeSynchronizationEvent
|
||||||
|
//
|
||||||
|
|
||||||
|
MEDIA_CHANGE_DETECTION_STATE MediaChangeDetectionState;
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a count of how many time MCD has been disabled. if it is
|
||||||
|
// set to zero, then we'll poll the device for MCN events with the
|
||||||
|
// then-current method (ie. TEST UNIT READY or GESN). this is
|
||||||
|
// protected by MediaChangeMutex
|
||||||
|
//
|
||||||
|
|
||||||
|
LONG MediaChangeDetectionDisableCount;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The timer value to support media change events. This is a countdown
|
||||||
|
// value used to determine when to poll the device for a media change.
|
||||||
|
// The max value for the timer is 255 seconds. This is not protected
|
||||||
|
// by an event -- simply InterlockedExchanged() as needed.
|
||||||
|
//
|
||||||
|
|
||||||
|
LONG MediaChangeCountDown;
|
||||||
|
|
||||||
|
//
|
||||||
|
// recent changes allowed instant retries of the MCN irp. Since this
|
||||||
|
// could cause an infinite loop, keep a count of how many times we've
|
||||||
|
// retried immediately so that we can catch if the count exceeds an
|
||||||
|
// arbitrary limit.
|
||||||
|
//
|
||||||
|
|
||||||
|
LONG MediaChangeRetryCount;
|
||||||
|
|
||||||
|
//
|
||||||
|
// use GESN if it's available
|
||||||
|
//
|
||||||
|
|
||||||
|
struct {
|
||||||
|
BOOLEAN Supported;
|
||||||
|
BOOLEAN HackEventMask;
|
||||||
|
UCHAR EventMask;
|
||||||
|
UCHAR NoChangeEventMask;
|
||||||
|
PUCHAR Buffer;
|
||||||
|
PMDL Mdl;
|
||||||
|
ULONG BufferSize;
|
||||||
|
} Gesn;
|
||||||
|
|
||||||
|
//
|
||||||
|
// If this value is one, then the irp is currently in use.
|
||||||
|
// If this value is zero, then the irp is available.
|
||||||
|
// Use InterlockedCompareExchange() to set from "available" to "in use".
|
||||||
|
// ASSERT that InterlockedCompareExchange() showed previous value of
|
||||||
|
// "in use" when changing back to "available" state.
|
||||||
|
// This also implicitly protects the MediaChangeSrb and SenseBuffer
|
||||||
|
//
|
||||||
|
|
||||||
|
LONG MediaChangeIrpInUse;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer to the irp to be used for media change detection.
|
||||||
|
// protected by Interlocked MediaChangeIrpInUse
|
||||||
|
//
|
||||||
|
|
||||||
|
PIRP MediaChangeIrp;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The srb for the media change detection.
|
||||||
|
// protected by Interlocked MediaChangeIrpInUse
|
||||||
|
//
|
||||||
|
|
||||||
|
SCSI_REQUEST_BLOCK MediaChangeSrb;
|
||||||
|
PUCHAR SenseBuffer;
|
||||||
|
ULONG SrbFlags;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Second timer to keep track of how long the media change IRP has been
|
||||||
|
// in use. If this value exceeds the timeout (#defined) then we should
|
||||||
|
// print out a message to the user and set the MediaChangeIrpLost flag
|
||||||
|
// protected by using Interlocked() operations in ClasspSendMediaStateIrp,
|
||||||
|
// the only routine which should modify this value.
|
||||||
|
//
|
||||||
|
|
||||||
|
LONG MediaChangeIrpTimeInUse;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set by CdRomTickHandler when we determine that the media change irp has
|
||||||
|
// been lost
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN MediaChangeIrpLost;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SimpleMediaLock,
|
||||||
|
SecureMediaLock,
|
||||||
|
InternalMediaLock
|
||||||
|
} MEDIA_LOCK_TYPE, *PMEDIA_LOCK_TYPE;
|
||||||
|
|
||||||
|
typedef struct _FAILURE_PREDICTION_INFO {
|
||||||
|
FAILURE_PREDICTION_METHOD Method;
|
||||||
|
ULONG CountDown; // Countdown timer
|
||||||
|
ULONG Period; // Countdown period
|
||||||
|
|
||||||
|
PIO_WORKITEM WorkQueueItem;
|
||||||
|
|
||||||
|
KEVENT Event;
|
||||||
|
} FAILURE_PREDICTION_INFO, *PFAILURE_PREDICTION_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// This struct must always fit within four PVOIDs of info,
|
||||||
|
// as it uses the irp's "PVOID DriverContext[4]" to store
|
||||||
|
// this info
|
||||||
|
//
|
||||||
|
typedef struct _CLASS_RETRY_INFO {
|
||||||
|
struct _CLASS_RETRY_INFO *Next;
|
||||||
|
} CLASS_RETRY_INFO, *PCLASS_RETRY_INFO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _CSCAN_LIST {
|
||||||
|
|
||||||
|
//
|
||||||
|
// The current block which has an outstanding request.
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONGLONG BlockNumber;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The list of blocks past the CurrentBlock to which we're going to do
|
||||||
|
// i/o. This list is maintained in sorted order.
|
||||||
|
//
|
||||||
|
|
||||||
|
LIST_ENTRY CurrentSweep;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The list of blocks behind the current block for which we'll have to
|
||||||
|
// wait until the next scan across the disk. This is kept as a stack,
|
||||||
|
// the cost of sorting it is taken when it's moved over to be the
|
||||||
|
// running list.
|
||||||
|
//
|
||||||
|
|
||||||
|
LIST_ENTRY NextSweep;
|
||||||
|
|
||||||
|
} CSCAN_LIST, *PCSCAN_LIST;
|
||||||
|
|
||||||
|
//
|
||||||
|
// add to the front of this structure to help prevent illegal
|
||||||
|
// snooping by other utilities.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum _CLASS_DETECTION_STATE {
|
||||||
|
ClassDetectionUnknown = 0,
|
||||||
|
ClassDetectionUnsupported = 1,
|
||||||
|
ClassDetectionSupported = 2
|
||||||
|
} CLASS_DETECTION_STATE, *PCLASS_DETECTION_STATE;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _CLASS_ERROR_LOG_DATA {
|
||||||
|
LARGE_INTEGER TickCount; // Offset 0x00
|
||||||
|
ULONG PortNumber; // Offset 0x08
|
||||||
|
|
||||||
|
UCHAR ErrorPaging : 1; // Offset 0x0c
|
||||||
|
UCHAR ErrorRetried : 1;
|
||||||
|
UCHAR ErrorUnhandled : 1;
|
||||||
|
UCHAR ErrorReserved : 5;
|
||||||
|
|
||||||
|
UCHAR Reserved[3];
|
||||||
|
|
||||||
|
SCSI_REQUEST_BLOCK Srb; // Offset 0x10
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We define the SenseData as the default length.
|
||||||
|
* Since the sense data returned by the port driver may be longer,
|
||||||
|
* SenseData must be at the end of this structure.
|
||||||
|
* For our internal error log, we only log the default length.
|
||||||
|
*/
|
||||||
|
SENSE_DATA SenseData; // Offset 0x50 for x86 (or 0x68 for ia64) (ULONG32 Alignment required!)
|
||||||
|
} CLASS_ERROR_LOG_DATA, *PCLASS_ERROR_LOG_DATA;
|
||||||
|
|
||||||
|
#define NUM_ERROR_LOG_ENTRIES 16
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _TRANSFER_PACKET {
|
||||||
|
|
||||||
|
LIST_ENTRY AllPktsListEntry; // entry in fdoData's static AllTransferPacketsList
|
||||||
|
SINGLE_LIST_ENTRY SlistEntry; // for when in free list (use fast slist)
|
||||||
|
|
||||||
|
PIRP Irp;
|
||||||
|
PDEVICE_OBJECT Fdo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the client IRP that this TRANSFER_PACKET is currently
|
||||||
|
* servicing.
|
||||||
|
*/
|
||||||
|
PIRP OriginalIrp;
|
||||||
|
BOOLEAN CompleteOriginalIrpWhenLastPacketCompletes;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stuff for retrying the transfer.
|
||||||
|
*/
|
||||||
|
ULONG NumRetries;
|
||||||
|
KTIMER RetryTimer;
|
||||||
|
KDPC RetryTimerDPC;
|
||||||
|
ULONG RetryIntervalSec;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event for synchronizing the transfer (optional).
|
||||||
|
* (Note that we can't have the event in the packet itself because
|
||||||
|
* by the time a thread waits on an event the packet may have
|
||||||
|
* been completed and re-issued.
|
||||||
|
*/
|
||||||
|
PKEVENT SyncEventPtr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stuff for retrying during extreme low-memory stress
|
||||||
|
* (when we retry 1 page at a time).
|
||||||
|
*/
|
||||||
|
BOOLEAN InLowMemRetry;
|
||||||
|
PUCHAR LowMemRetry_remainingBufPtr;
|
||||||
|
ULONG LowMemRetry_remainingBufLen;
|
||||||
|
LARGE_INTEGER LowMemRetry_nextChunkTargetLocation;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fields used for cancelling the packet.
|
||||||
|
*/
|
||||||
|
// BOOLEAN Cancelled;
|
||||||
|
// KEVENT CancelledEvent;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We keep the buffer and length values here as well
|
||||||
|
* as in the SRB because some miniports return
|
||||||
|
* the transferred length in SRB.DataTransferLength,
|
||||||
|
* and if the SRB failed we need that value again for the retry.
|
||||||
|
* We don't trust the lower stack to preserve any of these values in the SRB.
|
||||||
|
*/
|
||||||
|
PUCHAR BufPtrCopy;
|
||||||
|
ULONG BufLenCopy;
|
||||||
|
LARGE_INTEGER TargetLocationCopy;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a standard SCSI structure that receives a detailed
|
||||||
|
* report about a SCSI error on the hardware.
|
||||||
|
*/
|
||||||
|
SENSE_DATA SrbErrorSenseData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the SRB block for this TRANSFER_PACKET.
|
||||||
|
* For IOCTLs, the SRB block includes two DWORDs for
|
||||||
|
* device object and ioctl code; so these must
|
||||||
|
* immediately follow the SRB block.
|
||||||
|
*/
|
||||||
|
SCSI_REQUEST_BLOCK Srb;
|
||||||
|
// ULONG SrbIoctlDevObj; // not handling ioctls yet
|
||||||
|
// ULONG SrbIoctlCode;
|
||||||
|
|
||||||
|
} TRANSFER_PACKET, *PTRANSFER_PACKET;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MIN_INITIAL_TRANSFER_PACKETS is the minimum number of packets that
|
||||||
|
* we preallocate at startup for each device (we need at least one packet
|
||||||
|
* to guarantee forward progress during memory stress).
|
||||||
|
* MIN_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
|
||||||
|
* we allow to build up and remain for each device;
|
||||||
|
* we _lazily_ work down to this number when they're not needed.
|
||||||
|
* MAX_WORKINGSET_TRANSFER_PACKETS is the number of TRANSFER_PACKETs
|
||||||
|
* that we _immediately_ reduce to when they are not needed.
|
||||||
|
*
|
||||||
|
* The absolute maximum number of packets that we will allocate is
|
||||||
|
* whatever is required by the current activity, up to the memory limit;
|
||||||
|
* as soon as stress ends, we snap down to MAX_WORKINGSET_TRANSFER_PACKETS;
|
||||||
|
* we then lazily work down to MIN_WORKINGSET_TRANSFER_PACKETS.
|
||||||
|
*/
|
||||||
|
#define MIN_INITIAL_TRANSFER_PACKETS 1
|
||||||
|
#define MIN_WORKINGSET_TRANSFER_PACKETS_Consumer 4
|
||||||
|
#define MAX_WORKINGSET_TRANSFER_PACKETS_Consumer 64
|
||||||
|
#define MIN_WORKINGSET_TRANSFER_PACKETS_Server 64
|
||||||
|
#define MAX_WORKINGSET_TRANSFER_PACKETS_Server 1024
|
||||||
|
#define MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise 256
|
||||||
|
#define MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise 2048
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// add to the front of this structure to help prevent illegal
|
||||||
|
// snooping by other utilities.
|
||||||
|
//
|
||||||
|
struct _CLASS_PRIVATE_FDO_DATA {
|
||||||
|
|
||||||
|
//
|
||||||
|
// this private structure allows us to
|
||||||
|
// dynamically re-enable the perf benefits
|
||||||
|
// lost due to transient error conditions.
|
||||||
|
// in w2k, a reboot was required. :(
|
||||||
|
//
|
||||||
|
struct {
|
||||||
|
ULONG OriginalSrbFlags;
|
||||||
|
ULONG SuccessfulIO;
|
||||||
|
ULONG ReEnableThreshhold; // 0 means never
|
||||||
|
} Perf;
|
||||||
|
|
||||||
|
ULONG_PTR HackFlags;
|
||||||
|
|
||||||
|
STORAGE_HOTPLUG_INFO HotplugInfo;
|
||||||
|
|
||||||
|
// Legacy. Still used by obsolete legacy code.
|
||||||
|
struct {
|
||||||
|
LARGE_INTEGER Delta; // in ticks
|
||||||
|
LARGE_INTEGER Tick; // when it should fire
|
||||||
|
PCLASS_RETRY_INFO ListHead; // singly-linked list
|
||||||
|
ULONG Granularity; // static
|
||||||
|
KSPIN_LOCK Lock; // protective spin lock
|
||||||
|
KDPC Dpc; // DPC routine object
|
||||||
|
KTIMER Timer; // timer to fire DPC
|
||||||
|
} Retry;
|
||||||
|
|
||||||
|
BOOLEAN TimerStarted;
|
||||||
|
BOOLEAN LoggedTURFailureSinceLastIO;
|
||||||
|
|
||||||
|
//
|
||||||
|
// privately allocated release queue irp
|
||||||
|
// protected by fdoExtension->ReleaseQueueSpinLock
|
||||||
|
//
|
||||||
|
BOOLEAN ReleaseQueueIrpAllocated;
|
||||||
|
PIRP ReleaseQueueIrp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queues for TRANSFER_PACKETs that contextualize the IRPs and SRBs
|
||||||
|
* that we send down to the port driver.
|
||||||
|
* (The free list is an slist so that we can use fast
|
||||||
|
* interlocked operations on it; but the relatively-static
|
||||||
|
* AllTransferPacketsList list has to be
|
||||||
|
* a doubly-linked list since we have to dequeue from the middle).
|
||||||
|
*/
|
||||||
|
LIST_ENTRY AllTransferPacketsList;
|
||||||
|
SLIST_HEADER FreeTransferPacketsList;
|
||||||
|
ULONG NumFreeTransferPackets;
|
||||||
|
ULONG NumTotalTransferPackets;
|
||||||
|
ULONG DbgPeakNumTransferPackets;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Queue for deferred client irps
|
||||||
|
*/
|
||||||
|
LIST_ENTRY DeferredClientIrpList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Precomputed maximum transfer length for the hardware.
|
||||||
|
*/
|
||||||
|
ULONG HwMaxXferLen;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SCSI_REQUEST_BLOCK template preconfigured with the constant values.
|
||||||
|
* This is slapped into the SRB in the TRANSFER_PACKET for each transfer.
|
||||||
|
*/
|
||||||
|
SCSI_REQUEST_BLOCK SrbTemplate;
|
||||||
|
|
||||||
|
KSPIN_LOCK SpinLock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Circular array of timestamped logs of errors that occurred on this device.
|
||||||
|
*/
|
||||||
|
ULONG ErrorLogNextIndex;
|
||||||
|
CLASS_ERROR_LOG_DATA ErrorLogs[NUM_ERROR_LOG_ENTRIES];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
|
|
||||||
|
#define NOT_READY_RETRY_INTERVAL 10
|
||||||
|
#define MINIMUM_RETRY_UNITS ((LONGLONG)32)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple singly-linked-list queuing macros, with no synchronization.
|
||||||
|
*/
|
||||||
|
static inline VOID SimpleInitSlistHdr(SINGLE_LIST_ENTRY *SListHdr)
|
||||||
|
{
|
||||||
|
SListHdr->Next = NULL;
|
||||||
|
}
|
||||||
|
static inline VOID SimplePushSlist(SINGLE_LIST_ENTRY *SListHdr, SINGLE_LIST_ENTRY *SListEntry)
|
||||||
|
{
|
||||||
|
SListEntry->Next = SListHdr->Next;
|
||||||
|
SListHdr->Next = SListEntry;
|
||||||
|
}
|
||||||
|
static inline SINGLE_LIST_ENTRY *SimplePopSlist(SINGLE_LIST_ENTRY *SListHdr)
|
||||||
|
{
|
||||||
|
SINGLE_LIST_ENTRY *sListEntry = SListHdr->Next;
|
||||||
|
if (sListEntry){
|
||||||
|
SListHdr->Next = sListEntry->Next;
|
||||||
|
sListEntry->Next = NULL;
|
||||||
|
}
|
||||||
|
return sListEntry;
|
||||||
|
}
|
||||||
|
static inline BOOLEAN SimpleIsSlistEmpty(SINGLE_LIST_ENTRY *SListHdr)
|
||||||
|
{
|
||||||
|
return (SListHdr->Next == NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DriverEntry(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClassUnload(
|
||||||
|
IN PDRIVER_OBJECT DriverObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassCreateClose(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspCreateClose(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspCleanupProtectedLocks(
|
||||||
|
IN PFILE_OBJECT_EXTENSION FsContext
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspEjectionControl(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN MEDIA_LOCK_TYPE LockType,
|
||||||
|
IN BOOLEAN Lock
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassReadWrite(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassDeviceControlDispatch(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassDeviceControl(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassDispatchPnp(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassPnpStartDevice(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassInternalIoControl (
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassShutdownFlush(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassSystemControl(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Class internal routines
|
||||||
|
//
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassAddDevice(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN OUT PDEVICE_OBJECT PhysicalDeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspSendSynchronousCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
RetryRequest(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
BOOLEAN Associated,
|
||||||
|
ULONG RetryInterval
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassIoCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassPnpQueryFdoRelations(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassRetrieveDeviceRelations(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN DEVICE_RELATION_TYPE RelationType,
|
||||||
|
OUT PDEVICE_RELATIONS *DeviceRelations
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassGetPdoId(
|
||||||
|
IN PDEVICE_OBJECT Pdo,
|
||||||
|
IN BUS_QUERY_ID_TYPE IdType,
|
||||||
|
IN PUNICODE_STRING IdString
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassQueryPnpCapabilities(
|
||||||
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||||
|
IN PDEVICE_CAPABILITIES Capabilities
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspStartIo(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspPagingNotificationCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PDEVICE_OBJECT RealDeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspMediaChangeCompletion(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
PFILE_OBJECT_EXTENSION
|
||||||
|
ClasspGetFsContext(
|
||||||
|
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||||
|
IN PFILE_OBJECT FileObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspMcnControl(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspRegisterMountedDeviceInterface(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspDisableTimer(
|
||||||
|
PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspEnableTimer(
|
||||||
|
PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// routines for dictionary list support
|
||||||
|
//
|
||||||
|
|
||||||
|
VOID
|
||||||
|
InitializeDictionary(
|
||||||
|
IN PDICTIONARY Dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
TestDictionarySignature(
|
||||||
|
IN PDICTIONARY Dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
AllocateDictionaryEntry(
|
||||||
|
IN PDICTIONARY Dictionary,
|
||||||
|
IN ULONGLONG Key,
|
||||||
|
IN ULONG Size,
|
||||||
|
IN ULONG Tag,
|
||||||
|
OUT PVOID *Entry
|
||||||
|
);
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
GetDictionaryEntry(
|
||||||
|
IN PDICTIONARY Dictionary,
|
||||||
|
IN ULONGLONG Key
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FreeDictionaryEntry(
|
||||||
|
IN PDICTIONARY Dictionary,
|
||||||
|
IN PVOID Entry
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspAllocateReleaseRequest(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspFreeReleaseRequest(
|
||||||
|
IN PDEVICE_OBJECT Fdo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassReleaseQueueCompletion(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspReleaseQueue(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP ReleaseQueueIrp
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspDisablePowerNotification(
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// class power routines
|
||||||
|
//
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassDispatchPower(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassMinimalPowerHandler(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Child list routines
|
||||||
|
//
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClassAddChild(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
|
||||||
|
IN PPHYSICAL_DEVICE_EXTENSION Child,
|
||||||
|
IN BOOLEAN AcquireLock
|
||||||
|
);
|
||||||
|
|
||||||
|
PPHYSICAL_DEVICE_EXTENSION
|
||||||
|
ClassRemoveChild(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION Parent,
|
||||||
|
IN PPHYSICAL_DEVICE_EXTENSION Child,
|
||||||
|
IN BOOLEAN AcquireLock
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspRetryDpcTimer(
|
||||||
|
IN PCLASS_PRIVATE_FDO_DATA FdoData
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspRetryRequestDpc(
|
||||||
|
IN PKDPC Dpc,
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PVOID Arg1,
|
||||||
|
IN PVOID Arg2
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClassFreeOrReuseSrb(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClassRetryRequest(
|
||||||
|
IN PDEVICE_OBJECT SelfDeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN LARGE_INTEGER TimeDelta100ns // in 100ns units
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspBuildRequestEx(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION Fdo,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspAllocateReleaseQueueIrp(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspInitializeGesn(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN PMEDIA_CHANGE_DETECTION_INFO Info
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspSendNotification(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN const GUID * Guid,
|
||||||
|
IN ULONG ExtraDataSize,
|
||||||
|
IN PVOID ExtraData
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClassSendEjectionNotification(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspScanForSpecialInRegistry(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspScanForClassHacks(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN ULONG_PTR Data
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspInitializeHotplugInfo(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspPerfIncrementErrorCount(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
);
|
||||||
|
VOID
|
||||||
|
ClasspPerfIncrementSuccessfulIo(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo);
|
||||||
|
VOID DestroyTransferPacket(PTRANSFER_PACKET Pkt);
|
||||||
|
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt);
|
||||||
|
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded);
|
||||||
|
VOID SetupReadWriteTransferPacket(PTRANSFER_PACKET pkt, PVOID Buf, ULONG Len, LARGE_INTEGER DiskLocation, PIRP OriginalIrp);
|
||||||
|
VOID SubmitTransferPacket(PTRANSFER_PACKET Pkt);
|
||||||
|
NTSTATUS TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context);
|
||||||
|
VOID ServiceTransferRequest(PDEVICE_OBJECT Fdo, PIRP Irp);
|
||||||
|
VOID TransferPacketRetryTimerDpc(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2);
|
||||||
|
BOOLEAN InterpretTransferPacketError(PTRANSFER_PACKET Pkt);
|
||||||
|
BOOLEAN RetryTransferPacket(PTRANSFER_PACKET Pkt);
|
||||||
|
VOID EnqueueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp);
|
||||||
|
PIRP DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData);
|
||||||
|
VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation);
|
||||||
|
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt);
|
||||||
|
VOID SetupEjectionTransferPacket(TRANSFER_PACKET *Pkt, BOOLEAN PreventMediaRemoval, PKEVENT SyncEventPtr, PIRP OriginalIrp);
|
||||||
|
VOID SetupModeSenseTransferPacket(TRANSFER_PACKET *Pkt, PKEVENT SyncEventPtr, PVOID ModeSenseBuffer, UCHAR ModeSenseBufferLen, UCHAR PageMode, PIRP OriginalIrp);
|
||||||
|
VOID SetupDriveCapacityTransferPacket(TRANSFER_PACKET *Pkt, PVOID ReadCapacityBuffer, ULONG ReadCapacityBufferLen, PKEVENT SyncEventPtr, PIRP OriginalIrp);
|
||||||
|
PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen);
|
||||||
|
VOID FreeDeviceInputMdl(PMDL Mdl);
|
||||||
|
NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo);
|
||||||
|
VOID DestroyAllTransferPackets(PDEVICE_OBJECT Fdo);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
37
reactos/drivers/storage/classpnp/classpnp.rbuild
Normal file
37
reactos/drivers/storage/classpnp/classpnp.rbuild
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!DOCTYPE module SYSTEM "../../../../tools/rbuild/project.dtd">
|
||||||
|
<module name="classpnp" type="kernelmodedriver" installbase="system32/drivers" installname="classpnp.sys">
|
||||||
|
<bootstrap installbase="$(CDOUTPUT)" />
|
||||||
|
<importlibrary definition="class.def" />
|
||||||
|
<library>ntoskrnl</library>
|
||||||
|
<library>hal</library>
|
||||||
|
<library>pseh</library>
|
||||||
|
<library>libcntpr</library>
|
||||||
|
<include base="classpnp">../inc</include>
|
||||||
|
<define name="CLASS_GLOBAL_BREAK_ON_LOST_IRPS">0</define>
|
||||||
|
<define name="CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB">100</define>
|
||||||
|
<define name="CLASS_GLOBAL_USE_DELAYED_RETRY">1</define>
|
||||||
|
<define name="CLASS_GLOBAL_BUFFERED_DEBUG_PRINT">0</define>
|
||||||
|
<define name="CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE">512</define>
|
||||||
|
<define name="CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS">512</define>
|
||||||
|
<group compilerset="gcc">
|
||||||
|
<compilerflag>-mrtd</compilerflag>
|
||||||
|
<compilerflag>-fno-builtin</compilerflag>
|
||||||
|
<compilerflag>-w</compilerflag>
|
||||||
|
</group>
|
||||||
|
<file>autorun.c</file>
|
||||||
|
<file>class.c</file>
|
||||||
|
<file>classwmi.c</file>
|
||||||
|
<file>create.c</file>
|
||||||
|
<file>data.c</file>
|
||||||
|
<file>dictlib.c</file>
|
||||||
|
<file>lock.c</file>
|
||||||
|
<file>power.c</file>
|
||||||
|
<file>xferpkt.c</file>
|
||||||
|
<file>clntirp.c</file>
|
||||||
|
<file>retry.c</file>
|
||||||
|
<file>utils.c</file>
|
||||||
|
<file>obsolete.c</file>
|
||||||
|
<file>debug.c</file>
|
||||||
|
<file>class.rc</file>
|
||||||
|
</module>
|
778
reactos/drivers/storage/classpnp/classwmi.c
Normal file
778
reactos/drivers/storage/classpnp/classwmi.c
Normal file
|
@ -0,0 +1,778 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
classwmi.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
SCSI class driver routines
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "stddef.h"
|
||||||
|
#include "ntddk.h"
|
||||||
|
#include "scsi.h"
|
||||||
|
|
||||||
|
#include "classpnp.h"
|
||||||
|
|
||||||
|
#include "mountdev.h"
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "wmistr.h"
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassSystemControl(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
ClassFindGuid(
|
||||||
|
PGUIDREGINFO GuidList,
|
||||||
|
ULONG GuidCount,
|
||||||
|
LPGUID Guid,
|
||||||
|
PULONG GuidIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is the name for the MOF resource that must be part of all drivers that
|
||||||
|
// register via this interface.
|
||||||
|
#define MOFRESOURCENAME L"MofResourceName"
|
||||||
|
|
||||||
|
//
|
||||||
|
// What can be paged ???
|
||||||
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, ClassSystemControl)
|
||||||
|
#pragma alloc_text(PAGE, ClassFindGuid)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassFindGuid()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This routine will search the list of guids registered and return
|
||||||
|
the index for the one that was registered.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
GuidList is the list of guids to search
|
||||||
|
|
||||||
|
GuidCount is the count of guids in the list
|
||||||
|
|
||||||
|
Guid is the guid being searched for
|
||||||
|
|
||||||
|
*GuidIndex returns the index to the guid
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
TRUE if guid is found else FALSE
|
||||||
|
|
||||||
|
--*/
|
||||||
|
BOOLEAN
|
||||||
|
ClassFindGuid(
|
||||||
|
PGUIDREGINFO GuidList,
|
||||||
|
ULONG GuidCount,
|
||||||
|
LPGUID Guid,
|
||||||
|
PULONG GuidIndex
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ULONG i;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
for (i = 0; i < GuidCount; i++)
|
||||||
|
{
|
||||||
|
if (IsEqualGUID(Guid, &GuidList[i].Guid))
|
||||||
|
{
|
||||||
|
*GuidIndex = i;
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(FALSE);
|
||||||
|
} // end ClassFindGuid()
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassSystemControl()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Dispatch routine for IRP_MJ_SYSTEM_CONTROL. This routine will process
|
||||||
|
all wmi requests received, forwarding them if they are not for this
|
||||||
|
driver or determining if the guid is valid and if so passing it to
|
||||||
|
the driver specific function for handing wmi requests.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - Supplies a pointer to the device object for this request.
|
||||||
|
|
||||||
|
Irp - Supplies the Irp making the request.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
status
|
||||||
|
|
||||||
|
--*/
|
||||||
|
NTSTATUS
|
||||||
|
ClassSystemControl(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||||
|
PCLASS_DRIVER_EXTENSION driverExtension;
|
||||||
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
ULONG isRemoved;
|
||||||
|
ULONG bufferSize;
|
||||||
|
PUCHAR buffer;
|
||||||
|
NTSTATUS status;
|
||||||
|
UCHAR minorFunction;
|
||||||
|
ULONG guidIndex;
|
||||||
|
PCLASS_WMI_INFO classWmiInfo;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure device has not been removed
|
||||||
|
isRemoved = ClassAcquireRemoveLock(DeviceObject, Irp);
|
||||||
|
if(isRemoved)
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST;
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_DEVICE_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the irp is not a WMI irp or it is not targetted at this device
|
||||||
|
// or this device has not regstered with WMI then just forward it on.
|
||||||
|
minorFunction = irpStack->MinorFunction;
|
||||||
|
if ((minorFunction > IRP_MN_EXECUTE_METHOD) ||
|
||||||
|
(irpStack->Parameters.WMI.ProviderId != (ULONG_PTR)DeviceObject) ||
|
||||||
|
((minorFunction != IRP_MN_REGINFO) &&
|
||||||
|
(commonExtension->GuidRegInfo == NULL)))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// CONSIDER: Do I need to hang onto lock until IoCallDriver returns ?
|
||||||
|
IoSkipCurrentIrpStackLocation(Irp);
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
return(IoCallDriver(commonExtension->LowerDeviceObject, Irp));
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
|
||||||
|
bufferSize = irpStack->Parameters.WMI.BufferSize;
|
||||||
|
|
||||||
|
if (minorFunction != IRP_MN_REGINFO)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// For all requests other than query registration info we are passed
|
||||||
|
// a guid. Determine if the guid is one that is supported by the
|
||||||
|
// device.
|
||||||
|
if (ClassFindGuid(commonExtension->GuidRegInfo,
|
||||||
|
commonExtension->GuidCount,
|
||||||
|
(LPGUID)irpStack->Parameters.WMI.DataPath,
|
||||||
|
&guidIndex))
|
||||||
|
{
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
status = STATUS_WMI_GUID_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status) &&
|
||||||
|
((minorFunction == IRP_MN_QUERY_SINGLE_INSTANCE) ||
|
||||||
|
(minorFunction == IRP_MN_CHANGE_SINGLE_INSTANCE) ||
|
||||||
|
(minorFunction == IRP_MN_CHANGE_SINGLE_ITEM) ||
|
||||||
|
(minorFunction == IRP_MN_EXECUTE_METHOD)))
|
||||||
|
{
|
||||||
|
if ( (((PWNODE_HEADER)buffer)->Flags) &
|
||||||
|
WNODE_FLAG_STATIC_INSTANCE_NAMES)
|
||||||
|
{
|
||||||
|
if ( ((PWNODE_SINGLE_INSTANCE)buffer)->InstanceIndex != 0 )
|
||||||
|
{
|
||||||
|
status = STATUS_WMI_INSTANCE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = STATUS_WMI_INSTANCE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
Irp->IoStatus.Status = status;
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||||
|
return(status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
driverExtension = commonExtension->DriverExtension;
|
||||||
|
|
||||||
|
classWmiInfo = commonExtension->IsFdo ?
|
||||||
|
&driverExtension->InitData.FdoData.ClassWmiInfo :
|
||||||
|
&driverExtension->InitData.PdoData.ClassWmiInfo;
|
||||||
|
switch(minorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_REGINFO:
|
||||||
|
{
|
||||||
|
ULONG guidCount;
|
||||||
|
PGUIDREGINFO guidList;
|
||||||
|
PWMIREGINFOW wmiRegInfo;
|
||||||
|
PWMIREGGUIDW wmiRegGuid;
|
||||||
|
PDEVICE_OBJECT pdo;
|
||||||
|
PUNICODE_STRING regPath;
|
||||||
|
PWCHAR stringPtr;
|
||||||
|
ULONG retSize;
|
||||||
|
ULONG registryPathOffset;
|
||||||
|
ULONG mofResourceOffset;
|
||||||
|
ULONG bufferNeeded;
|
||||||
|
ULONG i;
|
||||||
|
ULONG_PTR nameInfo;
|
||||||
|
ULONG nameSize, nameOffset, nameFlags;
|
||||||
|
UNICODE_STRING name, mofName;
|
||||||
|
PCLASS_QUERY_WMI_REGINFO_EX ClassQueryWmiRegInfoEx;
|
||||||
|
|
||||||
|
name.Buffer = NULL;
|
||||||
|
name.Length = 0;
|
||||||
|
name.MaximumLength = 0;
|
||||||
|
nameFlags = 0;
|
||||||
|
|
||||||
|
ClassQueryWmiRegInfoEx = commonExtension->IsFdo ?
|
||||||
|
driverExtension->ClassFdoQueryWmiRegInfoEx :
|
||||||
|
driverExtension->ClassPdoQueryWmiRegInfoEx;
|
||||||
|
|
||||||
|
if (ClassQueryWmiRegInfoEx == NULL)
|
||||||
|
{
|
||||||
|
status = classWmiInfo->ClassQueryWmiRegInfo(
|
||||||
|
DeviceObject,
|
||||||
|
&nameFlags,
|
||||||
|
&name);
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&mofName, MOFRESOURCENAME);
|
||||||
|
} else {
|
||||||
|
RtlInitUnicodeString(&mofName, L"");
|
||||||
|
status = (*ClassQueryWmiRegInfoEx)(
|
||||||
|
DeviceObject,
|
||||||
|
&nameFlags,
|
||||||
|
&name,
|
||||||
|
&mofName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status) &&
|
||||||
|
(! (nameFlags & WMIREG_FLAG_INSTANCE_PDO) &&
|
||||||
|
(name.Buffer == NULL)))
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// if PDO flag not specified then an instance name must be
|
||||||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
guidList = classWmiInfo->GuidRegInfo;
|
||||||
|
guidCount = classWmiInfo->GuidCount;
|
||||||
|
|
||||||
|
nameOffset = sizeof(WMIREGINFO) +
|
||||||
|
guidCount * sizeof(WMIREGGUIDW);
|
||||||
|
|
||||||
|
if (nameFlags & WMIREG_FLAG_INSTANCE_PDO)
|
||||||
|
{
|
||||||
|
nameSize = 0;
|
||||||
|
nameInfo = commonExtension->IsFdo ?
|
||||||
|
(ULONG_PTR)((PFUNCTIONAL_DEVICE_EXTENSION)commonExtension)->LowerPdo :
|
||||||
|
(ULONG_PTR)DeviceObject;
|
||||||
|
} else {
|
||||||
|
nameFlags |= WMIREG_FLAG_INSTANCE_LIST;
|
||||||
|
nameSize = name.Length + sizeof(USHORT);
|
||||||
|
nameInfo = nameOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
mofResourceOffset = nameOffset + nameSize;
|
||||||
|
|
||||||
|
registryPathOffset = mofResourceOffset +
|
||||||
|
mofName.Length + sizeof(USHORT);
|
||||||
|
|
||||||
|
regPath = &driverExtension->RegistryPath;
|
||||||
|
bufferNeeded = registryPathOffset +
|
||||||
|
regPath->Length + sizeof(USHORT);
|
||||||
|
|
||||||
|
if (bufferNeeded <= bufferSize)
|
||||||
|
{
|
||||||
|
retSize = bufferNeeded;
|
||||||
|
|
||||||
|
commonExtension->GuidCount = guidCount;
|
||||||
|
commonExtension->GuidRegInfo = guidList;
|
||||||
|
|
||||||
|
wmiRegInfo = (PWMIREGINFO)buffer;
|
||||||
|
wmiRegInfo->BufferSize = bufferNeeded;
|
||||||
|
wmiRegInfo->NextWmiRegInfo = 0;
|
||||||
|
wmiRegInfo->MofResourceName = mofResourceOffset;
|
||||||
|
wmiRegInfo->RegistryPath = registryPathOffset;
|
||||||
|
wmiRegInfo->GuidCount = guidCount;
|
||||||
|
|
||||||
|
for (i = 0; i < guidCount; i++)
|
||||||
|
{
|
||||||
|
wmiRegGuid = &wmiRegInfo->WmiRegGuid[i];
|
||||||
|
wmiRegGuid->Guid = guidList[i].Guid;
|
||||||
|
wmiRegGuid->Flags = guidList[i].Flags | nameFlags;
|
||||||
|
wmiRegGuid->InstanceInfo = nameInfo;
|
||||||
|
wmiRegGuid->InstanceCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( nameFlags & WMIREG_FLAG_INSTANCE_LIST)
|
||||||
|
{
|
||||||
|
stringPtr = (PWCHAR)((PUCHAR)buffer + nameOffset);
|
||||||
|
*stringPtr++ = name.Length;
|
||||||
|
RtlCopyMemory(stringPtr,
|
||||||
|
name.Buffer,
|
||||||
|
name.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
stringPtr = (PWCHAR)((PUCHAR)buffer + mofResourceOffset);
|
||||||
|
*stringPtr++ = mofName.Length;
|
||||||
|
RtlCopyMemory(stringPtr,
|
||||||
|
mofName.Buffer,
|
||||||
|
mofName.Length);
|
||||||
|
|
||||||
|
stringPtr = (PWCHAR)((PUCHAR)buffer + registryPathOffset);
|
||||||
|
*stringPtr++ = regPath->Length;
|
||||||
|
RtlCopyMemory(stringPtr,
|
||||||
|
regPath->Buffer,
|
||||||
|
regPath->Length);
|
||||||
|
} else {
|
||||||
|
*((PULONG)buffer) = bufferNeeded;
|
||||||
|
retSize = sizeof(ULONG);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
retSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.Buffer != NULL)
|
||||||
|
{
|
||||||
|
ExFreePool(name.Buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = status;
|
||||||
|
Irp->IoStatus.Information = retSize;
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||||
|
return(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_QUERY_ALL_DATA:
|
||||||
|
{
|
||||||
|
PWNODE_ALL_DATA wnode;
|
||||||
|
ULONG bufferAvail;
|
||||||
|
|
||||||
|
wnode = (PWNODE_ALL_DATA)buffer;
|
||||||
|
|
||||||
|
if (bufferSize < sizeof(WNODE_ALL_DATA))
|
||||||
|
{
|
||||||
|
bufferAvail = 0;
|
||||||
|
} else {
|
||||||
|
bufferAvail = bufferSize - sizeof(WNODE_ALL_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
wnode->DataBlockOffset = sizeof(WNODE_ALL_DATA);
|
||||||
|
|
||||||
|
status = classWmiInfo->ClassQueryWmiDataBlock(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
bufferAvail,
|
||||||
|
buffer + sizeof(WNODE_ALL_DATA));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_QUERY_SINGLE_INSTANCE:
|
||||||
|
{
|
||||||
|
PWNODE_SINGLE_INSTANCE wnode;
|
||||||
|
ULONG dataBlockOffset;
|
||||||
|
|
||||||
|
wnode = (PWNODE_SINGLE_INSTANCE)buffer;
|
||||||
|
|
||||||
|
dataBlockOffset = wnode->DataBlockOffset;
|
||||||
|
|
||||||
|
status = classWmiInfo->ClassQueryWmiDataBlock(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
bufferSize - dataBlockOffset,
|
||||||
|
(PUCHAR)wnode + dataBlockOffset);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_CHANGE_SINGLE_INSTANCE:
|
||||||
|
{
|
||||||
|
PWNODE_SINGLE_INSTANCE wnode;
|
||||||
|
|
||||||
|
wnode = (PWNODE_SINGLE_INSTANCE)buffer;
|
||||||
|
|
||||||
|
status = classWmiInfo->ClassSetWmiDataBlock(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
wnode->SizeDataBlock,
|
||||||
|
(PUCHAR)wnode + wnode->DataBlockOffset);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_CHANGE_SINGLE_ITEM:
|
||||||
|
{
|
||||||
|
PWNODE_SINGLE_ITEM wnode;
|
||||||
|
|
||||||
|
wnode = (PWNODE_SINGLE_ITEM)buffer;
|
||||||
|
|
||||||
|
status = classWmiInfo->ClassSetWmiDataItem(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
wnode->ItemId,
|
||||||
|
wnode->SizeDataItem,
|
||||||
|
(PUCHAR)wnode + wnode->DataBlockOffset);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_EXECUTE_METHOD:
|
||||||
|
{
|
||||||
|
PWNODE_METHOD_ITEM wnode;
|
||||||
|
|
||||||
|
wnode = (PWNODE_METHOD_ITEM)buffer;
|
||||||
|
|
||||||
|
status = classWmiInfo->ClassExecuteWmiMethod(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
wnode->MethodId,
|
||||||
|
wnode->SizeDataBlock,
|
||||||
|
bufferSize - wnode->DataBlockOffset,
|
||||||
|
buffer + wnode->DataBlockOffset);
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_ENABLE_EVENTS:
|
||||||
|
{
|
||||||
|
status = classWmiInfo->ClassWmiFunctionControl(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
EventGeneration,
|
||||||
|
TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_DISABLE_EVENTS:
|
||||||
|
{
|
||||||
|
status = classWmiInfo->ClassWmiFunctionControl(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
EventGeneration,
|
||||||
|
FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_ENABLE_COLLECTION:
|
||||||
|
{
|
||||||
|
status = classWmiInfo->ClassWmiFunctionControl(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
DataBlockCollection,
|
||||||
|
TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_DISABLE_COLLECTION:
|
||||||
|
{
|
||||||
|
status = classWmiInfo->ClassWmiFunctionControl(
|
||||||
|
DeviceObject,
|
||||||
|
Irp,
|
||||||
|
guidIndex,
|
||||||
|
DataBlockCollection,
|
||||||
|
FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return(status);
|
||||||
|
} // end ClassSystemControl()
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassWmiCompleteRequest()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
|
||||||
|
This routine will do the work of completing a WMI irp. Depending upon the
|
||||||
|
the WMI request this routine will fixup the returned WNODE appropriately.
|
||||||
|
|
||||||
|
NOTE: This routine assumes that the ClassRemoveLock is held and it will
|
||||||
|
release it.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - Supplies a pointer to the device object for this request.
|
||||||
|
|
||||||
|
Irp - Supplies the Irp making the request.
|
||||||
|
|
||||||
|
Status - Status to complete the irp with. STATUS_BUFFER_TOO_SMALL is used
|
||||||
|
to indicate that more buffer is required for the data requested.
|
||||||
|
|
||||||
|
BufferUsed - number of bytes of actual data to return (not including WMI
|
||||||
|
specific structures)
|
||||||
|
|
||||||
|
PriorityBoost - priority boost to pass to ClassCompleteRequest
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
status
|
||||||
|
|
||||||
|
--*/
|
||||||
|
SCSIPORTAPI
|
||||||
|
NTSTATUS
|
||||||
|
ClassWmiCompleteRequest(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN NTSTATUS Status,
|
||||||
|
IN ULONG BufferUsed,
|
||||||
|
IN CCHAR PriorityBoost
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||||
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
UCHAR MinorFunction;
|
||||||
|
PUCHAR buffer;
|
||||||
|
ULONG retSize;
|
||||||
|
UCHAR minorFunction;
|
||||||
|
ULONG bufferSize;
|
||||||
|
|
||||||
|
minorFunction = irpStack->MinorFunction;
|
||||||
|
buffer = (PUCHAR)irpStack->Parameters.WMI.Buffer;
|
||||||
|
bufferSize = irpStack->Parameters.WMI.BufferSize;
|
||||||
|
|
||||||
|
switch(minorFunction)
|
||||||
|
{
|
||||||
|
case IRP_MN_QUERY_ALL_DATA:
|
||||||
|
{
|
||||||
|
PWNODE_ALL_DATA wnode;
|
||||||
|
PWNODE_TOO_SMALL wnodeTooSmall;
|
||||||
|
ULONG bufferNeeded;
|
||||||
|
|
||||||
|
wnode = (PWNODE_ALL_DATA)buffer;
|
||||||
|
|
||||||
|
bufferNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
retSize = bufferNeeded;
|
||||||
|
wnode->WnodeHeader.BufferSize = bufferNeeded;
|
||||||
|
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
|
||||||
|
wnode->WnodeHeader.Flags |= WNODE_FLAG_FIXED_INSTANCE_SIZE;
|
||||||
|
wnode->FixedInstanceSize = BufferUsed;
|
||||||
|
wnode->InstanceCount = 1;
|
||||||
|
|
||||||
|
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
|
||||||
|
wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
|
||||||
|
|
||||||
|
wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
|
||||||
|
wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
|
||||||
|
wnodeTooSmall->SizeNeeded = sizeof(WNODE_ALL_DATA) + BufferUsed;
|
||||||
|
retSize = sizeof(WNODE_TOO_SMALL);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
retSize = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_QUERY_SINGLE_INSTANCE:
|
||||||
|
{
|
||||||
|
PWNODE_SINGLE_INSTANCE wnode;
|
||||||
|
PWNODE_TOO_SMALL wnodeTooSmall;
|
||||||
|
ULONG bufferNeeded;
|
||||||
|
|
||||||
|
wnode = (PWNODE_SINGLE_INSTANCE)buffer;
|
||||||
|
|
||||||
|
bufferNeeded = wnode->DataBlockOffset + BufferUsed;
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
retSize = bufferNeeded;
|
||||||
|
wnode->WnodeHeader.BufferSize = bufferNeeded;
|
||||||
|
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
|
||||||
|
wnode->SizeDataBlock = BufferUsed;
|
||||||
|
|
||||||
|
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
|
||||||
|
wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
|
||||||
|
|
||||||
|
wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
|
||||||
|
wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
|
||||||
|
wnodeTooSmall->SizeNeeded = bufferNeeded;
|
||||||
|
retSize = sizeof(WNODE_TOO_SMALL);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
retSize = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IRP_MN_EXECUTE_METHOD:
|
||||||
|
{
|
||||||
|
PWNODE_METHOD_ITEM wnode;
|
||||||
|
PWNODE_TOO_SMALL wnodeTooSmall;
|
||||||
|
ULONG bufferNeeded;
|
||||||
|
|
||||||
|
wnode = (PWNODE_METHOD_ITEM)buffer;
|
||||||
|
|
||||||
|
bufferNeeded = wnode->DataBlockOffset + BufferUsed;
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
retSize = bufferNeeded;
|
||||||
|
wnode->WnodeHeader.BufferSize = bufferNeeded;
|
||||||
|
KeQuerySystemTime(&wnode->WnodeHeader.TimeStamp);
|
||||||
|
wnode->SizeDataBlock = BufferUsed;
|
||||||
|
|
||||||
|
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
|
||||||
|
wnodeTooSmall = (PWNODE_TOO_SMALL)wnode;
|
||||||
|
|
||||||
|
wnodeTooSmall->WnodeHeader.BufferSize = sizeof(WNODE_TOO_SMALL);
|
||||||
|
wnodeTooSmall->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
|
||||||
|
wnodeTooSmall->SizeNeeded = bufferNeeded;
|
||||||
|
retSize = sizeof(WNODE_TOO_SMALL);
|
||||||
|
Status = STATUS_SUCCESS;
|
||||||
|
} else {
|
||||||
|
retSize = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// All other requests don't return any data
|
||||||
|
retSize = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = Status;
|
||||||
|
Irp->IoStatus.Information = retSize;
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
ClassCompleteRequest(DeviceObject, Irp, PriorityBoost);
|
||||||
|
return(Status);
|
||||||
|
} // end ClassWmiCompleteRequest()
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassWmiFireEvent()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This routine will fire a WMI event using the data buffer passed. This
|
||||||
|
routine may be called at or below DPC level
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - Supplies a pointer to the device object for this event
|
||||||
|
|
||||||
|
Guid is pointer to the GUID that represents the event
|
||||||
|
|
||||||
|
InstanceIndex is the index of the instance of the event
|
||||||
|
|
||||||
|
EventDataSize is the number of bytes of data that is being fired with
|
||||||
|
with the event
|
||||||
|
|
||||||
|
EventData is the data that is fired with the events. This may be NULL
|
||||||
|
if there is no data associated with the event
|
||||||
|
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
status
|
||||||
|
|
||||||
|
--*/
|
||||||
|
NTSTATUS
|
||||||
|
ClassWmiFireEvent(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN LPGUID Guid,
|
||||||
|
IN ULONG InstanceIndex,
|
||||||
|
IN ULONG EventDataSize,
|
||||||
|
IN PVOID EventData
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
ULONG sizeNeeded;
|
||||||
|
PWNODE_SINGLE_INSTANCE event;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
if (EventData == NULL)
|
||||||
|
{
|
||||||
|
EventDataSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventDataSize;
|
||||||
|
|
||||||
|
event = ExAllocatePoolWithTag(NonPagedPool, sizeNeeded, CLASS_TAG_WMI);
|
||||||
|
if (event != NULL)
|
||||||
|
{
|
||||||
|
event->WnodeHeader.Guid = *Guid;
|
||||||
|
event->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(DeviceObject);
|
||||||
|
event->WnodeHeader.BufferSize = sizeNeeded;
|
||||||
|
event->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
|
||||||
|
WNODE_FLAG_EVENT_ITEM |
|
||||||
|
WNODE_FLAG_STATIC_INSTANCE_NAMES;
|
||||||
|
KeQuerySystemTime(&event->WnodeHeader.TimeStamp);
|
||||||
|
|
||||||
|
event->InstanceIndex = InstanceIndex;
|
||||||
|
event->SizeDataBlock = EventDataSize;
|
||||||
|
event->DataBlockOffset = sizeof(WNODE_SINGLE_INSTANCE);
|
||||||
|
if (EventData != NULL)
|
||||||
|
{
|
||||||
|
RtlCopyMemory( &event->VariableData, EventData, EventDataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = IoWMIWriteEvent(event);
|
||||||
|
if (! NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
ExFreePool(event);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(status);
|
||||||
|
} // end ClassWmiFireEvent()
|
||||||
|
|
74
reactos/drivers/storage/classpnp/clntirp.c
Normal file
74
reactos/drivers/storage/classpnp/clntirp.c
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
clntirp.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Client IRP queuing routines for CLASSPNP
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "classp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EnqueueDeferredClientIrp
|
||||||
|
*
|
||||||
|
* Note: we currently do not support Cancel for storage irps.
|
||||||
|
*/
|
||||||
|
VOID EnqueueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData, PIRP Irp)
|
||||||
|
{
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&FdoData->SpinLock, &oldIrql);
|
||||||
|
InsertTailList(&FdoData->DeferredClientIrpList, &Irp->Tail.Overlay.ListEntry);
|
||||||
|
KeReleaseSpinLock(&FdoData->SpinLock, oldIrql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DequeueDeferredClientIrp
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
PIRP DequeueDeferredClientIrp(PCLASS_PRIVATE_FDO_DATA FdoData)
|
||||||
|
{
|
||||||
|
KIRQL oldIrql;
|
||||||
|
PLIST_ENTRY listEntry;
|
||||||
|
PIRP irp;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&FdoData->SpinLock, &oldIrql);
|
||||||
|
if (IsListEmpty(&FdoData->DeferredClientIrpList)){
|
||||||
|
listEntry = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
listEntry = RemoveHeadList(&FdoData->DeferredClientIrpList);
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&FdoData->SpinLock, oldIrql);
|
||||||
|
|
||||||
|
if (listEntry == NULL) {
|
||||||
|
irp = NULL;
|
||||||
|
} else {
|
||||||
|
irp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
|
||||||
|
ASSERT(irp->Type == IO_TYPE_IRP);
|
||||||
|
InitializeListHead(&irp->Tail.Overlay.ListEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return irp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
977
reactos/drivers/storage/classpnp/create.c
Normal file
977
reactos/drivers/storage/classpnp/create.c
Normal file
|
@ -0,0 +1,977 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
class.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
SCSI class driver routines
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#define CLASS_INIT_GUID 0
|
||||||
|
#include "classp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
ULONG BreakOnClose = 0;
|
||||||
|
|
||||||
|
PUCHAR LockTypeStrings[] = {
|
||||||
|
"Simple",
|
||||||
|
"Secure",
|
||||||
|
"Internal"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PFILE_OBJECT_EXTENSION
|
||||||
|
ClasspGetFsContext(
|
||||||
|
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||||
|
IN PFILE_OBJECT FileObject
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspCleanupDisableMcn(
|
||||||
|
IN PFILE_OBJECT_EXTENSION FsContext
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, ClassCreateClose)
|
||||||
|
#pragma alloc_text(PAGE, ClasspCreateClose)
|
||||||
|
#pragma alloc_text(PAGE, ClasspCleanupProtectedLocks)
|
||||||
|
#pragma alloc_text(PAGE, ClasspEjectionControl)
|
||||||
|
#pragma alloc_text(PAGE, ClasspCleanupDisableMcn)
|
||||||
|
#pragma alloc_text(PAGE, ClasspGetFsContext)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClassCreateClose(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
)
|
||||||
|
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
SCSI class driver create and close routine. This is called by the I/O system
|
||||||
|
when the device is opened or closed.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DriverObject - Pointer to driver object created by system.
|
||||||
|
|
||||||
|
Irp - IRP involved.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
Device-specific drivers return value or STATUS_SUCCESS.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||||
|
ULONG removeState;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
//
|
||||||
|
// If we're getting a close request then we know the device object hasn't
|
||||||
|
// been completely destroyed. Let the driver cleanup if necessary.
|
||||||
|
//
|
||||||
|
|
||||||
|
removeState = ClassAcquireRemoveLock(DeviceObject, Irp);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Invoke the device-specific routine, if one exists. Otherwise complete
|
||||||
|
// with SUCCESS
|
||||||
|
//
|
||||||
|
|
||||||
|
if((removeState == NO_REMOVE) ||
|
||||||
|
IS_CLEANUP_REQUEST(IoGetCurrentIrpStackLocation(Irp)->MajorFunction)) {
|
||||||
|
|
||||||
|
status = ClasspCreateClose(DeviceObject, Irp);
|
||||||
|
|
||||||
|
if((NT_SUCCESS(status)) &&
|
||||||
|
(commonExtension->DevInfo->ClassCreateClose)) {
|
||||||
|
|
||||||
|
return commonExtension->DevInfo->ClassCreateClose(DeviceObject, Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
status = STATUS_DEVICE_DOES_NOT_EXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = status;
|
||||||
|
ClassReleaseRemoveLock(DeviceObject, Irp);
|
||||||
|
ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ClasspCreateClose(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
)
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This routine will handle create/close operations for a given classpnp
|
||||||
|
device if the class driver doesn't supply it's own handler. If there
|
||||||
|
is a file object supplied for our driver (if it's a FO_DIRECT_DEVICE_OPEN
|
||||||
|
file object) then it will initialize a file extension on create or destroy
|
||||||
|
the extension on a close.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - the device object being opened or closed.
|
||||||
|
|
||||||
|
Irp - the create/close irp
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
status
|
||||||
|
|
||||||
|
--*/
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||||
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
PFILE_OBJECT fileObject = irpStack->FileObject;
|
||||||
|
|
||||||
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// ISSUE-2000/3/28-henrygab - if lower stack fails create/close, we end up
|
||||||
|
// in an inconsistent state. re-write to verify all args and allocate all
|
||||||
|
// required resources, then pass the irp down, then complete the
|
||||||
|
// transaction. this is because we also cannot forward the irp, then fail
|
||||||
|
// it after it has succeeded a lower-level driver.
|
||||||
|
//
|
||||||
|
|
||||||
|
if(irpStack->MajorFunction == IRP_MJ_CREATE) {
|
||||||
|
|
||||||
|
PIO_SECURITY_CONTEXT securityContext =
|
||||||
|
irpStack->Parameters.Create.SecurityContext;
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCREATEClose: create received for device %p\n",
|
||||||
|
DeviceObject));
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCREATEClose: desired access %lx\n",
|
||||||
|
securityContext->DesiredAccess));
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCREATEClose: file object %lx\n",
|
||||||
|
irpStack->FileObject));
|
||||||
|
|
||||||
|
ASSERT(BreakOnClose == FALSE);
|
||||||
|
|
||||||
|
if(irpStack->FileObject != NULL) {
|
||||||
|
|
||||||
|
PFILE_OBJECT_EXTENSION fsContext;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate our own file object extension for this device object.
|
||||||
|
//
|
||||||
|
|
||||||
|
status = AllocateDictionaryEntry(
|
||||||
|
&commonExtension->FileObjectDictionary,
|
||||||
|
(ULONGLONG) irpStack->FileObject,
|
||||||
|
sizeof(FILE_OBJECT_EXTENSION),
|
||||||
|
CLASS_TAG_FILE_OBJECT_EXTENSION,
|
||||||
|
&fsContext);
|
||||||
|
|
||||||
|
if(NT_SUCCESS(status)) {
|
||||||
|
|
||||||
|
RtlZeroMemory(fsContext,
|
||||||
|
sizeof(FILE_OBJECT_EXTENSION));
|
||||||
|
|
||||||
|
fsContext->FileObject = irpStack->FileObject;
|
||||||
|
fsContext->DeviceObject = DeviceObject;
|
||||||
|
} else if (status == STATUS_OBJECT_NAME_COLLISION) {
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCreateCLOSE: close received for device %p\n",
|
||||||
|
DeviceObject));
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCreateCLOSE: file object %p\n",
|
||||||
|
fileObject));
|
||||||
|
|
||||||
|
if(irpStack->FileObject != NULL) {
|
||||||
|
|
||||||
|
PFILE_OBJECT_EXTENSION fsContext =
|
||||||
|
ClasspGetFsContext(commonExtension, irpStack->FileObject);
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCreateCLOSE: file extension %p\n",
|
||||||
|
fsContext));
|
||||||
|
|
||||||
|
if(fsContext != NULL) {
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCreateCLOSE: extension is ours - "
|
||||||
|
"freeing\n"));
|
||||||
|
ASSERT(BreakOnClose == FALSE);
|
||||||
|
|
||||||
|
ClasspCleanupProtectedLocks(fsContext);
|
||||||
|
|
||||||
|
ClasspCleanupDisableMcn(fsContext);
|
||||||
|
|
||||||
|
FreeDictionaryEntry(&(commonExtension->FileObjectDictionary),
|
||||||
|
fsContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notify the lower levels about the create or close operation - give them
|
||||||
|
// a chance to cleanup too.
|
||||||
|
//
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCreateClose: %s for devobj %p\n",
|
||||||
|
(NT_SUCCESS(status) ? "Success" : "FAILED"),
|
||||||
|
DeviceObject));
|
||||||
|
|
||||||
|
|
||||||
|
if(NT_SUCCESS(status)) {
|
||||||
|
|
||||||
|
KEVENT event;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set up the event to wait on
|
||||||
|
//
|
||||||
|
|
||||||
|
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
||||||
|
|
||||||
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
||||||
|
IoSetCompletionRoutine( Irp, ClassSignalCompletion, &event,
|
||||||
|
TRUE, TRUE, TRUE);
|
||||||
|
|
||||||
|
status = IoCallDriver(commonExtension->LowerDeviceObject, Irp);
|
||||||
|
|
||||||
|
if(status == STATUS_PENDING) {
|
||||||
|
KeWaitForSingleObject(&event,
|
||||||
|
Executive,
|
||||||
|
KernelMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status)) {
|
||||||
|
DebugPrint((ClassDebugError,
|
||||||
|
"ClasspCreateClose: Lower driver failed, but we "
|
||||||
|
"succeeded. This is a problem, lock counts will be "
|
||||||
|
"out of sync between levels.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspCleanupProtectedLocks(
|
||||||
|
IN PFILE_OBJECT_EXTENSION FsContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension =
|
||||||
|
FsContext->DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
|
||||||
|
commonExtension->PartitionZeroExtension;
|
||||||
|
|
||||||
|
ULONG newDeviceLockCount = 1;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCleanupProtectedLocks called for %p\n",
|
||||||
|
FsContext->DeviceObject));
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCleanupProtectedLocks - FsContext %p is locked "
|
||||||
|
"%d times\n", FsContext, FsContext->LockCount));
|
||||||
|
|
||||||
|
ASSERT(BreakOnClose == FALSE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Synchronize with ejection and ejection control requests.
|
||||||
|
//
|
||||||
|
|
||||||
|
KeEnterCriticalRegion();
|
||||||
|
KeWaitForSingleObject(&(fdoExtension->EjectSynchronizationEvent),
|
||||||
|
UserRequest,
|
||||||
|
UserMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// For each secure lock on this handle decrement the secured lock count
|
||||||
|
// for the FDO. Keep track of the new value.
|
||||||
|
//
|
||||||
|
|
||||||
|
if(FsContext->LockCount != 0) {
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
InterlockedDecrement(&FsContext->LockCount);
|
||||||
|
|
||||||
|
newDeviceLockCount =
|
||||||
|
InterlockedDecrement(&fdoExtension->ProtectedLockCount);
|
||||||
|
|
||||||
|
} while(FsContext->LockCount != 0);
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the new lock count has been dropped to zero then issue a lock
|
||||||
|
// command to the device.
|
||||||
|
//
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCleanupProtectedLocks: FDO secured lock count = %d "
|
||||||
|
"lock count = %d\n",
|
||||||
|
fdoExtension->ProtectedLockCount,
|
||||||
|
fdoExtension->LockCount));
|
||||||
|
|
||||||
|
if((newDeviceLockCount == 0) && (fdoExtension->LockCount == 0)) {
|
||||||
|
|
||||||
|
SCSI_REQUEST_BLOCK srb;
|
||||||
|
PCDB cdb;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCleanupProtectedLocks: FDO lock count dropped "
|
||||||
|
"to zero\n"));
|
||||||
|
|
||||||
|
RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
cdb = (PCDB) &(srb.Cdb);
|
||||||
|
|
||||||
|
srb.CdbLength = 6;
|
||||||
|
|
||||||
|
cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// TRUE - prevent media removal.
|
||||||
|
// FALSE - allow media removal.
|
||||||
|
//
|
||||||
|
|
||||||
|
cdb->MEDIA_REMOVAL.Prevent = FALSE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set timeout value.
|
||||||
|
//
|
||||||
|
|
||||||
|
srb.TimeOutValue = fdoExtension->TimeOutValue;
|
||||||
|
status = ClassSendSrbSynchronous(fdoExtension->DeviceObject,
|
||||||
|
&srb,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspCleanupProtectedLocks: unlock request to drive "
|
||||||
|
"returned status %lx\n", status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeSetEvent(&fdoExtension->EjectSynchronizationEvent,
|
||||||
|
IO_NO_INCREMENT,
|
||||||
|
FALSE);
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspCleanupDisableMcn(
|
||||||
|
IN PFILE_OBJECT_EXTENSION FsContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension =
|
||||||
|
FsContext->DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExtension =
|
||||||
|
commonExtension->PartitionZeroExtension;
|
||||||
|
|
||||||
|
ULONG newCount = 1;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugTrace,
|
||||||
|
"ClasspCleanupDisableMcn called for %p\n",
|
||||||
|
FsContext->DeviceObject));
|
||||||
|
DebugPrint((ClassDebugTrace,
|
||||||
|
"ClasspCleanupDisableMcn - FsContext %p is disabled "
|
||||||
|
"%d times\n", FsContext, FsContext->McnDisableCount));
|
||||||
|
|
||||||
|
//
|
||||||
|
// For each secure lock on this handle decrement the secured lock count
|
||||||
|
// for the FDO. Keep track of the new value.
|
||||||
|
//
|
||||||
|
|
||||||
|
while(FsContext->McnDisableCount != 0) {
|
||||||
|
FsContext->McnDisableCount--;
|
||||||
|
ClassEnableMediaChangeDetection(fdoExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/*
|
||||||
|
* BUGBUG REMOVE this old function implementation as soon as the
|
||||||
|
* boottime pagefile problems with the new one (below)
|
||||||
|
* are resolved.
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
ClasspEjectionControl(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN MEDIA_LOCK_TYPE LockType,
|
||||||
|
IN BOOLEAN Lock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION FdoExtension = Fdo->DeviceExtension;
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension =
|
||||||
|
(PCOMMON_DEVICE_EXTENSION) FdoExtension;
|
||||||
|
|
||||||
|
PFILE_OBJECT_EXTENSION fsContext = NULL;
|
||||||
|
NTSTATUS status;
|
||||||
|
PSCSI_REQUEST_BLOCK srb = NULL;
|
||||||
|
BOOLEAN countChanged = FALSE;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
//
|
||||||
|
// Interlock with ejection and secure lock cleanup code. This is a
|
||||||
|
// user request so we can allow the stack to get swapped out while we
|
||||||
|
// wait for synchronization.
|
||||||
|
//
|
||||||
|
|
||||||
|
status = KeWaitForSingleObject(
|
||||||
|
&(FdoExtension->EjectSynchronizationEvent),
|
||||||
|
UserRequest,
|
||||||
|
UserMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
ASSERT(status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspEjectionControl: "
|
||||||
|
"Received request for %s lock type\n",
|
||||||
|
LockTypeStrings[LockType]
|
||||||
|
));
|
||||||
|
|
||||||
|
_SEH2_TRY {
|
||||||
|
PCDB cdb;
|
||||||
|
|
||||||
|
srb = ClasspAllocateSrb(FdoExtension);
|
||||||
|
|
||||||
|
if(srb == NULL) {
|
||||||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
|
||||||
|
cdb = (PCDB) srb->Cdb;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine if this is a "secured" request.
|
||||||
|
//
|
||||||
|
|
||||||
|
if(LockType == SecureMediaLock) {
|
||||||
|
|
||||||
|
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
PFILE_OBJECT fileObject = irpStack->FileObject;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure that the file object we are supplied has a
|
||||||
|
// proper FsContext before we try doing a secured lock.
|
||||||
|
//
|
||||||
|
|
||||||
|
if(fileObject != NULL) {
|
||||||
|
fsContext = ClasspGetFsContext(commonExtension, fileObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fsContext == NULL) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// This handle isn't setup correctly. We can't let the
|
||||||
|
// operation go.
|
||||||
|
//
|
||||||
|
|
||||||
|
status = STATUS_INVALID_PARAMETER;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Lock) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is a lock command. Reissue the command in case bus or
|
||||||
|
// device was reset and the lock was cleared.
|
||||||
|
// note: may need to decrement count if actual lock operation
|
||||||
|
// failed....
|
||||||
|
//
|
||||||
|
|
||||||
|
switch(LockType) {
|
||||||
|
|
||||||
|
case SimpleMediaLock: {
|
||||||
|
FdoExtension->LockCount++;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SecureMediaLock: {
|
||||||
|
fsContext->LockCount++;
|
||||||
|
FdoExtension->ProtectedLockCount++;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InternalMediaLock: {
|
||||||
|
FdoExtension->InternalLockCount++;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//
|
||||||
|
// This is an unlock command. If it's a secured one then make sure
|
||||||
|
// the caller has a lock outstanding or return an error.
|
||||||
|
// note: may need to re-increment the count if actual unlock
|
||||||
|
// operation fails....
|
||||||
|
//
|
||||||
|
|
||||||
|
switch(LockType) {
|
||||||
|
|
||||||
|
case SimpleMediaLock: {
|
||||||
|
if(FdoExtension->LockCount != 0) {
|
||||||
|
FdoExtension->LockCount--;
|
||||||
|
countChanged = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SecureMediaLock: {
|
||||||
|
if(fsContext->LockCount == 0) {
|
||||||
|
status = STATUS_INVALID_DEVICE_STATE;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
fsContext->LockCount--;
|
||||||
|
FdoExtension->ProtectedLockCount--;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InternalMediaLock: {
|
||||||
|
ASSERT(FdoExtension->InternalLockCount != 0);
|
||||||
|
FdoExtension->InternalLockCount--;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We only send an unlock command to the drive if both the
|
||||||
|
// secured and unsecured lock counts have dropped to zero.
|
||||||
|
//
|
||||||
|
|
||||||
|
if((FdoExtension->ProtectedLockCount != 0) ||
|
||||||
|
(FdoExtension->InternalLockCount != 0) ||
|
||||||
|
(FdoExtension->LockCount != 0)) {
|
||||||
|
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
_SEH2_LEAVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
|
||||||
|
|
||||||
|
srb->CdbLength = 6;
|
||||||
|
cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
||||||
|
|
||||||
|
//
|
||||||
|
// TRUE - prevent media removal.
|
||||||
|
// FALSE - allow media removal.
|
||||||
|
//
|
||||||
|
|
||||||
|
cdb->MEDIA_REMOVAL.Prevent = Lock;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set timeout value.
|
||||||
|
//
|
||||||
|
|
||||||
|
srb->TimeOutValue = FdoExtension->TimeOutValue;
|
||||||
|
|
||||||
|
//
|
||||||
|
// The actual lock operation on the device isn't so important
|
||||||
|
// as the internal lock counts. Ignore failures.
|
||||||
|
//
|
||||||
|
|
||||||
|
status = ClassSendSrbSynchronous(FdoExtension->DeviceObject,
|
||||||
|
srb,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
} _SEH2_FINALLY {
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status)) {
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspEjectionControl: FAILED status %x -- "
|
||||||
|
"reverting lock counts\n", status));
|
||||||
|
|
||||||
|
if (countChanged) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// have to revert to previous counts if the
|
||||||
|
// lock/unlock operation actually failed.
|
||||||
|
//
|
||||||
|
|
||||||
|
if(Lock) {
|
||||||
|
|
||||||
|
switch(LockType) {
|
||||||
|
|
||||||
|
case SimpleMediaLock: {
|
||||||
|
FdoExtension->LockCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SecureMediaLock: {
|
||||||
|
fsContext->LockCount--;
|
||||||
|
FdoExtension->ProtectedLockCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InternalMediaLock: {
|
||||||
|
FdoExtension->InternalLockCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
switch(LockType) {
|
||||||
|
|
||||||
|
case SimpleMediaLock: {
|
||||||
|
FdoExtension->LockCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SecureMediaLock: {
|
||||||
|
fsContext->LockCount++;
|
||||||
|
FdoExtension->ProtectedLockCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InternalMediaLock: {
|
||||||
|
FdoExtension->InternalLockCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspEjectionControl: Succeeded\n"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugPrint((2,
|
||||||
|
"ClasspEjectionControl: "
|
||||||
|
"Current Counts: Internal: %x Secure: %x Simple: %x\n",
|
||||||
|
FdoExtension->InternalLockCount,
|
||||||
|
FdoExtension->ProtectedLockCount,
|
||||||
|
FdoExtension->LockCount
|
||||||
|
));
|
||||||
|
|
||||||
|
KeSetEvent(&(FdoExtension->EjectSynchronizationEvent),
|
||||||
|
IO_NO_INCREMENT,
|
||||||
|
FALSE);
|
||||||
|
if (srb) {
|
||||||
|
ClassFreeOrReuseSrb(FdoExtension, srb);
|
||||||
|
}
|
||||||
|
|
||||||
|
} _SEH2_END;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BUGBUG RESTORE
|
||||||
|
* This is a new implementation of the function that doesn't thrash memory
|
||||||
|
* or depend on the srbLookasideList.
|
||||||
|
* HOWEVER, it seems to cause pagefile initialization to fail during boot
|
||||||
|
* for some reason. Need to resolve this before switching to this function.
|
||||||
|
*/
|
||||||
|
NTSTATUS
|
||||||
|
ClasspEjectionControl(
|
||||||
|
IN PDEVICE_OBJECT Fdo,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN MEDIA_LOCK_TYPE LockType,
|
||||||
|
IN BOOLEAN Lock
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||||
|
PFILE_OBJECT_EXTENSION fsContext;
|
||||||
|
BOOLEAN fileHandleOk = TRUE;
|
||||||
|
BOOLEAN countChanged = FALSE;
|
||||||
|
NTSTATUS status;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
status = KeWaitForSingleObject(
|
||||||
|
&fdoExt->EjectSynchronizationEvent,
|
||||||
|
UserRequest,
|
||||||
|
UserMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
ASSERT(status == STATUS_SUCCESS);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is a "secured" request, we have to make sure
|
||||||
|
* that the file handle is valid.
|
||||||
|
*/
|
||||||
|
if (LockType == SecureMediaLock){
|
||||||
|
PIO_STACK_LOCATION thisSp = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure that the file object we are supplied has a
|
||||||
|
* proper FsContext before we try doing a secured lock.
|
||||||
|
*/
|
||||||
|
if (thisSp->FileObject){
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExt = (PCOMMON_DEVICE_EXTENSION)fdoExt;
|
||||||
|
fsContext = ClasspGetFsContext(commonExt, thisSp->FileObject);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fsContext = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fsContext){
|
||||||
|
ASSERT(fsContext);
|
||||||
|
fileHandleOk = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileHandleOk){
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adjust the lock counts and make sure they make sense.
|
||||||
|
*/
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
if (Lock){
|
||||||
|
switch(LockType) {
|
||||||
|
case SimpleMediaLock:
|
||||||
|
fdoExt->LockCount++;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
case SecureMediaLock:
|
||||||
|
fsContext->LockCount++;
|
||||||
|
fdoExt->ProtectedLockCount++;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
case InternalMediaLock:
|
||||||
|
fdoExt->InternalLockCount++;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* This is an unlock command. If it's a secured one then make sure
|
||||||
|
* the caller has a lock outstanding or return an error.
|
||||||
|
*/
|
||||||
|
switch (LockType){
|
||||||
|
case SimpleMediaLock:
|
||||||
|
if (fdoExt->LockCount > 0){
|
||||||
|
fdoExt->LockCount--;
|
||||||
|
countChanged = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ASSERT(fdoExt->LockCount > 0);
|
||||||
|
status = STATUS_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SecureMediaLock:
|
||||||
|
if (fsContext->LockCount > 0){
|
||||||
|
ASSERT(fdoExt->ProtectedLockCount > 0);
|
||||||
|
fsContext->LockCount--;
|
||||||
|
fdoExt->ProtectedLockCount--;
|
||||||
|
countChanged = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ASSERT(fsContext->LockCount > 0);
|
||||||
|
status = STATUS_INVALID_DEVICE_STATE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InternalMediaLock:
|
||||||
|
ASSERT(fdoExt->InternalLockCount > 0);
|
||||||
|
fdoExt->InternalLockCount--;
|
||||||
|
countChanged = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status)){
|
||||||
|
/*
|
||||||
|
* We only send an unlock command to the drive if
|
||||||
|
* all the lock counts have dropped to zero.
|
||||||
|
*/
|
||||||
|
if (!Lock &&
|
||||||
|
(fdoExt->ProtectedLockCount ||
|
||||||
|
fdoExt->InternalLockCount ||
|
||||||
|
fdoExt->LockCount)){
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The lock count is still positive, so don't unlock yet.
|
||||||
|
*/
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else if (!TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
|
||||||
|
/*
|
||||||
|
* The device isn't removable media. don't send a cmd.
|
||||||
|
*/
|
||||||
|
status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRANSFER_PACKET *pkt;
|
||||||
|
|
||||||
|
pkt = DequeueFreeTransferPacket(Fdo, TRUE);
|
||||||
|
if (pkt){
|
||||||
|
KEVENT event;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store the number of packets servicing the irp (one)
|
||||||
|
* inside the original IRP. It will be used to counted down
|
||||||
|
* to zero when the packet completes.
|
||||||
|
* Initialize the original IRP's status to success.
|
||||||
|
* If the packet fails, we will set it to the error status.
|
||||||
|
*/
|
||||||
|
Irp->Tail.Overlay.DriverContext[0] = LongToPtr(1);
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set this up as a SYNCHRONOUS transfer, submit it,
|
||||||
|
* and wait for the packet to complete. The result
|
||||||
|
* status will be written to the original irp.
|
||||||
|
*/
|
||||||
|
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
||||||
|
SetupEjectionTransferPacket(pkt, Lock, &event, Irp);
|
||||||
|
SubmitTransferPacket(pkt);
|
||||||
|
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
|
||||||
|
status = Irp->IoStatus.Status;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(status) && countChanged) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// have to revert to previous counts if the
|
||||||
|
// lock/unlock operation actually failed.
|
||||||
|
//
|
||||||
|
|
||||||
|
if(Lock) {
|
||||||
|
|
||||||
|
switch(LockType) {
|
||||||
|
|
||||||
|
case SimpleMediaLock: {
|
||||||
|
FdoExtension->LockCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SecureMediaLock: {
|
||||||
|
fsContext->LockCount--;
|
||||||
|
FdoExtension->ProtectedLockCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InternalMediaLock: {
|
||||||
|
FdoExtension->InternalLockCount--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
switch(LockType) {
|
||||||
|
|
||||||
|
case SimpleMediaLock: {
|
||||||
|
FdoExtension->LockCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SecureMediaLock: {
|
||||||
|
fsContext->LockCount++;
|
||||||
|
FdoExtension->ProtectedLockCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case InternalMediaLock: {
|
||||||
|
FdoExtension->InternalLockCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
KeSetEvent(&fdoExt->EjectSynchronizationEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PFILE_OBJECT_EXTENSION
|
||||||
|
ClasspGetFsContext(
|
||||||
|
IN PCOMMON_DEVICE_EXTENSION CommonExtension,
|
||||||
|
IN PFILE_OBJECT FileObject
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
return GetDictionaryEntry(&(CommonExtension->FileObjectDictionary),
|
||||||
|
(ULONGLONG) FileObject);
|
||||||
|
}
|
||||||
|
|
48
reactos/drivers/storage/classpnp/data.c
Normal file
48
reactos/drivers/storage/classpnp/data.c
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
disk.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
SCSI disk class driver
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "classp.h"
|
||||||
|
|
||||||
|
#ifdef ALLOC_DATA_PRAGMA
|
||||||
|
#pragma data_seg("PAGE")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define FDO_HACK_CANNOT_LOCK_MEDIA (0x00000001)
|
||||||
|
#define FDO_HACK_GESN_IS_BAD (0x00000002)
|
||||||
|
*/
|
||||||
|
|
||||||
|
CLASSPNP_SCAN_FOR_SPECIAL_INFO ClassBadItems[] = {
|
||||||
|
{ "" , "MITSUMI CD-ROM FX240" , NULL, 0x02 },
|
||||||
|
{ "" , "MITSUMI CD-ROM FX320" , NULL, 0x02 },
|
||||||
|
{ "" , "MITSUMI CD-ROM FX322" , NULL, 0x02 },
|
||||||
|
{ "" , "COMPAQ CRD-8481B" , NULL, 0x04 },
|
||||||
|
{ NULL , NULL , NULL, 0x0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GUID ClassGuidQueryRegInfoEx = GUID_CLASSPNP_QUERY_REGINFOEX;
|
||||||
|
|
||||||
|
#ifdef ALLOC_DATA_PRAGMA
|
||||||
|
#pragma data_seg()
|
||||||
|
#endif
|
||||||
|
|
693
reactos/drivers/storage/classpnp/debug.c
Normal file
693
reactos/drivers/storage/classpnp/debug.c
Normal file
|
@ -0,0 +1,693 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
debug.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
CLASSPNP debug code and data
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "classp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
|
||||||
|
//
|
||||||
|
// default to not breaking in for lost irps, five minutes before we even
|
||||||
|
// bother checking for lost irps, using standard debug print macros, and
|
||||||
|
// using a 64k debug print buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CLASS_GLOBAL_BREAK_ON_LOST_IRPS
|
||||||
|
#error "CLASS_GLOBAL_BREAK_ON_LOST_IRPS undefined"
|
||||||
|
#define CLASS_GLOBAL_BREAK_ON_LOST_IRPS 0
|
||||||
|
#endif // CLASS_GLOBAL_BREAK_ON_LOST_IRPS
|
||||||
|
|
||||||
|
#ifndef CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB
|
||||||
|
#error "CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB undefined"
|
||||||
|
#define CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB 300
|
||||||
|
#endif // CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB
|
||||||
|
|
||||||
|
#ifndef CLASS_GLOBAL_USE_DELAYED_RETRY
|
||||||
|
#error "CLASS_GLOBAL_USE_DELAYED_RETRY undefined"
|
||||||
|
#define CLASS_GLOBAL_USE_DELAYED_RETRY 1
|
||||||
|
#endif // CLASS_GLOBAL_USE_DELAYED_RETRY
|
||||||
|
|
||||||
|
#ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT
|
||||||
|
#error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT undefined"
|
||||||
|
#define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT 0
|
||||||
|
#endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT
|
||||||
|
|
||||||
|
#ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE
|
||||||
|
#error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE undefined"
|
||||||
|
#define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE 512
|
||||||
|
#endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE
|
||||||
|
|
||||||
|
#ifndef CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS
|
||||||
|
#error "CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS undefined"
|
||||||
|
#define CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS 512
|
||||||
|
#endif // CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS
|
||||||
|
|
||||||
|
#pragma data_seg("NONPAGE")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CLASSPNP_GLOBALS ClasspnpGlobals;
|
||||||
|
|
||||||
|
//
|
||||||
|
// the low sixteen bits are used to see if the debug level is high enough
|
||||||
|
// the high sixteen bits are used to singly enable debug levels 1-16
|
||||||
|
//
|
||||||
|
LONG ClassDebug = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
BOOLEAN DebugTrapOnWarn = FALSE;
|
||||||
|
|
||||||
|
VOID ClasspInitializeDebugGlobals()
|
||||||
|
{
|
||||||
|
KIRQL irql;
|
||||||
|
|
||||||
|
if (InterlockedCompareExchange(&ClasspnpGlobals.Initializing, 1, 0) == 0) {
|
||||||
|
|
||||||
|
KeInitializeSpinLock(&ClasspnpGlobals.SpinLock);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&ClasspnpGlobals.SpinLock, &irql);
|
||||||
|
|
||||||
|
DebugPrint((1, "CLASSPNP.SYS => Initializing ClasspnpGlobals...\n"));
|
||||||
|
|
||||||
|
ClasspnpGlobals.Buffer = NULL;
|
||||||
|
ClasspnpGlobals.Index = -1;
|
||||||
|
ClasspnpGlobals.BreakOnLostIrps = CLASS_GLOBAL_BREAK_ON_LOST_IRPS;
|
||||||
|
ClasspnpGlobals.EachBufferSize = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE;
|
||||||
|
ClasspnpGlobals.NumberOfBuffers = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS;
|
||||||
|
ClasspnpGlobals.SecondsToWaitForIrps = CLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB;
|
||||||
|
|
||||||
|
//
|
||||||
|
// this should be the last item set
|
||||||
|
//
|
||||||
|
|
||||||
|
ClasspnpGlobals.UseBufferedDebugPrint = CLASS_GLOBAL_BUFFERED_DEBUG_PRINT;
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&ClasspnpGlobals.SpinLock, irql);
|
||||||
|
|
||||||
|
InterlockedExchange(&ClasspnpGlobals.Initialized, 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassDebugPrint()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
Debug print for all class drivers, NOOP on FRE versions.
|
||||||
|
Allows printing to a debug buffer (with auto fallback to kdprint) by
|
||||||
|
properly setting the Globals in classpnp on CHK versions.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
Debug print level, or from 0 to 3 for legacy drivers.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
--*/
|
||||||
|
VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, DebugMessage);
|
||||||
|
|
||||||
|
if ((DebugPrintLevel <= (ClassDebug & 0x0000ffff)) ||
|
||||||
|
((1 << (DebugPrintLevel + 15)) & ClassDebug)) {
|
||||||
|
|
||||||
|
if (ClasspnpGlobals.UseBufferedDebugPrint &&
|
||||||
|
ClasspnpGlobals.Buffer == NULL) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// this double-check prevents always taking
|
||||||
|
// a spinlock just to ensure we have a buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
KIRQL irql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&ClasspnpGlobals.SpinLock, &irql);
|
||||||
|
if (ClasspnpGlobals.Buffer == NULL) {
|
||||||
|
|
||||||
|
SIZE_T bufferSize;
|
||||||
|
bufferSize = ClasspnpGlobals.NumberOfBuffers *
|
||||||
|
ClasspnpGlobals.EachBufferSize;
|
||||||
|
DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
|
||||||
|
"ClassDebugPrint: Allocating %x bytes for "
|
||||||
|
"classdebugprint buffer\n", bufferSize);
|
||||||
|
ClasspnpGlobals.Index = -1;
|
||||||
|
ClasspnpGlobals.Buffer =
|
||||||
|
ExAllocatePoolWithTag(NonPagedPool, bufferSize, 'bDcS');
|
||||||
|
DbgPrintEx(DPFLTR_CLASSPNP_ID, DPFLTR_ERROR_LEVEL,
|
||||||
|
"ClassDebugPrint: Allocated buffer at %p\n",
|
||||||
|
ClasspnpGlobals.Buffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&ClasspnpGlobals.SpinLock, irql);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ClasspnpGlobals.UseBufferedDebugPrint &&
|
||||||
|
ClasspnpGlobals.Buffer != NULL) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// we never free the buffer, so once it exists,
|
||||||
|
// we can just print to it with immunity
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG index;
|
||||||
|
PUCHAR buffer;
|
||||||
|
index = InterlockedIncrement(&ClasspnpGlobals.Index);
|
||||||
|
index %= ClasspnpGlobals.NumberOfBuffers;
|
||||||
|
index *= (ULONG)ClasspnpGlobals.EachBufferSize;
|
||||||
|
|
||||||
|
buffer = ClasspnpGlobals.Buffer;
|
||||||
|
buffer += index;
|
||||||
|
|
||||||
|
_vsnprintf(buffer, ClasspnpGlobals.EachBufferSize, DebugMessage, ap);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
//
|
||||||
|
// either we could not allocate a buffer for debug prints
|
||||||
|
// or buffered debug prints are disabled
|
||||||
|
//
|
||||||
|
vDbgPrintEx(-1, DPFLTR_ERROR_LEVEL, DebugMessage, ap);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *DbgGetIoctlStr(ULONG ioctl)
|
||||||
|
{
|
||||||
|
char *ioctlStr = "?";
|
||||||
|
|
||||||
|
switch (ioctl){
|
||||||
|
|
||||||
|
#undef MAKE_CASE
|
||||||
|
#define MAKE_CASE(ioctlCode) case ioctlCode: ioctlStr = #ioctlCode; break;
|
||||||
|
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_CHECK_VERIFY2)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_MEDIA_REMOVAL)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_EJECT_MEDIA)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_LOAD_MEDIA2)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_RESERVE)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_RELEASE)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_FIND_NEW_DEVICES)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_EJECTION_CONTROL)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_MCN_CONTROL)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_TYPES_EX)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_GET_HOTPLUG_INFO)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_RESET_BUS)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_RESET_DEVICE)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_GET_DEVICE_NUMBER)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_PREDICT_FAILURE)
|
||||||
|
MAKE_CASE(IOCTL_STORAGE_QUERY_PROPERTY)
|
||||||
|
MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_BUS)
|
||||||
|
MAKE_CASE(OBSOLETE_IOCTL_STORAGE_RESET_DEVICE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ioctlStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *DbgGetScsiOpStr(PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
{
|
||||||
|
PCDB pCdb = (PCDB)Srb->Cdb;
|
||||||
|
UCHAR scsiOp = pCdb->CDB6GENERIC.OperationCode;
|
||||||
|
char *scsiOpStr = "?";
|
||||||
|
|
||||||
|
switch (scsiOp){
|
||||||
|
|
||||||
|
#undef MAKE_CASE
|
||||||
|
#define MAKE_CASE(scsiOpCode) case scsiOpCode: scsiOpStr = #scsiOpCode; break;
|
||||||
|
|
||||||
|
MAKE_CASE(SCSIOP_TEST_UNIT_READY)
|
||||||
|
MAKE_CASE(SCSIOP_REWIND) // aka SCSIOP_REZERO_UNIT
|
||||||
|
MAKE_CASE(SCSIOP_REQUEST_BLOCK_ADDR)
|
||||||
|
MAKE_CASE(SCSIOP_REQUEST_SENSE)
|
||||||
|
MAKE_CASE(SCSIOP_FORMAT_UNIT)
|
||||||
|
MAKE_CASE(SCSIOP_READ_BLOCK_LIMITS)
|
||||||
|
MAKE_CASE(SCSIOP_INIT_ELEMENT_STATUS) // aka SCSIOP_REASSIGN_BLOCKS
|
||||||
|
MAKE_CASE(SCSIOP_RECEIVE) // aka SCSIOP_READ6
|
||||||
|
MAKE_CASE(SCSIOP_SEND) // aka SCSIOP_WRITE6, SCSIOP_PRINT
|
||||||
|
MAKE_CASE(SCSIOP_SLEW_PRINT) // aka SCSIOP_SEEK6, SCSIOP_TRACK_SELECT
|
||||||
|
MAKE_CASE(SCSIOP_SEEK_BLOCK)
|
||||||
|
MAKE_CASE(SCSIOP_PARTITION)
|
||||||
|
MAKE_CASE(SCSIOP_READ_REVERSE)
|
||||||
|
MAKE_CASE(SCSIOP_FLUSH_BUFFER) // aka SCSIOP_WRITE_FILEMARKS
|
||||||
|
MAKE_CASE(SCSIOP_SPACE)
|
||||||
|
MAKE_CASE(SCSIOP_INQUIRY)
|
||||||
|
MAKE_CASE(SCSIOP_VERIFY6)
|
||||||
|
MAKE_CASE(SCSIOP_RECOVER_BUF_DATA)
|
||||||
|
MAKE_CASE(SCSIOP_MODE_SELECT)
|
||||||
|
MAKE_CASE(SCSIOP_RESERVE_UNIT)
|
||||||
|
MAKE_CASE(SCSIOP_RELEASE_UNIT)
|
||||||
|
MAKE_CASE(SCSIOP_COPY)
|
||||||
|
MAKE_CASE(SCSIOP_ERASE)
|
||||||
|
MAKE_CASE(SCSIOP_MODE_SENSE)
|
||||||
|
MAKE_CASE(SCSIOP_START_STOP_UNIT) // aka SCSIOP_STOP_PRINT, SCSIOP_LOAD_UNLOAD
|
||||||
|
MAKE_CASE(SCSIOP_RECEIVE_DIAGNOSTIC)
|
||||||
|
MAKE_CASE(SCSIOP_SEND_DIAGNOSTIC)
|
||||||
|
MAKE_CASE(SCSIOP_MEDIUM_REMOVAL)
|
||||||
|
MAKE_CASE(SCSIOP_READ_FORMATTED_CAPACITY)
|
||||||
|
MAKE_CASE(SCSIOP_READ_CAPACITY)
|
||||||
|
MAKE_CASE(SCSIOP_READ)
|
||||||
|
MAKE_CASE(SCSIOP_WRITE)
|
||||||
|
MAKE_CASE(SCSIOP_SEEK) // aka SCSIOP_LOCATE, SCSIOP_POSITION_TO_ELEMENT
|
||||||
|
MAKE_CASE(SCSIOP_WRITE_VERIFY)
|
||||||
|
MAKE_CASE(SCSIOP_VERIFY)
|
||||||
|
MAKE_CASE(SCSIOP_SEARCH_DATA_HIGH)
|
||||||
|
MAKE_CASE(SCSIOP_SEARCH_DATA_EQUAL)
|
||||||
|
MAKE_CASE(SCSIOP_SEARCH_DATA_LOW)
|
||||||
|
MAKE_CASE(SCSIOP_SET_LIMITS)
|
||||||
|
MAKE_CASE(SCSIOP_READ_POSITION)
|
||||||
|
MAKE_CASE(SCSIOP_SYNCHRONIZE_CACHE)
|
||||||
|
MAKE_CASE(SCSIOP_COMPARE)
|
||||||
|
MAKE_CASE(SCSIOP_COPY_COMPARE)
|
||||||
|
MAKE_CASE(SCSIOP_WRITE_DATA_BUFF)
|
||||||
|
MAKE_CASE(SCSIOP_READ_DATA_BUFF)
|
||||||
|
MAKE_CASE(SCSIOP_CHANGE_DEFINITION)
|
||||||
|
MAKE_CASE(SCSIOP_READ_SUB_CHANNEL)
|
||||||
|
MAKE_CASE(SCSIOP_READ_TOC)
|
||||||
|
MAKE_CASE(SCSIOP_READ_HEADER)
|
||||||
|
MAKE_CASE(SCSIOP_PLAY_AUDIO)
|
||||||
|
MAKE_CASE(SCSIOP_GET_CONFIGURATION)
|
||||||
|
MAKE_CASE(SCSIOP_PLAY_AUDIO_MSF)
|
||||||
|
MAKE_CASE(SCSIOP_PLAY_TRACK_INDEX)
|
||||||
|
MAKE_CASE(SCSIOP_PLAY_TRACK_RELATIVE)
|
||||||
|
MAKE_CASE(SCSIOP_GET_EVENT_STATUS)
|
||||||
|
MAKE_CASE(SCSIOP_PAUSE_RESUME)
|
||||||
|
MAKE_CASE(SCSIOP_LOG_SELECT)
|
||||||
|
MAKE_CASE(SCSIOP_LOG_SENSE)
|
||||||
|
MAKE_CASE(SCSIOP_STOP_PLAY_SCAN)
|
||||||
|
MAKE_CASE(SCSIOP_READ_DISK_INFORMATION)
|
||||||
|
MAKE_CASE(SCSIOP_READ_TRACK_INFORMATION)
|
||||||
|
MAKE_CASE(SCSIOP_RESERVE_TRACK_RZONE)
|
||||||
|
MAKE_CASE(SCSIOP_SEND_OPC_INFORMATION)
|
||||||
|
MAKE_CASE(SCSIOP_MODE_SELECT10)
|
||||||
|
MAKE_CASE(SCSIOP_MODE_SENSE10)
|
||||||
|
MAKE_CASE(SCSIOP_CLOSE_TRACK_SESSION)
|
||||||
|
MAKE_CASE(SCSIOP_READ_BUFFER_CAPACITY)
|
||||||
|
MAKE_CASE(SCSIOP_SEND_CUE_SHEET)
|
||||||
|
MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_IN)
|
||||||
|
MAKE_CASE(SCSIOP_PERSISTENT_RESERVE_OUT)
|
||||||
|
MAKE_CASE(SCSIOP_REPORT_LUNS)
|
||||||
|
MAKE_CASE(SCSIOP_BLANK)
|
||||||
|
MAKE_CASE(SCSIOP_SEND_KEY)
|
||||||
|
MAKE_CASE(SCSIOP_REPORT_KEY)
|
||||||
|
MAKE_CASE(SCSIOP_MOVE_MEDIUM)
|
||||||
|
MAKE_CASE(SCSIOP_LOAD_UNLOAD_SLOT) // aka SCSIOP_EXCHANGE_MEDIUM
|
||||||
|
MAKE_CASE(SCSIOP_SET_READ_AHEAD)
|
||||||
|
MAKE_CASE(SCSIOP_READ_DVD_STRUCTURE)
|
||||||
|
MAKE_CASE(SCSIOP_REQUEST_VOL_ELEMENT)
|
||||||
|
MAKE_CASE(SCSIOP_SEND_VOLUME_TAG)
|
||||||
|
MAKE_CASE(SCSIOP_READ_ELEMENT_STATUS)
|
||||||
|
MAKE_CASE(SCSIOP_READ_CD_MSF)
|
||||||
|
MAKE_CASE(SCSIOP_SCAN_CD)
|
||||||
|
MAKE_CASE(SCSIOP_SET_CD_SPEED)
|
||||||
|
MAKE_CASE(SCSIOP_PLAY_CD)
|
||||||
|
MAKE_CASE(SCSIOP_MECHANISM_STATUS)
|
||||||
|
MAKE_CASE(SCSIOP_READ_CD)
|
||||||
|
MAKE_CASE(SCSIOP_SEND_DVD_STRUCTURE)
|
||||||
|
MAKE_CASE(SCSIOP_INIT_ELEMENT_RANGE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return scsiOpStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *DbgGetSrbStatusStr(PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
{
|
||||||
|
char *srbStatStr = "?";
|
||||||
|
|
||||||
|
switch (Srb->SrbStatus){
|
||||||
|
|
||||||
|
#undef MAKE_CASE
|
||||||
|
#define MAKE_CASE(srbStat) \
|
||||||
|
case srbStat: \
|
||||||
|
srbStatStr = #srbStat; \
|
||||||
|
break; \
|
||||||
|
case srbStat|SRB_STATUS_QUEUE_FROZEN: \
|
||||||
|
srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN"; \
|
||||||
|
break; \
|
||||||
|
case srbStat|SRB_STATUS_AUTOSENSE_VALID: \
|
||||||
|
srbStatStr = #srbStat "|SRB_STATUS_AUTOSENSE_VALID"; \
|
||||||
|
break; \
|
||||||
|
case srbStat|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID: \
|
||||||
|
srbStatStr = #srbStat "|SRB_STATUS_QUEUE_FROZEN|SRB_STATUS_AUTOSENSE_VALID"; \
|
||||||
|
break;
|
||||||
|
|
||||||
|
MAKE_CASE(SRB_STATUS_PENDING)
|
||||||
|
MAKE_CASE(SRB_STATUS_SUCCESS)
|
||||||
|
MAKE_CASE(SRB_STATUS_ABORTED)
|
||||||
|
MAKE_CASE(SRB_STATUS_ABORT_FAILED)
|
||||||
|
MAKE_CASE(SRB_STATUS_ERROR)
|
||||||
|
MAKE_CASE(SRB_STATUS_BUSY)
|
||||||
|
MAKE_CASE(SRB_STATUS_INVALID_REQUEST)
|
||||||
|
MAKE_CASE(SRB_STATUS_INVALID_PATH_ID)
|
||||||
|
MAKE_CASE(SRB_STATUS_NO_DEVICE)
|
||||||
|
MAKE_CASE(SRB_STATUS_TIMEOUT)
|
||||||
|
MAKE_CASE(SRB_STATUS_SELECTION_TIMEOUT)
|
||||||
|
MAKE_CASE(SRB_STATUS_COMMAND_TIMEOUT)
|
||||||
|
MAKE_CASE(SRB_STATUS_MESSAGE_REJECTED)
|
||||||
|
MAKE_CASE(SRB_STATUS_BUS_RESET)
|
||||||
|
MAKE_CASE(SRB_STATUS_PARITY_ERROR)
|
||||||
|
MAKE_CASE(SRB_STATUS_REQUEST_SENSE_FAILED)
|
||||||
|
MAKE_CASE(SRB_STATUS_NO_HBA)
|
||||||
|
MAKE_CASE(SRB_STATUS_DATA_OVERRUN)
|
||||||
|
MAKE_CASE(SRB_STATUS_UNEXPECTED_BUS_FREE)
|
||||||
|
MAKE_CASE(SRB_STATUS_PHASE_SEQUENCE_FAILURE)
|
||||||
|
MAKE_CASE(SRB_STATUS_BAD_SRB_BLOCK_LENGTH)
|
||||||
|
MAKE_CASE(SRB_STATUS_REQUEST_FLUSHED)
|
||||||
|
MAKE_CASE(SRB_STATUS_INVALID_LUN)
|
||||||
|
MAKE_CASE(SRB_STATUS_INVALID_TARGET_ID)
|
||||||
|
MAKE_CASE(SRB_STATUS_BAD_FUNCTION)
|
||||||
|
MAKE_CASE(SRB_STATUS_ERROR_RECOVERY)
|
||||||
|
MAKE_CASE(SRB_STATUS_NOT_POWERED)
|
||||||
|
MAKE_CASE(SRB_STATUS_INTERNAL_ERROR)
|
||||||
|
}
|
||||||
|
|
||||||
|
return srbStatStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *DbgGetSenseCodeStr(PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
{
|
||||||
|
char *senseCodeStr = "?";
|
||||||
|
|
||||||
|
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
|
||||||
|
PSENSE_DATA senseData;
|
||||||
|
UCHAR senseCode;
|
||||||
|
|
||||||
|
ASSERT(Srb->SenseInfoBuffer);
|
||||||
|
senseData = Srb->SenseInfoBuffer;
|
||||||
|
senseCode = senseData->SenseKey & 0xf;
|
||||||
|
|
||||||
|
switch (senseCode){
|
||||||
|
|
||||||
|
#undef MAKE_CASE
|
||||||
|
#define MAKE_CASE(snsCod) case snsCod: senseCodeStr = #snsCod; break;
|
||||||
|
|
||||||
|
MAKE_CASE(SCSI_SENSE_NO_SENSE)
|
||||||
|
MAKE_CASE(SCSI_SENSE_RECOVERED_ERROR)
|
||||||
|
MAKE_CASE(SCSI_SENSE_NOT_READY)
|
||||||
|
MAKE_CASE(SCSI_SENSE_MEDIUM_ERROR)
|
||||||
|
MAKE_CASE(SCSI_SENSE_HARDWARE_ERROR)
|
||||||
|
MAKE_CASE(SCSI_SENSE_ILLEGAL_REQUEST)
|
||||||
|
MAKE_CASE(SCSI_SENSE_UNIT_ATTENTION)
|
||||||
|
MAKE_CASE(SCSI_SENSE_DATA_PROTECT)
|
||||||
|
MAKE_CASE(SCSI_SENSE_BLANK_CHECK)
|
||||||
|
MAKE_CASE(SCSI_SENSE_UNIQUE)
|
||||||
|
MAKE_CASE(SCSI_SENSE_COPY_ABORTED)
|
||||||
|
MAKE_CASE(SCSI_SENSE_ABORTED_COMMAND)
|
||||||
|
MAKE_CASE(SCSI_SENSE_EQUAL)
|
||||||
|
MAKE_CASE(SCSI_SENSE_VOL_OVERFLOW)
|
||||||
|
MAKE_CASE(SCSI_SENSE_MISCOMPARE)
|
||||||
|
MAKE_CASE(SCSI_SENSE_RESERVED)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return senseCodeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *DbgGetAdditionalSenseCodeStr(PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
{
|
||||||
|
char *adSenseCodeStr = "?";
|
||||||
|
|
||||||
|
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
|
||||||
|
PSENSE_DATA senseData;
|
||||||
|
UCHAR adSenseCode;
|
||||||
|
|
||||||
|
ASSERT(Srb->SenseInfoBuffer);
|
||||||
|
senseData = Srb->SenseInfoBuffer;
|
||||||
|
adSenseCode = senseData->AdditionalSenseCode;
|
||||||
|
|
||||||
|
switch (adSenseCode){
|
||||||
|
|
||||||
|
#undef MAKE_CASE
|
||||||
|
#define MAKE_CASE(adSnsCod) case adSnsCod: adSenseCodeStr = #adSnsCod; break;
|
||||||
|
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_NO_SENSE)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_LUN_NOT_READY)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_TRACK_ERROR)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_SEEK_ERROR)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_REC_DATA_NOECC)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_REC_DATA_ECC)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_ILLEGAL_COMMAND)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_ILLEGAL_BLOCK)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_INVALID_CDB)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_INVALID_LUN)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_WRITE_PROTECT) // aka SCSI_ADWRITE_PROTECT
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_MEDIUM_CHANGED)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_BUS_RESET)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_INVALID_MEDIA)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_POSITION_ERROR)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_OPERATOR_REQUEST)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_FAILURE_PREDICTION_THRESHOLD_EXCEEDED)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_COPY_PROTECTION_FAILURE)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_VENDOR_UNIQUE)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_MUSIC_AREA)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_DATA_AREA)
|
||||||
|
MAKE_CASE(SCSI_ADSENSE_VOLUME_OVERFLOW)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return adSenseCodeStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *DbgGetAdditionalSenseCodeQualifierStr(PSCSI_REQUEST_BLOCK Srb)
|
||||||
|
{
|
||||||
|
char *adSenseCodeQualStr = "?";
|
||||||
|
|
||||||
|
if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID){
|
||||||
|
PSENSE_DATA senseData;
|
||||||
|
UCHAR adSenseCode;
|
||||||
|
UCHAR adSenseCodeQual;
|
||||||
|
|
||||||
|
ASSERT(Srb->SenseInfoBuffer);
|
||||||
|
senseData = Srb->SenseInfoBuffer;
|
||||||
|
adSenseCode = senseData->AdditionalSenseCode;
|
||||||
|
adSenseCodeQual = senseData->AdditionalSenseCodeQualifier;
|
||||||
|
|
||||||
|
switch (adSenseCode){
|
||||||
|
|
||||||
|
#undef MAKE_CASE
|
||||||
|
#define MAKE_CASE(adSnsCodQual) case adSnsCodQual: adSenseCodeQualStr = #adSnsCodQual; break;
|
||||||
|
|
||||||
|
case SCSI_ADSENSE_LUN_NOT_READY:
|
||||||
|
switch (adSenseCodeQual){
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_CAUSE_NOT_REPORTABLE)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_BECOMING_READY)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_INIT_COMMAND_REQUIRED)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_MANUAL_INTERVENTION_REQUIRED)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_FORMAT_IN_PROGRESS)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_REBUILD_IN_PROGRESS)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_RECALCULATION_IN_PROGRESS)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_OPERATION_IN_PROGRESS)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCSI_ADSENSE_NO_SENSE:
|
||||||
|
switch (adSenseCodeQual){
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_FILEMARK_DETECTED)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_END_OF_MEDIA_DETECTED)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_SETMARK_DETECTED)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCSI_ADSENSE_ILLEGAL_BLOCK:
|
||||||
|
switch (adSenseCodeQual){
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_ILLEGAL_ELEMENT_ADDR)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCSI_ADSENSE_POSITION_ERROR:
|
||||||
|
switch (adSenseCodeQual){
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_DESTINATION_FULL)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_SOURCE_EMPTY)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCSI_ADSENSE_INVALID_MEDIA:
|
||||||
|
switch (adSenseCodeQual){
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_MEDIA_INSTALLED)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_UNKNOWN_FORMAT)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_INCOMPATIBLE_FORMAT)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_CLEANING_CARTRIDGE_INSTALLED)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCSI_ADSENSE_OPERATOR_REQUEST:
|
||||||
|
switch (adSenseCodeQual){
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_STATE_CHANGE_INPUT)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_MEDIUM_REMOVAL)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_ENABLE)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_WRITE_PROTECT_DISABLE)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SCSI_ADSENSE_COPY_PROTECTION_FAILURE:
|
||||||
|
switch (adSenseCodeQual){
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_AUTHENTICATION_FAILURE)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_KEY_NOT_PRESENT)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_KEY_NOT_ESTABLISHED)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_READ_OF_SCRAMBLED_SECTOR_WITHOUT_AUTHENTICATION)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_MEDIA_CODE_MISMATCHED_TO_LOGICAL_UNIT)
|
||||||
|
MAKE_CASE(SCSI_SENSEQ_LOGICAL_UNIT_RESET_COUNT_ERROR)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return adSenseCodeQualStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DbgCheckReturnedPkt
|
||||||
|
*
|
||||||
|
* Check a completed TRANSFER_PACKET for all sorts of error conditions
|
||||||
|
* and warn/trap appropriately.
|
||||||
|
*/
|
||||||
|
VOID DbgCheckReturnedPkt(TRANSFER_PACKET *Pkt)
|
||||||
|
{
|
||||||
|
PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
|
||||||
|
ASSERT(Pkt->Srb.OriginalRequest == Pkt->Irp);
|
||||||
|
ASSERT(Pkt->Srb.DataBuffer == Pkt->BufPtrCopy);
|
||||||
|
ASSERT(Pkt->Srb.DataTransferLength <= Pkt->BufLenCopy);
|
||||||
|
ASSERT(!Pkt->Irp->CancelRoutine);
|
||||||
|
|
||||||
|
if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_PENDING){
|
||||||
|
DBGERR(("SRB completed with status PENDING in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
|
||||||
|
Pkt,
|
||||||
|
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||||
|
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||||
|
(ULONG)Pkt->Srb.SrbStatus,
|
||||||
|
Pkt->Irp->IoStatus.Status));
|
||||||
|
}
|
||||||
|
else if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
|
||||||
|
/*
|
||||||
|
* Make sure SRB and IRP status match.
|
||||||
|
*/
|
||||||
|
if (!NT_SUCCESS(Pkt->Irp->IoStatus.Status)){
|
||||||
|
DBGWARN(("SRB and IRP status don't match in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
|
||||||
|
Pkt,
|
||||||
|
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||||
|
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||||
|
(ULONG)Pkt->Srb.SrbStatus,
|
||||||
|
Pkt->Irp->IoStatus.Status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Pkt->Irp->IoStatus.Information != Pkt->Srb.DataTransferLength){
|
||||||
|
DBGERR(("SRB and IRP result transfer lengths don't match in succeeded packet %ph: (op=%s, SrbStatus=%s, Srb.DataTransferLength=%xh, Irp->IoStatus.Information=%xh).",
|
||||||
|
Pkt,
|
||||||
|
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||||
|
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||||
|
Pkt->Srb.DataTransferLength,
|
||||||
|
Pkt->Irp->IoStatus.Information));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (NT_SUCCESS(Pkt->Irp->IoStatus.Status)){
|
||||||
|
DBGWARN(("SRB and IRP status don't match in packet %ph: (op=%s srbstat=%s(%xh), irpstat=%xh)",
|
||||||
|
Pkt,
|
||||||
|
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||||
|
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||||
|
(ULONG)Pkt->Srb.SrbStatus,
|
||||||
|
Pkt->Irp->IoStatus.Status));
|
||||||
|
}
|
||||||
|
DBGTRACE(ClassDebugWarning, ("Packet %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)",
|
||||||
|
Pkt,
|
||||||
|
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||||
|
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||||
|
(ULONG)Pkt->Srb.SrbStatus,
|
||||||
|
Pkt->Irp->IoStatus.Status,
|
||||||
|
DBGGETSENSECODESTR(&Pkt->Srb),
|
||||||
|
DBGGETADSENSECODESTR(&Pkt->Srb),
|
||||||
|
DBGGETADSENSEQUALIFIERSTR(&Pkt->Srb)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the SRB failed with underrun or overrun, then the actual
|
||||||
|
* transferred length should be returned in both SRB and IRP.
|
||||||
|
* (SRB's only have an error status for overrun, so it's overloaded).
|
||||||
|
*/
|
||||||
|
if ((SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) &&
|
||||||
|
(Pkt->Irp->IoStatus.Information != Pkt->Srb.DataTransferLength)){
|
||||||
|
DBGERR(("SRB and IRP result transfer lengths don't match in failed packet %ph: (op=%s, SrbStatus=%s, Srb.DataTransferLength=%xh, Irp->IoStatus.Information=%xh).",
|
||||||
|
Pkt,
|
||||||
|
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||||
|
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||||
|
Pkt->Srb.DataTransferLength,
|
||||||
|
Pkt->Irp->IoStatus.Information));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some miniport drivers have been caught changing the SCSI operation
|
||||||
|
* code in the SRB. This is absolutely disallowed as it breaks our error handling.
|
||||||
|
*/
|
||||||
|
switch (pCdb->CDB10.OperationCode){
|
||||||
|
case SCSIOP_MEDIUM_REMOVAL:
|
||||||
|
case SCSIOP_MODE_SENSE:
|
||||||
|
case SCSIOP_READ_CAPACITY:
|
||||||
|
case SCSIOP_READ:
|
||||||
|
case SCSIOP_WRITE:
|
||||||
|
case SCSIOP_START_STOP_UNIT:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBGERR(("Miniport illegally changed Srb.Cdb.OperationCode in packet %ph failed (op=%s srbstat=%s(%xh), irpstat=%xh, sense=%s/%s/%s)",
|
||||||
|
Pkt,
|
||||||
|
DBGGETSCSIOPSTR(&Pkt->Srb),
|
||||||
|
DBGGETSRBSTATUSSTR(&Pkt->Srb),
|
||||||
|
(ULONG)Pkt->Srb.SrbStatus,
|
||||||
|
Pkt->Irp->IoStatus.Status,
|
||||||
|
DBGGETSENSECODESTR(&Pkt->Srb),
|
||||||
|
DBGGETADSENSECODESTR(&Pkt->Srb),
|
||||||
|
DBGGETADSENSEQUALIFIERSTR(&Pkt->Srb)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// We have to keep this in the retail build for legacy.
|
||||||
|
VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...)
|
||||||
|
{
|
||||||
|
DbgPrint("retail build\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
148
reactos/drivers/storage/classpnp/debug.h
Normal file
148
reactos/drivers/storage/classpnp/debug.h
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
debug.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
VOID ClassDebugPrint(CLASS_DEBUG_LEVEL DebugPrintLevel, PCCHAR DebugMessage, ...);
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
|
||||||
|
typedef struct _CLASSPNP_GLOBALS {
|
||||||
|
|
||||||
|
//
|
||||||
|
// whether or not to ASSERT for lost irps
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG BreakOnLostIrps;
|
||||||
|
ULONG SecondsToWaitForIrps;
|
||||||
|
|
||||||
|
//
|
||||||
|
// use a buffered debug print to help
|
||||||
|
// catch timing issues that do not
|
||||||
|
// reproduce with std debugprints enabled
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG UseBufferedDebugPrint;
|
||||||
|
ULONG UseDelayedRetry;
|
||||||
|
|
||||||
|
//
|
||||||
|
// the next four are the buffered printing support
|
||||||
|
// (currently unimplemented) and require the spinlock
|
||||||
|
// to use
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG Index; // index into buffer
|
||||||
|
KSPIN_LOCK SpinLock;
|
||||||
|
PUCHAR Buffer; // requires spinlock to access
|
||||||
|
ULONG NumberOfBuffers; // number of buffers available
|
||||||
|
SIZE_T EachBufferSize; // size of each buffer
|
||||||
|
|
||||||
|
//
|
||||||
|
// interlocked variables to initialize
|
||||||
|
// this data only once
|
||||||
|
//
|
||||||
|
|
||||||
|
LONG Initializing;
|
||||||
|
LONG Initialized;
|
||||||
|
|
||||||
|
} CLASSPNP_GLOBALS, *PCLASSPNP_GLOBALS;
|
||||||
|
|
||||||
|
#define DBGTRACE(dbgTraceLevel, args_in_parens) \
|
||||||
|
if (ClassDebug & (1 << (dbgTraceLevel+15))){ \
|
||||||
|
DbgPrint("CLASSPNP> *** TRACE *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||||
|
DbgPrint(" > "); \
|
||||||
|
DbgPrint args_in_parens; \
|
||||||
|
DbgPrint("\n"); \
|
||||||
|
if (DebugTrapOnWarn && (dbgTraceLevel == ClassDebugWarning)){ \
|
||||||
|
DbgBreakPoint(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define DBGWARN(args_in_parens) \
|
||||||
|
{ \
|
||||||
|
DbgPrint("CLASSPNP> *** WARNING *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||||
|
DbgPrint(" > "); \
|
||||||
|
DbgPrint args_in_parens; \
|
||||||
|
DbgPrint("\n"); \
|
||||||
|
if (DebugTrapOnWarn){ \
|
||||||
|
DbgBreakPoint(); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define DBGERR(args_in_parens) \
|
||||||
|
{ \
|
||||||
|
DbgPrint("CLASSPNP> *** ERROR *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||||
|
DbgPrint(" > "); \
|
||||||
|
DbgPrint args_in_parens; \
|
||||||
|
DbgPrint("\n"); \
|
||||||
|
DbgBreakPoint(); \
|
||||||
|
}
|
||||||
|
#define DBGTRAP(args_in_parens) \
|
||||||
|
{ \
|
||||||
|
DbgPrint("CLASSPNP> *** COVERAGE TRAP *** (file %s, line %d)\n", __FILE__, __LINE__ ); \
|
||||||
|
DbgPrint(" > "); \
|
||||||
|
DbgPrint args_in_parens; \
|
||||||
|
DbgPrint("\n"); \
|
||||||
|
DbgBreakPoint(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define DBGGETIOCTLSTR(_ioctl) DbgGetIoctlStr(_ioctl)
|
||||||
|
#define DBGGETSCSIOPSTR(_pSrb) DbgGetScsiOpStr(_pSrb)
|
||||||
|
#define DBGGETSENSECODESTR(_pSrb) DbgGetSenseCodeStr(_pSrb)
|
||||||
|
#define DBGGETADSENSECODESTR(_pSrb) DbgGetAdditionalSenseCodeStr(_pSrb)
|
||||||
|
#define DBGGETADSENSEQUALIFIERSTR(_pSrb) DbgGetAdditionalSenseCodeQualifierStr(_pSrb)
|
||||||
|
#define DBGCHECKRETURNEDPKT(_pkt) DbgCheckReturnedPkt(_pkt)
|
||||||
|
#define DBGGETSRBSTATUSSTR(_pSrb) DbgGetSrbStatusStr(_pSrb)
|
||||||
|
|
||||||
|
VOID ClasspInitializeDebugGlobals();
|
||||||
|
char *DbgGetIoctlStr(ULONG ioctl);
|
||||||
|
char *DbgGetScsiOpStr(PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
char *DbgGetSenseCodeStr(PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
char *DbgGetAdditionalSenseCodeStr(PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
char *DbgGetAdditionalSenseCodeQualifierStr(PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
VOID DbgCheckReturnedPkt(TRANSFER_PACKET *Pkt);
|
||||||
|
char *DbgGetSrbStatusStr(PSCSI_REQUEST_BLOCK Srb);
|
||||||
|
|
||||||
|
|
||||||
|
extern CLASSPNP_GLOBALS ClasspnpGlobals;
|
||||||
|
extern LONG ClassDebug;
|
||||||
|
extern BOOLEAN DebugTrapOnWarn;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define ClasspInitializeDebugGlobals()
|
||||||
|
#define DBGWARN(args_in_parens)
|
||||||
|
#define DBGERR(args_in_parens)
|
||||||
|
#define DBGTRACE(dbgTraceLevel, args_in_parens)
|
||||||
|
#define DBGTRAP(args_in_parens)
|
||||||
|
|
||||||
|
#define DBGGETIOCTLSTR(_ioctl)
|
||||||
|
#define DBGGETSCSIOPSTR(_pSrb)
|
||||||
|
#define DBGGETSENSECODESTR(_pSrb)
|
||||||
|
#define DBGGETADSENSECODESTR(_pSrb)
|
||||||
|
#define DBGGETADSENSEQUALIFIERSTR(_pSrb)
|
||||||
|
#define DBGCHECKRETURNEDPKT(_pkt)
|
||||||
|
#define DBGGETSRBSTATUSSTR(_pSrb)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
216
reactos/drivers/storage/classpnp/dictlib.c
Normal file
216
reactos/drivers/storage/classpnp/dictlib.c
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1990 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
dictlib.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Support library for maintaining a dictionary list (list of objects
|
||||||
|
referenced by a key value).
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
This module generates a static library
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include <ntddk.h>
|
||||||
|
#include <classpnp.h>
|
||||||
|
|
||||||
|
#define DICTIONARY_SIGNATURE (((ULONG)'dict' << 32) + 'sig ')
|
||||||
|
|
||||||
|
struct _DICTIONARY_HEADER {
|
||||||
|
struct _DICTIONARY_HEADER* Next;
|
||||||
|
ULONGLONG Key;
|
||||||
|
UCHAR Data[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _DICTIONARY_HEADER;
|
||||||
|
typedef struct _DICTIONARY_HEADER DICTIONARY_HEADER, *PDICTIONARY_HEADER;
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
InitializeDictionary(
|
||||||
|
IN PDICTIONARY Dictionary
|
||||||
|
)
|
||||||
|
{
|
||||||
|
RtlZeroMemory(Dictionary, sizeof(Dictionary));
|
||||||
|
Dictionary->Signature = DICTIONARY_SIGNATURE;
|
||||||
|
KeInitializeSpinLock(&Dictionary->SpinLock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
TestDictionarySignature(
|
||||||
|
IN PDICTIONARY Dictionary
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return Dictionary->Signature == DICTIONARY_SIGNATURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
AllocateDictionaryEntry(
|
||||||
|
IN PDICTIONARY Dictionary,
|
||||||
|
IN ULONGLONG Key,
|
||||||
|
IN ULONG Size,
|
||||||
|
IN ULONG Tag,
|
||||||
|
OUT PVOID *Entry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PDICTIONARY_HEADER header;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
PDICTIONARY_HEADER *entry;
|
||||||
|
|
||||||
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
*Entry = NULL;
|
||||||
|
|
||||||
|
header = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
Size + sizeof(DICTIONARY_HEADER),
|
||||||
|
Tag);
|
||||||
|
|
||||||
|
if(header == NULL) {
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(header, sizeof(DICTIONARY_HEADER) + Size);
|
||||||
|
header->Key = Key;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find the correct location for this entry in the dictionary.
|
||||||
|
//
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
||||||
|
|
||||||
|
TRY {
|
||||||
|
|
||||||
|
entry = &(Dictionary->List);
|
||||||
|
|
||||||
|
while(*entry != NULL) {
|
||||||
|
if((*entry)->Key == Key) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dictionary must have unique keys.
|
||||||
|
//
|
||||||
|
|
||||||
|
status = STATUS_OBJECT_NAME_COLLISION;
|
||||||
|
LEAVE;
|
||||||
|
|
||||||
|
} else if ((*entry)->Key < Key) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// We will go ahead and insert the key in here.
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
entry = &((*entry)->Next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If we make it here then we will go ahead and do the insertion.
|
||||||
|
//
|
||||||
|
|
||||||
|
header->Next = *entry;
|
||||||
|
*entry = header;
|
||||||
|
|
||||||
|
} FINALLY {
|
||||||
|
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
||||||
|
|
||||||
|
if(!NT_SUCCESS(status)) {
|
||||||
|
ExFreePool(header);
|
||||||
|
} else {
|
||||||
|
*Entry = (PVOID) header->Data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
GetDictionaryEntry(
|
||||||
|
IN PDICTIONARY Dictionary,
|
||||||
|
IN ULONGLONG Key
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PDICTIONARY_HEADER entry;
|
||||||
|
PVOID data;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
|
||||||
|
data = NULL;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
||||||
|
|
||||||
|
entry = Dictionary->List;
|
||||||
|
while (entry != NULL) {
|
||||||
|
|
||||||
|
if (entry->Key == Key) {
|
||||||
|
data = entry->Data;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
entry = entry->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID
|
||||||
|
FreeDictionaryEntry(
|
||||||
|
IN PDICTIONARY Dictionary,
|
||||||
|
IN PVOID Entry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PDICTIONARY_HEADER header;
|
||||||
|
PDICTIONARY_HEADER *entry;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
BOOLEAN found;
|
||||||
|
|
||||||
|
found = FALSE;
|
||||||
|
header = CONTAINING_RECORD(Entry, DICTIONARY_HEADER, Data);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&(Dictionary->SpinLock), &oldIrql);
|
||||||
|
|
||||||
|
entry = &(Dictionary->List);
|
||||||
|
while(*entry != NULL) {
|
||||||
|
|
||||||
|
if(*entry == header) {
|
||||||
|
*entry = header->Next;
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
entry = &(*entry)->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&(Dictionary->SpinLock), oldIrql);
|
||||||
|
|
||||||
|
//
|
||||||
|
// calling this w/an invalid pointer invalidates the dictionary system,
|
||||||
|
// so ASSERT() that we never try to Free something not in the list
|
||||||
|
//
|
||||||
|
|
||||||
|
ASSERT(found);
|
||||||
|
if (found) {
|
||||||
|
ExFreePool(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
418
reactos/drivers/storage/classpnp/lock.c
Normal file
418
reactos/drivers/storage/classpnp/lock.c
Normal file
|
@ -0,0 +1,418 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1990 - 1998
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
lock.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
This is the NT SCSI port driver.
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
This module is a driver dll for scsi miniports.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "classp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
LONG LockHighWatermark = 0;
|
||||||
|
LONG LockLowWatermark = 0;
|
||||||
|
LONG MaxLockedMinutes = 5;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Structure used for tracking remove lock allocations in checked builds
|
||||||
|
//
|
||||||
|
typedef struct _REMOVE_TRACKING_BLOCK {
|
||||||
|
struct _REMOVE_TRACKING_BLOCK *NextBlock;
|
||||||
|
PVOID Tag;
|
||||||
|
LARGE_INTEGER TimeLocked;
|
||||||
|
PCSTR File;
|
||||||
|
ULONG Line;
|
||||||
|
} REMOVE_TRACKING_BLOCK, *PREMOVE_TRACKING_BLOCK;
|
||||||
|
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassAcquireRemoveLockEx()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This routine is called to acquire the remove lock on the device object.
|
||||||
|
While the lock is held, the caller can assume that no pending pnp REMOVE
|
||||||
|
requests will be completed.
|
||||||
|
|
||||||
|
The lock should be acquired immediately upon entering a dispatch routine.
|
||||||
|
It should also be acquired before creating any new reference to the
|
||||||
|
device object if there's a chance of releasing the reference before the
|
||||||
|
new one is done.
|
||||||
|
|
||||||
|
This routine will return TRUE if the lock was successfully acquired or
|
||||||
|
FALSE if it cannot be because the device object has already been removed.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - the device object to lock
|
||||||
|
|
||||||
|
Tag - Used for tracking lock allocation and release. If an irp is
|
||||||
|
specified when acquiring the lock then the same Tag must be
|
||||||
|
used to release the lock before the Tag is completed.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
The value of the IsRemoved flag in the device extension. If this is
|
||||||
|
non-zero then the device object has received a Remove irp and non-cleanup
|
||||||
|
IRP's should fail.
|
||||||
|
|
||||||
|
If the value is REMOVE_COMPLETE, the caller should not even release the
|
||||||
|
lock.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
ULONG
|
||||||
|
ClassAcquireRemoveLockEx(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OPTIONAL PVOID Tag,
|
||||||
|
IN PCSTR File,
|
||||||
|
IN ULONG Line
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||||
|
LONG lockValue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Grab the remove lock
|
||||||
|
//
|
||||||
|
lockValue = InterlockedIncrement(&commonExtension->RemoveLock);
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugRemoveLock, "ClassAcquireRemoveLock: "
|
||||||
|
"Acquired for Object %p & irp %p - count is %d\n",
|
||||||
|
DeviceObject, Tag, lockValue));
|
||||||
|
|
||||||
|
ASSERTMSG("ClassAcquireRemoveLock - lock value was negative : ",
|
||||||
|
(lockValue > 0));
|
||||||
|
|
||||||
|
ASSERTMSG("RemoveLock increased to meet LockHighWatermark",
|
||||||
|
((LockHighWatermark == 0) ||
|
||||||
|
(lockValue != LockHighWatermark)));
|
||||||
|
|
||||||
|
if (commonExtension->IsRemoved != REMOVE_COMPLETE){
|
||||||
|
PREMOVE_TRACKING_BLOCK trackingBlock;
|
||||||
|
|
||||||
|
trackingBlock = ExAllocatePool(NonPagedPool,
|
||||||
|
sizeof(REMOVE_TRACKING_BLOCK));
|
||||||
|
|
||||||
|
if(trackingBlock == NULL) {
|
||||||
|
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||||
|
&oldIrql);
|
||||||
|
|
||||||
|
commonExtension->RemoveTrackingUntrackedCount++;
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugWarning, ">>>>>ClassAcquireRemoveLock: "
|
||||||
|
"Cannot track Tag %p - currently %d untracked requsts\n",
|
||||||
|
Tag, commonExtension->RemoveTrackingUntrackedCount));
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||||
|
oldIrql);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PREMOVE_TRACKING_BLOCK *removeTrackingList =
|
||||||
|
(PREMOVE_TRACKING_BLOCK)&commonExtension->RemoveTrackingList;
|
||||||
|
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
trackingBlock->Tag = Tag;
|
||||||
|
|
||||||
|
trackingBlock->File = File;
|
||||||
|
trackingBlock->Line = Line;
|
||||||
|
|
||||||
|
KeQueryTickCount((&trackingBlock->TimeLocked));
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||||
|
&oldIrql);
|
||||||
|
|
||||||
|
while(*removeTrackingList != NULL) {
|
||||||
|
|
||||||
|
if((*removeTrackingList)->Tag > Tag) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((*removeTrackingList)->Tag == Tag) {
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: "
|
||||||
|
"already tracking Tag %p\n", Tag));
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassAcquireRemoveLock: "
|
||||||
|
"acquired in file %s on line %d\n",
|
||||||
|
(*removeTrackingList)->File,
|
||||||
|
(*removeTrackingList)->Line));
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeTrackingList = &((*removeTrackingList)->NextBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
trackingBlock->NextBlock = *removeTrackingList;
|
||||||
|
*removeTrackingList = trackingBlock;
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||||
|
oldIrql);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (commonExtension->IsRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassReleaseRemoveLock()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This routine is called to release the remove lock on the device object. It
|
||||||
|
must be called when finished using a previously locked reference to the
|
||||||
|
device object. If an Tag was specified when acquiring the lock then the
|
||||||
|
same Tag must be specified when releasing the lock.
|
||||||
|
|
||||||
|
When the lock count reduces to zero, this routine will signal the waiting
|
||||||
|
remove Tag to delete the device object. As a result the DeviceObject
|
||||||
|
pointer should not be used again once the lock has been released.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - the device object to lock
|
||||||
|
|
||||||
|
Tag - The irp (if any) specified when acquiring the lock. This is used
|
||||||
|
for lock tracking purposes
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
none
|
||||||
|
|
||||||
|
--*/
|
||||||
|
VOID
|
||||||
|
ClassReleaseRemoveLock(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN OPTIONAL PIRP Tag
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||||
|
LONG lockValue;
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
PREMOVE_TRACKING_BLOCK *listEntry =
|
||||||
|
(PREMOVE_TRACKING_BLOCK)&commonExtension->RemoveTrackingList;
|
||||||
|
|
||||||
|
BOOLEAN found = FALSE;
|
||||||
|
|
||||||
|
LONGLONG maxCount;
|
||||||
|
|
||||||
|
BOOLEAN isRemoved = (commonExtension->IsRemoved == REMOVE_COMPLETE);
|
||||||
|
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
if(isRemoved) {
|
||||||
|
DBGTRAP(("ClassReleaseRemoveLock: REMOVE_COMPLETE set; this should never happen"));
|
||||||
|
InterlockedDecrement(&(commonExtension->RemoveLock));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the tick count and make sure this thing hasn't been locked
|
||||||
|
// for more than MaxLockedMinutes.
|
||||||
|
//
|
||||||
|
|
||||||
|
maxCount = KeQueryTimeIncrement() * 10; // microseconds
|
||||||
|
maxCount *= 1000; // milliseconds
|
||||||
|
maxCount *= 1000; // seconds
|
||||||
|
maxCount *= 60; // minutes
|
||||||
|
maxCount *= MaxLockedMinutes;
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||||
|
"maxCount = %0I64x\n", maxCount));
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||||
|
&oldIrql);
|
||||||
|
|
||||||
|
while(*listEntry != NULL) {
|
||||||
|
|
||||||
|
PREMOVE_TRACKING_BLOCK block;
|
||||||
|
LARGE_INTEGER difference;
|
||||||
|
|
||||||
|
block = *listEntry;
|
||||||
|
|
||||||
|
KeQueryTickCount((&difference));
|
||||||
|
|
||||||
|
difference.QuadPart -= block->TimeLocked.QuadPart;
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||||
|
"Object %p (tag %p) locked for %I64d ticks\n",
|
||||||
|
DeviceObject, block->Tag, difference.QuadPart));
|
||||||
|
|
||||||
|
if(difference.QuadPart >= maxCount) {
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||||
|
"Object %p (tag %p) locked for %I64d ticks - TOO LONG\n",
|
||||||
|
DeviceObject, block->Tag, difference.QuadPart));
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||||
|
"Lock acquired in file %s on line %d\n",
|
||||||
|
block->File, block->Line));
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((found == FALSE) && ((*listEntry)->Tag == Tag)) {
|
||||||
|
|
||||||
|
*listEntry = block->NextBlock;
|
||||||
|
ExFreePool(block);
|
||||||
|
found = TRUE;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
listEntry = &((*listEntry)->NextBlock);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found) {
|
||||||
|
if(commonExtension->RemoveTrackingUntrackedCount == 0) {
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||||
|
"Couldn't find Tag %p in the lock tracking list\n",
|
||||||
|
Tag));
|
||||||
|
ASSERT(FALSE);
|
||||||
|
} else {
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassReleaseRemoveLock: "
|
||||||
|
"Couldn't find Tag %p in the lock tracking list - "
|
||||||
|
"may be one of the %d untracked requests still "
|
||||||
|
"outstanding\n",
|
||||||
|
Tag,
|
||||||
|
commonExtension->RemoveTrackingUntrackedCount));
|
||||||
|
|
||||||
|
commonExtension->RemoveTrackingUntrackedCount--;
|
||||||
|
ASSERT(commonExtension->RemoveTrackingUntrackedCount >= 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||||
|
oldIrql);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
lockValue = InterlockedDecrement(&commonExtension->RemoveLock);
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||||
|
"Released for Object %p & irp %p - count is %d\n",
|
||||||
|
DeviceObject, Tag, lockValue));
|
||||||
|
|
||||||
|
ASSERT(lockValue >= 0);
|
||||||
|
|
||||||
|
ASSERTMSG("RemoveLock decreased to meet LockLowWatermark",
|
||||||
|
((LockLowWatermark == 0) || !(lockValue == LockLowWatermark)));
|
||||||
|
|
||||||
|
if(lockValue == 0) {
|
||||||
|
|
||||||
|
ASSERT(commonExtension->IsRemoved);
|
||||||
|
|
||||||
|
//
|
||||||
|
// The device needs to be removed. Signal the remove event
|
||||||
|
// that it's safe to go ahead.
|
||||||
|
//
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugRemoveLock, "ClassReleaseRemoveLock: "
|
||||||
|
"Release for object %p & irp %p caused lock to go to zero\n",
|
||||||
|
DeviceObject, Tag));
|
||||||
|
|
||||||
|
KeSetEvent(&commonExtension->RemoveEvent,
|
||||||
|
IO_NO_INCREMENT,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*++////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ClassCompleteRequest()
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
|
||||||
|
This routine is a wrapper around (and should be used instead of)
|
||||||
|
IoCompleteRequest. It is used primarily for debugging purposes.
|
||||||
|
The routine will assert if the Irp being completed is still holding
|
||||||
|
the release lock.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
DeviceObject - the device object that was handling this request
|
||||||
|
|
||||||
|
Irp - the irp to be completed by IoCompleteRequest
|
||||||
|
|
||||||
|
PriorityBoost - the priority boost to pass to IoCompleteRequest
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
|
||||||
|
none
|
||||||
|
|
||||||
|
--*/
|
||||||
|
VOID
|
||||||
|
ClassCompleteRequest(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN CCHAR PriorityBoost
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension;
|
||||||
|
PREMOVE_TRACKING_BLOCK *listEntry =
|
||||||
|
(PREMOVE_TRACKING_BLOCK)&commonExtension->RemoveTrackingList;
|
||||||
|
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&commonExtension->RemoveTrackingSpinlock,
|
||||||
|
&oldIrql);
|
||||||
|
|
||||||
|
while(*listEntry != NULL) {
|
||||||
|
|
||||||
|
if((*listEntry)->Tag == Irp) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
listEntry = &((*listEntry)->NextBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*listEntry != NULL) {
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassCompleteRequest: "
|
||||||
|
"Irp %p completed while still holding the remove lock\n",
|
||||||
|
Irp));
|
||||||
|
DebugPrint((ClassDebugError, ">>>>>ClassCompleteRequest: "
|
||||||
|
"Lock acquired in file %s on line %d\n",
|
||||||
|
(*listEntry)->File, (*listEntry)->Line));
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&commonExtension->RemoveTrackingSpinlock, oldIrql);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IoCompleteRequest(Irp, PriorityBoost);
|
||||||
|
return;
|
||||||
|
} // end ClassCompleteRequest()
|
||||||
|
|
1060
reactos/drivers/storage/classpnp/obsolete.c
Normal file
1060
reactos/drivers/storage/classpnp/obsolete.c
Normal file
File diff suppressed because it is too large
Load diff
1607
reactos/drivers/storage/classpnp/power.c
Normal file
1607
reactos/drivers/storage/classpnp/power.c
Normal file
File diff suppressed because it is too large
Load diff
349
reactos/drivers/storage/classpnp/retry.c
Normal file
349
reactos/drivers/storage/classpnp/retry.c
Normal file
|
@ -0,0 +1,349 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
retry.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Packet retry routines for CLASSPNP
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "classp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* InterpretTransferPacketError
|
||||||
|
*
|
||||||
|
* Interpret the SRB error into a meaningful IRP status.
|
||||||
|
* ClassInterpretSenseInfo also may modify the SRB for the retry.
|
||||||
|
*
|
||||||
|
* Return TRUE iff packet should be retried.
|
||||||
|
*/
|
||||||
|
BOOLEAN InterpretTransferPacketError(PTRANSFER_PACKET Pkt)
|
||||||
|
{
|
||||||
|
BOOLEAN shouldRetry = FALSE;
|
||||||
|
PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interpret the error using the returned sense info first.
|
||||||
|
*/
|
||||||
|
Pkt->RetryIntervalSec = 0;
|
||||||
|
if (pCdb->MEDIA_REMOVAL.OperationCode == SCSIOP_MEDIUM_REMOVAL){
|
||||||
|
/*
|
||||||
|
* This is an Ejection Control SRB. Interpret its sense info specially.
|
||||||
|
*/
|
||||||
|
shouldRetry = ClassInterpretSenseInfo(
|
||||||
|
Pkt->Fdo,
|
||||||
|
&Pkt->Srb,
|
||||||
|
IRP_MJ_SCSI,
|
||||||
|
0,
|
||||||
|
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||||
|
&Pkt->Irp->IoStatus.Status,
|
||||||
|
&Pkt->RetryIntervalSec);
|
||||||
|
if (shouldRetry){
|
||||||
|
/*
|
||||||
|
* If the device is not ready, wait at least 2 seconds before retrying.
|
||||||
|
*/
|
||||||
|
PSENSE_DATA senseInfoBuffer = Pkt->Srb.SenseInfoBuffer;
|
||||||
|
ASSERT(senseInfoBuffer);
|
||||||
|
if (((Pkt->Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) &&
|
||||||
|
(senseInfoBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)) ||
|
||||||
|
(SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)){
|
||||||
|
|
||||||
|
Pkt->RetryIntervalSec = MAX(Pkt->RetryIntervalSec, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE) ||
|
||||||
|
(pCdb->MODE_SENSE.OperationCode == SCSIOP_MODE_SENSE10)){
|
||||||
|
/*
|
||||||
|
* This is an Mode Sense SRB. Interpret its sense info specially.
|
||||||
|
*/
|
||||||
|
shouldRetry = ClassInterpretSenseInfo(
|
||||||
|
Pkt->Fdo,
|
||||||
|
&Pkt->Srb,
|
||||||
|
IRP_MJ_SCSI,
|
||||||
|
0,
|
||||||
|
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||||
|
&Pkt->Irp->IoStatus.Status,
|
||||||
|
&Pkt->RetryIntervalSec);
|
||||||
|
if (shouldRetry){
|
||||||
|
/*
|
||||||
|
* If the device is not ready, wait at least 2 seconds before retrying.
|
||||||
|
*/
|
||||||
|
PSENSE_DATA senseInfoBuffer = Pkt->Srb.SenseInfoBuffer;
|
||||||
|
ASSERT(senseInfoBuffer);
|
||||||
|
if (((Pkt->Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) &&
|
||||||
|
(senseInfoBuffer->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)) ||
|
||||||
|
(SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_SELECTION_TIMEOUT)){
|
||||||
|
|
||||||
|
Pkt->RetryIntervalSec = MAX(Pkt->RetryIntervalSec, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some special cases for mode sense.
|
||||||
|
*/
|
||||||
|
if (Pkt->Irp->IoStatus.Status == STATUS_VERIFY_REQUIRED){
|
||||||
|
shouldRetry = TRUE;
|
||||||
|
}
|
||||||
|
else if (SRB_STATUS(Pkt->Srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN){
|
||||||
|
/*
|
||||||
|
* This is a HACK.
|
||||||
|
* Atapi returns SRB_STATUS_DATA_OVERRUN when it really means
|
||||||
|
* underrun (i.e. success, and the buffer is longer than needed).
|
||||||
|
* So treat this as a success.
|
||||||
|
*/
|
||||||
|
Pkt->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
InterlockedExchangeAdd((PLONG)&Pkt->OriginalIrp->IoStatus.Information, (LONG)Pkt->Srb.DataTransferLength);
|
||||||
|
shouldRetry = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (pCdb->CDB10.OperationCode == SCSIOP_READ_CAPACITY){
|
||||||
|
/*
|
||||||
|
* This is a Drive Capacity SRB. Interpret its sense info specially.
|
||||||
|
*/
|
||||||
|
shouldRetry = ClassInterpretSenseInfo(
|
||||||
|
Pkt->Fdo,
|
||||||
|
&Pkt->Srb,
|
||||||
|
IRP_MJ_SCSI,
|
||||||
|
0,
|
||||||
|
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||||
|
&Pkt->Irp->IoStatus.Status,
|
||||||
|
&Pkt->RetryIntervalSec);
|
||||||
|
if (Pkt->Irp->IoStatus.Status == STATUS_VERIFY_REQUIRED){
|
||||||
|
shouldRetry = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((pCdb->CDB10.OperationCode == SCSIOP_READ) ||
|
||||||
|
(pCdb->CDB10.OperationCode == SCSIOP_WRITE)){
|
||||||
|
/*
|
||||||
|
* This is a Read/Write Data packet.
|
||||||
|
*/
|
||||||
|
PIO_STACK_LOCATION origCurrentSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp);
|
||||||
|
|
||||||
|
shouldRetry = ClassInterpretSenseInfo(
|
||||||
|
Pkt->Fdo,
|
||||||
|
&Pkt->Srb,
|
||||||
|
origCurrentSp->MajorFunction,
|
||||||
|
0,
|
||||||
|
MAXIMUM_RETRIES - Pkt->NumRetries,
|
||||||
|
&Pkt->Irp->IoStatus.Status,
|
||||||
|
&Pkt->RetryIntervalSec);
|
||||||
|
/*
|
||||||
|
* Deal with some special cases.
|
||||||
|
*/
|
||||||
|
if (Pkt->Irp->IoStatus.Status == STATUS_INSUFFICIENT_RESOURCES){
|
||||||
|
/*
|
||||||
|
* We are in extreme low-memory stress.
|
||||||
|
* We will retry in smaller chunks.
|
||||||
|
*/
|
||||||
|
shouldRetry = TRUE;
|
||||||
|
}
|
||||||
|
else if (TEST_FLAG(origCurrentSp->Flags, SL_OVERRIDE_VERIFY_VOLUME) &&
|
||||||
|
(Pkt->Irp->IoStatus.Status == STATUS_VERIFY_REQUIRED)){
|
||||||
|
/*
|
||||||
|
* We are still verifying a (possibly) reloaded disk/cdrom.
|
||||||
|
* So retry the request.
|
||||||
|
*/
|
||||||
|
Pkt->Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
|
||||||
|
shouldRetry = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBGERR(("Unhandled SRB Function %xh in error path for packet %p (did miniport change Srb.Cdb.OperationCode ?)", (ULONG)pCdb->CDB10.OperationCode, Pkt));
|
||||||
|
}
|
||||||
|
|
||||||
|
return shouldRetry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RetryTransferPacket
|
||||||
|
*
|
||||||
|
* Retry sending a TRANSFER_PACKET.
|
||||||
|
*
|
||||||
|
* Return TRUE iff the packet is complete.
|
||||||
|
* (if so the status in pkt->irp is the final status).
|
||||||
|
*/
|
||||||
|
BOOLEAN RetryTransferPacket(PTRANSFER_PACKET Pkt)
|
||||||
|
{
|
||||||
|
BOOLEAN packetDone;
|
||||||
|
|
||||||
|
DBGTRACE(ClassDebugTrace, ("retrying failed transfer (pkt=%ph, op=%s)", Pkt, DBGGETSCSIOPSTR(&Pkt->Srb)));
|
||||||
|
|
||||||
|
ASSERT(Pkt->NumRetries > 0);
|
||||||
|
Pkt->NumRetries--;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tone down performance on the retry.
|
||||||
|
* This increases the chance for success on the retry.
|
||||||
|
* We've seen instances of drives that fail consistently but then start working
|
||||||
|
* once this scale-down is applied.
|
||||||
|
*/
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
CLEAR_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||||
|
Pkt->Srb.QueueTag = SP_UNTAGGED;
|
||||||
|
|
||||||
|
if (Pkt->Irp->IoStatus.Status == STATUS_INSUFFICIENT_RESOURCES){
|
||||||
|
PCDB pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
BOOLEAN isReadWrite = ((pCdb->CDB10.OperationCode == SCSIOP_READ) ||
|
||||||
|
(pCdb->CDB10.OperationCode == SCSIOP_WRITE));
|
||||||
|
|
||||||
|
if (Pkt->InLowMemRetry || !isReadWrite){
|
||||||
|
/*
|
||||||
|
* This should never happen.
|
||||||
|
* The memory manager guarantees that at least four pages will
|
||||||
|
* be available to allow forward progress in the port driver.
|
||||||
|
* So a one-page transfer should never fail with insufficient resources.
|
||||||
|
*/
|
||||||
|
ASSERT(isReadWrite && !Pkt->InLowMemRetry);
|
||||||
|
packetDone = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* We are in low-memory stress.
|
||||||
|
* Start the low-memory retry state machine, which tries to
|
||||||
|
* resend the packet in little one-page chunks.
|
||||||
|
*/
|
||||||
|
InitLowMemRetry( Pkt,
|
||||||
|
Pkt->BufPtrCopy,
|
||||||
|
Pkt->BufLenCopy,
|
||||||
|
Pkt->TargetLocationCopy);
|
||||||
|
StepLowMemRetry(Pkt);
|
||||||
|
packetDone = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* Retry the packet by simply resending it after a delay.
|
||||||
|
* Put the packet back in the pending queue and
|
||||||
|
* schedule a timer to retry the transfer.
|
||||||
|
*
|
||||||
|
* Do not call SetupReadWriteTransferPacket again because:
|
||||||
|
* (1) The minidriver may have set some bits
|
||||||
|
* in the SRB that it needs again and
|
||||||
|
* (2) doing so would reset numRetries.
|
||||||
|
*
|
||||||
|
* BECAUSE we do not call SetupReadWriteTransferPacket again,
|
||||||
|
* we have to reset a couple fields in the SRB that
|
||||||
|
* some miniports overwrite when they fail an SRB.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Pkt->Srb.DataBuffer = Pkt->BufPtrCopy;
|
||||||
|
Pkt->Srb.DataTransferLength = Pkt->BufLenCopy;
|
||||||
|
|
||||||
|
if (Pkt->RetryIntervalSec == 0){
|
||||||
|
/*
|
||||||
|
* Always delay by at least a little when retrying.
|
||||||
|
* Some problems (e.g. CRC errors) are not recoverable without a slight delay.
|
||||||
|
*/
|
||||||
|
LARGE_INTEGER timerPeriod;
|
||||||
|
|
||||||
|
timerPeriod.HighPart = -1;
|
||||||
|
timerPeriod.LowPart = -(LONG)((ULONG)MINIMUM_RETRY_UNITS*KeQueryTimeIncrement());
|
||||||
|
KeInitializeTimer(&Pkt->RetryTimer);
|
||||||
|
KeInitializeDpc(&Pkt->RetryTimerDPC, TransferPacketRetryTimerDpc, Pkt);
|
||||||
|
KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LARGE_INTEGER timerPeriod;
|
||||||
|
|
||||||
|
ASSERT(Pkt->RetryIntervalSec < 100); // sanity check
|
||||||
|
timerPeriod.HighPart = -1;
|
||||||
|
timerPeriod.LowPart = Pkt->RetryIntervalSec*-10000000;
|
||||||
|
KeInitializeTimer(&Pkt->RetryTimer);
|
||||||
|
KeInitializeDpc(&Pkt->RetryTimerDPC, TransferPacketRetryTimerDpc, Pkt);
|
||||||
|
KeSetTimer(&Pkt->RetryTimer, timerPeriod, &Pkt->RetryTimerDPC);
|
||||||
|
}
|
||||||
|
packetDone = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return packetDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID TransferPacketRetryTimerDpc( IN PKDPC Dpc,
|
||||||
|
IN PVOID DeferredContext,
|
||||||
|
IN PVOID SystemArgument1,
|
||||||
|
IN PVOID SystemArgument2)
|
||||||
|
{
|
||||||
|
PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)DeferredContext;
|
||||||
|
SubmitTransferPacket(pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID InitLowMemRetry(PTRANSFER_PACKET Pkt, PVOID BufPtr, ULONG Len, LARGE_INTEGER TargetLocation)
|
||||||
|
{
|
||||||
|
ASSERT(Len > 0);
|
||||||
|
ASSERT(!Pkt->InLowMemRetry);
|
||||||
|
Pkt->InLowMemRetry = TRUE;
|
||||||
|
Pkt->LowMemRetry_remainingBufPtr = BufPtr;
|
||||||
|
Pkt->LowMemRetry_remainingBufLen = Len;
|
||||||
|
Pkt->LowMemRetry_nextChunkTargetLocation = TargetLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* StepLowMemRetry
|
||||||
|
*
|
||||||
|
* During extreme low-memory stress, this function retries
|
||||||
|
* a packet in small one-page chunks, sent serially.
|
||||||
|
*
|
||||||
|
* Returns TRUE iff the packet is done.
|
||||||
|
*/
|
||||||
|
BOOLEAN StepLowMemRetry(PTRANSFER_PACKET Pkt)
|
||||||
|
{
|
||||||
|
BOOLEAN packetDone;
|
||||||
|
|
||||||
|
if (Pkt->LowMemRetry_remainingBufLen == 0){
|
||||||
|
packetDone = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ULONG thisChunkLen;
|
||||||
|
ULONG bytesToNextPageBoundary;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the little chunk we send is <= a page length
|
||||||
|
* AND that it does not cross any page boundaries.
|
||||||
|
*/
|
||||||
|
bytesToNextPageBoundary = PAGE_SIZE-(ULONG)((ULONG_PTR)Pkt->LowMemRetry_remainingBufPtr%PAGE_SIZE);
|
||||||
|
thisChunkLen = MIN(Pkt->LowMemRetry_remainingBufLen, bytesToNextPageBoundary);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up the transfer packet for the new little chunk.
|
||||||
|
* This will reset numRetries so that we retry each chunk as required.
|
||||||
|
*/
|
||||||
|
SetupReadWriteTransferPacket(Pkt,
|
||||||
|
Pkt->LowMemRetry_remainingBufPtr,
|
||||||
|
thisChunkLen,
|
||||||
|
Pkt->LowMemRetry_nextChunkTargetLocation,
|
||||||
|
Pkt->OriginalIrp);
|
||||||
|
|
||||||
|
Pkt->LowMemRetry_remainingBufPtr += thisChunkLen;
|
||||||
|
Pkt->LowMemRetry_remainingBufLen -= thisChunkLen;
|
||||||
|
Pkt->LowMemRetry_nextChunkTargetLocation.QuadPart += thisChunkLen;
|
||||||
|
|
||||||
|
SubmitTransferPacket(Pkt);
|
||||||
|
packetDone = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return packetDone;
|
||||||
|
}
|
||||||
|
|
85
reactos/drivers/storage/classpnp/sources
Normal file
85
reactos/drivers/storage/classpnp/sources
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
!IF 0
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1996 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
sources.
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
TARGETNAME=classpnp
|
||||||
|
TARGETPATH=obj
|
||||||
|
TARGETTYPE=EXPORT_DRIVER
|
||||||
|
|
||||||
|
!IFNDEF MSC_WARNING_LEVEL
|
||||||
|
MSC_WARNING_LEVEL=/W3
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
MSC_WARNING_LEVEL=$(MSC_WARNING_LEVEL) /WX
|
||||||
|
|
||||||
|
PASS1_PUBLISH={$(O)\classpnp.lib=$(DDK_LIB_PATH)\classpnp.lib}
|
||||||
|
|
||||||
|
INCLUDES=..\inc;..\..\inc
|
||||||
|
|
||||||
|
#
|
||||||
|
# Specify whether to break into the debugger if synchronous irps
|
||||||
|
# sent via ClassSendSrbSynchronous() do not complete within the
|
||||||
|
# given timeout period
|
||||||
|
#
|
||||||
|
C_DEFINES=$(C_DEFINES) -DCLASS_GLOBAL_BREAK_ON_LOST_IRPS=0
|
||||||
|
|
||||||
|
#
|
||||||
|
# Specifies the number of seconds for breaking for above
|
||||||
|
# Implementation details are within the source.
|
||||||
|
#
|
||||||
|
C_DEFINES=$(C_DEFINES) -DCLASS_GLOBAL_SECONDS_TO_WAIT_FOR_SYNCHRONOUS_SRB=100
|
||||||
|
|
||||||
|
#
|
||||||
|
# Specifies that retried requests shall be delayed as
|
||||||
|
# specified by ClassInterpretSenseInfo().
|
||||||
|
# Implementation details are within the source.
|
||||||
|
#
|
||||||
|
C_DEFINES=$(C_DEFINES) -DCLASS_GLOBAL_USE_DELAYED_RETRY=1
|
||||||
|
|
||||||
|
#
|
||||||
|
# You can enable buffering of debug prints to a global buffer by setting
|
||||||
|
# this to 1. This allows debug prints while tracking timing issues.
|
||||||
|
# Implementation details are within the source.
|
||||||
|
#
|
||||||
|
C_DEFINES=$(C_DEFINES) -DCLASS_GLOBAL_BUFFERED_DEBUG_PRINT=0
|
||||||
|
|
||||||
|
#
|
||||||
|
# This is the maximum size for each debug print string sent to DebugPrint(()),
|
||||||
|
# including the trailing NUL character.
|
||||||
|
# Implementation details are within the source.
|
||||||
|
#
|
||||||
|
C_DEFINES=$(C_DEFINES) -DCLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFER_SIZE=512
|
||||||
|
|
||||||
|
#
|
||||||
|
# This is the number of unique buffers allocated for buffered printing.
|
||||||
|
# Implementation details are within the source.
|
||||||
|
#
|
||||||
|
C_DEFINES=$(C_DEFINES) -DCLASS_GLOBAL_BUFFERED_DEBUG_PRINT_BUFFERS=512
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES=autorun.c \
|
||||||
|
class.c \
|
||||||
|
classwmi.c \
|
||||||
|
create.c \
|
||||||
|
data.c \
|
||||||
|
dictlib.c \
|
||||||
|
lock.c \
|
||||||
|
power.c \
|
||||||
|
xferpkt.c \
|
||||||
|
clntirp.c \
|
||||||
|
retry.c \
|
||||||
|
utils.c \
|
||||||
|
obsolete.c \
|
||||||
|
debug.c \
|
||||||
|
class.rc
|
||||||
|
|
||||||
|
DLLDEF=$(O)\class.def
|
||||||
|
|
||||||
|
|
||||||
|
|
565
reactos/drivers/storage/classpnp/utils.c
Normal file
565
reactos/drivers/storage/classpnp/utils.c
Normal file
|
@ -0,0 +1,565 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
utils.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
SCSI class driver routines
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "classp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, ClassGetDeviceParameter)
|
||||||
|
#pragma alloc_text(PAGE, ClassScanForSpecial)
|
||||||
|
#pragma alloc_text(PAGE, ClassSetDeviceParameter)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// custom string match -- careful!
|
||||||
|
BOOLEAN ClasspMyStringMatches(IN PCHAR StringToMatch OPTIONAL, IN PCHAR TargetString)
|
||||||
|
{
|
||||||
|
ULONG length; // strlen returns an int, not size_t (!)
|
||||||
|
PAGED_CODE();
|
||||||
|
ASSERT(TargetString);
|
||||||
|
// if no match requested, return TRUE
|
||||||
|
if (StringToMatch == NULL) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
// cache the string length for efficiency
|
||||||
|
length = strlen(StringToMatch);
|
||||||
|
// ZERO-length strings may only match zero-length strings
|
||||||
|
if (length == 0) {
|
||||||
|
return (strlen(TargetString) == 0);
|
||||||
|
}
|
||||||
|
// strncmp returns zero if the strings match
|
||||||
|
return (strncmp(StringToMatch, TargetString, length) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID ClassGetDeviceParameter(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN PWSTR SubkeyName OPTIONAL,
|
||||||
|
IN PWSTR ParameterName,
|
||||||
|
IN OUT PULONG ParameterValue // also default value
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
RTL_QUERY_REGISTRY_TABLE queryTable[2];
|
||||||
|
HANDLE deviceParameterHandle;
|
||||||
|
HANDLE deviceSubkeyHandle;
|
||||||
|
ULONG defaultParameterValue;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
//
|
||||||
|
// open the given parameter
|
||||||
|
//
|
||||||
|
|
||||||
|
status = IoOpenDeviceRegistryKey(FdoExtension->LowerPdo,
|
||||||
|
PLUGPLAY_REGKEY_DEVICE,
|
||||||
|
KEY_READ,
|
||||||
|
&deviceParameterHandle);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
|
||||||
|
|
||||||
|
UNICODE_STRING subkeyName;
|
||||||
|
OBJECT_ATTRIBUTES objectAttributes;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&subkeyName, SubkeyName);
|
||||||
|
InitializeObjectAttributes(&objectAttributes,
|
||||||
|
&subkeyName,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
deviceParameterHandle,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
status = ZwOpenKey(&deviceSubkeyHandle,
|
||||||
|
KEY_READ,
|
||||||
|
&objectAttributes);
|
||||||
|
if (!NT_SUCCESS(status)) {
|
||||||
|
ZwClose(deviceParameterHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status)) {
|
||||||
|
|
||||||
|
RtlZeroMemory(queryTable, sizeof(queryTable));
|
||||||
|
|
||||||
|
defaultParameterValue = *ParameterValue;
|
||||||
|
|
||||||
|
queryTable->Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
|
||||||
|
queryTable->Name = ParameterName;
|
||||||
|
queryTable->EntryContext = ParameterValue;
|
||||||
|
queryTable->DefaultType = REG_DWORD;
|
||||||
|
queryTable->DefaultData = NULL;
|
||||||
|
queryTable->DefaultLength = 0;
|
||||||
|
|
||||||
|
status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
|
||||||
|
(PWSTR)(SubkeyName ?
|
||||||
|
deviceSubkeyHandle :
|
||||||
|
deviceParameterHandle),
|
||||||
|
queryTable,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(status)) {
|
||||||
|
*ParameterValue = defaultParameterValue; // use default value
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// close what we open
|
||||||
|
//
|
||||||
|
|
||||||
|
if (SubkeyName) {
|
||||||
|
ZwClose(deviceSubkeyHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZwClose(deviceParameterHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
} // end ClassGetDeviceParameter()
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS ClassSetDeviceParameter(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN PWSTR SubkeyName OPTIONAL,
|
||||||
|
IN PWSTR ParameterName,
|
||||||
|
IN ULONG ParameterValue)
|
||||||
|
{
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE deviceParameterHandle;
|
||||||
|
HANDLE deviceSubkeyHandle;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
//
|
||||||
|
// open the given parameter
|
||||||
|
//
|
||||||
|
|
||||||
|
status = IoOpenDeviceRegistryKey(FdoExtension->LowerPdo,
|
||||||
|
PLUGPLAY_REGKEY_DEVICE,
|
||||||
|
KEY_READ | KEY_WRITE,
|
||||||
|
&deviceParameterHandle);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status) && (SubkeyName != NULL)) {
|
||||||
|
|
||||||
|
UNICODE_STRING subkeyName;
|
||||||
|
OBJECT_ATTRIBUTES objectAttributes;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&subkeyName, SubkeyName);
|
||||||
|
InitializeObjectAttributes(&objectAttributes,
|
||||||
|
&subkeyName,
|
||||||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||||
|
deviceParameterHandle,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
status = ZwCreateKey(&deviceSubkeyHandle,
|
||||||
|
KEY_READ | KEY_WRITE,
|
||||||
|
&objectAttributes,
|
||||||
|
0, NULL, 0, NULL);
|
||||||
|
if (!NT_SUCCESS(status)) {
|
||||||
|
ZwClose(deviceParameterHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NT_SUCCESS(status)) {
|
||||||
|
|
||||||
|
status = RtlWriteRegistryValue(
|
||||||
|
RTL_REGISTRY_HANDLE,
|
||||||
|
(PWSTR) (SubkeyName ?
|
||||||
|
deviceSubkeyHandle :
|
||||||
|
deviceParameterHandle),
|
||||||
|
ParameterName,
|
||||||
|
REG_DWORD,
|
||||||
|
&ParameterValue,
|
||||||
|
sizeof(ULONG));
|
||||||
|
|
||||||
|
//
|
||||||
|
// close what we open
|
||||||
|
//
|
||||||
|
|
||||||
|
if (SubkeyName) {
|
||||||
|
ZwClose(deviceSubkeyHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZwClose(deviceParameterHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
|
||||||
|
} // end ClassSetDeviceParameter()
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ClassScanForSpecial
|
||||||
|
*
|
||||||
|
* This routine was written to simplify scanning for special
|
||||||
|
* hardware based upon id strings. it does not check the registry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
VOID ClassScanForSpecial(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
|
||||||
|
IN CLASSPNP_SCAN_FOR_SPECIAL_INFO DeviceList[],
|
||||||
|
IN PCLASS_SCAN_FOR_SPECIAL_HANDLER Function)
|
||||||
|
{
|
||||||
|
PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
|
||||||
|
PUCHAR vendorId;
|
||||||
|
PUCHAR productId;
|
||||||
|
PUCHAR productRevision;
|
||||||
|
UCHAR nullString[] = "";
|
||||||
|
ULONG j;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
ASSERT(DeviceList);
|
||||||
|
ASSERT(Function);
|
||||||
|
|
||||||
|
deviceDescriptor = FdoExtension->DeviceDescriptor;
|
||||||
|
|
||||||
|
if (DeviceList == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Function == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SCSI sets offsets to -1, ATAPI sets to 0. check for both.
|
||||||
|
//
|
||||||
|
|
||||||
|
if (deviceDescriptor->VendorIdOffset != 0 &&
|
||||||
|
deviceDescriptor->VendorIdOffset != -1) {
|
||||||
|
vendorId = ((PUCHAR)deviceDescriptor);
|
||||||
|
vendorId += deviceDescriptor->VendorIdOffset;
|
||||||
|
} else {
|
||||||
|
vendorId = nullString;
|
||||||
|
}
|
||||||
|
if (deviceDescriptor->ProductIdOffset != 0 &&
|
||||||
|
deviceDescriptor->ProductIdOffset != -1) {
|
||||||
|
productId = ((PUCHAR)deviceDescriptor);
|
||||||
|
productId += deviceDescriptor->ProductIdOffset;
|
||||||
|
} else {
|
||||||
|
productId = nullString;
|
||||||
|
}
|
||||||
|
if (deviceDescriptor->VendorIdOffset != 0 &&
|
||||||
|
deviceDescriptor->VendorIdOffset != -1) {
|
||||||
|
productRevision = ((PUCHAR)deviceDescriptor);
|
||||||
|
productRevision += deviceDescriptor->ProductRevisionOffset;
|
||||||
|
} else {
|
||||||
|
productRevision = nullString;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// loop while the device list is valid (not null-filled)
|
||||||
|
//
|
||||||
|
|
||||||
|
for (;(DeviceList->VendorId != NULL ||
|
||||||
|
DeviceList->ProductId != NULL ||
|
||||||
|
DeviceList->ProductRevision != NULL);DeviceList++) {
|
||||||
|
|
||||||
|
if (ClasspMyStringMatches(DeviceList->VendorId, vendorId) &&
|
||||||
|
ClasspMyStringMatches(DeviceList->ProductId, productId) &&
|
||||||
|
ClasspMyStringMatches(DeviceList->ProductRevision, productRevision)
|
||||||
|
) {
|
||||||
|
|
||||||
|
DebugPrint((1, "ClasspScanForSpecialByInquiry: Found matching "
|
||||||
|
"controller Ven: %s Prod: %s Rev: %s\n",
|
||||||
|
vendorId, productId, productRevision));
|
||||||
|
|
||||||
|
//
|
||||||
|
// pass the context to the call back routine and exit
|
||||||
|
//
|
||||||
|
|
||||||
|
(Function)(FdoExtension, DeviceList->Data);
|
||||||
|
|
||||||
|
//
|
||||||
|
// for CHK builds, try to prevent wierd stacks by having a debug
|
||||||
|
// print here. it's a hack, but i know of no other way to prevent
|
||||||
|
// the stack from being wrong.
|
||||||
|
//
|
||||||
|
|
||||||
|
DebugPrint((16, "ClasspScanForSpecialByInquiry: "
|
||||||
|
"completed callback\n"));
|
||||||
|
return;
|
||||||
|
|
||||||
|
} // else the strings did not match
|
||||||
|
|
||||||
|
} // none of the devices matched.
|
||||||
|
|
||||||
|
DebugPrint((1, "ClasspScanForSpecialByInquiry: no match found for %p\n",
|
||||||
|
FdoExtension->DeviceObject));
|
||||||
|
return;
|
||||||
|
|
||||||
|
} // end ClasspScanForSpecialByInquiry()
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// In order to provide better performance without the need to reboot,
|
||||||
|
// we need to implement a self-adjusting method to set and clear the
|
||||||
|
// srb flags based upon current performance.
|
||||||
|
//
|
||||||
|
// whenever there is an error, immediately grab the spin lock. the
|
||||||
|
// MP perf hit here is acceptable, since we're in an error path. this
|
||||||
|
// is also neccessary because we are guaranteed to be modifying the
|
||||||
|
// SRB flags here, setting SuccessfulIO to zero, and incrementing the
|
||||||
|
// actual error count (which is always done within this spinlock).
|
||||||
|
//
|
||||||
|
// whenever there is no error, increment a counter. if there have been
|
||||||
|
// errors on the device, and we've enabled dynamic perf, *and* we've
|
||||||
|
// just crossed the perf threshhold, then grab the spin lock and
|
||||||
|
// double check that the threshhold has, indeed been hit(*). then
|
||||||
|
// decrement the error count, and if it's dropped sufficiently, undo
|
||||||
|
// some of the safety changes made in the SRB flags due to the errors.
|
||||||
|
//
|
||||||
|
// * this works in all cases. even if lots of ios occur after the
|
||||||
|
// previous guy went in and cleared the successfulio counter, that
|
||||||
|
// just means that we've hit the threshhold again, and so it's proper
|
||||||
|
// to run the inner loop again.
|
||||||
|
//
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspPerfIncrementErrorCount(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
ULONG errors;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||||
|
|
||||||
|
fdoData->Perf.SuccessfulIO = 0; // implicit interlock
|
||||||
|
errors = InterlockedIncrement(&FdoExtension->ErrorCount);
|
||||||
|
|
||||||
|
if (errors >= CLASS_ERROR_LEVEL_1) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// If the error count has exceeded the error limit, then disable
|
||||||
|
// any tagged queuing, multiple requests per lu queueing
|
||||||
|
// and sychronous data transfers.
|
||||||
|
//
|
||||||
|
// Clearing the no queue freeze flag prevents the port driver
|
||||||
|
// from sending multiple requests per logical unit.
|
||||||
|
//
|
||||||
|
|
||||||
|
CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||||
|
CLEAR_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||||
|
|
||||||
|
SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
|
||||||
|
DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
|
||||||
|
"Too many errors; disabling tagged queuing and "
|
||||||
|
"synchronous data tranfers.\n"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors >= CLASS_ERROR_LEVEL_2) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// If a second threshold is reached, disable disconnects.
|
||||||
|
//
|
||||||
|
|
||||||
|
SET_FLAG(FdoExtension->SrbFlags, SRB_FLAGS_DISABLE_DISCONNECT);
|
||||||
|
DebugPrint((ClassDebugError, "ClasspPerfIncrementErrorCount: "
|
||||||
|
"Too many errors; disabling disconnects.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ClasspPerfIncrementSuccessfulIo(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
ULONG errors;
|
||||||
|
ULONG succeeded = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
// don't take a hit from the interlocked op unless we're in
|
||||||
|
// a degraded state and we've got a threshold to hit.
|
||||||
|
//
|
||||||
|
|
||||||
|
if (FdoExtension->ErrorCount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fdoData->Perf.ReEnableThreshhold == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
succeeded = InterlockedIncrement(&fdoData->Perf.SuccessfulIO);
|
||||||
|
if (succeeded < fdoData->Perf.ReEnableThreshhold) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// if we hit the threshold, grab the spinlock and verify we've
|
||||||
|
// actually done so. this allows us to ignore the spinlock 99%
|
||||||
|
// of the time.
|
||||||
|
//
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||||
|
|
||||||
|
//
|
||||||
|
// re-read the value, so we don't run this multiple times
|
||||||
|
// for a single threshhold being hit. this keeps errorcount
|
||||||
|
// somewhat useful.
|
||||||
|
//
|
||||||
|
|
||||||
|
succeeded = fdoData->Perf.SuccessfulIO;
|
||||||
|
|
||||||
|
if ((FdoExtension->ErrorCount != 0) &&
|
||||||
|
(fdoData->Perf.ReEnableThreshhold <= succeeded)
|
||||||
|
) {
|
||||||
|
|
||||||
|
fdoData->Perf.SuccessfulIO = 0; // implicit interlock
|
||||||
|
|
||||||
|
ASSERT(FdoExtension->ErrorCount > 0);
|
||||||
|
errors = InterlockedDecrement(&FdoExtension->ErrorCount);
|
||||||
|
|
||||||
|
//
|
||||||
|
// note: do in reverse order of the sets "just in case"
|
||||||
|
//
|
||||||
|
|
||||||
|
if (errors < CLASS_ERROR_LEVEL_2) {
|
||||||
|
if (errors == CLASS_ERROR_LEVEL_2 - 1) {
|
||||||
|
DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
|
||||||
|
"Error level 2 no longer required.\n"));
|
||||||
|
}
|
||||||
|
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_DISCONNECT)) {
|
||||||
|
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_DISCONNECT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errors < CLASS_ERROR_LEVEL_1) {
|
||||||
|
if (errors == CLASS_ERROR_LEVEL_1 - 1) {
|
||||||
|
DebugPrint((ClassDebugError, "ClasspPerfIncrementSuccessfulIo: "
|
||||||
|
"Error level 1 no longer required.\n"));
|
||||||
|
}
|
||||||
|
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
|
||||||
|
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
}
|
||||||
|
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
|
||||||
|
SET_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||||
|
}
|
||||||
|
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_NO_QUEUE_FREEZE)) {
|
||||||
|
SET_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end of threshhold definitely being hit for first time
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PMDL BuildDeviceInputMdl(PVOID Buffer, ULONG BufferLen)
|
||||||
|
{
|
||||||
|
PMDL mdl;
|
||||||
|
|
||||||
|
mdl = IoAllocateMdl(Buffer, BufferLen, FALSE, FALSE, NULL);
|
||||||
|
if (mdl){
|
||||||
|
_SEH2_TRY {
|
||||||
|
/*
|
||||||
|
* We are reading from the device.
|
||||||
|
* Therefore, the device is WRITING to the locked memory.
|
||||||
|
* So we request IoWriteAccess.
|
||||||
|
*/
|
||||||
|
MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
|
||||||
|
|
||||||
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
||||||
|
NTSTATUS status = _SEH2_GetExceptionCode();
|
||||||
|
|
||||||
|
DBGWARN(("BuildReadMdl: MmProbeAndLockPages failed with %xh.", status));
|
||||||
|
IoFreeMdl(mdl);
|
||||||
|
mdl = NULL;
|
||||||
|
} _SEH2_END;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBGWARN(("BuildReadMdl: IoAllocateMdl failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mdl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID FreeDeviceInputMdl(PMDL Mdl)
|
||||||
|
{
|
||||||
|
MmUnlockPages(Mdl);
|
||||||
|
IoFreeMdl(Mdl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
VOID
|
||||||
|
ClasspPerfResetCounters(
|
||||||
|
IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension
|
||||||
|
)
|
||||||
|
{
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = FdoExtension->PrivateFdoData;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||||
|
DebugPrint((ClassDebugError, "ClasspPerfResetCounters: "
|
||||||
|
"Resetting all perf counters.\n"));
|
||||||
|
fdoData->Perf.SuccessfulIO = 0;
|
||||||
|
FdoExtension->ErrorCount = 0;
|
||||||
|
|
||||||
|
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_DISCONNECT)) {
|
||||||
|
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_DISCONNECT);
|
||||||
|
}
|
||||||
|
if (!TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_SYNCH_TRANSFER)) {
|
||||||
|
CLEAR_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
}
|
||||||
|
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_QUEUE_ACTION_ENABLE)) {
|
||||||
|
SET_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_QUEUE_ACTION_ENABLE);
|
||||||
|
}
|
||||||
|
if (TEST_FLAG(fdoData->Perf.OriginalSrbFlags,
|
||||||
|
SRB_FLAGS_NO_QUEUE_FREEZE)) {
|
||||||
|
SET_FLAG(FdoExtension->SrbFlags,
|
||||||
|
SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
911
reactos/drivers/storage/classpnp/xferpkt.c
Normal file
911
reactos/drivers/storage/classpnp/xferpkt.c
Normal file
|
@ -0,0 +1,911 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1991 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
xferpkt.c
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
Packet routines for CLASSPNP
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
|
||||||
|
kernel mode only
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "classp.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#ifdef ALLOC_PRAGMA
|
||||||
|
#pragma alloc_text(PAGE, InitializeTransferPackets)
|
||||||
|
#pragma alloc_text(PAGE, DestroyAllTransferPackets)
|
||||||
|
#pragma alloc_text(PAGE, SetupEjectionTransferPacket)
|
||||||
|
#pragma alloc_text(PAGE, SetupModeSenseTransferPacket)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
ULONG MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||||
|
ULONG MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* InitializeTransferPackets
|
||||||
|
*
|
||||||
|
* Allocate/initialize TRANSFER_PACKETs and related resources.
|
||||||
|
*/
|
||||||
|
NTSTATUS InitializeTransferPackets(PDEVICE_OBJECT Fdo)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExt = Fdo->DeviceExtension;
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PSTORAGE_ADAPTER_DESCRIPTOR adapterDesc = commonExt->PartitionZeroExtension->AdapterDescriptor;
|
||||||
|
ULONG hwMaxPages;
|
||||||
|
NTSTATUS status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Precompute the maximum transfer length
|
||||||
|
*/
|
||||||
|
ASSERT(adapterDesc->MaximumTransferLength);
|
||||||
|
ASSERT(adapterDesc->MaximumPhysicalPages);
|
||||||
|
hwMaxPages = adapterDesc->MaximumPhysicalPages ? adapterDesc->MaximumPhysicalPages-1 : 0;
|
||||||
|
|
||||||
|
#if defined(_AMD64_SIMULATOR_)
|
||||||
|
|
||||||
|
//
|
||||||
|
// The simulator appears to have a problem with large transfers.
|
||||||
|
//
|
||||||
|
|
||||||
|
if (hwMaxPages > 4) {
|
||||||
|
hwMaxPages = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fdoData->HwMaxXferLen = MIN(adapterDesc->MaximumTransferLength, hwMaxPages << PAGE_SHIFT);
|
||||||
|
fdoData->HwMaxXferLen = MAX(fdoData->HwMaxXferLen, PAGE_SIZE);
|
||||||
|
|
||||||
|
fdoData->NumTotalTransferPackets = 0;
|
||||||
|
fdoData->NumFreeTransferPackets = 0;
|
||||||
|
InitializeSListHead(&fdoData->FreeTransferPacketsList);
|
||||||
|
InitializeListHead(&fdoData->AllTransferPacketsList);
|
||||||
|
InitializeListHead(&fdoData->DeferredClientIrpList);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the packet threshold numbers based on the Windows SKU.
|
||||||
|
*/
|
||||||
|
if (ExVerifySuite(Personal)){
|
||||||
|
// this is Windows Personal
|
||||||
|
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||||
|
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||||
|
}
|
||||||
|
else if (ExVerifySuite(Enterprise) || ExVerifySuite(DataCenter)){
|
||||||
|
// this is Advanced Server or Datacenter
|
||||||
|
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Enterprise;
|
||||||
|
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Enterprise;
|
||||||
|
}
|
||||||
|
else if (ExVerifySuite(TerminalServer)){
|
||||||
|
// this is standard Server or Pro with terminal server
|
||||||
|
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Server;
|
||||||
|
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Server;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this is Professional without terminal server
|
||||||
|
MinWorkingSetTransferPackets = MIN_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||||
|
MaxWorkingSetTransferPackets = MAX_WORKINGSET_TRANSFER_PACKETS_Consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (fdoData->NumFreeTransferPackets < MIN_INITIAL_TRANSFER_PACKETS){
|
||||||
|
PTRANSFER_PACKET pkt = NewTransferPacket(Fdo);
|
||||||
|
if (pkt){
|
||||||
|
InterlockedIncrement(&fdoData->NumTotalTransferPackets);
|
||||||
|
EnqueueFreeTransferPacket(Fdo, pkt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fdoData->DbgPeakNumTransferPackets = fdoData->NumTotalTransferPackets;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pre-initialize our SCSI_REQUEST_BLOCK template with all
|
||||||
|
* the constant fields. This will save a little time for each xfer.
|
||||||
|
* NOTE: a CdbLength field of 10 may not always be appropriate
|
||||||
|
*/
|
||||||
|
RtlZeroMemory(&fdoData->SrbTemplate, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
fdoData->SrbTemplate.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||||
|
fdoData->SrbTemplate.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
|
fdoData->SrbTemplate.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||||
|
fdoData->SrbTemplate.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||||
|
fdoData->SrbTemplate.CdbLength = 10;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID DestroyAllTransferPackets(PDEVICE_OBJECT Fdo)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
TRANSFER_PACKET *pkt;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
ASSERT(IsListEmpty(&fdoData->DeferredClientIrpList));
|
||||||
|
|
||||||
|
while (pkt = DequeueFreeTransferPacket(Fdo, FALSE)){
|
||||||
|
DestroyTransferPacket(pkt);
|
||||||
|
InterlockedDecrement(&fdoData->NumTotalTransferPackets);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(fdoData->NumTotalTransferPackets == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PTRANSFER_PACKET NewTransferPacket(PDEVICE_OBJECT Fdo)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PTRANSFER_PACKET newPkt;
|
||||||
|
|
||||||
|
newPkt = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSFER_PACKET), 'pnPC');
|
||||||
|
if (newPkt){
|
||||||
|
RtlZeroMemory(newPkt, sizeof(TRANSFER_PACKET)); // just to be sure
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate resources for the packet.
|
||||||
|
*/
|
||||||
|
newPkt->Irp = IoAllocateIrp(Fdo->StackSize, FALSE);
|
||||||
|
if (newPkt->Irp){
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
newPkt->Fdo = Fdo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enqueue the packet in our static AllTransferPacketsList
|
||||||
|
* (just so we can find it during debugging if its stuck somewhere).
|
||||||
|
*/
|
||||||
|
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||||
|
InsertTailList(&fdoData->AllTransferPacketsList, &newPkt->AllPktsListEntry);
|
||||||
|
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ExFreePool(newPkt);
|
||||||
|
newPkt = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DestroyTransferPacket
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
VOID DestroyTransferPacket(PTRANSFER_PACKET Pkt)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
ASSERT(!Pkt->SlistEntry.Next);
|
||||||
|
ASSERT(!Pkt->OriginalIrp);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete the packet from our all-packets queue.
|
||||||
|
*/
|
||||||
|
ASSERT(!IsListEmpty(&Pkt->AllPktsListEntry));
|
||||||
|
ASSERT(!IsListEmpty(&fdoData->AllTransferPacketsList));
|
||||||
|
RemoveEntryList(&Pkt->AllPktsListEntry);
|
||||||
|
InitializeListHead(&Pkt->AllPktsListEntry);
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||||
|
|
||||||
|
IoFreeIrp(Pkt->Irp);
|
||||||
|
ExFreePool(Pkt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID EnqueueFreeTransferPacket(PDEVICE_OBJECT Fdo, PTRANSFER_PACKET Pkt)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
ULONG newNumPkts;
|
||||||
|
|
||||||
|
ASSERT(!Pkt->SlistEntry.Next);
|
||||||
|
|
||||||
|
InterlockedPushEntrySList(&fdoData->FreeTransferPacketsList, &Pkt->SlistEntry);
|
||||||
|
newNumPkts = InterlockedIncrement(&fdoData->NumFreeTransferPackets);
|
||||||
|
ASSERT(newNumPkts <= fdoData->NumTotalTransferPackets);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the total number of packets is larger than MinWorkingSetTransferPackets,
|
||||||
|
* that means that we've been in stress. If all those packets are now
|
||||||
|
* free, then we are now out of stress and can free the extra packets.
|
||||||
|
* Free down to MaxWorkingSetTransferPackets immediately, and
|
||||||
|
* down to MinWorkingSetTransferPackets lazily (one at a time).
|
||||||
|
*/
|
||||||
|
if (fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets){
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Immediately snap down to our UPPER threshold.
|
||||||
|
*/
|
||||||
|
if (fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets){
|
||||||
|
SINGLE_LIST_ENTRY pktList;
|
||||||
|
PSINGLE_LIST_ENTRY slistEntry;
|
||||||
|
PTRANSFER_PACKET pktToDelete;
|
||||||
|
|
||||||
|
DBGTRACE(ClassDebugTrace, ("Exiting stress, block freeing (%d-%d) packets.", fdoData->NumTotalTransferPackets, MaxWorkingSetTransferPackets));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the counter again with lock held. This eliminates a race condition
|
||||||
|
* while still allowing us to not grab the spinlock in the common codepath.
|
||||||
|
*
|
||||||
|
* Note that the spinlock does not synchronize with threads dequeuing free
|
||||||
|
* packets to send (DequeueFreeTransferPacket does that with a lightweight
|
||||||
|
* interlocked exchange); the spinlock prevents multiple threads in this function
|
||||||
|
* from deciding to free too many extra packets at once.
|
||||||
|
*/
|
||||||
|
SimpleInitSlistHdr(&pktList);
|
||||||
|
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||||
|
while ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
|
||||||
|
(fdoData->NumTotalTransferPackets > MaxWorkingSetTransferPackets)){
|
||||||
|
|
||||||
|
pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
|
||||||
|
if (pktToDelete){
|
||||||
|
SimplePushSlist(&pktList, &pktToDelete->SlistEntry);
|
||||||
|
InterlockedDecrement(&fdoData->NumTotalTransferPackets);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (1).", MaxWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||||
|
|
||||||
|
while (slistEntry = SimplePopSlist(&pktList)){
|
||||||
|
pktToDelete = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
|
||||||
|
DestroyTransferPacket(pktToDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2. Lazily work down to our LOWER threshold (by only freeing one packet at a time).
|
||||||
|
*/
|
||||||
|
if (fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets){
|
||||||
|
/*
|
||||||
|
* Check the counter again with lock held. This eliminates a race condition
|
||||||
|
* while still allowing us to not grab the spinlock in the common codepath.
|
||||||
|
*
|
||||||
|
* Note that the spinlock does not synchronize with threads dequeuing free
|
||||||
|
* packets to send (DequeueFreeTransferPacket does that with a lightweight
|
||||||
|
* interlocked exchange); the spinlock prevents multiple threads in this function
|
||||||
|
* from deciding to free too many extra packets at once.
|
||||||
|
*/
|
||||||
|
PTRANSFER_PACKET pktToDelete = NULL;
|
||||||
|
|
||||||
|
DBGTRACE(ClassDebugTrace, ("Exiting stress, lazily freeing one of %d/%d packets.", fdoData->NumTotalTransferPackets, MinWorkingSetTransferPackets));
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&fdoData->SpinLock, &oldIrql);
|
||||||
|
if ((fdoData->NumFreeTransferPackets >= fdoData->NumTotalTransferPackets) &&
|
||||||
|
(fdoData->NumTotalTransferPackets > MinWorkingSetTransferPackets)){
|
||||||
|
|
||||||
|
pktToDelete = DequeueFreeTransferPacket(Fdo, FALSE);
|
||||||
|
if (pktToDelete){
|
||||||
|
InterlockedDecrement(&fdoData->NumTotalTransferPackets);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBGTRACE(ClassDebugTrace, ("Extremely unlikely condition (non-fatal): %d packets dequeued at once for Fdo %p. NumTotalTransferPackets=%d (2).", MinWorkingSetTransferPackets, Fdo, fdoData->NumTotalTransferPackets));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock(&fdoData->SpinLock, oldIrql);
|
||||||
|
|
||||||
|
if (pktToDelete){
|
||||||
|
DestroyTransferPacket(pktToDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PTRANSFER_PACKET pkt;
|
||||||
|
PSINGLE_LIST_ENTRY slistEntry;
|
||||||
|
KIRQL oldIrql;
|
||||||
|
|
||||||
|
slistEntry = InterlockedPopEntrySList(&fdoData->FreeTransferPacketsList);
|
||||||
|
if (slistEntry){
|
||||||
|
slistEntry->Next = NULL;
|
||||||
|
pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
|
||||||
|
ASSERT(fdoData->NumFreeTransferPackets > 0);
|
||||||
|
InterlockedDecrement(&fdoData->NumFreeTransferPackets);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (AllocIfNeeded){
|
||||||
|
/*
|
||||||
|
* We are in stress and have run out of lookaside packets.
|
||||||
|
* In order to service the current transfer,
|
||||||
|
* allocate an extra packet.
|
||||||
|
* We will free it lazily when we are out of stress.
|
||||||
|
*/
|
||||||
|
pkt = NewTransferPacket(Fdo);
|
||||||
|
if (pkt){
|
||||||
|
InterlockedIncrement(&fdoData->NumTotalTransferPackets);
|
||||||
|
fdoData->DbgPeakNumTransferPackets = max(fdoData->DbgPeakNumTransferPackets, fdoData->NumTotalTransferPackets);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DBGWARN(("DequeueFreeTransferPacket: packet allocation failed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pkt = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pkt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SetupReadWriteTransferPacket
|
||||||
|
*
|
||||||
|
* This function is called once to set up the first attempt to send a packet.
|
||||||
|
* It is not called before a retry, as SRB fields may be modified for the retry.
|
||||||
|
*
|
||||||
|
* Set up the Srb of the TRANSFER_PACKET for the transfer.
|
||||||
|
* The Irp is set up in SubmitTransferPacket because it must be reset
|
||||||
|
* for each packet submission.
|
||||||
|
*/
|
||||||
|
VOID SetupReadWriteTransferPacket( PTRANSFER_PACKET Pkt,
|
||||||
|
PVOID Buf,
|
||||||
|
ULONG Len,
|
||||||
|
LARGE_INTEGER DiskLocation,
|
||||||
|
PIRP OriginalIrp)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(OriginalIrp);
|
||||||
|
UCHAR majorFunc = origCurSp->MajorFunction;
|
||||||
|
ULONG logicalBlockAddr;
|
||||||
|
ULONG numTransferBlocks;
|
||||||
|
PCDB pCdb;
|
||||||
|
|
||||||
|
logicalBlockAddr = (ULONG)Int64ShrlMod32(DiskLocation.QuadPart, fdoExt->SectorShift);
|
||||||
|
numTransferBlocks = Len >> fdoExt->SectorShift;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Slap the constant SRB fields in from our pre-initialized template.
|
||||||
|
* We'll then only have to fill in the unique fields for this transfer.
|
||||||
|
* Tell lower drivers to sort the SRBs by the logical block address
|
||||||
|
* so that disk seeks are minimized.
|
||||||
|
*/
|
||||||
|
Pkt->Srb = fdoData->SrbTemplate; // copies _contents_ of SRB blocks
|
||||||
|
Pkt->Srb.DataBuffer = Buf;
|
||||||
|
Pkt->Srb.DataTransferLength = Len;
|
||||||
|
Pkt->Srb.QueueSortKey = logicalBlockAddr;
|
||||||
|
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||||
|
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||||
|
Pkt->Srb.TimeOutValue = (Len/0x10000) + ((Len%0x10000) ? 1 : 0);
|
||||||
|
Pkt->Srb.TimeOutValue *= fdoExt->TimeOutValue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arrange values in CDB in big-endian format.
|
||||||
|
*/
|
||||||
|
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
pCdb->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte3;
|
||||||
|
pCdb->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte2;
|
||||||
|
pCdb->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte1;
|
||||||
|
pCdb->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&logicalBlockAddr)->Byte0;
|
||||||
|
pCdb->CDB10.TransferBlocksMsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte1;
|
||||||
|
pCdb->CDB10.TransferBlocksLsb = ((PFOUR_BYTE)&numTransferBlocks)->Byte0;
|
||||||
|
pCdb->CDB10.OperationCode = (majorFunc==IRP_MJ_READ) ? SCSIOP_READ : SCSIOP_WRITE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set SRB and IRP flags
|
||||||
|
*/
|
||||||
|
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||||
|
if (TEST_FLAG(OriginalIrp->Flags, IRP_PAGING_IO) ||
|
||||||
|
TEST_FLAG(OriginalIrp->Flags, IRP_SYNCHRONOUS_PAGING_IO)){
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_CLASS_FLAGS_PAGING);
|
||||||
|
}
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, (majorFunc==IRP_MJ_READ) ? SRB_FLAGS_DATA_IN : SRB_FLAGS_DATA_OUT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow caching only if this is not a write-through request.
|
||||||
|
* If write-through and caching is enabled on the device, force
|
||||||
|
* media access.
|
||||||
|
*/
|
||||||
|
if (TEST_FLAG(origCurSp->Flags, SL_WRITE_THROUGH)){
|
||||||
|
if (TEST_FLAG(fdoExt->DeviceFlags, DEV_WRITE_CACHE)){
|
||||||
|
pCdb->CDB10.ForceUnitAccess = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_ADAPTER_CACHE_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remember the buf and len in the SRB because miniports
|
||||||
|
* can overwrite SRB.DataTransferLength and we may need it again
|
||||||
|
* for the retry.
|
||||||
|
*/
|
||||||
|
Pkt->BufPtrCopy = Buf;
|
||||||
|
Pkt->BufLenCopy = Len;
|
||||||
|
Pkt->TargetLocationCopy = DiskLocation;
|
||||||
|
|
||||||
|
Pkt->OriginalIrp = OriginalIrp;
|
||||||
|
Pkt->NumRetries = MAXIMUM_RETRIES;
|
||||||
|
Pkt->SyncEventPtr = NULL;
|
||||||
|
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SubmitTransferPacket
|
||||||
|
*
|
||||||
|
* Set up the IRP for the TRANSFER_PACKET submission and send it down.
|
||||||
|
*/
|
||||||
|
VOID SubmitTransferPacket(PTRANSFER_PACKET Pkt)
|
||||||
|
{
|
||||||
|
PCOMMON_DEVICE_EXTENSION commonExtension = Pkt->Fdo->DeviceExtension;
|
||||||
|
PDEVICE_OBJECT nextDevObj = commonExtension->LowerDeviceObject;
|
||||||
|
PIO_STACK_LOCATION nextSp = IoGetNextIrpStackLocation(Pkt->Irp);
|
||||||
|
|
||||||
|
ASSERT(Pkt->Irp->CurrentLocation == Pkt->Irp->StackCount+1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attach the SRB to the IRP.
|
||||||
|
* The reused IRP's stack location has to be rewritten for each retry
|
||||||
|
* call because IoCompleteRequest clears the stack locations.
|
||||||
|
*/
|
||||||
|
IoReuseIrp(Pkt->Irp, STATUS_NOT_SUPPORTED);
|
||||||
|
nextSp->MajorFunction = IRP_MJ_SCSI;
|
||||||
|
nextSp->Parameters.Scsi.Srb = &Pkt->Srb;
|
||||||
|
Pkt->Srb.ScsiStatus = Pkt->Srb.SrbStatus = 0;
|
||||||
|
if (Pkt->CompleteOriginalIrpWhenLastPacketCompletes){
|
||||||
|
/*
|
||||||
|
* Only dereference the "original IRP"'s stack location
|
||||||
|
* if its a real client irp (as opposed to a static irp
|
||||||
|
* we're using just for result status for one of the non-IO scsi commands).
|
||||||
|
*
|
||||||
|
* For read/write, propagate the storage-specific IRP stack location flags
|
||||||
|
* (e.g. SL_OVERRIDE_VERIFY_VOLUME, SL_WRITE_THROUGH).
|
||||||
|
*/
|
||||||
|
PIO_STACK_LOCATION origCurSp = IoGetCurrentIrpStackLocation(Pkt->OriginalIrp);
|
||||||
|
nextSp->Flags = origCurSp->Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write MDL address to new IRP. In the port driver the SRB DataBuffer
|
||||||
|
* field is used as the actual buffer pointer within the MDL,
|
||||||
|
* so the same MDL can be used for each partial transfer.
|
||||||
|
* This saves having to build a new MDL for each partial transfer.
|
||||||
|
*/
|
||||||
|
Pkt->Irp->MdlAddress = Pkt->OriginalIrp->MdlAddress;
|
||||||
|
|
||||||
|
IoSetCompletionRoutine(Pkt->Irp, TransferPktComplete, Pkt, TRUE, TRUE, TRUE);
|
||||||
|
IoCallDriver(nextDevObj, Pkt->Irp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS TransferPktComplete(IN PDEVICE_OBJECT NullFdo, IN PIRP Irp, IN PVOID Context)
|
||||||
|
{
|
||||||
|
PTRANSFER_PACKET pkt = (PTRANSFER_PACKET)Context;
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = pkt->Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PIO_STACK_LOCATION origCurrentSp = IoGetCurrentIrpStackLocation(pkt->OriginalIrp);
|
||||||
|
BOOLEAN packetDone = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put all the assertions and spew in here so we don't have to look at them.
|
||||||
|
*/
|
||||||
|
DBGCHECKRETURNEDPKT(pkt);
|
||||||
|
|
||||||
|
if (SRB_STATUS(pkt->Srb.SrbStatus) == SRB_STATUS_SUCCESS){
|
||||||
|
|
||||||
|
fdoData->LoggedTURFailureSinceLastIO = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The port driver should not have allocated a sense buffer
|
||||||
|
* if the SRB succeeded.
|
||||||
|
*/
|
||||||
|
ASSERT(!PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add this packet's transferred length to the original IRP's.
|
||||||
|
*/
|
||||||
|
InterlockedExchangeAdd((PLONG)&pkt->OriginalIrp->IoStatus.Information,
|
||||||
|
(LONG)pkt->Srb.DataTransferLength);
|
||||||
|
|
||||||
|
if (pkt->InLowMemRetry){
|
||||||
|
packetDone = StepLowMemRetry(pkt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
packetDone = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* The packet failed. We may retry it if possible.
|
||||||
|
*/
|
||||||
|
BOOLEAN shouldRetry;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure IRP status matches SRB error status (since we propagate it).
|
||||||
|
*/
|
||||||
|
if (NT_SUCCESS(Irp->IoStatus.Status)){
|
||||||
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Interpret the SRB error (to a meaningful IRP status)
|
||||||
|
* and determine if we should retry this packet.
|
||||||
|
* This call looks at the returned SENSE info to figure out what to do.
|
||||||
|
*/
|
||||||
|
shouldRetry = InterpretTransferPacketError(pkt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sometimes the port driver can allocates a new 'sense' buffer
|
||||||
|
* to report transfer errors, e.g. when the default sense buffer
|
||||||
|
* is too small. If so, it is up to us to free it.
|
||||||
|
* Now that we're done interpreting the sense info, free it if appropriate.
|
||||||
|
*/
|
||||||
|
if (PORT_ALLOCATED_SENSE(fdoExt, &pkt->Srb)) {
|
||||||
|
DBGTRACE(ClassDebugSenseInfo, ("Freeing port-allocated sense buffer for pkt %ph.", pkt));
|
||||||
|
FREE_PORT_ALLOCATED_SENSE_BUFFER(fdoExt, &pkt->Srb);
|
||||||
|
pkt->Srb.SenseInfoBuffer = &pkt->SrbErrorSenseData;
|
||||||
|
pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the SRB queue is locked-up, release it.
|
||||||
|
* Do this after calling the error handler.
|
||||||
|
*/
|
||||||
|
if (pkt->Srb.SrbStatus & SRB_STATUS_QUEUE_FROZEN){
|
||||||
|
ClassReleaseQueue(pkt->Fdo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldRetry && (pkt->NumRetries > 0)){
|
||||||
|
packetDone = RetryTransferPacket(pkt);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
packetDone = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the packet is completed, put it back in the free list.
|
||||||
|
* If it is the last packet servicing the original request, complete the original irp.
|
||||||
|
*/
|
||||||
|
if (packetDone){
|
||||||
|
LONG numPacketsRemaining;
|
||||||
|
PIRP deferredIrp;
|
||||||
|
PDEVICE_OBJECT Fdo = pkt->Fdo;
|
||||||
|
UCHAR uniqueAddr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case a remove is pending, bump the lock count so we don't get freed
|
||||||
|
* right after we complete the original irp.
|
||||||
|
*/
|
||||||
|
ClassAcquireRemoveLock(Fdo, (PIRP)&uniqueAddr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The original IRP should get an error code
|
||||||
|
* if any one of the packets failed.
|
||||||
|
*/
|
||||||
|
if (!NT_SUCCESS(Irp->IoStatus.Status)){
|
||||||
|
pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the original I/O originated in user space (i.e. it is thread-queued),
|
||||||
|
* and the error is user-correctable (e.g. media is missing, for removable media),
|
||||||
|
* alert the user.
|
||||||
|
* Since this is only one of possibly several packets completing for the original IRP,
|
||||||
|
* we may do this more than once for a single request. That's ok; this allows
|
||||||
|
* us to test each returned status with IoIsErrorUserInduced().
|
||||||
|
*/
|
||||||
|
if (IoIsErrorUserInduced(Irp->IoStatus.Status) &&
|
||||||
|
pkt->CompleteOriginalIrpWhenLastPacketCompletes &&
|
||||||
|
pkt->OriginalIrp->Tail.Overlay.Thread){
|
||||||
|
|
||||||
|
IoSetHardErrorOrVerifyDevice(pkt->OriginalIrp, pkt->Fdo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use a field in the original IRP to count
|
||||||
|
* down the transfer pieces as they complete.
|
||||||
|
*/
|
||||||
|
numPacketsRemaining = InterlockedDecrement(
|
||||||
|
(PLONG)&pkt->OriginalIrp->Tail.Overlay.DriverContext[0]);
|
||||||
|
|
||||||
|
if (numPacketsRemaining > 0){
|
||||||
|
/*
|
||||||
|
* More transfer pieces remain for the original request.
|
||||||
|
* Wait for them to complete before completing the original irp.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All the transfer pieces are done.
|
||||||
|
* Complete the original irp if appropriate.
|
||||||
|
*/
|
||||||
|
ASSERT(numPacketsRemaining == 0);
|
||||||
|
if (pkt->CompleteOriginalIrpWhenLastPacketCompletes){
|
||||||
|
if (NT_SUCCESS(pkt->OriginalIrp->IoStatus.Status)){
|
||||||
|
ASSERT((ULONG)pkt->OriginalIrp->IoStatus.Information == origCurrentSp->Parameters.Read.Length);
|
||||||
|
ClasspPerfIncrementSuccessfulIo(fdoExt);
|
||||||
|
}
|
||||||
|
ClassReleaseRemoveLock(pkt->Fdo, pkt->OriginalIrp);
|
||||||
|
|
||||||
|
ClassCompleteRequest(pkt->Fdo, pkt->OriginalIrp, IO_DISK_INCREMENT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We may have been called by one of the class drivers (e.g. cdrom)
|
||||||
|
* via the legacy API ClassSplitRequest.
|
||||||
|
* This is the only case for which the packet engine is called for an FDO
|
||||||
|
* with a StartIo routine; in that case, we have to call IoStartNextPacket
|
||||||
|
* now that the original irp has been completed.
|
||||||
|
*/
|
||||||
|
if (fdoExt->CommonExtension.DriverExtension->InitData.ClassStartIo) {
|
||||||
|
if (TEST_FLAG(pkt->Srb.SrbFlags, SRB_FLAGS_DONT_START_NEXT_PACKET)){
|
||||||
|
DBGTRAP(("SRB_FLAGS_DONT_START_NEXT_PACKET should never be set here (?)"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
KIRQL oldIrql;
|
||||||
|
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
||||||
|
IoStartNextPacket(pkt->Fdo, FALSE);
|
||||||
|
KeLowerIrql(oldIrql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the packet was synchronous, write the final
|
||||||
|
* result back to the issuer's status buffer and
|
||||||
|
* signal his event.
|
||||||
|
*/
|
||||||
|
if (pkt->SyncEventPtr){
|
||||||
|
KeSetEvent(pkt->SyncEventPtr, 0, FALSE);
|
||||||
|
pkt->SyncEventPtr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the completed packet.
|
||||||
|
*/
|
||||||
|
pkt->OriginalIrp = NULL;
|
||||||
|
pkt->InLowMemRetry = FALSE;
|
||||||
|
EnqueueFreeTransferPacket(pkt->Fdo, pkt);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now that we have freed some resources,
|
||||||
|
* try again to send one of the previously deferred irps.
|
||||||
|
*/
|
||||||
|
deferredIrp = DequeueDeferredClientIrp(fdoData);
|
||||||
|
if (deferredIrp){
|
||||||
|
DBGWARN(("... retrying deferred irp %xh.", deferredIrp));
|
||||||
|
ServiceTransferRequest(pkt->Fdo, deferredIrp);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassReleaseRemoveLock(Fdo, (PIRP)&uniqueAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SetupEjectionTransferPacket
|
||||||
|
*
|
||||||
|
* Set up a transferPacket for a synchronous Ejection Control transfer.
|
||||||
|
*/
|
||||||
|
VOID SetupEjectionTransferPacket( TRANSFER_PACKET *Pkt,
|
||||||
|
BOOLEAN PreventMediaRemoval,
|
||||||
|
PKEVENT SyncEventPtr,
|
||||||
|
PIRP OriginalIrp)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PCDB pCdb;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
|
||||||
|
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||||
|
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
|
Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||||
|
Pkt->Srb.CdbLength = 6;
|
||||||
|
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||||
|
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||||
|
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||||
|
Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
|
||||||
|
|
||||||
|
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||||
|
|
||||||
|
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
pCdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL;
|
||||||
|
pCdb->MEDIA_REMOVAL.Prevent = PreventMediaRemoval;
|
||||||
|
|
||||||
|
Pkt->BufPtrCopy = NULL;
|
||||||
|
Pkt->BufLenCopy = 0;
|
||||||
|
|
||||||
|
Pkt->OriginalIrp = OriginalIrp;
|
||||||
|
Pkt->NumRetries = NUM_LOCKMEDIAREMOVAL_RETRIES;
|
||||||
|
Pkt->SyncEventPtr = SyncEventPtr;
|
||||||
|
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SetupModeSenseTransferPacket
|
||||||
|
*
|
||||||
|
* Set up a transferPacket for a synchronous Mode Sense transfer.
|
||||||
|
*/
|
||||||
|
VOID SetupModeSenseTransferPacket( TRANSFER_PACKET *Pkt,
|
||||||
|
PKEVENT SyncEventPtr,
|
||||||
|
PVOID ModeSenseBuffer,
|
||||||
|
UCHAR ModeSenseBufferLen,
|
||||||
|
UCHAR PageMode,
|
||||||
|
PIRP OriginalIrp)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PCDB pCdb;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
|
||||||
|
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||||
|
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
|
Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||||
|
Pkt->Srb.CdbLength = 6;
|
||||||
|
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||||
|
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||||
|
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||||
|
Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
|
||||||
|
Pkt->Srb.DataBuffer = ModeSenseBuffer;
|
||||||
|
Pkt->Srb.DataTransferLength = ModeSenseBufferLen;
|
||||||
|
|
||||||
|
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DATA_IN);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||||
|
|
||||||
|
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
pCdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
|
||||||
|
pCdb->MODE_SENSE.PageCode = PageMode;
|
||||||
|
pCdb->MODE_SENSE.AllocationLength = (UCHAR)ModeSenseBufferLen;
|
||||||
|
|
||||||
|
Pkt->BufPtrCopy = ModeSenseBuffer;
|
||||||
|
Pkt->BufLenCopy = ModeSenseBufferLen;
|
||||||
|
|
||||||
|
Pkt->OriginalIrp = OriginalIrp;
|
||||||
|
Pkt->NumRetries = NUM_MODESENSE_RETRIES;
|
||||||
|
Pkt->SyncEventPtr = SyncEventPtr;
|
||||||
|
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SetupDriveCapacityTransferPacket
|
||||||
|
*
|
||||||
|
* Set up a transferPacket for a synchronous Drive Capacity transfer.
|
||||||
|
*/
|
||||||
|
VOID SetupDriveCapacityTransferPacket( TRANSFER_PACKET *Pkt,
|
||||||
|
PVOID ReadCapacityBuffer,
|
||||||
|
ULONG ReadCapacityBufferLen,
|
||||||
|
PKEVENT SyncEventPtr,
|
||||||
|
PIRP OriginalIrp)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PCDB pCdb;
|
||||||
|
|
||||||
|
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
|
||||||
|
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||||
|
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
|
Pkt->Srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
|
||||||
|
Pkt->Srb.CdbLength = 10;
|
||||||
|
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||||
|
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||||
|
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||||
|
Pkt->Srb.TimeOutValue = fdoExt->TimeOutValue;
|
||||||
|
Pkt->Srb.DataBuffer = ReadCapacityBuffer;
|
||||||
|
Pkt->Srb.DataTransferLength = ReadCapacityBufferLen;
|
||||||
|
|
||||||
|
Pkt->Srb.SrbFlags = fdoExt->SrbFlags;
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DATA_IN);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_QUEUE_FREEZE);
|
||||||
|
|
||||||
|
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
pCdb->CDB10.OperationCode = SCSIOP_READ_CAPACITY;
|
||||||
|
|
||||||
|
Pkt->BufPtrCopy = ReadCapacityBuffer;
|
||||||
|
Pkt->BufLenCopy = ReadCapacityBufferLen;
|
||||||
|
|
||||||
|
Pkt->OriginalIrp = OriginalIrp;
|
||||||
|
Pkt->NumRetries = NUM_DRIVECAPACITY_RETRIES;
|
||||||
|
Pkt->SyncEventPtr = SyncEventPtr;
|
||||||
|
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* SetupSendStartUnitTransferPacket
|
||||||
|
*
|
||||||
|
* Set up a transferPacket for a synchronous Send Start Unit transfer.
|
||||||
|
*/
|
||||||
|
VOID SetupSendStartUnitTransferPacket( TRANSFER_PACKET *Pkt,
|
||||||
|
PIRP OriginalIrp)
|
||||||
|
{
|
||||||
|
PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Pkt->Fdo->DeviceExtension;
|
||||||
|
PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
|
||||||
|
PCDB pCdb;
|
||||||
|
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
RtlZeroMemory(&Pkt->Srb, sizeof(SCSI_REQUEST_BLOCK));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the SRB.
|
||||||
|
* Use a very long timeout value to give the drive time to spin up.
|
||||||
|
*/
|
||||||
|
Pkt->Srb.Length = sizeof(SCSI_REQUEST_BLOCK);
|
||||||
|
Pkt->Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||||
|
Pkt->Srb.TimeOutValue = START_UNIT_TIMEOUT;
|
||||||
|
Pkt->Srb.CdbLength = 6;
|
||||||
|
Pkt->Srb.OriginalRequest = Pkt->Irp;
|
||||||
|
Pkt->Srb.SenseInfoBuffer = &Pkt->SrbErrorSenseData;
|
||||||
|
Pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
|
||||||
|
Pkt->Srb.Lun = 0;
|
||||||
|
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_NO_DATA_TRANSFER);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_AUTOSENSE);
|
||||||
|
SET_FLAG(Pkt->Srb.SrbFlags, SRB_FLAGS_DISABLE_SYNCH_TRANSFER);
|
||||||
|
|
||||||
|
pCdb = (PCDB)Pkt->Srb.Cdb;
|
||||||
|
pCdb->START_STOP.OperationCode = SCSIOP_START_STOP_UNIT;
|
||||||
|
pCdb->START_STOP.Start = 1;
|
||||||
|
pCdb->START_STOP.Immediate = 0;
|
||||||
|
pCdb->START_STOP.LogicalUnitNumber = 0;
|
||||||
|
|
||||||
|
Pkt->OriginalIrp = OriginalIrp;
|
||||||
|
Pkt->NumRetries = 0;
|
||||||
|
Pkt->SyncEventPtr = NULL;
|
||||||
|
Pkt->CompleteOriginalIrpWhenLastPacketCompletes = FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -16,4 +16,7 @@
|
||||||
<directory name="scsiport">
|
<directory name="scsiport">
|
||||||
<xi:include href="scsiport/scsiport.rbuild" />
|
<xi:include href="scsiport/scsiport.rbuild" />
|
||||||
</directory>
|
</directory>
|
||||||
|
<directory name="classpnp">
|
||||||
|
<xi:include href="classpnp/classpnp.rbuild" />
|
||||||
|
</directory>
|
||||||
</group>
|
</group>
|
||||||
|
|
374
reactos/drivers/storage/inc/class.h
Normal file
374
reactos/drivers/storage/inc/class.h
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 1991 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
class.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
These are the structures and defines that are used in the
|
||||||
|
SCSI class drivers.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Mike Glass (mglass)
|
||||||
|
Jeff Havens (jhavens)
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#ifndef _CLASS_
|
||||||
|
|
||||||
|
#include <ntdddisk.h>
|
||||||
|
#include <ntddcdrm.h>
|
||||||
|
#include <ntddtape.h>
|
||||||
|
#include <ntddchgr.h>
|
||||||
|
#include <ntddstor.h>
|
||||||
|
#include "ntddscsi.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// begin_ntminitape
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
|
||||||
|
#define DebugPrint(x) ScsiDebugPrint x
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define DebugPrint(x)
|
||||||
|
|
||||||
|
#endif // DBG
|
||||||
|
|
||||||
|
// end_ntminitape
|
||||||
|
|
||||||
|
#ifdef POOL_TAGGING
|
||||||
|
#undef ExAllocatePool
|
||||||
|
#undef ExAllocatePoolWithQuota
|
||||||
|
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'HscS')
|
||||||
|
#define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,'HscS')
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAXIMUM_RETRIES 4
|
||||||
|
|
||||||
|
typedef
|
||||||
|
VOID
|
||||||
|
(*PCLASS_ERROR) (
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
IN OUT NTSTATUS *Status,
|
||||||
|
IN OUT BOOLEAN *Retry
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef struct _DEVICE_EXTENSION {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Back pointer to device object
|
||||||
|
//
|
||||||
|
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer to port device object
|
||||||
|
//
|
||||||
|
|
||||||
|
PDEVICE_OBJECT PortDeviceObject;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Length of partition in bytes
|
||||||
|
//
|
||||||
|
|
||||||
|
LARGE_INTEGER PartitionLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Number of bytes before start of partition
|
||||||
|
//
|
||||||
|
|
||||||
|
LARGE_INTEGER StartingOffset;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Bytes to skew all requests, since DM Driver has been placed on an IDE drive.
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG DMByteSkew;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sectors to skew all requests.
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG DMSkew;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Flag to indicate whether DM driver has been located on an IDE drive.
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN DMActive;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Pointer to the specific class error routine.
|
||||||
|
//
|
||||||
|
|
||||||
|
PCLASS_ERROR ClassError;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SCSI port driver capabilities
|
||||||
|
//
|
||||||
|
|
||||||
|
PIO_SCSI_CAPABILITIES PortCapabilities;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Buffer for drive parameters returned in IO device control.
|
||||||
|
//
|
||||||
|
|
||||||
|
PDISK_GEOMETRY DiskGeometry;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Back pointer to device object of physical device
|
||||||
|
//
|
||||||
|
|
||||||
|
PDEVICE_OBJECT PhysicalDevice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Request Sense Buffer
|
||||||
|
//
|
||||||
|
|
||||||
|
PSENSE_DATA SenseData;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Request timeout in seconds;
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG TimeOutValue;
|
||||||
|
|
||||||
|
//
|
||||||
|
// System device number
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG DeviceNumber;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add default Srb Flags.
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG SrbFlags;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Total number of SCSI protocol errors on the device.
|
||||||
|
//
|
||||||
|
|
||||||
|
ULONG ErrorCount;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Spinlock for split requests
|
||||||
|
//
|
||||||
|
|
||||||
|
KSPIN_LOCK SplitRequestSpinLock;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Zone header and spin lock for zoned SRB requests.
|
||||||
|
//
|
||||||
|
|
||||||
|
PZONE_HEADER SrbZone;
|
||||||
|
|
||||||
|
PKSPIN_LOCK SrbZoneSpinLock;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Lock count for removable media.
|
||||||
|
//
|
||||||
|
|
||||||
|
LONG LockCount;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Scsi port number
|
||||||
|
//
|
||||||
|
|
||||||
|
UCHAR PortNumber;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SCSI path id
|
||||||
|
//
|
||||||
|
|
||||||
|
UCHAR PathId;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SCSI bus target id
|
||||||
|
//
|
||||||
|
|
||||||
|
UCHAR TargetId;
|
||||||
|
|
||||||
|
//
|
||||||
|
// SCSI bus logical unit number
|
||||||
|
//
|
||||||
|
|
||||||
|
UCHAR Lun;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Log2 of sector size
|
||||||
|
//
|
||||||
|
|
||||||
|
UCHAR SectorShift;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Flag to indicate that the device has write caching enabled.
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN WriteCache;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Build SCSI 1 or SCSI 2 CDBs
|
||||||
|
//
|
||||||
|
|
||||||
|
BOOLEAN UseScsi1;
|
||||||
|
|
||||||
|
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define context structure for asynchronous completions.
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _COMPLETION_CONTEXT {
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
SCSI_REQUEST_BLOCK Srb;
|
||||||
|
}COMPLETION_CONTEXT, *PCOMPLETION_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassGetCapabilities(
|
||||||
|
IN PDEVICE_OBJECT PortDeviceObject,
|
||||||
|
OUT PIO_SCSI_CAPABILITIES *PortCapabilities
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassGetInquiryData(
|
||||||
|
IN PDEVICE_OBJECT PortDeviceObject,
|
||||||
|
IN PSCSI_ADAPTER_BUS_INFO *ConfigInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassReadDriveCapacity(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ScsiClassReleaseQueue(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassRemoveDevice(
|
||||||
|
IN PDEVICE_OBJECT PortDeviceObject,
|
||||||
|
IN UCHAR PathId,
|
||||||
|
IN UCHAR TargetId,
|
||||||
|
IN UCHAR Lun
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassAsynchronousCompletion(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ScsiClassSplitRequest(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN ULONG MaximumBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassDeviceControl(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassIoComplete(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassIoCompleteAssociated(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp,
|
||||||
|
IN PVOID Context
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
ScsiClassInterpretSenseInfo(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
IN UCHAR MajorFunctionCode,
|
||||||
|
IN ULONG IoDeviceCode,
|
||||||
|
IN ULONG RetryCount,
|
||||||
|
OUT NTSTATUS *Status
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassSendSrbSynchronous(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
PVOID BufferAddress,
|
||||||
|
ULONG BufferLength,
|
||||||
|
BOOLEAN WriteToDevice
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassSendSrbAsynchronous(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
PIRP Irp,
|
||||||
|
PVOID BufferAddress,
|
||||||
|
ULONG BufferLength,
|
||||||
|
BOOLEAN WriteToDevice
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
ScsiClassBuildRequest(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
ScsiClassModeSense(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PCHAR ModeSenseBuffer,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN UCHAR PageMode
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
ScsiClassModeSelect(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PCHAR ModeSelectBuffer,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN BOOLEAN SavePage
|
||||||
|
);
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
ScsiClassFindModePage(
|
||||||
|
IN PCHAR ModeSenseBuffer,
|
||||||
|
IN ULONG Length,
|
||||||
|
IN UCHAR PageMode
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassClaimDevice(
|
||||||
|
IN PDEVICE_OBJECT PortDeviceObject,
|
||||||
|
IN PSCSI_INQUIRY_DATA LunInfo,
|
||||||
|
IN BOOLEAN Release,
|
||||||
|
OUT PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiClassInternalIoControl (
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif /* _CLASS_ */
|
||||||
|
|
495
reactos/drivers/storage/inc/ide.h
Normal file
495
reactos/drivers/storage/inc/ide.h
Normal file
|
@ -0,0 +1,495 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1999 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
ide.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
These are the structures and defines that are used in the
|
||||||
|
PCI IDE mini drivers.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined (___ide_h___)
|
||||||
|
#define ___ide_h___
|
||||||
|
|
||||||
|
#include "ideuser.h"
|
||||||
|
|
||||||
|
#define MAX_IDE_DEVICE 2
|
||||||
|
#define MAX_IDE_LINE 2
|
||||||
|
#define MAX_IDE_CHANNEL 2
|
||||||
|
|
||||||
|
//
|
||||||
|
// Some miniports need this structure.
|
||||||
|
// IdentifyData is passed to the miniport in
|
||||||
|
// the XfermodeSelect structure
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// IDENTIFY data
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma pack (1)
|
||||||
|
typedef struct _IDENTIFY_DATA {
|
||||||
|
USHORT GeneralConfiguration; // 00 00
|
||||||
|
USHORT NumCylinders; // 02 1
|
||||||
|
USHORT Reserved1; // 04 2
|
||||||
|
USHORT NumHeads; // 06 3
|
||||||
|
USHORT UnformattedBytesPerTrack; // 08 4
|
||||||
|
USHORT UnformattedBytesPerSector; // 0A 5
|
||||||
|
USHORT NumSectorsPerTrack; // 0C 6
|
||||||
|
USHORT VendorUnique1[3]; // 0E 7-9
|
||||||
|
UCHAR SerialNumber[20]; // 14 10-19
|
||||||
|
USHORT BufferType; // 28 20
|
||||||
|
USHORT BufferSectorSize; // 2A 21
|
||||||
|
USHORT NumberOfEccBytes; // 2C 22
|
||||||
|
UCHAR FirmwareRevision[8]; // 2E 23-26
|
||||||
|
UCHAR ModelNumber[40]; // 36 27-46
|
||||||
|
UCHAR MaximumBlockTransfer; // 5E 47
|
||||||
|
UCHAR VendorUnique2; // 5F
|
||||||
|
USHORT DoubleWordIo; // 60 48
|
||||||
|
USHORT Capabilities; // 62 49
|
||||||
|
USHORT Reserved2; // 64 50
|
||||||
|
UCHAR VendorUnique3; // 66 51
|
||||||
|
UCHAR PioCycleTimingMode; // 67
|
||||||
|
UCHAR VendorUnique4; // 68 52
|
||||||
|
UCHAR DmaCycleTimingMode; // 69
|
||||||
|
USHORT TranslationFieldsValid:3; // 6A 53
|
||||||
|
USHORT Reserved3:13;
|
||||||
|
USHORT NumberOfCurrentCylinders; // 6C 54
|
||||||
|
USHORT NumberOfCurrentHeads; // 6E 55
|
||||||
|
USHORT CurrentSectorsPerTrack; // 70 56
|
||||||
|
ULONG CurrentSectorCapacity; // 72 57-58
|
||||||
|
USHORT CurrentMultiSectorSetting; // 59
|
||||||
|
ULONG UserAddressableSectors; // 60-61
|
||||||
|
USHORT SingleWordDMASupport : 8; // 62
|
||||||
|
USHORT SingleWordDMAActive : 8;
|
||||||
|
USHORT MultiWordDMASupport : 8; // 63
|
||||||
|
USHORT MultiWordDMAActive : 8;
|
||||||
|
USHORT AdvancedPIOModes : 8; // 64
|
||||||
|
USHORT Reserved4 : 8;
|
||||||
|
USHORT MinimumMWXferCycleTime; // 65
|
||||||
|
USHORT RecommendedMWXferCycleTime; // 66
|
||||||
|
USHORT MinimumPIOCycleTime; // 67
|
||||||
|
USHORT MinimumPIOCycleTimeIORDY; // 68
|
||||||
|
USHORT Reserved5[11]; // 69-79
|
||||||
|
USHORT MajorRevision; // 80
|
||||||
|
USHORT MinorRevision; // 81
|
||||||
|
USHORT Reserved6; // 82
|
||||||
|
USHORT CommandSetSupport; // 83
|
||||||
|
USHORT Reserved6a[2]; // 84-85
|
||||||
|
USHORT CommandSetActive; // 86
|
||||||
|
USHORT Reserved6b; // 87
|
||||||
|
USHORT UltraDMASupport : 8; // 88
|
||||||
|
USHORT UltraDMAActive : 8; //
|
||||||
|
USHORT Reserved7[11]; // 89-99
|
||||||
|
ULONG Max48BitLBA[2]; // 100-103
|
||||||
|
USHORT Reserved7a[22]; // 104-125
|
||||||
|
USHORT LastLun:3; // 126
|
||||||
|
USHORT Reserved8:13;
|
||||||
|
USHORT MediaStatusNotification:2; // 127
|
||||||
|
USHORT Reserved9:6;
|
||||||
|
USHORT DeviceWriteProtect:1;
|
||||||
|
USHORT Reserved10:7;
|
||||||
|
USHORT Reserved11[128]; // 128-255
|
||||||
|
} IDENTIFY_DATA, *PIDENTIFY_DATA;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Identify data without the Reserved4.
|
||||||
|
//
|
||||||
|
|
||||||
|
//typedef struct _IDENTIFY_DATA2 {
|
||||||
|
// USHORT GeneralConfiguration; // 00 00
|
||||||
|
// USHORT NumCylinders; // 02 1
|
||||||
|
// USHORT Reserved1; // 04 2
|
||||||
|
// USHORT NumHeads; // 06 3
|
||||||
|
// USHORT UnformattedBytesPerTrack; // 08 4
|
||||||
|
// USHORT UnformattedBytesPerSector; // 0A 5
|
||||||
|
// USHORT NumSectorsPerTrack; // 0C 6
|
||||||
|
// USHORT VendorUnique1[3]; // 0E 7-9
|
||||||
|
// UCHAR SerialNumber[20]; // 14 10-19
|
||||||
|
// USHORT BufferType; // 28 20
|
||||||
|
// USHORT BufferSectorSize; // 2A 21
|
||||||
|
// USHORT NumberOfEccBytes; // 2C 22
|
||||||
|
// UCHAR FirmwareRevision[8]; // 2E 23-26
|
||||||
|
// UCHAR ModelNumber[40]; // 36 27-46
|
||||||
|
// UCHAR MaximumBlockTransfer; // 5E 47
|
||||||
|
// UCHAR VendorUnique2; // 5F
|
||||||
|
// USHORT DoubleWordIo; // 60 48
|
||||||
|
// USHORT Capabilities; // 62 49
|
||||||
|
// USHORT Reserved2; // 64 50
|
||||||
|
// UCHAR VendorUnique3; // 66 51
|
||||||
|
// UCHAR PioCycleTimingMode; // 67
|
||||||
|
// UCHAR VendorUnique4; // 68 52
|
||||||
|
// UCHAR DmaCycleTimingMode; // 69
|
||||||
|
// USHORT TranslationFieldsValid:3; // 6A 53
|
||||||
|
// USHORT Reserved3:13;
|
||||||
|
// USHORT NumberOfCurrentCylinders; // 6C 54
|
||||||
|
// USHORT NumberOfCurrentHeads; // 6E 55
|
||||||
|
// USHORT CurrentSectorsPerTrack; // 70 56
|
||||||
|
// ULONG CurrentSectorCapacity; // 72 57-58
|
||||||
|
// USHORT CurrentMultiSectorSetting; // 59
|
||||||
|
// ULONG UserAddressableSectors; // 60-61
|
||||||
|
// USHORT SingleWordDMASupport : 8; // 62
|
||||||
|
// USHORT SingleWordDMAActive : 8;
|
||||||
|
// USHORT MultiWordDMASupport : 8; // 63
|
||||||
|
// USHORT MultiWordDMAActive : 8;
|
||||||
|
// USHORT AdvancedPIOModes : 8; // 64
|
||||||
|
// USHORT Reserved4 : 8;
|
||||||
|
// USHORT MinimumMWXferCycleTime; // 65
|
||||||
|
// USHORT RecommendedMWXferCycleTime; // 66
|
||||||
|
// USHORT MinimumPIOCycleTime; // 67
|
||||||
|
// USHORT MinimumPIOCycleTimeIORDY; // 68
|
||||||
|
// USHORT Reserved5[11]; // 69-79
|
||||||
|
// USHORT MajorRevision; // 80
|
||||||
|
// USHORT MinorRevision; // 81
|
||||||
|
// USHORT Reserved6[6]; // 82-87
|
||||||
|
// USHORT UltraDMASupport : 8; // 88
|
||||||
|
// USHORT UltraDMAActive : 8; //
|
||||||
|
// USHORT Reserved7[37]; // 89-125
|
||||||
|
// USHORT LastLun:3; // 126
|
||||||
|
// USHORT Reserved8:13;
|
||||||
|
// USHORT MediaStatusNotification:2; // 127
|
||||||
|
// USHORT Reserved9:6;
|
||||||
|
// USHORT DeviceWriteProtect:1;
|
||||||
|
// USHORT Reserved10:7;
|
||||||
|
//} IDENTIFY_DATA2, *PIDENTIFY_DATA2;
|
||||||
|
#pragma pack ()
|
||||||
|
|
||||||
|
#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA)
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The structure is passed to pci ide mini driver
|
||||||
|
// TransferModeSelect callback for selecting
|
||||||
|
// proper transfer mode the the devices connected
|
||||||
|
// to the given IDE channel
|
||||||
|
//
|
||||||
|
typedef struct _PCIIDE_TRANSFER_MODE_SELECT {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Input Parameters
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// IDE Channel Number. 0 or 1
|
||||||
|
//
|
||||||
|
ULONG Channel;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate whether devices are present
|
||||||
|
//
|
||||||
|
BOOLEAN DevicePresent[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate whether devices are ATA harddisk
|
||||||
|
//
|
||||||
|
BOOLEAN FixedDisk[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate whether devices support IO Ready Line
|
||||||
|
//
|
||||||
|
BOOLEAN IoReadySupported[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate the data transfer modes devices support
|
||||||
|
//
|
||||||
|
ULONG DeviceTransferModeSupported[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate devices' best timings for PIO, single word DMA,
|
||||||
|
// multiword DMA, and Ultra DMA modes
|
||||||
|
//
|
||||||
|
ULONG BestPioCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
ULONG BestSwDmaCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
ULONG BestMwDmaCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
ULONG BestUDmaCycleTime[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate devices' current data transfer modes
|
||||||
|
//
|
||||||
|
ULONG DeviceTransferModeCurrent[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// The user's choice. This will allow pciidex to
|
||||||
|
// default to a transfer mode indicated by the mini driver
|
||||||
|
//
|
||||||
|
ULONG UserChoiceTransferMode[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// This enables UDMA66 on the intel chipsets
|
||||||
|
//
|
||||||
|
ULONG EnableUDMA66;
|
||||||
|
|
||||||
|
//
|
||||||
|
//Some miniports need this
|
||||||
|
// The miniport will save this data in their deviceExtension
|
||||||
|
//
|
||||||
|
IDENTIFY_DATA IdentifyData[MAX_IDE_DEVICE];
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Output Parameters
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate devices' data transfer modes chosen by
|
||||||
|
// the pcii ide mini drive
|
||||||
|
//
|
||||||
|
ULONG DeviceTransferModeSelected[MAX_IDE_DEVICE * MAX_IDE_LINE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// Transfermode timings
|
||||||
|
//
|
||||||
|
PULONG TransferModeTimingTable;
|
||||||
|
ULONG TransferModeTableLength;
|
||||||
|
|
||||||
|
} PCIIDE_TRANSFER_MODE_SELECT, *PPCIIDE_TRANSFER_MODE_SELECT;
|
||||||
|
|
||||||
|
//
|
||||||
|
// possible ide channel state
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ChannelDisabled = 0,
|
||||||
|
ChannelEnabled,
|
||||||
|
ChannelStateUnknown
|
||||||
|
} IDE_CHANNEL_STATE;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Prototype for different PCI IDE mini driver
|
||||||
|
// callbacks
|
||||||
|
//
|
||||||
|
typedef IDE_CHANNEL_STATE
|
||||||
|
(*PCIIDE_CHANNEL_ENABLED) (
|
||||||
|
IN PVOID DeviceExtension,
|
||||||
|
IN ULONG Channel
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef BOOLEAN
|
||||||
|
(*PCIIDE_SYNC_ACCESS_REQUIRED) (
|
||||||
|
IN PVOID DeviceExtension
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef NTSTATUS
|
||||||
|
(*PCIIDE_TRANSFER_MODE_SELECT_FUNC) (
|
||||||
|
IN PVOID DeviceExtension,
|
||||||
|
IN OUT PPCIIDE_TRANSFER_MODE_SELECT TransferModeSelect
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef ULONG
|
||||||
|
(*PCIIDE_USEDMA_FUNC)(
|
||||||
|
IN PVOID deviceExtension,
|
||||||
|
IN PVOID cdbCmd,
|
||||||
|
IN UCHAR targetID
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef NTSTATUS
|
||||||
|
(*PCIIDE_UDMA_MODES_SUPPORTED) (
|
||||||
|
IDENTIFY_DATA IdentifyData,
|
||||||
|
PULONG BestXferMode,
|
||||||
|
PULONG CurrentMode
|
||||||
|
);
|
||||||
|
//
|
||||||
|
// This structure is for the PCI IDE mini driver to
|
||||||
|
// return its properties
|
||||||
|
//
|
||||||
|
typedef struct _IDE_CONTROLLER_PROPERTIES {
|
||||||
|
|
||||||
|
//
|
||||||
|
// sizeof (IDE_CONTROLLER_PROPERTIES)
|
||||||
|
//
|
||||||
|
ULONG Size;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate the amount of memory PCI IDE mini driver
|
||||||
|
// needs for its private data
|
||||||
|
//
|
||||||
|
ULONG ExtensionSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Indicate all the data transfer modes the PCI IDE
|
||||||
|
// controller supports
|
||||||
|
//
|
||||||
|
ULONG SupportedTransferMode[MAX_IDE_CHANNEL][MAX_IDE_DEVICE];
|
||||||
|
|
||||||
|
//
|
||||||
|
// callback to query whether a IDE channel is enabled
|
||||||
|
//
|
||||||
|
PCIIDE_CHANNEL_ENABLED PciIdeChannelEnabled;
|
||||||
|
|
||||||
|
//
|
||||||
|
// callback to query whether both IDE channels requires
|
||||||
|
// synchronized access. (one channel at a time)
|
||||||
|
//
|
||||||
|
PCIIDE_SYNC_ACCESS_REQUIRED PciIdeSyncAccessRequired;
|
||||||
|
|
||||||
|
//
|
||||||
|
// callback to select proper transfer modes for the
|
||||||
|
// given devices
|
||||||
|
//
|
||||||
|
PCIIDE_TRANSFER_MODE_SELECT_FUNC PciIdeTransferModeSelect;
|
||||||
|
|
||||||
|
//
|
||||||
|
// at the end of a ATA data transfer, ignores busmaster
|
||||||
|
// status active bit. Normally, it should be FALSE
|
||||||
|
//
|
||||||
|
BOOLEAN IgnoreActiveBitForAtaDevice;
|
||||||
|
|
||||||
|
//
|
||||||
|
// always clear the busmaster interrupt on every interrupt
|
||||||
|
// generated by the device. Normnally, it should be FALSE
|
||||||
|
//
|
||||||
|
BOOLEAN AlwaysClearBusMasterInterrupt;
|
||||||
|
|
||||||
|
//
|
||||||
|
// callback to determine whether DMA should be used or not
|
||||||
|
// called for every IO
|
||||||
|
//
|
||||||
|
PCIIDE_USEDMA_FUNC PciIdeUseDma;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// if the miniport needs a different alignment
|
||||||
|
//
|
||||||
|
ULONG AlignmentRequirement;
|
||||||
|
|
||||||
|
ULONG DefaultPIO;
|
||||||
|
|
||||||
|
//
|
||||||
|
// retrieves the supported udma modes from the Identify data
|
||||||
|
//
|
||||||
|
PCIIDE_UDMA_MODES_SUPPORTED PciIdeUdmaModesSupported;
|
||||||
|
|
||||||
|
} IDE_CONTROLLER_PROPERTIES, *PIDE_CONTROLLER_PROPERTIES;
|
||||||
|
|
||||||
|
//
|
||||||
|
// callback to query PCI IDE controller properties
|
||||||
|
//
|
||||||
|
typedef
|
||||||
|
NTSTATUS (*PCONTROLLER_PROPERTIES) (
|
||||||
|
IN PVOID DeviceExtension,
|
||||||
|
IN PIDE_CONTROLLER_PROPERTIES ControllerProperties
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// To initailize PCI IDE mini driver
|
||||||
|
//
|
||||||
|
NTSTATUS
|
||||||
|
PciIdeXInitialize(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath,
|
||||||
|
IN PCONTROLLER_PROPERTIES PciIdeGetControllerProperties,
|
||||||
|
IN ULONG ExtensionSize
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// To query PCI IDE config space data
|
||||||
|
//
|
||||||
|
NTSTATUS
|
||||||
|
PciIdeXGetBusData(
|
||||||
|
IN PVOID DeviceExtension,
|
||||||
|
IN PVOID Buffer,
|
||||||
|
IN ULONG ConfigDataOffset,
|
||||||
|
IN ULONG BufferLength
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// To save PCI IDE config space data
|
||||||
|
//
|
||||||
|
NTSTATUS
|
||||||
|
PciIdeXSetBusData(
|
||||||
|
IN PVOID DeviceExtension,
|
||||||
|
IN PVOID Buffer,
|
||||||
|
IN PVOID DataMask,
|
||||||
|
IN ULONG ConfigDataOffset,
|
||||||
|
IN ULONG BufferLength
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
typedef struct _PCIIDE_CONFIG_HEADER {
|
||||||
|
|
||||||
|
USHORT VendorID; // (ro)
|
||||||
|
USHORT DeviceID; // (ro)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Command
|
||||||
|
//
|
||||||
|
union {
|
||||||
|
|
||||||
|
struct {
|
||||||
|
|
||||||
|
USHORT IoAccessEnable:1; // Device control
|
||||||
|
USHORT MemAccessEnable:1;
|
||||||
|
USHORT MasterEnable:1;
|
||||||
|
USHORT SpecialCycle:1;
|
||||||
|
USHORT MemWriteInvalidateEnable:1;
|
||||||
|
USHORT VgaPaletteSnoopEnable:1;
|
||||||
|
USHORT ParityErrorResponse:1;
|
||||||
|
USHORT WaitCycleEnable:1;
|
||||||
|
USHORT SystemErrorEnable:1;
|
||||||
|
USHORT FastBackToBackEnable:1;
|
||||||
|
USHORT CommandReserved:6;
|
||||||
|
} b;
|
||||||
|
|
||||||
|
USHORT w;
|
||||||
|
|
||||||
|
} Command;
|
||||||
|
|
||||||
|
|
||||||
|
USHORT Status;
|
||||||
|
UCHAR RevisionID; // (ro)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Program Interface
|
||||||
|
//
|
||||||
|
UCHAR Chan0OpMode:1;
|
||||||
|
UCHAR Chan0Programmable:1;
|
||||||
|
UCHAR Chan1OpMode:1;
|
||||||
|
UCHAR Chan1Programmable:1;
|
||||||
|
UCHAR ProgIfReserved:3;
|
||||||
|
UCHAR MasterIde:1;
|
||||||
|
|
||||||
|
UCHAR SubClass; // (ro)
|
||||||
|
UCHAR BaseClass; // (ro)
|
||||||
|
UCHAR CacheLineSize; // (ro+)
|
||||||
|
UCHAR LatencyTimer; // (ro+)
|
||||||
|
UCHAR HeaderType; // (ro)
|
||||||
|
UCHAR BIST; // Built in self test
|
||||||
|
|
||||||
|
struct _PCI_HEADER_TYPE_0 type0;
|
||||||
|
|
||||||
|
} PCIIDE_CONFIG_HEADER, *PPCIIDE_CONFIG_HEADER;
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
//
|
||||||
|
// Debug Print
|
||||||
|
//
|
||||||
|
#if DBG
|
||||||
|
|
||||||
|
VOID
|
||||||
|
PciIdeXDebugPrint(
|
||||||
|
ULONG DebugPrintLevel,
|
||||||
|
PCCHAR DebugMessage,
|
||||||
|
...
|
||||||
|
);
|
||||||
|
|
||||||
|
#define PciIdeXDebugPrint(x) PciIdeXDebugPrint x
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define PciIdeXDebugPrint(x)
|
||||||
|
|
||||||
|
#endif // DBG
|
||||||
|
|
||||||
|
#endif // ___ide_h___
|
||||||
|
|
132
reactos/drivers/storage/inc/ideuser.h
Normal file
132
reactos/drivers/storage/inc/ideuser.h
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1999 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
ideuser.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
These are the structures and defines that are used in the
|
||||||
|
PCI IDE mini drivers.
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#if !defined (___ideuser_h___)
|
||||||
|
#define ___ideuser_h___
|
||||||
|
|
||||||
|
|
||||||
|
#define PIO_MODE0 (1 << 0)
|
||||||
|
#define PIO_MODE1 (1 << 1)
|
||||||
|
#define PIO_MODE2 (1 << 2)
|
||||||
|
#define PIO_MODE3 (1 << 3)
|
||||||
|
#define PIO_MODE4 (1 << 4)
|
||||||
|
|
||||||
|
#define SWDMA_MODE0 (1 << 5)
|
||||||
|
#define SWDMA_MODE1 (1 << 6)
|
||||||
|
#define SWDMA_MODE2 (1 << 7)
|
||||||
|
|
||||||
|
#define MWDMA_MODE0 (1 << 8)
|
||||||
|
#define MWDMA_MODE1 (1 << 9)
|
||||||
|
#define MWDMA_MODE2 (1 << 10)
|
||||||
|
|
||||||
|
#define UDMA_MODE0 (1 << 11)
|
||||||
|
#define UDMA_MODE1 (1 << 12)
|
||||||
|
#define UDMA_MODE2 (1 << 13)
|
||||||
|
#define UDMA_MODE3 (1 << 14)
|
||||||
|
#define UDMA_MODE4 (1 << 15)
|
||||||
|
#define UDMA_MODE5 (1 << 16)
|
||||||
|
|
||||||
|
#define PIO_SUPPORT (PIO_MODE0 | PIO_MODE1 | PIO_MODE2 | PIO_MODE3 | PIO_MODE4)
|
||||||
|
#define SWDMA_SUPPORT (SWDMA_MODE0 | SWDMA_MODE1 | SWDMA_MODE2)
|
||||||
|
#define MWDMA_SUPPORT (MWDMA_MODE0 | MWDMA_MODE1 | MWDMA_MODE2)
|
||||||
|
#define UDMA33_SUPPORT (UDMA_MODE0 | UDMA_MODE1 | UDMA_MODE2)
|
||||||
|
#define UDMA66_SUPPORT (UDMA_MODE3 | UDMA_MODE4)
|
||||||
|
#define UDMA100_SUPPORT (UDMA_MODE5 )
|
||||||
|
#define UDMA_SUPPORT (UNINITIALIZED_TRANSFER_MODE & (~(PIO_SUPPORT | SWDMA_SUPPORT | MWDMA_SUPPORT)))
|
||||||
|
|
||||||
|
#define DMA_SUPPORT (SWDMA_SUPPORT | MWDMA_SUPPORT | UDMA_SUPPORT)
|
||||||
|
#define ALL_MODE_SUPPORT (PIO_SUPPORT | DMA_SUPPORT)
|
||||||
|
|
||||||
|
#define PIO0 0
|
||||||
|
#define PIO1 1
|
||||||
|
#define PIO2 2
|
||||||
|
#define PIO3 3
|
||||||
|
#define PIO4 4
|
||||||
|
#define SWDMA0 5
|
||||||
|
#define SWDMA1 6
|
||||||
|
#define SWDMA2 7
|
||||||
|
#define MWDMA0 8
|
||||||
|
#define MWDMA1 9
|
||||||
|
#define MWDMA2 10
|
||||||
|
#define UDMA0 11
|
||||||
|
|
||||||
|
#define MAX_XFER_MODE 17
|
||||||
|
#define UNINITIALIZED_CYCLE_TIME 0xffffffff
|
||||||
|
#define UNINITIALIZED_TRANSFER_MODE 0x7fffffff
|
||||||
|
#define IS_DEFAULT(mode) (!(mode & 0x80000000))
|
||||||
|
|
||||||
|
#define GenTransferModeMask(i, mode) {\
|
||||||
|
ULONG temp=0xffffffff; \
|
||||||
|
mode |= (temp >> (31-(i)));\
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// mode should not be 0
|
||||||
|
//
|
||||||
|
#define GetHighestTransferMode(mode, i) {\
|
||||||
|
ULONG temp=(mode); \
|
||||||
|
ASSERT(temp); \
|
||||||
|
i=0; \
|
||||||
|
while ( temp) { \
|
||||||
|
temp = (temp >> 1);\
|
||||||
|
i++;\
|
||||||
|
} \
|
||||||
|
i--; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GetHighestDMATransferMode(mode, i) {\
|
||||||
|
ULONG temp=mode >> 5;\
|
||||||
|
i=5; \
|
||||||
|
while ( temp) { \
|
||||||
|
temp = (temp >> 1); \
|
||||||
|
i++; \
|
||||||
|
} \
|
||||||
|
i--; \
|
||||||
|
}
|
||||||
|
#define GetHighestPIOTransferMode(mode, i) { \
|
||||||
|
ULONG temp = (mode & PIO_SUPPORT); \
|
||||||
|
i=0; \
|
||||||
|
temp = temp >> 1; \
|
||||||
|
while (temp) { \
|
||||||
|
temp = temp >> 1; \
|
||||||
|
i++; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SetDefaultTiming(timingTable, length) {\
|
||||||
|
timingTable[0]=PIO_MODE0_CYCLE_TIME; \
|
||||||
|
timingTable[1]=PIO_MODE1_CYCLE_TIME; \
|
||||||
|
timingTable[2]=PIO_MODE2_CYCLE_TIME; \
|
||||||
|
timingTable[3]=PIO_MODE3_CYCLE_TIME; \
|
||||||
|
timingTable[4]=PIO_MODE4_CYCLE_TIME; \
|
||||||
|
timingTable[5]=SWDMA_MODE0_CYCLE_TIME; \
|
||||||
|
timingTable[6]=SWDMA_MODE1_CYCLE_TIME; \
|
||||||
|
timingTable[7]=SWDMA_MODE2_CYCLE_TIME; \
|
||||||
|
timingTable[8]=MWDMA_MODE0_CYCLE_TIME; \
|
||||||
|
timingTable[9]=MWDMA_MODE1_CYCLE_TIME; \
|
||||||
|
timingTable[10]=MWDMA_MODE2_CYCLE_TIME; \
|
||||||
|
timingTable[11]=UDMA_MODE0_CYCLE_TIME; \
|
||||||
|
timingTable[12]=UDMA_MODE1_CYCLE_TIME; \
|
||||||
|
timingTable[13]=UDMA_MODE2_CYCLE_TIME; \
|
||||||
|
timingTable[14]=UDMA_MODE3_CYCLE_TIME; \
|
||||||
|
timingTable[15]=UDMA_MODE4_CYCLE_TIME; \
|
||||||
|
timingTable[16]=UDMA_MODE5_CYCLE_TIME; \
|
||||||
|
length = MAX_XFER_MODE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ___ideuser_h___
|
||||||
|
|
115
reactos/drivers/storage/inc/physlogi.h
Normal file
115
reactos/drivers/storage/inc/physlogi.h
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 1992 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
physlogi.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
This file contains structures and defines that are used
|
||||||
|
specifically for the tape drivers. Contains #define's,
|
||||||
|
function protypes, etc. for use in calling functions in
|
||||||
|
physlogi.c that do physical to pseudo-logical and pseudo-
|
||||||
|
logical to physical tape block address/position translation.
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Mike Colandreo (Maynard)
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
// begin_ntminitape
|
||||||
|
|
||||||
|
//
|
||||||
|
// defines for QIC tape density codes
|
||||||
|
//
|
||||||
|
|
||||||
|
#define QIC_XX 0 // ????
|
||||||
|
#define QIC_24 5 // 0x05
|
||||||
|
#define QIC_120 15 // 0x0F
|
||||||
|
#define QIC_150 16 // 0x10
|
||||||
|
#define QIC_525 17 // 0x11
|
||||||
|
#define QIC_1350 18 // 0x12
|
||||||
|
#define QIC_1000 21 // 0x15
|
||||||
|
#define QIC_1000C 30 // 0x1E
|
||||||
|
#define QIC_2100 31 // 0x1F
|
||||||
|
#define QIC_2GB 34 // 0x22
|
||||||
|
#define QIC_5GB 40 // 0x28
|
||||||
|
|
||||||
|
//
|
||||||
|
// defines for QIC tape media codes
|
||||||
|
//
|
||||||
|
|
||||||
|
#define DCXXXX 0
|
||||||
|
#define DC300 1
|
||||||
|
#define DC300XLP 2
|
||||||
|
#define DC615 3
|
||||||
|
#define DC600 4
|
||||||
|
#define DC6037 5
|
||||||
|
#define DC6150 6
|
||||||
|
#define DC6250 7
|
||||||
|
#define DC6320 8
|
||||||
|
#define DC6525 9
|
||||||
|
#define DC9135SL 33 //0x21
|
||||||
|
#define DC9210 34 //0x22
|
||||||
|
#define DC9135 35 //0x23
|
||||||
|
#define DC9100 36 //0x24
|
||||||
|
#define DC9120 37 //0x25
|
||||||
|
#define DC9120SL 38 //0x26
|
||||||
|
#define DC9164 39 //0x27
|
||||||
|
#define DCXXXXFW 48 //0x30
|
||||||
|
#define DC9200SL 49 //0x31
|
||||||
|
#define DC9210XL 50 //0x32
|
||||||
|
#define DC10GB 51 //0x33
|
||||||
|
#define DC9200 52 //0x34
|
||||||
|
#define DC9120XL 53 //0x35
|
||||||
|
#define DC9210SL 54 //0x36
|
||||||
|
#define DC9164XL 55 //0x37
|
||||||
|
#define DC9200XL 64 //0x40
|
||||||
|
#define DC9400 65 //0x41
|
||||||
|
#define DC9500 66 //0x42
|
||||||
|
#define DC9500SL 70 //0x46
|
||||||
|
|
||||||
|
//
|
||||||
|
// defines for translation reference point
|
||||||
|
//
|
||||||
|
|
||||||
|
#define NOT_FROM_BOT 0
|
||||||
|
#define FROM_BOT 1
|
||||||
|
|
||||||
|
//
|
||||||
|
// info/structure returned by/from
|
||||||
|
// TapeLogicalBlockToPhysicalBlock( )
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _TAPE_PHYS_POSITION {
|
||||||
|
ULONG SeekBlockAddress;
|
||||||
|
ULONG SpaceBlockCount;
|
||||||
|
} TAPE_PHYS_POSITION, PTAPE_PHYS_POSITION;
|
||||||
|
|
||||||
|
//
|
||||||
|
// function prototypes
|
||||||
|
//
|
||||||
|
|
||||||
|
TAPE_PHYS_POSITION
|
||||||
|
TapeClassLogicalBlockToPhysicalBlock(
|
||||||
|
IN UCHAR DensityCode,
|
||||||
|
IN ULONG LogicalBlockAddress,
|
||||||
|
IN ULONG BlockLength,
|
||||||
|
IN BOOLEAN FromBOT
|
||||||
|
);
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
TapeClassPhysicalBlockToLogicalBlock(
|
||||||
|
IN UCHAR DensityCode,
|
||||||
|
IN ULONG PhysicalBlockAddress,
|
||||||
|
IN ULONG BlockLength,
|
||||||
|
IN BOOLEAN FromBOT
|
||||||
|
);
|
||||||
|
|
||||||
|
// end_ntminitape
|
||||||
|
|
180
reactos/drivers/storage/inc/rbc.h
Normal file
180
reactos/drivers/storage/inc/rbc.h
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (C) Microsoft Corporation, 1998 - 1999
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
rbc.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
These are the structures and defines used in the Reduced Block Command set
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
|
||||||
|
George Chrysanthakopoulos(georgioc) - April 1998
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
Dan Knudson (DanKn), 23 Sep 1999 - updated per rev 10 of RBC spec
|
||||||
|
|
||||||
|
--*/
|
||||||
|
#ifndef _NTRBC_
|
||||||
|
#define _NTRBC_
|
||||||
|
|
||||||
|
#include "scsi.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Command Descriptor Block. encapsulated under the bus/protocol specific request block
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef union _CDB_RBC {
|
||||||
|
|
||||||
|
//
|
||||||
|
// format unit
|
||||||
|
//
|
||||||
|
|
||||||
|
struct _FORMAT_RBC {
|
||||||
|
UCHAR OperationCode;
|
||||||
|
UCHAR VendorSpecific;
|
||||||
|
UCHAR Increment : 1;
|
||||||
|
UCHAR Percent_Time : 1;
|
||||||
|
UCHAR Reserved1 : 1;
|
||||||
|
UCHAR VendorSpecific1 : 5;
|
||||||
|
UCHAR Reserved2[2];
|
||||||
|
UCHAR Control;
|
||||||
|
} FORMAT_RBC, *PFORMAT_RBC;
|
||||||
|
|
||||||
|
//
|
||||||
|
// prevent/allow medium removal
|
||||||
|
//
|
||||||
|
|
||||||
|
struct _MEDIA_REMOVAL_RBC {
|
||||||
|
UCHAR OperationCode;
|
||||||
|
UCHAR Reserved[3];
|
||||||
|
|
||||||
|
UCHAR Prevent : 1;
|
||||||
|
UCHAR Persistant : 1;
|
||||||
|
UCHAR Reserved3 : 6;
|
||||||
|
|
||||||
|
UCHAR Control;
|
||||||
|
} MEDIA_REMOVAL_RBC, *PMEDIA_REMOVAL_RBC;
|
||||||
|
|
||||||
|
//
|
||||||
|
// START_STOP_UNIT
|
||||||
|
//
|
||||||
|
|
||||||
|
struct _START_STOP_RBC {
|
||||||
|
UCHAR OperationCode;
|
||||||
|
UCHAR Immediate: 1;
|
||||||
|
UCHAR Reserved1 : 7;
|
||||||
|
UCHAR Reserved2[2];
|
||||||
|
UCHAR Start : 1;
|
||||||
|
UCHAR LoadEject : 1;
|
||||||
|
UCHAR Reserved3 : 2;
|
||||||
|
UCHAR PowerConditions : 4;
|
||||||
|
UCHAR Control;
|
||||||
|
} START_STOP_RBC, *PSTART_STOP_RBC;
|
||||||
|
|
||||||
|
struct _SYNCHRONIZE_CACHE_RBC {
|
||||||
|
|
||||||
|
UCHAR OperationCode; // 0x35
|
||||||
|
UCHAR Reserved[8];
|
||||||
|
UCHAR Control;
|
||||||
|
|
||||||
|
} SYNCHRONIZE_CACHE_RBC, *PSYNCHRONIZE_CACHE_RBC;
|
||||||
|
|
||||||
|
|
||||||
|
} CDB_RBC, *PCDB_RBC;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// START_STOP_UNIT Power Condition descriptions
|
||||||
|
//
|
||||||
|
|
||||||
|
#define START_STOP_RBC_POWER_CND_NO_CHANGE 0
|
||||||
|
#define START_STOP_RBC_POWER_CND_ACTIVE 1
|
||||||
|
#define START_STOP_RBC_POWER_CND_IDLE 2
|
||||||
|
#define START_STOP_RBC_POWER_CND_STANDBY 3
|
||||||
|
#define START_STOP_RBC_POWER_CND_SLEEP 5
|
||||||
|
#define START_STOP_RBC_POWER_CND_DEVICE_CTRL 7
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mode Sense/Select page constants.
|
||||||
|
//
|
||||||
|
|
||||||
|
#define MODE_PAGE_RBC_DEVICE_PARAMETERS 0x06
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// DeviceType field in inquiry Data
|
||||||
|
//
|
||||||
|
|
||||||
|
#define RBC_DEVICE 0x0E
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define Device Capabilities page.
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_RBC_DEVICE_PARAMETERS_PAGE {
|
||||||
|
UCHAR PageCode : 6;
|
||||||
|
UCHAR Reserved : 1;
|
||||||
|
UCHAR PageSavable : 1;
|
||||||
|
UCHAR PageLength;
|
||||||
|
UCHAR WriteCacheDisable : 1;
|
||||||
|
UCHAR Reserved1 : 7;
|
||||||
|
UCHAR LogicalBlockSize[2];
|
||||||
|
UCHAR NumberOfLogicalBlocks[5];
|
||||||
|
UCHAR PowerPerformance;
|
||||||
|
UCHAR LockDisabled : 1;
|
||||||
|
UCHAR FormatDisabled : 1;
|
||||||
|
UCHAR WriteDisabled : 1;
|
||||||
|
UCHAR ReadDisabled : 1;
|
||||||
|
UCHAR Reserved2 : 4;
|
||||||
|
UCHAR Reserved3;
|
||||||
|
|
||||||
|
}MODE_RBC_DEVICE_PARAMETERS_PAGE, *PMODE_RBC_DEVICE_PARAMETERS_PAGE;
|
||||||
|
|
||||||
|
typedef struct _MODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE {
|
||||||
|
|
||||||
|
MODE_PARAMETER_HEADER Header;
|
||||||
|
MODE_RBC_DEVICE_PARAMETERS_PAGE Page;
|
||||||
|
|
||||||
|
}MODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE,
|
||||||
|
*PMODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// unsolicited status sense code qualifier values
|
||||||
|
//
|
||||||
|
|
||||||
|
#define RBC_UNSOLICITED_STATUS 0x02
|
||||||
|
#define RBC_UNSOLICITED_SENSE_KEY 0x06
|
||||||
|
|
||||||
|
#define RBC_UNSOLICITED_SC_PWR_STATE_CHNG 0xFF
|
||||||
|
#define RBC_UNSOLICITED_SC_EVENT_STATUS 0xFE
|
||||||
|
|
||||||
|
#define RBC_UNSOLICITED_CLASS_ASQ_DEVICE 0x06
|
||||||
|
#define RBC_UNSOLICITED_CLASS_ASQ_MEDIA 0x04
|
||||||
|
#define RBC_UNSOLICITED_CLASS_ASQ_POWER 0x02
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Translation routine used to convert SCSI requests that differ from RBC
|
||||||
|
//
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
Rbc_Scsi_Conversion(
|
||||||
|
IN PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
IN PSCSI_REQUEST_BLOCK *OriginalSrb,
|
||||||
|
IN PMODE_RBC_DEVICE_PARAMETERS_HEADER_AND_PAGE RbcHeaderAndPage,
|
||||||
|
IN BOOLEAN OutgoingRequest,
|
||||||
|
IN BOOLEAN RemovableMedia
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
312
reactos/drivers/storage/inc/tape.h
Normal file
312
reactos/drivers/storage/inc/tape.h
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
/*++
|
||||||
|
|
||||||
|
Copyright (c) 1992 Microsoft Corporation
|
||||||
|
|
||||||
|
Module Name:
|
||||||
|
|
||||||
|
tape.h
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
|
||||||
|
These are the structures and defines that are used in the
|
||||||
|
SCSI tape class drivers. The tape class driver is separated
|
||||||
|
into two modules. Tape.c contains code common to all tape
|
||||||
|
class drivers including the driver's major entry points.
|
||||||
|
The major entry point names each begin with the prefix
|
||||||
|
'ScsiTape.' The second module is the device specific code.
|
||||||
|
It provides support for a set of functions. Each device
|
||||||
|
specific function name is prefixed by 'Tape.'
|
||||||
|
|
||||||
|
Author:
|
||||||
|
|
||||||
|
Mike Glass
|
||||||
|
|
||||||
|
Revision History:
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#include "scsi.h"
|
||||||
|
#include "class.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define the maximum inquiry data length.
|
||||||
|
//
|
||||||
|
|
||||||
|
#define MAXIMUM_TAPE_INQUIRY_DATA 252
|
||||||
|
|
||||||
|
//
|
||||||
|
// Tape device data
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _TAPE_DATA {
|
||||||
|
ULONG Flags;
|
||||||
|
ULONG CurrentPartition;
|
||||||
|
PVOID DeviceSpecificExtension;
|
||||||
|
PSCSI_INQUIRY_DATA InquiryData;
|
||||||
|
} TAPE_DATA, *PTAPE_DATA;
|
||||||
|
|
||||||
|
#define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION) + sizeof(TAPE_DATA)
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define Device Configuration Page
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_DEVICE_CONFIGURATION_PAGE {
|
||||||
|
|
||||||
|
UCHAR PageCode : 6;
|
||||||
|
UCHAR Reserved1 : 1;
|
||||||
|
UCHAR PS : 1;
|
||||||
|
UCHAR PageLength;
|
||||||
|
UCHAR ActiveFormat : 5;
|
||||||
|
UCHAR CAFBit : 1;
|
||||||
|
UCHAR CAPBit : 1;
|
||||||
|
UCHAR Reserved2 : 1;
|
||||||
|
UCHAR ActivePartition;
|
||||||
|
UCHAR WriteBufferFullRatio;
|
||||||
|
UCHAR ReadBufferEmptyRatio;
|
||||||
|
UCHAR WriteDelayTime[2];
|
||||||
|
UCHAR REW : 1;
|
||||||
|
UCHAR RBO : 1;
|
||||||
|
UCHAR SOCF : 2;
|
||||||
|
UCHAR AVC : 1;
|
||||||
|
UCHAR RSmk : 1;
|
||||||
|
UCHAR BIS : 1;
|
||||||
|
UCHAR DBR : 1;
|
||||||
|
UCHAR GapSize;
|
||||||
|
UCHAR Reserved3 : 3;
|
||||||
|
UCHAR SEW : 1;
|
||||||
|
UCHAR EEG : 1;
|
||||||
|
UCHAR EODdefined : 3;
|
||||||
|
UCHAR BufferSize[3];
|
||||||
|
UCHAR DCAlgorithm;
|
||||||
|
UCHAR Reserved4;
|
||||||
|
|
||||||
|
} MODE_DEVICE_CONFIGURATION_PAGE, *PMODE_DEVICE_CONFIGURATION_PAGE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define Medium Partition Page
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_MEDIUM_PARTITION_PAGE {
|
||||||
|
|
||||||
|
UCHAR PageCode : 6;
|
||||||
|
UCHAR Reserved1 : 1;
|
||||||
|
UCHAR PSBit : 1;
|
||||||
|
UCHAR PageLength;
|
||||||
|
UCHAR MaximumAdditionalPartitions;
|
||||||
|
UCHAR AdditionalPartitionDefined;
|
||||||
|
UCHAR Reserved2 : 3;
|
||||||
|
UCHAR PSUMBit : 2;
|
||||||
|
UCHAR IDPBit : 1;
|
||||||
|
UCHAR SDPBit : 1;
|
||||||
|
UCHAR FDPBit : 1;
|
||||||
|
UCHAR MediumFormatRecognition;
|
||||||
|
UCHAR Reserved3[2];
|
||||||
|
UCHAR Partition0Size[2];
|
||||||
|
UCHAR Partition1Size[2];
|
||||||
|
|
||||||
|
} MODE_MEDIUM_PARTITION_PAGE, *PMODE_MEDIUM_PARTITION_PAGE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define Data Compression Page
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_DATA_COMPRESSION_PAGE {
|
||||||
|
|
||||||
|
UCHAR PageCode : 6;
|
||||||
|
UCHAR Reserved1 : 2;
|
||||||
|
UCHAR PageLength;
|
||||||
|
UCHAR Reserved2 : 6;
|
||||||
|
UCHAR DCC : 1;
|
||||||
|
UCHAR DCE : 1;
|
||||||
|
UCHAR Reserved3 : 5;
|
||||||
|
UCHAR RED : 2;
|
||||||
|
UCHAR DDE : 1;
|
||||||
|
UCHAR CompressionAlgorithm[4];
|
||||||
|
UCHAR DecompressionAlgorithm[4];
|
||||||
|
UCHAR Reserved4[4];
|
||||||
|
|
||||||
|
} MODE_DATA_COMPRESSION_PAGE, *PMODE_DATA_COMPRESSION_PAGE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mode parameter list header and medium partition page -
|
||||||
|
// used in creating partitions
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_MEDIUM_PART_PAGE {
|
||||||
|
|
||||||
|
MODE_PARAMETER_HEADER ParameterListHeader;
|
||||||
|
MODE_MEDIUM_PARTITION_PAGE MediumPartPage;
|
||||||
|
|
||||||
|
} MODE_MEDIUM_PART_PAGE, *PMODE_MEDIUM_PART_PAGE;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mode parameters for retrieving tape or media information
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_TAPE_MEDIA_INFORMATION {
|
||||||
|
|
||||||
|
MODE_PARAMETER_HEADER ParameterListHeader;
|
||||||
|
MODE_PARAMETER_BLOCK ParameterListBlock;
|
||||||
|
MODE_MEDIUM_PARTITION_PAGE MediumPartPage;
|
||||||
|
|
||||||
|
} MODE_TAPE_MEDIA_INFORMATION, *PMODE_TAPE_MEDIA_INFORMATION;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mode parameter list header and device configuration page -
|
||||||
|
// used in retrieving device configuration information
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_DEVICE_CONFIG_PAGE {
|
||||||
|
|
||||||
|
MODE_PARAMETER_HEADER ParameterListHeader;
|
||||||
|
MODE_DEVICE_CONFIGURATION_PAGE DeviceConfigPage;
|
||||||
|
|
||||||
|
} MODE_DEVICE_CONFIG_PAGE, *PMODE_DEVICE_CONFIG_PAGE;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Mode parameter list header and data compression page -
|
||||||
|
// used in retrieving data compression information
|
||||||
|
//
|
||||||
|
|
||||||
|
typedef struct _MODE_DATA_COMPRESS_PAGE {
|
||||||
|
|
||||||
|
MODE_PARAMETER_HEADER ParameterListHeader;
|
||||||
|
MODE_DATA_COMPRESSION_PAGE DataCompressPage;
|
||||||
|
|
||||||
|
} MODE_DATA_COMPRESS_PAGE, *PMODE_DATA_COMPRESS_PAGE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following routines are the exported entry points for
|
||||||
|
// all tape class drivers. Note all these routines name start
|
||||||
|
// with 'ScsiTape.'
|
||||||
|
//
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
DriverEntry(
|
||||||
|
IN PDRIVER_OBJECT DriverObject,
|
||||||
|
IN PUNICODE_STRING RegistryPath
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiTapeInitialize(
|
||||||
|
IN PDRIVER_OBJECT DriverObject
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiTapeCreate (
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiTapeReadWrite (
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
ScsiTapeDeviceControl(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// The following routines are provided by the tape
|
||||||
|
// device-specific module. Each routine name is
|
||||||
|
// prefixed with 'Tape.'
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeCreatePartition(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeErase(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
TapeError(
|
||||||
|
PDEVICE_OBJECT DeviceObject,
|
||||||
|
PSCSI_REQUEST_BLOCK Srb,
|
||||||
|
NTSTATUS *Status,
|
||||||
|
BOOLEAN *Retry
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeGetDriveParameters(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeGetMediaParameters(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeGetPosition(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeGetStatus(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapePrepare(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeReadWrite(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeSetDriveParameters(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeSetMediaParameters(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeSetPosition(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
TapeVerifyInquiry(
|
||||||
|
IN PSCSI_INQUIRY_DATA LunInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
TapeWriteMarks(
|
||||||
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue