Annotation of Gnu-Mach/i386/i386at/gpl/linux/block/cmd640.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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