Basic work on disk driver stack (still incomplete).

svn path=/trunk/; revision=2568
This commit is contained in:
Eric Kohl 2002-01-27 01:25:49 +00:00
parent 8dff4a88dc
commit f48e849f05
7 changed files with 2163 additions and 1588 deletions

File diff suppressed because it is too large Load diff

View file

@ -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;

View file

@ -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)

View file

@ -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);
}

View file

@ -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;
//

View file

@ -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,

View file

@ -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 */