| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
|  | 2 | *  linux/drivers/ide/legacy/dtc2278.c		Version 0.02	Feb 10, 1996 | 
|  | 3 | * | 
|  | 4 | *  Copyright (C) 1996  Linus Torvalds & author (see below) | 
|  | 5 | */ | 
|  | 6 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 7 | #include <linux/module.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 8 | #include <linux/types.h> | 
|  | 9 | #include <linux/kernel.h> | 
|  | 10 | #include <linux/delay.h> | 
|  | 11 | #include <linux/timer.h> | 
|  | 12 | #include <linux/mm.h> | 
|  | 13 | #include <linux/ioport.h> | 
|  | 14 | #include <linux/blkdev.h> | 
|  | 15 | #include <linux/hdreg.h> | 
|  | 16 | #include <linux/ide.h> | 
|  | 17 | #include <linux/init.h> | 
|  | 18 |  | 
|  | 19 | #include <asm/io.h> | 
|  | 20 |  | 
|  | 21 | /* | 
|  | 22 | * Changing this #undef to #define may solve start up problems in some systems. | 
|  | 23 | */ | 
|  | 24 | #undef ALWAYS_SET_DTC2278_PIO_MODE | 
|  | 25 |  | 
|  | 26 | /* | 
|  | 27 | * From: andy@cercle.cts.com (Dyan Wile) | 
|  | 28 | * | 
|  | 29 | * Below is a patch for DTC-2278 - alike software-programmable controllers | 
|  | 30 | * The code enables the secondary IDE controller and the PIO4 (3?) timings on | 
|  | 31 | * the primary (EIDE). You may probably have to enable the 32-bit support to | 
|  | 32 | * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 | 
|  | 33 | * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my | 
|  | 34 | * filesystem  corrupted with -u1, but under heavy disk load only :-) | 
|  | 35 | * | 
|  | 36 | * This card is now forced to use the "serialize" feature, | 
|  | 37 | * and irq-unmasking is disallowed.  If io_32bit is enabled, | 
|  | 38 | * it must be done for BOTH drives on each interface. | 
|  | 39 | * | 
|  | 40 | * This code was written for the DTC2278E, but might work with any of these: | 
|  | 41 | * | 
|  | 42 | * DTC2278S has only a single IDE interface. | 
|  | 43 | * DTC2278D has two IDE interfaces and is otherwise identical to the S version. | 
|  | 44 | * DTC2278E also has serial ports and a printer port | 
|  | 45 | * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu> | 
|  | 46 | * | 
|  | 47 | * There may be a fourth controller type. The S and D versions use the | 
|  | 48 | * Winbond chip, and I think the E version does also. | 
|  | 49 | * | 
|  | 50 | */ | 
|  | 51 |  | 
|  | 52 | static void sub22 (char b, char c) | 
|  | 53 | { | 
|  | 54 | int i; | 
|  | 55 |  | 
|  | 56 | for(i = 0; i < 3; ++i) { | 
|  | 57 | inb(0x3f6); | 
|  | 58 | outb_p(b,0xb0); | 
|  | 59 | inb(0x3f6); | 
|  | 60 | outb_p(c,0xb4); | 
|  | 61 | inb(0x3f6); | 
|  | 62 | if(inb(0xb4) == c) { | 
|  | 63 | outb_p(7,0xb0); | 
|  | 64 | inb(0x3f6); | 
|  | 65 | return;	/* success */ | 
|  | 66 | } | 
|  | 67 | } | 
|  | 68 | } | 
|  | 69 |  | 
| Bartlomiej Zolnierkiewicz | a34a875 | 2007-10-20 00:32:35 +0200 | [diff] [blame] | 70 | static DEFINE_SPINLOCK(dtc2278_lock); | 
|  | 71 |  | 
| Bartlomiej Zolnierkiewicz | 26bcb87 | 2007-10-11 23:54:00 +0200 | [diff] [blame] | 72 | static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 73 | { | 
|  | 74 | unsigned long flags; | 
|  | 75 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 76 | if (pio >= 3) { | 
| Bartlomiej Zolnierkiewicz | a34a875 | 2007-10-20 00:32:35 +0200 | [diff] [blame] | 77 | spin_lock_irqsave(&dtc2278_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 | /* | 
|  | 79 | * This enables PIO mode4 (3?) on the first interface | 
|  | 80 | */ | 
|  | 81 | sub22(1,0xc3); | 
|  | 82 | sub22(0,0xa0); | 
| Bartlomiej Zolnierkiewicz | a34a875 | 2007-10-20 00:32:35 +0200 | [diff] [blame] | 83 | spin_unlock_irqrestore(&dtc2278_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 84 | } else { | 
|  | 85 | /* we don't know how to set it back again.. */ | 
| Alan Cox | d3bad45 | 2007-10-20 00:32:37 +0200 | [diff] [blame] | 86 | /* Actually we do - there is a data sheet available for the | 
|  | 87 | Winbond but does anyone actually care */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 88 | } | 
|  | 89 |  | 
|  | 90 | /* | 
|  | 91 | * 32bit I/O has to be enabled for *both* drives at the same time. | 
|  | 92 | */ | 
|  | 93 | drive->io_32bit = 1; | 
|  | 94 | HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1; | 
|  | 95 | } | 
|  | 96 |  | 
| Bartlomiej Zolnierkiewicz | 8491388 | 2007-03-03 17:48:55 +0100 | [diff] [blame] | 97 | static int __init dtc2278_probe(void) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | { | 
|  | 99 | unsigned long flags; | 
|  | 100 | ide_hwif_t *hwif, *mate; | 
| Bartlomiej Zolnierkiewicz | 8447d9d | 2007-10-20 00:32:31 +0200 | [diff] [blame] | 101 | static u8 idx[4] = { 0, 1, 0xff, 0xff }; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 102 |  | 
|  | 103 | hwif = &ide_hwifs[0]; | 
|  | 104 | mate = &ide_hwifs[1]; | 
|  | 105 |  | 
|  | 106 | if (hwif->chipset != ide_unknown || mate->chipset != ide_unknown) | 
|  | 107 | return 1; | 
|  | 108 |  | 
|  | 109 | local_irq_save(flags); | 
|  | 110 | /* | 
|  | 111 | * This enables the second interface | 
|  | 112 | */ | 
|  | 113 | outb_p(4,0xb0); | 
|  | 114 | inb(0x3f6); | 
|  | 115 | outb_p(0x20,0xb4); | 
|  | 116 | inb(0x3f6); | 
|  | 117 | #ifdef ALWAYS_SET_DTC2278_PIO_MODE | 
|  | 118 | /* | 
|  | 119 | * This enables PIO mode4 (3?) on the first interface | 
|  | 120 | * and may solve start-up problems for some people. | 
|  | 121 | */ | 
|  | 122 | sub22(1,0xc3); | 
|  | 123 | sub22(0,0xa0); | 
|  | 124 | #endif | 
|  | 125 | local_irq_restore(flags); | 
|  | 126 |  | 
|  | 127 | hwif->serialized = 1; | 
|  | 128 | hwif->chipset = ide_dtc2278; | 
| Bartlomiej Zolnierkiewicz | 4099d14 | 2007-07-20 01:11:59 +0200 | [diff] [blame] | 129 | hwif->pio_mask = ATA_PIO4; | 
| Bartlomiej Zolnierkiewicz | 26bcb87 | 2007-10-11 23:54:00 +0200 | [diff] [blame] | 130 | hwif->set_pio_mode = &dtc2278_set_pio_mode; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 131 | hwif->drives[0].no_unmask = 1; | 
|  | 132 | hwif->drives[1].no_unmask = 1; | 
|  | 133 | hwif->mate = mate; | 
|  | 134 |  | 
|  | 135 | mate->serialized = 1; | 
|  | 136 | mate->chipset = ide_dtc2278; | 
| Bartlomiej Zolnierkiewicz | 691da76 | 2007-10-20 00:32:33 +0200 | [diff] [blame] | 137 | mate->pio_mask = ATA_PIO4; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 138 | mate->drives[0].no_unmask = 1; | 
|  | 139 | mate->drives[1].no_unmask = 1; | 
|  | 140 | mate->mate = hwif; | 
|  | 141 | mate->channel = 1; | 
|  | 142 |  | 
| Bartlomiej Zolnierkiewicz | 8447d9d | 2007-10-20 00:32:31 +0200 | [diff] [blame] | 143 | ide_device_add(idx); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 144 |  | 
|  | 145 | return 0; | 
|  | 146 | } | 
|  | 147 |  | 
| Bartlomiej Zolnierkiewicz | 8491388 | 2007-03-03 17:48:55 +0100 | [diff] [blame] | 148 | int probe_dtc2278 = 0; | 
|  | 149 |  | 
|  | 150 | module_param_named(probe, probe_dtc2278, bool, 0); | 
|  | 151 | MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); | 
|  | 152 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 153 | /* Can be called directly from ide.c. */ | 
|  | 154 | int __init dtc2278_init(void) | 
|  | 155 | { | 
| Bartlomiej Zolnierkiewicz | 8491388 | 2007-03-03 17:48:55 +0100 | [diff] [blame] | 156 | if (probe_dtc2278 == 0) | 
|  | 157 | return -ENODEV; | 
|  | 158 |  | 
|  | 159 | if (dtc2278_probe()) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 160 | printk(KERN_ERR "dtc2278: ide interfaces already in use!\n"); | 
|  | 161 | return -EBUSY; | 
|  | 162 | } | 
|  | 163 | return 0; | 
|  | 164 | } | 
|  | 165 |  | 
|  | 166 | #ifdef MODULE | 
|  | 167 | module_init(dtc2278_init); | 
|  | 168 | #endif | 
|  | 169 |  | 
|  | 170 | MODULE_AUTHOR("See Local File"); | 
|  | 171 | MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); | 
|  | 172 | MODULE_LICENSE("GPL"); |