diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 17:09:26 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 17:09:26 -0500 |
commit | 94f5a86dc37c66b9ec0d7426a7518740fa41d871 (patch) | |
tree | 09cf08464f56f5b36115e583a0cc0e6b9b33545f /drivers/ide/ide-cd.c | |
parent | 64814f2399e7dd1e6e53dd7d08a4ad54d02665d3 (diff) |
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>
Diffstat (limited to 'drivers/ide/ide-cd.c')
-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 2e0c93377582..58397617b281 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) | |||
739 | } | 739 | } |
740 | 740 | ||
741 | /* | 741 | /* |
742 | * Interrupt routine. Called when a read request has completed. | ||
743 | */ | ||
744 | static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) | ||
745 | { | ||
746 | int stat; | ||
747 | int ireason, len, sectors_to_transfer, nskip; | ||
748 | struct cdrom_info *info = drive->driver_data; | ||
749 | u8 lowcyl = 0, highcyl = 0; | ||
750 | int dma = info->dma, dma_error = 0; | ||
751 | |||
752 | struct request *rq = HWGROUP(drive)->rq; | ||
753 | |||
754 | /* | ||
755 | * handle dma case | ||
756 | */ | ||
757 | if (dma) { | ||
758 | info->dma = 0; | ||
759 | dma_error = HWIF(drive)->ide_dma_end(drive); | ||
760 | if (dma_error) { | ||
761 | printk(KERN_ERR "%s: DMA read error\n", drive->name); | ||
762 | ide_dma_off(drive); | ||
763 | } | ||
764 | } | ||
765 | |||
766 | if (cdrom_decode_status(drive, 0, &stat)) | ||
767 | return ide_stopped; | ||
768 | |||
769 | if (dma) { | ||
770 | if (!dma_error) { | ||
771 | ide_end_request(drive, 1, rq->nr_sectors); | ||
772 | return ide_stopped; | ||
773 | } else | ||
774 | return ide_error(drive, "dma error", stat); | ||
775 | } | ||
776 | |||
777 | /* Read the interrupt reason and the transfer length. */ | ||
778 | ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; | ||
779 | lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); | ||
780 | highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); | ||
781 | |||
782 | len = lowcyl + (256 * highcyl); | ||
783 | |||
784 | /* If DRQ is clear, the command has completed. */ | ||
785 | if ((stat & DRQ_STAT) == 0) { | ||
786 | /* If we're not done filling the current buffer, complain. | ||
787 | Otherwise, complete the command normally. */ | ||
788 | if (rq->current_nr_sectors > 0) { | ||
789 | printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n", | ||
790 | drive->name, rq->current_nr_sectors); | ||
791 | rq->cmd_flags |= REQ_FAILED; | ||
792 | cdrom_end_request(drive, 0); | ||
793 | } else | ||
794 | cdrom_end_request(drive, 1); | ||
795 | return ide_stopped; | ||
796 | } | ||
797 | |||
798 | /* Check that the drive is expecting to do the same thing we are. */ | ||
799 | if (cdrom_read_check_ireason (drive, len, ireason)) | ||
800 | return ide_stopped; | ||
801 | |||
802 | if (ide_cd_check_transfer_size(drive, len)) { | ||
803 | cdrom_end_request(drive, 0); | ||
804 | return ide_stopped; | ||
805 | } | ||
806 | |||
807 | /* The number of sectors we need to read from the drive. */ | ||
808 | sectors_to_transfer = len / SECTOR_SIZE; | ||
809 | |||
810 | /* First, figure out if we need to bit-bucket | ||
811 | any of the leading sectors. */ | ||
812 | nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer); | ||
813 | |||
814 | if (nskip > 0) { | ||
815 | ide_cd_drain_data(drive, nskip); | ||
816 | rq->current_nr_sectors -= nskip; | ||
817 | sectors_to_transfer -= nskip; | ||
818 | } | ||
819 | |||
820 | /* Now loop while we still have data to read from the drive. */ | ||
821 | while (sectors_to_transfer > 0) { | ||
822 | int this_transfer; | ||
823 | |||
824 | /* If we've filled the present buffer but there's another | ||
825 | chained buffer after it, move on. */ | ||
826 | if (rq->current_nr_sectors == 0 && rq->nr_sectors) | ||
827 | cdrom_end_request(drive, 1); | ||
828 | |||
829 | /* If the buffers are full, cache the rest of the data in our | ||
830 | internal buffer. */ | ||
831 | if (rq->current_nr_sectors == 0) { | ||
832 | cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer); | ||
833 | sectors_to_transfer = 0; | ||
834 | } else { | ||
835 | /* Transfer data to the buffers. | ||
836 | Figure out how many sectors we can transfer | ||
837 | to the current buffer. */ | ||
838 | this_transfer = min_t(int, sectors_to_transfer, | ||
839 | rq->current_nr_sectors); | ||
840 | |||
841 | /* Read this_transfer sectors | ||
842 | into the current buffer. */ | ||
843 | while (this_transfer > 0) { | ||
844 | HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE); | ||
845 | rq->buffer += SECTOR_SIZE; | ||
846 | --rq->nr_sectors; | ||
847 | --rq->current_nr_sectors; | ||
848 | ++rq->sector; | ||
849 | --this_transfer; | ||
850 | --sectors_to_transfer; | ||
851 | } | ||
852 | } | ||
853 | } | ||
854 | |||
855 | /* Done moving data! Wait for another interrupt. */ | ||
856 | ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL); | ||
857 | return ide_started; | ||
858 | } | ||
859 | |||
860 | /* | ||
861 | * Try to satisfy some of the current read request from our cached data. | 742 | * Try to satisfy some of the current read request from our cached data. |
862 | * Returns nonzero if the request has been completed, zero otherwise. | 743 | * Returns nonzero if the request has been completed, zero otherwise. |
863 | */ | 744 | */ |
@@ -916,6 +797,8 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) | |||
916 | return 0; | 797 | return 0; |
917 | } | 798 | } |
918 | 799 | ||
800 | static ide_startstop_t cdrom_rw_intr(ide_drive_t *); | ||
801 | |||
919 | /* | 802 | /* |
920 | * Routine to send a read packet command to the drive. | 803 | * Routine to send a read packet command to the drive. |
921 | * This is usually called directly from cdrom_start_read. | 804 | * 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) | |||
954 | rq->timeout = ATAPI_WAIT_PC; | 837 | rq->timeout = ATAPI_WAIT_PC; |
955 | 838 | ||
956 | /* Send the command to the drive and return. */ | 839 | /* Send the command to the drive and return. */ |
957 | return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr); | 840 | return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr); |
958 | } | 841 | } |
959 | 842 | ||
960 | 843 | ||
@@ -1168,7 +1051,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq) | |||
1168 | /* | 1051 | /* |
1169 | * best way to deal with dma that is not sector aligned right now... note | 1052 | * best way to deal with dma that is not sector aligned right now... note |
1170 | * that in this path we are not using ->data or ->buffer at all. this irs | 1053 | * that in this path we are not using ->data or ->buffer at all. this irs |
1171 | * can replace cdrom_read_intr() and cdrom_write_intr() in the future. | 1054 | * can replace cdrom_rw_intr() in the future. |
1172 | */ | 1055 | */ |
1173 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | 1056 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) |
1174 | { | 1057 | { |
@@ -1343,21 +1226,22 @@ end_request: | |||
1343 | return ide_stopped; | 1226 | return ide_stopped; |
1344 | } | 1227 | } |
1345 | 1228 | ||
1346 | static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) | 1229 | static ide_startstop_t cdrom_rw_intr(ide_drive_t *drive) |
1347 | { | 1230 | { |
1348 | int stat, ireason, len, sectors_to_transfer, uptodate; | ||
1349 | struct cdrom_info *info = drive->driver_data; | 1231 | struct cdrom_info *info = drive->driver_data; |
1350 | int dma_error = 0, dma = info->dma; | ||
1351 | u8 lowcyl = 0, highcyl = 0; | ||
1352 | |||
1353 | struct request *rq = HWGROUP(drive)->rq; | 1232 | struct request *rq = HWGROUP(drive)->rq; |
1233 | xfer_func_t *xferfunc; | ||
1234 | int stat, ireason, len, sectors_to_transfer, uptodate, nskip; | ||
1235 | int dma_error = 0, dma = info->dma, write = rq_data_dir(rq) == WRITE; | ||
1236 | u8 lowcyl = 0, highcyl = 0; | ||
1354 | 1237 | ||
1355 | /* Check for errors. */ | 1238 | /* Check for errors. */ |
1356 | if (dma) { | 1239 | if (dma) { |
1357 | info->dma = 0; | 1240 | info->dma = 0; |
1358 | dma_error = HWIF(drive)->ide_dma_end(drive); | 1241 | dma_error = HWIF(drive)->ide_dma_end(drive); |
1359 | if (dma_error) { | 1242 | if (dma_error) { |
1360 | printk(KERN_ERR "%s: DMA write error\n", drive->name); | 1243 | printk(KERN_ERR "%s: DMA %s error\n", drive->name, |
1244 | write ? "write" : "read"); | ||
1361 | ide_dma_off(drive); | 1245 | ide_dma_off(drive); |
1362 | } | 1246 | } |
1363 | } | 1247 | } |
@@ -1385,7 +1269,8 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) | |||
1385 | 1269 | ||
1386 | /* If DRQ is clear, the command has completed. */ | 1270 | /* If DRQ is clear, the command has completed. */ |
1387 | if ((stat & DRQ_STAT) == 0) { | 1271 | if ((stat & DRQ_STAT) == 0) { |
1388 | /* If we're not done writing, complain. | 1272 | /* |
1273 | * If we're not done reading/writing, complain. | ||
1389 | * Otherwise, complete the command normally. | 1274 | * Otherwise, complete the command normally. |
1390 | */ | 1275 | */ |
1391 | uptodate = 1; | 1276 | uptodate = 1; |
@@ -1393,27 +1278,73 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) | |||
1393 | printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n", | 1278 | printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n", |
1394 | drive->name, __FUNCTION__, | 1279 | drive->name, __FUNCTION__, |
1395 | rq->current_nr_sectors); | 1280 | rq->current_nr_sectors); |
1281 | if (!write) | ||
1282 | rq->cmd_flags |= REQ_FAILED; | ||
1396 | uptodate = 0; | 1283 | uptodate = 0; |
1397 | } | 1284 | } |
1398 | cdrom_end_request(drive, uptodate); | 1285 | cdrom_end_request(drive, uptodate); |
1399 | return ide_stopped; | 1286 | return ide_stopped; |
1400 | } | 1287 | } |
1401 | 1288 | ||
1289 | sectors_to_transfer = len / SECTOR_SIZE; | ||
1290 | |||
1402 | /* Check that the drive is expecting to do the same thing we are. */ | 1291 | /* Check that the drive is expecting to do the same thing we are. */ |
1403 | if (cdrom_write_check_ireason(drive, len, ireason)) | 1292 | if (write) { |
1404 | return ide_stopped; | 1293 | if (cdrom_write_check_ireason(drive, len, ireason)) |
1294 | return ide_stopped; | ||
1405 | 1295 | ||
1406 | sectors_to_transfer = len / SECTOR_SIZE; | 1296 | xferfunc = HWIF(drive)->atapi_output_bytes; |
1297 | } else { | ||
1298 | if (cdrom_read_check_ireason(drive, len, ireason)) | ||
1299 | return ide_stopped; | ||
1300 | |||
1301 | if (ide_cd_check_transfer_size(drive, len)) { | ||
1302 | cdrom_end_request(drive, 0); | ||
1303 | return ide_stopped; | ||
1304 | } | ||
1305 | |||
1306 | /* | ||
1307 | * First, figure out if we need to bit-bucket | ||
1308 | * any of the leading sectors. | ||
1309 | */ | ||
1310 | nskip = min_t(int, rq->current_nr_sectors | ||
1311 | - bio_cur_sectors(rq->bio), | ||
1312 | sectors_to_transfer); | ||
1313 | |||
1314 | if (nskip > 0) { | ||
1315 | ide_cd_drain_data(drive, nskip); | ||
1316 | rq->current_nr_sectors -= nskip; | ||
1317 | sectors_to_transfer -= nskip; | ||
1318 | } | ||
1319 | |||
1320 | xferfunc = HWIF(drive)->atapi_input_bytes; | ||
1321 | } | ||
1407 | 1322 | ||
1408 | /* | 1323 | /* |
1409 | * now loop and write out the data | 1324 | * now loop and read/write the data |
1410 | */ | 1325 | */ |
1411 | while (sectors_to_transfer > 0) { | 1326 | while (sectors_to_transfer > 0) { |
1412 | int this_transfer; | 1327 | int this_transfer; |
1413 | 1328 | ||
1329 | /* | ||
1330 | * If we've filled the present buffer but there's another | ||
1331 | * chained buffer after it, move on. | ||
1332 | */ | ||
1333 | if (!write && rq->current_nr_sectors == 0 && rq->nr_sectors) | ||
1334 | cdrom_end_request(drive, 1); | ||
1335 | |||
1414 | if (!rq->current_nr_sectors) { | 1336 | if (!rq->current_nr_sectors) { |
1415 | printk(KERN_ERR "%s: %s: confused, missing data\n", | 1337 | if (!write) |
1416 | drive->name, __FUNCTION__); | 1338 | /* |
1339 | * If the buffers are full, cache the rest | ||
1340 | * of the data in our internal buffer. | ||
1341 | */ | ||
1342 | cdrom_buffer_sectors(drive, rq->sector, | ||
1343 | sectors_to_transfer); | ||
1344 | else | ||
1345 | printk(KERN_ERR "%s: %s: confused, missing " | ||
1346 | "data\n", | ||
1347 | drive->name, __FUNCTION__); | ||
1417 | break; | 1348 | break; |
1418 | } | 1349 | } |
1419 | 1350 | ||
@@ -1423,7 +1354,7 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) | |||
1423 | this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors); | 1354 | this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors); |
1424 | 1355 | ||
1425 | while (this_transfer > 0) { | 1356 | while (this_transfer > 0) { |
1426 | HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE); | 1357 | xferfunc(drive, rq->buffer, SECTOR_SIZE); |
1427 | rq->buffer += SECTOR_SIZE; | 1358 | rq->buffer += SECTOR_SIZE; |
1428 | --rq->nr_sectors; | 1359 | --rq->nr_sectors; |
1429 | --rq->current_nr_sectors; | 1360 | --rq->current_nr_sectors; |
@@ -1435,12 +1366,12 @@ static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) | |||
1435 | /* | 1366 | /* |
1436 | * current buffer complete, move on | 1367 | * current buffer complete, move on |
1437 | */ | 1368 | */ |
1438 | if (rq->current_nr_sectors == 0 && rq->nr_sectors) | 1369 | if (write && rq->current_nr_sectors == 0 && rq->nr_sectors) |
1439 | cdrom_end_request(drive, 1); | 1370 | cdrom_end_request(drive, 1); |
1440 | } | 1371 | } |
1441 | 1372 | ||
1442 | /* re-arm handler */ | 1373 | /* re-arm handler */ |
1443 | ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL); | 1374 | ide_set_handler(drive, cdrom_rw_intr, ATAPI_WAIT_PC, NULL); |
1444 | return ide_started; | 1375 | return ide_started; |
1445 | } | 1376 | } |
1446 | 1377 | ||
@@ -1453,7 +1384,7 @@ static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive) | |||
1453 | #endif | 1384 | #endif |
1454 | rq->timeout = ATAPI_WAIT_PC; | 1385 | rq->timeout = ATAPI_WAIT_PC; |
1455 | 1386 | ||
1456 | return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr); | 1387 | return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr); |
1457 | } | 1388 | } |
1458 | 1389 | ||
1459 | static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) | 1390 | static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq) |