summaryrefslogtreecommitdiff
path: root/drivers/ata/pata_legacy.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/pata_legacy.c')
-rw-r--r--drivers/ata/pata_legacy.c163
1 files changed, 90 insertions, 73 deletions
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index be816428b430..e7ac142c2423 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* pata-legacy.c - Legacy port PATA/SATA controller driver.
* Copyright 2005/2006 Red Hat, all rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
* An ATA driver for the legacy ATA ports.
*
* Data Sources:
@@ -55,7 +42,6 @@
*
* For now use autospeed and pio_mask as above with the W83759A. This may
* change.
- *
*/
#include <linux/async.h>
@@ -77,7 +63,66 @@
static int all;
module_param(all, int, 0444);
-MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
+MODULE_PARM_DESC(all,
+ "Set to probe unclaimed pri/sec ISA port ranges even if PCI");
+
+static int probe_all;
+module_param(probe_all, int, 0);
+MODULE_PARM_DESC(probe_all,
+ "Set to probe tertiary+ ISA port ranges even if PCI");
+
+static int probe_mask = ~0;
+module_param(probe_mask, int, 0);
+MODULE_PARM_DESC(probe_mask, "Probe mask for legacy ISA PATA ports");
+
+static int autospeed;
+module_param(autospeed, int, 0);
+MODULE_PARM_DESC(autospeed, "Chip present that snoops speed changes");
+
+static int pio_mask = ATA_PIO4;
+module_param(pio_mask, int, 0);
+MODULE_PARM_DESC(pio_mask, "PIO range for autospeed devices");
+
+static int iordy_mask = 0xFFFFFFFF;
+module_param(iordy_mask, int, 0);
+MODULE_PARM_DESC(iordy_mask, "Use IORDY if available");
+
+static int ht6560a;
+module_param(ht6560a, int, 0);
+MODULE_PARM_DESC(ht6560a, "HT 6560A on primary 1, second 2, both 3");
+
+static int ht6560b;
+module_param(ht6560b, int, 0);
+MODULE_PARM_DESC(ht6560b, "HT 6560B on primary 1, secondary 2, both 3");
+
+static int opti82c611a;
+module_param(opti82c611a, int, 0);
+MODULE_PARM_DESC(opti82c611a,
+ "Opti 82c611A on primary 1, secondary 2, both 3");
+
+static int opti82c46x;
+module_param(opti82c46x, int, 0);
+MODULE_PARM_DESC(opti82c46x,
+ "Opti 82c465MV on primary 1, secondary 2, both 3");
+
+#ifdef CONFIG_PATA_QDI_MODULE
+static int qdi = 1;
+#else
+static int qdi;
+#endif
+module_param(qdi, int, 0);
+MODULE_PARM_DESC(qdi, "Set to probe QDI controllers");
+
+#ifdef CONFIG_PATA_WINBOND_VLB_MODULE
+static int winbond = 1;
+#else
+static int winbond;
+#endif
+module_param(winbond, int, 0);
+MODULE_PARM_DESC(winbond,
+ "Set to probe Winbond controllers, "
+ "give I/O port if non standard");
+
enum controller {
BIOS = 0,
@@ -128,32 +173,6 @@ static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
static struct legacy_probe probe_list[NR_HOST];
static struct legacy_data legacy_data[NR_HOST];
static struct ata_host *legacy_host[NR_HOST];
-static int nr_legacy_host;
-
-
-static int probe_all; /* Set to check all ISA port ranges */
-static int ht6560a; /* HT 6560A on primary 1, second 2, both 3 */
-static int ht6560b; /* HT 6560A on primary 1, second 2, both 3 */
-static int opti82c611a; /* Opti82c611A on primary 1, sec 2, both 3 */
-static int opti82c46x; /* Opti 82c465MV present(pri/sec autodetect) */
-static int autospeed; /* Chip present which snoops speed changes */
-static int pio_mask = ATA_PIO4; /* PIO range for autospeed devices */
-static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */
-
-/* Set to probe QDI controllers */
-#ifdef CONFIG_PATA_QDI_MODULE
-static int qdi = 1;
-#else
-static int qdi;
-#endif
-
-#ifdef CONFIG_PATA_WINBOND_VLB_MODULE
-static int winbond = 1; /* Set to probe Winbond controllers,
- give I/O port if non standard */
-#else
-static int winbond; /* Set to probe Winbond controllers,
- give I/O port if non standard */
-#endif
/**
* legacy_probe_add - Add interface to probe list
@@ -182,6 +201,8 @@ static int legacy_probe_add(unsigned long port, unsigned int irq,
free = lp;
/* Matching port, or the correct slot for ordering */
if (lp->port == port || legacy_port[i] == port) {
+ if (!(probe_mask & 1 << i))
+ return -1;
free = lp;
break;
}
@@ -227,7 +248,7 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
return 0;
}
-static struct scsi_host_template legacy_sht = {
+static const struct scsi_host_template legacy_sht = {
ATA_PIO_SHT(DRV_NAME),
};
@@ -246,12 +267,12 @@ static const struct ata_port_operations legacy_base_port_ops = {
static struct ata_port_operations simple_port_ops = {
.inherits = &legacy_base_port_ops,
- .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .sff_data_xfer = ata_sff_data_xfer32,
};
static struct ata_port_operations legacy_port_ops = {
.inherits = &legacy_base_port_ops,
- .sff_data_xfer = ata_sff_data_xfer_noirq,
+ .sff_data_xfer = ata_sff_data_xfer32,
.set_mode = legacy_set_mode,
};
@@ -292,9 +313,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
outb(inb(0x1F4) & 0x07, 0x1F4);
rt = inb(0x1F3);
- rt &= 0x07 << (3 * adev->devno);
+ rt &= ~(0x07 << (3 * !adev->devno));
if (pio)
- rt |= (1 + 3 * pio) << (3 * adev->devno);
+ rt |= (1 + 3 * pio) << (3 * !adev->devno);
+ outb(rt, 0x1F3);
udelay(100);
outb(inb(0x1F2) | 0x01, 0x1F2);
@@ -303,11 +325,12 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
}
-static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
+static unsigned int pdc_data_xfer_vlb(struct ata_queued_cmd *qc,
unsigned char *buf, unsigned int buflen, int rw)
{
- int slop = buflen & 3;
+ struct ata_device *dev = qc->dev;
struct ata_port *ap = dev->link->ap;
+ int slop = buflen & 3;
/* 32bit I/O capable *and* we need to write a whole number of dwords */
if (ata_id_has_dword_io(dev->id) && (slop == 0 || slop == 3)
@@ -328,7 +351,8 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
if (unlikely(slop)) {
- __le32 pad;
+ __le32 pad = 0;
+
if (rw == READ) {
pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
memcpy(buf + buflen - slop, &pad, slop);
@@ -340,7 +364,7 @@ static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
}
local_irq_restore(flags);
} else
- buflen = ata_sff_data_xfer_noirq(dev, buf, buflen, rw);
+ buflen = ata_sff_data_xfer32(qc, buf, buflen, rw);
return buflen;
}
@@ -601,7 +625,7 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
}
/**
- * opt82c465mv_qc_issue - command issue
+ * opti82c46x_qc_issue - command issue
* @qc: command pending
*
* Called when the libata layer is about to issue a command. We wrap
@@ -702,9 +726,11 @@ static unsigned int qdi_qc_issue(struct ata_queued_cmd *qc)
return ata_sff_qc_issue(qc);
}
-static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
- unsigned int buflen, int rw)
+static unsigned int vlb32_data_xfer(struct ata_queued_cmd *qc,
+ unsigned char *buf,
+ unsigned int buflen, int rw)
{
+ struct ata_device *adev = qc->dev;
struct ata_port *ap = adev->link->ap;
int slop = buflen & 3;
@@ -716,7 +742,8 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
if (unlikely(slop)) {
- __le32 pad;
+ __le32 pad = 0;
+
if (rw == WRITE) {
memcpy(&pad, buf + buflen - slop, slop);
iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
@@ -727,7 +754,7 @@ static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
}
return (buflen + 3) & ~3;
} else
- return ata_sff_data_xfer(adev, buf, buflen, rw);
+ return ata_sff_data_xfer(qc, buf, buflen, rw);
}
static int qdi_port(struct platform_device *dev,
@@ -916,7 +943,6 @@ static __init int probe_chip_type(struct legacy_probe *probe)
local_irq_restore(flags);
return BIOS;
}
- local_irq_restore(flags);
}
if (ht6560a & mask)
@@ -935,7 +961,7 @@ static __init int probe_chip_type(struct legacy_probe *probe)
/**
* legacy_init_one - attach a legacy interface
- * @pl: probe record
+ * @probe: probe record
*
* Register an ISA bus IDE interface. Such interfaces are PIO and we
* assume do not support IRQ sharing.
@@ -1021,8 +1047,8 @@ fail:
/**
* legacy_check_special_cases - ATA special cases
* @p: PCI device to check
- * @master: set this if we find an ATA master
- * @master: set this if we find an ATA secondary
+ * @primary: set this if we find an ATA master
+ * @secondary: set this if we find an ATA secondary
*
* A small number of vendors implemented early PCI ATA interfaces
* on bridge logic without the ATA interface being PCI visible.
@@ -1248,9 +1274,11 @@ static __exit void legacy_exit(void)
{
int i;
- for (i = 0; i < nr_legacy_host; i++) {
+ for (i = 0; i < NR_HOST; i++) {
struct legacy_data *ld = &legacy_data[i];
- ata_host_detach(legacy_host[i]);
+
+ if (legacy_host[i])
+ ata_host_detach(legacy_host[i]);
platform_device_unregister(ld->platform_dev);
}
}
@@ -1262,16 +1290,5 @@ MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("pata_qdi");
MODULE_ALIAS("pata_winbond");
-module_param(probe_all, int, 0);
-module_param(autospeed, int, 0);
-module_param(ht6560a, int, 0);
-module_param(ht6560b, int, 0);
-module_param(opti82c611a, int, 0);
-module_param(opti82c46x, int, 0);
-module_param(qdi, int, 0);
-module_param(winbond, int, 0);
-module_param(pio_mask, int, 0);
-module_param(iordy_mask, int, 0);
-
module_init(legacy_init);
module_exit(legacy_exit);