This source file includes following definitions.
- put_cmd640_reg_pci1
- get_cmd640_reg_pci1
- put_cmd640_reg_pci2
- get_cmd640_reg_pci2
- put_cmd640_reg_vlb
- get_cmd640_reg_vlb
- probe_for_cmd640_pci1
- probe_for_cmd640_pci2
- probe_for_cmd640_vlb
- ide_probe_for_cmd640x
- as_clocks
- cmd640_set_timing
- known_drive_pio
- cmd640_timings_to_regvals
- set_pio_mode
- cmd640_tune_drive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 static void (*put_cmd640_reg)(int key, int reg_no, int val);
20 static byte (*get_cmd640_reg)(int key, int reg_no);
21
22 enum { none, vlb, pci1, pci2 };
23 static int bus_type = none;
24 static int cmd640_chip_version;
25 static int cmd640_key;
26 static byte is_cmd640[MAX_HWIFS];
27
28
29
30
31
32
33
34
35 static void put_cmd640_reg_pci1(int key, int reg_no, int val)
36 {
37 unsigned long flags;
38
39 save_flags(flags);
40 cli();
41 outl_p((reg_no & 0xfc) | key, 0xcf8);
42 outb_p(val, (reg_no & 3) + 0xcfc);
43 restore_flags(flags);
44 }
45
46 static byte get_cmd640_reg_pci1(int key, int reg_no)
47 {
48 byte b;
49 unsigned long flags;
50
51 save_flags(flags);
52 cli();
53 outl_p((reg_no & 0xfc) | key, 0xcf8);
54 b = inb(0xcfc + (reg_no & 3));
55 restore_flags(flags);
56 return b;
57 }
58
59
60
61 static void put_cmd640_reg_pci2(int key, int reg_no, int val)
62 {
63 unsigned long flags;
64
65 save_flags(flags);
66 cli();
67 outb_p(0x10, 0xcf8);
68 outb_p(val, key + reg_no);
69 outb_p(0, 0xcf8);
70 restore_flags(flags);
71 }
72
73 static byte get_cmd640_reg_pci2(int key, int reg_no)
74 {
75 byte b;
76 unsigned long flags;
77
78 save_flags(flags);
79 cli();
80 outb_p(0x10, 0xcf8);
81 b = inb(key + reg_no);
82 outb_p(0, 0xcf8);
83 restore_flags(flags);
84 return b;
85 }
86
87
88
89 static void put_cmd640_reg_vlb(int key, int reg_no, int val)
90 {
91 unsigned long flags;
92
93 save_flags(flags);
94 cli();
95 outb(reg_no, key + 8);
96 outb(val, key + 0xc);
97 restore_flags(flags);
98 }
99
100 static byte get_cmd640_reg_vlb(int key, int reg_no)
101 {
102 byte b;
103 unsigned long flags;
104
105 save_flags(flags);
106 cli();
107 outb(reg_no, key + 8);
108 b = inb(key + 0xc);
109 restore_flags(flags);
110 return b;
111 }
112
113
114
115
116
117 static int probe_for_cmd640_pci1(void)
118 {
119 long id;
120 int k;
121
122 for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
123 outl(k, 0xcf8);
124 id = inl(0xcfc);
125 if (id != 0x06401095)
126 continue;
127 put_cmd640_reg = put_cmd640_reg_pci1;
128 get_cmd640_reg = get_cmd640_reg_pci1;
129 cmd640_key = k;
130 return 1;
131 }
132 return 0;
133 }
134
135
136
137
138
139 static int probe_for_cmd640_pci2(void)
140 {
141 int i;
142 int v_id;
143 int d_id;
144
145 for (i = 0xc000; i <= 0xcf00; i += 0x100) {
146 outb(0x10, 0xcf8);
147 v_id = inw(i);
148 d_id = inw(i + 2);
149 outb(0, 0xcf8);
150 if (v_id != 0x1095 || d_id != 0x640)
151 continue;
152 put_cmd640_reg = put_cmd640_reg_pci2;
153 get_cmd640_reg = get_cmd640_reg_pci2;
154 cmd640_key = i;
155 return 1;
156 }
157 return 0;
158 }
159
160
161
162
163
164 static int probe_for_cmd640_vlb(void) {
165 byte b;
166
167 outb(0x50, 0x178);
168 b = inb(0x17c);
169 if (b == 0xff || b == 0 || (b & 0x20)) {
170 outb(0x50, 0xc78);
171 b = inb(0x7c);
172 if (b == 0xff || b == 0 || !(b & 0x20))
173 return 0;
174 cmd640_key = 0x70;
175 } else {
176 cmd640_key = 0x170;
177 }
178 put_cmd640_reg = put_cmd640_reg_vlb;
179 get_cmd640_reg = get_cmd640_reg_vlb;
180 return 1;
181 }
182
183
184
185
186
187 int ide_probe_for_cmd640x(void)
188 {
189 int i;
190
191 for (i = 0; i < MAX_HWIFS; i++)
192 is_cmd640[i] = 0;
193
194 if (probe_for_cmd640_pci1()) {
195 bus_type = pci1;
196 } else if (probe_for_cmd640_pci2()) {
197 bus_type = pci2;
198 } else if (cmd640_vlb && probe_for_cmd640_vlb()) {
199
200 bus_type = vlb;
201 } else {
202 return 0;
203 }
204
205
206
207
208
209 put_cmd640_reg(cmd640_key, 0x5b, 0xbd);
210 if (get_cmd640_reg(cmd640_key, 0x5b) != 0xbd) {
211 printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
212 return 0;
213 }
214 put_cmd640_reg(cmd640_key, 0x5b, 0);
215
216
217
218
219
220 cmd640_chip_version = get_cmd640_reg(cmd640_key, 0x50) & 3;
221 if (cmd640_chip_version == 0) {
222 printk ("ide: wrong CMD640 version -- 0\n");
223 return 0;
224 }
225
226 put_cmd640_reg(cmd640_key, 0x51, get_cmd640_reg(cmd640_key, 0x51) | 0xc8);
227 put_cmd640_reg(cmd640_key, 0x57, 0);
228 put_cmd640_reg(cmd640_key, 0x57, get_cmd640_reg(cmd640_key, 0x57) | 0x0c);
229
230 serialized = 1;
231
232 printk("ide: buggy CMD640 interface at ");
233 switch (bus_type) {
234 case vlb :
235 printk("local bus, port 0x%x", cmd640_key);
236 break;
237 case pci1:
238 printk("pci, (0x%x)", cmd640_key);
239 break;
240 case pci2:
241 printk("pci,(access method 2) (0x%x)", cmd640_key);
242 break;
243 }
244
245 is_cmd640[0] = is_cmd640[1] = 1;
246
247
248
249
250
251 put_cmd640_reg(cmd640_key, 0x58, 0);
252 put_cmd640_reg(cmd640_key, 0x52, 0);
253
254 printk("\n ... serialized, disabled read-ahead, secondary interface enabled\n");
255
256 return 1;
257 }
258
259 static int as_clocks(int a) {
260 switch (a & 0xf0) {
261 case 0 : return 4;
262 case 0x40 : return 2;
263 case 0x80 : return 3;
264 case 0xc0 : return 5;
265 default : return -1;
266 }
267 }
268
269
270
271
272
273 static void cmd640_set_timing(int if_num, int dr_num, int r1, int r2) {
274 int b_reg;
275 byte b;
276 int r52;
277
278 b_reg = if_num ? 0x57 : dr_num ? 0x55 : 0x53;
279
280 if (if_num == 0) {
281 put_cmd640_reg(cmd640_key, b_reg, r1);
282 put_cmd640_reg(cmd640_key, b_reg + 1, r2);
283 } else {
284 b = get_cmd640_reg(cmd640_key, b_reg);
285 if ((b&1) == 0) {
286 put_cmd640_reg(cmd640_key, b_reg, r1);
287 } else {
288 if (as_clocks(b) < as_clocks(r1))
289 put_cmd640_reg(cmd640_key, b_reg, r1);
290 }
291 b = get_cmd640_reg(cmd640_key, b_reg + 1);
292 if (b == 0) {
293 put_cmd640_reg(cmd640_key, b_reg + 1, r2);
294 } else {
295 r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
296 r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
297 put_cmd640_reg(cmd640_key, b_reg+1, r52);
298 }
299 }
300
301 b = get_cmd640_reg(cmd640_key, 0x52);
302 if (b == 0) {
303 put_cmd640_reg(cmd640_key, 0x52, r2);
304 } else {
305 r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
306 r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
307 put_cmd640_reg(cmd640_key, 0x52, r52);
308 }
309 }
310
311 static int bus_speed = 33;
312
313 struct pio_timing {
314 int mc_time;
315 int av_time;
316 int ds_time;
317 } pio_timings[6] = {
318 { 70, 165, 600 },
319 { 50, 125, 383 },
320 { 30, 100, 240 },
321 { 30, 80, 180 },
322 { 25, 70, 125 },
323 { 20, 50, 100 }
324 };
325
326 struct drive_pio_info {
327 const char *name;
328 int pio;
329 } drive_pios[] = {
330 { "Maxtor 7131 AT", 1 },
331 { "Maxtor 7171 AT", 1 },
332 { "Maxtor 7213 AT", 1 },
333 { "Maxtor 7245 AT", 1 },
334 { "SAMSUNG SHD-3122A", 1 },
335 { "QUANTUM ELS127A", 0 },
336 { "QUANTUM LPS240A", 0 },
337 { "QUANTUM LPS270A", 3 },
338 { "QUANTUM LPS540A", 3 },
339 { NULL, 0 }
340 };
341
342 static int known_drive_pio(char* name) {
343 struct drive_pio_info* pi;
344
345 for (pi = drive_pios; pi->name != NULL; pi++) {
346 if (strcmp(pi->name, name) == 0)
347 return pi->pio;
348 }
349 return -1;
350 }
351
352 static void cmd640_timings_to_regvals(int mc_time, int av_time, int ds_time,
353 int clock_time,
354 int* r1, int* r2)
355 {
356 int a, b;
357
358 a = (mc_time + clock_time - 1)/clock_time;
359 if (a <= 2) *r1 = 0x40;
360 else if (a == 3) *r1 = 0x80;
361 else if (a == 4) *r1 = 0;
362 else *r1 = 0xc0;
363
364 a = (av_time + clock_time - 1)/clock_time;
365 if (a < 2)
366 a = 2;
367 b = (ds_time + clock_time - 1)/clock_time - a;
368 if (b < 2)
369 b = 2;
370 if (b > 0x11) {
371 a += b - 0x11;
372 b = 0x11;
373 }
374 if (a > 0xf)
375 a = 0;
376 if (cmd640_chip_version > 1)
377 b -= 1;
378 if (b > 0xf)
379 b = 0;
380 *r2 = (a << 4) | b;
381 }
382
383 static void set_pio_mode(int if_num, int drv_num, int mode_num) {
384 int p_base;
385 int i;
386
387 p_base = if_num ? 0x170 : 0x1f0;
388 outb(3, p_base + 1);
389 outb(mode_num | 8, p_base + 2);
390 outb((drv_num | 0xa) << 4, p_base + 6);
391 outb(0xef, p_base + 7);
392 for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
393 delay_10ms();
394 }
395
396 void cmd640_tune_drive(ide_drive_t* drive) {
397 int interface_number;
398 int drive_number;
399 int clock_time;
400 int max_pio;
401 int mc_time, av_time, ds_time;
402 struct hd_driveid* id;
403 int r1, r2;
404
405
406
407
408 interface_number = HWIF(drive) - ide_hwifs;
409 if (!is_cmd640[interface_number])
410 return;
411
412 drive_number = drive - HWIF(drive)->drives;
413 clock_time = 1000/bus_speed;
414 id = drive->id;
415 if ((max_pio = known_drive_pio(id->model)) != -1) {
416 mc_time = pio_timings[max_pio].mc_time;
417 av_time = pio_timings[max_pio].av_time;
418 ds_time = pio_timings[max_pio].ds_time;
419 } else {
420 max_pio = id->tPIO;
421 mc_time = pio_timings[max_pio].mc_time;
422 av_time = pio_timings[max_pio].av_time;
423 ds_time = pio_timings[max_pio].ds_time;
424 if (id->field_valid & 2) {
425 if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
426 if (id->eide_pio_modes & 4) max_pio = 5;
427 else if (id->eide_pio_modes & 2) max_pio = 4;
428 else max_pio = 3;
429 ds_time = id->eide_pio_iordy;
430 mc_time = pio_timings[max_pio].mc_time;
431 av_time = pio_timings[max_pio].av_time;
432 } else {
433 ds_time = id->eide_pio;
434 }
435 if (ds_time == 0)
436 ds_time = pio_timings[max_pio].ds_time;
437 }
438 }
439 cmd640_timings_to_regvals(mc_time, av_time, ds_time, clock_time,
440 &r1, &r2);
441 set_pio_mode(interface_number, drive_number, max_pio);
442 cmd640_set_timing(interface_number, drive_number, r1, r2);
443 printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2);
444 }