]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-floppy.c
ide-floppy: merge callbacks
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-floppy.c
index 6e891bccd052db8d228ccb961179c3fcc6b534b4..2058a6f3f3316b2fbd9c615fe2e0dc3254389f1d 100644 (file)
@@ -231,6 +231,7 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
 static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
                                  unsigned int bcount, int direction)
 {
+       ide_hwif_t *hwif = drive->hwif;
        struct request *rq = pc->rq;
        struct req_iterator iter;
        struct bio_vec *bvec;
@@ -246,9 +247,9 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
 
                data = bvec_kmap_irq(bvec, &flags);
                if (direction)
-                       drive->hwif->atapi_output_bytes(drive, data, count);
+                       hwif->output_data(drive, NULL, data, count);
                else
-                       drive->hwif->atapi_input_bytes(drive, data, count);
+                       hwif->input_data(drive, NULL, data, count);
                bvec_kunmap_irq(data, &flags);
 
                bcount -= count;
@@ -261,10 +262,7 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
        if (bcount) {
                printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
                                drive->name, __func__, bcount);
-               if (direction)
-                       ide_atapi_write_zeros(drive, bcount);
-               else
-                       ide_atapi_discard_data(drive, bcount);
+               ide_pad_transfer(drive, direction, bcount);
        }
 }
 
@@ -288,11 +286,12 @@ static void idefloppy_queue_pc_head(ide_drive_t *drive, struct ide_atapi_pc *pc,
 {
        struct ide_floppy_obj *floppy = drive->driver_data;
 
-       ide_init_drive_cmd(rq);
+       blk_rq_init(NULL, rq);
        rq->buffer = (char *) pc;
        rq->cmd_type = REQ_TYPE_SPECIAL;
+       rq->cmd_flags |= REQ_PREEMPT;
        rq->rq_disk = floppy->disk;
-       (void) ide_do_drive_cmd(drive, rq, ide_preempt);
+       ide_do_drive_cmd(drive, rq);
 }
 
 static struct ide_atapi_pc *idefloppy_next_pc_storage(ide_drive_t *drive)
@@ -313,50 +312,38 @@ static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
        return (&floppy->rq_stack[floppy->rq_stack_index++]);
 }
 
-static void idefloppy_request_sense_callback(ide_drive_t *drive)
+static void ide_floppy_callback(ide_drive_t *drive)
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
-       u8 *buf = floppy->pc->buf;
+       struct ide_atapi_pc *pc = floppy->pc;
+       int uptodate = pc->error ? 0 : 1;
 
        debug_log("Reached %s\n", __func__);
 
-       if (!floppy->pc->error) {
-               floppy->sense_key = buf[2] & 0x0F;
-               floppy->asc = buf[12];
-               floppy->ascq = buf[13];
-               floppy->progress_indication = buf[15] & 0x80 ?
-                       (u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
+       if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
+           (pc->rq && blk_pc_request(pc->rq)))
+               uptodate = 1; /* FIXME */
+       else if (pc->c[0] == GPCMD_REQUEST_SENSE) {
+               u8 *buf = floppy->pc->buf;
 
-               if (floppy->failed_pc)
-                       debug_log("pc = %x, sense key = %x, asc = %x,"
-                                       " ascq = %x\n",
-                                       floppy->failed_pc->c[0],
-                                       floppy->sense_key,
-                                       floppy->asc,
-                                       floppy->ascq);
-               else
-                       debug_log("sense key = %x, asc = %x, ascq = %x\n",
-                                       floppy->sense_key,
-                                       floppy->asc,
-                                       floppy->ascq);
+               if (!pc->error) {
+                       floppy->sense_key = buf[2] & 0x0F;
+                       floppy->asc = buf[12];
+                       floppy->ascq = buf[13];
+                       floppy->progress_indication = buf[15] & 0x80 ?
+                               (u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
 
+                       if (floppy->failed_pc)
+                               debug_log("pc = %x, ", floppy->failed_pc->c[0]);
 
-               idefloppy_end_request(drive, 1, 0);
-       } else {
-               printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting"
-                               " request!\n");
-               idefloppy_end_request(drive, 0, 0);
+                       debug_log("sense key = %x, asc = %x, ascq = %x\n",
+                                 floppy->sense_key, floppy->asc, floppy->ascq);
+               } else
+                       printk(KERN_ERR "Error in REQUEST SENSE itself - "
+                                       "Aborting request!\n");
        }
-}
-
-/* General packet command callback function. */
-static void idefloppy_pc_callback(ide_drive_t *drive)
-{
-       idefloppy_floppy_t *floppy = drive->driver_data;
 
-       debug_log("Reached %s\n", __func__);
-
-       idefloppy_end_request(drive, floppy->pc->error ? 0 : 1, 0);
+       idefloppy_end_request(drive, uptodate, 0);
 }
 
 static void idefloppy_init_pc(struct ide_atapi_pc *pc)
@@ -367,7 +354,7 @@ static void idefloppy_init_pc(struct ide_atapi_pc *pc)
        pc->req_xfer = 0;
        pc->buf = pc->pc_buf;
        pc->buf_size = IDEFLOPPY_PC_BUFFER_SIZE;
-       pc->idefloppy_callback = &idefloppy_pc_callback;
+       pc->idefloppy_callback = &ide_floppy_callback;
 }
 
 static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
@@ -376,7 +363,6 @@ static void idefloppy_create_request_sense_cmd(struct ide_atapi_pc *pc)
        pc->c[0] = GPCMD_REQUEST_SENSE;
        pc->c[4] = 255;
        pc->req_xfer = 18;
-       pc->idefloppy_callback = &idefloppy_request_sense_callback;
 }
 
 /*
@@ -439,8 +425,8 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
                        debug_log("%s: I/O error\n", drive->name);
                        rq->errors++;
                        if (pc->c[0] == GPCMD_REQUEST_SENSE) {
-                               printk(KERN_ERR "ide-floppy: I/O error in "
-                                       "request sense command\n");
+                               printk(KERN_ERR "%s: I/O error in request sense"
+                                               " command\n", drive->name);
                                return ide_do_reset(drive);
                        }
                        /* Retry operation */
@@ -458,27 +444,27 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
 
        if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
                pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
-               printk(KERN_ERR "ide-floppy: The floppy wants to issue "
-                       "more interrupts in DMA mode\n");
+               printk(KERN_ERR "%s: The device wants to issue more interrupts "
+                               "in DMA mode\n", drive->name);
                ide_dma_off(drive);
                return ide_do_reset(drive);
        }
 
        /* Get the number of bytes to transfer */
-       bcount = (hwif->INB(hwif->io_ports[IDE_BCOUNTH_OFFSET]) << 8) |
-                 hwif->INB(hwif->io_ports[IDE_BCOUNTL_OFFSET]);
+       bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) |
+                 hwif->INB(hwif->io_ports.lbam_addr);
        /* on this interrupt */
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
 
        if (ireason & CD) {
-               printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
+               printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__);
                return ide_do_reset(drive);
        }
        if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
                /* Hopefully, we will never get here */
-               printk(KERN_ERR "ide-floppy: We wanted to %s, ",
-                               (ireason & IO) ? "Write" : "Read");
-               printk(KERN_ERR "but the floppy wants us to %s !\n",
+               printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
+                               "to %s!\n", drive->name,
+                               (ireason & IO) ? "Write" : "Read",
                                (ireason & IO) ? "Read" : "Write");
                return ide_do_reset(drive);
        }
@@ -487,10 +473,11 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
                temp = pc->xferred + bcount;
                if (temp > pc->req_xfer) {
                        if (temp > pc->buf_size) {
-                               printk(KERN_ERR "ide-floppy: The floppy wants "
-                                       "to send us more data than expected "
-                                       "- discarding data\n");
-                               ide_atapi_discard_data(drive, bcount);
+                               printk(KERN_ERR "%s: The device wants to send "
+                                               "us more data than expected - "
+                                               "discarding data\n",
+                                               drive->name);
+                               ide_pad_transfer(drive, 0, bcount);
 
                                ide_set_handler(drive,
                                                &idefloppy_pc_intr,
@@ -498,17 +485,17 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
                                                NULL);
                                return ide_started;
                        }
-                       debug_log("The floppy wants to send us more data than"
-                                       " expected - allowing transfer\n");
+                       debug_log("The device wants to send us more data than "
+                                 "expected - allowing transfer\n");
                }
        }
        if (pc->flags & PC_FLAG_WRITING)
-               xferfunc = hwif->atapi_output_bytes;
+               xferfunc = hwif->output_data;
        else
-               xferfunc = hwif->atapi_input_bytes;
+               xferfunc = hwif->input_data;
 
        if (pc->buf)
-               xferfunc(drive, pc->cur_pos, bcount);
+               xferfunc(drive, NULL, pc->cur_pos, bcount);
        else
                ide_floppy_io_buffers(drive, pc, bcount,
                                      !!(pc->flags & PC_FLAG_WRITING));
@@ -522,38 +509,6 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
        return ide_started;
 }
 
-/*
- * This is the original routine that did the packet transfer.
- * It fails at high speeds on the Iomega ZIP drive, so there's a slower version
- * for that drive below. The algorithm is chosen based on drive type
- */
-static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
-{
-       ide_hwif_t *hwif = drive->hwif;
-       ide_startstop_t startstop;
-       idefloppy_floppy_t *floppy = drive->driver_data;
-       u8 ireason;
-
-       if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
-               printk(KERN_ERR "ide-floppy: Strange, packet command "
-                               "initiated yet DRQ isn't asserted\n");
-               return startstop;
-       }
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
-       if ((ireason & CD) == 0 || (ireason & IO)) {
-               printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
-                               "issuing a packet command\n");
-               return ide_do_reset(drive);
-       }
-
-       /* Set the interrupt routine */
-       ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
-       /* Send the actual packet */
-       HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12);
-       return ide_started;
-}
-
-
 /*
  * What we have here is a classic case of a top half / bottom half interrupt
  * service routine. In interrupt mode, the device sends an interrupt to signal
@@ -569,7 +524,8 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive)
        idefloppy_floppy_t *floppy = drive->driver_data;
 
        /* Send the actual packet */
-       HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12);
+       drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
+
        /* Timeout for the packet command */
        return IDEFLOPPY_WAIT_CMD;
 }
@@ -578,18 +534,20 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
        idefloppy_floppy_t *floppy = drive->driver_data;
+       ide_expiry_t *expiry;
+       unsigned int timeout;
        ide_startstop_t startstop;
        u8 ireason;
 
        if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
-               printk(KERN_ERR "ide-floppy: Strange, packet command "
-                               "initiated yet DRQ isn't asserted\n");
+               printk(KERN_ERR "%s: Strange, packet command initiated yet "
+                               "DRQ isn't asserted\n", drive->name);
                return startstop;
        }
-       ireason = hwif->INB(hwif->io_ports[IDE_IREASON_OFFSET]);
+       ireason = hwif->INB(hwif->io_ports.nsect_addr);
        if ((ireason & CD) == 0 || (ireason & IO)) {
-               printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
-                               "while issuing a packet command\n");
+               printk(KERN_ERR "%s: (IO,CoD) != (0,1) while issuing "
+                               "a packet command\n", drive->name);
                return ide_do_reset(drive);
        }
        /*
@@ -600,9 +558,20 @@ static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
         * 40 and 50msec work well. idefloppy_pc_intr will not be actually
         * used until after the packet is moved in about 50 msec.
         */
+       if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) {
+               timeout = floppy->ticks;
+               expiry = &idefloppy_transfer_pc2;
+       } else {
+               timeout = IDEFLOPPY_WAIT_CMD;
+               expiry = NULL;
+       }
+
+       ide_set_handler(drive, &idefloppy_pc_intr, timeout, expiry);
+
+       if ((floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) == 0)
+               /* Send the actual packet */
+               hwif->output_data(drive, NULL, floppy->pc->c, 12);
 
-       ide_set_handler(drive, &idefloppy_pc_intr, floppy->ticks,
-                       &idefloppy_transfer_pc2);
        return ide_started;
 }
 
@@ -627,7 +596,6 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
 {
        idefloppy_floppy_t *floppy = drive->driver_data;
        ide_hwif_t *hwif = drive->hwif;
-       ide_handler_t *pkt_xfer_routine;
        u16 bcount;
        u8 dma;
 
@@ -665,8 +633,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
        if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
                dma = !hwif->dma_ops->dma_setup(drive);
 
-       ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
-                          IDE_TFLAG_OUT_DEVICE, bcount, dma);
+       ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_DEVICE, bcount, dma);
 
        if (dma) {
                /* Begin DMA, if necessary */
@@ -674,37 +641,20 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
                hwif->dma_ops->dma_start(drive);
        }
 
-       /* Can we transfer the packet when we get the interrupt or wait? */
-       if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) {
-               /* wait */
-               pkt_xfer_routine = &idefloppy_transfer_pc1;
-       } else {
-               /* immediate */
-               pkt_xfer_routine = &idefloppy_transfer_pc;
-       }
-
        if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
                /* Issue the packet command */
                ide_execute_command(drive, WIN_PACKETCMD,
-                               pkt_xfer_routine,
+                               &idefloppy_transfer_pc1,
                                IDEFLOPPY_WAIT_CMD,
                                NULL);
                return ide_started;
        } else {
                /* Issue the packet command */
-               hwif->OUTB(WIN_PACKETCMD, hwif->io_ports[IDE_COMMAND_OFFSET]);
-               return (*pkt_xfer_routine) (drive);
+               ide_execute_pkt_cmd(drive);
+               return idefloppy_transfer_pc1(drive);
        }
 }
 
-static void idefloppy_rw_callback(ide_drive_t *drive)
-{
-       debug_log("Reached %s\n", __func__);
-
-       idefloppy_end_request(drive, 1, 0);
-       return;
-}
-
 static void idefloppy_create_prevent_cmd(struct ide_atapi_pc *pc, int prevent)
 {
        debug_log("creating prevent removal command, prevent = %d\n", prevent);
@@ -799,7 +749,6 @@ static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
        put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
        put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
 
-       pc->idefloppy_callback = &idefloppy_rw_callback;
        pc->rq = rq;
        pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
        if (rq->cmd_flags & REQ_RW)
@@ -813,7 +762,6 @@ static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
                struct ide_atapi_pc *pc, struct request *rq)
 {
        idefloppy_init_pc(pc);
-       pc->idefloppy_callback = &idefloppy_rw_callback;
        memcpy(pc->c, rq->cmd, sizeof(pc->c));
        pc->rq = rq;
        pc->b_count = rq->data_len;
@@ -885,14 +833,16 @@ static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
 static int idefloppy_queue_pc_tail(ide_drive_t *drive, struct ide_atapi_pc *pc)
 {
        struct ide_floppy_obj *floppy = drive->driver_data;
-       struct request rq;
+       struct request *rq;
+       int error;
 
-       ide_init_drive_cmd(&rq);
-       rq.buffer = (char *) pc;
-       rq.cmd_type = REQ_TYPE_SPECIAL;
-       rq.rq_disk = floppy->disk;
+       rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+       rq->buffer = (char *) pc;
+       rq->cmd_type = REQ_TYPE_SPECIAL;
+       error = blk_execute_rq(drive->queue, floppy->disk, rq, 0);
+       blk_put_request(rq);
 
-       return ide_do_drive_cmd(drive, &rq, ide_wait);
+       return error;
 }
 
 /*