Blame view

drivers/ide/ide-iops.c 13.5 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   *  Copyright (C) 2000-2002	Andre Hedrick <andre@linux-ide.org>
ccd32e221   Alan Cox   ide: Switch to a ...
3
   *  Copyright (C) 2003		Red Hat
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
   *
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
  #include <linux/timer.h>
  #include <linux/mm.h>
  #include <linux/interrupt.h>
  #include <linux/major.h>
  #include <linux/errno.h>
  #include <linux/genhd.h>
  #include <linux/blkpg.h>
  #include <linux/slab.h>
  #include <linux/pci.h>
  #include <linux/delay.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
  #include <linux/ide.h>
  #include <linux/bitops.h>
1e86240f3   Michal Schmidt   [PATCH] IDE: Touc...
22
  #include <linux/nmi.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
  
  #include <asm/byteorder.h>
  #include <asm/irq.h>
  #include <asm/uaccess.h>
  #include <asm/io.h>
ed4af48fd   Bartlomiej Zolnierkiewicz   ide: move IRQ unm...
28
  void SELECT_MASK(ide_drive_t *drive, int mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
29
  {
ac95beedf   Bartlomiej Zolnierkiewicz   ide: add struct i...
30
31
32
33
  	const struct ide_port_ops *port_ops = drive->hwif->port_ops;
  
  	if (port_ops && port_ops->maskproc)
  		port_ops->maskproc(drive, mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  }
92eb43800   Bartlomiej Zolnierkiewicz   ide: use ->tf_rea...
35
36
  u8 ide_read_error(ide_drive_t *drive)
  {
3153c26b5   Sergei Shtylyov   ide: refactor tf_...
37
  	struct ide_taskfile tf;
92eb43800   Bartlomiej Zolnierkiewicz   ide: use ->tf_rea...
38

3153c26b5   Sergei Shtylyov   ide: refactor tf_...
39
  	drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_ERROR);
92eb43800   Bartlomiej Zolnierkiewicz   ide: use ->tf_rea...
40

3153c26b5   Sergei Shtylyov   ide: refactor tf_...
41
  	return tf.error;
92eb43800   Bartlomiej Zolnierkiewicz   ide: use ->tf_rea...
42
43
  }
  EXPORT_SYMBOL_GPL(ide_read_error);
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
44
  void ide_fix_driveid(u16 *id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
45
46
47
48
  {
  #ifndef __LITTLE_ENDIAN
  # ifdef __BIG_ENDIAN
  	int i;
5b90e9909   Bartlomiej Zolnierkiewicz   ide: cleanup ide_...
49

48fb2688a   Bartlomiej Zolnierkiewicz   ide: remove drive...
50
  	for (i = 0; i < 256; i++)
5b90e9909   Bartlomiej Zolnierkiewicz   ide: cleanup ide_...
51
  		id[i] = __le16_to_cpu(id[i]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
53
54
55
56
  # else
  #  error "Please fix <asm/byteorder.h>"
  # endif
  #endif
  }
01745112d   Bartlomiej Zolnierkiewicz   ide: move ide_fix...
57
58
59
60
  /*
   * ide_fixstring() cleans up and (optionally) byte-swaps a text string,
   * removing leading/trailing blanks and compressing internal blanks.
   * It is primarily used to tidy up the model name/number fields as
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
61
   * returned by the ATA_CMD_ID_ATA[PI] commands.
01745112d   Bartlomiej Zolnierkiewicz   ide: move ide_fix...
62
   */
122f06f8b   Bartlomiej Zolnierkiewicz   ide: checkpatch.p...
63
  void ide_fixstring(u8 *s, const int bytecount, const int byteswap)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  {
1a7809e34   Linus Torvalds   ide: re-code ide_...
65
  	u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
  
  	if (byteswap) {
  		/* convert from big-endian to host byte order */
1a7809e34   Linus Torvalds   ide: re-code ide_...
69
70
  		for (p = s ; p != end ; p += 2)
  			be16_to_cpus((u16 *) p);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  	}
1a7809e34   Linus Torvalds   ide: re-code ide_...
72

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  	/* strip leading blanks */
1a7809e34   Linus Torvalds   ide: re-code ide_...
74
  	p = s;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
78
79
80
81
82
83
84
85
  	while (s != end && *s == ' ')
  		++s;
  	/* compress internal blanks and strip trailing blanks */
  	while (s != end && *s) {
  		if (*s++ != ' ' || (s != end && *s && *s != ' '))
  			*p++ = *(s-1);
  	}
  	/* wipe out trailing garbage */
  	while (p != end)
  		*p++ = '\0';
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
  EXPORT_SYMBOL(ide_fixstring);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
87
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
   * This routine busy-waits for the drive status to be not "busy".
   * It then checks the status for all of the "good" bits and none
   * of the "bad" bits, and if all is okay it returns 0.  All other
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
91
   * cases return error -- caller may then invoke ide_error().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
97
   *
   * This routine should get fixed to not hog the cpu during extra long waits..
   * That could be done by busy-waiting for the first jiffy or two, and then
   * setting a timer to wake up at half second intervals thereafter,
   * until timeout is achieved, before timing out.
   */
fa56d4cb4   Bartlomiej Zolnierkiewicz   ide: allow ide_de...
98
99
  int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad,
  		    unsigned long timeout, u8 *rstat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
  {
b73c7ee25   Bartlomiej Zolnierkiewicz   ide: add ->read_s...
101
  	ide_hwif_t *hwif = drive->hwif;
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
102
  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
  	unsigned long flags;
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
104
105
  	int i;
  	u8 stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
106
107
  
  	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
108
  	stat = tp_ops->read_status(hwif);
c47137a99   Bartlomiej Zolnierkiewicz   ide: add ide_read...
109

3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
110
  	if (stat & ATA_BUSY) {
9b896033a   Bartlomiej Zolnierkiewicz   ide: fix accident...
111
  		local_save_flags(flags);
54cc1428c   Bartlomiej Zolnierkiewicz   ide: remove local...
112
  		local_irq_enable_in_hardirq();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  		timeout += jiffies;
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
114
  		while ((stat = tp_ops->read_status(hwif)) & ATA_BUSY) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115
116
117
118
119
120
  			if (time_after(jiffies, timeout)) {
  				/*
  				 * One last read after the timeout in case
  				 * heavy interrupt load made us not make any
  				 * progress during the timeout..
  				 */
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
121
  				stat = tp_ops->read_status(hwif);
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
122
  				if ((stat & ATA_BUSY) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123
124
125
  					break;
  
  				local_irq_restore(flags);
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
126
127
  				*rstat = stat;
  				return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
129
130
131
132
133
134
135
136
137
138
139
140
  			}
  		}
  		local_irq_restore(flags);
  	}
  	/*
  	 * Allow status to settle, then read it again.
  	 * A few rare drives vastly violate the 400ns spec here,
  	 * so we'll wait up to 10usec for a "good" status
  	 * rather than expensively fail things immediately.
  	 * This fix courtesy of Matthew Faupel & Niccolo Rigacci.
  	 */
  	for (i = 0; i < 10; i++) {
  		udelay(1);
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
141
  		stat = tp_ops->read_status(hwif);
c47137a99   Bartlomiej Zolnierkiewicz   ide: add ide_read...
142
143
  
  		if (OK_STAT(stat, good, bad)) {
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
144
  			*rstat = stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  			return 0;
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
146
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  	}
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
148
149
150
151
152
153
154
155
156
  	*rstat = stat;
  	return -EFAULT;
  }
  
  /*
   * In case of error returns error value after doing "*startstop = ide_error()".
   * The caller should return the updated value of "startstop" in this case,
   * "startstop" is unchanged when the function returns 0.
   */
122f06f8b   Bartlomiej Zolnierkiewicz   ide: checkpatch.p...
157
158
  int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good,
  		  u8 bad, unsigned long timeout)
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
  {
  	int err;
  	u8 stat;
  
  	/* bail early if we've exceeded max_failures */
  	if (drive->max_failures && (drive->failures > drive->max_failures)) {
  		*startstop = ide_stopped;
  		return 1;
  	}
  
  	err = __ide_wait_stat(drive, good, bad, timeout, &stat);
  
  	if (err) {
  		char *s = (err == -EBUSY) ? "status timeout" : "status error";
  		*startstop = ide_error(drive, s, stat);
  	}
  
  	return err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
  EXPORT_SYMBOL(ide_wait_stat);
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
179
180
181
  /**
   *	ide_in_drive_list	-	look for drive in black/white list
   *	@id: drive identifier
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
182
   *	@table: list to inspect
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
183
184
185
186
   *
   *	Look for a drive in the blacklist and the whitelist tables
   *	Returns 1 if the drive is found in the table.
   */
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
187
  int ide_in_drive_list(u16 *id, const struct drive_list_entry *table)
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
188
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
189
190
191
192
  	for ( ; table->id_model; table++)
  		if ((!strcmp(table->id_model, (char *)&id[ATA_ID_PROD])) &&
  		    (!table->id_firmware ||
  		     strstr((char *)&id[ATA_ID_FW_REV], table->id_firmware)))
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
193
194
195
  			return 1;
  	return 0;
  }
b0244a004   Bartlomiej Zolnierkiewicz   ide-disk: workaro...
196
  EXPORT_SYMBOL_GPL(ide_in_drive_list);
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
197
198
  /*
   * Early UDMA66 devices don't set bit14 to 1, only bit13 is valid.
8588a2b73   Bartlomiej Zolnierkiewicz   ide: add SH-S202J...
199
   * Some optical devices with the buggy firmwares have the same problem.
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
200
201
202
   */
  static const struct drive_list_entry ivb_list[] = {
  	{ "QUANTUM FIREBALLlct10 05"	, "A03.0900"	},
ba9413bd2   Bartlomiej Zolnierkiewicz   ide: add QUANTUM ...
203
  	{ "QUANTUM FIREBALLlct20 30"	, "APL.0900"	},
8588a2b73   Bartlomiej Zolnierkiewicz   ide: add SH-S202J...
204
  	{ "TSSTcorp CDDVDW SH-S202J"	, "SB00"	},
e97564f36   Peter Missel   ide: More TSST dr...
205
206
207
  	{ "TSSTcorp CDDVDW SH-S202J"	, "SB01"	},
  	{ "TSSTcorp CDDVDW SH-S202N"	, "SB00"	},
  	{ "TSSTcorp CDDVDW SH-S202N"	, "SB01"	},
3ced5c49b   Alexander Smal   ide: add TSSTcorp...
208
209
  	{ "TSSTcorp CDDVDW SH-S202H"	, "SB00"	},
  	{ "TSSTcorp CDDVDW SH-S202H"	, "SB01"	},
c7b997b37   Bartlomiej Zolnierkiewicz   ide: add SAMSUNG ...
210
  	{ "SAMSUNG SP0822N"		, "WA100-10"	},
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
211
212
  	{ NULL				, NULL		}
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
216
  /*
   *  All hosts that use the 80c ribbon must use!
   *  The name is derived from upper byte of word 93 and the 80c ribbon.
   */
122f06f8b   Bartlomiej Zolnierkiewicz   ide: checkpatch.p...
217
  u8 eighty_ninty_three(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  {
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
219
  	ide_hwif_t *hwif = drive->hwif;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
220
  	u16 *id = drive->id;
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
221
  	int ivb = ide_in_drive_list(id, ivb_list);
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
222

76937fa76   Bartlomiej Zolnierkiewicz   ide: add SATA cab...
223
  	if (hwif->cbl == ATA_CBL_SATA || hwif->cbl == ATA_CBL_PATA40_SHORT)
49521f97c   Bartlomiej Zolnierkiewicz   ide: add short ca...
224
  		return 1;
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
225
226
227
228
  	if (ivb)
  		printk(KERN_DEBUG "%s: skipping word 93 validity check
  ",
  				  drive->name);
367d7e78d   Bartlomiej Zolnierkiewicz   ide: ide_dev_is_s...
229
  	if (ata_id_is_sata(id) && !ivb)
b98f8803c   George Kibardin   ide: fix cable de...
230
  		return 1;
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
231
  	if (hwif->cbl != ATA_CBL_PATA80 && !ivb)
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
232
  		goto no_80w;
1a1276e7b   Alan Cox   [PATCH] Old IDE, ...
233

f68d9320c   Bartlomiej Zolnierkiewicz   ide: revert "ide:...
234
235
  	/*
  	 * FIXME:
f367bed00   Bartlomiej Zolnierkiewicz   Revert "ide: chan...
236
  	 * - change master/slave IDENTIFY order
a5b7e70d7   Bartlomiej Zolnierkiewicz   ide: add cable de...
237
  	 * - force bit13 (80c cable present) check also for !ivb devices
f68d9320c   Bartlomiej Zolnierkiewicz   ide: revert "ide:...
238
239
  	 *   (unless the slave device is pre-ATA3)
  	 */
8369d5fa6   Bartlomiej Zolnierkiewicz   ide: fix 40-wire ...
240
  	if (id[ATA_ID_HW_CONFIG] & 0x4000)
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
241
  		return 1;
8369d5fa6   Bartlomiej Zolnierkiewicz   ide: fix 40-wire ...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  	if (ivb) {
  		const char *model = (char *)&id[ATA_ID_PROD];
  
  		if (strstr(model, "TSSTcorp CDDVDW SH-S202")) {
  			/*
  			 * These ATAPI devices always report 80c cable
  			 * so we have to depend on the host in this case.
  			 */
  			if (hwif->cbl == ATA_CBL_PATA80)
  				return 1;
  		} else {
  			/* Depend on the device side cable detection. */
  			if (id[ATA_ID_HW_CONFIG] & 0x2000)
  				return 1;
  		}
  	}
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
258
  no_80w:
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
259
  	if (drive->dev_flags & IDE_DFLAG_UDMA33_WARNED)
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
260
261
262
263
264
  		return 0;
  
  	printk(KERN_WARNING "%s: %s side 80-wire cable detection failed, "
  			    "limiting max speed to UDMA33
  ",
49521f97c   Bartlomiej Zolnierkiewicz   ide: add short ca...
265
266
  			    drive->name,
  			    hwif->cbl == ATA_CBL_PATA80 ? "drive" : "host");
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
267

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
268
  	drive->dev_flags |= IDE_DFLAG_UDMA33_WARNED;
7f8f48af0   Bartlomiej Zolnierkiewicz   ide: cable detect...
269
270
  
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
  }
8bc1e5aa0   Bartlomiej Zolnierkiewicz   ide: respect quir...
272
273
274
275
276
277
278
279
280
  static const char *nien_quirk_list[] = {
  	"QUANTUM FIREBALLlct08 08",
  	"QUANTUM FIREBALLP KA6.4",
  	"QUANTUM FIREBALLP KA9.1",
  	"QUANTUM FIREBALLP KX13.6",
  	"QUANTUM FIREBALLP KX20.5",
  	"QUANTUM FIREBALLP KX27.3",
  	"QUANTUM FIREBALLP LM20.4",
  	"QUANTUM FIREBALLP LM20.5",
a2d10568f   Wu Zhangjin   ide: fixup for fu...
281
  	"FUJITSU MHZ2160BH G2",
8bc1e5aa0   Bartlomiej Zolnierkiewicz   ide: respect quir...
282
283
284
285
286
287
288
289
290
  	NULL
  };
  
  void ide_check_nien_quirk_list(ide_drive_t *drive)
  {
  	const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
  
  	for (list = nien_quirk_list; *list != NULL; list++)
  		if (strstr(m, *list) != NULL) {
734affdca   Bartlomiej Zolnierkiewicz   ide: add IDE_DFLA...
291
  			drive->dev_flags |= IDE_DFLAG_NIEN_QUIRK;
8bc1e5aa0   Bartlomiej Zolnierkiewicz   ide: respect quir...
292
293
  			return;
  		}
8bc1e5aa0   Bartlomiej Zolnierkiewicz   ide: respect quir...
294
  }
8a4551340   Bartlomiej Zolnierkiewicz   ide: remove dead ...
295
  int ide_driveid_update(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  {
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
297
  	u16 *id;
2ebe1d9ef   Bartlomiej Zolnierkiewicz   ide: use try_to_i...
298
  	int rc;
2f40c9b0b   Bartlomiej Zolnierkiewicz   ide: fix kmalloc(...
299
300
301
302
  
  	id = kmalloc(SECTOR_SIZE, GFP_ATOMIC);
  	if (id == NULL)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
  	SELECT_MASK(drive, 1);
fa56d4cb4   Bartlomiej Zolnierkiewicz   ide: allow ide_de...
305
  	rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id, 1);
2ebe1d9ef   Bartlomiej Zolnierkiewicz   ide: use try_to_i...
306
  	SELECT_MASK(drive, 0);
2f40c9b0b   Bartlomiej Zolnierkiewicz   ide: fix kmalloc(...
307

2ebe1d9ef   Bartlomiej Zolnierkiewicz   ide: use try_to_i...
308
  	if (rc)
2f40c9b0b   Bartlomiej Zolnierkiewicz   ide: fix kmalloc(...
309
  		goto out_err;
f323b80dc   Bartlomiej Zolnierkiewicz   ide: sanitize SEL...
310

4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
311
312
313
  	drive->id[ATA_ID_UDMA_MODES]  = id[ATA_ID_UDMA_MODES];
  	drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES];
  	drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES];
74638c848   Sergei Shtylyov   ide: add support ...
314
  	drive->id[ATA_ID_CFA_MODES]   = id[ATA_ID_CFA_MODES];
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
315
316
317
  	/* anything more ? */
  
  	kfree(id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
  	return 1;
2f40c9b0b   Bartlomiej Zolnierkiewicz   ide: fix kmalloc(...
319
  out_err:
2f40c9b0b   Bartlomiej Zolnierkiewicz   ide: fix kmalloc(...
320
321
322
323
324
  	if (rc == 2)
  		printk(KERN_ERR "%s: %s: bad status
  ", drive->name, __func__);
  	kfree(id);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  }
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
326
  int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
  {
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
328
  	ide_hwif_t *hwif = drive->hwif;
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
329
  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
c9ff9e7b6   Sergei Shtylyov   ide: refactor tf_...
330
  	struct ide_taskfile tf;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
331
  	u16 *id = drive->id, i;
89613e667   Sergei Shtylyov   ide: don't set PI...
332
  	int error = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
  	u8 stat;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
  #ifdef CONFIG_BLK_DEV_IDEDMA
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
335
336
  	if (hwif->dma_ops)	/* check if host supports DMA */
  		hwif->dma_ops->dma_host_set(drive, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
  #endif
89613e667   Sergei Shtylyov   ide: don't set PI...
338
  	/* Skip setting PIO flow-control modes on pre-EIDE drives */
48fb2688a   Bartlomiej Zolnierkiewicz   ide: remove drive...
339
  	if ((speed & 0xf8) == XFER_PIO_0 && ata_id_has_iordy(drive->id) == 0)
89613e667   Sergei Shtylyov   ide: don't set PI...
340
  		goto skip;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
345
346
  	/*
  	 * Don't use ide_wait_cmd here - it will
  	 * attempt to set_geometry and recalibrate,
  	 * but for some reason these don't work at
  	 * this point (lost interrupt).
  	 */
ee1b1cc97   Bartlomiej Zolnierkiewicz   ide: fix comments...
347

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
  	udelay(1);
fdd88f0af   Sergei Shtylyov   ide: inline SELEC...
349
  	tp_ops->dev_select(drive);
e5403bff8   Sergei Shtylyov   ide: mask interru...
350
  	SELECT_MASK(drive, 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351
  	udelay(1);
ecf3a31d2   Sergei Shtylyov   ide: turn set_irq...
352
  	tp_ops->write_devctl(hwif, ATA_NIEN | ATA_DEVCTL_OBS);
59be2c80f   Bartlomiej Zolnierkiewicz   ide: use ->tf_loa...
353

c9ff9e7b6   Sergei Shtylyov   ide: refactor tf_...
354
355
356
  	memset(&tf, 0, sizeof(tf));
  	tf.feature = SETFEATURES_XFER;
  	tf.nsect   = speed;
59be2c80f   Bartlomiej Zolnierkiewicz   ide: use ->tf_loa...
357

c9ff9e7b6   Sergei Shtylyov   ide: refactor tf_...
358
  	tp_ops->tf_load(drive, &tf, IDE_VALID_FEATURE | IDE_VALID_NSECT);
59be2c80f   Bartlomiej Zolnierkiewicz   ide: use ->tf_loa...
359

aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
360
  	tp_ops->exec_command(hwif, ATA_CMD_SET_FEATURES);
59be2c80f   Bartlomiej Zolnierkiewicz   ide: use ->tf_loa...
361

734affdca   Bartlomiej Zolnierkiewicz   ide: add IDE_DFLA...
362
  	if (drive->dev_flags & IDE_DFLAG_NIEN_QUIRK)
ecf3a31d2   Sergei Shtylyov   ide: turn set_irq...
363
  		tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364

74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
365
  	error = __ide_wait_stat(drive, drive->ready_stat,
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
366
  				ATA_BUSY | ATA_DRQ | ATA_ERR,
74af21cf4   Bartlomiej Zolnierkiewicz   ide: add __ide_wa...
367
  				WAIT_CMD, &stat);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
  
  	SELECT_MASK(drive, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
  	if (error) {
  		(void) ide_dump_status(drive, "set_drive_speed_status", stat);
  		return error;
  	}
c4199930b   Sergei Shtylyov   ide-iops: only cl...
374
375
376
377
  	if (speed >= XFER_SW_DMA_0) {
  		id[ATA_ID_UDMA_MODES]  &= ~0xFF00;
  		id[ATA_ID_MWDMA_MODES] &= ~0x0700;
  		id[ATA_ID_SWDMA_MODES] &= ~0x0700;
74638c848   Sergei Shtylyov   ide: add support ...
378
379
380
381
  		if (ata_id_is_cfa(id))
  			id[ATA_ID_CFA_MODES] &= ~0x0E00;
  	} else	if (ata_id_is_cfa(id))
  		id[ATA_ID_CFA_MODES] &= ~0x01C0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382

89613e667   Sergei Shtylyov   ide: don't set PI...
383
   skip:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
384
  #ifdef CONFIG_BLK_DEV_IDEDMA
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
385
  	if (speed >= XFER_SW_DMA_0 && (drive->dev_flags & IDE_DFLAG_USING_DMA))
5e37bdc08   Bartlomiej Zolnierkiewicz   ide: add struct i...
386
387
  		hwif->dma_ops->dma_host_set(drive, 1);
  	else if (hwif->dma_ops)	/* check if host supports DMA */
4a546e046   Bartlomiej Zolnierkiewicz   ide: remove ->ide...
388
  		ide_dma_off_quietly(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
389
  #endif
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
390
391
392
  	if (speed >= XFER_UDMA_0) {
  		i = 1 << (speed - XFER_UDMA_0);
  		id[ATA_ID_UDMA_MODES] |= (i << 8 | i);
74638c848   Sergei Shtylyov   ide: add support ...
393
394
395
  	} else if (ata_id_is_cfa(id) && speed >= XFER_MW_DMA_3) {
  		i = speed - XFER_MW_DMA_2;
  		id[ATA_ID_CFA_MODES] |= i << 9;
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
396
397
398
399
400
401
  	} else if (speed >= XFER_MW_DMA_0) {
  		i = 1 << (speed - XFER_MW_DMA_0);
  		id[ATA_ID_MWDMA_MODES] |= (i << 8 | i);
  	} else if (speed >= XFER_SW_DMA_0) {
  		i = 1 << (speed - XFER_SW_DMA_0);
  		id[ATA_ID_SWDMA_MODES] |= (i << 8 | i);
74638c848   Sergei Shtylyov   ide: add support ...
402
403
404
  	} else if (ata_id_is_cfa(id) && speed >= XFER_PIO_5) {
  		i = speed - XFER_PIO_4;
  		id[ATA_ID_CFA_MODES] |= i << 6;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
  	}
4dde4492d   Bartlomiej Zolnierkiewicz   ide: make drive->...
406

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
409
410
411
  	if (!drive->init_speed)
  		drive->init_speed = speed;
  	drive->current_speed = speed;
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
412
413
414
415
416
417
418
419
420
  /*
   * This should get invoked any time we exit the driver to
   * wait for an interrupt response from a drive.  handler() points
   * at the appropriate code to handle the next interrupt, and a
   * timer is started to prevent us from waiting forever in case
   * something goes wrong (see the ide_timer_expiry() handler later on).
   *
   * See also ide_execute_command
   */
327fa1c29   Bartlomiej Zolnierkiewicz   ide: move error h...
421
  void __ide_set_handler(ide_drive_t *drive, ide_handler_t *handler,
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
422
  		       unsigned int timeout)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
  {
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
424
425
426
427
  	ide_hwif_t *hwif = drive->hwif;
  
  	BUG_ON(hwif->handler);
  	hwif->handler		= handler;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
428
429
430
  	hwif->timer.expires	= jiffies + timeout;
  	hwif->req_gen_timer	= hwif->req_gen;
  	add_timer(&hwif->timer);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  }
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
432
433
  void ide_set_handler(ide_drive_t *drive, ide_handler_t *handler,
  		     unsigned int timeout)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
434
  {
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
435
  	ide_hwif_t *hwif = drive->hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
436
  	unsigned long flags;
2a2ca6a96   Bartlomiej Zolnierkiewicz   ide: replace the ...
437

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
438
  	spin_lock_irqsave(&hwif->lock, flags);
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
439
  	__ide_set_handler(drive, handler, timeout);
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
440
  	spin_unlock_irqrestore(&hwif->lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
441
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  EXPORT_SYMBOL(ide_set_handler);
122f06f8b   Bartlomiej Zolnierkiewicz   ide: checkpatch.p...
443

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
  /**
   *	ide_execute_command	-	execute an IDE command
   *	@drive: IDE drive to issue the command against
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
447
   *	@cmd: command
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
   *	@handler: handler for next phase
   *	@timeout: timeout for command
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
451
   *
   *	Helper function to issue an IDE command. This handles the
122f06f8b   Bartlomiej Zolnierkiewicz   ide: checkpatch.p...
452
   *	atomicity requirements, command timing and ensures that the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
   *	handler and IRQ setup do not race. All IDE command kick off
   *	should go via this function or do equivalent locking.
   */
cd2a2d969   Bartlomiej Zolnierkiewicz   ide: remove task_...
456

35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
457
458
  void ide_execute_command(ide_drive_t *drive, struct ide_cmd *cmd,
  			 ide_handler_t *handler, unsigned timeout)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
  {
2a2ca6a96   Bartlomiej Zolnierkiewicz   ide: replace the ...
460
  	ide_hwif_t *hwif = drive->hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
461
  	unsigned long flags;
629f944bb   Bartlomiej Zolnierkiewicz   ide: use __ide_se...
462

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
463
  	spin_lock_irqsave(&hwif->lock, flags);
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
464
465
466
467
468
  	if ((cmd->protocol != ATAPI_PROT_DMA &&
  	     cmd->protocol != ATAPI_PROT_PIO) ||
  	    (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT))
  		__ide_set_handler(drive, handler, timeout);
  	hwif->tp_ops->exec_command(hwif, cmd->tf.command);
629f944bb   Bartlomiej Zolnierkiewicz   ide: use __ide_se...
469
470
471
472
473
474
  	/*
  	 * Drive takes 400nS to respond, we must avoid the IRQ being
  	 * serviced before that.
  	 *
  	 * FIXME: we could skip this delay with care on non shared devices
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
475
  	ndelay(400);
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
476
  	spin_unlock_irqrestore(&hwif->lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
480
  /*
   * ide_wait_not_busy() waits for the currently selected device on the hwif
9d501529b   Bartlomiej Zolnierkiewicz   ide: make probe_h...
481
   * to report a non-busy status, see comments in ide_probe_port().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
484
485
   */
  int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
  {
  	u8 stat = 0;
122f06f8b   Bartlomiej Zolnierkiewicz   ide: checkpatch.p...
486
  	while (timeout--) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
488
489
490
491
  		/*
  		 * Turn this into a schedule() sleep once I'm sure
  		 * about locking issues (2.5 work ?).
  		 */
  		mdelay(1);
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
492
  		stat = hwif->tp_ops->read_status(hwif);
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
493
  		if ((stat & ATA_BUSY) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
497
498
499
500
501
  			return 0;
  		/*
  		 * Assume a value of 0xff means nothing is connected to
  		 * the interface and it doesn't implement the pull-down
  		 * resistor on D7.
  		 */
  		if (stat == 0xff)
  			return -ENODEV;
6842f8c8d   Ingo Molnar   [PATCH] solve fal...
502
  		touch_softlockup_watchdog();
1e86240f3   Michal Schmidt   [PATCH] IDE: Touc...
503
  		touch_nmi_watchdog();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
  	}
  	return -EBUSY;
  }