Blame view

drivers/ide/ide-atapi.c 17.7 KB
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
1
2
3
4
5
  /*
   * ATAPI support.
   */
  
  #include <linux/kernel.h>
4cad085ef   Borislav Petkov   ide-cd: move cdro...
6
  #include <linux/cdrom.h>
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
7
  #include <linux/delay.h>
38789fda2   Paul Gortmaker   ide/ata: Add expo...
8
  #include <linux/export.h>
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
9
  #include <linux/ide.h>
479edf065   Geert Uytterhoeven   ide: drivers/ide/...
10
  #include <linux/scatterlist.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
11
  #include <linux/gfp.h>
479edf065   Geert Uytterhoeven   ide: drivers/ide/...
12

646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
13
  #include <scsi/scsi.h>
103f7033b   Borislav Petkov   ide: unify interr...
14
15
  #define DRV_NAME "ide-atapi"
  #define PFX DRV_NAME ": "
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
16
17
18
19
20
21
  #ifdef DEBUG
  #define debug_log(fmt, args...) \
  	printk(KERN_INFO "ide: " fmt, ## args)
  #else
  #define debug_log(fmt, args...) do {} while (0)
  #endif
8c662852d   Borislav Petkov   ide-atapi: comput...
22
  #define ATAPI_MIN_CDB_BYTES	12
991cb26a6   Borislav Petkov   ide-atapi: add a ...
23
24
  static inline int dev_is_idecd(ide_drive_t *drive)
  {
5317464dc   Borislav Petkov   ide: remove the l...
25
  	return drive->media == ide_cdrom || drive->media == ide_optical;
991cb26a6   Borislav Petkov   ide-atapi: add a ...
26
  }
51509eec3   Bartlomiej Zolnierkiewicz   ide: add ide_chec...
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
  /*
   * Check whether we can support a device,
   * based on the ATAPI IDENTIFY command results.
   */
  int ide_check_atapi_device(ide_drive_t *drive, const char *s)
  {
  	u16 *id = drive->id;
  	u8 gcw[2], protocol, device_type, removable, drq_type, packet_size;
  
  	*((u16 *)&gcw) = id[ATA_ID_CONFIG];
  
  	protocol    = (gcw[1] & 0xC0) >> 6;
  	device_type =  gcw[1] & 0x1F;
  	removable   = (gcw[0] & 0x80) >> 7;
  	drq_type    = (gcw[0] & 0x60) >> 5;
  	packet_size =  gcw[0] & 0x03;
  
  #ifdef CONFIG_PPC
  	/* kludge for Apple PowerBook internal zip */
  	if (drive->media == ide_floppy && device_type == 5 &&
  	    !strstr((char *)&id[ATA_ID_PROD], "CD-ROM") &&
  	    strstr((char *)&id[ATA_ID_PROD], "ZIP"))
  		device_type = 0;
  #endif
  
  	if (protocol != 2)
  		printk(KERN_ERR "%s: %s: protocol (0x%02x) is not ATAPI
  ",
  			s, drive->name, protocol);
  	else if ((drive->media == ide_floppy && device_type != 0) ||
  		 (drive->media == ide_tape && device_type != 1))
  		printk(KERN_ERR "%s: %s: invalid device type (0x%02x)
  ",
  			s, drive->name, device_type);
  	else if (removable == 0)
  		printk(KERN_ERR "%s: %s: the removable flag is not set
  ",
  			s, drive->name);
  	else if (drive->media == ide_floppy && drq_type == 3)
  		printk(KERN_ERR "%s: %s: sorry, DRQ type (0x%02x) not "
  			"supported
  ", s, drive->name, drq_type);
  	else if (packet_size != 0)
  		printk(KERN_ERR "%s: %s: packet size (0x%02x) is not 12 "
  			"bytes
  ", s, drive->name, packet_size);
  	else
  		return 1;
  	return 0;
  }
  EXPORT_SYMBOL_GPL(ide_check_atapi_device);
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
78
79
80
  void ide_init_pc(struct ide_atapi_pc *pc)
  {
  	memset(pc, 0, sizeof(*pc));
7bf7420a3   Bartlomiej Zolnierkiewicz   ide: add ide_init...
81
82
  }
  EXPORT_SYMBOL_GPL(ide_init_pc);
7645c1514   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
83
  /*
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
84
85
86
87
   * Add a special packet command request to the tail of the request queue,
   * and wait for it to be serviced.
   */
  int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
b13345f39   Borislav Petkov   ide-atapi: add a ...
88
  		      struct ide_atapi_pc *pc, void *buf, unsigned int bufflen)
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
89
90
91
92
93
94
  {
  	struct request *rq;
  	int error;
  
  	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
  	rq->cmd_type = REQ_TYPE_SPECIAL;
c267cc1c4   Tejun Heo   ide-atapi: don't ...
95
  	rq->special = (char *)pc;
3eb76c1cc   Borislav Petkov   ide-floppy: do no...
96

b13345f39   Borislav Petkov   ide-atapi: add a ...
97
98
  	if (buf && bufflen) {
  		error = blk_rq_map_kern(drive->queue, rq, buf, bufflen,
5c4be5724   Tejun Heo   ide-cd,atapi: use...
99
100
101
  					GFP_NOIO);
  		if (error)
  			goto put_req;
3eb76c1cc   Borislav Petkov   ide-floppy: do no...
102
  	}
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
103
104
105
106
  	memcpy(rq->cmd, pc->c, 12);
  	if (drive->media == ide_tape)
  		rq->cmd[13] = REQ_IDETAPE_PC1;
  	error = blk_execute_rq(drive->queue, disk, rq, 0);
5c4be5724   Tejun Heo   ide-cd,atapi: use...
107
  put_req:
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
108
  	blk_put_request(rq);
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
109
110
111
  	return error;
  }
  EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
de699ad59   Bartlomiej Zolnierkiewicz   ide: add ide_do_t...
112
113
114
115
116
117
  int ide_do_test_unit_ready(ide_drive_t *drive, struct gendisk *disk)
  {
  	struct ide_atapi_pc pc;
  
  	ide_init_pc(&pc);
  	pc.c[0] = TEST_UNIT_READY;
b13345f39   Borislav Petkov   ide-atapi: add a ...
118
  	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
de699ad59   Bartlomiej Zolnierkiewicz   ide: add ide_do_t...
119
120
  }
  EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
121
122
123
124
125
126
127
128
129
130
  int ide_do_start_stop(ide_drive_t *drive, struct gendisk *disk, int start)
  {
  	struct ide_atapi_pc pc;
  
  	ide_init_pc(&pc);
  	pc.c[0] = START_STOP;
  	pc.c[4] = start;
  
  	if (drive->media == ide_tape)
  		pc.flags |= PC_FLAG_WAIT_FOR_DSC;
b13345f39   Borislav Petkov   ide-atapi: add a ...
131
  	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
132
133
  }
  EXPORT_SYMBOL_GPL(ide_do_start_stop);
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
134
135
136
  int ide_set_media_lock(ide_drive_t *drive, struct gendisk *disk, int on)
  {
  	struct ide_atapi_pc pc;
42619d35c   Bartlomiej Zolnierkiewicz   ide: remove IDE_A...
137
  	if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
138
139
140
141
142
  		return 0;
  
  	ide_init_pc(&pc);
  	pc.c[0] = ALLOW_MEDIUM_REMOVAL;
  	pc.c[4] = on;
b13345f39   Borislav Petkov   ide-atapi: add a ...
143
  	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
144
145
  }
  EXPORT_SYMBOL_GPL(ide_set_media_lock);
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
146
147
148
149
150
151
152
153
154
155
156
157
158
  void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc)
  {
  	ide_init_pc(pc);
  	pc->c[0] = REQUEST_SENSE;
  	if (drive->media == ide_floppy) {
  		pc->c[4] = 255;
  		pc->req_xfer = 18;
  	} else {
  		pc->c[4] = 20;
  		pc->req_xfer = 20;
  	}
  }
  EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd);
a1df5169f   Borislav Petkov   ide: add helpers ...
159
160
161
162
163
  void ide_prep_sense(ide_drive_t *drive, struct request *rq)
  {
  	struct request_sense *sense = &drive->sense_data;
  	struct request *sense_rq = &drive->sense_rq;
  	unsigned int cmd_len, sense_len;
5c4be5724   Tejun Heo   ide-cd,atapi: use...
164
  	int err;
a1df5169f   Borislav Petkov   ide: add helpers ...
165

a1df5169f   Borislav Petkov   ide: add helpers ...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  	switch (drive->media) {
  	case ide_floppy:
  		cmd_len = 255;
  		sense_len = 18;
  		break;
  	case ide_tape:
  		cmd_len = 20;
  		sense_len = 20;
  		break;
  	default:
  		cmd_len = 18;
  		sense_len = 18;
  	}
  
  	BUG_ON(sense_len > sizeof(*sense));
33659ebba   Christoph Hellwig   block: remove wra...
181
  	if (rq->cmd_type == REQ_TYPE_SENSE || drive->sense_rq_armed)
a1df5169f   Borislav Petkov   ide: add helpers ...
182
183
184
185
186
  		return;
  
  	memset(sense, 0, sizeof(*sense));
  
  	blk_rq_init(rq->q, sense_rq);
a1df5169f   Borislav Petkov   ide: add helpers ...
187

5c4be5724   Tejun Heo   ide-cd,atapi: use...
188
189
190
191
  	err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
  			      GFP_NOIO);
  	if (unlikely(err)) {
  		if (printk_ratelimit())
103f7033b   Borislav Petkov   ide: unify interr...
192
193
194
  			printk(KERN_WARNING PFX "%s: failed to map sense "
  					    "buffer
  ", drive->name);
5c4be5724   Tejun Heo   ide-cd,atapi: use...
195
196
197
198
  		return;
  	}
  
  	sense_rq->rq_disk = rq->rq_disk;
a1df5169f   Borislav Petkov   ide: add helpers ...
199
200
  	sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
  	sense_rq->cmd[4] = cmd_len;
a1df5169f   Borislav Petkov   ide: add helpers ...
201
202
203
204
205
206
207
208
209
  	sense_rq->cmd_type = REQ_TYPE_SENSE;
  	sense_rq->cmd_flags |= REQ_PREEMPT;
  
  	if (drive->media == ide_tape)
  		sense_rq->cmd[13] = REQ_IDETAPE_PC1;
  
  	drive->sense_rq_armed = true;
  }
  EXPORT_SYMBOL_GPL(ide_prep_sense);
5c4be5724   Tejun Heo   ide-cd,atapi: use...
210
  int ide_queue_sense_rq(ide_drive_t *drive, void *special)
a1df5169f   Borislav Petkov   ide: add helpers ...
211
  {
5c4be5724   Tejun Heo   ide-cd,atapi: use...
212
213
  	/* deferred failure from ide_prep_sense() */
  	if (!drive->sense_rq_armed) {
103f7033b   Borislav Petkov   ide: unify interr...
214
215
  		printk(KERN_WARNING PFX "%s: error queuing a sense request
  ",
5c4be5724   Tejun Heo   ide-cd,atapi: use...
216
217
218
  		       drive->name);
  		return -ENOMEM;
  	}
a1df5169f   Borislav Petkov   ide: add helpers ...
219
220
221
222
223
  
  	drive->sense_rq.special = special;
  	drive->sense_rq_armed = false;
  
  	drive->hwif->rq = NULL;
7eaceacca   Jens Axboe   block: remove per...
224
  	elv_add_request(drive->queue, &drive->sense_rq, ELEVATOR_INSERT_FRONT);
5c4be5724   Tejun Heo   ide-cd,atapi: use...
225
  	return 0;
a1df5169f   Borislav Petkov   ide: add helpers ...
226
227
  }
  EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
228
229
  /*
   * Called when an error was detected during the last packet command.
6b544fcc8   Borislav Petkov   ide-atapi: conver...
230
231
   * We queue a request sense packet command at the head of the request
   * queue.
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
232
   */
6b544fcc8   Borislav Petkov   ide-atapi: conver...
233
  void ide_retry_pc(ide_drive_t *drive)
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
234
  {
8f6205cd5   Tejun Heo   ide: dequeue in-f...
235
  	struct request *failed_rq = drive->hwif->rq;
6b544fcc8   Borislav Petkov   ide-atapi: conver...
236
  	struct request *sense_rq = &drive->sense_rq;
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
237
238
239
  	struct ide_atapi_pc *pc = &drive->request_sense_pc;
  
  	(void)ide_read_error(drive);
6b544fcc8   Borislav Petkov   ide-atapi: conver...
240
241
242
243
  
  	/* init pc from sense_rq */
  	ide_init_pc(pc);
  	memcpy(pc->c, sense_rq->cmd, 12);
6b544fcc8   Borislav Petkov   ide-atapi: conver...
244

6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
245
  	if (drive->media == ide_tape)
626542ca2   Borislav Petkov   ide-tape: change ...
246
  		drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC;
6b544fcc8   Borislav Petkov   ide-atapi: conver...
247

8f6205cd5   Tejun Heo   ide: dequeue in-f...
248
249
250
251
252
  	/*
  	 * Push back the failed request and put request sense on top
  	 * of it.  The failed command will be retried after sense data
  	 * is acquired.
  	 */
8f6205cd5   Tejun Heo   ide: dequeue in-f...
253
  	drive->hwif->rq = NULL;
1af185034   Herbert Xu   ide: Must hold qu...
254
  	ide_requeue_and_plug(drive, failed_rq);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
255
  	if (ide_queue_sense_rq(drive, pc)) {
9934c8c04   Tejun Heo   block: implement ...
256
  		blk_start_request(failed_rq);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
257
258
  		ide_complete_rq(drive, -EIO, blk_rq_bytes(failed_rq));
  	}
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
259
260
  }
  EXPORT_SYMBOL_GPL(ide_retry_pc);
4cad085ef   Borislav Petkov   ide-cd: move cdro...
261
262
  int ide_cd_expiry(ide_drive_t *drive)
  {
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
263
  	struct request *rq = drive->hwif->rq;
4cad085ef   Borislav Petkov   ide-cd: move cdro...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
  	unsigned long wait = 0;
  
  	debug_log("%s: rq->cmd[0]: 0x%x
  ", __func__, rq->cmd[0]);
  
  	/*
  	 * Some commands are *slow* and normally take a long time to complete.
  	 * Usually we can use the ATAPI "disconnect" to bypass this, but not all
  	 * commands/drives support that. Let ide_timer_expiry keep polling us
  	 * for these.
  	 */
  	switch (rq->cmd[0]) {
  	case GPCMD_BLANK:
  	case GPCMD_FORMAT_UNIT:
  	case GPCMD_RESERVE_RZONE_TRACK:
  	case GPCMD_CLOSE_TRACK:
  	case GPCMD_FLUSH_CACHE:
  		wait = ATAPI_WAIT_PC;
  		break;
  	default:
  		if (!(rq->cmd_flags & REQ_QUIET))
103f7033b   Borislav Petkov   ide: unify interr...
285
286
  			printk(KERN_INFO PFX "cmd 0x%x timed out
  ",
4cad085ef   Borislav Petkov   ide-cd: move cdro...
287
288
289
290
291
292
293
  					 rq->cmd[0]);
  		wait = 0;
  		break;
  	}
  	return wait;
  }
  EXPORT_SYMBOL_GPL(ide_cd_expiry);
392de1d53   Borislav Petkov   ide-atapi: accomo...
294
295
  int ide_cd_get_xferlen(struct request *rq)
  {
4c4762d10   Christoph Hellwig   block: fix some m...
296
  	switch (rq->cmd_type) {
33659ebba   Christoph Hellwig   block: remove wra...
297
  	case REQ_TYPE_FS:
392de1d53   Borislav Petkov   ide-atapi: accomo...
298
  		return 32768;
33659ebba   Christoph Hellwig   block: remove wra...
299
300
301
  	case REQ_TYPE_SENSE:
  	case REQ_TYPE_BLOCK_PC:
  	case REQ_TYPE_ATA_PC:
34b7d2c95   Tejun Heo   ide: cleanup rq->...
302
  		return blk_rq_bytes(rq);
33659ebba   Christoph Hellwig   block: remove wra...
303
  	default:
392de1d53   Borislav Petkov   ide-atapi: accomo...
304
  		return 0;
33659ebba   Christoph Hellwig   block: remove wra...
305
  	}
392de1d53   Borislav Petkov   ide-atapi: accomo...
306
307
  }
  EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
0d6a9754c   Bartlomiej Zolnierkiewicz   ide: move ide_rea...
308
309
  void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
  {
3153c26b5   Sergei Shtylyov   ide: refactor tf_...
310
  	struct ide_taskfile tf;
0d6a9754c   Bartlomiej Zolnierkiewicz   ide: move ide_rea...
311

3153c26b5   Sergei Shtylyov   ide: refactor tf_...
312
313
  	drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_NSECT |
  				     IDE_VALID_LBAM | IDE_VALID_LBAH);
0d6a9754c   Bartlomiej Zolnierkiewicz   ide: move ide_rea...
314

3153c26b5   Sergei Shtylyov   ide: refactor tf_...
315
316
  	*bcount = (tf.lbah << 8) | tf.lbam;
  	*ireason = tf.nsect & 3;
0d6a9754c   Bartlomiej Zolnierkiewicz   ide: move ide_rea...
317
318
  }
  EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
aa5d2de7b   Bartlomiej Zolnierkiewicz   ide: make ide_pc_...
319
  /*
103f7033b   Borislav Petkov   ide: unify interr...
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
   * Check the contents of the interrupt reason register and attempt to recover if
   * there are problems.
   *
   * Returns:
   * - 0 if everything's ok
   * - 1 if the request has to be terminated.
   */
  int ide_check_ireason(ide_drive_t *drive, struct request *rq, int len,
  		      int ireason, int rw)
  {
  	ide_hwif_t *hwif = drive->hwif;
  
  	debug_log("ireason: 0x%x, rw: 0x%x
  ", ireason, rw);
  
  	if (ireason == (!rw << 1))
  		return 0;
  	else if (ireason == (rw << 1)) {
  		printk(KERN_ERR PFX "%s: %s: wrong transfer direction!
  ",
  				drive->name, __func__);
  
  		if (dev_is_idecd(drive))
  			ide_pad_transfer(drive, rw, len);
  	} else if (!rw && ireason == ATAPI_COD) {
  		if (dev_is_idecd(drive)) {
  			/*
  			 * Some drives (ASUS) seem to tell us that status info
  			 * is available.  Just get it and ignore.
  			 */
  			(void)hwif->tp_ops->read_status(hwif);
  			return 0;
  		}
  	} else {
  		if (ireason & ATAPI_COD)
  			printk(KERN_ERR PFX "%s: CoD != 0 in %s
  ", drive->name,
  					__func__);
  
  		/* drive wants a command packet, or invalid ireason... */
  		printk(KERN_ERR PFX "%s: %s: bad interrupt reason 0x%02x
  ",
  				drive->name, __func__, ireason);
  	}
  
  	if (dev_is_idecd(drive) && rq->cmd_type == REQ_TYPE_ATA_PC)
  		rq->cmd_flags |= REQ_FAILED;
  
  	return 1;
  }
  EXPORT_SYMBOL_GPL(ide_check_ireason);
  
  /*
aa5d2de7b   Bartlomiej Zolnierkiewicz   ide: make ide_pc_...
373
374
375
376
377
   * This is the usual interrupt handler which will be called during a packet
   * command.  We will transfer some of the data (as requested by the drive)
   * and will re-point interrupt handler to us.
   */
  static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
378
  {
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
379
  	struct ide_atapi_pc *pc = drive->pc;
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
380
  	ide_hwif_t *hwif = drive->hwif;
f094d4d83   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
381
  	struct ide_cmd *cmd = &hwif->cmd;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
382
  	struct request *rq = hwif->rq;
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
383
  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
d93bc4521   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
384
  	unsigned int timeout, done;
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
385
  	u16 bcount;
5d655a03b   Borislav Petkov   ide-atapi: remove...
386
  	u8 stat, ireason, dsc = 0;
d93bc4521   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
387
  	u8 write = !!(pc->flags & PC_FLAG_WRITING);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
388
389
390
  
  	debug_log("Enter %s - interrupt handler
  ", __func__);
5d655a03b   Borislav Petkov   ide-atapi: remove...
391
392
  	timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
  					       : WAIT_TAPE_CMD;
844b94685   Bartlomiej Zolnierkiewicz   ide: drop 'timeou...
393

646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
394
  	/* Clear the interrupt */
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
395
  	stat = tp_ops->read_status(hwif);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
396
397
  
  	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
88b4132e1   Bartlomiej Zolnierkiewicz   ide: set/clear dr...
398
  		int rc;
4453011f9   Bartlomiej Zolnierkiewicz   ide: destroy DMA ...
399

88b4132e1   Bartlomiej Zolnierkiewicz   ide: set/clear dr...
400
401
  		drive->waiting_for_dma = 0;
  		rc = hwif->dma_ops->dma_end(drive);
f094d4d83   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
402
  		ide_dma_unmap_sg(drive, cmd);
4453011f9   Bartlomiej Zolnierkiewicz   ide: destroy DMA ...
403
404
  
  		if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) {
5d655a03b   Borislav Petkov   ide-atapi: remove...
405
  			if (drive->media == ide_floppy)
103f7033b   Borislav Petkov   ide: unify interr...
406
407
  				printk(KERN_ERR PFX "%s: DMA %s error
  ",
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
408
409
410
  					drive->name, rq_data_dir(pc->rq)
  						     ? "write" : "read");
  			pc->flags |= PC_FLAG_DMA_ERROR;
6d7003877   Tejun Heo   ide-atapi: kill u...
411
  		} else
077e6dba2   Borislav Petkov   ide-atapi: switch...
412
  			rq->resid_len = 0;
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
413
414
415
416
417
  		debug_log("%s: DMA finished
  ", drive->name);
  	}
  
  	/* No more interrupts */
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
418
  	if ((stat & ATA_DRQ) == 0) {
5b6c942dd   Borislav Petkov   ide-floppy: do no...
419
  		int uptodate, error;
03a2faaea   Bartlomiej Zolnierkiewicz   ide: return reque...
420

646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
421
422
  		debug_log("Packet command completed, %d bytes transferred
  ",
077e6dba2   Borislav Petkov   ide-atapi: switch...
423
  			  blk_rq_bytes(rq));
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
424
425
426
427
  
  		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
  
  		local_irq_enable_in_hardirq();
5d655a03b   Borislav Petkov   ide-atapi: remove...
428
  		if (drive->media == ide_tape &&
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
429
430
  		    (stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE)
  			stat &= ~ATA_ERR;
8fccf8995   Borislav Petkov   ide: use rq->cmd ...
431

3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
432
  		if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) {
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
433
434
435
  			/* Error detected */
  			debug_log("%s: I/O error
  ", drive->name);
5d655a03b   Borislav Petkov   ide-atapi: remove...
436
  			if (drive->media != ide_tape)
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
437
  				pc->rq->errors++;
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
438

8fccf8995   Borislav Petkov   ide: use rq->cmd ...
439
  			if (rq->cmd[0] == REQUEST_SENSE) {
103f7033b   Borislav Petkov   ide: unify interr...
440
441
442
  				printk(KERN_ERR PFX "%s: I/O error in request "
  						"sense command
  ", drive->name);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
443
444
  				return ide_do_reset(drive);
  			}
8fccf8995   Borislav Petkov   ide: use rq->cmd ...
445
446
  			debug_log("[cmd %x]: check condition
  ", rq->cmd[0]);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
447
448
  
  			/* Retry operation */
6b544fcc8   Borislav Petkov   ide-atapi: conver...
449
  			ide_retry_pc(drive);
8fccf8995   Borislav Petkov   ide: use rq->cmd ...
450

646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
451
452
453
  			/* queued, but not started */
  			return ide_stopped;
  		}
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
454
  		pc->error = 0;
b14c72127   Bartlomiej Zolnierkiewicz   ide: drop dsc_han...
455
456
457
  
  		if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0)
  			dsc = 1;
8fccf8995   Borislav Petkov   ide: use rq->cmd ...
458

b3071d190   Tejun Heo   ide-atapi,tape,fl...
459
460
461
462
  		/*
  		 * ->pc_callback() might change rq->data_len for
  		 * residual count, cache total length.
  		 */
21d9c5d22   Tejun Heo   ide-tape: use sta...
463
  		done = blk_rq_bytes(rq);
b3071d190   Tejun Heo   ide-atapi,tape,fl...
464

646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
465
  		/* Command finished - Call the callback function */
03a2faaea   Bartlomiej Zolnierkiewicz   ide: return reque...
466
467
468
469
  		uptodate = drive->pc_callback(drive, dsc);
  
  		if (uptodate == 0)
  			drive->failed_pc = NULL;
4c4762d10   Christoph Hellwig   block: fix some m...
470
  		if (rq->cmd_type == REQ_TYPE_SPECIAL) {
6902a5331   Bartlomiej Zolnierkiewicz   ide: pass error v...
471
  			rq->errors = 0;
5b6c942dd   Borislav Petkov   ide-floppy: do no...
472
  			error = 0;
89f78b326   Bartlomiej Zolnierkiewicz   ide: move rq->err...
473
  		} else {
349d12a1f   Bartlomiej Zolnierkiewicz   ide-floppy: use i...
474

4c4762d10   Christoph Hellwig   block: fix some m...
475
  			if (rq->cmd_type != REQ_TYPE_FS && uptodate <= 0) {
89f78b326   Bartlomiej Zolnierkiewicz   ide: move rq->err...
476
477
478
  				if (rq->errors == 0)
  					rq->errors = -EIO;
  			}
349d12a1f   Bartlomiej Zolnierkiewicz   ide-floppy: use i...
479

5b6c942dd   Borislav Petkov   ide-floppy: do no...
480
  			error = uptodate ? 0 : -EIO;
89f78b326   Bartlomiej Zolnierkiewicz   ide: move rq->err...
481
  		}
8fccf8995   Borislav Petkov   ide: use rq->cmd ...
482

c3a4d78c5   Tejun Heo   block: add rq->re...
483
  		ide_complete_rq(drive, error, blk_rq_bytes(rq));
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
484
485
486
487
488
  		return ide_stopped;
  	}
  
  	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
  		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
103f7033b   Borislav Petkov   ide: unify interr...
489
490
491
  		printk(KERN_ERR PFX "%s: The device wants to issue more "
  				"interrupts in DMA mode
  ", drive->name);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
492
493
494
  		ide_dma_off(drive);
  		return ide_do_reset(drive);
  	}
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
495

1823649b5   Bartlomiej Zolnierkiewicz   ide: add ide_read...
496
497
  	/* Get the number of bytes to transfer on this interrupt. */
  	ide_read_bcount_and_ireason(drive, &bcount, &ireason);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
498

103f7033b   Borislav Petkov   ide: unify interr...
499
  	if (ide_check_ireason(drive, rq, bcount, ireason, write))
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
500
  		return ide_do_reset(drive);
8fccf8995   Borislav Petkov   ide: use rq->cmd ...
501

6d7003877   Tejun Heo   ide-atapi: kill u...
502
503
  	done = min_t(unsigned int, bcount, cmd->nleft);
  	ide_pio_bytes(drive, cmd, write, done);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
504

6d7003877   Tejun Heo   ide-atapi: kill u...
505
  	/* Update transferred byte count */
077e6dba2   Borislav Petkov   ide-atapi: switch...
506
  	rq->resid_len -= done;
d93bc4521   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
507
508
509
510
511
  
  	bcount -= done;
  
  	if (bcount)
  		ide_pad_transfer(drive, write, bcount);
077e6dba2   Borislav Petkov   ide-atapi: switch...
512
513
514
  	debug_log("[cmd %x] transferred %d bytes, padded %d bytes, resid: %u
  ",
  		  rq->cmd[0], done, bcount, rq->resid_len);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
515

646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
516
  	/* And set the interrupt handler again */
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
517
  	ide_set_handler(drive, ide_pc_intr, timeout);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
518
519
  	return ide_started;
  }
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
520

60f85019c   Sergei Shtylyov   ide: replace IDE_...
521
  static void ide_init_packet_cmd(struct ide_cmd *cmd, u8 valid_tf,
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
522
  				u16 bcount, u8 dma)
7a254df00   Bartlomiej Zolnierkiewicz   ide: move ide_pkt...
523
  {
60f85019c   Sergei Shtylyov   ide: replace IDE_...
524
525
526
  	cmd->protocol = dma ? ATAPI_PROT_DMA : ATAPI_PROT_PIO;
  	cmd->valid.out.tf = IDE_VALID_LBAH | IDE_VALID_LBAM |
  			    IDE_VALID_FEATURE | valid_tf;
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
527
  	cmd->tf.command = ATA_CMD_PACKET;
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
528
529
530
  	cmd->tf.feature = dma;		/* Use PIO/DMA */
  	cmd->tf.lbam    = bcount & 0xff;
  	cmd->tf.lbah    = (bcount >> 8) & 0xff;
7a254df00   Bartlomiej Zolnierkiewicz   ide: move ide_pkt...
531
  }
88a72109b   Bartlomiej Zolnierkiewicz   ide: add ide_read...
532
533
  static u8 ide_read_ireason(ide_drive_t *drive)
  {
3153c26b5   Sergei Shtylyov   ide: refactor tf_...
534
  	struct ide_taskfile tf;
88a72109b   Bartlomiej Zolnierkiewicz   ide: add ide_read...
535

3153c26b5   Sergei Shtylyov   ide: refactor tf_...
536
  	drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_NSECT);
88a72109b   Bartlomiej Zolnierkiewicz   ide: add ide_read...
537

3153c26b5   Sergei Shtylyov   ide: refactor tf_...
538
  	return tf.nsect & 3;
88a72109b   Bartlomiej Zolnierkiewicz   ide: add ide_read...
539
  }
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
540
541
  static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
  {
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
542
  	int retries = 100;
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
543
544
  	while (retries-- && ((ireason & ATAPI_COD) == 0 ||
  		(ireason & ATAPI_IO))) {
103f7033b   Borislav Petkov   ide: unify interr...
545
  		printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing "
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
546
547
548
  				"a packet command, retrying
  ", drive->name);
  		udelay(100);
88a72109b   Bartlomiej Zolnierkiewicz   ide: add ide_read...
549
  		ireason = ide_read_ireason(drive);
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
550
  		if (retries == 0) {
103f7033b   Borislav Petkov   ide: unify interr...
551
552
553
  			printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing"
  					" a packet command, ignoring
  ",
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
554
  					drive->name);
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
555
556
  			ireason |= ATAPI_COD;
  			ireason &= ~ATAPI_IO;
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
557
558
559
560
561
  		}
  	}
  
  	return ireason;
  }
baf08f0be   Bartlomiej Zolnierkiewicz   ide: make ide_tra...
562
563
564
565
566
567
568
569
570
571
  static int ide_delayed_transfer_pc(ide_drive_t *drive)
  {
  	/* Send the actual packet */
  	drive->hwif->tp_ops->output_data(drive, NULL, drive->pc->c, 12);
  
  	/* Timeout for the packet command */
  	return WAIT_FLOPPY_CMD;
  }
  
  static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
572
  {
b16aabc93   Borislav Petkov   ide-atapi: start ...
573
  	struct ide_atapi_pc *uninitialized_var(pc);
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
574
  	ide_hwif_t *hwif = drive->hwif;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
575
  	struct request *rq = hwif->rq;
baf08f0be   Bartlomiej Zolnierkiewicz   ide: make ide_tra...
576
577
  	ide_expiry_t *expiry;
  	unsigned int timeout;
8c662852d   Borislav Petkov   ide-atapi: comput...
578
  	int cmd_len;
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
579
580
  	ide_startstop_t startstop;
  	u8 ireason;
3a7d24841   Bartlomiej Zolnierkiewicz   ide: use ATA_* de...
581
  	if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) {
103f7033b   Borislav Petkov   ide: unify interr...
582
  		printk(KERN_ERR PFX "%s: Strange, packet command initiated yet "
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
583
584
585
586
  				"DRQ isn't asserted
  ", drive->name);
  		return startstop;
  	}
5f25843fa   Borislav Petkov   ide-atapi: teach ...
587
588
589
590
  	if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) {
  		if (drive->dma)
  			drive->waiting_for_dma = 1;
  	}
8c662852d   Borislav Petkov   ide-atapi: comput...
591
592
593
594
595
  	if (dev_is_idecd(drive)) {
  		/* ATAPI commands get padded out to 12 bytes minimum */
  		cmd_len = COMMAND_SIZE(rq->cmd[0]);
  		if (cmd_len < ATAPI_MIN_CDB_BYTES)
  			cmd_len = ATAPI_MIN_CDB_BYTES;
8c662852d   Borislav Petkov   ide-atapi: comput...
596

def860d06   Borislav Petkov   ide-atapi: assign...
597
598
  		timeout = rq->timeout;
  		expiry  = ide_cd_expiry;
baf08f0be   Bartlomiej Zolnierkiewicz   ide: make ide_tra...
599
  	} else {
b16aabc93   Borislav Petkov   ide-atapi: start ...
600
  		pc = drive->pc;
def860d06   Borislav Petkov   ide-atapi: assign...
601
602
603
604
  		cmd_len = ATAPI_MIN_CDB_BYTES;
  
  		/*
  		 * If necessary schedule the packet transfer to occur 'timeout'
19af5cdb7   Martin Olsson   trivial: fix typo...
605
  		 * milliseconds later in ide_delayed_transfer_pc() after the
def860d06   Borislav Petkov   ide-atapi: assign...
606
607
608
609
610
611
612
613
614
615
  		 * device says it's ready for a packet.
  		 */
  		if (drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) {
  			timeout = drive->pc_delay;
  			expiry = &ide_delayed_transfer_pc;
  		} else {
  			timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
  							       : WAIT_TAPE_CMD;
  			expiry = NULL;
  		}
06cc2778a   Borislav Petkov   ide-atapi: put th...
616
617
618
619
620
621
  
  		ireason = ide_read_ireason(drive);
  		if (drive->media == ide_tape)
  			ireason = ide_wait_ireason(drive, ireason);
  
  		if ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO)) {
103f7033b   Borislav Petkov   ide: unify interr...
622
623
624
  			printk(KERN_ERR PFX "%s: (IO,CoD) != (0,1) while "
  				"issuing a packet command
  ", drive->name);
06cc2778a   Borislav Petkov   ide-atapi: put th...
625
626
627
  
  			return ide_do_reset(drive);
  		}
baf08f0be   Bartlomiej Zolnierkiewicz   ide: make ide_tra...
628
  	}
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
629
  	hwif->expiry = expiry;
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
630
  	/* Set the interrupt routine */
d6251d448   Borislav Petkov   ide-cd: convert t...
631
632
633
  	ide_set_handler(drive,
  			(dev_is_idecd(drive) ? drive->irq_handler
  					     : ide_pc_intr),
60c0cd02b   Bartlomiej Zolnierkiewicz   ide: set hwif->ex...
634
  			timeout);
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
635

2eba08270   Borislav Petkov   ide-atapi: start ...
636
637
638
  	/* Send the actual packet */
  	if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
  		hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
639
  	/* Begin DMA, if necessary */
b16aabc93   Borislav Petkov   ide-atapi: start ...
640
641
642
643
644
645
646
647
  	if (dev_is_idecd(drive)) {
  		if (drive->dma)
  			hwif->dma_ops->dma_start(drive);
  	} else {
  		if (pc->flags & PC_FLAG_DMA_OK) {
  			pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
  			hwif->dma_ops->dma_start(drive);
  		}
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
648
  	}
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
649
650
  	return ide_started;
  }
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
651

b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
652
  ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
653
  {
d77612ab0   Borislav Petkov   ide-atapi: split ...
654
  	struct ide_atapi_pc *pc;
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
655
  	ide_hwif_t *hwif = drive->hwif;
4cad085ef   Borislav Petkov   ide-cd: move cdro...
656
  	ide_expiry_t *expiry = NULL;
e6830a86c   Bartlomiej Zolnierkiewicz   ide: call ide_bui...
657
  	struct request *rq = hwif->rq;
dfb7e621f   Borislav Petkov   ide-atapi: switch...
658
  	unsigned int timeout, bytes;
392de1d53   Borislav Petkov   ide-atapi: accomo...
659
  	u16 bcount;
60f85019c   Sergei Shtylyov   ide: replace IDE_...
660
  	u8 valid_tf;
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
661
  	u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT);
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
662

ed48554fa   Borislav Petkov   ide-atapi: combin...
663
  	if (dev_is_idecd(drive)) {
60f85019c   Sergei Shtylyov   ide: replace IDE_...
664
  		valid_tf = IDE_VALID_NSECT | IDE_VALID_LBAL;
e6830a86c   Bartlomiej Zolnierkiewicz   ide: call ide_bui...
665
  		bcount = ide_cd_get_xferlen(rq);
4cad085ef   Borislav Petkov   ide-cd: move cdro...
666
  		expiry = ide_cd_expiry;
28ad91db7   Borislav Petkov   ide-atapi: remove...
667
  		timeout = ATAPI_WAIT_PC;
d77612ab0   Borislav Petkov   ide-atapi: split ...
668

5ae5412d9   Bartlomiej Zolnierkiewicz   ide: add ide_dma_...
669
670
  		if (drive->dma)
  			drive->dma = !ide_dma_prepare(drive, cmd);
ed48554fa   Borislav Petkov   ide-atapi: combin...
671
  	} else {
d77612ab0   Borislav Petkov   ide-atapi: split ...
672
  		pc = drive->pc;
60f85019c   Sergei Shtylyov   ide: replace IDE_...
673
  		valid_tf = IDE_VALID_DEVICE;
dfb7e621f   Borislav Petkov   ide-atapi: switch...
674
  		bytes = blk_rq_bytes(rq);
dfb7e621f   Borislav Petkov   ide-atapi: switch...
675
676
677
  		bcount = ((drive->media == ide_tape) ? bytes
  						     : min_t(unsigned int,
  							     bytes, 63 * 1024));
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
678

077e6dba2   Borislav Petkov   ide-atapi: switch...
679
680
  		/* We haven't transferred any data yet */
  		rq->resid_len = bcount;
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
681

d77612ab0   Borislav Petkov   ide-atapi: split ...
682
683
684
685
  		if (pc->flags & PC_FLAG_DMA_ERROR) {
  			pc->flags &= ~PC_FLAG_DMA_ERROR;
  			ide_dma_off(drive);
  		}
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
686

5ae5412d9   Bartlomiej Zolnierkiewicz   ide: add ide_dma_...
687
688
  		if (pc->flags & PC_FLAG_DMA_OK)
  			drive->dma = !ide_dma_prepare(drive, cmd);
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
689

d77612ab0   Borislav Petkov   ide-atapi: split ...
690
691
  		if (!drive->dma)
  			pc->flags &= ~PC_FLAG_DMA_OK;
28ad91db7   Borislav Petkov   ide-atapi: remove...
692
693
694
  
  		timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
  						       : WAIT_TAPE_CMD;
d77612ab0   Borislav Petkov   ide-atapi: split ...
695
  	}
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
696

60f85019c   Sergei Shtylyov   ide: replace IDE_...
697
  	ide_init_packet_cmd(cmd, valid_tf, bcount, drive->dma);
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
698
699
  
  	(void)do_rw_taskfile(drive, cmd);
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
700

35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
701
  	if (drq_int) {
5f25843fa   Borislav Petkov   ide-atapi: teach ...
702
703
  		if (drive->dma)
  			drive->waiting_for_dma = 0;
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
704
  		hwif->expiry = expiry;
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
705
  	}
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
706
707
708
709
  
  	ide_execute_command(drive, cmd, ide_transfer_pc, timeout);
  
  	return drq_int ? ide_started : ide_transfer_pc(drive);
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
710
711
  }
  EXPORT_SYMBOL_GPL(ide_issue_pc);