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.c168
1 files changed, 55 insertions, 113 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 2fb5d28a9be5..3e43b889dd64 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -6,6 +6,8 @@
6#include <linux/cdrom.h> 6#include <linux/cdrom.h>
7#include <linux/delay.h> 7#include <linux/delay.h>
8#include <linux/ide.h> 8#include <linux/ide.h>
9#include <linux/scatterlist.h>
10
9#include <scsi/scsi.h> 11#include <scsi/scsi.h>
10 12
11#ifdef DEBUG 13#ifdef DEBUG
@@ -69,56 +71,6 @@ int ide_check_atapi_device(ide_drive_t *drive, const char *s)
69} 71}
70EXPORT_SYMBOL_GPL(ide_check_atapi_device); 72EXPORT_SYMBOL_GPL(ide_check_atapi_device);
71 73
72/* PIO data transfer routine using the scatter gather table. */
73int ide_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
74 unsigned int bcount, int write)
75{
76 ide_hwif_t *hwif = drive->hwif;
77 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
78 xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
79 struct scatterlist *sg = pc->sg;
80 char *buf;
81 int count, done = 0;
82
83 while (bcount) {
84 count = min(sg->length - pc->b_count, bcount);
85
86 if (PageHighMem(sg_page(sg))) {
87 unsigned long flags;
88
89 local_irq_save(flags);
90 buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;
91 xf(drive, NULL, buf + pc->b_count, count);
92 kunmap_atomic(buf - sg->offset, KM_IRQ0);
93 local_irq_restore(flags);
94 } else {
95 buf = sg_virt(sg);
96 xf(drive, NULL, buf + pc->b_count, count);
97 }
98
99 bcount -= count;
100 pc->b_count += count;
101 done += count;
102
103 if (pc->b_count == sg->length) {
104 if (!--pc->sg_cnt)
105 break;
106 pc->sg = sg = sg_next(sg);
107 pc->b_count = 0;
108 }
109 }
110
111 if (bcount) {
112 printk(KERN_ERR "%s: %d leftover bytes, %s\n", drive->name,
113 bcount, write ? "padding with zeros"
114 : "discarding data");
115 ide_pad_transfer(drive, write, bcount);
116 }
117
118 return done;
119}
120EXPORT_SYMBOL_GPL(ide_io_buffers);
121
122void ide_init_pc(struct ide_atapi_pc *pc) 74void ide_init_pc(struct ide_atapi_pc *pc)
123{ 75{
124 memset(pc, 0, sizeof(*pc)); 76 memset(pc, 0, sizeof(*pc));
@@ -324,12 +276,14 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
324{ 276{
325 struct ide_atapi_pc *pc = drive->pc; 277 struct ide_atapi_pc *pc = drive->pc;
326 ide_hwif_t *hwif = drive->hwif; 278 ide_hwif_t *hwif = drive->hwif;
279 struct ide_cmd *cmd = &hwif->cmd;
327 struct request *rq = hwif->rq; 280 struct request *rq = hwif->rq;
328 const struct ide_tp_ops *tp_ops = hwif->tp_ops; 281 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
329 xfer_func_t *xferfunc; 282 xfer_func_t *xferfunc;
330 unsigned int timeout, temp; 283 unsigned int timeout, done;
331 u16 bcount; 284 u16 bcount;
332 u8 stat, ireason, dsc = 0; 285 u8 stat, ireason, dsc = 0;
286 u8 write = !!(pc->flags & PC_FLAG_WRITING);
333 287
334 debug_log("Enter %s - interrupt handler\n", __func__); 288 debug_log("Enter %s - interrupt handler\n", __func__);
335 289
@@ -340,8 +294,13 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
340 stat = tp_ops->read_status(hwif); 294 stat = tp_ops->read_status(hwif);
341 295
342 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { 296 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
343 if (hwif->dma_ops->dma_end(drive) || 297 int rc;
344 (drive->media == ide_tape && (stat & ATA_ERR))) { 298
299 drive->waiting_for_dma = 0;
300 rc = hwif->dma_ops->dma_end(drive);
301 ide_dma_unmap_sg(drive, cmd);
302
303 if (rc || (drive->media == ide_tape && (stat & ATA_ERR))) {
345 if (drive->media == ide_floppy) 304 if (drive->media == ide_floppy)
346 printk(KERN_ERR "%s: DMA %s error\n", 305 printk(KERN_ERR "%s: DMA %s error\n",
347 drive->name, rq_data_dir(pc->rq) 306 drive->name, rq_data_dir(pc->rq)
@@ -357,7 +316,8 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
357 316
358 /* No more interrupts */ 317 /* No more interrupts */
359 if ((stat & ATA_DRQ) == 0) { 318 if ((stat & ATA_DRQ) == 0) {
360 int uptodate; 319 int uptodate, error;
320 unsigned int done;
361 321
362 debug_log("Packet command completed, %d bytes transferred\n", 322 debug_log("Packet command completed, %d bytes transferred\n",
363 pc->xferred); 323 pc->xferred);
@@ -404,16 +364,24 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
404 364
405 if (blk_special_request(rq)) { 365 if (blk_special_request(rq)) {
406 rq->errors = 0; 366 rq->errors = 0;
407 ide_complete_rq(drive, 0, blk_rq_bytes(rq)); 367 done = blk_rq_bytes(rq);
368 error = 0;
408 } else { 369 } else {
370
409 if (blk_fs_request(rq) == 0 && uptodate <= 0) { 371 if (blk_fs_request(rq) == 0 && uptodate <= 0) {
410 if (rq->errors == 0) 372 if (rq->errors == 0)
411 rq->errors = -EIO; 373 rq->errors = -EIO;
412 } 374 }
413 ide_complete_rq(drive, uptodate ? 0 : -EIO, 375
414 ide_rq_bytes(rq)); 376 if (drive->media == ide_tape)
377 done = ide_rq_bytes(rq); /* FIXME */
378 else
379 done = blk_rq_bytes(rq);
380
381 error = uptodate ? 0 : -EIO;
415 } 382 }
416 383
384 ide_complete_rq(drive, error, done);
417 return ide_stopped; 385 return ide_stopped;
418 } 386 }
419 387
@@ -433,8 +401,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
433 return ide_do_reset(drive); 401 return ide_do_reset(drive);
434 } 402 }
435 403
436 if (((ireason & ATAPI_IO) == ATAPI_IO) == 404 if (((ireason & ATAPI_IO) == ATAPI_IO) == write) {
437 !!(pc->flags & PC_FLAG_WRITING)) {
438 /* Hopefully, we will never get here */ 405 /* Hopefully, we will never get here */
439 printk(KERN_ERR "%s: We wanted to %s, but the device wants us " 406 printk(KERN_ERR "%s: We wanted to %s, but the device wants us "
440 "to %s!\n", drive->name, 407 "to %s!\n", drive->name,
@@ -443,45 +410,30 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
443 return ide_do_reset(drive); 410 return ide_do_reset(drive);
444 } 411 }
445 412
446 if (!(pc->flags & PC_FLAG_WRITING)) { 413 xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
447 /* Reading - Check that we have enough space */ 414
448 temp = pc->xferred + bcount; 415 if (drive->media == ide_floppy && pc->buf == NULL) {
449 if (temp > pc->req_xfer) { 416 done = min_t(unsigned int, bcount, cmd->nleft);
450 if (temp > pc->buf_size) { 417 ide_pio_bytes(drive, cmd, write, done);
451 printk(KERN_ERR "%s: The device wants to send " 418 } else if (drive->media == ide_tape && pc->bh) {
452 "us more data than expected - " 419 done = drive->pc_io_buffers(drive, pc, bcount, write);
453 "discarding data\n", 420 } else {
454 drive->name); 421 done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
455 422 xferfunc(drive, NULL, pc->cur_pos, done);
456 ide_pad_transfer(drive, 0, bcount); 423 }
457 goto next_irq;
458 }
459 debug_log("The device wants to send us more data than "
460 "expected - allowing transfer\n");
461 }
462 xferfunc = tp_ops->input_data;
463 } else
464 xferfunc = tp_ops->output_data;
465
466 if ((drive->media == ide_floppy && !pc->buf) ||
467 (drive->media == ide_tape && pc->bh)) {
468 int done = drive->pc_io_buffers(drive, pc, bcount,
469 !!(pc->flags & PC_FLAG_WRITING));
470
471 /* FIXME: don't do partial completions */
472 if (drive->media == ide_floppy)
473 ide_complete_rq(drive, 0,
474 done ? done : ide_rq_bytes(rq));
475 } else
476 xferfunc(drive, NULL, pc->cur_pos, bcount);
477 424
478 /* Update the current position */ 425 /* Update the current position */
479 pc->xferred += bcount; 426 pc->xferred += done;
480 pc->cur_pos += bcount; 427 pc->cur_pos += done;
428
429 bcount -= done;
430
431 if (bcount)
432 ide_pad_transfer(drive, write, bcount);
433
434 debug_log("[cmd %x] transferred %d bytes, padded %d bytes\n",
435 rq->cmd[0], done, bcount);
481 436
482 debug_log("[cmd %x] transferred %d bytes on that intr.\n",
483 rq->cmd[0], bcount);
484next_irq:
485 /* And set the interrupt handler again */ 437 /* And set the interrupt handler again */
486 ide_set_handler(drive, ide_pc_intr, timeout); 438 ide_set_handler(drive, ide_pc_intr, timeout);
487 return ide_started; 439 return ide_started;
@@ -611,6 +563,10 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
611 : ide_pc_intr), 563 : ide_pc_intr),
612 timeout); 564 timeout);
613 565
566 /* Send the actual packet */
567 if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
568 hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
569
614 /* Begin DMA, if necessary */ 570 /* Begin DMA, if necessary */
615 if (dev_is_idecd(drive)) { 571 if (dev_is_idecd(drive)) {
616 if (drive->dma) 572 if (drive->dma)
@@ -622,10 +578,6 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
622 } 578 }
623 } 579 }
624 580
625 /* Send the actual packet */
626 if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
627 hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
628
629 return ide_started; 581 return ide_started;
630} 582}
631 583
@@ -633,7 +585,6 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
633{ 585{
634 struct ide_atapi_pc *pc; 586 struct ide_atapi_pc *pc;
635 ide_hwif_t *hwif = drive->hwif; 587 ide_hwif_t *hwif = drive->hwif;
636 const struct ide_dma_ops *dma_ops = hwif->dma_ops;
637 ide_expiry_t *expiry = NULL; 588 ide_expiry_t *expiry = NULL;
638 struct request *rq = hwif->rq; 589 struct request *rq = hwif->rq;
639 unsigned int timeout; 590 unsigned int timeout;
@@ -647,12 +598,8 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
647 expiry = ide_cd_expiry; 598 expiry = ide_cd_expiry;
648 timeout = ATAPI_WAIT_PC; 599 timeout = ATAPI_WAIT_PC;
649 600
650 if (drive->dma) { 601 if (drive->dma)
651 if (ide_build_sglist(drive, cmd)) 602 drive->dma = !ide_dma_prepare(drive, cmd);
652 drive->dma = !dma_ops->dma_setup(drive, cmd);
653 else
654 drive->dma = 0;
655 }
656 } else { 603 } else {
657 pc = drive->pc; 604 pc = drive->pc;
658 605
@@ -670,13 +617,8 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
670 ide_dma_off(drive); 617 ide_dma_off(drive);
671 } 618 }
672 619
673 if ((pc->flags & PC_FLAG_DMA_OK) && 620 if (pc->flags & PC_FLAG_DMA_OK)
674 (drive->dev_flags & IDE_DFLAG_USING_DMA)) { 621 drive->dma = !ide_dma_prepare(drive, cmd);
675 if (ide_build_sglist(drive, cmd))
676 drive->dma = !dma_ops->dma_setup(drive, cmd);
677 else
678 drive->dma = 0;
679 }
680 622
681 if (!drive->dma) 623 if (!drive->dma)
682 pc->flags &= ~PC_FLAG_DMA_OK; 624 pc->flags &= ~PC_FLAG_DMA_OK;