diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 17:09:25 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 17:09:25 -0500 |
commit | ff1bfbc1f02f7c293a03a64722291c539deb162c (patch) | |
tree | 7d7a3fa534025f0673574655c74dd54e74e234f2 /drivers/ide/ide-cd.c | |
parent | 8b67ebf6dae0b0743bad1641e9691a1205adbf9e (diff) |
ide-cd: merge cdrom_pc_intr() and cdrom_newpc_intr()
Add handling of REQ_TYPE_{SENSE,ATA_PC} requests to cdrom_newpc_intr()
(please note that these requests never have 'bio' attached to them
and they never use DMA), then remove no longer needed cdrom_pc_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 | 171 |
1 files changed, 58 insertions, 113 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 6f698b4c275a..97d0c1375247 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -1061,90 +1061,7 @@ static void ide_cd_request_sense_fixup(struct request *rq) | |||
1061 | } | 1061 | } |
1062 | } | 1062 | } |
1063 | 1063 | ||
1064 | /* Interrupt routine for packet command completion. */ | 1064 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); |
1065 | static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive) | ||
1066 | { | ||
1067 | struct request *rq = HWGROUP(drive)->rq; | ||
1068 | xfer_func_t *xferfunc = NULL; | ||
1069 | int stat, ireason, len, thislen, write, update; | ||
1070 | u8 lowcyl = 0, highcyl = 0; | ||
1071 | |||
1072 | /* Check for errors. */ | ||
1073 | if (cdrom_decode_status(drive, 0, &stat)) | ||
1074 | return ide_stopped; | ||
1075 | |||
1076 | /* Read the interrupt reason and the transfer length. */ | ||
1077 | ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3; | ||
1078 | lowcyl = HWIF(drive)->INB(IDE_BCOUNTL_REG); | ||
1079 | highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG); | ||
1080 | |||
1081 | len = lowcyl + (256 * highcyl); | ||
1082 | |||
1083 | /* If DRQ is clear, the command has completed. | ||
1084 | Complain if we still have data left to transfer. */ | ||
1085 | if ((stat & DRQ_STAT) == 0) { | ||
1086 | ide_cd_request_sense_fixup(rq); | ||
1087 | update = rq->data_len ? 0 : 1; | ||
1088 | goto end_request; | ||
1089 | } | ||
1090 | |||
1091 | /* Figure out how much data to transfer. */ | ||
1092 | thislen = rq->data_len; | ||
1093 | if (thislen > len) | ||
1094 | thislen = len; | ||
1095 | |||
1096 | if (ireason == 0) { | ||
1097 | write = 1; | ||
1098 | xferfunc = HWIF(drive)->atapi_output_bytes; | ||
1099 | } else if (ireason == 2) { | ||
1100 | write = 0; | ||
1101 | xferfunc = HWIF(drive)->atapi_input_bytes; | ||
1102 | } | ||
1103 | |||
1104 | if (xferfunc) { | ||
1105 | if (!rq->data) { | ||
1106 | printk(KERN_ERR "%s: confused, missing data\n", | ||
1107 | drive->name); | ||
1108 | blk_dump_rq_flags(rq, write ? "cdrom_pc_intr, write" | ||
1109 | : "cdrom_pc_intr, read"); | ||
1110 | goto pad; | ||
1111 | } | ||
1112 | /* Transfer the data. */ | ||
1113 | xferfunc(drive, rq->data, thislen); | ||
1114 | |||
1115 | /* Keep count of how much data we've moved. */ | ||
1116 | len -= thislen; | ||
1117 | rq->data += thislen; | ||
1118 | rq->data_len -= thislen; | ||
1119 | |||
1120 | if (write && blk_sense_request(rq)) | ||
1121 | rq->sense_len += thislen; | ||
1122 | } else { | ||
1123 | printk (KERN_ERR "%s: cdrom_pc_intr: The drive " | ||
1124 | "appears confused (ireason = 0x%02x). " | ||
1125 | "Trying to recover by ending request.\n", | ||
1126 | drive->name, ireason); | ||
1127 | update = 0; | ||
1128 | goto end_request; | ||
1129 | } | ||
1130 | pad: | ||
1131 | /* | ||
1132 | * If we haven't moved enough data to satisfy the drive, | ||
1133 | * add some padding. | ||
1134 | */ | ||
1135 | if (len > 0) | ||
1136 | ide_cd_pad_transfer(drive, xferfunc, len); | ||
1137 | |||
1138 | /* Now we wait for another interrupt. */ | ||
1139 | ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry); | ||
1140 | return ide_started; | ||
1141 | |||
1142 | end_request: | ||
1143 | if (!update) | ||
1144 | rq->cmd_flags |= REQ_FAILED; | ||
1145 | cdrom_end_request(drive, update); | ||
1146 | return ide_stopped; | ||
1147 | } | ||
1148 | 1065 | ||
1149 | static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive) | 1066 | static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive) |
1150 | { | 1067 | { |
@@ -1154,10 +1071,9 @@ static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive) | |||
1154 | rq->timeout = ATAPI_WAIT_PC; | 1071 | rq->timeout = ATAPI_WAIT_PC; |
1155 | 1072 | ||
1156 | /* Send the command to the drive and return. */ | 1073 | /* Send the command to the drive and return. */ |
1157 | return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr); | 1074 | return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr); |
1158 | } | 1075 | } |
1159 | 1076 | ||
1160 | |||
1161 | static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) | 1077 | static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive) |
1162 | { | 1078 | { |
1163 | int len; | 1079 | int len; |
@@ -1263,27 +1179,27 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq) | |||
1263 | /* | 1179 | /* |
1264 | * best way to deal with dma that is not sector aligned right now... note | 1180 | * best way to deal with dma that is not sector aligned right now... note |
1265 | * that in this path we are not using ->data or ->buffer at all. this irs | 1181 | * that in this path we are not using ->data or ->buffer at all. this irs |
1266 | * can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the | 1182 | * can replace cdrom_read_intr() and cdrom_write_intr() in the future. |
1267 | * future. | ||
1268 | */ | 1183 | */ |
1269 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | 1184 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) |
1270 | { | 1185 | { |
1271 | struct cdrom_info *info = drive->driver_data; | 1186 | struct cdrom_info *info = drive->driver_data; |
1272 | struct request *rq = HWGROUP(drive)->rq; | 1187 | struct request *rq = HWGROUP(drive)->rq; |
1273 | int dma_error, dma, stat, ireason, len, thislen; | ||
1274 | u8 lowcyl, highcyl; | ||
1275 | xfer_func_t *xferfunc; | 1188 | xfer_func_t *xferfunc; |
1276 | unsigned long flags; | 1189 | ide_expiry_t *expiry; |
1190 | int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0; | ||
1191 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0; | ||
1192 | unsigned int timeout; | ||
1193 | u8 lowcyl, highcyl; | ||
1277 | 1194 | ||
1278 | /* Check for errors. */ | 1195 | /* Check for errors. */ |
1279 | dma_error = 0; | ||
1280 | dma = info->dma; | 1196 | dma = info->dma; |
1281 | if (dma) { | 1197 | if (dma) { |
1282 | info->dma = 0; | 1198 | info->dma = 0; |
1283 | dma_error = HWIF(drive)->ide_dma_end(drive); | 1199 | dma_error = HWIF(drive)->ide_dma_end(drive); |
1284 | if (dma_error) { | 1200 | if (dma_error) { |
1285 | printk(KERN_ERR "%s: DMA %s error\n", drive->name, | 1201 | printk(KERN_ERR "%s: DMA %s error\n", drive->name, |
1286 | rq_data_dir(rq) ? "write" : "read"); | 1202 | write ? "write" : "read"); |
1287 | ide_dma_off(drive); | 1203 | ide_dma_off(drive); |
1288 | } | 1204 | } |
1289 | } | 1205 | } |
@@ -1297,14 +1213,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1297 | if (dma) { | 1213 | if (dma) { |
1298 | if (dma_error) | 1214 | if (dma_error) |
1299 | return ide_error(drive, "dma error", stat); | 1215 | return ide_error(drive, "dma error", stat); |
1300 | 1216 | goto end_request; | |
1301 | spin_lock_irqsave(&ide_lock, flags); | ||
1302 | if (__blk_end_request(rq, 0, rq->data_len)) | ||
1303 | BUG(); | ||
1304 | HWGROUP(drive)->rq = NULL; | ||
1305 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1306 | |||
1307 | return ide_stopped; | ||
1308 | } | 1217 | } |
1309 | 1218 | ||
1310 | /* | 1219 | /* |
@@ -1323,34 +1232,43 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1323 | * If DRQ is clear, the command has completed. | 1232 | * If DRQ is clear, the command has completed. |
1324 | */ | 1233 | */ |
1325 | if ((stat & DRQ_STAT) == 0) { | 1234 | if ((stat & DRQ_STAT) == 0) { |
1326 | spin_lock_irqsave(&ide_lock, flags); | 1235 | if (!blk_pc_request(rq)) { |
1327 | if (__blk_end_request(rq, 0, rq->data_len)) | 1236 | ide_cd_request_sense_fixup(rq); |
1328 | BUG(); | 1237 | /* Complain if we still have data left to transfer. */ |
1329 | HWGROUP(drive)->rq = NULL; | 1238 | uptodate = rq->data_len ? 0 : 1; |
1330 | spin_unlock_irqrestore(&ide_lock, flags); | 1239 | } |
1331 | 1240 | goto end_request; | |
1332 | return ide_stopped; | ||
1333 | } | 1241 | } |
1334 | 1242 | ||
1335 | /* | 1243 | /* |
1336 | * check which way to transfer data | 1244 | * check which way to transfer data |
1337 | */ | 1245 | */ |
1338 | if (rq_data_dir(rq) == WRITE) { | 1246 | if (blk_pc_request(rq) && rq_data_dir(rq) == WRITE) { |
1339 | /* | 1247 | /* |
1340 | * write to drive | 1248 | * write to drive |
1341 | */ | 1249 | */ |
1342 | if (cdrom_write_check_ireason(drive, len, ireason)) | 1250 | if (cdrom_write_check_ireason(drive, len, ireason)) |
1343 | return ide_stopped; | 1251 | return ide_stopped; |
1344 | 1252 | } else if (blk_pc_request(rq)) { | |
1345 | xferfunc = HWIF(drive)->atapi_output_bytes; | ||
1346 | } else { | ||
1347 | /* | 1253 | /* |
1348 | * read from drive | 1254 | * read from drive |
1349 | */ | 1255 | */ |
1350 | if (cdrom_read_check_ireason(drive, len, ireason)) | 1256 | if (cdrom_read_check_ireason(drive, len, ireason)) |
1351 | return ide_stopped; | 1257 | return ide_stopped; |
1258 | } | ||
1352 | 1259 | ||
1260 | if (ireason == 0) { | ||
1261 | write = 1; | ||
1262 | xferfunc = HWIF(drive)->atapi_output_bytes; | ||
1263 | } else if (ireason == 2 || (ireason == 1 && blk_pc_request(rq))) { | ||
1264 | write = 0; | ||
1353 | xferfunc = HWIF(drive)->atapi_input_bytes; | 1265 | xferfunc = HWIF(drive)->atapi_input_bytes; |
1266 | } else { | ||
1267 | printk(KERN_ERR "%s: %s: The drive " | ||
1268 | "appears confused (ireason = 0x%02x). " | ||
1269 | "Trying to recover by ending request.\n", | ||
1270 | drive->name, __FUNCTION__, ireason); | ||
1271 | goto end_request; | ||
1354 | } | 1272 | } |
1355 | 1273 | ||
1356 | /* | 1274 | /* |
@@ -1399,14 +1317,41 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1399 | rq->data += blen; | 1317 | rq->data += blen; |
1400 | } | 1318 | } |
1401 | 1319 | ||
1320 | if (write && blk_sense_request(rq)) | ||
1321 | rq->sense_len += thislen; | ||
1322 | |||
1402 | /* | 1323 | /* |
1403 | * pad, if necessary | 1324 | * pad, if necessary |
1404 | */ | 1325 | */ |
1405 | if (len > 0) | 1326 | if (len > 0) |
1406 | ide_cd_pad_transfer(drive, xferfunc, len); | 1327 | ide_cd_pad_transfer(drive, xferfunc, len); |
1407 | 1328 | ||
1408 | ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL); | 1329 | if (blk_pc_request(rq)) { |
1330 | timeout = rq->timeout; | ||
1331 | expiry = NULL; | ||
1332 | } else { | ||
1333 | timeout = ATAPI_WAIT_PC; | ||
1334 | expiry = cdrom_timer_expiry; | ||
1335 | } | ||
1336 | |||
1337 | ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry); | ||
1409 | return ide_started; | 1338 | return ide_started; |
1339 | |||
1340 | end_request: | ||
1341 | if (blk_pc_request(rq)) { | ||
1342 | unsigned long flags; | ||
1343 | |||
1344 | spin_lock_irqsave(&ide_lock, flags); | ||
1345 | if (__blk_end_request(rq, 0, rq->data_len)) | ||
1346 | BUG(); | ||
1347 | HWGROUP(drive)->rq = NULL; | ||
1348 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1349 | } else { | ||
1350 | if (!uptodate) | ||
1351 | rq->cmd_flags |= REQ_FAILED; | ||
1352 | cdrom_end_request(drive, uptodate); | ||
1353 | } | ||
1354 | return ide_stopped; | ||
1410 | } | 1355 | } |
1411 | 1356 | ||
1412 | static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) | 1357 | static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) |