Merge branch 'master' of ssh://master.kernel.org/home/ftp/pub/scm/linux/kernel/git...
[linux-2.6] / drivers / ide / ide-io-std.c
1
2 #include <linux/kernel.h>
3 #include <linux/ide.h>
4
5 /*
6  *      Conventional PIO operations for ATA devices
7  */
8
9 static u8 ide_inb(unsigned long port)
10 {
11         return (u8) inb(port);
12 }
13
14 static void ide_outb(u8 val, unsigned long port)
15 {
16         outb(val, port);
17 }
18
19 /*
20  *      MMIO operations, typically used for SATA controllers
21  */
22
23 static u8 ide_mm_inb(unsigned long port)
24 {
25         return (u8) readb((void __iomem *) port);
26 }
27
28 static void ide_mm_outb(u8 value, unsigned long port)
29 {
30         writeb(value, (void __iomem *) port);
31 }
32
33 void ide_exec_command(ide_hwif_t *hwif, u8 cmd)
34 {
35         if (hwif->host_flags & IDE_HFLAG_MMIO)
36                 writeb(cmd, (void __iomem *)hwif->io_ports.command_addr);
37         else
38                 outb(cmd, hwif->io_ports.command_addr);
39 }
40 EXPORT_SYMBOL_GPL(ide_exec_command);
41
42 u8 ide_read_status(ide_hwif_t *hwif)
43 {
44         if (hwif->host_flags & IDE_HFLAG_MMIO)
45                 return readb((void __iomem *)hwif->io_ports.status_addr);
46         else
47                 return inb(hwif->io_ports.status_addr);
48 }
49 EXPORT_SYMBOL_GPL(ide_read_status);
50
51 u8 ide_read_altstatus(ide_hwif_t *hwif)
52 {
53         if (hwif->host_flags & IDE_HFLAG_MMIO)
54                 return readb((void __iomem *)hwif->io_ports.ctl_addr);
55         else
56                 return inb(hwif->io_ports.ctl_addr);
57 }
58 EXPORT_SYMBOL_GPL(ide_read_altstatus);
59
60 void ide_set_irq(ide_hwif_t *hwif, int on)
61 {
62         u8 ctl = ATA_DEVCTL_OBS;
63
64         if (on == 4) { /* hack for SRST */
65                 ctl |= 4;
66                 on &= ~4;
67         }
68
69         ctl |= on ? 0 : 2;
70
71         if (hwif->host_flags & IDE_HFLAG_MMIO)
72                 writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr);
73         else
74                 outb(ctl, hwif->io_ports.ctl_addr);
75 }
76 EXPORT_SYMBOL_GPL(ide_set_irq);
77
78 void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
79 {
80         ide_hwif_t *hwif = drive->hwif;
81         struct ide_io_ports *io_ports = &hwif->io_ports;
82         struct ide_taskfile *tf = &task->tf;
83         void (*tf_outb)(u8 addr, unsigned long port);
84         u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
85         u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
86
87         if (mmio)
88                 tf_outb = ide_mm_outb;
89         else
90                 tf_outb = ide_outb;
91
92         if (task->tf_flags & IDE_TFLAG_FLAGGED)
93                 HIHI = 0xFF;
94
95         if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
96                 u16 data = (tf->hob_data << 8) | tf->data;
97
98                 if (mmio)
99                         writew(data, (void __iomem *)io_ports->data_addr);
100                 else
101                         outw(data, io_ports->data_addr);
102         }
103
104         if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
105                 tf_outb(tf->hob_feature, io_ports->feature_addr);
106         if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
107                 tf_outb(tf->hob_nsect, io_ports->nsect_addr);
108         if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
109                 tf_outb(tf->hob_lbal, io_ports->lbal_addr);
110         if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
111                 tf_outb(tf->hob_lbam, io_ports->lbam_addr);
112         if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
113                 tf_outb(tf->hob_lbah, io_ports->lbah_addr);
114
115         if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
116                 tf_outb(tf->feature, io_ports->feature_addr);
117         if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
118                 tf_outb(tf->nsect, io_ports->nsect_addr);
119         if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
120                 tf_outb(tf->lbal, io_ports->lbal_addr);
121         if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
122                 tf_outb(tf->lbam, io_ports->lbam_addr);
123         if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
124                 tf_outb(tf->lbah, io_ports->lbah_addr);
125
126         if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
127                 tf_outb((tf->device & HIHI) | drive->select,
128                          io_ports->device_addr);
129 }
130 EXPORT_SYMBOL_GPL(ide_tf_load);
131
132 void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
133 {
134         ide_hwif_t *hwif = drive->hwif;
135         struct ide_io_ports *io_ports = &hwif->io_ports;
136         struct ide_taskfile *tf = &task->tf;
137         void (*tf_outb)(u8 addr, unsigned long port);
138         u8 (*tf_inb)(unsigned long port);
139         u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
140
141         if (mmio) {
142                 tf_outb = ide_mm_outb;
143                 tf_inb  = ide_mm_inb;
144         } else {
145                 tf_outb = ide_outb;
146                 tf_inb  = ide_inb;
147         }
148
149         if (task->tf_flags & IDE_TFLAG_IN_DATA) {
150                 u16 data;
151
152                 if (mmio)
153                         data = readw((void __iomem *)io_ports->data_addr);
154                 else
155                         data = inw(io_ports->data_addr);
156
157                 tf->data = data & 0xff;
158                 tf->hob_data = (data >> 8) & 0xff;
159         }
160
161         /* be sure we're looking at the low order bits */
162         tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr);
163
164         if (task->tf_flags & IDE_TFLAG_IN_FEATURE)
165                 tf->feature = tf_inb(io_ports->feature_addr);
166         if (task->tf_flags & IDE_TFLAG_IN_NSECT)
167                 tf->nsect  = tf_inb(io_ports->nsect_addr);
168         if (task->tf_flags & IDE_TFLAG_IN_LBAL)
169                 tf->lbal   = tf_inb(io_ports->lbal_addr);
170         if (task->tf_flags & IDE_TFLAG_IN_LBAM)
171                 tf->lbam   = tf_inb(io_ports->lbam_addr);
172         if (task->tf_flags & IDE_TFLAG_IN_LBAH)
173                 tf->lbah   = tf_inb(io_ports->lbah_addr);
174         if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
175                 tf->device = tf_inb(io_ports->device_addr);
176
177         if (task->tf_flags & IDE_TFLAG_LBA48) {
178                 tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr);
179
180                 if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
181                         tf->hob_feature = tf_inb(io_ports->feature_addr);
182                 if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
183                         tf->hob_nsect   = tf_inb(io_ports->nsect_addr);
184                 if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
185                         tf->hob_lbal    = tf_inb(io_ports->lbal_addr);
186                 if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
187                         tf->hob_lbam    = tf_inb(io_ports->lbam_addr);
188                 if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
189                         tf->hob_lbah    = tf_inb(io_ports->lbah_addr);
190         }
191 }
192 EXPORT_SYMBOL_GPL(ide_tf_read);
193
194 /*
195  * Some localbus EIDE interfaces require a special access sequence
196  * when using 32-bit I/O instructions to transfer data.  We call this
197  * the "vlb_sync" sequence, which consists of three successive reads
198  * of the sector count register location, with interrupts disabled
199  * to ensure that the reads all happen together.
200  */
201 static void ata_vlb_sync(unsigned long port)
202 {
203         (void)inb(port);
204         (void)inb(port);
205         (void)inb(port);
206 }
207
208 /*
209  * This is used for most PIO data transfers *from* the IDE interface
210  *
211  * These routines will round up any request for an odd number of bytes,
212  * so if an odd len is specified, be sure that there's at least one
213  * extra byte allocated for the buffer.
214  */
215 void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf,
216                     unsigned int len)
217 {
218         ide_hwif_t *hwif = drive->hwif;
219         struct ide_io_ports *io_ports = &hwif->io_ports;
220         unsigned long data_addr = io_ports->data_addr;
221         u8 io_32bit = drive->io_32bit;
222         u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
223
224         len++;
225
226         if (io_32bit) {
227                 unsigned long uninitialized_var(flags);
228
229                 if ((io_32bit & 2) && !mmio) {
230                         local_irq_save(flags);
231                         ata_vlb_sync(io_ports->nsect_addr);
232                 }
233
234                 if (mmio)
235                         __ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
236                 else
237                         insl(data_addr, buf, len / 4);
238
239                 if ((io_32bit & 2) && !mmio)
240                         local_irq_restore(flags);
241
242                 if ((len & 3) >= 2) {
243                         if (mmio)
244                                 __ide_mm_insw((void __iomem *)data_addr,
245                                                 (u8 *)buf + (len & ~3), 1);
246                         else
247                                 insw(data_addr, (u8 *)buf + (len & ~3), 1);
248                 }
249         } else {
250                 if (mmio)
251                         __ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
252                 else
253                         insw(data_addr, buf, len / 2);
254         }
255 }
256 EXPORT_SYMBOL_GPL(ide_input_data);
257
258 /*
259  * This is used for most PIO data transfers *to* the IDE interface
260  */
261 void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf,
262                      unsigned int len)
263 {
264         ide_hwif_t *hwif = drive->hwif;
265         struct ide_io_ports *io_ports = &hwif->io_ports;
266         unsigned long data_addr = io_ports->data_addr;
267         u8 io_32bit = drive->io_32bit;
268         u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
269
270         len++;
271
272         if (io_32bit) {
273                 unsigned long uninitialized_var(flags);
274
275                 if ((io_32bit & 2) && !mmio) {
276                         local_irq_save(flags);
277                         ata_vlb_sync(io_ports->nsect_addr);
278                 }
279
280                 if (mmio)
281                         __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
282                 else
283                         outsl(data_addr, buf, len / 4);
284
285                 if ((io_32bit & 2) && !mmio)
286                         local_irq_restore(flags);
287
288                 if ((len & 3) >= 2) {
289                         if (mmio)
290                                 __ide_mm_outsw((void __iomem *)data_addr,
291                                                  (u8 *)buf + (len & ~3), 1);
292                         else
293                                 outsw(data_addr, (u8 *)buf + (len & ~3), 1);
294                 }
295         } else {
296                 if (mmio)
297                         __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
298                 else
299                         outsw(data_addr, buf, len / 2);
300         }
301 }
302 EXPORT_SYMBOL_GPL(ide_output_data);
303
304 const struct ide_tp_ops default_tp_ops = {
305         .exec_command           = ide_exec_command,
306         .read_status            = ide_read_status,
307         .read_altstatus         = ide_read_altstatus,
308
309         .set_irq                = ide_set_irq,
310
311         .tf_load                = ide_tf_load,
312         .tf_read                = ide_tf_read,
313
314         .input_data             = ide_input_data,
315         .output_data            = ide_output_data,
316 };