#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/kmod.h>
+#include <linux/scatterlist.h>
#include <asm/byteorder.h>
#include <asm/irq.h>
return ide_stopped;
}
-EXPORT_SYMBOL(ide_error);
-
/**
* ide_abort - abort pending IDE operatins
* @drive: drive the error occurred on
* This differs fundamentally from ide_error because in
* this case the command is doing just fine when we
* blow it away.
+ *
+ * FIXME: need to fix locking corner cases
*/
ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
{
ide_hwif_t *hwif;
struct request *rq;
+ unsigned long flags;
- if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
+ spin_lock_irqsave(&ide_lock, flags);
+ if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL) {
+ spin_unlock_irqrestore(&ide_lock, flags);
return ide_stopped;
-
+ }
hwif = HWIF(drive);
/* retry only "normal" I/O: */
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
rq->errors = 1;
+ spin_unlock_irqrestore(&ide_lock, flags);
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
if (rq->flags & REQ_DRIVE_TASKFILE) {
rq->errors = 1;
+ spin_unlock_irqrestore(&ide_lock, flags);
ide_end_drive_cmd(drive, BUSY_STAT, 0);
return ide_stopped;
}
rq->errors |= ERROR_RESET;
+ spin_unlock_irqrestore(&ide_lock, flags);
DRIVER(drive)->end_request(drive, 0, 0);
return ide_stopped;
}
-EXPORT_SYMBOL(ide_abort);
-
/**
* ide_cmd - issue a simple drive command
* @drive: drive the command is for
* The drive must be selected beforehand.
*/
-void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler)
+static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
+ ide_handler_t *handler)
{
ide_hwif_t *hwif = HWIF(drive);
if (IDE_CONTROL_REG)
ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
}
-EXPORT_SYMBOL(ide_cmd);
-
/**
* drive_cmd_intr - drive command completion interrupt
* @drive: drive the completion interrupt occurred on
* the request
*/
-ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
+static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
{
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
return ide_stopped;
}
-EXPORT_SYMBOL(drive_cmd_intr);
-
/**
* do_special - issue some special commands
* @drive: drive the command is for
* back.
*/
-ide_startstop_t do_special (ide_drive_t *drive)
+static ide_startstop_t do_special (ide_drive_t *drive)
{
special_t *s = &drive->special;
return DRIVER(drive)->special(drive);
}
-EXPORT_SYMBOL(do_special);
+void ide_map_sg(ide_drive_t *drive, struct request *rq)
+{
+ ide_hwif_t *hwif = drive->hwif;
+ struct scatterlist *sg = hwif->sg_table;
+
+ if (hwif->sg_mapped) /* needed by ide-scsi */
+ return;
+
+ if ((rq->flags & REQ_DRIVE_TASKFILE) == 0) {
+ hwif->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
+ } else {
+ sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE);
+ hwif->sg_nents = 1;
+ }
+}
+
+EXPORT_SYMBOL_GPL(ide_map_sg);
+
+void ide_init_sg_cmd(ide_drive_t *drive, struct request *rq)
+{
+ ide_hwif_t *hwif = drive->hwif;
+
+ hwif->nsect = hwif->nleft = rq->nr_sectors;
+ hwif->cursg = hwif->cursg_ofs = 0;
+}
+
+EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
/**
* execute_drive_command - issue special drive command
* all commands to finish. Don't do this as that is due to change
*/
-ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
+ struct request *rq)
{
ide_hwif_t *hwif = HWIF(drive);
if (rq->flags & REQ_DRIVE_TASKFILE) {
hwif->data_phase = args->data_phase;
+ switch (hwif->data_phase) {
+ case TASKFILE_MULTI_OUT:
+ case TASKFILE_OUT:
+ case TASKFILE_MULTI_IN:
+ case TASKFILE_IN:
+ ide_init_sg_cmd(drive, rq);
+ ide_map_sg(drive, rq);
+ default:
+ break;
+ }
+
if (args->tf_out_flags.all != 0)
return flagged_taskfile(drive, args);
return do_rw_taskfile(drive, args);
return ide_stopped;
}
-EXPORT_SYMBOL(execute_drive_cmd);
-
/**
* start_request - start of I/O and command issuing for IDE
*
* FIXME: this function needs a rename
*/
-ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
+static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
{
ide_startstop_t startstop;
sector_t block;
return ide_stopped;
}
-EXPORT_SYMBOL(start_request);
-
/**
* ide_stall_queue - pause an IDE device
* @drive: drive to stall
* the driver. This makes the driver much more friendlier to shared IRQs
* than previous designs, while remaining 100% (?) SMP safe and capable.
*/
-/* --BenH: made non-static as ide-pmac.c uses it to kick the hwgroup back
- * into life on wakeup from machine sleep.
- */
-void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
{
ide_drive_t *drive;
ide_hwif_t *hwif;
}
}
-EXPORT_SYMBOL(ide_do_request);
-
/*
* Passes the stuff to ide_do_request
*/
HWGROUP(drive)->rq = NULL;
rq->errors = 0;
+
+ if (!rq->bio)
+ goto out;
+
rq->sector = rq->bio->bi_sector;
rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
rq->hard_cur_sectors = rq->current_nr_sectors;
- if (rq->bio)
- rq->buffer = NULL;
-
+ rq->buffer = bio_data(rq->bio);
+out:
return ret;
}
spin_unlock_irqrestore(&ide_lock, flags);
}
-EXPORT_SYMBOL(ide_timer_expiry);
-
/**
* unexpected_intr - handle an unexpected IDE interrupt
* @irq: interrupt line
return IRQ_NONE;
}
+ if (hwif->polling) {
+ /* We took an interrupt during a polled drive retune.
+ This should go away eventually when that code uses
+ the polling logic like do_reset1 */
+ spin_unlock_irqrestore(&ide_lock, flags);
+ return IRQ_HANDLED;
+ }
if ((handler = hwgroup->handler) == NULL ||
hwgroup->poll_timeout != 0) {
/*
return IRQ_HANDLED;
}
-EXPORT_SYMBOL(ide_intr);
-
/**
* ide_init_drive_cmd - initialize a drive command request
* @rq: request object
int where = ELEVATOR_INSERT_BACK, err;
int must_wait = (action == ide_wait || action == ide_head_wait);
-#ifdef CONFIG_BLK_DEV_PDC4030
- /*
- * FIXME: there should be a drive or hwif->special
- * handler that points here by default, not hacks
- * in the ide-io.c code
- *
- * FIXME2: That code breaks power management if used with
- * this chipset, that really doesn't belong here !
- */
- if (HWIF(drive)->chipset == ide_pdc4030 && rq->buffer != NULL)
- return -ENOSYS; /* special drive cmds not supported */
-#endif
rq->errors = 0;
rq->rq_status = RQ_ACTIVE;