root/drivers/block/cmd640.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. put_cmd640_reg_pci1
  2. get_cmd640_reg_pci1
  3. put_cmd640_reg_pci2
  4. get_cmd640_reg_pci2
  5. put_cmd640_reg_vlb
  6. get_cmd640_reg_vlb
  7. probe_for_cmd640_pci1
  8. probe_for_cmd640_pci2
  9. probe_for_cmd640_vlb
  10. cmd640_reset_controller
  11. ide_probe_for_cmd640x
  12. cmd640_off
  13. set_readahead_mode
  14. strmatch
  15. known_drive_readahead
  16. pack_arttim
  17. pack_counts
  18. max
  19. max4
  20. cmd640_set_timing
  21. cmd640_timings_to_clocks
  22. set_pio_mode
  23. cmd640_set_mode
  24. cmd640_tune_drive

   1 /*
   2  *  linux/drivers/block/cmd640.c        Version 0.07  Jan 27, 1996
   3  *
   4  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
   5  */
   6 
   7 /*
   8  *  Principal Author/Maintainer:  abramov@cecmow.enet.dec.com (Igor Abramov)
   9  *
  10  *  This file provides support for the advanced features and bugs
  11  *  of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
  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        Fixes for vlb initialization code, enable
  18  *                      read-ahead for versions 'B' and 'C' of chip by
  19  *                      default, some code cleanup.
  20  *
  21  *  Version 0.03        Added reset of secondary interface,
  22  *                      and black list for devices which are not compatible
  23  *                      with read ahead mode. Separate function for setting
  24  *                      readahead is added, possibly it will be called some
  25  *                      day from ioctl processing code.
  26  *  
  27  *  Version 0.04        Now configs/compiles separate from ide.c  -ml 
  28  *
  29  *  Version 0.05        Major rewrite of interface timing code.
  30  *                      Added new function cmd640_set_mode to set PIO mode
  31  *                      from ioctl call. New drives added to black list.
  32  *
  33  *  Version 0.06        More code cleanup. Readahead is enabled only for
  34  *                      detected hard drives, not included in readahed
  35  *                      black list.
  36  * 
  37  *  Version 0.07        Changed to more conservative drive tuning policy.
  38  *                      Unknown drives, which report PIO < 4 are set to 
  39  *                      (reported_PIO - 1) if it is supported, or to PIO0.
  40  *                      List of known drives extended by info provided by
  41  *                      CMD at their ftp site.
  42  *
  43  *  Version 0.08        Added autotune/noautotune support.  -ml
  44  *                      
  45  */
  46 
  47 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
  48 
  49 #include <linux/types.h>
  50 #include <linux/kernel.h>
  51 #include <linux/delay.h>
  52 #include <linux/timer.h>
  53 #include <linux/mm.h>
  54 #include <linux/ioport.h>
  55 #include <linux/blkdev.h>
  56 #include <linux/hdreg.h>
  57 #include <asm/io.h>
  58 #include "ide.h"
  59 #include "ide_modes.h"
  60 
  61 int cmd640_vlb = 0;
  62 
  63 /*
  64  * CMD640 specific registers definition.
  65  */
  66 
  67 #define VID             0x00
  68 #define DID             0x02
  69 #define PCMD            0x04
  70 #define PSTTS           0x06
  71 #define REVID           0x08
  72 #define PROGIF          0x09
  73 #define SUBCL           0x0a
  74 #define BASCL           0x0b
  75 #define BaseA0          0x10
  76 #define BaseA1          0x14
  77 #define BaseA2          0x18
  78 #define BaseA3          0x1c
  79 #define INTLINE         0x3c
  80 #define INPINE          0x3d
  81 
  82 #define CFR             0x50
  83 #define   CFR_DEVREV            0x03
  84 #define   CFR_IDE01INTR         0x04
  85 #define   CFR_DEVID             0x18
  86 #define   CFR_AT_VESA_078h      0x20
  87 #define   CFR_DSA1              0x40
  88 #define   CFR_DSA0              0x80
  89 
  90 #define CNTRL           0x51
  91 #define   CNTRL_DIS_RA0         0x40
  92 #define   CNTRL_DIS_RA1         0x80
  93 #define   CNTRL_ENA_2ND         0x08
  94 
  95 #define CMDTIM          0x52
  96 #define ARTTIM0         0x53
  97 #define DRWTIM0         0x54
  98 #define ARTTIM1         0x55
  99 #define DRWTIM1         0x56
 100 #define ARTTIM23        0x57
 101 #define   DIS_RA2               0x04
 102 #define   DIS_RA3               0x08
 103 #define DRWTIM23        0x58
 104 #define BRST            0x59
 105 
 106 static ide_tuneproc_t cmd640_tune_drive;
 107 
 108 /* Interface to access cmd640x registers */
 109 static void (*put_cmd640_reg)(int reg_no, int val);
 110 static byte (*get_cmd640_reg)(int reg_no);
 111 
 112 enum { none, vlb, pci1, pci2 };
 113 static int      bus_type = none;
 114 static int      cmd640_chip_version;
 115 static int      cmd640_key;
 116 static int      bus_speed; /* MHz */
 117 
 118 /*
 119  * For some unknown reasons pcibios functions which read and write registers
 120  * do not always work with cmd640. We use direct IO instead.
 121  */
 122 
 123 /* PCI method 1 access */
 124 
 125 static void put_cmd640_reg_pci1(int reg_no, int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127         unsigned long flags;
 128 
 129         save_flags(flags);
 130         cli();
 131         outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
 132         outb_p(val, (reg_no & 3) + 0xcfc);
 133         restore_flags(flags);
 134 }
 135 
 136 static byte get_cmd640_reg_pci1(int reg_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 137 {
 138         byte b;
 139         unsigned long flags;
 140 
 141         save_flags(flags);
 142         cli();
 143         outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
 144         b = inb_p(0xcfc + (reg_no & 3));
 145         restore_flags(flags);
 146         return b;
 147 }
 148 
 149 /* PCI method 2 access (from CMD datasheet) */
 150  
 151 static void put_cmd640_reg_pci2(int reg_no, int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 152 {
 153         unsigned long flags;
 154 
 155         save_flags(flags);
 156         cli();
 157         outb_p(0x10, 0xcf8);
 158         outb_p(val, cmd640_key + reg_no);
 159         outb_p(0, 0xcf8);
 160         restore_flags(flags);
 161 }
 162 
 163 static byte get_cmd640_reg_pci2(int reg_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 164 {
 165         byte b;
 166         unsigned long flags;
 167 
 168         save_flags(flags);
 169         cli();
 170         outb_p(0x10, 0xcf8);
 171         b = inb_p(cmd640_key + reg_no);
 172         outb_p(0, 0xcf8);
 173         restore_flags(flags);
 174         return b;
 175 }
 176 
 177 /* VLB access */
 178 
 179 static void put_cmd640_reg_vlb(int reg_no, int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181         unsigned long flags;
 182 
 183         save_flags(flags);
 184         cli();
 185         outb_p(reg_no, cmd640_key + 8);
 186         outb_p(val, cmd640_key + 0xc);
 187         restore_flags(flags);
 188 }
 189 
 190 static byte get_cmd640_reg_vlb(int reg_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192         byte b;
 193         unsigned long flags;
 194 
 195         save_flags(flags);
 196         cli();
 197         outb_p(reg_no, cmd640_key + 8);
 198         b = inb_p(cmd640_key + 0xc);
 199         restore_flags(flags);
 200         return b;
 201 }
 202 
 203 /*
 204  * Probe for CMD640x -- pci method 1
 205  */
 206 
 207 static int probe_for_cmd640_pci1(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209         long id;
 210         int     k;
 211 
 212         for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
 213                 outl(k, 0xcf8);
 214                 id = inl(0xcfc);
 215                 if (id != 0x06401095)
 216                         continue;
 217                 put_cmd640_reg = put_cmd640_reg_pci1;
 218                 get_cmd640_reg = get_cmd640_reg_pci1;
 219                 cmd640_key = k;
 220                 return 1;
 221         }
 222         return 0;
 223 }
 224 
 225 /*
 226  * Probe for CMD640x -- pci method 2
 227  */
 228 
 229 static int probe_for_cmd640_pci2(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 230 {
 231         int i;
 232         int v_id;
 233         int d_id;
 234 
 235         for (i = 0xc000; i <= 0xcf00; i += 0x100) {
 236                 outb(0x10, 0xcf8);
 237                 v_id = inw(i);
 238                 d_id = inw(i + 2);
 239                 outb(0, 0xcf8);
 240                 if (v_id != 0x1095 || d_id != 0x640)
 241                         continue;
 242                 put_cmd640_reg = put_cmd640_reg_pci2;
 243                 get_cmd640_reg = get_cmd640_reg_pci2;
 244                 cmd640_key = i;
 245                 return 1;
 246         }
 247         return 0;
 248 }
 249 
 250 /*
 251  * Probe for CMD640x -- vlb
 252  */
 253 
 254 static int probe_for_cmd640_vlb(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 255         byte b;
 256 
 257         outb(CFR, 0x178);
 258         b = inb(0x17c);
 259         if (b == 0xff || b == 0 || (b & CFR_AT_VESA_078h)) {
 260                 outb(CFR, 0x78);
 261                 b = inb(0x7c);
 262                 if (b == 0xff || b == 0 || !(b & CFR_AT_VESA_078h))
 263                         return 0;
 264                 cmd640_key = 0x70;
 265         } else {
 266                 cmd640_key = 0x170;
 267         }
 268         put_cmd640_reg = put_cmd640_reg_vlb;
 269         get_cmd640_reg = get_cmd640_reg_vlb;
 270         return 1;
 271 }
 272 
 273 /*
 274  * Low level reset for controller, actually it has nothing specific for
 275  * CMD640, but I don't know how to use standard reset routine before
 276  * we recognized any drives.
 277  */
 278 
 279 static void cmd640_reset_controller(int iface_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281         int retry_count = 600;
 282         int base_port = iface_no ? 0x170 : 0x1f0;
 283 
 284         outb_p(4, base_port + 7);
 285         udelay(5);
 286         outb_p(0, base_port + 7);
 287 
 288         do {
 289                 udelay(5);
 290                 retry_count -= 1;
 291         } while ((inb_p(base_port + 7) & 0x80) && retry_count);
 292 
 293         if (retry_count == 0)
 294                 printk("cmd640: failed to reset controller %d\n", iface_no);
 295 #if 0   
 296         else
 297                 printk("cmd640: controller %d reset [%d]\n", 
 298                         iface_no, retry_count);
 299 #endif
 300 }
 301 
 302 /*
 303  * Probe for Cmd640x and initialize it if found
 304  */
 305 
 306 int ide_probe_for_cmd640x(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308         int  second_port;
 309         byte b;
 310 
 311         if (probe_for_cmd640_pci1()) {
 312                 bus_type = pci1;
 313         } else if (probe_for_cmd640_pci2()) {
 314                 bus_type = pci2;
 315         } else if (cmd640_vlb && probe_for_cmd640_vlb()) {
 316                 /* May be remove cmd640_vlb at all, and probe in any case */
 317                 bus_type = vlb;
 318         } else {
 319                 return 0;
 320         }
 321 
 322         ide_hwifs[0].serialized = 1;    /* ensure this *always* gets set */
 323         
 324 #if 0   
 325         /* Dump initial state of chip registers */
 326         for (b = 0; b != 0xff; b++) {
 327                 printk(" %2x%c", get_cmd640_reg(b),
 328                                 ((b&0xf) == 0xf) ? '\n' : ',');
 329         }
 330 
 331 #endif
 332 
 333         /*
 334          * Undocumented magic. (There is no 0x5b port in specs)
 335          */
 336 
 337         put_cmd640_reg(0x5b, 0xbd);
 338         if (get_cmd640_reg(0x5b) != 0xbd) {
 339                 printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
 340                 return 0;
 341         }
 342         put_cmd640_reg(0x5b, 0);
 343 
 344         /*
 345          * Documented magic.
 346          */
 347 
 348         cmd640_chip_version = get_cmd640_reg(CFR) & CFR_DEVREV;
 349         if (cmd640_chip_version == 0) {
 350                 printk ("ide: wrong CMD640 version -- 0\n");
 351                 return 0;
 352         }
 353 
 354         /*
 355          * Setup the most conservative timings for all drives,
 356          */
 357         put_cmd640_reg(ARTTIM0, 0xc0);
 358         put_cmd640_reg(ARTTIM1, 0xc0);
 359         put_cmd640_reg(ARTTIM23, 0xcc); /* 0xc0? */
 360 
 361         /*
 362          * Do not initialize secondary controller for vlbus
 363          */
 364         second_port = (bus_type != vlb);
 365 
 366         /*
 367          * Set the maximum allowed bus speed (it is safest until we
 368          *                                    find how to detect bus speed)
 369          * Normally PCI bus runs at 33MHz, but often works overclocked to 40
 370          */
 371         bus_speed = (bus_type == vlb) ? 50 : 40; 
 372 
 373         /*
 374          * Setup Control Register
 375          */
 376         b = get_cmd640_reg(CNTRL);      
 377 
 378         if (second_port)
 379                 b |= CNTRL_ENA_2ND;
 380         else
 381                 b &= ~CNTRL_ENA_2ND;
 382 
 383         /*
 384          * Disable readahead for drives at primary interface
 385          */
 386         b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
 387 
 388         put_cmd640_reg(CNTRL, b);
 389 
 390         /*
 391          * Note that we assume that the first interface is at 0x1f0,
 392          * and that the second interface, if enabled, is at 0x170.
 393          */
 394         ide_hwifs[0].chipset = ide_cmd640;
 395         ide_hwifs[0].tuneproc = &cmd640_tune_drive;
 396         if (ide_hwifs[0].drives[0].autotune == 0)
 397                 ide_hwifs[0].drives[0].autotune = 1;
 398         if (ide_hwifs[0].drives[1].autotune == 0)
 399                 ide_hwifs[0].drives[1].autotune = 1;
 400 
 401         /*
 402          * Initialize 2nd IDE port, if required
 403          */
 404         if (second_port) {
 405                 ide_hwifs[1].chipset = ide_cmd640;
 406                 ide_hwifs[1].tuneproc = &cmd640_tune_drive;
 407                 if (ide_hwifs[1].drives[0].autotune == 0)
 408                         ide_hwifs[1].drives[0].autotune = 1;
 409                 if (ide_hwifs[1].drives[1].autotune == 0)
 410                         ide_hwifs[1].drives[1].autotune = 1;
 411                 /* We reset timings, and disable read-ahead */
 412                 put_cmd640_reg(ARTTIM23, (DIS_RA2 | DIS_RA3));
 413                 put_cmd640_reg(DRWTIM23, 0);
 414 
 415                 cmd640_reset_controller(1);
 416         }
 417 
 418         printk("ide: buggy CMD640%c interface at ", 
 419                'A' - 1 + cmd640_chip_version);
 420         switch (bus_type) {
 421                 case vlb :
 422                         printk("local bus, port 0x%x", cmd640_key);
 423                         break;
 424                 case pci1:
 425                         printk("pci, (0x%x)", cmd640_key);
 426                         break;
 427                 case pci2:
 428                         printk("pci,(access method 2) (0x%x)", cmd640_key);
 429                         break;
 430         }
 431 
 432         /*
 433          * Reset interface timings
 434          */
 435         put_cmd640_reg(CMDTIM, 0);
 436 
 437         printk("\n ... serialized, secondary interface %s\n",
 438                second_port ? "enabled" : "disabled");
 439 
 440         return 1;
 441 }
 442 
 443 int cmd640_off(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 444         static int a = 0;
 445         byte b;
 446 
 447         if (bus_type == none || a == 1)
 448                 return 0;
 449         a = 1;
 450         b = get_cmd640_reg(CNTRL);      
 451         b &= ~CNTRL_ENA_2ND;
 452         put_cmd640_reg(CNTRL, b);
 453         return 1;
 454 }
 455 
 456 /*
 457  * Sets readahead mode for specific drive
 458  *  in the future it could be called from ioctl
 459  */
 460 
 461 static void set_readahead_mode(int mode, int if_num, int dr_num)
     /* [previous][next][first][last][top][bottom][index][help] */
 462 {
 463         static int masks[2][2] = 
 464                 { 
 465                         {CNTRL_DIS_RA0, CNTRL_DIS_RA1}, 
 466                         {DIS_RA2,       DIS_RA3}
 467                 };
 468 
 469         int port = (if_num == 0) ? CNTRL : ARTTIM23;
 470         int mask = masks[if_num][dr_num];
 471         byte b;
 472 
 473         b = get_cmd640_reg(port);
 474         if (mode)
 475                 b &= ~mask;     /* Enable readahead for specific drive */
 476         else
 477                 b |= mask;      /* Disable readahed for specific drive */
 478         put_cmd640_reg(port, b);
 479 }               
 480 
 481 static struct readahead_black_list {
 482         const char*     name;
 483         int             mode;   
 484 } drives_ra[] = {
 485         { "QUANTUM LIGHTNING 540A", 0 },
 486         { "ST3655A",    0 },
 487         { "SAMSUNG",    0 },    /* Be conservative */
 488         { NULL, 0 }
 489 };      
 490 
 491 static int strmatch(const char* pattern, const char* name) {
     /* [previous][next][first][last][top][bottom][index][help] */
 492         char c1, c2;
 493 
 494         while (1) {
 495                 c1 = *pattern++;
 496                 c2 = *name++;
 497                 if (c1 == 0) {
 498                         return 0;
 499                 }
 500                 if (c1 != c2)
 501                         return 1;
 502         }
 503 }
 504 
 505 static int known_drive_readahead(char* name) {
     /* [previous][next][first][last][top][bottom][index][help] */
 506         int i;
 507 
 508         for (i = 0; drives_ra[i].name != NULL; i++) {
 509                 if (strmatch(drives_ra[i].name, name) == 0) {
 510                         return drives_ra[i].mode;
 511                 }
 512         }
 513         return -1;
 514 }
 515 
 516 static int arttim[4]  = {2, 2, 2, 2};   /* Address setup count (in clocks) */
 517 static int a_count[4] = {1, 1, 1, 1};   /* Active count   (encoded) */
 518 static int r_count[4] = {1, 1, 1, 1};   /* Recovery count (encoded) */
 519 
 520 /*
 521  * Convert address setup count from number of clocks 
 522  * to representation used by controller
 523  */
 524 
 525 inline static int pack_arttim(int clocks)
     /* [previous][next][first][last][top][bottom][index][help] */
 526 {
 527         if (clocks <= 2) return 0x40;
 528         else if (clocks == 3) return 0x80;
 529         else if (clocks == 4) return 0x00;
 530         else return 0xc0;
 531 }
 532 
 533 /*
 534  * Pack active and recovery counts into single byte representation
 535  * used by controller
 536  */
 537 
 538 inline static int pack_counts(int act_count, int rec_count)
     /* [previous][next][first][last][top][bottom][index][help] */
 539 {
 540         return ((act_count & 0x0f)<<4) | (rec_count & 0x0f);
 541 }
 542 
 543 inline int max(int a, int b) { return a > b ? a : b; }
     /* [previous][next][first][last][top][bottom][index][help] */
 544 inline int max4(int *p) { return max(p[0], max(p[1], max(p[2], p[3]))); }
     /* [previous][next][first][last][top][bottom][index][help] */
 545 
 546 /*
 547  * Set timing parameters
 548  */
 549 
 550 static void cmd640_set_timing(int if_num, int dr_num)
     /* [previous][next][first][last][top][bottom][index][help] */
 551 {
 552         int     b_reg;
 553         int     ac, rc, at;
 554 
 555         /*
 556          * Set address setup count and drive read/write timing registers.
 557          * Primary interface has individual count/timing registers for
 558          * each drive. Secondary interface has common set of registers, and
 559          * we should set timings for the slowest drive.
 560          */
 561 
 562         if (if_num == 0) {
 563                 b_reg = dr_num ? ARTTIM1 : ARTTIM0;
 564                 at = arttim[dr_num];
 565                 ac = a_count[dr_num];
 566                 rc = r_count[dr_num];
 567         } else {
 568                 b_reg = ARTTIM23;
 569                 at = max(arttim[2], arttim[3]);
 570                 ac = max(a_count[2], a_count[3]);
 571                 rc = max(r_count[2], r_count[3]);
 572         }
 573 
 574         put_cmd640_reg(b_reg, pack_arttim(at));
 575         put_cmd640_reg(b_reg + 1, pack_counts(ac, rc));
 576 
 577         /*
 578          * Update CMDTIM (IDE Command Block Timing Register) 
 579          */
 580 
 581         ac = max4(r_count);
 582         rc = max4(a_count);
 583         put_cmd640_reg(CMDTIM, pack_counts(ac, rc));
 584 }
 585 
 586 /*
 587  * Standard timings for PIO modes
 588  */
 589 
 590 static struct pio_timing {
 591         int     mc_time;        /* Minimal cycle time (ns) */
 592         int     av_time;        /* Address valid to DIOR-/DIOW- setup (ns) */
 593         int     ds_time;        /* DIOR data setup      (ns) */
 594 } pio_timings[6] = {
 595         { 70,   165,    600 },  /* PIO Mode 0 */
 596         { 50,   125,    383 },  /* PIO Mode 1 */
 597         { 30,   100,    240 },  /* PIO Mode 2 */
 598         { 30,   80,     180 },  /* PIO Mode 3 */
 599         { 25,   70,     125 },  /* PIO Mode 4  -- should be 120, not 125 */
 600         { 20,   50,     100 }   /* PIO Mode ? (nonstandard) */
 601 };
 602 
 603 static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time,
     /* [previous][next][first][last][top][bottom][index][help] */
 604                                 int clock_time, int drv_idx)
 605 {
 606         int a, b;
 607 
 608         arttim[drv_idx] = (mc_time + clock_time - 1)/clock_time;
 609 
 610         a = (av_time + clock_time - 1)/clock_time;
 611         if (a < 2)
 612                 a = 2;
 613         b = (ds_time + clock_time - 1)/clock_time - a;
 614         if (b < 2)
 615                 b = 2;
 616         if (b > 0x11) {
 617                 a += b - 0x11;
 618                 b = 0x11;
 619         }
 620         if (a > 0x10)
 621                 a = 0x10;
 622         if (cmd640_chip_version > 1)
 623                 b -= 1;
 624         if (b > 0x10)
 625                 b = 0x10;
 626 
 627         a_count[drv_idx] = a;
 628         r_count[drv_idx] = b;
 629 }
 630 
 631 static void set_pio_mode(int if_num, int drv_num, int mode_num) {
     /* [previous][next][first][last][top][bottom][index][help] */
 632         int p_base;
 633         int i;
 634 
 635         p_base = if_num ? 0x170 : 0x1f0;
 636         outb_p(3, p_base + 1);
 637         outb_p(mode_num | 8, p_base + 2);
 638         outb_p((drv_num | 0xa) << 4, p_base + 6);
 639         outb_p(0xef, p_base + 7);
 640         for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
 641                 udelay(10000);
 642 }
 643 
 644 /*
 645  * Set a specific pio_mode for a drive
 646  */
 647 
 648 static void cmd640_set_mode(ide_drive_t* drive, int pio_mode) {
     /* [previous][next][first][last][top][bottom][index][help] */
 649         int interface_number;
 650         int drive_number;
 651         int clock_time; /* ns */
 652         int mc_time, av_time, ds_time;
 653 
 654         interface_number = HWIF(drive)->index;
 655         drive_number = drive->select.b.unit;
 656         clock_time = 1000/bus_speed;
 657 
 658         mc_time = pio_timings[pio_mode].mc_time;
 659         av_time = pio_timings[pio_mode].av_time;
 660         ds_time = pio_timings[pio_mode].ds_time;
 661 
 662         cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
 663                                 interface_number*2 + drive_number);
 664         set_pio_mode(interface_number, drive_number, pio_mode);
 665         cmd640_set_timing(interface_number, drive_number);
 666 }
 667 
 668 /*
 669  * Drive PIO mode "autoconfiguration".
 670  * Ideally, this code should *always* call cmd640_set_mode(), but it doesn't.
 671  */
 672 
 673 static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) {
     /* [previous][next][first][last][top][bottom][index][help] */
 674         int interface_number;
 675         int drive_number;
 676         int clock_time; /* ns */
 677         int max_pio;
 678         int mc_time, av_time, ds_time;
 679         struct hd_driveid* id;
 680         int readahead;  /* there is a global named read_ahead */
 681 
 682         if (pio_mode != 255) {
 683                 cmd640_set_mode(drive, pio_mode);
 684                 return;
 685         }
 686 
 687         interface_number = HWIF(drive)->index;
 688         drive_number = drive->select.b.unit;
 689         clock_time = 1000/bus_speed;
 690         id = drive->id;
 691         if ((max_pio = ide_scan_pio_blacklist(id->model)) != -1) {
 692                 ds_time = pio_timings[max_pio].ds_time;
 693         } else {
 694                 max_pio = id->tPIO;
 695                 ds_time = pio_timings[max_pio].ds_time;
 696                 if (id->field_valid & 2) {
 697                         if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
 698                                 if (id->eide_pio_modes & 4) max_pio = 5;
 699                                 else if (id->eide_pio_modes & 2) max_pio = 4;
 700                                 else max_pio = 3;
 701                                 ds_time = id->eide_pio_iordy;
 702                         } else {
 703                                 ds_time = id->eide_pio;
 704                         }
 705                         if (ds_time == 0)
 706                                 ds_time = pio_timings[max_pio].ds_time;
 707                 }
 708 
 709                 /*
 710                  * Conservative "downgrade"
 711                  */
 712                 if (max_pio < 4 && max_pio != 0) {
 713                         max_pio -= 1;
 714                         ds_time = pio_timings[max_pio].ds_time;         
 715                 }
 716         }
 717         mc_time = pio_timings[max_pio].mc_time;
 718         av_time = pio_timings[max_pio].av_time;
 719         cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
 720                                 interface_number*2 + drive_number);
 721         set_pio_mode(interface_number, drive_number, max_pio);
 722         cmd640_set_timing(interface_number, drive_number);
 723 
 724         /*
 725          * Disable (or set) readahead mode
 726          */
 727 
 728         readahead = 0;
 729         if (cmd640_chip_version > 1) {  /* Mmmm.. probably should be > 2 ?? */
 730                 readahead = known_drive_readahead(id->model);
 731                 if (readahead == -1)
 732                         readahead = 1;  /* Mmmm.. probably be 0 ?? */
 733                 set_readahead_mode(readahead, interface_number, drive_number);
 734         }   
 735 
 736         printk ("Mode and Timing set to PIO%d, Readahead is %s\n", 
 737                 max_pio, readahead ? "enabled" : "disabled");
 738 }
 739 

/* [previous][next][first][last][top][bottom][index][help] */