Commit 66c6ef7678939f2119eb649074babf5d5b2666f6
1 parent
ea185bbd
better support of removable media
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2123 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
69 additions
and
51 deletions
hw/ide.c
@@ -943,26 +943,44 @@ static void cd_data_to_raw(uint8_t *buf, int lba) | @@ -943,26 +943,44 @@ static void cd_data_to_raw(uint8_t *buf, int lba) | ||
943 | memset(buf, 0, 288); | 943 | memset(buf, 0, 288); |
944 | } | 944 | } |
945 | 945 | ||
946 | -static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, | 946 | +static int cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, |
947 | int sector_size) | 947 | int sector_size) |
948 | { | 948 | { |
949 | + int ret; | ||
950 | + | ||
949 | switch(sector_size) { | 951 | switch(sector_size) { |
950 | case 2048: | 952 | case 2048: |
951 | - bdrv_read(bs, (int64_t)lba << 2, buf, 4); | 953 | + ret = bdrv_read(bs, (int64_t)lba << 2, buf, 4); |
952 | break; | 954 | break; |
953 | case 2352: | 955 | case 2352: |
954 | - bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4); | 956 | + ret = bdrv_read(bs, (int64_t)lba << 2, buf + 16, 4); |
957 | + if (ret < 0) | ||
958 | + return ret; | ||
955 | cd_data_to_raw(buf, lba); | 959 | cd_data_to_raw(buf, lba); |
956 | break; | 960 | break; |
957 | default: | 961 | default: |
962 | + ret = -EIO; | ||
958 | break; | 963 | break; |
959 | } | 964 | } |
965 | + return ret; | ||
966 | +} | ||
967 | + | ||
968 | +static void ide_atapi_io_error(IDEState *s, int ret) | ||
969 | +{ | ||
970 | + /* XXX: handle more errors */ | ||
971 | + if (ret == -ENOMEDIUM) { | ||
972 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | ||
973 | + ASC_MEDIUM_NOT_PRESENT); | ||
974 | + } else { | ||
975 | + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | ||
976 | + ASC_LOGICAL_BLOCK_OOR); | ||
977 | + } | ||
960 | } | 978 | } |
961 | 979 | ||
962 | /* The whole ATAPI transfer logic is handled in this function */ | 980 | /* The whole ATAPI transfer logic is handled in this function */ |
963 | static void ide_atapi_cmd_reply_end(IDEState *s) | 981 | static void ide_atapi_cmd_reply_end(IDEState *s) |
964 | { | 982 | { |
965 | - int byte_count_limit, size; | 983 | + int byte_count_limit, size, ret; |
966 | #ifdef DEBUG_IDE_ATAPI | 984 | #ifdef DEBUG_IDE_ATAPI |
967 | printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", | 985 | printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", |
968 | s->packet_transfer_size, | 986 | s->packet_transfer_size, |
@@ -981,7 +999,12 @@ static void ide_atapi_cmd_reply_end(IDEState *s) | @@ -981,7 +999,12 @@ static void ide_atapi_cmd_reply_end(IDEState *s) | ||
981 | } else { | 999 | } else { |
982 | /* see if a new sector must be read */ | 1000 | /* see if a new sector must be read */ |
983 | if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { | 1001 | if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { |
984 | - cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); | 1002 | + ret = cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); |
1003 | + if (ret < 0) { | ||
1004 | + ide_transfer_stop(s); | ||
1005 | + ide_atapi_io_error(s, ret); | ||
1006 | + return; | ||
1007 | + } | ||
985 | s->lba++; | 1008 | s->lba++; |
986 | s->io_buffer_index = 0; | 1009 | s->io_buffer_index = 0; |
987 | } | 1010 | } |
@@ -1070,6 +1093,11 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) | @@ -1070,6 +1093,11 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) | ||
1070 | IDEState *s = bm->ide_if; | 1093 | IDEState *s = bm->ide_if; |
1071 | int data_offset, n; | 1094 | int data_offset, n; |
1072 | 1095 | ||
1096 | + if (ret < 0) { | ||
1097 | + ide_atapi_io_error(s, ret); | ||
1098 | + goto eot; | ||
1099 | + } | ||
1100 | + | ||
1073 | if (s->io_buffer_size > 0) { | 1101 | if (s->io_buffer_size > 0) { |
1074 | if (s->cd_sector_size == 2352) { | 1102 | if (s->cd_sector_size == 2352) { |
1075 | n = 1; | 1103 | n = 1; |
@@ -1114,6 +1142,12 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) | @@ -1114,6 +1142,12 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret) | ||
1114 | bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2, | 1142 | bm->aiocb = bdrv_aio_read(s->bs, (int64_t)s->lba << 2, |
1115 | s->io_buffer + data_offset, n * 4, | 1143 | s->io_buffer + data_offset, n * 4, |
1116 | ide_atapi_cmd_read_dma_cb, bm); | 1144 | ide_atapi_cmd_read_dma_cb, bm); |
1145 | + if (!bm->aiocb) { | ||
1146 | + /* Note: media not present is the most likely case */ | ||
1147 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | ||
1148 | + ASC_MEDIUM_NOT_PRESENT); | ||
1149 | + goto eot; | ||
1150 | + } | ||
1117 | } | 1151 | } |
1118 | 1152 | ||
1119 | /* start a CD-CDROM read command with DMA */ | 1153 | /* start a CD-CDROM read command with DMA */ |
@@ -1270,11 +1304,6 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1270,11 +1304,6 @@ static void ide_atapi_cmd(IDEState *s) | ||
1270 | { | 1304 | { |
1271 | int nb_sectors, lba; | 1305 | int nb_sectors, lba; |
1272 | 1306 | ||
1273 | - if (!bdrv_is_inserted(s->bs)) { | ||
1274 | - ide_atapi_cmd_error(s, SENSE_NOT_READY, | ||
1275 | - ASC_MEDIUM_NOT_PRESENT); | ||
1276 | - break; | ||
1277 | - } | ||
1278 | if (packet[0] == GPCMD_READ_10) | 1307 | if (packet[0] == GPCMD_READ_10) |
1279 | nb_sectors = ube16_to_cpu(packet + 7); | 1308 | nb_sectors = ube16_to_cpu(packet + 7); |
1280 | else | 1309 | else |
@@ -1284,11 +1313,6 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1284,11 +1313,6 @@ static void ide_atapi_cmd(IDEState *s) | ||
1284 | ide_atapi_cmd_ok(s); | 1313 | ide_atapi_cmd_ok(s); |
1285 | break; | 1314 | break; |
1286 | } | 1315 | } |
1287 | - if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) { | ||
1288 | - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | ||
1289 | - ASC_LOGICAL_BLOCK_OOR); | ||
1290 | - break; | ||
1291 | - } | ||
1292 | ide_atapi_cmd_read(s, lba, nb_sectors, 2048); | 1316 | ide_atapi_cmd_read(s, lba, nb_sectors, 2048); |
1293 | } | 1317 | } |
1294 | break; | 1318 | break; |
@@ -1296,22 +1320,12 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1296,22 +1320,12 @@ static void ide_atapi_cmd(IDEState *s) | ||
1296 | { | 1320 | { |
1297 | int nb_sectors, lba, transfer_request; | 1321 | int nb_sectors, lba, transfer_request; |
1298 | 1322 | ||
1299 | - if (!bdrv_is_inserted(s->bs)) { | ||
1300 | - ide_atapi_cmd_error(s, SENSE_NOT_READY, | ||
1301 | - ASC_MEDIUM_NOT_PRESENT); | ||
1302 | - break; | ||
1303 | - } | ||
1304 | nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8]; | 1323 | nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8]; |
1305 | lba = ube32_to_cpu(packet + 2); | 1324 | lba = ube32_to_cpu(packet + 2); |
1306 | if (nb_sectors == 0) { | 1325 | if (nb_sectors == 0) { |
1307 | ide_atapi_cmd_ok(s); | 1326 | ide_atapi_cmd_ok(s); |
1308 | break; | 1327 | break; |
1309 | } | 1328 | } |
1310 | - if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) { | ||
1311 | - ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | ||
1312 | - ASC_LOGICAL_BLOCK_OOR); | ||
1313 | - break; | ||
1314 | - } | ||
1315 | transfer_request = packet[9]; | 1329 | transfer_request = packet[9]; |
1316 | switch(transfer_request & 0xf8) { | 1330 | switch(transfer_request & 0xf8) { |
1317 | case 0x00: | 1331 | case 0x00: |
@@ -1336,13 +1350,17 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1336,13 +1350,17 @@ static void ide_atapi_cmd(IDEState *s) | ||
1336 | case GPCMD_SEEK: | 1350 | case GPCMD_SEEK: |
1337 | { | 1351 | { |
1338 | int lba; | 1352 | int lba; |
1339 | - if (!bdrv_is_inserted(s->bs)) { | 1353 | + int64_t total_sectors; |
1354 | + | ||
1355 | + bdrv_get_geometry(s->bs, &total_sectors); | ||
1356 | + total_sectors >>= 2; | ||
1357 | + if (total_sectors <= 0) { | ||
1340 | ide_atapi_cmd_error(s, SENSE_NOT_READY, | 1358 | ide_atapi_cmd_error(s, SENSE_NOT_READY, |
1341 | ASC_MEDIUM_NOT_PRESENT); | 1359 | ASC_MEDIUM_NOT_PRESENT); |
1342 | break; | 1360 | break; |
1343 | } | 1361 | } |
1344 | lba = ube32_to_cpu(packet + 2); | 1362 | lba = ube32_to_cpu(packet + 2); |
1345 | - if (((int64_t)lba << 2) > s->nb_sectors) { | 1363 | + if (lba >= total_sectors) { |
1346 | ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | 1364 | ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, |
1347 | ASC_LOGICAL_BLOCK_OOR); | 1365 | ASC_LOGICAL_BLOCK_OOR); |
1348 | break; | 1366 | break; |
@@ -1358,7 +1376,10 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1358,7 +1376,10 @@ static void ide_atapi_cmd(IDEState *s) | ||
1358 | 1376 | ||
1359 | if (eject && !start) { | 1377 | if (eject && !start) { |
1360 | /* eject the disk */ | 1378 | /* eject the disk */ |
1361 | - bdrv_close(s->bs); | 1379 | + bdrv_eject(s->bs, 1); |
1380 | + } else if (eject && start) { | ||
1381 | + /* close the tray */ | ||
1382 | + bdrv_eject(s->bs, 0); | ||
1362 | } | 1383 | } |
1363 | ide_atapi_cmd_ok(s); | 1384 | ide_atapi_cmd_ok(s); |
1364 | } | 1385 | } |
@@ -1379,8 +1400,11 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1379,8 +1400,11 @@ static void ide_atapi_cmd(IDEState *s) | ||
1379 | case GPCMD_READ_TOC_PMA_ATIP: | 1400 | case GPCMD_READ_TOC_PMA_ATIP: |
1380 | { | 1401 | { |
1381 | int format, msf, start_track, len; | 1402 | int format, msf, start_track, len; |
1403 | + int64_t total_sectors; | ||
1382 | 1404 | ||
1383 | - if (!bdrv_is_inserted(s->bs)) { | 1405 | + bdrv_get_geometry(s->bs, &total_sectors); |
1406 | + total_sectors >>= 2; | ||
1407 | + if (total_sectors <= 0) { | ||
1384 | ide_atapi_cmd_error(s, SENSE_NOT_READY, | 1408 | ide_atapi_cmd_error(s, SENSE_NOT_READY, |
1385 | ASC_MEDIUM_NOT_PRESENT); | 1409 | ASC_MEDIUM_NOT_PRESENT); |
1386 | break; | 1410 | break; |
@@ -1391,7 +1415,7 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1391,7 +1415,7 @@ static void ide_atapi_cmd(IDEState *s) | ||
1391 | start_track = packet[6]; | 1415 | start_track = packet[6]; |
1392 | switch(format) { | 1416 | switch(format) { |
1393 | case 0: | 1417 | case 0: |
1394 | - len = cdrom_read_toc(s->nb_sectors >> 2, buf, msf, start_track); | 1418 | + len = cdrom_read_toc(total_sectors, buf, msf, start_track); |
1395 | if (len < 0) | 1419 | if (len < 0) |
1396 | goto error_cmd; | 1420 | goto error_cmd; |
1397 | ide_atapi_cmd_reply(s, len, max_len); | 1421 | ide_atapi_cmd_reply(s, len, max_len); |
@@ -1405,7 +1429,7 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1405,7 +1429,7 @@ static void ide_atapi_cmd(IDEState *s) | ||
1405 | ide_atapi_cmd_reply(s, 12, max_len); | 1429 | ide_atapi_cmd_reply(s, 12, max_len); |
1406 | break; | 1430 | break; |
1407 | case 2: | 1431 | case 2: |
1408 | - len = cdrom_read_toc_raw(s->nb_sectors >> 2, buf, msf, start_track); | 1432 | + len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track); |
1409 | if (len < 0) | 1433 | if (len < 0) |
1410 | goto error_cmd; | 1434 | goto error_cmd; |
1411 | ide_atapi_cmd_reply(s, len, max_len); | 1435 | ide_atapi_cmd_reply(s, len, max_len); |
@@ -1419,15 +1443,21 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1419,15 +1443,21 @@ static void ide_atapi_cmd(IDEState *s) | ||
1419 | } | 1443 | } |
1420 | break; | 1444 | break; |
1421 | case GPCMD_READ_CDVD_CAPACITY: | 1445 | case GPCMD_READ_CDVD_CAPACITY: |
1422 | - if (!bdrv_is_inserted(s->bs)) { | ||
1423 | - ide_atapi_cmd_error(s, SENSE_NOT_READY, | ||
1424 | - ASC_MEDIUM_NOT_PRESENT); | ||
1425 | - break; | 1446 | + { |
1447 | + int64_t total_sectors; | ||
1448 | + | ||
1449 | + bdrv_get_geometry(s->bs, &total_sectors); | ||
1450 | + total_sectors >>= 2; | ||
1451 | + if (total_sectors <= 0) { | ||
1452 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | ||
1453 | + ASC_MEDIUM_NOT_PRESENT); | ||
1454 | + break; | ||
1455 | + } | ||
1456 | + /* NOTE: it is really the number of sectors minus 1 */ | ||
1457 | + cpu_to_ube32(buf, total_sectors - 1); | ||
1458 | + cpu_to_ube32(buf + 4, 2048); | ||
1459 | + ide_atapi_cmd_reply(s, 8, 8); | ||
1426 | } | 1460 | } |
1427 | - /* NOTE: it is really the number of sectors minus 1 */ | ||
1428 | - cpu_to_ube32(buf, (s->nb_sectors >> 2) - 1); | ||
1429 | - cpu_to_ube32(buf + 4, 2048); | ||
1430 | - ide_atapi_cmd_reply(s, 8, 8); | ||
1431 | break; | 1461 | break; |
1432 | case GPCMD_INQUIRY: | 1462 | case GPCMD_INQUIRY: |
1433 | max_len = packet[4]; | 1463 | max_len = packet[4]; |
@@ -1451,17 +1481,6 @@ static void ide_atapi_cmd(IDEState *s) | @@ -1451,17 +1481,6 @@ static void ide_atapi_cmd(IDEState *s) | ||
1451 | } | 1481 | } |
1452 | } | 1482 | } |
1453 | 1483 | ||
1454 | -/* called when the inserted state of the media has changed */ | ||
1455 | -static void cdrom_change_cb(void *opaque) | ||
1456 | -{ | ||
1457 | - IDEState *s = opaque; | ||
1458 | - int64_t nb_sectors; | ||
1459 | - | ||
1460 | - /* XXX: send interrupt too */ | ||
1461 | - bdrv_get_geometry(s->bs, &nb_sectors); | ||
1462 | - s->nb_sectors = nb_sectors; | ||
1463 | -} | ||
1464 | - | ||
1465 | static void ide_cmd_lba48_transform(IDEState *s, int lba48) | 1484 | static void ide_cmd_lba48_transform(IDEState *s, int lba48) |
1466 | { | 1485 | { |
1467 | s->lba48 = lba48; | 1486 | s->lba48 = lba48; |
@@ -2092,7 +2111,6 @@ static void ide_init2(IDEState *ide_state, | @@ -2092,7 +2111,6 @@ static void ide_init2(IDEState *ide_state, | ||
2092 | } | 2111 | } |
2093 | if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { | 2112 | if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { |
2094 | s->is_cdrom = 1; | 2113 | s->is_cdrom = 1; |
2095 | - bdrv_set_change_cb(s->bs, cdrom_change_cb, s); | ||
2096 | } | 2114 | } |
2097 | } | 2115 | } |
2098 | s->drive_serial = drive_serial++; | 2116 | s->drive_serial = drive_serial++; |