linux/drivers/ide/pci/cmd640.c
<<
>>
Prefs
   1/*
   2 *  linux/drivers/ide/pci/cmd640.c              Version 1.02  Sep 01, 1996
   3 *
   4 *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
   5 */
   6
   7/*
   8 *  Original authors:   abramov@cecmow.enet.dec.com (Igor Abramov)
   9 *                      mlord@pobox.com (Mark Lord)
  10 *
  11 *  See linux/MAINTAINERS for address of current maintainer.
  12 *
  13 *  This file provides support for the advanced features and bugs
  14 *  of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
  15 *
  16 *  These chips are basically fucked by design, and getting this driver
  17 *  to work on every motherboard design that uses this screwed chip seems
  18 *  bloody well impossible.  However, we're still trying.
  19 *
  20 *  Version 0.97 worked for everybody.
  21 *
  22 *  User feedback is essential.  Many thanks to the beta test team:
  23 *
  24 *  A.Hartgers@stud.tue.nl, JZDQC@CUNYVM.CUNY.edu, abramov@cecmow.enet.dec.com,
  25 *  bardj@utopia.ppp.sn.no, bart@gaga.tue.nl, bbol001@cs.auckland.ac.nz,
  26 *  chrisc@dbass.demon.co.uk, dalecki@namu26.Num.Math.Uni-Goettingen.de,
  27 *  derekn@vw.ece.cmu.edu, florian@btp2x3.phy.uni-bayreuth.de,
  28 *  flynn@dei.unipd.it, gadio@netvision.net.il, godzilla@futuris.net,
  29 *  j@pobox.com, jkemp1@mises.uni-paderborn.de, jtoppe@hiwaay.net,
  30 *  kerouac@ssnet.com, meskes@informatik.rwth-aachen.de, hzoli@cs.elte.hu,
  31 *  peter@udgaard.isgtec.com, phil@tazenda.demon.co.uk, roadcapw@cfw.com,
  32 *  s0033las@sun10.vsz.bme.hu, schaffer@tam.cornell.edu, sjd@slip.net,
  33 *  steve@ei.org, ulrpeg@bigcomm.gun.de, ism@tardis.ed.ac.uk, mack@cray.com
  34 *  liug@mama.indstate.edu, and others.
  35 *
  36 *  Version 0.01        Initial version, hacked out of ide.c,
  37 *                      and #include'd rather than compiled separately.
  38 *                      This will get cleaned up in a subsequent release.
  39 *
  40 *  Version 0.02        Fixes for vlb initialization code, enable prefetch
  41 *                      for versions 'B' and 'C' of chip by default,
  42 *                      some code cleanup.
  43 *
  44 *  Version 0.03        Added reset of secondary interface,
  45 *                      and black list for devices which are not compatible
  46 *                      with prefetch mode. Separate function for setting
  47 *                      prefetch is added, possibly it will be called some
  48 *                      day from ioctl processing code.
  49 *
  50 *  Version 0.04        Now configs/compiles separate from ide.c
  51 *
  52 *  Version 0.05        Major rewrite of interface timing code.
  53 *                      Added new function cmd640_set_mode to set PIO mode
  54 *                      from ioctl call. New drives added to black list.
  55 *
  56 *  Version 0.06        More code cleanup. Prefetch is enabled only for
  57 *                      detected hard drives, not included in prefetch
  58 *                      black list.
  59 *
  60 *  Version 0.07        Changed to more conservative drive tuning policy.
  61 *                      Unknown drives, which report PIO < 4 are set to
  62 *                      (reported_PIO - 1) if it is supported, or to PIO0.
  63 *                      List of known drives extended by info provided by
  64 *                      CMD at their ftp site.
  65 *
  66 *  Version 0.08        Added autotune/noautotune support.
  67 *
  68 *  Version 0.09        Try to be smarter about 2nd port enabling.
  69 *  Version 0.10        Be nice and don't reset 2nd port.
  70 *  Version 0.11        Try to handle more weird situations.
  71 *
  72 *  Version 0.12        Lots of bug fixes from Laszlo Peter
  73 *                      irq unmasking disabled for reliability.
  74 *                      try to be even smarter about the second port.
  75 *                      tidy up source code formatting.
  76 *  Version 0.13        permit irq unmasking again.
  77 *  Version 0.90        massive code cleanup, some bugs fixed.
  78 *                      defaults all drives to PIO mode0, prefetch off.
  79 *                      autotune is OFF by default, with compile time flag.
  80 *                      prefetch can be turned OFF/ON using "hdparm -p8/-p9"
  81 *                       (requires hdparm-3.1 or newer)
  82 *  Version 0.91        first release to linux-kernel list.
  83 *  Version 0.92        move initial reg dump to separate callable function
  84 *                      change "readahead" to "prefetch" to avoid confusion
  85 *  Version 0.95        respect original BIOS timings unless autotuning.
  86 *                      tons of code cleanup and rearrangement.
  87 *                      added CONFIG_BLK_DEV_CMD640_ENHANCED option
  88 *                      prevent use of unmask when prefetch is on
  89 *  Version 0.96        prevent use of io_32bit when prefetch is off
  90 *  Version 0.97        fix VLB secondary interface for sjd@slip.net
  91 *                      other minor tune-ups:  0.96 was very good.
  92 *  Version 0.98        ignore PCI version when disabled by BIOS
  93 *  Version 0.99        display setup/active/recovery clocks with PIO mode
  94 *  Version 1.00        Mmm.. cannot depend on PCMD_ENA in all systems
  95 *  Version 1.01        slow/fast devsel can be selected with "hdparm -p6/-p7"
  96 *                       ("fast" is necessary for 32bit I/O in some systems)
  97 *  Version 1.02        fix bug that resulted in slow "setup times"
  98 *                       (patch courtesy of Zoltan Hidvegi)
  99 */
 100
 101#define CMD640_PREFETCH_MASKS 1
 102
 103//#define CMD640_DUMP_REGS
 104
 105#include <linux/types.h>
 106#include <linux/kernel.h>
 107#include <linux/delay.h>
 108#include <linux/timer.h>
 109#include <linux/mm.h>
 110#include <linux/ioport.h>
 111#include <linux/blkdev.h>
 112#include <linux/hdreg.h>
 113#include <linux/ide.h>
 114#include <linux/init.h>
 115
 116#include <asm/io.h>
 117
 118/*
 119 * This flag is set in ide.c by the parameter:  ide0=cmd640_vlb
 120 */
 121int cmd640_vlb = 0;
 122
 123/*
 124 * CMD640 specific registers definition.
 125 */
 126
 127#define VID             0x00
 128#define DID             0x02
 129#define PCMD            0x04
 130#define   PCMD_ENA      0x01
 131#define PSTTS           0x06
 132#define REVID           0x08
 133#define PROGIF          0x09
 134#define SUBCL           0x0a
 135#define BASCL           0x0b
 136#define BaseA0          0x10
 137#define BaseA1          0x14
 138#define BaseA2          0x18
 139#define BaseA3          0x1c
 140#define INTLINE         0x3c
 141#define INPINE          0x3d
 142
 143#define CFR             0x50
 144#define   CFR_DEVREV            0x03
 145#define   CFR_IDE01INTR         0x04
 146#define   CFR_DEVID             0x18
 147#define   CFR_AT_VESA_078h      0x20
 148#define   CFR_DSA1              0x40
 149#define   CFR_DSA0              0x80
 150
 151#define CNTRL           0x51
 152#define   CNTRL_DIS_RA0         0x40
 153#define   CNTRL_DIS_RA1         0x80
 154#define   CNTRL_ENA_2ND         0x08
 155
 156#define CMDTIM          0x52
 157#define ARTTIM0         0x53
 158#define DRWTIM0         0x54
 159#define ARTTIM1         0x55
 160#define DRWTIM1         0x56
 161#define ARTTIM23        0x57
 162#define   ARTTIM23_DIS_RA2      0x04
 163#define   ARTTIM23_DIS_RA3      0x08
 164#define DRWTIM23        0x58
 165#define BRST            0x59
 166
 167/*
 168 * Registers and masks for easy access by drive index:
 169 */
 170static u8 prefetch_regs[4]  = {CNTRL, CNTRL, ARTTIM23, ARTTIM23};
 171static u8 prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3};
 172
 173#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 174
 175static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
 176static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23};
 177
 178/*
 179 * Current cmd640 timing values for each drive.
 180 * The defaults for each are the slowest possible timings.
 181 */
 182static u8 setup_counts[4]    = {4, 4, 4, 4};     /* Address setup count (in clocks) */
 183static u8 active_counts[4]   = {16, 16, 16, 16}; /* Active count   (encoded) */
 184static u8 recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */
 185
 186#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 187
 188static DEFINE_SPINLOCK(cmd640_lock);
 189
 190/*
 191 * These are initialized to point at the devices we control
 192 */
 193static ide_hwif_t  *cmd_hwif0, *cmd_hwif1;
 194static ide_drive_t *cmd_drives[4];
 195
 196/*
 197 * Interface to access cmd640x registers
 198 */
 199static unsigned int cmd640_key;
 200static void (*__put_cmd640_reg)(u16 reg, u8 val);
 201static u8 (*__get_cmd640_reg)(u16 reg);
 202
 203/*
 204 * This is read from the CFR reg, and is used in several places.
 205 */
 206static unsigned int cmd640_chip_version;
 207
 208/*
 209 * The CMD640x chip does not support DWORD config write cycles, but some
 210 * of the BIOSes use them to implement the config services.
 211 * Therefore, we must use direct IO instead.
 212 */
 213
 214/* PCI method 1 access */
 215
 216static void put_cmd640_reg_pci1 (u16 reg, u8 val)
 217{
 218        outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
 219        outb_p(val, (reg & 3) | 0xcfc);
 220}
 221
 222static u8 get_cmd640_reg_pci1 (u16 reg)
 223{
 224        outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
 225        return inb_p((reg & 3) | 0xcfc);
 226}
 227
 228/* PCI method 2 access (from CMD datasheet) */
 229
 230static void put_cmd640_reg_pci2 (u16 reg, u8 val)
 231{
 232        outb_p(0x10, 0xcf8);
 233        outb_p(val, cmd640_key + reg);
 234        outb_p(0, 0xcf8);
 235}
 236
 237static u8 get_cmd640_reg_pci2 (u16 reg)
 238{
 239        u8 b;
 240
 241        outb_p(0x10, 0xcf8);
 242        b = inb_p(cmd640_key + reg);
 243        outb_p(0, 0xcf8);
 244        return b;
 245}
 246
 247/* VLB access */
 248
 249static void put_cmd640_reg_vlb (u16 reg, u8 val)
 250{
 251        outb_p(reg, cmd640_key);
 252        outb_p(val, cmd640_key + 4);
 253}
 254
 255static u8 get_cmd640_reg_vlb (u16 reg)
 256{
 257        outb_p(reg, cmd640_key);
 258        return inb_p(cmd640_key + 4);
 259}
 260
 261static u8 get_cmd640_reg(u16 reg)
 262{
 263        unsigned long flags;
 264        u8 b;
 265
 266        spin_lock_irqsave(&cmd640_lock, flags);
 267        b = __get_cmd640_reg(reg);
 268        spin_unlock_irqrestore(&cmd640_lock, flags);
 269        return b;
 270}
 271
 272static void put_cmd640_reg(u16 reg, u8 val)
 273{
 274        unsigned long flags;
 275
 276        spin_lock_irqsave(&cmd640_lock, flags);
 277        __put_cmd640_reg(reg,val);
 278        spin_unlock_irqrestore(&cmd640_lock, flags);
 279}
 280
 281static int __init match_pci_cmd640_device (void)
 282{
 283        const u8 ven_dev[4] = {0x95, 0x10, 0x40, 0x06};
 284        unsigned int i;
 285        for (i = 0; i < 4; i++) {
 286                if (get_cmd640_reg(i) != ven_dev[i])
 287                        return 0;
 288        }
 289#ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT
 290        if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) {
 291                printk("ide: cmd640 on PCI disabled by BIOS\n");
 292                return 0;
 293        }
 294#endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */
 295        return 1; /* success */
 296}
 297
 298/*
 299 * Probe for CMD640x -- pci method 1
 300 */
 301static int __init probe_for_cmd640_pci1 (void)
 302{
 303        __get_cmd640_reg = get_cmd640_reg_pci1;
 304        __put_cmd640_reg = put_cmd640_reg_pci1;
 305        for (cmd640_key = 0x80000000;
 306             cmd640_key <= 0x8000f800;
 307             cmd640_key += 0x800) {
 308                if (match_pci_cmd640_device())
 309                        return 1; /* success */
 310        }
 311        return 0;
 312}
 313
 314/*
 315 * Probe for CMD640x -- pci method 2
 316 */
 317static int __init probe_for_cmd640_pci2 (void)
 318{
 319        __get_cmd640_reg = get_cmd640_reg_pci2;
 320        __put_cmd640_reg = put_cmd640_reg_pci2;
 321        for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) {
 322                if (match_pci_cmd640_device())
 323                        return 1; /* success */
 324        }
 325        return 0;
 326}
 327
 328/*
 329 * Probe for CMD640x -- vlb
 330 */
 331static int __init probe_for_cmd640_vlb (void)
 332{
 333        u8 b;
 334
 335        __get_cmd640_reg = get_cmd640_reg_vlb;
 336        __put_cmd640_reg = put_cmd640_reg_vlb;
 337        cmd640_key = 0x178;
 338        b = get_cmd640_reg(CFR);
 339        if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) {
 340                cmd640_key = 0x78;
 341                b = get_cmd640_reg(CFR);
 342                if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h))
 343                        return 0;
 344        }
 345        return 1; /* success */
 346}
 347
 348/*
 349 *  Returns 1 if an IDE interface/drive exists at 0x170,
 350 *  Returns 0 otherwise.
 351 */
 352static int __init secondary_port_responding (void)
 353{
 354        unsigned long flags;
 355
 356        spin_lock_irqsave(&cmd640_lock, flags);
 357
 358        outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET);        /* select drive0 */
 359        udelay(100);
 360        if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) {
 361                outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */
 362                udelay(100);
 363                if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) {
 364                        spin_unlock_irqrestore(&cmd640_lock, flags);
 365                        return 0; /* nothing responded */
 366                }
 367        }
 368        spin_unlock_irqrestore(&cmd640_lock, flags);
 369        return 1; /* success */
 370}
 371
 372#ifdef CMD640_DUMP_REGS
 373/*
 374 * Dump out all cmd640 registers.  May be called from ide.c
 375 */
 376static void cmd640_dump_regs (void)
 377{
 378        unsigned int reg = cmd640_vlb ? 0x50 : 0x00;
 379
 380        /* Dump current state of chip registers */
 381        printk("ide: cmd640 internal register dump:");
 382        for (; reg <= 0x59; reg++) {
 383                if (!(reg & 0x0f))
 384                        printk("\n%04x:", reg);
 385                printk(" %02x", get_cmd640_reg(reg));
 386        }
 387        printk("\n");
 388}
 389#endif
 390
 391/*
 392 * Check whether prefetch is on for a drive,
 393 * and initialize the unmask flags for safe operation.
 394 */
 395static void __init check_prefetch (unsigned int index)
 396{
 397        ide_drive_t *drive = cmd_drives[index];
 398        u8 b = get_cmd640_reg(prefetch_regs[index]);
 399
 400        if (b & prefetch_masks[index]) {        /* is prefetch off? */
 401                drive->no_unmask = 0;
 402                drive->no_io_32bit = 1;
 403                drive->io_32bit = 0;
 404        } else {
 405#if CMD640_PREFETCH_MASKS
 406                drive->no_unmask = 1;
 407                drive->unmask = 0;
 408#endif
 409                drive->no_io_32bit = 0;
 410        }
 411}
 412
 413/*
 414 * Figure out which devices we control
 415 */
 416static void __init setup_device_ptrs (void)
 417{
 418        unsigned int i;
 419
 420        cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */
 421        cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */
 422        for (i = 0; i < MAX_HWIFS; i++) {
 423                ide_hwif_t *hwif = &ide_hwifs[i];
 424                if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) {
 425                        if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0)
 426                                cmd_hwif0 = hwif;
 427                        else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170)
 428                                cmd_hwif1 = hwif;
 429                }
 430        }
 431        cmd_drives[0] = &cmd_hwif0->drives[0];
 432        cmd_drives[1] = &cmd_hwif0->drives[1];
 433        cmd_drives[2] = &cmd_hwif1->drives[0];
 434        cmd_drives[3] = &cmd_hwif1->drives[1];
 435}
 436
 437#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 438
 439/*
 440 * Sets prefetch mode for a drive.
 441 */
 442static void set_prefetch_mode (unsigned int index, int mode)
 443{
 444        ide_drive_t *drive = cmd_drives[index];
 445        unsigned long flags;
 446        int reg = prefetch_regs[index];
 447        u8 b;
 448
 449        spin_lock_irqsave(&cmd640_lock, flags);
 450        b = __get_cmd640_reg(reg);
 451        if (mode) {     /* want prefetch on? */
 452#if CMD640_PREFETCH_MASKS
 453                drive->no_unmask = 1;
 454                drive->unmask = 0;
 455#endif
 456                drive->no_io_32bit = 0;
 457                b &= ~prefetch_masks[index];    /* enable prefetch */
 458        } else {
 459                drive->no_unmask = 0;
 460                drive->no_io_32bit = 1;
 461                drive->io_32bit = 0;
 462                b |= prefetch_masks[index];     /* disable prefetch */
 463        }
 464        __put_cmd640_reg(reg, b);
 465        spin_unlock_irqrestore(&cmd640_lock, flags);
 466}
 467
 468/*
 469 * Dump out current drive clocks settings
 470 */
 471static void display_clocks (unsigned int index)
 472{
 473        u8 active_count, recovery_count;
 474
 475        active_count = active_counts[index];
 476        if (active_count == 1)
 477                ++active_count;
 478        recovery_count = recovery_counts[index];
 479        if (active_count > 3 && recovery_count == 1)
 480                ++recovery_count;
 481        if (cmd640_chip_version > 1)
 482                recovery_count += 1;  /* cmd640b uses (count + 1)*/
 483        printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count);
 484}
 485
 486/*
 487 * Pack active and recovery counts into single byte representation
 488 * used by controller
 489 */
 490static inline u8 pack_nibbles (u8 upper, u8 lower)
 491{
 492        return ((upper & 0x0f) << 4) | (lower & 0x0f);
 493}
 494
 495/*
 496 * This routine retrieves the initial drive timings from the chipset.
 497 */
 498static void __init retrieve_drive_counts (unsigned int index)
 499{
 500        u8 b;
 501
 502        /*
 503         * Get the internal setup timing, and convert to clock count
 504         */
 505        b = get_cmd640_reg(arttim_regs[index]) & ~0x3f;
 506        switch (b) {
 507                case 0x00: b = 4; break;
 508                case 0x80: b = 3; break;
 509                case 0x40: b = 2; break;
 510                default:   b = 5; break;
 511        }
 512        setup_counts[index] = b;
 513
 514        /*
 515         * Get the active/recovery counts
 516         */
 517        b = get_cmd640_reg(drwtim_regs[index]);
 518        active_counts[index]   = (b >> 4)   ? (b >> 4)   : 0x10;
 519        recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10;
 520}
 521
 522
 523/*
 524 * This routine writes the prepared setup/active/recovery counts
 525 * for a drive into the cmd640 chipset registers to active them.
 526 */
 527static void program_drive_counts (unsigned int index)
 528{
 529        unsigned long flags;
 530        u8 setup_count    = setup_counts[index];
 531        u8 active_count   = active_counts[index];
 532        u8 recovery_count = recovery_counts[index];
 533
 534        /*
 535         * Set up address setup count and drive read/write timing registers.
 536         * Primary interface has individual count/timing registers for
 537         * each drive.  Secondary interface has one common set of registers,
 538         * so we merge the timings, using the slowest value for each timing.
 539         */
 540        if (index > 1) {
 541                unsigned int mate;
 542                if (cmd_drives[mate = index ^ 1]->present) {
 543                        if (setup_count < setup_counts[mate])
 544                                setup_count = setup_counts[mate];
 545                        if (active_count < active_counts[mate])
 546                                active_count = active_counts[mate];
 547                        if (recovery_count < recovery_counts[mate])
 548                                recovery_count = recovery_counts[mate];
 549                }
 550        }
 551
 552        /*
 553         * Convert setup_count to internal chipset representation
 554         */
 555        switch (setup_count) {
 556                case 4:  setup_count = 0x00; break;
 557                case 3:  setup_count = 0x80; break;
 558                case 1:
 559                case 2:  setup_count = 0x40; break;
 560                default: setup_count = 0xc0; /* case 5 */
 561        }
 562
 563        /*
 564         * Now that everything is ready, program the new timings
 565         */
 566        spin_lock_irqsave(&cmd640_lock, flags);
 567        /*
 568         * Program the address_setup clocks into ARTTIM reg,
 569         * and then the active/recovery counts into the DRWTIM reg
 570         * (this converts counts of 16 into counts of zero -- okay).
 571         */
 572        setup_count |= __get_cmd640_reg(arttim_regs[index]) & 0x3f;
 573        __put_cmd640_reg(arttim_regs[index], setup_count);
 574        __put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count));
 575        spin_unlock_irqrestore(&cmd640_lock, flags);
 576}
 577
 578/*
 579 * Set a specific pio_mode for a drive
 580 */
 581static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time)
 582{
 583        int setup_time, active_time, recovery_time, clock_time;
 584        u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count;
 585        int bus_speed = system_bus_clock();
 586
 587        if (pio_mode > 5)
 588                pio_mode = 5;
 589        setup_time  = ide_pio_timings[pio_mode].setup_time;
 590        active_time = ide_pio_timings[pio_mode].active_time;
 591        recovery_time = cycle_time - (setup_time + active_time);
 592        clock_time = 1000 / bus_speed;
 593        cycle_count = (cycle_time + clock_time - 1) / clock_time;
 594
 595        setup_count = (setup_time + clock_time - 1) / clock_time;
 596
 597        active_count = (active_time + clock_time - 1) / clock_time;
 598        if (active_count < 2)
 599                active_count = 2; /* minimum allowed by cmd640 */
 600
 601        recovery_count = (recovery_time + clock_time - 1) / clock_time;
 602        recovery_count2 = cycle_count - (setup_count + active_count);
 603        if (recovery_count2 > recovery_count)
 604                recovery_count = recovery_count2;
 605        if (recovery_count < 2)
 606                recovery_count = 2; /* minimum allowed by cmd640 */
 607        if (recovery_count > 17) {
 608                active_count += recovery_count - 17;
 609                recovery_count = 17;
 610        }
 611        if (active_count > 16)
 612                active_count = 16; /* maximum allowed by cmd640 */
 613        if (cmd640_chip_version > 1)
 614                recovery_count -= 1;  /* cmd640b uses (count + 1)*/
 615        if (recovery_count > 16)
 616                recovery_count = 16; /* maximum allowed by cmd640 */
 617
 618        setup_counts[index]    = setup_count;
 619        active_counts[index]   = active_count;
 620        recovery_counts[index] = recovery_count;
 621
 622        /*
 623         * In a perfect world, we might set the drive pio mode here
 624         * (using WIN_SETFEATURE) before continuing.
 625         *
 626         * But we do not, because:
 627         *      1) this is the wrong place to do it (proper is do_special() in ide.c)
 628         *      2) in practice this is rarely, if ever, necessary
 629         */
 630        program_drive_counts (index);
 631}
 632
 633static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio)
 634{
 635        unsigned int index = 0, cycle_time;
 636        u8 b;
 637
 638        while (drive != cmd_drives[index]) {
 639                if (++index > 3) {
 640                        printk(KERN_ERR "%s: bad news in %s\n",
 641                                        drive->name, __FUNCTION__);
 642                        return;
 643                }
 644        }
 645        switch (pio) {
 646                case 6: /* set fast-devsel off */
 647                case 7: /* set fast-devsel on */
 648                        b = get_cmd640_reg(CNTRL) & ~0x27;
 649                        if (pio & 1)
 650                                b |= 0x27;
 651                        put_cmd640_reg(CNTRL, b);
 652                        printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, (pio & 1) ? "en" : "dis");
 653                        return;
 654
 655                case 8: /* set prefetch off */
 656                case 9: /* set prefetch on */
 657                        set_prefetch_mode(index, pio & 1);
 658                        printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis");
 659                        return;
 660        }
 661
 662        cycle_time = ide_pio_cycle_time(drive, pio);
 663        cmd640_set_mode(index, pio, cycle_time);
 664
 665        printk("%s: selected cmd640 PIO mode%d (%dns)",
 666                drive->name, pio, cycle_time);
 667
 668        display_clocks(index);
 669}
 670
 671#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 672
 673static int pci_conf1(void)
 674{
 675        unsigned long flags;
 676        u32 tmp;
 677
 678        spin_lock_irqsave(&cmd640_lock, flags);
 679        outb(0x01, 0xCFB);
 680        tmp = inl(0xCF8);
 681        outl(0x80000000, 0xCF8);
 682        if (inl(0xCF8) == 0x80000000) {
 683                outl(tmp, 0xCF8);
 684                spin_unlock_irqrestore(&cmd640_lock, flags);
 685                return 1;
 686        }
 687        outl(tmp, 0xCF8);
 688        spin_unlock_irqrestore(&cmd640_lock, flags);
 689        return 0;
 690}
 691
 692static int pci_conf2(void)
 693{
 694        unsigned long flags;
 695
 696        spin_lock_irqsave(&cmd640_lock, flags);
 697        outb(0x00, 0xCFB);
 698        outb(0x00, 0xCF8);
 699        outb(0x00, 0xCFA);
 700        if (inb(0xCF8) == 0x00 && inb(0xCF8) == 0x00) {
 701                spin_unlock_irqrestore(&cmd640_lock, flags);
 702                return 1;
 703        }
 704        spin_unlock_irqrestore(&cmd640_lock, flags);
 705        return 0;
 706}
 707
 708/*
 709 * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
 710 */
 711int __init ide_probe_for_cmd640x (void)
 712{
 713#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 714        int second_port_toggled = 0;
 715#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 716        int second_port_cmd640 = 0;
 717        const char *bus_type, *port2;
 718        unsigned int index;
 719        u8 b, cfr;
 720
 721        if (cmd640_vlb && probe_for_cmd640_vlb()) {
 722                bus_type = "VLB";
 723        } else {
 724                cmd640_vlb = 0;
 725                /* Find out what kind of PCI probing is supported otherwise
 726                   Justin Gibbs will sulk.. */
 727                if (pci_conf1() && probe_for_cmd640_pci1())
 728                        bus_type = "PCI (type1)";
 729                else if (pci_conf2() && probe_for_cmd640_pci2())
 730                        bus_type = "PCI (type2)";
 731                else
 732                        return 0;
 733        }
 734        /*
 735         * Undocumented magic (there is no 0x5b reg in specs)
 736         */
 737        put_cmd640_reg(0x5b, 0xbd);
 738        if (get_cmd640_reg(0x5b) != 0xbd) {
 739                printk(KERN_ERR "ide: cmd640 init failed: wrong value in reg 0x5b\n");
 740                return 0;
 741        }
 742        put_cmd640_reg(0x5b, 0);
 743
 744#ifdef CMD640_DUMP_REGS
 745        cmd640_dump_regs();
 746#endif
 747
 748        /*
 749         * Documented magic begins here
 750         */
 751        cfr = get_cmd640_reg(CFR);
 752        cmd640_chip_version = cfr & CFR_DEVREV;
 753        if (cmd640_chip_version == 0) {
 754                printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version);
 755                return 0;
 756        }
 757
 758        /*
 759         * Initialize data for primary port
 760         */
 761        setup_device_ptrs ();
 762        printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n",
 763               cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr);
 764        cmd_hwif0->chipset = ide_cmd640;
 765#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 766        cmd_hwif0->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
 767                                IDE_HFLAG_ABUSE_FAST_DEVSEL;
 768        cmd_hwif0->pio_mask = ATA_PIO5;
 769        cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
 770#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 771
 772        /*
 773         * Ensure compatibility by always using the slowest timings
 774         * for access to the drive's command register block,
 775         * and reset the prefetch burstsize to default (512 bytes).
 776         *
 777         * Maybe we need a way to NOT do these on *some* systems?
 778         */
 779        put_cmd640_reg(CMDTIM, 0);
 780        put_cmd640_reg(BRST, 0x40);
 781
 782        /*
 783         * Try to enable the secondary interface, if not already enabled
 784         */
 785        if (cmd_hwif1->noprobe) {
 786                port2 = "not probed";
 787        } else {
 788                b = get_cmd640_reg(CNTRL);
 789                if (secondary_port_responding()) {
 790                        if ((b & CNTRL_ENA_2ND)) {
 791                                second_port_cmd640 = 1;
 792                                port2 = "okay";
 793                        } else if (cmd640_vlb) {
 794                                second_port_cmd640 = 1;
 795                                port2 = "alive";
 796                        } else
 797                                port2 = "not cmd640";
 798                } else {
 799                        put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */
 800                        if (secondary_port_responding()) {
 801                                second_port_cmd640 = 1;
 802#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 803                                second_port_toggled = 1;
 804#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 805                                port2 = "enabled";
 806                        } else {
 807                                put_cmd640_reg(CNTRL, b); /* restore original setting */
 808                                port2 = "not responding";
 809                        }
 810                }
 811        }
 812
 813        /*
 814         * Initialize data for secondary cmd640 port, if enabled
 815         */
 816        if (second_port_cmd640) {
 817                cmd_hwif0->serialized = 1;
 818                cmd_hwif1->serialized = 1;
 819                cmd_hwif1->chipset = ide_cmd640;
 820                cmd_hwif0->mate = cmd_hwif1;
 821                cmd_hwif1->mate = cmd_hwif0;
 822                cmd_hwif1->channel = 1;
 823#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 824                cmd_hwif1->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
 825                                        IDE_HFLAG_ABUSE_FAST_DEVSEL;
 826                cmd_hwif1->pio_mask = ATA_PIO5;
 827                cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
 828#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 829        }
 830        printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
 831                cmd_hwif0->serialized ? "" : "not ", port2);
 832
 833        /*
 834         * Establish initial timings/prefetch for all drives.
 835         * Do not unnecessarily disturb any prior BIOS setup of these.
 836         */
 837        for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) {
 838                ide_drive_t *drive = cmd_drives[index];
 839#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 840                if (drive->autotune || ((index > 1) && second_port_toggled)) {
 841                        /*
 842                         * Reset timing to the slowest speed and turn off prefetch.
 843                         * This way, the drive identify code has a better chance.
 844                         */
 845                        setup_counts    [index] = 4;    /* max possible */
 846                        active_counts   [index] = 16;   /* max possible */
 847                        recovery_counts [index] = 16;   /* max possible */
 848                        program_drive_counts (index);
 849                        set_prefetch_mode (index, 0);
 850                        printk("cmd640: drive%d timings/prefetch cleared\n", index);
 851                } else {
 852                        /*
 853                         * Record timings/prefetch without changing them.
 854                         * This preserves any prior BIOS setup.
 855                         */
 856                        retrieve_drive_counts (index);
 857                        check_prefetch (index);
 858                        printk("cmd640: drive%d timings/prefetch(%s) preserved",
 859                                index, drive->no_io_32bit ? "off" : "on");
 860                        display_clocks(index);
 861                }
 862#else
 863                /*
 864                 * Set the drive unmask flags to match the prefetch setting
 865                 */
 866                check_prefetch (index);
 867                printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
 868                        index, drive->no_io_32bit ? "off" : "on");
 869#endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 870        }
 871
 872#ifdef CMD640_DUMP_REGS
 873        cmd640_dump_regs();
 874#endif
 875        return 1;
 876}
 877
 878
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.