diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 23:09:26 +0100 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 23:09:26 +0100 |
commit | 94f5a86dc37c66b9ec0d7426a7518740fa41d871 (patch) | |
tree | 09cf08464f56f5b36115e583a0cc0e6b9b33545f | |
parent | 64814f2399e7dd1e6e53dd7d08a4ad54d02665d3 (diff) | |
download | op-kernel-dev-94f5a86dc37c66b9ec0d7426a7518740fa41d871.zip op-kernel-dev-94f5a86dc37c66b9ec0d7426a7518740fa41d871.tar.gz |
ide-cd: merge cdrom_read_intr() and cdrom_write_intr()
Add handling of read requests to cdrom_write_intr(), rename it
to cdrom_rw_intr() and remove no longer needed cdrom_read_intr().
There should be no functionality changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/ide-cd.c | 207 |
1 files changed, 69 insertions, 138 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 2e0c933..5839761 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -739,125 +739,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) } /* - * Interrupt routine. Called when a read request has completed. - */ -static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) -{ - int stat; - int ireason, len, sectors_to_transfer, nskip; - struct cdrom_info *info = drive->driver_data; - u8 lowcyl = 0, highcyl = 0; - int dma = info->dma, dma_error = 0; - - struct request *rq = HWGROUP(drive)->rq; - - /* - * handle dma case - */ - if (dma) { - info->dma = 0; - dma_error = HWIF(drive)->ide_dma_end(drive); - if (dma_error) { - printk(KERN_ERR "%s: DMA read error\n", drive->name); - ide_dma_off(drive); - } - } - - if (cdrom_decode_status(drive, 0, &stat)) - return ide_stopped; - - if (dma) { - if (!dma_error) { - ide_end_request(drive, 1, rq->nr_sectors); - return ide_stopped; - } else - return ide_error(drive, "dma error", stat); - } - - /* Read the interrupt reason and the transfer length. */ - ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; - lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); - highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); - - len = lowcyl + (256 * highcyl); - - /* If DRQ is clear, the command has completed. */ - if ((stat & DRQ_STAT) == 0) { - /* If we're not done filling the current buffer, complain. - Otherwise, complete the command normally. */ - if (rq->current_nr_sectors > 0) { - printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n", - drive->name, rq->current_nr_sectors); - rq->cmd_flags |= REQ_FAILED; - cdrom_end_request(drive, 0); - } else - cdrom_end_request(drive, 1); - return ide_stopped; - } - - /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_read_check_ireason (drive, len, ireason)) - return ide_stopped; - - if (ide_cd_check_transfer_size(drive, len)) { - cdrom_end_request(drive, 0); - return ide_stopped; - } - - /* The number of sectors we need to read from the drive. */ - sectors_to_transfer = len / SECTOR_SIZE; - - /* First, figure out if we need to bit-bucket - any of the leading sectors. */ - nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer); - - if (nskip > 0) { - ide_cd_drain_data(drive, nskip); - rq->current_nr_sectors -= nskip; - sectors_to_transfer -= nskip; - } - - /* Now loop while we still have data to read from the drive. */ - while (sectors_to_transfer > 0) { - int this_transfer; - - /* If we've filled the present buffer but there's another - chained buffer after it, move on. */ - if (rq->current_nr_sectors == 0 && rq->nr_sectors) - cdrom_end_request(drive, 1); - - /* If the buffers are full, cache the rest of the data in our - internal buffer. */ - if (rq->current_nr_sectors == 0) { - cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer); - sectors_to_transfer = 0; - } else { - /* Transfer data to the buffers. - Figure out how many sectors we can transfer - to the current buffer. */ - this_transfer = min_t(int, sectors_to_transfer, - rq->current_nr_sectors); - - /* Read this_transfer sectors - into the current buffer. */ - while (this_transfer > 0) { - HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); - rq->buffer += SECTOR_SIZE; - --rq->nr_sectors; - --rq->current_nr_sectors; - ++rq->sector; - --this_transfer; - --sectors_to_transfer; - } - } - } - - /* Done moving data! Wait for another interrupt. */ - ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL); - return ide_started; -} - -/* * Try to satisfy some of the current read request from our cached data. * Returns nonzero if the request has been completed, zero otherwise. */ @@ -916,6 +797,8 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) return 0; } +static ide_startstop_t cdrom_rw_intr(ide_drive_t *); + /* * Routine to send a read packet command to the drive. * This is usually called directly from cdrom_start_read. @@ -954,7 +837,7 @@ static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive) rq->timeout = ATAPI_WAIT_PC; /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr); + return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr); } @@ -1168,7 +1051,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq) /* * best way to deal with dma that is not sector aligned right now... note * that in this path we are not using ->data or ->buffer at all. this irs - * can replace cdrom_read_intr() and cdrom_write_intr() in the future. + * can replace cdrom_rw_intr() in the future. */ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) { @@ -1343,21 +1226,22 @@ end_request: return ide_stopped; } -static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) +static ide_startstop_t cdrom_rw_intr(ide_drive_t *drive) { - int stat, ireason, len, sectors_to_transfer, uptodate; struct cdrom_info *info = drive->driver_data; - int dma_error = 0, dma = info->dma; - u8 lowcyl = 0, highcyl = 0; - struct request *rq = HWGROUP(drive)->rq; + xfer_func_t *xferfunc; + int stat, ireason, len, sectors_to_transfer, uptodate, nskip; + int dma_error = 0, dma = info->dma, write = rq_data_dir(rq) == WRITE; + u8 lowcyl = 0, highcyl = 0; /* Check for errors. */ if (dma) { info->dma = 0; dma_error = HWIF(drive)->ide_dma_end(drive); if (dma_error) { - printk(KERN_ERR "%s: DMA write error\n", drive->name); + printk(KERN_ERR "%s: DMA %s error\n", drive->name, + write ? "write" : "read"); ide_dma_off(drive); } } @@ -1385,7 +1269,8 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) /* If DRQ is clear, the command has completed. */ if ((stat & DRQ_STAT) == 0) { - /* If we're not done writing, complain. + /* + * If we're not done reading/writing, complain. * Otherwise, complete the command normally. */ uptodate = 1; @@ -1393,27 +1278,73 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n", drive->name, __FUNCTION__, rq->current_nr_sectors); + if (!write) + rq->cmd_flags |= REQ_FAILED; uptodate = 0; } cdrom_end_request(drive, uptodate); return ide_stopped; } + sectors_to_transfer = len / SECTOR_SIZE; + /* Check that the drive is expecting to do the same thing we are. */ - if (cdrom_write_check_ireason(drive, len, ireason)) - return ide_stopped; + if (write) { + if (cdrom_write_check_ireason(drive, len, ireason)) + return ide_stopped; - sectors_to_transfer = len / SECTOR_SIZE; + xferfunc = HWIF(drive)->atapi_output_bytes; + } else { + if (cdrom_read_check_ireason(drive, len, ireason)) + return ide_stopped; + + if (ide_cd_check_transfer_size(drive, len)) { + cdrom_end_request(drive, 0); + return ide_stopped; + } + + /* + * First, figure out if we need to bit-bucket + * any of the leading sectors. + */ + nskip = min_t(int, rq->current_nr_sectors + - bio_cur_sectors(rq->bio), + sectors_to_transfer); + + if (nskip > 0) { + ide_cd_drain_data(drive, nskip); + rq->current_nr_sectors -= nskip; + sectors_to_transfer -= nskip; + } + + xferfunc = HWIF(drive)->atapi_input_bytes; + } /* - * now loop and write out the data + * now loop and read/write the data */ while (sectors_to_transfer > 0) { int this_transfer; + /* + * If we've filled the present buffer but there's another + * chained buffer after it, move on. + */ + if (!write && rq->current_nr_sectors == 0 && rq->nr_sectors) + cdrom_end_request(drive, 1); + if (!rq->current_nr_sectors) { - printk(KERN_ERR "%s: %s: confused, missing data\n", - drive->name, __FUNCTION__); + if (!write) + /* + * If the buffers are full, cache the rest + * of the data in our internal buffer. + */ + cdrom_buffer_sectors(drive, rq->sector, + sectors_to_transfer); + else + printk(KERN_ERR "%s: %s: confused, missing " + "data\n", + drive->name, __FUNCTION__); break; } @@ -1423,7 +1354,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors); while (this_transfer > 0) { - HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE); + xferfunc(drive, rq->buffer, SECTOR_SIZE); rq->buffer += SECTOR_SIZE; --rq->nr_sectors; --rq->current_nr_sectors; @@ -1435,12 +1366,12 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) /* * current buffer complete, move on */ - if (rq->current_nr_sectors == 0 && rq->nr_sectors) + if (write && rq->current_nr_sectors == 0 && rq->nr_sectors) cdrom_end_request(drive, 1); } /* re-arm handler */ - ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL); + ide_set_handler(drive, cdrom_rw_intr, ATAPI_WAIT_PC, NULL); return ide_started; } @@ -1453,7 +1384,7 @@ static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive) #endif rq->timeout = ATAPI_WAIT_PC; - return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr); + return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr); } static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) |