sata_sil.c revision 98ac62defe529d04a192688f40d801a2d8fbcf98
120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/* 220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * sata_sil.c - Silicon Image SATA 320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 48b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik * Maintained by: Jeff Garzik <jgarzik@pobox.com> 520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Please ALWAYS copy linux-ide@vger.kernel.org 620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * on emails. 720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Copyright 2003-2005 Red Hat, Inc. 920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Copyright 2003 Benjamin Herrenschmidt 1020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 1120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 1220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is free software; you can redistribute it and/or modify 1320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * it under the terms of the GNU General Public License as published by 1420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * the Free Software Foundation; either version 2, or (at your option) 1520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * any later version. 1620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 1720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * This program is distributed in the hope that it will be useful, 1820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * but WITHOUT ANY WARRANTY; without even the implied warranty of 1920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * GNU General Public License for more details. 2120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 2220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * You should have received a copy of the GNU General Public License 2320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * along with this program; see the file COPYING. If not, write to 2420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 2520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 2620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 2720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * libata documentation is available via 'make {ps|pdf}docs', 2820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * as Documentation/DocBook/libata.* 2920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 3020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Documentation for SiI 3112: 3120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 32a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik * 3320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Other errata and documentation available under NDA. 34193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik * 3520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ */ 3620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 3720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/kernel.h> 3820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/module.h> 397e6c1208598004a80b1c1fca4953eb9f2a6aa8bcBrett Russ#include <linux/pci.h> 4020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/init.h> 4120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/blkdev.h> 4220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/delay.h> 4320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/interrupt.h> 4420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/device.h> 4520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <scsi/scsi_host.h> 4620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#include <linux/libata.h> 4720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 4820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_NAME "sata_sil" 4920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ#define DRV_VERSION "0.9" 5020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 5120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russenum { 5220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_FLAG_MOD15WRITE = (1 << 30), 53bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik 54bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik sil_3112 = 0, 5520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ sil_3112_m15w = 1, 5620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ sil_3114 = 2, 5720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 5820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_FIFO_R0 = 0x40, 5920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_FIFO_W0 = 0x41, 6020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_FIFO_R1 = 0x44, 6131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_FIFO_W1 = 0x45, 6220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_FIFO_R2 = 0x240, 6331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_FIFO_W2 = 0x241, 6431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_FIFO_R3 = 0x244, 6531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_FIFO_W3 = 0x245, 6631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 6731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_SYSCFG = 0x48, 6831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_MASK_IDE0_INT = (1 << 22), 6931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_MASK_IDE1_INT = (1 << 23), 7031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_MASK_IDE2_INT = (1 << 24), 7131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_MASK_IDE3_INT = (1 << 25), 7231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_MASK_2PORT = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT, 7331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_MASK_4PORT = SIL_MASK_2PORT | 7431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, 7531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 7631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_IDE2_BMDMA = 0x200, 7720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 7820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_INTR_STEERING = (1 << 1), 7920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_QUIRK_MOD15WRITE = (1 << 0), 8031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ SIL_QUIRK_UDMA5MAX = (1 << 1), 8120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 8220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 8320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); 8420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void sil_dev_config(struct ata_port *ap, struct ata_device *dev); 8520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg); 8631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); 8731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void sil_post_set_mode (struct ata_port *ap); 8847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 8920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 9020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic const struct pci_device_id sil_pci_tbl[] = { 9120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, 9247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik { 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, 9347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik { 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 }, 9447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik { 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 }, 9520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, 9631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, 9731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w }, 9831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { } /* terminate list */ 9931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ}; 10031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 10131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 10231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ/* TODO firmware versions should be added - eric */ 10331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic const struct sil_drivelist { 10431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ const char * product; 10531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned int quirk; 10620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} sil_blacklist [] = { 10720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST320012AS", SIL_QUIRK_MOD15WRITE }, 10831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { "ST330013AS", SIL_QUIRK_MOD15WRITE }, 10931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { "ST340017AS", SIL_QUIRK_MOD15WRITE }, 11020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST360015AS", SIL_QUIRK_MOD15WRITE }, 11120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST380013AS", SIL_QUIRK_MOD15WRITE }, 11220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST380023AS", SIL_QUIRK_MOD15WRITE }, 11320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, 11420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST3160023AS", SIL_QUIRK_MOD15WRITE }, 11520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST3120026AS", SIL_QUIRK_MOD15WRITE }, 11620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST3200822AS", SIL_QUIRK_MOD15WRITE }, 11720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, 11820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, 11920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, 12020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, 12120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, 12220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, 12320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { } 12420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 12520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 12620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic struct pci_driver sil_pci_driver = { 12720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 12820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .id_table = sil_pci_tbl, 12920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .probe = sil_init_one, 13020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .remove = ata_pci_remove_one, 13120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 13220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 1338b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzikstatic struct scsi_host_template sil_sht = { 13420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .module = THIS_MODULE, 13520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .name = DRV_NAME, 13620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .ioctl = ata_scsi_ioctl, 13720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .queuecommand = ata_scsi_queuecmd, 13820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .eh_strategy_handler = ata_scsi_error, 13920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .can_queue = ATA_DEF_QUEUE, 14020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .this_id = ATA_SHT_THIS_ID, 14131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .sg_tablesize = LIBATA_MAX_PRD, 14220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .max_sectors = ATA_MAX_SECTORS, 14320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .cmd_per_lun = ATA_SHT_CMD_PER_LUN, 14420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .emulated = ATA_SHT_EMULATED, 14520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .use_clustering = ATA_SHT_USE_CLUSTERING, 14631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .proc_name = DRV_NAME, 14731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .dma_boundary = ATA_DMA_BOUNDARY, 14820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .slave_configure = ata_scsi_slave_config, 14920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .bios_param = ata_std_bios_param, 15020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .ordered_flush = 1, 15120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 15247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 153bca1c4eb9411533d613123618c0d127fae532595Jeff Garzikstatic const struct ata_port_operations sil_ops = { 154bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik .port_disable = ata_port_disable, 155bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik .dev_config = sil_dev_config, 156bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik .tf_load = ata_tf_load, 157bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik .tf_read = ata_tf_read, 15820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .check_status = ata_check_status, 15920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .exec_command = ata_exec_command, 16020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .dev_select = ata_std_dev_select, 16131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .phy_reset = sata_phy_reset, 16231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .post_set_mode = sil_post_set_mode, 16331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .bmdma_setup = ata_bmdma_setup, 16431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .bmdma_start = ata_bmdma_start, 16531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .bmdma_stop = ata_bmdma_stop, 16620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .bmdma_status = ata_bmdma_status, 16720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .qc_prep = ata_qc_prep, 16820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .qc_issue = ata_qc_issue_prot, 16920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .eng_timeout = ata_eng_timeout, 17020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .irq_handler = ata_interrupt, 17120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .irq_clear = ata_bmdma_irq_clear, 17220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_read = sil_scr_read, 17320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .scr_write = sil_scr_write, 17420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .port_start = ata_port_start, 17520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .port_stop = ata_port_stop, 17620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .host_stop = ata_pci_host_stop, 17720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 17820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 17920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic const struct ata_port_info sil_port_info[] = { 18020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* sil_3112 */ 18120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { 18220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .sht = &sil_sht, 18320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 18420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ATA_FLAG_SRST | ATA_FLAG_MMIO, 18520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 18620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .mwdma_mask = 0x07, /* mwdma0-2 */ 1878b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik .udma_mask = 0x3f, /* udma0-5 */ 18820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .port_ops = &sil_ops, 18920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, /* sil_3112_15w - keep it sync'd w/ sil_3112 */ 1908b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik { 19120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .sht = &sil_sht, 1928b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 19320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ATA_FLAG_SRST | ATA_FLAG_MMIO | 19420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ SIL_FLAG_MOD15WRITE, 19531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 19631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .mwdma_mask = 0x07, /* mwdma0-2 */ 19731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .udma_mask = 0x3f, /* udma0-5 */ 19831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .port_ops = &sil_ops, 19931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ }, /* sil_3114 */ 20031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { 20131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .sht = &sil_sht, 20231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 20331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ ATA_FLAG_SRST | ATA_FLAG_MMIO, 20431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .pio_mask = 0x1f, /* pio0-4 */ 20531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ .mwdma_mask = 0x07, /* mwdma0-2 */ 20620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .udma_mask = 0x3f, /* udma0-5 */ 20720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ .port_ops = &sil_ops, 20820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ }, 20920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ}; 21020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 211bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik/* per-port register offsets */ 212bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik/* TODO: we can probably calculate rather than use a table */ 21331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic const struct { 21431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned long tf; /* ATA taskfile register block */ 21547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik unsigned long ctl; /* ATA control/altstatus register block */ 21647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik unsigned long bmdma; /* DMA register block */ 21747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik unsigned long scr; /* SATA control register block */ 21847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik unsigned long sien; /* SATA Interrupt Enable register */ 21947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik unsigned long xfer_mode;/* data transfer mode register */ 22020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} sil_port[] = { 22131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* port 0 ... */ 22231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4 }, 22331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4 }, 22420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4 }, 22520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4 }, 226bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik /* ... port 3 */ 227bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik}; 228095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 229095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff GarzikMODULE_AUTHOR("Jeff Garzik"); 230095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff GarzikMODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller"); 231095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff GarzikMODULE_LICENSE("GPL"); 232095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff GarzikMODULE_DEVICE_TABLE(pci, sil_pci_tbl); 233095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff GarzikMODULE_VERSION(DRV_VERSION); 234095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 235095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik 236095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzikstatic unsigned char sil_get_device_cache_line(struct pci_dev *pdev) 237095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik{ 238095fec887eaa1c38d17c0c929a6733c744a9fa1fJeff Garzik u8 cache_line = 0; 23931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line); 24031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return cache_line; 24131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 24231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 24331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic void sil_post_set_mode (struct ata_port *ap) 24431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 24531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_host_set *host_set = ap->host_set; 24620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ struct ata_device *dev; 24731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void __iomem *addr = 24831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ host_set->mmio_base + sil_port[ap->port_no].xfer_mode; 24931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ u32 tmp, dev_mode[2]; 25031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned int i; 25131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 25220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (i = 0; i < 2; i++) { 25320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ dev = &ap->device[i]; 25431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (!ata_dev_present(dev)) 25531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dev_mode[i] = 0; /* PIO0/1/2 */ 25631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else if (dev->flags & ATA_DFLAG_PIO) 25731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dev_mode[i] = 1; /* PIO3/4 */ 25831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ else 25931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dev_mode[i] = 3; /* UDMA */ 26031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ /* value 2 indicates MDMA */ 26120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 26231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 26331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tmp = readl(addr); 26431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0)); 26531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tmp |= dev_mode[0]; 26631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tmp |= (dev_mode[1] << 4); 26731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writel(tmp, addr); 26831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ readl(addr); /* flush */ 26931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 27031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 27131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic inline unsigned long sil_scr_addr(struct ata_port *ap, unsigned int sc_reg) 27231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 27331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned long offset = ap->ioaddr.scr_addr; 27431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 275bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik switch (sc_reg) { 276bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case SCR_STATUS: 277bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return offset + 4; 278bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik case SCR_ERROR: 279bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik return offset + 8; 28047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik case SCR_CONTROL: 28147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik return offset; 28247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik default: 28347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik /* do nothing */ 28447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik break; 28547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 28647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 28747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik return 0; 28847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik} 28931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 29031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg) 291bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik{ 29247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik void __iomem *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg); 29320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (mmio) 29420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return readl(mmio); 29520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return 0xffffffffU; 29620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 29720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 29820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) 29931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 30031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ void *mmio = (void __iomem *) sil_scr_addr(ap, sc_reg); 30131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (mmio) 30231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writel(val, mmio); 30331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 30420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 30520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ/** 30631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * sil_dev_config - Apply device/host-specific errata fixups 30720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * @ap: Port containing device to be examined 30820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * @dev: Device to be examined 30947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * 31047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * After the IDENTIFY [PACKET] DEVICE step is complete, and a 31147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * device is known to be present, this function is called. 31247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * We apply two errata fixups which are specific to Silicon Image, 31347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * a Seagate and a Maxtor fixup. 31447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * 31547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * For certain Seagate devices, we must limit the maximum sectors 31647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * to under 8K. 31747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * 31847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * For certain Maxtor devices, we must not program the drive 31947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * beyond udma5. 32047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik * 321193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzik * Both fixups are unfairly pessimistic. As soon as I get more 32220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * information on these errata, I will create a more exhaustive 32320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * list, and apply the fixups to only the specific 32420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * devices/hosts/firmwares that need it. 32520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 32620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted 32731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * The Maxtor quirk is in the blacklist, but I'm keeping the original 32820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * pessimistic fix for the following reasons... 32931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * - There seems to be less info on it, only one device gleaned off the 33020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * Windows driver, maybe only one is affected. More info would be greatly 33120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * appreciated. 33220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ * - But then again UDMA5 is hardly anything to complain about 33331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 33420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic void sil_dev_config(struct ata_port *ap, struct ata_device *dev) 33520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 33620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int n, quirks = 0; 33720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned char model_num[40]; 33820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ const char *s; 33920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ unsigned int len; 34020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 341057ace5e79da9ebf2aa82833cfea825533ac06fbJeff Garzik ata_dev_id_string(dev->id, model_num, ATA_ID_PROD_OFS, 34220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ sizeof(model_num)); 34320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ s = &model_num[0]; 34420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ len = strnlen(s, sizeof(model_num)); 34520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 34620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* ATAPI specifies that empty space is blank-filled; remove blanks */ 34720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ while ((len > 0) && (s[len - 1] == ' ')) 34820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ len--; 34920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 35020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ for (n = 0; sil_blacklist[n].product; n++) 35120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (!memcmp(sil_blacklist[n].product, s, 35231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ strlen(sil_blacklist[n].product))) { 35331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ quirks = sil_blacklist[n].quirk; 35420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ break; 35531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 35620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 35720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* limit requests to 15 sectors */ 35820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if ((ap->flags & SIL_FLAG_MOD15WRITE) && (quirks & SIL_QUIRK_MOD15WRITE)) { 35920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ printk(KERN_INFO "ata%u(%u): applying Seagate errata fix\n", 36020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ap->id, dev->devno); 36120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ap->host->max_sectors = 15; 36220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ap->host->hostt->max_sectors = 15; 36331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ dev->flags |= ATA_DFLAG_LOCK_SECTORS; 36431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 36531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 36620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 36720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* limit to udma5 */ 36820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (quirks & SIL_QUIRK_UDMA5MAX) { 36920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ printk(KERN_INFO "ata%u(%u): applying Maxtor errata fix %s\n", 37020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ap->id, dev->devno, s); 37131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ ap->udma_mask &= ATA_UDMA5; 37231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return; 37331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ } 37420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ} 37520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 37620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russstatic int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) 37720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ{ 37831961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ static int printed_version; 37931961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ struct ata_probe_ent *probe_ent = NULL; 38031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ unsigned long base; 38120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ void __iomem *mmio_base; 38220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ int rc; 38347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik unsigned int i; 38447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik int pci_dev_busy = 0; 38547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u32 tmp, irq_mask; 38647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik u8 cls; 38747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 38847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (!printed_version++) 38947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); 39020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 39120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* 39231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * If this driver happens to only be useful on Apple's K2, then 39331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ * we should check that here as it has a normal Serverworks ID 39431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ */ 39520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ rc = pci_enable_device(pdev); 39620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (rc) 39720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ return rc; 39820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 3998b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik rc = pci_request_regions(pdev, DRV_NAME); 40031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ if (rc) { 40131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_dev_busy = 1; 40231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ goto err_out; 40320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 40420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 40520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); 40620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (rc) 4073b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzik goto err_out_regions; 408bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); 40920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (rc) 41020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ goto err_out_regions; 41147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 41220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL); 413bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if (probe_ent == NULL) { 41420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ rc = -ENOMEM; 41520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ goto err_out_regions; 41620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 41720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 41820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ memset(probe_ent, 0, sizeof(*probe_ent)); 41929179539dac74bf46b519b889602f23841be12e8Jeff Garzik INIT_LIST_HEAD(&probe_ent->node); 42029179539dac74bf46b519b889602f23841be12e8Jeff Garzik probe_ent->dev = pci_dev_to_dev(pdev); 42120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->port_ops = sil_port_info[ent->driver_data].port_ops; 42220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->sht = sil_port_info[ent->driver_data].sht; 42320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->n_ports = (ent->driver_data == sil_3114) ? 4 : 2; 42420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->pio_mask = sil_port_info[ent->driver_data].pio_mask; 42520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->mwdma_mask = sil_port_info[ent->driver_data].mwdma_mask; 42620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->udma_mask = sil_port_info[ent->driver_data].udma_mask; 42720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->irq = pdev->irq; 42820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->irq_flags = SA_SHIRQ; 42920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags; 43020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 43147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik mmio_base = pci_iomap(pdev, 5, 0); 43247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik if (mmio_base == NULL) { 43347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik rc = -ENOMEM; 43447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik goto err_out_free_ent; 43547c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik } 43647c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 43747c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik probe_ent->mmio_base = mmio_base; 43847c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 43947c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik base = (unsigned long) mmio_base; 44047c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik 44147c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik for (i = 0; i < probe_ent->n_ports; i++) { 44247c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik probe_ent->port[i].cmd_addr = base + sil_port[i].tf; 44347c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik probe_ent->port[i].altstatus_addr = 44447c2b677daeed9c79ecb7167c211ff36876ea611Jeff Garzik probe_ent->port[i].ctl_addr = base + sil_port[i].ctl; 44520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->port[i].bmdma_addr = base + sil_port[i].bmdma; 44620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ probe_ent->port[i].scr_addr = base + sil_port[i].scr; 44720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ ata_std_ports(&probe_ent->port[i]); 44820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 44920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 45020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ /* Initialize FIFO PCI bus arbitration */ 45120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ cls = sil_get_device_cache_line(pdev); 45220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (cls) { 45320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ cls >>= 3; 45420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ cls++; /* cls = (line_size/8)+1 */ 45520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writeb(cls, mmio_base + SIL_FIFO_R0); 45620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writeb(cls, mmio_base + SIL_FIFO_W0); 45720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writeb(cls, mmio_base + SIL_FIFO_R1); 45820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writeb(cls, mmio_base + SIL_FIFO_W1); 45920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (ent->driver_data == sil_3114) { 46020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writeb(cls, mmio_base + SIL_FIFO_R2); 46120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writeb(cls, mmio_base + SIL_FIFO_W2); 46220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writeb(cls, mmio_base + SIL_FIFO_R3); 4638b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik writeb(cls, mmio_base + SIL_FIFO_W3); 46420f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 46520f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } else 46620f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ dev_printk(KERN_WARNING, &pdev->dev, 46720f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ "cache line size not set. Driver may not function\n"); 46820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 46920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ if (ent->driver_data == sil_3114) { 47020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ irq_mask = SIL_MASK_4PORT; 47120f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 472bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik /* flip the magic "make 4 ports work" bit */ 47331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ tmp = readl(mmio_base + SIL_IDE2_BMDMA); 474bca1c4eb9411533d613123618c0d127fae532595Jeff Garzik if ((tmp & SIL_INTR_STEERING) == 0) 47531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ writel(tmp | SIL_INTR_STEERING, 47631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ mmio_base + SIL_IDE2_BMDMA); 47731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 47820f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } else { 47920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ irq_mask = SIL_MASK_2PORT; 48020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ } 48105b308e1df6d9d673daedb517969241f41278b52Brett Russ 48205b308e1df6d9d673daedb517969241f41278b52Brett Russ /* make sure IDE0/1/2/3 interrupts are not masked */ 48305b308e1df6d9d673daedb517969241f41278b52Brett Russ tmp = readl(mmio_base + SIL_SYSCFG); 48405b308e1df6d9d673daedb517969241f41278b52Brett Russ if (tmp & irq_mask) { 48505b308e1df6d9d673daedb517969241f41278b52Brett Russ tmp &= ~irq_mask; 48605b308e1df6d9d673daedb517969241f41278b52Brett Russ writel(tmp, mmio_base + SIL_SYSCFG); 48705b308e1df6d9d673daedb517969241f41278b52Brett Russ readl(mmio_base + SIL_SYSCFG); /* flush */ 48805b308e1df6d9d673daedb517969241f41278b52Brett Russ } 48905b308e1df6d9d673daedb517969241f41278b52Brett Russ 49005b308e1df6d9d673daedb517969241f41278b52Brett Russ /* mask all SATA phy-related interrupts */ 49105b308e1df6d9d673daedb517969241f41278b52Brett Russ /* TODO: unmask bit 6 (SError N bit) for hotplug */ 492afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ for (i = 0; i < probe_ent->n_ports; i++) 49320f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ writel(0, mmio_base + sil_port[i].sien); 494afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ 495afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ pci_set_master(pdev); 496afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ 497afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ /* FIXME: check ata_device_add return value */ 498afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ ata_device_add(probe_ent); 49920f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ kfree(probe_ent); 50020f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 50105b308e1df6d9d673daedb517969241f41278b52Brett Russ return 0; 50205b308e1df6d9d673daedb517969241f41278b52Brett Russ 50305b308e1df6d9d673daedb517969241f41278b52Brett Russerr_out_free_ent: 50405b308e1df6d9d673daedb517969241f41278b52Brett Russ kfree(probe_ent); 50505b308e1df6d9d673daedb517969241f41278b52Brett Russerr_out_regions: 50605b308e1df6d9d673daedb517969241f41278b52Brett Russ pci_release_regions(pdev); 50705b308e1df6d9d673daedb517969241f41278b52Brett Russerr_out: 50805b308e1df6d9d673daedb517969241f41278b52Brett Russ if (!pci_dev_busy) 50905b308e1df6d9d673daedb517969241f41278b52Brett Russ pci_disable_device(pdev); 51005b308e1df6d9d673daedb517969241f41278b52Brett Russ return rc; 51131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 51220f733e7d75a16bffc34842b7682c9247dd5f954Brett Russ 51331961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russstatic int __init sil_init(void) 51431961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ{ 51531961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ return pci_module_init(&sil_pci_driver); 51631961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 51731961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 518afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russstatic void __exit sil_exit(void) 519afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ{ 52031961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ pci_unregister_driver(&sil_pci_driver); 52131961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ} 52231961943e3110c5a1c36b1e0069c29f7c4380e51Brett Russ 523afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russ 524afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russmodule_init(sil_init); 525afb0edd922c7ed6e73678730921dfcccebec17e8Brett Russmodule_exit(sil_exit); 5268b260248d9e0e8b64bb72fd4dee03ad86984c344Jeff Garzik