| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | /* | 
|  | 2 | *  Copyright (C) 1996  Linus Torvalds & author (see below) | 
|  | 3 | */ | 
|  | 4 |  | 
|  | 5 | #include <linux/module.h> | 
|  | 6 | #include <linux/types.h> | 
|  | 7 | #include <linux/kernel.h> | 
|  | 8 | #include <linux/delay.h> | 
|  | 9 | #include <linux/timer.h> | 
|  | 10 | #include <linux/mm.h> | 
|  | 11 | #include <linux/ioport.h> | 
|  | 12 | #include <linux/blkdev.h> | 
|  | 13 | #include <linux/ide.h> | 
|  | 14 | #include <linux/init.h> | 
|  | 15 |  | 
|  | 16 | #include <asm/io.h> | 
|  | 17 |  | 
|  | 18 | #define DRV_NAME "dtc2278" | 
|  | 19 |  | 
|  | 20 | /* | 
|  | 21 | * Changing this #undef to #define may solve start up problems in some systems. | 
|  | 22 | */ | 
|  | 23 | #undef ALWAYS_SET_DTC2278_PIO_MODE | 
|  | 24 |  | 
|  | 25 | /* | 
|  | 26 | * From: andy@cercle.cts.com (Dyan Wile) | 
|  | 27 | * | 
|  | 28 | * Below is a patch for DTC-2278 - alike software-programmable controllers | 
|  | 29 | * The code enables the secondary IDE controller and the PIO4 (3?) timings on | 
|  | 30 | * the primary (EIDE). You may probably have to enable the 32-bit support to | 
|  | 31 | * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 | 
|  | 32 | * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my | 
|  | 33 | * filesystem  corrupted with -u1, but under heavy disk load only :-) | 
|  | 34 | * | 
|  | 35 | * This card is now forced to use the "serialize" feature, | 
|  | 36 | * and irq-unmasking is disallowed.  If io_32bit is enabled, | 
|  | 37 | * it must be done for BOTH drives on each interface. | 
|  | 38 | * | 
|  | 39 | * This code was written for the DTC2278E, but might work with any of these: | 
|  | 40 | * | 
|  | 41 | * DTC2278S has only a single IDE interface. | 
|  | 42 | * DTC2278D has two IDE interfaces and is otherwise identical to the S version. | 
|  | 43 | * DTC2278E also has serial ports and a printer port | 
|  | 44 | * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu> | 
|  | 45 | * | 
|  | 46 | * There may be a fourth controller type. The S and D versions use the | 
|  | 47 | * Winbond chip, and I think the E version does also. | 
|  | 48 | * | 
|  | 49 | */ | 
|  | 50 |  | 
|  | 51 | static void sub22 (char b, char c) | 
|  | 52 | { | 
|  | 53 | int i; | 
|  | 54 |  | 
|  | 55 | for(i = 0; i < 3; ++i) { | 
|  | 56 | inb(0x3f6); | 
|  | 57 | outb_p(b,0xb0); | 
|  | 58 | inb(0x3f6); | 
|  | 59 | outb_p(c,0xb4); | 
|  | 60 | inb(0x3f6); | 
|  | 61 | if(inb(0xb4) == c) { | 
|  | 62 | outb_p(7,0xb0); | 
|  | 63 | inb(0x3f6); | 
|  | 64 | return;	/* success */ | 
|  | 65 | } | 
|  | 66 | } | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | static DEFINE_SPINLOCK(dtc2278_lock); | 
|  | 70 |  | 
|  | 71 | static void dtc2278_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) | 
|  | 72 | { | 
|  | 73 | unsigned long flags; | 
|  | 74 |  | 
|  | 75 | if (drive->pio_mode >= XFER_PIO_3) { | 
|  | 76 | spin_lock_irqsave(&dtc2278_lock, flags); | 
|  | 77 | /* | 
|  | 78 | * This enables PIO mode4 (3?) on the first interface | 
|  | 79 | */ | 
|  | 80 | sub22(1,0xc3); | 
|  | 81 | sub22(0,0xa0); | 
|  | 82 | spin_unlock_irqrestore(&dtc2278_lock, flags); | 
|  | 83 | } else { | 
|  | 84 | /* we don't know how to set it back again.. */ | 
|  | 85 | /* Actually we do - there is a data sheet available for the | 
|  | 86 | Winbond but does anyone actually care */ | 
|  | 87 | } | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | static const struct ide_port_ops dtc2278_port_ops = { | 
|  | 91 | .set_pio_mode		= dtc2278_set_pio_mode, | 
|  | 92 | }; | 
|  | 93 |  | 
|  | 94 | static const struct ide_port_info dtc2278_port_info __initconst = { | 
|  | 95 | .name			= DRV_NAME, | 
|  | 96 | .chipset		= ide_dtc2278, | 
|  | 97 | .port_ops		= &dtc2278_port_ops, | 
|  | 98 | .host_flags		= IDE_HFLAG_SERIALIZE | | 
|  | 99 | IDE_HFLAG_NO_UNMASK_IRQS | | 
|  | 100 | IDE_HFLAG_IO_32BIT | | 
|  | 101 | /* disallow ->io_32bit changes */ | 
|  | 102 | IDE_HFLAG_NO_IO_32BIT | | 
|  | 103 | IDE_HFLAG_NO_DMA | | 
|  | 104 | IDE_HFLAG_DTC2278, | 
|  | 105 | .pio_mask		= ATA_PIO4, | 
|  | 106 | }; | 
|  | 107 |  | 
|  | 108 | static int __init dtc2278_probe(void) | 
|  | 109 | { | 
|  | 110 | unsigned long flags; | 
|  | 111 |  | 
|  | 112 | local_irq_save(flags); | 
|  | 113 | /* | 
|  | 114 | * This enables the second interface | 
|  | 115 | */ | 
|  | 116 | outb_p(4,0xb0); | 
|  | 117 | inb(0x3f6); | 
|  | 118 | outb_p(0x20,0xb4); | 
|  | 119 | inb(0x3f6); | 
|  | 120 | #ifdef ALWAYS_SET_DTC2278_PIO_MODE | 
|  | 121 | /* | 
|  | 122 | * This enables PIO mode4 (3?) on the first interface | 
|  | 123 | * and may solve start-up problems for some people. | 
|  | 124 | */ | 
|  | 125 | sub22(1,0xc3); | 
|  | 126 | sub22(0,0xa0); | 
|  | 127 | #endif | 
|  | 128 | local_irq_restore(flags); | 
|  | 129 |  | 
|  | 130 | return ide_legacy_device_add(&dtc2278_port_info, 0); | 
|  | 131 | } | 
|  | 132 |  | 
|  | 133 | static bool probe_dtc2278; | 
|  | 134 |  | 
|  | 135 | module_param_named(probe, probe_dtc2278, bool, 0); | 
|  | 136 | MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); | 
|  | 137 |  | 
|  | 138 | static int __init dtc2278_init(void) | 
|  | 139 | { | 
|  | 140 | if (probe_dtc2278 == 0) | 
|  | 141 | return -ENODEV; | 
|  | 142 |  | 
|  | 143 | if (dtc2278_probe()) { | 
|  | 144 | printk(KERN_ERR "dtc2278: ide interfaces already in use!\n"); | 
|  | 145 | return -EBUSY; | 
|  | 146 | } | 
|  | 147 | return 0; | 
|  | 148 | } | 
|  | 149 |  | 
|  | 150 | module_init(dtc2278_init); | 
|  | 151 |  | 
|  | 152 | MODULE_AUTHOR("See Local File"); | 
|  | 153 | MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); | 
|  | 154 | MODULE_LICENSE("GPL"); |