Improved recognition of ATAPI devices.

Minor cleanup.

svn path=/trunk/; revision=2683
This commit is contained in:
Eric Kohl 2002-03-08 11:58:23 +00:00
parent 9ccb920754
commit c309738334
2 changed files with 287 additions and 165 deletions

View file

@ -1,4 +1,22 @@
/* $Id: atapi.c,v 1.10 2002/03/05 00:05:28 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: atapi.c,v 1.11 2002/03/08 11:58:23 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS ATAPI miniport driver
@ -35,7 +53,7 @@
#define NDEBUG
#include <debug.h>
#define VERSION "V0.0.1"
#define VERSION "0.0.1"
// ------------------------------------------------------- File Static Data
@ -200,27 +218,6 @@ IDESwapBytePairs(char *Buf,
}
static BOOLEAN
IdeFindDrive(int Address,
int DriveIdx)
{
ULONG Cyl;
DPRINT1("IdeFindDrive(Address %lx DriveIdx %lu) called!\n", Address, DriveIdx);
IDEWriteDriveHead(Address, IDE_DH_FIXED | (DriveIdx ? IDE_DH_DRV1 : 0));
IDEWriteCylinderLow(Address, 0x30);
Cyl = IDEReadCylinderLow(Address);
DPRINT1("Cylinder %lx\n", Cyl);
DPRINT1("IdeFindDrive() done!\n");
// for(;;);
return(Cyl == 0x30);
}
// ------------------------------------------------------- Public Interface
// DriverEntry
@ -320,7 +317,7 @@ DriverEntry(IN PDRIVER_OBJECT DriverObject,
// statusToReturn = newStatus;
#endif
DPRINT1( "Returning from DriverEntry\n" );
DPRINT( "Returning from DriverEntry\n" );
return(Status);
}
@ -386,17 +383,15 @@ AtapiFindCompatiblePciController(PVOID DeviceExtension,
// (PciConfig.ProgIf & 0x05) == 0)
{
/* both channels are in compatibility mode */
DPRINT1("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
ConfigInfo->SystemIoBusNumber,
// SlotNumber.u.AsULONG >> 3,
// SlotNumber.u.AsULONG & 0x07,
SlotNumber.u.bits.DeviceNumber,
SlotNumber.u.bits.FunctionNumber,
PciConfig.VendorID,
PciConfig.DeviceID);
DPRINT("ProgIF 0x%02hx\n", PciConfig.ProgIf);
DPRINT1("Found IDE controller in compatibility mode!\n");
DPRINT("Found IDE controller in compatibility mode!\n");
ConfigInfo->NumberOfBuses = 1;
ConfigInfo->MaximumNumberOfTargets = 2;
@ -405,7 +400,7 @@ AtapiFindCompatiblePciController(PVOID DeviceExtension,
if (ConfigInfo->AtdiskPrimaryClaimed == FALSE)
{
/* Both channels unclaimed: Claim primary channel */
DPRINT1("Primary channel!\n");
DPRINT("Primary channel!\n");
DevExt->CommandPortBase = 0x01F0;
DevExt->ControlPortBase = 0x03F6;
@ -429,7 +424,7 @@ AtapiFindCompatiblePciController(PVOID DeviceExtension,
else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE)
{
/* Primary channel already claimed: claim secondary channel */
DPRINT1("Secondary channel!\n");
DPRINT("Secondary channel!\n");
DevExt->CommandPortBase = 0x0170;
DevExt->ControlPortBase = 0x0376;
@ -542,7 +537,7 @@ AtapiStartIo(IN PVOID DeviceExtension,
PATAPI_MINIPORT_EXTENSION DevExt;
ULONG Result;
DPRINT1("AtapiStartIo() called\n");
DPRINT("AtapiStartIo() called\n");
DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
@ -581,10 +576,10 @@ AtapiStartIo(IN PVOID DeviceExtension,
}
else
{
DPRINT1("SrbStatus = SRB_STATUS_PENDING\n");
DPRINT("SrbStatus = SRB_STATUS_PENDING\n");
}
DPRINT1("AtapiStartIo() done\n");
DPRINT("AtapiStartIo() done\n");
return(TRUE);
}
@ -777,13 +772,7 @@ AtapiInterrupt(IN PVOID DeviceExtension)
ControllerExtension);
#endif
}
else if (IsLastBlock)
{
#if 0
/* Else more data is needed, setup next device I/O */
IDEStartController((PVOID)DeviceExtension);
#endif
}
if (IsLastBlock)
{
@ -811,6 +800,28 @@ AtapiInterrupt(IN PVOID DeviceExtension)
// ---------------------------------------------------- Discardable statics
/**********************************************************************
* NAME INTERNAL
* AtapiFindDevices
*
* DESCRIPTION
* Searches for devices on the given port.
*
* RUN LEVEL
* PASSIVE_LEVEL
*
* ARGUMENTS
* DeviceExtension
* Port device specific information.
*
* ConfigInfo
* Port configuration information.
*
* RETURN VALUE
* TRUE: At least one device is attached to the port.
* FALSE: No device is attached to the port.
*/
static BOOLEAN
AtapiFindDevices(PATAPI_MINIPORT_EXTENSION DeviceExtension,
PPORT_CONFIGURATION_INFORMATION ConfigInfo)
@ -1261,9 +1272,204 @@ static ULONG
AtapiSendAtapiCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb)
{
DPRINT1("AtapiSendAtapiComamnd() called!\n");
DPRINT1("Not implemented yet!\n");
return(SRB_STATUS_SELECTION_TIMEOUT);
#if 0
// PIDE_DRIVE_IDENTIFY DeviceParams;
// ULONG StartingSector,i;
// ULONG SectorCount;
UCHAR ByteCountHigh;
UCHAR ByteCountLow;
// UCHAR DrvHead;
// UCHAR SectorNumber;
// UCHAR Command;
ULONG Retries;
UCHAR Status;
DPRINT1("AtapiSendAtapiCommand() called!\n");
if ((Srb->PathId != 0) ||
(Srb->TargetId > 1) ||
(Srb->Lun != 0) ||
(DeviceExtension->DevicePresent[Srb->TargetId] == FALSE))
{
return(SRB_STATUS_SELECTION_TIMEOUT);
}
DPRINT1("AtapiSendAtapiCommand(): TargetId: %lu\n",
Srb->TargetId);
/* Set pointer to data buffer. */
DeviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
DeviceExtension->CurrentSrb = Srb;
DeviceExtension->ExpectingInterrupt = TRUE;
/* wait for BUSY to clear */
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
{
Status = IDEReadStatus(DeviceExtension->CommandPortBase);
if (!(Status & IDE_SR_BUSY))
{
break;
}
ScsiPortStallExecution(10);
}
DPRINT("status=%02x\n", Status);
DPRINT("waited %ld usecs for busy to clear\n", Retries * 10);
if (Retries >= IDE_MAX_BUSY_RETRIES)
{
DPRINT ("Drive is BUSY for too long\n");
return(SRB_STATUS_BUSY);
#if 0
if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES)
{
DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
Irp = ControllerExtension->CurrentIrp;
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
Irp->IoStatus.Information = 0;
return FALSE;
}
else
{
DPRINT ("Beginning drive reset sequence\n");
IDEBeginControllerReset(ControllerExtension);
return TRUE;
}
#endif
}
/* Select the desired drive */
IDEWriteDriveHead(DeviceExtension->CommandPortBase,
IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0));
/* wait for BUSY to clear and DRDY to assert */
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
{
Status = IDEReadStatus(DeviceExtension->CommandPortBase);
if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY))
{
break;
}
ScsiPortStallExecution(10);
}
DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries * 10);
if (Retries >= IDE_MAX_BUSY_RETRIES)
{
DPRINT("Drive is BUSY for too long after drive select\n");
return(SRB_STATUS_BUSY);
#if 0
if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES)
{
DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
Irp = ControllerExtension->CurrentIrp;
Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
Irp->IoStatus.Information = 0;
return FALSE;
}
else
{
DPRINT("Beginning drive reset sequence\n");
IDEBeginControllerReset(ControllerExtension);
return TRUE;
}
#endif
}
ByteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
ByteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
IDEWriteCylinderHigh(DeviceExtension->CommandPortBase, ByteCountHigh);
IDEWriteCylinderLow(DeviceExtension->CommandPortBase, ByteCountLow);
// IDEWriteDriveHead(DeviceExtension->CommandPortBase, IDE_DH_FIXED | DrvHead);
/* Issue command to drive */
IDEWriteCommand(DeviceExtension->CommandPortBase, 0xA0); /* Packet command */
/* wait for DRQ to assert */
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
{
Status = IDEReadStatus(DeviceExtension->CommandPortBase);
if ((Status & IDE_SR_DRQ))
{
break;
}
ScsiPortStallExecution(10);
}
IDEWriteBlock(DeviceExtension->CommandPortBase,
(PUSHORT)Srb->Cdb,
12);
DPRINT1("AtapiSendAtapiCommand() done\n");
return(SRB_STATUS_PENDING);
#endif
//#if 0
ULONG SrbStatus = SRB_STATUS_SELECTION_TIMEOUT;
DPRINT("AtapiSendAtapiCommand() called!\n");
switch (Srb->Cdb[0])
{
case SCSIOP_INQUIRY:
DPRINT(" SCSIOP_INQUIRY\n");
SrbStatus = AtapiInquiry(DeviceExtension,
Srb);
break;
case SCSIOP_READ_CAPACITY:
DPRINT1(" SCSIOP_READ_CAPACITY\n");
break;
case SCSIOP_READ:
DPRINT1(" SCSIOP_READ\n");
break;
case SCSIOP_WRITE:
DPRINT1(" SCSIOP_WRITE\n");
break;
case SCSIOP_MODE_SENSE:
DPRINT1(" SCSIOP_MODE_SENSE\n");
break;
case SCSIOP_TEST_UNIT_READY:
DPRINT1(" SCSIOP_TEST_UNIT_READY\n");
break;
case SCSIOP_VERIFY:
DPRINT1(" SCSIOP_VERIFY\n");
break;
case SCSIOP_START_STOP_UNIT:
DPRINT1(" SCSIOP_START_STOP_UNIT\n");
break;
case SCSIOP_REQUEST_SENSE:
DPRINT1(" SCSIOP_REQUEST_SENSE\n");
break;
default:
DbgPrint("AtapiSendIdeCommand():unknown command %x\n",
Srb->Cdb[0]);
break;
}
if (SrbStatus == SRB_STATUS_SELECTION_TIMEOUT)
{
DPRINT1("Not implemented yet!\n");
}
return(SrbStatus);
//#endif
}
@ -1273,7 +1479,7 @@ AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
{
ULONG SrbStatus = SRB_STATUS_SUCCESS;
DPRINT1("AtapiSendIdeCommand() called!\n");
DPRINT("AtapiSendIdeCommand() called!\n");
DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n",
Srb->PathId,
@ -1306,13 +1512,13 @@ AtapiSendIdeCommand(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
break;
default:
DPRINT1("AtapiSendIdeCommand():unknown command %x\n",
Srb->Cdb[0]);
DbgPrint("AtapiSendIdeCommand():unknown command %x\n",
Srb->Cdb[0]);
SrbStatus = SRB_STATUS_INVALID_REQUEST;
break;
}
DPRINT1("AtapiSendIdeCommand() done!\n");
DPRINT("AtapiSendIdeCommand() done!\n");
return(SrbStatus);
}
@ -1326,7 +1532,7 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
PINQUIRYDATA InquiryData;
ULONG i;
DPRINT1("SCSIOP_INQUIRY: TargetId: %lu\n", Srb->TargetId);
DPRINT("SCSIOP_INQUIRY: TargetId: %lu\n", Srb->TargetId);
if ((Srb->PathId != 0) ||
(Srb->TargetId > 1) ||
@ -1353,15 +1559,15 @@ AtapiInquiry(PATAPI_MINIPORT_EXTENSION DeviceExtension,
}
else
{
/* FIXME: this is incorrect use SCSI-INQUIRY command!! */
/* cdrom drive */
InquiryData->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
/* get it from the ATAPI configuration word */
InquiryData->DeviceType = (DeviceParams->ConfigBits >> 8) & 0x1F;
DPRINT("Device class: %u\n", InquiryData->DeviceType);
}
DPRINT("ConfigBits: 0x%x\n", DeviceParams->ConfigBits);
if (DeviceParams->ConfigBits & 0x80)
{
DPRINT1("Removable media!\n");
DPRINT("Removable media!\n");
InquiryData->RemovableMedia = 1;
}
@ -1398,7 +1604,7 @@ AtapiReadCapacity(PATAPI_MINIPORT_EXTENSION DeviceExtension,
PIDE_DRIVE_IDENTIFY DeviceParams;
ULONG LastSector;
DPRINT1("SCSIOP_READ_CAPACITY: TargetId: %lu\n", Srb->TargetId);
DPRINT("SCSIOP_READ_CAPACITY: TargetId: %lu\n", Srb->TargetId);
if ((Srb->PathId != 0) ||
(Srb->TargetId > 1) ||
@ -1459,7 +1665,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
UCHAR Status;
DPRINT1("AtapiReadWrite() called!\n");
DPRINT("AtapiReadWrite() called!\n");
if ((Srb->PathId != 0) ||
(Srb->TargetId > 1) ||
@ -1520,7 +1726,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
if (DrvHead & IDE_DH_LBA)
{
DPRINT1("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
DPRINT("%s:BUS=%04x:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
(Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE",
DeviceExtension->CommandPortBase,
DrvHead & IDE_DH_DRV1 ? 1 : 0,
@ -1531,7 +1737,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
}
else
{
DPRINT1("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
DPRINT("%s:BUS=%04x:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
(Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "READ" : "WRITE",
DeviceExtension->CommandPortBase,
DrvHead & IDE_DH_DRV1 ? 1 : 0,
@ -1561,8 +1767,8 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
}
ScsiPortStallExecution(10);
}
DPRINT ("status=%02x\n", Status);
DPRINT ("waited %ld usecs for busy to clear\n", Retries * 10);
DPRINT("status=%02x\n", Status);
DPRINT("waited %ld usecs for busy to clear\n", Retries * 10);
if (Retries >= IDE_MAX_BUSY_RETRIES)
{
DPRINT ("Drive is BUSY for too long\n");
@ -1601,10 +1807,10 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
}
ScsiPortStallExecution(10);
}
DPRINT ("waited %ld usecs for busy to clear after drive select\n", Retries * 10);
DPRINT("waited %ld usecs for busy to clear after drive select\n", Retries * 10);
if (Retries >= IDE_MAX_BUSY_RETRIES)
{
DPRINT ("Drive is BUSY for too long after drive select\n");
DPRINT("Drive is BUSY for too long after drive select\n");
return(SRB_STATUS_BUSY);
#if 0
if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES)
@ -1618,7 +1824,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
}
else
{
DPRINT ("Beginning drive reset sequence\n");
DPRINT("Beginning drive reset sequence\n");
IDEBeginControllerReset(ControllerExtension);
return TRUE;
@ -1652,7 +1858,7 @@ AtapiReadWrite(PATAPI_MINIPORT_EXTENSION DeviceExtension,
/* FIXME: Write data here! */
DPRINT1("AtapiReadWrite() done!\n");
DPRINT("AtapiReadWrite() done!\n");
/* Wait for interrupt. */
return(SRB_STATUS_PENDING);

View file

@ -1,5 +1,5 @@
//
// IDE.H - defines and typedefs for the IDE Driver module.
// ATAPI.H - defines and typedefs for the IDE Driver module.
//
#ifndef __ATAPI_H
@ -118,90 +118,6 @@ extern "C" {
#define IDEWriteDriveControl(Address, Data) \
(ScsiPortWritePortUchar((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data)))
// IDE_DEVICE_EXTENSION
//
// DESCRIPTION:
// Extension to be placed in each device object
//
// ACCESS:
// Allocated from NON-PAGED POOL
// Available at any IRQL
//
typedef struct _IDE_DEVICE_EXTENSION
{
PDEVICE_OBJECT DeviceObject;
PCONTROLLER_OBJECT ControllerObject;
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;
} IDE_DEVICE_EXTENSION, *PIDE_DEVICE_EXTENSION;
// IDE_TIMER_STATES
//
// DESCRIPTION:
// An enumeration containing the states in the timer DFA
//
typedef enum _IDE_TIMER_STATES {
IDETimerIdle,
IDETimerCmdWait,
IDETimerResetWaitForBusyNegate,
IDETimerResetWaitForDrdyAssert
} IDE_TIMER_STATES;
// IDE_CONTROLLER_EXTENSION
//
// DESCRIPTION:
// Driver-defined structure used to hold miscellaneous controller information.
//
// ACCESS:
// Allocated from NON-PAGED POOL
// Available at any IRQL
//
typedef struct _IDE_CONTROLLER_EXTENSION
{
KSPIN_LOCK SpinLock;
int Number;
int Vector;
int CommandPortBase;
int ControlPortBase;
BOOLEAN DMASupported;
BOOLEAN ControllerInterruptBug;
PKINTERRUPT Interrupt;
BOOLEAN OperationInProgress;
BYTE DeviceStatus;
PIDE_DEVICE_EXTENSION DeviceForOperation;
PIRP CurrentIrp;
int Retries;
IDE_TIMER_STATES TimerState;
LONG TimerCount;
PDEVICE_OBJECT TimerDevice;
} IDE_CONTROLLER_EXTENSION, *PIDE_CONTROLLER_EXTENSION;
// IDE_DRIVE_IDENTIFY