aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-02-01 17:09:28 -0500
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-02-01 17:09:28 -0500
commit0041e7c6ca9719309bef6a4754e4eb9566b37ae1 (patch)
tree204b36cb8c31d9ed6799f256f04d03a7870231f0 /drivers/ide
parent48ea0b216ba96d14228ee0cb4c964b3b495ff0a8 (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')
-rw-r--r--drivers/ide/ide-cd.c272
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
800static ide_startstop_t cdrom_rw_intr(ide_drive_t *); 800static 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 */
1032static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) 1027static 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
1205static 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
1354static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) 1270static 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;