mirror of
https://github.com/reactos/reactos.git
synced 2024-08-13 06:37:06 +00:00
Basic work on disk driver stack (still incomplete).
svn path=/trunk/; revision=2568
This commit is contained in:
parent
8dff4a88dc
commit
f48e849f05
File diff suppressed because it is too large
Load diff
|
@ -55,18 +55,18 @@ extern "C" {
|
|||
#define IDE_DH_HDMASK 0x0F
|
||||
#define IDE_DH_DRV0 0x00
|
||||
#define IDE_DH_DRV1 0x10
|
||||
#define IDE_REG_STATUS 0x0007
|
||||
#define IDE_SR_BUSY 0x80
|
||||
#define IDE_SR_DRDY 0x40
|
||||
#define IDE_SR_DRQ 0x08
|
||||
#define IDE_SR_ERR 0x01
|
||||
#define IDE_REG_COMMAND 0x0007
|
||||
#define IDE_CMD_READ 0x20
|
||||
#define IDE_CMD_READ_RETRY 0x21
|
||||
#define IDE_CMD_WRITE 0x30
|
||||
#define IDE_CMD_WRITE_RETRY 0x31
|
||||
#define IDE_CMD_IDENT_DRV 0xEC
|
||||
|
||||
#define IDE_REG_STATUS 0x0007
|
||||
#define IDE_SR_BUSY 0x80
|
||||
#define IDE_SR_DRDY 0x40
|
||||
#define IDE_SR_DRQ 0x08
|
||||
#define IDE_SR_ERR 0x01
|
||||
#define IDE_REG_COMMAND 0x0007
|
||||
#define IDE_CMD_READ 0x20
|
||||
#define IDE_CMD_READ_RETRY 0x21
|
||||
#define IDE_CMD_WRITE 0x30
|
||||
#define IDE_CMD_WRITE_RETRY 0x31
|
||||
#define IDE_CMD_IDENT_ATA_DRV 0xEC
|
||||
#define IDE_CMD_IDENT_ATAPI_DRV 0xA1
|
||||
//
|
||||
// Access macros for command registers
|
||||
// Each macro takes an address of the command port block, and data
|
||||
|
@ -154,46 +154,6 @@ typedef struct _IDE_DEVICE_EXTENSION
|
|||
} IDE_DEVICE_EXTENSION, *PIDE_DEVICE_EXTENSION;
|
||||
|
||||
|
||||
// ATAPI_PORT_EXTENSION
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Extension to be placed in each device object
|
||||
//
|
||||
// ACCESS:
|
||||
// Allocated from NON-PAGED POOL
|
||||
// Available at any IRQL
|
||||
//
|
||||
|
||||
typedef struct _ATAPI_PORT_EXTENSION
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PCONTROLLER_OBJECT ControllerObject;
|
||||
ULONG PortNumber;
|
||||
#if 0
|
||||
struct _IDE_DEVICE_EXTESION *DiskExtension;
|
||||
PARTITION_INFORMATION PartitionInfo;
|
||||
int UnitNumber;
|
||||
BOOLEAN LBASupported;
|
||||
BOOLEAN DMASupported;
|
||||
int BytesPerSector;
|
||||
int LogicalHeads;
|
||||
int LogicalCylinders;
|
||||
int SectorsPerLogCyl;
|
||||
int SectorsPerLogTrk;
|
||||
int Offset;
|
||||
int Size;
|
||||
|
||||
int Operation;
|
||||
ULONG BytesRequested;
|
||||
ULONG BytesToTransfer;
|
||||
ULONG BytesRemaining;
|
||||
ULONG StartingSector;
|
||||
int SectorsTransferred;
|
||||
BYTE *TargetAddress;
|
||||
#endif
|
||||
} ATAPI_PORT_EXTENSION, *PATAPI_PORT_EXTENSION;
|
||||
|
||||
|
||||
// IDE_TIMER_STATES
|
||||
//
|
||||
// DESCRIPTION:
|
||||
|
@ -217,7 +177,8 @@ typedef enum _IDE_TIMER_STATES {
|
|||
// Available at any IRQL
|
||||
//
|
||||
|
||||
typedef struct _IDE_CONTROLLER_EXTENSION {
|
||||
typedef struct _IDE_CONTROLLER_EXTENSION
|
||||
{
|
||||
KSPIN_LOCK SpinLock;
|
||||
int Number;
|
||||
int Vector;
|
||||
|
@ -239,9 +200,12 @@ typedef struct _IDE_CONTROLLER_EXTENSION {
|
|||
|
||||
} IDE_CONTROLLER_EXTENSION, *PIDE_CONTROLLER_EXTENSION;
|
||||
|
||||
|
||||
|
||||
// IDE_DRIVE_IDENTIFY
|
||||
|
||||
typedef struct _IDE_DRIVE_IDENTIFY {
|
||||
typedef struct _IDE_DRIVE_IDENTIFY
|
||||
{
|
||||
WORD ConfigBits; /*00*/
|
||||
WORD LogicalCyls; /*01*/
|
||||
WORD Reserved02; /*02*/
|
||||
|
@ -280,7 +244,8 @@ typedef struct _IDE_DRIVE_IDENTIFY {
|
|||
WORD Reserved59; /*59*/
|
||||
WORD TMSectorCountLo; /*60*/
|
||||
WORD TMSectorCountHi; /*61*/
|
||||
WORD Reserved62[194]; /*62*/
|
||||
WORD Reserved62[193]; /*62*/
|
||||
WORD Checksum; /*255*/
|
||||
} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: class2.c,v 1.2 2002/01/14 01:43:26 ekohl Exp $
|
||||
/* $Id: class2.c,v 1.3 2002/01/27 01:25:01 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -7,14 +7,21 @@
|
|||
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - ScsiClassClaimDevice() must send a claim/unclaim request to
|
||||
* scsiport.sys.
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include "../include/scsi.h"
|
||||
#include "../include/class2.h"
|
||||
|
||||
//#define NDEBUG
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
//#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0)
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
|
@ -41,7 +48,8 @@ static NTSTATUS STDCALL
|
|||
ScsiClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
// ------------------------------------------------------- Public Interface
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
// DriverEntry
|
||||
//
|
||||
|
@ -113,7 +121,28 @@ ScsiClassClaimDevice(PDEVICE_OBJECT PortDeviceObject,
|
|||
BOOLEAN Release,
|
||||
PDEVICE_OBJECT *NewPortDeviceObject OPTIONAL)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT1("ScsiClassClaimDevice() called\n");
|
||||
|
||||
if (NewPortDeviceObject != NULL)
|
||||
*NewPortDeviceObject = NULL;
|
||||
|
||||
if (Release == TRUE)
|
||||
{
|
||||
ObDereferenceObject(PortDeviceObject);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
ObReferenceObjectByPointer(PortDeviceObject,
|
||||
0,
|
||||
NULL,
|
||||
KernelMode);
|
||||
|
||||
if (NewPortDeviceObject != NULL)
|
||||
*NewPortDeviceObject = PortDeviceObject;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -124,7 +153,20 @@ ScsiClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
|
|||
IN OUT PDEVICE_OBJECT *DeviceObject,
|
||||
IN PCLASS_INIT_DATA InitializationData)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
DPRINT1("ScsiClassCreateDeviceObject() called\n");
|
||||
|
||||
#if 0
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
InitializationData->DeviceExtensionSize,
|
||||
&UnicodeName,
|
||||
InitializationData->DeviceType,
|
||||
InitializationData->DeviceCharacteristics,
|
||||
FALSE,
|
||||
&InternalDeviceObject);
|
||||
#endif
|
||||
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,8 +192,43 @@ ULONG STDCALL
|
|||
ScsiClassFindUnclaimedDevices(PCLASS_INIT_DATA InitializationData,
|
||||
PSCSI_ADAPTER_BUS_INFO AdapterInformation)
|
||||
{
|
||||
PSCSI_INQUIRY_DATA UnitInfo;
|
||||
PINQUIRYDATA InquiryData;
|
||||
PUCHAR Buffer;
|
||||
ULONG Bus;
|
||||
ULONG UnclaimedDevices = 0;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("ScsiClassFindUnclaimedDevices() called!\n");
|
||||
return(0);
|
||||
|
||||
DPRINT("NumberOfBuses: %lu\n",AdapterInformation->NumberOfBuses);
|
||||
Buffer = (PUCHAR)AdapterInformation;
|
||||
for (Bus = 0; Bus < (ULONG)AdapterInformation->NumberOfBuses; Bus++)
|
||||
{
|
||||
DPRINT("Searching bus %lu\n", Bus);
|
||||
|
||||
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterInformation->BusData[Bus].InquiryDataOffset);
|
||||
|
||||
while (AdapterInformation->BusData[Bus].InquiryDataOffset)
|
||||
{
|
||||
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
|
||||
|
||||
DPRINT("Device: '%.8s'\n", InquiryData->VendorId);
|
||||
|
||||
if ((InitializationData->ClassFindDeviceCallBack(InquiryData) == TRUE) &&
|
||||
(UnitInfo->DeviceClaimed == FALSE))
|
||||
{
|
||||
UnclaimedDevices++;
|
||||
}
|
||||
|
||||
if (UnitInfo->NextInquiryDataOffset == 0)
|
||||
break;
|
||||
|
||||
UnitInfo = (PSCSI_INQUIRY_DATA) (Buffer + UnitInfo->NextInquiryDataOffset);
|
||||
}
|
||||
}
|
||||
|
||||
return(UnclaimedDevices);
|
||||
}
|
||||
|
||||
|
||||
|
@ -159,11 +236,20 @@ NTSTATUS STDCALL
|
|||
ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
|
||||
PIO_SCSI_CAPABILITIES *PortCapabilities)
|
||||
{
|
||||
PIO_SCSI_CAPABILITIES Buffer;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
|
||||
*PortCapabilities = NULL;
|
||||
Buffer = ExAllocatePool(NonPagedPool, /* FIXME: use paged pool */
|
||||
sizeof(IO_SCSI_CAPABILITIES));
|
||||
if (Buffer == NULL)
|
||||
{
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
KeInitializeEvent(&Event,
|
||||
NotificationEvent,
|
||||
FALSE);
|
||||
|
@ -172,13 +258,14 @@ ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
|
|||
PortDeviceObject,
|
||||
NULL,
|
||||
0,
|
||||
PortCapabilities,
|
||||
sizeof(PVOID),
|
||||
Buffer,
|
||||
sizeof(IO_SCSI_CAPABILITIES),
|
||||
FALSE,
|
||||
&Event,
|
||||
&IoStatusBlock);
|
||||
if (Irp == NULL)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
|
@ -191,7 +278,16 @@ ScsiClassGetCapabilities(PDEVICE_OBJECT PortDeviceObject,
|
|||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
return(IoStatusBlock.Status);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
*PortCapabilities = Buffer;
|
||||
}
|
||||
|
||||
return(Status);
|
||||
|
@ -208,10 +304,9 @@ ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
|
|||
KEVENT Event;
|
||||
PIRP Irp;
|
||||
|
||||
Buffer = ExAllocatePool(NonPagedPool, /* FIXME: use paged pool */
|
||||
*ConfigInfo = NULL;
|
||||
Buffer = ExAllocatePool(NonPagedPool,
|
||||
INQUIRY_DATA_SIZE);
|
||||
*ConfigInfo = Buffer;
|
||||
|
||||
if (Buffer == NULL)
|
||||
{
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
@ -232,6 +327,7 @@ ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
|
|||
&IoStatusBlock);
|
||||
if (Irp == NULL)
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
|
@ -250,7 +346,10 @@ ScsiClassGetInquiryData(PDEVICE_OBJECT PortDeviceObject,
|
|||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
ExFreePool(Buffer);
|
||||
*ConfigInfo = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ConfigInfo = Buffer;
|
||||
}
|
||||
|
||||
return(Status);
|
||||
|
@ -262,15 +361,18 @@ ScsiClassInitialize(PVOID Argument1,
|
|||
PVOID Argument2,
|
||||
PCLASS_INIT_DATA InitializationData)
|
||||
{
|
||||
PCONFIGURATION_INFORMATION ConfigInfo;
|
||||
PDRIVER_OBJECT DriverObject = Argument1;
|
||||
WCHAR NameBuffer[80];
|
||||
UNICODE_STRING PortName;
|
||||
ULONG PortNumber = 0;
|
||||
ULONG PortNumber;
|
||||
PDEVICE_OBJECT PortDeviceObject;
|
||||
PFILE_OBJECT FileObject;
|
||||
BOOLEAN DiskFound = FALSE;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("ScsiClassInitialize() called!\n");
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiClassCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiClassCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = ScsiClassReadWrite;
|
||||
|
@ -284,20 +386,22 @@ ScsiClassInitialize(PVOID Argument1,
|
|||
DriverObject->DriverStartIo = InitializationData->ClassStartIo;
|
||||
}
|
||||
|
||||
ConfigInfo = IoGetConfigurationInformation();
|
||||
|
||||
/* look for ScsiPortX scsi port devices */
|
||||
do
|
||||
for (PortNumber = 0; PortNumber < ConfigInfo->ScsiPortCount; PortNumber++)
|
||||
{
|
||||
swprintf(NameBuffer,
|
||||
L"\\Device\\ScsiPort%lu",
|
||||
PortNumber);
|
||||
RtlInitUnicodeString(&PortName,
|
||||
NameBuffer);
|
||||
DPRINT1("Checking scsi port %ld\n", PortNumber);
|
||||
DPRINT("Checking scsi port %ld\n", PortNumber);
|
||||
Status = IoGetDeviceObjectPointer(&PortName,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
&FileObject,
|
||||
&PortDeviceObject);
|
||||
DPRINT1("Status 0x%08lX\n", Status);
|
||||
DPRINT("Status 0x%08lX\n", Status);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("ScsiPort%lu found.\n", PortNumber);
|
||||
|
@ -311,14 +415,10 @@ ScsiClassInitialize(PVOID Argument1,
|
|||
{
|
||||
DiskFound = TRUE;
|
||||
}
|
||||
|
||||
ObDereferenceObject(PortDeviceObject);
|
||||
ObDereferenceObject(FileObject);
|
||||
}
|
||||
PortNumber++;
|
||||
}
|
||||
while (NT_SUCCESS(Status));
|
||||
|
||||
DPRINT("ScsiClassInitialize() done!\n");
|
||||
for(;;);
|
||||
|
||||
return((DiskFound == TRUE) ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE);
|
||||
|
@ -434,12 +534,17 @@ ScsiClassSplitRequest(PDEVICE_OBJECT DeviceObject,
|
|||
}
|
||||
|
||||
|
||||
/* Internal Routines **************/
|
||||
/* INTERNAL FUNCTIONS *******************************************************/
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
// PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
// if (deviceExtension->ClassCreateClose)
|
||||
// return(deviceExtension->ClassCreateClose(DeviceObject, Irp));
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
@ -447,6 +552,7 @@ ScsiClassCreateClose(IN PDEVICE_OBJECT DeviceObject,
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiClassReadWrite(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $Id: disk.c,v 1.2 2002/01/14 01:44:03 ekohl Exp $
|
||||
/* $Id: disk.c,v 1.3 2002/01/27 01:25:15 ekohl Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
|
@ -10,14 +10,17 @@
|
|||
#include "../include/class2.h"
|
||||
#include "../include/ntddscsi.h"
|
||||
|
||||
//#define NDEBUG
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define VERSION "V0.0.1"
|
||||
|
||||
|
||||
//static NTSTATUS
|
||||
//DiskCreateDevices(VOID);
|
||||
typedef struct _DISK_DEVICE_EXTENSION
|
||||
{
|
||||
ULONG Dummy;
|
||||
} DISK_DEVICE_EXTENSION, *PDISK_DEVICE_EXTENSION;
|
||||
|
||||
|
||||
|
||||
BOOLEAN STDCALL
|
||||
|
@ -27,6 +30,19 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
|
|||
PDEVICE_OBJECT PortDeviceObject,
|
||||
ULONG PortNumber);
|
||||
|
||||
BOOLEAN STDCALL
|
||||
DiskClassCheckDevice(IN PINQUIRYDATA InquiryData);
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath, /* what's this used for? */
|
||||
IN PDEVICE_OBJECT PortDeviceObject,
|
||||
IN ULONG PortNumber,
|
||||
IN ULONG DiskNumber,
|
||||
IN PIO_SCSI_CAPABILITIES Capabilities, /* what's this used for? */
|
||||
IN PSCSI_INQUIRY_DATA InquiryData,
|
||||
IN PCLASS_INIT_DATA InitializationData);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -38,6 +54,7 @@ DiskClassShutdownFlush(IN PDEVICE_OBJECT DeviceObject,
|
|||
|
||||
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
// DriverEntry
|
||||
//
|
||||
|
@ -64,16 +81,22 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
|||
{
|
||||
CLASS_INIT_DATA InitData;
|
||||
|
||||
DbgPrint("Disk Class Driver %s\n", VERSION);
|
||||
DbgPrint("Disk Class Driver %s\n",
|
||||
VERSION);
|
||||
DPRINT("RegistryPath '%wZ'\n",
|
||||
RegistryPath);
|
||||
|
||||
RtlZeroMemory(&InitData,
|
||||
sizeof(CLASS_INIT_DATA));
|
||||
|
||||
InitData.InitializationDataSize = sizeof(CLASS_INIT_DATA);
|
||||
InitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION); // + sizeof(DISK_DATA)
|
||||
InitData.DeviceExtensionSize = sizeof(DISK_DEVICE_EXTENSION);
|
||||
InitData.DeviceType = FILE_DEVICE_DISK;
|
||||
InitData.DeviceCharacteristics = 0;
|
||||
|
||||
InitData.ClassError = NULL; // DiskClassProcessError;
|
||||
InitData.ClassReadWriteVerification = NULL; // DiskClassReadWriteVerification;
|
||||
InitData.ClassFindDeviceCallBack = NULL; // DiskClassDeviceVerification;
|
||||
InitData.ClassReadWriteVerification = NULL; // DiskClassReadWriteCheck;
|
||||
InitData.ClassFindDeviceCallBack = DiskClassCheckDevice;
|
||||
InitData.ClassFindDevices = DiskClassFindDevices;
|
||||
InitData.ClassDeviceControl = DiskClassDeviceControl;
|
||||
InitData.ClassShutdownFlush = DiskClassShutdownFlush;
|
||||
|
@ -86,25 +109,37 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
|||
}
|
||||
|
||||
|
||||
// DiskClassFindDevices
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// This function searches for device that are attached to the given scsi port.
|
||||
//
|
||||
// RUN LEVEL:
|
||||
// PASSIVE_LEVEL
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// IN PDRIVER_OBJECT DriverObject System allocated Driver Object for this driver
|
||||
// IN PUNICODE_STRING RegistryPath Name of registry driver service key
|
||||
// IN PCLASS_INIT_DATA InitializationData Pointer to the main initialization data
|
||||
// IN PDEVICE_OBJECT PortDeviceObject Scsi port device object
|
||||
// IN ULONG PortNumber Port number
|
||||
//
|
||||
// RETURNS:
|
||||
// TRUE: At least one disk drive was found
|
||||
// FALSE: No disk drive found
|
||||
//
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* DiskClassFindDevices
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function searches for device that are attached to the
|
||||
* given scsi port.
|
||||
*
|
||||
* RUN LEVEL
|
||||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS
|
||||
* DriverObject
|
||||
* System allocated Driver Object for this driver
|
||||
*
|
||||
* RegistryPath
|
||||
* Name of registry driver service key
|
||||
*
|
||||
* InitializationData
|
||||
* Pointer to the main initialization data
|
||||
*
|
||||
* PortDeviceObject
|
||||
* Pointer to the port Device Object
|
||||
*
|
||||
* PortNumber
|
||||
* Port number
|
||||
*
|
||||
* RETURN VALUE
|
||||
* TRUE: At least one disk drive was found
|
||||
* FALSE: No disk drive found
|
||||
*/
|
||||
|
||||
BOOLEAN STDCALL
|
||||
DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
|
||||
|
@ -113,12 +148,16 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
|
|||
PDEVICE_OBJECT PortDeviceObject,
|
||||
ULONG PortNumber)
|
||||
{
|
||||
PIO_SCSI_CAPABILITIES PortCapabilities = NULL;
|
||||
PCONFIGURATION_INFORMATION ConfigInfo;
|
||||
PIO_SCSI_CAPABILITIES PortCapabilities;
|
||||
PSCSI_ADAPTER_BUS_INFO AdapterBusInfo;
|
||||
PSCSI_INQUIRY_DATA UnitInfo;
|
||||
PINQUIRYDATA InquiryData;
|
||||
PCHAR Buffer;
|
||||
ULONG Bus;
|
||||
ULONG DeviceCount;
|
||||
BOOLEAN FoundDevice;
|
||||
NTSTATUS Status;
|
||||
// PCONFIGURATION_INFORMATION ConfigInfo;
|
||||
|
||||
DPRINT1("DiskClassFindDevices() called.\n");
|
||||
|
||||
|
@ -131,160 +170,282 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
|
|||
return(FALSE);
|
||||
}
|
||||
|
||||
// DPRINT1("MaximumTransferLength: %lu\n", Capabilities.MaximumTransferLength);
|
||||
DPRINT1("MaximumTransferLength: %lu\n", PortCapabilities->MaximumTransferLength);
|
||||
|
||||
/* Get inquiry data */
|
||||
Status = ScsiClassGetInquiryData(PortDeviceObject,
|
||||
(PSCSI_ADAPTER_BUS_INFO *)&Buffer);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("ScsiClassGetInquiryData() failed! (Status 0x%lX)\n", Status);
|
||||
DPRINT("ScsiClassGetInquiryData() failed! (Status %x)\n", Status);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Get number of unclaimed devices */
|
||||
/* Check whether there are unclaimed devices */
|
||||
AdapterBusInfo = (PSCSI_ADAPTER_BUS_INFO)Buffer;
|
||||
DeviceCount = ScsiClassFindUnclaimedDevices(InitializationData,
|
||||
AdapterBusInfo);
|
||||
if (DeviceCount == 0)
|
||||
{
|
||||
DPRINT("ScsiClassFindUnclaimedDevices() returned 0!");
|
||||
DPRINT1("No unclaimed devices!\n");
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// ConfigInfo = IoGetConfigurationInformation();
|
||||
// DPRINT1("Number of SCSI ports: %lu\n", ConfigInfo->ScsiPortCount);
|
||||
DPRINT1("Found %lu unclaimed devices!\n", DeviceCount);
|
||||
|
||||
ConfigInfo = IoGetConfigurationInformation();
|
||||
|
||||
/* Search each bus of this adapter */
|
||||
for (Bus = 0; Bus < (ULONG)AdapterBusInfo->NumberOfBuses; Bus++)
|
||||
{
|
||||
DPRINT("Searching bus %lu\n", Bus);
|
||||
|
||||
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + AdapterBusInfo->BusData[Bus].InquiryDataOffset);
|
||||
|
||||
while (AdapterBusInfo->BusData[Bus].InquiryDataOffset)
|
||||
{
|
||||
InquiryData = (PINQUIRYDATA)UnitInfo->InquiryData;
|
||||
|
||||
if (((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE) ||
|
||||
(InquiryData->DeviceType == OPTICAL_DEVICE)) &&
|
||||
(InquiryData->DeviceTypeQualifier == 0) &&
|
||||
(UnitInfo->DeviceClaimed == FALSE))
|
||||
{
|
||||
DPRINT1("Vendor: '%.24s'\n",
|
||||
InquiryData->VendorId);
|
||||
|
||||
/* Create device objects for disk */
|
||||
Status = DiskClassCreateDeviceObject(DriverObject,
|
||||
RegistryPath,
|
||||
PortDeviceObject,
|
||||
PortNumber,
|
||||
ConfigInfo->DiskCount,
|
||||
PortCapabilities,
|
||||
UnitInfo,
|
||||
InitializationData);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
ConfigInfo->DiskCount++;
|
||||
FoundDevice = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (UnitInfo->NextInquiryDataOffset == 0)
|
||||
break;
|
||||
|
||||
UnitInfo = (PSCSI_INQUIRY_DATA)(Buffer + UnitInfo->NextInquiryDataOffset);
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(Buffer);
|
||||
ExFreePool(PortCapabilities);
|
||||
|
||||
return(TRUE);
|
||||
DPRINT1("DiskClassFindDevices() done\n");
|
||||
|
||||
return(FoundDevice);
|
||||
}
|
||||
|
||||
|
||||
// IDECreateDevice
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* DiskClassCheckDevice
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function checks the InquiryData for the correct device
|
||||
* type and qualifier.
|
||||
*
|
||||
* RUN LEVEL
|
||||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS
|
||||
* InquiryData
|
||||
* Pointer to the inquiry data for the device in question.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* TRUE: A disk device was found.
|
||||
* FALSE: Otherwise.
|
||||
*/
|
||||
|
||||
BOOLEAN STDCALL
|
||||
DiskClassCheckDevice(IN PINQUIRYDATA InquiryData)
|
||||
{
|
||||
return((InquiryData->DeviceType == DIRECT_ACCESS_DEVICE ||
|
||||
InquiryData->DeviceType == OPTICAL_DEVICE) &&
|
||||
InquiryData->DeviceTypeQualifier == 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// IDECreateDevices
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Creates a device by calling IoCreateDevice and a symbolic link for Win32
|
||||
// Create the raw device and any partition devices on this drive
|
||||
//
|
||||
// RUN LEVEL:
|
||||
// PASSIVE_LEVEL
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// IN PDRIVER_OBJECT DriverObject The system supplied driver object
|
||||
// OUT PDEVICE_OBJECT *DeviceObject The created device object
|
||||
// IN PCONTROLLER_OBJECT ControllerObject The Controller for the device
|
||||
// IN BOOLEAN LBASupported Does the drive support LBA addressing?
|
||||
// IN BOOLEAN DMASupported Does the drive support DMA?
|
||||
// IN int SectorsPerLogCyl Sectors per cylinder
|
||||
// IN int SectorsPerLogTrk Sectors per track
|
||||
// IN DWORD Offset First valid sector for this device
|
||||
// IN DWORD Size Count of valid sectors for this device
|
||||
// IN PDRIVER_OBJECT DriverObject The system created driver object
|
||||
// IN PCONTROLLER_OBJECT ControllerObject
|
||||
// IN PIDE_CONTROLLER_EXTENSION ControllerExtension
|
||||
// The IDE controller extension for
|
||||
// this device
|
||||
// IN int DriveIdx The index of the drive on this
|
||||
// controller
|
||||
// IN int HarddiskIdx The NT device number for this
|
||||
// drive
|
||||
//
|
||||
// RETURNS:
|
||||
// NTSTATUS
|
||||
// TRUE Drive exists and devices were created
|
||||
// FALSE no devices were created for this device
|
||||
//
|
||||
#if 0
|
||||
NTSTATUS
|
||||
IDECreateDevice(IN PDRIVER_OBJECT DriverObject,
|
||||
OUT PDEVICE_OBJECT *DeviceObject,
|
||||
IN PCONTROLLER_OBJECT ControllerObject,
|
||||
IN int UnitNumber,
|
||||
IN ULONG DiskNumber,
|
||||
IN ULONG PartitionNumber,
|
||||
IN PIDE_DRIVE_IDENTIFY DrvParms,
|
||||
IN DWORD Offset,
|
||||
IN DWORD Size)
|
||||
|
||||
static NTSTATUS
|
||||
DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath, /* what's this used for? */
|
||||
IN PDEVICE_OBJECT PortDeviceObject,
|
||||
IN ULONG PortNumber,
|
||||
IN ULONG DiskNumber,
|
||||
IN PIO_SCSI_CAPABILITIES Capabilities, /* what's this used for? */
|
||||
IN PSCSI_INQUIRY_DATA InquiryData,
|
||||
IN PCLASS_INIT_DATA InitializationData) /* what's this used for? */
|
||||
{
|
||||
WCHAR NameBuffer[IDE_MAX_NAME_LENGTH];
|
||||
WCHAR ArcNameBuffer[IDE_MAX_NAME_LENGTH + 15];
|
||||
UNICODE_STRING DeviceName;
|
||||
UNICODE_STRING ArcName;
|
||||
NTSTATUS RC;
|
||||
PIDE_DEVICE_EXTENSION DeviceExtension;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING UnicodeDeviceDirName;
|
||||
WCHAR NameBuffer[80];
|
||||
CHAR NameBuffer2[80];
|
||||
PDEVICE_OBJECT DiskDeviceObject;
|
||||
HANDLE Handle;
|
||||
|
||||
// Create a unicode device name
|
||||
swprintf(NameBuffer,
|
||||
L"\\Device\\Harddisk%d\\Partition%d",
|
||||
DiskNumber,
|
||||
PartitionNumber);
|
||||
RtlInitUnicodeString(&DeviceName,
|
||||
NameBuffer);
|
||||
|
||||
// Create the device
|
||||
RC = IoCreateDevice(DriverObject, sizeof(IDE_DEVICE_EXTENSION),
|
||||
&DeviceName, FILE_DEVICE_DISK, 0, TRUE, DeviceObject);
|
||||
if (!NT_SUCCESS(RC))
|
||||
{
|
||||
DPRINT("IoCreateDevice call failed\n",0);
|
||||
return RC;
|
||||
}
|
||||
|
||||
// Set the buffering strategy here...
|
||||
(*DeviceObject)->Flags |= DO_DIRECT_IO;
|
||||
(*DeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
||||
|
||||
// Fill out Device extension data
|
||||
DeviceExtension = (PIDE_DEVICE_EXTENSION) (*DeviceObject)->DeviceExtension;
|
||||
DeviceExtension->DeviceObject = (*DeviceObject);
|
||||
DeviceExtension->ControllerObject = ControllerObject;
|
||||
DeviceExtension->UnitNumber = UnitNumber;
|
||||
DeviceExtension->LBASupported =
|
||||
(DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0;
|
||||
DeviceExtension->DMASupported =
|
||||
(DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0;
|
||||
// FIXME: deal with bizarre sector sizes
|
||||
DeviceExtension->BytesPerSector = 512 /* DrvParms->BytesPerSector */;
|
||||
DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads *
|
||||
DrvParms->SectorsPerTrack;
|
||||
DeviceExtension->SectorsPerLogTrk = DrvParms->SectorsPerTrack;
|
||||
DeviceExtension->LogicalHeads = DrvParms->LogicalHeads;
|
||||
DeviceExtension->Offset = Offset;
|
||||
DeviceExtension->Size = Size;
|
||||
DPRINT("%wZ: offset %d size %d \n",
|
||||
&DeviceName,
|
||||
DeviceExtension->Offset,
|
||||
DeviceExtension->Size);
|
||||
|
||||
// Initialize the DPC object here
|
||||
IoInitializeDpcRequest(*DeviceObject, IDEDpcForIsr);
|
||||
|
||||
if (PartitionNumber != 0)
|
||||
{
|
||||
DbgPrint("%wZ %dMB\n", &DeviceName, Size / 2048);
|
||||
}
|
||||
|
||||
/* assign arc name */
|
||||
if (PartitionNumber == 0)
|
||||
{
|
||||
swprintf(ArcNameBuffer,
|
||||
L"\\ArcName\\multi(0)disk(0)rdisk(%d)",
|
||||
DiskNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
swprintf(ArcNameBuffer,
|
||||
L"\\ArcName\\multi(0)disk(0)rdisk(%d)partition(%d)",
|
||||
DiskNumber,
|
||||
PartitionNumber);
|
||||
}
|
||||
RtlInitUnicodeString (&ArcName,
|
||||
ArcNameBuffer);
|
||||
DPRINT("%wZ ==> %wZ\n", &ArcName, &DeviceName);
|
||||
RC = IoAssignArcName (&ArcName,
|
||||
&DeviceName);
|
||||
if (!NT_SUCCESS(RC))
|
||||
{
|
||||
DPRINT("IoAssignArcName (%wZ) failed (Status %x)\n",
|
||||
&ArcName, RC);
|
||||
}
|
||||
|
||||
|
||||
return RC;
|
||||
}
|
||||
#if 0
|
||||
IDE_DRIVE_IDENTIFY DrvParms;
|
||||
PIDE_DEVICE_EXTENSION DiskDeviceExtension;
|
||||
PDEVICE_OBJECT PartitionDeviceObject;
|
||||
PIDE_DEVICE_EXTENSION PartitionDeviceExtension;
|
||||
ULONG SectorCount = 0;
|
||||
PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
|
||||
PPARTITION_INFORMATION PartitionEntry;
|
||||
#endif
|
||||
ULONG i;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT1("DiskClassCreateDeviceObjects() called\n");
|
||||
|
||||
/* Create the harddisk device directory */
|
||||
swprintf(NameBuffer,
|
||||
L"\\Device\\Harddisk%d",
|
||||
DiskNumber);
|
||||
RtlInitUnicodeString(&UnicodeDeviceDirName,
|
||||
NameBuffer);
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&UnicodeDeviceDirName,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
Status = ZwCreateDirectoryObject(&Handle,
|
||||
0,
|
||||
&ObjectAttributes);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Could not create device dir object\n");
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* Claim the disk device */
|
||||
Status = ScsiClassClaimDevice(PortDeviceObject,
|
||||
InquiryData,
|
||||
FALSE,
|
||||
&PortDeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Could not claim disk device\n");
|
||||
|
||||
ZwMakeTemporaryObject(Handle);
|
||||
ZwClose(Handle);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* Create disk device (Partition 0) */
|
||||
sprintf(NameBuffer2,
|
||||
"\\Device\\Harddisk%d\\Partition0",
|
||||
DiskNumber);
|
||||
|
||||
Status = ScsiClassCreateDeviceObject(DriverObject,
|
||||
NameBuffer2,
|
||||
NULL,
|
||||
&DiskDeviceObject,
|
||||
InitializationData);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("ScsiClassCreateDeviceObject() failed (Status %x)\n", Status);
|
||||
|
||||
ScsiClassClaimDevice(PortDeviceObject,
|
||||
InquiryData,
|
||||
TRUE,
|
||||
NULL);
|
||||
ZwMakeTemporaryObject(Handle);
|
||||
ZwClose(Handle);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Read partition table */
|
||||
Status = IoReadPartitionTable(DiskDeviceObject,
|
||||
DrvParms.BytesPerSector,
|
||||
TRUE,
|
||||
&PartitionList);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("IoReadPartitionTable() failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT(" Number of partitions: %u\n", PartitionList->PartitionCount);
|
||||
for (i=0;i < PartitionList->PartitionCount; i++)
|
||||
{
|
||||
PartitionEntry = &PartitionList->PartitionEntry[i];
|
||||
|
||||
DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
|
||||
i,
|
||||
PartitionEntry->PartitionNumber,
|
||||
PartitionEntry->BootIndicator,
|
||||
PartitionEntry->PartitionType,
|
||||
PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
|
||||
PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
|
||||
|
||||
/* Create device for partition */
|
||||
Status = IDECreateDevice(DriverObject,
|
||||
&PartitionDeviceObject,
|
||||
ControllerObject,
|
||||
DriveIdx,
|
||||
HarddiskIdx,
|
||||
&DrvParms,
|
||||
PartitionEntry->PartitionNumber,
|
||||
PartitionEntry->StartingOffset.QuadPart / 512 /* DrvParms.BytesPerSector*/,
|
||||
PartitionEntry->PartitionLength.QuadPart / 512 /*DrvParms.BytesPerSector*/);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("IDECreateDevice() failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize pointer to disk device extension */
|
||||
PartitionDeviceExtension = (PIDE_DEVICE_EXTENSION)PartitionDeviceObject->DeviceExtension;
|
||||
PartitionDeviceExtension->DiskExtension = (PVOID)DiskDeviceExtension;
|
||||
}
|
||||
|
||||
if (PartitionList != NULL)
|
||||
ExFreePool(PartitionList);
|
||||
#endif
|
||||
|
||||
DPRINT1("DiskClassCreateDeviceObjects() done\n");
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: scsi.h,v 1.2 2002/01/14 01:44:18 ekohl Exp $
|
||||
/* $Id: scsi.h,v 1.3 2002/01/27 01:25:33 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -10,175 +10,157 @@
|
|||
#ifndef __STORAGE_INCLUDE_SCSI_H
|
||||
#define __STORAGE_INCLUDE_SCSI_H
|
||||
|
||||
//
|
||||
// Command Descriptor Block. Passed by SCSI controller chip over the SCSI bus
|
||||
//
|
||||
|
||||
typedef union _CDB {
|
||||
/* Command Descriptor Block */
|
||||
|
||||
//
|
||||
// Generic 6-Byte CDB
|
||||
//
|
||||
|
||||
struct _CDB6GENERIC {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Immediate : 1;
|
||||
UCHAR CommandUniqueBits : 4;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR CommandUniqueBytes[3];
|
||||
UCHAR Link : 1;
|
||||
UCHAR Flag : 1;
|
||||
UCHAR Reserved : 4;
|
||||
UCHAR VendorUnique : 2;
|
||||
typedef union _CDB
|
||||
{
|
||||
/* Generic 6-Byte CDB */
|
||||
struct _CDB6GENERIC
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Immediate:1;
|
||||
UCHAR CommandUniqueBits:4;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR CommandUniqueBytes[3];
|
||||
UCHAR Link:1;
|
||||
UCHAR Flag:1;
|
||||
UCHAR Reserved:4;
|
||||
UCHAR VendorUnique:2;
|
||||
} CDB6GENERIC, *PCDB6GENERIC;
|
||||
|
||||
//
|
||||
// Standard 6-byte CDB
|
||||
//
|
||||
|
||||
struct _CDB6READWRITE {
|
||||
UCHAR OperationCode;
|
||||
UCHAR LogicalBlockMsb1 : 5;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR LogicalBlockMsb0;
|
||||
UCHAR LogicalBlockLsb;
|
||||
UCHAR TransferBlocks;
|
||||
UCHAR Control;
|
||||
/* Standard 6-byte CDB */
|
||||
struct _CDB6READWRITE
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR LogicalBlockMsb1:5;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR LogicalBlockMsb0;
|
||||
UCHAR LogicalBlockLsb;
|
||||
UCHAR TransferBlocks;
|
||||
UCHAR Control;
|
||||
} CDB6READWRITE, *PCDB6READWRITE;
|
||||
|
||||
|
||||
//
|
||||
// SCSI Inquiry CDB
|
||||
//
|
||||
|
||||
struct _CDB6INQUIRY {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1 : 5;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR PageCode;
|
||||
UCHAR IReserved;
|
||||
UCHAR AllocationLength;
|
||||
UCHAR Control;
|
||||
/* SCSI Inquiry CDB */
|
||||
struct _CDB6INQUIRY
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1:5;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR PageCode;
|
||||
UCHAR IReserved;
|
||||
UCHAR AllocationLength;
|
||||
UCHAR Control;
|
||||
} CDB6INQUIRY, *PCDB6INQUIRY;
|
||||
|
||||
//
|
||||
// SCSI Format CDB
|
||||
//
|
||||
|
||||
struct _CDB6FORMAT {
|
||||
UCHAR OperationCode;
|
||||
UCHAR FormatControl : 5;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR FReserved1;
|
||||
UCHAR InterleaveMsb;
|
||||
UCHAR InterleaveLsb;
|
||||
UCHAR FReserved2;
|
||||
/* SCSI Format CDB */
|
||||
struct _CDB6FORMAT
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR FormatControl:5;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR FReserved1;
|
||||
UCHAR InterleaveMsb;
|
||||
UCHAR InterleaveLsb;
|
||||
UCHAR FReserved2;
|
||||
} CDB6FORMAT, *PCDB6FORMAT;
|
||||
|
||||
//
|
||||
// Standard 10-byte CDB
|
||||
|
||||
struct _CDB10 {
|
||||
UCHAR OperationCode;
|
||||
UCHAR RelativeAddress : 1;
|
||||
UCHAR Reserved1 : 2;
|
||||
UCHAR ForceUnitAccess : 1;
|
||||
UCHAR DisablePageOut : 1;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR LogicalBlockByte0;
|
||||
UCHAR LogicalBlockByte1;
|
||||
UCHAR LogicalBlockByte2;
|
||||
UCHAR LogicalBlockByte3;
|
||||
UCHAR Reserved2;
|
||||
UCHAR TransferBlocksMsb;
|
||||
UCHAR TransferBlocksLsb;
|
||||
UCHAR Control;
|
||||
/* Standard 10-byte CDB */
|
||||
struct _CDB10
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR RelativeAddress:1;
|
||||
UCHAR Reserved1:2;
|
||||
UCHAR ForceUnitAccess:1;
|
||||
UCHAR DisablePageOut:1;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR LogicalBlockByte0;
|
||||
UCHAR LogicalBlockByte1;
|
||||
UCHAR LogicalBlockByte2;
|
||||
UCHAR LogicalBlockByte3;
|
||||
UCHAR Reserved2;
|
||||
UCHAR TransferBlocksMsb;
|
||||
UCHAR TransferBlocksLsb;
|
||||
UCHAR Control;
|
||||
} CDB10, *PCDB10;
|
||||
|
||||
//
|
||||
// CD Rom Audio CDBs
|
||||
//
|
||||
|
||||
struct _PAUSE_RESUME {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1 : 5;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR Reserved2[6];
|
||||
UCHAR Action;
|
||||
UCHAR Control;
|
||||
/* CD Rom Audio CDBs */
|
||||
struct _PAUSE_RESUME
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1:5;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR Reserved2[6];
|
||||
UCHAR Action;
|
||||
UCHAR Control;
|
||||
} PAUSE_RESUME, *PPAUSE_RESUME;
|
||||
|
||||
//
|
||||
// Read Table of Contents
|
||||
//
|
||||
|
||||
struct _READ_TOC {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved0 : 1;
|
||||
UCHAR Msf : 1;
|
||||
UCHAR Reserved1 : 3;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR Reserved2[4];
|
||||
UCHAR StartingTrack;
|
||||
UCHAR AllocationLength[2];
|
||||
UCHAR Control : 6;
|
||||
UCHAR Format : 2;
|
||||
/* Read Table of Contents */
|
||||
struct _READ_TOC
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved0:1;
|
||||
UCHAR Msf:1;
|
||||
UCHAR Reserved1:3;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR Reserved2[4];
|
||||
UCHAR StartingTrack;
|
||||
UCHAR AllocationLength[2];
|
||||
UCHAR Control:6;
|
||||
UCHAR Format:2;
|
||||
} READ_TOC, *PREAD_TOC;
|
||||
|
||||
struct _PLAY_AUDIO_MSF {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1 : 5;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR Reserved2;
|
||||
UCHAR StartingM;
|
||||
UCHAR StartingS;
|
||||
UCHAR StartingF;
|
||||
UCHAR EndingM;
|
||||
UCHAR EndingS;
|
||||
UCHAR EndingF;
|
||||
UCHAR Control;
|
||||
struct _PLAY_AUDIO_MSF
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1:5;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR Reserved2;
|
||||
UCHAR StartingM;
|
||||
UCHAR StartingS;
|
||||
UCHAR StartingF;
|
||||
UCHAR EndingM;
|
||||
UCHAR EndingS;
|
||||
UCHAR EndingF;
|
||||
UCHAR Control;
|
||||
} PLAY_AUDIO_MSF, *PPLAY_AUDIO_MSF;
|
||||
|
||||
//
|
||||
// Read SubChannel Data
|
||||
//
|
||||
|
||||
struct _SUBCHANNEL {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved0 : 1;
|
||||
UCHAR Msf : 1;
|
||||
UCHAR Reserved1 : 3;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
UCHAR Reserved2 : 6;
|
||||
UCHAR SubQ : 1;
|
||||
UCHAR Reserved3 : 1;
|
||||
UCHAR Format;
|
||||
UCHAR Reserved4[2];
|
||||
UCHAR TrackNumber;
|
||||
UCHAR AllocationLength[2];
|
||||
UCHAR Control;
|
||||
/* Read SubChannel Data */
|
||||
struct _SUBCHANNEL
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved0:1;
|
||||
UCHAR Msf:1;
|
||||
UCHAR Reserved1:3;
|
||||
UCHAR LogicalUnitNumber:3;
|
||||
UCHAR Reserved2:6;
|
||||
UCHAR SubQ:1;
|
||||
UCHAR Reserved3:1;
|
||||
UCHAR Format;
|
||||
UCHAR Reserved4[2];
|
||||
UCHAR TrackNumber;
|
||||
UCHAR AllocationLength[2];
|
||||
UCHAR Control;
|
||||
} SUBCHANNEL, *PSUBCHANNEL;
|
||||
|
||||
//
|
||||
// Read CD. Used by Atapi for raw sector reads.
|
||||
//
|
||||
|
||||
struct _READ_CD {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved0 : 2;
|
||||
UCHAR ExpectedSectorType : 3;
|
||||
UCHAR Reserved1 : 3;
|
||||
UCHAR StartingLBA[4];
|
||||
UCHAR TransferBlocks[3];
|
||||
UCHAR Reserved2 : 1;
|
||||
UCHAR ErrorFlags : 2;
|
||||
UCHAR IncludeEDC : 1;
|
||||
UCHAR IncludeUserData : 1;
|
||||
UCHAR HeaderCode : 2;
|
||||
UCHAR IncludeSyncData : 1;
|
||||
UCHAR SubChannelSelection : 3;
|
||||
UCHAR Reserved3 : 5;
|
||||
UCHAR Reserved4;
|
||||
/* Read CD. Used by Atapi for raw sector reads. */
|
||||
struct _READ_CD
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved0 : 2;
|
||||
UCHAR ExpectedSectorType : 3;
|
||||
UCHAR Reserved1 : 3;
|
||||
UCHAR StartingLBA[4];
|
||||
UCHAR TransferBlocks[3];
|
||||
UCHAR Reserved2 : 1;
|
||||
UCHAR ErrorFlags : 2;
|
||||
UCHAR IncludeEDC : 1;
|
||||
UCHAR IncludeUserData : 1;
|
||||
UCHAR HeaderCode : 2;
|
||||
UCHAR IncludeSyncData : 1;
|
||||
UCHAR SubChannelSelection : 3;
|
||||
UCHAR Reserved3 : 5;
|
||||
UCHAR Reserved4;
|
||||
} READ_CD, *PREAD_CD;
|
||||
|
||||
//
|
||||
|
@ -320,7 +302,7 @@ typedef union _CDB {
|
|||
UCHAR Control;
|
||||
} SEEK, *PSEEK;
|
||||
|
||||
struct _ERASE {
|
||||
struct _ERASE {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Long : 1;
|
||||
UCHAR Immediate : 1;
|
||||
|
@ -330,7 +312,8 @@ typedef union _CDB {
|
|||
UCHAR Control;
|
||||
} ERASE, *PERASE;
|
||||
|
||||
struct _START_STOP {
|
||||
struct _START_STOP
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Immediate: 1;
|
||||
UCHAR Reserved1 : 4;
|
||||
|
@ -342,7 +325,7 @@ typedef union _CDB {
|
|||
UCHAR Control;
|
||||
} START_STOP, *PSTART_STOP;
|
||||
|
||||
struct _MEDIA_REMOVAL {
|
||||
struct _MEDIA_REMOVAL {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1 : 5;
|
||||
UCHAR LogicalUnitNumber : 3;
|
||||
|
@ -461,29 +444,25 @@ typedef union _CDB {
|
|||
UCHAR Reserved5[3];
|
||||
} LOAD_UNLOAD, *PLOAD_UNLOAD;
|
||||
|
||||
struct _MECH_STATUS {
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1[7];
|
||||
UCHAR AllocationLength[2];
|
||||
UCHAR Reserved2[2];
|
||||
struct _MECH_STATUS
|
||||
{
|
||||
UCHAR OperationCode;
|
||||
UCHAR Reserved1[7];
|
||||
UCHAR AllocationLength[2];
|
||||
UCHAR Reserved2[2];
|
||||
} MECH_STATUS, *PMECH_STATUS;
|
||||
|
||||
} CDB, *PCDB;
|
||||
|
||||
//
|
||||
// Command Descriptor Block constants.
|
||||
//
|
||||
|
||||
/* Command Descriptor Block constants */
|
||||
#define CDB6GENERIC_LENGTH 6
|
||||
#define CDB10GENERIC_LENGTH 10
|
||||
#define CDB12GENERIC_LENGTH 12
|
||||
|
||||
#define SETBITON 1
|
||||
#define SETBITOFF 0
|
||||
//
|
||||
// Mode Sense/Select page constants.
|
||||
//
|
||||
|
||||
/* Mode Sense/Select page constants */
|
||||
#define MODE_PAGE_ERROR_RECOVERY 0x01
|
||||
#define MODE_PAGE_DISCONNECT 0x02
|
||||
#define MODE_PAGE_FORMAT_DEVICE 0x03
|
||||
|
@ -863,10 +842,7 @@ typedef struct _SENSE_DATA
|
|||
#define SCSI_SENSEQ_END_OF_MEDIA_DETECTED 0x02
|
||||
#define SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED 0x04
|
||||
|
||||
|
||||
//
|
||||
// SCSI IO Device Control Codes
|
||||
//
|
||||
/* SCSI IO Device Control Codes */
|
||||
|
||||
#define FILE_DEVICE_SCSI 0x0000001b
|
||||
|
||||
|
@ -874,9 +850,7 @@ typedef struct _SENSE_DATA
|
|||
#define IOCTL_SCSI_EXECUTE_OUT ((FILE_DEVICE_SCSI << 16) + 0x0012)
|
||||
#define IOCTL_SCSI_EXECUTE_NONE ((FILE_DEVICE_SCSI << 16) + 0x0013)
|
||||
|
||||
//
|
||||
// SMART support in atapi
|
||||
//
|
||||
/* SMART support in atapi */
|
||||
|
||||
#define IOCTL_SCSI_MINIPORT_SMART_VERSION ((FILE_DEVICE_SCSI << 16) + 0x0500)
|
||||
#define IOCTL_SCSI_MINIPORT_IDENTIFY ((FILE_DEVICE_SCSI << 16) + 0x0501)
|
||||
|
@ -893,8 +867,9 @@ typedef struct _SENSE_DATA
|
|||
// Read Capacity Data - returned in Big Endian format
|
||||
//
|
||||
|
||||
typedef struct _READ_CAPACITY_DATA {
|
||||
ULONG LogicalBlockAddress;
|
||||
typedef struct _READ_CAPACITY_DATA
|
||||
{
|
||||
ULONG LogicalBlockAddress;
|
||||
ULONG BytesPerBlock;
|
||||
} READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
|
||||
|
||||
|
@ -952,23 +927,22 @@ typedef struct _MODE_PARAMETER_BLOCK {
|
|||
UCHAR BlockLength[3];
|
||||
}MODE_PARAMETER_BLOCK, *PMODE_PARAMETER_BLOCK;
|
||||
|
||||
//
|
||||
// Define Disconnect-Reconnect page.
|
||||
//
|
||||
|
||||
typedef struct _MODE_DISCONNECT_PAGE {
|
||||
UCHAR PageCode : 6;
|
||||
UCHAR Reserved : 1;
|
||||
UCHAR PageSavable : 1;
|
||||
UCHAR PageLength;
|
||||
UCHAR BufferFullRatio;
|
||||
UCHAR BufferEmptyRatio;
|
||||
UCHAR BusInactivityLimit[2];
|
||||
UCHAR BusDisconnectTime[2];
|
||||
UCHAR BusConnectTime[2];
|
||||
UCHAR MaximumBurstSize[2];
|
||||
UCHAR DataTransferDisconnect : 2;
|
||||
UCHAR Reserved2[3];
|
||||
/* Define Disconnect-Reconnect page */
|
||||
typedef struct _MODE_DISCONNECT_PAGE
|
||||
{
|
||||
UCHAR PageCode:6;
|
||||
UCHAR Reserved:1;
|
||||
UCHAR PageSavable:1;
|
||||
UCHAR PageLength;
|
||||
UCHAR BufferFullRatio;
|
||||
UCHAR BufferEmptyRatio;
|
||||
UCHAR BusInactivityLimit[2];
|
||||
UCHAR BusDisconnectTime[2];
|
||||
UCHAR BusConnectTime[2];
|
||||
UCHAR MaximumBurstSize[2];
|
||||
UCHAR DataTransferDisconnect:2;
|
||||
UCHAR Reserved2[3];
|
||||
}MODE_DISCONNECT_PAGE, *PMODE_DISCONNECT_PAGE;
|
||||
|
||||
//
|
||||
|
@ -1212,14 +1186,15 @@ typedef struct _PORT_OUTPUT {
|
|||
UCHAR Volume;
|
||||
} PORT_OUTPUT, *PPORT_OUTPUT;
|
||||
|
||||
typedef struct _AUDIO_OUTPUT {
|
||||
UCHAR CodePage;
|
||||
UCHAR ParameterLength;
|
||||
UCHAR Immediate;
|
||||
UCHAR Reserved[2];
|
||||
UCHAR LbaFormat;
|
||||
UCHAR LogicalBlocksPerSecond[2];
|
||||
PORT_OUTPUT PortOutput[4];
|
||||
typedef struct _AUDIO_OUTPUT
|
||||
{
|
||||
UCHAR CodePage;
|
||||
UCHAR ParameterLength;
|
||||
UCHAR Immediate;
|
||||
UCHAR Reserved[2];
|
||||
UCHAR LbaFormat;
|
||||
UCHAR LogicalBlocksPerSecond[2];
|
||||
PORT_OUTPUT PortOutput[4];
|
||||
} AUDIO_OUTPUT, *PAUDIO_OUTPUT;
|
||||
|
||||
//
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: srb.h,v 1.2 2002/01/14 01:44:19 ekohl Exp $
|
||||
/* $Id: srb.h,v 1.3 2002/01/27 01:25:34 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -59,7 +59,8 @@ typedef struct _PORT_CONFIGURATION_INFORMATION
|
|||
DMA_SPEED DmaSpeed;
|
||||
ULONG AlignmentMask;
|
||||
ULONG NumberOfAccessRanges;
|
||||
ACCESS_RANGE (*AccessRanges)[];
|
||||
// ACCESS_RANGE (*AccessRanges)[];
|
||||
PACCESS_RANGE AccessRanges;
|
||||
PVOID Reserved;
|
||||
UCHAR NumberOfBuses;
|
||||
CCHAR InitiatorBusId[8];
|
||||
|
@ -336,102 +337,74 @@ ScsiPortConvertUlongToPhysicalAddress(IN ULONG UlongAddress);
|
|||
VOID STDCALL
|
||||
ScsiPortFlushDma(IN PVOID HwDeviceExtension);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
ScsiPortFreeDeviceBase (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN PVOID MappedAddress
|
||||
);
|
||||
|
||||
ULONG
|
||||
STDCALL
|
||||
ScsiPortGetBusData (
|
||||
IN PVOID DeviceExtension,
|
||||
IN ULONG BusDataType,
|
||||
IN ULONG SystemIoBusNumber,
|
||||
IN ULONG SlotNumber,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Length
|
||||
);
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
ScsiPortGetDeviceBase (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN INTERFACE_TYPE BusType,
|
||||
IN ULONG SystemIoBusNumber,
|
||||
IN SCSI_PHYSICAL_ADDRESS IoAddress,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN BOOLEAN InIoSpace
|
||||
);
|
||||
|
||||
PVOID
|
||||
STDCALL
|
||||
ScsiPortGetLogicalUnit (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN UCHAR PathId,
|
||||
IN UCHAR TargetId,
|
||||
IN UCHAR Lun
|
||||
);
|
||||
|
||||
SCSI_PHYSICAL_ADDRESS
|
||||
STDCALL
|
||||
ScsiPortGetPhysicalAddress (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT PULONG Length
|
||||
);
|
||||
|
||||
PSCSI_REQUEST_BLOCK
|
||||
STDCALL
|
||||
ScsiPortGetSrb (
|
||||
IN PVOID DeviceExtension,
|
||||
IN UCHAR PathId,
|
||||
IN UCHAR TargetId,
|
||||
IN UCHAR Lun,
|
||||
IN LONG QueueTag
|
||||
);
|
||||
|
||||
PVOID STDCALL
|
||||
ScsiPortGetUncachedExtension (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
||||
IN ULONG NumberOfBytes
|
||||
);
|
||||
|
||||
PVOID STDCALL
|
||||
ScsiPortGetVirtualAddress (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN SCSI_PHYSICAL_ADDRESS PhysicalAddress
|
||||
);
|
||||
VOID STDCALL
|
||||
ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
|
||||
IN PVOID MappedAddress);
|
||||
|
||||
ULONG STDCALL
|
||||
ScsiPortInitialize (
|
||||
IN PVOID Argument1,
|
||||
IN PVOID Argument2,
|
||||
IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
|
||||
IN PVOID HwContext
|
||||
);
|
||||
ScsiPortGetBusData(IN PVOID DeviceExtension,
|
||||
IN ULONG BusDataType,
|
||||
IN ULONG SystemIoBusNumber,
|
||||
IN ULONG SlotNumber,
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Length);
|
||||
|
||||
PVOID STDCALL
|
||||
ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
|
||||
IN INTERFACE_TYPE BusType,
|
||||
IN ULONG SystemIoBusNumber,
|
||||
IN SCSI_PHYSICAL_ADDRESS IoAddress,
|
||||
IN ULONG NumberOfBytes,
|
||||
IN BOOLEAN InIoSpace);
|
||||
|
||||
PVOID STDCALL
|
||||
ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
|
||||
IN UCHAR PathId,
|
||||
IN UCHAR TargetId,
|
||||
IN UCHAR Lun);
|
||||
|
||||
SCSI_PHYSICAL_ADDRESS STDCALL
|
||||
ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT PULONG Length);
|
||||
|
||||
PSCSI_REQUEST_BLOCK STDCALL
|
||||
ScsiPortGetSrb(IN PVOID DeviceExtension,
|
||||
IN UCHAR PathId,
|
||||
IN UCHAR TargetId,
|
||||
IN UCHAR Lun,
|
||||
IN LONG QueueTag);
|
||||
|
||||
PVOID STDCALL
|
||||
ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
|
||||
IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
|
||||
IN ULONG NumberOfBytes);
|
||||
|
||||
PVOID STDCALL
|
||||
ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
|
||||
IN SCSI_PHYSICAL_ADDRESS PhysicalAddress);
|
||||
|
||||
ULONG STDCALL
|
||||
ScsiPortInitialize(IN PVOID Argument1,
|
||||
IN PVOID Argument2,
|
||||
IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
|
||||
IN PVOID HwContext);
|
||||
|
||||
VOID STDCALL
|
||||
ScsiPortIoMapTransfer (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb,
|
||||
IN ULONG LogicalAddress,
|
||||
IN ULONG Length
|
||||
);
|
||||
ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb,
|
||||
IN ULONG LogicalAddress,
|
||||
IN ULONG Length);
|
||||
|
||||
VOID STDCALL
|
||||
ScsiPortLogError (
|
||||
IN PVOID HwDeviceExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
|
||||
IN UCHAR PathId,
|
||||
IN UCHAR TargetId,
|
||||
IN UCHAR Lun,
|
||||
IN ULONG ErrorCode,
|
||||
IN ULONG UniqueId
|
||||
);
|
||||
ScsiPortLogError(IN PVOID HwDeviceExtension,
|
||||
IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
|
||||
IN UCHAR PathId,
|
||||
IN UCHAR TargetId,
|
||||
IN UCHAR Lun,
|
||||
IN ULONG ErrorCode,
|
||||
IN ULONG UniqueId);
|
||||
|
||||
VOID STDCALL
|
||||
ScsiPortMoveMemory(OUT PVOID Destination,
|
||||
|
|
|
@ -1,4 +1,22 @@
|
|||
/* $Id: scsiport.c,v 1.2 2002/01/14 01:45:03 ekohl Exp $
|
||||
/*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 2001, 2002 ReactOS Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: scsiport.c,v 1.3 2002/01/27 01:25:49 ekohl Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -7,39 +25,153 @@
|
|||
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include "../include/srb.h"
|
||||
#include "../include/scsi.h"
|
||||
#include "../include/ntddscsi.h"
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define UNIMPLEMENTED do {DbgPrint("%s:%d: Function not implemented", __FILE__, __LINE__); for(;;);} while (0)
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
|
||||
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
/*
|
||||
* SCSI_PORT_DEVICE_EXTENSION
|
||||
*
|
||||
* DESCRIPTION
|
||||
* First part of the port objects device extension. The second
|
||||
* part is the miniport-specific device extension.
|
||||
*/
|
||||
|
||||
typedef struct _SCSI_PORT_DEVICE_EXTENSION
|
||||
{
|
||||
ULONG Length;
|
||||
ULONG MiniPortExtensionSize;
|
||||
PORT_CONFIGURATION_INFORMATION PortConfig;
|
||||
|
||||
PHW_STARTIO HwStartIo;
|
||||
|
||||
UCHAR MiniPortDeviceExtension[1]; /* must be the last entry */
|
||||
} SCSI_PORT_DEVICE_EXTENSION, *PSCSI_PORT_DEVICE_EXTENSION;
|
||||
|
||||
|
||||
/*
|
||||
* SCSI_PORT_TIMER_STATES
|
||||
*
|
||||
* DESCRIPTION
|
||||
* An enumeration containing the states in the timer DFA
|
||||
*/
|
||||
|
||||
typedef enum _SCSI_PORT_TIMER_STATES
|
||||
{
|
||||
IDETimerIdle,
|
||||
IDETimerCmdWait,
|
||||
IDETimerResetWaitForBusyNegate,
|
||||
IDETimerResetWaitForDrdyAssert
|
||||
} SCSI_PORT_TIMER_STATES;
|
||||
|
||||
|
||||
/*
|
||||
* SCSI_PORT_CONTROLLER_EXTENSION
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Driver-defined structure used to hold miscellaneous controller information.
|
||||
*
|
||||
* ACCESS
|
||||
* Allocated from NON-PAGED POOL
|
||||
* Available at any IRQL
|
||||
*/
|
||||
|
||||
typedef struct _SCSI_PORT_CONTROLLER_EXTENSION
|
||||
{
|
||||
KSPIN_LOCK SpinLock;
|
||||
ULONG Number;
|
||||
ULONG Vector;
|
||||
BOOLEAN DMASupported;
|
||||
BOOLEAN ControllerInterruptBug;
|
||||
PKINTERRUPT Interrupt;
|
||||
|
||||
BOOLEAN OperationInProgress;
|
||||
UCHAR DeviceStatus;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceForOperation;
|
||||
PIRP CurrentIrp;
|
||||
ULONG Retries;
|
||||
|
||||
SCSI_PORT_TIMER_STATES TimerState;
|
||||
LONG TimerCount;
|
||||
|
||||
PDEVICE_OBJECT PortDeviceObject;
|
||||
|
||||
} SCSI_PORT_CONTROLLER_EXTENSION, *PSCSI_PORT_CONTROLLER_EXTENSION;
|
||||
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
static VOID STDCALL
|
||||
ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp);
|
||||
|
||||
static NTSTATUS
|
||||
ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
|
||||
IN ULONG PortCount);
|
||||
|
||||
static BOOLEAN STDCALL
|
||||
ScsiPortIsr(IN PKINTERRUPT Interrupt,
|
||||
IN PVOID ServiceContext);
|
||||
|
||||
static VOID
|
||||
ScsiPortDpcForIsr(IN PKDPC Dpc,
|
||||
IN PDEVICE_OBJECT DpcDeviceObject,
|
||||
IN PIRP DpcIrp,
|
||||
IN PVOID DpcContext);
|
||||
|
||||
static VOID STDCALL
|
||||
ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||
PVOID Context);
|
||||
|
||||
|
||||
// ------------------------------------------------------- Public Interface
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
// DriverEntry
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// This function initializes the driver.
|
||||
//
|
||||
// RUN LEVEL:
|
||||
// PASSIVE_LEVEL
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// IN PDRIVER_OBJECT DriverObject System allocated Driver Object
|
||||
// for this driver
|
||||
// IN PUNICODE_STRING RegistryPath Name of registry driver service
|
||||
// key
|
||||
//
|
||||
// RETURNS:
|
||||
// NTSTATUS
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* DriverEntry
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This function initializes the driver.
|
||||
*
|
||||
* RUN LEVEL
|
||||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS
|
||||
* DriverObject
|
||||
* System allocated Driver Object for this driver.
|
||||
*
|
||||
* RegistryPath
|
||||
* Name of registry driver service key.
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Status.
|
||||
*/
|
||||
|
||||
NTSTATUS STDCALL
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||
|
@ -50,6 +182,30 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME EXPORTED
|
||||
* ScsiDebugPrint
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Prints debugging messages.
|
||||
*
|
||||
* RUN LEVEL
|
||||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS
|
||||
* DebugPrintLevel
|
||||
* Debug level of the given message.
|
||||
*
|
||||
* DebugMessage
|
||||
* Pointer to printf()-compatible format string.
|
||||
*
|
||||
* ...
|
||||
Additional output data (see printf()).
|
||||
*
|
||||
* RETURN VALUE
|
||||
* None.
|
||||
*/
|
||||
|
||||
VOID
|
||||
ScsiDebugPrint(IN ULONG DebugPrintLevel,
|
||||
IN PCHAR DebugMessage,
|
||||
|
@ -215,6 +371,18 @@ ScsiPortInitialize(IN PVOID Argument1,
|
|||
{
|
||||
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
|
||||
PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
|
||||
PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension;
|
||||
PCONFIGURATION_INFORMATION SystemConfig;
|
||||
PPORT_CONFIGURATION_INFORMATION PortConfig;
|
||||
BOOLEAN Again;
|
||||
ULONG i;
|
||||
ULONG Result;
|
||||
NTSTATUS Status;
|
||||
ULONG MaxBus;
|
||||
PACCESS_RANGE AccessRanges;
|
||||
ULONG ExtensionSize;
|
||||
|
||||
DPRINT1("ScsiPortInitialize() called!\n");
|
||||
|
||||
if ((HwInitializationData->HwInitialize == NULL) ||
|
||||
(HwInitializationData->HwStartIo == NULL) ||
|
||||
|
@ -223,20 +391,113 @@ ScsiPortInitialize(IN PVOID Argument1,
|
|||
(HwInitializationData->HwResetBus == NULL))
|
||||
return(STATUS_INVALID_PARAMETER);
|
||||
|
||||
// DriverObject->DriverStartIo = HwInitializationData->HwStartIo;
|
||||
|
||||
// DriverObject->DriverStartIo = ScsiPortStartIo;
|
||||
DriverObject->DriverStartIo = ScsiPortStartIo;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
|
||||
// DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
|
||||
// DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
|
||||
|
||||
// DriverObject->MajorFunction[IRP_MJ_READ] = IDEDispatchReadWrite;
|
||||
// DriverObject->MajorFunction[IRP_MJ_WRITE] = IDEDispatchReadWrite;
|
||||
// DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = IDEDispatchQueryInformation;
|
||||
// DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = IDEDispatchSetInformation;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
|
||||
|
||||
|
||||
SystemConfig = IoGetConfigurationInformation();
|
||||
|
||||
ExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
|
||||
HwInitializationData->DeviceExtensionSize;
|
||||
PseudoDeviceExtension = ExAllocatePool(PagedPool,
|
||||
ExtensionSize);
|
||||
RtlZeroMemory(PseudoDeviceExtension,
|
||||
ExtensionSize);
|
||||
PseudoDeviceExtension->Length = ExtensionSize;
|
||||
PseudoDeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
|
||||
PseudoDeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
|
||||
|
||||
PortConfig = &PseudoDeviceExtension->PortConfig;
|
||||
|
||||
PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
|
||||
PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
|
||||
PortConfig->InterruptMode =
|
||||
(PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
|
||||
PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
|
||||
PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
|
||||
PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
|
||||
|
||||
PortConfig->AccessRanges =
|
||||
ExAllocatePool(PagedPool,
|
||||
sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
|
||||
|
||||
|
||||
PortConfig->SystemIoBusNumber = 0;
|
||||
PortConfig->SlotNumber = 0;
|
||||
|
||||
MaxBus = (PortConfig->AdapterInterfaceType == PCIBus) ? 8 : 1;
|
||||
|
||||
DPRINT("MaxBus: %lu\n", MaxBus);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
|
||||
|
||||
// RtlZeroMemory(AccessRanges,
|
||||
// sizeof(ACCESS_RANGE) * PortConfig->NumberOfAccessRanges);
|
||||
|
||||
/* Note: HwFindAdapter is called once for each bus */
|
||||
Result = (HwInitializationData->HwFindAdapter)(&PseudoDeviceExtension->MiniPortDeviceExtension,
|
||||
HwContext,
|
||||
NULL, /* BusInformation */
|
||||
NULL, /* ArgumentString */
|
||||
&PseudoDeviceExtension->PortConfig,
|
||||
&Again);
|
||||
DPRINT("HwFindAdapter() result: %lu\n", Result);
|
||||
|
||||
if (Result == SP_RETURN_FOUND)
|
||||
{
|
||||
DPRINT("ScsiPortInitialize(): Found HBA!\n");
|
||||
|
||||
Status = ScsiPortCreatePortDevice(DriverObject,
|
||||
PseudoDeviceExtension,
|
||||
SystemConfig->ScsiPortCount);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("ScsiPortCreatePortDevice() failed! (Status 0x%lX)\n", Status);
|
||||
|
||||
ExFreePool(PortConfig->AccessRanges);
|
||||
ExFreePool(PseudoDeviceExtension);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* Update the configuration info */
|
||||
SystemConfig->AtDiskPrimaryAddressClaimed = PortConfig->AtdiskPrimaryClaimed;
|
||||
SystemConfig->AtDiskSecondaryAddressClaimed = PortConfig->AtdiskSecondaryClaimed;
|
||||
SystemConfig->ScsiPortCount++;
|
||||
}
|
||||
|
||||
if (Again == FALSE)
|
||||
{
|
||||
PortConfig->SystemIoBusNumber++;
|
||||
PortConfig->SlotNumber = 0;
|
||||
}
|
||||
|
||||
DPRINT("Bus: %lu MaxBus: %lu\n", PortConfig->SystemIoBusNumber, MaxBus);
|
||||
if (PortConfig->SystemIoBusNumber >= MaxBus)
|
||||
{
|
||||
DPRINT1("Scanned all buses!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ExFreePool(PortConfig->AccessRanges);
|
||||
ExFreePool(PseudoDeviceExtension);
|
||||
|
||||
DPRINT1("ScsiPortInitialize() done!\n");
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -314,19 +575,460 @@ ScsiPortValidateRange(IN PVOID HwDeviceExtension,
|
|||
}
|
||||
|
||||
|
||||
/* internal functions ******/
|
||||
/* INTERNAL FUNCTIONS ********************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
* NAME INTERNAL
|
||||
* ScsiPortCreateClose
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Answer requests for Create/Close calls: a null operation.
|
||||
*
|
||||
* RUN LEVEL
|
||||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS
|
||||
* DeviceObject
|
||||
* Pointer to a device object.
|
||||
*
|
||||
* Irp
|
||||
* Pointer to an IRP.
|
||||
*
|
||||
* ...
|
||||
Additional output data (see printf()).
|
||||
*
|
||||
* RETURN VALUE
|
||||
* Status.
|
||||
*/
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("ScsiPortCreateClose()\n");
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
// ScsiPortDispatchScsi
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Answer requests for SCSI calls
|
||||
//
|
||||
// RUN LEVEL:
|
||||
// PASSIVE_LEVEL
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// Standard dispatch arguments
|
||||
//
|
||||
// RETURNS:
|
||||
// NTSTATUS
|
||||
//
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
DPRINT("ScsiPortDispatchScsi()\n");
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
// ScsiPortDeviceControl
|
||||
//
|
||||
// DESCRIPTION:
|
||||
// Answer requests for device control calls
|
||||
//
|
||||
// RUN LEVEL:
|
||||
// PASSIVE_LEVEL
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// Standard dispatch arguments
|
||||
//
|
||||
// RETURNS:
|
||||
// NTSTATUS
|
||||
//
|
||||
|
||||
static NTSTATUS STDCALL
|
||||
ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
DPRINT("ScsiPortDeviceControl()\n");
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
switch (Stack->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_SCSI_EXECUTE_IN:
|
||||
{
|
||||
DPRINT1(" IOCTL_SCSI_EXECUTE_IN\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_EXECUTE_OUT:
|
||||
{
|
||||
DPRINT1(" IOCTL_SCSI_EXECUTE_OUT\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_EXECUTE_NONE:
|
||||
{
|
||||
DPRINT1(" IOCTL_SCSI_EXECUTE_NONE\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_GET_CAPABILITIES:
|
||||
{
|
||||
PIO_SCSI_CAPABILITIES Capabilities;
|
||||
|
||||
DPRINT1(" IOCTL_SCSI_GET_CAPABILITIES\n");
|
||||
|
||||
Capabilities = (PIO_SCSI_CAPABILITIES)Irp->AssociatedIrp.SystemBuffer;
|
||||
Capabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
|
||||
Capabilities->MaximumTransferLength =
|
||||
DeviceExtension->PortConfig.MaximumTransferLength;
|
||||
Capabilities->MaximumPhysicalPages = 1;
|
||||
Capabilities->SupportedAsynchronousEvents = 0;
|
||||
Capabilities->AlignmentMask =
|
||||
DeviceExtension->PortConfig.AlignmentMask;
|
||||
Capabilities->TaggedQueuing =
|
||||
DeviceExtension->PortConfig.TaggedQueuing;
|
||||
Capabilities->AdapterScansDown =
|
||||
DeviceExtension->PortConfig.AdapterScansDown;
|
||||
Capabilities->AdapterUsesPio = TRUE;
|
||||
|
||||
Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_SCSI_GET_INQUIRY_DATA:
|
||||
{
|
||||
PSCSI_ADAPTER_BUS_INFO AdapterInfo;
|
||||
PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
|
||||
SCSI_REQUEST_BLOCK Srb;
|
||||
ULONG Bus;
|
||||
ULONG Target;
|
||||
ULONG UnitCount;
|
||||
BOOLEAN Result;
|
||||
|
||||
DPRINT1(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
|
||||
|
||||
AdapterInfo =(PSCSI_ADAPTER_BUS_INFO)Irp->AssociatedIrp.SystemBuffer;
|
||||
AdapterInfo->NumberOfBuses = DeviceExtension->PortConfig.NumberOfBuses;
|
||||
|
||||
UnitInfo = (PSCSI_INQUIRY_DATA)
|
||||
((PUCHAR)AdapterInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
|
||||
(sizeof(SCSI_BUS_DATA) * (AdapterInfo->NumberOfBuses - 1)));
|
||||
|
||||
Srb.DataBuffer = ExAllocatePool(NonPagedPool, 256);
|
||||
RtlZeroMemory(&Srb,
|
||||
sizeof(SCSI_REQUEST_BLOCK));
|
||||
Srb.Function = SRB_FUNCTION_EXECUTE_SCSI;
|
||||
Srb.DataTransferLength = 256;
|
||||
Srb.Cdb[0] = SCSIOP_INQUIRY;
|
||||
|
||||
for (Bus = 0; Bus < AdapterInfo->NumberOfBuses; Bus++)
|
||||
{
|
||||
Srb.PathId = Bus;
|
||||
|
||||
AdapterInfo->BusData[Bus].InitiatorBusId = 0; /* ? */
|
||||
AdapterInfo->BusData[Bus].InquiryDataOffset =
|
||||
(ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterInfo);
|
||||
|
||||
PrevUnit = NULL;
|
||||
UnitCount = 0;
|
||||
|
||||
for (Target = 0; Target < DeviceExtension->PortConfig.MaximumNumberOfTargets; Target++)
|
||||
{
|
||||
Srb.TargetId = Target;
|
||||
Srb.Lun = 0;
|
||||
|
||||
Result = DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
|
||||
&Srb);
|
||||
if (Result == TRUE)
|
||||
{
|
||||
UnitInfo->PathId = Bus;
|
||||
UnitInfo->TargetId = Target;
|
||||
UnitInfo->Lun = 0;
|
||||
UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
|
||||
memcpy(&UnitInfo->InquiryData,
|
||||
Srb.DataBuffer,
|
||||
INQUIRYDATABUFFERSIZE);
|
||||
if (PrevUnit != NULL)
|
||||
PrevUnit->NextInquiryDataOffset = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
|
||||
PrevUnit = UnitInfo;
|
||||
UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
|
||||
UnitCount++;
|
||||
}
|
||||
}
|
||||
AdapterInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
|
||||
}
|
||||
|
||||
ExFreePool(Srb.DataBuffer);
|
||||
DPRINT1("BufferSize: %lu\n",(ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo));
|
||||
Irp->IoStatus.Information = (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterInfo);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DPRINT1(" unknown ioctl code: 0x%lX\n",
|
||||
Stack->Parameters.DeviceIoControl.IoControlCode);
|
||||
break;
|
||||
}
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
static VOID STDCALL
|
||||
ScsiPortStartIo(IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IrpStack;
|
||||
|
||||
DPRINT("ScsiPortStartIo() called!\n");
|
||||
|
||||
IrpStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
// DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
||||
|
||||
// FIXME: implement the supported functions
|
||||
|
||||
switch (IrpStack->MajorFunction)
|
||||
{
|
||||
|
||||
default:
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
// KeBugCheck((ULONG)Irp);
|
||||
IoCompleteRequest(Irp,
|
||||
IO_NO_INCREMENT);
|
||||
IoStartNextPacket(DeviceObject,
|
||||
FALSE);
|
||||
break;
|
||||
}
|
||||
DPRINT("ScsiPortStartIo() finished!\n");
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS
|
||||
ScsiPortCreatePortDevice(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PSCSI_PORT_DEVICE_EXTENSION PseudoDeviceExtension,
|
||||
IN ULONG PortNumber)
|
||||
{
|
||||
PSCSI_PORT_CONTROLLER_EXTENSION ControllerExtension;
|
||||
PCONTROLLER_OBJECT ControllerObject;
|
||||
PSCSI_PORT_DEVICE_EXTENSION PortDeviceExtension;
|
||||
PDEVICE_OBJECT PortDeviceObject;
|
||||
WCHAR NameBuffer[80];
|
||||
UNICODE_STRING DeviceName;
|
||||
WCHAR DosNameBuffer[80];
|
||||
UNICODE_STRING DosDeviceName;
|
||||
NTSTATUS Status;
|
||||
ULONG AccessRangeSize;
|
||||
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
|
||||
DPRINT("ScsiPortCreatePortDevice() called\n");
|
||||
|
||||
MappedIrq = HalGetInterruptVector(PseudoDeviceExtension->PortConfig.AdapterInterfaceType,
|
||||
PseudoDeviceExtension->PortConfig.SystemIoBusNumber,
|
||||
0,
|
||||
PseudoDeviceExtension->PortConfig.BusInterruptLevel,
|
||||
&Dirql,
|
||||
&Affinity);
|
||||
|
||||
ControllerObject = IoCreateController(sizeof(SCSI_PORT_CONTROLLER_EXTENSION));
|
||||
if (ControllerObject == NULL)
|
||||
{
|
||||
DbgPrint("Could not create controller object for port %d\n",
|
||||
PortNumber);
|
||||
return(STATUS_NO_SUCH_DEVICE);
|
||||
}
|
||||
|
||||
/* Fill out Controller extension data */
|
||||
ControllerExtension = (PSCSI_PORT_CONTROLLER_EXTENSION)
|
||||
ControllerObject->ControllerExtension;
|
||||
ControllerExtension->Number = PortNumber;
|
||||
ControllerExtension->Vector = PseudoDeviceExtension->PortConfig.BusInterruptVector;
|
||||
ControllerExtension->DMASupported = FALSE;
|
||||
ControllerExtension->ControllerInterruptBug = FALSE;
|
||||
ControllerExtension->OperationInProgress = FALSE;
|
||||
|
||||
/* Initialize the spin lock in the controller extension */
|
||||
KeInitializeSpinLock(&ControllerExtension->SpinLock);
|
||||
|
||||
/* Register an interrupt handler for this controller */
|
||||
Status = IoConnectInterrupt(&ControllerExtension->Interrupt,
|
||||
ScsiPortIsr,
|
||||
ControllerExtension,
|
||||
&ControllerExtension->SpinLock,
|
||||
MappedIrq,
|
||||
Dirql,
|
||||
Dirql,
|
||||
PseudoDeviceExtension->PortConfig.InterruptMode,
|
||||
FALSE,
|
||||
Affinity,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Could not Connect Interrupt %d\n",
|
||||
ControllerExtension->Vector);
|
||||
IoDeleteController (ControllerObject);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/* Create a unicode device name */
|
||||
swprintf(NameBuffer,
|
||||
L"\\Device\\ScsiPort%lu",
|
||||
PortNumber);
|
||||
RtlInitUnicodeString(&DeviceName,
|
||||
NameBuffer);
|
||||
|
||||
DPRINT("Creating device: %wZ\n", &DeviceName);
|
||||
|
||||
/* Create the port device */
|
||||
Status = IoCreateDevice(DriverObject,
|
||||
PseudoDeviceExtension->Length,
|
||||
&DeviceName,
|
||||
FILE_DEVICE_CONTROLLER,
|
||||
0,
|
||||
FALSE,
|
||||
&PortDeviceObject);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
|
||||
IoDisconnectInterrupt(ControllerExtension->Interrupt);
|
||||
IoDeleteController(ControllerObject);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
DPRINT("Created device: %wZ\n", &DeviceName);
|
||||
|
||||
/* Set the buffering strategy here... */
|
||||
PortDeviceObject->Flags |= DO_DIRECT_IO;
|
||||
PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
|
||||
|
||||
PortDeviceExtension = PortDeviceObject->DeviceExtension;
|
||||
|
||||
ControllerExtension->PortDeviceObject = PortDeviceObject;
|
||||
|
||||
/* Initialize the DPC object here */
|
||||
IoInitializeDpcRequest(ControllerExtension->PortDeviceObject,
|
||||
ScsiPortDpcForIsr);
|
||||
|
||||
/*
|
||||
* Initialize the controller timer here
|
||||
* (since it has to be tied to a device)
|
||||
*/
|
||||
ControllerExtension->TimerState = IDETimerIdle;
|
||||
ControllerExtension->TimerCount = 0;
|
||||
IoInitializeTimer(ControllerExtension->PortDeviceObject,
|
||||
ScsiPortIoTimer,
|
||||
ControllerExtension);
|
||||
|
||||
/* Copy port configuration in device extension */
|
||||
memcpy(PortDeviceExtension,
|
||||
PseudoDeviceExtension,
|
||||
PseudoDeviceExtension->Length);
|
||||
|
||||
/* Copy access ranges */
|
||||
AccessRangeSize =
|
||||
sizeof(ACCESS_RANGE) * PseudoDeviceExtension->PortConfig.NumberOfAccessRanges;
|
||||
PortDeviceExtension->PortConfig.AccessRanges = ExAllocatePool(NonPagedPool,
|
||||
AccessRangeSize);
|
||||
memcpy(PortDeviceExtension->PortConfig.AccessRanges,
|
||||
PseudoDeviceExtension->PortConfig.AccessRanges,
|
||||
AccessRangeSize);
|
||||
|
||||
/* FIXME: Copy or configure any more? */
|
||||
|
||||
/* Create the dos device */
|
||||
swprintf(DosNameBuffer,
|
||||
L"\\??\\Scsi%lu:",
|
||||
PortNumber);
|
||||
RtlInitUnicodeString(&DosDeviceName,
|
||||
DosNameBuffer);
|
||||
|
||||
IoCreateSymbolicLink(&DosDeviceName,
|
||||
&DeviceName);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static BOOLEAN STDCALL
|
||||
ScsiPortIsr(IN PKINTERRUPT Interrupt,
|
||||
IN PVOID ServiceContext)
|
||||
{
|
||||
DPRINT1("ScsiPortIsr() called!\n");
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// ScsiPortDpcForIsr
|
||||
// DESCRIPTION:
|
||||
//
|
||||
// RUN LEVEL:
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// IN PKDPC Dpc
|
||||
// IN PDEVICE_OBJECT DpcDeviceObject
|
||||
// IN PIRP DpcIrp
|
||||
// IN PVOID DpcContext
|
||||
//
|
||||
static VOID
|
||||
ScsiPortDpcForIsr(IN PKDPC Dpc,
|
||||
IN PDEVICE_OBJECT DpcDeviceObject,
|
||||
IN PIRP DpcIrp,
|
||||
IN PVOID DpcContext)
|
||||
{
|
||||
DPRINT("ScsiPortDpcForIsr()\n");
|
||||
// IDEFinishOperation((PIDE_CONTROLLER_EXTENSION) DpcContext);
|
||||
}
|
||||
|
||||
|
||||
// ScsiPortIoTimer
|
||||
// DESCRIPTION:
|
||||
// This function handles timeouts and other time delayed processing
|
||||
//
|
||||
// RUN LEVEL:
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// IN PDEVICE_OBJECT DeviceObject Device object registered with timer
|
||||
// IN PVOID Context the Controller extension for the
|
||||
// controller the device is on
|
||||
//
|
||||
static VOID STDCALL
|
||||
ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
|
||||
PVOID Context)
|
||||
{
|
||||
DPRINT("ScsiPortIoTimer()\n");
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue