diff options
-rw-r--r-- | drivers/ide/ide-atapi.c | 177 | ||||
-rw-r--r-- | drivers/ide/ide-floppy.c | 128 | ||||
-rw-r--r-- | drivers/ide/ide-tape.c | 132 | ||||
-rw-r--r-- | drivers/scsi/ide-scsi.c | 115 | ||||
-rw-r--r-- | include/linux/ide.h | 6 |
5 files changed, 195 insertions, 363 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 932a83abaf06..2802031de670 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
@@ -5,6 +5,183 @@ | |||
5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
6 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
7 | #include <linux/ide.h> | 7 | #include <linux/ide.h> |
8 | #include <scsi/scsi.h> | ||
9 | |||
10 | #ifdef DEBUG | ||
11 | #define debug_log(fmt, args...) \ | ||
12 | printk(KERN_INFO "ide: " fmt, ## args) | ||
13 | #else | ||
14 | #define debug_log(fmt, args...) do {} while (0) | ||
15 | #endif | ||
16 | |||
17 | /* TODO: unify the code thus making some arguments go away */ | ||
18 | ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
19 | ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, | ||
20 | void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), | ||
21 | void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), | ||
22 | void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned, int)) | ||
23 | { | ||
24 | ide_hwif_t *hwif = drive->hwif; | ||
25 | xfer_func_t *xferfunc; | ||
26 | unsigned int temp; | ||
27 | u16 bcount; | ||
28 | u8 stat, ireason, scsi = drive->scsi; | ||
29 | |||
30 | debug_log("Enter %s - interrupt handler\n", __func__); | ||
31 | |||
32 | if (pc->flags & PC_FLAG_TIMEDOUT) { | ||
33 | pc->callback(drive); | ||
34 | return ide_stopped; | ||
35 | } | ||
36 | |||
37 | /* Clear the interrupt */ | ||
38 | stat = ide_read_status(drive); | ||
39 | |||
40 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
41 | if (hwif->dma_ops->dma_end(drive) || | ||
42 | (drive->media == ide_tape && !scsi && (stat & ERR_STAT))) { | ||
43 | if (drive->media == ide_floppy && !scsi) | ||
44 | printk(KERN_ERR "%s: DMA %s error\n", | ||
45 | drive->name, rq_data_dir(pc->rq) | ||
46 | ? "write" : "read"); | ||
47 | pc->flags |= PC_FLAG_DMA_ERROR; | ||
48 | } else { | ||
49 | pc->xferred = pc->req_xfer; | ||
50 | if (update_buffers) | ||
51 | update_buffers(drive, pc); | ||
52 | } | ||
53 | debug_log("%s: DMA finished\n", drive->name); | ||
54 | } | ||
55 | |||
56 | /* No more interrupts */ | ||
57 | if ((stat & DRQ_STAT) == 0) { | ||
58 | debug_log("Packet command completed, %d bytes transferred\n", | ||
59 | pc->xferred); | ||
60 | |||
61 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
62 | |||
63 | local_irq_enable_in_hardirq(); | ||
64 | |||
65 | if (drive->media == ide_tape && !scsi && | ||
66 | (stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE) | ||
67 | stat &= ~ERR_STAT; | ||
68 | if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { | ||
69 | /* Error detected */ | ||
70 | debug_log("%s: I/O error\n", drive->name); | ||
71 | |||
72 | if (drive->media != ide_tape || scsi) { | ||
73 | pc->rq->errors++; | ||
74 | if (scsi) | ||
75 | goto cmd_finished; | ||
76 | } | ||
77 | |||
78 | if (pc->c[0] == REQUEST_SENSE) { | ||
79 | printk(KERN_ERR "%s: I/O error in request sense" | ||
80 | " command\n", drive->name); | ||
81 | return ide_do_reset(drive); | ||
82 | } | ||
83 | |||
84 | debug_log("[cmd %x]: check condition\n", pc->c[0]); | ||
85 | |||
86 | /* Retry operation */ | ||
87 | retry_pc(drive); | ||
88 | /* queued, but not started */ | ||
89 | return ide_stopped; | ||
90 | } | ||
91 | cmd_finished: | ||
92 | pc->error = 0; | ||
93 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && | ||
94 | (stat & SEEK_STAT) == 0) { | ||
95 | dsc_handle(drive); | ||
96 | return ide_stopped; | ||
97 | } | ||
98 | /* Command finished - Call the callback function */ | ||
99 | pc->callback(drive); | ||
100 | return ide_stopped; | ||
101 | } | ||
102 | |||
103 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
104 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
105 | printk(KERN_ERR "%s: The device wants to issue more interrupts " | ||
106 | "in DMA mode\n", drive->name); | ||
107 | ide_dma_off(drive); | ||
108 | return ide_do_reset(drive); | ||
109 | } | ||
110 | /* Get the number of bytes to transfer on this interrupt. */ | ||
111 | bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | | ||
112 | hwif->INB(hwif->io_ports.lbam_addr); | ||
113 | |||
114 | ireason = hwif->INB(hwif->io_ports.nsect_addr); | ||
115 | |||
116 | if (ireason & CD) { | ||
117 | printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); | ||
118 | return ide_do_reset(drive); | ||
119 | } | ||
120 | if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { | ||
121 | /* Hopefully, we will never get here */ | ||
122 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | ||
123 | "to %s!\n", drive->name, | ||
124 | (ireason & IO) ? "Write" : "Read", | ||
125 | (ireason & IO) ? "Read" : "Write"); | ||
126 | return ide_do_reset(drive); | ||
127 | } | ||
128 | if (!(pc->flags & PC_FLAG_WRITING)) { | ||
129 | /* Reading - Check that we have enough space */ | ||
130 | temp = pc->xferred + bcount; | ||
131 | if (temp > pc->req_xfer) { | ||
132 | if (temp > pc->buf_size) { | ||
133 | printk(KERN_ERR "%s: The device wants to send " | ||
134 | "us more data than expected - " | ||
135 | "discarding data\n", | ||
136 | drive->name); | ||
137 | if (scsi) | ||
138 | temp = pc->buf_size - pc->xferred; | ||
139 | else | ||
140 | temp = 0; | ||
141 | if (temp) { | ||
142 | if (pc->sg) | ||
143 | io_buffers(drive, pc, temp, 0); | ||
144 | else | ||
145 | hwif->input_data(drive, NULL, | ||
146 | pc->cur_pos, temp); | ||
147 | printk(KERN_ERR "%s: transferred %d of " | ||
148 | "%d bytes\n", | ||
149 | drive->name, | ||
150 | temp, bcount); | ||
151 | } | ||
152 | pc->xferred += temp; | ||
153 | pc->cur_pos += temp; | ||
154 | ide_pad_transfer(drive, 0, bcount - temp); | ||
155 | ide_set_handler(drive, handler, timeout, | ||
156 | expiry); | ||
157 | return ide_started; | ||
158 | } | ||
159 | debug_log("The device wants to send us more data than " | ||
160 | "expected - allowing transfer\n"); | ||
161 | } | ||
162 | xferfunc = hwif->input_data; | ||
163 | } else | ||
164 | xferfunc = hwif->output_data; | ||
165 | |||
166 | if ((drive->media == ide_floppy && !scsi && !pc->buf) || | ||
167 | (drive->media == ide_tape && !scsi && pc->bh) || | ||
168 | (scsi && pc->sg)) | ||
169 | io_buffers(drive, pc, bcount, !!(pc->flags & PC_FLAG_WRITING)); | ||
170 | else | ||
171 | xferfunc(drive, NULL, pc->cur_pos, bcount); | ||
172 | |||
173 | /* Update the current position */ | ||
174 | pc->xferred += bcount; | ||
175 | pc->cur_pos += bcount; | ||
176 | |||
177 | debug_log("[cmd %x] transferred %d bytes on that intr.\n", | ||
178 | pc->c[0], bcount); | ||
179 | |||
180 | /* And set the interrupt handler again */ | ||
181 | ide_set_handler(drive, handler, timeout, expiry); | ||
182 | return ide_started; | ||
183 | } | ||
184 | EXPORT_SYMBOL_GPL(ide_pc_intr); | ||
8 | 185 | ||
9 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) | 186 | static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) |
10 | { | 187 | { |
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 | /* |
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 | /* |
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index ada733ca6725..683bce375c74 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -356,120 +356,11 @@ static int idescsi_expiry(ide_drive_t *drive) | |||
356 | static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) | 356 | static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) |
357 | { | 357 | { |
358 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); | 358 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); |
359 | ide_hwif_t *hwif = drive->hwif; | ||
360 | struct ide_atapi_pc *pc = scsi->pc; | 359 | struct ide_atapi_pc *pc = scsi->pc; |
361 | struct request *rq = pc->rq; | ||
362 | xfer_func_t *xferfunc; | ||
363 | unsigned int temp; | ||
364 | u16 bcount; | ||
365 | u8 stat, ireason; | ||
366 | |||
367 | debug_log("Enter %s - interrupt handler\n", __func__); | ||
368 | |||
369 | if (pc->flags & PC_FLAG_TIMEDOUT) { | ||
370 | pc->callback(drive); | ||
371 | return ide_stopped; | ||
372 | } | ||
373 | |||
374 | /* Clear the interrupt */ | ||
375 | stat = ide_read_status(drive); | ||
376 | |||
377 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
378 | if (hwif->dma_ops->dma_end(drive)) | ||
379 | pc->flags |= PC_FLAG_DMA_ERROR; | ||
380 | else | ||
381 | pc->xferred = pc->req_xfer; | ||
382 | debug_log("%s: DMA finished\n", drive->name); | ||
383 | } | ||
384 | |||
385 | if ((stat & DRQ_STAT) == 0) { | ||
386 | /* No more interrupts */ | ||
387 | debug_log("Packet command completed, %d bytes transferred\n", | ||
388 | pc->xferred); | ||
389 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
390 | local_irq_enable_in_hardirq(); | ||
391 | if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) { | ||
392 | /* Error detected */ | ||
393 | debug_log("%s: I/O error\n", drive->name); | ||
394 | |||
395 | rq->errors++; | ||
396 | } | ||
397 | pc->callback(drive); | ||
398 | return ide_stopped; | ||
399 | } | ||
400 | if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { | ||
401 | pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS; | ||
402 | printk(KERN_ERR "%s: The device wants to issue more interrupts " | ||
403 | "in DMA mode\n", drive->name); | ||
404 | ide_dma_off(drive); | ||
405 | return ide_do_reset(drive); | ||
406 | } | ||
407 | bcount = (hwif->INB(hwif->io_ports.lbah_addr) << 8) | | ||
408 | hwif->INB(hwif->io_ports.lbam_addr); | ||
409 | ireason = hwif->INB(hwif->io_ports.nsect_addr); | ||
410 | |||
411 | if (ireason & CD) { | ||
412 | printk(KERN_ERR "%s: CoD != 0 in %s\n", drive->name, __func__); | ||
413 | return ide_do_reset (drive); | ||
414 | } | ||
415 | if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) { | ||
416 | /* Hopefully, we will never get here */ | ||
417 | printk(KERN_ERR "%s: We wanted to %s, but the device wants us " | ||
418 | "to %s!\n", drive->name, | ||
419 | (ireason & IO) ? "Write" : "Read", | ||
420 | (ireason & IO) ? "Read" : "Write"); | ||
421 | return ide_do_reset(drive); | ||
422 | } | ||
423 | if (!(pc->flags & PC_FLAG_WRITING)) { | ||
424 | temp = pc->xferred + bcount; | ||
425 | if (temp > pc->req_xfer) { | ||
426 | if (temp > pc->buf_size) { | ||
427 | printk(KERN_ERR "%s: The device wants to send " | ||
428 | "us more data than expected - " | ||
429 | "discarding data\n", | ||
430 | drive->name); | ||
431 | temp = pc->buf_size - pc->xferred; | ||
432 | if (temp) { | ||
433 | if (pc->sg) | ||
434 | ide_scsi_io_buffers(drive, pc, | ||
435 | temp, 0); | ||
436 | else | ||
437 | hwif->input_data(drive, NULL, | ||
438 | pc->cur_pos, temp); | ||
439 | printk(KERN_ERR "%s: transferred %d of " | ||
440 | "%d bytes\n", | ||
441 | drive->name, | ||
442 | temp, bcount); | ||
443 | } | ||
444 | pc->xferred += temp; | ||
445 | pc->cur_pos += temp; | ||
446 | ide_pad_transfer(drive, 0, bcount - temp); | ||
447 | ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); | ||
448 | return ide_started; | ||
449 | } | ||
450 | debug_log("The device wants to send us more data than " | ||
451 | "expected - allowing transfer\n"); | ||
452 | } | ||
453 | xferfunc = hwif->input_data; | ||
454 | } else | ||
455 | xferfunc = hwif->output_data; | ||
456 | |||
457 | if (pc->sg) | ||
458 | ide_scsi_io_buffers(drive, pc, bcount, | ||
459 | !!(pc->flags & PC_FLAG_WRITING)); | ||
460 | else | ||
461 | xferfunc(drive, NULL, pc->cur_pos, bcount); | ||
462 | |||
463 | /* Update the current position */ | ||
464 | pc->xferred += bcount; | ||
465 | pc->cur_pos += bcount; | ||
466 | |||
467 | debug_log("[cmd %x] transferred %d bytes on that intr.\n", | ||
468 | pc->c[0], bcount); | ||
469 | 360 | ||
470 | /* And set the interrupt handler again */ | 361 | return ide_pc_intr(drive, pc, idescsi_pc_intr, get_timeout(pc), |
471 | ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); | 362 | idescsi_expiry, NULL, NULL, NULL, |
472 | return ide_started; | 363 | ide_scsi_io_buffers); |
473 | } | 364 | } |
474 | 365 | ||
475 | static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) | 366 | static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) |
diff --git a/include/linux/ide.h b/include/linux/ide.h index fee07a7edb19..ac4eeb2932ef 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -968,6 +968,12 @@ extern int drive_is_ready(ide_drive_t *); | |||
968 | 968 | ||
969 | void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8); | 969 | void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8); |
970 | 970 | ||
971 | ide_startstop_t ide_pc_intr(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
972 | ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry, | ||
973 | void (*update_buffers)(ide_drive_t *, struct ide_atapi_pc *), | ||
974 | void (*retry_pc)(ide_drive_t *), void (*dsc_handle)(ide_drive_t *), | ||
975 | void (*io_buffers)(ide_drive_t *, struct ide_atapi_pc *, unsigned int, | ||
976 | int)); | ||
971 | ide_startstop_t ide_transfer_pc(ide_drive_t *, struct ide_atapi_pc *, | 977 | ide_startstop_t ide_transfer_pc(ide_drive_t *, struct ide_atapi_pc *, |
972 | ide_handler_t *, unsigned int, ide_expiry_t *); | 978 | ide_handler_t *, unsigned int, ide_expiry_t *); |
973 | ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_atapi_pc *, | 979 | ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_atapi_pc *, |