aboutsummaryrefslogtreecommitdiff
path: root/drivers/ide/ide-taskfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-taskfile.c')
-rw-r--r--drivers/ide/ide-taskfile.c63
1 files changed, 31 insertions, 32 deletions
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index a1796cf5835..5eb6fa15dc4 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -750,31 +750,11 @@ abort:
}
#endif
-static int ide_wait_cmd(ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature,
- u8 sectors, u8 *buf)
-{
- struct request rq;
- u8 buffer[4];
-
- if (!buf)
- buf = buffer;
- memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
- ide_init_drive_cmd(&rq);
- rq.cmd_type = REQ_TYPE_ATA_CMD;
- rq.buffer = buf;
- *buf++ = cmd;
- *buf++ = nsect;
- *buf++ = feature;
- *buf++ = sectors;
- return ide_do_drive_cmd(drive, &rq, ide_wait);
-}
-
int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
{
- int err = 0;
- u8 args[4], *argbuf = args;
- u8 xfer_rate = 0;
- int argsize = 4;
+ u8 *buf = NULL;
+ int bufsize = 0, err = 0;
+ u8 args[4], xfer_rate = 0;
ide_task_t tfargs;
struct ide_taskfile *tf = &tfargs.tf;
@@ -792,23 +772,39 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
memset(&tfargs, 0, sizeof(ide_task_t));
tf->feature = args[2];
- tf->nsect = args[3];
- tf->lbal = args[1];
+ if (args[0] == WIN_SMART) {
+ tf->nsect = args[3];
+ tf->lbal = args[1];
+ tf->lbam = 0x4f;
+ tf->lbah = 0xc2;
+ tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
+ } else {
+ tf->nsect = args[1];
+ tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
+ IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
+ }
tf->command = args[0];
+ tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
if (args[3]) {
- argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
- argbuf = kzalloc(argsize, GFP_KERNEL);
- if (argbuf == NULL)
+ tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
+ bufsize = SECTOR_WORDS * 4 * args[3];
+ buf = kzalloc(bufsize, GFP_KERNEL);
+ if (buf == NULL)
return -ENOMEM;
}
+
if (set_transfer(drive, &tfargs)) {
xfer_rate = args[1];
if (ide_ata66_check(drive, &tfargs))
goto abort;
}
- err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
+ err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
+
+ args[0] = tf->status;
+ args[1] = tf->error;
+ args[2] = tf->nsect;
if (!err && xfer_rate) {
/* active-retuning-calls future */
@@ -816,10 +812,13 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
ide_driveid_update(drive);
}
abort:
- if (copy_to_user((void __user *)arg, argbuf, argsize))
+ if (copy_to_user((void __user *)arg, &args, 4))
err = -EFAULT;
- if (argsize > 4)
- kfree(argbuf);
+ if (buf) {
+ if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
+ err = -EFAULT;
+ kfree(buf);
+ }
return err;
}