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