diff options
Diffstat (limited to 'drivers/ide/legacy/umc8672.c')
-rw-r--r-- | drivers/ide/legacy/umc8672.c | 92 |
1 files changed, 41 insertions, 51 deletions
diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index bc1944811b99..b54a14a57755 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c | |||
@@ -19,7 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * VLB Controller Support from | 22 | * VLB Controller Support from |
23 | * Wolfram Podien | 23 | * Wolfram Podien |
24 | * Rohoefe 3 | 24 | * Rohoefe 3 |
25 | * D28832 Achim | 25 | * D28832 Achim |
@@ -32,7 +32,7 @@ | |||
32 | * #define UMC_DRIVE0 11 | 32 | * #define UMC_DRIVE0 11 |
33 | * in the beginning of the driver, which sets the speed of drive 0 to 11 (there | 33 | * in the beginning of the driver, which sets the speed of drive 0 to 11 (there |
34 | * are some lines present). 0 - 11 are allowed speed values. These values are | 34 | * are some lines present). 0 - 11 are allowed speed values. These values are |
35 | * the results from the DOS speed test program supplied from UMC. 11 is the | 35 | * the results from the DOS speed test program supplied from UMC. 11 is the |
36 | * highest speed (about PIO mode 3) | 36 | * highest speed (about PIO mode 3) |
37 | */ | 37 | */ |
38 | #define REALLY_SLOW_IO /* some systems can safely undef this */ | 38 | #define REALLY_SLOW_IO /* some systems can safely undef this */ |
@@ -51,6 +51,8 @@ | |||
51 | 51 | ||
52 | #include <asm/io.h> | 52 | #include <asm/io.h> |
53 | 53 | ||
54 | #define DRV_NAME "umc8672" | ||
55 | |||
54 | /* | 56 | /* |
55 | * Default speeds. These can be changed with "auto-tune" and/or hdparm. | 57 | * Default speeds. These can be changed with "auto-tune" and/or hdparm. |
56 | */ | 58 | */ |
@@ -60,115 +62,103 @@ | |||
60 | #define UMC_DRIVE3 1 /* In case of crash reduce speed */ | 62 | #define UMC_DRIVE3 1 /* In case of crash reduce speed */ |
61 | 63 | ||
62 | static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; | 64 | static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3}; |
63 | static const u8 pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */ | 65 | static const u8 pio_to_umc [5] = {0, 3, 7, 10, 11}; /* rough guesses */ |
64 | 66 | ||
65 | /* 0 1 2 3 4 5 6 7 8 9 10 11 */ | 67 | /* 0 1 2 3 4 5 6 7 8 9 10 11 */ |
66 | static const u8 speedtab [3][12] = { | 68 | static const u8 speedtab [3][12] = { |
67 | {0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, | 69 | {0x0f, 0x0b, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, |
68 | {0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }, | 70 | {0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1}, |
69 | {0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}}; | 71 | {0xff, 0xcb, 0xc0, 0x58, 0x36, 0x33, 0x23, 0x22, 0x21, 0x11, 0x10, 0x0} |
72 | }; | ||
70 | 73 | ||
71 | static void out_umc (char port,char wert) | 74 | static void out_umc(char port, char wert) |
72 | { | 75 | { |
73 | outb_p(port,0x108); | 76 | outb_p(port, 0x108); |
74 | outb_p(wert,0x109); | 77 | outb_p(wert, 0x109); |
75 | } | 78 | } |
76 | 79 | ||
77 | static inline u8 in_umc (char port) | 80 | static inline u8 in_umc(char port) |
78 | { | 81 | { |
79 | outb_p(port,0x108); | 82 | outb_p(port, 0x108); |
80 | return inb_p(0x109); | 83 | return inb_p(0x109); |
81 | } | 84 | } |
82 | 85 | ||
83 | static void umc_set_speeds (u8 speeds[]) | 86 | static void umc_set_speeds(u8 speeds[]) |
84 | { | 87 | { |
85 | int i, tmp; | 88 | int i, tmp; |
86 | 89 | ||
87 | outb_p(0x5A,0x108); /* enable umc */ | 90 | outb_p(0x5A, 0x108); /* enable umc */ |
88 | 91 | ||
89 | out_umc (0xd7,(speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); | 92 | out_umc(0xd7, (speedtab[0][speeds[2]] | (speedtab[0][speeds[3]]<<4))); |
90 | out_umc (0xd6,(speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); | 93 | out_umc(0xd6, (speedtab[0][speeds[0]] | (speedtab[0][speeds[1]]<<4))); |
91 | tmp = 0; | 94 | tmp = 0; |
92 | for (i = 3; i >= 0; i--) { | 95 | for (i = 3; i >= 0; i--) |
93 | tmp = (tmp << 2) | speedtab[1][speeds[i]]; | 96 | tmp = (tmp << 2) | speedtab[1][speeds[i]]; |
97 | out_umc(0xdc, tmp); | ||
98 | for (i = 0; i < 4; i++) { | ||
99 | out_umc(0xd0 + i, speedtab[2][speeds[i]]); | ||
100 | out_umc(0xd8 + i, speedtab[2][speeds[i]]); | ||
94 | } | 101 | } |
95 | out_umc (0xdc,tmp); | 102 | outb_p(0xa5, 0x108); /* disable umc */ |
96 | for (i = 0;i < 4; i++) { | ||
97 | out_umc (0xd0+i,speedtab[2][speeds[i]]); | ||
98 | out_umc (0xd8+i,speedtab[2][speeds[i]]); | ||
99 | } | ||
100 | outb_p(0xa5,0x108); /* disable umc */ | ||
101 | 103 | ||
102 | printk ("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", | 104 | printk("umc8672: drive speeds [0 to 11]: %d %d %d %d\n", |
103 | speeds[0], speeds[1], speeds[2], speeds[3]); | 105 | speeds[0], speeds[1], speeds[2], speeds[3]); |
104 | } | 106 | } |
105 | 107 | ||
106 | static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) | 108 | static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) |
107 | { | 109 | { |
110 | ide_hwif_t *hwif = drive->hwif; | ||
108 | unsigned long flags; | 111 | unsigned long flags; |
109 | ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup; | ||
110 | 112 | ||
111 | printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", | 113 | printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", |
112 | drive->name, pio, pio_to_umc[pio]); | 114 | drive->name, pio, pio_to_umc[pio]); |
113 | spin_lock_irqsave(&ide_lock, flags); | 115 | spin_lock_irqsave(&ide_lock, flags); |
114 | if (hwgroup && hwgroup->handler != NULL) { | 116 | if (hwif->mate && hwif->mate->hwgroup->handler) { |
115 | printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); | 117 | printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); |
116 | } else { | 118 | } else { |
117 | current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; | 119 | current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; |
118 | umc_set_speeds (current_speeds); | 120 | umc_set_speeds(current_speeds); |
119 | } | 121 | } |
120 | spin_unlock_irqrestore(&ide_lock, flags); | 122 | spin_unlock_irqrestore(&ide_lock, flags); |
121 | } | 123 | } |
122 | 124 | ||
125 | static const struct ide_port_ops umc8672_port_ops = { | ||
126 | .set_pio_mode = umc_set_pio_mode, | ||
127 | }; | ||
128 | |||
123 | static const struct ide_port_info umc8672_port_info __initdata = { | 129 | static const struct ide_port_info umc8672_port_info __initdata = { |
130 | .name = DRV_NAME, | ||
124 | .chipset = ide_umc8672, | 131 | .chipset = ide_umc8672, |
125 | .host_flags = IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE, | 132 | .port_ops = &umc8672_port_ops, |
133 | .host_flags = IDE_HFLAG_NO_DMA, | ||
126 | .pio_mask = ATA_PIO4, | 134 | .pio_mask = ATA_PIO4, |
127 | }; | 135 | }; |
128 | 136 | ||
129 | static int __init umc8672_probe(void) | 137 | static int __init umc8672_probe(void) |
130 | { | 138 | { |
131 | unsigned long flags; | 139 | unsigned long flags; |
132 | static u8 idx[4] = { 0, 1, 0xff, 0xff }; | ||
133 | hw_regs_t hw[2]; | ||
134 | 140 | ||
135 | if (!request_region(0x108, 2, "umc8672")) { | 141 | if (!request_region(0x108, 2, "umc8672")) { |
136 | printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); | 142 | printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n"); |
137 | return 1; | 143 | return 1; |
138 | } | 144 | } |
139 | local_irq_save(flags); | 145 | local_irq_save(flags); |
140 | outb_p(0x5A,0x108); /* enable umc */ | 146 | outb_p(0x5A, 0x108); /* enable umc */ |
141 | if (in_umc (0xd5) != 0xa0) { | 147 | if (in_umc (0xd5) != 0xa0) { |
142 | local_irq_restore(flags); | 148 | local_irq_restore(flags); |
143 | printk(KERN_ERR "umc8672: not found\n"); | 149 | printk(KERN_ERR "umc8672: not found\n"); |
144 | release_region(0x108, 2); | 150 | release_region(0x108, 2); |
145 | return 1; | 151 | return 1; |
146 | } | 152 | } |
147 | outb_p(0xa5,0x108); /* disable umc */ | 153 | outb_p(0xa5, 0x108); /* disable umc */ |
148 | 154 | ||
149 | umc_set_speeds (current_speeds); | 155 | umc_set_speeds(current_speeds); |
150 | local_irq_restore(flags); | 156 | local_irq_restore(flags); |
151 | 157 | ||
152 | memset(&hw, 0, sizeof(hw)); | 158 | return ide_legacy_device_add(&umc8672_port_info, 0); |
153 | |||
154 | ide_std_init_ports(&hw[0], 0x1f0, 0x3f6); | ||
155 | hw[0].irq = 14; | ||
156 | |||
157 | ide_std_init_ports(&hw[1], 0x170, 0x376); | ||
158 | hw[1].irq = 15; | ||
159 | |||
160 | ide_init_port_hw(&ide_hwifs[0], &hw[0]); | ||
161 | ide_init_port_hw(&ide_hwifs[1], &hw[1]); | ||
162 | |||
163 | ide_hwifs[0].set_pio_mode = &umc_set_pio_mode; | ||
164 | ide_hwifs[1].set_pio_mode = &umc_set_pio_mode; | ||
165 | |||
166 | ide_device_add(idx, &umc8672_port_info); | ||
167 | |||
168 | return 0; | ||
169 | } | 159 | } |
170 | 160 | ||
171 | int probe_umc8672 = 0; | 161 | static int probe_umc8672; |
172 | 162 | ||
173 | module_param_named(probe, probe_umc8672, bool, 0); | 163 | module_param_named(probe, probe_umc8672, bool, 0); |
174 | MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); | 164 | MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); |