diff options
Diffstat (limited to 'drivers/ide/ide-tape.c')
-rw-r--r-- | drivers/ide/ide-tape.c | 132 |
1 files changed, 6 insertions, 126 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 10f2d3336286..0afa109ec99a 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -56,8 +56,6 @@ enum { | |||
56 | DBG_PROCS = (1 << 3), | 56 | DBG_PROCS = (1 << 3), |
57 | /* buffer alloc info (pc_stack & rq_stack) */ | 57 | /* buffer alloc info (pc_stack & rq_stack) */ |
58 | DBG_PCRQ_STACK = (1 << 4), | 58 | DBG_PCRQ_STACK = (1 << 4), |
59 | /* IRQ handler (always log debug info if debugging is on) */ | ||
60 | DBG_PC_INTR = (1 << 5), | ||
61 | }; | 59 | }; |
62 | 60 | ||
63 | /* define to see debug info */ | 61 | /* define to see debug info */ |
@@ -66,7 +64,7 @@ enum { | |||
66 | #if IDETAPE_DEBUG_LOG | 64 | #if IDETAPE_DEBUG_LOG |
67 | #define debug_log(lvl, fmt, args...) \ | 65 | #define debug_log(lvl, fmt, args...) \ |
68 | { \ | 66 | { \ |
69 | if ((lvl & DBG_PC_INTR) || (tape->debug_mask & lvl)) \ | 67 | if (tape->debug_mask & lvl) \ |
70 | printk(KERN_INFO "ide-tape: " fmt, ## args); \ | 68 | printk(KERN_INFO "ide-tape: " fmt, ## args); \ |
71 | } | 69 | } |
72 | #else | 70 | #else |
@@ -441,7 +439,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
441 | } | 439 | } |
442 | } | 440 | } |
443 | 441 | ||
444 | static void idetape_update_buffers(struct ide_atapi_pc *pc) | 442 | static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) |
445 | { | 443 | { |
446 | struct idetape_bh *bh = pc->bh; | 444 | struct idetape_bh *bh = pc->bh; |
447 | int count; | 445 | int count; |
@@ -526,7 +524,7 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) | |||
526 | pc->xferred = pc->req_xfer - | 524 | pc->xferred = pc->req_xfer - |
527 | tape->blk_size * | 525 | tape->blk_size * |
528 | get_unaligned_be32(&sense[3]); | 526 | get_unaligned_be32(&sense[3]); |
529 | idetape_update_buffers(pc); | 527 | idetape_update_buffers(drive, pc); |
530 | } | 528 | } |
531 | 529 | ||
532 | /* | 530 | /* |
@@ -800,129 +798,11 @@ static void ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
800 | */ | 798 | */ |
801 | static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) | 799 | static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) |
802 | { | 800 | { |
803 | ide_hwif_t *hwif = drive->hwif; | ||
804 | idetape_tape_t *tape = drive->driver_data; | 801 | idetape_tape_t *tape = drive->driver_data; |
805 | struct ide_atapi_pc *pc = tape->pc; | ||
806 | xfer_func_t *xferfunc; | ||
807 | unsigned int temp; | ||
808 | u16 bcount; | ||
809 | u8 stat, ireason; | ||
810 | |||
811 | debug_log(DBG_PC_INTR, "Enter %s - interrupt handler\n", __func__); | ||
812 | |||
813 | /* Clear the interrupt */ | ||
814 | stat = ide_read_status(drive); | ||
815 | |||
816 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
817 | if (hwif->dma_ops->dma_end(drive) || (stat & ERR_STAT)) { | ||
818 | pc->flags |= PC_FLAG_DMA_ERROR; | ||
819 | } else { | ||
820 | pc->xferred = pc->req_xfer; | ||
821 | idetape_update_buffers(pc); | ||
822 | } | ||
823 | debug_log(DBG_PC_INTR, "%s: DMA finished\n", drive->name); | ||
824 | } | ||
825 | |||
826 | /* No more interrupts */ | ||
827 | if ((stat & DRQ_STAT) == 0) { | ||
828 | debug_log(DBG_PC_INTR, "Packet command completed, %d bytes" | ||
829 | " transferred\n", pc->xferred); | ||
830 | |||
831 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
832 | local_irq_enable_in_hardirq(); | ||
833 | |||
834 | if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE) | ||
835 | stat &= ~ERR_STAT; | ||
836 | if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { | ||
837 | /* Error detected */ | ||
838 | debug_log(DBG_PC_INTR, "%s: I/O error\n", drive->name); | ||
839 | |||
840 | if (pc->c[0] == REQUEST_SENSE) { | ||
841 | printk(KERN_ERR "%s: I/O error in request sense" | ||
842 | " command\n", drive->name); | ||
843 | return ide_do_reset(drive); | ||
844 | } | ||
845 | debug_log(DBG_PC_INTR, "[cmd %x]: check condition\n", | ||
846 | pc->c[0]); | ||
847 | |||
848 | /* Retry operation */ | ||
849 | idetape_retry_pc(drive); | ||
850 | return ide_stopped; | ||
851 | } | ||
852 | pc->error = 0; | ||
853 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && | ||
854 | (stat & SEEK_STAT) == 0) { | ||
855 | ide_tape_handle_dsc(drive); | ||
856 | return ide_stopped; | ||
857 | } | ||
858 | /* Command finished - Call the callback function */ | ||
859 | pc->callback(drive); | ||
860 | return ide_stopped; | ||
861 | } | ||
862 | |||
863 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
864 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
865 | printk(KERN_ERR "%s: The device wants to issue more interrupts " | ||
866 | "in DMA mode\n", drive->name); | ||
867 | ide_dma_off(drive); | ||
868 | return ide_do_reset(drive); | ||
869 | } | ||
870 | /* Get the number of bytes to transfer on this interrupt. */ | ||
871 | bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | | ||
872 | hwif->INB(hwif->io_ports.lbam_addr); | ||
873 | |||
874 | ireason = hwif->INB(hwif->io_ports.nsect_addr); | ||
875 | |||
876 | if (ireason & CD) { | ||
877 | printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); | ||
878 | return ide_do_reset(drive); | ||
879 | } | ||
880 | if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { | ||
881 | /* Hopefully, we will never get here */ | ||
882 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | ||
883 | "to %s!\n", drive->name, | ||
884 | (ireason & IO) ? "Write" : "Read", | ||
885 | (ireason & IO) ? "Read" : "Write"); | ||
886 | return ide_do_reset(drive); | ||
887 | } | ||
888 | if (!(pc->flags & PC_FLAG_WRITING)) { | ||
889 | /* Reading - Check that we have enough space */ | ||
890 | temp = pc->xferred + bcount; | ||
891 | if (temp > pc->req_xfer) { | ||
892 | if (temp > pc->buf_size) { | ||
893 | printk(KERN_ERR "%s: The device wants to send " | ||
894 | "us more data than expected - " | ||
895 | "discarding data\n", | ||
896 | drive->name); | ||
897 | ide_pad_transfer(drive, 0, bcount); | ||
898 | ide_set_handler(drive, &idetape_pc_intr, | ||
899 | IDETAPE_WAIT_CMD, NULL); | ||
900 | return ide_started; | ||
901 | } | ||
902 | debug_log(DBG_PC_INTR, "The device wants to send us more " | ||
903 | "data than expected - allowing transfer\n"); | ||
904 | } | ||
905 | xferfunc = hwif->input_data; | ||
906 | } else { | ||
907 | xferfunc = hwif->output_data; | ||
908 | } | ||
909 | |||
910 | if (pc->bh) | ||
911 | ide_tape_io_buffers(drive, pc, bcount, | ||
912 | !!(pc->flags & PC_FLAG_WRITING)); | ||
913 | else | ||
914 | xferfunc(drive, NULL, pc->cur_pos, bcount); | ||
915 | |||
916 | /* Update the current position */ | ||
917 | pc->xferred += bcount; | ||
918 | pc->cur_pos += bcount; | ||
919 | |||
920 | debug_log(DBG_PC_INTR, "[cmd %x] transferred %d bytes on that intr.\n", | ||
921 | pc->c[0], bcount); | ||
922 | 802 | ||
923 | /* And set the interrupt handler again */ | 803 | return ide_pc_intr(drive, tape->pc, idetape_pc_intr, IDETAPE_WAIT_CMD, |
924 | ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); | 804 | NULL, idetape_update_buffers, idetape_retry_pc, |
925 | return ide_started; | 805 | ide_tape_handle_dsc, ide_tape_io_buffers); |
926 | } | 806 | } |
927 | 807 | ||
928 | /* | 808 | /* |