Blame view

drivers/ide/ide-io.c 23.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  /*
   *	IDE I/O functions
   *
   *	Basic PIO and command management functionality.
   *
   * This code was split off from ide.c. See ide.c for history and original
   * copyrights.
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
   * Free Software Foundation; either version 2, or (at your option) any
   * later version.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * For the avoidance of doubt the "preferred form" of this code is one which
   * is in an open non patent encumbered format. Where cryptographic key signing
   * forms part of the process of creating an executable the information
   * including keys needed to generate an equivalently functional executable
   * are deemed to be part of the source code.
   */
   
   
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  #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/init.h>
  #include <linux/pci.h>
  #include <linux/delay.h>
  #include <linux/ide.h>
  #include <linux/completion.h>
  #include <linux/reboot.h>
  #include <linux/cdrom.h>
  #include <linux/seq_file.h>
  #include <linux/device.h>
  #include <linux/kmod.h>
  #include <linux/scatterlist.h>
1977f0327   Jiri Slaby   remove asm/bitops...
50
  #include <linux/bitops.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
  
  #include <asm/byteorder.h>
  #include <asm/irq.h>
  #include <asm/uaccess.h>
  #include <asm/io.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56

37245aabf   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
57
  int ide_end_rq(ide_drive_t *drive, struct request *rq, int error,
1caf236da   Bartlomiej Zolnierkiewicz   ide: add ide_end_...
58
  	       unsigned int nr_bytes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
  	/*
  	 * decide whether to reenable DMA -- 3 is a random magic for now,
  	 * if we DMA timeout more than 3 times, just stay in PIO
  	 */
c39220483   Bartlomiej Zolnierkiewicz   ide: DMA_PIO_RETR...
64
65
66
  	if ((drive->dev_flags & IDE_DFLAG_DMA_PIO_RETRY) &&
  	    drive->retry_pio <= 3) {
  		drive->dev_flags &= ~IDE_DFLAG_DMA_PIO_RETRY;
4a546e046   Bartlomiej Zolnierkiewicz   ide: remove ->ide...
67
  		ide_dma_on(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  	}
1caf236da   Bartlomiej Zolnierkiewicz   ide: add ide_end_...
69
  	return blk_end_request(rq, error, nr_bytes);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  }
1caf236da   Bartlomiej Zolnierkiewicz   ide: add ide_end_...
71
  EXPORT_SYMBOL_GPL(ide_end_rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
73
  void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err)
e120237c0   Bartlomiej Zolnierkiewicz   ide: factor out c...
74
  {
35218d1ca   Sergei Shtylyov   ide: move data re...
75
  	const struct ide_tp_ops *tp_ops = drive->hwif->tp_ops;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
76
77
  	struct ide_taskfile *tf = &cmd->tf;
  	struct request *rq = cmd->rq;
e7fedc3ca   Bartlomiej Zolnierkiewicz   ide: use ide_comp...
78
  	u8 tf_cmd = tf->command;
e120237c0   Bartlomiej Zolnierkiewicz   ide: factor out c...
79
80
81
  
  	tf->error = err;
  	tf->status = stat;
35218d1ca   Sergei Shtylyov   ide: move data re...
82
83
84
85
  	if (cmd->ftf_flags & IDE_FTFLAG_IN_DATA) {
  		u8 data[2];
  
  		tp_ops->input_data(drive, cmd, data, 2);
745483f10   Sergei Shtylyov   ide: simplify 'st...
86
87
  		cmd->tf.data  = data[0];
  		cmd->hob.data = data[1];
35218d1ca   Sergei Shtylyov   ide: move data re...
88
  	}
3153c26b5   Sergei Shtylyov   ide: refactor tf_...
89
  	ide_tf_readback(drive, cmd);
e120237c0   Bartlomiej Zolnierkiewicz   ide: factor out c...
90

e7fedc3ca   Bartlomiej Zolnierkiewicz   ide: use ide_comp...
91
92
93
94
95
96
  	if ((cmd->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) &&
  	    tf_cmd == ATA_CMD_IDLEIMMEDIATE) {
  		if (tf->lbal != 0xc4) {
  			printk(KERN_ERR "%s: head unload failed!
  ",
  			       drive->name);
745483f10   Sergei Shtylyov   ide: simplify 'st...
97
  			ide_tf_dump(drive->name, cmd);
e7fedc3ca   Bartlomiej Zolnierkiewicz   ide: use ide_comp...
98
99
100
  		} else
  			drive->dev_flags |= IDE_DFLAG_PARKED;
  	}
f505d49ff   Bartlomiej Zolnierkiewicz   ide: fix barriers...
101
102
  	if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
  		struct ide_cmd *orig_cmd = rq->special;
a09485df9   Bartlomiej Zolnierkiewicz   ide: move request...
103

f505d49ff   Bartlomiej Zolnierkiewicz   ide: fix barriers...
104
105
106
107
108
  		if (cmd->tf_flags & IDE_TFLAG_DYN)
  			kfree(orig_cmd);
  		else
  			memcpy(orig_cmd, cmd, sizeof(*cmd));
  	}
e120237c0   Bartlomiej Zolnierkiewicz   ide: factor out c...
109
  }
f974b196f   Bartlomiej Zolnierkiewicz   ide: pass number ...
110
  int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  {
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
112
113
  	ide_hwif_t *hwif = drive->hwif;
  	struct request *rq = hwif->rq;
a9587fd8c   Bartlomiej Zolnierkiewicz   ide: remove BUG()...
114
  	int rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
115

130e88670   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
116
117
118
119
120
  	/*
  	 * if failfast is set on a request, override number of sectors
  	 * and complete the whole request right now
  	 */
  	if (blk_noretry_request(rq) && error <= 0)
5b93629b4   Tejun Heo   block: implement ...
121
  		nr_bytes = blk_rq_sectors(rq) << 9;
130e88670   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
122

ba7d479c3   Bartlomiej Zolnierkiewicz   ide: use ide_end_...
123
  	rc = ide_end_rq(drive, rq, error, nr_bytes);
a9587fd8c   Bartlomiej Zolnierkiewicz   ide: remove BUG()...
124
125
  	if (rc == 0)
  		hwif->rq = NULL;
1d0bf587d   Bartlomiej Zolnierkiewicz   ide: ide_hwgroup_...
126

a9587fd8c   Bartlomiej Zolnierkiewicz   ide: remove BUG()...
127
  	return rc;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  }
a09485df9   Bartlomiej Zolnierkiewicz   ide: move request...
129
  EXPORT_SYMBOL(ide_complete_rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130

327fa1c29   Bartlomiej Zolnierkiewicz   ide: move error h...
131
  void ide_kill_rq(ide_drive_t *drive, struct request *rq)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
132
  {
33659ebba   Christoph Hellwig   block: remove wra...
133
  	u8 drv_req = (rq->cmd_type == REQ_TYPE_SPECIAL) && rq->rq_disk;
3ee38302f   Bartlomiej Zolnierkiewicz   ide: remove ->end...
134
  	u8 media = drive->media;
c152cc1a9   Bartlomiej Zolnierkiewicz   ide: use ->end_re...
135
  	drive->failed_pc = NULL;
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
136
137
  	if ((media == ide_floppy || media == ide_tape) && drv_req) {
  		rq->errors = 0;
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
138
139
140
  	} else {
  		if (media == ide_tape)
  			rq->errors = IDE_DRV_ERROR_GENERAL;
33659ebba   Christoph Hellwig   block: remove wra...
141
  		else if (rq->cmd_type != REQ_TYPE_FS && rq->errors == 0)
89f78b326   Bartlomiej Zolnierkiewicz   ide: move rq->err...
142
  			rq->errors = -EIO;
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
143
  	}
5e955245d   Bartlomiej Zolnierkiewicz   ide: always kill ...
144
145
  
  	ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  }
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
147
  static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
  {
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
149
150
151
152
  	tf->nsect   = drive->sect;
  	tf->lbal    = drive->sect;
  	tf->lbam    = drive->cyl;
  	tf->lbah    = drive->cyl >> 8;
7f612f272   Bartlomiej Zolnierkiewicz   ide: remove [ata_...
153
  	tf->device  = (drive->head - 1) | drive->select;
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
154
  	tf->command = ATA_CMD_INIT_DEV_PARAMS;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
  }
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
156
  static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  {
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
158
  	tf->nsect   = drive->sect;
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
159
  	tf->command = ATA_CMD_RESTORE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
  }
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
161
  static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  {
57d7366b7   Bartlomiej Zolnierkiewicz   ide: remove 'hand...
163
  	tf->nsect   = drive->mult_req;
aaaade3f0   Bartlomiej Zolnierkiewicz   ide: WIN_* -> ATA...
164
  	tf->command = ATA_CMD_SET_MULTI;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  }
582078ee3   Bartlomiej Zolnierkiewicz   ide: merge ide_di...
166
167
168
169
170
171
172
173
174
  /**
   *	do_special		-	issue some special commands
   *	@drive: drive the command is for
   *
   *	do_special() is used to issue ATA_CMD_INIT_DEV_PARAMS,
   *	ATA_CMD_RESTORE and ATA_CMD_SET_MULTI commands to a drive.
   */
  
  static ide_startstop_t do_special(ide_drive_t *drive)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
176
  	struct ide_cmd cmd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
177

582078ee3   Bartlomiej Zolnierkiewicz   ide: merge ide_di...
178
  #ifdef DEBUG
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
179
180
181
  	printk(KERN_DEBUG "%s: %s: 0x%02x
  ", drive->name, __func__,
  		drive->special_flags);
582078ee3   Bartlomiej Zolnierkiewicz   ide: merge ide_di...
182
183
  #endif
  	if (drive->media != ide_disk) {
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
184
  		drive->special_flags = 0;
582078ee3   Bartlomiej Zolnierkiewicz   ide: merge ide_di...
185
186
187
  		drive->mult_req = 0;
  		return ide_stopped;
  	}
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
188
  	memset(&cmd, 0, sizeof(cmd));
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
189
  	cmd.protocol = ATA_PROT_NODATA;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190

ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
191
192
  	if (drive->special_flags & IDE_SFLAG_SET_GEOMETRY) {
  		drive->special_flags &= ~IDE_SFLAG_SET_GEOMETRY;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
193
  		ide_tf_set_specify_cmd(drive, &cmd.tf);
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
194
195
  	} else if (drive->special_flags & IDE_SFLAG_RECALIBRATE) {
  		drive->special_flags &= ~IDE_SFLAG_RECALIBRATE;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
196
  		ide_tf_set_restore_cmd(drive, &cmd.tf);
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
197
198
  	} else if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) {
  		drive->special_flags &= ~IDE_SFLAG_SET_MULTMODE;
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
199
  		ide_tf_set_setmult_cmd(drive, &cmd.tf);
5f582c8e2   Bartlomiej Zolnierkiewicz   ide: BUG() on unk...
200
201
  	} else
  		BUG();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202

60f85019c   Sergei Shtylyov   ide: replace IDE_...
203
204
205
  	cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
  	cmd.valid.in.tf  = IDE_VALID_IN_TF  | IDE_VALID_DEVICE;
  	cmd.tf_flags = IDE_TFLAG_CUSTOM_HANDLER;
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
206

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
207
  	do_rw_taskfile(drive, &cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
  
  	return ide_started;
  }
229816941   Bartlomiej Zolnierkiewicz   ide: pass command...
211
  void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
213
214
  {
  	ide_hwif_t *hwif = drive->hwif;
  	struct scatterlist *sg = hwif->sg_table;
229816941   Bartlomiej Zolnierkiewicz   ide: pass command...
215
  	struct request *rq = cmd->rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216

5ad960fe8   Tejun Heo   ide: drop rq->dat...
217
  	cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
  EXPORT_SYMBOL_GPL(ide_map_sg);
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
220
  void ide_init_sg_cmd(struct ide_cmd *cmd, unsigned int nr_bytes)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
  {
bf717c0a2   Bartlomiej Zolnierkiewicz   ide: keep track o...
222
  	cmd->nbytes = cmd->nleft = nr_bytes;
b6308ee0c   Bartlomiej Zolnierkiewicz   ide: move command...
223
224
  	cmd->cursg_ofs = 0;
  	cmd->cursg = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226
227
228
229
  EXPORT_SYMBOL_GPL(ide_init_sg_cmd);
  
  /**
   *	execute_drive_command	-	issue special drive command
338cec325   Adrian Bunk   [PATCH] merge som...
230
   *	@drive: the drive to issue the command on
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
232
233
234
235
236
237
238
239
240
241
242
   *	@rq: the request structure holding the command
   *
   *	execute_drive_cmd() issues a special drive command,  usually 
   *	initiated by ioctl() from the external hdparm program. The
   *	command can be a drive command, drive task or taskfile 
   *	operation. Weirdly you can call it with NULL to wait for
   *	all commands to finish. Don't do this as that is due to change
   */
  
  static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
  		struct request *rq)
  {
22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
243
  	struct ide_cmd *cmd = rq->special;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
244

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
245
  	if (cmd) {
0dfb991c6   Bartlomiej Zolnierkiewicz   ide: use ata_tf_p...
246
  		if (cmd->protocol == ATA_PROT_PIO) {
9780e2dd8   Tejun Heo   ide: convert to r...
247
  			ide_init_sg_cmd(cmd, blk_rq_sectors(rq) << 9);
229816941   Bartlomiej Zolnierkiewicz   ide: pass command...
248
  			ide_map_sg(drive, cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  		}
74095a91e   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
250

22aa4b32a   Bartlomiej Zolnierkiewicz   ide: remove ide_t...
251
  		return do_rw_taskfile(drive, cmd);
21d535c91   Bartlomiej Zolnierkiewicz   ide: execute_driv...
252
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253
254
255
256
257
258
259
260
   	/*
   	 * NULL is actually a valid way of waiting for
   	 * all current requests to be flushed from the queue.
   	 */
  #ifdef DEBUG
   	printk("%s: DRIVE_CMD (null)
  ", drive->name);
  #endif
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
261
  	rq->errors = 0;
f974b196f   Bartlomiej Zolnierkiewicz   ide: pass number ...
262
  	ide_complete_rq(drive, 0, blk_rq_bytes(rq));
64a57fe43   Bartlomiej Zolnierkiewicz   ide: add ide_read...
263

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
264
   	return ide_stopped;
1bc6daae4   Bartlomiej Zolnierkiewicz   ide: factor out p...
265
  }
79e36a9f5   Elias Oltmanns   IDE: Fix HDIO_DRI...
266
267
  static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
  {
4abdc6ee7   Elias Oltmanns   ide: Implement di...
268
  	u8 cmd = rq->cmd[0];
4abdc6ee7   Elias Oltmanns   ide: Implement di...
269
  	switch (cmd) {
1bc6daae4   Bartlomiej Zolnierkiewicz   ide: factor out p...
270
271
272
  	case REQ_PARK_HEADS:
  	case REQ_UNPARK_HEADS:
  		return ide_do_park_unpark(drive, rq);
92f1f8fd8   Elias Oltmanns   ide: Remove ide_s...
273
  	case REQ_DEVSET_EXEC:
1bc6daae4   Bartlomiej Zolnierkiewicz   ide: factor out p...
274
  		return ide_do_devset(drive, rq);
79e36a9f5   Elias Oltmanns   IDE: Fix HDIO_DRI...
275
276
277
  	case REQ_DRIVE_RESET:
  		return ide_do_reset(drive);
  	default:
1713788ff   Bartlomiej Zolnierkiewicz   ide: make ide_spe...
278
  		BUG();
79e36a9f5   Elias Oltmanns   IDE: Fix HDIO_DRI...
279
280
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281
282
283
284
  /**
   *	start_request	-	start of I/O and command issuing for IDE
   *
   *	start_request() initiates handling of a new I/O request. It
3c619ffd4   Bartlomiej Zolnierkiewicz   ide: remove no lo...
285
   *	accepts commands and I/O (read/write) requests.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
289
290
291
292
   *
   *	FIXME: this function needs a rename
   */
   
  static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
  {
  	ide_startstop_t startstop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293

33659ebba   Christoph Hellwig   block: remove wra...
294
  	BUG_ON(!(rq->cmd_flags & REQ_STARTED));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
296
297
298
  
  #ifdef DEBUG
  	printk("%s: start_request: current=0x%08lx
  ",
898ec223f   Bartlomiej Zolnierkiewicz   ide: remove HWIF(...
299
  		drive->hwif->name, (unsigned long) rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300
301
302
303
  #endif
  
  	/* bail early if we've exceeded max_failures */
  	if (drive->max_failures && (drive->failures > drive->max_failures)) {
b5e1a4e28   Aristeu Rozanski   ide-io: set REQ_F...
304
  		rq->cmd_flags |= REQ_FAILED;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
305
306
  		goto kill_rq;
  	}
ad3caddaa   Jens Axboe   [PATCH] Get rid o...
307
308
  	if (blk_pm_request(rq))
  		ide_check_pm_state(drive, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309

fdd88f0af   Sergei Shtylyov   ide: inline SELEC...
310
  	drive->hwif->tp_ops->dev_select(drive);
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
311
312
  	if (ide_wait_stat(&startstop, drive, drive->ready_stat,
  			  ATA_BUSY | ATA_DRQ, WAIT_READY)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
315
316
  		printk(KERN_ERR "%s: drive not ready for command
  ", drive->name);
  		return startstop;
  	}
ca1b96e00   Bartlomiej Zolnierkiewicz   ide: replace spec...
317
318
  
  	if (drive->special_flags == 0) {
7f3c868ba   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
319
  		struct ide_driver *drv;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
320

513daadd1   Suleiman Souhlal   ide: use correct ...
321
322
323
324
325
326
  		/*
  		 * We reset the drive so we need to issue a SETFEATURES.
  		 * Do it _after_ do_special() restored device parameters.
  		 */
  		if (drive->current_speed == 0xff)
  			ide_config_drive_speed(drive, drive->desired_speed);
7267c3377   Bartlomiej Zolnierkiewicz   ide: remove REQ_T...
327
  		if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
  			return execute_drive_cmd(drive, rq);
  		else if (blk_pm_request(rq)) {
765139ef5   Tejun Heo   ide-pm: don't abu...
330
  			struct request_pm_state *pm = rq->special;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331
332
333
  #ifdef DEBUG_PM
  			printk("%s: start_power_step(step: %d)
  ",
6b7d8fc36   Bartlomiej Zolnierkiewicz   ide: fix build fo...
334
  				drive->name, pm->pm_step);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
337
  #endif
  			startstop = ide_start_power_step(drive, rq);
  			if (startstop == ide_stopped &&
0d346ba07   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
338
  			    pm->pm_step == IDE_PM_COMPLETED)
3616b6536   Bartlomiej Zolnierkiewicz   ide: complete pow...
339
  				ide_complete_pm_rq(drive, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
  			return startstop;
4c4762d10   Christoph Hellwig   block: fix some m...
341
  		} else if (!rq->rq_disk && rq->cmd_type == REQ_TYPE_SPECIAL)
79e36a9f5   Elias Oltmanns   IDE: Fix HDIO_DRI...
342
343
344
345
346
347
348
349
350
  			/*
  			 * TODO: Once all ULDs have been modified to
  			 * check for specific op codes rather than
  			 * blindly accepting any special request, the
  			 * check for ->rq_disk above may be replaced
  			 * by a more suitable mechanism or even
  			 * dropped entirely.
  			 */
  			return ide_special_rq(drive, rq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

7f3c868ba   Bartlomiej Zolnierkiewicz   ide: remove ide_d...
352
  		drv = *(struct ide_driver **)rq->rq_disk->private_data;
3c619ffd4   Bartlomiej Zolnierkiewicz   ide: remove no lo...
353

9780e2dd8   Tejun Heo   ide: convert to r...
354
  		return drv->do_request(drive, rq, blk_rq_pos(rq));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
357
358
359
360
361
362
363
364
365
366
367
  	}
  	return do_special(drive);
  kill_rq:
  	ide_kill_rq(drive, rq);
  	return ide_stopped;
  }
  
  /**
   *	ide_stall_queue		-	pause an IDE device
   *	@drive: drive to stall
   *	@timeout: time to stall for (jiffies)
   *
   *	ide_stall_queue() can be used by a drive to give excess bandwidth back
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
368
   *	to the port by sleeping for timeout jiffies.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
370
371
372
373
374
375
   */
   
  void ide_stall_queue (ide_drive_t *drive, unsigned long timeout)
  {
  	if (timeout > WAIT_WORSTCASE)
  		timeout = WAIT_WORSTCASE;
  	drive->sleep = timeout + jiffies;
97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
376
  	drive->dev_flags |= IDE_DFLAG_SLEEPING;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
378
  EXPORT_SYMBOL(ide_stall_queue);
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
  static inline int ide_lock_port(ide_hwif_t *hwif)
  {
  	if (hwif->busy)
  		return 1;
  
  	hwif->busy = 1;
  
  	return 0;
  }
  
  static inline void ide_unlock_port(ide_hwif_t *hwif)
  {
  	hwif->busy = 0;
  }
  
  static inline int ide_lock_host(struct ide_host *host, ide_hwif_t *hwif)
  {
  	int rc = 0;
  
  	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
  		rc = test_and_set_bit_lock(IDE_HOST_BUSY, &host->host_busy);
  		if (rc == 0) {
e354c1d80   Bartlomiej Zolnierkiewicz   ide: remove IDE_A...
401
402
  			if (host->get_lock)
  				host->get_lock(ide_intr, hwif);
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
403
404
405
406
407
408
409
410
  		}
  	}
  	return rc;
  }
  
  static inline void ide_unlock_host(struct ide_host *host)
  {
  	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
e354c1d80   Bartlomiej Zolnierkiewicz   ide: remove IDE_A...
411
412
  		if (host->release_lock)
  			host->release_lock();
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
413
414
415
  		clear_bit_unlock(IDE_HOST_BUSY, &host->host_busy);
  	}
  }
782b86e26   Jens Axboe   ide: always ensur...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq)
  {
  	if (rq)
  		blk_requeue_request(q, rq);
  	if (rq || blk_peek_request(q)) {
  		/* Use 3ms as that was the old plug delay */
  		blk_delay_queue(q, 3);
  	}
  }
  
  void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
  {
  	struct request_queue *q = drive->queue;
  	unsigned long flags;
  
  	spin_lock_irqsave(q->queue_lock, flags);
  	__ide_requeue_and_plug(q, rq);
  	spin_unlock_irqrestore(q->queue_lock, flags);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
  /*
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
436
   * Issue a new request to a device.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
   */
295f00042   Bartlomiej Zolnierkiewicz   ide: don't execut...
438
  void do_ide_request(struct request_queue *q)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439
  {
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
440
441
  	ide_drive_t	*drive = q->queuedata;
  	ide_hwif_t	*hwif = drive->hwif;
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
442
  	struct ide_host *host = hwif->host;
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
443
  	struct request	*rq = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  	ide_startstop_t	startstop;
9ced0b95b   Jens Axboe   ide: ensure that ...
445
  	unsigned long queue_run_ms = 3; /* old plug delay */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446

201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
447
  	spin_unlock_irq(q->queue_lock);
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
448

02e7cf8f8   Tejun Heo   ide-cd,atapi: use...
449
450
  	/* HLD do_request() callback might sleep, make sure it's okay */
  	might_sleep();
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
451
452
  	if (ide_lock_host(host, hwif))
  		goto plug_device_2;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
453
  	spin_lock_irq(&hwif->lock);
295f00042   Bartlomiej Zolnierkiewicz   ide: don't execut...
454

5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
455
  	if (!ide_lock_port(hwif)) {
42cf2611b   Bartlomiej Zolnierkiewicz   ide: fix setting ...
456
  		ide_hwif_t *prev_port;
3503e0acb   David S. Miller   Revert "ide: impr...
457
458
  
  		WARN_ON_ONCE(hwif->rq);
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
459
  repeat:
bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
460
  		prev_port = hwif->host->cur_port;
9010941c5   Elias Oltmanns   ide: Fix code dea...
461
462
  		if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
  		    time_after(drive->sleep, jiffies)) {
9ced0b95b   Jens Axboe   ide: ensure that ...
463
464
465
  			unsigned long left = jiffies - drive->sleep;
  
  			queue_run_ms = jiffies_to_msecs(left + 1);
9010941c5   Elias Oltmanns   ide: Fix code dea...
466
467
  			ide_unlock_port(hwif);
  			goto plug_device;
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
468
  		}
295f00042   Bartlomiej Zolnierkiewicz   ide: don't execut...
469

bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
470
471
  		if ((hwif->host->host_flags & IDE_HFLAG_SERIALIZE) &&
  		    hwif != prev_port) {
734affdca   Bartlomiej Zolnierkiewicz   ide: add IDE_DFLA...
472
473
  			ide_drive_t *cur_dev =
  				prev_port ? prev_port->cur_dev : NULL;
7299a3918   Bartlomiej Zolnierkiewicz   ide: remove hwif-...
474
  			/*
42cf2611b   Bartlomiej Zolnierkiewicz   ide: fix setting ...
475
  			 * set nIEN for previous port, drives in the
734affdca   Bartlomiej Zolnierkiewicz   ide: add IDE_DFLA...
476
  			 * quirk list may not like intr setups/cleanups
7299a3918   Bartlomiej Zolnierkiewicz   ide: remove hwif-...
477
  			 */
734affdca   Bartlomiej Zolnierkiewicz   ide: add IDE_DFLA...
478
479
  			if (cur_dev &&
  			    (cur_dev->dev_flags & IDE_DFLAG_NIEN_QUIRK) == 0)
ecf3a31d2   Sergei Shtylyov   ide: turn set_irq...
480
481
482
  				prev_port->tp_ops->write_devctl(prev_port,
  								ATA_NIEN |
  								ATA_DEVCTL_OBS);
bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
483
484
  
  			hwif->host->cur_port = hwif;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
  		}
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
486
  		hwif->cur_dev = drive;
4abdc6ee7   Elias Oltmanns   ide: Implement di...
487
  		drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488

3503e0acb   David S. Miller   Revert "ide: impr...
489
490
491
492
493
494
495
  		spin_unlock_irq(&hwif->lock);
  		spin_lock_irq(q->queue_lock);
  		/*
  		 * we know that the queue isn't empty, but this can happen
  		 * if the q->prep_rq_fn() decides to kill a request
  		 */
  		if (!rq)
9934c8c04   Tejun Heo   block: implement ...
496
  			rq = blk_fetch_request(drive->queue);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
497

3503e0acb   David S. Miller   Revert "ide: impr...
498
499
500
501
502
503
  		spin_unlock_irq(q->queue_lock);
  		spin_lock_irq(&hwif->lock);
  
  		if (!rq) {
  			ide_unlock_port(hwif);
  			goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
504
505
506
507
  		}
  
  		/*
  		 * Sanity: don't accept a request that isn't a PM request
3503e0acb   David S. Miller   Revert "ide: impr...
508
509
510
511
512
513
514
515
516
517
  		 * if we are currently power managed. This is very important as
  		 * blk_stop_queue() doesn't prevent the blk_fetch_request()
  		 * above to return us whatever is in the queue. Since we call
  		 * ide_do_request() ourselves, we end up taking requests while
  		 * the queue is blocked...
  		 * 
  		 * We let requests forced at head of queue with ide-preempt
  		 * though. I hope that doesn't happen too much, hopefully not
  		 * unless the subdriver triggers such a thing in its own PM
  		 * state machine.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518
  		 */
3503e0acb   David S. Miller   Revert "ide: impr...
519
520
521
522
523
524
525
  		if ((drive->dev_flags & IDE_DFLAG_BLOCKED) &&
  		    blk_pm_request(rq) == 0 &&
  		    (rq->cmd_flags & REQ_PREEMPT) == 0) {
  			/* there should be no pending command at this point */
  			ide_unlock_port(hwif);
  			goto plug_device;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
526

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
527
  		hwif->rq = rq;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
529
  		spin_unlock_irq(&hwif->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
530
  		startstop = start_request(drive, rq);
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
531
  		spin_lock_irq(&hwif->lock);
295f00042   Bartlomiej Zolnierkiewicz   ide: don't execut...
532

8f6205cd5   Tejun Heo   ide: dequeue in-f...
533
534
535
  		if (startstop == ide_stopped) {
  			rq = hwif->rq;
  			hwif->rq = NULL;
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
536
  			goto repeat;
8f6205cd5   Tejun Heo   ide: dequeue in-f...
537
  		}
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
538
539
540
  	} else
  		goto plug_device;
  out:
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
541
  	spin_unlock_irq(&hwif->lock);
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
542
543
  	if (rq == NULL)
  		ide_unlock_host(host);
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
544
  	spin_lock_irq(q->queue_lock);
295f00042   Bartlomiej Zolnierkiewicz   ide: don't execut...
545
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
546

295f00042   Bartlomiej Zolnierkiewicz   ide: don't execut...
547
  plug_device:
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
548
  	spin_unlock_irq(&hwif->lock);
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
549
550
  	ide_unlock_host(host);
  plug_device_2:
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
551
  	spin_lock_irq(q->queue_lock);
782b86e26   Jens Axboe   ide: always ensur...
552
  	__ide_requeue_and_plug(q, rq);
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
553
  }
b6a45a0b1   Bartlomiej Zolnierkiewicz   ide: move drive_i...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
  static int drive_is_ready(ide_drive_t *drive)
  {
  	ide_hwif_t *hwif = drive->hwif;
  	u8 stat = 0;
  
  	if (drive->waiting_for_dma)
  		return hwif->dma_ops->dma_test_irq(drive);
  
  	if (hwif->io_ports.ctl_addr &&
  	    (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0)
  		stat = hwif->tp_ops->read_altstatus(hwif);
  	else
  		/* Note: this may clear a pending IRQ!! */
  		stat = hwif->tp_ops->read_status(hwif);
  
  	if (stat & ATA_BUSY)
  		/* drive busy: definitely not interrupting */
  		return 0;
  
  	/* drive ready: *might* be interrupting */
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
  /**
   *	ide_timer_expiry	-	handle lack of an IDE interrupt
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
578
   *	@data: timer callback magic (hwif)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
579
580
581
582
583
584
585
586
587
588
589
590
591
   *
   *	An IDE command has timed out before the expected drive return
   *	occurred. At this point we attempt to clean up the current
   *	mess. If the current handler includes an expiry handler then
   *	we invoke the expiry handler, and providing it is happy the
   *	work is done. If that fails we apply generic recovery rules
   *	invoking the handler and checking the drive DMA status. We
   *	have an excessively incestuous relationship with the DMA
   *	logic that wants cleaning up.
   */
   
  void ide_timer_expiry (unsigned long data)
  {
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
592
  	ide_hwif_t	*hwif = (ide_hwif_t *)data;
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
593
  	ide_drive_t	*uninitialized_var(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
  	ide_handler_t	*handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
595
  	unsigned long	flags;
e0c6dcd8d   Roel Kluin   ide: expiry() ret...
596
  	int		wait = -1;
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
597
  	int		plug_device = 0;
8f6205cd5   Tejun Heo   ide: dequeue in-f...
598
  	struct request	*uninitialized_var(rq_in_flight);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
600
601
602
  	spin_lock_irqsave(&hwif->lock, flags);
  
  	handler = hwif->handler;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
604
  	if (handler == NULL || hwif->req_gen != hwif->req_gen_timer) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
608
609
610
  		/*
  		 * Either a marginal timeout occurred
  		 * (got the interrupt just as timer expired),
  		 * or we were "sleeping" to give other devices a chance.
  		 * Either way, we don't really want to complain about anything.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
  	} else {
c38714ed4   Bartlomiej Zolnierkiewicz   ide: remove now r...
612
613
  		ide_expiry_t *expiry = hwif->expiry;
  		ide_startstop_t startstop = ide_stopped;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
614
  		drive = hwif->cur_dev;
c38714ed4   Bartlomiej Zolnierkiewicz   ide: remove now r...
615
616
617
618
619
620
621
622
623
624
  
  		if (expiry) {
  			wait = expiry(drive);
  			if (wait > 0) { /* continue */
  				/* reset timer */
  				hwif->timer.expires = jiffies + wait;
  				hwif->req_gen_timer = hwif->req_gen;
  				add_timer(&hwif->timer);
  				spin_unlock_irqrestore(&hwif->lock, flags);
  				return;
295f00042   Bartlomiej Zolnierkiewicz   ide: don't execut...
625
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
  		}
c38714ed4   Bartlomiej Zolnierkiewicz   ide: remove now r...
627
  		hwif->handler = NULL;
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
628
  		hwif->expiry = NULL;
c38714ed4   Bartlomiej Zolnierkiewicz   ide: remove now r...
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  		/*
  		 * We need to simulate a real interrupt when invoking
  		 * the handler() function, which means we need to
  		 * globally mask the specific IRQ:
  		 */
  		spin_unlock(&hwif->lock);
  		/* disable_irq_nosync ?? */
  		disable_irq(hwif->irq);
  		/* local CPU only, as if we were handling an interrupt */
  		local_irq_disable();
  		if (hwif->polling) {
  			startstop = handler(drive);
  		} else if (drive_is_ready(drive)) {
  			if (drive->waiting_for_dma)
  				hwif->dma_ops->dma_lost_irq(drive);
53b987d5e   Sergei Shtylyov   ide: call clear_i...
644
645
  			if (hwif->port_ops && hwif->port_ops->clear_irq)
  				hwif->port_ops->clear_irq(drive);
c38714ed4   Bartlomiej Zolnierkiewicz   ide: remove now r...
646
647
648
649
650
651
652
653
654
655
656
657
658
  			printk(KERN_WARNING "%s: lost interrupt
  ",
  				drive->name);
  			startstop = handler(drive);
  		} else {
  			if (drive->waiting_for_dma)
  				startstop = ide_dma_timeout_retry(drive, wait);
  			else
  				startstop = ide_error(drive, "irq timeout",
  					hwif->tp_ops->read_status(hwif));
  		}
  		spin_lock_irq(&hwif->lock);
  		enable_irq(hwif->irq);
e3b29f051   Bartlomiej Zolnierkiewicz   ide: fix OOPS dur...
659
  		if (startstop == ide_stopped && hwif->polling == 0) {
8f6205cd5   Tejun Heo   ide: dequeue in-f...
660
661
  			rq_in_flight = hwif->rq;
  			hwif->rq = NULL;
c38714ed4   Bartlomiej Zolnierkiewicz   ide: remove now r...
662
663
664
  			ide_unlock_port(hwif);
  			plug_device = 1;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  	}
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
666
  	spin_unlock_irqrestore(&hwif->lock, flags);
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
667

5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
668
669
  	if (plug_device) {
  		ide_unlock_host(hwif->host);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
670
  		ide_requeue_and_plug(drive, rq_in_flight);
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
671
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
673
674
675
676
  }
  
  /**
   *	unexpected_intr		-	handle an unexpected IDE interrupt
   *	@irq: interrupt line
bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
677
   *	@hwif: port being processed
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
   *
   *	There's nothing really useful we can do with an unexpected interrupt,
   *	other than reading the status register (to clear it), and logging it.
   *	There should be no way that an irq can happen before we're ready for it,
   *	so we needn't worry much about losing an "important" interrupt here.
   *
   *	On laptops (and "green" PCs), an unexpected interrupt occurs whenever
   *	the drive enters "idle", "standby", or "sleep" mode, so if the status
   *	looks "good", we just ignore the interrupt completely.
   *
   *	This routine assumes __cli() is in effect when called.
   *
   *	If an unexpected interrupt happens on irq15 while we are handling irq14
   *	and if the two interfaces are "serialized" (CMD640), then it looks like
   *	we could screw up by interfering with a new request being set up for 
   *	irq15.
   *
   *	In reality, this is a non-issue.  The new command is not sent unless 
   *	the drive is ready to accept one, in which case we know the drive is
   *	not trying to interrupt us.  And ide_set_handler() is always invoked
   *	before completing the issuance of any new drive command, so we will not
   *	be accidentally invoked as a result of any valid command completion
   *	interrupt.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
701
   */
bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
702
703
  
  static void unexpected_intr(int irq, ide_hwif_t *hwif)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  {
ae86afaee   Bartlomiej Zolnierkiewicz   ide: use per-port...
705
706
707
708
709
710
711
712
713
714
715
716
717
  	u8 stat = hwif->tp_ops->read_status(hwif);
  
  	if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
  		/* Try to not flood the console with msgs */
  		static unsigned long last_msgtime, count;
  		++count;
  
  		if (time_after(jiffies, last_msgtime + HZ)) {
  			last_msgtime = jiffies;
  			printk(KERN_ERR "%s: unexpected interrupt, "
  				"status=0x%02x, count=%ld
  ",
  				hwif->name, stat, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
718
  		}
ae86afaee   Bartlomiej Zolnierkiewicz   ide: use per-port...
719
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
720
721
722
723
724
  }
  
  /**
   *	ide_intr	-	default IDE interrupt handler
   *	@irq: interrupt number
ae86afaee   Bartlomiej Zolnierkiewicz   ide: use per-port...
725
   *	@dev_id: hwif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
728
729
730
731
   *	@regs: unused weirdness from the kernel irq layer
   *
   *	This is the default IRQ handler for the IDE layer. You should
   *	not need to override it. If you do be aware it is subtle in
   *	places
   *
bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
732
   *	hwif is the interface in the group currently performing
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
733
   *	a command. hwif->cur_dev is the drive and hwif->handler is
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
734
735
736
737
738
739
740
741
742
743
   *	the IRQ handler to call. As we issue a command the handlers
   *	step through multiple states, reassigning the handler to the
   *	next step in the process. Unlike a smart SCSI controller IDE
   *	expects the main processor to sequence the various transfer
   *	stages. We also manage a poll timer to catch up with most
   *	timeout situations. There are still a few where the handlers
   *	don't ever decide to give up.
   *
   *	The handler eventually returns ide_stopped to indicate the
   *	request completed. At this point we issue the next request
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
744
   *	on the port and the process begins again.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
745
   */
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
746

7d12e780e   David Howells   IRQ: Maintain reg...
747
  irqreturn_t ide_intr (int irq, void *dev_id)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
748
  {
ae86afaee   Bartlomiej Zolnierkiewicz   ide: use per-port...
749
  	ide_hwif_t *hwif = (ide_hwif_t *)dev_id;
255115fb3   Bartlomiej Zolnierkiewicz   ide: allow host d...
750
  	struct ide_host *host = hwif->host;
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
751
  	ide_drive_t *uninitialized_var(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
752
  	ide_handler_t *handler;
ae86afaee   Bartlomiej Zolnierkiewicz   ide: use per-port...
753
  	unsigned long flags;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
754
  	ide_startstop_t startstop;
3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
755
  	irqreturn_t irq_ret = IRQ_NONE;
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
756
  	int plug_device = 0;
8f6205cd5   Tejun Heo   ide: dequeue in-f...
757
  	struct request *uninitialized_var(rq_in_flight);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
758

255115fb3   Bartlomiej Zolnierkiewicz   ide: allow host d...
759
760
  	if (host->host_flags & IDE_HFLAG_SERIALIZE) {
  		if (hwif != host->cur_port)
ae86afaee   Bartlomiej Zolnierkiewicz   ide: use per-port...
761
762
  			goto out_early;
  	}
bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
763

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
764
  	spin_lock_irqsave(&hwif->lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
765

f4d3ffa52   Sergei Shtylyov   ide: move ack_int...
766
767
  	if (hwif->port_ops && hwif->port_ops->test_irq &&
  	    hwif->port_ops->test_irq(hwif) == 0)
3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
768
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
770
771
772
  	handler = hwif->handler;
  
  	if (handler == NULL || hwif->polling) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
774
775
776
777
778
779
780
781
782
783
  		/*
  		 * Not expecting an interrupt from this drive.
  		 * That means this could be:
  		 *	(1) an interrupt from another PCI device
  		 *	sharing the same PCI INT# as us.
  		 * or	(2) a drive just entered sleep or standby mode,
  		 *	and is interrupting to let us know.
  		 * or	(3) a spurious interrupt of unknown origin.
  		 *
  		 * For PCI, we cannot tell the difference,
  		 * so in that case we just ignore it and hope it goes away.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
  		 */
255115fb3   Bartlomiej Zolnierkiewicz   ide: allow host d...
785
  		if ((host->irq_flags & IRQF_SHARED) == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
786
787
788
789
  			/*
  			 * Probably not a shared PCI interrupt,
  			 * so we can safely try to do something about it:
  			 */
bd53cbcce   Bartlomiej Zolnierkiewicz   ide: add ->cur_po...
790
  			unexpected_intr(irq, hwif);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
791
792
793
794
795
  		} else {
  			/*
  			 * Whack the status register, just in case
  			 * we have a leftover pending IRQ.
  			 */
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
796
  			(void)hwif->tp_ops->read_status(hwif);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
  		}
3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
798
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
799
  	}
3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
800

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
801
  	drive = hwif->cur_dev;
3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
802
803
  
  	if (!drive_is_ready(drive))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804
805
806
807
808
809
810
  		/*
  		 * This happens regularly when we share a PCI IRQ with
  		 * another device.  Unfortunately, it can also happen
  		 * with some buggy drives that trigger the IRQ before
  		 * their status register is up to date.  Hopefully we have
  		 * enough advance overhead that the latter isn't a problem.
  		 */
3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
811
  		goto out;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
812
  	hwif->handler = NULL;
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
813
  	hwif->expiry = NULL;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
814
815
816
  	hwif->req_gen++;
  	del_timer(&hwif->timer);
  	spin_unlock(&hwif->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817

bfa7d8e55   Bartlomiej Zolnierkiewicz   ide: ->ide_dma_cl...
818
819
  	if (hwif->port_ops && hwif->port_ops->clear_irq)
  		hwif->port_ops->clear_irq(drive);
f0dd8712e   Albert Lee   ide: clear bmdma ...
820

97100fc81   Bartlomiej Zolnierkiewicz   ide: add device f...
821
  	if (drive->dev_flags & IDE_DFLAG_UNMASK)
366c7f554   Ingo Molnar   [PATCH] lockdep: ...
822
  		local_irq_enable_in_hardirq();
bfa7d8e55   Bartlomiej Zolnierkiewicz   ide: ->ide_dma_cl...
823

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
824
825
  	/* service this interrupt, may set handler for next interrupt */
  	startstop = handler(drive);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826

b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
827
  	spin_lock_irq(&hwif->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
831
832
833
834
  	/*
  	 * Note that handler() may have set things up for another
  	 * interrupt to occur soon, but it cannot happen until
  	 * we exit from this routine, because it will be the
  	 * same irq as is currently being serviced here, and Linux
  	 * won't allow another of the same (on any CPU) until we return.
  	 */
e3b29f051   Bartlomiej Zolnierkiewicz   ide: fix OOPS dur...
835
  	if (startstop == ide_stopped && hwif->polling == 0) {
9600dcf13   Bartlomiej Zolnierkiewicz   ide: make "parano...
836
  		BUG_ON(hwif->handler);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
837
838
  		rq_in_flight = hwif->rq;
  		hwif->rq = NULL;
9600dcf13   Bartlomiej Zolnierkiewicz   ide: make "parano...
839
840
  		ide_unlock_port(hwif);
  		plug_device = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
841
  	}
3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
842
843
  	irq_ret = IRQ_HANDLED;
  out:
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
844
  	spin_unlock_irqrestore(&hwif->lock, flags);
ae86afaee   Bartlomiej Zolnierkiewicz   ide: use per-port...
845
  out_early:
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
846
847
  	if (plug_device) {
  		ide_unlock_host(hwif->host);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
848
  		ide_requeue_and_plug(drive, rq_in_flight);
5b31f855f   Bartlomiej Zolnierkiewicz   ide: use lock bit...
849
  	}
201bffa46   Bartlomiej Zolnierkiewicz   ide: use per-devi...
850

3e0e29f73   Bartlomiej Zolnierkiewicz   ide: unify ide_in...
851
  	return irq_ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
852
  }
849d71300   Stanislaw Gruszka   ide: allow to wra...
853
  EXPORT_SYMBOL_GPL(ide_intr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854

9f87abe89   Bartlomiej Zolnierkiewicz   ide: add ide_pad_...
855
856
857
858
859
860
861
  void ide_pad_transfer(ide_drive_t *drive, int write, int len)
  {
  	ide_hwif_t *hwif = drive->hwif;
  	u8 buf[4] = { 0 };
  
  	while (len > 0) {
  		if (write)
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
862
  			hwif->tp_ops->output_data(drive, NULL, buf, min(4, len));
9f87abe89   Bartlomiej Zolnierkiewicz   ide: add ide_pad_...
863
  		else
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
864
  			hwif->tp_ops->input_data(drive, NULL, buf, min(4, len));
9f87abe89   Bartlomiej Zolnierkiewicz   ide: add ide_pad_...
865
866
867
868
  		len -= 4;
  	}
  }
  EXPORT_SYMBOL_GPL(ide_pad_transfer);