Commit 76d04538 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.19 IDE 80

 - Sanitize the handling of the ioctl's and fix a bug on the way in dealing with
   the WIN_SMART command where arguments where exchanged.

 - Finally sanitize ioctl further until it turned out that we could get rid of
   the special request type REQ_DRIVE_CMD entierly. We are now using
   consistently REQ_DRIVE_ACB.

   One hidden code path less again!

 - Realize the ide_end_drive_cmd can be on the REQ_DRIVE_ACB only for ioctl() to
   a disk. Eliminate it's usage from device type driver modules.

 - Remove command member from struct  hd_drive_task_hdr and place it in strcut
   ata_taskfile. It is not common between the normal register file and HOB.

   We will have to introduce some helper functions for particular command types.
parent b6e6f175
......@@ -490,11 +490,21 @@ void blk_queue_invalidate_tags(request_queue_t *q)
}
}
static char *rq_flags[] = { "REQ_RW", "REQ_RW_AHEAD", "REQ_BARRIER",
"REQ_CMD", "REQ_NOMERGE", "REQ_STARTED",
"REQ_DONTPREP", "REQ_QUEUED", "REQ_DRIVE_CMD",
"REQ_DRIVE_ACB", "REQ_PC", "REQ_BLOCK_PC",
"REQ_SENSE", "REQ_SPECIAL" };
static char *rq_flags[] = {
"REQ_RW",
"REQ_RW_AHEAD",
"REQ_BARRIER",
"REQ_CMD",
"REQ_NOMERGE",
"REQ_STARTED",
"REQ_DONTPREP",
"REQ_QUEUED",
"REQ_DRIVE_ACB",
"REQ_PC",
"REQ_BLOCK_PC",
"REQ_SENSE",
"REQ_SPECIAL"
};
void blk_dump_rq_flags(struct request *rq, char *msg)
{
......
......@@ -170,7 +170,7 @@ static ide_startstop_t chs_do_request(struct ata_device *drive, struct request *
args.taskfile.device_head = head;
args.taskfile.device_head |= drive->select.all;
args.taskfile.command = get_command(drive, rq_data_dir(rq));
args.cmd = get_command(drive, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
......@@ -211,7 +211,7 @@ static ide_startstop_t lba28_do_request(struct ata_device *drive, struct request
args.taskfile.device_head = ((block >> 8) & 0x0f);
args.taskfile.device_head |= drive->select.all;
args.taskfile.command = get_command(drive, rq_data_dir(rq));
args.cmd = get_command(drive, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
......@@ -264,7 +264,7 @@ static ide_startstop_t lba48_do_request(struct ata_device *drive, struct request
args.hobfile.high_cylinder = (block >>= 8); /* hi lba */
args.hobfile.device_head = drive->select.all;
args.taskfile.command = get_command(drive, rq_data_dir(rq));
args.cmd = get_command(drive, rq_data_dir(rq));
#ifdef DEBUG
printk("%s: %sing: ", drive->name,
......@@ -355,7 +355,7 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi
memset(&args, 0, sizeof(args));
args.taskfile.command = WIN_DOORLOCK;
args.cmd = WIN_DOORLOCK;
ide_cmd_type_parser(&args);
/*
......@@ -377,9 +377,9 @@ static int idedisk_flushcache(struct ata_device *drive)
memset(&args, 0, sizeof(args));
if (drive->id->cfs_enable_2 & 0x2400)
args.taskfile.command = WIN_FLUSH_CACHE_EXT;
args.cmd = WIN_FLUSH_CACHE_EXT;
else
args.taskfile.command = WIN_FLUSH_CACHE;
args.cmd = WIN_FLUSH_CACHE;
ide_cmd_type_parser(&args);
......@@ -395,7 +395,7 @@ static void idedisk_release(struct inode *inode, struct file *filp, struct ata_d
invalidate_bdev(inode->i_bdev, 0);
memset(&args, 0, sizeof(args));
args.taskfile.command = WIN_DOORUNLOCK;
args.cmd = WIN_DOORUNLOCK;
ide_cmd_type_parser(&args);
if (drive->doorlocking &&
......@@ -444,7 +444,7 @@ static int set_multcount(struct ata_device *drive, int arg)
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = arg;
args.taskfile.command = WIN_SETMULT;
args.cmd = WIN_SETMULT;
ide_cmd_type_parser(&args);
if (!ide_raw_taskfile(drive, &args)) {
......@@ -475,7 +475,7 @@ static int write_cache(struct ata_device *drive, int arg)
memset(&args, 0, sizeof(args));
args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
args.taskfile.command = WIN_SETFEATURES;
args.cmd = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
ide_raw_taskfile(drive, &args);
......@@ -489,7 +489,7 @@ static int idedisk_standby(struct ata_device *drive)
struct ata_taskfile args;
memset(&args, 0, sizeof(args));
args.taskfile.command = WIN_STANDBYNOW1;
args.cmd = WIN_STANDBYNOW1;
ide_cmd_type_parser(&args);
return ide_raw_taskfile(drive, &args);
......@@ -502,7 +502,7 @@ static int set_acoustic(struct ata_device *drive, int arg)
memset(&args, 0, sizeof(args));
args.taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM;
args.taskfile.sector_count = arg;
args.taskfile.command = WIN_SETFEATURES;
args.cmd = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
ide_raw_taskfile(drive, &args);
......@@ -622,14 +622,14 @@ static unsigned long native_max_address(struct ata_device *drive)
/* Create IDE/ATA command request structure */
memset(&args, 0, sizeof(args));
args.taskfile.device_head = 0x40;
args.taskfile.command = WIN_READ_NATIVE_MAX;
args.cmd = WIN_READ_NATIVE_MAX;
args.handler = task_no_data_intr;
/* submit command request */
ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */
if ((args.taskfile.command & 0x01) == 0) {
if ((args.cmd & 0x01) == 0) {
addr = ((args.taskfile.device_head & 0x0f) << 24)
| (args.taskfile.high_cylinder << 16)
| (args.taskfile.low_cylinder << 8)
......@@ -650,14 +650,14 @@ static u64 native_max_address_ext(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.device_head = 0x40;
args.taskfile.command = WIN_READ_NATIVE_MAX_EXT;
args.cmd = WIN_READ_NATIVE_MAX_EXT;
args.handler = task_no_data_intr;
/* submit command request */
ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */
if ((args.taskfile.command & 0x01) == 0) {
if ((args.cmd & 0x01) == 0) {
u32 high = (args.hobfile.high_cylinder << 16) |
(args.hobfile.low_cylinder << 8) |
args.hobfile.sector_number;
......@@ -691,12 +691,12 @@ static sector_t set_max_address(struct ata_device *drive, sector_t addr_req)
args.taskfile.high_cylinder = (addr_req >> 16);
args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40;
args.taskfile.command = WIN_SET_MAX;
args.cmd = WIN_SET_MAX;
args.handler = task_no_data_intr;
/* submit command request */
ide_raw_taskfile(drive, &args);
/* if OK, read new maximum address value */
if ((args.taskfile.command & 0x01) == 0) {
if ((args.cmd & 0x01) == 0) {
addr_set = ((args.taskfile.device_head & 0x0f) << 24)
| (args.taskfile.high_cylinder << 16)
| (args.taskfile.low_cylinder << 8)
......@@ -719,7 +719,7 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req)
args.taskfile.low_cylinder = (addr_req >>= 8);
args.taskfile.high_cylinder = (addr_req >>= 8);
args.taskfile.device_head = 0x40;
args.taskfile.command = WIN_SET_MAX_EXT;
args.cmd = WIN_SET_MAX_EXT;
args.hobfile.sector_number = (addr_req >>= 8);
args.hobfile.low_cylinder = (addr_req >>= 8);
......@@ -731,7 +731,7 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req)
/* submit command request */
ide_raw_taskfile(drive, &args);
/* if OK, compute maximum address value */
if ((args.taskfile.command & 0x01) == 0) {
if ((args.cmd & 0x01) == 0) {
u32 high = (args.hobfile.high_cylinder << 16) |
(args.hobfile.low_cylinder << 8) |
args.hobfile.sector_number;
......
......@@ -620,7 +620,7 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i
#if IDEFLOPPY_DEBUG_LOG
printk (KERN_INFO "Reached idefloppy_end_request\n");
#endif /* IDEFLOPPY_DEBUG_LOG */
#endif
switch (uptodate) {
case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
......@@ -632,12 +632,16 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i
/* Why does this happen? */
if (!rq)
return 0;
if (!(rq->flags & IDEFLOPPY_RQ)) {
ide_end_request(drive, rq, uptodate);
return 0;
}
rq->errors = error;
ide_end_drive_cmd (drive, rq, 0);
blkdev_dequeue_request(rq);
drive->rq = NULL;
end_that_request_last(rq);
return 0;
}
......
......@@ -1864,9 +1864,12 @@ static int idetape_end_request(struct ata_device *drive, struct request *rq, int
idetape_increase_max_pipeline_stages (drive);
}
}
ide_end_drive_cmd(drive, rq, 0);
blkdev_dequeue_request(rq);
drive->rq = NULL;
end_that_request_last(rq);
if (remove_stage)
idetape_remove_stage_head (drive);
idetape_remove_stage_head(drive);
if (tape->active_data_request == NULL)
clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
spin_unlock_irqrestore(&tape->spinlock, flags);
......
......@@ -311,34 +311,34 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
}
ide_startstop_t ata_taskfile(struct ata_device *drive,
struct ata_taskfile *args, struct request *rq)
struct ata_taskfile *ar, struct request *rq)
{
struct hd_driveid *id = drive->id;
/* (ks/hs): Moved to start, do not use for multiple out commands */
if (args->handler != task_mulout_intr) {
if (ar->handler != task_mulout_intr) {
ata_irq_enable(drive, 1);
ata_mask(drive);
}
if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) &&
(drive->addressing == 1))
ata_out_regfile(drive, &args->hobfile);
ata_out_regfile(drive, &ar->hobfile);
ata_out_regfile(drive, &args->taskfile);
ata_out_regfile(drive, &ar->taskfile);
{
u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF;
OUT_BYTE((args->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
OUT_BYTE((ar->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
}
if (args->handler != NULL) {
if (ar->handler != NULL) {
/* This is apparently supposed to reset the wait timeout for
* the interrupt to accur.
*/
ide_set_handler(drive, args->handler, WAIT_CMD, NULL);
OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
ide_set_handler(drive, ar->handler, WAIT_CMD, NULL);
OUT_BYTE(ar->cmd, IDE_COMMAND_REG);
/*
* Warning check for race between handler and prehandler for
......@@ -346,8 +346,8 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
* inside the boundaries of the seek, we should be okay.
*/
if (args->prehandler != NULL)
return args->prehandler(drive, rq);
if (ar->prehandler != NULL)
return ar->prehandler(drive, rq);
} else {
/*
* FIXME: this is a gross hack, need to unify tcq dma proc and
......@@ -358,21 +358,20 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
return ide_started;
/* for dma commands we don't set the handler */
if (args->taskfile.command == WIN_WRITEDMA
|| args->taskfile.command == WIN_WRITEDMA_EXT)
if (ar->cmd == WIN_WRITEDMA || ar->cmd == WIN_WRITEDMA_EXT)
return !udma_write(drive, rq);
else if (args->taskfile.command == WIN_READDMA
|| args->taskfile.command == WIN_READDMA_EXT)
else if (ar->cmd == WIN_READDMA
|| ar->cmd == WIN_READDMA_EXT)
return !udma_read(drive, rq);
#ifdef CONFIG_BLK_DEV_IDE_TCQ
else if (args->taskfile.command == WIN_WRITEDMA_QUEUED
|| args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT
|| args->taskfile.command == WIN_READDMA_QUEUED
|| args->taskfile.command == WIN_READDMA_QUEUED_EXT)
else if (ar->cmd == WIN_WRITEDMA_QUEUED
|| ar->cmd == WIN_WRITEDMA_QUEUED_EXT
|| ar->cmd == WIN_READDMA_QUEUED
|| ar->cmd == WIN_READDMA_QUEUED_EXT)
return udma_tcq_taskfile(drive, rq);
#endif
else {
printk("ata_taskfile: unknown command %x\n", args->taskfile.command);
printk("ata_taskfile: unknown command %x\n", ar->cmd);
return ide_stopped;
}
}
......@@ -396,18 +395,18 @@ ide_startstop_t recal_intr(struct ata_device *drive, struct request *rq)
*/
ide_startstop_t task_no_data_intr(struct ata_device *drive, struct request *rq)
{
struct ata_taskfile *args = rq->special;
struct ata_taskfile *ar = rq->special;
ide__sti(); /* local CPU only */
if (!ata_status(drive, READY_STAT, BAD_STAT)) {
/* Keep quiet for NOP because it is expected to fail. */
if (args && args->taskfile.command != WIN_NOP)
if (ar && ar->cmd != WIN_NOP)
return ata_error(drive, rq, __FUNCTION__);
}
if (args)
ide_end_drive_cmd(drive, rq, GET_ERR());
if (ar)
ide_end_drive_cmd(drive, rq);
return ide_stopped;
}
......@@ -466,8 +465,8 @@ static ide_startstop_t pre_task_out_intr(struct ata_device *drive, struct reques
}
/* (ks/hs): Fixed Multi Write */
if ((args->taskfile.command != WIN_MULTWRITE) &&
(args->taskfile.command != WIN_MULTWRITE_EXT)) {
if ((args->cmd != WIN_MULTWRITE) &&
(args->cmd != WIN_MULTWRITE_EXT)) {
unsigned long flags;
char *buf = ide_map_rq(rq, &flags);
/* For Write_sectors we need to stuff the first sector */
......@@ -569,7 +568,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
args->prehandler = NULL;
args->handler = NULL;
switch(args->taskfile.command) {
switch (args->cmd) {
case WIN_IDENTIFY:
case WIN_PIDENTIFY:
args->handler = task_in_intr;
......@@ -817,13 +816,6 @@ int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args)
memset(&rq, 0, sizeof(rq));
rq.flags = REQ_DRIVE_ACB;
#if 0
if (args->command_type != IDE_DRIVE_TASK_NO_DATA)
rq.current_nr_sectors = rq.nr_sectors
= (args->hobfile.sector_count << 8)
| args->taskfile.sector_count;
#endif
rq.special = args;
return ide_do_drive_cmd(drive, &rq, ide_wait);
......
......@@ -395,38 +395,30 @@ static inline u32 read_24(struct ata_device *drive)
*
* Should be called under lock held.
*/
void ide_end_drive_cmd(struct ata_device *drive, struct request *rq, u8 err)
void ide_end_drive_cmd(struct ata_device *drive, struct request *rq)
{
if (rq->flags & REQ_DRIVE_CMD) {
u8 *args = rq->buffer;
rq->errors = !ata_status(drive, READY_STAT, BAD_STAT);
if (args) {
args[0] = drive->status;
args[1] = err;
args[2] = IN_BYTE(IDE_NSECTOR_REG);
}
} else if (rq->flags & REQ_DRIVE_ACB) {
struct ata_taskfile *args = rq->special;
if (rq->flags & REQ_DRIVE_ACB) {
struct ata_taskfile *ar = rq->special;
rq->errors = !ata_status(drive, READY_STAT, BAD_STAT);
if (args) {
args->taskfile.feature = err;
args->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
args->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
args->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
args->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
args->taskfile.device_head = IN_BYTE(IDE_SELECT_REG);
args->taskfile.command = drive->status;
if (ar) {
ar->taskfile.feature = IN_BYTE(IDE_ERROR_REG);
ar->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
ar->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
ar->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
ar->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
ar->taskfile.device_head = IN_BYTE(IDE_SELECT_REG);
ar->cmd = drive->status;
if ((drive->id->command_set_2 & 0x0400) &&
(drive->id->cfs_enable_2 & 0x0400) &&
(drive->addressing == 1)) {
/* The following command goes to the hob file! */
OUT_BYTE(0x80, drive->channel->io_ports[IDE_CONTROL_OFFSET]);
args->hobfile.feature = IN_BYTE(IDE_FEATURE_REG);
args->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
args->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
args->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
args->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
ar->hobfile.feature = IN_BYTE(IDE_FEATURE_REG);
ar->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG);
ar->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG);
ar->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG);
ar->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG);
}
}
}
......@@ -583,7 +575,7 @@ static int do_recalibrate(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = drive->sect;
args.taskfile.command = WIN_RESTORE;
args.cmd = WIN_RESTORE;
args.handler = recal_intr;
ata_taskfile(drive, &args, NULL);
}
......@@ -602,10 +594,12 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
err = ide_dump_status(drive, rq, msg, stat);
if (!drive || !rq)
return ide_stopped;
/* retry only "normal" I/O: */
if (!(rq->flags & REQ_CMD)) {
rq->errors = 1;
ide_end_drive_cmd(drive, rq, err);
ide_end_drive_cmd(drive, rq);
return ide_stopped;
}
/* other bits are useless when BUSY */
......@@ -648,30 +642,6 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
return ide_stopped;
}
/*
* Invoked on completion of a special DRIVE_CMD.
*/
static ide_startstop_t drive_cmd_intr(struct ata_device *drive, struct request *rq)
{
u8 *args = rq->buffer;
ide__sti(); /* local CPU only */
if (!ata_status(drive, 0, DRQ_STAT) && args && args[3]) {
int retries = 10;
ata_read(drive, &args[4], args[3] * SECTOR_WORDS);
while (!ata_status(drive, 0, BUSY_STAT) && retries--)
udelay(100);
}
if (!ata_status(drive, READY_STAT, BAD_STAT))
return ata_error(drive, rq, __FUNCTION__); /* already calls ide_end_drive_cmd */
ide_end_drive_cmd(drive, rq, GET_ERR());
return ide_stopped;
}
/*
* Busy-wait for the drive status to be not "busy". Check then the status for
* all of the "good" bits and none of the "bad" bits, and if all is okay it
......@@ -775,53 +745,20 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
}
}
/* This issues a special drive command, usually initiated by ioctl()
* from the external hdparm program.
/* This issues a special drive command.
*/
if (rq->flags & REQ_DRIVE_ACB) {
struct ata_taskfile *args = rq->special;
struct ata_taskfile *ar = rq->special;
if (!(args))
if (!(ar))
goto args_error;
ata_taskfile(drive, args, NULL);
if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
(args->command_type == IDE_DRIVE_TASK_OUT)) &&
args->prehandler && args->handler)
return args->prehandler(drive, rq);
return ide_started;
}
ata_taskfile(drive, ar, NULL);
if (rq->flags & REQ_DRIVE_CMD) {
u8 *args = rq->buffer;
if (!(args))
goto args_error;
#ifdef DEBUG
printk("%s: DRIVE_CMD ", drive->name);
printk("cmd=0x%02x ", args[0]);
printk(" sc=0x%02x ", args[1]);
printk(" fr=0x%02x ", args[2]);
printk(" xx=0x%02x\n", args[3]);
#endif
ide_set_handler(drive, drive_cmd_intr, WAIT_CMD, NULL);
ata_irq_enable(drive, 1);
ata_mask(drive);
if (args[0] == WIN_SMART) {
struct hd_drive_task_hdr regfile;
regfile.feature = args[2];
regfile.sector_count = args[3];
regfile.sector_number = args[1];
regfile.low_cylinder = 0x4f;
regfile.high_cylinder = 0xc2;
ata_out_regfile(drive, &regfile);
} else {
OUT_BYTE(args[2], IDE_FEATURE_REG);
OUT_BYTE(args[1], IDE_NSECTOR_REG);
}
OUT_BYTE(args[0], IDE_COMMAND_REG);
if (((ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) ||
(ar->command_type == IDE_DRIVE_TASK_OUT)) &&
ar->prehandler && ar->handler)
return ar->prehandler(drive, rq);
return ide_started;
}
......@@ -863,7 +800,7 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
#ifdef DEBUG
printk("%s: DRIVE_CMD (null)\n", drive->name);
#endif
ide_end_drive_cmd(drive, rq, GET_ERR());
ide_end_drive_cmd(drive, rq);
return ide_stopped;
}
......
......@@ -23,6 +23,7 @@
#include <linux/errno.h>
#include <linux/blkpg.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/cdrom.h>
#include <linux/device.h>
......@@ -32,6 +33,30 @@
#include "ioctl.h"
/*
* Invoked on completion of a special DRIVE_CMD.
*/
static ide_startstop_t drive_cmd_intr(struct ata_device *drive, struct request *rq)
{
struct ata_taskfile *ar = rq->special;
ide__sti(); /* local CPU only */
if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) {
int retries = 10;
ata_read(drive, rq->buffer, ar->taskfile.sector_number * SECTOR_WORDS);
while (!ata_status(drive, 0, BUSY_STAT) && retries--)
udelay(100);
}
if (!ata_status(drive, READY_STAT, BAD_STAT))
return ata_error(drive, rq, __FUNCTION__); /* already calls ide_end_drive_cmd */
ide_end_drive_cmd(drive, rq);
return ide_stopped;
}
/*
* Implement generic ioctls invoked from userspace to imlpement specific
* functionality.
......@@ -39,36 +64,37 @@
* Unfortunately every single low level programm out there is using this
* interface.
*/
static int cmd_ioctl(struct ata_device *drive, unsigned long arg)
static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg)
{
int err = 0;
u8 vals[4];
u8 *argbuf = vals;
u8 pio = 0;
int argsize = 4;
struct ata_taskfile args;
struct request rq;
memset(&rq, 0, sizeof(rq));
rq.flags = REQ_DRIVE_CMD;
/* If empty parameter file - wait for drive ready.
*/
if (!arg)
return ide_do_drive_cmd(drive, &rq, ide_wait);
/* Second phase.
*/
if (copy_from_user(vals, (void *)arg, 4))
return -EFAULT;
memset(&rq, 0, sizeof(rq));
rq.flags = REQ_DRIVE_ACB;
memset(&args, 0, sizeof(args));
args.taskfile.feature = vals[2];
args.taskfile.sector_count = vals[3];
args.taskfile.sector_number = vals[1];
args.taskfile.low_cylinder = 0x00;
args.taskfile.high_cylinder = 0x00;
args.taskfile.sector_count = vals[1];
args.taskfile.sector_number = vals[3];
if (vals[0] == WIN_SMART) {
args.taskfile.low_cylinder = 0x4f;
args.taskfile.high_cylinder = 0xc2;
} else {
args.taskfile.low_cylinder = 0x00;
args.taskfile.high_cylinder = 0x00;
}
args.taskfile.device_head = 0x00;
args.taskfile.command = vals[0];
args.cmd = vals[0];
if (vals[3]) {
argsize = 4 + (SECTOR_WORDS * 4 * vals[3]);
......@@ -79,63 +105,18 @@ static int cmd_ioctl(struct ata_device *drive, unsigned long arg)
memset(argbuf + 4, 0, argsize - 4);
}
/*
* Always make sure the transfer reate has been setup.
*
* FIXME: what about setting up the drive with ->tuneproc?
*
* Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
* 1 : Safe to update drive->id DMA registers.
* 0 : OOPs not allowed.
*/
if ((args.taskfile.command == WIN_SETFEATURES) &&
(args.taskfile.sector_number >= XFER_SW_DMA_0) &&
(args.taskfile.feature == SETFEATURES_XFER) &&
(drive->id->dma_ultra ||
drive->id->dma_mword ||
drive->id->dma_1word)) {
pio = vals[1];
/*
* Verify that we are doing an approved SETFEATURES_XFER with
* respect to the hardware being able to support request.
* Since some hardware can improperly report capabilties, we
* check to see if the host adapter in combination with the
* device (usually a disk) properly detect and acknowledge each
* end of the ribbon.
*/
if (args.taskfile.sector_number > XFER_UDMA_2) {
if (!drive->channel->udma_four) {
printk(KERN_WARNING "%s: Speed warnings UDMA > 2 is not functional.\n",
drive->channel->name);
goto abort;
}
#ifndef CONFIG_IDEDMA_IVB
if (!(drive->id->hw_config & 0x6000))
#else
if (!(drive->id->hw_config & 0x2000) ||
!(drive->id->hw_config & 0x4000))
#endif
{
printk(KERN_WARNING "%s: Speed warnings UDMA > 2 is not functional.\n",
drive->name);
goto abort;
}
}
}
/* Issue ATA command and wait for completion.
*/
rq.buffer = argbuf;
args.handler = drive_cmd_intr;
rq.buffer = argbuf + 4;
rq.special = &args;
err = ide_do_drive_cmd(drive, &rq, ide_wait);
if (!err && pio) {
/* active-retuning-calls future */
/* FIXME: what about the setup for the drive?! */
if (drive->channel->speedproc)
drive->channel->speedproc(drive, pio);
}
argbuf[0] = drive->status;
argbuf[1] = args.taskfile.feature;
argbuf[2] = args.taskfile.sector_count;
abort:
if (copy_to_user((void *)arg, argbuf, argsize))
err = -EFAULT;
......@@ -153,7 +134,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
{
unsigned int major, minor;
struct ata_device *drive;
// struct request rq;
kdev_t dev;
dev = inode->i_rdev;
......@@ -354,10 +334,14 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned
return 0;
case HDIO_DRIVE_CMD:
if (!capable(CAP_SYS_RAWIO))
return -EACCES;
if (!arg) {
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
else
return 0;
}
return cmd_ioctl(drive, arg);
return do_cmd_ioctl(drive, arg);
/*
* uniform packet command handling
......
......@@ -541,9 +541,10 @@ int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request *
ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */
if ((rq->flags & REQ_DRIVE_ACB) && (drive->addressing == 1)) {
/* FIXME: this should never happen */
struct ata_taskfile *args = rq->special;
outb(args->taskfile.command, IDE_COMMAND_REG);
outb(args->cmd, IDE_COMMAND_REG);
} else if (drive->addressing) {
outb(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG);
} else {
......
......@@ -630,7 +630,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
outb(taskfile->low_cylinder, IDE_LCYL_REG);
outb(taskfile->high_cylinder, IDE_HCYL_REG);
outb(taskfile->device_head, IDE_SELECT_REG);
outb(taskfile->command, IDE_COMMAND_REG);
outb(args->cmd, IDE_COMMAND_REG);
switch (rq_data_dir(rq)) {
case READ:
......@@ -708,7 +708,7 @@ ide_startstop_t promise_do_request(struct ata_device *drive, struct request *rq,
args.taskfile.low_cylinder = (block>>=8);
args.taskfile.high_cylinder = (block>>=8);
args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all;
args.taskfile.command = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE;
args.cmd = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE;
/* We can't call ide_cmd_type_parser here, since it won't understand
our command, but that doesn't matter, since we don't use the
......
......@@ -60,7 +60,7 @@ static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request
struct ata_taskfile *args = rq->special;
ide__sti();
ide_end_drive_cmd(drive, rq, GET_ERR());
ide_end_drive_cmd(drive, rq);
kfree(args);
return ide_stopped;
......@@ -118,7 +118,7 @@ static void tcq_invalidate_queue(struct ata_device *drive)
BUG_ON(!rq);
rq->special = args;
args->taskfile.command = WIN_NOP;
args->cmd = WIN_NOP;
args->handler = tcq_nop_handler;
args->command_type = IDE_DRIVE_TASK_NO_DATA;
......@@ -407,7 +407,7 @@ static int check_autopoll(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.feature = 0x01;
args.taskfile.command = WIN_NOP;
args.cmd = WIN_NOP;
ide_cmd_type_parser(&args);
/*
......@@ -442,7 +442,7 @@ static int configure_tcq(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_EN_WCACHE;
args.taskfile.command = WIN_SETFEATURES;
args.cmd = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args)) {
......@@ -456,7 +456,7 @@ static int configure_tcq(struct ata_device *drive)
*/
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_DIS_RI;
args.taskfile.command = WIN_SETFEATURES;
args.cmd = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args)) {
......@@ -470,7 +470,7 @@ static int configure_tcq(struct ata_device *drive)
*/
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_EN_SI;
args.taskfile.command = WIN_SETFEATURES;
args.cmd = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args)) {
......@@ -554,7 +554,7 @@ ide_startstop_t udma_tcq_taskfile(struct ata_device *drive, struct request *rq)
ata_irq_enable(drive, 0);
#endif
OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG);
OUT_BYTE(args->cmd, IDE_COMMAND_REG);
if (wait_altstat(drive, &stat, BUSY_STAT)) {
ide_dump_status(drive, rq, "queued start", stat);
......
......@@ -242,7 +242,11 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int
ide_end_request(drive, rq, uptodate);
return 0;
}
ide_end_drive_cmd(drive, rq, 0);
blkdev_dequeue_request(rq);
drive->rq = NULL;
end_that_request_last(rq);
if (rq->errors >= ERROR_MAX) {
pc->s.scsi_cmd->result = DID_ERROR << 16;
if (log)
......
......@@ -81,7 +81,6 @@ enum rq_flag_bits {
/*
* for ATA/ATAPI devices
*/
__REQ_DRIVE_CMD,
__REQ_DRIVE_ACB,
__REQ_PC, /* packet command (special) */
......@@ -101,7 +100,6 @@ enum rq_flag_bits {
#define REQ_STARTED (1 << __REQ_STARTED)
#define REQ_DONTPREP (1 << __REQ_DONTPREP)
#define REQ_QUEUED (1 << __REQ_QUEUED)
#define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD)
#define REQ_DRIVE_ACB (1 << __REQ_DRIVE_ACB)
#define REQ_PC (1 << __REQ_PC)
#define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC)
......
......@@ -74,16 +74,12 @@
#define IDE_DRIVE_TASK_RAW_WRITE 4
struct hd_drive_task_hdr {
u8 data;
u8 feature;
u8 sector_count;
u8 sector_number;
u8 low_cylinder;
u8 high_cylinder;
u8 device_head;
/* FXIME: Consider moving this out from here. */
u8 command;
} __attribute__((packed));
/*
......
......@@ -253,11 +253,11 @@ typedef union {
unsigned all : 8; /* all of the bits together */
struct {
#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned XXX_head : 4; /* always zeros here */
unsigned head : 4; /* always zeros here */
unsigned unit : 1; /* drive select number: 0/1 */
unsigned XXX_bit5 : 1; /* always 1 */
unsigned bit5 : 1; /* always 1 */
unsigned lba : 1; /* using LBA instead of CHS */
unsigned XXX_bit7 : 1; /* always 1 */
unsigned bit7 : 1; /* always 1 */
#elif defined(__BIG_ENDIAN_BITFIELD)
unsigned bit7 : 1;
unsigned lba : 1;
......@@ -666,11 +666,12 @@ extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t)
/*
* Clean up after success/failure of an explicit drive cmd.
*/
extern void ide_end_drive_cmd(struct ata_device *, struct request *, u8);
extern void ide_end_drive_cmd(struct ata_device *, struct request *);
struct ata_taskfile {
struct hd_drive_task_hdr taskfile;
struct hd_drive_task_hdr hobfile;
u8 cmd; /* actual ATA command */
int command_type;
ide_startstop_t (*prehandler)(struct ata_device *, struct request *);
ide_startstop_t (*handler)(struct ata_device *, struct request *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment