diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/ide/legacy/umc8672.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/ide/legacy/umc8672.c')
-rw-r--r-- | drivers/ide/legacy/umc8672.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c new file mode 100644 index 000000000000..cdbdb2ff9f15 --- /dev/null +++ b/drivers/ide/legacy/umc8672.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * linux/drivers/ide/legacy/umc8672.c Version 0.05 Jul 31, 1996 | ||
3 | * | ||
4 | * Copyright (C) 1995-1996 Linus Torvalds & author (see below) | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * Principal Author/Maintainer: PODIEN@hml2.atlas.de (Wolfram Podien) | ||
9 | * | ||
10 | * This file provides support for the advanced features | ||
11 | * of the UMC 8672 IDE interface. | ||
12 | * | ||
13 | * Version 0.01 Initial version, hacked out of ide.c, | ||
14 | * and #include'd rather than compiled separately. | ||
15 | * This will get cleaned up in a subsequent release. | ||
16 | * | ||
17 | * Version 0.02 now configs/compiles separate from ide.c -ml | ||
18 | * Version 0.03 enhanced auto-tune, fix display bug | ||
19 | * Version 0.05 replace sti() with restore_flags() -ml | ||
20 | * add detection of possible race condition -ml | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * VLB Controller Support from | ||
25 | * Wolfram Podien | ||
26 | * Rohoefe 3 | ||
27 | * D28832 Achim | ||
28 | * Germany | ||
29 | * | ||
30 | * To enable UMC8672 support there must a lilo line like | ||
31 | * append="ide0=umc8672"... | ||
32 | * To set the speed according to the abilities of the hardware there must be a | ||
33 | * line like | ||
34 | * #define UMC_DRIVE0 11 | ||
35 | * in the beginning of the driver, which sets the speed of drive 0 to 11 (there | ||
36 | * are some lines present). 0 - 11 are allowed speed values. These values are | ||
37 | * the results from the DOS speed test program supplied from UMC. 11 is the | ||
38 | * highest speed (about PIO mode 3) | ||
39 | */ | ||
40 | #define REALLY_SLOW_IO /* some systems can safely undef this */ | ||
41 | |||
42 | #include <linux/module.h> | ||
43 | #include <linux/config.h> | ||
44 | #include <linux/types.h> | ||
45 | #include <linux/kernel.h> | ||
46 | #include <linux/delay.h> | ||
47 | #include <linux/timer.h> | ||
48 | #include <linux/mm.h> | ||
49 | #include <linux/ioport.h> | ||
50 | #include <linux/blkdev.h> | ||
51 | #include <linux/hdreg.h> | ||
52 | #include <linux/ide.h> | ||
53 | #include <linux/init.h> | ||
54 | |||
55 | #include <asm/io.h> | ||
56 | |||
57 | /* | ||
58 | * Default speeds. These can be changed with "auto-tune" and/or hdparm. | ||
59 | */ | ||
60 | #define UMC_DRIVE0 1 /* DOS measured drive speeds */ | ||
61 | #define UMC_DRIVE1 1 /* 0 to 11 allowed */ | ||
62 | #define UMC_DRIVE2 1 /* 11 = Fastest Speed */ | ||
63 | #define UMC_DRIVE3 1 /* In case of crash reduce speed */ | ||
64 | |||
65 | static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; | ||
66 | static const u8 pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ | ||
67 | |||
68 | /* 0 1 2 3 4 5 6 7 8 9 10 11 */ | ||
69 | static const u8 speedtab [3][12] = { | ||
70 | {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, | ||
71 | {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, | ||
72 | {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; | ||
73 | |||
74 | static void out_umc (char port,char wert) | ||
75 | { | ||
76 | outb_p(port,0x108); | ||
77 | outb_p(wert,0x109); | ||
78 | } | ||
79 | |||
80 | static inline u8 in_umc (char port) | ||
81 | { | ||
82 | outb_p(port,0x108); | ||
83 | return inb_p(0x109); | ||
84 | } | ||
85 | |||
86 | static void umc_set_speeds (u8 speeds[]) | ||
87 | { | ||
88 | int i, tmp; | ||
89 | |||
90 | outb_p(0x5A,0x108); /* enable umc */ | ||
91 | |||
92 | out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); | ||
93 | out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); | ||
94 | tmp = 0; | ||
95 | for (i = 3; i >= 0; i--) { | ||
96 | tmp = (tmp << 2) | speedtab[1][speeds[i]]; | ||
97 | } | ||
98 | out_umc (0xdc,tmp); | ||
99 | for (i = 0;i < 4; i++) { | ||
100 | out_umc (0xd0+i,speedtab[2][speeds[i]]); | ||
101 | out_umc (0xd8+i,speedtab[2][speeds[i]]); | ||
102 | } | ||
103 | outb_p(0xa5,0x108); /* disable umc */ | ||
104 | |||
105 | printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", | ||
106 | speeds[0], speeds[1], speeds[2], speeds[3]); | ||
107 | } | ||
108 | |||
109 | static void tune_umc (ide_drive_t *drive, u8 pio) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; | ||
113 | |||
114 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); | ||
115 | printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", | ||
116 | drive->name, pio, pio_to_umc[pio]); | ||
117 | spin_lock_irqsave(&ide_lock, flags); | ||
118 | if (hwgroup && hwgroup->handler != NULL) { | ||
119 | printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); | ||
120 | } else { | ||
121 | current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; | ||
122 | umc_set_speeds (current_speeds); | ||
123 | } | ||
124 | spin_unlock_irqrestore(&ide_lock, flags); | ||
125 | } | ||
126 | |||
127 | static int __init umc8672_probe(void) | ||
128 | { | ||
129 | unsigned long flags; | ||
130 | ide_hwif_t *hwif, *mate; | ||
131 | |||
132 | if (!request_region(0x108, 2, "umc8672")) { | ||
133 | printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); | ||
134 | return 1; | ||
135 | } | ||
136 | local_irq_save(flags); | ||
137 | outb_p(0x5A,0x108); /* enable umc */ | ||
138 | if (in_umc (0xd5) != 0xa0) { | ||
139 | local_irq_restore(flags); | ||
140 | printk(KERN_ERR "umc8672: not found\n"); | ||
141 | release_region(0x108, 2); | ||
142 | return 1; | ||
143 | } | ||
144 | outb_p(0xa5,0x108); /* disable umc */ | ||
145 | |||
146 | umc_set_speeds (current_speeds); | ||
147 | local_irq_restore(flags); | ||
148 | |||
149 | hwif = &ide_hwifs[0]; | ||
150 | mate = &ide_hwifs[1]; | ||
151 | |||
152 | hwif->chipset = ide_umc8672; | ||
153 | hwif->tuneproc = &tune_umc; | ||
154 | hwif->mate = mate; | ||
155 | |||
156 | mate->chipset = ide_umc8672; | ||
157 | mate->tuneproc = &tune_umc; | ||
158 | mate->mate = hwif; | ||
159 | mate->channel = 1; | ||
160 | |||
161 | probe_hwif_init(hwif); | ||
162 | probe_hwif_init(mate); | ||
163 | |||
164 | create_proc_ide_interfaces(); | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | /* Can be called directly from ide.c. */ | ||
170 | int __init umc8672_init(void) | ||
171 | { | ||
172 | if (umc8672_probe()) | ||
173 | return -ENODEV; | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | #ifdef MODULE | ||
178 | module_init(umc8672_init); | ||
179 | #endif | ||
180 | |||
181 | MODULE_AUTHOR("Wolfram Podien"); | ||
182 | MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset"); | ||
183 | MODULE_LICENSE("GPL"); | ||