diff options
| author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-03-11 20:53:05 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-03-11 20:53:05 -0800 |
| commit | a8b828f4f202557dbdc8455f525ae8a02f8b43a2 (patch) | |
| tree | 0aefcd8e597ed5e203b02fd924ac9a34d32ae312 /drivers | |
| parent | 2d0512a44c24ea3e51118158503ab24c4b872175 (diff) | |
| parent | 3f9d4e0f0e28691b42995a7e78035425632d4743 (diff) | |
Merge bk://gkernel.bkbits.net/libata-2.5
into ppc970.osdl.org:/home/torvalds/v2.5/linux
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/scsi/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/scsi/Makefile | 1 | ||||
| -rw-r--r-- | drivers/scsi/libata-core.c | 61 | ||||
| -rw-r--r-- | drivers/scsi/sata_promise.c | 26 | ||||
| -rw-r--r-- | drivers/scsi/sata_sil.c | 26 | ||||
| -rw-r--r-- | drivers/scsi/sata_svw.c | 31 | ||||
| -rw-r--r-- | drivers/scsi/sata_via.c | 38 | ||||
| -rw-r--r-- | drivers/scsi/sata_vsc.c | 392 |
8 files changed, 455 insertions, 128 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 90e6568cbaaf..9bb7e738504a 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -457,6 +457,14 @@ config SCSI_SATA_VIA If unsure, say N. +config SCSI_SATA_VITESSE + tristate "VITESSE VSC-7174 SATA support" + depends on SCSI_SATA && PCI && EXPERIMENTAL + help + This option enables support for Vitesse VSC7174 Serial ATA. + + If unsure, say N. + config SCSI_BUSLOGIC tristate "BusLogic SCSI support" depends on (PCI || ISA || MCA) && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 93ff0c8b59f3..58f92ae17bd3 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -122,6 +122,7 @@ obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o +obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index a2a17924390d..a53d7f2d2141 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -141,7 +141,7 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf) } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - outb(tf->hob_feature, ioaddr->error_addr); + outb(tf->hob_feature, ioaddr->feature_addr); outb(tf->hob_nsect, ioaddr->nsect_addr); outb(tf->hob_lbal, ioaddr->lbal_addr); outb(tf->hob_lbam, ioaddr->lbam_addr); @@ -155,7 +155,7 @@ void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf) } if (is_addr) { - outb(tf->feature, ioaddr->error_addr); + outb(tf->feature, ioaddr->feature_addr); outb(tf->nsect, ioaddr->nsect_addr); outb(tf->lbal, ioaddr->lbal_addr); outb(tf->lbam, ioaddr->lbam_addr); @@ -199,7 +199,7 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - writeb(tf->hob_feature, (void *) ioaddr->error_addr); + writeb(tf->hob_feature, (void *) ioaddr->feature_addr); writeb(tf->hob_nsect, (void *) ioaddr->nsect_addr); writeb(tf->hob_lbal, (void *) ioaddr->lbal_addr); writeb(tf->hob_lbam, (void *) ioaddr->lbam_addr); @@ -213,7 +213,7 @@ void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf) } if (is_addr) { - writeb(tf->feature, (void *) ioaddr->error_addr); + writeb(tf->feature, (void *) ioaddr->feature_addr); writeb(tf->nsect, (void *) ioaddr->nsect_addr); writeb(tf->lbal, (void *) ioaddr->lbal_addr); writeb(tf->lbam, (void *) ioaddr->lbam_addr); @@ -250,7 +250,7 @@ void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf) { DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); - outb(tf->command, ap->ioaddr.cmdstat_addr); + outb(tf->command, ap->ioaddr.command_addr); ata_pause(ap); } @@ -271,7 +271,7 @@ void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf) { DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); - writeb(tf->command, (void *) ap->ioaddr.cmdstat_addr); + writeb(tf->command, (void *) ap->ioaddr.command_addr); ata_pause(ap); } @@ -417,7 +417,7 @@ void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf) */ u8 ata_check_status_pio(struct ata_port *ap) { - return inb(ap->ioaddr.cmdstat_addr); + return inb(ap->ioaddr.status_addr); } /** @@ -433,7 +433,7 @@ u8 ata_check_status_pio(struct ata_port *ap) */ u8 ata_check_status_mmio(struct ata_port *ap) { - return readb((void *) ap->ioaddr.cmdstat_addr); + return readb((void *) ap->ioaddr.status_addr); } static const char * udma_str[] = { @@ -1346,12 +1346,6 @@ void ata_bus_reset(struct ata_port *ap) DPRINTK("ENTER, host %u, port %u\n", ap->id, ap->port_no); - /* set up device control */ - if (ap->flags & ATA_FLAG_MMIO) - writeb(ap->ctl, ioaddr->ctl_addr); - else - outb(ap->ctl, ioaddr->ctl_addr); - /* determine if device 0/1 are present */ if (ap->flags & ATA_FLAG_SATA_RESET) dev0 = 1; @@ -1372,8 +1366,14 @@ void ata_bus_reset(struct ata_port *ap) /* issue bus reset */ if (ap->flags & ATA_FLAG_SRST) rc = ata_bus_softreset(ap, devmask); - else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) + else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) { + /* set up device control */ + if (ap->flags & ATA_FLAG_MMIO) + writeb(ap->ctl, ioaddr->ctl_addr); + else + outb(ap->ctl, ioaddr->ctl_addr); rc = ata_bus_edd(ap); + } if (rc) goto err_out; @@ -1399,6 +1399,14 @@ void ata_bus_reset(struct ata_port *ap) (ap->device[1].class == ATA_DEV_NONE)) goto err_out; + if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) { + /* set up device control for ATA_FLAG_SATA_RESET */ + if (ap->flags & ATA_FLAG_MMIO) + writeb(ap->ctl, ioaddr->ctl_addr); + else + outb(ap->ctl, ioaddr->ctl_addr); + } + DPRINTK("EXIT\n"); return; @@ -1445,7 +1453,8 @@ static void ata_host_set_pio(struct ata_port *ap) if (ata_dev_present(&ap->device[i])) { ap->device[i].pio_mode = (pio == 3) ? XFER_PIO_3 : XFER_PIO_4; - ap->ops->set_piomode(ap, &ap->device[i], pio); + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, &ap->device[i], pio); } return; @@ -1509,7 +1518,9 @@ static void ata_host_set_udma(struct ata_port *ap) for (i = 0; i < ATA_MAX_DEVICES; i++) if (ata_dev_present(&ap->device[i])) { ap->device[i].udma_mode = udma_mode; - ap->ops->set_udmamode(ap, &ap->device[i], udma_mode); + if (ap->ops->set_udmamode) + ap->ops->set_udmamode(ap, &ap->device[i], + udma_mode); } return; @@ -2369,8 +2380,8 @@ static void ata_dma_complete(struct ata_port *ap, u8 host_stat, * One if interrupt was handled, zero if not (shared irq). */ -static inline unsigned int ata_host_intr (struct ata_port *ap, - struct ata_queued_cmd *qc) +inline unsigned int ata_host_intr (struct ata_port *ap, + struct ata_queued_cmd *qc) { u8 status, host_stat; unsigned int handled = 0; @@ -2728,7 +2739,7 @@ int ata_port_start (struct ata_port *ap) if (!ap->prd) return -ENOMEM; - DPRINTK("prd alloc, virt %p, dma %x\n", ap->prd, ap->prd_dma); + DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma); return 0; } @@ -3026,12 +3037,14 @@ void ata_std_ports(struct ata_ioports *ioaddr) { ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA; ioaddr->error_addr = ioaddr->cmd_addr + ATA_REG_ERR; + ioaddr->feature_addr = ioaddr->cmd_addr + ATA_REG_FEATURE; ioaddr->nsect_addr = ioaddr->cmd_addr + ATA_REG_NSECT; ioaddr->lbal_addr = ioaddr->cmd_addr + ATA_REG_LBAL; ioaddr->lbam_addr = ioaddr->cmd_addr + ATA_REG_LBAM; ioaddr->lbah_addr = ioaddr->cmd_addr + ATA_REG_LBAH; ioaddr->device_addr = ioaddr->cmd_addr + ATA_REG_DEVICE; - ioaddr->cmdstat_addr = ioaddr->cmd_addr + ATA_REG_CMD; + ioaddr->status_addr = ioaddr->cmd_addr + ATA_REG_STATUS; + ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD; } /** @@ -3153,12 +3166,14 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, if (legacy_mode) { probe_ent->port[0].cmd_addr = 0x1f0; + probe_ent->port[0].altstatus_addr = probe_ent->port[0].ctl_addr = 0x3f6; probe_ent->n_ports = 1; probe_ent->irq = 14; ata_std_ports(&probe_ent->port[0]); probe_ent2->port[0].cmd_addr = 0x170; + probe_ent2->port[0].altstatus_addr = probe_ent2->port[0].ctl_addr = 0x376; probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8; probe_ent2->n_ports = 1; @@ -3173,11 +3188,13 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, } else { probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0); ata_std_ports(&probe_ent->port[0]); + probe_ent->port[0].altstatus_addr = probe_ent->port[0].ctl_addr = pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2); ata_std_ports(&probe_ent->port[1]); + probe_ent->port[1].altstatus_addr = probe_ent->port[1].ctl_addr = pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS; probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8; @@ -3367,4 +3384,4 @@ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); EXPORT_SYMBOL_GPL(ata_scsi_error); EXPORT_SYMBOL_GPL(ata_scsi_slave_config); EXPORT_SYMBOL_GPL(ata_scsi_release); - +EXPORT_SYMBOL_GPL(ata_host_intr); diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index 47761bf50770..f61f7e6dafa1 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -146,10 +146,6 @@ struct pdc_host_priv { static u32 pdc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg); static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); -static void pdc_sata_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio); -static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma); static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void pdc_dma_start(struct ata_queued_cmd *qc); static void pdc20621_dma_start(struct ata_queued_cmd *qc); @@ -200,8 +196,6 @@ static Scsi_Host_Template pdc_sata_sht = { static struct ata_port_operations pdc_sata_ops = { .port_disable = ata_port_disable, - .set_piomode = pdc_sata_set_piomode, - .set_udmamode = pdc_sata_set_udmamode, .tf_load = pdc_tf_load_mmio, .tf_read = ata_tf_read_mmio, .check_status = ata_check_status_mmio, @@ -220,8 +214,6 @@ static struct ata_port_operations pdc_sata_ops = { static struct ata_port_operations pdc_20621_ops = { .port_disable = ata_port_disable, - .set_piomode = pdc_sata_set_piomode, - .set_udmamode = pdc_sata_set_udmamode, .tf_load = pdc_tf_load_mmio, .tf_read = ata_tf_read_mmio, .check_status = ata_check_status_mmio, @@ -378,19 +370,6 @@ static void pdc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); } -static void pdc_sata_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio) -{ - /* dummy */ -} - - -static void pdc_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma) -{ - /* dummy */ -} - enum pdc_packet_bits { PDC_PKT_READ = (1 << 2), PDC_PKT_NODATA = (1 << 3), @@ -1172,13 +1151,16 @@ static void pdc_sata_setup_port(struct ata_ioports *port, unsigned long base) { port->cmd_addr = base; port->data_addr = base; + port->feature_addr = port->error_addr = base + 0x4; port->nsect_addr = base + 0x8; port->lbal_addr = base + 0xc; port->lbam_addr = base + 0x10; port->lbah_addr = base + 0x14; port->device_addr = base + 0x18; - port->cmdstat_addr = base + 0x1c; + port->command_addr = + port->status_addr = base + 0x1c; + port->altstatus_addr = port->ctl_addr = base + 0x38; } diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 95eaaa0c2a07..c14d333d37b9 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -75,10 +75,6 @@ enum { SIL_QUIRK_UDMA5MAX = (1 << 1), }; -static void sil_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio); -static void sil_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma); static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void sil_dev_config(struct ata_port *ap, struct ata_device *dev); static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); @@ -141,8 +137,6 @@ static Scsi_Host_Template sil_sht = { static struct ata_port_operations sil_ops = { .port_disable = ata_port_disable, .dev_config = sil_dev_config, - .set_piomode = sil_set_piomode, - .set_udmamode = sil_set_udmamode, .tf_load = ata_tf_load_mmio, .tf_read = ata_tf_read_mmio, .check_status = ata_check_status_mmio, @@ -287,22 +281,6 @@ static void sil_dev_config(struct ata_port *ap, struct ata_device *dev) } } -static void sil_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio) -{ - /* We need empty implementation, the core doesn't test for NULL - * function pointer - */ -} - -static void sil_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma) -{ - /* We need empty implementation, the core doesn't test for NULL - * function pointer - */ -} - static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int printed_version; @@ -360,12 +338,14 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) base = (unsigned long) mmio_base; probe_ent->port[0].cmd_addr = base + SIL_IDE0_TF; + probe_ent->port[0].altstatus_addr = probe_ent->port[0].ctl_addr = base + SIL_IDE0_CTL; probe_ent->port[0].bmdma_addr = base + SIL_IDE0_BMDMA; probe_ent->port[0].scr_addr = base + SIL_IDE0_SCR; ata_std_ports(&probe_ent->port[0]); probe_ent->port[1].cmd_addr = base + SIL_IDE1_TF; + probe_ent->port[1].altstatus_addr = probe_ent->port[1].ctl_addr = base + SIL_IDE1_CTL; probe_ent->port[1].bmdma_addr = base + SIL_IDE1_BMDMA; probe_ent->port[1].scr_addr = base + SIL_IDE1_SCR; @@ -373,12 +353,14 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (ent->driver_data == sil_3114) { probe_ent->port[2].cmd_addr = base + SIL_IDE2_TF; + probe_ent->port[2].altstatus_addr = probe_ent->port[2].ctl_addr = base + SIL_IDE2_CTL; probe_ent->port[2].bmdma_addr = base + SIL_IDE2_BMDMA; probe_ent->port[2].scr_addr = base + SIL_IDE2_SCR; ata_std_ports(&probe_ent->port[2]); probe_ent->port[3].cmd_addr = base + SIL_IDE3_TF; + probe_ent->port[3].altstatus_addr = probe_ent->port[3].ctl_addr = base + SIL_IDE3_CTL; probe_ent->port[3].bmdma_addr = base + SIL_IDE3_BMDMA; probe_ent->port[3].scr_addr = base + SIL_IDE3_SCR; diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index 1b61d7fd4dcc..3f7e75805830 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -103,13 +103,13 @@ static void k2_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf) ata_wait_idle(ap); } if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->error_addr); + writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr); writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr); writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr); writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr); writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr); } else if (is_addr) { - writew(tf->feature, ioaddr->error_addr); + writew(tf->feature, ioaddr->feature_addr); writew(tf->nsect, ioaddr->nsect_addr); writew(tf->lbal, ioaddr->lbal_addr); writew(tf->lbam, ioaddr->lbam_addr); @@ -146,27 +146,9 @@ static void k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) static u8 k2_stat_check_status(struct ata_port *ap) { - return readl((void *) ap->ioaddr.cmdstat_addr); + return readl((void *) ap->ioaddr.status_addr); } -static void k2_sata_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio) -{ - /* We need empty implementation, the core doesn't test for NULL - * function pointer - */ -} - - -static void k2_sata_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma) -{ - /* We need empty implementation, the core doesn't test for NULL - * function pointer - */ -} - - #ifdef CONFIG_PPC_OF /* * k2_sata_proc_info @@ -239,8 +221,6 @@ static Scsi_Host_Template k2_sata_sht = { static struct ata_port_operations k2_sata_ops = { .port_disable = ata_port_disable, - .set_piomode = k2_sata_set_piomode, - .set_udmamode = k2_sata_set_udmamode, .tf_load = k2_sata_tf_load, .tf_read = k2_sata_tf_read, .check_status = k2_stat_check_status, @@ -261,13 +241,16 @@ static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base) { port->cmd_addr = base + K2_SATA_TF_CMD_OFFSET; port->data_addr = base + K2_SATA_TF_DATA_OFFSET; + port->feature_addr = port->error_addr = base + K2_SATA_TF_ERROR_OFFSET; port->nsect_addr = base + K2_SATA_TF_NSECT_OFFSET; port->lbal_addr = base + K2_SATA_TF_LBAL_OFFSET; port->lbam_addr = base + K2_SATA_TF_LBAM_OFFSET; port->lbah_addr = base + K2_SATA_TF_LBAH_OFFSET; port->device_addr = base + K2_SATA_TF_DEVICE_OFFSET; - port->cmdstat_addr = base + K2_SATA_TF_CMDSTAT_OFFSET; + port->command_addr = + port->status_addr = base + K2_SATA_TF_CMDSTAT_OFFSET; + port->altstatus_addr = port->ctl_addr = base + K2_SATA_TF_CTL_OFFSET; port->bmdma_addr = base + K2_SATA_DMA_CMD_OFFSET; port->scr_addr = base + K2_SATA_SCR_STATUS_OFFSET; diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index a6bbe9eb6ae9..9e8f25212080 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -43,10 +43,6 @@ enum { static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static void svia_sata_phy_reset(struct ata_port *ap); static void svia_port_disable(struct ata_port *ap); -static void svia_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio); -static void svia_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma); static unsigned int in_module_init = 1; @@ -83,8 +79,6 @@ static Scsi_Host_Template svia_sht = { static struct ata_port_operations svia_sata_ops = { .port_disable = svia_port_disable, - .set_piomode = svia_set_piomode, - .set_udmamode = svia_set_udmamode, .tf_load = ata_tf_load_pio, .tf_read = ata_tf_read_pio, @@ -167,38 +161,6 @@ static void svia_port_disable(struct ata_port *ap) } /** - * svia_set_piomode - - * @ap: - * @adev: - * @pio: - * - * LOCKING: - * - */ - -static void svia_set_piomode (struct ata_port *ap, struct ata_device *adev, - unsigned int pio) -{ - /* FIXME: needed? */ -} - -/** - * svia_set_udmamode - - * @ap: - * @adev: - * @udma: - * - * LOCKING: - * - */ - -static void svia_set_udmamode (struct ata_port *ap, struct ata_device *adev, - unsigned int udma) -{ - /* FIXME: needed? */ -} - -/** * svia_init_one - * @pdev: * @ent: diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c new file mode 100644 index 000000000000..31f6f7bb7d73 --- /dev/null +++ b/drivers/scsi/sata_vsc.c @@ -0,0 +1,392 @@ +/* + * sata_vsc.c - Vitesse VSC7174 4 port DPA SATA + * + * Copyright 2004 SGI + * + * Bits from Jeff Garzik, Copyright RedHat, Inc. + * + * 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 <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/blkdev.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include "scsi.h" +#include "hosts.h" +#include <linux/libata.h> + +#define DRV_NAME "sata_vsc" +#define DRV_VERSION "0.01" + +/* Interrupt register offsets (from chip base address) */ +#define VSC_SATA_INT_STAT_OFFSET 0x00 +#define VSC_SATA_INT_MASK_OFFSET 0x04 + +/* Taskfile registers offsets */ +#define VSC_SATA_TF_CMD_OFFSET 0x00 +#define VSC_SATA_TF_DATA_OFFSET 0x00 +#define VSC_SATA_TF_ERROR_OFFSET 0x04 +#define VSC_SATA_TF_FEATURE_OFFSET 0x06 +#define VSC_SATA_TF_NSECT_OFFSET 0x08 +#define VSC_SATA_TF_LBAL_OFFSET 0x0c +#define VSC_SATA_TF_LBAM_OFFSET 0x10 +#define VSC_SATA_TF_LBAH_OFFSET 0x14 +#define VSC_SATA_TF_DEVICE_OFFSET 0x18 +#define VSC_SATA_TF_STATUS_OFFSET 0x1c +#define VSC_SATA_TF_COMMAND_OFFSET 0x1d +#define VSC_SATA_TF_ALTSTATUS_OFFSET 0x28 +#define VSC_SATA_TF_CTL_OFFSET 0x29 + +/* DMA base */ +#define VSC_SATA_DMA_CMD_OFFSET 0x70 + +/* SCRs base */ +#define VSC_SATA_SCR_STATUS_OFFSET 0x100 +#define VSC_SATA_SCR_ERROR_OFFSET 0x104 +#define VSC_SATA_SCR_CONTROL_OFFSET 0x108 + +/* Port stride */ +#define VSC_SATA_PORT_OFFSET 0x200 + + +static u32 vsc_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) +{ + if (sc_reg > SCR_CONTROL) + return 0xffffffffU; + return readl((void *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} + + +static void vsc_sata_scr_write (struct ata_port *ap, unsigned int sc_reg, + u32 val) +{ + if (sc_reg > SCR_CONTROL) + return; + writel(val, (void *) ap->ioaddr.scr_addr + (sc_reg * 4)); +} + + +static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl) +{ + unsigned long mask_addr; + u8 mask; + + mask_addr = (unsigned long) ap->host_set->mmio_base + + VSC_SATA_INT_MASK_OFFSET + ap->port_no; + mask = readb(mask_addr); + if (ctl & ATA_NIEN) + mask |= 0x80; + else + mask &= 0x7F; + writeb(mask, mask_addr); +} + + +static void vsc_sata_tf_load(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; + + /* + * The only thing the ctl register is used for is SRST. + * That is not enabled or disabled via tf_load. + * However, if ATA_NIEN is changed, then we need to change the interrupt register. + */ + if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) { + ap->last_ctl = tf->ctl; + vsc_intr_mask_update(ap, tf->ctl & ATA_NIEN); + } + if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { + writew(tf->feature | (((u16)tf->hob_feature) << 8), ioaddr->feature_addr); + writew(tf->nsect | (((u16)tf->hob_nsect) << 8), ioaddr->nsect_addr); + writew(tf->lbal | (((u16)tf->hob_lbal) << 8), ioaddr->lbal_addr); + writew(tf->lbam | (((u16)tf->hob_lbam) << 8), ioaddr->lbam_addr); + writew(tf->lbah | (((u16)tf->hob_lbah) << 8), ioaddr->lbah_addr); + } else if (is_addr) { + writew(tf->feature, ioaddr->feature_addr); + writew(tf->nsect, ioaddr->nsect_addr); + writew(tf->lbal, ioaddr->lbal_addr); + writew(tf->lbam, ioaddr->lbam_addr); + writew(tf->lbah, ioaddr->lbah_addr); + } + + if (tf->flags & ATA_TFLAG_DEVICE) + writeb(tf->device, ioaddr->device_addr); + + ata_wait_idle(ap); +} + + +static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct ata_ioports *ioaddr = &ap->ioaddr; + u16 nsect, lbal, lbam, lbah; + + nsect = tf->nsect = readw(ioaddr->nsect_addr); + lbal = tf->lbal = readw(ioaddr->lbal_addr); + lbam = tf->lbam = readw(ioaddr->lbam_addr); + lbah = tf->lbah = readw(ioaddr->lbah_addr); + tf->device = readw(ioaddr->device_addr); + + if (tf->flags & ATA_TFLAG_LBA48) { + tf->hob_feature = readb(ioaddr->error_addr); + tf->hob_nsect = nsect >> 8; + tf->hob_lbal = lbal >> 8; + tf->hob_lbam = lbam >> 8; + tf->hob_lbah = lbah >> 8; + } +} + + +/* + * vsc_sata_interrupt + * + * Read the interrupt register and process for the devices that have them pending. + */ +irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, struct pt_regs *regs) +{ + struct ata_host_set *host_set = dev_instance; + unsigned int i; + unsigned int handled = 0; + u32 int_status; + + spin_lock(&host_set->lock); + + int_status = readl(host_set->mmio_base + VSC_SATA_INT_STAT_OFFSET); + + for (i = 0; i < host_set->n_ports; i++) { + if (int_status & ((u32) 0xFF << (8 * i))) { + struct ata_port *ap; + + ap = host_set->ports[i]; + if (ap && (!(ap->flags & ATA_FLAG_PORT_DISABLED))) { + struct ata_queued_cmd *qc; + + qc = ata_qc_from_tag(ap, ap->active_tag); + if (qc && ((qc->flags & ATA_QCFLAG_POLL) == 0)) + handled += ata_host_intr(ap, qc); + } + } + } + + spin_unlock(&host_set->lock); + + return IRQ_RETVAL(handled); +} + + +static Scsi_Host_Template vsc_sata_sht = { + .module = THIS_MODULE, + .name = DRV_NAME, + .queuecommand = ata_scsi_queuecmd, + .eh_strategy_handler = ata_scsi_error, + .can_queue = ATA_DEF_QUEUE, + .this_id = ATA_SHT_THIS_ID, + .sg_tablesize = LIBATA_MAX_PRD, + .max_sectors = ATA_MAX_SECTORS, + .cmd_per_lun = ATA_SHT_CMD_PER_LUN, + .emulated = ATA_SHT_EMULATED, + .use_clustering = ATA_SHT_USE_CLUSTERING, + .proc_name = DRV_NAME, + .dma_boundary = ATA_DMA_BOUNDARY, + .slave_configure = ata_scsi_slave_config, + .bios_param = ata_std_bios_param, +}; + + +static struct ata_port_operations vsc_sata_ops = { + .port_disable = ata_port_disable, + .tf_load = vsc_sata_tf_load, + .tf_read = vsc_sata_tf_read, + .exec_command = ata_exec_command_mmio, + .check_status = ata_check_status_mmio, + .phy_reset = sata_phy_reset, + .phy_config = pata_phy_config, /* not a typo */ + .bmdma_start = ata_bmdma_start_mmio, + .fill_sg = ata_fill_sg, + .eng_timeout = ata_eng_timeout, + .irq_handler = vsc_sata_interrupt, + .scr_read = vsc_sata_scr_read, + .scr_write = vsc_sata_scr_write, + .port_start = ata_port_start, + .port_stop = ata_port_stop, +}; + +static void vsc_sata_setup_port(struct ata_ioports *port, unsigned long base) +{ + port->cmd_addr = base + VSC_SATA_TF_CMD_OFFSET; + port->data_addr = base + VSC_SATA_TF_DATA_OFFSET; + port->error_addr = base + VSC_SATA_TF_ERROR_OFFSET; + port->feature_addr = base + VSC_SATA_TF_FEATURE_OFFSET; + port->nsect_addr = base + VSC_SATA_TF_NSECT_OFFSET; + port->lbal_addr = base + VSC_SATA_TF_LBAL_OFFSET; + port->lbam_addr = base + VSC_SATA_TF_LBAM_OFFSET; + port->lbah_addr = base + VSC_SATA_TF_LBAH_OFFSET; + port->device_addr = base + VSC_SATA_TF_DEVICE_OFFSET; + port->status_addr = base + VSC_SATA_TF_STATUS_OFFSET; + port->command_addr = base + VSC_SATA_TF_COMMAND_OFFSET; + port->altstatus_addr = base + VSC_SATA_TF_ALTSTATUS_OFFSET; + port->ctl_addr = base + VSC_SATA_TF_CTL_OFFSET; + port->bmdma_addr = base + VSC_SATA_DMA_CMD_OFFSET; + port->scr_addr = base + VSC_SATA_SCR_STATUS_OFFSET; +} + + +static int vsc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) +{ + static int printed_version; + struct ata_probe_ent *probe_ent = NULL; + unsigned long base; + void *mmio_base; + int rc; + + if (!printed_version++) + printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n"); + + rc = pci_enable_device(pdev); + if (rc) + return rc; + + /* + * Check if we have needed resource mapped. + */ + if (pci_resource_len(pdev, 0) == 0) { + rc = -ENODEV; + goto err_out; + } + + rc = pci_request_regions(pdev, DRV_NAME); + if (rc) + goto err_out; + + /* + * Use 32 bit DMA mask, because 64 bit address support is poor. + */ + rc = pci_set_dma_mask(pdev, 0xFFFFFFFF); + if (rc) + goto err_out_regions; + rc = pci_set_consistent_dma_mask(pdev, 0xFFFFFFFF); + if (rc) + goto err_out_regions; + + probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); + if (probe_ent == NULL) { + rc = -ENOMEM; + goto err_out_regions; + } + memset(probe_ent, 0, sizeof(*probe_ent)); + probe_ent->pdev = pdev; + INIT_LIST_HEAD(&probe_ent->node); + + mmio_base = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + if (mmio_base == NULL) { + rc = -ENOMEM; + goto err_out_free_ent; + } + base = (unsigned long) mmio_base; + + /* + * Due to a bug in the chip, the default cache line size can't be used + */ + pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80); + + probe_ent->sht = &vsc_sata_sht; + probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_SATA_RESET; + probe_ent->port_ops = &vsc_sata_ops; + probe_ent->n_ports = 4; + probe_ent->irq = pdev->irq; + probe_ent->irq_flags = SA_SHIRQ; + probe_ent->mmio_base = mmio_base; + + /* We don't care much about the PIO/UDMA masks, but the core won't like us + * if we don't fill these + */ + probe_ent->pio_mask = 0x1f; + probe_ent->udma_mask = 0x3f; + + /* We have 4 ports per PCI function */ + vsc_sata_setup_port(&probe_ent->port[0], base + 1 * VSC_SATA_PORT_OFFSET); + vsc_sata_setup_port(&probe_ent->port[1], base + 2 * VSC_SATA_PORT_OFFSET); + vsc_sata_setup_port(&probe_ent->port[2], base + 3 * VSC_SATA_PORT_OFFSET); + vsc_sata_setup_port(&probe_ent->port[3], base + 4 * VSC_SATA_PORT_OFFSET); + + pci_set_master(pdev); + + /* FIXME: check ata_device_add return value */ + ata_device_add(probe_ent); + kfree(probe_ent); + + return 0; + +err_out_free_ent: + kfree(probe_ent); +err_out_regions: + pci_release_regions(pdev); +err_out: + pci_disable_device(pdev); + return rc; +} + + +static struct pci_device_id vsc_sata_pci_tbl[] = { + { 0x1725, 0x7174, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, + { 0x8086, 0x3200, PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 }, + { } +}; + + +static struct pci_driver vsc_sata_pci_driver = { + .name = DRV_NAME, + .id_table = vsc_sata_pci_tbl, + .probe = vsc_sata_init_one, + .remove = ata_pci_remove_one, +}; + + +static int __init vsc_sata_init(void) +{ + int rc; + + rc = pci_module_init(&vsc_sata_pci_driver); + if (rc) + return rc; + + return 0; +} + + +static void __exit vsc_sata_exit(void) +{ + pci_unregister_driver(&vsc_sata_pci_driver); +} + + +MODULE_AUTHOR("Jeremy Higdon"); +MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl); + +module_init(vsc_sata_init); +module_exit(vsc_sata_exit); |
