* [PATCH] libata MWDMA support, xfer mode rework
@ 2004-07-04 21:38 Jeff Garzik
0 siblings, 0 replies; only message in thread
From: Jeff Garzik @ 2004-07-04 21:38 UTC (permalink / raw)
To: linux-ide; +Cc: Bartlomiej Zolnierkiewicz
[-- Attachment #1: Type: text/plain, Size: 281 bytes --]
Since I need MWDMA support to make a few of my CD-ROMs work :) I hacked
it into libata. It doesn't seem to break anything.
But enable the #if 0 in ata_piix (enables mwdma timings), the IDE
controller locks up. So, more work needed, probably in the ata_piix driver.
Jeff
[-- Attachment #2: patch --]
[-- Type: text/plain, Size: 28971 bytes --]
# ChangeSet
# 2004/07/04 17:35:29-04:00 jgarzik@pobox.com
# [libata] transfer mode cleanup
#
# Add MWDMA support, and rework pio/mwdma/udma mode setup.
#
# In the lone test case for PATA support, ata_piix, MWDMA mode setting
# does not appear to work here. UDMA and PIO continue to work, so nobody
# will really notice. But beware. Probably a driver problem, not
# a bug in the core.
#
# Also, doesn't bother writing to dummy timing registers on ICH5/6 SATA
# anymore.
#
diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/ata_piix.c 2004-07-04 17:35:44 -04:00
@@ -65,10 +65,8 @@
static void piix_pata_phy_reset(struct ata_port *ap);
static void piix_sata_phy_reset(struct ata_port *ap);
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
- unsigned int pio);
-static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
- unsigned int udma);
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev);
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev);
static unsigned int in_module_init = 1;
@@ -126,7 +124,7 @@
static struct ata_port_operations piix_pata_ops = {
.port_disable = ata_port_disable,
.set_piomode = piix_set_piomode,
- .set_udmamode = piix_set_udmamode,
+ .set_dmamode = piix_set_dmamode,
.tf_load = ata_tf_load_pio,
.tf_read = ata_tf_read_pio,
@@ -151,8 +149,6 @@
static struct ata_port_operations piix_sata_ops = {
.port_disable = ata_port_disable,
- .set_piomode = piix_set_piomode,
- .set_udmamode = piix_set_udmamode,
.tf_load = ata_tf_load_pio,
.tf_read = ata_tf_read_pio,
@@ -181,7 +177,12 @@
.sht = &piix_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST |
PIIX_FLAG_CHECKINTR,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
+#if 0
+ .mwdma_mask = 0x06, /* mwdma1-2 */
+#else
+ .mwdma_mask = 0x00, /* mwdma broken */
+#endif
.udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */
.port_ops = &piix_pata_ops,
},
@@ -191,8 +192,9 @@
.sht = &piix_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR,
- .pio_mask = 0x03, /* pio3-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops,
},
@@ -200,7 +202,12 @@
{
.sht = &piix_sht,
.host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
+#if 0
+ .mwdma_mask = 0x06, /* mwdma1-2 */
+#else
+ .mwdma_mask = 0x00, /* mwdma broken */
+#endif
.udma_mask = ATA_UDMA_MASK_40C, /* FIXME: cbl det */
.port_ops = &piix_pata_ops,
},
@@ -211,8 +218,9 @@
.host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR |
ATA_FLAG_SLAVE_POSS,
- .pio_mask = 0x03, /* pio3-4 */
- .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 */
.port_ops = &piix_sata_ops,
},
};
@@ -368,9 +376,9 @@
* None (inherited from caller).
*/
-static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev,
- unsigned int pio)
+static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev)
{
+ unsigned int pio = adev->pio_mode;
struct pci_dev *dev = ap->host_set->pdev;
unsigned int is_slave = (adev->flags & ATA_DFLAG_MASTER) ? 0 : 1;
unsigned int master_port= ap->port_no ? 0x42 : 0x40;
@@ -409,7 +417,7 @@
}
/**
- * piix_set_udmamode - Initialize host controller PATA PIO timings
+ * piix_set_dmamode - Initialize host controller PATA PIO timings
* @ap: Port whose timings we are configuring
* @adev: um
* @udma: udma mode, 0 - 6
@@ -420,9 +428,9 @@
* None (inherited from caller).
*/
-static void piix_set_udmamode (struct ata_port *ap, struct ata_device *adev,
- unsigned int udma)
+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev)
{
+ unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */
struct pci_dev *dev = ap->host_set->pdev;
u8 maslave = ap->port_no ? 0x42 : 0x40;
u8 speed = udma;
@@ -452,25 +460,38 @@
case XFER_UDMA_3:
case XFER_UDMA_1: u_speed = 1 << (drive_dn * 4); break;
case XFER_UDMA_0: u_speed = 0 << (drive_dn * 4); break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1: break;
default:
BUG();
return;
}
- if (!(reg48 & u_flag))
- pci_write_config_byte(dev, 0x48, reg48 | u_flag);
- if (speed == XFER_UDMA_5) {
- pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+ if (speed >= XFER_UDMA_0) {
+ if (!(reg48 & u_flag))
+ pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+ if (speed == XFER_UDMA_5) {
+ pci_write_config_byte(dev, 0x55, (u8) reg55|w_flag);
+ } else {
+ pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+ }
+ if ((reg4a & a_speed) != u_speed)
+ pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
+ if (speed > XFER_UDMA_2) {
+ if (!(reg54 & v_flag))
+ pci_write_config_byte(dev, 0x54, reg54 | v_flag);
+ } else
+ pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
} else {
- pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
+ if (reg48 & u_flag)
+ pci_write_config_byte(dev, 0x48, reg48 & ~u_flag);
+ if (reg4a & a_speed)
+ pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
+ if (reg54 & v_flag)
+ pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
+ if (reg55 & w_flag)
+ pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
}
- if ((reg4a & a_speed) != u_speed)
- pci_write_config_word(dev, 0x4a, (reg4a & ~a_speed) | u_speed);
- if (speed > XFER_UDMA_2) {
- if (!(reg54 & v_flag))
- pci_write_config_byte(dev, 0x54, reg54 | v_flag);
- } else
- pci_write_config_byte(dev, 0x54, reg54 & ~v_flag);
}
/* move to PCI layer, integrate w/ MSI stuff */
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/libata-core.c 2004-07-04 17:35:44 -04:00
@@ -50,11 +50,13 @@
unsigned long tmout_pat,
unsigned long tmout);
static void __ata_dev_select (struct ata_port *ap, unsigned int device);
-static void ata_host_set_pio(struct ata_port *ap);
-static void ata_host_set_udma(struct ata_port *ap);
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device);
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device);
static void ata_set_mode(struct ata_port *ap);
+static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev);
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift);
+static int fgb(unsigned long bitmap);
+static int ata_choose_xfer_mode(struct ata_port *ap,
+ unsigned int *xfer_mode_out,
+ unsigned int *xfer_shift_out);
static unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
@@ -524,7 +526,7 @@
dev->write_cmd = (cmd >> 8) & 0xff;
}
-static const char * udma_str[] = {
+static const char * xfer_mode_str[] = {
"UDMA/16",
"UDMA/25",
"UDMA/33",
@@ -533,6 +535,14 @@
"UDMA/100",
"UDMA/133",
"UDMA7",
+ "MWDMA0",
+ "MWDMA1",
+ "MWDMA2",
+ "PIO0",
+ "PIO1",
+ "PIO2",
+ "PIO3",
+ "PIO4",
};
/**
@@ -550,16 +560,24 @@
* @udma_mask, or the constant C string "<n/a>".
*/
-static const char *ata_udma_string(unsigned int udma_mask)
+static const char *ata_mode_string(unsigned int mask)
{
int i;
- for (i = 7; i >= 0; i--) {
- if (udma_mask & (1 << i))
- return udma_str[i];
- }
+ for (i = 7; i >= 0; i--)
+ if (mask & (1 << i))
+ goto out;
+ for (i = ATA_SHIFT_MWDMA + 2; i >= ATA_SHIFT_MWDMA; i--)
+ if (mask & (1 << i))
+ goto out;
+ for (i = ATA_SHIFT_PIO + 4; i >= ATA_SHIFT_PIO; i--)
+ if (mask & (1 << i))
+ goto out;
return "<n/a>";
+
+out:
+ return xfer_mode_str[i];
}
/**
@@ -930,7 +948,7 @@
{
struct ata_device *dev = &ap->device[device];
unsigned int i;
- u16 tmp, udma_modes;
+ u16 tmp, xfer_modes;
u8 status;
struct ata_taskfile tf;
unsigned int using_edd;
@@ -1046,11 +1064,12 @@
}
/* we require UDMA support */
- udma_modes =
- tmp = dev->id[ATA_ID_UDMA_MODES];
- if ((tmp & 0xff) == 0) {
- printk(KERN_DEBUG "ata%u: no udma\n", ap->id);
- goto err_out_nosup;
+ xfer_modes = dev->id[ATA_ID_UDMA_MODES];
+ if (!xfer_modes)
+ xfer_modes = (dev->id[ATA_ID_MWDMA_MODES]) << ATA_SHIFT_MWDMA;
+ if (!xfer_modes) {
+ xfer_modes = (dev->id[ATA_ID_PIO_MODES]) << (ATA_SHIFT_PIO + 3);
+ xfer_modes |= (0x7 << ATA_SHIFT_PIO);
}
ata_dump_id(dev);
@@ -1083,7 +1102,7 @@
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n",
ap->id, device,
- ata_udma_string(udma_modes),
+ ata_mode_string(xfer_modes),
(unsigned long long)dev->n_sectors,
dev->flags & ATA_DFLAG_LBA48 ? " lba48" : "");
}
@@ -1101,7 +1120,7 @@
/* print device info to dmesg */
printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n",
ap->id, device,
- ata_udma_string(udma_modes));
+ ata_mode_string(xfer_modes));
}
DPRINTK("EXIT, drv_stat = 0x%x\n", ata_chk_status(ap));
@@ -1232,6 +1251,89 @@
ap->flags |= ATA_FLAG_PORT_DISABLED;
}
+static struct {
+ unsigned int shift;
+ unsigned int base;
+} xfer_mode_classes[] = {
+ { ATA_SHIFT_UDMA, XFER_UDMA_0 },
+ { ATA_SHIFT_MWDMA, XFER_MW_DMA_0 },
+ { ATA_SHIFT_PIO, XFER_PIO_0 },
+};
+
+static inline unsigned int base_from_shift(unsigned int shift)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++)
+ if (xfer_mode_classes[i].shift == shift)
+ return xfer_mode_classes[i].base;
+
+ return 0xffffffff;
+}
+
+static void ata_dev_set_mode(struct ata_port *ap, struct ata_device *dev)
+{
+ unsigned int base, offset;
+
+ if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
+ return;
+
+ ata_dev_set_xfermode(ap, dev);
+
+ base = base_from_shift(dev->xfer_shift);
+ offset = dev->xfer_mode - base;
+
+ printk(KERN_INFO "ata%u: dev %u configured for %s\n",
+ ap->id, dev->devno,
+ xfer_mode_str[offset + dev->xfer_shift]);
+}
+
+static int ata_host_set_pio(struct ata_port *ap)
+{
+ unsigned int mask, base, xfer_mode;
+ int x, i;
+
+ mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO);
+ x = fgb(mask);
+ if (x < 0) {
+ printk(KERN_WARNING "ata%u: no PIO support\n", ap->id);
+ return -1;
+ }
+
+ base = base_from_shift(ATA_SHIFT_PIO);
+ xfer_mode = base + x;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+ if (ata_dev_present(dev)) {
+ dev->pio_mode = xfer_mode;
+ dev->xfer_mode = xfer_mode;
+ dev->xfer_shift = ATA_SHIFT_PIO;
+ if (ap->ops->set_piomode)
+ ap->ops->set_piomode(ap, dev);
+ }
+ }
+
+ return 0;
+}
+
+static void ata_host_set_dma(struct ata_port *ap, unsigned int xfer_mode,
+ unsigned int xfer_shift)
+{
+ int i;
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+ if (ata_dev_present(dev)) {
+ dev->dma_mode = xfer_mode;
+ dev->xfer_mode = xfer_mode;
+ dev->xfer_shift = xfer_shift;
+ if (ap->ops->set_dmamode)
+ ap->ops->set_dmamode(ap, dev);
+ }
+ }
+}
+
/**
* ata_set_mode - Program timings and issue SET FEATURES - XFER
* @ap: port on which timings will be programmed
@@ -1241,29 +1343,27 @@
*/
static void ata_set_mode(struct ata_port *ap)
{
- unsigned int force_pio, i;
-
- ata_host_set_pio(ap);
- if (ap->flags & ATA_FLAG_PORT_DISABLED)
- return;
+ unsigned int i, xfer_mode, xfer_shift;
+ int rc;
- ata_host_set_udma(ap);
- if (ap->flags & ATA_FLAG_PORT_DISABLED)
- return;
+ /* step 1: always set host PIO timings */
+ rc = ata_host_set_pio(ap);
+ if (rc)
+ goto err_out;
-#ifdef ATA_FORCE_PIO
- force_pio = 1;
-#else
- force_pio = 0;
-#endif
+ /* step 2: choose the best data xfer mode */
+ xfer_mode = xfer_shift = 0;
+ rc = ata_choose_xfer_mode(ap, &xfer_mode, &xfer_shift);
+ if (rc)
+ goto err_out;
- if (force_pio) {
- ata_dev_set_pio(ap, 0);
- ata_dev_set_pio(ap, 1);
- } else {
- ata_dev_set_udma(ap, 0);
- ata_dev_set_udma(ap, 1);
- }
+ /* step 3: if that xfer mode isn't PIO, set host DMA timings */
+ if (xfer_shift != ATA_SHIFT_PIO)
+ ata_host_set_dma(ap, xfer_mode, xfer_shift);
+
+ /* step 4: update devices' xfer mode */
+ ata_dev_set_mode(ap, &ap->device[0]);
+ ata_dev_set_mode(ap, &ap->device[1]);
if (ap->flags & ATA_FLAG_PORT_DISABLED)
return;
@@ -1275,6 +1375,11 @@
struct ata_device *dev = &ap->device[i];
ata_dev_set_protocol(dev);
}
+
+ return;
+
+err_out:
+ ata_port_disable(ap);
}
/**
@@ -1536,116 +1641,101 @@
DPRINTK("EXIT\n");
}
-/**
- * ata_host_set_pio -
- * @ap:
- *
- * LOCKING:
- */
-
-static void ata_host_set_pio(struct ata_port *ap)
+static unsigned int ata_get_mode_mask(struct ata_port *ap, int shift)
{
struct ata_device *master, *slave;
- unsigned int pio, i;
- u16 mask;
+ unsigned int mask;
master = &ap->device[0];
slave = &ap->device[1];
assert (ata_dev_present(master) || ata_dev_present(slave));
- mask = ap->pio_mask;
- if (ata_dev_present(master))
- mask &= (master->id[ATA_ID_PIO_MODES] & 0x03);
- if (ata_dev_present(slave))
- mask &= (slave->id[ATA_ID_PIO_MODES] & 0x03);
-
- /* require pio mode 3 or 4 support for host and all devices */
- if (mask == 0) {
- printk(KERN_WARNING "ata%u: no PIO3/4 support, ignoring\n",
- ap->id);
- goto err_out;
+ if (shift == ATA_SHIFT_UDMA) {
+ mask = ap->udma_mask;
+ if (ata_dev_present(master))
+ mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
+ if (ata_dev_present(slave))
+ mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
+ }
+ else if (shift == ATA_SHIFT_MWDMA) {
+ mask = ap->mwdma_mask;
+ if (ata_dev_present(master))
+ mask &= (master->id[ATA_ID_MWDMA_MODES] & 0x07);
+ if (ata_dev_present(slave))
+ mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07);
+ }
+ else if (shift == ATA_SHIFT_PIO) {
+ mask = ap->pio_mask;
+ if (ata_dev_present(master)) {
+ /* spec doesn't return explicit support for
+ * PIO0-2, so we fake it
+ */
+ u16 tmp_mode = master->id[ATA_ID_PIO_MODES] & 0x03;
+ tmp_mode <<= 3;
+ tmp_mode |= 0x7;
+ mask &= tmp_mode;
+ }
+ if (ata_dev_present(slave)) {
+ /* spec doesn't return explicit support for
+ * PIO0-2, so we fake it
+ */
+ u16 tmp_mode = slave->id[ATA_ID_PIO_MODES] & 0x03;
+ tmp_mode <<= 3;
+ tmp_mode |= 0x7;
+ mask &= tmp_mode;
+ }
+ }
+ else {
+ mask = 0xffffffff; /* shut up compiler warning */
+ BUG();
}
- pio = (mask & ATA_ID_PIO4) ? 4 : 3;
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ata_dev_present(&ap->device[i])) {
- ap->device[i].pio_mode = (pio == 3) ?
- XFER_PIO_3 : XFER_PIO_4;
- if (ap->ops->set_piomode)
- ap->ops->set_piomode(ap, &ap->device[i], pio);
- }
+ return mask;
+}
- return;
+/* find greatest bit */
+static int fgb(unsigned long bitmap)
+{
+ int i, x = -1;
-err_out:
- ap->ops->port_disable(ap);
+ for (i = 0; i < (sizeof(unsigned long) * 8); i++)
+ if (bitmap & (1 << i))
+ x = i;
+
+ return x;
}
/**
- * ata_host_set_udma -
+ * ata_choose_xfer_mode -
* @ap:
*
* LOCKING:
+ *
+ * RETURNS:
+ * Zero on success, negative on error.
*/
-static void ata_host_set_udma(struct ata_port *ap)
-{
- struct ata_device *master, *slave;
- u16 mask;
- unsigned int i, j;
- int udma_mode = -1;
-
- master = &ap->device[0];
- slave = &ap->device[1];
-
- assert (ata_dev_present(master) || ata_dev_present(slave));
- assert ((ap->flags & ATA_FLAG_PORT_DISABLED) == 0);
-
- DPRINTK("udma masks: host 0x%X, master 0x%X, slave 0x%X\n",
- ap->udma_mask,
- (!ata_dev_present(master)) ? 0xff :
- (master->id[ATA_ID_UDMA_MODES] & 0xff),
- (!ata_dev_present(slave)) ? 0xff :
- (slave->id[ATA_ID_UDMA_MODES] & 0xff));
-
- mask = ap->udma_mask;
- if (ata_dev_present(master))
- mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff);
- if (ata_dev_present(slave))
- mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff);
-
- i = XFER_UDMA_7;
- while (i >= XFER_UDMA_0) {
- j = i - XFER_UDMA_0;
- DPRINTK("mask 0x%X i 0x%X j %u\n", mask, i, j);
- if (mask & (1 << j)) {
- udma_mode = i;
- break;
+static int ata_choose_xfer_mode(struct ata_port *ap,
+ unsigned int *xfer_mode_out,
+ unsigned int *xfer_shift_out)
+{
+ unsigned int mask, shift;
+ int x, i;
+
+ for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) {
+ shift = xfer_mode_classes[i].shift;
+ mask = ata_get_mode_mask(ap, shift);
+
+ x = fgb(mask);
+ if (x >= 0) {
+ *xfer_mode_out = xfer_mode_classes[i].base + x;
+ *xfer_shift_out = shift;
+ return 0;
}
-
- i--;
- }
-
- /* require udma for host and all attached devices */
- if (udma_mode < 0) {
- printk(KERN_WARNING "ata%u: no UltraDMA support, ignoring\n",
- ap->id);
- goto err_out;
}
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- if (ata_dev_present(&ap->device[i])) {
- ap->device[i].udma_mode = udma_mode;
- if (ap->ops->set_udmamode)
- ap->ops->set_udmamode(ap, &ap->device[i],
- udma_mode);
- }
-
- return;
-
-err_out:
- ap->ops->port_disable(ap);
+ return -1;
}
/**
@@ -1668,10 +1758,7 @@
tf.feature = SETFEATURES_XFER;
tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf.protocol = ATA_PROT_NODATA;
- if (dev->flags & ATA_DFLAG_PIO)
- tf.nsect = dev->pio_mode;
- else
- tf.nsect = dev->udma_mode;
+ tf.nsect = dev->xfer_mode;
/* do bus reset */
ata_tf_to_host(ap, &tf);
@@ -1690,57 +1777,6 @@
}
/**
- * ata_dev_set_udma - Set ATA device's transfer mode to Ultra DMA
- * @ap: Port associated with device @dev
- * @device: Device whose mode will be set
- *
- * LOCKING:
- */
-
-static void ata_dev_set_udma(struct ata_port *ap, unsigned int device)
-{
- struct ata_device *dev = &ap->device[device];
-
- if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
- return;
-
- ata_dev_set_xfermode(ap, dev);
-
- assert((dev->udma_mode >= XFER_UDMA_0) &&
- (dev->udma_mode <= XFER_UDMA_7));
- printk(KERN_INFO "ata%u: dev %u configured for %s\n",
- ap->id, device,
- udma_str[dev->udma_mode - XFER_UDMA_0]);
-}
-
-/**
- * ata_dev_set_pio - Set ATA device's transfer mode to PIO
- * @ap: Port associated with device @dev
- * @device: Device whose mode will be set
- *
- * LOCKING:
- */
-
-static void ata_dev_set_pio(struct ata_port *ap, unsigned int device)
-{
- struct ata_device *dev = &ap->device[device];
-
- if (!ata_dev_present(dev) || (ap->flags & ATA_FLAG_PORT_DISABLED))
- return;
-
- /* force PIO mode */
- dev->flags |= ATA_DFLAG_PIO;
-
- ata_dev_set_xfermode(ap, dev);
-
- assert((dev->pio_mode >= XFER_PIO_3) &&
- (dev->pio_mode <= XFER_PIO_4));
- printk(KERN_INFO "ata%u: dev %u configured for PIO%c\n",
- ap->id, device,
- dev->pio_mode == 3 ? '3' : '4');
-}
-
-/**
* ata_sg_clean -
* @qc:
*
@@ -2801,6 +2837,7 @@
ap->host_set = host_set;
ap->port_no = port_no;
ap->pio_mask = ent->pio_mask;
+ ap->mwdma_mask = ent->mwdma_mask;
ap->udma_mask = ent->udma_mask;
ap->flags |= ent->host_flags;
ap->ops = ent->port_ops;
@@ -2898,19 +2935,23 @@
/* register each port bound to this device */
for (i = 0; i < ent->n_ports; i++) {
struct ata_port *ap;
+ unsigned int xfer_mode_mask;
ap = ata_host_add(ent, host_set, i);
if (!ap)
goto err_out;
host_set->ports[i] = ap;
+ xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) |
+ (ap->mwdma_mask << ATA_SHIFT_MWDMA) |
+ (ap->pio_mask << ATA_SHIFT_PIO);
/* print per-port info to dmesg */
printk(KERN_INFO "ata%u: %cATA max %s cmd 0x%lX ctl 0x%lX "
"bmdma 0x%lX irq %lu\n",
ap->id,
ap->flags & ATA_FLAG_SATA ? 'S' : 'P',
- ata_udma_string(ent->udma_mask),
+ ata_mode_string(xfer_mode_mask),
ap->ioaddr.cmd_addr,
ap->ioaddr.ctl_addr,
ap->ioaddr.bmdma_addr,
@@ -3149,6 +3190,7 @@
probe_ent->sht = port0->sht;
probe_ent->host_flags = port0->host_flags;
probe_ent->pio_mask = port0->pio_mask;
+ probe_ent->mwdma_mask = port0->mwdma_mask;
probe_ent->udma_mask = port0->udma_mask;
probe_ent->port_ops = port0->port_ops;
@@ -3171,6 +3213,7 @@
probe_ent2->sht = port1->sht;
probe_ent2->host_flags = port1->host_flags;
probe_ent2->pio_mask = port1->pio_mask;
+ probe_ent2->mwdma_mask = port1->mwdma_mask;
probe_ent2->udma_mask = port1->udma_mask;
probe_ent2->port_ops = port1->port_ops;
} else {
diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_nv.c 2004-07-04 17:35:44 -04:00
@@ -39,6 +39,7 @@
#define NV_PORTS 2
#define NV_PIO_MASK 0x1f
+#define NV_MWDMA_MASK 0x07
#define NV_UDMA_MASK 0x7f
#define NV_PORT0_BMDMA_REG_OFFSET 0x00
#define NV_PORT1_BMDMA_REG_OFFSET 0x08
@@ -289,6 +290,7 @@
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->pio_mask = NV_PIO_MASK;
+ probe_ent->mwdma_mask = NV_MWDMA_MASK;
probe_ent->udma_mask = NV_UDMA_MASK;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_promise.c 2004-07-04 17:35:44 -04:00
@@ -130,7 +130,8 @@
.sht = &pdc_sata_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_sata_ops,
},
@@ -140,7 +141,8 @@
.sht = &pdc_sata_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_sata_ops,
},
@@ -601,6 +603,7 @@
probe_ent->sht = pdc_port_info[board_idx].sht;
probe_ent->host_flags = pdc_port_info[board_idx].host_flags;
probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask;
+ probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask;
probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask;
probe_ent->port_ops = pdc_port_info[board_idx].port_ops;
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_sil.c 2004-07-04 17:35:44 -04:00
@@ -149,7 +149,8 @@
.sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
}, /* sil_3114 */
@@ -157,7 +158,8 @@
.sht = &sil_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x3f, /* udma0-5 */
.port_ops = &sil_ops,
},
@@ -363,6 +365,7 @@
probe_ent->sht = sil_port_info[ent->driver_data].sht;
probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2;
probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask;
+ probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask;
probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_sis.c 2004-07-04 17:35:44 -04:00
@@ -230,7 +230,8 @@
probe_ent->host_flags |= SIS_FLAG_CFGSCR;
}
- probe_ent->pio_mask = 0x03;
+ probe_ent->pio_mask = 0x1f;
+ probe_ent->mwdma_mask = 0x7;
probe_ent->udma_mask = 0x7f;
probe_ent->port_ops = &sis_ops;
diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_svw.c 2004-07-04 17:35:44 -04:00
@@ -343,6 +343,7 @@
* if we don't fill these
*/
probe_ent->pio_mask = 0x1f;
+ probe_ent->mwdma_mask = 0x7;
probe_ent->udma_mask = 0x7f;
/* We have 4 ports per PCI function */
diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_sx4.c 2004-07-04 17:35:44 -04:00
@@ -217,7 +217,8 @@
.sht = &pdc_sata_sht,
.host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_SRST | ATA_FLAG_MMIO,
- .pio_mask = 0x03, /* pio3-4 */
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_20621_ops,
},
@@ -1384,6 +1385,7 @@
probe_ent->sht = pdc_port_info[board_idx].sht;
probe_ent->host_flags = pdc_port_info[board_idx].host_flags;
probe_ent->pio_mask = pdc_port_info[board_idx].pio_mask;
+ probe_ent->mwdma_mask = pdc_port_info[board_idx].mwdma_mask;
probe_ent->udma_mask = pdc_port_info[board_idx].udma_mask;
probe_ent->port_ops = pdc_port_info[board_idx].port_ops;
diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_via.c 2004-07-04 17:35:44 -04:00
@@ -214,6 +214,7 @@
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->pio_mask = 0x1f;
+ probe_ent->mwdma_mask = 0x07;
probe_ent->udma_mask = 0x7f;
probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c 2004-07-04 17:35:44 -04:00
+++ b/drivers/scsi/sata_vsc.c 2004-07-04 17:35:44 -04:00
@@ -320,6 +320,7 @@
* if we don't fill these
*/
probe_ent->pio_mask = 0x1f;
+ probe_ent->mwdma_mask = 0x07;
probe_ent->udma_mask = 0x7f;
/* We have 4 ports per PCI function */
diff -Nru a/include/linux/ata.h b/include/linux/ata.h
--- a/include/linux/ata.h 2004-07-04 17:35:44 -04:00
+++ b/include/linux/ata.h 2004-07-04 17:35:44 -04:00
@@ -42,6 +42,7 @@
ATA_ID_SERNO_OFS = 10,
ATA_ID_MAJOR_VER = 80,
ATA_ID_PIO_MODES = 64,
+ ATA_ID_MWDMA_MODES = 63,
ATA_ID_UDMA_MODES = 88,
ATA_ID_PIO4 = (1 << 1),
@@ -133,8 +134,14 @@
XFER_UDMA_2 = 0x42,
XFER_UDMA_1 = 0x41,
XFER_UDMA_0 = 0x40,
+ XFER_MW_DMA_2 = 0x22,
+ XFER_MW_DMA_1 = 0x21,
+ XFER_MW_DMA_0 = 0x20,
XFER_PIO_4 = 0x0C,
XFER_PIO_3 = 0x0B,
+ XFER_PIO_2 = 0x0A,
+ XFER_PIO_1 = 0x09,
+ XFER_PIO_0 = 0x08,
/* ATAPI stuff */
ATAPI_PKT_DMA = (1 << 0),
diff -Nru a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h 2004-07-04 17:35:44 -04:00
+++ b/include/linux/libata.h 2004-07-04 17:35:44 -04:00
@@ -32,7 +32,6 @@
/*
* compile-time options
*/
-#undef ATA_FORCE_PIO /* do not configure or use DMA */
#undef ATA_DEBUG /* debugging output */
#undef ATA_VERBOSE_DEBUG /* yet more debugging output */
#undef ATA_IRQ_TRAP /* define to ack screaming irqs */
@@ -140,6 +139,13 @@
PORT_UNKNOWN = 0,
PORT_ENABLED = 1,
PORT_DISABLED = 2,
+
+ /* encoding various smaller bitmaps into a single
+ * unsigned long bitmap
+ */
+ ATA_SHIFT_UDMA = 0,
+ ATA_SHIFT_MWDMA = 8,
+ ATA_SHIFT_PIO = 11,
};
enum pio_task_states {
@@ -188,6 +194,7 @@
struct ata_ioports port[ATA_MAX_PORTS];
unsigned int n_ports;
unsigned int pio_mask;
+ unsigned int mwdma_mask;
unsigned int udma_mask;
unsigned int legacy_mode;
unsigned long irq;
@@ -252,7 +259,9 @@
unsigned int devno; /* 0 or 1 */
u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
unsigned int pio_mode;
- unsigned int udma_mode;
+ unsigned int dma_mode;
+ unsigned int xfer_mode;
+ unsigned int xfer_shift; /* ATA_SHIFT_xxx */
/* cache info about current transfer mode */
u8 xfer_protocol; /* taskfile xfer protocol */
@@ -277,6 +286,7 @@
unsigned int bus_state;
unsigned int port_state;
unsigned int pio_mask;
+ unsigned int mwdma_mask;
unsigned int udma_mask;
unsigned int cbl; /* cable type; ATA_CBL_xxx */
@@ -303,10 +313,8 @@
void (*dev_config) (struct ata_port *, struct ata_device *);
- void (*set_piomode) (struct ata_port *, struct ata_device *,
- unsigned int);
- void (*set_udmamode) (struct ata_port *, struct ata_device *,
- unsigned int);
+ void (*set_piomode) (struct ata_port *, struct ata_device *);
+ void (*set_dmamode) (struct ata_port *, struct ata_device *);
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -342,6 +350,7 @@
Scsi_Host_Template *sht;
unsigned long host_flags;
unsigned long pio_mask;
+ unsigned long mwdma_mask;
unsigned long udma_mask;
struct ata_port_operations *port_ops;
};
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2004-07-04 21:38 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-07-04 21:38 [PATCH] libata MWDMA support, xfer mode rework Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).