Commit 66c6ef7678939f2119eb649074babf5d5b2666f6

Authored by bellard
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++;