aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/ide-atapi.c177
-rw-r--r--drivers/ide/ide-floppy.c128
-rw-r--r--drivers/ide/ide-tape.c132
3 files changed, 186 insertions, 251 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/*