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