[go: nahoru, domu]

11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1996  Linus Torvalds & author (see below)
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/blkdev.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ide.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18d92f1a2829dbe29c644569a3b64a021e4d90005dBartlomiej Zolnierkiewicz#define DRV_NAME "dtc2278"
19d92f1a2829dbe29c644569a3b64a021e4d90005dBartlomiej Zolnierkiewicz
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Changing this #undef to #define may solve start up problems in some systems.
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#undef ALWAYS_SET_DTC2278_PIO_MODE
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * From: andy@cercle.cts.com (Dyan Wile)
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Below is a patch for DTC-2278 - alike software-programmable controllers
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The code enables the secondary IDE controller and the PIO4 (3?) timings on
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the primary (EIDE). You may probably have to enable the 32-bit support to
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * get the full speed. You better get the disk interrupts disabled ( hdparm -u0
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * filesystem  corrupted with -u1, but under heavy disk load only :-)
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This card is now forced to use the "serialize" feature,
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and irq-unmasking is disallowed.  If io_32bit is enabled,
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it must be done for BOTH drives on each interface.
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code was written for the DTC2278E, but might work with any of these:
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DTC2278S has only a single IDE interface.
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DTC2278D has two IDE interfaces and is otherwise identical to the S version.
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DTC2278E also has serial ports and a printer port
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * There may be a fourth controller type. The S and D versions use the
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Winbond chip, and I think the E version does also.
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sub22 (char b, char c)
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for(i = 0; i < 3; ++i) {
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		inb(0x3f6);
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(b,0xb0);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		inb(0x3f6);
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb_p(c,0xb4);
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		inb(0x3f6);
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if(inb(0xb4) == c) {
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb_p(7,0xb0);
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			inb(0x3f6);
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return;	/* success */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
69a34a8751f312bd4674d48d63556efa8f0e3a1021Bartlomiej Zolnierkiewiczstatic DEFINE_SPINLOCK(dtc2278_lock);
70a34a8751f312bd4674d48d63556efa8f0e3a1021Bartlomiej Zolnierkiewicz
71e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewiczstatic void dtc2278_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
75e085b3cae85af47eb0a3eda3186bd898310fb322Bartlomiej Zolnierkiewicz	if (drive->pio_mode >= XFER_PIO_3) {
76a34a8751f312bd4674d48d63556efa8f0e3a1021Bartlomiej Zolnierkiewicz		spin_lock_irqsave(&dtc2278_lock, flags);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * This enables PIO mode4 (3?) on the first interface
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sub22(1,0xc3);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sub22(0,0xa0);
82a34a8751f312bd4674d48d63556efa8f0e3a1021Bartlomiej Zolnierkiewicz		spin_unlock_irqrestore(&dtc2278_lock, flags);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* we don't know how to set it back again.. */
85d3bad45f0232e273cce9237d66c98aafe12c0b0eAlan Cox		/* Actually we do - there is a data sheet available for the
86d3bad45f0232e273cce9237d66c98aafe12c0b0eAlan Cox		   Winbond but does anyone actually care */
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewiczstatic const struct ide_port_ops dtc2278_port_ops = {
91ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.set_pio_mode		= dtc2278_set_pio_mode,
92ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz};
93ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz
94e6b53703b9966a3636be2bd4b7b8e0bfeb1b3f8dAndi Kleenstatic const struct ide_port_info dtc2278_port_info __initconst = {
95d92f1a2829dbe29c644569a3b64a021e4d90005dBartlomiej Zolnierkiewicz	.name			= DRV_NAME,
96c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz	.chipset		= ide_dtc2278,
97ac95beedf8bc97b24f9540d4da9952f07221c023Bartlomiej Zolnierkiewicz	.port_ops		= &dtc2278_port_ops,
98c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz	.host_flags		= IDE_HFLAG_SERIALIZE |
99807b90d0be23b8d088d4369b02539dada70f03f4Bartlomiej Zolnierkiewicz				  IDE_HFLAG_NO_UNMASK_IRQS |
100c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz				  IDE_HFLAG_IO_32BIT |
101807b90d0be23b8d088d4369b02539dada70f03f4Bartlomiej Zolnierkiewicz				  /* disallow ->io_32bit changes */
102807b90d0be23b8d088d4369b02539dada70f03f4Bartlomiej Zolnierkiewicz				  IDE_HFLAG_NO_IO_32BIT |
1032787cb8ae5c68a6945eb82ccf96b5f2c4f238323Bartlomiej Zolnierkiewicz				  IDE_HFLAG_NO_DMA |
1042787cb8ae5c68a6945eb82ccf96b5f2c4f238323Bartlomiej Zolnierkiewicz				  IDE_HFLAG_DTC2278,
105c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz	.pio_mask		= ATA_PIO4,
106c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz};
107c413b9b94d9a8e7548cc4b2e04b7df0439ce76fdBartlomiej Zolnierkiewicz
108849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewiczstatic int __init dtc2278_probe(void)
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_save(flags);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This enables the second interface
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb_p(4,0xb0);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	inb(0x3f6);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb_p(0x20,0xb4);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	inb(0x3f6);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ALWAYS_SET_DTC2278_PIO_MODE
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This enables PIO mode4 (3?) on the first interface
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * and may solve start-up problems for some people.
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sub22(1,0xc3);
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sub22(0,0xa0);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_restore(flags);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1300bfeee7d4190938291a76536c7f6cd8f4e2dc30cBartlomiej Zolnierkiewicz	return ide_legacy_device_add(&dtc2278_port_info, 0);
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13390ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool probe_dtc2278;
134849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz
135849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewiczmodule_param_named(probe, probe_dtc2278, bool, 0);
136849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej ZolnierkiewiczMODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
137849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz
138ade2daf9c6e57845fe83a24e0a9fa1c03c6e91b1Bartlomiej Zolnierkiewiczstatic int __init dtc2278_init(void)
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
140849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz	if (probe_dtc2278 == 0)
141849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz		return -ENODEV;
142849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz
143849138827c962589ac50496fa7feeb2a2d51b467Bartlomiej Zolnierkiewicz	if (dtc2278_probe()) {
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EBUSY;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(dtc2278_init);
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("See Local File");
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
155