aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-atapi.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2009-04-05 02:14:15 -0400
committerLen Brown <len.brown@intel.com>2009-04-05 02:14:15 -0400
commit478c6a43fcbc6c11609f8cee7c7b57223907754f (patch)
treea7f7952099da60d33032aed6de9c0c56c9f8779e /drivers/ide/ide-atapi.c
parent8a3f257c704e02aee9869decd069a806b45be3f1 (diff)
parent6bb597507f9839b13498781e481f5458aea33620 (diff)
Merge branch 'linus' into release
Conflicts: arch/x86/kernel/cpu/cpufreq/longhaul.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r--drivers/ide/ide-atapi.c242
1 files changed, 120 insertions, 122 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index e9d042dba0e0..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));
@@ -149,7 +101,10 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk,
149 memcpy(rq->cmd, pc->c, 12); 101 memcpy(rq->cmd, pc->c, 12);
150 if (drive->media == ide_tape) 102 if (drive->media == ide_tape)
151 rq->cmd[13] = REQ_IDETAPE_PC1; 103 rq->cmd[13] = REQ_IDETAPE_PC1;
152 ide_do_drive_cmd(drive, rq); 104
105 drive->hwif->rq = NULL;
106
107 elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0);
153} 108}
154 109
155/* 110/*
@@ -297,6 +252,21 @@ int ide_cd_get_xferlen(struct request *rq)
297} 252}
298EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); 253EXPORT_SYMBOL_GPL(ide_cd_get_xferlen);
299 254
255void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason)
256{
257 struct ide_cmd cmd;
258
259 memset(&cmd, 0, sizeof(cmd));
260 cmd.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM |
261 IDE_TFLAG_IN_NSECT;
262
263 drive->hwif->tp_ops->tf_read(drive, &cmd);
264
265 *bcount = (cmd.tf.lbah << 8) | cmd.tf.lbam;
266 *ireason = cmd.tf.nsect & 3;
267}
268EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason);
269
300/* 270/*
301 * This is the usual interrupt handler which will be called during a packet 271 * This is the usual interrupt handler which will be called during a packet
302 * command. We will transfer some of the data (as requested by the drive) 272 * command. We will transfer some of the data (as requested by the drive)
@@ -306,29 +276,31 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
306{ 276{
307 struct ide_atapi_pc *pc = drive->pc; 277 struct ide_atapi_pc *pc = drive->pc;
308 ide_hwif_t *hwif = drive->hwif; 278 ide_hwif_t *hwif = drive->hwif;
279 struct ide_cmd *cmd = &hwif->cmd;
309 struct request *rq = hwif->rq; 280 struct request *rq = hwif->rq;
310 const struct ide_tp_ops *tp_ops = hwif->tp_ops; 281 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
311 xfer_func_t *xferfunc; 282 xfer_func_t *xferfunc;
312 unsigned int timeout, temp; 283 unsigned int timeout, done;
313 u16 bcount; 284 u16 bcount;
314 u8 stat, ireason, dsc = 0; 285 u8 stat, ireason, dsc = 0;
286 u8 write = !!(pc->flags & PC_FLAG_WRITING);
315 287
316 debug_log("Enter %s - interrupt handler\n", __func__); 288 debug_log("Enter %s - interrupt handler\n", __func__);
317 289
318 timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD 290 timeout = (drive->media == ide_floppy) ? WAIT_FLOPPY_CMD
319 : WAIT_TAPE_CMD; 291 : WAIT_TAPE_CMD;
320 292
321 if (pc->flags & PC_FLAG_TIMEDOUT) {
322 drive->pc_callback(drive, 0);
323 return ide_stopped;
324 }
325
326 /* Clear the interrupt */ 293 /* Clear the interrupt */
327 stat = tp_ops->read_status(hwif); 294 stat = tp_ops->read_status(hwif);
328 295
329 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) { 296 if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
330 if (hwif->dma_ops->dma_end(drive) || 297 int rc;
331 (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))) {
332 if (drive->media == ide_floppy) 304 if (drive->media == ide_floppy)
333 printk(KERN_ERR "%s: DMA %s error\n", 305 printk(KERN_ERR "%s: DMA %s error\n",
334 drive->name, rq_data_dir(pc->rq) 306 drive->name, rq_data_dir(pc->rq)
@@ -344,6 +316,9 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
344 316
345 /* No more interrupts */ 317 /* No more interrupts */
346 if ((stat & ATA_DRQ) == 0) { 318 if ((stat & ATA_DRQ) == 0) {
319 int uptodate, error;
320 unsigned int done;
321
347 debug_log("Packet command completed, %d bytes transferred\n", 322 debug_log("Packet command completed, %d bytes transferred\n",
348 pc->xferred); 323 pc->xferred);
349 324
@@ -382,8 +357,31 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
382 dsc = 1; 357 dsc = 1;
383 358
384 /* Command finished - Call the callback function */ 359 /* Command finished - Call the callback function */
385 drive->pc_callback(drive, dsc); 360 uptodate = drive->pc_callback(drive, dsc);
361
362 if (uptodate == 0)
363 drive->failed_pc = NULL;
364
365 if (blk_special_request(rq)) {
366 rq->errors = 0;
367 done = blk_rq_bytes(rq);
368 error = 0;
369 } else {
386 370
371 if (blk_fs_request(rq) == 0 && uptodate <= 0) {
372 if (rq->errors == 0)
373 rq->errors = -EIO;
374 }
375
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;
382 }
383
384 ide_complete_rq(drive, error, done);
387 return ide_stopped; 385 return ide_stopped;
388 } 386 }
389 387
@@ -403,8 +401,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
403 return ide_do_reset(drive); 401 return ide_do_reset(drive);
404 } 402 }
405 403
406 if (((ireason & ATAPI_IO) == ATAPI_IO) == 404 if (((ireason & ATAPI_IO) == ATAPI_IO) == write) {
407 !!(pc->flags & PC_FLAG_WRITING)) {
408 /* Hopefully, we will never get here */ 405 /* Hopefully, we will never get here */
409 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 "
410 "to %s!\n", drive->name, 407 "to %s!\n", drive->name,
@@ -413,59 +410,57 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
413 return ide_do_reset(drive); 410 return ide_do_reset(drive);
414 } 411 }
415 412
416 if (!(pc->flags & PC_FLAG_WRITING)) { 413 xferfunc = write ? tp_ops->output_data : tp_ops->input_data;
417 /* Reading - Check that we have enough space */
418 temp = pc->xferred + bcount;
419 if (temp > pc->req_xfer) {
420 if (temp > pc->buf_size) {
421 printk(KERN_ERR "%s: The device wants to send "
422 "us more data than expected - "
423 "discarding data\n",
424 drive->name);
425
426 ide_pad_transfer(drive, 0, bcount);
427 goto next_irq;
428 }
429 debug_log("The device wants to send us more data than "
430 "expected - allowing transfer\n");
431 }
432 xferfunc = tp_ops->input_data;
433 } else
434 xferfunc = tp_ops->output_data;
435
436 if ((drive->media == ide_floppy && !pc->buf) ||
437 (drive->media == ide_tape && pc->bh)) {
438 int done = drive->pc_io_buffers(drive, pc, bcount,
439 !!(pc->flags & PC_FLAG_WRITING));
440 414
441 /* FIXME: don't do partial completions */ 415 if (drive->media == ide_floppy && pc->buf == NULL) {
442 if (drive->media == ide_floppy) 416 done = min_t(unsigned int, bcount, cmd->nleft);
443 ide_end_request(drive, 1, done >> 9); 417 ide_pio_bytes(drive, cmd, write, done);
444 } else 418 } else if (drive->media == ide_tape && pc->bh) {
445 xferfunc(drive, NULL, pc->cur_pos, bcount); 419 done = drive->pc_io_buffers(drive, pc, bcount, write);
420 } else {
421 done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
422 xferfunc(drive, NULL, pc->cur_pos, done);
423 }
446 424
447 /* Update the current position */ 425 /* Update the current position */
448 pc->xferred += bcount; 426 pc->xferred += done;
449 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);
450 436
451 debug_log("[cmd %x] transferred %d bytes on that intr.\n",
452 rq->cmd[0], bcount);
453next_irq:
454 /* And set the interrupt handler again */ 437 /* And set the interrupt handler again */
455 ide_set_handler(drive, ide_pc_intr, timeout, NULL); 438 ide_set_handler(drive, ide_pc_intr, timeout);
456 return ide_started; 439 return ide_started;
457} 440}
458 441
442static void ide_init_packet_cmd(struct ide_cmd *cmd, u32 tf_flags,
443 u16 bcount, u8 dma)
444{
445 cmd->protocol = dma ? ATAPI_PROT_DMA : ATAPI_PROT_PIO;
446 cmd->tf_flags |= IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
447 IDE_TFLAG_OUT_FEATURE | tf_flags;
448 cmd->tf.command = ATA_CMD_PACKET;
449 cmd->tf.feature = dma; /* Use PIO/DMA */
450 cmd->tf.lbam = bcount & 0xff;
451 cmd->tf.lbah = (bcount >> 8) & 0xff;
452}
453
459static u8 ide_read_ireason(ide_drive_t *drive) 454static u8 ide_read_ireason(ide_drive_t *drive)
460{ 455{
461 ide_task_t task; 456 struct ide_cmd cmd;
462 457
463 memset(&task, 0, sizeof(task)); 458 memset(&cmd, 0, sizeof(cmd));
464 task.tf_flags = IDE_TFLAG_IN_NSECT; 459 cmd.tf_flags = IDE_TFLAG_IN_NSECT;
465 460
466 drive->hwif->tp_ops->tf_read(drive, &task); 461 drive->hwif->tp_ops->tf_read(drive, &cmd);
467 462
468 return task.tf.nsect & 3; 463 return cmd.tf.nsect & 3;
469} 464}
470 465
471static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason) 466static u8 ide_wait_ireason(ide_drive_t *drive, u8 ireason)
@@ -560,11 +555,17 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
560 } 555 }
561 } 556 }
562 557
558 hwif->expiry = expiry;
559
563 /* Set the interrupt routine */ 560 /* Set the interrupt routine */
564 ide_set_handler(drive, 561 ide_set_handler(drive,
565 (dev_is_idecd(drive) ? drive->irq_handler 562 (dev_is_idecd(drive) ? drive->irq_handler
566 : ide_pc_intr), 563 : ide_pc_intr),
567 timeout, expiry); 564 timeout);
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);
568 569
569 /* Begin DMA, if necessary */ 570 /* Begin DMA, if necessary */
570 if (dev_is_idecd(drive)) { 571 if (dev_is_idecd(drive)) {
@@ -577,30 +578,28 @@ static ide_startstop_t ide_transfer_pc(ide_drive_t *drive)
577 } 578 }
578 } 579 }
579 580
580 /* Send the actual packet */
581 if ((drive->atapi_flags & IDE_AFLAG_ZIP_DRIVE) == 0)
582 hwif->tp_ops->output_data(drive, NULL, rq->cmd, cmd_len);
583
584 return ide_started; 581 return ide_started;
585} 582}
586 583
587ide_startstop_t ide_issue_pc(ide_drive_t *drive) 584ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd)
588{ 585{
589 struct ide_atapi_pc *pc; 586 struct ide_atapi_pc *pc;
590 ide_hwif_t *hwif = drive->hwif; 587 ide_hwif_t *hwif = drive->hwif;
591 ide_expiry_t *expiry = NULL; 588 ide_expiry_t *expiry = NULL;
589 struct request *rq = hwif->rq;
592 unsigned int timeout; 590 unsigned int timeout;
593 u32 tf_flags; 591 u32 tf_flags;
594 u16 bcount; 592 u16 bcount;
593 u8 drq_int = !!(drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT);
595 594
596 if (dev_is_idecd(drive)) { 595 if (dev_is_idecd(drive)) {
597 tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL; 596 tf_flags = IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL;
598 bcount = ide_cd_get_xferlen(hwif->rq); 597 bcount = ide_cd_get_xferlen(rq);
599 expiry = ide_cd_expiry; 598 expiry = ide_cd_expiry;
600 timeout = ATAPI_WAIT_PC; 599 timeout = ATAPI_WAIT_PC;
601 600
602 if (drive->dma) 601 if (drive->dma)
603 drive->dma = !hwif->dma_ops->dma_setup(drive); 602 drive->dma = !ide_dma_prepare(drive, cmd);
604 } else { 603 } else {
605 pc = drive->pc; 604 pc = drive->pc;
606 605
@@ -618,9 +617,8 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive)
618 ide_dma_off(drive); 617 ide_dma_off(drive);
619 } 618 }
620 619
621 if ((pc->flags & PC_FLAG_DMA_OK) && 620 if (pc->flags & PC_FLAG_DMA_OK)
622 (drive->dev_flags & IDE_DFLAG_USING_DMA)) 621 drive->dma = !ide_dma_prepare(drive, cmd);
623 drive->dma = !hwif->dma_ops->dma_setup(drive);
624 622
625 if (!drive->dma) 623 if (!drive->dma)
626 pc->flags &= ~PC_FLAG_DMA_OK; 624 pc->flags &= ~PC_FLAG_DMA_OK;
@@ -629,18 +627,18 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive)
629 : WAIT_TAPE_CMD; 627 : WAIT_TAPE_CMD;
630 } 628 }
631 629
632 ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); 630 ide_init_packet_cmd(cmd, tf_flags, bcount, drive->dma);
633 631
634 /* Issue the packet command */ 632 (void)do_rw_taskfile(drive, cmd);
635 if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { 633
634 if (drq_int) {
636 if (drive->dma) 635 if (drive->dma)
637 drive->waiting_for_dma = 0; 636 drive->waiting_for_dma = 0;
638 ide_execute_command(drive, ATA_CMD_PACKET, ide_transfer_pc, 637 hwif->expiry = expiry;
639 timeout, expiry);
640 return ide_started;
641 } else {
642 ide_execute_pkt_cmd(drive);
643 return ide_transfer_pc(drive);
644 } 638 }
639
640 ide_execute_command(drive, cmd, ide_transfer_pc, timeout);
641
642 return drq_int ? ide_started : ide_transfer_pc(drive);
645} 643}
646EXPORT_SYMBOL_GPL(ide_issue_pc); 644EXPORT_SYMBOL_GPL(ide_issue_pc);