diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-07-15 15:22:03 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-07-15 15:22:03 -0400 |
commit | 646c0cb6c430f8d3ad3769dd1518fe664ff0ce27 (patch) | |
tree | 4e02a6ffe70aceeb36093534845f3308c81a11b5 /drivers/scsi/ide-scsi.c | |
parent | 55d82bfa6763d6761670d740ab3bac2f1c042d87 (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>
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r-- | drivers/scsi/ide-scsi.c | 115 |
1 files changed, 3 insertions, 112 deletions
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) | |||
356 | static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive) | 356 | static 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 | ||
475 | static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) | 366 | static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive) |