aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-07-15 15:22:03 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-07-15 15:22:03 -0400
commit646c0cb6c430f8d3ad3769dd1518fe664ff0ce27 (patch)
tree4e02a6ffe70aceeb36093534845f3308c81a11b5
parent55d82bfa6763d6761670d740ab3bac2f1c042d87 (diff)
ide: add ide_pc_intr() helper
* ide-tape.c: add 'drive' argument to idetape_update_buffers(). * Add generic ide_pc_intr() helper to ide-atapi.c and then convert ide-{floppy,tape,scsi} device drivers to use it. * ide-tape.c: remove no longer needed DBG_PC_INTR. There should be no functional changes caused by this patch (unless the debugging is explicitely compiled in). Cc: Borislav Petkov <petkovbb@gmail.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/ide/ide-atapi.c177
-rw-r--r--drivers/ide/ide-floppy.c128
-rw-r--r--drivers/ide/ide-tape.c132
-rw-r--r--drivers/scsi/ide-scsi.c115
-rw-r--r--include/linux/ide.h6
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 */
18ide_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 }
91cmd_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}
184EXPORT_SYMBOL_GPL(ide_pc_intr);
8 185
9static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) 186static 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)
388static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive) 388static 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
444static void idetape_update_buffers(struct ide_atapi_pc *pc) 442static 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 */
801static ide_startstop_t idetape_pc_intr(ide_drive_t *drive) 799static 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)
356static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) 356static 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
475static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) 366static 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
969void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8); 969void ide_pktcmd_tf_load(ide_drive_t *, u32, u16, u8);
970 970
971ide_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));
971ide_startstop_t ide_transfer_pc(ide_drive_t *, struct ide_atapi_pc *, 977ide_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 *);
973ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_atapi_pc *, 979ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_atapi_pc *,