aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-atapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r--drivers/ide/ide-atapi.c68
1 files changed, 16 insertions, 52 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 40f413b20bd8..100e6f94b4f0 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -71,49 +71,6 @@ int ide_check_atapi_device(ide_drive_t *drive, const char *s)
71} 71}
72EXPORT_SYMBOL_GPL(ide_check_atapi_device); 72EXPORT_SYMBOL_GPL(ide_check_atapi_device);
73 73
74/* PIO data transfer routine using the scatter gather table. */
75int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
76 unsigned int bcount, int write)
77{
78 ide_hwif_t *hwif = drive->hwif;
79 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
80 xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
81 struct scatterlist *sg = pc->sg;
82 char *buf;
83 int count, done = 0;
84
85 while (bcount) {
86 count = min(sg->length - pc->b_count, bcount);
87
88 if (PageHighMem(sg_page(sg))) {
89 unsigned long flags;
90
91 local_irq_save(flags);
92 buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
93 xf(drive, NULL, buf + pc->b_count, count);
94 kunmap_atomic(buf - sg->offset, KM_IRQ0);
95 local_irq_restore(flags);
96 } else {
97 buf = sg_virt(sg);
98 xf(drive, NULL, buf + pc->b_count, count);
99 }
100
101 bcount -= count;
102 pc->b_count += count;
103 done += count;
104
105 if (pc->b_count == sg->length) {
106 if (!--pc->sg_cnt)
107 break;
108 pc->sg = sg = sg_next(sg);
109 pc->b_count = 0;
110 }
111 }
112
113 return done;
114}
115EXPORT_SYMBOL_GPL(ide_io_buffers);
116
117void ide_init_pc(struct ide_atapi_pc *pc) 74void ide_init_pc(struct ide_atapi_pc *pc)
118{ 75{
119 memset(pc, 0, sizeof(*pc)); 76 memset(pc, 0, sizeof(*pc));
@@ -353,6 +310,9 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
353 pc->xferred = pc->req_xfer; 310 pc->xferred = pc->req_xfer;
354 if (drive->pc_update_buffers) 311 if (drive->pc_update_buffers)
355 drive->pc_update_buffers(drive, pc); 312 drive->pc_update_buffers(drive, pc);
313
314 if (drive->media == ide_floppy)
315 ide_complete_rq(drive, 0, blk_rq_bytes(rq));
356 } 316 }
357 debug_log("%s: DMA finished\n", drive->name); 317 debug_log("%s: DMA finished\n", drive->name);
358 } 318 }
@@ -408,12 +368,19 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
408 rq->errors = 0; 368 rq->errors = 0;
409 ide_complete_rq(drive, 0, blk_rq_bytes(rq)); 369 ide_complete_rq(drive, 0, blk_rq_bytes(rq));
410 } else { 370 } else {
371 unsigned int done;
372
411 if (blk_fs_request(rq) == 0 && uptodate <= 0) { 373 if (blk_fs_request(rq) == 0 && uptodate <= 0) {
412 if (rq->errors == 0) 374 if (rq->errors == 0)
413 rq->errors = -EIO; 375 rq->errors = -EIO;
414 } 376 }
415 ide_complete_rq(drive, uptodate ? 0 : -EIO, 377
416 ide_rq_bytes(rq)); 378 if (drive->media == ide_tape)
379 done = ide_rq_bytes(rq); /* FIXME */
380 else
381 done = blk_rq_bytes(rq);
382
383 ide_complete_rq(drive, uptodate ? 0 : -EIO, done);
417 } 384 }
418 385
419 return ide_stopped; 386 return ide_stopped;
@@ -446,14 +413,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
446 413
447 xferfunc = write ? tp_ops->output_data : tp_ops->input_data; 414 xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
448 415
449 if ((drive->media == ide_floppy && !pc->buf) || 416 if (drive->media == ide_floppy && pc->buf == NULL) {
450 (drive->media == ide_tape && pc->bh)) { 417 done = min_t(unsigned int, bcount, cmd->nleft);
418 ide_pio_bytes(drive, cmd, write, done);
419 } else if (drive->media == ide_tape && pc->bh) {
451 done = drive->pc_io_buffers(drive, pc, bcount, write); 420 done = drive->pc_io_buffers(drive, pc, bcount, write);
452
453 /* FIXME: don't do partial completions */
454 if (drive->media == ide_floppy)
455 ide_complete_rq(drive, 0,
456 done ? done : ide_rq_bytes(rq));
457 } else { 421 } else {
458 done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred); 422 done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
459 xferfunc(drive, NULL, pc->cur_pos, done); 423 xferfunc(drive, NULL, pc->cur_pos, done);