diff options
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r-- | drivers/ide/ide-cd.c | 289 |
1 files changed, 138 insertions, 151 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 35729a47f797..925eb9e245d1 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -265,35 +265,61 @@ static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq) | |||
265 | cdrom_analyze_sense_data(drive, NULL, sense); | 265 | cdrom_analyze_sense_data(drive, NULL, sense); |
266 | } | 266 | } |
267 | 267 | ||
268 | |||
268 | /* | 269 | /* |
270 | * Allow the drive 5 seconds to recover; some devices will return NOT_READY | ||
271 | * while flushing data from cache. | ||
272 | * | ||
273 | * returns: 0 failed (write timeout expired) | ||
274 | * 1 success | ||
275 | */ | ||
276 | static int ide_cd_breathe(ide_drive_t *drive, struct request *rq) | ||
277 | { | ||
278 | |||
279 | struct cdrom_info *info = drive->driver_data; | ||
280 | |||
281 | if (!rq->errors) | ||
282 | info->write_timeout = jiffies + ATAPI_WAIT_WRITE_BUSY; | ||
283 | |||
284 | rq->errors = 1; | ||
285 | |||
286 | if (time_after(jiffies, info->write_timeout)) | ||
287 | return 0; | ||
288 | else { | ||
289 | struct request_queue *q = drive->queue; | ||
290 | unsigned long flags; | ||
291 | |||
292 | /* | ||
293 | * take a breather relying on the unplug timer to kick us again | ||
294 | */ | ||
295 | |||
296 | spin_lock_irqsave(q->queue_lock, flags); | ||
297 | blk_plug_device(q); | ||
298 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
299 | |||
300 | return 1; | ||
301 | } | ||
302 | } | ||
303 | |||
304 | /** | ||
269 | * Returns: | 305 | * Returns: |
270 | * 0: if the request should be continued. | 306 | * 0: if the request should be continued. |
271 | * 1: if the request will be going through error recovery. | 307 | * 1: if the request will be going through error recovery. |
272 | * 2: if the request should be ended. | 308 | * 2: if the request should be ended. |
273 | */ | 309 | */ |
274 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | 310 | static int cdrom_decode_status(ide_drive_t *drive, u8 stat) |
275 | { | 311 | { |
276 | ide_hwif_t *hwif = drive->hwif; | 312 | ide_hwif_t *hwif = drive->hwif; |
277 | struct request *rq = hwif->rq; | 313 | struct request *rq = hwif->rq; |
278 | int stat, err, sense_key; | 314 | int err, sense_key, do_end_request = 0; |
279 | |||
280 | /* check for errors */ | ||
281 | stat = hwif->tp_ops->read_status(hwif); | ||
282 | |||
283 | if (stat_ret) | ||
284 | *stat_ret = stat; | ||
285 | |||
286 | if (OK_STAT(stat, good_stat, BAD_R_STAT)) | ||
287 | return 0; | ||
288 | 315 | ||
289 | /* get the IDE error register */ | 316 | /* get the IDE error register */ |
290 | err = ide_read_error(drive); | 317 | err = ide_read_error(drive); |
291 | sense_key = err >> 4; | 318 | sense_key = err >> 4; |
292 | 319 | ||
293 | ide_debug_log(IDE_DBG_RQ, "stat: 0x%x, good_stat: 0x%x, cmd[0]: 0x%x, " | 320 | ide_debug_log(IDE_DBG_RQ, "cmd: 0x%x, rq->cmd_type: 0x%x, err: 0x%x, " |
294 | "rq->cmd_type: 0x%x, err: 0x%x", | 321 | "stat 0x%x", |
295 | stat, good_stat, rq->cmd[0], rq->cmd_type, | 322 | rq->cmd[0], rq->cmd_type, err, stat); |
296 | err); | ||
297 | 323 | ||
298 | if (blk_sense_request(rq)) { | 324 | if (blk_sense_request(rq)) { |
299 | /* | 325 | /* |
@@ -303,151 +329,108 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | |||
303 | */ | 329 | */ |
304 | rq->cmd_flags |= REQ_FAILED; | 330 | rq->cmd_flags |= REQ_FAILED; |
305 | return 2; | 331 | return 2; |
306 | } else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) { | 332 | } |
307 | /* All other functions, except for READ. */ | ||
308 | 333 | ||
309 | /* | 334 | /* if we have an error, pass CHECK_CONDITION as the SCSI status byte */ |
310 | * if we have an error, pass back CHECK_CONDITION as the | 335 | if (blk_pc_request(rq) && !rq->errors) |
311 | * scsi status byte | 336 | rq->errors = SAM_STAT_CHECK_CONDITION; |
312 | */ | ||
313 | if (blk_pc_request(rq) && !rq->errors) | ||
314 | rq->errors = SAM_STAT_CHECK_CONDITION; | ||
315 | 337 | ||
316 | /* check for tray open */ | 338 | if (blk_noretry_request(rq)) |
317 | if (sense_key == NOT_READY) { | 339 | do_end_request = 1; |
318 | cdrom_saw_media_change(drive); | 340 | |
319 | } else if (sense_key == UNIT_ATTENTION) { | 341 | switch (sense_key) { |
320 | /* check for media change */ | 342 | case NOT_READY: |
343 | if (blk_fs_request(rq) && rq_data_dir(rq) == WRITE) { | ||
344 | if (ide_cd_breathe(drive, rq)) | ||
345 | return 1; | ||
346 | } else { | ||
321 | cdrom_saw_media_change(drive); | 347 | cdrom_saw_media_change(drive); |
322 | return 0; | 348 | |
323 | } else if (sense_key == ILLEGAL_REQUEST && | 349 | if (blk_fs_request(rq) && !blk_rq_quiet(rq)) |
324 | rq->cmd[0] == GPCMD_START_STOP_UNIT) { | 350 | printk(KERN_ERR PFX "%s: tray open\n", |
325 | /* | 351 | drive->name); |
326 | * Don't print error message for this condition-- | ||
327 | * SFF8090i indicates that 5/24/00 is the correct | ||
328 | * response to a request to close the tray if the | ||
329 | * drive doesn't have that capability. | ||
330 | * cdrom_log_sense() knows this! | ||
331 | */ | ||
332 | } else if (!(rq->cmd_flags & REQ_QUIET)) { | ||
333 | /* otherwise, print an error */ | ||
334 | ide_dump_status(drive, "packet command error", stat); | ||
335 | } | 352 | } |
353 | do_end_request = 1; | ||
354 | break; | ||
355 | case UNIT_ATTENTION: | ||
356 | cdrom_saw_media_change(drive); | ||
336 | 357 | ||
337 | rq->cmd_flags |= REQ_FAILED; | 358 | if (blk_fs_request(rq) == 0) |
359 | return 0; | ||
338 | 360 | ||
339 | /* | 361 | /* |
340 | * instead of playing games with moving completions around, | 362 | * Arrange to retry the request but be sure to give up if we've |
341 | * remove failed request completely and end it when the | 363 | * retried too many times. |
342 | * request sense has completed | ||
343 | */ | 364 | */ |
344 | goto end_request; | 365 | if (++rq->errors > ERROR_MAX) |
345 | |||
346 | } else if (blk_fs_request(rq)) { | ||
347 | int do_end_request = 0; | ||
348 | |||
349 | /* handle errors from READ and WRITE requests */ | ||
350 | |||
351 | if (blk_noretry_request(rq)) | ||
352 | do_end_request = 1; | 366 | do_end_request = 1; |
353 | 367 | break; | |
354 | if (sense_key == NOT_READY) { | 368 | case ILLEGAL_REQUEST: |
355 | /* tray open */ | 369 | /* |
356 | if (rq_data_dir(rq) == READ) { | 370 | * Don't print error message for this condition -- SFF8090i |
357 | cdrom_saw_media_change(drive); | 371 | * indicates that 5/24/00 is the correct response to a request |
358 | 372 | * to close the tray if the drive doesn't have that capability. | |
359 | /* fail the request */ | 373 | * |
360 | printk(KERN_ERR PFX "%s: tray open\n", | 374 | * cdrom_log_sense() knows this! |
361 | drive->name); | 375 | */ |
362 | do_end_request = 1; | 376 | if (rq->cmd[0] == GPCMD_START_STOP_UNIT) |
363 | } else { | 377 | break; |
364 | struct cdrom_info *info = drive->driver_data; | 378 | /* fall-through */ |
365 | 379 | case DATA_PROTECT: | |
366 | /* | 380 | /* |
367 | * Allow the drive 5 seconds to recover, some | 381 | * No point in retrying after an illegal request or data |
368 | * devices will return this error while flushing | 382 | * protect error. |
369 | * data from cache. | 383 | */ |
370 | */ | 384 | if (!blk_rq_quiet(rq)) |
371 | if (!rq->errors) | ||
372 | info->write_timeout = jiffies + | ||
373 | ATAPI_WAIT_WRITE_BUSY; | ||
374 | rq->errors = 1; | ||
375 | if (time_after(jiffies, info->write_timeout)) | ||
376 | do_end_request = 1; | ||
377 | else { | ||
378 | struct request_queue *q = drive->queue; | ||
379 | unsigned long flags; | ||
380 | |||
381 | /* | ||
382 | * take a breather relying on the unplug | ||
383 | * timer to kick us again | ||
384 | */ | ||
385 | spin_lock_irqsave(q->queue_lock, flags); | ||
386 | blk_plug_device(q); | ||
387 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
388 | |||
389 | return 1; | ||
390 | } | ||
391 | } | ||
392 | } else if (sense_key == UNIT_ATTENTION) { | ||
393 | /* media change */ | ||
394 | cdrom_saw_media_change(drive); | ||
395 | |||
396 | /* | ||
397 | * Arrange to retry the request but be sure to give up | ||
398 | * if we've retried too many times. | ||
399 | */ | ||
400 | if (++rq->errors > ERROR_MAX) | ||
401 | do_end_request = 1; | ||
402 | } else if (sense_key == ILLEGAL_REQUEST || | ||
403 | sense_key == DATA_PROTECT) { | ||
404 | /* | ||
405 | * No point in retrying after an illegal request or data | ||
406 | * protect error. | ||
407 | */ | ||
408 | ide_dump_status(drive, "command error", stat); | 385 | ide_dump_status(drive, "command error", stat); |
409 | do_end_request = 1; | 386 | do_end_request = 1; |
410 | } else if (sense_key == MEDIUM_ERROR) { | 387 | break; |
411 | /* | 388 | case MEDIUM_ERROR: |
412 | * No point in re-trying a zillion times on a bad | 389 | /* |
413 | * sector. If we got here the error is not correctable. | 390 | * No point in re-trying a zillion times on a bad sector. |
414 | */ | 391 | * If we got here the error is not correctable. |
415 | ide_dump_status(drive, "media error (bad sector)", | 392 | */ |
393 | if (!blk_rq_quiet(rq)) | ||
394 | ide_dump_status(drive, "media error " | ||
395 | "(bad sector)", stat); | ||
396 | do_end_request = 1; | ||
397 | break; | ||
398 | case BLANK_CHECK: | ||
399 | /* disk appears blank? */ | ||
400 | if (!blk_rq_quiet(rq)) | ||
401 | ide_dump_status(drive, "media error (blank)", | ||
416 | stat); | 402 | stat); |
417 | do_end_request = 1; | 403 | do_end_request = 1; |
418 | } else if (sense_key == BLANK_CHECK) { | 404 | break; |
419 | /* disk appears blank ?? */ | 405 | default: |
420 | ide_dump_status(drive, "media error (blank)", stat); | 406 | if (blk_fs_request(rq) == 0) |
421 | do_end_request = 1; | 407 | break; |
422 | } else if ((err & ~ATA_ABORTED) != 0) { | 408 | if (err & ~ATA_ABORTED) { |
423 | /* go to the default handler for other errors */ | 409 | /* go to the default handler for other errors */ |
424 | ide_error(drive, "cdrom_decode_status", stat); | 410 | ide_error(drive, "cdrom_decode_status", stat); |
425 | return 1; | 411 | return 1; |
426 | } else if ((++rq->errors > ERROR_MAX)) { | 412 | } else if (++rq->errors > ERROR_MAX) |
427 | /* we've racked up too many retries, abort */ | 413 | /* we've racked up too many retries, abort */ |
428 | do_end_request = 1; | 414 | do_end_request = 1; |
429 | } | 415 | } |
430 | |||
431 | /* | ||
432 | * End a request through request sense analysis when we have | ||
433 | * sense data. We need this in order to perform end of media | ||
434 | * processing. | ||
435 | */ | ||
436 | if (do_end_request) | ||
437 | goto end_request; | ||
438 | 416 | ||
439 | /* | 417 | if (blk_fs_request(rq) == 0) { |
440 | * If we got a CHECK_CONDITION status, queue | 418 | rq->cmd_flags |= REQ_FAILED; |
441 | * a request sense command. | 419 | do_end_request = 1; |
442 | */ | ||
443 | if (stat & ATA_ERR) | ||
444 | cdrom_queue_request_sense(drive, NULL, NULL); | ||
445 | return 1; | ||
446 | } else { | ||
447 | blk_dump_rq_flags(rq, PFX "bad rq"); | ||
448 | return 2; | ||
449 | } | 420 | } |
450 | 421 | ||
422 | /* | ||
423 | * End a request through request sense analysis when we have sense data. | ||
424 | * We need this in order to perform end of media processing. | ||
425 | */ | ||
426 | if (do_end_request) | ||
427 | goto end_request; | ||
428 | |||
429 | /* if we got a CHECK_CONDITION status, queue a request sense command */ | ||
430 | if (stat & ATA_ERR) | ||
431 | cdrom_queue_request_sense(drive, NULL, NULL); | ||
432 | return 1; | ||
433 | |||
451 | end_request: | 434 | end_request: |
452 | if (stat & ATA_ERR) { | 435 | if (stat & ATA_ERR) { |
453 | struct request_queue *q = drive->queue; | 436 | struct request_queue *q = drive->queue; |
@@ -624,15 +607,14 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
624 | struct ide_cmd *cmd = &hwif->cmd; | 607 | struct ide_cmd *cmd = &hwif->cmd; |
625 | struct request *rq = hwif->rq; | 608 | struct request *rq = hwif->rq; |
626 | ide_expiry_t *expiry = NULL; | 609 | ide_expiry_t *expiry = NULL; |
627 | int dma_error = 0, dma, stat, thislen, uptodate = 0; | 610 | int dma_error = 0, dma, thislen, uptodate = 0; |
628 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors; | 611 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0, nsectors; |
629 | int sense = blk_sense_request(rq); | 612 | int sense = blk_sense_request(rq); |
630 | unsigned int timeout; | 613 | unsigned int timeout; |
631 | u16 len; | 614 | u16 len; |
632 | u8 ireason; | 615 | u8 ireason, stat; |
633 | 616 | ||
634 | ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x", | 617 | ide_debug_log(IDE_DBG_PC, "cmd: 0x%x, write: 0x%x", rq->cmd[0], write); |
635 | rq->cmd[0], write); | ||
636 | 618 | ||
637 | /* check for errors */ | 619 | /* check for errors */ |
638 | dma = drive->dma; | 620 | dma = drive->dma; |
@@ -648,11 +630,16 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
648 | } | 630 | } |
649 | } | 631 | } |
650 | 632 | ||
651 | rc = cdrom_decode_status(drive, 0, &stat); | 633 | /* check status */ |
652 | if (rc) { | 634 | stat = hwif->tp_ops->read_status(hwif); |
653 | if (rc == 2) | 635 | |
654 | goto out_end; | 636 | if (!OK_STAT(stat, 0, BAD_R_STAT)) { |
655 | return ide_stopped; | 637 | rc = cdrom_decode_status(drive, stat); |
638 | if (rc) { | ||
639 | if (rc == 2) | ||
640 | goto out_end; | ||
641 | return ide_stopped; | ||
642 | } | ||
656 | } | 643 | } |
657 | 644 | ||
658 | /* using dma, transfer is complete now */ | 645 | /* using dma, transfer is complete now */ |