ide: add struct ide_tp_ops (take 2)

* Add struct ide_tp_ops for transport methods.

* Add 'const struct ide_tp_ops *tp_ops' to struct ide_port_info
  and ide_hwif_t.

* Set the default hwif->tp_ops in ide_init_port_data().

* Set host driver specific hwif->tp_ops in ide_init_port().

* Export ide_exec_command(), ide_read_status(), ide_read_altstatus(),
  ide_read_sff_dma_status(), ide_set_irq(), ide_tf_{load,read}()
  and ata_{in,out}put_data().

* Convert host drivers and core code to use struct ide_tp_ops.

* Remove no longer needed default_hwif_transport().

* Cleanup ide_hwif_t from methods that are now in struct ide_tp_ops.

While at it:

* Use struct ide_port_info in falconide.c and q40ide.c.

* Rename ata_{in,out}put_data() to ide_{in,out}put_data().

v2:

* Fix missing convertion in ns87415.c.

There should be no functional changes caused by this patch.

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index c9d15be..07da5fb 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -68,7 +68,7 @@
 	memset(&task, 0, sizeof(task));
 	task.tf_flags = IDE_TFLAG_OUT_DEVICE;
 
-	drive->hwif->tf_load(drive, &task);
+	drive->hwif->tp_ops->tf_load(drive, &task);
 }
 
 void SELECT_MASK(ide_drive_t *drive, int mask)
@@ -79,39 +79,43 @@
 		port_ops->maskproc(drive, mask);
 }
 
-static void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
+void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
 {
 	if (hwif->host_flags & IDE_HFLAG_MMIO)
 		writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
 	else
 		outb(cmd, hwif->io_ports.command_addr);
 }
+EXPORT_SYMBOL_GPL(ide_exec_command);
 
-static u8 ide_read_status(ide_hwif_t *hwif)
+u8 ide_read_status(ide_hwif_t *hwif)
 {
 	if (hwif->host_flags & IDE_HFLAG_MMIO)
 		return readb((void __iomem *)hwif->io_ports.status_addr);
 	else
 		return inb(hwif->io_ports.status_addr);
 }
+EXPORT_SYMBOL_GPL(ide_read_status);
 
-static u8 ide_read_altstatus(ide_hwif_t *hwif)
+u8 ide_read_altstatus(ide_hwif_t *hwif)
 {
 	if (hwif->host_flags & IDE_HFLAG_MMIO)
 		return readb((void __iomem *)hwif->io_ports.ctl_addr);
 	else
 		return inb(hwif->io_ports.ctl_addr);
 }
+EXPORT_SYMBOL_GPL(ide_read_altstatus);
 
-static u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
+u8 ide_read_sff_dma_status(ide_hwif_t *hwif)
 {
 	if (hwif->host_flags & IDE_HFLAG_MMIO)
 		return readb((void __iomem *)(hwif->dma_base + ATA_DMA_STATUS));
 	else
 		return inb(hwif->dma_base + ATA_DMA_STATUS);
 }
+EXPORT_SYMBOL_GPL(ide_read_sff_dma_status);
 
-static void ide_set_irq(ide_hwif_t *hwif, int on)
+void ide_set_irq(ide_hwif_t *hwif, int on)
 {
 	u8 ctl = ATA_DEVCTL_OBS;
 
@@ -127,8 +131,9 @@
 	else
 		outb(ctl, hwif->io_ports.ctl_addr);
 }
+EXPORT_SYMBOL_GPL(ide_set_irq);
 
-static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -180,8 +185,9 @@
 		tf_outb((tf->device & HIHI) | drive->select.all,
 			 io_ports->device_addr);
 }
+EXPORT_SYMBOL_GPL(ide_tf_load);
 
-static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -241,6 +247,7 @@
 			tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
 	}
 }
+EXPORT_SYMBOL_GPL(ide_tf_read);
 
 /*
  * Some localbus EIDE interfaces require a special access sequence
@@ -263,8 +270,8 @@
  * so if an odd len is specified, be sure that there's at least one
  * extra byte allocated for the buffer.
  */
-static void ata_input_data(ide_drive_t *drive, struct request *rq,
-			   void *buf, unsigned int len)
+void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
+		    unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -304,12 +311,13 @@
 			insw(data_addr, buf, len / 2);
 	}
 }
+EXPORT_SYMBOL_GPL(ide_input_data);
 
 /*
  * This is used for most PIO data transfers *to* the IDE interface
  */
-static void ata_output_data(ide_drive_t *drive, struct request *rq,
-			    void *buf, unsigned int len)
+void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
+		     unsigned int len)
 {
 	ide_hwif_t *hwif = drive->hwif;
 	struct ide_io_ports *io_ports = &hwif->io_ports;
@@ -347,22 +355,7 @@
 			outsw(data_addr, buf, len / 2);
 	}
 }
-
-void default_hwif_transport(ide_hwif_t *hwif)
-{
-	hwif->exec_command	  = ide_exec_command;
-	hwif->read_status	  = ide_read_status;
-	hwif->read_altstatus	  = ide_read_altstatus;
-	hwif->read_sff_dma_status = ide_read_sff_dma_status;
-
-	hwif->set_irq	  = ide_set_irq;
-
-	hwif->tf_load	  = ide_tf_load;
-	hwif->tf_read	  = ide_tf_read;
-
-	hwif->input_data  = ata_input_data;
-	hwif->output_data = ata_output_data;
-}
+EXPORT_SYMBOL_GPL(ide_output_data);
 
 u8 ide_read_error(ide_drive_t *drive)
 {
@@ -371,7 +364,7 @@
 	memset(&task, 0, sizeof(task));
 	task.tf_flags = IDE_TFLAG_IN_FEATURE;
 
-	drive->hwif->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &task);
 
 	return task.tf.error;
 }
@@ -385,13 +378,28 @@
 	task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
 			IDE_TFLAG_IN_NSECT;
 
-	drive->hwif->tf_read(drive, &task);
+	drive->hwif->tp_ops->tf_read(drive, &task);
 
 	*bcount = (task.tf.lbah << 8) | task.tf.lbam;
 	*ireason = task.tf.nsect & 3;
 }
 EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
 
+const struct ide_tp_ops default_tp_ops = {
+	.exec_command		= ide_exec_command,
+	.read_status		= ide_read_status,
+	.read_altstatus		= ide_read_altstatus,
+	.read_sff_dma_status	= ide_read_sff_dma_status,
+
+	.set_irq		= ide_set_irq,
+
+	.tf_load		= ide_tf_load,
+	.tf_read		= ide_tf_read,
+
+	.input_data		= ide_input_data,
+	.output_data		= ide_output_data,
+};
+
 void ide_fix_driveid (struct hd_driveid *id)
 {
 #ifndef __LITTLE_ENDIAN
@@ -545,10 +553,10 @@
 	 * about possible isa-pnp and pci-pnp issues yet.
 	 */
 	if (hwif->io_ports.ctl_addr)
-		stat = hwif->read_altstatus(hwif);
+		stat = hwif->tp_ops->read_altstatus(hwif);
 	else
 		/* Note: this may clear a pending IRQ!! */
-		stat = hwif->read_status(hwif);
+		stat = hwif->tp_ops->read_status(hwif);
 
 	if (stat & BUSY_STAT)
 		/* drive busy:  definitely not interrupting */
@@ -574,24 +582,25 @@
 static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	unsigned long flags;
 	int i;
 	u8 stat;
 
 	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */
-	stat = hwif->read_status(hwif);
+	stat = tp_ops->read_status(hwif);
 
 	if (stat & BUSY_STAT) {
 		local_irq_set(flags);
 		timeout += jiffies;
-		while ((stat = hwif->read_status(hwif)) & BUSY_STAT) {
+		while ((stat = tp_ops->read_status(hwif)) & BUSY_STAT) {
 			if (time_after(jiffies, timeout)) {
 				/*
 				 * One last read after the timeout in case
 				 * heavy interrupt load made us not make any
 				 * progress during the timeout..
 				 */
-				stat = hwif->read_status(hwif);
+				stat = tp_ops->read_status(hwif);
 				if (!(stat & BUSY_STAT))
 					break;
 
@@ -611,7 +620,7 @@
 	 */
 	for (i = 0; i < 10; i++) {
 		udelay(1);
-		stat = hwif->read_status(hwif);
+		stat = tp_ops->read_status(hwif);
 
 		if (OK_STAT(stat, good, bad)) {
 			*rstat = stat;
@@ -737,6 +746,7 @@
 int ide_driveid_update(ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	struct hd_driveid *id;
 	unsigned long timeout, flags;
 	u8 stat;
@@ -747,9 +757,9 @@
 	 */
 
 	SELECT_MASK(drive, 1);
-	hwif->set_irq(hwif, 0);
+	tp_ops->set_irq(hwif, 0);
 	msleep(50);
-	hwif->exec_command(hwif, WIN_IDENTIFY);
+	tp_ops->exec_command(hwif, WIN_IDENTIFY);
 	timeout = jiffies + WAIT_WORSTCASE;
 	do {
 		if (time_after(jiffies, timeout)) {
@@ -758,11 +768,11 @@
 		}
 
 		msleep(50);	/* give drive a breather */
-		stat = hwif->read_altstatus(hwif);
+		stat = tp_ops->read_altstatus(hwif);
 	} while (stat & BUSY_STAT);
 
 	msleep(50);	/* wait for IRQ and DRQ_STAT */
-	stat = hwif->read_status(hwif);
+	stat = tp_ops->read_status(hwif);
 
 	if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
 		SELECT_MASK(drive, 0);
@@ -776,8 +786,8 @@
 		local_irq_restore(flags);
 		return 0;
 	}
-	hwif->input_data(drive, NULL, id, SECTOR_SIZE);
-	(void)hwif->read_status(hwif);	/* clear drive IRQ */
+	tp_ops->input_data(drive, NULL, id, SECTOR_SIZE);
+	(void)tp_ops->read_status(hwif);	/* clear drive IRQ */
 	local_irq_enable();
 	local_irq_restore(flags);
 	ide_fix_driveid(id);
@@ -798,6 +808,7 @@
 int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 {
 	ide_hwif_t *hwif = drive->hwif;
+	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
 	int error = 0;
 	u8 stat;
 	ide_task_t task;
@@ -833,19 +844,19 @@
 	SELECT_DRIVE(drive);
 	SELECT_MASK(drive, 0);
 	udelay(1);
-	hwif->set_irq(hwif, 0);
+	tp_ops->set_irq(hwif, 0);
 
 	memset(&task, 0, sizeof(task));
 	task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT;
 	task.tf.feature = SETFEATURES_XFER;
 	task.tf.nsect   = speed;
 
-	hwif->tf_load(drive, &task);
+	tp_ops->tf_load(drive, &task);
 
-	hwif->exec_command(hwif, WIN_SETFEATURES);
+	tp_ops->exec_command(hwif, WIN_SETFEATURES);
 
 	if (drive->quirk_list == 2)
-		hwif->set_irq(hwif, 1);
+		tp_ops->set_irq(hwif, 1);
 
 	error = __ide_wait_stat(drive, drive->ready_stat,
 				BUSY_STAT|DRQ_STAT|ERR_STAT,
@@ -950,7 +961,7 @@
 
 	spin_lock_irqsave(&ide_lock, flags);
 	__ide_set_handler(drive, handler, timeout, expiry);
-	hwif->exec_command(hwif, cmd);
+	hwif->tp_ops->exec_command(hwif, cmd);
 	/*
 	 * Drive takes 400nS to respond, we must avoid the IRQ being
 	 * serviced before that.
@@ -968,7 +979,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&ide_lock, flags);
-	hwif->exec_command(hwif, WIN_PACKETCMD);
+	hwif->tp_ops->exec_command(hwif, WIN_PACKETCMD);
 	ndelay(400);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
@@ -999,7 +1010,7 @@
 
 	SELECT_DRIVE(drive);
 	udelay (10);
-	stat = hwif->read_status(hwif);
+	stat = hwif->tp_ops->read_status(hwif);
 
 	if (OK_STAT(stat, 0, BUSY_STAT))
 		printk("%s: ATAPI reset complete\n", drive->name);
@@ -1045,7 +1056,7 @@
 		}
 	}
 
-	tmp = hwif->read_status(hwif);
+	tmp = hwif->tp_ops->read_status(hwif);
 
 	if (!OK_STAT(tmp, 0, BUSY_STAT)) {
 		if (time_before(jiffies, hwgroup->poll_timeout)) {
@@ -1159,6 +1170,7 @@
 	ide_hwif_t *hwif;
 	ide_hwgroup_t *hwgroup;
 	struct ide_io_ports *io_ports;
+	const struct ide_tp_ops *tp_ops;
 	const struct ide_port_ops *port_ops;
 
 	spin_lock_irqsave(&ide_lock, flags);
@@ -1167,6 +1179,8 @@
 
 	io_ports = &hwif->io_ports;
 
+	tp_ops = hwif->tp_ops;
+
 	/* We must not reset with running handlers */
 	BUG_ON(hwgroup->handler != NULL);
 
@@ -1175,7 +1189,7 @@
 		pre_reset(drive);
 		SELECT_DRIVE(drive);
 		udelay (20);
-		hwif->exec_command(hwif, WIN_SRST);
+		tp_ops->exec_command(hwif, WIN_SRST);
 		ndelay(400);
 		hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
 		hwgroup->polling = 1;
@@ -1208,11 +1222,11 @@
 	 * TODO: add ->softreset method and stop abusing ->set_irq
 	 */
 	/* set SRST and nIEN */
-	hwif->set_irq(hwif, 4);
+	tp_ops->set_irq(hwif, 4);
 	/* more than enough time */
 	udelay(10);
 	/* clear SRST, leave nIEN (unless device is on the quirk list) */
-	hwif->set_irq(hwif, drive->quirk_list == 2);
+	tp_ops->set_irq(hwif, drive->quirk_list == 2);
 	/* more than enough time */
 	udelay(10);
 	hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
@@ -1257,7 +1271,7 @@
 		 * about locking issues (2.5 work ?).
 		 */
 		mdelay(1);
-		stat = hwif->read_status(hwif);
+		stat = hwif->tp_ops->read_status(hwif);
 		if ((stat & BUSY_STAT) == 0)
 			return 0;
 		/*