ide-dma-sff.c 8.87 KB
Newer Older
1
2
#include <linux/types.h>
#include <linux/kernel.h>
3
#include <linux/export.h>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <linux/ide.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/io.h>

/**
 *	config_drive_for_dma	-	attempt to activate IDE DMA
 *	@drive: the drive to place in DMA mode
 *
 *	If the drive supports at least mode 2 DMA or UDMA of any kind
 *	then attempt to place it into DMA mode. Drives that are known to
 *	support DMA but predate the DMA properties or that are known
 *	to have DMA handling bugs are also set up appropriately based
 *	on the good/bad drive lists.
 */

int config_drive_for_dma(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	u16 *id = drive->id;

	if (drive->media != ide_disk) {
		if (hwif->host_flags & IDE_HFLAG_NO_ATAPI_DMA)
			return 0;
	}

	/*
	 * Enable DMA on any drive that has
	 * UltraDMA (mode 0/1/2/3/4/5/6) enabled
	 */
	if ((id[ATA_ID_FIELD_VALID] & 4) &&
	    ((id[ATA_ID_UDMA_MODES] >> 8) & 0x7f))
		return 1;

	/*
	 * Enable DMA on any drive that has mode2 DMA
	 * (multi or single) enabled
	 */
42
43
44
	if ((id[ATA_ID_MWDMA_MODES] & 0x404) == 0x404 ||
	    (id[ATA_ID_SWDMA_MODES] & 0x404) == 0x404)
		return 1;
45
46
47
48
49
50
51
52

	/* Consult the list of known "good" drives */
	if (ide_dma_good_drive(drive))
		return 1;

	return 0;
}

53
54
55
56
57
58
59
60
61
62
63
u8 ide_dma_sff_read_status(ide_hwif_t *hwif)
{
	unsigned long addr = hwif->dma_base + ATA_DMA_STATUS;

	if (hwif->host_flags & IDE_HFLAG_MMIO)
		return readb((void __iomem *)addr);
	else
		return inb(addr);
}
EXPORT_SYMBOL_GPL(ide_dma_sff_read_status);

64
65
66
67
68
69
70
71
72
73
static void ide_dma_sff_write_status(ide_hwif_t *hwif, u8 val)
{
	unsigned long addr = hwif->dma_base + ATA_DMA_STATUS;

	if (hwif->host_flags & IDE_HFLAG_MMIO)
		writeb(val, (void __iomem *)addr);
	else
		outb(val, addr);
}

74
75
76
77
78
79
80
81
82
83
84
85
/**
 *	ide_dma_host_set	-	Enable/disable DMA on a host
 *	@drive: drive to control
 *
 *	Enable/disable DMA on an IDE controller following generic
 *	bus-mastering IDE controller behaviour.
 */

void ide_dma_host_set(ide_drive_t *drive, int on)
{
	ide_hwif_t *hwif = drive->hwif;
	u8 unit = drive->dn & 1;
86
	u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
87
88
89
90
91
92

	if (on)
		dma_stat |= (1 << (5 + unit));
	else
		dma_stat &= ~(1 << (5 + unit));

93
	ide_dma_sff_write_status(hwif, dma_stat);
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
}
EXPORT_SYMBOL_GPL(ide_dma_host_set);

/**
 *	ide_build_dmatable	-	build IDE DMA table
 *
 *	ide_build_dmatable() prepares a dma request. We map the command
 *	to get the pci bus addresses of the buffers and then build up
 *	the PRD table that the IDE layer wants to be fed.
 *
 *	Most chipsets correctly interpret a length of 0x0000 as 64KB,
 *	but at least one (e.g. CS5530) misinterprets it as zero (!).
 *	So we break the 64KB entry into two 32KB entries instead.
 *
 *	Returns the number of built PRD entries if all went okay,
 *	returns 0 otherwise.
 *
 *	May also be invoked from trm290.c
 */

114
int ide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
115
116
117
118
119
120
{
	ide_hwif_t *hwif = drive->hwif;
	__le32 *table = (__le32 *)hwif->dmatable_cpu;
	unsigned int count = 0;
	int i;
	struct scatterlist *sg;
121
	u8 is_trm290 = !!(hwif->host_flags & IDE_HFLAG_TRM290);
122

123
	for_each_sg(hwif->sg_table, sg, cmd->sg_nents, i) {
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
		u32 cur_addr, cur_len, xcount, bcount;

		cur_addr = sg_dma_address(sg);
		cur_len = sg_dma_len(sg);

		/*
		 * Fill in the dma table, without crossing any 64kB boundaries.
		 * Most hardware requires 16-bit alignment of all blocks,
		 * but the trm290 requires 32-bit alignment.
		 */

		while (cur_len) {
			if (count++ >= PRD_ENTRIES)
				goto use_pio_instead;

			bcount = 0x10000 - (cur_addr & 0xffff);
			if (bcount > cur_len)
				bcount = cur_len;
			*table++ = cpu_to_le32(cur_addr);
			xcount = bcount & 0xffff;
			if (is_trm290)
				xcount = ((xcount >> 2) - 1) << 16;
146
			else if (xcount == 0x0000) {
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
				if (count++ >= PRD_ENTRIES)
					goto use_pio_instead;
				*table++ = cpu_to_le32(0x8000);
				*table++ = cpu_to_le32(cur_addr + 0x8000);
				xcount = 0x8000;
			}
			*table++ = cpu_to_le32(xcount);
			cur_addr += bcount;
			cur_len -= bcount;
		}
	}

	if (count) {
		if (!is_trm290)
			*--table |= cpu_to_le32(0x80000000);
		return count;
	}

use_pio_instead:
	printk(KERN_ERR "%s: %s\n", drive->name,
		count ? "DMA table too small" : "empty DMA table?");

	return 0; /* revert to PIO for this request */
}
EXPORT_SYMBOL_GPL(ide_build_dmatable);

/**
 *	ide_dma_setup	-	begin a DMA phase
 *	@drive: target device
176
 *	@cmd: command
177
178
179
180
181
182
183
184
185
186
 *
 *	Build an IDE DMA PRD (IDE speak for scatter gather table)
 *	and then set up the DMA transfer registers for a device
 *	that follows generic IDE PCI DMA behaviour. Controllers can
 *	override this function if they need to
 *
 *	Returns 0 on success. If a PIO fallback is required then 1
 *	is returned.
 */

187
int ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
188
189
190
{
	ide_hwif_t *hwif = drive->hwif;
	u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
191
	u8 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR;
192
193
194
	u8 dma_stat;

	/* fall back to pio! */
195
196
	if (ide_build_dmatable(drive, cmd) == 0) {
		ide_map_sg(drive, cmd);
197
198
199
200
		return 1;
	}

	/* PRD table */
201
	if (mmio)
202
203
204
205
206
207
208
		writel(hwif->dmatable_dma,
		       (void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
	else
		outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);

	/* specify r/w */
	if (mmio)
209
		writeb(rw, (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
210
	else
211
		outb(rw, hwif->dma_base + ATA_DMA_CMD);
212
213

	/* read DMA status for INTR & ERROR flags */
214
	dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
215
216

	/* clear INTR & ERROR flags */
217
	ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR);
218
219
220
221
222
223

	return 0;
}
EXPORT_SYMBOL_GPL(ide_dma_setup);

/**
224
 *	ide_dma_sff_timer_expiry	-	handle a DMA timeout
225
226
227
228
229
230
231
232
233
234
235
236
 *	@drive: Drive that timed out
 *
 *	An IDE DMA transfer timed out. In the event of an error we ask
 *	the driver to resolve the problem, if a DMA transfer is still
 *	in progress we continue to wait (arguably we need to add a
 *	secondary 'I don't care what the drive thinks' timeout here)
 *	Finally if we have an interrupt we let it complete the I/O.
 *	But only one time - we clear expiry and if it's still not
 *	completed after WAIT_CMD, we error and retry in PIO.
 *	This can occur if an interrupt is lost or due to hang or bugs.
 */

237
int ide_dma_sff_timer_expiry(ide_drive_t *drive)
238
239
{
	ide_hwif_t *hwif = drive->hwif;
240
	u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
241
242
243
244
245
246
247

	printk(KERN_WARNING "%s: %s: DMA status (0x%02x)\n",
		drive->name, __func__, dma_stat);

	if ((dma_stat & 0x18) == 0x18)	/* BUSY Stupid Early Timer !! */
		return WAIT_CMD;

248
	hwif->expiry = NULL;	/* one free ride for now */
249

250
	if (dma_stat & ATA_DMA_ERR)	/* ERROR */
251
252
		return -1;

253
	if (dma_stat & ATA_DMA_ACTIVE)	/* DMAing */
254
255
		return WAIT_CMD;

256
	if (dma_stat & ATA_DMA_INTR)	/* Got an Interrupt */
257
258
259
260
		return WAIT_CMD;

	return 0;	/* Status is unknown -- reset the bus */
}
261
EXPORT_SYMBOL_GPL(ide_dma_sff_timer_expiry);
262
263
264
265
266
267
268
269
270
271
272
273
274

void ide_dma_start(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	u8 dma_cmd;

	/* Note that this is done *after* the cmd has
	 * been issued to the drive, as per the BM-IDE spec.
	 * The Promise Ultra33 doesn't work correctly when
	 * we do this part before issuing the drive cmd.
	 */
	if (hwif->host_flags & IDE_HFLAG_MMIO) {
		dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
275
		writeb(dma_cmd | ATA_DMA_START,
276
277
278
		       (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
	} else {
		dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
279
		outb(dma_cmd | ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
280
281
282
283
284
285
286
287
	}
}
EXPORT_SYMBOL_GPL(ide_dma_start);

/* returns 1 on error, 0 otherwise */
int ide_dma_end(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
288
	u8 dma_stat = 0, dma_cmd = 0;
289

290
	/* stop DMA */
291
	if (hwif->host_flags & IDE_HFLAG_MMIO) {
292
		dma_cmd = readb((void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
293
		writeb(dma_cmd & ~ATA_DMA_START,
294
295
296
		       (void __iomem *)(hwif->dma_base + ATA_DMA_CMD));
	} else {
		dma_cmd = inb(hwif->dma_base + ATA_DMA_CMD);
297
		outb(dma_cmd & ~ATA_DMA_START, hwif->dma_base + ATA_DMA_CMD);
298
299
300
	}

	/* get DMA status */
301
	dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
302

303
304
	/* clear INTR & ERROR bits */
	ide_dma_sff_write_status(hwif, dma_stat | ATA_DMA_ERR | ATA_DMA_INTR);
305

306
#define CHECK_DMA_MASK (ATA_DMA_ACTIVE | ATA_DMA_ERR | ATA_DMA_INTR)
307
308

	/* verify good DMA status */
309
	if ((dma_stat & CHECK_DMA_MASK) != ATA_DMA_INTR)
310
311
		return 0x10 | dma_stat;
	return 0;
312
313
314
315
316
317
318
}
EXPORT_SYMBOL_GPL(ide_dma_end);

/* returns 1 if dma irq issued, 0 otherwise */
int ide_dma_test_irq(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
319
	u8 dma_stat = hwif->dma_ops->dma_sff_read_status(hwif);
320

321
	return (dma_stat & ATA_DMA_INTR) ? 1 : 0;
322
323
324
325
326
327
328
329
330
331
}
EXPORT_SYMBOL_GPL(ide_dma_test_irq);

const struct ide_dma_ops sff_dma_ops = {
	.dma_host_set		= ide_dma_host_set,
	.dma_setup		= ide_dma_setup,
	.dma_start		= ide_dma_start,
	.dma_end		= ide_dma_end,
	.dma_test_irq		= ide_dma_test_irq,
	.dma_lost_irq		= ide_dma_lost_irq,
332
	.dma_timer_expiry	= ide_dma_sff_timer_expiry,
333
	.dma_sff_read_status	= ide_dma_sff_read_status,
334
335
};
EXPORT_SYMBOL_GPL(sff_dma_ops);