]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-taskfile.c
Merge branch 'xen-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/jeremy/xen
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-taskfile.c
index 97a9244312fc0492fc813e2effa99cbbe2542b55..2a3c8d498343ff417f398d1fb4b93e8678dbf82f 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/bitops.h>
+#include <linux/scatterlist.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -238,7 +239,7 @@ EXPORT_SYMBOL(task_no_data_intr);
 static u8 wait_drive_not_busy(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
-       int retries = 100;
+       int retries;
        u8 stat;
 
        /*
@@ -246,10 +247,14 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
         * This can take up to 10 usec, but we will wait max 1 ms
         * (drive_cmd_intr() waits that long).
         */
-       while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
-               udelay(10);
+       for (retries = 0; retries < 100; retries++) {
+               if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
+                       udelay(10);
+               else
+                       break;
+       }
 
-       if (!retries)
+       if (stat & BUSY_STAT)
                printk(KERN_ERR "%s: drive still BUSY!\n", drive->name);
 
        return stat;
@@ -259,6 +264,7 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct scatterlist *sg = hwif->sg_table;
+       struct scatterlist *cursg = hwif->cursg;
        struct page *page;
 #ifdef CONFIG_HIGHMEM
        unsigned long flags;
@@ -266,8 +272,14 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
        unsigned int offset;
        u8 *buf;
 
-       page = sg[hwif->cursg].page;
-       offset = sg[hwif->cursg].offset + hwif->cursg_ofs * SECTOR_SIZE;
+       cursg = hwif->cursg;
+       if (!cursg) {
+               cursg = sg;
+               hwif->cursg = sg;
+       }
+
+       page = cursg->page;
+       offset = cursg->offset + hwif->cursg_ofs * SECTOR_SIZE;
 
        /* get the current page and offset */
        page = nth_page(page, (offset >> PAGE_SHIFT));
@@ -281,8 +293,8 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
        hwif->nleft--;
        hwif->cursg_ofs++;
 
-       if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) {
-               hwif->cursg++;
+       if ((hwif->cursg_ofs * SECTOR_SIZE) == cursg->length) {
+               hwif->cursg = sg_next(hwif->cursg);
                hwif->cursg_ofs = 0;
        }
 
@@ -363,7 +375,9 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
 
 static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
 {
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
+       HWIF(drive)->cursg = NULL;
+
+       if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
                ide_task_t *task = rq->special;
 
                if (task->tf_out_flags.all) {
@@ -474,7 +488,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
        struct request rq;
 
        memset(&rq, 0, sizeof(rq));
-       rq.flags = REQ_DRIVE_TASKFILE;
+       rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
        rq.buffer = buf;
 
        /*
@@ -499,7 +513,7 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
                rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
 
                if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-                       rq.flags |= REQ_RW;
+                       rq.cmd_flags |= REQ_RW;
        }
 
        rq.special = args;
@@ -524,8 +538,8 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
        task_ioreg_t *hobsptr   = args.hobRegister;
        int err                 = 0;
        int tasksize            = sizeof(struct ide_task_request_s);
-       int taskin              = 0;
-       int taskout             = 0;
+       unsigned int taskin     = 0;
+       unsigned int taskout    = 0;
        u8 io_32bit             = drive->io_32bit;
        char __user *buf = (char __user *)arg;
 
@@ -538,8 +552,13 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
                return -EFAULT;
        }
 
-       taskout = (int) req_task->out_size;
-       taskin  = (int) req_task->in_size;
+       taskout = req_task->out_size;
+       taskin  = req_task->in_size;
+       
+       if (taskin > 65536 || taskout > 65536) {
+               err = -EINVAL;
+               goto abort;
+       }
 
        if (taskout) {
                int outtotal = tasksize;
@@ -737,7 +756,7 @@ static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
        struct request rq;
 
        ide_init_drive_cmd(&rq);
-       rq.flags = REQ_DRIVE_TASK;
+       rq.cmd_type = REQ_TYPE_ATA_TASK;
        rq.buffer = buf;
        return ide_do_drive_cmd(drive, &rq, ide_wait);
 }