ReactOS 0.4.16-dev-2206-gc56950d
hwidep.h
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Private header for ATA/ATAPI programmed I/O driver.
5 * COPYRIGHT: Copyright 2019-2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8#pragma once
9
10#define TAG_ATA_DEVICE 'dATA'
11
12#define ATA_STATUS_SUCCESS 0
13#define ATA_STATUS_PENDING 1
14#define ATA_STATUS_ERROR 2
15#define ATA_STATUS_RESET 3
16#define ATA_STATUS_RETRY 4
17
18#if defined(SARCH_PC98)
19/* Master/Slave devices for Bank 0 and Bank 1 */
20#define CHANNEL_MAX_DEVICES 4
21#define DEV_SLAVE(DeviceNumber) ((DeviceNumber) & 1)
22#else
23/* Master/Slave devices */
24#define CHANNEL_MAX_DEVICES 2
25#define DEV_SLAVE(DeviceNumber) (DeviceNumber)
26#endif
27
28#if defined(SARCH_XBOX)
29/* It's safe to enable the multiple mode */
30#define ATA_ENABLE_MULTIPLE_MODE
31/* nVidia PCI IDE controllers have a 32-bit data port */
32#define ATA_SUPPORT_32_BIT_IO
33#endif
34
35/* Delay of 400ns */
36#if defined(SARCH_PC98)
37#define ATA_IO_WAIT() WRITE_PORT_UCHAR((PUCHAR)0x5F, 0)
38#else
39#define ATA_IO_WAIT() StallExecutionProcessor(1)
40#endif
41
42#if defined(_M_IX86) || defined(_M_AMD64)
43/* x86 I/O address space spans from 0 to 0xFFFF */
44typedef USHORT IDE_REG;
45#else
47#endif
48
49#define ATA_MAX_LBA_28 0x0FFFFFFFULL
50#define ATA_MAX_LBA_48 (1ULL << 48)
51
52#define IDE_FEATURE_PIO 0x00
53
54#define IDE_DC_ALWAYS 0x08
55
56#define IDE_DRIVE_SELECT 0xA0
57
58#define ATAPI_INT_REASON_COD 0x01
59#define ATAPI_INT_REASON_IO 0x02
60#define ATAPI_INT_REASON_MASK (ATAPI_INT_REASON_IO | ATAPI_INT_REASON_COD)
61
62#define ATAPI_INT_REASON_STATUS_NEC 0x00
63#define ATAPI_INT_REASON_STATUS (ATAPI_INT_REASON_IO | ATAPI_INT_REASON_COD)
64#define ATAPI_INT_REASON_AWAIT_CDB (IDE_STATUS_DRQ | ATAPI_INT_REASON_COD)
65#define ATAPI_INT_REASON_DATA_IN (ATAPI_INT_REASON_IO | IDE_STATUS_DRQ)
66
67#define MAXIMUM_CDROM_SIZE 804 // == sizeof(CDROM_TOC)
68
69#define ATA_TIME_BUSY_SELECT 2000
70#define ATA_TIME_BUSY_POLL 500000
71#define ATA_TIME_BUSY_ENUM 100
72#define ATA_TIME_BUSY_RESET 1000000
73#define ATA_TIME_RESET_SELECT 200000
74#define ATA_TIME_DRQ_CLEAR 1000
75#define ATA_TIME_PHASE_CHANGE 100
76
77/* We keep the value as small as possible, since large timeout can break our error handling */
78#define ATA_TIME_DRQ_ASSERT 15
79
80#define ATA_WRITE(Port, Value) \
81 WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)(Port), (Value))
82
83#define ATA_WRITE_BLOCK_16(Port, Buffer, Count) \
84 WRITE_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)(Port), (PUSHORT)(Buffer), (Count))
85
86#define ATA_WRITE_BLOCK_32(Port, Buffer, Count) \
87 WRITE_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)(Port), (PULONG)(Buffer), (Count))
88
89#define ATA_READ(Port) \
90 READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)(Port))
91
92#define ATA_READ_BLOCK_16(Port, Buffer, Count) \
93 READ_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)(Port), (PUSHORT)(Buffer), (Count))
94
95#define ATA_READ_BLOCK_32(Port, Buffer, Count) \
96 READ_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)(Port), (PULONG)(Buffer), (Count))
97
99{
104
105typedef struct _IDE_REGISTERS
106{
108 union
109 {
112 };
113 union
114 {
117 };
119 union
120 {
124 };
125 union
126 {
130 };
132 union
133 {
136 };
137 union
138 {
141 };
143
144typedef struct _ATA_TASKFILE
145{
148 struct
149 {
155 } Data[2]; // 0 - low part, 1 - high part
157
159{
160 union
161 {
164 };
167#define REQUEST_FLAG_LBA48 0x00000001
168#define REQUEST_FLAG_READ_WRITE_MULTIPLE 0x00000002
169#define REQUEST_FLAG_PACKET_COMMAND 0x00000004
170#define REQUEST_FLAG_SET_DEVICE_REGISTER 0x00000008
171#define REQUEST_FLAG_AWAIT_CDB 0x00000010
172#define REQUEST_FLAG_READ_COMMAND 0x00000020
173#define REQUEST_FLAG_IDENTIFY_COMMAND 0x00000040
174
177
178typedef struct _HW_DEVICE_UNIT
179{
180 /* Public data, must be the first member */
182
192 union
193 {
196 };
198
202 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
203{
204 ULONG i;
205 UCHAR Crc;
206
207 /* Bits 0:8 of word 255 */
208 if (IdentifyData->Signature != 0xA5)
209 {
210 /* The integrity word is missing, assume the data provided by the device is valid */
211 return TRUE;
212 }
213
214 /* Verify the checksum */
215 Crc = 0;
216 for (i = 0; i < sizeof(*IdentifyData); ++i)
217 {
218 Crc += ((PUCHAR)IdentifyData)[i];
219 }
220
221 return (Crc == 0);
222}
223
225UCHAR
227 _In_ PIDENTIFY_PACKET_DATA IdentifyPacketData)
228{
229 /* Bits 0:2 of word 0 */
230 return (IdentifyPacketData->GeneralConfiguration.PacketType != 0) ? 8 : 6;
231}
232
236 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
237{
238 /* Bit 9 of word 49 */
239 return IdentifyData->Capabilities.LbaSupported;
240}
241
243ULONG
245 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
246{
247 /* Words 60-61 */
248 return IdentifyData->UserAddressableSectors;
249}
250
254 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
255{
256 /* Words 100-103 */
257 return ((ULONG64)IdentifyData->Max48BitLBA[1] << 32) | IdentifyData->Max48BitLBA[0];
258}
259
263 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
264{
265 /* Word 83: 15 = 0, 14 = 1 */
266 if (IdentifyData->CommandSetSupport.WordValid83 == 1)
267 {
268 /* Bit 10 of word 83 */
269 return IdentifyData->CommandSetSupport.BigLba;
270 }
271
272 return FALSE;
273}
274
278 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
279{
280 return ((IdentifyData->TranslationFieldsValid & 1) &&
281 (IdentifyData->NumberOfCurrentCylinders != 0) &&
282 (IdentifyData->NumberOfCurrentCylinders <= 63) &&
283 (IdentifyData->NumberOfCurrentHeads != 0) &&
284 (IdentifyData->NumberOfCurrentHeads <= 16) &&
285 (IdentifyData->CurrentSectorsPerTrack != 0));
286}
287
289VOID
291 _In_ PIDENTIFY_DEVICE_DATA IdentifyData,
292 _Out_ PUSHORT Cylinders,
293 _Out_ PUSHORT Heads,
295{
296 /* Word 1 */
297 *Cylinders = IdentifyData->NumCylinders;
298
299 /* Word 3 */
300 *Heads = IdentifyData->NumHeads;
301
302 /* Word 6 */
303 *SectorsPerTrack = IdentifyData->NumSectorsPerTrack;
304}
305
307VOID
309 _In_ PIDENTIFY_DEVICE_DATA IdentifyData,
310 _Out_ PUSHORT Cylinders,
311 _Out_ PUSHORT Heads,
313{
314 /* Word 54 */
315 *Cylinders = IdentifyData->NumberOfCurrentCylinders;
316
317 /* Word 55 */
318 *Heads = IdentifyData->NumberOfCurrentHeads;
319
320 /* Word 55 */
321 *SectorsPerTrack = IdentifyData->CurrentSectorsPerTrack;
322}
323
325UCHAR
327 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
328{
329 UCHAR MultiSectorCurrent;
330
331 /* Bit 8 of word 59 */
332 if (!(IdentifyData->MultiSectorSettingValid))
333 return 0;
334
335 /* The word 59 should be a power of 2 */
336 MultiSectorCurrent = IdentifyData->CurrentMultiSectorSetting;
337
338 if ((MultiSectorCurrent > 0) && ((MultiSectorCurrent & (MultiSectorCurrent - 1)) == 0))
339 return MultiSectorCurrent;
340
341 return 0;
342}
343
345UCHAR
347 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
348{
349 UCHAR MultiSectorMax;
350
351 /* The word 47 should be a power of 2 */
352 MultiSectorMax = IdentifyData->MaximumBlockTransfer;
353
354 if ((MultiSectorMax > 0) && ((MultiSectorMax & (MultiSectorMax - 1)) == 0))
355 return MultiSectorMax;
356
357 return 0;
358}
359
361ULONG
363 _In_ PIDENTIFY_DEVICE_DATA IdentifyData)
364{
365 ULONG WordCount;
366
367 /* Word 106: 15 = 0, 14 = 1, 12 = 1 */
368 if (IdentifyData->PhysicalLogicalSectorSize.Reserved1 == 1 &&
369 IdentifyData->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words)
370 {
371 /* Words 116-117 */
372 WordCount = IdentifyData->WordsPerLogicalSector[0];
373 WordCount |= (ULONG)IdentifyData->WordsPerLogicalSector[1] << 16;
374 }
375 else
376 {
377 /* 256 words = 512 bytes */
378 WordCount = 256;
379 }
380
381 return WordCount * sizeof(USHORT);
382}
383
387 _In_ ULONG64 SectorNumber,
389{
390 /* Use the 48-bit command when reasonable */
391 return (((SectorNumber + SectorCount) >= ATA_MAX_LBA_28) || (SectorCount > 0x100));
392}
unsigned char BOOLEAN
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
FORCEINLINE VOID AtaDevDefaultChsTranslation(_In_ PIDENTIFY_DEVICE_DATA IdentifyData, _Out_ PUSHORT Cylinders, _Out_ PUSHORT Heads, _Out_ PUSHORT SectorsPerTrack)
Definition: hwidep.h:290
struct _IDE_REGISTERS * PIDE_REGISTERS
FORCEINLINE ULONG AtaDevBytesPerLogicalSector(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:362
enum _ATA_DEVICE_CLASS ATA_DEVICE_CLASS
struct _HW_DEVICE_UNIT * PHW_DEVICE_UNIT
FORCEINLINE BOOLEAN AtaDevIsIdentifyDataValid(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:201
struct _IDE_REGISTERS IDE_REGISTERS
FORCEINLINE UCHAR AtaDevCurrentSectorsPerDrq(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:326
FORCEINLINE BOOLEAN AtaCommandUseLba48(_In_ ULONG64 SectorNumber, _In_ ULONG SectorCount)
Definition: hwidep.h:386
FORCEINLINE BOOLEAN AtaDevHas48BitAddressFeature(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:262
_ATA_DEVICE_CLASS
Definition: hwidep.h:99
@ DEV_ATA
Definition: hwidep.h:100
@ DEV_ATAPI
Definition: hwidep.h:101
@ DEV_NONE
Definition: hwidep.h:102
struct _ATA_DEVICE_REQUEST ATA_DEVICE_REQUEST
FORCEINLINE ULONG64 AtaDevUserAddressableSectors48Bit(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:253
enum _ATA_DEVICE_CLASS * PATA_DEVICE_CLASS
FORCEINLINE BOOLEAN AtaDevHasLbaTranslation(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:235
FORCEINLINE ULONG AtaDevUserAddressableSectors28Bit(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:244
FORCEINLINE UCHAR AtaDevMaximumSectorsPerDrq(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:346
#define ATA_MAX_LBA_28
Definition: hwidep.h:49
ULONG_PTR IDE_REG
Definition: hwidep.h:46
FORCEINLINE BOOLEAN AtaDevIsCurrentGeometryValid(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:277
struct _ATA_TASKFILE ATA_TASKFILE
struct _ATA_TASKFILE * PATA_TASKFILE
FORCEINLINE VOID AtaDevCurrentChsTranslation(_In_ PIDENTIFY_DEVICE_DATA IdentifyData, _Out_ PUSHORT Cylinders, _Out_ PUSHORT Heads, _Out_ PUSHORT SectorsPerTrack)
Definition: hwidep.h:308
struct _HW_DEVICE_UNIT HW_DEVICE_UNIT
struct _ATA_DEVICE_REQUEST * PATA_DEVICE_REQUEST
FORCEINLINE UCHAR AtaDevCdbSizeInWords(_In_ PIDENTIFY_PACKET_DATA IdentifyPacketData)
Definition: hwidep.h:226
unsigned __int64 ULONG64
Definition: imports.h:198
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
ULONG SectorCount
Definition: part_xbox.c:31
unsigned short USHORT
Definition: pedump.c:61
ATA_TASKFILE TaskFile
Definition: hwidep.h:163
UCHAR Cdb[16]
Definition: hwidep.h:162
ULONG DataTransferLength
Definition: hwidep.h:175
UCHAR SectorCount
Definition: hwidep.h:151
UCHAR Feature
Definition: hwidep.h:150
UCHAR MidLba
Definition: hwidep.h:153
UCHAR HighLba
Definition: hwidep.h:154
UCHAR Command
Definition: hwidep.h:147
UCHAR DriveSelect
Definition: hwidep.h:146
UCHAR LowLba
Definition: hwidep.h:152
Data structure for the ATA device.
Definition: hwide.h:12
ULONG MaximumTransferLength
Definition: hwidep.h:187
ULONG DrqByteCount
Definition: hwidep.h:186
ULONG BytesToTransfer
Definition: hwidep.h:184
UCHAR DeviceNumber
Definition: hwidep.h:188
UCHAR CdbSize
Definition: hwidep.h:190
UCHAR MultiSectorTransfer
Definition: hwidep.h:191
DEVICE_UNIT P
Definition: hwidep.h:181
UCHAR DeviceSelect
Definition: hwidep.h:189
IDENTIFY_PACKET_DATA IdentifyPacketData
Definition: hwidep.h:195
IDE_REGISTERS Registers
Definition: hwidep.h:183
IDENTIFY_DEVICE_DATA IdentifyDeviceData
Definition: hwidep.h:194
PUCHAR DataBuffer
Definition: hwidep.h:185
IDE_REG Error
Definition: hwidep.h:111
IDE_REG SignatureLow
Definition: hwidep.h:123
IDE_REG Control
Definition: hwidep.h:139
IDE_REG LbaLow
LBA bits 0-7, 24-31.
Definition: hwidep.h:118
IDE_REG LbaMid
LBA bits 8-15, 32-39.
Definition: hwidep.h:121
IDE_REG InterruptReason
Definition: hwidep.h:116
IDE_REG Data
Definition: hwidep.h:107
IDE_REG Command
Definition: hwidep.h:134
IDE_REG SignatureHigh
Definition: hwidep.h:129
IDE_REG Status
Definition: hwidep.h:135
IDE_REG LbaHigh
LBA bits 16-23, 40-47.
Definition: hwidep.h:127
IDE_REG Device
Definition: hwidep.h:131
IDE_REG ByteCountHigh
Definition: hwidep.h:128
IDE_REG AlternateStatus
Definition: hwidep.h:140
IDE_REG SectorCount
Definition: hwidep.h:115
IDE_REG ByteCountLow
Definition: hwidep.h:122
IDE_REG Features
Definition: hwidep.h:110
uint16_t * PUSHORT
Definition: typedefs.h:56
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define FORCEINLINE
Definition: wdftypes.h:67
_In_ ULONG _In_ ULONG SectorsPerTrack
Definition: iofuncs.h:2071
unsigned char UCHAR
Definition: xmlstorage.h:181