patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / ide / ide-taskfile.c
index 9a92a82..98f4f3e 100644 (file)
@@ -201,14 +201,6 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
                        if (!hwif->ide_dma_read(drive))
                                return ide_started;
                        break;
-#ifdef CONFIG_BLK_DEV_IDE_TCQ
-               case WIN_READDMA_QUEUED:
-               case WIN_READDMA_QUEUED_EXT:
-                       return __ide_dma_queued_read(drive);
-               case WIN_WRITEDMA_QUEUED:
-               case WIN_WRITEDMA_QUEUED_EXT:
-                       return __ide_dma_queued_write(drive);
-#endif
                default:
                        if (task->handler == NULL)
                                return ide_stopped;
@@ -309,38 +301,18 @@ EXPORT_SYMBOL(task_no_data_intr);
  */
 #ifndef CONFIG_IDE_TASKFILE_IO
 
-#define task_map_rq(rq, flags)         ide_map_buffer((rq), (flags))
-#define task_unmap_rq(rq, buf, flags)  ide_unmap_buffer((rq), (buf), (flags))
-
 /*
  * Handler for command with PIO data-in phase, READ
  */
-/*
- * FIXME before 2.4 enable ...
- *     DATA integrity issue upon error. <andre@linux-ide.org>
- */
 ide_startstop_t task_in_intr (ide_drive_t *drive)
 {
        struct request *rq      = HWGROUP(drive)->rq;
        ide_hwif_t *hwif        = HWIF(drive);
        char *pBuf              = NULL;
        u8 stat;
-       unsigned long flags;
 
        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) {
                if (stat & (ERR_STAT|DRQ_STAT)) {
-#if 0
-                       DTF("%s: attempting to recover last " \
-                               "sector counter status=0x%02x\n",
-                               drive->name, stat);
-                       /*
-                        * Expect a BUG BOMB if we attempt to rewind the
-                        * offset in the BH aka PAGE in the current BLOCK
-                        * segment.  This is different than the HOST segment.
-                        */
-#endif
-                       if (!rq->bio)
-                               rq->current_nr_sectors++;
                        return DRIVER(drive)->error(drive, "task_in_intr", stat);
                }
                if (!(stat & BUSY_STAT)) {
@@ -350,39 +322,13 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
                        return ide_started;  
                }
        }
-#if 0
 
-       /*
-        * Holding point for a brain dump of a thought :-/
-        */
-
-       if (!OK_STAT(stat,DRIVE_READY,drive->bad_wstat)) {
-               DTF("%s: READ attempting to recover last " \
-                       "sector counter status=0x%02x\n",
-                       drive->name, stat);
-               rq->current_nr_sectors++;
-               return DRIVER(drive)->error(drive, "task_in_intr", stat);
-        }
-       if (!rq->current_nr_sectors)
-               if (!DRIVER(drive)->end_request(drive, 1, 0))
-                       return ide_stopped;
-
-       if (--rq->current_nr_sectors <= 0)
-               if (!DRIVER(drive)->end_request(drive, 1, 0))
-                       return ide_stopped;
-#endif
-
-       pBuf = task_map_rq(rq, &flags);
+       pBuf = rq->buffer + task_rq_offset(rq);
        DTF("Read: %p, rq->current_nr_sectors: %d, stat: %02x\n",
                pBuf, (int) rq->current_nr_sectors, stat);
        taskfile_input_data(drive, pBuf, SECTOR_WORDS);
-       task_unmap_rq(rq, pBuf, &flags);
-       /*
-        * FIXME :: We really can not legally get a new page/bh
-        * regardless, if this is the end of our segment.
-        * BH walking or segment can only be updated after we have a good
-        * hwif->INB(IDE_STATUS_REG); return.
-        */
+
+       /* FIXME: check drive status */
        if (--rq->current_nr_sectors <= 0)
                if (!DRIVER(drive)->end_request(drive, 1, 0))
                        return ide_stopped;
@@ -407,21 +353,10 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive)
        char *pBuf              = NULL;
        unsigned int msect      = drive->mult_count;
        unsigned int nsect;
-       unsigned long flags;
        u8 stat;
 
        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),DATA_READY,BAD_R_STAT)) {
                if (stat & (ERR_STAT|DRQ_STAT)) {
-                       if (!rq->bio) {
-                               rq->current_nr_sectors += drive->mult_count;
-                               /*
-                                * NOTE: could rewind beyond beginning :-/
-                                */
-                       } else {
-                               printk(KERN_ERR "%s: MULTI-READ assume all data " \
-                                       "transfered is bad status=0x%02x\n",
-                                       drive->name, stat);
-                       }
                        return DRIVER(drive)->error(drive, "task_mulin_intr", stat);
                }
                /* no data yet, so wait for another interrupt */
@@ -434,21 +369,16 @@ ide_startstop_t task_mulin_intr (ide_drive_t *drive)
                nsect = rq->current_nr_sectors;
                if (nsect > msect)
                        nsect = msect;
-               pBuf = task_map_rq(rq, &flags);
+               pBuf = rq->buffer + task_rq_offset(rq);
                DTF("Multiread: %p, nsect: %d, msect: %d, " \
                        " rq->current_nr_sectors: %d\n",
                        pBuf, nsect, msect, rq->current_nr_sectors);
                taskfile_input_data(drive, pBuf, nsect * SECTOR_WORDS);
-               task_unmap_rq(rq, pBuf, &flags);
                rq->errors = 0;
                rq->current_nr_sectors -= nsect;
                msect -= nsect;
-               /*
-                * FIXME :: We really can not legally get a new page/bh
-                * regardless, if this is the end of our segment.
-                * BH walking or segment can only be updated after we have a
-                * good hwif->INB(IDE_STATUS_REG); return.
-                */
+
+               /* FIXME: check drive status */
                if (!rq->current_nr_sectors) {
                        if (!DRIVER(drive)->end_request(drive, 1, 0))
                                return ide_stopped;
@@ -467,8 +397,6 @@ EXPORT_SYMBOL(task_mulin_intr);
  */
 ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
 {
-       char *pBuf              = NULL;
-       unsigned long flags;
        ide_startstop_t startstop;
 
        if (ide_wait_stat(&startstop, drive, DATA_READY,
@@ -479,10 +407,8 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
                return startstop;
        }
        /* For Write_sectors we need to stuff the first sector */
-       pBuf = task_map_rq(rq, &flags);
-       taskfile_output_data(drive, pBuf, SECTOR_WORDS);
+       taskfile_output_data(drive, rq->buffer + task_rq_offset(rq), SECTOR_WORDS);
        rq->current_nr_sectors--;
-       task_unmap_rq(rq, pBuf, &flags);
        return ide_started;
 }
 
@@ -498,14 +424,9 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
        ide_hwif_t *hwif        = HWIF(drive);
        struct request *rq      = HWGROUP(drive)->rq;
        char *pBuf              = NULL;
-       unsigned long flags;
        u8 stat;
 
        if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), DRIVE_READY, drive->bad_wstat)) {
-               DTF("%s: WRITE attempting to recover last " \
-                       "sector counter status=0x%02x\n",
-                       drive->name, stat);
-               rq->current_nr_sectors++;
                return DRIVER(drive)->error(drive, "task_out_intr", stat);
        }
        /*
@@ -517,11 +438,10 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
                        return ide_stopped;
        if ((rq->current_nr_sectors==1) ^ (stat & DRQ_STAT)) {
                rq = HWGROUP(drive)->rq;
-               pBuf = task_map_rq(rq, &flags);
+               pBuf = rq->buffer + task_rq_offset(rq);
                DTF("write: %p, rq->current_nr_sectors: %d\n",
                        pBuf, (int) rq->current_nr_sectors);
                taskfile_output_data(drive, pBuf, SECTOR_WORDS);
-               task_unmap_rq(rq, pBuf, &flags);
                rq->errors = 0;
                rq->current_nr_sectors--;
        }
@@ -532,28 +452,11 @@ ide_startstop_t task_out_intr (ide_drive_t *drive)
 
 EXPORT_SYMBOL(task_out_intr);
 
-#undef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
-
 ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
 {
-#ifdef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
-       ide_hwif_t *hwif                = HWIF(drive);
-       char *pBuf                      = NULL;
-       unsigned int nsect = 0, msect   = drive->mult_count;
-        u8 stat;
-       unsigned long flags;
-#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
-
        ide_task_t *args = rq->special;
        ide_startstop_t startstop;
 
-#if 0
-       /*
-        * assign private copy for multi-write
-        */
-       memcpy(&HWGROUP(drive)->wrq, rq, sizeof(struct request));
-#endif
-
        if (ide_wait_stat(&startstop, drive, DATA_READY,
                        drive->bad_wstat, WAIT_DRQ)) {
                printk(KERN_ERR "%s: no DRQ after issuing %s\n",
@@ -561,31 +464,6 @@ ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
                        drive->addressing ? "MULTWRITE_EXT" : "MULTWRITE");
                return startstop;
        }
-#ifdef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
-
-       do {
-               nsect = rq->current_nr_sectors;
-               if (nsect > msect)
-                       nsect = msect;
-               pBuf = task_map_rq(rq, &flags);
-               DTF("Pre-Multiwrite: %p, nsect: %d, msect: %d, " \
-                       "rq->current_nr_sectors: %ld\n",
-                       pBuf, nsect, msect, rq->current_nr_sectors);
-               msect -= nsect;
-               taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
-               task_unmap_rq(rq, pBuf, &flags);
-               rq->current_nr_sectors -= nsect;
-               if (!rq->current_nr_sectors) {
-                       if (!DRIVER(drive)->end_request(drive, 1, 0))
-                               if (!rq->bio) {
-                                       stat = hwif->INB(IDE_STATUS_REG);
-                                       return ide_stopped;
-                               }
-               }
-       } while (msect);
-       rq->errors = 0;
-       return ide_started;
-#else /* ! ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
        if (!(drive_is_ready(drive))) {
                int i;
                for (i=0; i<100; i++) {
@@ -599,14 +477,10 @@ ide_startstop_t pre_task_mulout_intr (ide_drive_t *drive, struct request *rq)
         * move the DATA-TRANSFER T-Bar as BSY != 0. <andre@linux-ide.org>
         */
        return args->handler(drive);
-#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
 }
 
 EXPORT_SYMBOL(pre_task_mulout_intr);
 
-/*
- * FIXME before enabling in 2.4 ... DATA integrity issue upon error.
- */
 /*
  * Handler for command write multiple
  * Called directly from execute_drive_cmd for the first bunch of sectors,
@@ -618,49 +492,17 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive)
        u8 stat                         = hwif->INB(IDE_STATUS_REG);
        struct request *rq              = HWGROUP(drive)->rq;
        char *pBuf                      = NULL;
-       ide_startstop_t startstop       = ide_stopped;
        unsigned int msect              = drive->mult_count;
        unsigned int nsect;
-       unsigned long flags;
 
-       /*
-        * (ks/hs): Handle last IRQ on multi-sector transfer,
-        * occurs after all data was sent in this chunk
-        */
-       if (rq->current_nr_sectors == 0) {
+       if (!OK_STAT(stat, DATA_READY, BAD_R_STAT) || !rq->current_nr_sectors) {
                if (stat & (ERR_STAT|DRQ_STAT)) {
-                       if (!rq->bio) {
-                                rq->current_nr_sectors += drive->mult_count;
-                               /*
-                                * NOTE: could rewind beyond beginning :-/
-                                */
-                       } else {
-                               printk(KERN_ERR "%s: MULTI-WRITE assume all data " \
-                                       "transfered is bad status=0x%02x\n",
-                                       drive->name, stat);
-                       }
                        return DRIVER(drive)->error(drive, "task_mulout_intr", stat);
                }
-               if (!rq->bio)
+               /* Handle last IRQ, occurs after all data was sent. */
+               if (!rq->current_nr_sectors) {
                        DRIVER(drive)->end_request(drive, 1, 0);
-               return startstop;
-       }
-       /*
-        * DON'T be lazy code the above and below togather !!!
-        */
-       if (!OK_STAT(stat,DATA_READY,BAD_R_STAT)) {
-               if (stat & (ERR_STAT|DRQ_STAT)) {
-                       if (!rq->bio) {
-                               rq->current_nr_sectors += drive->mult_count;
-                               /*
-                                * NOTE: could rewind beyond beginning :-/
-                                */
-                       } else {
-                               printk("%s: MULTI-WRITE assume all data " \
-                                       "transfered is bad status=0x%02x\n",
-                                       drive->name, stat);
-                       }
-                       return DRIVER(drive)->error(drive, "task_mulout_intr", stat);
+                       return ide_stopped;
                }
                /* no data yet, so wait for another interrupt */
                if (HWGROUP(drive)->handler == NULL)
@@ -668,7 +510,6 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive)
                return ide_started;
        }
 
-#ifndef ALTERNATE_STATE_DIAGRAM_MULTI_OUT
        if (HWGROUP(drive)->handler != NULL) {
                unsigned long lflags;
                spin_lock_irqsave(&ide_lock, lflags);
@@ -676,26 +517,20 @@ ide_startstop_t task_mulout_intr (ide_drive_t *drive)
                del_timer(&HWGROUP(drive)->timer);
                spin_unlock_irqrestore(&ide_lock, lflags);
        }
-#endif /* ALTERNATE_STATE_DIAGRAM_MULTI_OUT */
 
        do {
                nsect = rq->current_nr_sectors;
                if (nsect > msect)
                        nsect = msect;
-               pBuf = task_map_rq(rq, &flags);
+               pBuf = rq->buffer + task_rq_offset(rq);
                DTF("Multiwrite: %p, nsect: %d, msect: %d, " \
                        "rq->current_nr_sectors: %ld\n",
                        pBuf, nsect, msect, rq->current_nr_sectors);
                msect -= nsect;
                taskfile_output_data(drive, pBuf, nsect * SECTOR_WORDS);
-               task_unmap_rq(rq, pBuf, &flags);
                rq->current_nr_sectors -= nsect;
-               /*
-                * FIXME :: We really can not legally get a new page/bh
-                * regardless, if this is the end of our segment.
-                * BH walking or segment can only be updated after we
-                * have a good  hwif->INB(IDE_STATUS_REG); return.
-                */
+
+               /* FIXME: check drive status */
                if (!rq->current_nr_sectors) {
                        if (!DRIVER(drive)->end_request(drive, 1, 0))
                                if (!rq->bio)
@@ -1011,6 +846,12 @@ int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_
                else
                        rq.nr_sectors = data_size / SECTOR_SIZE;
 
+               if (!rq.nr_sectors) {
+                       printk(KERN_ERR "%s: in/out command without data\n",
+                                       drive->name);
+                       return -EFAULT;
+               }
+
                rq.hard_nr_sectors = rq.nr_sectors;
                rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
        }
@@ -1052,13 +893,14 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
        int taskin              = 0;
        int taskout             = 0;
        u8 io_32bit             = drive->io_32bit;
+       char __user *buf = (char __user *)arg;
 
 //     printk("IDE Taskfile ...\n");
 
        req_task = kmalloc(tasksize, GFP_KERNEL);
        if (req_task == NULL) return -ENOMEM;
        memset(req_task, 0, tasksize);
-       if (copy_from_user(req_task, (void *) arg, tasksize)) {
+       if (copy_from_user(req_task, buf, tasksize)) {
                kfree(req_task);
                return -EFAULT;
        }
@@ -1074,7 +916,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
                        goto abort;
                }
                memset(outbuf, 0, taskout);
-               if (copy_from_user(outbuf, (void *)arg + outtotal, taskout)) {
+               if (copy_from_user(outbuf, buf + outtotal, taskout)) {
                        err = -EFAULT;
                        goto abort;
                }
@@ -1088,7 +930,7 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
                        goto abort;
                }
                memset(inbuf, 0, taskin);
-               if (copy_from_user(inbuf, (void *)arg + intotal , taskin)) {
+               if (copy_from_user(inbuf, buf + intotal, taskin)) {
                        err = -EFAULT;
                        goto abort;
                }
@@ -1196,20 +1038,20 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
        req_task->in_flags  = args.tf_in_flags;
        req_task->out_flags = args.tf_out_flags;
 
-       if (copy_to_user((void *)arg, req_task, tasksize)) {
+       if (copy_to_user(buf, req_task, tasksize)) {
                err = -EFAULT;
                goto abort;
        }
        if (taskout) {
                int outtotal = tasksize;
-               if (copy_to_user((void *)arg+outtotal, outbuf, taskout)) {
+               if (copy_to_user(buf + outtotal, outbuf, taskout)) {
                        err = -EFAULT;
                        goto abort;
                }
        }
        if (taskin) {
                int intotal = tasksize + taskout;
-               if (copy_to_user((void *)arg+intotal, inbuf, taskin)) {
+               if (copy_to_user(buf + intotal, inbuf, taskin)) {
                        err = -EFAULT;
                        goto abort;
                }
@@ -1266,7 +1108,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
                return ide_do_drive_cmd(drive, &rq, ide_wait);
        }
 
-       if (copy_from_user(args, (void *)arg, 4))
+       if (copy_from_user(args, (void __user *)arg, 4))
                return -EFAULT;
 
        memset(&tfargs, 0, sizeof(ide_task_t));
@@ -1299,7 +1141,7 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
                ide_driveid_update(drive);
        }
 abort:
-       if (copy_to_user((void *)arg, argbuf, argsize))
+       if (copy_to_user((void __user *)arg, argbuf, argsize))
                err = -EFAULT;
        if (argsize > 4)
                kfree(argbuf);
@@ -1325,14 +1167,15 @@ EXPORT_SYMBOL(ide_wait_cmd_task);
  */
 int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
 {
+       void __user *p = (void __user *)arg;
        int err = 0;
        u8 args[7], *argbuf = args;
        int argsize = 7;
 
-       if (copy_from_user(args, (void *)arg, 7))
+       if (copy_from_user(args, p, 7))
                return -EFAULT;
        err = ide_wait_cmd_task(drive, argbuf);
-       if (copy_to_user((void *)arg, argbuf, argsize))
+       if (copy_to_user(p, argbuf, argsize))
                err = -EFAULT;
        return err;
 }
@@ -1493,9 +1336,6 @@ ide_startstop_t flagged_task_in_intr (ide_drive_t *drive)
        char *pBuf              = NULL;
        int retries             = 5;
 
-       if (rq->current_nr_sectors == 0) 
-               return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat); 
-
        if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
                if (stat & ERR_STAT) {
                        return DRIVER(drive)->error(drive, "flagged_task_in_intr", stat);
@@ -1542,9 +1382,6 @@ ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive)
        int retries             = 5;
        unsigned int msect, nsect;
 
-       if (rq->current_nr_sectors == 0) 
-               return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (no data requested)", stat); 
-
        msect = drive->mult_count;
        if (msect == 0) 
                return DRIVER(drive)->error(drive, "flagged_task_mulin_intr (multimode not set)", stat); 
@@ -1596,14 +1433,8 @@ ide_startstop_t flagged_task_mulin_intr (ide_drive_t *drive)
  */
 ide_startstop_t flagged_pre_task_out_intr (ide_drive_t *drive, struct request *rq)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       u8 stat                 = hwif->INB(IDE_STATUS_REG);
        ide_startstop_t startstop;
 
-       if (!rq->current_nr_sectors) {
-               return DRIVER(drive)->error(drive, "flagged_pre_task_out_intr (write data not specified)", stat);
-       }
-
        if (ide_wait_stat(&startstop, drive, DATA_READY,
                        BAD_W_STAT, WAIT_DRQ)) {
                printk(KERN_ERR "%s: No DRQ bit after issuing write command.\n", drive->name);
@@ -1665,9 +1496,6 @@ ide_startstop_t flagged_pre_task_mulout_intr (ide_drive_t *drive, struct request
        ide_startstop_t startstop;
        unsigned int msect, nsect;
 
-       if (!rq->current_nr_sectors) 
-               return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (write data not specified)", stat);
-
        msect = drive->mult_count;
        if (msect == 0)
                return DRIVER(drive)->error(drive, "flagged_pre_task_mulout_intr (multimode not set)", stat);