1
2
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
22
23#undef ALWAYS_SET_DTC2278_PIO_MODE
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
51static 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;
65 }
66 }
67}
68
69static DEFINE_SPINLOCK(dtc2278_lock);
70
71static void dtc2278_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
72{
73 unsigned long flags;
74
75 if (drive->pio_mode >= XFER_PIO_3) {
76 spin_lock_irqsave(&dtc2278_lock, flags);
77
78
79
80 sub22(1,0xc3);
81 sub22(0,0xa0);
82 spin_unlock_irqrestore(&dtc2278_lock, flags);
83 } else {
84
85
86
87 }
88}
89
90static const struct ide_port_ops dtc2278_port_ops = {
91 .set_pio_mode = dtc2278_set_pio_mode,
92};
93
94static const struct ide_port_info dtc2278_port_info __initconst = {
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 IDE_HFLAG_NO_IO_32BIT |
103 IDE_HFLAG_NO_DMA |
104 IDE_HFLAG_DTC2278,
105 .pio_mask = ATA_PIO4,
106};
107
108static int __init dtc2278_probe(void)
109{
110 unsigned long flags;
111
112 local_irq_save(flags);
113
114
115
116 outb_p(4,0xb0);
117 inb(0x3f6);
118 outb_p(0x20,0xb4);
119 inb(0x3f6);
120#ifdef ALWAYS_SET_DTC2278_PIO_MODE
121
122
123
124
125 sub22(1,0xc3);
126 sub22(0,0xa0);
127#endif
128 local_irq_restore(flags);
129
130 return ide_legacy_device_add(&dtc2278_port_info, 0);
131}
132
133static bool probe_dtc2278;
134
135module_param_named(probe, probe_dtc2278, bool, 0);
136MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
137
138static int __init dtc2278_init(void)
139{
140 if (probe_dtc2278 == 0)
141 return -ENODEV;
142
143 if (dtc2278_probe()) {
144 printk(KERN_ERR "dtc2278: ide interfaces already in use!\n");
145 return -EBUSY;
146 }
147 return 0;
148}
149
150module_init(dtc2278_init);
151
152MODULE_AUTHOR("See Local File");
153MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
154MODULE_LICENSE("GPL");
155