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
20
21
22
23
24
25
26
27 #define VID 0x00
28 #define DID 0x02
29 #define PCMD 0x04
30 #define PSTTS 0x06
31 #define REVID 0x08
32 #define PROGIF 0x09
33 #define SUBCL 0x0a
34 #define BASCL 0x0b
35 #define BaseA0 0x10
36 #define BaseA1 0x14
37 #define BaseA2 0x18
38 #define BaseA3 0x1c
39 #define INTLINE 0x3c
40 #define INPINE 0x3d
41
42 #define CFR 0x50
43 #define CFR_DEVREV 0x03
44 #define CFR_IDE01INTR 0x04
45 #define CFR_DEVID 0x18
46 #define CFR_AT_VESA_078h 0x20
47 #define CFR_DSA1 0x40
48 #define CFR_DSA0 0x80
49
50 #define CNTRL 0x51
51 #define CNTRL_DIS_RA0 0x40
52 #define CNTRL_DIS_RA1 0x80
53 #define CNTRL_ENA_2ND 0x08
54
55 #define CMDTIM 0x52
56 #define ARTTIM0 0x53
57 #define DRWTIM0 0x54
58 #define ARTTIM1 0x55
59 #define DRWTIM1 0x56
60 #define ARTTIM23 0x57
61 #define DIS_RA2 0x04
62 #define DIS_RA3 0x08
63 #define DRWTIM23 0x58
64 #define BRST 0x59
65
66
67 static void (*put_cmd640_reg)(int key, int reg_no, int val);
68 static byte (*get_cmd640_reg)(int key, int reg_no);
69
70 enum { none, vlb, pci1, pci2 };
71 static int bus_type = none;
72 static int cmd640_chip_version;
73 static int cmd640_key;
74 static byte is_cmd640[MAX_HWIFS];
75 static int bus_speed;
76
77
78
79
80
81
82
83
84 static void put_cmd640_reg_pci1(int key, int reg_no, int val)
85 {
86 unsigned long flags;
87
88 save_flags(flags);
89 cli();
90 outl_p((reg_no & 0xfc) | key, 0xcf8);
91 outb_p(val, (reg_no & 3) + 0xcfc);
92 restore_flags(flags);
93 }
94
95 static byte get_cmd640_reg_pci1(int key, int reg_no)
96 {
97 byte b;
98 unsigned long flags;
99
100 save_flags(flags);
101 cli();
102 outl_p((reg_no & 0xfc) | key, 0xcf8);
103 b = inb_p(0xcfc + (reg_no & 3));
104 restore_flags(flags);
105 return b;
106 }
107
108
109
110 static void put_cmd640_reg_pci2(int key, int reg_no, int val)
111 {
112 unsigned long flags;
113
114 save_flags(flags);
115 cli();
116 outb_p(0x10, 0xcf8);
117 outb_p(val, key + reg_no);
118 outb_p(0, 0xcf8);
119 restore_flags(flags);
120 }
121
122 static byte get_cmd640_reg_pci2(int key, int reg_no)
123 {
124 byte b;
125 unsigned long flags;
126
127 save_flags(flags);
128 cli();
129 outb_p(0x10, 0xcf8);
130 b = inb_p(key + reg_no);
131 outb_p(0, 0xcf8);
132 restore_flags(flags);
133 return b;
134 }
135
136
137
138 static void put_cmd640_reg_vlb(int key, int reg_no, int val)
139 {
140 unsigned long flags;
141
142 save_flags(flags);
143 cli();
144 outb_p(reg_no, key + 8);
145 outb_p(val, key + 0xc);
146 restore_flags(flags);
147 }
148
149 static byte get_cmd640_reg_vlb(int key, int reg_no)
150 {
151 byte b;
152 unsigned long flags;
153
154 save_flags(flags);
155 cli();
156 outb_p(reg_no, key + 8);
157 b = inb_p(key + 0xc);
158 restore_flags(flags);
159 return b;
160 }
161
162
163
164
165
166 static int probe_for_cmd640_pci1(void)
167 {
168 long id;
169 int k;
170
171 for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
172 outl(k, 0xcf8);
173 id = inl(0xcfc);
174 if (id != 0x06401095)
175 continue;
176 put_cmd640_reg = put_cmd640_reg_pci1;
177 get_cmd640_reg = get_cmd640_reg_pci1;
178 cmd640_key = k;
179 return 1;
180 }
181 return 0;
182 }
183
184
185
186
187
188 static int probe_for_cmd640_pci2(void)
189 {
190 int i;
191 int v_id;
192 int d_id;
193
194 for (i = 0xc000; i <= 0xcf00; i += 0x100) {
195 outb(0x10, 0xcf8);
196 v_id = inw(i);
197 d_id = inw(i + 2);
198 outb(0, 0xcf8);
199 if (v_id != 0x1095 || d_id != 0x640)
200 continue;
201 put_cmd640_reg = put_cmd640_reg_pci2;
202 get_cmd640_reg = get_cmd640_reg_pci2;
203 cmd640_key = i;
204 return 1;
205 }
206 return 0;
207 }
208
209
210
211
212
213 static int probe_for_cmd640_vlb(void) {
214 byte b;
215
216 outb(CFR, 0x178);
217 b = inb(0x17c);
218 if (b == 0xff || b == 0 || (b & CFR_AT_VESA_078h)) {
219 outb(CFR, 0x78);
220 b = inb(0x7c);
221 if (b == 0xff || b == 0 || !(b & CFR_AT_VESA_078h))
222 return 0;
223 cmd640_key = 0x70;
224 } else {
225 cmd640_key = 0x170;
226 }
227 put_cmd640_reg = put_cmd640_reg_vlb;
228 get_cmd640_reg = get_cmd640_reg_vlb;
229 return 1;
230 }
231
232
233
234
235
236 int ide_probe_for_cmd640x(void)
237 {
238 int i;
239 int second_port;
240 int cmd_read_ahead;
241 byte b;
242
243 for (i = 0; i < MAX_HWIFS; i++)
244 is_cmd640[i] = 0;
245
246 if (probe_for_cmd640_pci1()) {
247 bus_type = pci1;
248 } else if (probe_for_cmd640_pci2()) {
249 bus_type = pci2;
250 } else if (cmd640_vlb && probe_for_cmd640_vlb()) {
251
252 bus_type = vlb;
253 } else {
254 return 0;
255 }
256
257
258
259
260
261 put_cmd640_reg(cmd640_key, 0x5b, 0xbd);
262 if (get_cmd640_reg(cmd640_key, 0x5b) != 0xbd) {
263 printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
264 return 0;
265 }
266 put_cmd640_reg(cmd640_key, 0x5b, 0);
267
268
269
270
271
272 cmd640_chip_version = get_cmd640_reg(cmd640_key, CFR) & CFR_DEVREV;
273 if (cmd640_chip_version == 0) {
274 printk ("ide: wrong CMD640 version -- 0\n");
275 return 0;
276 }
277
278
279
280
281 second_port = (bus_type != vlb);
282
283
284
285
286
287
288 bus_speed = (bus_type == vlb) ? 50 : 40;
289
290 #if 1
291
292
293
294 cmd_read_ahead = (cmd640_chip_version > 1);
295 #else
296 cmd_read_ahead = 0;
297 #endif
298
299
300
301 b = get_cmd640_reg(cmd640_key, CNTRL);
302 if (second_port)
303 b |= CNTRL_ENA_2ND;
304 else
305 b &= ~CNTRL_ENA_2ND;
306 if (cmd_read_ahead)
307 b &= ~(CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
308 else
309 b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
310 put_cmd640_reg(cmd640_key, CNTRL, b);
311
312
313
314
315 if (second_port) {
316
317 b = cmd_read_ahead ? 0 : (DIS_RA2 | DIS_RA3);
318 put_cmd640_reg(cmd640_key, ARTTIM23, b);
319 put_cmd640_reg(cmd640_key, DRWTIM23, 0);
320 }
321
322 serialized = 1;
323
324 printk("ide: buggy CMD640%c interface at ",
325 'A' - 1 + cmd640_chip_version);
326 switch (bus_type) {
327 case vlb :
328 printk("local bus, port 0x%x", cmd640_key);
329 break;
330 case pci1:
331 printk("pci, (0x%x)", cmd640_key);
332 break;
333 case pci2:
334 printk("pci,(access method 2) (0x%x)", cmd640_key);
335 break;
336 }
337
338 is_cmd640[0] = is_cmd640[1] = 1;
339
340
341
342
343 put_cmd640_reg(cmd640_key, CMDTIM, 0);
344
345 printk("\n ... serialized, %s read-ahead, secondary interface %s\n",
346 cmd_read_ahead ? "enabled" : "disabled",
347 second_port ? "enabled" : "disabled");
348
349 return 1;
350 }
351
352 static int as_clocks(int a) {
353 switch (a & 0xc0) {
354 case 0 : return 4;
355 case 0x40 : return 2;
356 case 0x80 : return 3;
357 case 0xc0 : return 5;
358 default : return -1;
359 }
360 }
361
362
363
364
365
366 static void cmd640_set_timing(int if_num, int dr_num, int r1, int r2) {
367 int b_reg;
368 byte b;
369 int r52;
370 static int a = 0;
371
372 b_reg = if_num ? ARTTIM23 : dr_num ? ARTTIM1 : ARTTIM0;
373
374 if (if_num == 0) {
375 put_cmd640_reg(cmd640_key, b_reg, r1);
376 put_cmd640_reg(cmd640_key, b_reg + 1, r2);
377 } else {
378 b = get_cmd640_reg(cmd640_key, b_reg);
379 if (a == 0 || as_clocks(b) < as_clocks(r1))
380 put_cmd640_reg(cmd640_key, b_reg, (b & 0xc0) | r1);
381
382 if (a == 0) {
383 put_cmd640_reg(cmd640_key, b_reg + 1, r2);
384 } else {
385 b = get_cmd640_reg(cmd640_key, b_reg + 1);
386 r52 = (b&0x0f) < (r2&0x0f) ? (r2&0x0f) : (b&0x0f);
387 r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
388 put_cmd640_reg(cmd640_key, b_reg+1, r52);
389 }
390 a = 1;
391 }
392
393 b = get_cmd640_reg(cmd640_key, CMDTIM);
394 if (b == 0) {
395 put_cmd640_reg(cmd640_key, CMDTIM, r2);
396 } else {
397 r52 = (b&0x0f) < (r2&0x0f) ? (r2&0x0f) : (b&0x0f);
398 r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
399 put_cmd640_reg(cmd640_key, CMDTIM, r52);
400 }
401 }
402
403 struct pio_timing {
404 int mc_time;
405 int av_time;
406 int ds_time;
407 } pio_timings[6] = {
408 { 70, 165, 600 },
409 { 50, 125, 383 },
410 { 30, 100, 240 },
411 { 30, 80, 180 },
412 { 25, 70, 125 },
413 { 20, 50, 100 }
414 };
415
416 struct drive_pio_info {
417 const char *name;
418 int pio;
419 } drive_pios[] = {
420 { "Maxtor 7131 AT", 1 },
421 { "Maxtor 7171 AT", 1 },
422 { "Maxtor 7213 AT", 1 },
423 { "Maxtor 7245 AT", 1 },
424 { "SAMSUNG SHD-3122A", 1 },
425 { "QUANTUM ELS127A", 0 },
426 { "QUANTUM LPS240A", 0 },
427 { "QUANTUM LPS270A", 3 },
428 { "QUANTUM LPS540A", 3 },
429 { NULL, 0 }
430 };
431
432 static int known_drive_pio(char* name) {
433 struct drive_pio_info* pi;
434
435 for (pi = drive_pios; pi->name != NULL; pi++) {
436 if (strcmp(pi->name, name) == 0)
437 return pi->pio;
438 }
439 return -1;
440 }
441
442 static void cmd640_timings_to_regvals(int mc_time, int av_time, int ds_time,
443 int clock_time,
444 int* r1, int* r2)
445 {
446 int a, b;
447
448 a = (mc_time + clock_time - 1)/clock_time;
449 if (a <= 2) *r1 = 0x40;
450 else if (a == 3) *r1 = 0x80;
451 else if (a == 4) *r1 = 0;
452 else *r1 = 0xc0;
453
454 a = (av_time + clock_time - 1)/clock_time;
455 if (a < 2)
456 a = 2;
457 b = (ds_time + clock_time - 1)/clock_time - a;
458 if (b < 2)
459 b = 2;
460 if (b > 0x11) {
461 a += b - 0x11;
462 b = 0x11;
463 }
464 if (a > 0xf)
465 a = 0;
466 if (cmd640_chip_version > 1)
467 b -= 1;
468 if (b > 0xf)
469 b = 0;
470 *r2 = (a << 4) | b;
471 }
472
473 static void set_pio_mode(int if_num, int drv_num, int mode_num) {
474 int p_base;
475 int i;
476
477 p_base = if_num ? 0x170 : 0x1f0;
478 outb_p(3, p_base + 1);
479 outb_p(mode_num | 8, p_base + 2);
480 outb_p((drv_num | 0xa) << 4, p_base + 6);
481 outb_p(0xef, p_base + 7);
482 for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
483 delay_10ms();
484 }
485
486 void cmd640_tune_drive(ide_drive_t* drive) {
487 int interface_number;
488 int drive_number;
489 int clock_time;
490 int max_pio;
491 int mc_time, av_time, ds_time;
492 struct hd_driveid* id;
493 int r1, r2;
494
495
496
497
498 interface_number = HWIF(drive) - ide_hwifs;
499 if (!is_cmd640[interface_number])
500 return;
501
502 drive_number = drive - HWIF(drive)->drives;
503 clock_time = 1000/bus_speed;
504 id = drive->id;
505 if ((max_pio = known_drive_pio(id->model)) != -1) {
506 mc_time = pio_timings[max_pio].mc_time;
507 av_time = pio_timings[max_pio].av_time;
508 ds_time = pio_timings[max_pio].ds_time;
509 } else {
510 max_pio = id->tPIO;
511 mc_time = pio_timings[max_pio].mc_time;
512 av_time = pio_timings[max_pio].av_time;
513 ds_time = pio_timings[max_pio].ds_time;
514 if (id->field_valid & 2) {
515 if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
516 if (id->eide_pio_modes & 4) max_pio = 5;
517 else if (id->eide_pio_modes & 2) max_pio = 4;
518 else max_pio = 3;
519 ds_time = id->eide_pio_iordy;
520 mc_time = pio_timings[max_pio].mc_time;
521 av_time = pio_timings[max_pio].av_time;
522 } else {
523 ds_time = id->eide_pio;
524 }
525 if (ds_time == 0)
526 ds_time = pio_timings[max_pio].ds_time;
527 }
528 }
529 cmd640_timings_to_regvals(mc_time, av_time, ds_time, clock_time,
530 &r1, &r2);
531 set_pio_mode(interface_number, drive_number, max_pio);
532 cmd640_set_timing(interface_number, drive_number, r1, r2);
533 printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2);
534 }
535