Blame view
drivers/ide/ide-atapi.c
17.7 KB
594c16d8d ide: add ide_tran... |
1 2 3 4 5 |
/* * ATAPI support. */ #include <linux/kernel.h> |
4cad085ef ide-cd: move cdro... |
6 |
#include <linux/cdrom.h> |
594c16d8d ide: add ide_tran... |
7 |
#include <linux/delay.h> |
38789fda2 ide/ata: Add expo... |
8 |
#include <linux/export.h> |
594c16d8d ide: add ide_tran... |
9 |
#include <linux/ide.h> |
479edf065 ide: drivers/ide/... |
10 |
#include <linux/scatterlist.h> |
5a0e3ad6a include cleanup: ... |
11 |
#include <linux/gfp.h> |
479edf065 ide: drivers/ide/... |
12 |
|
646c0cb6c ide: add ide_pc_i... |
13 |
#include <scsi/scsi.h> |
103f7033b ide: unify interr... |
14 15 |
#define DRV_NAME "ide-atapi" #define PFX DRV_NAME ": " |
646c0cb6c 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 ide-atapi: comput... |
22 |
#define ATAPI_MIN_CDB_BYTES 12 |
991cb26a6 ide-atapi: add a ... |
23 24 |
static inline int dev_is_idecd(ide_drive_t *drive) { |
5317464dc ide: remove the l... |
25 |
return drive->media == ide_cdrom || drive->media == ide_optical; |
991cb26a6 ide-atapi: add a ... |
26 |
} |
51509eec3 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 ide: add ide_init... |
78 79 80 |
void ide_init_pc(struct ide_atapi_pc *pc) { memset(pc, 0, sizeof(*pc)); |
7bf7420a3 ide: add ide_init... |
81 82 |
} EXPORT_SYMBOL_GPL(ide_init_pc); |
7645c1514 ide: add ide_queu... |
83 |
/* |
2ac07d920 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 ide-atapi: add a ... |
88 |
struct ide_atapi_pc *pc, void *buf, unsigned int bufflen) |
2ac07d920 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 ide-atapi: don't ... |
95 |
rq->special = (char *)pc; |
3eb76c1cc ide-floppy: do no... |
96 |
|
b13345f39 ide-atapi: add a ... |
97 98 |
if (buf && bufflen) { error = blk_rq_map_kern(drive->queue, rq, buf, bufflen, |
5c4be5724 ide-cd,atapi: use... |
99 100 101 |
GFP_NOIO); if (error) goto put_req; |
3eb76c1cc ide-floppy: do no... |
102 |
} |
2ac07d920 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 ide-cd,atapi: use... |
107 |
put_req: |
2ac07d920 ide: add ide_queu... |
108 |
blk_put_request(rq); |
2ac07d920 ide: add ide_queu... |
109 110 111 |
return error; } EXPORT_SYMBOL_GPL(ide_queue_pc_tail); |
de699ad59 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 ide-atapi: add a ... |
118 |
return ide_queue_pc_tail(drive, disk, &pc, NULL, 0); |
de699ad59 ide: add ide_do_t... |
119 120 |
} EXPORT_SYMBOL_GPL(ide_do_test_unit_ready); |
0c8a6c7ae 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 ide-atapi: add a ... |
131 |
return ide_queue_pc_tail(drive, disk, &pc, NULL, 0); |
0c8a6c7ae ide: add ide_do_s... |
132 133 |
} EXPORT_SYMBOL_GPL(ide_do_start_stop); |
0578042db 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 ide: remove IDE_A... |
137 |
if ((drive->dev_flags & IDE_DFLAG_DOORLOCKING) == 0) |
0578042db 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 ide-atapi: add a ... |
143 |
return ide_queue_pc_tail(drive, disk, &pc, NULL, 0); |
0578042db ide: add ide_set_... |
144 145 |
} EXPORT_SYMBOL_GPL(ide_set_media_lock); |
6b0da28b2 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 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 ide-cd,atapi: use... |
164 |
int err; |
a1df5169f ide: add helpers ... |
165 |
|
a1df5169f 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 block: remove wra... |
181 |
if (rq->cmd_type == REQ_TYPE_SENSE || drive->sense_rq_armed) |
a1df5169f ide: add helpers ... |
182 183 184 185 186 |
return; memset(sense, 0, sizeof(*sense)); blk_rq_init(rq->q, sense_rq); |
a1df5169f ide: add helpers ... |
187 |
|
5c4be5724 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 ide: unify interr... |
192 193 194 |
printk(KERN_WARNING PFX "%s: failed to map sense " "buffer ", drive->name); |
5c4be5724 ide-cd,atapi: use... |
195 196 197 198 |
return; } sense_rq->rq_disk = rq->rq_disk; |
a1df5169f ide: add helpers ... |
199 200 |
sense_rq->cmd[0] = GPCMD_REQUEST_SENSE; sense_rq->cmd[4] = cmd_len; |
a1df5169f 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 ide-cd,atapi: use... |
210 |
int ide_queue_sense_rq(ide_drive_t *drive, void *special) |
a1df5169f ide: add helpers ... |
211 |
{ |
5c4be5724 ide-cd,atapi: use... |
212 213 |
/* deferred failure from ide_prep_sense() */ if (!drive->sense_rq_armed) { |
103f7033b ide: unify interr... |
214 215 |
printk(KERN_WARNING PFX "%s: error queuing a sense request ", |
5c4be5724 ide-cd,atapi: use... |
216 217 218 |
drive->name); return -ENOMEM; } |
a1df5169f ide: add helpers ... |
219 220 221 222 223 |
drive->sense_rq.special = special; drive->sense_rq_armed = false; drive->hwif->rq = NULL; |
7eaceacca block: remove per... |
224 |
elv_add_request(drive->queue, &drive->sense_rq, ELEVATOR_INSERT_FRONT); |
5c4be5724 ide-cd,atapi: use... |
225 |
return 0; |
a1df5169f ide: add helpers ... |
226 227 |
} EXPORT_SYMBOL_GPL(ide_queue_sense_rq); |
6b0da28b2 ide: add ide_retr... |
228 229 |
/* * Called when an error was detected during the last packet command. |
6b544fcc8 ide-atapi: conver... |
230 231 |
* We queue a request sense packet command at the head of the request * queue. |
6b0da28b2 ide: add ide_retr... |
232 |
*/ |
6b544fcc8 ide-atapi: conver... |
233 |
void ide_retry_pc(ide_drive_t *drive) |
6b0da28b2 ide: add ide_retr... |
234 |
{ |
8f6205cd5 ide: dequeue in-f... |
235 |
struct request *failed_rq = drive->hwif->rq; |
6b544fcc8 ide-atapi: conver... |
236 |
struct request *sense_rq = &drive->sense_rq; |
6b0da28b2 ide: add ide_retr... |
237 238 239 |
struct ide_atapi_pc *pc = &drive->request_sense_pc; (void)ide_read_error(drive); |
6b544fcc8 ide-atapi: conver... |
240 241 242 243 |
/* init pc from sense_rq */ ide_init_pc(pc); memcpy(pc->c, sense_rq->cmd, 12); |
6b544fcc8 ide-atapi: conver... |
244 |
|
6b0da28b2 ide: add ide_retr... |
245 |
if (drive->media == ide_tape) |
626542ca2 ide-tape: change ... |
246 |
drive->atapi_flags |= IDE_AFLAG_IGNORE_DSC; |
6b544fcc8 ide-atapi: conver... |
247 |
|
8f6205cd5 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 ide: dequeue in-f... |
253 |
drive->hwif->rq = NULL; |
1af185034 ide: Must hold qu... |
254 |
ide_requeue_and_plug(drive, failed_rq); |
8f6205cd5 ide: dequeue in-f... |
255 |
if (ide_queue_sense_rq(drive, pc)) { |
9934c8c04 block: implement ... |
256 |
blk_start_request(failed_rq); |
8f6205cd5 ide: dequeue in-f... |
257 258 |
ide_complete_rq(drive, -EIO, blk_rq_bytes(failed_rq)); } |
6b0da28b2 ide: add ide_retr... |
259 260 |
} EXPORT_SYMBOL_GPL(ide_retry_pc); |
4cad085ef ide-cd: move cdro... |
261 262 |
int ide_cd_expiry(ide_drive_t *drive) { |
b65fac32c ide: merge ide_hw... |
263 |
struct request *rq = drive->hwif->rq; |
4cad085ef 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 ide: unify interr... |
285 286 |
printk(KERN_INFO PFX "cmd 0x%x timed out ", |
4cad085ef 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 ide-atapi: accomo... |
294 295 |
int ide_cd_get_xferlen(struct request *rq) { |
4c4762d10 block: fix some m... |
296 |
switch (rq->cmd_type) { |
33659ebba block: remove wra... |
297 |
case REQ_TYPE_FS: |
392de1d53 ide-atapi: accomo... |
298 |
return 32768; |
33659ebba block: remove wra... |
299 300 301 |
case REQ_TYPE_SENSE: case REQ_TYPE_BLOCK_PC: case REQ_TYPE_ATA_PC: |
34b7d2c95 ide: cleanup rq->... |
302 |
return blk_rq_bytes(rq); |
33659ebba block: remove wra... |
303 |
default: |
392de1d53 ide-atapi: accomo... |
304 |
return 0; |
33659ebba block: remove wra... |
305 |
} |
392de1d53 ide-atapi: accomo... |
306 307 |
} EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); |
0d6a9754c ide: move ide_rea... |
308 309 |
void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) { |
3153c26b5 ide: refactor tf_... |
310 |
struct ide_taskfile tf; |
0d6a9754c ide: move ide_rea... |
311 |
|
3153c26b5 ide: refactor tf_... |
312 313 |
drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_NSECT | IDE_VALID_LBAM | IDE_VALID_LBAH); |
0d6a9754c ide: move ide_rea... |
314 |
|
3153c26b5 ide: refactor tf_... |
315 316 |
*bcount = (tf.lbah << 8) | tf.lbam; *ireason = tf.nsect & 3; |
0d6a9754c ide: move ide_rea... |
317 318 |
} EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); |
aa5d2de7b ide: make ide_pc_... |
319 |
/* |
103f7033b 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 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 ide: add ide_pc_i... |
378 |
{ |
2b9efba48 ide: add pointer ... |
379 |
struct ide_atapi_pc *pc = drive->pc; |
646c0cb6c ide: add ide_pc_i... |
380 |
ide_hwif_t *hwif = drive->hwif; |
f094d4d83 ide: sanitize ide... |
381 |
struct ide_cmd *cmd = &hwif->cmd; |
b65fac32c ide: merge ide_hw... |
382 |
struct request *rq = hwif->rq; |
374e042c3 ide: add struct i... |
383 |
const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
d93bc4521 ide-{floppy,tape}... |
384 |
unsigned int timeout, done; |
646c0cb6c ide: add ide_pc_i... |
385 |
u16 bcount; |
5d655a03b ide-atapi: remove... |
386 |
u8 stat, ireason, dsc = 0; |
d93bc4521 ide-{floppy,tape}... |
387 |
u8 write = !!(pc->flags & PC_FLAG_WRITING); |
646c0cb6c ide: add ide_pc_i... |
388 389 390 |
debug_log("Enter %s - interrupt handler ", __func__); |
5d655a03b ide-atapi: remove... |
391 392 |
timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD : WAIT_TAPE_CMD; |
844b94685 ide: drop 'timeou... |
393 |
|
646c0cb6c ide: add ide_pc_i... |
394 |
/* Clear the interrupt */ |
374e042c3 ide: add struct i... |
395 |
stat = tp_ops->read_status(hwif); |
646c0cb6c ide: add ide_pc_i... |
396 397 |
if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { |
88b4132e1 ide: set/clear dr... |
398 |
int rc; |
4453011f9 ide: destroy DMA ... |
399 |
|
88b4132e1 ide: set/clear dr... |
400 401 |
drive->waiting_for_dma = 0; rc = hwif->dma_ops->dma_end(drive); |
f094d4d83 ide: sanitize ide... |
402 |
ide_dma_unmap_sg(drive, cmd); |
4453011f9 ide: destroy DMA ... |
403 404 |
if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) { |
5d655a03b ide-atapi: remove... |
405 |
if (drive->media == ide_floppy) |
103f7033b ide: unify interr... |
406 407 |
printk(KERN_ERR PFX "%s: DMA %s error ", |
646c0cb6c ide: add ide_pc_i... |
408 409 410 |
drive->name, rq_data_dir(pc->rq) ? "write" : "read"); pc->flags |= PC_FLAG_DMA_ERROR; |
6d7003877 ide-atapi: kill u... |
411 |
} else |
077e6dba2 ide-atapi: switch... |
412 |
rq->resid_len = 0; |
646c0cb6c ide: add ide_pc_i... |
413 414 415 416 417 |
debug_log("%s: DMA finished ", drive->name); } /* No more interrupts */ |
3a7d24841 ide: use ATA_* de... |
418 |
if ((stat & ATA_DRQ) == 0) { |
5b6c942dd ide-floppy: do no... |
419 |
int uptodate, error; |
03a2faaea ide: return reque... |
420 |
|
646c0cb6c ide: add ide_pc_i... |
421 422 |
debug_log("Packet command completed, %d bytes transferred ", |
077e6dba2 ide-atapi: switch... |
423 |
blk_rq_bytes(rq)); |
646c0cb6c ide: add ide_pc_i... |
424 425 426 427 |
pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; local_irq_enable_in_hardirq(); |
5d655a03b ide-atapi: remove... |
428 |
if (drive->media == ide_tape && |
3a7d24841 ide: use ATA_* de... |
429 430 |
(stat & ATA_ERR) && rq->cmd[0] == REQUEST_SENSE) stat &= ~ATA_ERR; |
8fccf8995 ide: use rq->cmd ... |
431 |
|
3a7d24841 ide: use ATA_* de... |
432 |
if ((stat & ATA_ERR) || (pc->flags & PC_FLAG_DMA_ERROR)) { |
646c0cb6c ide: add ide_pc_i... |
433 434 435 |
/* Error detected */ debug_log("%s: I/O error ", drive->name); |
5d655a03b ide-atapi: remove... |
436 |
if (drive->media != ide_tape) |
646c0cb6c ide: add ide_pc_i... |
437 |
pc->rq->errors++; |
646c0cb6c ide: add ide_pc_i... |
438 |
|
8fccf8995 ide: use rq->cmd ... |
439 |
if (rq->cmd[0] == REQUEST_SENSE) { |
103f7033b ide: unify interr... |
440 441 442 |
printk(KERN_ERR PFX "%s: I/O error in request " "sense command ", drive->name); |
646c0cb6c ide: add ide_pc_i... |
443 444 |
return ide_do_reset(drive); } |
8fccf8995 ide: use rq->cmd ... |
445 446 |
debug_log("[cmd %x]: check condition ", rq->cmd[0]); |
646c0cb6c ide: add ide_pc_i... |
447 448 |
/* Retry operation */ |
6b544fcc8 ide-atapi: conver... |
449 |
ide_retry_pc(drive); |
8fccf8995 ide: use rq->cmd ... |
450 |
|
646c0cb6c ide: add ide_pc_i... |
451 452 453 |
/* queued, but not started */ return ide_stopped; } |
646c0cb6c ide: add ide_pc_i... |
454 |
pc->error = 0; |
b14c72127 ide: drop dsc_han... |
455 456 457 |
if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) dsc = 1; |
8fccf8995 ide: use rq->cmd ... |
458 |
|
b3071d190 ide-atapi,tape,fl... |
459 460 461 462 |
/* * ->pc_callback() might change rq->data_len for * residual count, cache total length. */ |
21d9c5d22 ide-tape: use sta... |
463 |
done = blk_rq_bytes(rq); |
b3071d190 ide-atapi,tape,fl... |
464 |
|
646c0cb6c ide: add ide_pc_i... |
465 |
/* Command finished - Call the callback function */ |
03a2faaea ide: return reque... |
466 467 468 469 |
uptodate = drive->pc_callback(drive, dsc); if (uptodate == 0) drive->failed_pc = NULL; |
4c4762d10 block: fix some m... |
470 |
if (rq->cmd_type == REQ_TYPE_SPECIAL) { |
6902a5331 ide: pass error v... |
471 |
rq->errors = 0; |
5b6c942dd ide-floppy: do no... |
472 |
error = 0; |
89f78b326 ide: move rq->err... |
473 |
} else { |
349d12a1f ide-floppy: use i... |
474 |
|
4c4762d10 block: fix some m... |
475 |
if (rq->cmd_type != REQ_TYPE_FS && uptodate <= 0) { |
89f78b326 ide: move rq->err... |
476 477 478 |
if (rq->errors == 0) rq->errors = -EIO; } |
349d12a1f ide-floppy: use i... |
479 |
|
5b6c942dd ide-floppy: do no... |
480 |
error = uptodate ? 0 : -EIO; |
89f78b326 ide: move rq->err... |
481 |
} |
8fccf8995 ide: use rq->cmd ... |
482 |
|
c3a4d78c5 block: add rq->re... |
483 |
ide_complete_rq(drive, error, blk_rq_bytes(rq)); |
646c0cb6c 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 ide: unify interr... |
489 490 491 |
printk(KERN_ERR PFX "%s: The device wants to issue more " "interrupts in DMA mode ", drive->name); |
646c0cb6c ide: add ide_pc_i... |
492 493 494 |
ide_dma_off(drive); return ide_do_reset(drive); } |
646c0cb6c ide: add ide_pc_i... |
495 |
|
1823649b5 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 ide: add ide_pc_i... |
498 |
|
103f7033b ide: unify interr... |
499 |
if (ide_check_ireason(drive, rq, bcount, ireason, write)) |
646c0cb6c ide: add ide_pc_i... |
500 |
return ide_do_reset(drive); |
8fccf8995 ide: use rq->cmd ... |
501 |
|
6d7003877 ide-atapi: kill u... |
502 503 |
done = min_t(unsigned int, bcount, cmd->nleft); ide_pio_bytes(drive, cmd, write, done); |
646c0cb6c ide: add ide_pc_i... |
504 |
|
6d7003877 ide-atapi: kill u... |
505 |
/* Update transferred byte count */ |
077e6dba2 ide-atapi: switch... |
506 |
rq->resid_len -= done; |
d93bc4521 ide-{floppy,tape}... |
507 508 509 510 511 |
bcount -= done; if (bcount) ide_pad_transfer(drive, write, bcount); |
077e6dba2 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 ide: add ide_pc_i... |
515 |
|
646c0cb6c ide: add ide_pc_i... |
516 |
/* And set the interrupt handler again */ |
60c0cd02b ide: set hwif->ex... |
517 |
ide_set_handler(drive, ide_pc_intr, timeout); |
646c0cb6c ide: add ide_pc_i... |
518 519 |
return ide_started; } |
594c16d8d ide: add ide_tran... |
520 |
|
60f85019c ide: replace IDE_... |
521 |
static void ide_init_packet_cmd(struct ide_cmd *cmd, u8 valid_tf, |
b788ee9c6 ide: use do_rw_ta... |
522 |
u16 bcount, u8 dma) |
7a254df00 ide: move ide_pkt... |
523 |
{ |
60f85019c 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 ide: remove ide_e... |
527 |
cmd->tf.command = ATA_CMD_PACKET; |
b788ee9c6 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 ide: move ide_pkt... |
531 |
} |
88a72109b ide: add ide_read... |
532 533 |
static u8 ide_read_ireason(ide_drive_t *drive) { |
3153c26b5 ide: refactor tf_... |
534 |
struct ide_taskfile tf; |
88a72109b ide: add ide_read... |
535 |
|
3153c26b5 ide: refactor tf_... |
536 |
drive->hwif->tp_ops->tf_read(drive, &tf, IDE_VALID_NSECT); |
88a72109b ide: add ide_read... |
537 |
|
3153c26b5 ide: refactor tf_... |
538 |
return tf.nsect & 3; |
88a72109b ide: add ide_read... |
539 |
} |
594c16d8d ide: add ide_tran... |
540 541 |
static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) { |
594c16d8d ide: add ide_tran... |
542 |
int retries = 100; |
3a7d24841 ide: use ATA_* de... |
543 544 |
while (retries-- && ((ireason & ATAPI_COD) == 0 || (ireason & ATAPI_IO))) { |
103f7033b ide: unify interr... |
545 |
printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing " |
594c16d8d ide: add ide_tran... |
546 547 548 |
"a packet command, retrying ", drive->name); udelay(100); |
88a72109b ide: add ide_read... |
549 |
ireason = ide_read_ireason(drive); |
594c16d8d ide: add ide_tran... |
550 |
if (retries == 0) { |
103f7033b ide: unify interr... |
551 552 553 |
printk(KERN_ERR PFX "%s: (IO,CoD != (0,1) while issuing" " a packet command, ignoring ", |
594c16d8d ide: add ide_tran... |
554 |
drive->name); |
3a7d24841 ide: use ATA_* de... |
555 556 |
ireason |= ATAPI_COD; ireason &= ~ATAPI_IO; |
594c16d8d ide: add ide_tran... |
557 558 559 560 561 |
} } return ireason; } |
baf08f0be 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 ide: add ide_tran... |
572 |
{ |
b16aabc93 ide-atapi: start ... |
573 |
struct ide_atapi_pc *uninitialized_var(pc); |
594c16d8d ide: add ide_tran... |
574 |
ide_hwif_t *hwif = drive->hwif; |
b65fac32c ide: merge ide_hw... |
575 |
struct request *rq = hwif->rq; |
baf08f0be ide: make ide_tra... |
576 577 |
ide_expiry_t *expiry; unsigned int timeout; |
8c662852d ide-atapi: comput... |
578 |
int cmd_len; |
594c16d8d ide: add ide_tran... |
579 580 |
ide_startstop_t startstop; u8 ireason; |
3a7d24841 ide: use ATA_* de... |
581 |
if (ide_wait_stat(&startstop, drive, ATA_DRQ, ATA_BUSY, WAIT_READY)) { |
103f7033b ide: unify interr... |
582 |
printk(KERN_ERR PFX "%s: Strange, packet command initiated yet " |
594c16d8d ide: add ide_tran... |
583 584 585 586 |
"DRQ isn't asserted ", drive->name); return startstop; } |
5f25843fa ide-atapi: teach ... |
587 588 589 590 |
if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { if (drive->dma) drive->waiting_for_dma = 1; } |
8c662852d 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 ide-atapi: comput... |
596 |
|
def860d06 ide-atapi: assign... |
597 598 |
timeout = rq->timeout; expiry = ide_cd_expiry; |
baf08f0be ide: make ide_tra... |
599 |
} else { |
b16aabc93 ide-atapi: start ... |
600 |
pc = drive->pc; |
def860d06 ide-atapi: assign... |
601 602 603 604 |
cmd_len = ATAPI_MIN_CDB_BYTES; /* * If necessary schedule the packet transfer to occur 'timeout' |
19af5cdb7 trivial: fix typo... |
605 |
* milliseconds later in ide_delayed_transfer_pc() after the |
def860d06 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 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 ide: unify interr... |
622 623 624 |
printk(KERN_ERR PFX "%s: (IO,CoD) != (0,1) while " "issuing a packet command ", drive->name); |
06cc2778a ide-atapi: put th... |
625 626 627 |
return ide_do_reset(drive); } |
baf08f0be ide: make ide_tra... |
628 |
} |
60c0cd02b ide: set hwif->ex... |
629 |
hwif->expiry = expiry; |
594c16d8d ide: add ide_tran... |
630 |
/* Set the interrupt routine */ |
d6251d448 ide-cd: convert t... |
631 632 633 |
ide_set_handler(drive, (dev_is_idecd(drive) ? drive->irq_handler : ide_pc_intr), |
60c0cd02b ide: set hwif->ex... |
634 |
timeout); |
594c16d8d ide: add ide_tran... |
635 |
|
2eba08270 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 ide: add ide_tran... |
639 |
/* Begin DMA, if necessary */ |
b16aabc93 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 ide: add ide_tran... |
648 |
} |
594c16d8d ide: add ide_tran... |
649 650 |
return ide_started; } |
6bf1641ca ide: add ide_issu... |
651 |
|
b788ee9c6 ide: use do_rw_ta... |
652 |
ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) |
6bf1641ca ide: add ide_issu... |
653 |
{ |
d77612ab0 ide-atapi: split ... |
654 |
struct ide_atapi_pc *pc; |
6bf1641ca ide: add ide_issu... |
655 |
ide_hwif_t *hwif = drive->hwif; |
4cad085ef ide-cd: move cdro... |
656 |
ide_expiry_t *expiry = NULL; |
e6830a86c ide: call ide_bui... |
657 |
struct request *rq = hwif->rq; |
dfb7e621f ide-atapi: switch... |
658 |
unsigned int timeout, bytes; |
392de1d53 ide-atapi: accomo... |
659 |
u16 bcount; |
60f85019c ide: replace IDE_... |
660 |
u8 valid_tf; |
35b5d0be3 ide: remove ide_e... |
661 |
u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT); |
6bf1641ca ide: add ide_issu... |
662 |
|
ed48554fa ide-atapi: combin... |
663 |
if (dev_is_idecd(drive)) { |
60f85019c ide: replace IDE_... |
664 |
valid_tf = IDE_VALID_NSECT | IDE_VALID_LBAL; |
e6830a86c ide: call ide_bui... |
665 |
bcount = ide_cd_get_xferlen(rq); |
4cad085ef ide-cd: move cdro... |
666 |
expiry = ide_cd_expiry; |
28ad91db7 ide-atapi: remove... |
667 |
timeout = ATAPI_WAIT_PC; |
d77612ab0 ide-atapi: split ... |
668 |
|
5ae5412d9 ide: add ide_dma_... |
669 670 |
if (drive->dma) drive->dma = !ide_dma_prepare(drive, cmd); |
ed48554fa ide-atapi: combin... |
671 |
} else { |
d77612ab0 ide-atapi: split ... |
672 |
pc = drive->pc; |
60f85019c ide: replace IDE_... |
673 |
valid_tf = IDE_VALID_DEVICE; |
dfb7e621f ide-atapi: switch... |
674 |
bytes = blk_rq_bytes(rq); |
dfb7e621f ide-atapi: switch... |
675 676 677 |
bcount = ((drive->media == ide_tape) ? bytes : min_t(unsigned int, bytes, 63 * 1024)); |
6bf1641ca ide: add ide_issu... |
678 |
|
077e6dba2 ide-atapi: switch... |
679 680 |
/* We haven't transferred any data yet */ rq->resid_len = bcount; |
6bf1641ca ide: add ide_issu... |
681 |
|
d77612ab0 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 ide: add ide_issu... |
686 |
|
5ae5412d9 ide: add ide_dma_... |
687 688 |
if (pc->flags & PC_FLAG_DMA_OK) drive->dma = !ide_dma_prepare(drive, cmd); |
6bf1641ca ide: add ide_issu... |
689 |
|
d77612ab0 ide-atapi: split ... |
690 691 |
if (!drive->dma) pc->flags &= ~PC_FLAG_DMA_OK; |
28ad91db7 ide-atapi: remove... |
692 693 694 |
timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD : WAIT_TAPE_CMD; |
d77612ab0 ide-atapi: split ... |
695 |
} |
6bf1641ca ide: add ide_issu... |
696 |
|
60f85019c ide: replace IDE_... |
697 |
ide_init_packet_cmd(cmd, valid_tf, bcount, drive->dma); |
b788ee9c6 ide: use do_rw_ta... |
698 699 |
(void)do_rw_taskfile(drive, cmd); |
6bf1641ca ide: add ide_issu... |
700 |
|
35b5d0be3 ide: remove ide_e... |
701 |
if (drq_int) { |
5f25843fa ide-atapi: teach ... |
702 703 |
if (drive->dma) drive->waiting_for_dma = 0; |
22117d6ea ide: add ->dma_ti... |
704 |
hwif->expiry = expiry; |
6bf1641ca ide: add ide_issu... |
705 |
} |
35b5d0be3 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 ide: add ide_issu... |
710 711 |
} EXPORT_SYMBOL_GPL(ide_issue_pc); |