patch-1.3.61 linux/drivers/block/cmd640.c
Next file: linux/drivers/block/dtc2278.c
Previous file: linux/drivers/block/ali14xx.c
Back to the patch index
Back to the overall index
- Lines: 778
- Date:
Fri Feb 9 07:31:22 1996
- Orig file:
v1.3.60/linux/drivers/block/cmd640.c
- Orig date:
Tue Jan 23 21:15:37 1996
diff -u --recursive --new-file v1.3.60/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
@@ -1,11 +1,11 @@
/*
- * linux/drivers/block/cmd640.c Version 0.04 Jan 11, 1996
+ * linux/drivers/block/cmd640.c Version 0.07 Jan 27, 1996
*
* Copyright (C) 1995-1996 Linus Torvalds & author (see below)
*/
/*
- * Principal Author/Maintainer: abramov@cecmow.enet.dec.com (Igor)
+ * Principal Author/Maintainer: abramov@cecmow.enet.dec.com (Igor Abramov)
*
* This file provides support for the advanced features and bugs
* of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
@@ -23,26 +23,27 @@
* with read ahead mode. Separate function for setting
* readahead is added, possibly it will be called some
* day from ioctl processing code.
+ *
+ * Version 0.04 Now configs/compiles separate from ide.c -ml
*
- * Version 0.04 Now configs/compiles separate from ide.c -ml
- */
-
-/*
- * There is a known problem with current version of this driver.
- * If the only device on secondary interface is CD-ROM, at some
- * computers it is not recognized. In all reported cases CD-ROM
- * was 2x or 4x speed Mitsumi drive.
+ * Version 0.05 Major rewrite of interface timing code.
+ * Added new function cmd640_set_mode to set PIO mode
+ * from ioctl call. New drives added to black list.
*
- * The following workarounds could work:
+ * Version 0.06 More code cleanup. Readahead is enabled only for
+ * detected hard drives, not included in readahed
+ * black list.
*
- * 1. put CD-ROM as slave on primary interface
+ * Version 0.07 Changed to more conservative drive tuning policy.
+ * Unknown drives, which report PIO < 4 are set to
+ * (reported_PIO - 1) if it is supported, or to PIO0.
+ * List of known drives extended by info provided by
+ * CMD at their ftp site.
*
- * 2. or define symbol at next line as 0
- *
+ * Version 0.08 Added autotune/noautotune support. -ml
+ *
*/
-#define CMD640_NORMAL_INIT 1
-
#undef REALLY_SLOW_IO /* most systems can safely undef this */
#include <linux/types.h>
@@ -54,11 +55,8 @@
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <asm/io.h>
-
#include "ide.h"
-extern ide_hwif_t ide_hwifs[];
-
int cmd640_vlb = 0;
/*
@@ -104,63 +102,64 @@
#define DRWTIM23 0x58
#define BRST 0x59
+static ide_tuneproc_t cmd640_tune_drive;
+
/* Interface to access cmd640x registers */
-static void (*put_cmd640_reg)(int key, int reg_no, int val);
-static byte (*get_cmd640_reg)(int key, int reg_no);
+static void (*put_cmd640_reg)(int reg_no, int val);
+static byte (*get_cmd640_reg)(int reg_no);
enum { none, vlb, pci1, pci2 };
static int bus_type = none;
static int cmd640_chip_version;
static int cmd640_key;
-static byte is_cmd640[MAX_HWIFS];
static int bus_speed; /* MHz */
/*
* For some unknown reasons pcibios functions which read and write registers
- * do not always work with cmd640. We use direct io instead.
+ * do not always work with cmd640. We use direct IO instead.
*/
/* PCI method 1 access */
-static void put_cmd640_reg_pci1(int key, int reg_no, int val)
+static void put_cmd640_reg_pci1(int reg_no, int val)
{
unsigned long flags;
save_flags(flags);
cli();
- outl_p((reg_no & 0xfc) | key, 0xcf8);
+ outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
outb_p(val, (reg_no & 3) + 0xcfc);
restore_flags(flags);
}
-static byte get_cmd640_reg_pci1(int key, int reg_no)
+static byte get_cmd640_reg_pci1(int reg_no)
{
byte b;
unsigned long flags;
save_flags(flags);
cli();
- outl_p((reg_no & 0xfc) | key, 0xcf8);
+ outl_p((reg_no & 0xfc) | cmd640_key, 0xcf8);
b = inb_p(0xcfc + (reg_no & 3));
restore_flags(flags);
return b;
}
/* PCI method 2 access (from CMD datasheet) */
-
-static void put_cmd640_reg_pci2(int key, int reg_no, int val)
+
+static void put_cmd640_reg_pci2(int reg_no, int val)
{
unsigned long flags;
save_flags(flags);
cli();
outb_p(0x10, 0xcf8);
- outb_p(val, key + reg_no);
+ outb_p(val, cmd640_key + reg_no);
outb_p(0, 0xcf8);
restore_flags(flags);
}
-static byte get_cmd640_reg_pci2(int key, int reg_no)
+static byte get_cmd640_reg_pci2(int reg_no)
{
byte b;
unsigned long flags;
@@ -168,7 +167,7 @@
save_flags(flags);
cli();
outb_p(0x10, 0xcf8);
- b = inb_p(key + reg_no);
+ b = inb_p(cmd640_key + reg_no);
outb_p(0, 0xcf8);
restore_flags(flags);
return b;
@@ -176,26 +175,26 @@
/* VLB access */
-static void put_cmd640_reg_vlb(int key, int reg_no, int val)
+static void put_cmd640_reg_vlb(int reg_no, int val)
{
unsigned long flags;
save_flags(flags);
cli();
- outb_p(reg_no, key + 8);
- outb_p(val, key + 0xc);
+ outb_p(reg_no, cmd640_key + 8);
+ outb_p(val, cmd640_key + 0xc);
restore_flags(flags);
}
-static byte get_cmd640_reg_vlb(int key, int reg_no)
+static byte get_cmd640_reg_vlb(int reg_no)
{
byte b;
unsigned long flags;
save_flags(flags);
cli();
- outb_p(reg_no, key + 8);
- b = inb_p(key + 0xc);
+ outb_p(reg_no, cmd640_key + 8);
+ b = inb_p(cmd640_key + 0xc);
restore_flags(flags);
return b;
}
@@ -305,13 +304,8 @@
int ide_probe_for_cmd640x(void)
{
- int i;
int second_port;
- int cmd_read_ahead;
- byte b;
-
- for (i = 0; i < MAX_HWIFS; i++)
- is_cmd640[i] = 0;
+ byte b;
if (probe_for_cmd640_pci1()) {
bus_type = pci1;
@@ -324,28 +318,46 @@
return 0;
}
+ ide_hwifs[0].serialized = 1; /* ensure this *always* gets set */
+
+#if 0
+ /* Dump initial state of chip registers */
+ for (b = 0; b != 0xff; b++) {
+ printk(" %2x%c", get_cmd640_reg(b),
+ ((b&0xf) == 0xf) ? '\n' : ',');
+ }
+
+#endif
+
/*
* Undocumented magic. (There is no 0x5b port in specs)
*/
- put_cmd640_reg(cmd640_key, 0x5b, 0xbd);
- if (get_cmd640_reg(cmd640_key, 0x5b) != 0xbd) {
+ put_cmd640_reg(0x5b, 0xbd);
+ if (get_cmd640_reg(0x5b) != 0xbd) {
printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
return 0;
}
- put_cmd640_reg(cmd640_key, 0x5b, 0);
+ put_cmd640_reg(0x5b, 0);
/*
* Documented magic.
*/
- cmd640_chip_version = get_cmd640_reg(cmd640_key, CFR) & CFR_DEVREV;
+ cmd640_chip_version = get_cmd640_reg(CFR) & CFR_DEVREV;
if (cmd640_chip_version == 0) {
printk ("ide: wrong CMD640 version -- 0\n");
return 0;
}
/*
+ * Setup the most conservative timings for all drives,
+ */
+ put_cmd640_reg(ARTTIM0, 0xc0);
+ put_cmd640_reg(ARTTIM1, 0xc0);
+ put_cmd640_reg(ARTTIM23, 0xcc); /* 0xc0? */
+
+ /*
* Do not initialize secondary controller for vlbus
*/
second_port = (bus_type != vlb);
@@ -357,45 +369,51 @@
*/
bus_speed = (bus_type == vlb) ? 50 : 40;
- /*
- * Enable readahead for versions above 'A'
- */
- cmd_read_ahead = (cmd640_chip_version > 1);
-
- /*
+ /*
* Setup Control Register
*/
- b = get_cmd640_reg(cmd640_key, CNTRL);
+ b = get_cmd640_reg(CNTRL);
-#if CMD640_NORMAL_INIT
if (second_port)
b |= CNTRL_ENA_2ND;
else
b &= ~CNTRL_ENA_2ND;
-#endif
- if (cmd_read_ahead)
- b &= ~(CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
- else
- b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
+ /*
+ * Disable readahead for drives at primary interface
+ */
+ b |= (CNTRL_DIS_RA0 | CNTRL_DIS_RA1);
+ put_cmd640_reg(CNTRL, b);
- put_cmd640_reg(cmd640_key, CNTRL, b);
+ /*
+ * Note that we assume that the first interface is at 0x1f0,
+ * and that the second interface, if enabled, is at 0x170.
+ */
+ ide_hwifs[0].chipset = ide_cmd640;
+ ide_hwifs[0].tuneproc = &cmd640_tune_drive;
+ if (ide_hwifs[0].drives[0].autotune == 0)
+ ide_hwifs[0].drives[0].autotune = 1;
+ if (ide_hwifs[0].drives[1].autotune == 0)
+ ide_hwifs[0].drives[1].autotune = 1;
/*
* Initialize 2nd IDE port, if required
*/
if (second_port) {
- /* We reset timings, and setup read-ahead */
- b = cmd_read_ahead ? 0 : (DIS_RA2 | DIS_RA3);
- put_cmd640_reg(cmd640_key, ARTTIM23, b);
- put_cmd640_reg(cmd640_key, DRWTIM23, 0);
+ ide_hwifs[1].chipset = ide_cmd640;
+ ide_hwifs[1].tuneproc = &cmd640_tune_drive;
+ if (ide_hwifs[1].drives[0].autotune == 0)
+ ide_hwifs[1].drives[0].autotune = 1;
+ if (ide_hwifs[1].drives[1].autotune == 0)
+ ide_hwifs[1].drives[1].autotune = 1;
+ /* We reset timings, and disable read-ahead */
+ put_cmd640_reg(ARTTIM23, (DIS_RA2 | DIS_RA3));
+ put_cmd640_reg(DRWTIM23, 0);
cmd640_reset_controller(1);
}
- ide_hwifs[0].serialized = 1;
-
printk("ide: buggy CMD640%c interface at ",
'A' - 1 + cmd640_chip_version);
switch (bus_type) {
@@ -410,28 +428,28 @@
break;
}
- is_cmd640[0] = is_cmd640[1] = 1;
-
/*
* Reset interface timings
*/
- put_cmd640_reg(cmd640_key, CMDTIM, 0);
+ put_cmd640_reg(CMDTIM, 0);
- printk("\n ... serialized, %s read-ahead, secondary interface %s\n",
- cmd_read_ahead ? "enabled" : "disabled",
+ printk("\n ... serialized, secondary interface %s\n",
second_port ? "enabled" : "disabled");
return 1;
}
-static int as_clocks(int a) {
- switch (a & 0xc0) {
- case 0 : return 4;
- case 0x40 : return 2;
- case 0x80 : return 3;
- case 0xc0 : return 5;
- default : return -1;
- }
+int cmd640_off(void) {
+ static int a = 0;
+ byte b;
+
+ if (bus_type == none || a == 1)
+ return 0;
+ a = 1;
+ b = get_cmd640_reg(CNTRL);
+ b &= ~CNTRL_ENA_2ND;
+ put_cmd640_reg(CNTRL, b);
+ return 1;
}
/*
@@ -451,72 +469,122 @@
int mask = masks[if_num][dr_num];
byte b;
- b = get_cmd640_reg(cmd640_key, port);
+ b = get_cmd640_reg(port);
if (mode)
- b &= mask; /* Enable readahead for specific drive */
+ b &= ~mask; /* Enable readahead for specific drive */
else
- b |= mask; /* Disable readahed for specific drive */
- put_cmd640_reg(cmd640_key, port, b);
+ b |= mask; /* Disable readahed for specific drive */
+ put_cmd640_reg(port, b);
}
static struct readahead_black_list {
const char* name;
int mode;
} drives_ra[] = {
- { "ST3655A", 0 },
+ { "ST3655A", 0 },
+ { "SAMSUNG", 0 }, /* Be conservative */
{ NULL, 0 }
};
+static int strmatch(const char* pattern, const char* name) {
+ char c1, c2;
+
+ while (1) {
+ c1 = *pattern++;
+ c2 = *name++;
+ if (c1 == 0) {
+ return 0;
+ }
+ if (c1 != c2)
+ return 1;
+ }
+}
+
static int known_drive_readahead(char* name) {
int i;
- for (i = 0; drives_ra[i].name != NULL; i++)
- if (strcmp(name, drives_ra[i].name) == 0)
+ for (i = 0; drives_ra[i].name != NULL; i++) {
+ if (strmatch(drives_ra[i].name, name) == 0) {
return drives_ra[i].mode;
- return -1;
+ }
+ }
+ return -1;
}
+static int arttim[4] = {2, 2, 2, 2}; /* Address setup count (in clocks) */
+static int a_count[4] = {1, 1, 1, 1}; /* Active count (encoded) */
+static int r_count[4] = {1, 1, 1, 1}; /* Recovery count (encoded) */
+
/*
- * Tuning of drive parameters
+ * Convert address setup count from number of clocks
+ * to representation used by controller
*/
-static void cmd640_set_timing(int if_num, int dr_num, int r1, int r2) {
- int b_reg;
- byte b;
- int r52;
- static int a = 0;
+inline static int pack_arttim(int clocks)
+{
+ if (clocks <= 2) return 0x40;
+ else if (clocks == 3) return 0x80;
+ else if (clocks == 4) return 0x00;
+ else return 0xc0;
+}
+
+/*
+ * Pack active and recovery counts into single byte representation
+ * used by controller
+ */
+
+inline static int pack_counts(int act_count, int rec_count)
+{
+ return ((act_count & 0x0f)<<4) | (rec_count & 0x0f);
+}
+
+inline int max(int a, int b) { return a > b ? a : b; }
+inline int max4(int *p) { return max(p[0], max(p[1], max(p[2], p[3]))); }
+
+/*
+ * Set timing parameters
+ */
+
+static void cmd640_set_timing(int if_num, int dr_num)
+{
+ int b_reg;
+ int ac, rc, at;
- b_reg = if_num ? ARTTIM23 : dr_num ? ARTTIM1 : ARTTIM0;
+ /*
+ * Set address setup count and drive read/write timing registers.
+ * Primary interface has individual count/timing registers for
+ * each drive. Secondary interface has common set of registers, and
+ * we should set timings for the slowest drive.
+ */
if (if_num == 0) {
- put_cmd640_reg(cmd640_key, b_reg, r1);
- put_cmd640_reg(cmd640_key, b_reg + 1, r2);
+ b_reg = dr_num ? ARTTIM1 : ARTTIM0;
+ at = arttim[dr_num];
+ ac = a_count[dr_num];
+ rc = r_count[dr_num];
} else {
- b = get_cmd640_reg(cmd640_key, b_reg);
- if (a == 0 || as_clocks(b) < as_clocks(r1))
- put_cmd640_reg(cmd640_key, b_reg, (b & 0xc0) | r1);
-
- if (a == 0) {
- put_cmd640_reg(cmd640_key, b_reg + 1, r2);
- } else {
- b = get_cmd640_reg(cmd640_key, b_reg + 1);
- r52 = (b&0x0f) < (r2&0x0f) ? (r2&0x0f) : (b&0x0f);
- r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
- put_cmd640_reg(cmd640_key, b_reg+1, r52);
- }
- a = 1;
+ b_reg = ARTTIM23;
+ at = max(arttim[2], arttim[3]);
+ ac = max(a_count[2], a_count[3]);
+ rc = max(r_count[2], r_count[3]);
}
- b = get_cmd640_reg(cmd640_key, CMDTIM);
- if (b == 0) {
- put_cmd640_reg(cmd640_key, CMDTIM, r2);
- } else {
- r52 = (b&0x0f) < (r2&0x0f) ? (r2&0x0f) : (b&0x0f);
- r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
- put_cmd640_reg(cmd640_key, CMDTIM, r52);
- }
+ put_cmd640_reg(b_reg, pack_arttim(at));
+ put_cmd640_reg(b_reg + 1, pack_counts(ac, rc));
+
+ /*
+ * Update CMDTIM (IDE Command Block Timing Register)
+ */
+
+ ac = max4(r_count);
+ rc = max4(a_count);
+ put_cmd640_reg(CMDTIM, pack_counts(ac, rc));
}
+/*
+ * Standard timings for PIO modes
+ */
+
static struct pio_timing {
int mc_time; /* Minimal cycle time (ns) */
int av_time; /* Address valid to DIOR-/DIOW- setup (ns) */
@@ -527,23 +595,74 @@
{ 30, 100, 240 }, /* PIO Mode 2 */
{ 30, 80, 180 }, /* PIO Mode 3 */
{ 25, 70, 125 }, /* PIO Mode 4 */
- { 20, 50, 100 } /* PIO Mode ? */
+ { 20, 50, 100 } /* PIO Mode ? (nonstandard) */
};
+/*
+ * Black list. Some drives incorrectly report their maximal PIO modes, at least
+ * in respect to CMD640. Here we keep info on some known drives.
+ */
+
static struct drive_pio_info {
const char *name;
int pio;
} drive_pios[] = {
+/* { "Conner Peripherals 1275MB - CFS1275A", 4 }, */
+
+ { "WDC AC2700", 3 },
+ { "WDC AC2540", 3 },
+ { "WDC AC2420", 3 },
+ { "WDC AC2340", 3 },
+ { "WDC AC2250", 0 },
+ { "WDC AC2200", 0 },
+ { "WDC AC2120", 0 },
+ { "WDC AC2850", 3 },
+ { "WDC AC1270", 3 },
+ { "WDC AC1170", 3 },
+ { "WDC AC1210", 1 },
+ { "WDC AC280", 0 },
+/* { "WDC AC21000", 4 }, */
+ { "WDC AC31000", 3 },
+/* { "WDC AC21200", 4 }, */
+ { "WDC AC31200", 3 },
+/* { "WDC AC31600", 4 }, */
+
{ "Maxtor 7131 AT", 1 },
{ "Maxtor 7171 AT", 1 },
{ "Maxtor 7213 AT", 1 },
{ "Maxtor 7245 AT", 1 },
+ { "Maxtor 7345 AT", 1 },
+ { "Maxtor 7546 AT", 3 },
+ { "Maxtor 7540 AV", 3 },
+
+ { "SAMSUNG SHD-3121A", 1 },
{ "SAMSUNG SHD-3122A", 1 },
+ { "SAMSUNG SHD-3172A", 1 },
+
+/* { "ST51080A", 4 },
+ * { "ST51270A", 4 },
+ * { "ST31220A", 4 },
+ * { "ST31640A", 4 },
+ * { "ST32140A", 4 },
+ * { "ST3780A", 4 },
+ */ { "ST5660A", 3 },
+ { "ST3660A", 3 },
+ { "ST3630A", 3 },
+ { "ST3655A", 3 },
+ { "ST3391A", 3 },
+ { "ST3390A", 1 },
+ { "ST3600A", 1 },
+ { "ST3290A", 0 },
+ { "ST3144A", 0 },
+
{ "QUANTUM ELS127A", 0 },
+ { "QUANTUM ELS170A", 0 },
{ "QUANTUM LPS240A", 0 },
+ { "QUANTUM LPS210A", 3 },
{ "QUANTUM LPS270A", 3 },
+ { "QUANTUM LPS365A", 3 },
{ "QUANTUM LPS540A", 3 },
- { "QUANTUM FIREBALL1080A", 3 },
+ { "QUANTUM FIREBALL", 3 }, /* For models 540/640/1080/1280 */
{ NULL, 0 }
};
@@ -551,23 +670,18 @@
struct drive_pio_info* pi;
for (pi = drive_pios; pi->name != NULL; pi++) {
- if (strcmp(pi->name, name) == 0)
+ if (strmatch(pi->name, name) == 0)
return pi->pio;
}
return -1;
}
-static void cmd640_timings_to_regvals(int mc_time, int av_time, int ds_time,
- int clock_time,
- int* r1, int* r2)
+static void cmd640_timings_to_clocks(int mc_time, int av_time, int ds_time,
+ int clock_time, int drv_idx)
{
int a, b;
- a = (mc_time + clock_time - 1)/clock_time;
- if (a <= 2) *r1 = 0x40;
- else if (a == 3) *r1 = 0x80;
- else if (a == 4) *r1 = 0;
- else *r1 = 0xc0;
+ arttim[drv_idx] = (mc_time + clock_time - 1)/clock_time;
a = (av_time + clock_time - 1)/clock_time;
if (a < 2)
@@ -579,13 +693,15 @@
a += b - 0x11;
b = 0x11;
}
- if (a > 0xf)
- a = 0;
+ if (a > 0x10)
+ a = 0x10;
if (cmd640_chip_version > 1)
b -= 1;
- if (b > 0xf)
- b = 0;
- *r2 = (a << 4) | b;
+ if (b > 0x10)
+ b = 0x10;
+
+ a_count[drv_idx] = a;
+ r_count[drv_idx] = b;
}
static void set_pio_mode(int if_num, int drv_num, int mode_num) {
@@ -601,34 +717,57 @@
udelay(10000);
}
-void cmd640_tune_drive(ide_drive_t* drive) {
+/*
+ * Set a specific pio_mode for a drive
+ */
+
+static void cmd640_set_mode(ide_drive_t* drive, int pio_mode) {
+ int interface_number;
+ int drive_number;
+ int clock_time; /* ns */
+ int mc_time, av_time, ds_time;
+
+ interface_number = HWIF(drive)->index;
+ drive_number = drive->select.b.unit;
+ clock_time = 1000/bus_speed;
+
+ mc_time = pio_timings[pio_mode].mc_time;
+ av_time = pio_timings[pio_mode].av_time;
+ ds_time = pio_timings[pio_mode].ds_time;
+
+ cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
+ interface_number*2 + drive_number);
+ set_pio_mode(interface_number, drive_number, pio_mode);
+ cmd640_set_timing(interface_number, drive_number);
+}
+
+/*
+ * Drive PIO mode "autoconfiguration".
+ * Ideally, this code should *always* call cmd640_set_mode(), but it doesn't.
+ */
+
+static void cmd640_tune_drive(ide_drive_t *drive, byte pio_mode) {
int interface_number;
int drive_number;
int clock_time; /* ns */
int max_pio;
int mc_time, av_time, ds_time;
struct hd_driveid* id;
- int r1, r2;
- int mode;
+ int readahead; /* there is a global named read_ahead */
- /*
- * Determine if drive is under cmd640 control
- */
- interface_number = HWIF(drive) - ide_hwifs;
- if (!is_cmd640[interface_number])
+ if (pio_mode != 255) {
+ cmd640_set_mode(drive, pio_mode);
return;
+ }
- drive_number = drive - HWIF(drive)->drives;
+ interface_number = HWIF(drive)->index;
+ drive_number = drive->select.b.unit;
clock_time = 1000/bus_speed;
id = drive->id;
if ((max_pio = known_drive_pio(id->model)) != -1) {
- mc_time = pio_timings[max_pio].mc_time;
- av_time = pio_timings[max_pio].av_time;
ds_time = pio_timings[max_pio].ds_time;
} else {
max_pio = id->tPIO;
- mc_time = pio_timings[max_pio].mc_time;
- av_time = pio_timings[max_pio].av_time;
ds_time = pio_timings[max_pio].ds_time;
if (id->field_valid & 2) {
if ((id->capability & 8) && (id->eide_pio_modes & 7)) {
@@ -636,26 +775,41 @@
else if (id->eide_pio_modes & 2) max_pio = 4;
else max_pio = 3;
ds_time = id->eide_pio_iordy;
- mc_time = pio_timings[max_pio].mc_time;
- av_time = pio_timings[max_pio].av_time;
} else {
ds_time = id->eide_pio;
}
if (ds_time == 0)
ds_time = pio_timings[max_pio].ds_time;
}
+
+ /*
+ * Conservative "downgrade"
+ */
+ if (max_pio < 4 && max_pio != 0) {
+ max_pio -= 1;
+ ds_time = pio_timings[max_pio].ds_time;
+ }
}
- cmd640_timings_to_regvals(mc_time, av_time, ds_time, clock_time,
- &r1, &r2);
+ mc_time = pio_timings[max_pio].mc_time;
+ av_time = pio_timings[max_pio].av_time;
+ cmd640_timings_to_clocks(mc_time, av_time, ds_time, clock_time,
+ interface_number*2 + drive_number);
set_pio_mode(interface_number, drive_number, max_pio);
- cmd640_set_timing(interface_number, drive_number, r1, r2);
+ cmd640_set_timing(interface_number, drive_number);
/*
- * Disable (or set) readahead mode for known drive
+ * Disable (or set) readahead mode
*/
- if ((mode = known_drive_readahead(id->model)) != -1) {
- set_readahead_mode(mode, interface_number, drive_number);
- printk("Readahead %s,", mode ? "enabled" : "disabled");
- }
- printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2);
+
+ readahead = 0;
+ if (cmd640_chip_version > 1) { /* Mmmm.. probably should be > 2 ?? */
+ readahead = known_drive_readahead(id->model);
+ if (readahead == -1)
+ readahead = 1; /* Mmmm.. probably be 0 ?? */
+ set_readahead_mode(readahead, interface_number, drive_number);
+ }
+
+ printk ("Mode and Timing set to PIO%d, Readahead is %s\n",
+ max_pio, readahead ? "enabled" : "disabled");
}
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this