diff options
author | Jeff Garzik <jeff@garzik.org> | 2006-08-10 07:31:37 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-10 07:31:37 -0400 |
commit | c6fd280766a050b13360d7c2d59a3d6bd3a27d9a (patch) | |
tree | fdbeab639bc3dec29267bbf4b32cff7c8dd03593 /drivers/scsi/sata_svw.c | |
parent | 79ed35a9f139ad2b2653dfdd5f45a8f1453e2cbb (diff) |
Move libata to drivers/ata.
Diffstat (limited to 'drivers/scsi/sata_svw.c')
-rw-r--r-- | drivers/scsi/sata_svw.c | 508 |
1 files changed, 0 insertions, 508 deletions
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c deleted file mode 100644 index baf259a966d0..000000000000 --- a/drivers/scsi/sata_svw.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * sata_svw.c - ServerWorks / Apple K2 SATA - * - * Maintained by: Benjamin Herrenschmidt <benh@kernel.crashing.org> and - * Jeff Garzik <jgarzik@pobox.com> - * Please ALWAYS copy linux-ide@vger.kernel.org - * on emails. - * - * Copyright 2003 Benjamin Herrenschmidt <benh@kernel.crashing.org> - * - * Bits from Jeff Garzik, Copyright RedHat, Inc. - * - * This driver probably works with non-Apple versions of the - * Broadcom chipset... - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * libata documentation is available via 'make {ps|pdf}docs', - * as Documentation/DocBook/libata.* - * - * Hardware documentation available under NDA. - * - */ - -#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 <linux/device.h> -#include <scsi/scsi_host.h> -#include <linux/libata.h> - -#ifdef CONFIG_PPC_OF -#include <asm/prom.h> -#include <asm/pci-bridge.h> -#endif /* CONFIG_PPC_OF */ - -#define DRV_NAME "sata_svw" -#define DRV_VERSION "2.0" - -enum { - /* Taskfile registers offsets */ - K2_SATA_TF_CMD_OFFSET = 0x00, - K2_SATA_TF_DATA_OFFSET = 0x00, - K2_SATA_TF_ERROR_OFFSET = 0x04, - K2_SATA_TF_NSECT_OFFSET = 0x08, - K2_SATA_TF_LBAL_OFFSET = 0x0c, - K2_SATA_TF_LBAM_OFFSET = 0x10, - K2_SATA_TF_LBAH_OFFSET = 0x14, - K2_SATA_TF_DEVICE_OFFSET = 0x18, - K2_SATA_TF_CMDSTAT_OFFSET = 0x1c, - K2_SATA_TF_CTL_OFFSET = 0x20, - - /* DMA base */ - K2_SATA_DMA_CMD_OFFSET = 0x30, - - /* SCRs base */ - K2_SATA_SCR_STATUS_OFFSET = 0x40, - K2_SATA_SCR_ERROR_OFFSET = 0x44, - K2_SATA_SCR_CONTROL_OFFSET = 0x48, - - /* Others */ - K2_SATA_SICR1_OFFSET = 0x80, - K2_SATA_SICR2_OFFSET = 0x84, - K2_SATA_SIM_OFFSET = 0x88, - - /* Port stride */ - K2_SATA_PORT_OFFSET = 0x100, -}; - -static u8 k2_stat_check_status(struct ata_port *ap); - - -static u32 k2_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 k2_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 k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) -{ - struct ata_ioports *ioaddr = &ap->ioaddr; - unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - - if (tf->ctl != ap->last_ctl) { - writeb(tf->ctl, ioaddr->ctl_addr); - ap->last_ctl = tf->ctl; - ata_wait_idle(ap); - } - 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 k2_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) -{ - struct ata_ioports *ioaddr = &ap->ioaddr; - u16 nsect, lbal, lbam, lbah, feature; - - tf->command = k2_stat_check_status(ap); - tf->device = readw(ioaddr->device_addr); - feature = readw(ioaddr->error_addr); - nsect = readw(ioaddr->nsect_addr); - lbal = readw(ioaddr->lbal_addr); - lbam = readw(ioaddr->lbam_addr); - lbah = readw(ioaddr->lbah_addr); - - tf->feature = feature; - tf->nsect = nsect; - tf->lbal = lbal; - tf->lbam = lbam; - tf->lbah = lbah; - - if (tf->flags & ATA_TFLAG_LBA48) { - tf->hob_feature = feature >> 8; - tf->hob_nsect = nsect >> 8; - tf->hob_lbal = lbal >> 8; - tf->hob_lbam = lbam >> 8; - tf->hob_lbah = lbah >> 8; - } -} - -/** - * k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO) - * @qc: Info associated with this ATA transaction. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); - u8 dmactl; - void *mmio = (void *) ap->ioaddr.bmdma_addr; - /* load PRD table addr. */ - mb(); /* make sure PRD table writes are visible to controller */ - writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS); - - /* specify data direction, triple-check start bit is clear */ - dmactl = readb(mmio + ATA_DMA_CMD); - dmactl &= ~(ATA_DMA_WR | ATA_DMA_START); - if (!rw) - dmactl |= ATA_DMA_WR; - writeb(dmactl, mmio + ATA_DMA_CMD); - - /* issue r/w command if this is not a ATA DMA command*/ - if (qc->tf.protocol != ATA_PROT_DMA) - ap->ops->exec_command(ap, &qc->tf); -} - -/** - * k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO) - * @qc: Info associated with this ATA transaction. - * - * LOCKING: - * spin_lock_irqsave(host_set lock) - */ - -static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc) -{ - struct ata_port *ap = qc->ap; - void *mmio = (void *) ap->ioaddr.bmdma_addr; - u8 dmactl; - - /* start host DMA transaction */ - dmactl = readb(mmio + ATA_DMA_CMD); - writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD); - /* There is a race condition in certain SATA controllers that can - be seen when the r/w command is given to the controller before the - host DMA is started. On a Read command, the controller would initiate - the command to the drive even before it sees the DMA start. When there - are very fast drives connected to the controller, or when the data request - hits in the drive cache, there is the possibility that the drive returns a part - or all of the requested data to the controller before the DMA start is issued. - In this case, the controller would become confused as to what to do with the data. - In the worst case when all the data is returned back to the controller, the - controller could hang. In other cases it could return partial data returning - in data corruption. This problem has been seen in PPC systems and can also appear - on an system with very fast disks, where the SATA controller is sitting behind a - number of bridges, and hence there is significant latency between the r/w command - and the start command. */ - /* issue r/w command if the access is to ATA*/ - if (qc->tf.protocol == ATA_PROT_DMA) - ap->ops->exec_command(ap, &qc->tf); -} - - -static u8 k2_stat_check_status(struct ata_port *ap) -{ - return readl((void *) ap->ioaddr.status_addr); -} - -#ifdef CONFIG_PPC_OF -/* - * k2_sata_proc_info - * inout : decides on the direction of the dataflow and the meaning of the - * variables - * buffer: If inout==FALSE data is being written to it else read from it - * *start: If inout==FALSE start of the valid data in the buffer - * offset: If inout==FALSE offset from the beginning of the imaginary file - * from which we start writing into the buffer - * length: If inout==FALSE max number of bytes to be written into the buffer - * else number of bytes in the buffer - */ -static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, - off_t offset, int count, int inout) -{ - struct ata_port *ap; - struct device_node *np; - int len, index; - - /* Find the ata_port */ - ap = ata_shost_to_port(shost); - if (ap == NULL) - return 0; - - /* Find the OF node for the PCI device proper */ - np = pci_device_to_OF_node(to_pci_dev(ap->host_set->dev)); - if (np == NULL) - return 0; - - /* Match it to a port node */ - index = (ap == ap->host_set->ports[0]) ? 0 : 1; - for (np = np->child; np != NULL; np = np->sibling) { - u32 *reg = (u32 *)get_property(np, "reg", NULL); - if (!reg) - continue; - if (index == *reg) - break; - } - if (np == NULL) - return 0; - - len = sprintf(page, "devspec: %s\n", np->full_name); - - return len; -} -#endif /* CONFIG_PPC_OF */ - - -static struct scsi_host_template k2_sata_sht = { - .module = THIS_MODULE, - .name = DRV_NAME, - .ioctl = ata_scsi_ioctl, - .queuecommand = ata_scsi_queuecmd, - .can_queue = ATA_DEF_QUEUE, - .this_id = ATA_SHT_THIS_ID, - .sg_tablesize = LIBATA_MAX_PRD, - .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, - .slave_destroy = ata_scsi_slave_destroy, -#ifdef CONFIG_PPC_OF - .proc_info = k2_sata_proc_info, -#endif - .bios_param = ata_std_bios_param, -}; - - -static const struct ata_port_operations k2_sata_ops = { - .port_disable = ata_port_disable, - .tf_load = k2_sata_tf_load, - .tf_read = k2_sata_tf_read, - .check_status = k2_stat_check_status, - .exec_command = ata_exec_command, - .dev_select = ata_std_dev_select, - .bmdma_setup = k2_bmdma_setup_mmio, - .bmdma_start = k2_bmdma_start_mmio, - .bmdma_stop = ata_bmdma_stop, - .bmdma_status = ata_bmdma_status, - .qc_prep = ata_qc_prep, - .qc_issue = ata_qc_issue_prot, - .data_xfer = ata_mmio_data_xfer, - .freeze = ata_bmdma_freeze, - .thaw = ata_bmdma_thaw, - .error_handler = ata_bmdma_error_handler, - .post_internal_cmd = ata_bmdma_post_internal_cmd, - .irq_handler = ata_interrupt, - .irq_clear = ata_bmdma_irq_clear, - .scr_read = k2_sata_scr_read, - .scr_write = k2_sata_scr_write, - .port_start = ata_port_start, - .port_stop = ata_port_stop, - .host_stop = ata_pci_host_stop, -}; - -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->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; -} - - -static int k2_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 __iomem *mmio_base; - int pci_dev_busy = 0; - int rc; - int i; - - if (!printed_version++) - dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); - - /* - * If this driver happens to only be useful on Apple's K2, then - * we should check that here as it has a normal Serverworks ID - */ - rc = pci_enable_device(pdev); - if (rc) - return rc; - /* - * Check if we have resources mapped at all (second function may - * have been disabled by firmware) - */ - if (pci_resource_len(pdev, 5) == 0) - return -ENODEV; - - /* Request PCI regions */ - rc = pci_request_regions(pdev, DRV_NAME); - if (rc) { - pci_dev_busy = 1; - goto err_out; - } - - rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); - if (rc) - goto err_out_regions; - rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); - 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->dev = pci_dev_to_dev(pdev); - INIT_LIST_HEAD(&probe_ent->node); - - mmio_base = pci_iomap(pdev, 5, 0); - if (mmio_base == NULL) { - rc = -ENOMEM; - goto err_out_free_ent; - } - base = (unsigned long) mmio_base; - - /* Clear a magic bit in SCR1 according to Darwin, those help - * some funky seagate drives (though so far, those were already - * set by the firmware on the machines I had access to) - */ - writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000, - mmio_base + K2_SATA_SICR1_OFFSET); - - /* Clear SATA error & interrupts we don't use */ - writel(0xffffffff, mmio_base + K2_SATA_SCR_ERROR_OFFSET); - writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); - - probe_ent->sht = &k2_sata_sht; - probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO; - probe_ent->port_ops = &k2_sata_ops; - probe_ent->n_ports = 4; - probe_ent->irq = pdev->irq; - probe_ent->irq_flags = IRQF_SHARED; - 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->mwdma_mask = 0x7; - probe_ent->udma_mask = 0x7f; - - /* different controllers have different number of ports - currently 4 or 8 */ - /* All ports are on the same function. Multi-function device is no - * longer available. This should not be seen in any system. */ - for (i = 0; i < ent->driver_data; i++) - k2_sata_setup_port(&probe_ent->port[i], base + i * K2_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: - if (!pci_dev_busy) - pci_disable_device(pdev); - return rc; -} - -/* 0x240 is device ID for Apple K2 device - * 0x241 is device ID for Serverworks Frodo4 - * 0x242 is device ID for Serverworks Frodo8 - * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA - * controller - * */ -static const struct pci_device_id k2_sata_pci_tbl[] = { - { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 }, - { 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { 0x1166, 0x024b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, - { } -}; - - -static struct pci_driver k2_sata_pci_driver = { - .name = DRV_NAME, - .id_table = k2_sata_pci_tbl, - .probe = k2_sata_init_one, - .remove = ata_pci_remove_one, -}; - - -static int __init k2_sata_init(void) -{ - return pci_register_driver(&k2_sata_pci_driver); -} - - -static void __exit k2_sata_exit(void) -{ - pci_unregister_driver(&k2_sata_pci_driver); -} - - -MODULE_AUTHOR("Benjamin Herrenschmidt"); -MODULE_DESCRIPTION("low-level driver for K2 SATA controller"); -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, k2_sata_pci_tbl); -MODULE_VERSION(DRV_VERSION); - -module_init(k2_sata_init); -module_exit(k2_sata_exit); |