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