Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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 |
Christoph Hellwig | b7fb14d3 | 2021-06-16 15:46:58 +0200 | [diff] [blame] | 10 | the HD/IDE layer. These are by-and-large implemented (as of Linux 5.11) |
| 11 | drivers/ata/libata-scsi.c. |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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 |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 20 | HDIO_GET_32BIT get current io_32bit setting |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 21 | HDIO_GET_IDENTITY get IDE identification info |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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 |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 25 | ======================= ======================================= |
| 26 | |
| 27 | ioctls that pass non-pointer values: |
| 28 | |
| 29 | ======================= ======================================= |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 30 | HDIO_SET_32BIT change io_32bit flags |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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 | |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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: |
Christoph Hellwig | 250eec9 | 2020-09-03 07:40:56 +0200 | [diff] [blame] | 128 | - EINVAL Called on a partition instead of the whole disk device |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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 | |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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 | |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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 | |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 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: |
Christoph Hellwig | 250eec9 | 2020-09-03 07:40:56 +0200 | [diff] [blame] | 544 | - EINVAL Called on a partition instead of the whole disk device |
Mauro Carvalho Chehab | 5c04dce | 2019-04-18 11:38:26 -0300 | [diff] [blame] | 545 | - EACCES Access denied: requires CAP_SYS_ADMIN |
| 546 | - EINVAL value out of range [0 3] |
| 547 | - EBUSY Controller busy |