From 76945f6290afc35fbb8f23ba907947396e7dd632 Mon Sep 17 00:00:00 2001 From: Rod Whitby Date: Fri, 24 Feb 2006 22:41:46 +0000 Subject: ixp4xx-kernel: Added support for DSM-G600, and updated to 2.6.16-rc4-git5 --- conf/distro/slugos.conf | 2 +- packages/linux/ixp4xx-kernel.inc | 16 + .../ixp4xx-kernel/2.6.16/05-patch-2.6.16-rc2-ide2 | 16885 ----------------- .../2.6.16/06-remove-extraversion.patch | 2 +- .../ixp4xx-kernel/2.6.16/10-nslu2-fix-flash.patch | 14 - .../2.6.16/61-ixp4xx-beeper-irq.patch | 13 - .../ixp4xx-kernel/2.6.16/61-nslu2-beeper.patch | 32 - .../ixp4xx-kernel/2.6.16/70-artop-latency.patch | 18 +- .../linux/ixp4xx-kernel/2.6.16/75-dsmg600.patch | 353 + .../ixp4xx-kernel/2.6.16/80-nas100d-fix-i2c.patch | 18 - .../ixp4xx-kernel/2.6.16/81-nslu2-power.patch | 17 - packages/linux/ixp4xx-kernel/2.6.16/85-timer.patch | 24 +- .../linux/ixp4xx-kernel/2.6.16/91-maclist.patch | 33 +- .../ixp4xx-kernel/2.6.16/92-nslu2-maclist.patch | 10 +- .../ixp4xx-kernel/2.6.16/93-loft-maclist.patch | 96 - .../ixp4xx-kernel/2.6.16/94-nslu2-setup.patch | 6 +- .../ixp4xx-kernel/2.6.16/950-leds-timer.patch | 151 - .../linux/ixp4xx-kernel/2.6.16/96-loft-leds.patch | 62 - .../linux/ixp4xx-kernel/2.6.16/96-nslu2-leds.patch | 10 +- .../ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch | 299 + .../ixp4xx-kernel/2.6.16/97-ds101-buttons.patch | 4 +- .../linux/ixp4xx-kernel/2.6.16/97-ds101-doc.patch | 43 + .../ixp4xx-kernel/2.6.16/97-ds101-includes.patch | 19 +- .../linux/ixp4xx-kernel/2.6.16/97-ds101-misc.patch | 33 - .../ixp4xx-kernel/2.6.16/97-ds101-setup.patch | 32 +- packages/linux/ixp4xx-kernel/2.6.16/defconfig | 37 +- .../linux/ixp4xx-kernel/2.6.16/leds-class.patch | 676 +- .../ixp4xx-kernel/2.6.16/patch-2.6.16-rc4-ide1 | 18260 ------------------ .../ixp4xx-kernel/2.6.16/patch-2.6.16-rc4-ide2 | 18474 +++++++++++++++++++ packages/linux/ixp4xx-kernel_2.6.16-rc4-git5.bb | 50 + packages/linux/ixp4xx-kernel_2.6.16-rc4.bb | 50 - 31 files changed, 19559 insertions(+), 36180 deletions(-) delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/05-patch-2.6.16-rc2-ide2 delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/10-nslu2-fix-flash.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/61-ixp4xx-beeper-irq.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/61-nslu2-beeper.patch create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/75-dsmg600.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/80-nas100d-fix-i2c.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/81-nslu2-power.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/93-loft-maclist.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/950-leds-timer.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/96-loft-leds.patch create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/96-pata-ixp4xx.patch create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/97-ds101-doc.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/97-ds101-misc.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/patch-2.6.16-rc4-ide1 create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/patch-2.6.16-rc4-ide2 create mode 100644 packages/linux/ixp4xx-kernel_2.6.16-rc4-git5.bb delete mode 100644 packages/linux/ixp4xx-kernel_2.6.16-rc4.bb diff --git a/conf/distro/slugos.conf b/conf/distro/slugos.conf index 3b094d769d..2273aca31a 100644 --- a/conf/distro/slugos.conf +++ b/conf/distro/slugos.conf @@ -170,7 +170,7 @@ PREFERRED_VERSION_glibc ?= "2.3.5+cvs20050627" # Select the correct versions of the kernel and modules (these are the # defaults, override in the conf/distro top-level distro file). PREFERRED_PROVIDER_virtual/kernel ?= "ixp4xx-kernel" -PREFERRED_VERSION_ixp4xx-kernel ?= "2.6.15.2" +PREFERRED_VERSION_ixp4xx-kernel ?= "2.6.16-rc4-git5" # Built-in ethernet modules PREFERRED_PROVIDER_virtual/ixp-eth ?= "ixp400-eth" diff --git a/packages/linux/ixp4xx-kernel.inc b/packages/linux/ixp4xx-kernel.inc index 41ff745e71..52f216438a 100644 --- a/packages/linux/ixp4xx-kernel.inc +++ b/packages/linux/ixp4xx-kernel.inc @@ -297,6 +297,20 @@ pkg_postrm_kernel-image-nas100d () { update-alternatives --remove ${KERNEL_IMAGETYPE} /${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE}-nas100d${ARCH_BYTE_SEX}-${KERNEL_RELEASE} || true } +# The correct settings for the DSMG600 board: +dsmg600_MACHID = "964" +PACKAGES += "kernel-image-dsmg600" +PKG_kernel-image-dsmg600 = "kernel-image-${KERNEL_VERSION}" +PACKAGE_ARCH_kernel-image-dsmg600 = "dsmg600${ARCH_BYTE_SEX}" +DESCRIPTION_kernel-image-dsmg600 = "Linux kernel for the D-Link DSM-G600" +FILES_kernel-image-dsmg600 = "/${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE}-dsmg600${ARCH_BYTE_SEX}-${KERNEL_RELEASE}" +pkg_postinst_kernel-image-dsmg600 () { + update-alternatives --install /${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE} ${KERNEL_IMAGETYPE} /${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE}-dsmg600${ARCH_BYTE_SEX}-${KERNEL_RELEASE} ${KERNEL_PRIORITY} || true +} +pkg_postrm_kernel-image-dsmg600 () { + update-alternatives --remove ${KERNEL_IMAGETYPE} /${KERNEL_IMAGEDEST}/${KERNEL_IMAGETYPE}-dsmg600${ARCH_BYTE_SEX}-${KERNEL_RELEASE} || true +} + #FIXUP: the correct instructions to copy the kernel prepended with the le fixup #FIXME: do a fixup for BE too... FIXUP_armeb = "cp$" @@ -345,6 +359,7 @@ do_install_append() { install_image 'ds101${ARCH_BYTE_SEX}' '${ds101_MACHID}' install_image 'loft${ARCH_BYTE_SEX}' '${loft_MACHID}' install_image 'nas100d${ARCH_BYTE_SEX}' '${nas100d_MACHID}' + install_image 'dsmg600${ARCH_BYTE_SEX}' '${dsmg600_MACHID}' } do_deploy[dirs] = "${S}" @@ -362,6 +377,7 @@ do_deploy() { deploy_image 'ds101${ARCH_BYTE_SEX}' '${ds101_MACHID}' deploy_image 'loft${ARCH_BYTE_SEX}' '${loft_MACHID}' deploy_image 'nas100d${ARCH_BYTE_SEX}' '${nas100d_MACHID}' + deploy_image 'dsmg600${ARCH_BYTE_SEX}' '${dsmg600_MACHID}' } addtask deploy before do_build after do_compile diff --git a/packages/linux/ixp4xx-kernel/2.6.16/05-patch-2.6.16-rc2-ide2 b/packages/linux/ixp4xx-kernel/2.6.16/05-patch-2.6.16-rc2-ide2 deleted file mode 100644 index 3ea46331f6..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/05-patch-2.6.16-rc2-ide2 +++ /dev/null @@ -1,16885 +0,0 @@ -diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.vanilla-2.6.16-rc2/arch/i386/pci/fixup.c linux-2.6.16-rc2/arch/i386/pci/fixup.c ---- linux.vanilla-2.6.16-rc2/arch/i386/pci/fixup.c 2006-02-06 12:21:33.000000000 +0000 -+++ linux-2.6.16-rc2/arch/i386/pci/fixup.c 2006-02-01 14:49:17.000000000 +0000 -@@ -74,52 +74,6 @@ - } - DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810); - --static void __devinit pci_fixup_ide_bases(struct pci_dev *d) --{ -- int i; -- -- /* -- * PCI IDE controllers use non-standard I/O port decoding, respect it. -- */ -- if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) -- return; -- DBG("PCI: IDE base address fixup for %s\n", pci_name(d)); -- for(i=0; i<4; i++) { -- struct resource *r = &d->resource[i]; -- if ((r->start & ~0x80) == 0x374) { -- r->start |= 2; -- r->end = r->start; -- } -- } --} --DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); -- --static void __devinit pci_fixup_ide_trash(struct pci_dev *d) --{ -- int i; -- -- /* -- * Runs the fixup only for the first IDE controller -- * (Shai Fultheim - shai@ftcon.com) -- */ -- static int called = 0; -- if (called) -- return; -- called = 1; -- -- /* -- * There exist PCI IDE controllers which have utter garbage -- * in first four base registers. Ignore that. -- */ -- DBG("PCI: IDE base address trash cleared for %s\n", pci_name(d)); -- for(i=0; i<4; i++) -- d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0; --} --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash); --DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash); -- - static void __devinit pci_fixup_latency(struct pci_dev *d) - { - /* -diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.vanilla-2.6.16-rc2/drivers/cdrom/cdrom.c linux-2.6.16-rc2/drivers/cdrom/cdrom.c ---- linux.vanilla-2.6.16-rc2/drivers/cdrom/cdrom.c 2006-02-06 12:21:34.000000000 +0000 -+++ linux-2.6.16-rc2/drivers/cdrom/cdrom.c 2006-01-17 16:34:19.000000000 +0000 -@@ -1131,7 +1131,8 @@ - This ensures that the drive gets unlocked after a mount fails. This - is a goto to avoid bloating the driver with redundant code. */ - clean_up_and_return: -- cdinfo(CD_OPEN, "open failed.\n"); -+ /* Don't log this, its a perfectly normal user occurence */ -+ /* cdinfo(CD_WARNING, "open failed.\n"); */ - if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) { - cdo->lock_door(cdi, 0); - cdinfo(CD_OPEN, "door unlocked.\n"); -diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.vanilla-2.6.16-rc2/drivers/pci/probe.c linux-2.6.16-rc2/drivers/pci/probe.c ---- linux.vanilla-2.6.16-rc2/drivers/pci/probe.c 2006-02-06 12:21:35.000000000 +0000 -+++ linux-2.6.16-rc2/drivers/pci/probe.c 2006-02-01 15:56:28.000000000 +0000 -@@ -627,6 +627,7 @@ - static int pci_setup_device(struct pci_dev * dev) - { - u32 class; -+ u16 cmd; - - sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); -@@ -654,6 +655,31 @@ - pci_read_bases(dev, 6, PCI_ROM_ADDRESS); - pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); - pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device); -+ -+ /* -+ * Do the ugly legacy mode stuff here rather than broken chip -+ * quirk code. Legacy mode ATA controllers have fixed -+ * addresses. These are not always echoed in BAR0-3, and -+ * BAR0-3 in a few cases contain junk! -+ */ -+ if (class == PCI_CLASS_STORAGE_IDE) { -+ u8 progif; -+ pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); -+ if ((progif & 5) != 5) { -+ dev->resource[0].start = 0x1F0; -+ dev->resource[0].end = 0x1F7; -+ dev->resource[0].flags = IORESOURCE_IO; -+ dev->resource[1].start = 0x3F6; -+ dev->resource[1].end = 0x3F6; -+ dev->resource[1].flags = IORESOURCE_IO; -+ dev->resource[2].start = 0x170; -+ dev->resource[2].end = 0x177; -+ dev->resource[2].flags = IORESOURCE_IO; -+ dev->resource[3].start = 0x376; -+ dev->resource[3].end = 0x376; -+ dev->resource[3].flags = IORESOURCE_IO; -+ } -+ } - break; - - case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ -@@ -687,6 +713,10 @@ - dev->class = PCI_CLASS_NOT_DEFINED; - } - -+ /* BIOS enabled, so assume there is a good reason */ -+ pci_read_config_word(dev, PCI_COMMAND, &cmd); -+ if(cmd & PCI_COMMAND_MASTER) -+ dev->is_enabled = 1; - /* We found a fine healthy device, go go go... */ - return 0; - } -diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.vanilla-2.6.16-rc2/drivers/scsi/ata_generic.c linux-2.6.16-rc2/drivers/scsi/ata_generic.c ---- linux.vanilla-2.6.16-rc2/drivers/scsi/ata_generic.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.16-rc2/drivers/scsi/ata_generic.c 2006-02-07 13:47:27.337665568 +0000 -@@ -0,0 +1,242 @@ -+/* -+ * ata_generic.c - Generic PATA/SATA controller driver. -+ * Copyright 2005 Red Hat Inc , all rights reserved. -+ * -+ * Elements from ide/pci/generic.c -+ * Copyright (C) 2001-2002 Andre Hedrick -+ * Portions (C) Copyright 2002 Red Hat Inc -+ * -+ * May be copied or modified under the terms of the GNU General Public License -+ * -+ * Driver for PCI IDE interfaces implementing the standard bus mastering -+ * interface functionality. This assumes the BIOS did the drive set up and -+ * tuning for us. By default we do not grab all IDE class devices as they -+ * may have other drivers or need fixups to avoid problems. Instead we keep -+ * a default list of stuff without documentation/driver that appears to -+ * work. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include "scsi.h" -+#include -+#include -+ -+#define DRV_NAME "generic" -+#define DRV_VERSION "0.1" -+ -+/* -+ * A generic parallel ATA driver using libata -+ */ -+ -+static void genpata_phy_reset(struct ata_port *ap) -+{ -+ /* We know the BIOS already did the mode work. Don't tempt any -+ one else to "fix" things */ -+ ap->cbl = ATA_CBL_PATA80; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} -+ -+/** -+ * genpata_set_mode - mode setting -+ * @ap: interface to set up -+ * -+ * Use a non standard set_mode function. We don't want to be tuned. -+ * The BIOS configured everything. Our job is not to fiddle. We -+ * read the dma enabled bits from the PCI configuration of the device -+ * and respect them. -+ */ -+ -+static void genpata_set_mode(struct ata_port *ap) -+{ -+ int dma_enabled; -+ int i; -+ -+ /* Bits 5 and 6 indicate if DMA is active on master/slave */ -+ dma_enabled = inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD); -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *dev = &ap->device[i]; -+ if (ata_dev_present(dev)) { -+ /* We don't really care */ -+ dev->pio_mode = XFER_PIO_0; -+ dev->dma_mode = XFER_MW_DMA_0; -+ /* We do need the right mode information for DMA or PIO -+ and this comes from the current configuration flags */ -+ /* FIXME: at some point in the future this should become -+ a library helper which reads the disk modes from the -+ disk as well */ -+ if(dma_enabled & (1 << (5 + i))) { -+ dev->xfer_mode = XFER_MW_DMA_0; -+ dev->xfer_shift = ATA_SHIFT_MWDMA; -+ dev->flags &= ~ATA_DFLAG_PIO; -+ } else { -+ dev->xfer_mode = XFER_PIO_0; -+ dev->xfer_shift = ATA_SHIFT_PIO; -+ dev->flags |= ATA_DFLAG_PIO; -+ } -+ } -+ } -+} -+ -+static struct scsi_host_template genpata_sht = { -+ .module = THIS_MODULE, -+ .name = DRV_NAME, -+ .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, -+ .emulated = ATA_SHT_EMULATED, -+ .use_clustering = ATA_SHT_USE_CLUSTERING, -+ .proc_name = DRV_NAME, -+ .dma_boundary = ATA_DMA_BOUNDARY, -+ .slave_configure = ata_scsi_slave_config, -+ .bios_param = ata_std_bios_param, -+// .ordered_flush = 1, -+}; -+ -+static struct ata_port_operations genpata_port_ops = { -+ .set_mode = genpata_set_mode, -+ -+ .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 = genpata_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ -+ .data_xfer = ata_pio_data_xfer, -+ -+ .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, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop -+}; -+ -+static int ide_generic_all; /* Set to claim all devices */ -+ -+static int __init ide_generic_all_on(char *unused) -+{ -+ ide_generic_all = 1; -+ printk(KERN_INFO "ATA generic will claim all unknown PCI IDE class storage controllers.\n"); -+ return 1; -+} -+ -+__setup("all-generic-ide", ide_generic_all_on); -+ -+/** -+ * pata_generic_init - attach generic IDE -+ * @dev: PCI device found -+ * @id: match entry -+ * -+ * Called each time a matching IDE interface is found. We check if the -+ * interface is one we wish to claim and if so we perform any chip -+ * specific hacks then let the ATA layer do the heavy lifting. -+ */ -+ -+static int pata_generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) -+{ -+ u16 command; -+ static struct ata_port_info info = { -+ .sht = &genpata_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | ATA_FLAG_IRQ_MASK, -+ .pio_mask = 0x1f, -+ .mwdma_mask = 0x07, -+ .udma_mask = 0x3f, -+ .port_ops = &genpata_port_ops -+ }; -+ static struct ata_port_info *port_info[2] = { &info, &info }; -+ -+ /* Don't use the generic entry unless instructed to do so */ -+ if (id->driver_data == 1 && ide_generic_all == 0) -+ return -ENODEV; -+ -+ /* Devices that need care */ -+ if (dev->vendor == PCI_VENDOR_ID_UMC && -+ dev->device == PCI_DEVICE_ID_UMC_UM8886A && -+ (!(PCI_FUNC(dev->devfn) & 1))) -+ return -ENODEV; -+ -+ if (dev->vendor == PCI_VENDOR_ID_OPTI && -+ dev->device == PCI_DEVICE_ID_OPTI_82C558 && -+ (!(PCI_FUNC(dev->devfn) & 1))) -+ return -ENODEV; -+ -+ /* Don't re-enable devices in generic mode or we will break some -+ motherboards with disabled and unused IDE controllers */ -+ pci_read_config_word(dev, PCI_COMMAND, &command); -+ if (!(command & PCI_COMMAND_IO)) -+ return -ENODEV; -+ -+ if (dev->vendor == PCI_VENDOR_ID_AL) -+ ata_pci_clear_simplex(dev); -+ -+ return ata_pci_init_one(dev, port_info, 2); -+} -+ -+static struct pci_device_id pata_generic[] = { -+ { PCI_DEVICE(PCI_VENDOR_ID_NS,PCI_DEVICE_ID_NS_87410),}, -+ { PCI_DEVICE(PCI_VENDOR_ID_PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C558), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), }, -+ { PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), }, -+ /* Must come last. If you add entries adjust this table appropriately */ -+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1}, -+ { 0, }, -+}; -+ -+static struct pci_driver pata_generic_pci_driver = { -+ .name = DRV_NAME, -+ .id_table = pata_generic, -+ .probe = pata_generic_init_one, -+ .remove = ata_pci_remove_one -+}; -+ -+static int __init pata_generic_init(void) -+{ -+ return pci_module_init(&pata_generic_pci_driver); -+} -+ -+ -+static void __exit pata_generic_exit(void) -+{ -+ pci_unregister_driver(&pata_generic_pci_driver); -+} -+ -+ -+MODULE_AUTHOR("Alan Cox"); -+MODULE_DESCRIPTION("low-level driver for generic ATA"); -+MODULE_LICENSE("GPL"); -+MODULE_DEVICE_TABLE(pci, pata_generic); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(pata_generic_init); -+module_exit(pata_generic_exit); -diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.vanilla-2.6.16-rc2/drivers/scsi/ata_piix.c linux-2.6.16-rc2/drivers/scsi/ata_piix.c ---- linux.vanilla-2.6.16-rc2/drivers/scsi/ata_piix.c 2006-02-06 12:21:35.000000000 +0000 -+++ linux-2.6.16-rc2/drivers/scsi/ata_piix.c 2006-02-06 12:28:58.000000000 +0000 -@@ -91,9 +91,10 @@ - #include - #include - #include -+#include - - #define DRV_NAME "ata_piix" --#define DRV_VERSION "1.05" -+#define DRV_VERSION "1.05-ac1" - - enum { - PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ -@@ -122,6 +123,17 @@ - piix4_pata = 2, - ich6_sata = 3, - ich6_sata_ahci = 4, -+ ich0_pata = 5, -+ ich2_pata = 6, -+ ich3_pata = 7, -+ ich4_pata = 8, -+ cich_pata = 9, -+ piix3_pata = 10, -+ esb_pata = 11, -+ ich_pata = 12, -+ ich6_pata = 13, -+ ich7_pata = 14, -+ esb2_pata = 15, - - PIIX_AHCI_DEVICE = 6, - }; -@@ -130,20 +142,69 @@ - const struct pci_device_id *ent); - - static void piix_pata_phy_reset(struct ata_port *ap); -+static void ich_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); - static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev); -+static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev); - - static unsigned int in_module_init = 1; - - static const struct pci_device_id piix_pci_tbl[] = { - #ifdef ATA_ENABLE_PATA -+#if 0 -+ /* Neptune and earlier are simple PIO */ -+ /* 430HX and friends. MWDMA */ -+ { 0x8086, 0x122e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix3_pata }, -+ { 0x8086, 0x1230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix3_pata }, -+ /* Intel PIIX3 */ -+ { 0x8086, 0x7010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix3_pata }, -+#endif -+ /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ -+ /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ - { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, - { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, - { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, -+ /* Intel PIIX4 */ -+ { 0x8086, 0x7199, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, -+ /* Intel PIIX4 */ -+ { 0x8086, 0x7601, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, -+ /* Intel PIIX */ -+ { 0x8086, 0x84CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix4_pata }, -+ /* Intel ICH (i810, i815, i840) UDMA 66*/ -+ { 0x8086, 0x2411, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata }, -+ /* Intel ICH0 : UDMA 33*/ -+ { 0x8086, 0x2421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich0_pata }, -+ /* Intel ICH2M */ -+ { 0x8086, 0x244A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich2_pata }, -+ /* Intel ICH2 (i810E2, i845, 850, 860) UDMA 100 */ -+ { 0x8086, 0x244B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich2_pata }, -+ /* Intel ICH3M */ -+ { 0x8086, 0x248A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich3_pata }, -+ /* Intel ICH3 (E7500/1) UDMA 100 */ -+ { 0x8086, 0x248B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich3_pata }, -+#if 0 -+ { 0x8086, 0x24C1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, dunno_pata }, -+#endif -+ /* Intel ICH4 (i845GV, i845E, i852, i855) UDMA 100 */ -+ { 0x8086, 0x24CA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich4_pata }, -+ { 0x8086, 0x24CB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich4_pata }, -+ /* Intel ICH5 */ -+ { 0x8086, 0x24DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_pata }, -+ /* C-ICH (i810E2) */ -+ { 0x8086, 0x245B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, cich_pata }, -+ /* ESB (855GME/875P + 6300ESB) UDMA 100 */ -+ { 0x8086, 0x25A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb_pata }, -+ /* ICH6 (and 6) (i915) UDMA 100 */ -+ { 0x8086, 0x266F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_pata }, -+ /* ICH7/7-R (i945, i975) UDMA 100*/ -+ { 0x8086, 0x27DF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7_pata }, -+ { 0x8086, 0x269E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, esb2_pata }, - #endif -- -- /* NOTE: The following PCI ids must be kept in sync with the -+ /* -+ * SATA ports -+ * -+ * NOTE: The following PCI ids must be kept in sync with the - * list in drivers/pci/quirks.c. - */ - -@@ -213,6 +274,40 @@ - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, -+ -+ .data_xfer = ata_pio_data_xfer, -+ -+ .eng_timeout = ata_eng_timeout, -+ -+ .irq_handler = ata_interrupt, -+ .irq_clear = ata_bmdma_irq_clear, -+ -+ .port_start = ata_port_start, -+ .port_stop = ata_port_stop, -+ .host_stop = ata_host_stop, -+}; -+ -+static const struct ata_port_operations ich_pata_ops = { -+ .port_disable = ata_port_disable, -+ .set_piomode = piix_set_piomode, -+ .set_dmamode = ich_set_dmamode, -+ -+ .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 = ich_pata_phy_reset, -+ -+ .bmdma_setup = ata_bmdma_setup, -+ .bmdma_start = ata_bmdma_start, -+ .bmdma_stop = ata_bmdma_stop, -+ .bmdma_status = ata_bmdma_status, -+ .qc_prep = ata_qc_prep, -+ .qc_issue = ata_qc_issue_prot, -+ -+ .data_xfer = ata_pio_data_xfer, - - .eng_timeout = ata_eng_timeout, - -@@ -242,6 +337,8 @@ - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - -+ .data_xfer = ata_pio_data_xfer, -+ - .eng_timeout = ata_eng_timeout, - - .irq_handler = ata_interrupt, -@@ -259,13 +356,9 @@ - .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST | - PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio0-4 */ --#if 0 - .mwdma_mask = 0x06, /* mwdma1-2 */ --#else -- .mwdma_mask = 0x00, /* mwdma broken */ --#endif - .udma_mask = 0x3f, /* udma0-5 */ -- .port_ops = &piix_pata_ops, -+ .port_ops = &ich_pata_ops, - }, - - /* ich5_sata */ -@@ -284,11 +377,7 @@ - .sht = &piix_sht, - .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .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, - .port_ops = &piix_pata_ops, - }, -@@ -316,6 +405,116 @@ - .udma_mask = 0x7f, /* udma0-6 */ - .port_ops = &piix_sata_ops, - }, -+ -+ /* ich0_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ -+ .udma_mask = 0x07, /* UDMA33 only */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich2_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ -+ .udma_mask = 0x1f, /* UDMA100 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich3_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ -+ .udma_mask = 0x1f, /* UDMA100 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich4_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = 0x1f, /* UDMA100 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* cich_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = 0x1f, /* UDMA100 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* piix3_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, -+ .pio_mask = 0x1f, /* pio0-4 */ -+ .mwdma_mask = 0x07, /* mwdma1-2 */ -+ .udma_mask = ATA_UDMA_MASK_40C, -+ .port_ops = &piix_pata_ops, -+ }, -+ -+ /* esb_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = 0x1f, /* UDMA100 */ -+ .port_ops = &piix_pata_ops, -+ }, -+ -+ /* ich_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = 0x07, /* UDMA66 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich6_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = 0x3f, /* UDMA133 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* ich7_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = 0x3f, /* UDMA133 */ -+ .port_ops = &ich_pata_ops, -+ }, -+ -+ /* esb2_pata */ -+ { -+ .sht = &piix_sht, -+ .host_flags = ATA_FLAG_SRST | ATA_FLAG_SLAVE_POSS, -+ .pio_mask = 0x1f, /* pio 0-4 */ -+ .mwdma_mask = 0x06, /* Check: maybe 0x07 */ -+ .udma_mask = 0x1f, /* UDMA100 -- CHECKME --*/ -+ .port_ops = &ich_pata_ops, -+ }, - }; - - static struct pci_bits piix_enable_bits[] = { -@@ -339,7 +538,7 @@ - * LOCKING: - * None (inherited from caller). - */ --static void piix_pata_cbl_detect(struct ata_port *ap) -+static void ich_pata_cbl_detect(struct ata_port *ap) - { - struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - u8 tmp, mask; -@@ -366,8 +565,9 @@ - * piix_pata_phy_reset - Probe specified port on PATA host controller - * @ap: Port to probe - * -- * Probe PATA phy. -- * -+ * Probe PATA phy. Unlike the ICH we have no IOCFG register and -+ * don't do UDMA66+ anyway. -+ - * LOCKING: - * None (inherited from caller). - */ -@@ -381,11 +581,34 @@ - printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); - return; - } -+ ap->cbl = ATA_CBL_PATA40; -+ ata_port_probe(ap); -+ ata_bus_reset(ap); -+} - -- piix_pata_cbl_detect(ap); - -- ata_port_probe(ap); -+/** -+ * ich_pata_phy_reset - Probe specified port on PATA host controller -+ * @ap: Port to probe -+ * -+ * Probe PATA phy. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void ich_pata_phy_reset(struct ata_port *ap) -+{ -+ struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); - -+ if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->hard_port_no])) { -+ ata_port_disable(ap); -+ printk(KERN_INFO "ata%u: port disabled. ignoring.\n", ap->id); -+ return; -+ } -+ -+ ich_pata_cbl_detect(ap); -+ ata_port_probe(ap); - ata_bus_reset(ap); - } - -@@ -481,6 +704,13 @@ - unsigned int slave_port = 0x44; - u16 master_data; - u8 slave_data; -+ u8 udma_enable; -+ int control = 0; -+ -+ /* -+ * See Intel Document 298600-004 for the timing programing rules -+ * for ICH controllers. -+ */ - - static const /* ISP RTC */ - u8 timings[][2] = { { 0, 0 }, -@@ -489,20 +719,30 @@ - { 2, 1 }, - { 2, 3 }, }; - -+ if (pio > 2) -+ control |= 1; /* TIME1 enable */ -+ if (ata_pio_need_iordy(adev)) -+ control |= 2; /* IE enable */ -+ -+ /* Intel specifies that the PPE functionality is for disk only */ -+ if (adev->class == ATA_DEV_ATA) -+ control |= 4; /* PPE enable */ -+ - pci_read_config_word(dev, master_port, &master_data); - if (is_slave) { -+ /* Enable SITRE (seperate slave timing register) */ - master_data |= 0x4000; -- /* enable PPE, IE and TIME */ -- master_data |= 0x0070; -+ /* enable PPE1, IE1 and TIME1 as needed */ -+ master_data |= (control << 4); - pci_read_config_byte(dev, slave_port, &slave_data); - slave_data &= (ap->hard_port_no ? 0x0f : 0xf0); -- slave_data |= -- (timings[pio][0] << 2) | -- (timings[pio][1] << (ap->hard_port_no ? 4 : 0)); -+ /* Load the timing nibble for this slave */ -+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->hard_port_no ? 4 : 0); - } else { -+ /* Master keeps the bits in a different format */ - master_data &= 0xccf8; -- /* enable PPE, IE and TIME */ -- master_data |= 0x0007; -+ /* Enable PPE, IE and TIME as appropriate */ -+ master_data |= control; - master_data |= - (timings[pio][0] << 12) | - (timings[pio][1] << 8); -@@ -510,84 +750,165 @@ - pci_write_config_word(dev, master_port, master_data); - if (is_slave) - pci_write_config_byte(dev, slave_port, slave_data); -+ -+ /* Ensure the UDMA bit is off - it will be turned back on if -+ UDMA is selected */ -+ -+ if(ap->udma_mask) { -+ pci_read_config_byte(dev, 0x48, &udma_enable); -+ udma_enable &= ~(1 << (2 * ap->hard_port_no + adev->devno)); -+ pci_write_config_byte(dev, 0x48, udma_enable); -+ } - } - - /** -- * piix_set_dmamode - Initialize host controller PATA PIO timings -+ * do_piix_set_dmamode - Initialize host controller PATA PIO timings - * @ap: Port whose timings we are configuring -- * @adev: um -- * @udma: udma mode, 0 - 6 -+ * @adev: device to configure -+ * @isich: True if the device is an ICH and has IOCFG registers - * -- * Set UDMA mode for device, in host controller PCI config space. -+ * Set MW/UDMA mode for device, in host controller PCI config space. -+ * Note: We know the caller has already set the PIO mode. In doing -+ * so it has correctly set PPE, SITRE, IORDY and TIME1. We rely on that. - * - * LOCKING: - * None (inherited from caller). - */ - --static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+static void do_pata_set_dmamode (struct ata_port *ap, struct ata_device *adev, int isich) - { -- unsigned int udma = adev->dma_mode; /* FIXME: MWDMA too */ - struct pci_dev *dev = to_pci_dev(ap->host_set->dev); -- u8 maslave = ap->hard_port_no ? 0x42 : 0x40; -- u8 speed = udma; -- 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; -- int w_flag = 0x10 << drive_dn; -- int u_speed = 0; -- int sitre; -- u16 reg4042, reg4a; -- u8 reg48, reg54, reg55; -- -- pci_read_config_word(dev, maslave, ®4042); -- DPRINTK("reg4042 = 0x%04x\n", reg4042); -- sitre = (reg4042 & 0x4000) ? 1 : 0; -- pci_read_config_byte(dev, 0x48, ®48); -- pci_read_config_word(dev, 0x4a, ®4a); -- pci_read_config_byte(dev, 0x54, ®54); -- pci_read_config_byte(dev, 0x55, ®55); -- -- switch(speed) { -- case XFER_UDMA_4: -- case XFER_UDMA_2: u_speed = 2 << (drive_dn * 4); break; -- case XFER_UDMA_6: -- case XFER_UDMA_5: -- 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; -- } -+ u8 master_port = ap->hard_port_no ? 0x42 : 0x40; -+ u16 master_data; -+ u8 speed = adev->dma_mode; -+ int devid = adev->devno + 2 * ap->hard_port_no; -+ u8 udma_enable; -+ -+ static const /* ISP RTC */ -+ u8 timings[][2] = { { 0, 0 }, -+ { 0, 0 }, -+ { 1, 0 }, -+ { 2, 1 }, -+ { 2, 3 }, }; - -+ pci_read_config_word(dev, master_port, &master_data); -+ pci_read_config_byte(dev, 0x48, &udma_enable); -+ - 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); -+ unsigned int udma = adev->dma_mode - XFER_UDMA_0; -+ u16 udma_timing; -+ u32 ideconf; -+ int u_clock, u_speed; -+ -+ /* -+ * UDMA is handled by a combination of clock switching and -+ * selection of dividers -+ * -+ * Handy rule: Odd modes are UDMATIMx 01, even are 02 -+ * except UDMA0 which is 00 -+ */ -+ u_speed = min(2 - (udma & 1), udma); -+ if (udma == 5) -+ u_clock = 0x1000; /* 100Mhz */ -+ else if (udma > 2) -+ u_clock = 1; /* 66Mhz */ -+ else -+ u_clock = 0; /* 33Mhz */ -+ -+ udma_enable |= (1 << devid); -+ -+ /* Load the CT/RP selection */ -+ pci_read_config_word(dev, 0x4A, &udma_timing); -+ udma_timing &= ~(3 << (4 * devid)); -+ udma_timing |= u_speed << (4 * devid); -+ pci_write_config_word(dev, 0x4A, udma_timing); -+ -+ if(isich) { -+ /* Select a 33/66/100Mhz clock */ -+ pci_read_config_dword(dev, 0x54, &ideconf); -+ ideconf &= ~(0x1001 << devid); -+ ideconf |= u_clock << devid; -+ /* For ICH or later we should set bit 10 for better -+ performance (WR_PingPong_En) */ -+ pci_write_config_dword(dev, 0x54, ideconf); - } -- 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 { -- 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); -+ /* -+ * MWDMA is driven by the PIO timings. We must also enable -+ * IORDY unconditionally along with TIME1. PPE has already -+ * been set when the PIO timing was set. -+ */ -+ unsigned int mwdma = adev->dma_mode - XFER_MW_DMA_0; -+ unsigned int control; -+ u8 slave_data; -+ const unsigned int needed_pio[3] = { -+ XFER_PIO_0, XFER_PIO_3, XFER_PIO_4 -+ }; -+ int pio = needed_pio[mwdma] - XFER_PIO_0; -+ -+ control = 3; /* IORDY|TIME1 */ -+ -+ /* If the drive MWDMA is faster than it can do PIO then -+ we must force PIO into PIO0 */ -+ -+ if (adev->pio_mode < needed_pio[mwdma]) -+ /* Enable DMA timing only */ -+ control |= 8; /* PIO cycles in PIO0 */ -+ -+ if (adev->devno) { /* Slave */ -+ master_data &= 0xFF4F; /* Mask out IORDY|TIME1|DMAONLY */ -+ master_data |= control << 4; -+ pci_read_config_byte(dev, 0x44, &slave_data); -+ slave_data &= (0x0F + 0xE1 * ap->hard_port_no); -+ /* Load the matching timing */ -+ slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << (ap->hard_port_no ? 4 : 0); -+ pci_write_config_byte(dev, 0x44, slave_data); -+ } else { /* Master */ -+ master_data &= 0xCCF4; /* Mask out IORDY|TIME1|DMAONLY -+ and master timing bits */ -+ master_data |= control; -+ master_data |= -+ (timings[pio][0] << 12) | -+ (timings[pio][1] << 8); -+ } -+ udma_enable &= ~(1 << devid); -+ pci_write_config_word(dev, master_port, master_data); - } -+ /* Don't scribble on 0x48 if the controller does not support UDMA */ -+ if(ap->udma_mask) -+ pci_write_config_byte(dev, 0x48, udma_enable); -+} -+ -+/** -+ * piix_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set MW/UDMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ do_pata_set_dmamode(ap, adev, 0); -+} -+ -+/** -+ * ich_set_dmamode - Initialize host controller PATA DMA timings -+ * @ap: Port whose timings we are configuring -+ * @adev: um -+ * -+ * Set MW/UDMA mode for device, in host controller PCI config space. -+ * -+ * LOCKING: -+ * None (inherited from caller). -+ */ -+ -+static void ich_set_dmamode (struct ata_port *ap, struct ata_device *adev) -+{ -+ do_pata_set_dmamode(ap, adev, 1); - } - - #define AHCI_PCI_BAR 5 -diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.vanilla-2.6.16-rc2/drivers/scsi/Kconfig linux-2.6.16-rc2/drivers/scsi/Kconfig ---- linux.vanilla-2.6.16-rc2/drivers/scsi/Kconfig 2006-02-06 12:21:35.000000000 +0000 -+++ linux-2.6.16-rc2/drivers/scsi/Kconfig 2006-02-07 13:48:49.000000000 +0000 -@@ -599,6 +599,289 @@ - depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX) - default y - -+config SCSI_PATA_ALI -+ tristate "ALi PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the ALi ATA interfaces -+ found on the many ALi chipsets. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_AMD -+ tristate "AMD/NVidia PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the AMD and NVidia PATA -+ interfaces found on the chipsets for Athlon/Athlon64. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_ARTOP -+ tristate "ARTOP 6210/6260 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for ARTOP PATA controllers. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_ATIIXP -+ tristate "ATI PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the ATI ATA interfaces -+ found on the many ATI chipsets. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CMD64X -+ tristate "CMD64x PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the CMD64x series chips -+ except for the CMD640. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CS5520 -+ tristate "CS5510/5520 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the Cyrix 5510/5520 -+ companion chip used with the MediaGX/Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CS5530 -+ tristate "CS5530 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the Cyrix/NatSemi/AMD CS5530 -+ companion chip used with the MediaGX/Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CS5535 -+ tristate "CS5535 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && X86 && !X86_64 && EXPERIMENTAL -+ help -+ This option enables support for the NatSemi/AMD CS5535 -+ companion chip used with the Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_CYPRESS -+ tristate "Cypress CY82C693 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the Cypress/Contaq CY82C693 -+ chipset found in some Alpha systems -+ -+ If unsure, say N. -+ -+config SCSI_PATA_EFAR -+ tristate "EFAR SLC90E66 support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the EFAR SLC90E66 -+ IDE controller found on some older machines. -+ -+ If unsure, say N. -+ -+config SCSI_ATA_GENERIC -+ tristate "Generic PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for generic BIOS configured -+ PATA controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_HPT37X -+ tristate "HPT 370/370A/371/372/374/302 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the majority of the later HPT -+ PATA controllers via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_HPT3X2N -+ tristate "HPT 372N/302N PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the N variant HPT PATA -+ controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_HPT3X3 -+ tristate "HPT 343/363 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the HPT 343/363 -+ PATA controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_ISAPNP -+ tristate "ISA Plug and Play PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && EXPERIMENTAL -+ help -+ This option enables support for ISA plug & play ATA -+ controllers such as those found on old soundcards. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_IT8172 -+ tristate "IT8172 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the ITE 8172 PATA controller -+ via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_IT821X -+ tristate "IT821x PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the ITE 8211 and 8212 -+ PATA controllers via the new ATA layer, including RAID -+ mode. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_LEGACY -+ tristate "Legacy ISA PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for ISA bus legacy PATA -+ interfaces on ide2-5 and allows them to be accessed via -+ the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_MPIIX -+ tristate "Intel PATA MPIIX support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for MPIIX PATA support. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_NETCELL -+ tristate "NETCELL Revolution RAID support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the Netcell Revolution RAID -+ PATA controller. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_OLDPIIX -+ tristate "Intel PATA old PIIX support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for old(?) PIIX PATA support. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_OPTI -+ tristate "OPTI621/6215 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables full PIO support for the early Opti ATA -+ controllers found on some old motherboards. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_PCMCIA -+ tristate "PCMCIA PATA support (Raving Lunatic)" -+ depends on SCSI_SATA -+ help -+ This option enables support for PCMCIA ATA interfaces, including -+ compact flash card adapters via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_QDI -+ tristate "QDI VLB PATA support" -+ depends on SCSI_SATA -+ help -+ Support for QDI 6500 and 6580 PATA controllers on VESA local bus. -+ -+config SCSI_PATA_RZ1000 -+ tristate "PC Tech RZ1000 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables basic support for the PC Tech RZ1000/1 -+ PATA controllers via the new ATA layer -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SC1200 -+ tristate "SC1200 PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the NatSemi/AMD SC1200 SoC -+ companion chip used with the Geode processor family. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SERVERWORKS -+ tristate "SERVERWORKS OSB4/CSB5/CSB6 PATA support (Experimental)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for the Serverworks OSB4/CSB5 and -+ CSB6 IDE controllers, via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SIL680 -+ tristate "CMD / Silicon Image 680 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for CMD / Silicon Image 680 PATA. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_SIS -+ tristate "SiS PATA support (Experimental)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ This option enables support for SiS PATA controllers -+ -+ If unsure, say N. -+ -+config SCSI_PATA_TRIFLEX -+ tristate "Compaq Triflex PATA support (Raving Lunatic)" -+ depends on SCSI_SATA && PCI && EXPERIMENTAL -+ help -+ Enable support for the Compaq 'Triflex' IDE controller as found -+ on many Compaq Pentium-Pro systems, via the new ATA layer. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_VIA -+ tristate "VIA PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for the VIA PATA interfaces -+ found on the many VIA chipsets. -+ -+ If unsure, say N. -+ -+config SCSI_PATA_WINBOND -+ tristate "Winbond SL82C105 PATA support" -+ depends on SCSI_SATA && PCI -+ help -+ This option enables support for SL82C105 PATA devices found in the -+ Netwinder and some other systems -+ -+ If unsure, say N. -+ -+ - config SCSI_BUSLOGIC - tristate "BusLogic SCSI support" - depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API -diff -u --exclude-from /usr/src/exclude --new-file --recursive linux.vanilla-2.6.16-rc2/drivers/scsi/libata-core.c linux-2.6.16-rc2/drivers/scsi/libata-core.c ---- linux.vanilla-2.6.16-rc2/drivers/scsi/libata-core.c 2006-02-06 12:21:35.000000000 +0000 -+++ linux-2.6.16-rc2/drivers/scsi/libata-core.c 2006-02-07 11:23:41.765951784 +0000 -@@ -68,9 +68,10 @@ - static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev); - 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(const struct ata_port *ap, int shift); -+static unsigned int ata_get_mode_mask(const struct ata_port *ap, struct ata_device *adev, int shift); - static int fgb(u32 bitmap); - static int ata_choose_xfer_mode(const struct ata_port *ap, -+ struct ata_device *adev, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out); - static void __ata_qc_complete(struct ata_queued_cmd *qc); -@@ -614,7 +615,7 @@ - } else if (lba48 && (qc->ap->flags & ATA_FLAG_PIO_LBA48)) { - /* Unable to use DMA due to host limitation */ - tf->protocol = ATA_PROT_PIO; -- index = dev->multi_count ? 0 : 4; -+ index = dev->multi_count ? 0 : 8; - } else { - tf->protocol = ATA_PROT_DMA; - index = 16; -@@ -1205,6 +1206,48 @@ - return 0; - } - -+static void ata_dev_check_hpa(struct ata_port *ap, struct ata_device *dev) -+{ -+ struct ata_taskfile tf; -+ unsigned long long true_size; -+ unsigned int err_mask; -+ -+ if (!ata_id_has_hpa(dev->id) || !ata_id_hpa_enabled(dev->id)) -+ return; -+ -+ /* Issue a query for HPA */ -+ ata_dev_select(ap, dev->devno, 1, 1); -+ ata_tf_init(ap, &tf, dev->devno); -+ -+ if (dev->flags & ATA_DFLAG_LBA48) { -+ tf.command = ATA_CMD_READ_NATIVE_MAX_EXT; -+ tf.device |= 0x40; -+ err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); -+ if (err_mask) -+ return; -+ /* Ok HPA is live */ -+ true_size = (tf.hob_lbah << 16) | (tf.hob_lbam << 8) | (tf.hob_lbal); -+ true_size <<= 24; -+ true_size |= (tf.lbah << 16) | (tf.lbam << 8) | tf.lbal; -+ } else { -+ tf.command = ATA_CMD_READ_NATIVE_MAX; -+ tf.device |= 0x40; -+ err_mask = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0); -+ if (err_mask) -+ return; -+ /* Ok HPA is live */ -+ true_size = ((tf.device & 0x0F) << 24) | -+ (tf.lbah << 16) | -+ (tf.lbam << 8) | -+ tf.lbal; -+ } -+ dev->flags |= ATA_DFLAG_HPA; -+ /* Should save the HPA value and expose it for dmraid then -+ remove the clipping */ -+ printk(KERN_INFO "HPA present: true size %lld sectors.\n", -+ true_size + 1); -+} -+ - /** - * ata_dev_identify - obtain IDENTIFY x DEVICE page - * @ap: port on which device we wish to probe resides -@@ -1328,7 +1371,7 @@ - - /* ATA-specific feature tests */ - if (dev->class == ATA_DEV_ATA) { -- if (!ata_id_is_ata(dev->id)) /* sanity check */ -+ if (!ata_id_is_ata(dev->id) && !ata_id_is_cfa(dev->id)) /* sanity check */ - goto err_out_nosup; - - /* get major version */ -@@ -1400,6 +1443,13 @@ - } - - ap->host->max_cmd_len = 16; -+ -+ /* -+ * See if we have the HPA misfeature on the drive -+ */ -+#if 0 /* TESTING */ -+ ata_dev_check_hpa(ap, dev); -+#endif - } - - /* ATAPI-specific feature tests */ -@@ -1497,7 +1547,11 @@ - if ((!found) || (ap->flags & ATA_FLAG_PORT_DISABLED)) - goto err_out_disable; - -- ata_set_mode(ap); -+ if(ap->ops->set_mode) -+ ap->ops->set_mode(ap); -+ else -+ ata_set_mode(ap); -+ - if (ap->flags & ATA_FLAG_PORT_DISABLED) - goto err_out_disable; - -@@ -1824,16 +1878,19 @@ - ap->id, dev->devno, xfer_mode_str[idx]); - } - --static int ata_host_set_pio(struct ata_port *ap) -+static int ata_host_set_pio(struct ata_port *ap, struct ata_device *adev) - { - unsigned int mask; -- int x, i; -+ int x; - u8 base, xfer_mode; - -- mask = ata_get_mode_mask(ap, ATA_SHIFT_PIO); -+ if (!ata_dev_present(adev)) -+ return 0; -+ -+ mask = ata_get_mode_mask(ap, adev, ATA_SHIFT_PIO); - x = fgb(mask); - if (x < 0) { -- printk(KERN_WARNING "ata%u: no PIO support\n", ap->id); -+ printk(KERN_WARNING "ata%u: no PIO support for device %d.\n", ap->id, adev->devno); - return -1; - } - -@@ -1843,34 +1900,24 @@ - DPRINTK("base 0x%x xfer_mode 0x%x mask 0x%x x %d\n", - (int)base, (int)xfer_mode, mask, 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); -- } -- } -+ adev->pio_mode = xfer_mode; -+ adev->xfer_mode = xfer_mode; -+ adev->xfer_shift = ATA_SHIFT_PIO; -+ if (ap->ops->set_piomode) -+ ap->ops->set_piomode(ap, adev); - - return 0; - } - --static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode, -- unsigned int xfer_shift) -+static void ata_host_set_dma(struct ata_port *ap, struct ata_device *adev, -+ u8 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); -- } -+ if (ata_dev_present(adev)) { -+ adev->dma_mode = xfer_mode; -+ adev->xfer_mode = xfer_mode; -+ adev->xfer_shift = xfer_shift; -+ if (ap->ops->set_dmamode) -+ ap->ops->set_dmamode(ap, adev); - } - } - -@@ -1886,32 +1933,64 @@ - */ - static void ata_set_mode(struct ata_port *ap) - { -- unsigned int xfer_shift; -- u8 xfer_mode; -+ unsigned int xfer_shift[ATA_MAX_DEVICES]; -+ u8 xfer_mode[ATA_MAX_DEVICES]; - int rc; -+ int i; -+ int used_dma = 0; /* Track if DMA was used for this setup */ - -- /* step 1: always set host PIO timings */ -- rc = ata_host_set_pio(ap); -- if (rc) -- goto err_out; -+ /* We need to set timings individually for each device */ - -- /* 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; -+ /* Compute the timings first so that when we ask the device to do -+ speed configuration it can see all the intended device state in -+ full */ -+ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *adev = &ap->device[i]; -+ /* Choose the best data xfer mode */ -+ xfer_mode[i] = xfer_shift[i] = 0; -+ rc = ata_choose_xfer_mode(ap, adev, &xfer_mode[i], &xfer_shift[i]); -+ if (rc) -+ goto err_out; -+ -+ } -+ -+ /* Now set the mode tables we have computed */ -+ for (i = 0; i < ATA_MAX_DEVICES; i++) { -+ struct ata_device *adev = &ap->device[i]; -+ /* step 1: always set host PIO timings */ -+ rc = ata_host_set_pio(ap, adev); -+ if (rc) -+ goto err_out; -+ -+ /* step 2: if that xfer mode isn't PIO, set host DMA timings */ -+ if (xfer_shift[i] != ATA_SHIFT_PIO) { -+ ata_host_set_dma(ap, adev, xfer_mode[i], xfer_shift[i]); -+ used_dma = 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]); -+ /* In some cases the DMA mode will cause the driver to -+ update the pio mode to match chip limits. */ -+ -+ /* step 3: update devices' xfer mode */ -+ ata_dev_set_mode(ap, adev); -+ } - - if (ap->flags & ATA_FLAG_PORT_DISABLED) - return; - -+ /* -+ * Record simplex status. If we selected DMA then the other -+ * host channels are not permitted to do so. -+ */ -+ -+ if (used_dma && (ap->host_set->host_set_flags & ATA_HOST_SIMPLEX)) -+ ap->host_set->simplex_claimed = 1; -+ -+ /* -+ * Chip specific finalisation -+ */ -+ - if (ap->ops->post_set_mode) - ap->ops->post_set_mode(ap); - -@@ -2256,76 +2335,57 @@ - return 0; - } - --static unsigned int ata_get_mode_mask(const struct ata_port *ap, int shift) -+static unsigned int ata_get_mode_mask(const struct ata_port *ap, struct ata_device *adev, int shift) - { -- const struct ata_device *master, *slave; - unsigned int mask; -+ struct ata_host_set *hs = ap->host_set; -+ -+ if (!ata_dev_present(adev)) -+ return 0xFF; /* Drive isn't limiting anything */ -+ -+ if (shift == ATA_SHIFT_PIO) { -+ u16 tmp_mode = ata_pio_modes(adev); -+ mask = ap->pio_mask; -+ mask &= tmp_mode; -+ } - -- master = &ap->device[0]; -- slave = &ap->device[1]; -+ /* -+ * Enforce simplex rules if host is simplex -+ */ - -- assert (ata_dev_present(master) || ata_dev_present(slave)); -+ if (hs->host_set_flags & ATA_HOST_SIMPLEX) { -+ if (hs->simplex_claimed) { -+ if (shift != ATA_SHIFT_PIO) -+ return 0; -+ } -+ } - - if (shift == ATA_SHIFT_UDMA) { - mask = ap->udma_mask; -- if (ata_dev_present(master)) { -- mask &= (master->id[ATA_ID_UDMA_MODES] & 0xff); -- if (ata_dma_blacklisted(master)) { -- mask = 0; -- ata_pr_blacklisted(ap, master); -- } -- } -- if (ata_dev_present(slave)) { -- mask &= (slave->id[ATA_ID_UDMA_MODES] & 0xff); -- if (ata_dma_blacklisted(slave)) { -- mask = 0; -- ata_pr_blacklisted(ap, slave); -- } -+ mask &= (adev->id[ATA_ID_UDMA_MODES] & 0xff); -+ if (ata_dma_blacklisted(adev)) { -+ mask = 0; -+ ata_pr_blacklisted(ap, adev); - } - } - 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_dma_blacklisted(master)) { -- mask = 0; -- ata_pr_blacklisted(ap, master); -- } -- } -- if (ata_dev_present(slave)) { -- mask &= (slave->id[ATA_ID_MWDMA_MODES] & 0x07); -- if (ata_dma_blacklisted(slave)) { -- mask = 0; -- ata_pr_blacklisted(ap, slave); -- } -- } -- } -- 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; -+ mask &= (adev->id[ATA_ID_MWDMA_MODES] & 0x07); -+ if (ata_dma_blacklisted(adev)) { -+ mask = 0; -+ ata_pr_blacklisted(ap, adev); - } -- } -- else { -+ } else if (shift != ATA_SHIFT_PIO) { - mask = 0xffffffff; /* shut up compiler warning */ - BUG(); - } - -+ /* -+ * Allow the controller to see the proposed mode and -+ * device data to do any custom filtering rules. -+ */ -+ if(ap->ops->mode_filter) -+ mask = ap->ops->mode_filter(ap, adev, mask, shift); - return mask; - } - -@@ -2345,6 +2405,7 @@ - /** - * ata_choose_xfer_mode - attempt to find best transfer mode - * @ap: Port for which an xfer mode will be selected -+ * @adev: ATA device for which xfer mode is being selected - * @xfer_mode_out: (output) SET FEATURES - XFER MODE code - * @xfer_shift_out: (output) bit shift that selects this mode - * -@@ -2359,6 +2420,7 @@ - */ - - static int ata_choose_xfer_mode(const struct ata_port *ap, -+ struct ata_device *adev, - u8 *xfer_mode_out, - unsigned int *xfer_shift_out) - { -@@ -2367,7 +2429,7 @@ - - for (i = 0; i < ARRAY_SIZE(xfer_mode_classes); i++) { - shift = xfer_mode_classes[i].shift; -- mask = ata_get_mode_mask(ap, shift); -+ mask = ata_get_mode_mask(ap, adev, shift); - - x = fgb(mask); - if (x >= 0) { -@@ -3010,7 +3072,7 @@ - * Inherited from caller. - */ - --static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, -+void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) - { - unsigned int i; -@@ -3055,11 +3117,11 @@ - * Inherited from caller. - */ - --static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, -+void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) - { - unsigned int words = buflen >> 1; -- -+ - /* Transfer multiple of 2 bytes */ - if (write_data) - outsw(ap->ioaddr.data_addr, buf, words); -@@ -3082,36 +3144,53 @@ - } - - /** -- * ata_data_xfer - Transfer data from/to the data register. -+ * ata_pio_data_xfer_noirq - Transfer data from/to the data register. - * @ap: port to read/write - * @buf: data buffer - * @buflen: buffer length - * @do_write: read/write - * -- * Transfer data from/to the device data register. -+ * Transfer data from/to the device data register. This variant -+ * ensures local IRQs do not interrupt the data stream and this -+ * is needed for some controllers. - * - * LOCKING: - * Inherited from caller. - */ - --static void ata_data_xfer(struct ata_port *ap, unsigned char *buf, -+void ata_pio_data_xfer_noirq(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int do_write) - { - /* Make the crap hardware pay the costs not the good stuff */ -- if (unlikely(ap->flags & ATA_FLAG_IRQ_MASK)) { -- unsigned long flags; -- local_irq_save(flags); -- if (ap->flags & ATA_FLAG_MMIO) -- ata_mmio_data_xfer(ap, buf, buflen, do_write); -- else -- ata_pio_data_xfer(ap, buf, buflen, do_write); -- local_irq_restore(flags); -- } else { -- if (ap->flags & ATA_FLAG_MMIO) -- ata_mmio_data_xfer(ap, buf, buflen, do_write); -- else -- ata_pio_data_xfer(ap, buf, buflen, do_write); -- } -+ unsigned long flags; -+ local_irq_save(flags); -+ ata_pio_data_xfer(ap, buf, buflen, do_write); -+ local_irq_restore(flags); -+} -+ -+/** -+ * ata_mmio_data_xfer_noirq - Transfer data from/to the data register. -+ * @ap: address to read/write -+ * @buf: data buffer -+ * @buflen: buffer length -+ * @do_write: read/write -+ * -+ * Transfer data from/to the device data register. This variant -+ * ensures local IRQs do not interrupt the data stream and this -+ * is needed for some controllers. -+ * -+ * LOCKING: -+ * Inherited from caller. -+ */ -+ -+void ata_mmio_data_xfer_noirq(struct ata_port *ap, unsigned char *buf, -+ unsigned int buflen, int do_write) -+{ -+ /* Make the crap hardware pay the costs not the good stuff */ -+ unsigned long flags; -+ local_irq_save(flags); -+ ata_mmio_data_xfer(ap, buf, buflen, do_write); -+ local_irq_restore(flags); - } - - /** -@@ -3157,7 +3236,7 @@ - - /* do the actual data transfer */ - do_write = (qc->tf.flags & ATA_TFLAG_WRITE); -- ata_data_xfer(ap, buf, ATA_SECT_SIZE, do_write); -+ ap->ops->data_xfer(ap, buf, ATA_SECT_SIZE, do_write); - - kunmap(page); - } -@@ -3204,7 +3283,7 @@ - ap->id, bytes); - - for (i = 0; i < words; i++) -- ata_data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); -+ ap->ops->data_xfer(ap, (unsigned char*)pad_buf, 2, do_write); - - ap->hsm_task_state = HSM_ST_LAST; - return; -@@ -3239,7 +3318,7 @@ - DPRINTK("data %s\n", qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read"); - - /* do the actual data transfer */ -- ata_data_xfer(ap, buf, count, do_write); -+ ap->ops->data_xfer(ap, buf, count, do_write); - - kunmap(page); - -@@ -3947,14 +4026,15 @@ - - void ata_bmdma_irq_clear(struct ata_port *ap) - { -- if (ap->flags & ATA_FLAG_MMIO) { -- void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; -- writeb(readb(mmio), mmio); -- } else { -- unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; -- outb(inb(addr), addr); -- } -- -+ if (ap->ioaddr.bmdma_addr) { -+ if (ap->flags & ATA_FLAG_MMIO) { -+ void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS; -+ writeb(readb(mmio), mmio); -+ } else { -+ unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS; -+ outb(inb(addr), addr); -+ } -+ } - } - - -@@ -4193,12 +4273,12 @@ - */ - spin_lock_irqsave(&ap->host_set->lock, flags); - ap->flags &= ~ATA_FLAG_NOINTR; -- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); -+ ap->ops->data_xfer(ap, qc->cdb, ap->cdb_len, 1); - if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) - ap->ops->bmdma_start(qc); /* initiate bmdma */ - spin_unlock_irqrestore(&ap->host_set->lock, flags); - } else { -- ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); -+ ap->ops->data_xfer(ap, qc->cdb, ap->cdb_len, 1); - - /* PIO commands are handled by polling */ - ap->hsm_task_state = HSM_ST; -@@ -4504,7 +4584,7 @@ - * Number of ports registered. Zero on error (no ports registered). - */ - --int ata_device_add(const struct ata_probe_ent *ent) -+int ata_device_add(struct ata_probe_ent *ent) - { - unsigned int count = 0, i; - struct device *dev = ent->dev; -@@ -4524,6 +4604,9 @@ - host_set->mmio_base = ent->mmio_base; - host_set->private_data = ent->private_data; - host_set->ops = ent->port_ops; -+ host_set->host_set_flags = ent->host_set_flags; -+ -+ ent->host_set = host_set; - - /* register each port bound to this device */ - for (i = 0; i < ent->n_ports; i++) { -@@ -4535,6 +4618,14 @@ - goto err_out; - - host_set->ports[i] = ap; -+ -+ /* Tidy up if we have no bus master base -+ Not sure this is the right spot to do it */ -+ if (ap->ioaddr.bmdma_addr == 0) { -+ ap->udma_mask = 0; -+ ap->mwdma_mask = 0; -+ } -+ - xfer_mode