diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 17:09:28 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 17:09:28 -0500 |
commit | 0041e7c6ca9719309bef6a4754e4eb9566b37ae1 (patch) | |
tree | 204b36cb8c31d9ed6799f256f04d03a7870231f0 /drivers/ide/ide-cd.c | |
parent | 48ea0b216ba96d14228ee0cb4c964b3b495ff0a8 (diff) |
ide-cd: merge cdrom_rw_intr() and cdrom_newpc_intr()
Add handling of fs read/write requests to cdrom_nepwc_intr()
and remove no longer needed cdrom_rw_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 | 272 |
1 files changed, 94 insertions, 178 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 53af68eed875..50f78eb7dce9 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -797,7 +797,7 @@ static int cdrom_read_from_buffer (ide_drive_t *drive) | |||
797 | return 0; | 797 | return 0; |
798 | } | 798 | } |
799 | 799 | ||
800 | static ide_startstop_t cdrom_rw_intr(ide_drive_t *); | 800 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); |
801 | 801 | ||
802 | /* | 802 | /* |
803 | * Routine to send a read/write packet command to the drive. | 803 | * Routine to send a read/write packet command to the drive. |
@@ -846,7 +846,7 @@ static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive) | |||
846 | rq->timeout = ATAPI_WAIT_PC; | 846 | rq->timeout = ATAPI_WAIT_PC; |
847 | 847 | ||
848 | /* Send the command to the drive and return. */ | 848 | /* Send the command to the drive and return. */ |
849 | return cdrom_transfer_packet_command(drive, rq, cdrom_rw_intr); | 849 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); |
850 | } | 850 | } |
851 | 851 | ||
852 | #define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ | 852 | #define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */ |
@@ -1024,17 +1024,12 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq) | |||
1024 | return 1; | 1024 | return 1; |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | /* | ||
1028 | * best way to deal with dma that is not sector aligned right now... note | ||
1029 | * that in this path we are not using ->data or ->buffer at all. this irs | ||
1030 | * can replace cdrom_rw_intr() in the future. | ||
1031 | */ | ||
1032 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | 1027 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) |
1033 | { | 1028 | { |
1034 | struct cdrom_info *info = drive->driver_data; | 1029 | struct cdrom_info *info = drive->driver_data; |
1035 | struct request *rq = HWGROUP(drive)->rq; | 1030 | struct request *rq = HWGROUP(drive)->rq; |
1036 | xfer_func_t *xferfunc; | 1031 | xfer_func_t *xferfunc; |
1037 | ide_expiry_t *expiry; | 1032 | ide_expiry_t *expiry = NULL; |
1038 | int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0; | 1033 | int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0; |
1039 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0; | 1034 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0; |
1040 | unsigned int timeout; | 1035 | unsigned int timeout; |
@@ -1061,6 +1056,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1061 | if (dma) { | 1056 | if (dma) { |
1062 | if (dma_error) | 1057 | if (dma_error) |
1063 | return ide_error(drive, "dma error", stat); | 1058 | return ide_error(drive, "dma error", stat); |
1059 | if (blk_fs_request(rq)) { | ||
1060 | ide_end_request(drive, 1, rq->nr_sectors); | ||
1061 | return ide_stopped; | ||
1062 | } | ||
1064 | goto end_request; | 1063 | goto end_request; |
1065 | } | 1064 | } |
1066 | 1065 | ||
@@ -1072,7 +1071,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1072 | highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); | 1071 | highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); |
1073 | 1072 | ||
1074 | len = lowcyl + (256 * highcyl); | 1073 | len = lowcyl + (256 * highcyl); |
1075 | thislen = rq->data_len; | 1074 | |
1075 | thislen = blk_fs_request(rq) ? len : rq->data_len; | ||
1076 | if (thislen > len) | 1076 | if (thislen > len) |
1077 | thislen = len; | 1077 | thislen = len; |
1078 | 1078 | ||
@@ -1080,7 +1080,24 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1080 | * If DRQ is clear, the command has completed. | 1080 | * If DRQ is clear, the command has completed. |
1081 | */ | 1081 | */ |
1082 | if ((stat & DRQ_STAT) == 0) { | 1082 | if ((stat & DRQ_STAT) == 0) { |
1083 | if (!blk_pc_request(rq)) { | 1083 | if (blk_fs_request(rq)) { |
1084 | /* | ||
1085 | * If we're not done reading/writing, complain. | ||
1086 | * Otherwise, complete the command normally. | ||
1087 | */ | ||
1088 | uptodate = 1; | ||
1089 | if (rq->current_nr_sectors > 0) { | ||
1090 | printk(KERN_ERR "%s: %s: data underrun " | ||
1091 | "(%d blocks)\n", | ||
1092 | drive->name, __FUNCTION__, | ||
1093 | rq->current_nr_sectors); | ||
1094 | if (!write) | ||
1095 | rq->cmd_flags |= REQ_FAILED; | ||
1096 | uptodate = 0; | ||
1097 | } | ||
1098 | cdrom_end_request(drive, uptodate); | ||
1099 | return ide_stopped; | ||
1100 | } else if (!blk_pc_request(rq)) { | ||
1084 | ide_cd_request_sense_fixup(rq); | 1101 | ide_cd_request_sense_fixup(rq); |
1085 | /* Complain if we still have data left to transfer. */ | 1102 | /* Complain if we still have data left to transfer. */ |
1086 | uptodate = rq->data_len ? 0 : 1; | 1103 | uptodate = rq->data_len ? 0 : 1; |
@@ -1091,24 +1108,47 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1091 | /* | 1108 | /* |
1092 | * check which way to transfer data | 1109 | * check which way to transfer data |
1093 | */ | 1110 | */ |
1094 | if (blk_pc_request(rq) && rq_data_dir(rq) == WRITE) { | 1111 | if ((blk_fs_request(rq) || blk_pc_request(rq)) && write) { |
1095 | /* | 1112 | /* |
1096 | * write to drive | 1113 | * write to drive |
1097 | */ | 1114 | */ |
1098 | if (cdrom_write_check_ireason(drive, len, ireason)) | 1115 | if (cdrom_write_check_ireason(drive, len, ireason)) |
1099 | return ide_stopped; | 1116 | return ide_stopped; |
1100 | } else if (blk_pc_request(rq)) { | 1117 | } else if (blk_fs_request(rq) || blk_pc_request(rq)) { |
1101 | /* | 1118 | /* |
1102 | * read from drive | 1119 | * read from drive |
1103 | */ | 1120 | */ |
1104 | if (cdrom_read_check_ireason(drive, len, ireason)) | 1121 | if (cdrom_read_check_ireason(drive, len, ireason)) |
1105 | return ide_stopped; | 1122 | return ide_stopped; |
1123 | |||
1124 | if (blk_fs_request(rq)) { | ||
1125 | int nskip; | ||
1126 | |||
1127 | if (ide_cd_check_transfer_size(drive, len)) { | ||
1128 | cdrom_end_request(drive, 0); | ||
1129 | return ide_stopped; | ||
1130 | } | ||
1131 | |||
1132 | /* | ||
1133 | * First, figure out if we need to bit-bucket | ||
1134 | * any of the leading sectors. | ||
1135 | */ | ||
1136 | nskip = min_t(int, rq->current_nr_sectors | ||
1137 | - bio_cur_sectors(rq->bio), | ||
1138 | thislen >> 9); | ||
1139 | if (nskip > 0) { | ||
1140 | ide_cd_drain_data(drive, nskip); | ||
1141 | rq->current_nr_sectors -= nskip; | ||
1142 | thislen -= (nskip << 9); | ||
1143 | } | ||
1144 | } | ||
1106 | } | 1145 | } |
1107 | 1146 | ||
1108 | if (ireason == 0) { | 1147 | if (ireason == 0) { |
1109 | write = 1; | 1148 | write = 1; |
1110 | xferfunc = HWIF(drive)->atapi_output_bytes; | 1149 | xferfunc = HWIF(drive)->atapi_output_bytes; |
1111 | } else if (ireason == 2 || (ireason == 1 && blk_pc_request(rq))) { | 1150 | } else if (ireason == 2 || (ireason == 1 && |
1151 | (blk_fs_request(rq) || blk_pc_request(rq)))) { | ||
1112 | write = 0; | 1152 | write = 0; |
1113 | xferfunc = HWIF(drive)->atapi_input_bytes; | 1153 | xferfunc = HWIF(drive)->atapi_input_bytes; |
1114 | } else { | 1154 | } else { |
@@ -1123,23 +1163,37 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1123 | * transfer data | 1163 | * transfer data |
1124 | */ | 1164 | */ |
1125 | while (thislen > 0) { | 1165 | while (thislen > 0) { |
1126 | u8 *ptr = rq->data; | 1166 | u8 *ptr = blk_fs_request(rq) ? NULL : rq->data; |
1127 | int blen = rq->data_len; | 1167 | int blen = rq->data_len; |
1128 | 1168 | ||
1129 | /* | 1169 | /* |
1130 | * bio backed? | 1170 | * bio backed? |
1131 | */ | 1171 | */ |
1132 | if (rq->bio) { | 1172 | if (rq->bio) { |
1133 | ptr = bio_data(rq->bio); | 1173 | if (blk_fs_request(rq)) { |
1134 | blen = bio_iovec(rq->bio)->bv_len; | 1174 | ptr = rq->buffer; |
1175 | blen = rq->current_nr_sectors << 9; | ||
1176 | } else { | ||
1177 | ptr = bio_data(rq->bio); | ||
1178 | blen = bio_iovec(rq->bio)->bv_len; | ||
1179 | } | ||
1135 | } | 1180 | } |
1136 | 1181 | ||
1137 | if (!ptr) { | 1182 | if (!ptr) { |
1138 | printk(KERN_ERR "%s: confused, missing data\n", | 1183 | if (blk_fs_request(rq) && !write) |
1139 | drive->name); | 1184 | /* |
1140 | blk_dump_rq_flags(rq, rq_data_dir(rq) | 1185 | * If the buffers are full, cache the rest |
1141 | ? "cdrom_newpc_intr, write" | 1186 | * of the data in our internal buffer. |
1142 | : "cdrom_newpc_intr, read"); | 1187 | */ |
1188 | cdrom_buffer_sectors(drive, rq->sector, | ||
1189 | thislen >> 9); | ||
1190 | else { | ||
1191 | printk(KERN_ERR "%s: confused, missing data\n", | ||
1192 | drive->name); | ||
1193 | blk_dump_rq_flags(rq, rq_data_dir(rq) | ||
1194 | ? "cdrom_newpc_intr, write" | ||
1195 | : "cdrom_newpc_intr, read"); | ||
1196 | } | ||
1143 | break; | 1197 | break; |
1144 | } | 1198 | } |
1145 | 1199 | ||
@@ -1150,19 +1204,30 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1150 | 1204 | ||
1151 | thislen -= blen; | 1205 | thislen -= blen; |
1152 | len -= blen; | 1206 | len -= blen; |
1153 | rq->data_len -= blen; | ||
1154 | 1207 | ||
1155 | if (rq->bio) | 1208 | if (blk_fs_request(rq)) { |
1209 | rq->buffer += blen; | ||
1210 | rq->nr_sectors -= (blen >> 9); | ||
1211 | rq->current_nr_sectors -= (blen >> 9); | ||
1212 | rq->sector += (blen >> 9); | ||
1213 | |||
1214 | if (rq->current_nr_sectors == 0 && rq->nr_sectors) | ||
1215 | cdrom_end_request(drive, 1); | ||
1216 | } else { | ||
1217 | rq->data_len -= blen; | ||
1218 | |||
1156 | /* | 1219 | /* |
1157 | * The request can't be completed until DRQ is cleared. | 1220 | * The request can't be completed until DRQ is cleared. |
1158 | * So complete the data, but don't complete the request | 1221 | * So complete the data, but don't complete the request |
1159 | * using the dummy function for the callback feature | 1222 | * using the dummy function for the callback feature |
1160 | * of blk_end_request_callback(). | 1223 | * of blk_end_request_callback(). |
1161 | */ | 1224 | */ |
1162 | blk_end_request_callback(rq, 0, blen, | 1225 | if (rq->bio) |
1226 | blk_end_request_callback(rq, 0, blen, | ||
1163 | cdrom_newpc_intr_dummy_cb); | 1227 | cdrom_newpc_intr_dummy_cb); |
1164 | else | 1228 | else |
1165 | rq->data += blen; | 1229 | rq->data += blen; |
1230 | } | ||
1166 | } | 1231 | } |
1167 | 1232 | ||
1168 | if (write && blk_sense_request(rq)) | 1233 | if (write && blk_sense_request(rq)) |
@@ -1171,15 +1236,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1171 | /* | 1236 | /* |
1172 | * pad, if necessary | 1237 | * pad, if necessary |
1173 | */ | 1238 | */ |
1174 | if (len > 0) | 1239 | if (!blk_fs_request(rq) && len > 0) |
1175 | ide_cd_pad_transfer(drive, xferfunc, len); | 1240 | ide_cd_pad_transfer(drive, xferfunc, len); |
1176 | 1241 | ||
1177 | if (blk_pc_request(rq)) { | 1242 | if (blk_pc_request(rq)) { |
1178 | timeout = rq->timeout; | 1243 | timeout = rq->timeout; |
1179 | expiry = NULL; | ||
1180 | } else { | 1244 | } else { |
1181 | timeout = ATAPI_WAIT_PC; | 1245 | timeout = ATAPI_WAIT_PC; |
1182 | expiry = cdrom_timer_expiry; | 1246 | if (!blk_fs_request(rq)) |
1247 | expiry = cdrom_timer_expiry; | ||
1183 | } | 1248 | } |
1184 | 1249 | ||
1185 | ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry); | 1250 | ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry); |
@@ -1202,155 +1267,6 @@ end_request: | |||
1202 | return ide_stopped; | 1267 | return ide_stopped; |
1203 | } | 1268 | } |
1204 | 1269 | ||
1205 | static ide_startstop_t cdrom_rw_intr(ide_drive_t *drive) | ||
1206 | { | ||
1207 | struct cdrom_info *info = drive->driver_data; | ||
1208 | struct request *rq = HWGROUP(drive)->rq; | ||
1209 | xfer_func_t *xferfunc; | ||
1210 | int stat, ireason, len, thislen, uptodate, nskip; | ||
1211 | int dma_error = 0, dma = info->dma, write = rq_data_dir(rq) == WRITE; | ||
1212 | u8 lowcyl = 0, highcyl = 0; | ||
1213 | |||
1214 | /* Check for errors. */ | ||
1215 | if (dma) { | ||
1216 | info->dma = 0; | ||
1217 | dma_error = HWIF(drive)->ide_dma_end(drive); | ||
1218 | if (dma_error) { | ||
1219 | printk(KERN_ERR "%s: DMA %s error\n", drive->name, | ||
1220 | write ? "write" : "read"); | ||
1221 | ide_dma_off(drive); | ||
1222 | } | ||
1223 | } | ||
1224 | |||
1225 | if (cdrom_decode_status(drive, 0, &stat)) | ||
1226 | return ide_stopped; | ||
1227 | |||
1228 | /* | ||
1229 | * using dma, transfer is complete now | ||
1230 | */ | ||
1231 | if (dma) { | ||
1232 | if (dma_error) | ||
1233 | return ide_error(drive, "dma error", stat); | ||
1234 | |||
1235 | ide_end_request(drive, 1, rq->nr_sectors); | ||
1236 | return ide_stopped; | ||
1237 | } | ||
1238 | |||
1239 | /* Read the interrupt reason and the transfer length. */ | ||
1240 | ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; | ||
1241 | lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); | ||
1242 | highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); | ||
1243 | |||
1244 | len = lowcyl + (256 * highcyl); | ||
1245 | |||
1246 | /* If DRQ is clear, the command has completed. */ | ||
1247 | if ((stat & DRQ_STAT) == 0) { | ||
1248 | /* | ||
1249 | * If we're not done reading/writing, complain. | ||
1250 | * Otherwise, complete the command normally. | ||
1251 | */ | ||
1252 | uptodate = 1; | ||
1253 | if (rq->current_nr_sectors > 0) { | ||
1254 | printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n", | ||
1255 | drive->name, __FUNCTION__, | ||
1256 | rq->current_nr_sectors); | ||
1257 | if (!write) | ||
1258 | rq->cmd_flags |= REQ_FAILED; | ||
1259 | uptodate = 0; | ||
1260 | } | ||
1261 | cdrom_end_request(drive, uptodate); | ||
1262 | return ide_stopped; | ||
1263 | } | ||
1264 | |||
1265 | thislen = len; | ||
1266 | |||
1267 | /* Check that the drive is expecting to do the same thing we are. */ | ||
1268 | if (write) { | ||
1269 | if (cdrom_write_check_ireason(drive, len, ireason)) | ||
1270 | return ide_stopped; | ||
1271 | |||
1272 | xferfunc = HWIF(drive)->atapi_output_bytes; | ||
1273 | } else { | ||
1274 | if (cdrom_read_check_ireason(drive, len, ireason)) | ||
1275 | return ide_stopped; | ||
1276 | |||
1277 | if (ide_cd_check_transfer_size(drive, len)) { | ||
1278 | cdrom_end_request(drive, 0); | ||
1279 | return ide_stopped; | ||
1280 | } | ||
1281 | |||
1282 | /* | ||
1283 | * First, figure out if we need to bit-bucket | ||
1284 | * any of the leading sectors. | ||
1285 | */ | ||
1286 | nskip = min_t(int, rq->current_nr_sectors | ||
1287 | - bio_cur_sectors(rq->bio), | ||
1288 | thislen >> 9); | ||
1289 | |||
1290 | if (nskip > 0) { | ||
1291 | ide_cd_drain_data(drive, nskip); | ||
1292 | rq->current_nr_sectors -= nskip; | ||
1293 | thislen -= (nskip << 9); | ||
1294 | } | ||
1295 | |||
1296 | xferfunc = HWIF(drive)->atapi_input_bytes; | ||
1297 | } | ||
1298 | |||
1299 | /* | ||
1300 | * now loop and read/write the data | ||
1301 | */ | ||
1302 | while (thislen > 0) { | ||
1303 | u8 *ptr = NULL; | ||
1304 | int blen; | ||
1305 | |||
1306 | if (rq->bio) { | ||
1307 | ptr = rq->buffer; | ||
1308 | blen = rq->current_nr_sectors << 9; | ||
1309 | } | ||
1310 | |||
1311 | if (!ptr) { | ||
1312 | if (!write) | ||
1313 | /* | ||
1314 | * If the buffers are full, cache the rest | ||
1315 | * of the data in our internal buffer. | ||
1316 | */ | ||
1317 | cdrom_buffer_sectors(drive, rq->sector, | ||
1318 | thislen >> 9); | ||
1319 | else { | ||
1320 | printk(KERN_ERR "%s: %s: confused, missing " | ||
1321 | "data\n", | ||
1322 | drive->name, __FUNCTION__); | ||
1323 | blk_dump_rq_flags(rq, "cdrom_rw_intr, write"); | ||
1324 | } | ||
1325 | break; | ||
1326 | } | ||
1327 | |||
1328 | /* | ||
1329 | * Figure out how many sectors we can transfer | ||
1330 | */ | ||
1331 | if (blen > thislen) | ||
1332 | blen = thislen; | ||
1333 | |||
1334 | xferfunc(drive, ptr, blen); | ||
1335 | |||
1336 | thislen -= blen; | ||
1337 | rq->buffer += blen; | ||
1338 | rq->nr_sectors -= (blen >> 9); | ||
1339 | rq->current_nr_sectors -= (blen >> 9); | ||
1340 | rq->sector += (blen >> 9); | ||
1341 | |||
1342 | /* | ||
1343 | * current buffer complete, move on | ||
1344 | */ | ||
1345 | if (rq->current_nr_sectors == 0 && rq->nr_sectors) | ||
1346 | cdrom_end_request(drive, 1); | ||
1347 | } | ||
1348 | |||
1349 | /* re-arm handler */ | ||
1350 | ide_set_handler(drive, cdrom_rw_intr, ATAPI_WAIT_PC, NULL); | ||
1351 | return ide_started; | ||
1352 | } | ||
1353 | |||
1354 | static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | 1270 | static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) |
1355 | { | 1271 | { |
1356 | struct cdrom_info *cd = drive->driver_data; | 1272 | struct cdrom_info *cd = drive->driver_data; |