diff options
Diffstat (limited to 'drivers/ide/dtc2278.c')
-rw-r--r-- | drivers/ide/dtc2278.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c new file mode 100644 index 000000000000..689b2e493413 --- /dev/null +++ b/drivers/ide/dtc2278.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996 Linus Torvalds & author (see below) | ||
3 | */ | ||
4 | |||
5 | #include <linux/module.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/timer.h> | ||
10 | #include <linux/mm.h> | ||
11 | #include <linux/ioport.h> | ||
12 | #include <linux/blkdev.h> | ||
13 | #include <linux/ide.h> | ||
14 | #include <linux/init.h> | ||
15 | |||
16 | #include <asm/io.h> | ||
17 | |||
18 | #define DRV_NAME "dtc2278" | ||
19 | |||
20 | /* | ||
21 | * Changing this #undef to #define may solve start up problems in some systems. | ||
22 | */ | ||
23 | #undef ALWAYS_SET_DTC2278_PIO_MODE | ||
24 | |||
25 | /* | ||
26 | * From: andy@cercle.cts.com (Dyan Wile) | ||
27 | * | ||
28 | * Below is a patch for DTC-2278 - alike software-programmable controllers | ||
29 | * The code enables the secondary IDE controller and the PIO4 (3?) timings on | ||
30 | * the primary (EIDE). You may probably have to enable the 32-bit support to | ||
31 | * get the full speed. You better get the disk interrupts disabled ( hdparm -u0 | ||
32 | * /dev/hd.. ) for the drives connected to the EIDE interface. (I get my | ||
33 | * filesystem corrupted with -u1, but under heavy disk load only :-) | ||
34 | * | ||
35 | * This card is now forced to use the "serialize" feature, | ||
36 | * and irq-unmasking is disallowed. If io_32bit is enabled, | ||
37 | * it must be done for BOTH drives on each interface. | ||
38 | * | ||
39 | * This code was written for the DTC2278E, but might work with any of these: | ||
40 | * | ||
41 | * DTC2278S has only a single IDE interface. | ||
42 | * DTC2278D has two IDE interfaces and is otherwise identical to the S version. | ||
43 | * DTC2278E also has serial ports and a printer port | ||
44 | * DTC2278EB: has onboard BIOS, and "works like a charm" -- Kent Bradford <kent@theory.caltech.edu> | ||
45 | * | ||
46 | * There may be a fourth controller type. The S and D versions use the | ||
47 | * Winbond chip, and I think the E version does also. | ||
48 | * | ||
49 | */ | ||
50 | |||
51 | static void sub22 (char b, char c) | ||
52 | { | ||
53 | int i; | ||
54 | |||
55 | for(i = 0; i < 3; ++i) { | ||
56 | inb(0x3f6); | ||
57 | outb_p(b,0xb0); | ||
58 | inb(0x3f6); | ||
59 | outb_p(c,0xb4); | ||
60 | inb(0x3f6); | ||
61 | if(inb(0xb4) == c) { | ||
62 | outb_p(7,0xb0); | ||
63 | inb(0x3f6); | ||
64 | return; /* success */ | ||
65 | } | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static DEFINE_SPINLOCK(dtc2278_lock); | ||
70 | |||
71 | static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio) | ||
72 | { | ||
73 | unsigned long flags; | ||
74 | |||
75 | if (pio >= 3) { | ||
76 | spin_lock_irqsave(&dtc2278_lock, flags); | ||
77 | /* | ||
78 | * This enables PIO mode4 (3?) on the first interface | ||
79 | */ | ||
80 | sub22(1,0xc3); | ||
81 | sub22(0,0xa0); | ||
82 | spin_unlock_irqrestore(&dtc2278_lock, flags); | ||
83 | } else { | ||
84 | /* we don't know how to set it back again.. */ | ||
85 | /* Actually we do - there is a data sheet available for the | ||
86 | Winbond but does anyone actually care */ | ||
87 | } | ||
88 | } | ||
89 | |||
90 | static const struct ide_port_ops dtc2278_port_ops = { | ||
91 | .set_pio_mode = dtc2278_set_pio_mode, | ||
92 | }; | ||
93 | |||
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 | /* disallow ->io_32bit changes */ | ||
102 | IDE_HFLAG_NO_IO_32BIT | | ||
103 | IDE_HFLAG_NO_DMA, | ||
104 | .pio_mask = ATA_PIO4, | ||
105 | }; | ||
106 | |||
107 | static int __init dtc2278_probe(void) | ||
108 | { | ||
109 | unsigned long flags; | ||
110 | |||
111 | local_irq_save(flags); | ||
112 | /* | ||
113 | * This enables the second interface | ||
114 | */ | ||
115 | outb_p(4,0xb0); | ||
116 | inb(0x3f6); | ||
117 | outb_p(0x20,0xb4); | ||
118 | inb(0x3f6); | ||
119 | #ifdef ALWAYS_SET_DTC2278_PIO_MODE | ||
120 | /* | ||
121 | * This enables PIO mode4 (3?) on the first interface | ||
122 | * and may solve start-up problems for some people. | ||
123 | */ | ||
124 | sub22(1,0xc3); | ||
125 | sub22(0,0xa0); | ||
126 | #endif | ||
127 | local_irq_restore(flags); | ||
128 | |||
129 | return ide_legacy_device_add(&dtc2278_port_info, 0); | ||
130 | } | ||
131 | |||
132 | static int probe_dtc2278; | ||
133 | |||
134 | module_param_named(probe, probe_dtc2278, bool, 0); | ||
135 | MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); | ||
136 | |||
137 | static int __init dtc2278_init(void) | ||
138 | { | ||
139 | if (probe_dtc2278 == 0) | ||
140 | return -ENODEV; | ||
141 | |||
142 | if (dtc2278_probe()) { | ||
143 | printk(KERN_ERR "dtc2278: ide interfaces already in use!\n"); | ||
144 | return -EBUSY; | ||
145 | } | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | module_init(dtc2278_init); | ||
150 | |||
151 | MODULE_AUTHOR("See Local File"); | ||
152 | MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets"); | ||
153 | MODULE_LICENSE("GPL"); | ||