[CMAKE]
[reactos.git] / drivers / storage / ide / atapi / atapi.h
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
16 typedef 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
26 typedef struct _IDE_REGISTERS_2 {
27 UCHAR AlternateStatus;
28 UCHAR DriveAddress;
29 } IDE_REGISTERS_2, *PIDE_REGISTERS_2;
30
31 typedef 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
69 typedef 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
80 typedef 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
91 typedef 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
166 typedef 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
176 typedef 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
192 typedef 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
248 typedef 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
298 typedef struct _BROKEN_CONTROLLER_INFORMATION {
299 PCHAR VendorId;
300 ULONG VendorIdLength;
301 PCHAR DeviceId;
302 ULONG DeviceIdLength;
303 }BROKEN_CONTROLLER_INFORMATION, *PBROKEN_CONTROLLER_INFORMATION;
304
305 BROKEN_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
312 typedef 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
319 NATIVE_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