root/vendorsrc/linux/current/drivers/ide/pci/cmd640.c @ 29

Revision 28, 24.3 KB (checked in by ckauhaus, 8 years ago)

Import Linux 2.4.26

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