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. known_drive_pio
  22. cmd640_timings_to_clocks
  23. set_pio_mode
  24. cmd640_set_mode
  25. 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 
  60 int cmd640_vlb = 0;
  61 
  62 /*
  63  * CMD640 specific registers definition.
  64  */
  65 
  66 #define VID             0x00
  67 #define DID             0x02
  68 #define PCMD            0x04
  69 #define PSTTS           0x06
  70 #define REVID           0x08
  71 #define PROGIF          0x09
  72 #define SUBCL           0x0a
  73 #define BASCL           0x0b
  74 #define BaseA0          0x10
  75 #define BaseA1          0x14
  76 #define BaseA2          0x18
  77 #define BaseA3          0x1c
  78 #define INTLINE         0x3c
  79 #define INPINE          0x3d
  80 
  81 #define CFR             0x50
  82 #define   CFR_DEVREV            0x03
  83 #define   CFR_IDE01INTR         0x04
  84 #define   CFR_DEVID             0x18
  85 #define   CFR_AT_VESA_078h      0x20
  86 #define   CFR_DSA1              0x40
  87 #define   CFR_DSA0              0x80
  88 
  89 #define CNTRL           0x51
  90 #define   CNTRL_DIS_RA0         0x40
  91 #define   CNTRL_DIS_RA1         0x80
  92 #define   CNTRL_ENA_2ND         0x08
  93 
  94 #define CMDTIM          0x52
  95 #define ARTTIM0         0x53
  96 #define DRWTIM0         0x54
  97 #define ARTTIM1         0x55
  98 #define DRWTIM1         0x56
  99 #define ARTTIM23        0x57
 100 #define   DIS_RA2               0x04
 101 #define   DIS_RA3               0x08
 102 #define DRWTIM23        0x58
 103 #define BRST            0x59
 104 
 105 static ide_tuneproc_t cmd640_tune_drive;
 106 
 107 /* Interface to access cmd640x registers */
 108 static void (*put_cmd640_reg)(int reg_no, int val);
 109 static byte (*get_cmd640_reg)(int reg_no);
 110 
 111 enum { none, vlb, pci1, pci2 };
 112 static int      bus_type = none;
 113 static int      cmd640_chip_version;
 114 static int      cmd640_key;
 115 static int      bus_speed; /* MHz */
 116 
 117 /*
 118  * For some unknown reasons pcibios functions which read and write registers
 119  * do not always work with cmd640. We use direct IO instead.
 120  */
 121 
 122 /* PCI method 1 access */
 123 
 124 static void put_cmd640_reg_pci1(int reg_no, int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         unsigned long flags;
 127 
 128         save_flags(flags);
 129         cli();
 130         outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
 131         outb_p(val, (reg_no & 3) + 0xcfc);
 132         restore_flags(flags);
 133 }
 134 
 135 static byte get_cmd640_reg_pci1(int reg_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 136 {
 137         byte b;
 138         unsigned long flags;
 139 
 140         save_flags(flags);
 141         cli();
 142         outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
 143         b = inb_p(0xcfc + (reg_no & 3));
 144         restore_flags(flags);
 145         return b;
 146 }
 147 
 148 /* PCI method 2 access (from CMD datasheet) */
 149  
 150 static void put_cmd640_reg_pci2(int reg_no, int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152         unsigned long flags;
 153 
 154         save_flags(flags);
 155         cli();
 156         outb_p(0x10, 0xcf8);
 157         outb_p(val, cmd640_key + reg_no);
 158         outb_p(0, 0xcf8);
 159         restore_flags(flags);
 160 }
 161 
 162 static byte get_cmd640_reg_pci2(int reg_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 163 {
 164         byte b;
 165         unsigned long flags;
 166 
 167         save_flags(flags);
 168         cli();
 169         outb_p(0x10, 0xcf8);
 170         b = inb_p(cmd640_key + reg_no);
 171         outb_p(0, 0xcf8);
 172         restore_flags(flags);
 173         return b;
 174 }
 175 
 176 /* VLB access */
 177 
 178 static void put_cmd640_reg_vlb(int reg_no, int val)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180         unsigned long flags;
 181 
 182         save_flags(flags);
 183         cli();
 184         outb_p(reg_no, cmd640_key + 8);
 185         outb_p(val, cmd640_key + 0xc);
 186         restore_flags(flags);
 187 }
 188 
 189 static byte get_cmd640_reg_vlb(int reg_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191         byte b;
 192         unsigned long flags;
 193 
 194         save_flags(flags);
 195         cli();
 196         outb_p(reg_no, cmd640_key + 8);
 197         b = inb_p(cmd640_key + 0xc);
 198         restore_flags(flags);
 199         return b;
 200 }
 201 
 202 /*
 203  * Probe for CMD640x -- pci method 1
 204  */
 205 
 206 static int probe_for_cmd640_pci1(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 207 {
 208         long id;
 209         int     k;
 210 
 211         for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
 212                 outl(k, 0xcf8);
 213                 id = inl(0xcfc);
 214                 if (id != 0x06401095)
 215                         continue;
 216                 put_cmd640_reg = put_cmd640_reg_pci1;
 217                 get_cmd640_reg = get_cmd640_reg_pci1;
 218                 cmd640_key = k;
 219                 return 1;
 220         }
 221         return 0;
 222 }
 223 
 224 /*
 225  * Probe for CMD640x -- pci method 2
 226  */
 227 
 228 static int probe_for_cmd640_pci2(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 229 {
 230         int i;
 231         int v_id;
 232         int d_id;
 233 
 234         for (i = 0xc000; i <= 0xcf00; i += 0x100) {
 235                 outb(0x10, 0xcf8);
 236                 v_id = inw(i);
 237                 d_id = inw(i + 2);
 238                 outb(0, 0xcf8);
 239                 if (v_id != 0x1095 || d_id != 0x640)
 240                         continue;
 241                 put_cmd640_reg = put_cmd640_reg_pci2;
 242                 get_cmd640_reg = get_cmd640_reg_pci2;
 243                 cmd640_key = i;
 244                 return 1;
 245         }
 246         return 0;
 247 }
 248 
 249 /*
 250  * Probe for CMD640x -- vlb
 251  */
 252 
 253 static int probe_for_cmd640_vlb(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 254         byte b;
 255 
 256         outb(CFR, 0x178);
 257         b = inb(0x17c);
 258         if (b == 0xff || b == 0 || (b & CFR_AT_VESA_078h)) {
 259                 outb(CFR, 0x78);
 260                 b = inb(0x7c);
 261                 if (b == 0xff || b == 0 || !(b & CFR_AT_VESA_078h))
 262                         return 0;
 263                 cmd640_key = 0x70;
 264         } else {
 265                 cmd640_key = 0x170;
 266         }
 267         put_cmd640_reg = put_cmd640_reg_vlb;
 268         get_cmd640_reg = get_cmd640_reg_vlb;
 269         return 1;
 270 }
 271 
 272 /*
 273  * Low level reset for controller, actually it has nothing specific for
 274  * CMD640, but I don't know how to use standard reset routine before
 275  * we recognized any drives.
 276  */
 277 
 278 static void cmd640_reset_controller(int iface_no)
     /* [previous][next][first][last][top][bottom][index][help] */
 279 {
 280         int retry_count = 600;
 281         int base_port = iface_no ? 0x170 : 0x1f0;
 282 
 283         outb_p(4, base_port + 7);
 284         udelay(5);
 285         outb_p(0, base_port + 7);
 286 
 287         do {
 288                 udelay(5);
 289                 retry_count -= 1;
 290         } while ((inb_p(base_port + 7) & 0x80) && retry_count);
 291 
 292         if (retry_count == 0)
 293                 printk("cmd640: failed to reset controller %d\n", iface_no);
 294 #if 0   
 295         else
 296                 printk("cmd640: controller %d reset [%d]\n", 
 297                         iface_no, retry_count);
 298 #endif
 299 }
 300 
 301 /*
 302  * Probe for Cmd640x and initialize it if found
 303  */
 304 
 305 int ide_probe_for_cmd640x(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 306 {
 307         int  second_port;
 308         byte b;
 309 
 310         if (probe_for_cmd640_pci1()) {
 311                 bus_type = pci1;
 312         } else if (probe_for_cmd640_pci2()) {
 313                 bus_type = pci2;
 314         } else if (cmd640_vlb && probe_for_cmd640_vlb()) {
 315                 /* May be remove cmd640_vlb at all, and probe in any case */
 316                 bus_type = vlb;
 317         } else {
 318                 return 0;
 319         }
 320 
 321         ide_hwifs[0].serialized = 1;    /* ensure this *always* gets set */
 322         
 323 #if 0   
 324         /* Dump initial state of chip registers */
 325         for (b = 0; b != 0xff; b++) {
 326                 printk(" %2x%c", get_cmd640_reg(b),
 327                                 ((b&0xf) == 0xf) ? '\n' : ',');
 328         }
 329 
 330 #endif
 331 
 332         /*
 333          * Undocumented magic. (There is no 0x5b port in specs)
 334          */
 335 
 336         put_cmd640_reg(0x5b, 0xbd);
 337         if (get_cmd640_reg(0x5b) != 0xbd) {
 338                 printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
 339                 return 0;
 340         }
 341         put_cmd640_reg(0x5b, 0);
 342 
 343         /*
 344          * Documented magic.
 345          */
 346 
 347         cmd640_chip_version = get_cmd640_reg(CFR) & CFR_DEVREV;
 348         if (cmd640_chip_version == 0) {
 349                 printk ("ide: wrong CMD640 version -- 0\n");
 350                 return 0;
 351         }
 352 
 353         /*
 354          * Setup the most conservative timings for all drives,
 355          */
 356         put_cmd640_reg(ARTTIM0, 0xc0);
 357         put_cmd640_reg(ARTTIM1, 0xc0);
 358         put_cmd640_reg(ARTTIM23, 0xcc); /* 0xc0? */
 359 
 360         /*
 361          * Do not initialize secondary controller for vlbus
 362          */
 363         second_port = (bus_type != vlb);
 364 
 365         /*
 366          * Set the maximum allowed bus speed (it is safest until we
 367          *                                    find how to detect bus speed)
 368          * Normally PCI bus runs at 33MHz, but often works overclocked to 40
 369          */
 370         bus_speed = (bus_type == vlb) ? 50 : 40; 
 371 
 372         /*
 373          * Setup Control Register
 374          */
 375         b = get_cmd640_reg(CNTRL);      
 376 
 377         if (second_port)
 378                 b |= CNTRL_ENA_2ND;
 379         else
 380                 b &= ~CNTRL_ENA_2ND;
 381 
 382         /*
 383          * Disable readahead for drives at primary interface
 384          */
 385         b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
 386 
 387         put_cmd640_reg(CNTRL, b);
 388 
 389         /*
 390          * Note that we assume that the first interface is at 0x1f0,
 391          * and that the second interface, if enabled, is at 0x170.
 392          */
 393         ide_hwifs[0].chipset = ide_cmd640;
 394         ide_hwifs[0].tuneproc = &cmd640_tune_drive;
 395         if (ide_hwifs[0].drives[0].autotune == 0)
 396                 ide_hwifs[0].drives[0].autotune = 1;
 397         if (ide_hwifs[0].drives[1].autotune == 0)
 398                 ide_hwifs[0].drives[1].autotune = 1;
 399 
 400         /*
 401          * Initialize 2nd IDE port, if required
 402          */
 403         if (second_port) {
 404                 ide_hwifs[1].chipset = ide_cmd640;
 405                 ide_hwifs[1].tuneproc = &cmd640_tune_drive;
 406                 if (ide_hwifs[1].drives[0].autotune == 0)
 407                         ide_hwifs[1].drives[0].autotune = 1;
 408                 if (ide_hwifs[1].drives[1].autotune == 0)
 409                         ide_hwifs[1].drives[1].autotune = 1;
 410                 /* We reset timings, and disable read-ahead */
 411                 put_cmd640_reg(ARTTIM23, (DIS_RA2 | DIS_RA3));
 412                 put_cmd640_reg(DRWTIM23, 0);
 413 
 414                 cmd640_reset_controller(1);
 415         }
 416 
 417         printk("ide: buggy CMD640%c interface at ", 
 418                'A' - 1 + cmd640_chip_version);
 419         switch (bus_type) {
 420                 case vlb :
 421                         printk("local bus, port 0x%x", cmd640_key);
 422                         break;
 423                 case pci1:
 424                         printk("pci, (0x%x)", cmd640_key);
 425                         break;
 426                 case pci2:
 427                         printk("pci,(access method 2) (0x%x)", cmd640_key);
 428                         break;
 429         }
 430 
 431         /*
 432          * Reset interface timings
 433          */
 434         put_cmd640_reg(CMDTIM, 0);
 435 
 436         printk("\n ... serialized, secondary interface %s\n",
 437                second_port ? "enabled" : "disabled");
 438 
 439         return 1;
 440 }
 441 
 442 int cmd640_off(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 443         static int a = 0;
 444         byte b;
 445 
 446         if (bus_type == none || a == 1)
 447                 return 0;
 448         a = 1;
 449         b = get_cmd640_reg(CNTRL);      
 450         b &= ~CNTRL_ENA_2ND;
 451         put_cmd640_reg(CNTRL, b);
 452         return 1;
 453 }
 454 
 455 /*
 456  * Sets readahead mode for specific drive
 457  *  in the future it could be called from ioctl
 458  */
 459 
 460 static void set_readahead_mode(int mode, int if_num, int dr_num)
     /* [previous][next][first][last][top][bottom][index][help] */
 461 {
 462         static int masks[2][2] = 
 463                 { 
 464                         {CNTRL_DIS_RA0, CNTRL_DIS_RA1}, 
 465                         {DIS_RA2,       DIS_RA3}
 466                 };
 467 
 468         int port = (if_num == 0) ? CNTRL : ARTTIM23;
 469         int mask = masks[if_num][dr_num];
 470         byte b;
 471 
 472         b = get_cmd640_reg(port);
 473         if (mode)
 474                 b &= ~mask;     /* Enable readahead for specific drive */
 475         else
 476                 b |= mask;      /* Disable readahed for specific drive */
 477         put_cmd640_reg(port, b);
 478 }               
 479 
 480 static struct readahead_black_list {
 481         const char*     name;
 482         int             mode;   
 483 } drives_ra[] = {
 484         { "ST3655A",    0 },
 485         { "SAMSUNG",    0 },    /* Be conservative */
 486         { NULL, 0 }
 487 };      
 488 
 489 static int strmatch(const char* pattern, const char* name) {
     /* [previous][next][first][last][top][bottom][index][help] */
 490         char c1, c2;
 491 
 492         while (1) {
 493                 c1 = *pattern++;
 494                 c2 = *name++;
 495                 if (c1 == 0) {
 496                         return 0;
 497                 }
 498                 if (c1 != c2)
 499                         return 1;
 500         }
 501 }
 502 
 503 static int known_drive_readahead(char* name) {
     /* [previous][next][first][last][top][bottom][index][help] */
 504         int i;
 505 
 506         for (i = 0; drives_ra[i].name != NULL; i++) {
 507                 if (strmatch(drives_ra[i].name, name) == 0) {
 508                         return drives_ra[i].mode;
 509                 }
 510         }
 511         return -1;
 512 }
 513 
 514 static int arttim[4]  = {2, 2, 2, 2};   /* Address setup count (in clocks) */
 515 static int a_count[4] = {1, 1, 1, 1};   /* Active count   (encoded) */
 516 static int r_count[4] = {1, 1, 1, 1};   /* Recovery count (encoded) */
 517 
 518 /*
 519  * Convert address setup count from number of clocks 
 520  * to representation used by controller
 521  */
 522 
 523 inline static int pack_arttim(int clocks)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525         if (clocks <= 2) return 0x40;
 526         else if (clocks == 3) return 0x80;
 527         else if (clocks == 4) return 0x00;
 528         else return 0xc0;
 529 }
 530 
 531 /*
 532  * Pack active and recovery counts into single byte representation
 533  * used by controller
 534  */
 535 
 536 inline static int pack_counts(int act_count, int rec_count)
     /* [previous][next][first][last][top][bottom][index][help] */
 537 {
 538         return ((act_count & 0x0f)<<4) | (rec_count & 0x0f);
 539 }
 540 
 541 inline int max(int a, int b) { return a > b ? a : b; }
     /* [previous][next][first][last][top][bottom][index][help] */
 542 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] */
 543 
 544 /*
 545  * Set timing parameters
 546  */
 547 
 548 static void cmd640_set_timing(int if_num, int dr_num)
     /* [previous][next][first][last][top][bottom][index][help] */
 549 {
 550         int     b_reg;
 551         int     ac, rc, at;
 552 
 553         /*
 554          * Set address setup count and drive read/write timing registers.
 555          * Primary interface has individual count/timing registers for
 556          * each drive. Secondary interface has common set of registers, and
 557          * we should set timings for the slowest drive.
 558          */
 559 
 560         if (if_num == 0) {
 561                 b_reg = dr_num ? ARTTIM1 : ARTTIM0;
 562                 at = arttim[dr_num];
 563                 ac = a_count[dr_num];
 564                 rc = r_count[dr_num];
 565         } else {
 566                 b_reg = ARTTIM23;
 567                 at = max(arttim[2], arttim[3]);
 568                 ac = max(a_count[2], a_count[3]);
 569                 rc = max(r_count[2], r_count[3]);
 570         }
 571 
 572         put_cmd640_reg(b_reg, pack_arttim(at));
 573         put_cmd640_reg(b_reg + 1, pack_counts(ac, rc));
 574 
 575         /*
 576          * Update CMDTIM (IDE Command Block Timing Register) 
 577          */
 578 
 579         ac = max4(r_count);
 580         rc = max4(a_count);
 581         put_cmd640_reg(CMDTIM, pack_counts(ac, rc));
 582 }
 583 
 584 /*
 585  * Standard timings for PIO modes
 586  */
 587 
 588 static struct pio_timing {
 589         int     mc_time;        /* Minimal cycle time (ns) */
 590         int     av_time;        /* Address valid to DIOR-/DIOW- setup (ns) */
 591         int     ds_time;        /* DIOR data setup      (ns) */
 592 } pio_timings[6] = {
 593         { 70,   165,    600 },  /* PIO Mode 0 */
 594         { 50,   125,    383 },  /* PIO Mode 1 */
 595         { 30,   100,    240 },  /* PIO Mode 2 */
 596         { 30,   80,     180 },  /* PIO Mode 3 */
 597         { 25,   70,     125 },  /* PIO Mode 4 */
 598         { 20,   50,     100 }   /* PIO Mode ? (nonstandard) */
 599 };
 600 
 601 /*
 602  * Black list. Some drives incorrectly report their maximal PIO modes, at least
 603  * in respect to CMD640. Here we keep info on some known drives.
 604  */
 605 
 606 static struct drive_pio_info {
 607         const char      *name;
 608         int             pio;
 609 } drive_pios[] = {
 610 /*      { "Conner Peripherals 1275MB - CFS1275A", 4 }, */
 611 
 612         { "WDC AC2700",  3 },
 613         { "WDC AC2540",  3 },
 614         { "WDC AC2420",  3 },
 615         { "WDC AC2340",  3 },
 616         { "WDC AC2250",  0 },
 617         { "WDC AC2200",  0 },
 618         { "WDC AC2120",  0 },
 619         { "WDC AC2850",  3 },
 620         { "WDC AC1270",  3 },
 621         { "WDC AC1170",  3 },
 622         { "WDC AC1210",  1 },
 623         { "WDC AC280",   0 },
 624 /*      { "WDC AC21000", 4 }, */
 625         { "WDC AC31000", 3 },
 626 /*      { "WDC AC21200", 4 }, */
 627         { "WDC AC31200", 3 },
 628 /*      { "WDC AC31600", 4 }, */
 629 
 630         { "Maxtor 7131 AT", 1 },
 631         { "Maxtor 7171 AT", 1 },
 632         { "Maxtor 7213 AT", 1 },
 633         { "Maxtor 7245 AT", 1 },
 634         { "Maxtor 7345 AT", 1 },
 635         { "Maxtor 7546 AT", 3 },
 636         { "Maxtor 7540 AV", 3 },
 637 
 638         { "SAMSUNG SHD-3121A", 1 },
 639         { "SAMSUNG SHD-3122A", 1 },
 640         { "SAMSUNG SHD-3172A", 1 },
 641 
 642 /*      { "ST51080A", 4 },
 643  *      { "ST51270A", 4 },
 644  *      { "ST31220A", 4 },
 645  *      { "ST31640A", 4 },
 646  *      { "ST32140A", 4 },
 647  *      { "ST3780A",  4 },
 648  */     { "ST5660A",  3 },
 649         { "ST3660A",  3 },
 650         { "ST3630A",  3 },
 651         { "ST3655A",  3 },
 652         { "ST3391A",  3 },
 653         { "ST3390A",  1 },
 654         { "ST3600A",  1 },
 655         { "ST3290A",  0 },
 656         { "ST3144A",  0 },
 657 
 658         { "QUANTUM ELS127A", 0 },
 659         { "QUANTUM ELS170A", 0 },
 660         { "QUANTUM LPS240A", 0 },
 661         { "QUANTUM LPS210A", 3 },
 662         { "QUANTUM LPS270A", 3 },
 663         { "QUANTUM LPS365A", 3 },
 664         { "QUANTUM LPS540A", 3 },
 665         { "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */
 666         { NULL, 0 }
 667 };
 668 
 669 static int known_drive_pio(char* name) {
     /* [previous][next][first][last][top][bottom][index][help] */
 670         struct drive_pio_info* pi;
 671 
 672         for (pi = drive_pios; pi->name != NULL; pi++) {
 673                 if (strmatch(pi->name, name) == 0)
 674                         return pi->pio;
 675         }
 676         return -1;
 677 }
 678 
 679 static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time,
     /* [previous][next][first][last][top][bottom][index][help] */
 680                                 int clock_time, int drv_idx)
 681 {
 682         int a, b;
 683 
 684         arttim[drv_idx] = (mc_time + clock_time - 1)/clock_time;
 685 
 686         a = (av_time + clock_time - 1)/clock_time;
 687         if (a < 2)
 688                 a = 2;
 689         b = (ds_time + clock_time - 1)/clock_time - a;
 690         if (b < 2)
 691                 b = 2;
 692         if (b > 0x11) {
 693                 a += b - 0x11;
 694                 b = 0x11;
 695         }
 696         if (a > 0x10)
 697                 a = 0x10;
 698         if (cmd640_chip_version > 1)
 699                 b -= 1;
 700         if (b > 0x10)
 701                 b = 0x10;
 702 
 703         a_count[drv_idx] = a;
 704         r_count[drv_idx] = b;
 705 }
 706 
 707 static void set_pio_mode(int if_num, int drv_num, int mode_num) {
     /* [previous][next][first][last][top][bottom][index][help] */
 708         int p_base;
 709         int i;
 710 
 711         p_base = if_num ? 0x170 : 0x1f0;
 712         outb_p(3, p_base + 1);
 713         outb_p(mode_num | 8, p_base + 2);
 714         outb_p((drv_num | 0xa) << 4, p_base + 6);
 715         outb_p(0xef, p_base + 7);
 716         for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
 717                 udelay(10000);
 718 }
 719 
 720 /*
 721  * Set a specific pio_mode for a drive
 722  */
 723 
 724 static void cmd640_set_mode(ide_drive_t* drive, int pio_mode) {
     /* [previous][next][first][last][top][bottom][index][help] */
 725         int interface_number;
 726         int drive_number;
 727         int clock_time; /* ns */
 728         int mc_time, av_time, ds_time;
 729 
 730         interface_number = HWIF(drive)->index;
 731         drive_number = drive->select.b.unit;
 732         clock_time = 1000/bus_speed;
 733 
 734         mc_time = pio_timings[pio_mode].mc_time;
 735         av_time = pio_timings[pio_mode].av_time;
 736         ds_time = pio_timings[pio_mode].ds_time;
 737 
 738         cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
 739                                 interface_number*2 + drive_number);
 740         set_pio_mode(interface_number, drive_number, pio_mode);
 741         cmd640_set_timing(interface_number, drive_number);
 742 }
 743 
 744 /*
 745  * Drive PIO mode "autoconfiguration".
 746  * Ideally, this code should *always* call cmd640_set_mode(), but it doesn't.
 747  */
 748 
 749 static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) {
     /* [previous][next][first][last][top][bottom][index][help] */
 750         int interface_number;
 751         int drive_number;
 752         int clock_time; /* ns */
 753         int max_pio;
 754         int mc_time, av_time, ds_time;
 755         struct hd_driveid* id;
 756         int readahead;  /* there is a global named read_ahead */
 757 
 758         if (pio_mode != 255) {
 759                 cmd640_set_mode(drive, pio_mode);
 760                 return;
 761         }
 762 
 763         interface_number = HWIF(drive)->index;
 764         drive_number = drive->select.b.unit;
 765         clock_time = 1000/bus_speed;
 766         id = drive->id;
 767         if ((max_pio = known_drive_pio(id->model)) != -1) {
 768                 ds_time = pio_timings[max_pio].ds_time;
 769         } else {
 770                 max_pio = id->tPIO;
 771                 ds_time = pio_timings[max_pio].ds_time;
 772                 if (id->field_valid & 2) {
 773                         if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
 774                                 if (id->eide_pio_modes & 4) max_pio = 5;
 775                                 else if (id->eide_pio_modes & 2) max_pio = 4;
 776                                 else max_pio = 3;
 777                                 ds_time = id->eide_pio_iordy;
 778                         } else {
 779                                 ds_time = id->eide_pio;
 780                         }
 781                         if (ds_time == 0)
 782                                 ds_time = pio_timings[max_pio].ds_time;
 783                 }
 784 
 785                 /*
 786                  * Conservative "downgrade"
 787                  */
 788                 if (max_pio < 4 && max_pio != 0) {
 789                         max_pio -= 1;
 790                         ds_time = pio_timings[max_pio].ds_time;         
 791                 }
 792         }
 793         mc_time = pio_timings[max_pio].mc_time;
 794         av_time = pio_timings[max_pio].av_time;
 795         cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
 796                                 interface_number*2 + drive_number);
 797         set_pio_mode(interface_number, drive_number, max_pio);
 798         cmd640_set_timing(interface_number, drive_number);
 799 
 800         /*
 801          * Disable (or set) readahead mode
 802          */
 803 
 804         readahead = 0;
 805         if (cmd640_chip_version > 1) {  /* Mmmm.. probably should be > 2 ?? */
 806                 readahead = known_drive_readahead(id->model);
 807                 if (readahead == -1)
 808                         readahead = 1;  /* Mmmm.. probably be 0 ?? */
 809                 set_readahead_mode(readahead, interface_number, drive_number);
 810         }   
 811 
 812         printk ("Mode and Timing set to PIO%d, Readahead is %s\n", 
 813                 max_pio, readahead ? "enabled" : "disabled");
 814 }
 815 

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