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