1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include "hw/ide/internal.h"
27#include "hw/scsi/scsi.h"
28#include "sysemu/block-backend.h"
29
30static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret);
31
32static void padstr8(uint8_t *buf, int buf_size, const char *src)
33{
34 int i;
35 for(i = 0; i < buf_size; i++) {
36 if (*src)
37 buf[i] = *src++;
38 else
39 buf[i] = ' ';
40 }
41}
42
43static inline void cpu_to_ube16(uint8_t *buf, int val)
44{
45 buf[0] = val >> 8;
46 buf[1] = val & 0xff;
47}
48
49static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
50{
51 buf[0] = val >> 24;
52 buf[1] = val >> 16;
53 buf[2] = val >> 8;
54 buf[3] = val & 0xff;
55}
56
57static inline int ube16_to_cpu(const uint8_t *buf)
58{
59 return (buf[0] << 8) | buf[1];
60}
61
62static inline int ube32_to_cpu(const uint8_t *buf)
63{
64 return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
65}
66
67static void lba_to_msf(uint8_t *buf, int lba)
68{
69 lba += 150;
70 buf[0] = (lba / 75) / 60;
71 buf[1] = (lba / 75) % 60;
72 buf[2] = lba % 75;
73}
74
75static inline int media_present(IDEState *s)
76{
77 return !s->tray_open && s->nb_sectors > 0;
78}
79
80
81static inline int media_is_dvd(IDEState *s)
82{
83 return (media_present(s) && s->nb_sectors > CD_MAX_SECTORS);
84}
85
86static inline int media_is_cd(IDEState *s)
87{
88 return (media_present(s) && s->nb_sectors <= CD_MAX_SECTORS);
89}
90
91static void cd_data_to_raw(uint8_t *buf, int lba)
92{
93
94 buf[0] = 0x00;
95 memset(buf + 1, 0xff, 10);
96 buf[11] = 0x00;
97 buf += 12;
98
99 lba_to_msf(buf, lba);
100 buf[3] = 0x01;
101 buf += 4;
102
103 buf += 2048;
104
105 memset(buf, 0, 288);
106}
107
108static int cd_read_sector(IDEState *s, int lba, uint8_t *buf, int sector_size)
109{
110 int ret;
111
112 switch(sector_size) {
113 case 2048:
114 block_acct_start(blk_get_stats(s->blk), &s->acct,
115 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
116 ret = blk_read(s->blk, (int64_t)lba << 2, buf, 4);
117 block_acct_done(blk_get_stats(s->blk), &s->acct);
118 break;
119 case 2352:
120 block_acct_start(blk_get_stats(s->blk), &s->acct,
121 4 * BDRV_SECTOR_SIZE, BLOCK_ACCT_READ);
122 ret = blk_read(s->blk, (int64_t)lba << 2, buf + 16, 4);
123 block_acct_done(blk_get_stats(s->blk), &s->acct);
124 if (ret < 0)
125 return ret;
126 cd_data_to_raw(buf, lba);
127 break;
128 default:
129 ret = -EIO;
130 break;
131 }
132 return ret;
133}
134
135void ide_atapi_cmd_ok(IDEState *s)
136{
137 s->error = 0;
138 s->status = READY_STAT | SEEK_STAT;
139 s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
140 ide_transfer_stop(s);
141 ide_set_irq(s->bus);
142}
143
144void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
145{
146#ifdef DEBUG_IDE_ATAPI
147 printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
148#endif
149 s->error = sense_key << 4;
150 s->status = READY_STAT | ERR_STAT;
151 s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
152 s->sense_key = sense_key;
153 s->asc = asc;
154 ide_transfer_stop(s);
155 ide_set_irq(s->bus);
156}
157
158void ide_atapi_io_error(IDEState *s, int ret)
159{
160
161 if (ret == -ENOMEDIUM) {
162 ide_atapi_cmd_error(s, NOT_READY,
163 ASC_MEDIUM_NOT_PRESENT);
164 } else {
165 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
166 ASC_LOGICAL_BLOCK_OOR);
167 }
168}
169
170
171void ide_atapi_cmd_reply_end(IDEState *s)
172{
173 int byte_count_limit, size, ret;
174#ifdef DEBUG_IDE_ATAPI
175 printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
176 s->packet_transfer_size,
177 s->elementary_transfer_size,
178 s->io_buffer_index);
179#endif
180 if (s->packet_transfer_size <= 0) {
181
182 ide_atapi_cmd_ok(s);
183 ide_set_irq(s->bus);
184#ifdef DEBUG_IDE_ATAPI
185 printf("status=0x%x\n", s->status);
186#endif
187 } else {
188
189 if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
190 ret = cd_read_sector(s, s->lba, s->io_buffer, s->cd_sector_size);
191 if (ret < 0) {
192 ide_atapi_io_error(s, ret);
193 return;
194 }
195 s->lba++;
196 s->io_buffer_index = 0;
197 }
198 if (s->elementary_transfer_size > 0) {
199
200
201 size = s->cd_sector_size - s->io_buffer_index;
202 if (size > s->elementary_transfer_size)
203 size = s->elementary_transfer_size;
204 s->packet_transfer_size -= size;
205 s->elementary_transfer_size -= size;
206 s->io_buffer_index += size;
207 ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
208 size, ide_atapi_cmd_reply_end);
209 } else {
210
211 s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
212 byte_count_limit = s->lcyl | (s->hcyl << 8);
213#ifdef DEBUG_IDE_ATAPI
214 printf("byte_count_limit=%d\n", byte_count_limit);
215#endif
216 if (byte_count_limit == 0xffff)
217 byte_count_limit--;
218 size = s->packet_transfer_size;
219 if (size > byte_count_limit) {
220
221 if (byte_count_limit & 1)
222 byte_count_limit--;
223 size = byte_count_limit;
224 }
225 s->lcyl = size;
226 s->hcyl = size >> 8;
227 s->elementary_transfer_size = size;
228
229 if (s->lba != -1) {
230 if (size > (s->cd_sector_size - s->io_buffer_index))
231 size = (s->cd_sector_size - s->io_buffer_index);
232 }
233 s->packet_transfer_size -= size;
234 s->elementary_transfer_size -= size;
235 s->io_buffer_index += size;
236 ide_transfer_start(s, s->io_buffer + s->io_buffer_index - size,
237 size, ide_atapi_cmd_reply_end);
238 ide_set_irq(s->bus);
239#ifdef DEBUG_IDE_ATAPI
240 printf("status=0x%x\n", s->status);
241#endif
242 }
243 }
244}
245
246
247static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
248{
249 if (size > max_size)
250 size = max_size;
251 s->lba = -1;
252 s->packet_transfer_size = size;
253 s->io_buffer_size = size;
254 s->elementary_transfer_size = 0;
255
256 if (s->atapi_dma) {
257 block_acct_start(blk_get_stats(s->blk), &s->acct, size,
258 BLOCK_ACCT_READ);
259 s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
260 ide_start_dma(s, ide_atapi_cmd_read_dma_cb);
261 } else {
262 s->status = READY_STAT | SEEK_STAT;
263 s->io_buffer_index = 0;
264 ide_atapi_cmd_reply_end(s);
265 }
266}
267
268
269static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
270 int sector_size)
271{
272 s->lba = lba;
273 s->packet_transfer_size = nb_sectors * sector_size;
274 s->elementary_transfer_size = 0;
275 s->io_buffer_index = sector_size;
276 s->cd_sector_size = sector_size;
277
278 s->status = READY_STAT | SEEK_STAT;
279 ide_atapi_cmd_reply_end(s);
280}
281
282static void ide_atapi_cmd_check_status(IDEState *s)
283{
284#ifdef DEBUG_IDE_ATAPI
285 printf("atapi_cmd_check_status\n");
286#endif
287 s->error = MC_ERR | (UNIT_ATTENTION << 4);
288 s->status = ERR_STAT;
289 s->nsector = 0;
290 ide_set_irq(s->bus);
291}
292
293
294
295static void ide_atapi_cmd_read_dma_cb(void *opaque, int ret)
296{
297 IDEState *s = opaque;
298 int data_offset, n;
299
300 if (ret < 0) {
301 ide_atapi_io_error(s, ret);
302 goto eot;
303 }
304
305 if (s->io_buffer_size > 0) {
306
307
308
309
310
311
312
313 if (s->lba != -1) {
314 if (s->cd_sector_size == 2352) {
315 n = 1;
316 cd_data_to_raw(s->io_buffer, s->lba);
317 } else {
318 n = s->io_buffer_size >> 11;
319 }
320 s->lba += n;
321 }
322 s->packet_transfer_size -= s->io_buffer_size;
323 if (s->bus->dma->ops->rw_buf(s->bus->dma, 1) == 0)
324 goto eot;
325 }
326
327 if (s->packet_transfer_size <= 0) {
328 s->status = READY_STAT | SEEK_STAT;
329 s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
330 ide_set_irq(s->bus);
331 goto eot;
332 }
333
334 s->io_buffer_index = 0;
335 if (s->cd_sector_size == 2352) {
336 n = 1;
337 s->io_buffer_size = s->cd_sector_size;
338 data_offset = 16;
339 } else {
340 n = s->packet_transfer_size >> 11;
341 if (n > (IDE_DMA_BUF_SECTORS / 4))
342 n = (IDE_DMA_BUF_SECTORS / 4);
343 s->io_buffer_size = n * 2048;
344 data_offset = 0;
345 }
346#ifdef DEBUG_AIO
347 printf("aio_read_cd: lba=%u n=%d\n", s->lba, n);
348#endif
349
350 s->bus->dma->iov.iov_base = (void *)(s->io_buffer + data_offset);
351 s->bus->dma->iov.iov_len = n * 4 * 512;
352 qemu_iovec_init_external(&s->bus->dma->qiov, &s->bus->dma->iov, 1);
353
354 s->bus->dma->aiocb = blk_aio_readv(s->blk, (int64_t)s->lba << 2,
355 &s->bus->dma->qiov, n * 4,
356 ide_atapi_cmd_read_dma_cb, s);
357 return;
358
359eot:
360 block_acct_done(blk_get_stats(s->blk), &s->acct);
361 ide_set_inactive(s, false);
362}
363
364
365
366static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
367 int sector_size)
368{
369 s->lba = lba;
370 s->packet_transfer_size = nb_sectors * sector_size;
371 s->io_buffer_size = 0;
372 s->cd_sector_size = sector_size;
373
374 block_acct_start(blk_get_stats(s->blk), &s->acct, s->packet_transfer_size,
375 BLOCK_ACCT_READ);
376
377
378 s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
379 ide_start_dma(s, ide_atapi_cmd_read_dma_cb);
380}
381
382static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
383 int sector_size)
384{
385#ifdef DEBUG_IDE_ATAPI
386 printf("read %s: LBA=%d nb_sectors=%d\n", s->atapi_dma ? "dma" : "pio",
387 lba, nb_sectors);
388#endif
389 if (s->atapi_dma) {
390 ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
391 } else {
392 ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);
393 }
394}
395
396
397
398
399
400void ide_atapi_dma_restart(IDEState *s)
401{
402
403
404
405
406
407
408
409
410 ide_atapi_cmd_error(s, MEDIUM_ERROR, ASC_NO_SEEK_COMPLETE);
411}
412
413static inline uint8_t ide_atapi_set_profile(uint8_t *buf, uint8_t *index,
414 uint16_t profile)
415{
416 uint8_t *buf_profile = buf + 12;
417
418 buf_profile += ((*index) * 4);
419 cpu_to_ube16 (buf_profile, profile);
420 buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7]));
421
422
423 (*index)++;
424 buf[11] += 4;
425
426 return 4;
427}
428
429static int ide_dvd_read_structure(IDEState *s, int format,
430 const uint8_t *packet, uint8_t *buf)
431{
432 switch (format) {
433 case 0x0:
434 {
435 int layer = packet[6];
436 uint64_t total_sectors;
437
438 if (layer != 0)
439 return -ASC_INV_FIELD_IN_CMD_PACKET;
440
441 total_sectors = s->nb_sectors >> 2;
442 if (total_sectors == 0) {
443 return -ASC_MEDIUM_NOT_PRESENT;
444 }
445
446 buf[4] = 1;
447 buf[5] = 0xf;
448 buf[6] = 1;
449 buf[7] = 0;
450
451
452 cpu_to_ube32(buf + 8, 0);
453 cpu_to_ube32(buf + 12, total_sectors - 1);
454 cpu_to_ube32(buf + 16, total_sectors - 1);
455
456
457 stw_be_p(buf, 2048 + 2);
458
459
460 return (2048 + 4);
461 }
462
463 case 0x01:
464 buf[4] = 0;
465 buf[5] = 0;
466
467
468 stw_be_p(buf, 4 + 2);
469
470
471 return (4 + 4);
472
473 case 0x03:
474 return -ASC_INV_FIELD_IN_CMD_PACKET;
475
476 case 0x04:
477
478 stw_be_p(buf, 2048 + 2);
479
480
481 return (2048 + 4);
482
483 case 0xff:
484
485
486
487
488
489 buf[4] = 0x00;
490 buf[5] = 0x40;
491 stw_be_p(buf + 6, 2048 + 4);
492
493 buf[8] = 0x01;
494 buf[9] = 0x40;
495 stw_be_p(buf + 10, 4 + 4);
496
497 buf[12] = 0x03;
498 buf[13] = 0x40;
499 stw_be_p(buf + 14, 188 + 4);
500
501 buf[16] = 0x04;
502 buf[17] = 0x40;
503 stw_be_p(buf + 18, 2048 + 4);
504
505
506 stw_be_p(buf, 16 + 2);
507
508
509 return (16 + 4);
510
511 default:
512 return -ASC_INV_FIELD_IN_CMD_PACKET;
513 }
514}
515
516static unsigned int event_status_media(IDEState *s,
517 uint8_t *buf)
518{
519 uint8_t event_code, media_status;
520
521 media_status = 0;
522 if (s->tray_open) {
523 media_status = MS_TRAY_OPEN;
524 } else if (blk_is_inserted(s->blk)) {
525 media_status = MS_MEDIA_PRESENT;
526 }
527
528
529 event_code = MEC_NO_CHANGE;
530 if (media_status != MS_TRAY_OPEN) {
531 if (s->events.new_media) {
532 event_code = MEC_NEW_MEDIA;
533 s->events.new_media = false;
534 } else if (s->events.eject_request) {
535 event_code = MEC_EJECT_REQUESTED;
536 s->events.eject_request = false;
537 }
538 }
539
540 buf[4] = event_code;
541 buf[5] = media_status;
542
543
544 buf[6] = 0;
545 buf[7] = 0;
546
547 return 8;
548}
549
550static void cmd_get_event_status_notification(IDEState *s,
551 uint8_t *buf)
552{
553 const uint8_t *packet = buf;
554
555 struct {
556 uint8_t opcode;
557 uint8_t polled;
558 uint8_t reserved2[2];
559 uint8_t class;
560 uint8_t reserved3[2];
561 uint16_t len;
562 uint8_t control;
563 } QEMU_PACKED *gesn_cdb;
564
565 struct {
566 uint16_t len;
567 uint8_t notification_class;
568 uint8_t supported_events;
569 } QEMU_PACKED *gesn_event_header;
570 unsigned int max_len, used_len;
571
572 gesn_cdb = (void *)packet;
573 gesn_event_header = (void *)buf;
574
575 max_len = be16_to_cpu(gesn_cdb->len);
576
577
578 if (!(gesn_cdb->polled & 0x01)) {
579
580 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
581 ASC_INV_FIELD_IN_CMD_PACKET);
582 return;
583 }
584
585
586
587
588
589
590
591
592
593
594
595 gesn_event_header->supported_events = 1 << GESN_MEDIA;
596
597
598
599
600
601
602 gesn_event_header->notification_class = 0;
603
604
605
606
607
608
609 if (gesn_cdb->class & (1 << GESN_MEDIA)) {
610 gesn_event_header->notification_class |= GESN_MEDIA;
611 used_len = event_status_media(s, buf);
612 } else {
613 gesn_event_header->notification_class = 0x80;
614 used_len = sizeof(*gesn_event_header);
615 }
616 gesn_event_header->len = cpu_to_be16(used_len
617 - sizeof(*gesn_event_header));
618 ide_atapi_cmd_reply(s, used_len, max_len);
619}
620
621static void cmd_request_sense(IDEState *s, uint8_t *buf)
622{
623 int max_len = buf[4];
624
625 memset(buf, 0, 18);
626 buf[0] = 0x70 | (1 << 7);
627 buf[2] = s->sense_key;
628 buf[7] = 10;
629 buf[12] = s->asc;
630
631 if (s->sense_key == UNIT_ATTENTION) {
632 s->sense_key = NO_SENSE;
633 }
634
635 ide_atapi_cmd_reply(s, 18, max_len);
636}
637
638static void cmd_inquiry(IDEState *s, uint8_t *buf)
639{
640 uint8_t page_code = buf[2];
641 int max_len = buf[4];
642
643 unsigned idx = 0;
644 unsigned size_idx;
645 unsigned preamble_len;
646
647
648
649 if (buf[1] & 0x01) {
650 preamble_len = 4;
651 size_idx = 3;
652
653 buf[idx++] = 0x05;
654 buf[idx++] = page_code;
655 buf[idx++] = 0x00;
656 idx++;
657
658 switch (page_code) {
659 case 0x00:
660
661 buf[idx++] = 0x00;
662 buf[idx++] = 0x83;
663 break;
664
665 case 0x83:
666
667
668
669
670
671 if (idx + 24 > max_len) {
672
673
674 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
675 ASC_DATA_PHASE_ERROR);
676 return;
677 }
678 buf[idx++] = 0x02;
679 buf[idx++] = 0x00;
680 buf[idx++] = 0x00;
681 buf[idx++] = 20;
682 padstr8(buf + idx, 20, s->drive_serial_str);
683 idx += 20;
684
685
686 if (idx + 72 > max_len) {
687
688 goto out;
689 }
690 buf[idx++] = 0x02;
691 buf[idx++] = 0x01;
692 buf[idx++] = 0x00;
693 buf[idx++] = 68;
694 padstr8(buf + idx, 8, "ATA");
695 idx += 8;
696 padstr8(buf + idx, 40, s->drive_model_str);
697 idx += 40;
698 padstr8(buf + idx, 20, s->drive_serial_str);
699 idx += 20;
700
701
702 if (s->wwn && (idx + 12 <= max_len)) {
703
704 buf[idx++] = 0x01;
705 buf[idx++] = 0x03;
706 buf[idx++] = 0x00;
707 buf[idx++] = 0x08;
708 stq_be_p(&buf[idx], s->wwn);
709 idx += 8;
710 }
711 break;
712
713 default:
714
715 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
716 ASC_INV_FIELD_IN_CMD_PACKET);
717 return;
718 }
719 } else {
720 preamble_len = 5;
721 size_idx = 4;
722
723 buf[0] = 0x05;
724 buf[1] = 0x80;
725 buf[2] = 0x00;
726 buf[3] = 0x21;
727
728 buf[5] = 0;
729 buf[6] = 0;
730 buf[7] = 0;
731 padstr8(buf + 8, 8, "QEMU");
732 padstr8(buf + 16, 16, "QEMU DVD-ROM");
733 padstr8(buf + 32, 4, s->version);
734 idx = 36;
735 }
736
737 out:
738 buf[size_idx] = idx - preamble_len;
739 ide_atapi_cmd_reply(s, idx, max_len);
740 return;
741}
742
743static void cmd_get_configuration(IDEState *s, uint8_t *buf)
744{
745 uint32_t len;
746 uint8_t index = 0;
747 int max_len;
748
749
750 if (buf[2] != 0 || buf[3] != 0) {
751 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
752 ASC_INV_FIELD_IN_CMD_PACKET);
753 return;
754 }
755
756
757 max_len = ube16_to_cpu(buf + 7);
758
759
760
761
762
763
764
765
766 if (max_len > 512) {
767
768 max_len = 512;
769 }
770
771 memset(buf, 0, max_len);
772
773
774
775
776 if (media_is_dvd(s)) {
777 cpu_to_ube16(buf + 6, MMC_PROFILE_DVD_ROM);
778 } else if (media_is_cd(s)) {
779 cpu_to_ube16(buf + 6, MMC_PROFILE_CD_ROM);
780 }
781
782 buf[10] = 0x02 | 0x01;
783 len = 12;
784 len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_DVD_ROM);
785 len += ide_atapi_set_profile(buf, &index, MMC_PROFILE_CD_ROM);
786 cpu_to_ube32(buf, len - 4);
787
788 ide_atapi_cmd_reply(s, len, max_len);
789}
790
791static void cmd_mode_sense(IDEState *s, uint8_t *buf)
792{
793 int action, code;
794 int max_len;
795
796 max_len = ube16_to_cpu(buf + 7);
797 action = buf[2] >> 6;
798 code = buf[2] & 0x3f;
799
800 switch(action) {
801 case 0:
802 switch(code) {
803 case MODE_PAGE_R_W_ERROR:
804 cpu_to_ube16(&buf[0], 16 - 2);
805 buf[2] = 0x70;
806 buf[3] = 0;
807 buf[4] = 0;
808 buf[5] = 0;
809 buf[6] = 0;
810 buf[7] = 0;
811
812 buf[8] = MODE_PAGE_R_W_ERROR;
813 buf[9] = 16 - 10;
814 buf[10] = 0x00;
815 buf[11] = 0x05;
816 buf[12] = 0x00;
817 buf[13] = 0x00;
818 buf[14] = 0x00;
819 buf[15] = 0x00;
820 ide_atapi_cmd_reply(s, 16, max_len);
821 break;
822 case MODE_PAGE_AUDIO_CTL:
823 cpu_to_ube16(&buf[0], 24 - 2);
824 buf[2] = 0x70;
825 buf[3] = 0;
826 buf[4] = 0;
827 buf[5] = 0;
828 buf[6] = 0;
829 buf[7] = 0;
830
831 buf[8] = MODE_PAGE_AUDIO_CTL;
832 buf[9] = 24 - 10;
833
834 buf[17] = 0;
835 buf[19] = 0;
836 buf[21] = 0;
837 buf[23] = 0;
838
839 ide_atapi_cmd_reply(s, 24, max_len);
840 break;
841 case MODE_PAGE_CAPABILITIES:
842 cpu_to_ube16(&buf[0], 30 - 2);
843 buf[2] = 0x70;
844 buf[3] = 0;
845 buf[4] = 0;
846 buf[5] = 0;
847 buf[6] = 0;
848 buf[7] = 0;
849
850 buf[8] = MODE_PAGE_CAPABILITIES;
851 buf[9] = 30 - 10;
852 buf[10] = 0x3b;
853 buf[11] = 0x00;
854
855
856
857 buf[12] = 0x71;
858 buf[13] = 3 << 5;
859 buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
860 if (s->tray_locked) {
861 buf[14] |= 1 << 1;
862 }
863 buf[15] = 0x00;
864 cpu_to_ube16(&buf[16], 704);
865 buf[18] = 0;
866 buf[19] = 2;
867 cpu_to_ube16(&buf[20], 512);
868 cpu_to_ube16(&buf[22], 704);
869 buf[24] = 0;
870 buf[25] = 0;
871 buf[26] = 0;
872 buf[27] = 0;
873 buf[28] = 0;
874 buf[29] = 0;
875 ide_atapi_cmd_reply(s, 30, max_len);
876 break;
877 default:
878 goto error_cmd;
879 }
880 break;
881 case 1:
882 goto error_cmd;
883 case 2:
884 goto error_cmd;
885 default:
886 case 3:
887 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
888 ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
889 break;
890 }
891 return;
892
893error_cmd:
894 ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
895}
896
897static void cmd_test_unit_ready(IDEState *s, uint8_t *buf)
898{
899
900
901 ide_atapi_cmd_ok(s);
902}
903
904static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf)
905{
906 s->tray_locked = buf[4] & 1;
907 blk_lock_medium(s->blk, buf[4] & 1);
908 ide_atapi_cmd_ok(s);
909}
910
911static void cmd_read(IDEState *s, uint8_t* buf)
912{
913 int nb_sectors, lba;
914
915 if (buf[0] == GPCMD_READ_10) {
916 nb_sectors = ube16_to_cpu(buf + 7);
917 } else {
918 nb_sectors = ube32_to_cpu(buf + 6);
919 }
920
921 lba = ube32_to_cpu(buf + 2);
922 if (nb_sectors == 0) {
923 ide_atapi_cmd_ok(s);
924 return;
925 }
926
927 ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
928}
929
930static void cmd_read_cd(IDEState *s, uint8_t* buf)
931{
932 int nb_sectors, lba, transfer_request;
933
934 nb_sectors = (buf[6] << 16) | (buf[7] << 8) | buf[8];
935 lba = ube32_to_cpu(buf + 2);
936
937 if (nb_sectors == 0) {
938 ide_atapi_cmd_ok(s);
939 return;
940 }
941
942 transfer_request = buf[9];
943 switch(transfer_request & 0xf8) {
944 case 0x00:
945
946 ide_atapi_cmd_ok(s);
947 break;
948 case 0x10:
949
950 ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
951 break;
952 case 0xf8:
953
954 ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
955 break;
956 default:
957 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
958 ASC_INV_FIELD_IN_CMD_PACKET);
959 break;
960 }
961}
962
963static void cmd_seek(IDEState *s, uint8_t* buf)
964{
965 unsigned int lba;
966 uint64_t total_sectors = s->nb_sectors >> 2;
967
968 lba = ube32_to_cpu(buf + 2);
969 if (lba >= total_sectors) {
970 ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
971 return;
972 }
973
974 ide_atapi_cmd_ok(s);
975}
976
977static void cmd_start_stop_unit(IDEState *s, uint8_t* buf)
978{
979 int sense;
980 bool start = buf[4] & 1;
981 bool loej = buf[4] & 2;
982 int pwrcnd = buf[4] & 0xf0;
983
984 if (pwrcnd) {
985
986 ide_atapi_cmd_ok(s);
987 return;
988 }
989
990 if (loej) {
991 if (!start && !s->tray_open && s->tray_locked) {
992 sense = blk_is_inserted(s->blk)
993 ? NOT_READY : ILLEGAL_REQUEST;
994 ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED);
995 return;
996 }
997
998 if (s->tray_open != !start) {
999 blk_eject(s->blk, !start);
1000 s->tray_open = !start;
1001 }
1002 }
1003
1004 ide_atapi_cmd_ok(s);
1005}
1006
1007static void cmd_mechanism_status(IDEState *s, uint8_t* buf)
1008{
1009 int max_len = ube16_to_cpu(buf + 8);
1010
1011 cpu_to_ube16(buf, 0);
1012
1013 buf[2] = 0;
1014 buf[3] = 0;
1015 buf[4] = 0;
1016 buf[5] = 1;
1017 cpu_to_ube16(buf + 6, 0);
1018 ide_atapi_cmd_reply(s, 8, max_len);
1019}
1020
1021static void cmd_read_toc_pma_atip(IDEState *s, uint8_t* buf)
1022{
1023 int format, msf, start_track, len;
1024 int max_len;
1025 uint64_t total_sectors = s->nb_sectors >> 2;
1026
1027 max_len = ube16_to_cpu(buf + 7);
1028 format = buf[9] >> 6;
1029 msf = (buf[1] >> 1) & 1;
1030 start_track = buf[6];
1031
1032 switch(format) {
1033 case 0:
1034 len = cdrom_read_toc(total_sectors, buf, msf, start_track);
1035 if (len < 0)
1036 goto error_cmd;
1037 ide_atapi_cmd_reply(s, len, max_len);
1038 break;
1039 case 1:
1040
1041 memset(buf, 0, 12);
1042 buf[1] = 0x0a;
1043 buf[2] = 0x01;
1044 buf[3] = 0x01;
1045 ide_atapi_cmd_reply(s, 12, max_len);
1046 break;
1047 case 2:
1048 len = cdrom_read_toc_raw(total_sectors, buf, msf, start_track);
1049 if (len < 0)
1050 goto error_cmd;
1051 ide_atapi_cmd_reply(s, len, max_len);
1052 break;
1053 default:
1054 error_cmd:
1055 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
1056 ASC_INV_FIELD_IN_CMD_PACKET);
1057 }
1058}
1059
1060static void cmd_read_cdvd_capacity(IDEState *s, uint8_t* buf)
1061{
1062 uint64_t total_sectors = s->nb_sectors >> 2;
1063
1064
1065 cpu_to_ube32(buf, total_sectors - 1);
1066 cpu_to_ube32(buf + 4, 2048);
1067 ide_atapi_cmd_reply(s, 8, 8);
1068}
1069
1070static void cmd_read_disc_information(IDEState *s, uint8_t* buf)
1071{
1072 uint8_t type = buf[1] & 7;
1073 uint32_t max_len = ube16_to_cpu(buf + 7);
1074
1075
1076 if (type != 0) {
1077 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
1078 ASC_INV_FIELD_IN_CMD_PACKET);
1079 return;
1080 }
1081
1082 memset(buf, 0, 34);
1083 buf[1] = 32;
1084 buf[2] = 0xe;
1085 buf[3] = 1;
1086 buf[4] = 1;
1087 buf[5] = 1;
1088 buf[6] = 1;
1089 buf[7] = 0x20;
1090 buf[8] = 0x00;
1091
1092
1093
1094
1095
1096
1097 ide_atapi_cmd_reply(s, 34, max_len);
1098}
1099
1100static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf)
1101{
1102 int max_len;
1103 int media = buf[1];
1104 int format = buf[7];
1105 int ret;
1106
1107 max_len = ube16_to_cpu(buf + 8);
1108
1109 if (format < 0xff) {
1110 if (media_is_cd(s)) {
1111 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
1112 ASC_INCOMPATIBLE_FORMAT);
1113 return;
1114 } else if (!media_present(s)) {
1115 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
1116 ASC_INV_FIELD_IN_CMD_PACKET);
1117 return;
1118 }
1119 }
1120
1121 memset(buf, 0, max_len > IDE_DMA_BUF_SECTORS * 512 + 4 ?
1122 IDE_DMA_BUF_SECTORS * 512 + 4 : max_len);
1123
1124 switch (format) {
1125 case 0x00 ... 0x7f:
1126 case 0xff:
1127 if (media == 0) {
1128 ret = ide_dvd_read_structure(s, format, buf, buf);
1129
1130 if (ret < 0) {
1131 ide_atapi_cmd_error(s, ILLEGAL_REQUEST, -ret);
1132 } else {
1133 ide_atapi_cmd_reply(s, ret, max_len);
1134 }
1135
1136 break;
1137 }
1138
1139
1140
1141 case 0x80:
1142 case 0x81:
1143 case 0x82:
1144 case 0x83:
1145 case 0x90:
1146 case 0xc0:
1147 default:
1148 ide_atapi_cmd_error(s, ILLEGAL_REQUEST,
1149 ASC_INV_FIELD_IN_CMD_PACKET);
1150 break;
1151 }
1152}
1153
1154static void cmd_set_speed(IDEState *s, uint8_t* buf)
1155{
1156 ide_atapi_cmd_ok(s);
1157}
1158
1159enum {
1160
1161
1162
1163
1164 ALLOW_UA = 0x01,
1165
1166
1167
1168
1169
1170
1171 CHECK_READY = 0x02,
1172};
1173
1174static const struct {
1175 void (*handler)(IDEState *s, uint8_t *buf);
1176 int flags;
1177} atapi_cmd_table[0x100] = {
1178 [ 0x00 ] = { cmd_test_unit_ready, CHECK_READY },
1179 [ 0x03 ] = { cmd_request_sense, ALLOW_UA },
1180 [ 0x12 ] = { cmd_inquiry, ALLOW_UA },
1181 [ 0x1b ] = { cmd_start_stop_unit, 0 },
1182 [ 0x1e ] = { cmd_prevent_allow_medium_removal, 0 },
1183 [ 0x25 ] = { cmd_read_cdvd_capacity, CHECK_READY },
1184 [ 0x28 ] = { cmd_read, CHECK_READY },
1185 [ 0x2b ] = { cmd_seek, CHECK_READY },
1186 [ 0x43 ] = { cmd_read_toc_pma_atip, CHECK_READY },
1187 [ 0x46 ] = { cmd_get_configuration, ALLOW_UA },
1188 [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA },
1189 [ 0x51 ] = { cmd_read_disc_information, CHECK_READY },
1190 [ 0x5a ] = { cmd_mode_sense, 0 },
1191 [ 0xa8 ] = { cmd_read, CHECK_READY },
1192 [ 0xad ] = { cmd_read_dvd_structure, CHECK_READY },
1193 [ 0xbb ] = { cmd_set_speed, 0 },
1194 [ 0xbd ] = { cmd_mechanism_status, 0 },
1195 [ 0xbe ] = { cmd_read_cd, CHECK_READY },
1196
1197};
1198
1199void ide_atapi_cmd(IDEState *s)
1200{
1201 uint8_t *buf;
1202
1203 buf = s->io_buffer;
1204#ifdef DEBUG_IDE_ATAPI
1205 {
1206 int i;
1207 printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
1208 for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
1209 printf(" %02x", buf[i]);
1210 }
1211 printf("\n");
1212 }
1213#endif
1214
1215
1216
1217
1218
1219
1220 if (s->sense_key == UNIT_ATTENTION &&
1221 !(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA)) {
1222 ide_atapi_cmd_check_status(s);
1223 return;
1224 }
1225
1226
1227
1228
1229
1230
1231
1232 if (!(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA) &&
1233 !s->tray_open && blk_is_inserted(s->blk) && s->cdrom_changed) {
1234
1235 if (s->cdrom_changed == 1) {
1236 ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
1237 s->cdrom_changed = 2;
1238 } else {
1239 ide_atapi_cmd_error(s, UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED);
1240 s->cdrom_changed = 0;
1241 }
1242
1243 return;
1244 }
1245
1246
1247 if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) &&
1248 (!media_present(s) || !blk_is_inserted(s->blk)))
1249 {
1250 ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
1251 return;
1252 }
1253
1254
1255 if (atapi_cmd_table[s->io_buffer[0]].handler) {
1256 atapi_cmd_table[s->io_buffer[0]].handler(s, buf);
1257 return;
1258 }
1259
1260 ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE);
1261}
1262