diff options
Diffstat (limited to 'drivers/ide/legacy/dtc2278.c')
-rw-r--r-- | drivers/ide/legacy/dtc2278.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c new file mode 100644 index 000000000000..20eb5b872ca9 --- /dev/null +++ b/drivers/ide/legacy/dtc2278.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * linux/drivers/ide/legacy/dtc2278.c Version 0.02 Feb 10, 1996 | ||
3 | * | ||
4 | * Copyright (C) 1996 Linus Torvalds & author (see below) | ||
5 | */ | ||
6 | |||
7 | #undef REALLY_SLOW_IO /* most systems can safely undef this */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/config.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/timer.h> | ||
15 | #include <linux/mm.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/blkdev.h> | ||
18 | #include <linux/hdreg.h> | ||
19 | #include <linux/ide.h> | ||
20 | #include <linux/init.h> | ||
21 | |||
22 | #include <asm/io.h> | ||
23 | |||
24 | /* | ||
25 | * Changing this #undef to #define may solve start up problems in some systems. | ||
26 | */ | ||
27 | #undef ALWAYS_SET_DTC2278_PIO_MODE | ||
28 | |||
29 | /* | ||
30 | * From: andy@cercle.cts.com (Dyan Wile) | ||
31 | * | ||
32 | * Below is a patch for DTC-2278 - alike software-programmable controllers | ||
33 | * The code enables the secondary IDE controller and the PIO4 (3?) timings on | ||
34 | * the primary (EIDE). You may probably have to enable the 32-bit support to | ||
35 | * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 | ||
36 | * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my | ||
37 | * filesystem corrupted with -u1, but under heavy disk load only :-) | ||
38 | * | ||
39 | * This card is now forced to use the "serialize" feature, | ||
40 | * and irq-unmasking is disallowed. If io_32bit is enabled, | ||
41 | * it must be done for BOTH drives on each interface. | ||
42 | * | ||
43 | * This code was written for the DTC2278E, but might work with any of these: | ||
44 | * | ||
45 | * DTC2278S has only a single IDE interface. | ||
46 | * DTC2278D has two IDE interfaces and is otherwise identical to the S version. | ||
47 | * DTC2278E also has serial ports and a printer port | ||
48 | * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu> | ||
49 | * | ||
50 | * There may be a fourth controller type. The S and D versions use the | ||
51 | * Winbond chip, and I think the E version does also. | ||
52 | * | ||
53 | */ | ||
54 | |||
55 | static void sub22 (char b, char c) | ||
56 | { | ||
57 | int i; | ||
58 | |||
59 | for(i = 0; i < 3; ++i) { | ||
60 | inb(0x3f6); | ||
61 | outb_p(b,0xb0); | ||
62 | inb(0x3f6); | ||
63 | outb_p(c,0xb4); | ||
64 | inb(0x3f6); | ||
65 | if(inb(0xb4) == c) { | ||
66 | outb_p(7,0xb0); | ||
67 | inb(0x3f6); | ||
68 | return; /* success */ | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static void tune_dtc2278 (ide_drive_t *drive, u8 pio) | ||
74 | { | ||
75 | unsigned long flags; | ||
76 | |||
77 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | ||
78 | |||
79 | if (pio >= 3) { | ||
80 | spin_lock_irqsave(&ide_lock, flags); | ||
81 | /* | ||
82 | * This enables PIO mode4 (3?) on the first interface | ||
83 | */ | ||
84 | sub22(1,0xc3); | ||
85 | sub22(0,0xa0); | ||
86 | spin_unlock_irqrestore(&ide_lock, flags); | ||
87 | } else { | ||
88 | /* we don't know how to set it back again.. */ | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * 32bit I/O has to be enabled for *both* drives at the same time. | ||
93 | */ | ||
94 | drive->io_32bit = 1; | ||
95 | HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; | ||
96 | } | ||
97 | |||
98 | static int __init probe_dtc2278(void) | ||
99 | { | ||
100 | unsigned long flags; | ||
101 | ide_hwif_t *hwif, *mate; | ||
102 | |||
103 | hwif = &ide_hwifs[0]; | ||
104 | mate = &ide_hwifs[1]; | ||
105 | |||
106 | if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown) | ||
107 | return 1; | ||
108 | |||
109 | local_irq_save(flags); | ||
110 | /* | ||
111 | * This enables the second interface | ||
112 | */ | ||
113 | outb_p(4,0xb0); | ||
114 | inb(0x3f6); | ||
115 | outb_p(0x20,0xb4); | ||
116 | inb(0x3f6); | ||
117 | #ifdef ALWAYS_SET_DTC2278_PIO_MODE | ||
118 | /* | ||
119 | * This enables PIO mode4 (3?) on the first interface | ||
120 | * and may solve start-up problems for some people. | ||
121 | */ | ||
122 | sub22(1,0xc3); | ||
123 | sub22(0,0xa0); | ||
124 | #endif | ||
125 | local_irq_restore(flags); | ||
126 | |||
127 | hwif->serialized = 1; | ||
128 | hwif->chipset = ide_dtc2278; | ||
129 | hwif->tuneproc = &tune_dtc2278; | ||
130 | hwif->drives[0].no_unmask = 1; | ||
131 | hwif->drives[1].no_unmask = 1; | ||
132 | hwif->mate = mate; | ||
133 | |||
134 | mate->serialized = 1; | ||
135 | mate->chipset = ide_dtc2278; | ||
136 | mate->drives[0].no_unmask = 1; | ||
137 | mate->drives[1].no_unmask = 1; | ||
138 | mate->mate = hwif; | ||
139 | mate->channel = 1; | ||
140 | |||
141 | probe_hwif_init(hwif); | ||
142 | probe_hwif_init(mate); | ||
143 | |||
144 | create_proc_ide_interfaces(); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | /* Can be called directly from ide.c. */ | ||
150 | int __init dtc2278_init(void) | ||
151 | { | ||
152 | if (probe_dtc2278()) { | ||
153 | printk(KERN_ERR "dtc2278: ide interfaces already in use!\n"); | ||
154 | return -EBUSY; | ||
155 | } | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | #ifdef MODULE | ||
160 | module_init(dtc2278_init); | ||
161 | #endif | ||
162 | |||
163 | MODULE_AUTHOR("See Local File"); | ||
164 | MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); | ||
165 | MODULE_LICENSE("GPL"); | ||