|
|
1.1 ! root 1: /* ! 2: * linux/drivers/block/cmd640.c Version 1.02 Sep 01, 1996 ! 3: * ! 4: * Copyright (C) 1995-1996 Linus Torvalds & authors (see below) ! 5: */ ! 6: ! 7: /* ! 8: * Original author: [email protected] (Igor Abramov) ! 9: * ! 10: * Maintained by: [email protected] (Mark Lord) ! 11: * with fanatical support from a legion of hackers! ! 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: * [email protected], [email protected], [email protected], ! 25: * [email protected], [email protected], [email protected], ! 26: * [email protected], [email protected], ! 27: * [email protected], [email protected], ! 28: * [email protected], [email protected], [email protected], ! 29: * [email protected], [email protected], [email protected], ! 30: * [email protected], [email protected], [email protected], ! 31: * [email protected], [email protected], [email protected], ! 32: * [email protected], [email protected], [email protected], ! 33: * [email protected], [email protected], [email protected], [email protected] ! 34: * [email protected], 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 wierd 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 [email protected] ! 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: #undef REALLY_SLOW_IO /* most systems can safely undef this */ ! 102: #define CMD640_PREFETCH_MASKS 1 ! 103: ! 104: #include <linux/config.h> ! 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 <asm/io.h> ! 114: #include "ide.h" ! 115: #include "ide_modes.h" ! 116: ! 117: /* ! 118: * This flag is set in ide.c by the parameter: ide0=cmd640_vlb ! 119: */ ! 120: int cmd640_vlb = 0; ! 121: ! 122: /* ! 123: * CMD640 specific registers definition. ! 124: */ ! 125: ! 126: #define VID 0x00 ! 127: #define DID 0x02 ! 128: #define PCMD 0x04 ! 129: #define PCMD_ENA 0x01 ! 130: #define PSTTS 0x06 ! 131: #define REVID 0x08 ! 132: #define PROGIF 0x09 ! 133: #define SUBCL 0x0a ! 134: #define BASCL 0x0b ! 135: #define BaseA0 0x10 ! 136: #define BaseA1 0x14 ! 137: #define BaseA2 0x18 ! 138: #define BaseA3 0x1c ! 139: #define INTLINE 0x3c ! 140: #define INPINE 0x3d ! 141: ! 142: #define CFR 0x50 ! 143: #define CFR_DEVREV 0x03 ! 144: #define CFR_IDE01INTR 0x04 ! 145: #define CFR_DEVID 0x18 ! 146: #define CFR_AT_VESA_078h 0x20 ! 147: #define CFR_DSA1 0x40 ! 148: #define CFR_DSA0 0x80 ! 149: ! 150: #define CNTRL 0x51 ! 151: #define CNTRL_DIS_RA0 0x40 ! 152: #define CNTRL_DIS_RA1 0x80 ! 153: #define CNTRL_ENA_2ND 0x08 ! 154: ! 155: #define CMDTIM 0x52 ! 156: #define ARTTIM0 0x53 ! 157: #define DRWTIM0 0x54 ! 158: #define ARTTIM1 0x55 ! 159: #define DRWTIM1 0x56 ! 160: #define ARTTIM23 0x57 ! 161: #define ARTTIM23_DIS_RA2 0x04 ! 162: #define ARTTIM23_DIS_RA3 0x08 ! 163: #define DRWTIM23 0x58 ! 164: #define BRST 0x59 ! 165: ! 166: /* ! 167: * Registers and masks for easy access by drive index: ! 168: */ ! 169: static byte prefetch_regs[4] = {CNTRL, CNTRL, ARTTIM23, ARTTIM23}; ! 170: static byte prefetch_masks[4] = {CNTRL_DIS_RA0, CNTRL_DIS_RA1, ARTTIM23_DIS_RA2, ARTTIM23_DIS_RA3}; ! 171: ! 172: #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED ! 173: ! 174: static byte arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23}; ! 175: static byte drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23}; ! 176: ! 177: /* ! 178: * Current cmd640 timing values for each drive. ! 179: * The defaults for each are the slowest possible timings. ! 180: */ ! 181: static byte setup_counts[4] = {4, 4, 4, 4}; /* Address setup count (in clocks) */ ! 182: static byte active_counts[4] = {16, 16, 16, 16}; /* Active count (encoded) */ ! 183: static byte recovery_counts[4] = {16, 16, 16, 16}; /* Recovery count (encoded) */ ! 184: ! 185: #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ ! 186: ! 187: /* ! 188: * These are initialized to point at the devices we control ! 189: */ ! 190: static ide_hwif_t *cmd_hwif0, *cmd_hwif1; ! 191: static ide_drive_t *cmd_drives[4]; ! 192: ! 193: /* ! 194: * Interface to access cmd640x registers ! 195: */ ! 196: static unsigned int cmd640_key; ! 197: static void (*put_cmd640_reg)(unsigned short reg, byte val); ! 198: static byte (*get_cmd640_reg)(unsigned short reg); ! 199: ! 200: /* ! 201: * This is read from the CFR reg, and is used in several places. ! 202: */ ! 203: static unsigned int cmd640_chip_version; ! 204: ! 205: /* ! 206: * The CMD640x chip does not support DWORD config write cycles, but some ! 207: * of the BIOSes use them to implement the config services. ! 208: * Therefore, we must use direct IO instead. ! 209: */ ! 210: ! 211: /* PCI method 1 access */ ! 212: ! 213: static void put_cmd640_reg_pci1 (unsigned short reg, byte val) ! 214: { ! 215: unsigned long flags; ! 216: ! 217: save_flags(flags); ! 218: cli(); ! 219: outl_p((reg & 0xfc) | cmd640_key, 0xcf8); ! 220: outb_p(val, (reg & 3) | 0xcfc); ! 221: restore_flags(flags); ! 222: } ! 223: ! 224: static byte get_cmd640_reg_pci1 (unsigned short reg) ! 225: { ! 226: byte b; ! 227: unsigned long flags; ! 228: ! 229: save_flags(flags); ! 230: cli(); ! 231: outl_p((reg & 0xfc) | cmd640_key, 0xcf8); ! 232: b = inb_p((reg & 3) | 0xcfc); ! 233: restore_flags(flags); ! 234: return b; ! 235: } ! 236: ! 237: /* PCI method 2 access (from CMD datasheet) */ ! 238: ! 239: static void put_cmd640_reg_pci2 (unsigned short reg, byte val) ! 240: { ! 241: unsigned long flags; ! 242: ! 243: save_flags(flags); ! 244: cli(); ! 245: outb_p(0x10, 0xcf8); ! 246: outb_p(val, cmd640_key + reg); ! 247: outb_p(0, 0xcf8); ! 248: restore_flags(flags); ! 249: } ! 250: ! 251: static byte get_cmd640_reg_pci2 (unsigned short reg) ! 252: { ! 253: byte b; ! 254: unsigned long flags; ! 255: ! 256: save_flags(flags); ! 257: cli(); ! 258: outb_p(0x10, 0xcf8); ! 259: b = inb_p(cmd640_key + reg); ! 260: outb_p(0, 0xcf8); ! 261: restore_flags(flags); ! 262: return b; ! 263: } ! 264: ! 265: /* VLB access */ ! 266: ! 267: static void put_cmd640_reg_vlb (unsigned short reg, byte val) ! 268: { ! 269: unsigned long flags; ! 270: ! 271: save_flags(flags); ! 272: cli(); ! 273: outb_p(reg, cmd640_key); ! 274: outb_p(val, cmd640_key + 4); ! 275: restore_flags(flags); ! 276: } ! 277: ! 278: static byte get_cmd640_reg_vlb (unsigned short reg) ! 279: { ! 280: byte b; ! 281: unsigned long flags; ! 282: ! 283: save_flags(flags); ! 284: cli(); ! 285: outb_p(reg, cmd640_key); ! 286: b = inb_p(cmd640_key + 4); ! 287: restore_flags(flags); ! 288: return b; ! 289: } ! 290: ! 291: static int match_pci_cmd640_device (void) ! 292: { ! 293: const byte ven_dev[4] = {0x95, 0x10, 0x40, 0x06}; ! 294: unsigned int i; ! 295: for (i = 0; i < 4; i++) { ! 296: if (get_cmd640_reg(i) != ven_dev[i]) ! 297: return 0; ! 298: } ! 299: #ifdef STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT ! 300: if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) { ! 301: printk("ide: cmd640 on PCI disabled by BIOS\n"); ! 302: return 0; ! 303: } ! 304: #endif /* STUPIDLY_TRUST_BROKEN_PCMD_ENA_BIT */ ! 305: return 1; /* success */ ! 306: } ! 307: ! 308: /* ! 309: * Probe for CMD640x -- pci method 1 ! 310: */ ! 311: static int probe_for_cmd640_pci1 (void) ! 312: { ! 313: get_cmd640_reg = get_cmd640_reg_pci1; ! 314: put_cmd640_reg = put_cmd640_reg_pci1; ! 315: for (cmd640_key = 0x80000000; cmd640_key <= 0x8000f800; cmd640_key += 0x800) { ! 316: if (match_pci_cmd640_device()) ! 317: return 1; /* success */ ! 318: } ! 319: return 0; ! 320: } ! 321: ! 322: /* ! 323: * Probe for CMD640x -- pci method 2 ! 324: */ ! 325: static int probe_for_cmd640_pci2 (void) ! 326: { ! 327: get_cmd640_reg = get_cmd640_reg_pci2; ! 328: put_cmd640_reg = put_cmd640_reg_pci2; ! 329: for (cmd640_key = 0xc000; cmd640_key <= 0xcf00; cmd640_key += 0x100) { ! 330: if (match_pci_cmd640_device()) ! 331: return 1; /* success */ ! 332: } ! 333: return 0; ! 334: } ! 335: ! 336: /* ! 337: * Probe for CMD640x -- vlb ! 338: */ ! 339: static int probe_for_cmd640_vlb (void) ! 340: { ! 341: byte b; ! 342: ! 343: get_cmd640_reg = get_cmd640_reg_vlb; ! 344: put_cmd640_reg = put_cmd640_reg_vlb; ! 345: cmd640_key = 0x178; ! 346: b = get_cmd640_reg(CFR); ! 347: if (b == 0xff || b == 0x00 || (b & CFR_AT_VESA_078h)) { ! 348: cmd640_key = 0x78; ! 349: b = get_cmd640_reg(CFR); ! 350: if (b == 0xff || b == 0x00 || !(b & CFR_AT_VESA_078h)) ! 351: return 0; ! 352: } ! 353: return 1; /* success */ ! 354: } ! 355: ! 356: /* ! 357: * Returns 1 if an IDE interface/drive exists at 0x170, ! 358: * Returns 0 otherwise. ! 359: */ ! 360: static int secondary_port_responding (void) ! 361: { ! 362: unsigned long flags; ! 363: ! 364: save_flags(flags); ! 365: cli(); ! 366: ! 367: outb_p(0x0a, 0x170 + IDE_SELECT_OFFSET); /* select drive0 */ ! 368: udelay(100); ! 369: if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x0a) { ! 370: outb_p(0x1a, 0x170 + IDE_SELECT_OFFSET); /* select drive1 */ ! 371: udelay(100); ! 372: if ((inb_p(0x170 + IDE_SELECT_OFFSET) & 0x1f) != 0x1a) { ! 373: restore_flags(flags); ! 374: return 0; /* nothing responded */ ! 375: } ! 376: } ! 377: restore_flags(flags); ! 378: return 1; /* success */ ! 379: } ! 380: ! 381: #ifdef CMD640_DUMP_REGS ! 382: /* ! 383: * Dump out all cmd640 registers. May be called from ide.c ! 384: */ ! 385: void cmd640_dump_regs (void) ! 386: { ! 387: unsigned int reg = cmd640_vlb ? 0x50 : 0x00; ! 388: ! 389: /* Dump current state of chip registers */ ! 390: printk("ide: cmd640 internal register dump:"); ! 391: for (; reg <= 0x59; reg++) { ! 392: if (!(reg & 0x0f)) ! 393: printk("\n%04x:", reg); ! 394: printk(" %02x", get_cmd640_reg(reg)); ! 395: } ! 396: printk("\n"); ! 397: } ! 398: #endif ! 399: ! 400: /* ! 401: * Check whether prefetch is on for a drive, ! 402: * and initialize the unmask flags for safe operation. ! 403: */ ! 404: static void check_prefetch (unsigned int index) ! 405: { ! 406: ide_drive_t *drive = cmd_drives[index]; ! 407: byte b = get_cmd640_reg(prefetch_regs[index]); ! 408: ! 409: if (b & prefetch_masks[index]) { /* is prefetch off? */ ! 410: drive->no_unmask = 0; ! 411: drive->no_io_32bit = 1; ! 412: drive->io_32bit = 0; ! 413: } else { ! 414: #if CMD640_PREFETCH_MASKS ! 415: drive->no_unmask = 1; ! 416: drive->unmask = 0; ! 417: #endif ! 418: drive->no_io_32bit = 0; ! 419: } ! 420: } ! 421: ! 422: /* ! 423: * Figure out which devices we control ! 424: */ ! 425: static void setup_device_ptrs (void) ! 426: { ! 427: unsigned int i; ! 428: ! 429: cmd_hwif0 = &ide_hwifs[0]; /* default, if not found below */ ! 430: cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ ! 431: for (i = 0; i < MAX_HWIFS; i++) { ! 432: ide_hwif_t *hwif = &ide_hwifs[i]; ! 433: if (hwif->chipset == ide_unknown || hwif->chipset == ide_generic) { ! 434: if (hwif->io_base == 0x1f0) ! 435: cmd_hwif0 = hwif; ! 436: else if (hwif->io_base == 0x170) ! 437: cmd_hwif1 = hwif; ! 438: } ! 439: } ! 440: cmd_drives[0] = &cmd_hwif0->drives[0]; ! 441: cmd_drives[1] = &cmd_hwif0->drives[1]; ! 442: cmd_drives[2] = &cmd_hwif1->drives[0]; ! 443: cmd_drives[3] = &cmd_hwif1->drives[1]; ! 444: } ! 445: ! 446: #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED ! 447: ! 448: /* ! 449: * Sets prefetch mode for a drive. ! 450: */ ! 451: static void set_prefetch_mode (unsigned int index, int mode) ! 452: { ! 453: ide_drive_t *drive = cmd_drives[index]; ! 454: int reg = prefetch_regs[index]; ! 455: byte b; ! 456: unsigned long flags; ! 457: ! 458: save_flags(flags); ! 459: cli(); ! 460: b = get_cmd640_reg(reg); ! 461: if (mode) { /* want prefetch on? */ ! 462: #if CMD640_PREFETCH_MASKS ! 463: drive->no_unmask = 1; ! 464: drive->unmask = 0; ! 465: #endif ! 466: drive->no_io_32bit = 0; ! 467: b &= ~prefetch_masks[index]; /* enable prefetch */ ! 468: } else { ! 469: drive->no_unmask = 0; ! 470: drive->no_io_32bit = 1; ! 471: drive->io_32bit = 0; ! 472: b |= prefetch_masks[index]; /* disable prefetch */ ! 473: } ! 474: put_cmd640_reg(reg, b); ! 475: restore_flags(flags); ! 476: } ! 477: ! 478: /* ! 479: * Dump out current drive clocks settings ! 480: */ ! 481: static void display_clocks (unsigned int index) ! 482: { ! 483: byte active_count, recovery_count; ! 484: ! 485: active_count = active_counts[index]; ! 486: if (active_count == 1) ! 487: ++active_count; ! 488: recovery_count = recovery_counts[index]; ! 489: if (active_count > 3 && recovery_count == 1) ! 490: ++recovery_count; ! 491: if (cmd640_chip_version > 1) ! 492: recovery_count += 1; /* cmd640b uses (count + 1)*/ ! 493: printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count); ! 494: } ! 495: ! 496: /* ! 497: * Pack active and recovery counts into single byte representation ! 498: * used by controller ! 499: */ ! 500: inline static byte pack_nibbles (byte upper, byte lower) ! 501: { ! 502: return ((upper & 0x0f) << 4) | (lower & 0x0f); ! 503: } ! 504: ! 505: /* ! 506: * This routine retrieves the initial drive timings from the chipset. ! 507: */ ! 508: static void retrieve_drive_counts (unsigned int index) ! 509: { ! 510: byte b; ! 511: ! 512: /* ! 513: * Get the internal setup timing, and convert to clock count ! 514: */ ! 515: b = get_cmd640_reg(arttim_regs[index]) & ~0x3f; ! 516: switch (b) { ! 517: case 0x00: b = 4; break; ! 518: case 0x80: b = 3; break; ! 519: case 0x40: b = 2; break; ! 520: default: b = 5; break; ! 521: } ! 522: setup_counts[index] = b; ! 523: ! 524: /* ! 525: * Get the active/recovery counts ! 526: */ ! 527: b = get_cmd640_reg(drwtim_regs[index]); ! 528: active_counts[index] = (b >> 4) ? (b >> 4) : 0x10; ! 529: recovery_counts[index] = (b & 0x0f) ? (b & 0x0f) : 0x10; ! 530: } ! 531: ! 532: ! 533: /* ! 534: * This routine writes the prepared setup/active/recovery counts ! 535: * for a drive into the cmd640 chipset registers to active them. ! 536: */ ! 537: static void program_drive_counts (unsigned int index) ! 538: { ! 539: unsigned long flags; ! 540: byte setup_count = setup_counts[index]; ! 541: byte active_count = active_counts[index]; ! 542: byte recovery_count = recovery_counts[index]; ! 543: ! 544: /* ! 545: * Set up address setup count and drive read/write timing registers. ! 546: * Primary interface has individual count/timing registers for ! 547: * each drive. Secondary interface has one common set of registers, ! 548: * so we merge the timings, using the slowest value for each timing. ! 549: */ ! 550: if (index > 1) { ! 551: unsigned int mate; ! 552: if (cmd_drives[mate = index ^ 1]->present) { ! 553: if (setup_count < setup_counts[mate]) ! 554: setup_count = setup_counts[mate]; ! 555: if (active_count < active_counts[mate]) ! 556: active_count = active_counts[mate]; ! 557: if (recovery_count < recovery_counts[mate]) ! 558: recovery_count = recovery_counts[mate]; ! 559: } ! 560: } ! 561: ! 562: /* ! 563: * Convert setup_count to internal chipset representation ! 564: */ ! 565: switch (setup_count) { ! 566: case 4: setup_count = 0x00; break; ! 567: case 3: setup_count = 0x80; break; ! 568: case 1: ! 569: case 2: setup_count = 0x40; break; ! 570: default: setup_count = 0xc0; /* case 5 */ ! 571: } ! 572: ! 573: /* ! 574: * Now that everything is ready, program the new timings ! 575: */ ! 576: save_flags (flags); ! 577: cli(); ! 578: /* ! 579: * Program the address_setup clocks into ARTTIM reg, ! 580: * and then the active/recovery counts into the DRWTIM reg ! 581: * (this converts counts of 16 into counts of zero -- okay). ! 582: */ ! 583: setup_count |= get_cmd640_reg(arttim_regs[index]) & 0x3f; ! 584: put_cmd640_reg(arttim_regs[index], setup_count); ! 585: put_cmd640_reg(drwtim_regs[index], pack_nibbles(active_count, recovery_count)); ! 586: restore_flags(flags); ! 587: } ! 588: ! 589: /* ! 590: * Set a specific pio_mode for a drive ! 591: */ ! 592: static void cmd640_set_mode (unsigned int index, byte pio_mode, unsigned int cycle_time) ! 593: { ! 594: int setup_time, active_time, recovery_time, clock_time; ! 595: byte setup_count, active_count, recovery_count, recovery_count2, cycle_count; ! 596: int bus_speed = ide_system_bus_speed(); ! 597: ! 598: if (pio_mode > 5) ! 599: pio_mode = 5; ! 600: setup_time = ide_pio_timings[pio_mode].setup_time; ! 601: active_time = ide_pio_timings[pio_mode].active_time; ! 602: recovery_time = cycle_time - (setup_time + active_time); ! 603: clock_time = 1000 / bus_speed; ! 604: cycle_count = (cycle_time + clock_time - 1) / clock_time; ! 605: ! 606: setup_count = (setup_time + clock_time - 1) / clock_time; ! 607: ! 608: active_count = (active_time + clock_time - 1) / clock_time; ! 609: if (active_count < 2) ! 610: active_count = 2; /* minimum allowed by cmd640 */ ! 611: ! 612: recovery_count = (recovery_time + clock_time - 1) / clock_time; ! 613: recovery_count2 = cycle_count - (setup_count + active_count); ! 614: if (recovery_count2 > recovery_count) ! 615: recovery_count = recovery_count2; ! 616: if (recovery_count < 2) ! 617: recovery_count = 2; /* minimum allowed by cmd640 */ ! 618: if (recovery_count > 17) { ! 619: active_count += recovery_count - 17; ! 620: recovery_count = 17; ! 621: } ! 622: if (active_count > 16) ! 623: active_count = 16; /* maximum allowed by cmd640 */ ! 624: if (cmd640_chip_version > 1) ! 625: recovery_count -= 1; /* cmd640b uses (count + 1)*/ ! 626: if (recovery_count > 16) ! 627: recovery_count = 16; /* maximum allowed by cmd640 */ ! 628: ! 629: setup_counts[index] = setup_count; ! 630: active_counts[index] = active_count; ! 631: recovery_counts[index] = recovery_count; ! 632: ! 633: /* ! 634: * In a perfect world, we might set the drive pio mode here ! 635: * (using WIN_SETFEATURE) before continuing. ! 636: * ! 637: * But we do not, because: ! 638: * 1) this is the wrong place to do it (proper is do_special() in ide.c) ! 639: * 2) in practice this is rarely, if ever, necessary ! 640: */ ! 641: program_drive_counts (index); ! 642: } ! 643: ! 644: /* ! 645: * Drive PIO mode selection: ! 646: */ ! 647: static void cmd640_tune_drive (ide_drive_t *drive, byte mode_wanted) ! 648: { ! 649: byte b; ! 650: ide_pio_data_t d; ! 651: unsigned int index = 0; ! 652: ! 653: while (drive != cmd_drives[index]) { ! 654: if (++index > 3) { ! 655: printk("%s: bad news in cmd640_tune_drive\n", drive->name); ! 656: return; ! 657: } ! 658: } ! 659: switch (mode_wanted) { ! 660: case 6: /* set fast-devsel off */ ! 661: case 7: /* set fast-devsel on */ ! 662: mode_wanted &= 1; ! 663: b = get_cmd640_reg(CNTRL) & ~0x27; ! 664: if (mode_wanted) ! 665: b |= 0x27; ! 666: put_cmd640_reg(CNTRL, b); ! 667: printk("%s: %sabled cmd640 fast host timing (devsel)\n", drive->name, mode_wanted ? "en" : "dis"); ! 668: return; ! 669: ! 670: case 8: /* set prefetch off */ ! 671: case 9: /* set prefetch on */ ! 672: mode_wanted &= 1; ! 673: set_prefetch_mode(index, mode_wanted); ! 674: printk("%s: %sabled cmd640 prefetch\n", drive->name, mode_wanted ? "en" : "dis"); ! 675: return; ! 676: } ! 677: ! 678: (void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d); ! 679: cmd640_set_mode (index, d.pio_mode, d.cycle_time); ! 680: ! 681: printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s", ! 682: drive->name, ! 683: d.pio_mode, ! 684: d.cycle_time, ! 685: d.use_iordy ? "w" : "wo", ! 686: d.overridden ? " (overriding vendor mode)" : ""); ! 687: display_clocks(index); ! 688: } ! 689: ! 690: #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ ! 691: ! 692: /* ! 693: * Probe for a cmd640 chipset, and initialize it if found. Called from ide.c ! 694: */ ! 695: int ide_probe_for_cmd640x (void) ! 696: { ! 697: #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED ! 698: int second_port_toggled = 0; ! 699: #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ ! 700: int second_port_cmd640 = 0; ! 701: const char *bus_type, *port2; ! 702: unsigned int index; ! 703: byte b, cfr; ! 704: ! 705: if (cmd640_vlb && probe_for_cmd640_vlb()) { ! 706: bus_type = "VLB"; ! 707: } else { ! 708: cmd640_vlb = 0; ! 709: if (probe_for_cmd640_pci1()) ! 710: bus_type = "PCI (type1)"; ! 711: else if (probe_for_cmd640_pci2()) ! 712: bus_type = "PCI (type2)"; ! 713: else ! 714: return 0; ! 715: } ! 716: /* ! 717: * Undocumented magic (there is no 0x5b reg in specs) ! 718: */ ! 719: put_cmd640_reg(0x5b, 0xbd); ! 720: if (get_cmd640_reg(0x5b) != 0xbd) { ! 721: printk("ide: cmd640 init failed: wrong value in reg 0x5b\n"); ! 722: return 0; ! 723: } ! 724: put_cmd640_reg(0x5b, 0); ! 725: ! 726: #ifdef CMD640_DUMP_REGS ! 727: CMD640_DUMP_REGS; ! 728: #endif ! 729: ! 730: /* ! 731: * Documented magic begins here ! 732: */ ! 733: cfr = get_cmd640_reg(CFR); ! 734: cmd640_chip_version = cfr & CFR_DEVREV; ! 735: if (cmd640_chip_version == 0) { ! 736: printk ("ide: bad cmd640 revision: %d\n", cmd640_chip_version); ! 737: return 0; ! 738: } ! 739: ! 740: /* ! 741: * Initialize data for primary port ! 742: */ ! 743: setup_device_ptrs (); ! 744: printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n", ! 745: cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr); ! 746: cmd_hwif0->chipset = ide_cmd640; ! 747: #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED ! 748: cmd_hwif0->tuneproc = &cmd640_tune_drive; ! 749: #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ ! 750: ! 751: /* ! 752: * Ensure compatibility by always using the slowest timings ! 753: * for access to the drive's command register block, ! 754: * and reset the prefetch burstsize to default (512 bytes). ! 755: * ! 756: * Maybe we need a way to NOT do these on *some* systems? ! 757: */ ! 758: put_cmd640_reg(CMDTIM, 0); ! 759: put_cmd640_reg(BRST, 0x40); ! 760: ! 761: /* ! 762: * Try to enable the secondary interface, if not already enabled ! 763: */ ! 764: if (cmd_hwif1->noprobe) { ! 765: port2 = "not probed"; ! 766: } else { ! 767: b = get_cmd640_reg(CNTRL); ! 768: if (secondary_port_responding()) { ! 769: if ((b & CNTRL_ENA_2ND)) { ! 770: second_port_cmd640 = 1; ! 771: port2 = "okay"; ! 772: } else if (cmd640_vlb) { ! 773: second_port_cmd640 = 1; ! 774: port2 = "alive"; ! 775: } else ! 776: port2 = "not cmd640"; ! 777: } else { ! 778: put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ ! 779: if (secondary_port_responding()) { ! 780: second_port_cmd640 = 1; ! 781: #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED ! 782: second_port_toggled = 1; ! 783: #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ ! 784: port2 = "enabled"; ! 785: } else { ! 786: put_cmd640_reg(CNTRL, b); /* restore original setting */ ! 787: port2 = "not responding"; ! 788: } ! 789: } ! 790: } ! 791: ! 792: /* ! 793: * Initialize data for secondary cmd640 port, if enabled ! 794: */ ! 795: if (second_port_cmd640) { ! 796: cmd_hwif0->serialized = 1; ! 797: cmd_hwif1->serialized = 1; ! 798: cmd_hwif1->chipset = ide_cmd640; ! 799: #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED ! 800: cmd_hwif1->tuneproc = &cmd640_tune_drive; ! 801: #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ ! 802: } ! 803: printk("%s: %sserialized, secondary interface %s\n", cmd_hwif1->name, ! 804: cmd_hwif0->serialized ? "" : "not ", port2); ! 805: ! 806: /* ! 807: * Establish initial timings/prefetch for all drives. ! 808: * Do not unnecessarily disturb any prior BIOS setup of these. ! 809: */ ! 810: for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { ! 811: ide_drive_t *drive = cmd_drives[index]; ! 812: #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED ! 813: if (drive->autotune || ((index > 1) && second_port_toggled)) { ! 814: /* ! 815: * Reset timing to the slowest speed and turn off prefetch. ! 816: * This way, the drive identify code has a better chance. ! 817: */ ! 818: setup_counts [index] = 4; /* max possible */ ! 819: active_counts [index] = 16; /* max possible */ ! 820: recovery_counts [index] = 16; /* max possible */ ! 821: program_drive_counts (index); ! 822: set_prefetch_mode (index, 0); ! 823: printk("cmd640: drive%d timings/prefetch cleared\n", index); ! 824: } else { ! 825: /* ! 826: * Record timings/prefetch without changing them. ! 827: * This preserves any prior BIOS setup. ! 828: */ ! 829: retrieve_drive_counts (index); ! 830: check_prefetch (index); ! 831: printk("cmd640: drive%d timings/prefetch(%s) preserved", ! 832: index, drive->no_io_32bit ? "off" : "on"); ! 833: display_clocks(index); ! 834: } ! 835: #else ! 836: /* ! 837: * Set the drive unmask flags to match the prefetch setting ! 838: */ ! 839: check_prefetch (index); ! 840: printk("cmd640: drive%d timings/prefetch(%s) preserved\n", ! 841: index, drive->no_io_32bit ? "off" : "on"); ! 842: #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ ! 843: } ! 844: ! 845: #ifdef CMD640_DUMP_REGS ! 846: CMD640_DUMP_REGS; ! 847: #endif ! 848: return 1; ! 849: } ! 850:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.