aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-07-12 10:05:41 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-07-12 15:59:35 -0400
commit15e0c694367332d7e7114c7c73044bc5fed9ee48 (patch)
treede18bd97c7438f44fac3b28ea5447f4aa9fcf98e /drivers
parentf6dc8c5b8e04ce28720155383e971561a23899d5 (diff)
[PATCH] ide: fix Jmicron support
Prior to 2.6.18rc1 you could install with devices on a JMicron chipset using the "all-generic-ide" option. As of this kernel the AHCI driver grabs the controller and rams it into AHCI mode losing the PATA ports and making CD drives and the like vanish. The all-generic-ide option fails because the AHCI driver grabbed the PCI device and reconfigured it. To fix this three things are needed. #1 We must put the chip into dual function mode #2 The AHCI driver must grab only function 0 (already in your rc1 tree) #3 Something must grab the PATA ports The attached patch is the minimal risk edition of this. It puts the chip into dual function mode so that AHCI will grab the SATA ports without losing the PATA ports. To keep the risk as low as possible the third patch adds the PCI identifiers for the PATA port and the FN check to the ide-generic driver. There is a more featured jmicron driver on its way but that adds risk and the ide-generic support is sufficient to install and run a system. The actual chip setup done by the quirk is the precise setup recommended by the vendor. (The JMB368 appears only in the ide-generic entry as it has no AHCI so does not need the quirk) Signed-off-by: Alan Cox <alan@redhat.com> Acked-by: Jeff Garzik <jgarzik@pobox.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/pci/generic.c8
-rw-r--r--drivers/pci/quirks.c49
2 files changed, 57 insertions, 0 deletions
diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
index f82e82109728..2f962cfa3f7f 100644
--- a/drivers/ide/pci/generic.c
+++ b/drivers/ide/pci/generic.c
@@ -212,6 +212,9 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi
212 (!(PCI_FUNC(dev->devfn) & 1))) 212 (!(PCI_FUNC(dev->devfn) & 1)))
213 goto out; 213 goto out;
214 214
215 if (dev->vendor == PCI_VENDOR_ID_JMICRON && PCI_FUNC(dev->devfn) != 1)
216 goto out;
217
215 pci_read_config_word(dev, PCI_COMMAND, &command); 218 pci_read_config_word(dev, PCI_COMMAND, &command);
216 if (!(command & PCI_COMMAND_IO)) { 219 if (!(command & PCI_COMMAND_IO)) {
217 printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name); 220 printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name);
@@ -239,6 +242,11 @@ static struct pci_device_id generic_pci_tbl[] = {
239 { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12}, 242 { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12},
240 { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13}, 243 { PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13},
241 { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14}, 244 { PCI_VENDOR_ID_NETCELL,PCI_DEVICE_ID_REVOLUTION, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14},
245 { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB361, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15},
246 { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB363, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16},
247 { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB365, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17},
248 { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB366, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18},
249 { PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB368, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19},
242 /* Must come last. If you add entries adjust this table appropriately and the init_one code */ 250 /* Must come last. If you add entries adjust this table appropriately and the init_one code */
243 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0}, 251 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 0},
244 { 0, }, 252 { 0, },
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index e9a57afa1a08..de3bbc88fb26 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1175,6 +1175,55 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_
1175DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus ); 1175DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
1176DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus ); 1176DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
1177 1177
1178#if defined(CONFIG_SCSI_SATA) || defined(CONFIG_SCSI_SATA_MODULE)
1179
1180/*
1181 * If we are using libata we can drive this chip properly but must
1182 * do this early on to make the additional device appear during
1183 * the PCI scanning.
1184 */
1185
1186static void __devinit quirk_jmicron_dualfn(struct pci_dev *pdev)
1187{
1188 u32 conf;
1189 u8 hdr;
1190
1191 /* Only poke fn 0 */
1192 if (PCI_FUNC(pdev->devfn))
1193 return;
1194
1195 switch(pdev->device) {
1196 case PCI_DEVICE_ID_JMICRON_JMB365:
1197 case PCI_DEVICE_ID_JMICRON_JMB366:
1198 /* Redirect IDE second PATA port to the right spot */
1199 pci_read_config_dword(pdev, 0x80, &conf);
1200 conf |= (1 << 24);
1201 /* Fall through */
1202 pci_write_config_dword(pdev, 0x80, conf);
1203 case PCI_DEVICE_ID_JMICRON_JMB361:
1204 case PCI_DEVICE_ID_JMICRON_JMB363:
1205 pci_read_config_dword(pdev, 0x40, &conf);
1206 /* Enable dual function mode, AHCI on fn 0, IDE fn1 */
1207 /* Set the class codes correctly and then direct IDE 0 */
1208 conf &= ~0x000F0200; /* Clear bit 9 and 16-19 */
1209 conf |= 0x00C20002; /* Set bit 1, 17, 22, 23 */
1210 pci_write_config_dword(pdev, 0x40, conf);
1211
1212 /* Reconfigure so that the PCI scanner discovers the
1213 device is now multifunction */
1214
1215 pci_read_config_byte(pdev, PCI_HEADER_TYPE, &hdr);
1216 pdev->hdr_type = hdr & 0x7f;
1217 pdev->multifunction = !!(hdr & 0x80);
1218
1219 break;
1220 }
1221}
1222
1223DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, quirk_jmicron_dualfn);
1224
1225#endif
1226
1178#ifdef CONFIG_X86_IO_APIC 1227#ifdef CONFIG_X86_IO_APIC
1179static void __init quirk_alder_ioapic(struct pci_dev *pdev) 1228static void __init quirk_alder_ioapic(struct pci_dev *pdev)
1180{ 1229{