patch-1.3.44 linux/drivers/block/cmd640.c

Next file: linux/drivers/block/ide-cd.c
Previous file: linux/drivers/block/README.ide
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.43/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
@@ -1,444 +0,0 @@
-/*
- *  linux/drivers/block/cmd640.c	Version 0.01  Nov 16, 1995
- *
- *  Copyright (C) 1995  Linus Torvalds & author (see below)
- */
-
-/*
- *  Principal Author/Maintainer:  abramov@cecmow.enet.dec.com (Igor)
- *
- *  This file provides support for the advanced features and bugs
- *  of IDE interfaces using the CMD Technologies 0640 IDE interface chip.
- *
- *  Version 0.01	Initial version, hacked out of ide.c,
- *			and #include'd rather than compiled separately.
- *			This will get cleaned up in a subsequent release.
- */
-
-/* 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);
-
-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];
-
-/*
- * For some unknown reasons pcibios functions which read and write registers
- * do not 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)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outl_p((reg_no & 0xfc) | key, 0xcf8);
-	outb_p(val, (reg_no & 3) + 0xcfc);
-	restore_flags(flags);
-}
-
-static byte get_cmd640_reg_pci1(int key, int reg_no)
-{
-	byte b;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outl_p((reg_no & 0xfc) | key, 0xcf8);
-	b = inb(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)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb_p(0x10, 0xcf8);
-	outb_p(val, key + reg_no);
-	outb_p(0, 0xcf8);
-	restore_flags(flags);
-}
-
-static byte get_cmd640_reg_pci2(int key, int reg_no)
-{
-	byte b;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb_p(0x10, 0xcf8);
-	b = inb(key + reg_no);
-	outb_p(0, 0xcf8);
-	restore_flags(flags);
-	return b;
-}
-
-/* VLB access */
-
-static void put_cmd640_reg_vlb(int key, int reg_no, int val)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb(reg_no, key + 8);
-	outb(val, key + 0xc);
-	restore_flags(flags);
-}
-
-static byte get_cmd640_reg_vlb(int key, int reg_no)
-{
-	byte b;
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	outb(reg_no, key + 8);
-	b = inb(key + 0xc);
-	restore_flags(flags);
-	return b;
-}
-
-/*
- * Probe for CMD640x -- pci method 1
- */
-
-static int probe_for_cmd640_pci1(void)
-{
-	long id;
-	int	k;
-
-	for (k = 0x80000000; k <= 0x8000f800; k += 0x800) {
-		outl(k, 0xcf8);
-		id = inl(0xcfc);
-		if (id != 0x06401095)
-			continue;
-		put_cmd640_reg = put_cmd640_reg_pci1;
-		get_cmd640_reg = get_cmd640_reg_pci1;
-		cmd640_key = k;
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Probe for CMD640x -- pci method 2
- */
-
-static int probe_for_cmd640_pci2(void)
-{
-	int i;
-	int v_id;
-	int d_id;
-
-	for (i = 0xc000; i <= 0xcf00; i += 0x100) {
-		outb(0x10, 0xcf8);
-		v_id = inw(i);
-		d_id = inw(i + 2);
-		outb(0, 0xcf8);
-		if (v_id != 0x1095 || d_id != 0x640)
-			continue;
-		put_cmd640_reg = put_cmd640_reg_pci2;
-		get_cmd640_reg = get_cmd640_reg_pci2;
-		cmd640_key = i;
-		return 1;
-	}
-	return 0;
-}
-
-/*
- * Probe for CMD640x -- vlb
- */
-
-static int probe_for_cmd640_vlb(void) {
-	byte b;
-
-	outb(0x50, 0x178);
-	b = inb(0x17c);
-	if (b == 0xff || b == 0 || (b & 0x20)) {
-		outb(0x50, 0xc78);
-		b = inb(0x7c);
-		if (b == 0xff || b == 0 || !(b & 0x20))
-			return 0;
-		cmd640_key = 0x70;
-	} else {
-		cmd640_key = 0x170;
-	}
-	put_cmd640_reg = put_cmd640_reg_vlb;
-	get_cmd640_reg = get_cmd640_reg_vlb;
-	return 1;
-}
-
-/*
- * Probe for Cmd640x and initialize it if found
- */
-
-int ide_probe_for_cmd640x(void)
-{
-	int i;
-
-	for (i = 0; i < MAX_HWIFS; i++)
-		is_cmd640[i] = 0;
-
-	if (probe_for_cmd640_pci1()) {
-		bus_type = pci1;
-	} else if (probe_for_cmd640_pci2()) {
-		bus_type = pci2;
-	} else if (cmd640_vlb && probe_for_cmd640_vlb()) {
-		/* May be remove cmd640_vlb at all, and probe in any case */
-		bus_type = vlb;
-	} else {
-		return 0;
-	}
-
-	/*
-	 * Undocumented magic. (There is no 0x5b port in specs)
-	 */
-
-	put_cmd640_reg(cmd640_key, 0x5b, 0xbd);
-	if (get_cmd640_reg(cmd640_key, 0x5b) != 0xbd) {
-		printk("ide: can't initialize cmd640 -- wrong value in 0x5b\n");
-		return 0;
-	}
-	put_cmd640_reg(cmd640_key, 0x5b, 0);
-
-	/*
-	 * Documented magic.
-	 */
-
-	cmd640_chip_version = get_cmd640_reg(cmd640_key, 0x50) & 3;
-	if (cmd640_chip_version == 0) {
-		printk ("ide: wrong CMD640 version -- 0\n");
-		return 0;
-	}
-
-	put_cmd640_reg(cmd640_key, 0x51, get_cmd640_reg(cmd640_key, 0x51) | 0xc8);
-	put_cmd640_reg(cmd640_key, 0x57, 0);
-	put_cmd640_reg(cmd640_key, 0x57, get_cmd640_reg(cmd640_key, 0x57) | 0x0c);
-
-	serialized = 1;
-
-	printk("ide: buggy CMD640 interface at ");
-	switch (bus_type) {
-		case vlb :
-			printk("local bus, port 0x%x", cmd640_key);
-			break;
-		case pci1:
-			printk("pci, (0x%x)", cmd640_key);
-			break;
-		case pci2:
-			printk("pci,(access method 2) (0x%x)", cmd640_key);
-			break;
-	}
-
-	is_cmd640[0] = is_cmd640[1] = 1;
-
-	/*
-	 * Reset interface timings
-	 */
-
-	put_cmd640_reg(cmd640_key, 0x58, 0);
-	put_cmd640_reg(cmd640_key, 0x52, 0);
-
-	printk("\n ... serialized, disabled read-ahead, secondary interface enabled\n");
-
-	return 1;
-}
-
-static int as_clocks(int a) {
-	switch (a & 0xf0) {
-		case 0 :	return 4;
-		case 0x40 :	return 2;
-		case 0x80 :	return 3;
-		case 0xc0 :	return 5;
-		default :	return -1;
-	}
-}
-
-/*
- * Tuning of drive parameters
- */
-
-static void cmd640_set_timing(int if_num, int dr_num, int r1, int r2) {
-	int  b_reg;
-	byte b;
-	int  r52;
-
-	b_reg = if_num ? 0x57 : dr_num ? 0x55 : 0x53;
-
-	if (if_num == 0) {
-		put_cmd640_reg(cmd640_key, b_reg, r1);
-		put_cmd640_reg(cmd640_key, b_reg + 1, r2);
-	} else {
-		b = get_cmd640_reg(cmd640_key, b_reg);
-		if ((b&1) == 0) {
-			put_cmd640_reg(cmd640_key, b_reg, r1);
-		} else {
-			if (as_clocks(b) < as_clocks(r1))
-				put_cmd640_reg(cmd640_key, b_reg, r1);
-		}
-		b = get_cmd640_reg(cmd640_key, b_reg + 1);
-		if (b == 0) {
-			put_cmd640_reg(cmd640_key, b_reg + 1, r2);
-		} else {
-			r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
-			r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
-			put_cmd640_reg(cmd640_key, b_reg+1, r52);
-		}
-	}
-
-	b = get_cmd640_reg(cmd640_key, 0x52);
-	if (b == 0) {
-		put_cmd640_reg(cmd640_key, 0x52, r2);
-	} else {
-		r52 = (b&0xf) < (r2&0xf) ? (r2&0xf) : (b&0xf);
-		r52 |= (b&0xf0) < (r2&0xf0) ? (r2&0xf0) : (b&0xf0);
-		put_cmd640_reg(cmd640_key, 0x52, r52);
-	}
-}
-
-static int bus_speed = 33; /* MHz */
-
-struct pio_timing {
-	int	mc_time;	/* Minimal cycle time (ns) */
-	int	av_time;	/* Address valid to DIOR-/DIOW- setup (ns) */
-	int	ds_time;	/* DIOR data setup	(ns) */
-} pio_timings[6] = {
-	{ 70,	165,	600 },	/* PIO Mode 0 */
-	{ 50,	125,	383 },	/* PIO Mode 1 */
-	{ 30,	100,	240 },	/* PIO Mode 2 */
-	{ 30,	80,	180 },	/* PIO Mode 3 */
-	{ 25,	70,	125 },	/* PIO Mode 4 */
-	{ 20,	50,	100 }	/* PIO Mode ? */
-};
-
-struct drive_pio_info {
-	const char	*name;
-	int		pio;
-} drive_pios[] = {
-	{ "Maxtor 7131 AT", 1 },
-	{ "Maxtor 7171 AT", 1 },
-	{ "Maxtor 7213 AT", 1 },
-	{ "Maxtor 7245 AT", 1 },
-	{ "SAMSUNG SHD-3122A", 1 },
-	{ "QUANTUM ELS127A", 0 },
-	{ "QUANTUM LPS240A", 0 },
-	{ "QUANTUM LPS270A", 3 },
-	{ "QUANTUM LPS540A", 3 },
-	{ NULL,	0 }
-};
-
-static int known_drive_pio(char* name) {
-	struct drive_pio_info* pi;
-
-	for (pi = drive_pios; pi->name != NULL; pi++) {
-		if (strcmp(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)
-{
-	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;
-
-	a = (av_time + clock_time - 1)/clock_time;
-	if (a < 2)
-		a = 2;
-	b = (ds_time + clock_time - 1)/clock_time - a;
-	if (b < 2)
-		b = 2;
-	if (b > 0x11) {
-		a += b - 0x11;
-		b = 0x11;
-	}
-	if (a > 0xf)
-		a = 0;
-	if (cmd640_chip_version > 1)
-		b -= 1;
-	if (b > 0xf)
-		b = 0;
-	*r2 = (a << 4) | b;
-}
-
-static void set_pio_mode(int if_num, int drv_num, int mode_num) {
-	int p_base;
-	int i;
-
-	p_base = if_num ? 0x170 : 0x1f0;
-	outb(3, p_base + 1);
-	outb(mode_num | 8, p_base + 2);
-	outb((drv_num | 0xa) << 4, p_base + 6);
-	outb(0xef, p_base + 7);
-	for (i = 0; (i < 100) && (inb (p_base + 7) & 0x80); i++)
-		delay_10ms();
-}
-
-void cmd640_tune_drive(ide_drive_t* drive) {
-	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;
-
-	/*
-	 * Determine if drive is under cmd640 control
-	 */
-	interface_number = HWIF(drive) - ide_hwifs;
-	if (!is_cmd640[interface_number])
-		return;
-
-	drive_number = drive - HWIF(drive)->drives;
-	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)) {
-				if (id->eide_pio_modes & 4) max_pio = 5;
-				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;
-		}
-	}
-	cmd640_timings_to_regvals(mc_time, av_time, ds_time, clock_time,
-				&r1, &r2);
-	set_pio_mode(interface_number, drive_number, max_pio);
-	cmd640_set_timing(interface_number, drive_number, r1, r2);
-	printk ("Mode and Timing set to PIO%d (0x%x 0x%x)\n", max_pio, r1, r2);
-}

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