diff options
Diffstat (limited to 'drivers/ide/ide-floppy.c')
-rw-r--r-- | drivers/ide/ide-floppy.c | 128 |
1 files changed, 3 insertions, 125 deletions
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 70aef97fb8bc..0f3602a5efb0 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -388,132 +388,10 @@ static void idefloppy_retry_pc(ide_drive_t *drive) | |||
388 | static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) | 388 | static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) |
389 | { | 389 | { |
390 | idefloppy_floppy_t *floppy = drive->driver_data; | 390 | idefloppy_floppy_t *floppy = drive->driver_data; |
391 | ide_hwif_t *hwif = drive->hwif; | ||
392 | struct ide_atapi_pc *pc = floppy->pc; | ||
393 | struct request *rq = pc->rq; | ||
394 | xfer_func_t *xferfunc; | ||
395 | unsigned int temp; | ||
396 | int dma_error = 0; | ||
397 | u16 bcount; | ||
398 | u8 stat, ireason; | ||
399 | |||
400 | debug_log("Enter %s - interrupt handler\n", __func__); | ||
401 | |||
402 | /* Clear the interrupt */ | ||
403 | stat = ide_read_status(drive); | ||
404 | |||
405 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
406 | dma_error = hwif->dma_ops->dma_end(drive); | ||
407 | if (dma_error) { | ||
408 | printk(KERN_ERR "%s: DMA %s error\n", drive->name, | ||
409 | rq_data_dir(rq) ? "write" : "read"); | ||
410 | pc->flags |= PC_FLAG_DMA_ERROR; | ||
411 | } else { | ||
412 | pc->xferred = pc->req_xfer; | ||
413 | idefloppy_update_buffers(drive, pc); | ||
414 | } | ||
415 | debug_log("%s: DMA finished\n", drive->name); | ||
416 | } | ||
417 | |||
418 | /* No more interrupts */ | ||
419 | if ((stat & DRQ_STAT) == 0) { | ||
420 | debug_log("Packet command completed, %d bytes transferred\n", | ||
421 | pc->xferred); | ||
422 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
423 | |||
424 | local_irq_enable_in_hardirq(); | ||
425 | |||
426 | if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { | ||
427 | /* Error detected */ | ||
428 | debug_log("%s: I/O error\n", drive->name); | ||
429 | rq->errors++; | ||
430 | if (pc->c[0] == GPCMD_REQUEST_SENSE) { | ||
431 | printk(KERN_ERR "%s: I/O error in request sense" | ||
432 | " command\n", drive->name); | ||
433 | return ide_do_reset(drive); | ||
434 | } | ||
435 | |||
436 | debug_log("[cmd %x]: check condition\n", pc->c[0]); | ||
437 | |||
438 | /* Retry operation */ | ||
439 | idefloppy_retry_pc(drive); | ||
440 | /* queued, but not started */ | ||
441 | return ide_stopped; | ||
442 | } | ||
443 | pc->error = 0; | ||
444 | /* Command finished - Call the callback function */ | ||
445 | pc->callback(drive); | ||
446 | return ide_stopped; | ||
447 | } | ||
448 | |||
449 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
450 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
451 | printk(KERN_ERR "%s: The device wants to issue more interrupts " | ||
452 | "in DMA mode\n", drive->name); | ||
453 | ide_dma_off(drive); | ||
454 | return ide_do_reset(drive); | ||
455 | } | ||
456 | |||
457 | /* Get the number of bytes to transfer */ | ||
458 | bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | | ||
459 | hwif->INB(hwif->io_ports.lbam_addr); | ||
460 | /* on this interrupt */ | ||
461 | ireason = hwif->INB(hwif->io_ports.nsect_addr); | ||
462 | |||
463 | if (ireason & CD) { | ||
464 | printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); | ||
465 | return ide_do_reset(drive); | ||
466 | } | ||
467 | if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { | ||
468 | /* Hopefully, we will never get here */ | ||
469 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | ||
470 | "to %s!\n", drive->name, | ||
471 | (ireason & IO) ? "Write" : "Read", | ||
472 | (ireason & IO) ? "Read" : "Write"); | ||
473 | return ide_do_reset(drive); | ||
474 | } | ||
475 | if (!(pc->flags & PC_FLAG_WRITING)) { | ||
476 | /* Reading - Check that we have enough space */ | ||
477 | temp = pc->xferred + bcount; | ||
478 | if (temp > pc->req_xfer) { | ||
479 | if (temp > pc->buf_size) { | ||
480 | printk(KERN_ERR "%s: The device wants to send " | ||
481 | "us more data than expected - " | ||
482 | "discarding data\n", | ||
483 | drive->name); | ||
484 | ide_pad_transfer(drive, 0, bcount); | ||
485 | |||
486 | ide_set_handler(drive, | ||
487 | &idefloppy_pc_intr, | ||
488 | IDEFLOPPY_WAIT_CMD, | ||
489 | NULL); | ||
490 | return ide_started; | ||
491 | } | ||
492 | debug_log("The device wants to send us more data than " | ||
493 | "expected - allowing transfer\n"); | ||
494 | } | ||
495 | } | ||
496 | if (pc->flags & PC_FLAG_WRITING) | ||
497 | xferfunc = hwif->output_data; | ||
498 | else | ||
499 | xferfunc = hwif->input_data; | ||
500 | |||
501 | if (pc->buf) | ||
502 | xferfunc(drive, NULL, pc->cur_pos, bcount); | ||
503 | else | ||
504 | ide_floppy_io_buffers(drive, pc, bcount, | ||
505 | !!(pc->flags & PC_FLAG_WRITING)); | ||
506 | |||
507 | /* Update the current position */ | ||
508 | pc->xferred += bcount; | ||
509 | pc->cur_pos += bcount; | ||
510 | |||
511 | debug_log("[cmd %x] transferred %d bytes on that intr.\n", | ||
512 | pc->c[0], bcount); | ||
513 | 391 | ||
514 | /* And set the interrupt handler again */ | 392 | return ide_pc_intr(drive, floppy->pc, idefloppy_pc_intr, |
515 | ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); | 393 | IDEFLOPPY_WAIT_CMD, NULL, idefloppy_update_buffers, |
516 | return ide_started; | 394 | idefloppy_retry_pc, NULL, ide_floppy_io_buffers); |
517 | } | 395 | } |
518 | 396 | ||
519 | /* | 397 | /* |