1/* 2 * generic/default IDE host driver 3 * 4 * Copyright (C) 2004, 2008-2009 Bartlomiej Zolnierkiewicz 5 * This code was split off from ide.c. See it for original copyrights. 6 * 7 * May be copied or modified under the terms of the GNU General Public License. 8 */ 9 10#include <linux/kernel.h> 11#include <linux/init.h> 12#include <linux/module.h> 13#include <linux/ide.h> 14#include <linux/pci_ids.h> 15 16/* FIXME: convert arm to use ide_platform host driver */ 17#ifdef CONFIG_ARM 18#include <asm/irq.h> 19#endif 20 21#define DRV_NAME "ide_generic" 22 23static int probe_mask; 24module_param(probe_mask, int, 0); 25MODULE_PARM_DESC(probe_mask, "probe mask for legacy ISA IDE ports"); 26 27static const struct ide_port_info ide_generic_port_info = { 28 .host_flags = IDE_HFLAG_NO_DMA, 29 .chipset = ide_generic, 30}; 31 32#ifdef CONFIG_ARM 33static const u16 legacy_bases[] = { 0x1f0 }; 34static const int legacy_irqs[] = { IRQ_HARDDISK }; 35#elif defined(CONFIG_ALPHA) 36static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168 }; 37static const int legacy_irqs[] = { 14, 15, 11, 10 }; 38#else 39static const u16 legacy_bases[] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 }; 40static const int legacy_irqs[] = { 14, 15, 11, 10, 8, 12 }; 41#endif 42 43static void ide_generic_check_pci_legacy_iobases(int *primary, int *secondary) 44{ 45#ifdef CONFIG_PCI 46 struct pci_dev *p = NULL; 47 u16 val; 48 49 for_each_pci_dev(p) { 50 if (pci_resource_start(p, 0) == 0x1f0) 51 *primary = 1; 52 if (pci_resource_start(p, 2) == 0x170) 53 *secondary = 1; 54 55 /* Cyrix CS55{1,2}0 pre SFF MWDMA ATA on the bridge */ 56 if (p->vendor == PCI_VENDOR_ID_CYRIX && 57 (p->device == PCI_DEVICE_ID_CYRIX_5510 || 58 p->device == PCI_DEVICE_ID_CYRIX_5520)) 59 *primary = *secondary = 1; 60 61 /* Intel MPIIX - PIO ATA on non PCI side of bridge */ 62 if (p->vendor == PCI_VENDOR_ID_INTEL && 63 p->device == PCI_DEVICE_ID_INTEL_82371MX) { 64 pci_read_config_word(p, 0x6C, &val); 65 if (val & 0x8000) { 66 /* ATA port enabled */ 67 if (val & 0x4000) 68 *secondary = 1; 69 else 70 *primary = 1; 71 } 72 } 73 } 74#endif 75} 76 77static int __init ide_generic_init(void) 78{ 79 struct ide_hw hw, *hws[] = { &hw }; 80 unsigned long io_addr; 81 int i, rc = 0, primary = 0, secondary = 0; 82 83 ide_generic_check_pci_legacy_iobases(&primary, &secondary); 84 85 if (!probe_mask) { 86 printk(KERN_INFO DRV_NAME ": please use \"probe_mask=0x3f\" " 87 "module parameter for probing all legacy ISA IDE ports\n"); 88 89 if (primary == 0) 90 probe_mask |= 0x1; 91 92 if (secondary == 0) 93 probe_mask |= 0x2; 94 } else 95 printk(KERN_INFO DRV_NAME ": enforcing probing of I/O ports " 96 "upon user request\n"); 97 98 for (i = 0; i < ARRAY_SIZE(legacy_bases); i++) { 99 io_addr = legacy_bases[i]; 100 101 if ((probe_mask & (1 << i)) && io_addr) { 102 if (!request_region(io_addr, 8, DRV_NAME)) { 103 printk(KERN_ERR "%s: I/O resource 0x%lX-0x%lX " 104 "not free.\n", 105 DRV_NAME, io_addr, io_addr + 7); 106 rc = -EBUSY; 107 continue; 108 } 109 110 if (!request_region(io_addr + 0x206, 1, DRV_NAME)) { 111 printk(KERN_ERR "%s: I/O resource 0x%lX " 112 "not free.\n", 113 DRV_NAME, io_addr + 0x206); 114 release_region(io_addr, 8); 115 rc = -EBUSY; 116 continue; 117 } 118 119 memset(&hw, 0, sizeof(hw)); 120 ide_std_init_ports(&hw, io_addr, io_addr + 0x206); 121#ifdef CONFIG_IA64 122 hw.irq = isa_irq_to_vector(legacy_irqs[i]); 123#else 124 hw.irq = legacy_irqs[i]; 125#endif 126 rc = ide_host_add(&ide_generic_port_info, hws, 1, NULL); 127 if (rc) { 128 release_region(io_addr + 0x206, 1); 129 release_region(io_addr, 8); 130 } 131 } 132 } 133 134 return rc; 135} 136 137module_init(ide_generic_init); 138 139MODULE_LICENSE("GPL"); 140