diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/arch/i386/pci/fixup.c linux-2.6.16-rc6/arch/i386/pci/fixup.c --- linux.vanilla-2.6.16-rc6/arch/i386/pci/fixup.c 2006-03-13 14:00:11.000000000 +0000 +++ linux-2.6.16-rc6/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 --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/cdrom/cdrom.c linux-2.6.16-rc6/drivers/cdrom/cdrom.c --- linux.vanilla-2.6.16-rc6/drivers/cdrom/cdrom.c 2006-03-13 14:00:12.000000000 +0000 +++ linux-2.6.16-rc6/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 --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/pci/probe.c linux-2.6.16-rc6/drivers/pci/probe.c --- linux.vanilla-2.6.16-rc6/drivers/pci/probe.c 2006-03-13 14:00:13.000000000 +0000 +++ linux-2.6.16-rc6/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 */ diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/ata_generic.c linux-2.6.16-rc6/drivers/scsi/ata_generic.c --- linux.vanilla-2.6.16-rc6/drivers/scsi/ata_generic.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.16-rc6/drivers/scsi/ata_generic.c 2006-02-16 15:35:41.000000000 +0000 @@ -0,0 +1,241 @@ +/* + * 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_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 --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/ata_piix.c linux-2.6.16-rc6/drivers/scsi/ata_piix.c --- linux.vanilla-2.6.16-rc6/drivers/scsi/ata_piix.c 2006-03-13 14:00:14.000000000 +0000 +++ linux-2.6.16-rc6/drivers/scsi/ata_piix.c 2006-02-20 20:06:17.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-ac7" 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, @@ -253,47 +350,39 @@ }; static struct ata_port_info piix_port_info[] = { - /* ich5_pata */ + /* ich5_pata: 0*/ { .sht = &piix_sht, .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, + .udma_mask = ATA_UDMA6, + .port_ops = &ich_pata_ops, }, - /* ich5_sata */ + /* ich5_sata: 1 */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | PIIX_FLAG_COMBINED | PIIX_FLAG_CHECKINTR, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 */ + .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, - /* piix4_pata */ + /* piix4_pata: 2 */ { .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, }, - /* ich6_sata */ + /* ich6_sata: 3 */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | @@ -301,11 +390,11 @@ ATA_FLAG_SLAVE_POSS, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 */ + .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, - /* ich6_sata_ahci */ + /* ich6_sata_ahci: 4 */ { .sht = &piix_sht, .host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST | @@ -313,9 +402,119 @@ ATA_FLAG_SLAVE_POSS | PIIX_FLAG_AHCI, .pio_mask = 0x1f, /* pio0-4 */ .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 */ + .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, + + /* ich0_pata: 5 */ + { + .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 = ATA_UDMA4, + .port_ops = &ich_pata_ops, + }, + + /* ich2_pata: 6 */ + { + .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 = ATA_UDMA5, + .port_ops = &ich_pata_ops, + }, + + /* ich3_pata: 7 */ + { + .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 = ATA_UDMA5, + .port_ops = &ich_pata_ops, + }, + + /* ich4_pata: 8 */ + { + .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 = ATA_UDMA5, + .port_ops = &ich_pata_ops, + }, + + /* cich_pata: 9 */ + { + .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 = ATA_UDMA5, + .port_ops = &ich_pata_ops, + }, + + /* piix3_pata: 10 */ + { + .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: 11 */ + { + .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 = ATA_UDMA5, + .port_ops = &piix_pata_ops, + }, + + /* ich_pata: 12 */ + { + .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 = ATA_UDMA4, /* UDMA66 */ + .port_ops = &ich_pata_ops, + }, + + /* ich6_pata: 13 */ + { + .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 = ATA_UDMA6, /* UDMA133 */ + .port_ops = &ich_pata_ops, + }, + + /* ich7_pata: 14 */ + { + .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 = ATA_UDMA6, + .port_ops = &ich_pata_ops, + }, + + /* esb2_pata: 15 */ + { + .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 = ATA_UDMA5, + .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; + u16 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_word(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_word(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 @@ -646,15 +967,15 @@ pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); pci_read_config_word(pdev, 0x41, &cfg); /* Only on the original revision: IDE DMA can hang */ - if(rev == 0x00) + if (rev == 0x00) no_piix_dma = 1; /* On all revisions below 5 PXB bus lock must be disabled for IDE */ - else if(cfg & (1<<14) && rev < 5) + else if (cfg & (1<<14) && rev < 5) no_piix_dma = 2; } - if(no_piix_dma) + if (no_piix_dma) dev_printk(KERN_WARNING, &ata_dev->dev, "450NX errata present, disabling IDE DMA.\n"); - if(no_piix_dma == 2) + if (no_piix_dma == 2) dev_printk(KERN_WARNING, &ata_dev->dev, "A BIOS update may resolve this.\n"); return no_piix_dma; } diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/Kconfig linux-2.6.16-rc6/drivers/scsi/Kconfig --- linux.vanilla-2.6.16-rc6/drivers/scsi/Kconfig 2006-03-13 14:00:13.000000000 +0000 +++ linux-2.6.16-rc6/drivers/scsi/Kconfig 2006-02-20 17:27:24.000000000 +0000 @@ -599,6 +599,316 @@ 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_NS87410 + tristate "Nat Semi NS87410 PATA support (Experimental)" + depends on SCSI_SATA && PCI + help + This option enables support for the National Semiconductor + NS87410 PCI-IDE 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 early PIIX PATA interfaces. + + 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 && PCMCIA + 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_PDC_OLD + tristate "Older Promise PATA controller support (Raving Lunatic)" + depends on SCSI_SATA && PCI && EXPERIMENTAL + help + This option enables support for the Promise 20246, 20262, 20263, + 20265 and 20267 adapters. + + 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_RADISYS + tristate "RADISYS 82600 PATA support (Raving Lunatic)" + depends on SCSI_SATA && PCI && EXPERIMENTAL + help + This option enables support for the RADISYS 82600 + PATA controllers via the new ATA layer + + If unsure, say N. + +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 --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.16-rc6/drivers/scsi/libata-core.c linux-2.6.16-rc6/drivers/scsi/libata-core.c --- linux.vanilla-2.6.16-rc6/drivers/scsi/libata-core.c 2006-03-13 14:00:14.000000000 +0000 +++ linux-2.6.16-rc6/drivers/scsi/libata-core.c 2006-03-13 14:30:45.838552760 +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); @@ -78,7 +79,7 @@ static unsigned int ata_unique_id = 1; static struct workqueue_struct *ata_wq; -int atapi_enabled = 0; +int atapi_enabled = 1; module_param(atapi_enabled, int, 0444); MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)"); @@ -1209,6 +1210,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 @@ -1332,7 +1375,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 */ @@ -1404,6 +1447,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 */ @@ -1489,10 +1539,24 @@ ap->ops->phy_reset(ap); if (ap->flags & ATA_FLAG_PORT_DISABLED) goto err_out; + + /* The reset means we are in PIO 0, but the controller may not + yet be correctly set up and may have old BIOS settings, or just + no settings at all. Set all the devices to PIO 0 */ + + for (i = 0; i < ATA_MAX_DEVICES; i++) + ap->device[i].pio_mode = XFER_PIO_0; for (i = 0; i < ATA_MAX_DEVICES; i++) { + struct ata_device *adev = & ap->device[i]; + + /* Set up the controller on this port for PIO 0. We must not + send the drive speed setting commands at this point */ + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, adev); + ata_dev_identify(ap, i); - if (ata_dev_present(&ap->device[i])) { + if (ata_dev_present(adev)) { found = 1; ata_dev_config(ap,i); } @@ -1501,7 +1565,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; @@ -1616,6 +1684,23 @@ } /** + * ata_dev_pair - return other device on cable + * @ap: port + * @adev: device + * + * Obtain the other device on the same cable, or if none is + * present NULL is returned + */ + +struct ata_device *ata_dev_pair(struct ata_port *ap, struct ata_device *adev) +{ + struct ata_device *pair = &ap->device[1 - adev->devno]; + if (!ata_dev_present(pair)) + return NULL; + return pair; +} + +/** * ata_port_disable - Disable port. * @ap: Port to be disabled. * @@ -1828,16 +1913,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; } @@ -1847,34 +1935,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); } } @@ -1890,32 +1968,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; - /* 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]); + } + + /* 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; + } + + /* 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); @@ -2054,6 +2164,12 @@ * crazy ATAPI devices... */ msleep(150); + /* Before we perform post reset processing we want to see if + the bus shows 0xFF because the odd clown forgets the D7 pulldown + resistor */ + + if (ata_check_status(ap) == 0xFF) + return 1; /* Positive is failure for some reason */ return ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT); } @@ -2087,9 +2203,17 @@ * status is checked. Because waiting for "a while" before * checking status is fine, post SRST, we perform this magic * delay here as well. + * + * Old drivers/ide uses the 2mS rule and then waits for ready */ msleep(150); - + + /* Before we perform post reset processing we want to see if + the bus shows 0xFF because the odd clown forgets the D7 pulldown + resistor */ + + if (ata_check_status(ap) == 0xFF) + return 1; /* Positive is failure for some reason */ ata_bus_post_reset(ap, devmask); return 0; @@ -2204,132 +2328,126 @@ } static const char * const ata_dma_blacklist [] = { - "WDC AC11000H", - "WDC AC22100H", - "WDC AC32500H", - "WDC AC33100H", - "WDC AC31600H", - "WDC AC32100H", - "WDC AC23200L", - "Compaq CRD-8241B", - "CRD-8400B", - "CRD-8480B", - "CRD-8482B", - "CRD-84", - "SanDisk SDP3B", - "SanDisk SDP3B-64", - "SANYO CD-ROM CRD", - "HITACHI CDR-8", - "HITACHI CDR-8335", - "HITACHI CDR-8435", - "Toshiba CD-ROM XM-6202B", - "TOSHIBA CD-ROM XM-1702BC", - "CD-532E-A", - "E-IDE CD-ROM CR-840", - "CD-ROM Drive/F5A", - "WPI CDD-820", - "SAMSUNG CD-ROM SC-148C", - "SAMSUNG CD-ROM SC", - "SanDisk SDP3B-64", - "ATAPI CD-ROM DRIVE 40X MAXIMUM", - "_NEC DV5800A", + "WDC AC11000H", NULL, + "WDC AC22100H", NULL, + "WDC AC32500H", NULL, + "WDC AC33100H", NULL, + "WDC AC31600H", NULL, + "WDC AC32100H", "24.09P07", + "WDC AC23200L", "21.10N21", + "Compaq CRD-8241B", NULL, + "CRD-8400B", NULL, + "CRD-8480B", NULL, + "CRD-8482B", NULL, + "CRD-84", NULL, + "SanDisk SDP3B", NULL, + "SanDisk SDP3B-64", NULL, + "SANYO CD-ROM CRD", NULL, + "HITACHI CDR-8", NULL, + "HITACHI CDR-8335", NULL, + "HITACHI CDR-8435", NULL, + "Toshiba CD-ROM XM-6202B", NULL, + "TOSHIBA CD-ROM XM-1702BC", NULL, + "CD-532E-A", NULL, + "E-IDE CD-ROM CR-840", NULL, + "CD-ROM Drive/F5A", NULL, + "WPI CDD-820", NULL, + "SAMSUNG CD-ROM SC-148C", NULL, + "SAMSUNG CD-ROM SC", NULL, + "SanDisk SDP3B-64", NULL, + "ATAPI CD-ROM DRIVE 40X MAXIMUM",NULL, + "_NEC DV5800A", NULL, + "SAMSUNG CD-ROM SN-124", "N001" }; -static int ata_dma_blacklisted(const struct ata_device *dev) +static int ata_strim(char *s, size_t len) { - unsigned char model_num[40]; - char *s; - unsigned int len; - int i; - - ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, - sizeof(model_num)); - s = &model_num[0]; - len = strnlen(s, sizeof(model_num)); + len = strnlen(s, len); /* ATAPI specifies that empty space is blank-filled; remove blanks */ while ((len > 0) && (s[len - 1] == ' ')) { len--; s[len] = 0; } + return len; +} - for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i++) - if (!strncmp(ata_dma_blacklist[i], s, len)) - return 1; +static int ata_dma_blacklisted(const struct ata_device *dev) +{ + unsigned char model_num[40]; + unsigned char model_rev[16]; + unsigned int nlen, rlen; + int i; + ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, + sizeof(model_num)); + ata_dev_id_string(dev->id, model_rev, ATA_ID_FW_REV_OFS, + sizeof(model_rev)); + nlen = ata_strim(model_num, sizeof(model_num)); + rlen = ata_strim(model_rev, sizeof(model_rev)); + + for (i = 0; i < ARRAY_SIZE(ata_dma_blacklist); i += 2) { + if (!strncmp(ata_dma_blacklist[i], model_num, nlen)) { + if (ata_dma_blacklist[i+1] == NULL) + return 1; + if (!strncmp(ata_dma_blacklist[i], model_rev, rlen)) + return 1; + } + } 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); } + /* 40 pin cable enforcement */ + if (ap->cbl == ATA_CBL_PATA40) + mask &= ATA_UDMA_MASK_40C; } 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 { - mask = 0xffffffff; /* shut up compiler warning */ - BUG(); - } - + } else if (shift != ATA_SHIFT_PIO) + panic("gmm:bad shift"); /* BUG confuses the compiler */ + /* + * 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; } @@ -2349,6 +2467,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 * @@ -2363,6 +2482,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) { @@ -2371,7 +2491,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) { @@ -3007,6 +3127,7 @@ /** * ata_mmio_data_xfer - Transfer data by MMIO * @ap: port to read/write + * @adev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -3017,8 +3138,8 @@ * Inherited from caller. */ -static void ata_mmio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) +void ata_mmio_data_xfer(struct ata_port *ap, struct ata_device *adev, + unsigned char *buf, unsigned int buflen, int write_data) { unsigned int i; unsigned int words = buflen >> 1; @@ -3052,6 +3173,7 @@ /** * ata_pio_data_xfer - Transfer data by PIO * @ap: port to read/write + * @adev: device to target * @buf: data buffer * @buflen: buffer length * @write_data: read/write @@ -3062,11 +3184,11 @@ * Inherited from caller. */ -static void ata_pio_data_xfer(struct ata_port *ap, unsigned char *buf, - unsigned int buflen, int write_data) +void ata_pio_data_xfer(struct ata_port *ap, struct ata_device *adev, + 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); @@ -3089,36 +3211,55 @@ } /** - * 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 + * @adev: device to target * @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, - unsigned int buflen, int do_write) +void ata_pio_data_xfer_noirq(struct ata_port *ap, struct ata_device *adev, + 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, adev, 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 + * @adev: device to target + * @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, struct ata_device *adev, + 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, adev, buf, buflen, do_write); + local_irq_restore(flags); } /** @@ -3164,7 +3305,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, qc->dev, buf, ATA_SECT_SIZE, do_write); kunmap(page); } @@ -3211,7 +3352,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, qc->dev, (unsigned char*)pad_buf, 2, do_write); ap->hsm_task_state = HSM_ST_LAST; return; @@ -3246,7 +3387,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, qc->dev, buf, count, do_write); kunmap(page); @@ -3955,14 +4096,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); + } + } } @@ -4093,9 +4235,9 @@ #ifdef ATA_IRQ_TRAP if ((ap->stats.idle_irq % 1000) == 0) { - handled = 1; ata_irq_ack(ap, 0); /* debug trap */ printk(KERN_WARNING "ata%d: irq trap\n", ap->id); + return 1; } #endif return 0; /* irq not handled */ @@ -4201,12 +4343,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->dev, 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->dev, qc->cdb, ap->cdb_len, 1); /* PIO commands are handled by polling */ ap->hsm_task_state = HSM_ST; @@ -4512,7 +4654,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; @@ -4532,6 +4674,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++) { @@ -4543,6 +4688,14 @@ goto err_out; host_set->ports[i