Annotation of Gnu-Mach/linux/src/drivers/block/cmd640.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.