Reactos
at listview 461 lines 15 kB view raw
1/* 2 * PROJECT: ReactOS Storage Stack 3 * LICENSE: DDK - see license.txt in the root dir 4 * FILE: drivers/storage/atapi/atapi.h 5 * PURPOSE: ATAPI IDE miniport driver 6 * PROGRAMMERS: Based on a source code sample from Microsoft NT4 DDK 7 */ 8 9#include <srb.h> 10#include <scsi.h> 11 12// 13// IDE register definition 14// 15 16typedef struct _IDE_REGISTERS_1 { 17 USHORT Data; 18 UCHAR BlockCount; 19 UCHAR BlockNumber; 20 UCHAR CylinderLow; 21 UCHAR CylinderHigh; 22 UCHAR DriveSelect; 23 UCHAR Command; 24} IDE_REGISTERS_1, *PIDE_REGISTERS_1; 25 26typedef struct _IDE_REGISTERS_2 { 27 UCHAR AlternateStatus; 28 UCHAR DriveAddress; 29} IDE_REGISTERS_2, *PIDE_REGISTERS_2; 30 31typedef struct _IDE_REGISTERS_3 { 32 ULONG Data; 33 UCHAR Others[4]; 34} IDE_REGISTERS_3, *PIDE_REGISTERS_3; 35 36// 37// Device Extension Device Flags 38// 39 40#define DFLAGS_DEVICE_PRESENT 0x0001 // Indicates that some device is present. 41#define DFLAGS_ATAPI_DEVICE 0x0002 // Indicates whether Atapi commands can be used. 42#define DFLAGS_TAPE_DEVICE 0x0004 // Indicates whether this is a tape device. 43#define DFLAGS_INT_DRQ 0x0008 // Indicates whether device interrupts as DRQ is set after 44 // receiving Atapi Packet Command 45#define DFLAGS_REMOVABLE_DRIVE 0x0010 // Indicates that the drive has the 'removable' bit set in 46 // identify data (offset 128) 47#define DFLAGS_MEDIA_STATUS_ENABLED 0x0020 // Media status notification enabled 48#define DFLAGS_ATAPI_CHANGER 0x0040 // Indicates atapi 2.5 changer present. 49#define DFLAGS_SANYO_ATAPI_CHANGER 0x0080 // Indicates multi-platter device, not conforming to the 2.5 spec. 50#define DFLAGS_CHANGER_INITED 0x0100 // Indicates that the init path for changers has already been done. 51// 52// Used to disable 'advanced' features. 53// 54 55#define MAX_ERRORS 4 56 57// 58// ATAPI command definitions 59// 60 61#define ATAPI_MODE_SENSE 0x5A 62#define ATAPI_MODE_SELECT 0x55 63#define ATAPI_FORMAT_UNIT 0x24 64 65// 66// ATAPI Command Descriptor Block 67// 68 69typedef struct _MODE_SENSE_10 { 70 UCHAR OperationCode; 71 UCHAR Reserved1; 72 UCHAR PageCode : 6; 73 UCHAR Pc : 2; 74 UCHAR Reserved2[4]; 75 UCHAR ParameterListLengthMsb; 76 UCHAR ParameterListLengthLsb; 77 UCHAR Reserved3[3]; 78} MODE_SENSE_10, *PMODE_SENSE_10; 79 80typedef struct _MODE_SELECT_10 { 81 UCHAR OperationCode; 82 UCHAR Reserved1 : 4; 83 UCHAR PFBit : 1; 84 UCHAR Reserved2 : 3; 85 UCHAR Reserved3[5]; 86 UCHAR ParameterListLengthMsb; 87 UCHAR ParameterListLengthLsb; 88 UCHAR Reserved4[3]; 89} MODE_SELECT_10, *PMODE_SELECT_10; 90 91typedef struct _MODE_PARAMETER_HEADER_10 { 92 UCHAR ModeDataLengthMsb; 93 UCHAR ModeDataLengthLsb; 94 UCHAR MediumType; 95 UCHAR Reserved[5]; 96}MODE_PARAMETER_HEADER_10, *PMODE_PARAMETER_HEADER_10; 97 98// 99// IDE command definitions 100// 101 102#define IDE_COMMAND_ATAPI_RESET 0x08 103#define IDE_COMMAND_RECALIBRATE 0x10 104#define IDE_COMMAND_READ 0x20 105#define IDE_COMMAND_WRITE 0x30 106#define IDE_COMMAND_VERIFY 0x40 107#define IDE_COMMAND_SEEK 0x70 108#define IDE_COMMAND_SET_DRIVE_PARAMETERS 0x91 109#define IDE_COMMAND_ATAPI_PACKET 0xA0 110#define IDE_COMMAND_ATAPI_IDENTIFY 0xA1 111#define IDE_COMMAND_READ_MULTIPLE 0xC4 112#define IDE_COMMAND_WRITE_MULTIPLE 0xC5 113#define IDE_COMMAND_SET_MULTIPLE 0xC6 114#define IDE_COMMAND_READ_DMA 0xC8 115#define IDE_COMMAND_WRITE_DMA 0xCA 116#define IDE_COMMAND_GET_MEDIA_STATUS 0xDA 117#define IDE_COMMAND_ENABLE_MEDIA_STATUS 0xEF 118#define IDE_COMMAND_IDENTIFY 0xEC 119#define IDE_COMMAND_MEDIA_EJECT 0xED 120 121// 122// IDE status definitions 123// 124 125#define IDE_STATUS_ERROR 0x01 126#define IDE_STATUS_INDEX 0x02 127#define IDE_STATUS_CORRECTED_ERROR 0x04 128#define IDE_STATUS_DRQ 0x08 129#define IDE_STATUS_DSC 0x10 130#define IDE_STATUS_DRDY 0x40 131#define IDE_STATUS_IDLE 0x50 132#define IDE_STATUS_BUSY 0x80 133 134// 135// IDE drive select/head definitions 136// 137 138#define IDE_DRIVE_SELECT_1 0xA0 139#define IDE_DRIVE_SELECT_2 0x10 140 141// 142// IDE drive control definitions 143// 144 145#define IDE_DC_DISABLE_INTERRUPTS 0x02 146#define IDE_DC_RESET_CONTROLLER 0x04 147#define IDE_DC_REENABLE_CONTROLLER 0x00 148 149// 150// IDE error definitions 151// 152 153#define IDE_ERROR_BAD_BLOCK 0x80 154#define IDE_ERROR_DATA_ERROR 0x40 155#define IDE_ERROR_MEDIA_CHANGE 0x20 156#define IDE_ERROR_ID_NOT_FOUND 0x10 157#define IDE_ERROR_MEDIA_CHANGE_REQ 0x08 158#define IDE_ERROR_COMMAND_ABORTED 0x04 159#define IDE_ERROR_END_OF_MEDIA 0x02 160#define IDE_ERROR_ILLEGAL_LENGTH 0x01 161 162// 163// ATAPI register definition 164// 165 166typedef struct _ATAPI_REGISTERS_1 { 167 USHORT Data; 168 UCHAR InterruptReason; 169 UCHAR Unused1; 170 UCHAR ByteCountLow; 171 UCHAR ByteCountHigh; 172 UCHAR DriveSelect; 173 UCHAR Command; 174} ATAPI_REGISTERS_1, *PATAPI_REGISTERS_1; 175 176typedef struct _ATAPI_REGISTERS_2 { 177 UCHAR AlternateStatus; 178 UCHAR DriveAddress; 179} ATAPI_REGISTERS_2, *PATAPI_REGISTERS_2; 180 181// 182// ATAPI interrupt reasons 183// 184 185#define ATAPI_IR_COD 0x01 186#define ATAPI_IR_IO 0x02 187 188// 189// IDENTIFY data 190// 191 192typedef struct _IDENTIFY_DATA { 193 USHORT GeneralConfiguration; // 00 00 194 USHORT NumberOfCylinders; // 02 1 195 USHORT Reserved1; // 04 2 196 USHORT NumberOfHeads; // 06 3 197 USHORT UnformattedBytesPerTrack; // 08 4 198 USHORT UnformattedBytesPerSector; // 0A 5 199 USHORT SectorsPerTrack; // 0C 6 200 USHORT VendorUnique1[3]; // 0E 7-9 201 USHORT SerialNumber[10]; // 14 10-19 202 USHORT BufferType; // 28 20 203 USHORT BufferSectorSize; // 2A 21 204 USHORT NumberOfEccBytes; // 2C 22 205 USHORT FirmwareRevision[4]; // 2E 23-26 206 USHORT ModelNumber[20]; // 36 27-46 207 UCHAR MaximumBlockTransfer; // 5E 47 208 UCHAR VendorUnique2; // 5F 209 USHORT DoubleWordIo; // 60 48 210 USHORT Capabilities; // 62 49 211 USHORT Reserved2; // 64 50 212 UCHAR VendorUnique3; // 66 51 213 UCHAR PioCycleTimingMode; // 67 214 UCHAR VendorUnique4; // 68 52 215 UCHAR DmaCycleTimingMode; // 69 216 USHORT TranslationFieldsValid:1; // 6A 53 217 USHORT Reserved3:15; 218 USHORT NumberOfCurrentCylinders; // 6C 54 219 USHORT NumberOfCurrentHeads; // 6E 55 220 USHORT CurrentSectorsPerTrack; // 70 56 221 ULONG CurrentSectorCapacity; // 72 57-58 222 USHORT CurrentMultiSectorSetting; // 59 223 ULONG UserAddressableSectors; // 60-61 224 USHORT SingleWordDMASupport : 8; // 62 225 USHORT SingleWordDMAActive : 8; 226 USHORT MultiWordDMASupport : 8; // 63 227 USHORT MultiWordDMAActive : 8; 228 USHORT AdvancedPIOModes : 8; // 64 229 USHORT Reserved4 : 8; 230 USHORT MinimumMWXferCycleTime; // 65 231 USHORT RecommendedMWXferCycleTime; // 66 232 USHORT MinimumPIOCycleTime; // 67 233 USHORT MinimumPIOCycleTimeIORDY; // 68 234 USHORT Reserved5[2]; // 69-70 235 USHORT ReleaseTimeOverlapped; // 71 236 USHORT ReleaseTimeServiceCommand; // 72 237 USHORT MajorRevision; // 73 238 USHORT MinorRevision; // 74 239 USHORT Reserved6[50]; // 75-126 240 USHORT SpecialFunctionsEnabled; // 127 241 USHORT Reserved7[128]; // 128-255 242} IDENTIFY_DATA, *PIDENTIFY_DATA; 243 244// 245// Identify data without the Reserved4. 246// 247 248typedef struct _IDENTIFY_DATA2 { 249 USHORT GeneralConfiguration; // 00 250 USHORT NumberOfCylinders; // 02 251 USHORT Reserved1; // 04 252 USHORT NumberOfHeads; // 06 253 USHORT UnformattedBytesPerTrack; // 08 254 USHORT UnformattedBytesPerSector; // 0A 255 USHORT SectorsPerTrack; // 0C 256 USHORT VendorUnique1[3]; // 0E 257 USHORT SerialNumber[10]; // 14 258 USHORT BufferType; // 28 259 USHORT BufferSectorSize; // 2A 260 USHORT NumberOfEccBytes; // 2C 261 USHORT FirmwareRevision[4]; // 2E 262 USHORT ModelNumber[20]; // 36 263 UCHAR MaximumBlockTransfer; // 5E 264 UCHAR VendorUnique2; // 5F 265 USHORT DoubleWordIo; // 60 266 USHORT Capabilities; // 62 267 USHORT Reserved2; // 64 268 UCHAR VendorUnique3; // 66 269 UCHAR PioCycleTimingMode; // 67 270 UCHAR VendorUnique4; // 68 271 UCHAR DmaCycleTimingMode; // 69 272 USHORT TranslationFieldsValid:1; // 6A 273 USHORT Reserved3:15; 274 USHORT NumberOfCurrentCylinders; // 6C 275 USHORT NumberOfCurrentHeads; // 6E 276 USHORT CurrentSectorsPerTrack; // 70 277 ULONG CurrentSectorCapacity; // 72 278} IDENTIFY_DATA2, *PIDENTIFY_DATA2; 279 280#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA) 281 282// 283// IDENTIFY capability bit definitions. 284// 285 286#define IDENTIFY_CAPABILITIES_DMA_SUPPORTED 0x0100 287#define IDENTIFY_CAPABILITIES_LBA_SUPPORTED 0x0200 288 289// 290// IDENTIFY DMA timing cycle modes. 291// 292 293#define IDENTIFY_DMA_CYCLES_MODE_0 0x00 294#define IDENTIFY_DMA_CYCLES_MODE_1 0x01 295#define IDENTIFY_DMA_CYCLES_MODE_2 0x02 296 297 298typedef struct _BROKEN_CONTROLLER_INFORMATION { 299 PCHAR VendorId; 300 ULONG VendorIdLength; 301 PCHAR DeviceId; 302 ULONG DeviceIdLength; 303}BROKEN_CONTROLLER_INFORMATION, *PBROKEN_CONTROLLER_INFORMATION; 304 305BROKEN_CONTROLLER_INFORMATION const BrokenAdapters[] = { 306 { "1095", 4, "0640", 4}, 307 { "1039", 4, "0601", 4} 308}; 309 310#define BROKEN_ADAPTERS (sizeof(BrokenAdapters) / sizeof(BROKEN_CONTROLLER_INFORMATION)) 311 312typedef struct _NATIVE_MODE_CONTROLLER_INFORMATION { 313 PCHAR VendorId; 314 ULONG VendorIdLength; 315 PCHAR DeviceId; 316 ULONG DeviceIdLength; 317}NATIVE_MODE_CONTROLLER_INFORMATION, *PNATIVE_MODE_CONTROLLER_INFORMATION; 318 319NATIVE_MODE_CONTROLLER_INFORMATION const NativeModeAdapters[] = { 320 { "10ad", 4, "0105", 4} 321}; 322#define NUM_NATIVE_MODE_ADAPTERS (sizeof(NativeModeAdapters) / sizeof(NATIVE_MODE_CONTROLLER_INFORMATION)) 323 324// 325// Beautification macros 326// 327 328#define GetStatus(BaseIoAddress, Status) \ 329 Status = ScsiPortReadPortUchar(&BaseIoAddress->AlternateStatus); 330 331#define GetBaseStatus(BaseIoAddress, Status) \ 332 Status = ScsiPortReadPortUchar(&BaseIoAddress->Command); 333 334#define WriteCommand(BaseIoAddress, Command) \ 335 ScsiPortWritePortUchar(&BaseIoAddress->Command, Command); 336 337 338 339#define ReadBuffer(BaseIoAddress, Buffer, Count) \ 340 ScsiPortReadPortBufferUshort(&BaseIoAddress->Data, \ 341 Buffer, \ 342 Count); 343 344#define WriteBuffer(BaseIoAddress, Buffer, Count) \ 345 ScsiPortWritePortBufferUshort(&BaseIoAddress->Data, \ 346 Buffer, \ 347 Count); 348 349#define ReadBuffer2(BaseIoAddress, Buffer, Count) \ 350 ScsiPortReadPortBufferUlong(&BaseIoAddress->Data, \ 351 Buffer, \ 352 Count); 353 354#define WriteBuffer2(BaseIoAddress, Buffer, Count) \ 355 ScsiPortWritePortBufferUlong(&BaseIoAddress->Data, \ 356 Buffer, \ 357 Count); 358 359#define WaitOnBusy(BaseIoAddress, Status) \ 360{ \ 361 ULONG i; \ 362 for (i=0; i<20000; i++) { \ 363 GetStatus(BaseIoAddress, Status); \ 364 if (Status & IDE_STATUS_BUSY) { \ 365 ScsiPortStallExecution(150); \ 366 continue; \ 367 } else { \ 368 break; \ 369 } \ 370 } \ 371} 372 373#define WaitOnBaseBusy(BaseIoAddress, Status) \ 374{ \ 375 ULONG i; \ 376 for (i=0; i<20000; i++) { \ 377 GetBaseStatus(BaseIoAddress, Status); \ 378 if (Status & IDE_STATUS_BUSY) { \ 379 ScsiPortStallExecution(150); \ 380 continue; \ 381 } else { \ 382 break; \ 383 } \ 384 } \ 385} 386 387#define WaitForDrq(BaseIoAddress, Status) \ 388{ \ 389 ULONG i; \ 390 for (i=0; i<1000; i++) { \ 391 GetStatus(BaseIoAddress, Status); \ 392 if (Status & IDE_STATUS_BUSY) { \ 393 ScsiPortStallExecution(100); \ 394 } else if (Status & IDE_STATUS_DRQ) { \ 395 break; \ 396 } else { \ 397 ScsiPortStallExecution(200); \ 398 } \ 399 } \ 400} 401 402 403#define WaitShortForDrq(BaseIoAddress, Status) \ 404{ \ 405 ULONG i; \ 406 for (i=0; i<2; i++) { \ 407 GetStatus(BaseIoAddress, Status); \ 408 if (Status & IDE_STATUS_BUSY) { \ 409 ScsiPortStallExecution(100); \ 410 } else if (Status & IDE_STATUS_DRQ) { \ 411 break; \ 412 } else { \ 413 ScsiPortStallExecution(100); \ 414 } \ 415 } \ 416} 417 418#define AtapiSoftReset(BaseIoAddress,DeviceNumber) \ 419{\ 420 UCHAR statusByte; \ 421 ULONG i = 1000*1000;\ 422 ScsiPortWritePortUchar(&BaseIoAddress->DriveSelect,(UCHAR)(((DeviceNumber & 0x1) << 4) | 0xA0)); \ 423 ScsiPortStallExecution(500);\ 424 ScsiPortWritePortUchar(&BaseIoAddress->Command, IDE_COMMAND_ATAPI_RESET); \ 425 while ((ScsiPortReadPortUchar(&BaseIoAddress->Command) & IDE_STATUS_BUSY) && i--)\ 426 ScsiPortStallExecution(30);\ 427 ScsiPortWritePortUchar(&BaseIoAddress->DriveSelect,(UCHAR)((DeviceNumber << 4) | 0xA0)); \ 428 WaitOnBusy( ((PIDE_REGISTERS_2)((PUCHAR)BaseIoAddress + 0x206)), statusByte); \ 429 ScsiPortStallExecution(500);\ 430} 431 432#define IdeHardReset(BaseIoAddress,result) \ 433{\ 434 UCHAR statusByte;\ 435 ULONG i;\ 436 ScsiPortWritePortUchar(&BaseIoAddress->AlternateStatus,IDE_DC_RESET_CONTROLLER );\ 437 ScsiPortStallExecution(50 * 1000);\ 438 ScsiPortWritePortUchar(&BaseIoAddress->AlternateStatus,IDE_DC_REENABLE_CONTROLLER);\ 439 for (i = 0; i < 1000 * 1000; i++) {\ 440 statusByte = ScsiPortReadPortUchar(&BaseIoAddress->AlternateStatus);\ 441 if (statusByte != IDE_STATUS_IDLE && statusByte != 0x0) {\ 442 ScsiPortStallExecution(5);\ 443 } else {\ 444 break;\ 445 }\ 446 }\ 447 if (i == 1000*1000) {\ 448 result = FALSE;\ 449 }\ 450 result = TRUE;\ 451} 452 453#define IS_RDP(OperationCode)\ 454 ((OperationCode == SCSIOP_ERASE)||\ 455 (OperationCode == SCSIOP_LOAD_UNLOAD)||\ 456 (OperationCode == SCSIOP_LOCATE)||\ 457 (OperationCode == SCSIOP_REWIND) ||\ 458 (OperationCode == SCSIOP_SPACE)||\ 459 (OperationCode == SCSIOP_SEEK)||\ 460 (OperationCode == SCSIOP_WRITE_FILEMARKS)) 461