mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-29 23:24:11 +08:00
[PATCH] libata CHS: calculate read/write commands and protocol on the fly (revise #6)
- merge ata_prot_to_cmd() and ata_dev_set_protocol() as ata_rwcmd_protocol() - pave road for read/write multiple support - remove usage of pre-cached command and protocol values and call ata_rwcmd_protocol() instead Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ============== Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
This commit is contained in:
parent
07506697d1
commit
8cbd6df1f0
@ -616,79 +616,53 @@ void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf)
|
|||||||
tf->hob_nsect = fis[13];
|
tf->hob_nsect = fis[13];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static const u8 ata_rw_cmds[] = {
|
||||||
* ata_prot_to_cmd - determine which read/write opcodes to use
|
/* pio multi */
|
||||||
* @protocol: ATA_PROT_xxx taskfile protocol
|
ATA_CMD_READ_MULTI,
|
||||||
* @lba48: true is lba48 is present
|
ATA_CMD_WRITE_MULTI,
|
||||||
*
|
ATA_CMD_READ_MULTI_EXT,
|
||||||
* Given necessary input, determine which read/write commands
|
ATA_CMD_WRITE_MULTI_EXT,
|
||||||
* to use to transfer data.
|
/* pio */
|
||||||
*
|
ATA_CMD_PIO_READ,
|
||||||
* LOCKING:
|
ATA_CMD_PIO_WRITE,
|
||||||
* None.
|
ATA_CMD_PIO_READ_EXT,
|
||||||
*/
|
ATA_CMD_PIO_WRITE_EXT,
|
||||||
static int ata_prot_to_cmd(int protocol, int lba48)
|
/* dma */
|
||||||
{
|
ATA_CMD_READ,
|
||||||
int rcmd = 0, wcmd = 0;
|
ATA_CMD_WRITE,
|
||||||
|
ATA_CMD_READ_EXT,
|
||||||
switch (protocol) {
|
ATA_CMD_WRITE_EXT
|
||||||
case ATA_PROT_PIO:
|
};
|
||||||
if (lba48) {
|
|
||||||
rcmd = ATA_CMD_PIO_READ_EXT;
|
|
||||||
wcmd = ATA_CMD_PIO_WRITE_EXT;
|
|
||||||
} else {
|
|
||||||
rcmd = ATA_CMD_PIO_READ;
|
|
||||||
wcmd = ATA_CMD_PIO_WRITE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ATA_PROT_DMA:
|
|
||||||
if (lba48) {
|
|
||||||
rcmd = ATA_CMD_READ_EXT;
|
|
||||||
wcmd = ATA_CMD_WRITE_EXT;
|
|
||||||
} else {
|
|
||||||
rcmd = ATA_CMD_READ;
|
|
||||||
wcmd = ATA_CMD_WRITE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rcmd | (wcmd << 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_dev_set_protocol - set taskfile protocol and r/w commands
|
* ata_rwcmd_protocol - set taskfile r/w commands and protocol
|
||||||
* @dev: device to examine and configure
|
* @qc: command to examine and configure
|
||||||
*
|
*
|
||||||
* Examine the device configuration, after we have
|
* Examine the device configuration and tf->flags to calculate
|
||||||
* read the identify-device page and configured the
|
* the proper read/write commands and protocol to use.
|
||||||
* data transfer mode. Set internal state related to
|
|
||||||
* the ATA taskfile protocol (pio, pio mult, dma, etc.)
|
|
||||||
* and calculate the proper read/write commands to use.
|
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* caller.
|
* caller.
|
||||||
*/
|
*/
|
||||||
static void ata_dev_set_protocol(struct ata_device *dev)
|
void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
int pio = (dev->flags & ATA_DFLAG_PIO);
|
struct ata_taskfile *tf = &qc->tf;
|
||||||
int lba48 = (dev->flags & ATA_DFLAG_LBA48);
|
struct ata_device *dev = qc->dev;
|
||||||
int proto, cmd;
|
|
||||||
|
|
||||||
if (pio)
|
int index, lba48, write;
|
||||||
proto = dev->xfer_protocol = ATA_PROT_PIO;
|
|
||||||
else
|
lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
|
||||||
proto = dev->xfer_protocol = ATA_PROT_DMA;
|
write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
|
||||||
|
|
||||||
cmd = ata_prot_to_cmd(proto, lba48);
|
if (dev->flags & ATA_DFLAG_PIO) {
|
||||||
if (cmd < 0)
|
tf->protocol = ATA_PROT_PIO;
|
||||||
BUG();
|
index = dev->multi_count ? 0 : 4;
|
||||||
|
} else {
|
||||||
|
tf->protocol = ATA_PROT_DMA;
|
||||||
|
index = 8;
|
||||||
|
}
|
||||||
|
|
||||||
dev->read_cmd = cmd & 0xff;
|
tf->command = ata_rw_cmds[index + lba48 + write];
|
||||||
dev->write_cmd = (cmd >> 8) & 0xff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * xfer_mode_str[] = {
|
static const char * xfer_mode_str[] = {
|
||||||
@ -1641,7 +1615,7 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
|
|||||||
*/
|
*/
|
||||||
static void ata_set_mode(struct ata_port *ap)
|
static void ata_set_mode(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
unsigned int i, xfer_shift;
|
unsigned int xfer_shift;
|
||||||
u8 xfer_mode;
|
u8 xfer_mode;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -1670,11 +1644,6 @@ static void ata_set_mode(struct ata_port *ap)
|
|||||||
if (ap->ops->post_set_mode)
|
if (ap->ops->post_set_mode)
|
||||||
ap->ops->post_set_mode(ap);
|
ap->ops->post_set_mode(ap);
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
|
||||||
struct ata_device *dev = &ap->device[i];
|
|
||||||
ata_dev_set_protocol(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
|
@ -742,15 +742,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
|||||||
u32 n_block;
|
u32 n_block;
|
||||||
|
|
||||||
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
|
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
|
||||||
tf->protocol = qc->dev->xfer_protocol;
|
|
||||||
|
|
||||||
if (scsicmd[0] == READ_10 || scsicmd[0] == READ_6 ||
|
if (scsicmd[0] == WRITE_10 || scsicmd[0] == WRITE_6 ||
|
||||||
scsicmd[0] == READ_16) {
|
scsicmd[0] == WRITE_16)
|
||||||
tf->command = qc->dev->read_cmd;
|
|
||||||
} else {
|
|
||||||
tf->command = qc->dev->write_cmd;
|
|
||||||
tf->flags |= ATA_TFLAG_WRITE;
|
tf->flags |= ATA_TFLAG_WRITE;
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the SCSI LBA and transfer length. */
|
/* Calculate the SCSI LBA and transfer length. */
|
||||||
switch (scsicmd[0]) {
|
switch (scsicmd[0]) {
|
||||||
@ -812,6 +807,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
|||||||
tf->device |= (block >> 24) & 0xf;
|
tf->device |= (block >> 24) & 0xf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ata_rwcmd_protocol(qc);
|
||||||
|
|
||||||
qc->nsect = n_block;
|
qc->nsect = n_block;
|
||||||
tf->nsect = n_block & 0xff;
|
tf->nsect = n_block & 0xff;
|
||||||
|
|
||||||
@ -828,6 +825,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
|||||||
if ((block >> 28) || (n_block > 256))
|
if ((block >> 28) || (n_block > 256))
|
||||||
goto out_of_range;
|
goto out_of_range;
|
||||||
|
|
||||||
|
ata_rwcmd_protocol(qc);
|
||||||
|
|
||||||
/* Convert LBA to CHS */
|
/* Convert LBA to CHS */
|
||||||
track = (u32)block / dev->sectors;
|
track = (u32)block / dev->sectors;
|
||||||
cyl = track / dev->heads;
|
cyl = track / dev->heads;
|
||||||
|
@ -42,6 +42,7 @@ extern int atapi_enabled;
|
|||||||
extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
|
extern int ata_qc_complete_noop(struct ata_queued_cmd *qc, u8 drv_stat);
|
||||||
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
|
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
|
||||||
struct ata_device *dev);
|
struct ata_device *dev);
|
||||||
|
extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc);
|
||||||
extern void ata_qc_free(struct ata_queued_cmd *qc);
|
extern void ata_qc_free(struct ata_queued_cmd *qc);
|
||||||
extern int ata_qc_issue(struct ata_queued_cmd *qc);
|
extern int ata_qc_issue(struct ata_queued_cmd *qc);
|
||||||
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
|
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
|
||||||
|
@ -128,6 +128,10 @@ enum {
|
|||||||
ATA_CMD_PIO_READ_EXT = 0x24,
|
ATA_CMD_PIO_READ_EXT = 0x24,
|
||||||
ATA_CMD_PIO_WRITE = 0x30,
|
ATA_CMD_PIO_WRITE = 0x30,
|
||||||
ATA_CMD_PIO_WRITE_EXT = 0x34,
|
ATA_CMD_PIO_WRITE_EXT = 0x34,
|
||||||
|
ATA_CMD_READ_MULTI = 0xC4,
|
||||||
|
ATA_CMD_READ_MULTI_EXT = 0x29,
|
||||||
|
ATA_CMD_WRITE_MULTI = 0xC5,
|
||||||
|
ATA_CMD_WRITE_MULTI_EXT = 0x39,
|
||||||
ATA_CMD_SET_FEATURES = 0xEF,
|
ATA_CMD_SET_FEATURES = 0xEF,
|
||||||
ATA_CMD_PACKET = 0xA0,
|
ATA_CMD_PACKET = 0xA0,
|
||||||
ATA_CMD_VERIFY = 0x40,
|
ATA_CMD_VERIFY = 0x40,
|
||||||
|
@ -283,10 +283,8 @@ struct ata_device {
|
|||||||
u8 xfer_mode;
|
u8 xfer_mode;
|
||||||
unsigned int xfer_shift; /* ATA_SHIFT_xxx */
|
unsigned int xfer_shift; /* ATA_SHIFT_xxx */
|
||||||
|
|
||||||
/* cache info about current transfer mode */
|
unsigned int multi_count; /* sectors count for
|
||||||
u8 xfer_protocol; /* taskfile xfer protocol */
|
READ/WRITE MULTIPLE */
|
||||||
u8 read_cmd; /* opcode to use on read */
|
|
||||||
u8 write_cmd; /* opcode to use on write */
|
|
||||||
|
|
||||||
/* for CHS addressing */
|
/* for CHS addressing */
|
||||||
u16 cylinders; /* Number of cylinders */
|
u16 cylinders; /* Number of cylinders */
|
||||||
|
Loading…
Reference in New Issue
Block a user