Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462/* * PROJECT: ReactOS Storage Stack * LICENSE: DDK - see license.txt in the root dir * FILE: drivers/storage/atapi/atapi.h * PURPOSE: ATAPI IDE miniport driver * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK */
#include <srb.h>#include <scsi.h>
//// IDE register definition//
typedef struct _IDE_REGISTERS_1 { USHORT Data; UCHAR BlockCount; UCHAR BlockNumber; UCHAR CylinderLow; UCHAR CylinderHigh; UCHAR DriveSelect; UCHAR Command;} IDE_REGISTERS_1, *PIDE_REGISTERS_1;
typedef struct _IDE_REGISTERS_2 { UCHAR AlternateStatus; UCHAR DriveAddress;} IDE_REGISTERS_2, *PIDE_REGISTERS_2;
typedef struct _IDE_REGISTERS_3 { ULONG Data; UCHAR Others[4];} IDE_REGISTERS_3, *PIDE_REGISTERS_3;
//// Device Extension Device Flags//
#define DFLAGS_DEVICE_PRESENT 0x0001 // Indicates that some device is present.#define DFLAGS_ATAPI_DEVICE 0x0002 // Indicates whether Atapi commands can be used.#define DFLAGS_TAPE_DEVICE 0x0004 // Indicates whether this is a tape device.#define DFLAGS_INT_DRQ 0x0008 // Indicates whether device interrupts as DRQ is set after // receiving Atapi Packet Command#define DFLAGS_REMOVABLE_DRIVE 0x0010 // Indicates that the drive has the 'removable' bit set in // identify data (offset 128)#define DFLAGS_MEDIA_STATUS_ENABLED 0x0020 // Media status notification enabled#define DFLAGS_ATAPI_CHANGER 0x0040 // Indicates atapi 2.5 changer present.#define DFLAGS_SANYO_ATAPI_CHANGER 0x0080 // Indicates multi-platter device, not conforming to the 2.5 spec.#define DFLAGS_CHANGER_INITED 0x0100 // Indicates that the init path for changers has already been done.//// Used to disable 'advanced' features.//
#define MAX_ERRORS 4
//// ATAPI command definitions//
#define ATAPI_MODE_SENSE 0x5A#define ATAPI_MODE_SELECT 0x55#define ATAPI_FORMAT_UNIT 0x24
//// ATAPI Command Descriptor Block//
typedef struct _MODE_SENSE_10 { UCHAR OperationCode; UCHAR Reserved1; UCHAR PageCode : 6; UCHAR Pc : 2; UCHAR Reserved2[4]; UCHAR ParameterListLengthMsb; UCHAR ParameterListLengthLsb; UCHAR Reserved3[3];} MODE_SENSE_10, *PMODE_SENSE_10;
typedef struct _MODE_SELECT_10 { UCHAR OperationCode; UCHAR Reserved1 : 4; UCHAR PFBit : 1; UCHAR Reserved2 : 3; UCHAR Reserved3[5]; UCHAR ParameterListLengthMsb; UCHAR ParameterListLengthLsb; UCHAR Reserved4[3];} MODE_SELECT_10, *PMODE_SELECT_10;
typedef struct _MODE_PARAMETER_HEADER_10 { UCHAR ModeDataLengthMsb; UCHAR ModeDataLengthLsb; UCHAR MediumType; UCHAR Reserved[5];}MODE_PARAMETER_HEADER_10, *PMODE_PARAMETER_HEADER_10;
//// IDE command definitions//
#define IDE_COMMAND_ATAPI_RESET 0x08#define IDE_COMMAND_RECALIBRATE 0x10#define IDE_COMMAND_READ 0x20#define IDE_COMMAND_WRITE 0x30#define IDE_COMMAND_VERIFY 0x40#define IDE_COMMAND_SEEK 0x70#define IDE_COMMAND_SET_DRIVE_PARAMETERS 0x91#define IDE_COMMAND_ATAPI_PACKET 0xA0#define IDE_COMMAND_ATAPI_IDENTIFY 0xA1#define IDE_COMMAND_READ_MULTIPLE 0xC4#define IDE_COMMAND_WRITE_MULTIPLE 0xC5#define IDE_COMMAND_SET_MULTIPLE 0xC6#define IDE_COMMAND_READ_DMA 0xC8#define IDE_COMMAND_WRITE_DMA 0xCA#define IDE_COMMAND_GET_MEDIA_STATUS 0xDA#define IDE_COMMAND_ENABLE_MEDIA_STATUS 0xEF#define IDE_COMMAND_IDENTIFY 0xEC#define IDE_COMMAND_MEDIA_EJECT 0xED
//// IDE status definitions//
#define IDE_STATUS_ERROR 0x01#define IDE_STATUS_INDEX 0x02#define IDE_STATUS_CORRECTED_ERROR 0x04#define IDE_STATUS_DRQ 0x08#define IDE_STATUS_DSC 0x10#define IDE_STATUS_DRDY 0x40#define IDE_STATUS_IDLE 0x50#define IDE_STATUS_BUSY 0x80
//// IDE drive select/head definitions//
#define IDE_DRIVE_SELECT_1 0xA0#define IDE_DRIVE_SELECT_2 0x10
//// IDE drive control definitions//
#define IDE_DC_DISABLE_INTERRUPTS 0x02#define IDE_DC_RESET_CONTROLLER 0x04#define IDE_DC_REENABLE_CONTROLLER 0x00
//// IDE error definitions//
#define IDE_ERROR_BAD_BLOCK 0x80#define IDE_ERROR_DATA_ERROR 0x40#define IDE_ERROR_MEDIA_CHANGE 0x20#define IDE_ERROR_ID_NOT_FOUND 0x10#define IDE_ERROR_MEDIA_CHANGE_REQ 0x08#define IDE_ERROR_COMMAND_ABORTED 0x04#define IDE_ERROR_END_OF_MEDIA 0x02#define IDE_ERROR_ILLEGAL_LENGTH 0x01
//// ATAPI register definition//
typedef struct _ATAPI_REGISTERS_1 { USHORT Data; UCHAR InterruptReason; UCHAR Unused1; UCHAR ByteCountLow; UCHAR ByteCountHigh; UCHAR DriveSelect; UCHAR Command;} ATAPI_REGISTERS_1, *PATAPI_REGISTERS_1;
typedef struct _ATAPI_REGISTERS_2 { UCHAR AlternateStatus; UCHAR DriveAddress;} ATAPI_REGISTERS_2, *PATAPI_REGISTERS_2;
//// ATAPI interrupt reasons//
#define ATAPI_IR_COD 0x01#define ATAPI_IR_IO 0x02
//// IDENTIFY data//
typedef struct _IDENTIFY_DATA { USHORT GeneralConfiguration; // 00 00 USHORT NumberOfCylinders; // 02 1 USHORT Reserved1; // 04 2 USHORT NumberOfHeads; // 06 3 USHORT UnformattedBytesPerTrack; // 08 4 USHORT UnformattedBytesPerSector; // 0A 5 USHORT SectorsPerTrack; // 0C 6 USHORT VendorUnique1[3]; // 0E 7-9 USHORT SerialNumber[10]; // 14 10-19 USHORT BufferType; // 28 20 USHORT BufferSectorSize; // 2A 21 USHORT NumberOfEccBytes; // 2C 22 USHORT FirmwareRevision[4]; // 2E 23-26 USHORT ModelNumber[20]; // 36 27-46 UCHAR MaximumBlockTransfer; // 5E 47 UCHAR VendorUnique2; // 5F USHORT DoubleWordIo; // 60 48 USHORT Capabilities; // 62 49 USHORT Reserved2; // 64 50 UCHAR VendorUnique3; // 66 51 UCHAR PioCycleTimingMode; // 67 UCHAR VendorUnique4; // 68 52 UCHAR DmaCycleTimingMode; // 69 USHORT TranslationFieldsValid:1; // 6A 53 USHORT Reserved3:15; USHORT NumberOfCurrentCylinders; // 6C 54 USHORT NumberOfCurrentHeads; // 6E 55 USHORT CurrentSectorsPerTrack; // 70 56 ULONG CurrentSectorCapacity; // 72 57-58 USHORT CurrentMultiSectorSetting; // 59 ULONG UserAddressableSectors; // 60-61 USHORT SingleWordDMASupport : 8; // 62 USHORT SingleWordDMAActive : 8; USHORT MultiWordDMASupport : 8; // 63 USHORT MultiWordDMAActive : 8; USHORT AdvancedPIOModes : 8; // 64 USHORT Reserved4 : 8; USHORT MinimumMWXferCycleTime; // 65 USHORT RecommendedMWXferCycleTime; // 66 USHORT MinimumPIOCycleTime; // 67 USHORT MinimumPIOCycleTimeIORDY; // 68 USHORT Reserved5[2]; // 69-70 USHORT ReleaseTimeOverlapped; // 71 USHORT ReleaseTimeServiceCommand; // 72 USHORT MajorRevision; // 73 USHORT MinorRevision; // 74 USHORT Reserved6[50]; // 75-126 USHORT SpecialFunctionsEnabled; // 127 USHORT Reserved7[128]; // 128-255} IDENTIFY_DATA, *PIDENTIFY_DATA;
//// Identify data without the Reserved4.//
typedef struct _IDENTIFY_DATA2 { USHORT GeneralConfiguration; // 00 USHORT NumberOfCylinders; // 02 USHORT Reserved1; // 04 USHORT NumberOfHeads; // 06 USHORT UnformattedBytesPerTrack; // 08 USHORT UnformattedBytesPerSector; // 0A USHORT SectorsPerTrack; // 0C USHORT VendorUnique1[3]; // 0E USHORT SerialNumber[10]; // 14 USHORT BufferType; // 28 USHORT BufferSectorSize; // 2A USHORT NumberOfEccBytes; // 2C USHORT FirmwareRevision[4]; // 2E USHORT ModelNumber[20]; // 36 UCHAR MaximumBlockTransfer; // 5E UCHAR VendorUnique2; // 5F USHORT DoubleWordIo; // 60 USHORT Capabilities; // 62 USHORT Reserved2; // 64 UCHAR VendorUnique3; // 66 UCHAR PioCycleTimingMode; // 67 UCHAR VendorUnique4; // 68 UCHAR DmaCycleTimingMode; // 69 USHORT TranslationFieldsValid:1; // 6A USHORT Reserved3:15; USHORT NumberOfCurrentCylinders; // 6C USHORT NumberOfCurrentHeads; // 6E USHORT CurrentSectorsPerTrack; // 70 ULONG CurrentSectorCapacity; // 72} IDENTIFY_DATA2, *PIDENTIFY_DATA2;
#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA)
//// IDENTIFY capability bit definitions.//
#define IDENTIFY_CAPABILITIES_DMA_SUPPORTED 0x0100#define IDENTIFY_CAPABILITIES_LBA_SUPPORTED 0x0200
//// IDENTIFY DMA timing cycle modes.//
#define IDENTIFY_DMA_CYCLES_MODE_0 0x00#define IDENTIFY_DMA_CYCLES_MODE_1 0x01#define IDENTIFY_DMA_CYCLES_MODE_2 0x02
typedef struct _BROKEN_CONTROLLER_INFORMATION { PCHAR VendorId; ULONG VendorIdLength; PCHAR DeviceId; ULONG DeviceIdLength;}BROKEN_CONTROLLER_INFORMATION, *PBROKEN_CONTROLLER_INFORMATION;
BROKEN_CONTROLLER_INFORMATION const BrokenAdapters[] = { { "1095", 4, "0640", 4}, { "1039", 4, "0601", 4}};
#define BROKEN_ADAPTERS (sizeof(BrokenAdapters) / sizeof(BROKEN_CONTROLLER_INFORMATION))
typedef struct _NATIVE_MODE_CONTROLLER_INFORMATION { PCHAR VendorId; ULONG VendorIdLength; PCHAR DeviceId; ULONG DeviceIdLength;}NATIVE_MODE_CONTROLLER_INFORMATION, *PNATIVE_MODE_CONTROLLER_INFORMATION;
NATIVE_MODE_CONTROLLER_INFORMATION const NativeModeAdapters[] = { { "10ad", 4, "0105", 4}};#define NUM_NATIVE_MODE_ADAPTERS (sizeof(NativeModeAdapters) / sizeof(NATIVE_MODE_CONTROLLER_INFORMATION))
//// Beautification macros//
#define GetStatus(BaseIoAddress, Status) \ Status = ScsiPortReadPortUchar(&BaseIoAddress->AlternateStatus);
#define GetBaseStatus(BaseIoAddress, Status) \ Status = ScsiPortReadPortUchar(&BaseIoAddress->Command);
#define WriteCommand(BaseIoAddress, Command) \ ScsiPortWritePortUchar(&BaseIoAddress->Command, Command);
#define ReadBuffer(BaseIoAddress, Buffer, Count) \ ScsiPortReadPortBufferUshort(&BaseIoAddress->Data, \ Buffer, \ Count);
#define WriteBuffer(BaseIoAddress, Buffer, Count) \ ScsiPortWritePortBufferUshort(&BaseIoAddress->Data, \ Buffer, \ Count);
#define ReadBuffer2(BaseIoAddress, Buffer, Count) \ ScsiPortReadPortBufferUlong(&BaseIoAddress->Data, \ Buffer, \ Count);
#define WriteBuffer2(BaseIoAddress, Buffer, Count) \ ScsiPortWritePortBufferUlong(&BaseIoAddress->Data, \ Buffer, \ Count);
#define WaitOnBusy(BaseIoAddress, Status) \{ \ ULONG i; \ for (i=0; i<20000; i++) { \ GetStatus(BaseIoAddress, Status); \ if (Status & IDE_STATUS_BUSY) { \ ScsiPortStallExecution(150); \ continue; \ } else { \ break; \ } \ } \}
#define WaitOnBaseBusy(BaseIoAddress, Status) \{ \ ULONG i; \ for (i=0; i<20000; i++) { \ GetBaseStatus(BaseIoAddress, Status); \ if (Status & IDE_STATUS_BUSY) { \ ScsiPortStallExecution(150); \ continue; \ } else { \ break; \ } \ } \}
#define WaitForDrq(BaseIoAddress, Status) \{ \ ULONG i; \ for (i=0; i<1000; i++) { \ GetStatus(BaseIoAddress, Status); \ if (Status & IDE_STATUS_BUSY) { \ ScsiPortStallExecution(100); \ } else if (Status & IDE_STATUS_DRQ) { \ break; \ } else { \ ScsiPortStallExecution(200); \ } \ } \}
#define WaitShortForDrq(BaseIoAddress, Status) \{ \ ULONG i; \ for (i=0; i<2; i++) { \ GetStatus(BaseIoAddress, Status); \ if (Status & IDE_STATUS_BUSY) { \ ScsiPortStallExecution(100); \ } else if (Status & IDE_STATUS_DRQ) { \ break; \ } else { \ ScsiPortStallExecution(100); \ } \ } \}
#define AtapiSoftReset(BaseIoAddress,DeviceNumber) \{\ UCHAR statusByte; \ ULONG i = 1000*1000;\ ScsiPortWritePortUchar(&BaseIoAddress->DriveSelect,(UCHAR)(((DeviceNumber & 0x1) << 4) | 0xA0)); \ ScsiPortStallExecution(500);\ ScsiPortWritePortUchar(&BaseIoAddress->Command, IDE_COMMAND_ATAPI_RESET); \ while ((ScsiPortReadPortUchar(&BaseIoAddress->Command) & IDE_STATUS_BUSY) && i--)\ ScsiPortStallExecution(30);\ ScsiPortWritePortUchar(&BaseIoAddress->DriveSelect,(UCHAR)((DeviceNumber << 4) | 0xA0)); \ WaitOnBusy( ((PIDE_REGISTERS_2)((PUCHAR)BaseIoAddress + 0x206)), statusByte); \ ScsiPortStallExecution(500);\}
#define IdeHardReset(BaseIoAddress,result) \{\ UCHAR statusByte;\ ULONG i;\ ScsiPortWritePortUchar(&BaseIoAddress->AlternateStatus,IDE_DC_RESET_CONTROLLER );\ ScsiPortStallExecution(50 * 1000);\ ScsiPortWritePortUchar(&BaseIoAddress->AlternateStatus,IDE_DC_REENABLE_CONTROLLER);\ for (i = 0; i < 1000 * 1000; i++) {\ statusByte = ScsiPortReadPortUchar(&BaseIoAddress->AlternateStatus);\ if (statusByte != IDE_STATUS_IDLE && statusByte != 0x0) {\ ScsiPortStallExecution(5);\ } else {\ break;\ }\ }\ if (i == 1000*1000) {\ result = FALSE;\ }\ result = TRUE;\}
#define IS_RDP(OperationCode)\ ((OperationCode == SCSIOP_ERASE)||\ (OperationCode == SCSIOP_LOAD_UNLOAD)||\ (OperationCode == SCSIOP_LOCATE)||\ (OperationCode == SCSIOP_REWIND) ||\ (OperationCode == SCSIOP_SPACE)||\ (OperationCode == SCSIOP_SEEK)||\ (OperationCode == SCSIOP_WRITE_FILEMARKS))