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