dtc2278.c 3.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 *  Copyright (C) 1996  Linus Torvalds & author (see below)
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/ide.h>
#include <linux/init.h>

#include <asm/io.h>

18 19
#define DRV_NAME "dtc2278"

L
Linus Torvalds 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
/*
 * Changing this #undef to #define may solve start up problems in some systems.
 */
#undef ALWAYS_SET_DTC2278_PIO_MODE

/*
 * From: andy@cercle.cts.com (Dyan Wile)
 *
 * Below is a patch for DTC-2278 - alike software-programmable controllers
 * The code enables the secondary IDE controller and the PIO4 (3?) timings on
 * the primary (EIDE). You may probably have to enable the 32-bit support to
 * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
 * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
 * filesystem  corrupted with -u1, but under heavy disk load only :-)
 *
 * This card is now forced to use the "serialize" feature,
 * and irq-unmasking is disallowed.  If io_32bit is enabled,
 * it must be done for BOTH drives on each interface.
 *
 * This code was written for the DTC2278E, but might work with any of these:
 *
 * DTC2278S has only a single IDE interface.
 * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
 * DTC2278E also has serial ports and a printer port
 * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
 *
 * There may be a fourth controller type. The S and D versions use the
 * Winbond chip, and I think the E version does also.
 *
 */

static void sub22 (char b, char c)
{
	int i;

	for(i = 0; i < 3; ++i) {
		inb(0x3f6);
		outb_p(b,0xb0);
		inb(0x3f6);
		outb_p(c,0xb4);
		inb(0x3f6);
		if(inb(0xb4) == c) {
			outb_p(7,0xb0);
			inb(0x3f6);
			return;	/* success */
		}
	}
}

69 70
static DEFINE_SPINLOCK(dtc2278_lock);

71
static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
L
Linus Torvalds 已提交
72 73 74 75
{
	unsigned long flags;

	if (pio >= 3) {
76
		spin_lock_irqsave(&dtc2278_lock, flags);
L
Linus Torvalds 已提交
77 78 79 80 81
		/*
		 * This enables PIO mode4 (3?) on the first interface
		 */
		sub22(1,0xc3);
		sub22(0,0xa0);
82
		spin_unlock_irqrestore(&dtc2278_lock, flags);
L
Linus Torvalds 已提交
83 84
	} else {
		/* we don't know how to set it back again.. */
A
Alan Cox 已提交
85 86
		/* Actually we do - there is a data sheet available for the
		   Winbond but does anyone actually care */
L
Linus Torvalds 已提交
87 88 89
	}
}

90 91 92 93
static const struct ide_port_ops dtc2278_port_ops = {
	.set_pio_mode		= dtc2278_set_pio_mode,
};

94
static const struct ide_port_info dtc2278_port_info __initdata = {
95
	.name			= DRV_NAME,
96
	.chipset		= ide_dtc2278,
97
	.port_ops		= &dtc2278_port_ops,
98
	.host_flags		= IDE_HFLAG_SERIALIZE |
99
				  IDE_HFLAG_NO_UNMASK_IRQS |
100
				  IDE_HFLAG_IO_32BIT |
101 102
				  /* disallow ->io_32bit changes */
				  IDE_HFLAG_NO_IO_32BIT |
103
				  IDE_HFLAG_NO_DMA,
104 105 106
	.pio_mask		= ATA_PIO4,
};

107
static int __init dtc2278_probe(void)
L
Linus Torvalds 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
{
	unsigned long flags;

	local_irq_save(flags);
	/*
	 * This enables the second interface
	 */
	outb_p(4,0xb0);
	inb(0x3f6);
	outb_p(0x20,0xb4);
	inb(0x3f6);
#ifdef ALWAYS_SET_DTC2278_PIO_MODE
	/*
	 * This enables PIO mode4 (3?) on the first interface
	 * and may solve start-up problems for some people.
	 */
	sub22(1,0xc3);
	sub22(0,0xa0);
#endif
	local_irq_restore(flags);

129
	return ide_legacy_device_add(&dtc2278_port_info, 0);
L
Linus Torvalds 已提交
130 131
}

132
static int probe_dtc2278;
133 134 135 136

module_param_named(probe, probe_dtc2278, bool, 0);
MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");

137
static int __init dtc2278_init(void)
L
Linus Torvalds 已提交
138
{
139 140 141 142
	if (probe_dtc2278 == 0)
		return -ENODEV;

	if (dtc2278_probe()) {
L
Linus Torvalds 已提交
143 144 145 146 147 148 149 150 151 152 153
		printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
		return -EBUSY;
	}
	return 0;
}

module_init(dtc2278_init);

MODULE_AUTHOR("See Local File");
MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
MODULE_LICENSE("GPL");