BK users:
bk pull bk://gkernel.bkbits.net/libata-2.4
This will update the following files:
Documentation/DocBook/Makefile | 2
Documentation/DocBook/libata.tmpl | 5
drivers/pci/quirks.c | 81 ++++++++++
drivers/scsi/Config.in | 1
drivers/scsi/Makefile | 1
drivers/scsi/ata_piix.c | 25 +--
drivers/scsi/libata-core.c | 96 ++++++++----
drivers/scsi/sata_nv.c | 35 ++--
drivers/scsi/sata_promise.c | 1
drivers/scsi/sata_sil.c | 1
drivers/scsi/sata_sis.c | 1
drivers/scsi/sata_svw.c | 1
drivers/scsi/sata_sx4.c | 3
drivers/scsi/sata_uli.c | 292 ++++++++++++++++++++++++++++++++++++++
drivers/scsi/sata_via.c | 1
drivers/scsi/sata_vsc.c | 1
include/linux/ioport.h | 1
include/linux/libata.h | 7
kernel/ksyms.c | 1
kernel/resource.c | 10 +
20 files changed, 509 insertions(+), 57 deletions(-)
through these ChangeSets:
Arjan van de Ven:
o [libata ata_piix] Use standard headers from include/scsi, not drivers/scsi
Bartlomiej Zolnierkiewicz:
o libata: PCI IDE legacy mode fix
François Romieu:
o sata_nv: housekeeping for goto labels
o sata_nv: wrong failure path and leak
o sata_nv: enable hotplug event on successfull init only
Jeff Garzik:
o [libata] add sata_uli driver for ULi (formerly ALi) SATA
o [libata] add hook, and export functions needed for sata2 drivers
o [PCI, libata] Fix "combined mode" PCI quirk for ICH6
o [libata ata_piix] re-enable combined mode support
o [libata ata_piix] ->qc_prep hook
o [libata ata_piix] fix DocBook docs
o [libata ata_piix] add ->bmdma_setup hook
o [libata] re-merge the rest of the 2.4 junk
diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
--- a/Documentation/DocBook/Makefile 2004-10-14 23:47:29 -04:00
+++ b/Documentation/DocBook/Makefile 2004-10-14 23:47:29 -04:00
@@ -82,10 +82,12 @@
libata.sgml: libata.tmpl $(TOPDIR)/drivers/scsi/libata-core.c \
$(TOPDIR)/drivers/scsi/libata-scsi.c \
$(TOPDIR)/drivers/scsi/sata_sil.c \
+ $(TOPDIR)/drivers/scsi/ata_piix.c \
$(TOPDIR)/drivers/scsi/sata_via.c
$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/scsi/libata-core.c \
$(TOPDIR)/drivers/scsi/libata-scsi.c \
$(TOPDIR)/drivers/scsi/sata_sil.c \
+ $(TOPDIR)/drivers/scsi/ata_piix.c \
$(TOPDIR)/drivers/scsi/sata_via.c \
< libata.tmpl > libata.sgml
diff -Nru a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
--- a/Documentation/DocBook/libata.tmpl 2004-10-14 23:47:29 -04:00
+++ b/Documentation/DocBook/libata.tmpl 2004-10-14 23:47:29 -04:00
@@ -77,6 +77,11 @@
!Idrivers/scsi/libata-scsi.c
+
+ ata_piix Internals
+!Idrivers/scsi/ata_piix.c
+
+
ata_sil Internals
!Idrivers/scsi/sata_sil.c
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/pci/quirks.c 2004-10-14 23:47:29 -04:00
@@ -719,6 +719,79 @@
}
}
+#ifdef CONFIG_SCSI_SATA
+static void __init quirk_intel_ide_combined(struct pci_dev *pdev)
+{
+ u8 prog, comb, tmp;
+ int ich = 0;
+
+ /*
+ * Narrow down to Intel SATA PCI devices.
+ */
+ switch (pdev->device) {
+ /* PCI ids taken from drivers/scsi/ata_piix.c */
+ case 0x24d1:
+ case 0x24df:
+ case 0x25a3:
+ case 0x25b0:
+ ich = 5;
+ break;
+ case 0x2651:
+ case 0x2652:
+ case 0x2653:
+ ich = 6;
+ break;
+ default:
+ /* we do not handle this PCI device */
+ return;
+ }
+
+ /*
+ * Read combined mode register.
+ */
+ pci_read_config_byte(pdev, 0x90, &tmp); /* combined mode reg */
+
+ if (ich == 5) {
+ tmp &= 0x6; /* interesting bits 2:1, PATA primary/secondary */
+ if (tmp == 0x4) /* bits 10x */
+ comb = (1 << 0); /* SATA port 0, PATA port 1 */
+ else if (tmp == 0x6) /* bits 11x */
+ comb = (1 << 2); /* PATA port 0, SATA port 1 */
+ else
+ return; /* not in combined mode */
+ } else {
+ WARN_ON(ich != 6);
+ tmp &= 0x3; /* interesting bits 1:0 */
+ if (tmp & (1 << 0))
+ comb = (1 << 2); /* PATA port 0, SATA port 1 */
+ else if (tmp & (1 << 1))
+ comb = (1 << 0); /* SATA port 0, PATA port 1 */
+ else
+ return; /* not in combined mode */
+ }
+
+ /*
+ * Read programming interface register.
+ * (Tells us if it's legacy or native mode)
+ */
+ pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
+
+ /* if SATA port is in native mode, we're ok. */
+ if (prog & comb)
+ return;
+
+ /* SATA port is in legacy mode. Reserve port so that
+ * IDE driver does not attempt to use it. If request_region
+ * fails, it will be obvious at boot time, so we don't bother
+ * checking return values.
+ */
+ if (comb == (1 << 0))
+ request_region(0x1f0, 8, "libata"); /* port 0 */
+ else
+ request_region(0x170, 8, "libata"); /* port 1 */
+}
+#endif /* CONFIG_SCSI_SATA */
+
/*
* The main table of quirks.
*/
@@ -807,6 +880,14 @@
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc },
+
+#ifdef CONFIG_SCSI_SATA
+ /* Fixup BIOSes that configure Parallel ATA (PATA / IDE) and
+ * Serial ATA (SATA) into the same PCI ID.
+ */
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
+ quirk_intel_ide_combined },
+#endif /* CONFIG_SCSI_SATA */
{ 0 }
};
diff -Nru a/drivers/scsi/Config.in b/drivers/scsi/Config.in
--- a/drivers/scsi/Config.in 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/Config.in 2004-10-14 23:47:29 -04:00
@@ -76,6 +76,7 @@
dep_tristate ' Promise SATA SX4 support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SX4 $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate ' Silicon Image SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIL $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate ' SiS 964/180 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_SIS $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate ' ULi Electronics SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_ULI $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate ' VIA SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_VIA $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
dep_tristate ' Vitesse VSC-7174 SATA support (EXPERIMENTAL)' CONFIG_SCSI_SATA_VITESSE $CONFIG_SCSI_SATA $CONFIG_PCI $CONFIG_EXPERIMENTAL
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/Makefile 2004-10-14 23:47:29 -04:00
@@ -139,6 +139,7 @@
obj-$(CONFIG_SCSI_SATA_SIS) += libata.o sata_sis.o
obj-$(CONFIG_SCSI_SATA_SX4) += libata.o sata_sx4.o
obj-$(CONFIG_SCSI_SATA_NV) += libata.o sata_nv.o
+obj-$(CONFIG_SCSI_SATA_ULI) += libata.o sata_uli.o
subdir-$(CONFIG_ARCH_ACORN) += ../acorn/scsi
obj-$(CONFIG_ARCH_ACORN) += ../acorn/scsi/acorn-scsi.o
diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/ata_piix.c 2004-10-14 23:47:29 -04:00
@@ -130,6 +130,7 @@
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
.phy_reset = piix_pata_phy_reset,
@@ -154,6 +155,7 @@
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
.phy_reset = piix_sata_phy_reset,
@@ -267,7 +269,7 @@
goto cbl40;
/* check BIOS cable detect results */
- mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
+ mask = ap->hard_port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC;
pci_read_config_byte(pdev, PIIX_IOCFG, &tmp);
if ((tmp & mask) == 0)
goto cbl40;
@@ -293,7 +295,7 @@
static void piix_pata_phy_reset(struct ata_port *ap)
{
if (!pci_test_config_bits(ap->host_set->pdev,
- &piix_enable_bits[ap->port_no])) {
+ &piix_enable_bits[ap->hard_port_no])) {
ata_port_disable(ap);
printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id);
return;
@@ -326,8 +328,8 @@
int orig_mask, mask, i;
u8 pcs;
- mask = (PIIX_PORT_PRESENT << ap->port_no) |
- (PIIX_PORT_ENABLED << ap->port_no);
+ mask = (PIIX_PORT_PRESENT << ap->hard_port_no) |
+ (PIIX_PORT_ENABLED << ap->hard_port_no);
pci_read_config_byte(pdev, ICH5_PCS, &pcs);
orig_mask = (int) pcs & 0xff;
@@ -344,7 +346,7 @@
mask = (PIIX_PORT_PRESENT << i) | (PIIX_PORT_ENABLED << i);
if ((orig_mask & mask) == mask)
- if (combined || (i == ap->port_no))
+ if (combined || (i == ap->hard_port_no))
return 1;
}
@@ -393,7 +395,7 @@
unsigned int pio = adev->pio_mode - XFER_PIO_0;
struct pci_dev *dev = ap->host_set->pdev;
unsigned int is_slave = (adev->devno != 0);
- unsigned int master_port= ap->port_no ? 0x42 : 0x40;
+ unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40;
unsigned int slave_port = 0x44;
u16 master_data;
u8 slave_data;
@@ -411,10 +413,10 @@
/* enable PPE, IE and TIME */
master_data |= 0x0070;
pci_read_config_byte(dev, slave_port, &slave_data);
- slave_data &= (ap->port_no ? 0x0f : 0xf0);
+ slave_data &= (ap->hard_port_no ? 0x0f : 0xf0);
slave_data |=
(timings[pio][0] << 2) |
- (timings[pio][1] << (ap->port_no ? 4 : 0));
+ (timings[pio][1] << (ap->hard_port_no ? 4 : 0));
} else {
master_data &= 0xccf8;
/* enable PPE, IE and TIME */
@@ -444,9 +446,9 @@
{
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 maslave = ap->hard_port_no ? 0x42 : 0x40;
u8 speed = udma;
- unsigned int drive_dn = (ap->port_no ? 2 : 0) + adev->devno;
+ unsigned int drive_dn = (ap->hard_port_no ? 2 : 0) + adev->devno;
int a_speed = 3 << (drive_dn * 4);
int u_flag = 1 << drive_dn;
int v_flag = 0x01 << drive_dn;
@@ -620,8 +622,7 @@
port_info[pata_chan] = &piix_port_info[ich5_pata];
n_ports++;
- printk(KERN_ERR DRV_NAME ": combined mode not supported\n");
- return -ENODEV;
+ printk(KERN_ERR DRV_NAME ": combined mode detected\n");
}
return ata_pci_init_one(pdev, port_info, n_ports);
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/libata-core.c 2004-10-14 23:47:29 -04:00
@@ -49,7 +49,6 @@
static unsigned int ata_busy_sleep (struct ata_port *ap,
unsigned long tmout_pat,
unsigned long tmout);
-static void __ata_dev_select (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);
@@ -659,7 +658,7 @@
struct ata_ioports *ioaddr = &ap->ioaddr;
u8 nsect, lbal;
- __ata_dev_select(ap, device);
+ ap->ops->dev_select(ap, device);
outb(0x55, ioaddr->nsect_addr);
outb(0xaa, ioaddr->lbal_addr);
@@ -703,7 +702,7 @@
struct ata_ioports *ioaddr = &ap->ioaddr;
u8 nsect, lbal;
- __ata_dev_select(ap, device);
+ ap->ops->dev_select(ap, device);
writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
@@ -760,7 +759,7 @@
* the event of failure.
*/
-static unsigned int ata_dev_classify(struct ata_taskfile *tf)
+unsigned int ata_dev_classify(struct ata_taskfile *tf)
{
/* Apple's open source Darwin code hints that some devices only
* put a proper signature into the LBA mid/high registers,
@@ -808,7 +807,7 @@
unsigned int class;
u8 err;
- __ata_dev_select(ap, device);
+ ap->ops->dev_select(ap, device);
memset(&tf, 0, sizeof(tf));
@@ -871,8 +870,12 @@
}
}
+void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
+{
+}
+
/**
- * __ata_dev_select - Select device 0/1 on ATA bus
+ * ata_std_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate
* @device: ATA device (numbered from zero) to select
*
@@ -884,7 +887,7 @@
* caller.
*/
-static void __ata_dev_select (struct ata_port *ap, unsigned int device)
+void ata_std_dev_select (struct ata_port *ap, unsigned int device)
{
u8 tmp;
@@ -912,7 +915,7 @@
* make either device 0, or device 1, active on the
* ATA channel.
*
- * This is a high-level version of __ata_dev_select(),
+ * This is a high-level version of ata_std_dev_select(),
* which additionally provides the services of inserting
* the proper pauses and status polling, where needed.
*
@@ -929,7 +932,7 @@
if (wait)
ata_wait_idle(ap);
- __ata_dev_select(ap, device);
+ ap->ops->dev_select(ap, device);
if (wait) {
if (can_sleep && ap->device[device].class == ATA_DEV_ATAPI)
@@ -1236,13 +1239,13 @@
}
/**
- * sata_phy_reset -
+ * __sata_phy_reset -
* @ap:
*
* LOCKING:
*
*/
-void sata_phy_reset(struct ata_port *ap)
+void __sata_phy_reset(struct ata_port *ap)
{
u32 sstatus;
unsigned long timeout = jiffies + (HZ * 5);
@@ -1280,6 +1283,21 @@
return;
}
+ ap->cbl = ATA_CBL_SATA;
+}
+
+/**
+ * __sata_phy_reset -
+ * @ap:
+ *
+ * LOCKING:
+ *
+ */
+void sata_phy_reset(struct ata_port *ap)
+{
+ __sata_phy_reset(ap);
+ if (ap->flags & ATA_FLAG_PORT_DISABLED)
+ return;
ata_bus_reset(ap);
}
@@ -1505,7 +1523,7 @@
while (dev1) {
u8 nsect, lbal;
- __ata_dev_select(ap, 1);
+ ap->ops->dev_select(ap, 1);
if (ap->flags & ATA_FLAG_MMIO) {
nsect = readb((void __iomem *) ioaddr->nsect_addr);
lbal = readb((void __iomem *) ioaddr->lbal_addr);
@@ -1525,11 +1543,11 @@
ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
/* is all this really necessary? */
- __ata_dev_select(ap, 0);
+ ap->ops->dev_select(ap, 0);
if (dev1)
- __ata_dev_select(ap, 1);
+ ap->ops->dev_select(ap, 1);
if (dev0)
- __ata_dev_select(ap, 0);
+ ap->ops->dev_select(ap, 0);
}
/**
@@ -1644,7 +1662,7 @@
devmask |= (1 << 1);
/* select device 0 again */
- __ata_dev_select(ap, 0);
+ ap->ops->dev_select(ap, 0);
/* issue bus reset */
if (ap->flags & ATA_FLAG_SRST)
@@ -1673,9 +1691,9 @@
/* is double-select really necessary? */
if (ap->device[1].class != ATA_DEV_NONE)
- __ata_dev_select(ap, 1);
+ ap->ops->dev_select(ap, 1);
if (ap->device[0].class != ATA_DEV_NONE)
- __ata_dev_select(ap, 0);
+ ap->ops->dev_select(ap, 0);
/* if no devices were detected, disable this port */
if ((ap->device[0].class == ATA_DEV_NONE) &&
@@ -2186,9 +2204,7 @@
qc->cursg_ofs = 0;
}
- DPRINTK("data %s, drv_stat 0x%X\n",
- qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read",
- status);
+ DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
/* do the actual data transfer */
do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -3036,6 +3052,8 @@
ap->ctl = ATA_DEVCTL_OBS;
ap->host_set = host_set;
ap->port_no = port_no;
+ ap->hard_port_no =
+ ent->legacy_mode ? ent->hard_port_no : port_no;
ap->pio_mask = ent->pio_mask;
ap->mwdma_mask = ent->mwdma_mask;
ap->udma_mask = ent->udma_mask;
@@ -3361,9 +3379,15 @@
probe_ent[0].n_ports = 1;
probe_ent[0].irq = 14;
+ probe_ent[0].hard_port_no = 0;
+ probe_ent[0].legacy_mode = 1;
+
probe_ent[1].n_ports = 1;
probe_ent[1].irq = 15;
+ probe_ent[1].hard_port_no = 1;
+ probe_ent[1].legacy_mode = 1;
+
probe_ent[0].port[0].cmd_addr = 0x1f0;
probe_ent[0].port[0].altstatus_addr =
probe_ent[0].port[0].ctl_addr = 0x3f6;
@@ -3433,14 +3457,28 @@
goto err_out;
if (legacy_mode) {
- if (!request_region(0x1f0, 8, "libata"))
- printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
- else
+ if (!request_region(0x1f0, 8, "libata")) {
+ struct resource *conflict, res;
+ res.start = 0x1f0;
+ res.end = 0x1f0 + 8 - 1;
+ conflict = ____request_resource(&ioport_resource, &res);
+ if (!strcmp(conflict->name, "libata"))
+ legacy_mode |= (1 << 0);
+ else
+ printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
+ } else
legacy_mode |= (1 << 0);
- if (!request_region(0x170, 8, "libata"))
- printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
- else
+ if (!request_region(0x170, 8, "libata")) {
+ struct resource *conflict, res;
+ res.start = 0x170;
+ res.end = 0x170 + 8 - 1;
+ conflict = ____request_resource(&ioport_resource, &res);
+ if (!strcmp(conflict->name, "libata"))
+ legacy_mode |= (1 << 1);
+ else
+ printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
+ } else
legacy_mode |= (1 << 1);
}
@@ -3646,6 +3684,8 @@
EXPORT_SYMBOL_GPL(ata_eng_timeout);
EXPORT_SYMBOL_GPL(ata_tf_load);
EXPORT_SYMBOL_GPL(ata_tf_read);
+EXPORT_SYMBOL_GPL(ata_noop_dev_select);
+EXPORT_SYMBOL_GPL(ata_std_dev_select);
EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis);
EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
@@ -3661,6 +3701,7 @@
EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
EXPORT_SYMBOL_GPL(ata_port_probe);
EXPORT_SYMBOL_GPL(sata_phy_reset);
+EXPORT_SYMBOL_GPL(__sata_phy_reset);
EXPORT_SYMBOL_GPL(ata_bus_reset);
EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_pci_init_one);
@@ -3673,4 +3714,5 @@
EXPORT_SYMBOL_GPL(libata_msleep);
EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_id_string);
diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_nv.c 2004-10-14 23:47:29 -04:00
@@ -203,6 +203,7 @@
.tf_read = ata_tf_read,
.exec_command = ata_exec_command,
.check_status = ata_check_status,
+ .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
@@ -311,7 +312,7 @@
static int printed_version = 0;
struct nv_host *host;
struct ata_port_info *ppi;
- struct ata_probe_ent *probe_ent = NULL;
+ struct ata_probe_ent *probe_ent;
int rc;
if (!printed_version++)
@@ -319,28 +320,26 @@
rc = pci_enable_device(pdev);
if (rc)
- return rc;
+ goto err_out;
rc = pci_request_regions(pdev, DRV_NAME);
if (rc)
- goto err_out;
+ goto err_out_disable;
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc)
goto err_out_regions;
+ rc = -ENOMEM;
+
ppi = &nv_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
- if (!probe_ent) {
- rc = -ENOMEM;
+ if (!probe_ent)
goto err_out_regions;
- }
host = kmalloc(sizeof(struct nv_host), GFP_KERNEL);
- if (!host) {
- rc = -ENOMEM;
+ if (!host)
goto err_out_free_ent;
- }
host->host_desc = &nv_device_tbl[ent->driver_data];
@@ -351,8 +350,10 @@
probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
pci_resource_len(pdev, 5));
- if (probe_ent->mmio_base == NULL)
- goto err_out_iounmap;
+ if (probe_ent->mmio_base == NULL) {
+ rc = -EIO;
+ goto err_out_free_host;
+ }
base = (unsigned long)probe_ent->mmio_base;
@@ -370,26 +371,26 @@
pci_set_master(pdev);
+ ata_add_to_probe_list(probe_ent);
+
// Enable hotplug event interrupts.
if (host->host_desc->enable_hotplug)
host->host_desc->enable_hotplug(probe_ent);
- ata_add_to_probe_list(probe_ent);
-
return 0;
err_out_iounmap:
if (host->host_desc->host_flags & NV_HOST_FLAGS_SCR_MMIO)
iounmap(probe_ent->mmio_base);
-
+err_out_free_host:
+ kfree(host);
err_out_free_ent:
kfree(probe_ent);
-
err_out_regions:
pci_release_regions(pdev);
-
-err_out:
+err_out_disable:
pci_disable_device(pdev);
+err_out:
return rc;
}
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_promise.c 2004-10-14 23:47:29 -04:00
@@ -112,6 +112,7 @@
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = pdc_exec_command_mmio,
+ .dev_select = ata_std_dev_select,
.phy_reset = pdc_phy_reset,
.qc_prep = pdc_qc_prep,
.qc_issue = pdc_qc_issue_prot,
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_sil.c 2004-10-14 23:47:29 -04:00
@@ -130,6 +130,7 @@
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup,
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_sis.c 2004-10-14 23:47:29 -04:00
@@ -99,6 +99,7 @@
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_svw.c 2004-10-14 23:47:29 -04:00
@@ -298,6 +298,7 @@
.tf_read = k2_sata_tf_read,
.check_status = k2_stat_check_status,
.exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio,
diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_sx4.c 2004-10-14 23:47:29 -04:00
@@ -197,6 +197,7 @@
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = pdc_exec_command_mmio,
+ .dev_select = ata_std_dev_select,
.phy_reset = pdc_20621_phy_reset,
.qc_prep = pdc20621_qc_prep,
.qc_issue = pdc20621_qc_issue_prot,
@@ -534,7 +535,7 @@
readl(dimm_mmio); /* MMIO PCI posting flush */
- VPRINTK("ata pkt buf ofs %u, prd size %u, mmio copied\n", i, sgt_len);
+ VPRINTK("ata pkt buf ofs %u, mmio copied\n", i);
}
static void pdc20621_qc_prep(struct ata_queued_cmd *qc)
diff -Nru a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
--- /dev/null Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/sata_uli.c 2004-10-14 23:47:29 -04:00
@@ -0,0 +1,292 @@
+/*
+ * sata_uli.c - ULi Electronics SATA
+ *
+ * The contents of this file are subject to the Open
+ * Software License version 1.1 that can be found at
+ * http://www.opensource.org/licenses/osl-1.1.txt and is included herein
+ * by reference.
+ *
+ * Alternatively, the contents of this file may be used under the terms
+ * of the GNU General Public License version 2 (the "GPL") as distributed
+ * in the kernel source COPYING file, in which case the provisions of
+ * the GPL are applicable instead of the above. If you wish to allow
+ * the use of your version of this file only under the terms of the
+ * GPL and not to allow others to use your version of this file under
+ * the OSL, indicate your decision by deleting the provisions above and
+ * replace them with the notice and other provisions required by the GPL.
+ * If you do not delete the provisions above, a recipient may use your
+ * version of this file under either the OSL or the GPL.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "scsi.h"
+#include
+#include
+
+#define DRV_NAME "sata_uli"
+#define DRV_VERSION "0.11"
+
+enum {
+ uli_5289 = 0,
+ uli_5287 = 1,
+
+ /* PCI configuration registers */
+ ULI_SCR_BASE = 0x90, /* sata0 phy SCR registers */
+ ULI_SATA1_OFS = 0x10, /* offset from sata0->sata1 phy regs */
+
+};
+
+static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg);
+static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
+
+static struct pci_device_id uli_pci_tbl[] = {
+ { PCI_VENDOR_ID_AL, 0x5289, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5289 },
+ { PCI_VENDOR_ID_AL, 0x5287, PCI_ANY_ID, PCI_ANY_ID, 0, 0, uli_5287 },
+ { } /* terminate list */
+};
+
+
+static struct pci_driver uli_pci_driver = {
+ .name = DRV_NAME,
+ .id_table = uli_pci_tbl,
+ .probe = uli_init_one,
+ .remove = ata_pci_remove_one,
+};
+
+static Scsi_Host_Template uli_sht = {
+ .module = THIS_MODULE,
+ .name = DRV_NAME,
+ .detect = ata_scsi_detect,
+ .release = ata_scsi_release,
+ .ioctl = ata_scsi_ioctl,
+ .queuecommand = ata_scsi_queuecmd,
+ .eh_strategy_handler = ata_scsi_error,
+ .can_queue = ATA_DEF_QUEUE,
+ .this_id = ATA_SHT_THIS_ID,
+ .sg_tablesize = LIBATA_MAX_PRD,
+ .max_sectors = ATA_MAX_SECTORS,
+ .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
+ .use_new_eh_code = ATA_SHT_NEW_EH_CODE,
+ .emulated = ATA_SHT_EMULATED,
+ .use_clustering = ATA_SHT_USE_CLUSTERING,
+ .proc_name = DRV_NAME,
+ .bios_param = ata_std_bios_param,
+};
+
+static struct ata_port_operations uli_ops = {
+ .port_disable = ata_port_disable,
+
+ .tf_load = ata_tf_load,
+ .tf_read = ata_tf_read,
+ .check_status = ata_check_status,
+ .exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
+
+ .phy_reset = sata_phy_reset,
+
+ .bmdma_setup = ata_bmdma_setup,
+ .bmdma_start = ata_bmdma_start,
+ .qc_prep = ata_qc_prep,
+ .qc_issue = ata_qc_issue_prot,
+
+ .eng_timeout = ata_eng_timeout,
+
+ .irq_handler = ata_interrupt,
+ .irq_clear = ata_bmdma_irq_clear,
+
+ .scr_read = uli_scr_read,
+ .scr_write = uli_scr_write,
+
+ .port_start = ata_port_start,
+ .port_stop = ata_port_stop,
+};
+
+static struct ata_port_info uli_port_info = {
+ .sht = &uli_sht,
+ .host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+ ATA_FLAG_NO_LEGACY,
+ .pio_mask = 0x03, //support pio mode 4 (FIXME)
+ .udma_mask = 0x7f, //support udma mode 6
+ .port_ops = &uli_ops,
+};
+
+
+MODULE_AUTHOR("Peer Chen");
+MODULE_DESCRIPTION("low-level driver for ULi Electronics SATA controller");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(pci, uli_pci_tbl);
+
+static unsigned int get_scr_cfg_addr(unsigned int port_no, unsigned int sc_reg)
+{
+ unsigned int addr = ULI_SCR_BASE + (4 * sc_reg);
+
+ switch (port_no) {
+ case 0:
+ break;
+ case 1:
+ addr += ULI_SATA1_OFS;
+ break;
+ case 2:
+ addr += ULI_SATA1_OFS*4;
+ break;
+ case 3:
+ addr += ULI_SATA1_OFS*5;
+ break;
+ default:
+ BUG();
+ break;
+ }
+ return addr;
+}
+
+static u32 uli_scr_cfg_read (struct ata_port *ap, unsigned int sc_reg)
+{
+ unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, sc_reg);
+ u32 val;
+
+ pci_read_config_dword(ap->host_set->pdev, cfg_addr, &val);
+ return val;
+}
+
+static void uli_scr_cfg_write (struct ata_port *ap, unsigned int scr, u32 val)
+{
+ unsigned int cfg_addr = get_scr_cfg_addr(ap->port_no, scr);
+
+ pci_write_config_dword(ap->host_set->pdev, cfg_addr, val);
+}
+
+static u32 uli_scr_read (struct ata_port *ap, unsigned int sc_reg)
+{
+ if (sc_reg > SCR_CONTROL)
+ return 0xffffffffU;
+
+ return uli_scr_cfg_read(ap, sc_reg);
+}
+
+static void uli_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
+{
+ if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0
+ return;
+
+ uli_scr_cfg_write(ap, sc_reg, val);
+}
+
+/* move to PCI layer, integrate w/ MSI stuff */
+static void pci_enable_intx(struct pci_dev *pdev)
+{
+ u16 pci_command;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+ if (pci_command & PCI_COMMAND_INTX_DISABLE) {
+ pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(pdev, PCI_COMMAND, pci_command);
+ }
+}
+
+static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct ata_probe_ent *probe_ent;
+ struct ata_port_info *ppi;
+ int rc;
+ unsigned int board_idx = (unsigned int) ent->driver_data;
+
+ rc = pci_enable_device(pdev);
+ if (rc)
+ return rc;
+
+ rc = pci_request_regions(pdev, DRV_NAME);
+ if (rc)
+ goto err_out;
+
+ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
+ if (rc)
+ goto err_out_regions;
+
+ ppi = &uli_port_info;
+ probe_ent = ata_pci_init_native_mode(pdev, &ppi);
+ if (!probe_ent) {
+ rc = -ENOMEM;
+ goto err_out_regions;
+ }
+
+ switch (board_idx) {
+ case uli_5287:
+ probe_ent->n_ports = 4;
+
+ probe_ent->port[2].cmd_addr = pci_resource_start(pdev, 0) + 8;
+ probe_ent->port[2].altstatus_addr =
+ probe_ent->port[2].ctl_addr =
+ (pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS) + 4;
+ probe_ent->port[2].bmdma_addr = pci_resource_start(pdev, 4) + 16;
+
+ probe_ent->port[3].cmd_addr = pci_resource_start(pdev, 2) + 8;
+ probe_ent->port[3].altstatus_addr =
+ probe_ent->port[3].ctl_addr =
+ (pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS) + 4;
+ probe_ent->port[3].bmdma_addr = pci_resource_start(pdev, 4) + 24;
+
+ ata_std_ports(&probe_ent->port[2]);
+ ata_std_ports(&probe_ent->port[3]);
+ break;
+
+ case uli_5289:
+ /* do nothing; ata_pci_init_native_mode did it all */
+ break;
+
+ default:
+ BUG();
+ break;
+ }
+
+ pci_set_master(pdev);
+ pci_enable_intx(pdev);
+
+ ata_add_to_probe_list(probe_ent);
+
+ return 0;
+
+err_out_regions:
+ pci_release_regions(pdev);
+
+err_out:
+ pci_disable_device(pdev);
+ return rc;
+
+}
+
+static int __init uli_init(void)
+{
+ int rc;
+
+ rc = pci_module_init(&uli_pci_driver);
+ if (rc)
+ return rc;
+
+ rc = scsi_register_module(MODULE_SCSI_HA, &uli_sht);
+ if (rc) {
+ pci_unregister_driver(&uli_pci_driver);
+ /* TODO: does scsi_register_module return errno val? */
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit uli_exit(void)
+{
+ scsi_unregister_module(MODULE_SCSI_HA, &uli_sht);
+ pci_unregister_driver(&uli_pci_driver);
+}
+
+
+module_init(uli_init);
+module_exit(uli_exit);
diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_via.c 2004-10-14 23:47:29 -04:00
@@ -105,6 +105,7 @@
.tf_read = ata_tf_read,
.check_status = ata_check_status,
.exec_command = ata_exec_command,
+ .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c 2004-10-14 23:47:29 -04:00
+++ b/drivers/scsi/sata_vsc.c 2004-10-14 23:47:29 -04:00
@@ -214,6 +214,7 @@
.tf_read = vsc_sata_tf_read,
.exec_command = ata_exec_command,
.check_status = ata_check_status,
+ .dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start,
diff -Nru a/include/linux/ioport.h b/include/linux/ioport.h
--- a/include/linux/ioport.h 2004-10-14 23:47:29 -04:00
+++ b/include/linux/ioport.h 2004-10-14 23:47:29 -04:00
@@ -85,6 +85,7 @@
extern int check_resource(struct resource *root, unsigned long, unsigned long);
extern int request_resource(struct resource *root, struct resource *new);
+extern struct resource * ____request_resource(struct resource *root, struct resource *new);
extern int release_resource(struct resource *new);
extern int allocate_resource(struct resource *root, struct resource *new,
unsigned long size,
diff -Nru a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h 2004-10-14 23:47:29 -04:00
+++ b/include/linux/libata.h 2004-10-14 23:47:29 -04:00
@@ -190,6 +190,7 @@
Scsi_Host_Template *sht;
struct ata_ioports port[ATA_MAX_PORTS];
unsigned int n_ports;
+ unsigned int hard_port_no;
unsigned int pio_mask;
unsigned int mwdma_mask;
unsigned int udma_mask;
@@ -274,6 +275,7 @@
unsigned long flags; /* ATA_FLAG_xxx */
unsigned int id; /* unique id req'd by scsi midlyr */
unsigned int port_no; /* unique port #; from zero */
+ unsigned int hard_port_no; /* hardware port #; from zero */
struct ata_prd *prd; /* our SG list */
dma_addr_t prd_dma; /* and its DMA mapping */
@@ -321,6 +323,7 @@
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
u8 (*check_status)(struct ata_port *ap);
+ void (*dev_select)(struct ata_port *ap, unsigned int device);
void (*phy_reset) (struct ata_port *ap);
void (*post_set_mode) (struct ata_port *ap);
@@ -363,6 +366,7 @@
};
extern void ata_port_probe(struct ata_port *);
+extern void __sata_phy_reset(struct ata_port *ap);
extern void sata_phy_reset(struct ata_port *ap);
extern void ata_bus_reset(struct ata_port *ap);
extern void ata_port_disable(struct ata_port *);
@@ -384,6 +388,8 @@
extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
+extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
+extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
extern u8 ata_check_status(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
@@ -399,6 +405,7 @@
unsigned int buflen);
extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem);
+extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c 2004-10-14 23:47:29 -04:00
+++ b/kernel/ksyms.c 2004-10-14 23:47:29 -04:00
@@ -448,6 +448,7 @@
#endif
/* resource handling */
+EXPORT_SYMBOL_GPL(____request_resource); /* may disappear in a few months */
EXPORT_SYMBOL(request_resource);
EXPORT_SYMBOL(release_resource);
EXPORT_SYMBOL(allocate_resource);
diff -Nru a/kernel/resource.c b/kernel/resource.c
--- a/kernel/resource.c 2004-10-14 23:47:29 -04:00
+++ b/kernel/resource.c 2004-10-14 23:47:29 -04:00
@@ -166,6 +166,16 @@
return conflict ? -EBUSY : 0;
}
+struct resource *____request_resource(struct resource *root, struct resource *new)
+{
+ struct resource *conflict;
+
+ write_lock(&resource_lock);
+ conflict = __request_resource(root, new);
+ write_unlock(&resource_lock);
+ return conflict;
+}
+
int release_resource(struct resource *old)
{
int retval;