diff options
-rw-r--r-- | drivers/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/ata/Kconfig | 148 | ||||
-rw-r--r-- | drivers/ata/Makefile | 21 | ||||
-rw-r--r-- | drivers/ata/ahci.c (renamed from drivers/scsi/ahci.c) | 661 | ||||
-rw-r--r-- | drivers/ata/ata_piix.c (renamed from drivers/scsi/ata_piix.c) | 26 | ||||
-rw-r--r-- | drivers/ata/libata-bmdma.c (renamed from drivers/scsi/libata-bmdma.c) | 160 | ||||
-rw-r--r-- | drivers/ata/libata-core.c (renamed from drivers/scsi/libata-core.c) | 358 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c (renamed from drivers/scsi/libata-eh.c) | 2 | ||||
-rw-r--r-- | drivers/ata/libata-scsi.c (renamed from drivers/scsi/libata-scsi.c) | 157 | ||||
-rw-r--r-- | drivers/ata/libata.h (renamed from drivers/scsi/libata.h) | 5 | ||||
-rw-r--r-- | drivers/ata/pdc_adma.c (renamed from drivers/scsi/pdc_adma.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_mv.c (renamed from drivers/scsi/sata_mv.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_nv.c (renamed from drivers/scsi/sata_nv.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_promise.c (renamed from drivers/scsi/sata_promise.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_promise.h (renamed from drivers/scsi/sata_promise.h) | 0 | ||||
-rw-r--r-- | drivers/ata/sata_qstor.c (renamed from drivers/scsi/sata_qstor.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_sil.c (renamed from drivers/scsi/sata_sil.c) | 6 | ||||
-rw-r--r-- | drivers/ata/sata_sil24.c (renamed from drivers/scsi/sata_sil24.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_sis.c (renamed from drivers/scsi/sata_sis.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_svw.c (renamed from drivers/scsi/sata_svw.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_sx4.c (renamed from drivers/scsi/sata_sx4.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_uli.c (renamed from drivers/scsi/sata_uli.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_via.c (renamed from drivers/scsi/sata_via.c) | 2 | ||||
-rw-r--r-- | drivers/ata/sata_vsc.c (renamed from drivers/scsi/sata_vsc.c) | 2 | ||||
-rw-r--r-- | drivers/scsi/Kconfig | 138 | ||||
-rw-r--r-- | drivers/scsi/Makefile | 16 | ||||
-rw-r--r-- | include/asm-alpha/libata-portmap.h | 1 | ||||
-rw-r--r-- | include/asm-generic/libata-portmap.h | 12 | ||||
-rw-r--r-- | include/asm-i386/libata-portmap.h | 1 | ||||
-rw-r--r-- | include/asm-ia64/libata-portmap.h | 1 | ||||
-rw-r--r-- | include/asm-powerpc/libata-portmap.h | 1 | ||||
-rw-r--r-- | include/asm-sparc/libata-portmap.h | 1 | ||||
-rw-r--r-- | include/asm-sparc64/libata-portmap.h | 1 | ||||
-rw-r--r-- | include/asm-x86_64/libata-portmap.h | 1 | ||||
-rw-r--r-- | include/linux/ata.h | 22 | ||||
-rw-r--r-- | include/linux/libata.h | 39 |
37 files changed, 1165 insertions, 640 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 8b11cebe65df..263e86ddc1a4 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -18,6 +18,8 @@ source "drivers/ide/Kconfig" source "drivers/scsi/Kconfig" +source "drivers/ata/Kconfig" + source "drivers/cdrom/Kconfig" source "drivers/md/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index fc2d744a4e4a..4ac14dab3079 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_PPC_PMAC) += macintosh/ obj-$(CONFIG_IDE) += ide/ obj-$(CONFIG_FC4) += fc4/ obj-$(CONFIG_SCSI) += scsi/ +obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_FUSION) += message/ obj-$(CONFIG_IEEE1394) += ieee1394/ obj-y += cdrom/ diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig new file mode 100644 index 000000000000..2109d755c14d --- /dev/null +++ b/drivers/ata/Kconfig @@ -0,0 +1,148 @@ +# +# SATA/PATA driver configuration +# + +menu "Serial ATA (prod) and Parallel ATA (experimental) drivers" + depends on SCSI + +config ATA + tristate "ATA device support" + depends on SCSI + ---help--- + If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or + any other ATA device under Linux, say Y and make sure that you know + the name of your ATA host adapter (the card inside your computer + that "speaks" the ATA protocol, also called ATA controller), + because you will be asked for it. + +config SATA_AHCI + tristate "AHCI SATA support" + depends on ATA && PCI + help + This option enables support for AHCI Serial ATA. + + If unsure, say N. + +config SATA_SVW + tristate "ServerWorks Frodo / Apple K2 SATA support" + depends on ATA && PCI + help + This option enables support for Broadcom/Serverworks/Apple K2 + SATA support. + + If unsure, say N. + +config ATA_PIIX + tristate "Intel PIIX/ICH SATA support" + depends on ATA && PCI + help + This option enables support for ICH5/6/7/8 Serial ATA. + If PATA support was enabled previously, this enables + support for select Intel PIIX/ICH PATA host controllers. + + If unsure, say N. + +config SATA_MV + tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)" + depends on ATA && PCI && EXPERIMENTAL + help + This option enables support for the Marvell Serial ATA family. + Currently supports 88SX[56]0[48][01] chips. + + If unsure, say N. + +config SATA_NV + tristate "NVIDIA SATA support" + depends on ATA && PCI + help + This option enables support for NVIDIA Serial ATA. + + If unsure, say N. + +config PDC_ADMA + tristate "Pacific Digital ADMA support" + depends on ATA && PCI + help + This option enables support for Pacific Digital ADMA controllers + + If unsure, say N. + +config SATA_QSTOR + tristate "Pacific Digital SATA QStor support" + depends on ATA && PCI + help + This option enables support for Pacific Digital Serial ATA QStor. + + If unsure, say N. + +config SATA_PROMISE + tristate "Promise SATA TX2/TX4 support" + depends on ATA && PCI + help + This option enables support for Promise Serial ATA TX2/TX4. + + If unsure, say N. + +config SATA_SX4 + tristate "Promise SATA SX4 support" + depends on ATA && PCI && EXPERIMENTAL + help + This option enables support for Promise Serial ATA SX4. + + If unsure, say N. + +config SATA_SIL + tristate "Silicon Image SATA support" + depends on ATA && PCI + help + This option enables support for Silicon Image Serial ATA. + + If unsure, say N. + +config SATA_SIL24 + tristate "Silicon Image 3124/3132 SATA support" + depends on ATA && PCI + help + This option enables support for Silicon Image 3124/3132 Serial ATA. + + If unsure, say N. + +config SATA_SIS + tristate "SiS 964/180 SATA support" + depends on ATA && PCI + help + This option enables support for SiS Serial ATA 964/180. + + If unsure, say N. + +config SATA_ULI + tristate "ULi Electronics SATA support" + depends on ATA && PCI + help + This option enables support for ULi Electronics SATA. + + If unsure, say N. + +config SATA_VIA + tristate "VIA SATA support" + depends on ATA && PCI + help + This option enables support for VIA Serial ATA. + + If unsure, say N. + +config SATA_VITESSE + tristate "VITESSE VSC-7174 / INTEL 31244 SATA support" + depends on ATA && PCI + help + This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA. + + If unsure, say N. + +config SATA_INTEL_COMBINED + bool + depends on IDE=y && !BLK_DEV_IDE_SATA && (SATA_AHCI || ATA_PIIX) + default y + +endmenu + diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile new file mode 100644 index 000000000000..c17ae9c8b91d --- /dev/null +++ b/drivers/ata/Makefile @@ -0,0 +1,21 @@ + +obj-$(CONFIG_ATA) += libata.o + +obj-$(CONFIG_SATA_AHCI) += ahci.o +obj-$(CONFIG_SATA_SVW) += sata_svw.o +obj-$(CONFIG_ATA_PIIX) += ata_piix.o +obj-$(CONFIG_SATA_PROMISE) += sata_promise.o +obj-$(CONFIG_SATA_QSTOR) += sata_qstor.o +obj-$(CONFIG_SATA_SIL) += sata_sil.o +obj-$(CONFIG_SATA_SIL24) += sata_sil24.o +obj-$(CONFIG_SATA_VIA) += sata_via.o +obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o +obj-$(CONFIG_SATA_SIS) += sata_sis.o +obj-$(CONFIG_SATA_SX4) += sata_sx4.o +obj-$(CONFIG_SATA_NV) += sata_nv.o +obj-$(CONFIG_SATA_ULI) += sata_uli.o +obj-$(CONFIG_SATA_MV) += sata_mv.o +obj-$(CONFIG_PDC_ADMA) += pdc_adma.o + +libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o + diff --git a/drivers/scsi/ahci.c b/drivers/ata/ahci.c index 904c25fb4ba4..813031c01fba 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/ata/ahci.c @@ -92,7 +92,9 @@ enum { HOST_AHCI_EN = (1 << 31), /* AHCI enabled */ /* HOST_CAP bits */ + HOST_CAP_SSC = (1 << 14), /* Slumber capable */ HOST_CAP_CLO = (1 << 24), /* Command List Override support */ + HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */ HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */ HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */ @@ -155,6 +157,7 @@ enum { PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */ PORT_CMD_START = (1 << 0), /* Enable port DMA engine */ + PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */ PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */ PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */ PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */ @@ -212,6 +215,10 @@ static void ahci_freeze(struct ata_port *ap); static void ahci_thaw(struct ata_port *ap); static void ahci_error_handler(struct ata_port *ap); static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); +static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg); +static int ahci_port_resume(struct ata_port *ap); +static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); +static int ahci_pci_device_resume(struct pci_dev *pdev); static void ahci_remove_one (struct pci_dev *pdev); static struct scsi_host_template ahci_sht = { @@ -231,6 +238,8 @@ static struct scsi_host_template ahci_sht = { .slave_configure = ata_scsi_slave_config, .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, + .suspend = ata_scsi_device_suspend, + .resume = ata_scsi_device_resume, }; static const struct ata_port_operations ahci_ops = { @@ -257,6 +266,9 @@ static const struct ata_port_operations ahci_ops = { .error_handler = ahci_error_handler, .post_internal_cmd = ahci_post_internal_cmd, + .port_suspend = ahci_port_suspend, + .port_resume = ahci_port_resume, + .port_start = ahci_port_start, .port_stop = ahci_port_stop, }; @@ -350,6 +362,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VENDOR_ID_NVIDIA, 0x044f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, board_ahci }, /* MCP65 */ + /* SiS */ + { PCI_VENDOR_ID_SI, 0x1184, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* SiS 966 */ + { PCI_VENDOR_ID_SI, 0x1185, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* SiS 966 */ + { PCI_VENDOR_ID_SI, 0x0186, PCI_ANY_ID, PCI_ANY_ID, 0, 0, + board_ahci }, /* SiS 968 */ + { } /* terminate list */ }; @@ -358,6 +378,8 @@ static struct pci_driver ahci_pci_driver = { .name = DRV_NAME, .id_table = ahci_pci_tbl, .probe = ahci_init_one, + .suspend = ahci_pci_device_suspend, + .resume = ahci_pci_device_resume, .remove = ahci_remove_one, }; @@ -372,177 +394,288 @@ static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int por return (void __iomem *) ahci_port_base_ul((unsigned long)base, port); } -static int ahci_port_start(struct ata_port *ap) +static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) { - struct device *dev = ap->host_set->dev; - struct ahci_host_priv *hpriv = ap->host_set->private_data; - struct ahci_port_priv *pp; - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - void *mem; - dma_addr_t mem_dma; - int rc; - - pp = kmalloc(sizeof(*pp), GFP_KERNEL); - if (!pp) - return -ENOMEM; - memset(pp, 0, sizeof(*pp)); + unsigned int sc_reg; - rc = ata_pad_alloc(ap, dev); - if (rc) { - kfree(pp); - return rc; + switch (sc_reg_in) { + case SCR_STATUS: sc_reg = 0; break; + case SCR_CONTROL: sc_reg = 1; break; + case SCR_ERROR: sc_reg = 2; break; + case SCR_ACTIVE: sc_reg = 3; break; + default: + return 0xffffffffU; } - mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); - if (!mem) { - ata_pad_free(ap, dev); - kfree(pp); - return -ENOMEM; - } - memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ); + return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} - /* - * First item in chunk of DMA memory: 32-slot command table, - * 32 bytes each in size - */ - pp->cmd_slot = mem; - pp->cmd_slot_dma = mem_dma; - mem += AHCI_CMD_SLOT_SZ; - mem_dma += AHCI_CMD_SLOT_SZ; +static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in, + u32 val) +{ + unsigned int sc_reg; - /* - * Second item: Received-FIS area - */ - pp->rx_fis = mem; - pp->rx_fis_dma = mem_dma; + switch (sc_reg_in) { + case SCR_STATUS: sc_reg = 0; break; + case SCR_CONTROL: sc_reg = 1; break; + case SCR_ERROR: sc_reg = 2; break; + case SCR_ACTIVE: sc_reg = 3; break; + default: + return; + } - mem += AHCI_RX_FIS_SZ; - mem_dma += AHCI_RX_FIS_SZ; + writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} - /* - * Third item: data area for storing a single command - * and its scatter-gather table - */ - pp->cmd_tbl = mem; - pp->cmd_tbl_dma = mem_dma; +static void ahci_start_engine(void __iomem *port_mmio) +{ + u32 tmp; - ap->private_data = pp; + /* start DMA */ + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_START; + writel(tmp, port_mmio + PORT_CMD); + readl(port_mmio + PORT_CMD); /* flush */ +} - if (hpriv->cap & HOST_CAP_64) - writel((pp->cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI); - writel(pp->cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR); - readl(port_mmio + PORT_LST_ADDR); /* flush */ +static int ahci_stop_engine(void __iomem *port_mmio) +{ + u32 tmp; - if (hpriv->cap & HOST_CAP_64) - writel((pp->rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI); - writel(pp->rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR); - readl(port_mmio + PORT_FIS_ADDR); /* flush */ + tmp = readl(port_mmio + PORT_CMD); - writel(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX | - PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP | - PORT_CMD_START, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ + /* check if the HBA is idle */ + if ((tmp & (PORT_CMD_START | PORT_CMD_LIST_ON)) == 0) + return 0; + + /* setting HBA to idle */ + tmp &= ~PORT_CMD_START; + writel(tmp, port_mmio + PORT_CMD); + + /* wait for engine to stop. This could be as long as 500 msec */ + tmp = ata_wait_register(port_mmio + PORT_CMD, + PORT_CMD_LIST_ON, PORT_CMD_LIST_ON, 1, 500); + if (tmp & PORT_CMD_LIST_ON) + return -EIO; return 0; } +static void ahci_start_fis_rx(void __iomem *port_mmio, u32 cap, + dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) +{ + u32 tmp; + + /* set FIS registers */ + if (cap & HOST_CAP_64) + writel((cmd_slot_dma >> 16) >> 16, port_mmio + PORT_LST_ADDR_HI); + writel(cmd_slot_dma & 0xffffffff, port_mmio + PORT_LST_ADDR); -static void ahci_port_stop(struct ata_port *ap) + if (cap & HOST_CAP_64) + writel((rx_fis_dma >> 16) >> 16, port_mmio + PORT_FIS_ADDR_HI); + writel(rx_fis_dma & 0xffffffff, port_mmio + PORT_FIS_ADDR); + + /* enable FIS reception */ + tmp = readl(port_mmio + PORT_CMD); + tmp |= PORT_CMD_FIS_RX; + writel(tmp, port_mmio + PORT_CMD); + + /* flush */ + readl(port_mmio + PORT_CMD); +} + +static int ahci_stop_fis_rx(void __iomem *port_mmio) { - struct device *dev = ap->host_set->dev; - struct ahci_port_priv *pp = ap->private_data; - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); u32 tmp; + /* disable FIS reception */ tmp = readl(port_mmio + PORT_CMD); - tmp &= ~(PORT_CMD_START | PORT_CMD_FIS_RX); + tmp &= ~PORT_CMD_FIS_RX; writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - /* spec says 500 msecs for each PORT_CMD_{START,FIS_RX} bit, so - * this is slightly incorrect. - */ - msleep(500); + /* wait for completion, spec says 500ms, give it 1000 */ + tmp = ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_FIS_ON, + PORT_CMD_FIS_ON, 10, 1000); + if (tmp & PORT_CMD_FIS_ON) + return -EBUSY; - ap->private_data = NULL; - dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, - pp->cmd_slot, pp->cmd_slot_dma); - ata_pad_free(ap, dev); - kfree(pp); + return 0; } -static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg_in) +static void ahci_power_up(void __iomem *port_mmio, u32 cap) { - unsigned int sc_reg; + u32 cmd; - switch (sc_reg_in) { - case SCR_STATUS: sc_reg = 0; break; - case SCR_CONTROL: sc_reg = 1; break; - case SCR_ERROR: sc_reg = 2; break; - case SCR_ACTIVE: sc_reg = 3; break; - default: - return 0xffffffffU; + cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK; + + /* spin up device */ + if (cap & HOST_CAP_SSS) { + cmd |= PORT_CMD_SPIN_UP; + writel(cmd, port_mmio + PORT_CMD); } - return readl((void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); + /* wake up link */ + writel(cmd | PORT_CMD_ICC_ACTIVE, port_mmio + PORT_CMD); } +static void ahci_power_down(void __iomem *port_mmio, u32 cap) +{ + u32 cmd, scontrol; -static void ahci_scr_write (struct ata_port *ap, unsigned int sc_reg_in, - u32 val) + cmd = readl(port_mmio + PORT_CMD) & ~PORT_CMD_ICC_MASK; + + if (cap & HOST_CAP_SSC) { + /* enable transitions to slumber mode */ + scontrol = readl(port_mmio + PORT_SCR_CTL); + if ((scontrol & 0x0f00) > 0x100) { + scontrol &= ~0xf00; + writel(scontrol, port_mmio + PORT_SCR_CTL); + } + + /* put device into slumber mode */ + writel(cmd | PORT_CMD_ICC_SLUMBER, port_mmio + PORT_CMD); + + /* wait for the transition to complete */ + ata_wait_register(port_mmio + PORT_CMD, PORT_CMD_ICC_SLUMBER, + PORT_CMD_ICC_SLUMBER, 1, 50); + } + + /* put device into listen mode */ + if (cap & HOST_CAP_SSS) { + /* first set PxSCTL.DET to 0 */ + scontrol = readl(port_mmio + PORT_SCR_CTL); + scontrol &= ~0xf; + writel(scontrol, port_mmio + PORT_SCR_CTL); + + /* then set PxCMD.SUD to 0 */ + cmd &= ~PORT_CMD_SPIN_UP; + writel(cmd, port_mmio + PORT_CMD); + } +} + +static void ahci_init_port(void __iomem *port_mmio, u32 cap, + dma_addr_t cmd_slot_dma, dma_addr_t rx_fis_dma) { - unsigned int sc_reg; + /* power up */ + ahci_power_up(port_mmio, cap); - switch (sc_reg_in) { - case SCR_STATUS: sc_reg = 0; break; - case SCR_CONTROL: sc_reg = 1; break; - case SCR_ERROR: sc_reg = 2; break; - case SCR_ACTIVE: sc_reg = 3; break; - default: - return; + /* enable FIS reception */ + ahci_start_fis_rx(port_mmio, cap, cmd_slot_dma, rx_fis_dma); + + /* enable DMA */ + ahci_start_engine(port_mmio); +} + +static int ahci_deinit_port(void __iomem *port_mmio, u32 cap, const char **emsg) +{ + int rc; + + /* disable DMA */ + rc = ahci_stop_engine(port_mmio); + if (rc) { + *emsg = "failed to stop engine"; + return rc; } - writel(val, (void __iomem *) ap->ioaddr.scr_addr + (sc_reg * 4)); + /* disable FIS reception */ + rc = ahci_stop_fis_rx(port_mmio); + if (rc) { + *emsg = "failed stop FIS RX"; + return rc; + } + + /* put device into slumber mode */ + ahci_power_down(port_mmio, cap); + + return 0; } -static int ahci_stop_engine(struct ata_port *ap) +static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) { - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); - int work; - u32 tmp; + u32 cap_save, tmp; - tmp = readl(port_mmio + PORT_CMD); - tmp &= ~PORT_CMD_START; - writel(tmp, port_mmio + PORT_CMD); + cap_save = readl(mmio + HOST_CAP); + cap_save &= ( (1<<28) | (1<<17) ); + cap_save |= (1 << 27); - /* wait for engine to stop. TODO: this could be - * as long as 500 msec + /* global controller reset */ + tmp = readl(mmio + HOST_CTL); + if ((tmp & HOST_RESET) == 0) { + writel(tmp | HOST_RESET, mmio + HOST_CTL); + readl(mmio + HOST_CTL); /* flush */ + } + + /* reset must complete within 1 second, or + * the hardware should be considered fried. */ - work = 1000; - while (work-- > 0) { - tmp = readl(port_mmio + PORT_CMD); - if ((tmp & PORT_CMD_LIST_ON) == 0) - return 0; - udelay(10); + ssleep(1); + + tmp = readl(mmio + HOST_CTL); + if (tmp & HOST_RESET) { + dev_printk(KERN_ERR, &pdev->dev, + "controller reset failed (0x%x)\n", tmp); + return -EIO; } - return -EIO; + writel(HOST_AHCI_EN, mmio + HOST_CTL); + (void) readl(mmio + HOST_CTL); /* flush */ + writel(cap_save, mmio + HOST_CAP); + writel(0xf, mmio + HOST_PORTS_IMPL); + (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ + + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + u16 tmp16; + + /* configure PCS */ + pci_read_config_word(pdev, 0x92, &tmp16); + tmp16 |= 0xf; + pci_write_config_word(pdev, 0x92, tmp16); + } + + return 0; } -static void ahci_start_engine(struct ata_port *ap) +static void ahci_init_controller(void __iomem *mmio, struct pci_dev *pdev, + int n_ports, u32 cap) { - void __iomem *mmio = ap->host_set->mmio_base; - void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + int i, rc; u32 tmp; - tmp = readl(port_mmio + PORT_CMD); - tmp |= PORT_CMD_START; - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ + for (i = 0; i < n_ports; i++) { + void __iomem *port_mmio = ahci_port_base(mmio, i); + const char *emsg = NULL; + +#if 0 /* BIOSen initialize this incorrectly */ + if (!(hpriv->port_map & (1 << i))) + continue; +#endif + + /* make sure port is not active */ + rc = ahci_deinit_port(port_mmio, cap, &emsg); + if (rc) + dev_printk(KERN_WARNING, &pdev->dev, + "%s (%d)\n", emsg, rc); + + /* clear SError */ + tmp = readl(port_mmio + PORT_SCR_ERR); + VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); + writel(tmp, port_mmio + PORT_SCR_ERR); + + /* clear port IRQ */ + tmp = readl(port_mmio + PORT_IRQ_STAT); + VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); + if (tmp) + writel(tmp, port_mmio + PORT_IRQ_STAT); + + writel(1 << i, mmio + HOST_IRQ_STAT); + } + + tmp = readl(mmio + HOST_CTL); + VPRINTK("HOST_CTL 0x%x\n", tmp); + writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); + tmp = readl(mmio + HOST_CTL); + VPRINTK("HOST_CTL 0x%x\n", tmp); } static unsigned int ahci_dev_classify(struct ata_port *ap) @@ -626,7 +759,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) } /* prepare for SRST (AHCI-1.1 10.4.1) */ - rc = ahci_stop_engine(ap); + rc = ahci_stop_engine(port_mmio); if (rc) { reason = "failed to stop engine"; goto fail_restart; @@ -647,7 +780,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) } /* restart engine */ - ahci_start_engine(ap); + ahci_start_engine(port_mmio); ata_tf_init(ap->device, &tf); fis = pp->cmd_tbl; @@ -706,7 +839,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) return 0; fail_restart: - ahci_start_engine(ap); + ahci_start_engine(port_mmio); fail: ata_port_printk(ap, KERN_ERR, "softreset failed (%s)\n", reason); return rc; @@ -717,11 +850,13 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) struct ahci_port_priv *pp = ap->private_data; u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG; struct ata_taskfile tf; + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); int rc; DPRINTK("ENTER\n"); - ahci_stop_engine(ap); + ahci_stop_engine(port_mmio); /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(ap->device, &tf); @@ -730,7 +865,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) rc = sata_std_hardreset(ap, class); - ahci_start_engine(ap); + ahci_start_engine(port_mmio); if (rc == 0 && ata_port_online(ap)) *class = ahci_dev_classify(ap); @@ -1046,10 +1181,13 @@ static void ahci_thaw(struct ata_port *ap) static void ahci_error_handler(struct ata_port *ap) { + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + if (!(ap->pflags & ATA_PFLAG_FROZEN)) { /* restart engine */ - ahci_stop_engine(ap); - ahci_start_engine(ap); + ahci_stop_engine(port_mmio); + ahci_start_engine(port_mmio); } /* perform recovery */ @@ -1060,15 +1198,176 @@ static void ahci_error_handler(struct ata_port *ap) static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) { struct ata_port *ap = qc->ap; + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); if (qc->flags & ATA_QCFLAG_FAILED) qc->err_mask |= AC_ERR_OTHER; if (qc->err_mask) { /* make DMA engine forget about the failed command */ - ahci_stop_engine(ap); - ahci_start_engine(ap); + ahci_stop_engine(port_mmio); + ahci_start_engine(port_mmio); + } +} + +static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) +{ + struct ahci_host_priv *hpriv = ap->host_set->private_data; + struct ahci_port_priv *pp = ap->private_data; + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + const char *emsg = NULL; + int rc; + + rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); + if (rc) { + ata_port_printk(ap, KERN_ERR, "%s (%d)\n", emsg, rc); + ahci_init_port(port_mmio, hpriv->cap, + pp->cmd_slot_dma, pp->rx_fis_dma); } + + return rc; +} + +static int ahci_port_resume(struct ata_port *ap) +{ + struct ahci_port_priv *pp = ap->private_data; + struct ahci_host_priv *hpriv = ap->host_set->private_data; + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + + ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); + + return 0; +} + +static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) +{ + struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev); + void __iomem *mmio = host_set->mmio_base; + u32 ctl; + + if (mesg.event == PM_EVENT_SUSPEND) { + /* AHCI spec rev1.1 section 8.3.3: + * Software must disable interrupts prior to requesting a + * transition of the HBA to D3 state. + */ + ctl = readl(mmio + HOST_CTL); + ctl &= ~HOST_IRQ_EN; + writel(ctl, mmio + HOST_CTL); + readl(mmio + HOST_CTL); /* flush */ + } + + return ata_pci_device_suspend(pdev, mesg); +} + +static int ahci_pci_device_resume(struct pci_dev *pdev) +{ + struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev); + struct ahci_host_priv *hpriv = host_set->private_data; + void __iomem *mmio = host_set->mmio_base; + int rc; + + ata_pci_device_do_resume(pdev); + + if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { + rc = ahci_reset_controller(mmio, pdev); + if (rc) + return rc; + + ahci_init_controller(mmio, pdev, host_set->n_ports, hpriv->cap); + } + + ata_host_set_resume(host_set); + + return 0; +} + +static int ahci_port_start(struct ata_port *ap) +{ + struct device *dev = ap->host_set->dev; + struct ahci_host_priv *hpriv = ap->host_set->private_data; + struct ahci_port_priv *pp; + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + void *mem; + dma_addr_t mem_dma; + int rc; + + pp = kmalloc(sizeof(*pp), GFP_KERNEL); + if (!pp) + return -ENOMEM; + memset(pp, 0, sizeof(*pp)); + + rc = ata_pad_alloc(ap, dev); + if (rc) { + kfree(pp); + return rc; + } + + mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); + if (!mem) { + ata_pad_free(ap, dev); + kfree(pp); + return -ENOMEM; + } + memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ); + + /* + * First item in chunk of DMA memory: 32-slot command table, + * 32 bytes each in size + */ + pp->cmd_slot = mem; + pp->cmd_slot_dma = mem_dma; + + mem += AHCI_CMD_SLOT_SZ; + mem_dma += AHCI_CMD_SLOT_SZ; + + /* + * Second item: Received-FIS area + */ + pp->rx_fis = mem; + pp->rx_fis_dma = mem_dma; + + mem += AHCI_RX_FIS_SZ; + mem_dma += AHCI_RX_FIS_SZ; + + /* + * Third item: data area for storing a single command + * and its scatter-gather table + */ + pp->cmd_tbl = mem; + pp->cmd_tbl_dma = mem_dma; + + ap->private_data = pp; + + /* initialize port */ + ahci_init_port(port_mmio, hpriv->cap, pp->cmd_slot_dma, pp->rx_fis_dma); + + return 0; +} + +static void ahci_port_stop(struct ata_port *ap) +{ + struct device *dev = ap->host_set->dev; + struct ahci_host_priv *hpriv = ap->host_set->private_data; + struct ahci_port_priv *pp = ap->private_data; + void __iomem *mmio = ap->host_set->mmio_base; + void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); + const char *emsg = NULL; + int rc; + + /* de-initialize port */ + rc = ahci_deinit_port(port_mmio, hpriv->cap, &emsg); + if (rc) + ata_port_printk(ap, KERN_WARNING, "%s (%d)\n", emsg, rc); + + ap->private_data = NULL; + dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, + pp->cmd_slot, pp->cmd_slot_dma); + ata_pad_free(ap, dev); + kfree(pp); } static void ahci_setup_port(struct ata_ioports *port, unsigned long base, @@ -1089,47 +1388,12 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) struct ahci_host_priv *hpriv = probe_ent->private_data; struct pci_dev *pdev = to_pci_dev(probe_ent->dev); void __iomem *mmio = probe_ent->mmio_base; - u32 tmp, cap_save; - unsigned int i, j, using_dac; + unsigned int i, using_dac; int rc; - void __iomem *port_mmio; - cap_save = readl(mmio + HOST_CAP); - cap_save &= ( (1<<28) | (1<<17) ); - cap_save |= (1 << 27); - - /* global controller reset */ - tmp = readl(mmio + HOST_CTL); - if ((tmp & HOST_RESET) == 0) { - writel(tmp | HOST_RESET, mmio + HOST_CTL); - readl(mmio + HOST_CTL); /* flush */ - } - - /* reset must complete within 1 second, or - * the hardware should be considered fried. - */ - ssleep(1); - - tmp = readl(mmio + HOST_CTL); - if (tmp & HOST_RESET) { - dev_printk(KERN_ERR, &pdev->dev, - "controller reset failed (0x%x)\n", tmp); - return -EIO; - } - - writel(HOST_AHCI_EN, mmio + HOST_CTL); - (void) readl(mmio + HOST_CTL); /* flush */ - writel(cap_save, mmio + HOST_CAP); - writel(0xf, mmio + HOST_PORTS_IMPL); - (void) readl(mmio + HOST_PORTS_IMPL); /* flush */ - - if (pdev->vendor == PCI_VENDOR_ID_INTEL) { - u16 tmp16; - - pci_read_config_word(pdev, 0x92, &tmp16); - tmp16 |= 0xf; - pci_write_config_word(pdev, 0x92, tmp16); - } + rc = ahci_reset_controller(mmio, pdev); + if (rc) + return rc; hpriv->cap = readl(mmio + HOST_CAP); hpriv->port_map = readl(mmio + HOST_PORTS_IMPL); @@ -1165,63 +1429,10 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent) } } - for (i = 0; i < probe_ent->n_ports; i++) { -#if 0 /* BIOSen initialize this incorrectly */ - if (!(hpriv->port_map & (1 << i))) - continue; -#endif - - port_mmio = ahci_port_base(mmio, i); - VPRINTK("mmio %p port_mmio %p\n", mmio, port_mmio); - - ahci_setup_port(&probe_ent->port[i], - (unsigned long) mmio, i); - - /* make sure port is not active */ - tmp = readl(port_mmio + PORT_CMD); - VPRINTK("PORT_CMD 0x%x\n", tmp); - if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | - PORT_CMD_FIS_RX | PORT_CMD_START)) { - tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON | - PORT_CMD_FIS_RX | PORT_CMD_START); - writel(tmp, port_mmio + PORT_CMD); - readl(port_mmio + PORT_CMD); /* flush */ - - /* spec says 500 msecs for each bit, so - * this is slightly incorrect. - */ - msleep(500); - } - - writel(PORT_CMD_SPIN_UP, port_mmio + PORT_CMD); - - j = 0; - while (j < 100) { - msleep(10); - tmp = readl(port_mmio + PORT_SCR_STAT); - if ((tmp & 0xf) == 0x3) - break; - j++; - } - - tmp = readl(port_mmio + PORT_SCR_ERR); - VPRINTK("PORT_SCR_ERR 0x%x\n", tmp); - writel(tmp, port_mmio + PORT_SCR_ERR); + for (i = 0; i < probe_ent->n_ports; i++) + ahci_setup_port(&probe_ent->port[i], (unsigned long) mmio, i); - /* ack any pending irq events for this port */ - tmp = readl(port_mmio + PORT_IRQ_STAT); - VPRINTK("PORT_IRQ_STAT 0x%x\n", tmp); - if (tmp) - writel(tmp, port_mmio + PORT_IRQ_STAT); - - writel(1 << i, mmio + HOST_IRQ_STAT); - } - - tmp = readl(mmio + HOST_CTL); - VPRINTK("HOST_CTL 0x%x\n", tmp); - writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); - tmp = readl(mmio + HOST_CTL); - VPRINTK("HOST_CTL 0x%x\n", tmp); + ahci_init_controller(mmio, pdev, probe_ent->n_ports, hpriv->cap); pci_set_master(pdev); @@ -1454,7 +1665,7 @@ static void ahci_remove_one (struct pci_dev *pdev) static int __init ahci_init(void) { - return pci_module_init(&ahci_pci_driver); + return pci_register_driver(&ahci_pci_driver); } static void __exit ahci_exit(void) diff --git a/drivers/scsi/ata_piix.c b/drivers/ata/ata_piix.c index 5e8afc876980..51d919c8073d 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -487,7 +487,7 @@ static void piix_pata_cbl_detect(struct ata_port *ap) goto cbl40; /* check BIOS cable detect results */ - mask = ap->hard_port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; + mask = ap->port_no == 0 ? PIIX_80C_PRI : PIIX_80C_SEC; pci_read_config_byte(pdev, PIIX_IOCFG, &tmp); if ((tmp & mask) == 0) goto cbl40; @@ -513,7 +513,7 @@ static int piix_pata_prereset(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])) { + if (!pci_test_config_bits(pdev, &piix_enable_bits[ap->port_no])) { ata_port_printk(ap, KERN_INFO, "port disabled. ignoring.\n"); ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; return 0; @@ -550,7 +550,7 @@ static int piix_sata_prereset(struct ata_port *ap) struct pci_dev *pdev = to_pci_dev(ap->host_set->dev); struct piix_host_priv *hpriv = ap->host_set->private_data; const unsigned int *map = hpriv->map; - int base = 2 * ap->hard_port_no; + int base = 2 * ap->port_no; unsigned int present = 0; int port, i; u16 pcs; @@ -601,7 +601,7 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) unsigned int pio = adev->pio_mode - XFER_PIO_0; struct pci_dev *dev = to_pci_dev(ap->host_set->dev); unsigned int is_slave = (adev->devno != 0); - unsigned int master_port= ap->hard_port_no ? 0x42 : 0x40; + unsigned int master_port= ap->port_no ? 0x42 : 0x40; unsigned int slave_port = 0x44; u16 master_data; u8 slave_data; @@ -619,10 +619,10 @@ static void piix_set_piomode (struct ata_port *ap, struct ata_device *adev) /* enable PPE, IE and TIME */ master_data |= 0x0070; pci_read_config_byte(dev, slave_port, &slave_data); - slave_data &= (ap->hard_port_no ? 0x0f : 0xf0); + slave_data &= (ap->port_no ? 0x0f : 0xf0); slave_data |= (timings[pio][0] << 2) | - (timings[pio][1] << (ap->hard_port_no ? 4 : 0)); + (timings[pio][1] << (ap->port_no ? 4 : 0)); } else { master_data &= 0xccf8; /* enable PPE, IE and TIME */ @@ -652,9 +652,9 @@ static void piix_set_dmamode (struct ata_port *ap, struct ata_device *adev) { 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 maslave = ap->port_no ? 0x42 : 0x40; u8 speed = udma; - unsigned int drive_dn = (ap->hard_port_no ? 2 : 0) + adev->devno; + unsigned int drive_dn = (ap->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; @@ -932,17 +932,19 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static void piix_host_stop(struct ata_host_set *host_set) { - if (host_set->next == NULL) - kfree(host_set->private_data); + struct piix_host_priv *hpriv = host_set->private_data; + ata_host_stop(host_set); + + kfree(hpriv); } static int __init piix_init(void) { int rc; - DPRINTK("pci_module_init\n"); - rc = pci_module_init(&piix_pci_driver); + DPRINTK("pci_register_driver\n"); + rc = pci_register_driver(&piix_pci_driver); if (rc) return rc; diff --git a/drivers/scsi/libata-bmdma.c b/drivers/ata/libata-bmdma.c index 9ce221f25954..158f62dbf21b 100644 --- a/drivers/scsi/libata-bmdma.c +++ b/drivers/ata/libata-bmdma.c @@ -797,32 +797,6 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc) } #ifdef CONFIG_PCI -static struct ata_probe_ent * -ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) -{ - struct ata_probe_ent *probe_ent; - - probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); - if (!probe_ent) { - printk(KERN_ERR DRV_NAME "(%s): out of memory\n", - kobject_name(&(dev->kobj))); - return NULL; - } - - INIT_LIST_HEAD(&probe_ent->node); - probe_ent->dev = dev; - - probe_ent->sht = port->sht; - probe_ent->host_flags = port->host_flags; - probe_ent->pio_mask = port->pio_mask; - probe_ent->mwdma_mask = port->mwdma_mask; - probe_ent->udma_mask = port->udma_mask; - probe_ent->port_ops = port->port_ops; - - return probe_ent; -} - - /** * ata_pci_init_native_mode - Initialize native-mode driver * @pdev: pci device to be initialized @@ -880,7 +854,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int if (bmdma) { bmdma += 8; if(inb(bmdma + 2) & 0x80) - probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; probe_ent->port[p].bmdma_addr = bmdma; } ata_std_ports(&probe_ent->port[p]); @@ -893,44 +867,48 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, - struct ata_port_info *port, int port_num) + struct ata_port_info **port, int port_mask) { struct ata_probe_ent *probe_ent; - unsigned long bmdma; + unsigned long bmdma = pci_resource_start(pdev, 4); - probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port); + probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]); if (!probe_ent) return NULL; - probe_ent->legacy_mode = 1; - probe_ent->n_ports = 1; - probe_ent->hard_port_no = port_num; - probe_ent->private_data = port->private_data; - - switch(port_num) - { - case 0: - probe_ent->irq = 14; - probe_ent->port[0].cmd_addr = 0x1f0; - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = 0x3f6; - break; - case 1: - probe_ent->irq = 15; - probe_ent->port[0].cmd_addr = 0x170; - probe_ent->port[0].altstatus_addr = - probe_ent->port[0].ctl_addr = 0x376; - break; - } + probe_ent->n_ports = 2; + probe_ent->private_data = port[0]->private_data; - bmdma = pci_resource_start(pdev, 4); - if (bmdma != 0) { - bmdma += 8 * port_num; - probe_ent->port[0].bmdma_addr = bmdma; - if (inb(bmdma + 2) & 0x80) - probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; - } - ata_std_ports(&probe_ent->port[0]); + if (port_mask & ATA_PORT_PRIMARY) { + probe_ent->irq = 14; + probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD; + probe_ent->port[0].altstatus_addr = + probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL; + if (bmdma) { + probe_ent->port[0].bmdma_addr = bmdma; + if (inb(bmdma + 2) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + } + ata_std_ports(&probe_ent->port[0]); + } else + probe_ent->dummy_port_mask |= ATA_PORT_PRIMARY; + + if (port_mask & ATA_PORT_SECONDARY) { + if (probe_ent->irq) + probe_ent->irq2 = 15; + else + probe_ent->irq = 15; + probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD; + probe_ent->port[1].altstatus_addr = + probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL; + if (bmdma) { + probe_ent->port[1].bmdma_addr = bmdma + 8; + if (inb(bmdma + 10) & 0x80) + probe_ent->host_set_flags |= ATA_HOST_SIMPLEX; + } + ata_std_ports(&probe_ent->port[1]); + } else + probe_ent->dummy_port_mask |= ATA_PORT_SECONDARY; return probe_ent; } @@ -950,6 +928,10 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, * regions, sets the dma mask, enables bus master mode, and calls * ata_device_add() * + * ASSUMPTION: + * Nobody makes a single channel controller that appears solely as + * the secondary legacy port on PCI. + * * LOCKING: * Inherited from PCI layer (may sleep). * @@ -960,7 +942,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, unsigned int n_ports) { - struct ata_probe_ent *probe_ent = NULL, *probe_ent2 = NULL; + struct ata_probe_ent *probe_ent = NULL; struct ata_port_info *port[2]; u8 tmp8, mask; unsigned int legacy_mode = 0; @@ -1009,35 +991,34 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, goto err_out; } - /* FIXME: Should use platform specific mappers for legacy port ranges */ if (legacy_mode) { - if (!request_region(0x1f0, 8, "libata")) { + if (!request_region(ATA_PRIMARY_CMD, 8, "libata")) { struct resource *conflict, res; - res.start = 0x1f0; - res.end = 0x1f0 + 8 - 1; + res.start = ATA_PRIMARY_CMD; + res.end = ATA_PRIMARY_CMD + 8 - 1; conflict = ____request_resource(&ioport_resource, &res); if (!strcmp(conflict->name, "libata")) - legacy_mode |= (1 << 0); + legacy_mode |= ATA_PORT_PRIMARY; else { disable_dev_on_err = 0; - printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); + printk(KERN_WARNING "ata: 0x%0X IDE port busy\n", ATA_PRIMARY_CMD); } } else - legacy_mode |= (1 << 0); + legacy_mode |= ATA_PORT_PRIMARY; - if (!request_region(0x170, 8, "libata")) { + if (!request_region(ATA_SECONDARY_CMD, 8, "libata")) { struct resource *conflict, res; - res.start = 0x170; - res.end = 0x170 + 8 - 1; + res.start = ATA_SECONDARY_CMD; + res.end = ATA_SECONDARY_CMD + 8 - 1; conflict = ____request_resource(&ioport_resource, &res); if (!strcmp(conflict->name, "libata")) - legacy_mode |= (1 << 1); + legacy_mode |= ATA_PORT_SECONDARY; else { disable_dev_on_err = 0; - printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); + printk(KERN_WARNING "ata: 0x%X IDE port busy\n", ATA_SECONDARY_CMD); } } else - legacy_mode |= (1 << 1); + legacy_mode |= ATA_PORT_SECONDARY; } /* we have legacy mode, but all ports are unavailable */ @@ -1055,17 +1036,14 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, goto err_out_regions; if (legacy_mode) { - if (legacy_mode & (1 << 0)) - probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0); - if (legacy_mode & (1 << 1)) - probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1); + probe_ent = ata_pci_init_legacy_port(pdev, port, legacy_mode); } else { if (n_ports == 2) probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); else probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY); } - if (!probe_ent && !probe_ent2) { + if (!probe_ent) { rc = -ENOMEM; goto err_out_regions; } @@ -1073,35 +1051,17 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, pci_set_master(pdev); /* FIXME: check ata_device_add return */ - if (legacy_mode) { - struct device *dev = &pdev->dev; - struct ata_host_set *host_set = NULL; - - if (legacy_mode & (1 << 0)) { - ata_device_add(probe_ent); - host_set = dev_get_drvdata(dev); - } - - if (legacy_mode & (1 << 1)) { - ata_device_add(probe_ent2); - if (host_set) { - host_set->next = dev_get_drvdata(dev); - dev_set_drvdata(dev, host_set); - } - } - } else - ata_device_add(probe_ent); + ata_device_add(probe_ent); kfree(probe_ent); - kfree(probe_ent2); return 0; err_out_regions: - if (legacy_mode & (1 << 0)) - release_region(0x1f0, 8); - if (legacy_mode & (1 << 1)) - release_region(0x170, 8); + if (legacy_mode & ATA_PORT_PRIMARY) + release_region(ATA_PRIMARY_CMD, 8); + if (legacy_mode & ATA_PORT_SECONDARY) + release_region(ATA_SECONDARY_CMD, 8); pci_release_regions(pdev); err_out: if (disable_dev_on_err) diff --git a/drivers/scsi/libata-core.c b/drivers/ata/libata-core.c index 73dd6c8deede..9092416a6301 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/ata/libata-core.c @@ -50,7 +50,6 @@ #include <linux/jiffies.h> #include <linux/scatterlist.h> #include <scsi/scsi.h> -#include "scsi_priv.h" #include <scsi/scsi_cmnd.h> #include <scsi/scsi_host.h> #include <linux/libata.h> @@ -387,9 +386,13 @@ static const char *ata_mode_string(unsigned int xfer_mask) "PIO2", "PIO3", "PIO4", + "PIO5", + "PIO6", "MWDMA0", "MWDMA1", "MWDMA2", + "MWDMA3", + "MWDMA4", "UDMA/16", "UDMA/25", "UDMA/33", @@ -876,6 +879,23 @@ static unsigned int ata_id_xfermask(const u16 *id) mwdma_mask = id[ATA_ID_MWDMA_MODES] & 0x07; + if (ata_id_is_cfa(id)) { + /* + * Process compact flash extended modes + */ + int pio = id[163] & 0x7; + int dma = (id[163] >> 3) & 7; + + if (pio) + pio_mask |= (1 << 5); + if (pio > 1) + pio_mask |= (1 << 6); + if (dma) + mwdma_mask |= (1 << 3); + if (dma > 1) + mwdma_mask |= (1 << 4); + } + udma_mask = 0; if (id[ATA_ID_FIELD_VALID] & (1 << 2)) udma_mask = id[ATA_ID_UDMA_MODES] & 0xff; @@ -1357,6 +1377,7 @@ int ata_dev_configure(struct ata_device *dev, int print_info) struct ata_port *ap = dev->ap; const u16 *id = dev->id; unsigned int xfer_mask; + char revbuf[7]; /* XYZ-99\0 */ int rc; if (!ata_dev_enabled(dev) && ata_msg_info(ap)) { @@ -1400,6 +1421,15 @@ int ata_dev_configure(struct ata_device *dev, int print_info) /* ATA-specific feature tests */ if (dev->class == ATA_DEV_ATA) { + if (ata_id_is_cfa(id)) { + if (id[162] & 1) /* CPRM may make this media unusable */ + ata_dev_printk(dev, KERN_WARNING, "ata%u: device %u supports DRM functions and may not be fully accessable.\n", + ap->id, dev->devno); + snprintf(revbuf, 7, "CFA"); + } + else + snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id)); + dev->n_sectors = ata_id_n_sectors(id); if (ata_id_has_lba(id)) { @@ -1418,9 +1448,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (ata_msg_drv(ap) && print_info) - ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + ata_dev_printk(dev, KERN_INFO, "%s, " "max %s, %Lu sectors: %s %s\n", - ata_id_major_version(id), + revbuf, ata_mode_string(xfer_mask), (unsigned long long)dev->n_sectors, lba_desc, ncq_desc); @@ -1441,9 +1471,9 @@ int ata_dev_configure(struct ata_device *dev, int print_info) /* print device info to dmesg */ if (ata_msg_drv(ap) && print_info) - ata_dev_printk(dev, KERN_INFO, "ATA-%d, " + ata_dev_printk(dev, KERN_INFO, "%s, " "max %s, %Lu sectors: CHS %u/%u/%u\n", - ata_id_major_version(id), + revbuf, ata_mode_string(xfer_mask), (unsigned long long)dev->n_sectors, dev->cylinders, dev->heads, @@ -1528,7 +1558,7 @@ err_out_nosup: * Zero on success, negative errno otherwise. */ -static int ata_bus_probe(struct ata_port *ap) +int ata_bus_probe(struct ata_port *ap) { unsigned int classes[ATA_MAX_DEVICES]; int tries[ATA_MAX_DEVICES]; @@ -1901,10 +1931,11 @@ int sata_set_spd(struct ata_port *ap) * drivers/ide/ide-timing.h and was originally written by Vojtech Pavlik */ /* - * PIO 0-5, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). + * PIO 0-4, MWDMA 0-2 and UDMA 0-6 timings (in nanoseconds). * These were taken from ATA/ATAPI-6 standard, rev 0a, except - * for PIO 5, which is a nonstandard extension and UDMA6, which - * is currently supported only by Maxtor drives. + * for UDMA6, which is currently supported only by Maxtor drives. + * + * For PIO 5/6 MWDMA 3/4 see the CFA specification 3.0. */ static const struct ata_timing ata_timing[] = { @@ -1914,6 +1945,8 @@ static const struct ata_timing ata_timing[] = { { XFER_UDMA_4, 0, 0, 0, 0, 0, 0, 0, 30 }, { XFER_UDMA_3, 0, 0, 0, 0, 0, 0, 0, 45 }, + { XFER_MW_DMA_4, 25, 0, 0, 0, 55, 20, 80, 0 }, + { XFER_MW_DMA_3, 25, 0, 0, 0, 65, 25, 100, 0 }, { XFER_UDMA_2, 0, 0, 0, 0, 0, 0, 0, 60 }, { XFER_UDMA_1, 0, 0, 0, 0, 0, 0, 0, 80 }, { XFER_UDMA_0, 0, 0, 0, 0, 0, 0, 0, 120 }, @@ -1928,7 +1961,8 @@ static const struct ata_timing ata_timing[] = { { XFER_SW_DMA_1, 90, 0, 0, 0, 240, 240, 480, 0 }, { XFER_SW_DMA_0, 120, 0, 0, 0, 480, 480, 960, 0 }, -/* { XFER_PIO_5, 20, 50, 30, 100, 50, 30, 100, 0 }, */ + { XFER_PIO_6, 10, 55, 20, 80, 55, 20, 80, 0 }, + { XFER_PIO_5, 15, 65, 25, 100, 65, 25, 100, 0 }, { XFER_PIO_4, 25, 70, 25, 120, 70, 25, 120, 0 }, { XFER_PIO_3, 30, 80, 70, 180, 80, 70, 180, 0 }, @@ -3040,10 +3074,6 @@ static int ata_dma_blacklisted(const struct ata_device *dev) * known limits including host controller limits, device * blacklist, etc... * - * FIXME: The current implementation limits all transfer modes to - * the fastest of the lowested device on the port. This is not - * required on most controllers. - * * LOCKING: * None. */ @@ -3052,8 +3082,8 @@ static void ata_dev_xfermask(struct ata_device *dev) struct ata_port *ap = dev->ap; struct ata_host_set *hs = ap->host_set; unsigned long xfer_mask; - int i; + /* controller modes available */ xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask, ap->udma_mask); @@ -3063,34 +3093,31 @@ static void ata_dev_xfermask(struct ata_device *dev) if (ap->cbl == ATA_CBL_PATA40) xfer_mask &= ~(0xF8 << ATA_SHIFT_UDMA); - /* FIXME: Use port-wide xfermask for now */ - for (i = 0; i < ATA_MAX_DEVICES; i++) { - struct ata_device *d = &ap->device[i]; - - if (ata_dev_absent(d)) - continue; - - if (ata_dev_disabled(d)) { - /* to avoid violating device selection timing */ - xfer_mask &= ata_pack_xfermask(d->pio_mask, - UINT_MAX, UINT_MAX); - continue; - } + xfer_mask &= ata_pack_xfermask(dev->pio_mask, + dev->mwdma_mask, dev->udma_mask); + xfer_mask &= ata_id_xfermask(dev->id); - xfer_mask &= ata_pack_xfermask(d->pio_mask, - d->mwdma_mask, d->udma_mask); - xfer_mask &= ata_id_xfermask(d->id); - if (ata_dma_blacklisted(d)) - xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + /* + * CFA Advanced TrueIDE timings are not allowed on a shared + * cable + */ + if (ata_dev_pair(dev)) { + /* No PIO5 or PIO6 */ + xfer_mask &= ~(0x03 << (ATA_SHIFT_PIO + 5)); + /* No MWDMA3 or MWDMA 4 */ + xfer_mask &= ~(0x03 << (ATA_SHIFT_MWDMA + 3)); } - if (ata_dma_blacklisted(dev)) + if (ata_dma_blacklisted(dev)) { + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); ata_dev_printk(dev, KERN_WARNING, "device is on DMA blacklist, disabling DMA\n"); + } - if (hs->flags & ATA_HOST_SIMPLEX) { - if (hs->simplex_claimed) - xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + if ((hs->flags & ATA_HOST_SIMPLEX) && hs->simplex_claimed) { + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + ata_dev_printk(dev, KERN_WARNING, "simplex DMA is claimed by " + "other device, disabling DMA\n"); } if (ap->ops->mode_filter) @@ -5218,41 +5245,29 @@ void ata_dev_init(struct ata_device *dev) } /** - * ata_host_init - Initialize an ata_port structure + * ata_port_init - Initialize an ata_port structure * @ap: Structure to initialize - * @host: associated SCSI mid-layer structure * @host_set: Collection of hosts to which @ap belongs * @ent: Probe information provided by low-level driver * @port_no: Port number associated with this ata_port * - * Initialize a new ata_port structure, and its associated - * scsi_host. + * Initialize a new ata_port structure. * * LOCKING: * Inherited from caller. */ -static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, - struct ata_host_set *host_set, - const struct ata_probe_ent *ent, unsigned int port_no) +void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set, + const struct ata_probe_ent *ent, unsigned int port_no) { unsigned int i; - host->max_id = 16; - host->max_lun = 1; - host->max_channel = 1; - host->unique_id = ata_unique_id++; - host->max_cmd_len = 12; - ap->lock = &host_set->lock; ap->flags = ATA_FLAG_DISABLED; - ap->id = host->unique_id; - ap->host = host; + ap->id = ata_unique_id++; ap->ctl = ATA_DEVCTL_OBS; ap->host_set = host_set; ap->dev = ent->dev; 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; @@ -5298,7 +5313,28 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, } /** - * ata_host_add - Attach low-level ATA driver to system + * ata_port_init_shost - Initialize SCSI host associated with ATA port + * @ap: ATA port to initialize SCSI host for + * @shost: SCSI host associated with @ap + * + * Initialize SCSI host @shost associated with ATA port @ap. + * + * LOCKING: + * Inherited from caller. + */ +static void ata_port_init_shost(struct ata_port *ap, struct Scsi_Host *shost) +{ + ap->host = shost; + + shost->unique_id = ap->id; + shost->max_id = 16; + shost->max_lun = 1; + shost->max_channel = 1; + shost->max_cmd_len = 12; +} + +/** + * ata_port_add - Attach low-level ATA driver to system * @ent: Information provided by low-level driver * @host_set: Collections of ports to which we add * @port_no: Port number associated with this host @@ -5311,14 +5347,12 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host, * RETURNS: * New ata_port on success, for NULL on error. */ - -static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, +static struct ata_port * ata_port_add(const struct ata_probe_ent *ent, struct ata_host_set *host_set, unsigned int port_no) { - struct Scsi_Host *host; + struct Scsi_Host *shost; struct ata_port *ap; - int rc; DPRINTK("ENTER\n"); @@ -5329,25 +5363,40 @@ static struct ata_port * ata_host_add(const struct ata_probe_ent *ent, return NULL; } - host = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); - if (!host) + shost = scsi_host_alloc(ent->sht, sizeof(struct ata_port)); + if (!shost) return NULL; - host->transportt = &ata_scsi_transport_template; + shost->transportt = &ata_scsi_transport_template; - ap = ata_shost_to_port(host); + ap = ata_shost_to_port(shost); - ata_host_init(ap, host, host_set, ent, port_no); - - rc = ap->ops->port_start(ap); - if (rc) - goto err_out; + ata_port_init(ap, host_set, ent, port_no); + ata_port_init_shost(ap, shost); return ap; +} -err_out: - scsi_host_put(host); - return NULL; +/** + * ata_sas_host_init - Initialize a host_set struct + * @host_set: host_set to initialize + * @dev: device host_set is attached to + * @flags: host_set flags + * @ops: port_ops + * + * LOCKING: + * PCI/etc. bus probe sem. + * + */ + +void ata_host_set_init(struct ata_host_set *host_set, + struct device *dev, unsigned long flags, + const struct ata_port_operations *ops) +{ + spin_lock_init(&host_set->lock); + host_set->dev = dev; + host_set->flags = flags; + host_set->ops = ops; } /** @@ -5370,7 +5419,7 @@ err_out: */ int ata_device_add(const struct ata_probe_ent *ent) { - unsigned int count = 0, i; + unsigned int i; struct device *dev = ent->dev; struct ata_host_set *host_set; int rc; @@ -5381,50 +5430,65 @@ int ata_device_add(const struct ata_probe_ent *ent) (ent->n_ports * sizeof(void *)), GFP_KERNEL); if (!host_set) return 0; - spin_lock_init(&host_set->lock); - host_set->dev = dev; + ata_host_set_init(host_set, dev, ent->host_set_flags, ent->port_ops); host_set->n_ports = ent->n_ports; host_set->irq = ent->irq; + host_set->irq2 = ent->irq2; host_set->mmio_base = ent->mmio_base; host_set->private_data = ent->private_data; - host_set->ops = ent->port_ops; - host_set->flags = ent->host_set_flags; /* register each port bound to this device */ - for (i = 0; i < ent->n_ports; i++) { + for (i = 0; i < host_set->n_ports; i++) { struct ata_port *ap; unsigned long xfer_mode_mask; + int irq_line = ent->irq; - ap = ata_host_add(ent, host_set, i); + ap = ata_port_add(ent, host_set, i); if (!ap) goto err_out; host_set->ports[i] = ap; + + /* dummy? */ + if (ent->dummy_port_mask & (1 << i)) { + ata_port_printk(ap, KERN_INFO, "DUMMY\n"); + ap->ops = &ata_dummy_port_ops; + continue; + } + + /* start port */ + rc = ap->ops->port_start(ap); + if (rc) { + host_set->ports[i] = NULL; + scsi_host_put(ap->host); + goto err_out; + } + + /* Report the secondary IRQ for second channel legacy */ + if (i == 1 && ent->irq2) + irq_line = ent->irq2; + xfer_mode_mask =(ap->udma_mask << ATA_SHIFT_UDMA) | (ap->mwdma_mask << ATA_SHIFT_MWDMA) | (ap->pio_mask << ATA_SHIFT_PIO); /* print per-port info to dmesg */ ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%lX " - "ctl 0x%lX bmdma 0x%lX irq %lu\n", + "ctl 0x%lX bmdma 0x%lX irq %d\n", ap->flags & ATA_FLAG_SATA ? 'S' : 'P', ata_mode_string(xfer_mode_mask), ap->ioaddr.cmd_addr, ap->ioaddr.ctl_addr, ap->ioaddr.bmdma_addr, - ent->irq); + irq_line); ata_chk_status(ap); host_set->ops->irq_clear(ap); ata_eh_freeze_port(ap); /* freeze port before requesting IRQ */ - count++; } - if (!count) - goto err_free_ret; - - /* obtain irq, that is shared between channels */ + /* obtain irq, that may be shared between channels */ rc = request_irq(ent->irq, ent->port_ops->irq_handler, ent->irq_flags, DRV_NAME, host_set); if (rc) { @@ -5433,15 +5497,28 @@ int ata_device_add(const struct ata_probe_ent *ent) goto err_out; } + /* do we have a second IRQ for the other channel, eg legacy mode */ + if (ent->irq2) { + /* We will get weird core code crashes later if this is true + so trap it now */ + BUG_ON(ent->irq == ent->irq2); + + rc = request_irq(ent->irq2, ent->port_ops->irq_handler, ent->irq_flags, + DRV_NAME, host_set); + if (rc) { + dev_printk(KERN_ERR, dev, "irq %lu request failed: %d\n", + ent->irq2, rc); + goto err_out_free_irq; + } + } + /* perform each probe synchronously */ DPRINTK("probe begin\n"); - for (i = 0; i < count; i++) { - struct ata_port *ap; + for (i = 0; i < host_set->n_ports; i++) { + struct ata_port *ap = host_set->ports[i]; u32 scontrol; int rc; - ap = host_set->ports[i]; - /* init sata_spd_limit to the current value */ if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) { int spd = (scontrol >> 4) & 0xf; @@ -5497,7 +5574,7 @@ int ata_device_add(const struct ata_probe_ent *ent) /* probes are done, now scan each port's disk(s) */ DPRINTK("host probe begin\n"); - for (i = 0; i < count; i++) { + for (i = 0; i < host_set->n_ports; i++) { struct ata_port *ap = host_set->ports[i]; ata_scsi_scan_host(ap); @@ -5508,15 +5585,17 @@ int ata_device_add(const struct ata_probe_ent *ent) VPRINTK("EXIT, returning %u\n", ent->n_ports); return ent->n_ports; /* success */ +err_out_free_irq: + free_irq(ent->irq, host_set); err_out: - for (i = 0; i < count; i++) { + for (i = 0; i < host_set->n_ports; i++) { struct ata_port *ap = host_set->ports[i]; if (ap) { ap->ops->port_stop(ap); scsi_host_put(ap->host); } } -err_free_ret: + kfree(host_set); VPRINTK("EXIT, returning 0\n"); return 0; @@ -5599,6 +5678,8 @@ void ata_host_set_remove(struct ata_host_set *host_set) ata_port_detach(host_set->ports[i]); free_irq(host_set->irq, host_set); + if (host_set->irq2) + free_irq(host_set->irq2, host_set); for (i = 0; i < host_set->n_ports; i++) { struct ata_port *ap = host_set->ports[i]; @@ -5608,10 +5689,11 @@ void ata_host_set_remove(struct ata_host_set *host_set) if ((ap->flags & ATA_FLAG_NO_LEGACY) == 0) { struct ata_ioports *ioaddr = &ap->ioaddr; - if (ioaddr->cmd_addr == 0x1f0) - release_region(0x1f0, 8); - else if (ioaddr->cmd_addr == 0x170) - release_region(0x170, 8); + /* FIXME: Add -ac IDE pci mods to remove these special cases */ + if (ioaddr->cmd_addr == ATA_PRIMARY_CMD) + release_region(ATA_PRIMARY_CMD, 8); + else if (ioaddr->cmd_addr == ATA_SECONDARY_CMD) + release_region(ATA_SECONDARY_CMD, 8); } scsi_host_put(ap->host); @@ -5650,6 +5732,31 @@ int ata_scsi_release(struct Scsi_Host *host) return 1; } +struct ata_probe_ent * +ata_probe_ent_alloc(struct device *dev, const struct ata_port_info *port) +{ + struct ata_probe_ent *probe_ent; + + probe_ent = kzalloc(sizeof(*probe_ent), GFP_KERNEL); + if (!probe_ent) { + printk(KERN_ERR DRV_NAME "(%s): out of memory\n", + kobject_name(&(dev->kobj))); + return NULL; + } + + INIT_LIST_HEAD(&probe_ent->node); + probe_ent->dev = dev; + + probe_ent->sht = port->sht; + probe_ent->host_flags = port->host_flags; + probe_ent->pio_mask = port->pio_mask; + probe_ent->mwdma_mask = port->mwdma_mask; + probe_ent->udma_mask = port->udma_mask; + probe_ent->port_ops = port->port_ops; + + return probe_ent; +} + /** * ata_std_ports - initialize ioaddr with standard port offsets. * @ioaddr: IO address structure to be initialized @@ -5704,11 +5811,8 @@ void ata_pci_remove_one (struct pci_dev *pdev) { struct device *dev = pci_dev_to_dev(pdev); struct ata_host_set *host_set = dev_get_drvdata(dev); - struct ata_host_set *host_set2 = host_set->next; ata_host_set_remove(host_set); - if (host_set2) - ata_host_set_remove(host_set2); pci_release_regions(pdev); pci_disable_device(pdev); @@ -5749,11 +5853,11 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits) return (tmp == bits->val) ? 1 : 0; } -void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state) +void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg) { pci_save_state(pdev); - if (state.event == PM_EVENT_SUSPEND) { + if (mesg.event == PM_EVENT_SUSPEND) { pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); } @@ -5767,24 +5871,16 @@ void ata_pci_device_do_resume(struct pci_dev *pdev) pci_set_master(pdev); } -int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state) +int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) { struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev); int rc = 0; - rc = ata_host_set_suspend(host_set, state); + rc = ata_host_set_suspend(host_set, mesg); if (rc) return rc; - if (host_set->next) { - rc = ata_host_set_suspend(host_set->next, state); - if (rc) { - ata_host_set_resume(host_set); - return rc; - } - } - - ata_pci_device_do_suspend(pdev, state); + ata_pci_device_do_suspend(pdev, mesg); return 0; } @@ -5795,9 +5891,6 @@ int ata_pci_device_resume(struct pci_dev *pdev) ata_pci_device_do_resume(pdev); ata_host_set_resume(host_set); - if (host_set->next) - ata_host_set_resume(host_set->next); - return 0; } #endif /* CONFIG_PCI */ @@ -5897,6 +5990,39 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, } /* + * Dummy port_ops + */ +static void ata_dummy_noret(struct ata_port *ap) { } +static int ata_dummy_ret0(struct ata_port *ap) { return 0; } +static void ata_dummy_qc_noret(struct ata_queued_cmd *qc) { } + +static u8 ata_dummy_check_status(struct ata_port *ap) +{ + return ATA_DRDY; +} + +static unsigned int ata_dummy_qc_issue(struct ata_queued_cmd *qc) +{ + return AC_ERR_SYSTEM; +} + +const struct ata_port_operations ata_dummy_port_ops = { + .port_disable = ata_port_disable, + .check_status = ata_dummy_check_status, + .check_altstatus = ata_dummy_check_status, + .dev_select = ata_noop_dev_select, + .qc_prep = ata_noop_qc_prep, + .qc_issue = ata_dummy_qc_issue, + .freeze = ata_dummy_noret, + .thaw = ata_dummy_noret, + .error_handler = ata_dummy_noret, + .post_internal_cmd = ata_dummy_qc_noret, + .irq_clear = ata_dummy_noret, + .port_start = ata_dummy_ret0, + .port_stop = ata_dummy_noret, +}; + +/* * libata is essentially a library of internal helper functions for * low-level ATA host controller drivers. As such, the API/ABI is * likely to change as new drivers are added and updated. @@ -5906,8 +6032,10 @@ u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, EXPORT_SYMBOL_GPL(sata_deb_timing_normal); EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug); EXPORT_SYMBOL_GPL(sata_deb_timing_long); +EXPORT_SYMBOL_GPL(ata_dummy_port_ops); EXPORT_SYMBOL_GPL(ata_std_bios_param); EXPORT_SYMBOL_GPL(ata_std_ports); +EXPORT_SYMBOL_GPL(ata_host_set_init); EXPORT_SYMBOL_GPL(ata_device_add); EXPORT_SYMBOL_GPL(ata_port_detach); EXPORT_SYMBOL_GPL(ata_host_set_remove); diff --git a/drivers/scsi/libata-eh.c b/drivers/ata/libata-eh.c index 29f59345305d..2c476eee463f 100644 --- a/drivers/scsi/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -39,7 +39,7 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> -#include "scsi_transport_api.h" +#include "../scsi/scsi_transport_api.h" #include <linux/libata.h> diff --git a/drivers/scsi/libata-scsi.c b/drivers/ata/libata-scsi.c index e92c31d698ff..d168e3413661 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -400,7 +400,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) /** * ata_scsi_device_suspend - suspend ATA device associated with sdev * @sdev: the SCSI device to suspend - * @state: target power management state + * @mesg: target power management message * * Request suspend EH action on the ATA device associated with * @sdev and wait for the operation to complete. @@ -411,7 +411,7 @@ void ata_dump_status(unsigned id, struct ata_taskfile *tf) * RETURNS: * 0 on success, -errno otherwise. */ -int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) +int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t mesg) { struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *dev = ata_scsi_find_dev(ap, sdev); @@ -438,7 +438,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) /* request suspend */ action = ATA_EH_SUSPEND; - if (state.event != PM_EVENT_SUSPEND) + if (mesg.event != PM_EVENT_SUSPEND) action |= ATA_EH_PM_FREEZE; ap->eh_info.dev_action[dev->devno] |= action; ap->eh_info.flags |= ATA_EHI_QUIET; @@ -463,7 +463,7 @@ int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state) spin_unlock_irqrestore(ap->lock, flags); out: if (rc == 0) - sdev->sdev_gendev.power.power_state = state; + sdev->sdev_gendev.power.power_state = mesg; return rc; } @@ -3171,3 +3171,152 @@ void ata_scsi_dev_rescan(void *data) scsi_rescan_device(&(dev->sdev->sdev_gendev)); } } + +/** + * ata_sas_port_alloc - Allocate port for a SAS attached SATA device + * @pdev: PCI device that the scsi device is attached to + * @port_info: Information from low-level host driver + * @host: SCSI host that the scsi device is attached to + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * ata_port pointer on success / NULL on failure. + */ + +struct ata_port *ata_sas_port_alloc(struct ata_host_set *host_set, + struct ata_port_info *port_info, + struct Scsi_Host *host) +{ + struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL); + struct ata_probe_ent *ent; + + if (!ap) + return NULL; + + ent = ata_probe_ent_alloc(host_set->dev, port_info); + if (!ent) { + kfree(ap); + return NULL; + } + + ata_port_init(ap, host_set, ent, 0); + ap->lock = host->host_lock; + kfree(ent); + return ap; +} +EXPORT_SYMBOL_GPL(ata_sas_port_alloc); + +/** + * ata_sas_port_start - Set port up for dma. + * @ap: Port to initialize + * + * Called just after data structures for each port are + * initialized. Allocates DMA pad. + * + * May be used as the port_start() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ +int ata_sas_port_start(struct ata_port *ap) +{ + return ata_pad_alloc(ap, ap->dev); +} +EXPORT_SYMBOL_GPL(ata_sas_port_start); + +/** + * ata_port_stop - Undo ata_sas_port_start() + * @ap: Port to shut down + * + * Frees the DMA pad. + * + * May be used as the port_stop() entry in ata_port_operations. + * + * LOCKING: + * Inherited from caller. + */ + +void ata_sas_port_stop(struct ata_port *ap) +{ + ata_pad_free(ap, ap->dev); +} +EXPORT_SYMBOL_GPL(ata_sas_port_stop); + +/** + * ata_sas_port_init - Initialize a SATA device + * @ap: SATA port to initialize + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +int ata_sas_port_init(struct ata_port *ap) +{ + int rc = ap->ops->port_start(ap); + + if (!rc) + rc = ata_bus_probe(ap); + + return rc; +} +EXPORT_SYMBOL_GPL(ata_sas_port_init); + +/** + * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc + * @ap: SATA port to destroy + * + */ + +void ata_sas_port_destroy(struct ata_port *ap) +{ + ap->ops->port_stop(ap); + kfree(ap); +} +EXPORT_SYMBOL_GPL(ata_sas_port_destroy); + +/** + * ata_sas_slave_configure - Default slave_config routine for libata devices + * @sdev: SCSI device to configure + * @ap: ATA port to which SCSI device is attached + * + * RETURNS: + * Zero. + */ + +int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) +{ + ata_scsi_sdev_config(sdev); + ata_scsi_dev_config(sdev, ap->device); + return 0; +} +EXPORT_SYMBOL_GPL(ata_sas_slave_configure); + +/** + * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device + * @cmd: SCSI command to be sent + * @done: Completion function, called when command is complete + * @ap: ATA port to which the command is being sent + * + * RETURNS: + * Zero. + */ + +int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap) +{ + ata_scsi_dump_cdb(ap, cmd); + + if (likely(ata_scsi_dev_enabled(ap->device))) + __ata_scsi_queuecmd(cmd, done, ap->device); + else { + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + } + return 0; +} +EXPORT_SYMBOL_GPL(ata_sas_queuecmd); diff --git a/drivers/scsi/libata.h b/drivers/ata/libata.h index c325679d9b54..d4a4f82360ec 100644 --- a/drivers/scsi/libata.h +++ b/drivers/ata/libata.h @@ -69,6 +69,10 @@ extern int ata_flush_cache(struct ata_device *dev); extern void ata_dev_init(struct ata_device *dev); extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg); extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); +extern void ata_port_init(struct ata_port *ap, struct ata_host_set *host_set, + const struct ata_probe_ent *ent, unsigned int port_no); +extern struct ata_probe_ent *ata_probe_ent_alloc(struct device *dev, + const struct ata_port_info *port); /* libata-scsi.c */ @@ -107,6 +111,7 @@ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); extern void ata_scsi_dev_rescan(void *data); +extern int ata_bus_probe(struct ata_port *ap); /* libata-eh.c */ extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); diff --git a/drivers/scsi/pdc_adma.c b/drivers/ata/pdc_adma.c index efc8fff1d250..61d2aa697b4d 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -722,7 +722,7 @@ err_out: static int __init adma_ata_init(void) { - return pci_module_init(&adma_ata_pci_driver); + return pci_register_driver(&adma_ata_pci_driver); } static void __exit adma_ata_exit(void) diff --git a/drivers/scsi/sata_mv.c b/drivers/ata/sata_mv.c index 1053c7c76b7d..a2915a56accd 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -2447,7 +2447,7 @@ err_out: static int __init mv_init(void) { - return pci_module_init(&mv_pci_driver); + return pci_register_driver(&mv_pci_driver); } static void __exit mv_exit(void) diff --git a/drivers/scsi/sata_nv.c b/drivers/ata/sata_nv.c index 56da25581f31..be46df75ab5a 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -583,7 +583,7 @@ static void nv_ck804_host_stop(struct ata_host_set *host_set) static int __init nv_init(void) { - return pci_module_init(&nv_pci_driver); + return pci_register_driver(&nv_pci_driver); } static void __exit nv_exit(void) diff --git a/drivers/scsi/sata_promise.c b/drivers/ata/sata_promise.c index 4776f4e55839..a5b3a7db7a9f 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -824,7 +824,7 @@ err_out: static int __init pdc_ata_init(void) { - return pci_module_init(&pdc_ata_pci_driver); + return pci_register_driver(&pdc_ata_pci_driver); } diff --git a/drivers/scsi/sata_promise.h b/drivers/ata/sata_promise.h index 6ee5e190262d..6ee5e190262d 100644 --- a/drivers/scsi/sata_promise.h +++ b/drivers/ata/sata_promise.h diff --git a/drivers/scsi/sata_qstor.c b/drivers/ata/sata_qstor.c index d374c1db0cf3..71bd6712b377 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -712,7 +712,7 @@ err_out: static int __init qs_ata_init(void) { - return pci_module_init(&qs_ata_pci_driver); + return pci_register_driver(&qs_ata_pci_driver); } static void __exit qs_ata_exit(void) diff --git a/drivers/scsi/sata_sil.c b/drivers/ata/sata_sil.c index d0a85073ebf7..907faa87239b 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -141,12 +141,8 @@ static const struct sil_drivelist { { "ST330013AS", SIL_QUIRK_MOD15WRITE }, { "ST340017AS", SIL_QUIRK_MOD15WRITE }, { "ST360015AS", SIL_QUIRK_MOD15WRITE }, - { "ST380013AS", SIL_QUIRK_MOD15WRITE }, { "ST380023AS", SIL_QUIRK_MOD15WRITE }, { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, - { "ST3160023AS", SIL_QUIRK_MOD15WRITE }, - { "ST3120026AS", SIL_QUIRK_MOD15WRITE }, - { "ST3200822AS", SIL_QUIRK_MOD15WRITE }, { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, @@ -714,7 +710,7 @@ static int sil_pci_device_resume(struct pci_dev *pdev) static int __init sil_init(void) { - return pci_module_init(&sil_pci_driver); + return pci_register_driver(&sil_pci_driver); } static void __exit sil_exit(void) diff --git a/drivers/scsi/sata_sil24.c b/drivers/ata/sata_sil24.c index 3f368c7d3ef9..3a0161ddc33f 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -1205,7 +1205,7 @@ static int sil24_pci_device_resume(struct pci_dev *pdev) static int __init sil24_init(void) { - return pci_module_init(&sil24_pci_driver); + return pci_register_driver(&sil24_pci_driver); } static void __exit sil24_exit(void) diff --git a/drivers/scsi/sata_sis.c b/drivers/ata/sata_sis.c index ee6b5df41d30..ac24f66897f6 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -334,7 +334,7 @@ err_out: static int __init sis_init(void) { - return pci_module_init(&sis_pci_driver); + return pci_register_driver(&sis_pci_driver); } static void __exit sis_exit(void) diff --git a/drivers/scsi/sata_svw.c b/drivers/ata/sata_svw.c index 7d0858095e1f..baf259a966d0 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -488,7 +488,7 @@ static struct pci_driver k2_sata_pci_driver = { static int __init k2_sata_init(void) { - return pci_module_init(&k2_sata_pci_driver); + return pci_register_driver(&k2_sata_pci_driver); } diff --git a/drivers/scsi/sata_sx4.c b/drivers/ata/sata_sx4.c index ccc8cad24f7d..0da83cba5c12 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -1482,7 +1482,7 @@ err_out: static int __init pdc_sata_init(void) { - return pci_module_init(&pdc_sata_pci_driver); + return pci_register_driver(&pdc_sata_pci_driver); } diff --git a/drivers/scsi/sata_uli.c b/drivers/ata/sata_uli.c index 33cdb4867ef1..654aae2b25c5 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -287,7 +287,7 @@ err_out: static int __init uli_init(void) { - return pci_module_init(&uli_pci_driver); + return pci_register_driver(&uli_pci_driver); } static void __exit uli_exit(void) diff --git a/drivers/scsi/sata_via.c b/drivers/ata/sata_via.c index 03baec2191bf..0bf1dbea6406 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/ata/sata_via.c @@ -381,7 +381,7 @@ err_out: static int __init svia_init(void) { - return pci_module_init(&svia_pci_driver); + return pci_register_driver(&svia_pci_driver); } static void __exit svia_exit(void) diff --git a/drivers/scsi/sata_vsc.c b/drivers/ata/sata_vsc.c index ad37871594f5..4c69a705a483 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -462,7 +462,7 @@ static struct pci_driver vsc_sata_pci_driver = { static int __init vsc_sata_init(void) { - return pci_module_init(&vsc_sata_pci_driver); + return pci_register_driver(&vsc_sata_pci_driver); } diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 96a81cd17617..2df4d15c9634 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -471,67 +471,6 @@ config SCSI_IN2000 source "drivers/scsi/megaraid/Kconfig.megaraid" -config SCSI_SATA - tristate "Serial ATA (SATA) support" - depends on SCSI - help - This driver family supports Serial ATA host controllers - and devices. - - If unsure, say N. - -config SCSI_SATA_AHCI - tristate "AHCI SATA support" - depends on SCSI_SATA && PCI - help - This option enables support for AHCI Serial ATA. - - If unsure, say N. - -config SCSI_SATA_SVW - tristate "ServerWorks Frodo / Apple K2 SATA support" - depends on SCSI_SATA && PCI - help - This option enables support for Broadcom/Serverworks/Apple K2 - SATA support. - - If unsure, say N. - -config SCSI_ATA_PIIX - tristate "Intel PIIX/ICH SATA support" - depends on SCSI_SATA && PCI - help - This option enables support for ICH5/6/7/8 Serial ATA. - If PATA support was enabled previously, this enables - support for select Intel PIIX/ICH PATA host controllers. - - If unsure, say N. - -config SCSI_SATA_MV - tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)" - depends on SCSI_SATA && PCI && EXPERIMENTAL - help - This option enables support for the Marvell Serial ATA family. - Currently supports 88SX[56]0[48][01] chips. - - If unsure, say N. - -config SCSI_SATA_NV - tristate "NVIDIA SATA support" - depends on SCSI_SATA && PCI && EXPERIMENTAL - help - This option enables support for NVIDIA Serial ATA. - - If unsure, say N. - -config SCSI_PDC_ADMA - tristate "Pacific Digital ADMA support" - depends on SCSI_SATA && PCI - help - This option enables support for Pacific Digital ADMA controllers - - If unsure, say N. - config SCSI_HPTIOP tristate "HighPoint RocketRAID 3xxx Controller support" depends on SCSI && PCI @@ -542,83 +481,6 @@ config SCSI_HPTIOP To compile this driver as a module, choose M here; the module will be called hptiop. If unsure, say N. -config SCSI_SATA_QSTOR - tristate "Pacific Digital SATA QStor support" - depends on SCSI_SATA && PCI - help - This option enables support for Pacific Digital Serial ATA QStor. - - If unsure, say N. - -config SCSI_SATA_PROMISE - tristate "Promise SATA TX2/TX4 support" - depends on SCSI_SATA && PCI - help - This option enables support for Promise Serial ATA TX2/TX4. - - If unsure, say N. - -config SCSI_SATA_SX4 - tristate "Promise SATA SX4 support" - depends on SCSI_SATA && PCI && EXPERIMENTAL - help - This option enables support for Promise Serial ATA SX4. - - If unsure, say N. - -config SCSI_SATA_SIL - tristate "Silicon Image SATA support" - depends on SCSI_SATA && PCI && EXPERIMENTAL - help - This option enables support for Silicon Image Serial ATA. - - If unsure, say N. - -config SCSI_SATA_SIL24 - tristate "Silicon Image 3124/3132 SATA support" - depends on SCSI_SATA && PCI && EXPERIMENTAL - help - This option enables support for Silicon Image 3124/3132 Serial ATA. - - If unsure, say N. - -config SCSI_SATA_SIS - tristate "SiS 964/180 SATA support" - depends on SCSI_SATA && PCI && EXPERIMENTAL - help - This option enables support for SiS Serial ATA 964/180. - - If unsure, say N. - -config SCSI_SATA_ULI - tristate "ULi Electronics SATA support" - depends on SCSI_SATA && PCI && EXPERIMENTAL - help - This option enables support for ULi Electronics SATA. - - If unsure, say N. - -config SCSI_SATA_VIA - tristate "VIA SATA support" - depends on SCSI_SATA && PCI - help - This option enables support for VIA Serial ATA. - - If unsure, say N. - -config SCSI_SATA_VITESSE - tristate "VITESSE VSC-7174 / INTEL 31244 SATA support" - depends on SCSI_SATA && PCI - help - This option enables support for Vitesse VSC7174 and Intel 31244 Serial ATA. - - If unsure, say N. - -config SCSI_SATA_INTEL_COMBINED - bool - depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX) - default y - config SCSI_BUSLOGIC tristate "BusLogic SCSI support" depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index ebd0cf00bf3e..b678f957cfe2 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -122,21 +122,6 @@ obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_IPR) += ipr.o obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ -obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o -obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o -obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o -obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o -obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o -obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o -obj-$(CONFIG_SCSI_SATA_SIL24) += libata.o sata_sil24.o -obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o -obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o -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 -obj-$(CONFIG_SCSI_SATA_MV) += libata.o sata_mv.o -obj-$(CONFIG_SCSI_PDC_ADMA) += libata.o pdc_adma.o obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o obj-$(CONFIG_ARM) += arm/ @@ -166,7 +151,6 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) zalon7xx-objs := zalon.o ncr53c8xx.o NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o -libata-objs := libata-core.o libata-scsi.o libata-bmdma.o libata-eh.o oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o # Files generated that shall be removed upon make clean diff --git a/include/asm-alpha/libata-portmap.h b/include/asm-alpha/libata-portmap.h new file mode 100644 index 000000000000..75484ef0c743 --- /dev/null +++ b/include/asm-alpha/libata-portmap.h @@ -0,0 +1 @@ +#include <asm-generic/libata-portmap.h> diff --git a/include/asm-generic/libata-portmap.h b/include/asm-generic/libata-portmap.h new file mode 100644 index 000000000000..9202fd02d5be --- /dev/null +++ b/include/asm-generic/libata-portmap.h @@ -0,0 +1,12 @@ +#ifndef __ASM_GENERIC_LIBATA_PORTMAP_H +#define __ASM_GENERIC_LIBATA_PORTMAP_H + +#define ATA_PRIMARY_CMD 0x1F0 +#define ATA_PRIMARY_CTL 0x3F6 +#define ATA_PRIMARY_IRQ 14 + +#define ATA_SECONDARY_CMD 0x170 +#define ATA_SECONDARY_CTL 0x376 +#define ATA_SECONDARY_IRQ 15 + +#endif diff --git a/include/asm-i386/libata-portmap.h b/include/asm-i386/libata-portmap.h new file mode 100644 index 000000000000..75484ef0c743 --- /dev/null +++ b/include/asm-i386/libata-portmap.h @@ -0,0 +1 @@ +#include <asm-generic/libata-portmap.h> diff --git a/include/asm-ia64/libata-portmap.h b/include/asm-ia64/libata-portmap.h new file mode 100644 index 000000000000..75484ef0c743 --- /dev/null +++ b/include/asm-ia64/libata-portmap.h @@ -0,0 +1 @@ +#include <asm-generic/libata-portmap.h> diff --git a/include/asm-powerpc/libata-portmap.h b/include/asm-powerpc/libata-portmap.h new file mode 100644 index 000000000000..75484ef0c743 --- /dev/null +++ b/include/asm-powerpc/libata-portmap.h @@ -0,0 +1 @@ +#include <asm-generic/libata-portmap.h> diff --git a/include/asm-sparc/libata-portmap.h b/include/asm-sparc/libata-portmap.h new file mode 100644 index 000000000000..75484ef0c743 --- /dev/null +++ b/include/asm-sparc/libata-portmap.h @@ -0,0 +1 @@ +#include <asm-generic/libata-portmap.h> diff --git a/include/asm-sparc64/libata-portmap.h b/include/asm-sparc64/libata-portmap.h new file mode 100644 index 000000000000..75484ef0c743 --- /dev/null +++ b/include/asm-sparc64/libata-portmap.h @@ -0,0 +1 @@ +#include <asm-generic/libata-portmap.h> diff --git a/include/asm-x86_64/libata-portmap.h b/include/asm-x86_64/libata-portmap.h new file mode 100644 index 000000000000..75484ef0c743 --- /dev/null +++ b/include/asm-x86_64/libata-portmap.h @@ -0,0 +1 @@ +#include <asm-generic/libata-portmap.h> diff --git a/include/linux/ata.h b/include/linux/ata.h index 3671af869696..991b858acc30 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -40,6 +40,8 @@ enum { ATA_MAX_DEVICES = 2, /* per bus/port */ ATA_MAX_PRD = 256, /* we could make these 256/256 */ ATA_SECT_SIZE = 512, + ATA_MAX_SECTORS = 256, + ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */ ATA_ID_WORDS = 256, ATA_ID_SERNO_OFS = 10, @@ -168,12 +170,16 @@ enum { XFER_UDMA_2 = 0x42, XFER_UDMA_1 = 0x41, XFER_UDMA_0 = 0x40, + XFER_MW_DMA_4 = 0x24, /* CFA only */ + XFER_MW_DMA_3 = 0x23, /* CFA only */ XFER_MW_DMA_2 = 0x22, XFER_MW_DMA_1 = 0x21, XFER_MW_DMA_0 = 0x20, XFER_SW_DMA_2 = 0x12, XFER_SW_DMA_1 = 0x11, XFER_SW_DMA_0 = 0x10, + XFER_PIO_6 = 0x0E, /* CFA only */ + XFER_PIO_5 = 0x0D, /* CFA only */ XFER_PIO_4 = 0x0C, XFER_PIO_3 = 0x0B, XFER_PIO_2 = 0x0A, @@ -272,7 +278,6 @@ struct ata_taskfile { }; #define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0) -#define ata_id_is_cfa(id) ((id)[0] == 0x848A) #define ata_id_is_sata(id) ((id)[93] == 0) #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) @@ -304,6 +309,9 @@ static inline unsigned int ata_id_major_version(const u16 *id) { unsigned int mver; + if (id[ATA_ID_MAJOR_VER] == 0xFFFF) + return 0; + for (mver = 14; mver >= 1; mver--) if (id[ATA_ID_MAJOR_VER] & (1 << mver)) break; @@ -322,6 +330,18 @@ static inline int ata_id_current_chs_valid(const u16 *id) id[56]; /* sectors in current translation */ } +static inline int ata_id_is_cfa(const u16 *id) +{ + u16 v = id[0]; + if (v == 0x848A) /* Standard CF */ + return 1; + /* Could be CF hiding as standard ATA */ + if (ata_id_major_version(id) >= 3 && id[82] != 0xFFFF && + (id[82] & ( 1 << 2))) + return 1; + return 0; +} + static inline int atapi_cdb_len(const u16 *dev_id) { u16 tmp = dev_id[0] & 0x3; diff --git a/include/linux/libata.h b/include/linux/libata.h index 66c3100c2b94..806682603ac5 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -36,6 +36,8 @@ #include <linux/workqueue.h> #include <scsi/scsi_host.h> +#include <asm/libata-portmap.h> + /* * compile-time options: to be removed as soon as all the drivers are * converted to the new debugging mechanism @@ -112,8 +114,6 @@ enum { /* tag ATA_MAX_QUEUE - 1 is reserved for internal commands */ ATA_MAX_QUEUE = 32, ATA_TAG_INTERNAL = ATA_MAX_QUEUE - 1, - ATA_MAX_SECTORS = 200, /* FIXME */ - ATA_MAX_SECTORS_LBA48 = 65535, ATA_MAX_BUS = 2, ATA_DEF_BUSY_WAIT = 10000, ATA_SHORT_PAUSE = (HZ >> 6) + 1, @@ -225,8 +225,8 @@ enum { /* encoding various smaller bitmaps into a single * unsigned int bitmap */ - ATA_BITS_PIO = 5, - ATA_BITS_MWDMA = 3, + ATA_BITS_PIO = 7, + ATA_BITS_MWDMA = 5, ATA_BITS_UDMA = 8, ATA_SHIFT_PIO = 0, @@ -350,12 +350,12 @@ struct ata_probe_ent { struct scsi_host_template *sht; struct ata_ioports port[ATA_MAX_PORTS]; unsigned int n_ports; - unsigned int hard_port_no; + unsigned int dummy_port_mask; unsigned int pio_mask; unsigned int mwdma_mask; unsigned int udma_mask; - unsigned int legacy_mode; unsigned long irq; + unsigned long irq2; unsigned int irq_flags; unsigned long host_flags; unsigned long host_set_flags; @@ -367,6 +367,7 @@ struct ata_host_set { spinlock_t lock; struct device *dev; unsigned long irq; + unsigned long irq2; void __iomem *mmio_base; unsigned int n_ports; void *private_data; @@ -374,7 +375,6 @@ struct ata_host_set { unsigned long flags; int simplex_claimed; /* Keep seperate in case we ever need to do this locked */ - struct ata_host_set *next; /* for legacy mode */ struct ata_port *ports[0]; }; @@ -505,7 +505,6 @@ struct ata_port { unsigned int pflags; /* ATA_PFLAG_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 */ @@ -649,6 +648,8 @@ extern const unsigned long sata_deb_timing_normal[]; extern const unsigned long sata_deb_timing_hotplug[]; extern const unsigned long sata_deb_timing_long[]; +extern const struct ata_port_operations ata_dummy_port_ops; + static inline const unsigned long * sata_ehc_deb_timing(struct ata_eh_context *ehc) { @@ -658,6 +659,11 @@ sata_ehc_deb_timing(struct ata_eh_context *ehc) return sata_deb_timing_normal; } +static inline int ata_port_is_dummy(struct ata_port *ap) +{ + return ap->ops == &ata_dummy_port_ops; +} + 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); @@ -676,19 +682,30 @@ extern void ata_std_ports(struct ata_ioports *ioaddr); extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, unsigned int n_ports); extern void ata_pci_remove_one (struct pci_dev *pdev); -extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state); +extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t mesg); extern void ata_pci_device_do_resume(struct pci_dev *pdev); -extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state); +extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg); extern int ata_pci_device_resume(struct pci_dev *pdev); extern int ata_pci_clear_simplex(struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); extern void ata_port_detach(struct ata_port *ap); +extern void ata_host_set_init(struct ata_host_set *, struct device *, + unsigned long, const struct ata_port_operations *); extern void ata_host_set_remove(struct ata_host_set *host_set); extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_release(struct Scsi_Host *host); +extern void ata_sas_port_destroy(struct ata_port *); +extern struct ata_port *ata_sas_port_alloc(struct ata_host_set *, + struct ata_port_info *, struct Scsi_Host *); +extern int ata_sas_port_init(struct ata_port *); +extern int ata_sas_port_start(struct ata_port *ap); +extern void ata_sas_port_stop(struct ata_port *ap); +extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *); +extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern int sata_scr_valid(struct ata_port *ap); extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val); @@ -697,7 +714,7 @@ extern int sata_scr_write_flush(struct ata_port *ap, int reg, u32 val); extern int ata_port_online(struct ata_port *ap); extern int ata_port_offline(struct ata_port *ap); extern int ata_scsi_device_resume(struct scsi_device *); -extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state); +extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg); extern int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg); extern void ata_host_set_resume(struct ata_host_set *host_set); |