blob: b07d4f4273b33d2970ceb9f2d7ea0b40af7860b0 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
3 * Portions (C) Copyright 2002 Red Hat Inc <alan@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * For the avoidance of doubt the "preferred form" of this code is one which
16 * is in an open non patent encumbered format. Where cryptographic key signing
17 * forms part of the process of creating an executable the information
18 * including keys needed to generate an equivalently functional executable
19 * are deemed to be part of the source code.
20 */
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/types.h>
23#include <linux/module.h>
24#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/hdreg.h>
26#include <linux/pci.h>
27#include <linux/ide.h>
28#include <linux/init.h>
29
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020030#define DRV_NAME "ide_pci_generic"
31
Alan Coxb1893462005-06-27 15:24:26 -070032static int ide_generic_all; /* Set to claim all devices */
33
Patrick Jeffersona4bea102006-10-03 01:14:34 -070034module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
35MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
Alan Coxb1893462005-06-27 15:24:26 -070036
Bartlomiej Zolnierkiewicz8acf28c2007-10-20 00:32:30 +020037#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS)
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020039#define DECLARE_GENERIC_PCI_DEV(extra_flags) \
Bartlomiej Zolnierkiewicz1c3dd322007-10-19 00:30:06 +020040 { \
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020041 .name = DRV_NAME, \
Bartlomiej Zolnierkiewicz7cab14a2007-10-19 00:30:06 +020042 .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA | \
Bartlomiej Zolnierkiewicz5e71d9c2008-04-26 17:36:35 +020043 extra_flags, \
Bartlomiej Zolnierkiewicz5f8b6c32007-10-19 00:30:07 +020044 .swdma_mask = ATA_SWDMA2, \
45 .mwdma_mask = ATA_MWDMA2, \
46 .udma_mask = ATA_UDMA6, \
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070048
Bartlomiej Zolnierkiewicz85620432007-10-20 00:32:34 +020049static const struct ide_port_info generic_chipsets[] __devinitdata = {
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020050 /* 0: Unknown */
51 DECLARE_GENERIC_PCI_DEV(0),
Bartlomiej Zolnierkiewicz1c3dd322007-10-19 00:30:06 +020052
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020053 { /* 1: NS87410 */
54 .name = DRV_NAME,
Paolo Ciarrocchi17deabd2008-04-26 17:36:40 +020055 .enablebits = { {0x43, 0x08, 0x08}, {0x47, 0x08, 0x08} },
Bartlomiej Zolnierkiewicz5e71d9c2008-04-26 17:36:35 +020056 .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA,
Bartlomiej Zolnierkiewicz5f8b6c32007-10-19 00:30:07 +020057 .swdma_mask = ATA_SWDMA2,
58 .mwdma_mask = ATA_MWDMA2,
59 .udma_mask = ATA_UDMA6,
Bartlomiej Zolnierkiewicz1c3dd322007-10-19 00:30:06 +020060 },
61
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020062 /* 2: SAMURAI / HT6565 / HINT_IDE */
63 DECLARE_GENERIC_PCI_DEV(0),
64 /* 3: UM8673F / UM8886A / UM8886BF */
65 DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC),
66 /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */
67 DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA),
Bartlomiej Zolnierkiewicz1c3dd322007-10-19 00:30:06 +020068
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020069 { /* 5: VIA8237SATA */
70 .name = DRV_NAME,
Bartlomiej Zolnierkiewicz7cab14a2007-10-19 00:30:06 +020071 .host_flags = IDE_HFLAG_TRUST_BIOS_FOR_DMA |
72 IDE_HFLAG_OFF_BOARD,
Bartlomiej Zolnierkiewicz5f8b6c32007-10-19 00:30:07 +020073 .swdma_mask = ATA_SWDMA2,
74 .mwdma_mask = ATA_MWDMA2,
75 .udma_mask = ATA_UDMA6,
Bartlomiej Zolnierkiewicz1c3dd322007-10-19 00:30:06 +020076 },
77
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +020078 { /* 6: Revolution */
79 .name = DRV_NAME,
Bartlomiej Zolnierkiewicz8ac2b42a2008-02-01 23:09:30 +010080 .host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
81 IDE_HFLAG_TRUST_BIOS_FOR_DMA |
Bartlomiej Zolnierkiewicz7cab14a2007-10-19 00:30:06 +020082 IDE_HFLAG_OFF_BOARD,
Bartlomiej Zolnierkiewicz5f8b6c32007-10-19 00:30:07 +020083 .swdma_mask = ATA_SWDMA2,
84 .mwdma_mask = ATA_MWDMA2,
85 .udma_mask = ATA_UDMA6,
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 }
87};
88
89/**
90 * generic_init_one - called when a PIIX is found
91 * @dev: the generic device
92 * @id: the matching pci id
93 *
94 * Called when the PCI registration layer (or the IDE initialization)
95 * finds a device matching our IDE device tables.
96 */
Paolo Ciarrocchi17deabd2008-04-26 17:36:40 +020097
Linus Torvalds1da177e2005-04-16 15:20:36 -070098static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
99{
Bartlomiej Zolnierkiewicz85620432007-10-20 00:32:34 +0200100 const struct ide_port_info *d = &generic_chipsets[id->driver_data];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101 int ret = -ENODEV;
102
Alan Coxb1893462005-06-27 15:24:26 -0700103 /* Don't use the generic entry unless instructed to do so */
104 if (id->driver_data == 0 && ide_generic_all == 0)
105 goto out;
106
Jiri Slabyea307592007-06-08 15:14:31 +0200107 switch (dev->vendor) {
108 case PCI_VENDOR_ID_UMC:
109 if (dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
110 !(PCI_FUNC(dev->devfn) & 1))
111 goto out; /* UM8886A/BF pair */
112 break;
113 case PCI_VENDOR_ID_OPTI:
114 if (dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
115 !(PCI_FUNC(dev->devfn) & 1))
Alan Coxc3335262006-10-28 10:38:57 -0700116 goto out;
Jiri Slabyea307592007-06-08 15:14:31 +0200117 break;
118 case PCI_VENDOR_ID_JMICRON:
119 if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 &&
120 PCI_FUNC(dev->devfn) != 1)
121 goto out;
122 break;
123 case PCI_VENDOR_ID_NS:
124 if (dev->device == PCI_DEVICE_ID_NS_87410 &&
125 (dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
126 goto out;
127 break;
Alan Coxc3335262006-10-28 10:38:57 -0700128 }
Alan Cox15e0c692006-07-12 15:05:41 +0100129
Alan Cox3719bc52006-10-11 01:21:47 -0700130 if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
Jiri Slabyea307592007-06-08 15:14:31 +0200131 u16 command;
Alan Cox3719bc52006-10-11 01:21:47 -0700132 pci_read_config_word(dev, PCI_COMMAND, &command);
133 if (!(command & PCI_COMMAND_IO)) {
Bartlomiej Zolnierkiewicz28cfd8a2008-07-24 22:53:31 +0200134 printk(KERN_INFO "%s %s: skipping disabled "
135 "controller\n", d->name, pci_name(dev));
Alan Cox3719bc52006-10-11 01:21:47 -0700136 goto out;
137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 }
Bartlomiej Zolnierkiewicz6cdf6eb2008-07-24 22:53:14 +0200139 ret = ide_pci_init_one(dev, d, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140out:
141 return ret;
142}
143
Bartlomiej Zolnierkiewicz9cbcc5e2007-10-16 22:29:56 +0200144static const struct pci_device_id generic_pci_tbl[] = {
145 { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_87410), 1 },
146 { PCI_VDEVICE(PCTECH, PCI_DEVICE_ID_PCTECH_SAMURAI_IDE), 2 },
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +0200147 { PCI_VDEVICE(HOLTEK, PCI_DEVICE_ID_HOLTEK_6565), 2 },
148 { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8673F), 3 },
149 { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886A), 3 },
150 { PCI_VDEVICE(UMC, PCI_DEVICE_ID_UMC_UM8886BF), 3 },
151 { PCI_VDEVICE(HINT, PCI_DEVICE_ID_HINT_VXPROII_IDE), 2 },
152 { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C561), 4 },
153 { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C558), 4 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#ifdef CONFIG_BLK_DEV_IDE_SATA
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +0200155 { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8237_SATA), 5 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156#endif
Bartlomiej Zolnierkiewiczced3ec82008-07-24 22:53:32 +0200157 { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO), 4 },
158 { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), 4 },
159 { PCI_VDEVICE(TOSHIBA, PCI_DEVICE_ID_TOSHIBA_PICCOLO_2), 4 },
160 { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), 6 },
Bartlomiej Zolnierkiewicz9cbcc5e2007-10-16 22:29:56 +0200161 /*
162 * Must come last. If you add entries adjust
163 * this table and generic_chipsets[] appropriately.
164 */
165 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 { 0, },
167};
168MODULE_DEVICE_TABLE(pci, generic_pci_tbl);
169
170static struct pci_driver driver = {
171 .name = "PCI_IDE",
172 .id_table = generic_pci_tbl,
173 .probe = generic_init_one,
Bartlomiej Zolnierkiewiczf566bca2008-07-24 22:53:21 +0200174 .remove = ide_pci_remove,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175};
176
Bartlomiej Zolnierkiewicz82ab1ee2007-01-27 13:46:56 +0100177static int __init generic_ide_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700178{
179 return ide_pci_register_driver(&driver);
180}
181
Bartlomiej Zolnierkiewiczf566bca2008-07-24 22:53:21 +0200182static void __exit generic_ide_exit(void)
183{
184 pci_unregister_driver(&driver);
185}
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187module_init(generic_ide_init);
Bartlomiej Zolnierkiewiczf566bca2008-07-24 22:53:21 +0200188module_exit(generic_ide_exit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189
190MODULE_AUTHOR("Andre Hedrick");
191MODULE_DESCRIPTION("PCI driver module for generic PCI IDE");
192MODULE_LICENSE("GPL");