sata_sil.c revision 41137aa61c1ccb7cd06981807113b7e2d0ad89ed
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sata_sil.c - Silicon Image SATA 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Maintained by: Jeff Garzik <jgarzik@pobox.com> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Please ALWAYS copy linux-ide@vger.kernel.org 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * on emails. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * Copyright 2003-2005 Red Hat, Inc. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 Benjamin Herrenschmidt 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 11af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 12af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * This program is free software; you can redistribute it and/or modify 13af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * it under the terms of the GNU General Public License as published by 14af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * the Free Software Foundation; either version 2, or (at your option) 15af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * any later version. 16af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 17af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * This program is distributed in the hope that it will be useful, 18af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * but WITHOUT ANY WARRANTY; without even the implied warranty of 19af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * GNU General Public License for more details. 21af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 22af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * You should have received a copy of the GNU General Public License 23af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * along with this program; see the file COPYING. If not, write to 24af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 25af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 26af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * 27af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * libata documentation is available via 'make {ps|pdf}docs', 28af36d7f0df56de3e3e4bbfb15d0915097ecb8cabJeff Garzik * as Documentation/DocBook/libata.* 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 30953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * Documentation for SiI 3112: 31953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * http://gkernel.sourceforge.net/specs/sii/3112A_SiI-DS-0095-B2.pdf.bz2 32953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * 33953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * Other errata and documentation available under NDA. 34953d1137fc4aba16deace262e93974913596dcfeJeff Garzik * 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h> 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 44a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik#include <linux/device.h> 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <scsi/scsi_host.h> 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/libata.h> 471737ef7598d3515fdc11cb9ba7e054f334404e04Alexander Beregalov#include <linux/dmi.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_NAME "sata_sil" 50c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock#define DRV_VERSION "2.4" 51c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 52c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock#define SIL_DMA_BOUNDARY 0x7fffffffUL 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 550d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo SIL_MMIO_BAR = 5, 560d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo 57e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 58e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * host flags 59e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 60201ce85946504ea0e6bd9a365de26684b437121eTejun Heo SIL_FLAG_NO_SATA_IRQ = (1 << 28), 61e4e10e3e7995f5bd481d2720bf30d3a661d110caTejun Heo SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29), 62e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo SIL_FLAG_MOD15WRITE = (1 << 30), 6320888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo 64cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik SIL_DFL_PORT_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | 650c88758b5a6325428aaadab619886242db20ceaeTejun Heo ATA_FLAG_MMIO, 66e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo 67e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 68e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Controller IDs 69e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sil_3112 = 0, 71201ce85946504ea0e6bd9a365de26684b437121eTejun Heo sil_3112_no_sata_irq = 1, 72201ce85946504ea0e6bd9a365de26684b437121eTejun Heo sil_3512 = 2, 73201ce85946504ea0e6bd9a365de26684b437121eTejun Heo sil_3114 = 3, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 75e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 76e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Register offsets 77e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_SYSCFG = 0x48, 79e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo 80e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 81e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Register bits 82e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 83e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* SYSCFG */ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE0_INT = (1 << 22), 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE1_INT = (1 << 23), 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE2_INT = (1 << 24), 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE3_INT = (1 << 25), 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_2PORT = SIL_MASK_IDE0_INT | SIL_MASK_IDE1_INT, 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_4PORT = SIL_MASK_2PORT | 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_MASK_IDE2_INT | SIL_MASK_IDE3_INT, 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 92e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* BMDMA/BMDMA2 */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_INTR_STEERING = (1 << 1), 94e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo 9520888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_ENABLE = (1 << 0), /* DMA run switch */ 9620888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_RDWR = (1 << 3), /* DMA Rd-Wr */ 9720888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_SATA_IRQ = (1 << 4), /* OR of all SATA IRQs */ 9820888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_ACTIVE = (1 << 16), /* DMA running */ 9920888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_ERROR = (1 << 17), /* PCI bus error */ 10020888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_COMPLETE = (1 << 18), /* cmd complete / IRQ pending */ 10120888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_SATA_IRQ = (1 << 6), /* SATA_IRQ for the next channel */ 10220888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_ACTIVE = (1 << 24), /* ACTIVE for the next channel */ 10320888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_ERROR = (1 << 25), /* ERROR for the next channel */ 10420888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_DMA_N_COMPLETE = (1 << 26), /* COMPLETE for the next channel */ 10520888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo 10620888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo /* SIEN */ 10720888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo SIL_SIEN_N = (1 << 16), /* triggered by SError.N */ 10820888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo 109e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo /* 110e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo * Others 111e653a1e6131d0a819288a2e2de654627233604e0Tejun Heo */ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_QUIRK_MOD15WRITE = (1 << 0), 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SIL_QUIRK_UDMA5MAX = (1 << 1), 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1165796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); 117281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#ifdef CONFIG_PM 118afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heostatic int sil_pci_device_resume(struct pci_dev *pdev); 119281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#endif 120cd0d3bbcdd650651b7ccfaf55d107e3fc237d95aAlan Coxstatic void sil_dev_config(struct ata_device *dev); 12182ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); 12282ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); 1230260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heostatic int sil_set_mode(struct ata_link *link, struct ata_device **r_failed); 124c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_qc_prep(struct ata_queued_cmd *qc); 125c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_setup(struct ata_queued_cmd *qc); 126c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_start(struct ata_queued_cmd *qc); 127c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_stop(struct ata_queued_cmd *qc); 128f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_freeze(struct ata_port *ap); 129f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_thaw(struct ata_port *ap); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131374b1873571bf80dc0c1fcceaaad067980f3b9deJeff Garzik 1323b7d697dfb7d03edb87e50b743a7ecff029618e9Jeff Garzikstatic const struct pci_device_id sil_pci_tbl[] = { 13354bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x3112), sil_3112 }, 13454bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x0240), sil_3112 }, 13554bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x3512), sil_3512 }, 13654bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(CMD, 0x3114), sil_3114 }, 13754bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(ATI, 0x436e), sil_3112 }, 13854bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(ATI, 0x4379), sil_3112_no_sata_irq }, 13954bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik { PCI_VDEVICE(ATI, 0x437a), sil_3112_no_sata_irq }, 14054bb3a94b192be09feb85993b664ff118d6433d0Jeff Garzik 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } /* terminate list */ 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TODO firmware versions should be added - eric */ 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct sil_drivelist { 1475796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik const char *product; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int quirk; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} sil_blacklist [] = { 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST320012AS", SIL_QUIRK_MOD15WRITE }, 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST330013AS", SIL_QUIRK_MOD15WRITE }, 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST340017AS", SIL_QUIRK_MOD15WRITE }, 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST360015AS", SIL_QUIRK_MOD15WRITE }, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST380023AS", SIL_QUIRK_MOD15WRITE }, 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST3120023AS", SIL_QUIRK_MOD15WRITE }, 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST340014ASL", SIL_QUIRK_MOD15WRITE }, 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST360014ASL", SIL_QUIRK_MOD15WRITE }, 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST380011ASL", SIL_QUIRK_MOD15WRITE }, 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST3120022ASL", SIL_QUIRK_MOD15WRITE }, 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "ST3160021ASL", SIL_QUIRK_MOD15WRITE }, 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { "Maxtor 4D060H3", SIL_QUIRK_UDMA5MAX }, 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver sil_pci_driver = { 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = DRV_NAME, 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = sil_pci_tbl, 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = sil_init_one, 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = ata_pci_remove_one, 170281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#ifdef CONFIG_PM 171afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo .suspend = ata_pci_device_suspend, 172afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo .resume = sil_pci_device_resume, 173281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#endif 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 176193515d51ccb363165d6b09e9ba5c21089e34badJeff Garzikstatic struct scsi_host_template sil_sht = { 177c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock ATA_BASE_SHT(DRV_NAME), 178c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /** These controllers support Large Block Transfer which allows 179c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock transfer chunks up to 2GB and which cross 64KB boundaries, 180c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock therefore the DMA limits are more relaxed than standard ATA SFF. */ 181c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .dma_boundary = SIL_DMA_BOUNDARY, 182c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .sg_tablesize = ATA_MAX_PRD 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 185029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heostatic struct ata_port_operations sil_ops = { 186029cfd6b74fc5c517865fad78cf4a3ea8d9b664aTejun Heo .inherits = &ata_bmdma_port_ops, 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .dev_config = sil_dev_config, 1889d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox .set_mode = sil_set_mode, 189c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .bmdma_setup = sil_bmdma_setup, 190c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .bmdma_start = sil_bmdma_start, 191c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .bmdma_stop = sil_bmdma_stop, 192c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock .qc_prep = sil_qc_prep, 193f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo .freeze = sil_freeze, 194f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo .thaw = sil_thaw, 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .scr_read = sil_scr_read, 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .scr_write = sil_scr_write, 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19998ac62defe529d04a192688f40d801a2d8fbcf98Arjan van de Venstatic const struct ata_port_info sil_port_info[] = { 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* sil_3112 */ 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 202cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, 203e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo .pio_mask = 0x1f, /* pio0-4 */ 204e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo .mwdma_mask = 0x07, /* mwdma0-2 */ 205bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 206e4deec6304cbd5fd08bf573eccc68787945071c2Tejun Heo .port_ops = &sil_ops, 2070ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo }, 208201ce85946504ea0e6bd9a365de26684b437121eTejun Heo /* sil_3112_no_sata_irq */ 209201ce85946504ea0e6bd9a365de26684b437121eTejun Heo { 210cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE | 211201ce85946504ea0e6bd9a365de26684b437121eTejun Heo SIL_FLAG_NO_SATA_IRQ, 212201ce85946504ea0e6bd9a365de26684b437121eTejun Heo .pio_mask = 0x1f, /* pio0-4 */ 213201ce85946504ea0e6bd9a365de26684b437121eTejun Heo .mwdma_mask = 0x07, /* mwdma0-2 */ 214bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 215201ce85946504ea0e6bd9a365de26684b437121eTejun Heo .port_ops = &sil_ops, 216201ce85946504ea0e6bd9a365de26684b437121eTejun Heo }, 2170ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo /* sil_3512 */ 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 219cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 2200ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo .pio_mask = 0x1f, /* pio0-4 */ 2210ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo .mwdma_mask = 0x07, /* mwdma0-2 */ 222bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 2230ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo .port_ops = &sil_ops, 2240ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo }, 2250ee304d5802dc62746f13f12d4cb4ec4ed285f66Tejun Heo /* sil_3114 */ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 227cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pio_mask = 0x1f, /* pio0-4 */ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mwdma_mask = 0x07, /* mwdma0-2 */ 230bf6263a853c9c143bf03f0a6fdcc68ab714fb5f5Jeff Garzik .udma_mask = ATA_UDMA5, 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .port_ops = &sil_ops, 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* per-port register offsets */ 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* TODO: we can probably calculate rather than use a table */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const struct { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long tf; /* ATA taskfile register block */ 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ctl; /* ATA control/altstatus register block */ 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long bmdma; /* DMA register block */ 24120888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo unsigned long bmdma2; /* DMA register block #2 */ 24248d4ef2a1df9867c67b515d66732ba028a73735dTejun Heo unsigned long fifo_cfg; /* FIFO Valid Byte Count and Control */ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long scr; /* SATA control register block */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long sien; /* SATA Interrupt Enable register */ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long xfer_mode;/* data transfer mode register */ 246e4e10e3e7995f5bd481d2720bf30d3a661d110caTejun Heo unsigned long sfis_cfg; /* SATA FIS reception config register */ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} sil_port[] = { 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* port 0 ... */ 2495bcd7a00a464fd81b4b68847b9b811a635a15b61Jeff Garzik /* tf ctl bmdma bmdma2 fifo scr sien mode sfis */ 2505bcd7a00a464fd81b4b68847b9b811a635a15b61Jeff Garzik { 0x80, 0x8A, 0x0, 0x10, 0x40, 0x100, 0x148, 0xb4, 0x14c }, 2515bcd7a00a464fd81b4b68847b9b811a635a15b61Jeff Garzik { 0xC0, 0xCA, 0x8, 0x18, 0x44, 0x180, 0x1c8, 0xf4, 0x1cc }, 25220888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo { 0x280, 0x28A, 0x200, 0x210, 0x240, 0x300, 0x348, 0x2b4, 0x34c }, 25320888d83687d5cb374cdb5b0afa746ab79666f4eTejun Heo { 0x2C0, 0x2CA, 0x208, 0x218, 0x244, 0x380, 0x3c8, 0x2f4, 0x3cc }, 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* ... port 3 */ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Jeff Garzik"); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("low-level driver for Silicon Image SATA controller"); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, sil_pci_tbl); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_VERSION(DRV_VERSION); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2635796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic int slow_down; 26451e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzikmodule_param(slow_down, int, 0444); 26551e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff GarzikMODULE_PARM_DESC(slow_down, "Sledgehammer used to work around random problems, by limiting commands to 15 sectors (0=off, 1=on)"); 26651e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik 267374b1873571bf80dc0c1fcceaaad067980f3b9deJeff Garzik 268c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_stop(struct ata_queued_cmd *qc) 269c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 270c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 271c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 272c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 273c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 274c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* clear start/stop bit - can safely always write 0 */ 275c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock iowrite8(0, bmdma2); 276c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 277c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ 278c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock ata_sff_dma_pause(ap); 279c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 280c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 281c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_setup(struct ata_queued_cmd *qc) 282c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 283c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 284c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *bmdma = ap->ioaddr.bmdma_addr; 285c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 286c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* load PRD table addr. */ 287c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock iowrite32(ap->prd_dma, bmdma + ATA_DMA_TABLE_OFS); 288c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 289c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* issue r/w command */ 290c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock ap->ops->sff_exec_command(ap, &qc->tf); 291c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 292c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 293c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_bmdma_start(struct ata_queued_cmd *qc) 294c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 295c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); 296c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 297c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 298c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock void __iomem *bmdma2 = mmio_base + sil_port[ap->port_no].bmdma2; 299c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock u8 dmactl = ATA_DMA_START; 300c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 301c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* set transfer direction, start host DMA transaction 302c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock Note: For Large Block Transfer to work, the DMA must be started 303c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock using the bmdma2 register. */ 304c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock if (!rw) 305c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock dmactl |= ATA_DMA_WR; 306c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock iowrite8(dmactl, bmdma2); 307c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 308c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 309c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock/* The way God intended PCI IDE scatter/gather lists to look and behave... */ 310c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_fill_sg(struct ata_queued_cmd *qc) 311c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 312c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct scatterlist *sg; 313c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_port *ap = qc->ap; 314c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock struct ata_prd *prd, *last_prd = NULL; 315c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock unsigned int si; 316c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 317c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock prd = &ap->prd[0]; 318c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock for_each_sg(qc->sg, sg, qc->n_elem, si) { 319c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock /* Note h/w doesn't support 64-bit, so we unconditionally 320c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock * truncate dma_addr_t to u32. 321c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock */ 322c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock u32 addr = (u32) sg_dma_address(sg); 323c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock u32 sg_len = sg_dma_len(sg); 324c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 325c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock prd->addr = cpu_to_le32(addr); 326c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock prd->flags_len = cpu_to_le32(sg_len); 32741137aa61c1ccb7cd06981807113b7e2d0ad89edPasi Kärkkäinen VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", si, addr, sg_len); 328c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 329c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock last_prd = prd; 330c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock prd++; 331c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock } 332c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 333c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock if (likely(last_prd)) 334c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock last_prd->flags_len |= cpu_to_le32(ATA_PRD_EOT); 335c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 336c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 337c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancockstatic void sil_qc_prep(struct ata_queued_cmd *qc) 338c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock{ 339c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock if (!(qc->flags & ATA_QCFLAG_DMAMAP)) 340c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock return; 341c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 342c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock sil_fill_sg(qc); 343c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock} 344c7e324f1bd17b25fcdca33bdad01cf6eb8be4933Robert Hancock 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char sil_get_device_cache_line(struct pci_dev *pdev) 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 cache_line = 0; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return cache_line; 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3529d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox/** 3539d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * sil_set_mode - wrap set_mode functions 3540260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo * @link: link to set up 3559d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * @r_failed: returned device when we fail 3569d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * 3579d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * Wrap the libata method for device setup as after the setup we need 3589d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox * to inspect the results and do some configuration work 3599d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox */ 3609d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox 3610260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heostatic int sil_set_mode(struct ata_link *link, struct ata_device **r_failed) 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3630260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo struct ata_port *ap = link->ap; 3640260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 3650d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *addr = mmio_base + sil_port[ap->port_no].xfer_mode; 3660260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo struct ata_device *dev; 367f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo u32 tmp, dev_mode[2] = { }; 3689d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox int rc; 369a617c09f6d646b60f31efc8afd9f81b752bf21b7Jeff Garzik 3700260731f0187840e272bfa10d3ba0f3e417976f5Tejun Heo rc = ata_do_set_mode(link, r_failed); 3719d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox if (rc) 3729d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox return rc; 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741eca4365be25c540650693e941bc06a66cf38f94Tejun Heo ata_for_each_dev(dev, link, ALL) { 375e1211e3fa7fd05ff0d4f597fd37e40de8acc6784Tejun Heo if (!ata_dev_enabled(dev)) 376f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo dev_mode[dev->devno] = 0; /* PIO0/1/2 */ 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (dev->flags & ATA_DFLAG_PIO) 378f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo dev_mode[dev->devno] = 1; /* PIO3/4 */ 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 380f58229f8060055b08b34008ea08f31de1e2f003cTejun Heo dev_mode[dev->devno] = 3; /* UDMA */ 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* value 2 indicates MDMA */ 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp = readl(addr); 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp &= ~((1<<5) | (1<<4) | (1<<1) | (1<<0)); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp |= dev_mode[0]; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds tmp |= (dev_mode[1] << 4); 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(tmp, addr); 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds readl(addr); /* flush */ 3909d2c7c75f889a3eefad016c71f651b0796e0a6e9Alan Cox return 0; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3935796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic inline void __iomem *sil_scr_addr(struct ata_port *ap, 3945796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzik unsigned int sc_reg) 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3960d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *offset = ap->ioaddr.scr_addr; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (sc_reg) { 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCR_STATUS: 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return offset + 4; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCR_ERROR: 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return offset + 8; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SCR_CONTROL: 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return offset; 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* do nothing */ 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4108d9db2d2fbae9e05022825c32f86e00c8e342860Randy Dunlap return NULL; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 41382ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 41582ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 416da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 417da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (mmio) { 418da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo *val = readl(mmio); 419da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 420da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 421da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42482ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heostatic int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 42682ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo void __iomem *mmio = sil_scr_addr(link->ap, sc_reg); 427da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo 428da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo if (mmio) { 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds writel(val, mmio); 430da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return 0; 431da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo } 432da3dbb17a0e9a9ec7f5aed95f1fddadb790edc9dTejun Heo return -EINVAL; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 435cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heostatic void sil_host_intr(struct ata_port *ap, u32 bmdma2) 436cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo{ 4379af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_eh_info *ehi = &ap->link.eh_info; 4389af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag); 439cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo u8 status; 440cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 441e573890b00426189e1e223967a2c46fb758bf06eTejun Heo if (unlikely(bmdma2 & SIL_DMA_SATA_IRQ)) { 442d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo u32 serror; 443d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo 444d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo /* SIEN doesn't mask SATA IRQs on some 3112s. Those 445d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo * controllers continue to assert IRQ as long as 446d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo * SError bits are pending. Clear SError immediately. 447d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo */ 44882ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo sil_scr_read(&ap->link, SCR_ERROR, &serror); 44982ef04fb4c82542b3eda81cca461f0594ce9cd0bTejun Heo sil_scr_write(&ap->link, SCR_ERROR, serror); 450d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo 4518cf32ac6578a70025be1103466da9d1d6141429eTejun Heo /* Sometimes spurious interrupts occur, double check 4528cf32ac6578a70025be1103466da9d1d6141429eTejun Heo * it's PHYRDY CHG. 453d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo */ 4548cf32ac6578a70025be1103466da9d1d6141429eTejun Heo if (serror & SERR_PHYRDY_CHG) { 455f7fe7ad4bcaba17f05d5cbf1119772c645783b08Tejun Heo ap->link.eh_info.serror |= serror; 4568cf32ac6578a70025be1103466da9d1d6141429eTejun Heo goto freeze; 457d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo } 458d4c85325a817d3351e61c4be64b437116e8483b4Tejun Heo 4598cf32ac6578a70025be1103466da9d1d6141429eTejun Heo if (!(bmdma2 & SIL_DMA_COMPLETE)) 4608cf32ac6578a70025be1103466da9d1d6141429eTejun Heo return; 461e573890b00426189e1e223967a2c46fb758bf06eTejun Heo } 462e573890b00426189e1e223967a2c46fb758bf06eTejun Heo 4638cf32ac6578a70025be1103466da9d1d6141429eTejun Heo if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) { 464e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo /* this sometimes happens, just clear IRQ */ 4655682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo ap->ops->sff_check_status(ap); 466e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo return; 467e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo } 468e2f8fb72144a9f38d44ccf3f939e939392eda659Tejun Heo 469cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* Check whether we are expecting interrupt in this state */ 470cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo switch (ap->hsm_task_state) { 471cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo case HSM_ST_FIRST: 472cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* Some pre-ATAPI-4 devices assert INTRQ 473cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo * at this state when ready to receive CDB. 474cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo */ 475cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 476cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* Check the ATA_DFLAG_CDB_INTR flag is enough here. 477405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo * The flag was turned on only for atapi devices. No 478405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo * need to check ata_is_atapi(qc->tf.protocol) again. 479cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo */ 480cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) 481cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo goto err_hsm; 482cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo break; 483cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo case HSM_ST_LAST: 484405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo if (ata_is_dma(qc->tf.protocol)) { 485cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* clear DMA-Start bit */ 486cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo ap->ops->bmdma_stop(qc); 487cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 488cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo if (bmdma2 & SIL_DMA_ERROR) { 489cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo qc->err_mask |= AC_ERR_HOST_BUS; 490cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo ap->hsm_task_state = HSM_ST_ERR; 491cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 492cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 493cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo break; 494cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo case HSM_ST: 495cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo break; 496cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo default: 497cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo goto err_hsm; 498cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 499cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 500cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* check main status, clearing INTRQ */ 5015682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo status = ap->ops->sff_check_status(ap); 502cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo if (unlikely(status & ATA_BUSY)) 503cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo goto err_hsm; 504cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 505cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* ack bmdma irq events */ 5069363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ata_sff_irq_clear(ap); 507cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 508cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo /* kick HSM in the ass */ 5099363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ata_sff_hsm_move(ap, qc, status, 0); 510cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 511405e66b38797875e80669eaf72d313dbb76533c3Tejun Heo if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) 512ea54763f8a7c51b9f8fcb14431812ae63fcbaf96Tejun Heo ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2); 513ea54763f8a7c51b9f8fcb14431812ae63fcbaf96Tejun Heo 514cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo return; 515cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 516cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo err_hsm: 517cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo qc->err_mask |= AC_ERR_HSM; 518cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo freeze: 519cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo ata_port_freeze(ap); 520cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo} 521cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 5227d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sil_interrupt(int irq, void *dev_instance) 523cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo{ 524cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_host *host = dev_instance; 5250d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 526cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo int handled = 0; 527cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo int i; 528cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 529cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_lock(&host->lock); 530cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 531cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik for (i = 0; i < host->n_ports; i++) { 532cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_port *ap = host->ports[i]; 533cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo u32 bmdma2 = readl(mmio_base + sil_port[ap->port_no].bmdma2); 534cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 535cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED)) 536cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo continue; 537cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 538201ce85946504ea0e6bd9a365de26684b437121eTejun Heo /* turn off SATA_IRQ if not supported */ 539201ce85946504ea0e6bd9a365de26684b437121eTejun Heo if (ap->flags & SIL_FLAG_NO_SATA_IRQ) 540201ce85946504ea0e6bd9a365de26684b437121eTejun Heo bmdma2 &= ~SIL_DMA_SATA_IRQ; 541201ce85946504ea0e6bd9a365de26684b437121eTejun Heo 54223fa9618094975f803ed0c6a44604b16747b9637Tejun Heo if (bmdma2 == 0xffffffff || 54323fa9618094975f803ed0c6a44604b16747b9637Tejun Heo !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ))) 544cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo continue; 545cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 546cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo sil_host_intr(ap, bmdma2); 547cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo handled = 1; 548cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo } 549cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 550cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik spin_unlock(&host->lock); 551cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 552cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo return IRQ_RETVAL(handled); 553cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo} 554cbe88fbc72d9e1aa4a6f994cb6e19fa08ae5a0baTejun Heo 555f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_freeze(struct ata_port *ap) 556f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo{ 5570d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 558f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo u32 tmp; 559f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 560e573890b00426189e1e223967a2c46fb758bf06eTejun Heo /* global IRQ mask doesn't block SATA IRQ, turn off explicitly */ 561e573890b00426189e1e223967a2c46fb758bf06eTejun Heo writel(0, mmio_base + sil_port[ap->port_no].sien); 562e573890b00426189e1e223967a2c46fb758bf06eTejun Heo 563f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo /* plug IRQ */ 564f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp = readl(mmio_base + SIL_SYSCFG); 565f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp |= SIL_MASK_IDE0_INT << ap->port_no; 566f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo writel(tmp, mmio_base + SIL_SYSCFG); 567f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo readl(mmio_base + SIL_SYSCFG); /* flush */ 568f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo} 569f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 570f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heostatic void sil_thaw(struct ata_port *ap) 571f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo{ 5720d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo void __iomem *mmio_base = ap->host->iomap[SIL_MMIO_BAR]; 573f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo u32 tmp; 574f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 575f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo /* clear IRQ */ 5765682ed33aae05d10a25c95633ef9d9c062825888Tejun Heo ap->ops->sff_check_status(ap); 5779363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ata_sff_irq_clear(ap); 578f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 579201ce85946504ea0e6bd9a365de26684b437121eTejun Heo /* turn on SATA IRQ if supported */ 580201ce85946504ea0e6bd9a365de26684b437121eTejun Heo if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ)) 581201ce85946504ea0e6bd9a365de26684b437121eTejun Heo writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien); 582e573890b00426189e1e223967a2c46fb758bf06eTejun Heo 583f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo /* turn on IRQ */ 584f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp = readl(mmio_base + SIL_SYSCFG); 585f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo tmp &= ~(SIL_MASK_IDE0_INT << ap->port_no); 586f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo writel(tmp, mmio_base + SIL_SYSCFG); 587f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo} 588f6aae27ed002ba9c0a98aff811dbde32ce749d28Tejun Heo 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sil_dev_config - Apply device/host-specific errata fixups 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * @dev: Device to be examined 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * After the IDENTIFY [PACKET] DEVICE step is complete, and a 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * device is known to be present, this function is called. 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We apply two errata fixups which are specific to Silicon Image, 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a Seagate and a Maxtor fixup. 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For certain Seagate devices, we must limit the maximum sectors 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to under 8K. 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For certain Maxtor devices, we must not program the drive 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * beyond udma5. 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Both fixups are unfairly pessimistic. As soon as I get more 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * information on these errata, I will create a more exhaustive 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * list, and apply the fixups to only the specific 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * devices/hosts/firmwares that need it. 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 20040111 - Seagate drives affected by the Mod15Write bug are blacklisted 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The Maxtor quirk is in the blacklist, but I'm keeping the original 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pessimistic fix for the following reasons... 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - There seems to be less info on it, only one device gleaned off the 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Windows driver, maybe only one is affected. More info would be greatly 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * appreciated. 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - But then again UDMA5 is hardly anything to complain about 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 617cd0d3bbcdd650651b7ccfaf55d107e3fc237d95aAlan Coxstatic void sil_dev_config(struct ata_device *dev) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6199af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo struct ata_port *ap = dev->link->ap; 6209af5c9c97dc9d599281778864c72b385f0c63341Tejun Heo int print_info = ap->link.eh_context.i.flags & ATA_EHI_PRINTINFO; 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int n, quirks = 0; 622a0cf733b333eeeafb7324e2897448006c693c26cTejun Heo unsigned char model_num[ATA_ID_PROD_LEN + 1]; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 624a0cf733b333eeeafb7324e2897448006c693c26cTejun Heo ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num)); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6268a60a07129fad60bba779a2a4038c7518b167fc7Jeff Garzik for (n = 0; sil_blacklist[n].product; n++) 6272e02671daa2cd69d93c828c40579bbe953f17210Tejun Heo if (!strcmp(sil_blacklist[n].product, model_num)) { 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds quirks = sil_blacklist[n].quirk; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6318a60a07129fad60bba779a2a4038c7518b167fc7Jeff Garzik 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* limit requests to 15 sectors */ 63351e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik if (slow_down || 63451e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik ((ap->flags & SIL_FLAG_MOD15WRITE) && 63551e9f2ff83df6b1c81c5c44f4486c68ed87aa20eJeff Garzik (quirks & SIL_QUIRK_MOD15WRITE))) { 636efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo if (print_info) 637efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo ata_dev_printk(dev, KERN_INFO, "applying Seagate " 638efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo "errata fix (mod15write workaround)\n"); 639b00eec1d58ee71131375bfeb86e64bceec3f5618Tejun Heo dev->max_sectors = 15; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* limit to udma5 */ 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (quirks & SIL_QUIRK_UDMA5MAX) { 645efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo if (print_info) 646efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo ata_dev_printk(dev, KERN_INFO, "applying Maxtor " 647efdaedc443e935eda82e9e78a6e65d1f993d242fTejun Heo "errata fix %s\n", model_num); 6485a529139554f12cb265715117a2153c936286294Tejun Heo dev->udma_mask &= ATA_UDMA5; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6534447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heostatic void sil_init_controller(struct ata_host *host) 6543d8ec91352099b32a400f1952112dc076da28106Tejun Heo{ 6554447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct pci_dev *pdev = to_pci_dev(host->dev); 6564447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR]; 6573d8ec91352099b32a400f1952112dc076da28106Tejun Heo u8 cls; 6583d8ec91352099b32a400f1952112dc076da28106Tejun Heo u32 tmp; 6593d8ec91352099b32a400f1952112dc076da28106Tejun Heo int i; 6603d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6613d8ec91352099b32a400f1952112dc076da28106Tejun Heo /* Initialize FIFO PCI bus arbitration */ 6623d8ec91352099b32a400f1952112dc076da28106Tejun Heo cls = sil_get_device_cache_line(pdev); 6633d8ec91352099b32a400f1952112dc076da28106Tejun Heo if (cls) { 6643d8ec91352099b32a400f1952112dc076da28106Tejun Heo cls >>= 3; 6653d8ec91352099b32a400f1952112dc076da28106Tejun Heo cls++; /* cls = (line_size/8)+1 */ 6664447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (i = 0; i < host->n_ports; i++) 6673d8ec91352099b32a400f1952112dc076da28106Tejun Heo writew(cls << 8 | cls, 6683d8ec91352099b32a400f1952112dc076da28106Tejun Heo mmio_base + sil_port[i].fifo_cfg); 6693d8ec91352099b32a400f1952112dc076da28106Tejun Heo } else 6703d8ec91352099b32a400f1952112dc076da28106Tejun Heo dev_printk(KERN_WARNING, &pdev->dev, 6713d8ec91352099b32a400f1952112dc076da28106Tejun Heo "cache line size not set. Driver may not function\n"); 6723d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6733d8ec91352099b32a400f1952112dc076da28106Tejun Heo /* Apply R_ERR on DMA activate FIS errata workaround */ 6744447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (host->ports[0]->flags & SIL_FLAG_RERR_ON_DMA_ACT) { 6753d8ec91352099b32a400f1952112dc076da28106Tejun Heo int cnt; 6763d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6774447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (i = 0, cnt = 0; i < host->n_ports; i++) { 6783d8ec91352099b32a400f1952112dc076da28106Tejun Heo tmp = readl(mmio_base + sil_port[i].sfis_cfg); 6793d8ec91352099b32a400f1952112dc076da28106Tejun Heo if ((tmp & 0x3) != 0x01) 6803d8ec91352099b32a400f1952112dc076da28106Tejun Heo continue; 6813d8ec91352099b32a400f1952112dc076da28106Tejun Heo if (!cnt) 6823d8ec91352099b32a400f1952112dc076da28106Tejun Heo dev_printk(KERN_INFO, &pdev->dev, 6833d8ec91352099b32a400f1952112dc076da28106Tejun Heo "Applying R_ERR on DMA activate " 6843d8ec91352099b32a400f1952112dc076da28106Tejun Heo "FIS errata fix\n"); 6853d8ec91352099b32a400f1952112dc076da28106Tejun Heo writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg); 6863d8ec91352099b32a400f1952112dc076da28106Tejun Heo cnt++; 6873d8ec91352099b32a400f1952112dc076da28106Tejun Heo } 6883d8ec91352099b32a400f1952112dc076da28106Tejun Heo } 6893d8ec91352099b32a400f1952112dc076da28106Tejun Heo 6904447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (host->n_ports == 4) { 6913d8ec91352099b32a400f1952112dc076da28106Tejun Heo /* flip the magic "make 4 ports work" bit */ 6923d8ec91352099b32a400f1952112dc076da28106Tejun Heo tmp = readl(mmio_base + sil_port[2].bmdma); 6933d8ec91352099b32a400f1952112dc076da28106Tejun Heo if ((tmp & SIL_INTR_STEERING) == 0) 6943d8ec91352099b32a400f1952112dc076da28106Tejun Heo writel(tmp | SIL_INTR_STEERING, 6953d8ec91352099b32a400f1952112dc076da28106Tejun Heo mmio_base + sil_port[2].bmdma); 6963d8ec91352099b32a400f1952112dc076da28106Tejun Heo } 6973d8ec91352099b32a400f1952112dc076da28106Tejun Heo} 6983d8ec91352099b32a400f1952112dc076da28106Tejun Heo 699e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysockistatic bool sil_broken_system_poweroff(struct pci_dev *pdev) 700e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki{ 701e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki static const struct dmi_system_id broken_systems[] = { 702e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki { 703e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki .ident = "HP Compaq nx6325", 704e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki .matches = { 705e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 706e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nx6325"), 707e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki }, 708e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki /* PCI slot number of the controller */ 709e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki .driver_data = (void *)0x12UL, 710e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki }, 711e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 712e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki { } /* terminate list */ 713e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki }; 714e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki const struct dmi_system_id *dmi = dmi_first_match(broken_systems); 715e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 716e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki if (dmi) { 717e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki unsigned long slot = (unsigned long)dmi->driver_data; 718e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki /* apply the quirk only to on-board controllers */ 719e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki return slot == PCI_SLOT(pdev->devfn); 720e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki } 721e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 722e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki return false; 723e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki} 724e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 7255796d1c4c89efff823259fda35b08ea66ebf8b23Jeff Garzikstatic int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int printed_version; 7284447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo int board_id = ent->driver_data; 729e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki struct ata_port_info pi = sil_port_info[board_id]; 730e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki const struct ata_port_info *ppi[] = { &pi, NULL }; 7314447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo struct ata_host *host; 732ea6ba10bbb88e106f9e2db7dc253993bb3bbbe3bJeff Garzik void __iomem *mmio_base; 7334447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo int n_ports, rc; 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int i; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!printed_version++) 737a9524a76f70f3343e4be27f95a7e92a8ba5f9009Jeff Garzik dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7394447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* allocate host */ 7404447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_ports = 2; 7414447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (board_id == sil_3114) 7424447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo n_ports = 4; 7434447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 744e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki if (sil_broken_system_poweroff(pdev)) { 745e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki pi.flags |= ATA_FLAG_NO_POWEROFF_SPINDOWN | 746e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki ATA_FLAG_NO_HIBERNATE_SPINDOWN; 747e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki dev_info(&pdev->dev, "quirky BIOS, skipping spindown " 748e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki "on poweroff and hibernation\n"); 749e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki } 750e57db7bde7bff95ae812736ca00c73bd5271455bRafael J. Wysocki 7514447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports); 7524447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo if (!host) 7534447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return -ENOMEM; 7544447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 7554447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* acquire resources and fill host */ 75624dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo rc = pcim_enable_device(pdev); 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7600d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo rc = pcim_iomap_regions(pdev, 1 << SIL_MMIO_BAR, DRV_NAME); 7610d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc == -EBUSY) 76224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo pcim_pin_device(pdev); 7630d5ff566779f894ca9937231a181eb31e4adff0eTejun Heo if (rc) 76424dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 7654447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo host->iomap = pcim_iomap_table(pdev); 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 76924dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) 77224dc5f33ea4b504cfbd23fa159a4cacba8e4d800Tejun Heo return rc; 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7744447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo mmio_base = host->iomap[SIL_MMIO_BAR]; 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7764447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo for (i = 0; i < host->n_ports; i++) { 777cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo struct ata_port *ap = host->ports[i]; 778cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo struct ata_ioports *ioaddr = &ap->ioaddr; 7794447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo 7804447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->cmd_addr = mmio_base + sil_port[i].tf; 7814447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->altstatus_addr = 7824447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->ctl_addr = mmio_base + sil_port[i].ctl; 7834447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->bmdma_addr = mmio_base + sil_port[i].bmdma; 7844447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo ioaddr->scr_addr = mmio_base + sil_port[i].scr; 7859363c3825ea9ad76561eb48a395349dd29211ed6Tejun Heo ata_sff_std_ports(ioaddr); 786cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo 787cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, -1, "mmio"); 788cbcdd87593a1d85c5c4b259945a3a09eee12814dTejun Heo ata_port_pbar_desc(ap, SIL_MMIO_BAR, sil_port[i].tf, "tf"); 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7914447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo /* initialize and activate */ 7924447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo sil_init_controller(host); 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_master(pdev); 7954447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo return ata_host_activate(host, pdev->irq, sil_interrupt, IRQF_SHARED, 7964447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo &sil_sht); 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 799281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#ifdef CONFIG_PM 800afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heostatic int sil_pci_device_resume(struct pci_dev *pdev) 801afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo{ 802cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik struct ata_host *host = dev_get_drvdata(&pdev->dev); 803553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo int rc; 804553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo 805553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo rc = ata_pci_device_do_resume(pdev); 806553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo if (rc) 807553c4aa630af7bc885e056d0436e4eb7f238579bTejun Heo return rc; 808afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo 8094447d35156169cf136e829eb6b5cac2d6370f2d9Tejun Heo sil_init_controller(host); 810cca3974e48607c3775dc73b544a5700b2e37c21aJeff Garzik ata_host_resume(host); 811afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo 812afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo return 0; 813afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo} 814281d426c7e64286f433645e27862e7744b1e9310Alexey Dobriyan#endif 815afb5a7cb84b1ea8b6045945e3d288303e6b71336Tejun Heo 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init sil_init(void) 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 818b7887196e38da54ff893897b80875d632d1a1114Pavel Roskin return pci_register_driver(&sil_pci_driver); 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit sil_exit(void) 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver(&sil_pci_driver); 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sil_init); 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(sil_exit); 829