Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07f6f7d0 authored by Albert Lee's avatar Albert Lee Committed by Jeff Garzik
Browse files

[PATCH] libata irq-pio: add read/write multiple support



   - add is_multi_taskfile() to ata.h
   - initialize ata_device->multi_count with device identify data
   - use ata_pio_sectors() to support r/w multiple commands

Signed-off-by: default avatarAlbert Lee <albertcc@tw.ibm.com>

========
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent fbcdd80b
Loading
Loading
Loading
Loading
+38 −6
Original line number Diff line number Diff line
@@ -1261,6 +1261,12 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)

		}

		if (dev->id[59] & 0x100) {
			dev->multi_count = dev->id[59] & 0xff;
			DPRINTK("ata%u: dev %u multi count %u\n",
				ap->id, device, dev->multi_count);
		}

		ap->host->max_cmd_len = 16;
	}

@@ -2804,7 +2810,7 @@ static int ata_pio_complete (struct ata_port *ap)
	 * we enter, BSY will be cleared in a chk-status or two.  If not,
	 * the drive is probably seeking or something.  Snooze for a couple
	 * msecs, then chk-status again.  If still busy, fall back to
	 * HSM_ST_POLL state.
	 * HSM_ST_LAST_POLL state.
	 */
	drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
	if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
@@ -3020,6 +3026,32 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
	}
}

/**
 *	ata_pio_sectors - Transfer one or many 512-byte sectors.
 *	@qc: Command on going
 *
 *	Transfer one or many ATA_SECT_SIZE of data from/to the 
 *	ATA device for the DRQ request.
 *
 *	LOCKING:
 *	Inherited from caller.
 */

static void ata_pio_sectors(struct ata_queued_cmd *qc)
{
	if (is_multi_taskfile(&qc->tf)) {
		/* READ/WRITE MULTIPLE */
		unsigned int nsect;

		assert(qc->dev->multi_count);

		nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
		while (nsect--)
			ata_pio_sector(qc);
	} else
		ata_pio_sector(qc);
}

/**
 *	atapi_send_cdb - Write CDB bytes to hardware
 *	@ap: Port to which ATAPI device is attached.
@@ -3118,11 +3150,11 @@ static int ata_pio_first_block(struct ata_port *ap)
		 * send first data block.
		 */

		/* ata_pio_sector() might change the state to HSM_ST_LAST.
		 * so, the state is changed here before ata_pio_sector().
		/* ata_pio_sectors() might change the state to HSM_ST_LAST.
		 * so, the state is changed here before ata_pio_sectors().
		 */
		ap->hsm_task_state = HSM_ST;
		ata_pio_sector(qc);
		ata_pio_sectors(qc);
		ata_altstatus(ap); /* flush */
	} else
		/* send CDB */
@@ -3327,7 +3359,7 @@ static void ata_pio_block(struct ata_port *ap)
			return;
		}

		ata_pio_sector(qc);
		ata_pio_sectors(qc);
	}

	ata_altstatus(ap); /* flush */
@@ -4213,7 +4245,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
				goto fsm_start;
			}

			ata_pio_sector(qc);
			ata_pio_sectors(qc);

			if (ap->hsm_task_state == HSM_ST_LAST &&
			    (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
+8 −0
Original line number Diff line number Diff line
@@ -293,6 +293,14 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
	       (tf->protocol == ATA_PROT_ATAPI_DMA);
}

static inline int is_multi_taskfile(struct ata_taskfile *tf)
{
	return (tf->command == ATA_CMD_READ_MULTI) ||
	       (tf->command == ATA_CMD_WRITE_MULTI) ||
	       (tf->command == ATA_CMD_READ_MULTI_EXT) ||
	       (tf->command == ATA_CMD_WRITE_MULTI_EXT);
}

static inline int ata_ok(u8 status)
{
	return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))