From: Tejun Heo This patch updates Documentation/ioctl/hdio.txt. I'm gonna use this documentation as reference for future changes, so I tried to include all the specifics. Signed-off-by: Tejun Heo Signed-off-by: Andrew Morton --- 25-akpm/Documentation/ioctl/hdio.txt | 167 +++++++++++++++++++++++++++-------- 1 files changed, 130 insertions(+), 37 deletions(-) diff -puN Documentation/ioctl/hdio.txt~ide-hdiotxt-update Documentation/ioctl/hdio.txt --- 25/Documentation/ioctl/hdio.txt~ide-hdiotxt-update 2005-03-02 20:20:14.000000000 -0800 +++ 25-akpm/Documentation/ioctl/hdio.txt 2005-03-02 20:20:14.000000000 -0800 @@ -573,26 +573,31 @@ HDIO_DRIVE_TASKFILE execute raw taskfil 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. notes: - [1] Currently (2.6.8), both the input and output buffers are - copied from the user and written back to the user, even when - not used. This may be a bug. - - [2] The out_flags and in_flags are returned to the user after - the ioctl completes. Currently (2.6.8) these are the same - as the input values, unchanged. In the future, they may have - more significance. - - Extreme caution should be used with using this ioctl. A - mistake can easily corrupt data or hang the system. - - 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. + [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. The + out_flags and in_flags are written back to the user after + the ioctl completes. These are the same as the input + values, unchanged. + + [3] 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. + + [4] 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: @@ -611,11 +616,66 @@ HDIO_DRIVE_TASKFILE execute raw taskfil out_size output (user->drive) buffer size, bytes in_size input (drive->user) buffer size, bytes - This ioctl does not necessarily respect all flags in the - out_flags and in_flags values -- some taskfile registers - may be written or read even if not requested in the flags. - Unused fields of io_ports[] and hob_ports[] should be set - to zero. + 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. + + If any bit in out_flags is set, the following registers are loaded. + + HOB_DATA If tf_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 tf_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 tf_out_flags.b.nsector_hob is set + HOB_SECTOR If tf_out_flags.b.sector_hob is set + HOB_LCYL If tf_out_flags.b.lcyl_hob is set + HOB_HCYL If tf_out_flags.b.hcyl_hob is set + FEATURE If tf_out_flags.b.feature is set + NSECTOR If tf_out_flags.b.nsector is set + SECTOR If tf_out_flags.b.sector is set + LCYL If tf_out_flags.b.lcyl is set + HCYL If tf_out_flags.b.hcyl is set + SELECT Or'ed with the default value of SELECT and + loaded regardless of tf_out_flags.b.select. + + 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. More than one bit is set in tf_out_flags. + 3. The requested data_phase is TASKFILE_NO_DATA. + + HOB_DATA If tf_in_flags.b.data is set. It will + contain DD8-DD15 on little endian machines + and DD0-DD7 on big endian machines. + DATA If tf_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 The data_phase field describes the data transfer to be performed. Value is one of: @@ -626,27 +686,30 @@ HDIO_DRIVE_TASKFILE execute raw taskfil TASKFILE_MULTI_OUT TASKFILE_IN_OUT TASKFILE_IN_DMA - TASKFILE_IN_DMAQ + TASKFILE_IN_DMAQ == IN_DMA (queueing not supported) TASKFILE_OUT_DMA - TASKFILE_OUT_DMAQ - TASKFILE_P_IN - TASKFILE_P_IN_DMA - TASKFILE_P_IN_DMAQ - TASKFILE_P_OUT - TASKFILE_P_OUT_DMA - TASKFILE_P_OUT_DMAQ + 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 + IDE_DRIVE_TASK_SET_XFER unimplemented IDE_DRIVE_TASK_IN - IDE_DRIVE_TASK_OUT + IDE_DRIVE_TASK_OUT unimplemented IDE_DRIVE_TASK_RAW_WRITE - - + [5] Do not access {in|out}_flags->all except for resetting + all the bits. Always access individual bit fields. ->all + value will flip depending on endianess. For the same + reason, do not use IDE_{TASKFILE|HOB}_STD_{OUT|IN}_FLAGS + constants defined in hdreg.h. @@ -663,7 +726,13 @@ HDIO_DRIVE_CMD execute a special drive inputs: - Taskfile register values: + 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 @@ -682,11 +751,28 @@ HDIO_DRIVE_CMD execute a special drive error returns: EACCES Access denied: requires CAP_SYS_RAWIO ENOMEM Unable to allocate memory for task + EIO Drive reports error notes: - Taskfile registers IDE_LCYL, IDE_HCYL, and IDE_SELECT are - set to zero before executing the command. + [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. @@ -726,7 +812,14 @@ HDIO_DRIVE_TASK execute task and speci 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. _