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
  {
  	struct request *rq;
  	int error;
71baba4b9   Mel Gorman   mm, page_alloc: r...
92
  	rq = blk_get_request(drive->queue, READ, __GFP_RECLAIM);
4f8c9510b   Christoph Hellwig   block: rename REQ...
93
  	rq->cmd_type = REQ_TYPE_DRV_PRIV;
c267cc1c4   Tejun Heo   ide-atapi: don't ...
94
  	rq->special = (char *)pc;
3eb76c1cc   Borislav Petkov   ide-floppy: do no...
95

b13345f39   Borislav Petkov   ide-atapi: add a ...
96
97
  	if (buf && bufflen) {
  		error = blk_rq_map_kern(drive->queue, rq, buf, bufflen,
5c4be5724   Tejun Heo   ide-cd,atapi: use...
98
99
100
  					GFP_NOIO);
  		if (error)
  			goto put_req;
3eb76c1cc   Borislav Petkov   ide-floppy: do no...
101
  	}
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
102
103
104
105
  	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...
106
  put_req:
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
107
  	blk_put_request(rq);
2ac07d920   Bartlomiej Zolnierkiewicz   ide: add ide_queu...
108
109
110
  	return error;
  }
  EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
de699ad59   Bartlomiej Zolnierkiewicz   ide: add ide_do_t...
111
112
113
114
115
116
  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 ...
117
  	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
de699ad59   Bartlomiej Zolnierkiewicz   ide: add ide_do_t...
118
119
  }
  EXPORT_SYMBOL_GPL(ide_do_test_unit_ready);
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
120
121
122
123
124
125
126
127
128
129
  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 ...
130
  	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
0c8a6c7ae   Bartlomiej Zolnierkiewicz   ide: add ide_do_s...
131
132
  }
  EXPORT_SYMBOL_GPL(ide_do_start_stop);
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
133
134
135
  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...
136
  	if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0)
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
137
138
139
140
141
  		return 0;
  
  	ide_init_pc(&pc);
  	pc.c[0] = ALLOW_MEDIUM_REMOVAL;
  	pc.c[4] = on;
b13345f39   Borislav Petkov   ide-atapi: add a ...
142
  	return ide_queue_pc_tail(drive, disk, &pc, NULL, 0);
0578042db   Bartlomiej Zolnierkiewicz   ide: add ide_set_...
143
144
  }
  EXPORT_SYMBOL_GPL(ide_set_media_lock);
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
145
146
147
148
149
150
151
152
153
154
155
156
157
  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 ...
158
159
160
161
162
  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...
163
  	int err;
a1df5169f   Borislav Petkov   ide: add helpers ...
164

a1df5169f   Borislav Petkov   ide: add helpers ...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  	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));
b0b93b48a   Christoph Hellwig   block: move REQ_T...
180
  	if (rq->cmd_type == REQ_TYPE_ATA_SENSE || drive->sense_rq_armed)
a1df5169f   Borislav Petkov   ide: add helpers ...
181
182
183
184
185
  		return;
  
  	memset(sense, 0, sizeof(*sense));
  
  	blk_rq_init(rq->q, sense_rq);
a1df5169f   Borislav Petkov   ide: add helpers ...
186

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

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

8f6205cd5   Tejun Heo   ide: dequeue in-f...
247
248
249
250
251
  	/*
  	 * 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...
252
  	drive->hwif->rq = NULL;
1af185034   Herbert Xu   ide: Must hold qu...
253
  	ide_requeue_and_plug(drive, failed_rq);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
254
  	if (ide_queue_sense_rq(drive, pc)) {
9934c8c04   Tejun Heo   block: implement ...
255
  		blk_start_request(failed_rq);
8f6205cd5   Tejun Heo   ide: dequeue in-f...
256
257
  		ide_complete_rq(drive, -EIO, blk_rq_bytes(failed_rq));
  	}
6b0da28b2   Bartlomiej Zolnierkiewicz   ide: add ide_retr...
258
259
  }
  EXPORT_SYMBOL_GPL(ide_retry_pc);
4cad085ef   Borislav Petkov   ide-cd: move cdro...
260
261
  int ide_cd_expiry(ide_drive_t *drive)
  {
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
262
  	struct request *rq = drive->hwif->rq;
4cad085ef   Borislav Petkov   ide-cd: move cdro...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  	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...
284
285
  			printk(KERN_INFO PFX "cmd 0x%x timed out
  ",
4cad085ef   Borislav Petkov   ide-cd: move cdro...
286
287
288
289
290
291
292
  					 rq->cmd[0]);
  		wait = 0;
  		break;
  	}
  	return wait;
  }
  EXPORT_SYMBOL_GPL(ide_cd_expiry);
392de1d53   Borislav Petkov   ide-atapi: accomo...
293
294
  int ide_cd_get_xferlen(struct request *rq)
  {
4c4762d10   Christoph Hellwig   block: fix some m...
295
  	switch (rq->cmd_type) {
33659ebba   Christoph Hellwig   block: remove wra...
296
  	case REQ_TYPE_FS:
392de1d53   Borislav Petkov   ide-atapi: accomo...
297
  		return 32768;
b0b93b48a   Christoph Hellwig   block: move REQ_T...
298
  	case REQ_TYPE_ATA_SENSE:
33659ebba   Christoph Hellwig   block: remove wra...
299
300
  	case REQ_TYPE_BLOCK_PC:
  	case REQ_TYPE_ATA_PC:
34b7d2c95   Tejun Heo   ide: cleanup rq->...
301
  		return blk_rq_bytes(rq);
33659ebba   Christoph Hellwig   block: remove wra...
302
  	default:
392de1d53   Borislav Petkov   ide-atapi: accomo...
303
  		return 0;
33659ebba   Christoph Hellwig   block: remove wra...
304
  	}
392de1d53   Borislav Petkov   ide-atapi: accomo...
305
306
  }
  EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
0d6a9754c   Bartlomiej Zolnierkiewicz   ide: move ide_rea...
307
308
  void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
  {
3153c26b5   Sergei Shtylyov   ide: refactor tf_...
309
  	struct ide_taskfile tf;
0d6a9754c   Bartlomiej Zolnierkiewicz   ide: move ide_rea...
310

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

3153c26b5   Sergei Shtylyov   ide: refactor tf_...
314
315
  	*bcount = (tf.lbah << 8) | tf.lbam;
  	*ireason = tf.nsect & 3;
0d6a9754c   Bartlomiej Zolnierkiewicz   ide: move ide_rea...
316
317
  }
  EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
aa5d2de7b   Bartlomiej Zolnierkiewicz   ide: make ide_pc_...
318
  /*
103f7033b   Borislav Petkov   ide: unify interr...
319
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
   * 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_...
372
373
374
375
376
   * 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...
377
  {
2b9efba48   Bartlomiej Zolnierkiewicz   ide: add pointer ...
378
  	struct ide_atapi_pc *pc = drive->pc;
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
379
  	ide_hwif_t *hwif = drive->hwif;
f094d4d83   Bartlomiej Zolnierkiewicz   ide: sanitize ide...
380
  	struct ide_cmd *cmd = &hwif->cmd;
b65fac32c   Bartlomiej Zolnierkiewicz   ide: merge ide_hw...
381
  	struct request *rq = hwif->rq;
374e042c3   Bartlomiej Zolnierkiewicz   ide: add struct i...
382
  	const struct ide_tp_ops *tp_ops = hwif->tp_ops;
d93bc4521   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
383
  	unsigned int timeout, done;
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
384
  	u16 bcount;
5d655a03b   Borislav Petkov   ide-atapi: remove...
385
  	u8 stat, ireason, dsc = 0;
d93bc4521   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
386
  	u8 write = !!(pc->flags & PC_FLAG_WRITING);
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
387
388
389
  
  	debug_log("Enter %s - interrupt handler
  ", __func__);
5d655a03b   Borislav Petkov   ide-atapi: remove...
390
391
  	timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
  					       : WAIT_TAPE_CMD;
844b94685   Bartlomiej Zolnierkiewicz   ide: drop 'timeou...
392

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

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

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

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

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

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

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

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

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

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

c3a4d78c5   Tejun Heo   block: add rq->re...
482
  		ide_complete_rq(drive, error, blk_rq_bytes(rq));
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
483
484
485
486
487
  		return ide_stopped;
  	}
  
  	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
  		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
103f7033b   Borislav Petkov   ide: unify interr...
488
489
490
  		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...
491
492
493
  		ide_dma_off(drive);
  		return ide_do_reset(drive);
  	}
646c0cb6c   Bartlomiej Zolnierkiewicz   ide: add ide_pc_i...
494

1823649b5   Bartlomiej Zolnierkiewicz   ide: add ide_read...
495
496
  	/* 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...
497

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

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

6d7003877   Tejun Heo   ide-atapi: kill u...
504
  	/* Update transferred byte count */
077e6dba2   Borislav Petkov   ide-atapi: switch...
505
  	rq->resid_len -= done;
d93bc4521   Bartlomiej Zolnierkiewicz   ide-{floppy,tape}...
506
507
508
509
510
  
  	bcount -= done;
  
  	if (bcount)
  		ide_pad_transfer(drive, write, bcount);
077e6dba2   Borislav Petkov   ide-atapi: switch...
511
512
513
  	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...
514

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

60f85019c   Sergei Shtylyov   ide: replace IDE_...
520
  static void ide_init_packet_cmd(struct ide_cmd *cmd, u8 valid_tf,
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
521
  				u16 bcount, u8 dma)
7a254df00   Bartlomiej Zolnierkiewicz   ide: move ide_pkt...
522
  {
60f85019c   Sergei Shtylyov   ide: replace IDE_...
523
524
525
  	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...
526
  	cmd->tf.command = ATA_CMD_PACKET;
b788ee9c6   Bartlomiej Zolnierkiewicz   ide: use do_rw_ta...
527
528
529
  	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...
530
  }
88a72109b   Bartlomiej Zolnierkiewicz   ide: add ide_read...
531
532
  static u8 ide_read_ireason(ide_drive_t *drive)
  {
3153c26b5   Sergei Shtylyov   ide: refactor tf_...
533
  	struct ide_taskfile tf;
88a72109b   Bartlomiej Zolnierkiewicz   ide: add ide_read...
534

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

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

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

2eba08270   Borislav Petkov   ide-atapi: start ...
635
636
637
  	/* 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...
638
  	/* Begin DMA, if necessary */
b16aabc93   Borislav Petkov   ide-atapi: start ...
639
640
641
642
643
644
645
646
  	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...
647
  	}
594c16d8d   Bartlomiej Zolnierkiewicz   ide: add ide_tran...
648
649
  	return ide_started;
  }
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
650

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

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

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

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

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

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

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

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

35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
700
  	if (drq_int) {
5f25843fa   Borislav Petkov   ide-atapi: teach ...
701
702
  		if (drive->dma)
  			drive->waiting_for_dma = 0;
22117d6ea   Bartlomiej Zolnierkiewicz   ide: add ->dma_ti...
703
  		hwif->expiry = expiry;
6bf1641ca   Bartlomiej Zolnierkiewicz   ide: add ide_issu...
704
  	}
35b5d0be3   Bartlomiej Zolnierkiewicz   ide: remove ide_e...
705
706
707
708
  
  	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...
709
710
  }
  EXPORT_SYMBOL_GPL(ide_issue_pc);