← Documents Documentation/userspace-api/ioctl/hdio.rst GitHub 원문 ↗

Linux 6.18.37 · Userspace API

HDIO ioctl 호출 요약

HD/IDE 계층의 지오메트리·식별 정보·I/O 폭 조회와 raw ATA taskfile 명령 ABI를 설명합니다.

Source pathDocumentation/userspace-api/ioctl/hdio.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

hdio.rst:1-547

이 문서는 `<linux/hdreg.h>`의 HD/IDE ioctl 가운데 지오메트리·식별 정보 조회, 16/32비트 I/O 설정, ATA taskfile 직접 실행 인터페이스를 다룹니다.

특히 `HDIO_DRIVE_TASKFILE`, `HDIO_DRIVE_CMD`, `HDIO_DRIVE_TASK`는 raw ATA 레지스터를 직접 다루므로 `CAP_SYS_RAWIO` 같은 높은 권한과 ATA 사양에 대한 정확한 이해가 필요합니다. 잘못 사용하면 데이터 손상이나 시스템 정지가 발생할 수 있습니다.

한국어 전문 번역은 원문 547줄 전체를 연속 구간으로 대조했으며 호출 예제, 구조체·상수·레지스터 이름, 오류 코드, source path와 원문 줄 좌표를 보존합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ==============================
2 Summary of `HDIO_` ioctl calls
3 ==============================
4
5 - Edward A. Falk <efalk@google.com>
6
7 November, 2004
8
9 This document attempts to describe the ioctl(2) calls supported by
10 the HD/IDE layer. These are by-and-large implemented (as of Linux 5.11)
11 drivers/ata/libata-scsi.c.
12
13 ioctl values are listed in <linux/hdreg.h>. As of this writing, they
14 are as follows:
15
16 ioctls that pass argument pointers to user space:
17
18 ======================= =======================================
19 HDIO_GETGEO get device geometry
20 HDIO_GET_32BIT get current io_32bit setting
21 HDIO_GET_IDENTITY get IDE identification info
22 HDIO_DRIVE_TASKFILE execute raw taskfile
23 HDIO_DRIVE_TASK execute task and special drive command
24 HDIO_DRIVE_CMD execute a special drive command
25 ======================= =======================================
26
27 ioctls that pass non-pointer values:
28
29 ======================= =======================================
30 HDIO_SET_32BIT change io_32bit flags
31 ======================= =======================================
32
33
34 The information that follows was determined from reading kernel source
35 code. It is likely that some corrections will be made over time.
36
37 ------------------------------------------------------------------------------
38
39 General:
40
41 Unless otherwise specified, all ioctl calls return 0 on success
42 and -1 with errno set to an appropriate value on error.
43
44 Unless otherwise specified, all ioctl calls return -1 and set
45 errno to EFAULT on a failed attempt to copy data to or from user
46 address space.
47
48 Unless otherwise specified, all data structures and constants
49 are defined in <linux/hdreg.h>
50
51 ------------------------------------------------------------------------------
52
53 HDIO_GETGEO
54 get device geometry
55
56
57 usage::
58
59 struct hd_geometry geom;
60
61 ioctl(fd, HDIO_GETGEO, &geom);
62
63
64 inputs:
65 none
66
67
68
69 outputs:
70 hd_geometry structure containing:
71
72
73 ========= ==================================
74 heads number of heads
75 sectors number of sectors/track
76 cylinders number of cylinders, mod 65536
77 start starting sector of this partition.
78 ========= ==================================
79
80
81 error returns:
82 - EINVAL
83
84 if the device is not a disk drive or floppy drive,
85 or if the user passes a null pointer
86
87
88 notes:
89 Not particularly useful with modern disk drives, whose geometry
90 is a polite fiction anyway. Modern drives are addressed
91 purely by sector number nowadays (lba addressing), and the
92 drive geometry is an abstraction which is actually subject
93 to change. Currently (as of Nov 2004), the geometry values
94 are the "bios" values -- presumably the values the drive had
95 when Linux first booted.
96
97 In addition, the cylinders field of the hd_geometry is an
98 unsigned short, meaning that on most architectures, this
99 ioctl will not return a meaningful value on drives with more
100 than 65535 tracks.
101
102 The start field is unsigned long, meaning that it will not
103 contain a meaningful value for disks over 219 Gb in size.
104
105
106
107 HDIO_GET_IDENTITY
108 get IDE identification info
109
110
111 usage::
112
113 unsigned char identity[512];
114
115 ioctl(fd, HDIO_GET_IDENTITY, identity);
116
117 inputs:
118 none
119
120
121
122 outputs:
123 ATA drive identity information. For full description, see
124 the IDENTIFY DEVICE and IDENTIFY PACKET DEVICE commands in
125 the ATA specification.
126
127 error returns:
128 - EINVAL Called on a partition instead of the whole disk device
129 - ENOMSG IDENTIFY DEVICE information not available
130
131 notes:
132 Returns information that was obtained when the drive was
133 probed. Some of this information is subject to change, and
134 this ioctl does not re-probe the drive to update the
135 information.
136
137 This information is also available from /proc/ide/hdX/identify
138
139
140
141 HDIO_GET_32BIT
142 get current io_32bit setting
143
144
145 usage::
146
147 long val;
148
149 ioctl(fd, HDIO_GET_32BIT, &val);
150
151 inputs:
152 none
153
154
155
156 outputs:
157 The value of the current io_32bit setting
158
159
160
161 notes:
162 0=16-bit, 1=32-bit, 2,3 = 32bit+sync
163
164
165
166 HDIO_DRIVE_TASKFILE
167 execute raw taskfile
168
169
170 Note:
171 If you don't have a copy of the ANSI ATA specification
172 handy, you should probably ignore this ioctl.
173
174 - Execute an ATA disk command directly by writing the "taskfile"
175 registers of the drive. Requires ADMIN and RAWIO access
176 privileges.
177
178 usage::
179
180 struct {
181
182 ide_task_request_t req_task;
183 u8 outbuf[OUTPUT_SIZE];
184 u8 inbuf[INPUT_SIZE];
185 } task;
186 memset(&task.req_task, 0, sizeof(task.req_task));
187 task.req_task.out_size = sizeof(task.outbuf);
188 task.req_task.in_size = sizeof(task.inbuf);
189 ...
190 ioctl(fd, HDIO_DRIVE_TASKFILE, &task);
191 ...
192
193 inputs:
194
195 (See below for details on memory area passed to ioctl.)
196
197 ============ ===================================================
198 io_ports[8] values to be written to taskfile registers
199 hob_ports[8] high-order bytes, for extended commands.
200 out_flags flags indicating which registers are valid
201 in_flags flags indicating which registers should be returned
202 data_phase see below
203 req_cmd command type to be executed
204 out_size size of output buffer
205 outbuf buffer of data to be transmitted to disk
206 inbuf buffer of data to be received from disk (see [1])
207 ============ ===================================================
208
209 outputs:
210
211 =========== ====================================================
212 io_ports[] values returned in the taskfile registers
213 hob_ports[] high-order bytes, for extended commands.
214 out_flags flags indicating which registers are valid (see [2])
215 in_flags flags indicating which registers should be returned
216 outbuf buffer of data to be transmitted to disk (see [1])
217 inbuf buffer of data to be received from disk
218 =========== ====================================================
219
220 error returns:
221 - EACCES CAP_SYS_ADMIN or CAP_SYS_RAWIO privilege not set.
222 - ENOMSG Device is not a disk drive.
223 - ENOMEM Unable to allocate memory for task
224 - EFAULT req_cmd == TASKFILE_IN_OUT (not implemented as of 2.6.8)
225 - EPERM
226
227 req_cmd == TASKFILE_MULTI_OUT and drive
228 multi-count not yet set.
229 - EIO Drive failed the command.
230
231 notes:
232
233 [1] READ THE FOLLOWING NOTES *CAREFULLY*. THIS IOCTL IS
234 FULL OF GOTCHAS. Extreme caution should be used with using
235 this ioctl. A mistake can easily corrupt data or hang the
236 system.
237
238 [2] Both the input and output buffers are copied from the
239 user and written back to the user, even when not used.
240
241 [3] If one or more bits are set in out_flags and in_flags is
242 zero, the following values are used for in_flags.all and
243 written back into in_flags on completion.
244
245 * IDE_TASKFILE_STD_IN_FLAGS | (IDE_HOB_STD_IN_FLAGS << 8)
246 if LBA48 addressing is enabled for the drive
247 * IDE_TASKFILE_STD_IN_FLAGS
248 if CHS/LBA28
249
250 The association between in_flags.all and each enable
251 bitfield flips depending on endianness; fortunately, TASKFILE
252 only uses inflags.b.data bit and ignores all other bits.
253 The end result is that, on any endian machines, it has no
254 effect other than modifying in_flags on completion.
255
256 [4] The default value of SELECT is (0xa0|DEV_bit|LBA_bit)
257 except for four drives per port chipsets. For four drives
258 per port chipsets, it's (0xa0|DEV_bit|LBA_bit) for the first
259 pair and (0x80|DEV_bit|LBA_bit) for the second pair.
260
261 [5] The argument to the ioctl is a pointer to a region of
262 memory containing a ide_task_request_t structure, followed
263 by an optional buffer of data to be transmitted to the
264 drive, followed by an optional buffer to receive data from
265 the drive.
266
267 Command is passed to the disk drive via the ide_task_request_t
268 structure, which contains these fields:
269
270 ============ ===============================================
271 io_ports[8] values for the taskfile registers
272 hob_ports[8] high-order bytes, for extended commands
273 out_flags flags indicating which entries in the
274 io_ports[] and hob_ports[] arrays
275 contain valid values. Type ide_reg_valid_t.
276 in_flags flags indicating which entries in the
277 io_ports[] and hob_ports[] arrays
278 are expected to contain valid values
279 on return.
280 data_phase See below
281 req_cmd Command type, see below
282 out_size output (user->drive) buffer size, bytes
283 in_size input (drive->user) buffer size, bytes
284 ============ ===============================================
285
286 When out_flags is zero, the following registers are loaded.
287
288 ============ ===============================================
289 HOB_FEATURE If the drive supports LBA48
290 HOB_NSECTOR If the drive supports LBA48
291 HOB_SECTOR If the drive supports LBA48
292 HOB_LCYL If the drive supports LBA48
293 HOB_HCYL If the drive supports LBA48
294 FEATURE
295 NSECTOR
296 SECTOR
297 LCYL
298 HCYL
299 SELECT First, masked with 0xE0 if LBA48, 0xEF
300 otherwise; then, or'ed with the default
301 value of SELECT.
302 ============ ===============================================
303
304 If any bit in out_flags is set, the following registers are loaded.
305
306 ============ ===============================================
307 HOB_DATA If out_flags.b.data is set. HOB_DATA will
308 travel on DD8-DD15 on little endian machines
309 and on DD0-DD7 on big endian machines.
310 DATA If out_flags.b.data is set. DATA will
311 travel on DD0-DD7 on little endian machines
312 and on DD8-DD15 on big endian machines.
313 HOB_NSECTOR If out_flags.b.nsector_hob is set
314 HOB_SECTOR If out_flags.b.sector_hob is set
315 HOB_LCYL If out_flags.b.lcyl_hob is set
316 HOB_HCYL If out_flags.b.hcyl_hob is set
317 FEATURE If out_flags.b.feature is set
318 NSECTOR If out_flags.b.nsector is set
319 SECTOR If out_flags.b.sector is set
320 LCYL If out_flags.b.lcyl is set
321 HCYL If out_flags.b.hcyl is set
322 SELECT Or'ed with the default value of SELECT and
323 loaded regardless of out_flags.b.select.
324 ============ ===============================================
325
326 Taskfile registers are read back from the drive into
327 {io|hob}_ports[] after the command completes iff one of the
328 following conditions is met; otherwise, the original values
329 will be written back, unchanged.
330
331 1. The drive fails the command (EIO).
332 2. One or more than one bits are set in out_flags.
333 3. The requested data_phase is TASKFILE_NO_DATA.
334
335 ============ ===============================================
336 HOB_DATA If in_flags.b.data is set. It will contain
337 DD8-DD15 on little endian machines and
338 DD0-DD7 on big endian machines.
339 DATA If in_flags.b.data is set. It will contain
340 DD0-DD7 on little endian machines and
341 DD8-DD15 on big endian machines.
342 HOB_FEATURE If the drive supports LBA48
343 HOB_NSECTOR If the drive supports LBA48
344 HOB_SECTOR If the drive supports LBA48
345 HOB_LCYL If the drive supports LBA48
346 HOB_HCYL If the drive supports LBA48
347 NSECTOR
348 SECTOR
349 LCYL
350 HCYL
351 ============ ===============================================
352
353 The data_phase field describes the data transfer to be
354 performed. Value is one of:
355
356 =================== ========================================
357 TASKFILE_IN
358 TASKFILE_MULTI_IN
359 TASKFILE_OUT
360 TASKFILE_MULTI_OUT
361 TASKFILE_IN_OUT
362 TASKFILE_IN_DMA
363 TASKFILE_IN_DMAQ == IN_DMA (queueing not supported)
364 TASKFILE_OUT_DMA
365 TASKFILE_OUT_DMAQ == OUT_DMA (queueing not supported)
366 TASKFILE_P_IN unimplemented
367 TASKFILE_P_IN_DMA unimplemented
368 TASKFILE_P_IN_DMAQ unimplemented
369 TASKFILE_P_OUT unimplemented
370 TASKFILE_P_OUT_DMA unimplemented
371 TASKFILE_P_OUT_DMAQ unimplemented
372 =================== ========================================
373
374 The req_cmd field classifies the command type. It may be
375 one of:
376
377 ======================== =======================================
378 IDE_DRIVE_TASK_NO_DATA
379 IDE_DRIVE_TASK_SET_XFER unimplemented
380 IDE_DRIVE_TASK_IN
381 IDE_DRIVE_TASK_OUT unimplemented
382 IDE_DRIVE_TASK_RAW_WRITE
383 ======================== =======================================
384
385 [6] Do not access {in|out}_flags->all except for resetting
386 all the bits. Always access individual bit fields. ->all
387 value will flip depending on endianness. For the same
388 reason, do not use IDE_{TASKFILE|HOB}_STD_{OUT|IN}_FLAGS
389 constants defined in hdreg.h.
390
391
392
393 HDIO_DRIVE_CMD
394 execute a special drive command
395
396
397 Note: If you don't have a copy of the ANSI ATA specification
398 handy, you should probably ignore this ioctl.
399
400 usage::
401
402 u8 args[4+XFER_SIZE];
403
404 ...
405 ioctl(fd, HDIO_DRIVE_CMD, args);
406
407 inputs:
408 Commands other than WIN_SMART:
409
410 ======= =======
411 args[0] COMMAND
412 args[1] NSECTOR
413 args[2] FEATURE
414 args[3] NSECTOR
415 ======= =======
416
417 WIN_SMART:
418
419 ======= =======
420 args[0] COMMAND
421 args[1] SECTOR
422 args[2] FEATURE
423 args[3] NSECTOR
424 ======= =======
425
426 outputs:
427 args[] buffer is filled with register values followed by any
428
429
430 data returned by the disk.
431
432 ======== ====================================================
433 args[0] status
434 args[1] error
435 args[2] NSECTOR
436 args[3] undefined
437 args[4+] NSECTOR * 512 bytes of data returned by the command.
438 ======== ====================================================
439
440 error returns:
441 - EACCES Access denied: requires CAP_SYS_RAWIO
442 - ENOMEM Unable to allocate memory for task
443 - EIO Drive reports error
444
445 notes:
446
447 [1] For commands other than WIN_SMART, args[1] should equal
448 args[3]. SECTOR, LCYL and HCYL are undefined. For
449 WIN_SMART, 0x4f and 0xc2 are loaded into LCYL and HCYL
450 respectively. In both cases SELECT will contain the default
451 value for the drive. Please refer to HDIO_DRIVE_TASKFILE
452 notes for the default value of SELECT.
453
454 [2] If NSECTOR value is greater than zero and the drive sets
455 DRQ when interrupting for the command, NSECTOR * 512 bytes
456 are read from the device into the area following NSECTOR.
457 In the above example, the area would be
458 args[4..4+XFER_SIZE]. 16bit PIO is used regardless of
459 HDIO_SET_32BIT setting.
460
461 [3] If COMMAND == WIN_SETFEATURES && FEATURE == SETFEATURES_XFER
462 && NSECTOR >= XFER_SW_DMA_0 && the drive supports any DMA
463 mode, IDE driver will try to tune the transfer mode of the
464 drive accordingly.
465
466
467
468 HDIO_DRIVE_TASK
469 execute task and special drive command
470
471
472 Note: If you don't have a copy of the ANSI ATA specification
473 handy, you should probably ignore this ioctl.
474
475 usage::
476
477 u8 args[7];
478
479 ...
480 ioctl(fd, HDIO_DRIVE_TASK, args);
481
482 inputs:
483 Taskfile register values:
484
485 ======= =======
486 args[0] COMMAND
487 args[1] FEATURE
488 args[2] NSECTOR
489 args[3] SECTOR
490 args[4] LCYL
491 args[5] HCYL
492 args[6] SELECT
493 ======= =======
494
495 outputs:
496 Taskfile register values:
497
498
499 ======= =======
500 args[0] status
501 args[1] error
502 args[2] NSECTOR
503 args[3] SECTOR
504 args[4] LCYL
505 args[5] HCYL
506 args[6] SELECT
507 ======= =======
508
509 error returns:
510 - EACCES Access denied: requires CAP_SYS_RAWIO
511 - ENOMEM Unable to allocate memory for task
512 - ENOMSG Device is not a disk drive.
513 - EIO Drive failed the command.
514
515 notes:
516
517 [1] DEV bit (0x10) of SELECT register is ignored and the
518 appropriate value for the drive is used. All other bits
519 are used unaltered.
520
521
522
523 HDIO_SET_32BIT
524 change io_32bit flags
525
526
527 usage::
528
529 int val;
530
531 ioctl(fd, HDIO_SET_32BIT, val);
532
533 inputs:
534 New value for io_32bit flag
535
536
537
538 outputs:
539 none
540
541
542
543 error return:
544 - EINVAL Called on a partition instead of the whole disk device
545 - EACCES Access denied: requires CAP_SYS_ADMIN
546 - EINVAL value out of range [0 3]
547 - EBUSY Controller busy
548

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

문서 범위와 공통 규칙

1-52

이 문서는 HD/IDE 계층이 지원하는 `ioctl(2)` 호출을 설명합니다. Edward A. Falk가 2004년 11월에 작성했으며, Linux 5.11 기준으로 이 호출의 대부분은 `drivers/ata/libata-scsi.c`에 구현되어 있습니다.

ioctl 값과 별도 언급이 없는 구조체·상수는 `<linux/hdreg.h>`에 정의됩니다. 사용자 공간 포인터를 받는 호출은 `HDIO_GETGEO`, `HDIO_GET_32BIT`, `HDIO_GET_IDENTITY`, `HDIO_DRIVE_TASKFILE`, `HDIO_DRIVE_TASK`, `HDIO_DRIVE_CMD`이고, 포인터가 아닌 값을 받는 호출은 `HDIO_SET_32BIT`입니다.

별도 설명이 없으면 성공 시 0을 반환합니다. 오류 시 -1을 반환하고 `errno`를 적절한 값으로 설정하며, 사용자 주소 공간과 데이터를 복사하는 과정이 실패하면 -1과 `EFAULT`를 반환합니다. 내용은 커널 소스를 읽어 정리한 것이므로 시간이 지나며 교정될 수 있습니다.

HDIO ioctl 인자 형태
항목설명
사용자 포인터HDIO_GETGEO, HDIO_GET_32BIT, HDIO_GET_IDENTITY
사용자 포인터HDIO_DRIVE_TASKFILE, HDIO_DRIVE_TASK, HDIO_DRIVE_CMD
비포인터 값HDIO_SET_32BIT
정의 헤더<linux/hdreg.h>
주요 구현 위치drivers/ata/libata-scsi.c

호출 시 세 번째 인자가 포인터인지 값인지 먼저 구분해야 합니다.

공통 반환 규칙
ioctl 호출성공이면 0실패이면 -1과 errno사용자 메모리 복사 실패이면 EFAULT

개별 ioctl 설명이 공통 규칙을 덮어쓸 수 있습니다.

==============================
Summary of `HDIO_` ioctl calls
==============================

- Edward A. Falk <efalk@google.com>

November, 2004

This document attempts to describe the ioctl(2) calls supported by
the HD/IDE layer.  These are by-and-large implemented (as of Linux 5.11)
drivers/ata/libata-scsi.c.

ioctl values are listed in <linux/hdreg.h>.  As of this writing, they
are as follows:

    ioctls that pass argument pointers to user space:

	=======================	=======================================
	HDIO_GETGEO		get device geometry
	HDIO_GET_32BIT		get current io_32bit setting
	HDIO_GET_IDENTITY	get IDE identification info
	HDIO_DRIVE_TASKFILE	execute raw taskfile
	HDIO_DRIVE_TASK		execute task and special drive command
	HDIO_DRIVE_CMD		execute a special drive command
	=======================	=======================================

    ioctls that pass non-pointer values:

	=======================	=======================================
	HDIO_SET_32BIT		change io_32bit flags
	=======================	=======================================


The information that follows was determined from reading kernel source
code.  It is likely that some corrections will be made over time.

------------------------------------------------------------------------------

General:

	Unless otherwise specified, all ioctl calls return 0 on success
	and -1 with errno set to an appropriate value on error.

	Unless otherwise specified, all ioctl calls return -1 and set
	errno to EFAULT on a failed attempt to copy data to or from user
	address space.

	Unless otherwise specified, all data structures and constants
	are defined in <linux/hdreg.h>

------------------------------------------------------------------------------

HDIO_GETGEO: 장치 지오메트리 조회

53-106

`HDIO_GETGEO`는 디스크 또는 플로피 장치의 지오메트리를 `struct hd_geometry`에 기록합니다. 입력값은 없고 사용법은 다음과 같습니다.

struct hd_geometry geom;

ioctl(fd, HDIO_GETGEO, &geom);
hd_geometry 출력 필드
항목설명
heads헤드 수
sectors트랙당 섹터 수
cylinders실린더 수를 65536으로 나눈 나머지
start이 파티션의 시작 섹터

파티션의 전통적인 CHS 지오메트리와 시작 섹터를 반환합니다.

장치가 디스크나 플로피 드라이브가 아니거나 사용자가 null 포인터를 전달하면 `EINVAL`입니다.

현대 디스크는 LBA 섹터 번호로 접근하므로 이 지오메트리는 실제 물리 형상이라기보다 호환성을 위한 추상화입니다. 2004년 11월 당시 반환값은 Linux 부팅 시 드라이브에 적용된 것으로 추정되는 'BIOS' 값이었습니다.

`cylinders`는 `unsigned short`이므로 대부분의 아키텍처에서 트랙이 65,535개보다 많은 드라이브를 의미 있게 표현하지 못합니다. `start`는 `unsigned long`이므로 219GB를 넘는 디스크에서도 의미 있는 값을 담지 못할 수 있습니다.

HDIO_GETGEO
	get device geometry


	usage::

	  struct hd_geometry geom;

	  ioctl(fd, HDIO_GETGEO, &geom);


	inputs:
		none



	outputs:
		hd_geometry structure containing:


	    =========	==================================
	    heads	number of heads
	    sectors	number of sectors/track
	    cylinders	number of cylinders, mod 65536
	    start	starting sector of this partition.
	    =========	==================================


	error returns:
	  - EINVAL

			if the device is not a disk drive or floppy drive,
			or if the user passes a null pointer


	notes:
		Not particularly useful with modern disk drives, whose geometry
		is a polite fiction anyway.  Modern drives are addressed
		purely by sector number nowadays (lba addressing), and the
		drive geometry is an abstraction which is actually subject
		to change.  Currently (as of Nov 2004), the geometry values
		are the "bios" values -- presumably the values the drive had
		when Linux first booted.

		In addition, the cylinders field of the hd_geometry is an
		unsigned short, meaning that on most architectures, this
		ioctl will not return a meaningful value on drives with more
		than 65535 tracks.

		The start field is unsigned long, meaning that it will not
		contain a meaningful value for disks over 219 Gb in size.


HDIO_GET_IDENTITY: IDE 식별 정보 조회

107-140

`HDIO_GET_IDENTITY`는 IDE 장치 식별 정보 512바이트를 사용자 버퍼에 반환합니다. 자세한 형식은 ATA 사양의 `IDENTIFY DEVICE` 및 `IDENTIFY PACKET DEVICE` 명령 설명을 참조해야 합니다.

unsigned char identity[512];

ioctl(fd, HDIO_GET_IDENTITY, identity);
HDIO_GET_IDENTITY 결과
항목설명
입력없음
출력ATA 식별 정보 512바이트
파티션에서 호출EINVAL
IDENTIFY DEVICE 정보 없음ENOMSG
다른 조회 위치/proc/ide/hdX/identify

전체 디스크 장치에서 탐색 당시 저장된 ATA 식별 정보를 읽습니다.

반환되는 정보는 드라이브 탐색 시 얻은 값입니다. 일부 필드는 이후 바뀔 수 있지만 이 ioctl은 드라이브를 다시 탐색하여 정보를 갱신하지 않습니다.

HDIO_GET_IDENTITY
	get IDE identification info


	usage::

	  unsigned char identity[512];

	  ioctl(fd, HDIO_GET_IDENTITY, identity);

	inputs:
		none



	outputs:
		ATA drive identity information.  For full description, see
		the IDENTIFY DEVICE and IDENTIFY PACKET DEVICE commands in
		the ATA specification.

	error returns:
	  - EINVAL	Called on a partition instead of the whole disk device
	  - ENOMSG	IDENTIFY DEVICE information not available

	notes:
		Returns information that was obtained when the drive was
		probed.  Some of this information is subject to change, and
		this ioctl does not re-probe the drive to update the
		information.

		This information is also available from /proc/ide/hdX/identify


HDIO_GET_32BIT: 현재 I/O 폭 설정 조회

141-165

`HDIO_GET_32BIT`는 현재 `io_32bit` 설정을 `long` 값으로 반환합니다. 입력값은 없습니다.

long val;

ioctl(fd, HDIO_GET_32BIT, &val);
io_32bit 값
항목설명
016비트
132비트
232비트와 동기화
332비트와 동기화

값은 전송 폭과 동기화 사용 여부를 나타냅니다.

HDIO_GET_32BIT
	get current io_32bit setting


	usage::

	  long val;

	  ioctl(fd, HDIO_GET_32BIT, &val);

	inputs:
		none



	outputs:
		The value of the current io_32bit setting



	notes:
		0=16-bit, 1=32-bit, 2,3 = 32bit+sync


HDIO_DRIVE_TASKFILE: 인터페이스와 입출력

166-230

`HDIO_DRIVE_TASKFILE`은 드라이브의 taskfile 레지스터를 직접 기록해 ATA 디스크 명령을 실행합니다. ANSI ATA 사양을 정확히 이해하는 관리 도구를 위한 저수준 인터페이스이며 `CAP_SYS_ADMIN`과 `CAP_SYS_RAWIO` 권한이 필요합니다.

struct {
  ide_task_request_t req_task;
  u8 outbuf[OUTPUT_SIZE];
  u8 inbuf[INPUT_SIZE];
} task;
memset(&task.req_task, 0, sizeof(task.req_task));
task.req_task.out_size = sizeof(task.outbuf);
task.req_task.in_size = sizeof(task.inbuf);
...
ioctl(fd, HDIO_DRIVE_TASKFILE, &task);
TASKFILE 입력
항목설명
io_ports[8]taskfile 레지스터에 쓸 값
hob_ports[8]확장 명령의 상위 바이트
out_flags유효한 출력 레지스터 표시
in_flags반환받을 레지스터 표시
data_phase데이터 전송 단계
req_cmd실행할 명령 유형
out_size / outbuf출력 버퍼 크기와 드라이브로 보낼 데이터
inbuf드라이브에서 받을 데이터

요청 구조체 다음에 선택적인 송신·수신 버퍼가 이어집니다.

TASKFILE 출력
항목설명
io_ports[] / hob_ports[]반환된 taskfile 레지스터와 확장 상위 바이트
out_flags유효 레지스터 플래그, 주석 [2] 참조
in_flags반환할 레지스터 플래그
outbuf송신 데이터 버퍼도 다시 기록됨
inbuf수신 데이터

완료 후 레지스터와 데이터 버퍼가 같은 사용자 메모리에 기록됩니다.

TASKFILE 오류
항목설명
EACCESCAP_SYS_ADMIN 또는 CAP_SYS_RAWIO 없음
ENOMSG장치가 디스크 드라이브가 아님
ENOMEMtask 메모리를 할당할 수 없음
EFAULTreq_cmd가 미구현 TASKFILE_IN_OUT
EPERMTASKFILE_MULTI_OUT인데 drive multi-count가 아직 설정되지 않음
EIO드라이브가 명령 실행에 실패

권한, 장치 유형, 메모리, 명령 상태에 따라 오류가 구분됩니다.

HDIO_DRIVE_TASKFILE
	execute raw taskfile


	Note:
		If you don't have a copy of the ANSI ATA specification
		handy, you should probably ignore this ioctl.

	- Execute an ATA disk command directly by writing the "taskfile"
	  registers of the drive.  Requires ADMIN and RAWIO access
	  privileges.

	usage::

	  struct {

	    ide_task_request_t req_task;
	    u8 outbuf[OUTPUT_SIZE];
	    u8 inbuf[INPUT_SIZE];
	  } task;
	  memset(&task.req_task, 0, sizeof(task.req_task));
	  task.req_task.out_size = sizeof(task.outbuf);
	  task.req_task.in_size = sizeof(task.inbuf);
	  ...
	  ioctl(fd, HDIO_DRIVE_TASKFILE, &task);
	  ...

	inputs:

	  (See below for details on memory area passed to ioctl.)

	  ============	===================================================
	  io_ports[8]	values to be written to taskfile registers
	  hob_ports[8]	high-order bytes, for extended commands.
	  out_flags	flags indicating which registers are valid
	  in_flags	flags indicating which registers should be returned
	  data_phase	see below
	  req_cmd	command type to be executed
	  out_size	size of output buffer
	  outbuf	buffer of data to be transmitted to disk
	  inbuf		buffer of data to be received from disk (see [1])
	  ============	===================================================

	outputs:

	  ===========	====================================================
	  io_ports[]	values returned in the taskfile registers
	  hob_ports[]	high-order bytes, for extended commands.
	  out_flags	flags indicating which registers are valid (see [2])
	  in_flags	flags indicating which registers should be returned
	  outbuf	buffer of data to be transmitted to disk (see [1])
	  inbuf		buffer of data to be received from disk
	  ===========	====================================================

	error returns:
	  - EACCES	CAP_SYS_ADMIN or CAP_SYS_RAWIO privilege not set.
	  - ENOMSG	Device is not a disk drive.
	  - ENOMEM	Unable to allocate memory for task
	  - EFAULT	req_cmd == TASKFILE_IN_OUT (not implemented as of 2.6.8)
	  - EPERM

			req_cmd == TASKFILE_MULTI_OUT and drive
			multi-count not yet set.
	  - EIO		Drive failed the command.

TASKFILE 주의사항, 플래그와 메모리 배치

231-285

이 ioctl은 실수하면 데이터를 손상하거나 시스템을 멈출 수 있으므로 극도로 주의해야 합니다. 입력·출력 버퍼는 실제 사용 여부와 관계없이 모두 사용자 공간에서 복사되어 다시 사용자 공간으로 기록됩니다.

`out_flags`에 하나 이상의 비트가 설정되고 `in_flags`가 0이면, LBA48에서는 `IDE_TASKFILE_STD_IN_FLAGS | (IDE_HOB_STD_IN_FLAGS << 8)`을, CHS/LBA28에서는 `IDE_TASKFILE_STD_IN_FLAGS`를 `in_flags.all`에 사용하고 완료 시 기록합니다.

`in_flags.all`과 개별 enable bitfield의 대응은 endianness에 따라 뒤집힙니다. TASKFILE은 `inflags.b.data`만 사용하고 다른 비트는 무시하므로 실제 효과는 어떤 endian에서도 완료 시 `in_flags`가 바뀌는 것뿐입니다.

`SELECT` 기본값은 `(0xa0|DEV_bit|LBA_bit)`입니다. 포트당 네 드라이브를 지원하는 칩셋에서는 첫 번째 쌍에 이 값을 쓰고 두 번째 쌍에는 `(0x80|DEV_bit|LBA_bit)`를 씁니다.

ioctl 인자는 연속 메모리 영역을 가리킵니다. 먼저 `ide_task_request_t`가 있고, 그 뒤에 선택적인 드라이브 송신 버퍼와 선택적인 드라이브 수신 버퍼가 차례로 옵니다.

ide_task_request_t 필드
항목설명
io_ports[8]taskfile 레지스터 값
hob_ports[8]확장 명령의 상위 바이트
out_flagsio_ports[]/hob_ports[]에서 유효한 입력 항목, ide_reg_valid_t
in_flags반환 시 유효해야 하는 레지스터 항목
data_phase수행할 데이터 전송
req_cmd명령 분류
out_sizeuser에서 drive로 가는 버퍼 크기(바이트)
in_sizedrive에서 user로 가는 버퍼 크기(바이트)

레지스터 유효성, 전송 방향과 버퍼 크기를 함께 기술합니다.

TASKFILE 메모리 배치
ide_task_request_t선택적 user->drive outbuf선택적 drive->user inbuf명령 완료 후 구조체와 버퍼 재기록

세 영역은 하나의 사용자 메모리 블록에 연속 배치됩니다.

	notes:

	  [1] READ THE FOLLOWING NOTES *CAREFULLY*.  THIS IOCTL IS
	  FULL OF GOTCHAS.  Extreme caution should be used with using
	  this ioctl.  A mistake can easily corrupt data or hang the
	  system.

	  [2] Both the input and output buffers are copied from the
	  user and written back to the user, even when not used.

	  [3] If one or more bits are set in out_flags and in_flags is
	  zero, the following values are used for in_flags.all and
	  written back into in_flags on completion.

	   * IDE_TASKFILE_STD_IN_FLAGS | (IDE_HOB_STD_IN_FLAGS << 8)
	     if LBA48 addressing is enabled for the drive
	   * IDE_TASKFILE_STD_IN_FLAGS
	     if CHS/LBA28

	  The association between in_flags.all and each enable
	  bitfield flips depending on endianness; fortunately, TASKFILE
	  only uses inflags.b.data bit and ignores all other bits.
	  The end result is that, on any endian machines, it has no
	  effect other than modifying in_flags on completion.

	  [4] The default value of SELECT is (0xa0|DEV_bit|LBA_bit)
	  except for four drives per port chipsets.  For four drives
	  per port chipsets, it's (0xa0|DEV_bit|LBA_bit) for the first
	  pair and (0x80|DEV_bit|LBA_bit) for the second pair.

	  [5] The argument to the ioctl is a pointer to a region of
	  memory containing a ide_task_request_t structure, followed
	  by an optional buffer of data to be transmitted to the
	  drive, followed by an optional buffer to receive data from
	  the drive.

	  Command is passed to the disk drive via the ide_task_request_t
	  structure, which contains these fields:

	    ============	===============================================
	    io_ports[8]		values for the taskfile registers
	    hob_ports[8]	high-order bytes, for extended commands
	    out_flags		flags indicating which entries in the
				io_ports[] and hob_ports[] arrays
				contain valid values.  Type ide_reg_valid_t.
	    in_flags		flags indicating which entries in the
				io_ports[] and hob_ports[] arrays
				are expected to contain valid values
				on return.
	    data_phase		See below
	    req_cmd		Command type, see below
	    out_size		output (user->drive) buffer size, bytes
	    in_size		input (drive->user) buffer size, bytes
	    ============	===============================================

out_flags가 0일 때 적재되는 레지스터

286-303

`out_flags`가 0이면 표준 taskfile 레지스터를 적재합니다. `HOB_FEATURE`, `HOB_NSECTOR`, `HOB_SECTOR`, `HOB_LCYL`, `HOB_HCYL`은 드라이브가 LBA48을 지원할 때만 적재되고, `FEATURE`, `NSECTOR`, `SECTOR`, `LCYL`, `HCYL`은 항상 대상입니다.

`SELECT`는 먼저 LBA48이면 `0xE0`, 아니면 `0xEF`로 마스킹한 다음 `SELECT` 기본값과 OR하여 적재합니다.

out_flags=0 레지스터
항목설명
HOB_FEATURELBA48 지원 시
HOB_NSECTOR / HOB_SECTORLBA48 지원 시
HOB_LCYL / HOB_HCYLLBA48 지원 시
FEATURE / NSECTOR / SECTOR적재
LCYL / HCYL적재
SELECTLBA48이면 0xE0, 아니면 0xEF로 마스킹 후 기본값과 OR

HOB 계열은 LBA48 지원 여부에 따라 조건부로 사용됩니다.

	  When out_flags is zero, the following registers are loaded.

	    ============	===============================================
	    HOB_FEATURE		If the drive supports LBA48
	    HOB_NSECTOR		If the drive supports LBA48
	    HOB_SECTOR		If the drive supports LBA48
	    HOB_LCYL		If the drive supports LBA48
	    HOB_HCYL		If the drive supports LBA48
	    FEATURE
	    NSECTOR
	    SECTOR
	    LCYL
	    HCYL
	    SELECT		First, masked with 0xE0 if LBA48, 0xEF
				otherwise; then, or'ed with the default
				value of SELECT.
	    ============	===============================================

out_flags 비트가 설정된 경우

304-325

`out_flags`의 비트가 하나라도 설정되면 해당 개별 bitfield가 가리키는 레지스터를 적재합니다. `HOB_DATA`와 `DATA`는 모두 `out_flags.b.data`로 활성화되며, 데이터 버스 바이트 배치는 endianness에 따라 달라집니다.

little-endian에서는 `HOB_DATA`가 DD8-DD15, `DATA`가 DD0-DD7로 이동합니다. big-endian에서는 반대로 `HOB_DATA`가 DD0-DD7, `DATA`가 DD8-DD15로 이동합니다.

`HOB_NSECTOR`, `HOB_SECTOR`, `HOB_LCYL`, `HOB_HCYL`은 각각 `nsector_hob`, `sector_hob`, `lcyl_hob`, `hcyl_hob` 비트에 대응하고, `FEATURE`, `NSECTOR`, `SECTOR`, `LCYL`, `HCYL`도 이름이 같은 비트에 대응합니다. `SELECT`는 `out_flags.b.select`와 무관하게 기본값과 OR하여 항상 적재합니다.

out_flags 비트 대응
항목설명
HOB_DATA / DATAout_flags.b.data; endian에 따라 DD0-DD7과 DD8-DD15 교환
HOB_NSECTORout_flags.b.nsector_hob
HOB_SECTORout_flags.b.sector_hob
HOB_LCYL / HOB_HCYLout_flags.b.lcyl_hob / hcyl_hob
FEATUREout_flags.b.feature
NSECTOR / SECTORout_flags.b.nsector / sector
LCYL / HCYLout_flags.b.lcyl / hcyl
SELECTselect 비트와 무관하게 기본값과 OR하여 적재

레지스터별 enable bit와 예외를 보존합니다.

	  If any bit in out_flags is set, the following registers are loaded.

	    ============	===============================================
	    HOB_DATA		If out_flags.b.data is set.  HOB_DATA will
				travel on DD8-DD15 on little endian machines
				and on DD0-DD7 on big endian machines.
	    DATA		If out_flags.b.data is set.  DATA will
				travel on DD0-DD7 on little endian machines
				and on DD8-DD15 on big endian machines.
	    HOB_NSECTOR		If out_flags.b.nsector_hob is set
	    HOB_SECTOR		If out_flags.b.sector_hob is set
	    HOB_LCYL		If out_flags.b.lcyl_hob is set
	    HOB_HCYL		If out_flags.b.hcyl_hob is set
	    FEATURE		If out_flags.b.feature is set
	    NSECTOR		If out_flags.b.nsector is set
	    SECTOR		If out_flags.b.sector is set
	    LCYL		If out_flags.b.lcyl is set
	    HCYL		If out_flags.b.hcyl is set
	    SELECT		Or'ed with the default value of SELECT and
				loaded regardless of out_flags.b.select.
	    ============	===============================================

명령 완료 후 레지스터 읽기

326-352

명령 완료 후 taskfile 레지스터를 `{io|hob}_ports[]`로 다시 읽는 조건은 세 가지입니다. 드라이브가 `EIO`로 명령에 실패했거나, `out_flags` 비트가 하나 이상 설정되었거나, 요청한 `data_phase`가 `TASKFILE_NO_DATA`여야 합니다. 어느 조건도 충족하지 않으면 원래 값이 바뀌지 않은 채 사용자 공간에 기록됩니다.

`in_flags.b.data`가 설정되면 `HOB_DATA`와 `DATA`를 읽습니다. little-endian에서는 각각 DD8-DD15와 DD0-DD7이고, big-endian에서는 각각 DD0-DD7과 DD8-DD15입니다.

`HOB_FEATURE`, `HOB_NSECTOR`, `HOB_SECTOR`, `HOB_LCYL`, `HOB_HCYL`은 LBA48 지원 시 읽습니다. 일반 `NSECTOR`, `SECTOR`, `LCYL`, `HCYL`도 반환됩니다.

레지스터 readback 조건
항목설명
조건 1드라이브 명령 실패(EIO)
조건 2out_flags 비트가 하나 이상 설정됨
조건 3data_phase == TASKFILE_NO_DATA
HOB_DATA / DATAin_flags.b.data와 endian 배치에 따름
HOB_*LBA48 지원 시
일반 반환NSECTOR, SECTOR, LCYL, HCYL

조건을 만족하지 않으면 요청 구조체의 원래 값이 그대로 돌아옵니다.

TASKFILE readback
ATA 명령 완료EIO·out_flags·NO_DATA 조건 검사조건 불충족이면 원래 값 유지조건 충족이면 in_flags 기준 레지스터 읽기io_ports[]와 hob_ports[] 기록

완료 조건과 플래그를 순서대로 적용합니다.

	  Taskfile registers are read back from the drive into
	  {io|hob}_ports[] after the command completes iff one of the
	  following conditions is met; otherwise, the original values
	  will be written back, unchanged.

	    1. The drive fails the command (EIO).
	    2. One or more than one bits are set in out_flags.
	    3. The requested data_phase is TASKFILE_NO_DATA.

	    ============	===============================================
	    HOB_DATA		If in_flags.b.data is set.  It will contain
				DD8-DD15 on little endian machines and
				DD0-DD7 on big endian machines.
	    DATA		If in_flags.b.data is set.  It will contain
				DD0-DD7 on little endian machines and
				DD8-DD15 on big endian machines.
	    HOB_FEATURE		If the drive supports LBA48
	    HOB_NSECTOR		If the drive supports LBA48
	    HOB_SECTOR		If the drive supports LBA48
	    HOB_LCYL		If the drive supports LBA48
	    HOB_HCYL		If the drive supports LBA48
	    NSECTOR
	    SECTOR
	    LCYL
	    HCYL
	    ============	===============================================

data_phase, req_cmd와 endian 규칙

353-392

`data_phase`는 수행할 데이터 전송을 지정합니다. 입력 계열은 `TASKFILE_IN`, `TASKFILE_MULTI_IN`, `TASKFILE_IN_DMA`이고 출력 계열은 `TASKFILE_OUT`, `TASKFILE_MULTI_OUT`, `TASKFILE_OUT_DMA`입니다. `TASKFILE_IN_OUT`도 값으로 정의되지만 앞선 오류 설명처럼 구현되지 않았습니다.

`TASKFILE_IN_DMAQ`는 `IN_DMA`, `TASKFILE_OUT_DMAQ`는 `OUT_DMA`와 같고 queueing은 지원하지 않습니다. `TASKFILE_P_IN`, `TASKFILE_P_IN_DMA`, `TASKFILE_P_IN_DMAQ`, `TASKFILE_P_OUT`, `TASKFILE_P_OUT_DMA`, `TASKFILE_P_OUT_DMAQ`는 구현되지 않았습니다.

`req_cmd`는 명령 종류를 분류합니다. 가능한 값은 `IDE_DRIVE_TASK_NO_DATA`, `IDE_DRIVE_TASK_SET_XFER`, `IDE_DRIVE_TASK_IN`, `IDE_DRIVE_TASK_OUT`, `IDE_DRIVE_TASK_RAW_WRITE`이며, `SET_XFER`와 `OUT`은 구현되지 않았습니다.

`{in|out}_flags->all`은 모든 비트를 초기화할 때만 접근하고, 평소에는 반드시 개별 bitfield를 사용해야 합니다. `->all` 값은 endianness에 따라 뒤집히므로 `hdreg.h`의 `IDE_{TASKFILE|HOB}_STD_{OUT|IN}_FLAGS` 상수도 사용하지 않아야 합니다.

data_phase 지원 상태
항목설명
TASKFILE_IN / MULTI_IN입력
TASKFILE_OUT / MULTI_OUT출력
TASKFILE_IN_OUT미구현
TASKFILE_IN_DMA / OUT_DMADMA 입력·출력
TASKFILE_IN_DMAQ / OUT_DMAQ각 DMA와 같음, queueing 미지원
TASKFILE_P_IN 계열미구현
TASKFILE_P_OUT 계열미구현

DMAQ는 queueing 없는 DMA 별칭이며 PIO packet 계열은 미구현입니다.

req_cmd 값
항목설명
IDE_DRIVE_TASK_NO_DATA데이터 없음
IDE_DRIVE_TASK_SET_XFER미구현
IDE_DRIVE_TASK_IN입력
IDE_DRIVE_TASK_OUT미구현
IDE_DRIVE_TASK_RAW_WRITEraw write

명령 분류 값과 구현 상태입니다.

	  The data_phase field describes the data transfer to be
	  performed.  Value is one of:

	    ===================        ========================================
	    TASKFILE_IN
	    TASKFILE_MULTI_IN
	    TASKFILE_OUT
	    TASKFILE_MULTI_OUT
	    TASKFILE_IN_OUT
	    TASKFILE_IN_DMA
	    TASKFILE_IN_DMAQ		== IN_DMA (queueing not supported)
	    TASKFILE_OUT_DMA
	    TASKFILE_OUT_DMAQ		== OUT_DMA (queueing not supported)
	    TASKFILE_P_IN		unimplemented
	    TASKFILE_P_IN_DMA		unimplemented
	    TASKFILE_P_IN_DMAQ		unimplemented
	    TASKFILE_P_OUT		unimplemented
	    TASKFILE_P_OUT_DMA		unimplemented
	    TASKFILE_P_OUT_DMAQ		unimplemented
	    ===================        ========================================

	  The req_cmd field classifies the command type.  It may be
	  one of:

	    ========================    =======================================
	    IDE_DRIVE_TASK_NO_DATA
	    IDE_DRIVE_TASK_SET_XFER	unimplemented
	    IDE_DRIVE_TASK_IN
	    IDE_DRIVE_TASK_OUT		unimplemented
	    IDE_DRIVE_TASK_RAW_WRITE
	    ========================    =======================================

	  [6] Do not access {in|out}_flags->all except for resetting
	  all the bits.  Always access individual bit fields.  ->all
	  value will flip depending on endianness.  For the same
	  reason, do not use IDE_{TASKFILE|HOB}_STD_{OUT|IN}_FLAGS
	  constants defined in hdreg.h.


HDIO_DRIVE_CMD: 특수 드라이브 명령

393-467

`HDIO_DRIVE_CMD`는 특수 드라이브 명령을 실행합니다. 이 인터페이스 역시 ANSI ATA 사양을 이해하는 프로그램에서만 사용해야 합니다.

u8 args[4+XFER_SIZE];

...
ioctl(fd, HDIO_DRIVE_CMD, args);

`WIN_SMART`가 아닌 명령에서는 `args[0]`부터 차례로 `COMMAND`, `NSECTOR`, `FEATURE`, `NSECTOR`를 넣습니다. `WIN_SMART`에서는 `args[1]`이 `SECTOR`이고 나머지는 `COMMAND`, `FEATURE`, `NSECTOR`입니다.

출력 버퍼는 레지스터 값 뒤에 디스크가 반환한 데이터를 붙입니다. `args[0]`은 status, `args[1]`은 error, `args[2]`는 NSECTOR, `args[3]`은 정의되지 않은 값이며, `args[4+]`에는 최대 `NSECTOR * 512`바이트가 옵니다.

DRIVE_CMD 오류
항목설명
EACCESCAP_SYS_RAWIO가 없어 접근 거부
ENOMEMtask 메모리를 할당할 수 없음
EIO드라이브가 오류를 보고

raw I/O 권한과 명령 실행 상태를 구분합니다.

`WIN_SMART`가 아닌 명령에서는 `args[1]`과 `args[3]`이 같아야 하며 `SECTOR`, `LCYL`, `HCYL`은 정의되지 않습니다. `WIN_SMART`에서는 `LCYL=0x4f`, `HCYL=0xc2`를 적재합니다. 두 경우 모두 `SELECT`에는 해당 드라이브 기본값이 들어갑니다.

`NSECTOR > 0`이고 드라이브가 명령 인터럽트에서 `DRQ`를 설정하면 장치에서 `NSECTOR * 512`바이트를 읽어 `args[4..4+XFER_SIZE]`에 둡니다. `HDIO_SET_32BIT` 설정과 무관하게 16비트 PIO를 사용합니다.

`COMMAND == WIN_SETFEATURES`, `FEATURE == SETFEATURES_XFER`, `NSECTOR >= XFER_SW_DMA_0`이고 드라이브가 DMA 모드를 지원하면 IDE 드라이버가 그에 맞게 전송 모드를 조정하려고 시도합니다.

HDIO_DRIVE_CMD 버퍼
args[0..3] 명령 레지스터 설정WIN_SMART 여부에 따라 args[1] 의미 선택CAP_SYS_RAWIO 확인명령 실행status·error·NSECTOR 반환DRQ이면 args[4+]에 NSECTOR*512바이트 수신

명령 종류에 따라 입력 레지스터 배치를 정하고 반환 데이터 길이를 검증합니다.

HDIO_DRIVE_CMD
	execute a special drive command


	Note:  If you don't have a copy of the ANSI ATA specification
	handy, you should probably ignore this ioctl.

	usage::

	  u8 args[4+XFER_SIZE];

	  ...
	  ioctl(fd, HDIO_DRIVE_CMD, args);

	inputs:
	    Commands other than WIN_SMART:

	    =======     =======
	    args[0]	COMMAND
	    args[1]	NSECTOR
	    args[2]	FEATURE
	    args[3]	NSECTOR
	    =======     =======

	    WIN_SMART:

	    =======     =======
	    args[0]	COMMAND
	    args[1]	SECTOR
	    args[2]	FEATURE
	    args[3]	NSECTOR
	    =======     =======

	outputs:
		args[] buffer is filled with register values followed by any


	  data returned by the disk.

	    ========	====================================================
	    args[0]	status
	    args[1]	error
	    args[2]	NSECTOR
	    args[3]	undefined
	    args[4+]	NSECTOR * 512 bytes of data returned by the command.
	    ========	====================================================

	error returns:
	  - EACCES	Access denied:  requires CAP_SYS_RAWIO
	  - ENOMEM	Unable to allocate memory for task
	  - EIO		Drive reports error

	notes:

	  [1] For commands other than WIN_SMART, args[1] should equal
	  args[3].  SECTOR, LCYL and HCYL are undefined.  For
	  WIN_SMART, 0x4f and 0xc2 are loaded into LCYL and HCYL
	  respectively.  In both cases SELECT will contain the default
	  value for the drive.  Please refer to HDIO_DRIVE_TASKFILE
	  notes for the default value of SELECT.

	  [2] If NSECTOR value is greater than zero and the drive sets
	  DRQ when interrupting for the command, NSECTOR * 512 bytes
	  are read from the device into the area following NSECTOR.
	  In the above example, the area would be
	  args[4..4+XFER_SIZE].  16bit PIO is used regardless of
	  HDIO_SET_32BIT setting.

	  [3] If COMMAND == WIN_SETFEATURES && FEATURE == SETFEATURES_XFER
	  && NSECTOR >= XFER_SW_DMA_0 && the drive supports any DMA
	  mode, IDE driver will try to tune the transfer mode of the
	  drive accordingly.


HDIO_DRIVE_TASK: task 및 특수 명령

468-522

`HDIO_DRIVE_TASK`는 7바이트 배열로 taskfile 레지스터를 직접 전달해 task 또는 특수 드라이브 명령을 실행합니다. ATA 사양을 정확히 아는 프로그램을 위한 인터페이스입니다.

u8 args[7];

...
ioctl(fd, HDIO_DRIVE_TASK, args);
DRIVE_TASK 입출력
항목설명
args[0]입력 COMMAND / 출력 status
args[1]입력 FEATURE / 출력 error
args[2]입출력 NSECTOR
args[3]입출력 SECTOR
args[4]입출력 LCYL
args[5]입출력 HCYL
args[6]입출력 SELECT

같은 배열이 명령 레지스터 입력과 완료 레지스터 출력에 사용됩니다.

DRIVE_TASK 오류
항목설명
EACCESCAP_SYS_RAWIO 없음
ENOMEMtask 메모리 할당 실패
ENOMSG장치가 디스크 드라이브가 아님
EIO드라이브가 명령에 실패

권한, 메모리, 장치 유형과 명령 실패를 구분합니다.

`SELECT` 레지스터의 DEV 비트 `0x10`은 무시되고 커널이 해당 드라이브에 맞는 값을 사용합니다. 나머지 비트는 변경하지 않고 그대로 사용합니다.

HDIO_DRIVE_TASK
	execute task and special drive command


	Note:  If you don't have a copy of the ANSI ATA specification
	handy, you should probably ignore this ioctl.

	usage::

	  u8 args[7];

	  ...
	  ioctl(fd, HDIO_DRIVE_TASK, args);

	inputs:
	    Taskfile register values:

	    =======	=======
	    args[0]	COMMAND
	    args[1]	FEATURE
	    args[2]	NSECTOR
	    args[3]	SECTOR
	    args[4]	LCYL
	    args[5]	HCYL
	    args[6]	SELECT
	    =======	=======

	outputs:
	    Taskfile register values:


	    =======	=======
	    args[0]	status
	    args[1]	error
	    args[2]	NSECTOR
	    args[3]	SECTOR
	    args[4]	LCYL
	    args[5]	HCYL
	    args[6]	SELECT
	    =======	=======

	error returns:
	  - EACCES	Access denied:  requires CAP_SYS_RAWIO
	  - ENOMEM	Unable to allocate memory for task
	  - ENOMSG	Device is not a disk drive.
	  - EIO		Drive failed the command.

	notes:

	  [1] DEV bit (0x10) of SELECT register is ignored and the
	  appropriate value for the drive is used.  All other bits
	  are used unaltered.


HDIO_SET_32BIT: I/O 폭 플래그 변경

523-547

`HDIO_SET_32BIT`는 포인터가 아니라 정수 값을 직접 전달해 `io_32bit` 플래그를 바꿉니다. 출력 데이터는 없습니다.

int val;

ioctl(fd, HDIO_SET_32BIT, val);
HDIO_SET_32BIT 오류
항목설명
EINVAL전체 디스크가 아닌 파티션에서 호출
EACCESCAP_SYS_ADMIN 없음
EINVAL값이 [0, 3] 범위를 벗어남
EBUSY컨트롤러가 사용 중

전체 디스크, 관리자 권한, 값 범위와 컨트롤러 상태를 확인합니다.

32비트 I/O 설정
전체 디스크 fd 확인CAP_SYS_ADMIN 확인val 범위 0..3 확인컨트롤러 busy 여부 확인io_32bit 플래그 변경

값은 앞서 설명한 0~3 범위여야 합니다.

HDIO_SET_32BIT
	change io_32bit flags


	usage::

	  int val;

	  ioctl(fd, HDIO_SET_32BIT, val);

	inputs:
		New value for io_32bit flag



	outputs:
		none



	error return:
	  - EINVAL	Called on a partition instead of the whole disk device
	  - EACCES	Access denied:  requires CAP_SYS_ADMIN
	  - EINVAL	value out of range [0 3]
	  - EBUSY	Controller busy