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