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

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