]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ide/ide-atapi.c
ACPI/PCI: Always query _OSC control field in pci_osc_control_set()
[linux-2.6-omap-h63xx.git] / drivers / ide / ide-atapi.c
index d758dcd871780329798351714d8cab44f1828739..4e58b9e7a58a01592eb3e130aee781a41e4891d1 100644 (file)
@@ -191,7 +191,7 @@ int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
 {
        struct ide_atapi_pc pc;
 
-       if (drive->atapi_flags & IDE_AFLAG_NO_DOORLOCK)
+       if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
                return 0;
 
        ide_init_pc(&pc);
@@ -246,10 +246,12 @@ int ide_scsi_expiry(ide_drive_t *drive)
 }
 EXPORT_SYMBOL_GPL(ide_scsi_expiry);
 
-/* TODO: unify the code thus making some arguments go away */
-ide_startstop_t ide_pc_intr(ide_drive_t *drive, ide_handler_t *handler,
-       void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *),
-       int (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int))
+/*
+ * This is the usual interrupt handler which will be called during a packet
+ * command.  We will transfer some of the data (as requested by the drive)
+ * and will re-point interrupt handler to us.
+ */
+static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
 {
        struct ide_atapi_pc *pc = drive->pc;
        ide_hwif_t *hwif = drive->hwif;
@@ -259,7 +261,7 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, ide_handler_t *handler,
        ide_expiry_t *expiry;
        unsigned int timeout, temp;
        u16 bcount;
-       u8 stat, ireason, scsi = drive->scsi, dsc = 0;
+       u8 stat, ireason, scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI), dsc = 0;
 
        debug_log("Enter %s - interrupt handler\n", __func__);
 
@@ -290,8 +292,8 @@ ide_startstop_t ide_pc_intr(ide_drive_t *drive, ide_handler_t *handler,
                        pc->flags |= PC_FLAG_DMA_ERROR;
                } else {
                        pc->xferred = pc->req_xfer;
-                       if (update_buffers)
-                               update_buffers(drive, pc);
+                       if (drive->pc_update_buffers)
+                               drive->pc_update_buffers(drive, pc);
                }
                debug_log("%s: DMA finished\n", drive->name);
        }
@@ -386,7 +388,8 @@ cmd_finished:
                                        temp = 0;
                                if (temp) {
                                        if (pc->sg)
-                                               io_buffers(drive, pc, temp, 0);
+                                               drive->pc_io_buffers(drive, pc,
+                                                                    temp, 0);
                                        else
                                                tp_ops->input_data(drive, NULL,
                                                        pc->cur_pos, temp);
@@ -410,7 +413,7 @@ cmd_finished:
        if ((drive->media == ide_floppy && !scsi && !pc->buf) ||
            (drive->media == ide_tape && !scsi && pc->bh) ||
            (scsi && pc->sg)) {
-               int done = io_buffers(drive, pc, bcount,
+               int done = drive->pc_io_buffers(drive, pc, bcount,
                                  !!(pc->flags & PC_FLAG_WRITING));
 
                /* FIXME: don't do partial completions */
@@ -427,10 +430,9 @@ cmd_finished:
                  rq->cmd[0], bcount);
 next_irq:
        /* And set the interrupt handler again */
-       ide_set_handler(drive, handler, timeout, expiry);
+       ide_set_handler(drive, ide_pc_intr, timeout, expiry);
        return ide_started;
 }
-EXPORT_SYMBOL_GPL(ide_pc_intr);
 
 static u8 ide_read_ireason(ide_drive_t *drive)
 {
@@ -466,13 +468,22 @@ static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
        return ireason;
 }
 
-ide_startstop_t ide_transfer_pc(ide_drive_t *drive,
-                               ide_handler_t *handler, unsigned int timeout,
-                               ide_expiry_t *expiry)
+static int ide_delayed_transfer_pc(ide_drive_t *drive)
+{
+       /* Send the actual packet */
+       drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12);
+
+       /* Timeout for the packet command */
+       return WAIT_FLOPPY_CMD;
+}
+
+static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
 {
        struct ide_atapi_pc *pc = drive->pc;
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq = hwif->hwgroup->rq;
+       ide_expiry_t *expiry;
+       unsigned int timeout;
        ide_startstop_t startstop;
        u8 ireason;
 
@@ -483,7 +494,8 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive,
        }
 
        ireason = ide_read_ireason(drive);
-       if (drive->media == ide_tape && !drive->scsi)
+       if (drive->media == ide_tape &&
+           (drive->dev_flags & IDE_DFLAG_SCSI) == 0)
                ireason = ide_wait_ireason(drive, ireason);
 
        if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
@@ -492,8 +504,27 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive,
                return ide_do_reset(drive);
        }
 
+       /*
+        * If necessary schedule the packet transfer to occur 'timeout'
+        * miliseconds later in ide_delayed_transfer_pc() after the device
+        * says it's ready for a packet.
+        */
+       if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
+               timeout = drive->pc_delay;
+               expiry = &ide_delayed_transfer_pc;
+       } else {
+               if (drive->dev_flags & IDE_DFLAG_SCSI) {
+                       timeout = ide_scsi_get_timeout(pc);
+                       expiry = ide_scsi_expiry;
+               } else {
+                       timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
+                                                              : WAIT_TAPE_CMD;
+                       expiry = NULL;
+               }
+       }
+
        /* Set the interrupt routine */
-       ide_set_handler(drive, handler, timeout, expiry);
+       ide_set_handler(drive, ide_pc_intr, timeout, expiry);
 
        /* Begin DMA, if necessary */
        if (pc->flags & PC_FLAG_DMA_OK) {
@@ -507,23 +538,22 @@ ide_startstop_t ide_transfer_pc(ide_drive_t *drive,
 
        return ide_started;
 }
-EXPORT_SYMBOL_GPL(ide_transfer_pc);
 
-ide_startstop_t ide_issue_pc(ide_drive_t *drive,
-                            ide_handler_t *handler, unsigned int timeout,
+ide_startstop_t ide_issue_pc(ide_drive_t *drive, unsigned int timeout,
                             ide_expiry_t *expiry)
 {
        struct ide_atapi_pc *pc = drive->pc;
        ide_hwif_t *hwif = drive->hwif;
+       u32 tf_flags;
        u16 bcount;
-       u8 dma = 0;
+       u8 scsi = !!(drive->dev_flags & IDE_DFLAG_SCSI);
 
        /* We haven't transferred any data yet */
        pc->xferred = 0;
        pc->cur_pos = pc->buf;
 
        /* Request to transfer the entire buffer at once */
-       if (drive->media == ide_tape && !drive->scsi)
+       if (drive->media == ide_tape && scsi == 0)
                bcount = pc->req_xfer;
        else
                bcount = min(pc->req_xfer, 63 * 1024);
@@ -533,28 +563,35 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive,
                ide_dma_off(drive);
        }
 
-       if ((pc->flags & PC_FLAG_DMA_OK) && drive->using_dma) {
-               if (drive->scsi)
+       if ((pc->flags & PC_FLAG_DMA_OK) &&
+           (drive->dev_flags & IDE_DFLAG_USING_DMA)) {
+               if (scsi)
                        hwif->sg_mapped = 1;
-               dma = !hwif->dma_ops->dma_setup(drive);
-               if (drive->scsi)
+               drive->dma = !hwif->dma_ops->dma_setup(drive);
+               if (scsi)
                        hwif->sg_mapped = 0;
        }
 
-       if (!dma)
+       if (!drive->dma)
                pc->flags &= ~PC_FLAG_DMA_OK;
 
-       ide_pktcmd_tf_load(drive, drive->scsi ? 0 : IDE_TFLAG_OUT_DEVICE,
-                          bcount, dma);
+       if (scsi)
+               tf_flags = 0;
+       else if (drive->media == ide_cdrom || drive->media == ide_optical)
+               tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
+       else
+               tf_flags = IDE_TFLAG_OUT_DEVICE;
+
+       ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma);
 
        /* Issue the packet command */
        if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
-               ide_execute_command(drive, ATA_CMD_PACKET, handler,
+               ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc,
                                    timeout, NULL);
                return ide_started;
        } else {
                ide_execute_pkt_cmd(drive);
-               return (*handler)(drive);
+               return ide_transfer_pc(drive);
        }
 }
 EXPORT_SYMBOL_GPL(ide_issue_pc);