Commit 98087450722d974b814e19a056ea82699440c0a7
1 parent
02ba45c5
BMDMA support - CDROM fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@971 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
546 additions
and
26 deletions
hw/ide.c
@@ -299,6 +299,7 @@ typedef struct IDEState { | @@ -299,6 +299,7 @@ typedef struct IDEState { | ||
299 | int irq; | 299 | int irq; |
300 | openpic_t *openpic; | 300 | openpic_t *openpic; |
301 | PCIDevice *pci_dev; | 301 | PCIDevice *pci_dev; |
302 | + struct BMDMAState *bmdma; | ||
302 | int drive_serial; | 303 | int drive_serial; |
303 | /* ide regs */ | 304 | /* ide regs */ |
304 | uint8_t feature; | 305 | uint8_t feature; |
@@ -321,7 +322,11 @@ typedef struct IDEState { | @@ -321,7 +322,11 @@ typedef struct IDEState { | ||
321 | int elementary_transfer_size; | 322 | int elementary_transfer_size; |
322 | int io_buffer_index; | 323 | int io_buffer_index; |
323 | int lba; | 324 | int lba; |
324 | - /* transfer handling */ | 325 | + int cd_sector_size; |
326 | + int atapi_dma; /* true if dma is requested for the packet cmd */ | ||
327 | + /* ATA DMA state */ | ||
328 | + int io_buffer_size; | ||
329 | + /* PIO transfer handling */ | ||
325 | int req_nb_sectors; /* number of sectors per interrupt */ | 330 | int req_nb_sectors; /* number of sectors per interrupt */ |
326 | EndTransferFunc *end_transfer_func; | 331 | EndTransferFunc *end_transfer_func; |
327 | uint8_t *data_ptr; | 332 | uint8_t *data_ptr; |
@@ -329,6 +334,34 @@ typedef struct IDEState { | @@ -329,6 +334,34 @@ typedef struct IDEState { | ||
329 | uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; | 334 | uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; |
330 | } IDEState; | 335 | } IDEState; |
331 | 336 | ||
337 | +#define BM_STATUS_DMAING 0x01 | ||
338 | +#define BM_STATUS_ERROR 0x02 | ||
339 | +#define BM_STATUS_INT 0x04 | ||
340 | + | ||
341 | +#define BM_CMD_START 0x01 | ||
342 | +#define BM_CMD_READ 0x08 | ||
343 | + | ||
344 | +typedef int IDEDMAFunc(IDEState *s, | ||
345 | + target_phys_addr_t phys_addr, | ||
346 | + int transfer_size1); | ||
347 | + | ||
348 | +typedef struct BMDMAState { | ||
349 | + uint8_t cmd; | ||
350 | + uint8_t status; | ||
351 | + uint32_t addr; | ||
352 | + /* current transfer state */ | ||
353 | + IDEState *ide_if; | ||
354 | + IDEDMAFunc *dma_cb; | ||
355 | +} BMDMAState; | ||
356 | + | ||
357 | +typedef struct PCIIDEState { | ||
358 | + PCIDevice dev; | ||
359 | + IDEState ide_if[4]; | ||
360 | + BMDMAState bmdma[2]; | ||
361 | +} PCIIDEState; | ||
362 | + | ||
363 | +static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb); | ||
364 | + | ||
332 | static void padstr(char *str, const char *src, int len) | 365 | static void padstr(char *str, const char *src, int len) |
333 | { | 366 | { |
334 | int i, v; | 367 | int i, v; |
@@ -554,6 +587,59 @@ static void ide_sector_read(IDEState *s) | @@ -554,6 +587,59 @@ static void ide_sector_read(IDEState *s) | ||
554 | } | 587 | } |
555 | } | 588 | } |
556 | 589 | ||
590 | +static int ide_read_dma_cb(IDEState *s, | ||
591 | + target_phys_addr_t phys_addr, | ||
592 | + int transfer_size1) | ||
593 | +{ | ||
594 | + int len, transfer_size, n; | ||
595 | + int64_t sector_num; | ||
596 | + | ||
597 | + transfer_size = transfer_size1; | ||
598 | + while (transfer_size > 0) { | ||
599 | + len = s->io_buffer_size - s->io_buffer_index; | ||
600 | + if (len <= 0) { | ||
601 | + /* transfert next data */ | ||
602 | + n = s->nsector; | ||
603 | + if (n == 0) | ||
604 | + break; | ||
605 | + if (n > MAX_MULT_SECTORS) | ||
606 | + n = MAX_MULT_SECTORS; | ||
607 | + sector_num = ide_get_sector(s); | ||
608 | + bdrv_read(s->bs, sector_num, s->io_buffer, n); | ||
609 | + s->io_buffer_index = 0; | ||
610 | + s->io_buffer_size = n * 512; | ||
611 | + len = s->io_buffer_size; | ||
612 | + sector_num += n; | ||
613 | + ide_set_sector(s, sector_num); | ||
614 | + s->nsector -= n; | ||
615 | + } | ||
616 | + if (len > transfer_size) | ||
617 | + len = transfer_size; | ||
618 | + cpu_physical_memory_write(phys_addr, | ||
619 | + s->io_buffer + s->io_buffer_index, len); | ||
620 | + s->io_buffer_index += len; | ||
621 | + transfer_size -= len; | ||
622 | + phys_addr += len; | ||
623 | + } | ||
624 | + if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) { | ||
625 | + s->status = READY_STAT | SEEK_STAT; | ||
626 | + ide_set_irq(s); | ||
627 | +#ifdef DEBUG_IDE_ATAPI | ||
628 | + printf("dma status=0x%x\n", s->status); | ||
629 | +#endif | ||
630 | + return 0; | ||
631 | + } | ||
632 | + return transfer_size1 - transfer_size; | ||
633 | +} | ||
634 | + | ||
635 | +static void ide_sector_read_dma(IDEState *s) | ||
636 | +{ | ||
637 | + s->status = READY_STAT | SEEK_STAT | DRQ_STAT; | ||
638 | + s->io_buffer_index = 0; | ||
639 | + s->io_buffer_size = 0; | ||
640 | + ide_dma_start(s, ide_read_dma_cb); | ||
641 | +} | ||
642 | + | ||
557 | static void ide_sector_write(IDEState *s) | 643 | static void ide_sector_write(IDEState *s) |
558 | { | 644 | { |
559 | int64_t sector_num; | 645 | int64_t sector_num; |
@@ -582,6 +668,62 @@ static void ide_sector_write(IDEState *s) | @@ -582,6 +668,62 @@ static void ide_sector_write(IDEState *s) | ||
582 | ide_set_irq(s); | 668 | ide_set_irq(s); |
583 | } | 669 | } |
584 | 670 | ||
671 | +static int ide_write_dma_cb(IDEState *s, | ||
672 | + target_phys_addr_t phys_addr, | ||
673 | + int transfer_size1) | ||
674 | +{ | ||
675 | + int len, transfer_size, n; | ||
676 | + int64_t sector_num; | ||
677 | + | ||
678 | + transfer_size = transfer_size1; | ||
679 | + for(;;) { | ||
680 | + len = s->io_buffer_size - s->io_buffer_index; | ||
681 | + if (len == 0) { | ||
682 | + n = s->io_buffer_size >> 9; | ||
683 | + sector_num = ide_get_sector(s); | ||
684 | + bdrv_write(s->bs, sector_num, s->io_buffer, | ||
685 | + s->io_buffer_size >> 9); | ||
686 | + sector_num += n; | ||
687 | + ide_set_sector(s, sector_num); | ||
688 | + s->nsector -= n; | ||
689 | + n = s->nsector; | ||
690 | + if (n == 0) { | ||
691 | + /* end of transfer */ | ||
692 | + s->status = READY_STAT | SEEK_STAT; | ||
693 | + ide_set_irq(s); | ||
694 | + return 0; | ||
695 | + } | ||
696 | + if (n > MAX_MULT_SECTORS) | ||
697 | + n = MAX_MULT_SECTORS; | ||
698 | + s->io_buffer_index = 0; | ||
699 | + s->io_buffer_size = n * 512; | ||
700 | + len = s->io_buffer_size; | ||
701 | + } | ||
702 | + if (transfer_size <= 0) | ||
703 | + break; | ||
704 | + if (len > transfer_size) | ||
705 | + len = transfer_size; | ||
706 | + cpu_physical_memory_read(phys_addr, | ||
707 | + s->io_buffer + s->io_buffer_index, len); | ||
708 | + s->io_buffer_index += len; | ||
709 | + transfer_size -= len; | ||
710 | + phys_addr += len; | ||
711 | + } | ||
712 | + return transfer_size1 - transfer_size; | ||
713 | +} | ||
714 | + | ||
715 | +static void ide_sector_write_dma(IDEState *s) | ||
716 | +{ | ||
717 | + int n; | ||
718 | + s->status = READY_STAT | SEEK_STAT | DRQ_STAT; | ||
719 | + n = s->nsector; | ||
720 | + if (n > MAX_MULT_SECTORS) | ||
721 | + n = MAX_MULT_SECTORS; | ||
722 | + s->io_buffer_index = 0; | ||
723 | + s->io_buffer_size = n * 512; | ||
724 | + ide_dma_start(s, ide_write_dma_cb); | ||
725 | +} | ||
726 | + | ||
585 | static void ide_atapi_cmd_ok(IDEState *s) | 727 | static void ide_atapi_cmd_ok(IDEState *s) |
586 | { | 728 | { |
587 | s->error = 0; | 729 | s->error = 0; |
@@ -627,6 +769,41 @@ static inline int ube32_to_cpu(const uint8_t *buf) | @@ -627,6 +769,41 @@ static inline int ube32_to_cpu(const uint8_t *buf) | ||
627 | return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; | 769 | return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; |
628 | } | 770 | } |
629 | 771 | ||
772 | +static void lba_to_msf(uint8_t *buf, int lba) | ||
773 | +{ | ||
774 | + lba += 150; | ||
775 | + buf[0] = (lba / 75) / 60; | ||
776 | + buf[1] = (lba / 75) % 60; | ||
777 | + buf[2] = lba % 75; | ||
778 | +} | ||
779 | + | ||
780 | +static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, | ||
781 | + int sector_size) | ||
782 | +{ | ||
783 | + switch(sector_size) { | ||
784 | + case 2048: | ||
785 | + bdrv_read(bs, (int64_t)lba << 2, buf, 4); | ||
786 | + break; | ||
787 | + case 2352: | ||
788 | + /* sync bytes */ | ||
789 | + buf[0] = 0x00; | ||
790 | + memset(buf + 1, 0xff, 11); | ||
791 | + buf += 12; | ||
792 | + /* MSF */ | ||
793 | + lba_to_msf(buf, lba); | ||
794 | + buf[3] = 0x01; /* mode 1 data */ | ||
795 | + buf += 4; | ||
796 | + /* data */ | ||
797 | + bdrv_read(bs, (int64_t)lba << 2, buf, 4); | ||
798 | + buf += 2048; | ||
799 | + /* ECC */ | ||
800 | + memset(buf, 0, 288); | ||
801 | + break; | ||
802 | + default: | ||
803 | + break; | ||
804 | + } | ||
805 | +} | ||
806 | + | ||
630 | /* The whole ATAPI transfer logic is handled in this function */ | 807 | /* The whole ATAPI transfer logic is handled in this function */ |
631 | static void ide_atapi_cmd_reply_end(IDEState *s) | 808 | static void ide_atapi_cmd_reply_end(IDEState *s) |
632 | { | 809 | { |
@@ -648,15 +825,15 @@ static void ide_atapi_cmd_reply_end(IDEState *s) | @@ -648,15 +825,15 @@ static void ide_atapi_cmd_reply_end(IDEState *s) | ||
648 | #endif | 825 | #endif |
649 | } else { | 826 | } else { |
650 | /* see if a new sector must be read */ | 827 | /* see if a new sector must be read */ |
651 | - if (s->lba != -1 && s->io_buffer_index >= 2048) { | ||
652 | - bdrv_read(s->bs, (int64_t)s->lba << 2, s->io_buffer, 4); | 828 | + if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { |
829 | + cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); | ||
653 | s->lba++; | 830 | s->lba++; |
654 | s->io_buffer_index = 0; | 831 | s->io_buffer_index = 0; |
655 | } | 832 | } |
656 | if (s->elementary_transfer_size > 0) { | 833 | if (s->elementary_transfer_size > 0) { |
657 | /* there are some data left to transmit in this elementary | 834 | /* there are some data left to transmit in this elementary |
658 | transfer */ | 835 | transfer */ |
659 | - size = 2048 - s->io_buffer_index; | 836 | + size = s->cd_sector_size - s->io_buffer_index; |
660 | if (size > s->elementary_transfer_size) | 837 | if (size > s->elementary_transfer_size) |
661 | size = s->elementary_transfer_size; | 838 | size = s->elementary_transfer_size; |
662 | ide_transfer_start(s, s->io_buffer + s->io_buffer_index, | 839 | ide_transfer_start(s, s->io_buffer + s->io_buffer_index, |
@@ -685,8 +862,8 @@ static void ide_atapi_cmd_reply_end(IDEState *s) | @@ -685,8 +862,8 @@ static void ide_atapi_cmd_reply_end(IDEState *s) | ||
685 | s->elementary_transfer_size = size; | 862 | s->elementary_transfer_size = size; |
686 | /* we cannot transmit more than one sector at a time */ | 863 | /* we cannot transmit more than one sector at a time */ |
687 | if (s->lba != -1) { | 864 | if (s->lba != -1) { |
688 | - if (size > (2048 - s->io_buffer_index)) | ||
689 | - size = (2048 - s->io_buffer_index); | 865 | + if (size > (s->cd_sector_size - s->io_buffer_index)) |
866 | + size = (s->cd_sector_size - s->io_buffer_index); | ||
690 | } | 867 | } |
691 | ide_transfer_start(s, s->io_buffer + s->io_buffer_index, | 868 | ide_transfer_start(s, s->io_buffer + s->io_buffer_index, |
692 | size, ide_atapi_cmd_reply_end); | 869 | size, ide_atapi_cmd_reply_end); |
@@ -716,21 +893,88 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) | @@ -716,21 +893,88 @@ static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) | ||
716 | } | 893 | } |
717 | 894 | ||
718 | /* start a CD-CDROM read command */ | 895 | /* start a CD-CDROM read command */ |
719 | -static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors) | 896 | +static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, |
897 | + int sector_size) | ||
720 | { | 898 | { |
721 | -#ifdef DEBUG_IDE_ATAPI | ||
722 | - printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors); | ||
723 | -#endif | ||
724 | s->lba = lba; | 899 | s->lba = lba; |
725 | - s->packet_transfer_size = nb_sectors * 2048; | 900 | + s->packet_transfer_size = nb_sectors * sector_size; |
726 | s->elementary_transfer_size = 0; | 901 | s->elementary_transfer_size = 0; |
727 | - s->io_buffer_index = 2048; | 902 | + s->io_buffer_index = sector_size; |
903 | + s->cd_sector_size = sector_size; | ||
728 | 904 | ||
729 | s->status = READY_STAT; | 905 | s->status = READY_STAT; |
730 | ide_atapi_cmd_reply_end(s); | 906 | ide_atapi_cmd_reply_end(s); |
731 | } | 907 | } |
732 | 908 | ||
909 | +/* ATAPI DMA support */ | ||
910 | +static int ide_atapi_cmd_read_dma_cb(IDEState *s, | ||
911 | + target_phys_addr_t phys_addr, | ||
912 | + int transfer_size1) | ||
913 | +{ | ||
914 | + int len, transfer_size; | ||
915 | + | ||
916 | + transfer_size = transfer_size1; | ||
917 | + while (transfer_size > 0) { | ||
918 | + if (s->packet_transfer_size <= 0) | ||
919 | + break; | ||
920 | + len = s->cd_sector_size - s->io_buffer_index; | ||
921 | + if (len <= 0) { | ||
922 | + /* transfert next data */ | ||
923 | + cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); | ||
924 | + s->lba++; | ||
925 | + s->io_buffer_index = 0; | ||
926 | + len = s->cd_sector_size; | ||
927 | + } | ||
928 | + if (len > transfer_size) | ||
929 | + len = transfer_size; | ||
930 | + cpu_physical_memory_write(phys_addr, | ||
931 | + s->io_buffer + s->io_buffer_index, len); | ||
932 | + s->packet_transfer_size -= len; | ||
933 | + s->io_buffer_index += len; | ||
934 | + transfer_size -= len; | ||
935 | + phys_addr += len; | ||
936 | + } | ||
937 | + if (s->packet_transfer_size <= 0) { | ||
938 | + s->status = READY_STAT; | ||
939 | + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; | ||
940 | + ide_set_irq(s); | ||
941 | +#ifdef DEBUG_IDE_ATAPI | ||
942 | + printf("dma status=0x%x\n", s->status); | ||
943 | +#endif | ||
944 | + return 0; | ||
945 | + } | ||
946 | + return transfer_size1 - transfer_size; | ||
947 | +} | ||
948 | + | ||
949 | +/* start a CD-CDROM read command with DMA */ | ||
950 | +/* XXX: test if DMA is available */ | ||
951 | +static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, | ||
952 | + int sector_size) | ||
953 | +{ | ||
954 | + s->lba = lba; | ||
955 | + s->packet_transfer_size = nb_sectors * sector_size; | ||
956 | + s->io_buffer_index = sector_size; | ||
957 | + s->cd_sector_size = sector_size; | ||
958 | + | ||
959 | + s->status = READY_STAT | DRQ_STAT; | ||
960 | + ide_dma_start(s, ide_atapi_cmd_read_dma_cb); | ||
961 | +} | ||
962 | + | ||
963 | +static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, | ||
964 | + int sector_size) | ||
965 | +{ | ||
966 | +#ifdef DEBUG_IDE_ATAPI | ||
967 | + printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors); | ||
968 | +#endif | ||
969 | + if (s->atapi_dma) { | ||
970 | + ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size); | ||
971 | + } else { | ||
972 | + ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size); | ||
973 | + } | ||
974 | +} | ||
975 | + | ||
733 | /* same toc as bochs. Return -1 if error or the toc length */ | 976 | /* same toc as bochs. Return -1 if error or the toc length */ |
977 | +/* XXX: check this */ | ||
734 | static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | 978 | static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) |
735 | { | 979 | { |
736 | uint8_t *q; | 980 | uint8_t *q; |
@@ -739,8 +983,8 @@ static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | @@ -739,8 +983,8 @@ static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | ||
739 | if (start_track > 1 && start_track != 0xaa) | 983 | if (start_track > 1 && start_track != 0xaa) |
740 | return -1; | 984 | return -1; |
741 | q = buf + 2; | 985 | q = buf + 2; |
742 | - *q++ = 1; | ||
743 | - *q++ = 1; | 986 | + *q++ = 1; /* first session */ |
987 | + *q++ = 1; /* last session */ | ||
744 | if (start_track <= 1) { | 988 | if (start_track <= 1) { |
745 | *q++ = 0; /* reserved */ | 989 | *q++ = 0; /* reserved */ |
746 | *q++ = 0x14; /* ADR, control */ | 990 | *q++ = 0x14; /* ADR, control */ |
@@ -765,9 +1009,8 @@ static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | @@ -765,9 +1009,8 @@ static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | ||
765 | nb_sectors = s->nb_sectors >> 2; | 1009 | nb_sectors = s->nb_sectors >> 2; |
766 | if (msf) { | 1010 | if (msf) { |
767 | *q++ = 0; /* reserved */ | 1011 | *q++ = 0; /* reserved */ |
768 | - *q++ = ((nb_sectors + 150) / 75) / 60; | ||
769 | - *q++ = ((nb_sectors + 150) / 75) % 60; | ||
770 | - *q++ = (nb_sectors + 150) % 75; | 1012 | + lba_to_msf(q, nb_sectors); |
1013 | + q += 3; | ||
771 | } else { | 1014 | } else { |
772 | cpu_to_ube32(q, nb_sectors); | 1015 | cpu_to_ube32(q, nb_sectors); |
773 | q += 4; | 1016 | q += 4; |
@@ -777,6 +1020,75 @@ static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | @@ -777,6 +1020,75 @@ static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) | ||
777 | return len; | 1020 | return len; |
778 | } | 1021 | } |
779 | 1022 | ||
1023 | +/* mostly same info as PearPc */ | ||
1024 | +static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf, | ||
1025 | + int session_num) | ||
1026 | +{ | ||
1027 | + uint8_t *q; | ||
1028 | + int nb_sectors, len; | ||
1029 | + | ||
1030 | + q = buf + 2; | ||
1031 | + *q++ = 1; /* first session */ | ||
1032 | + *q++ = 1; /* last session */ | ||
1033 | + | ||
1034 | + *q++ = 1; /* session number */ | ||
1035 | + *q++ = 0x14; /* data track */ | ||
1036 | + *q++ = 0; /* track number */ | ||
1037 | + *q++ = 0xa0; /* lead-in */ | ||
1038 | + *q++ = 0; /* min */ | ||
1039 | + *q++ = 0; /* sec */ | ||
1040 | + *q++ = 0; /* frame */ | ||
1041 | + *q++ = 0; | ||
1042 | + *q++ = 1; /* first track */ | ||
1043 | + *q++ = 0x00; /* disk type */ | ||
1044 | + *q++ = 0x00; | ||
1045 | + | ||
1046 | + *q++ = 1; /* session number */ | ||
1047 | + *q++ = 0x14; /* data track */ | ||
1048 | + *q++ = 0; /* track number */ | ||
1049 | + *q++ = 0xa1; | ||
1050 | + *q++ = 0; /* min */ | ||
1051 | + *q++ = 0; /* sec */ | ||
1052 | + *q++ = 0; /* frame */ | ||
1053 | + *q++ = 0; | ||
1054 | + *q++ = 1; /* last track */ | ||
1055 | + *q++ = 0x00; | ||
1056 | + *q++ = 0x00; | ||
1057 | + | ||
1058 | + *q++ = 1; /* session number */ | ||
1059 | + *q++ = 0x14; /* data track */ | ||
1060 | + *q++ = 0; /* track number */ | ||
1061 | + *q++ = 0xa2; /* lead-out */ | ||
1062 | + *q++ = 0; /* min */ | ||
1063 | + *q++ = 0; /* sec */ | ||
1064 | + *q++ = 0; /* frame */ | ||
1065 | + nb_sectors = s->nb_sectors >> 2; | ||
1066 | + if (msf) { | ||
1067 | + *q++ = 0; /* reserved */ | ||
1068 | + lba_to_msf(q, nb_sectors); | ||
1069 | + q += 3; | ||
1070 | + } else { | ||
1071 | + cpu_to_ube32(q, nb_sectors); | ||
1072 | + q += 4; | ||
1073 | + } | ||
1074 | + | ||
1075 | + *q++ = 1; /* session number */ | ||
1076 | + *q++ = 0x14; /* ADR, control */ | ||
1077 | + *q++ = 0; /* track number */ | ||
1078 | + *q++ = 1; /* point */ | ||
1079 | + *q++ = 0; /* min */ | ||
1080 | + *q++ = 0; /* sec */ | ||
1081 | + *q++ = 0; /* frame */ | ||
1082 | + *q++ = 0; | ||
1083 | + *q++ = 0; | ||
1084 | + *q++ = 0; | ||
1085 | + *q++ = 0; | ||
1086 | + | ||
1087 | + len = q - buf; | ||
1088 | + cpu_to_ube16(buf, len - 2); | ||
1089 | + return len; | ||
1090 | +} | ||
1091 | + | ||
780 | static void ide_atapi_cmd(IDEState *s) | 1092 | static void ide_atapi_cmd(IDEState *s) |
781 | { | 1093 | { |
782 | const uint8_t *packet; | 1094 | const uint8_t *packet; |
@@ -921,7 +1233,48 @@ static void ide_atapi_cmd(IDEState *s) | @@ -921,7 +1233,48 @@ static void ide_atapi_cmd(IDEState *s) | ||
921 | ASC_LOGICAL_BLOCK_OOR); | 1233 | ASC_LOGICAL_BLOCK_OOR); |
922 | break; | 1234 | break; |
923 | } | 1235 | } |
924 | - ide_atapi_cmd_read(s, lba, nb_sectors); | 1236 | + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); |
1237 | + } | ||
1238 | + break; | ||
1239 | + case GPCMD_READ_CD: | ||
1240 | + { | ||
1241 | + int nb_sectors, lba, transfer_request; | ||
1242 | + | ||
1243 | + if (!bdrv_is_inserted(s->bs)) { | ||
1244 | + ide_atapi_cmd_error(s, SENSE_NOT_READY, | ||
1245 | + ASC_MEDIUM_NOT_PRESENT); | ||
1246 | + break; | ||
1247 | + } | ||
1248 | + nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8]; | ||
1249 | + lba = ube32_to_cpu(packet + 2); | ||
1250 | + if (nb_sectors == 0) { | ||
1251 | + ide_atapi_cmd_ok(s); | ||
1252 | + break; | ||
1253 | + } | ||
1254 | + if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) { | ||
1255 | + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | ||
1256 | + ASC_LOGICAL_BLOCK_OOR); | ||
1257 | + break; | ||
1258 | + } | ||
1259 | + transfer_request = packet[9]; | ||
1260 | + switch(transfer_request & 0xf8) { | ||
1261 | + case 0x00: | ||
1262 | + /* nothing */ | ||
1263 | + ide_atapi_cmd_ok(s); | ||
1264 | + break; | ||
1265 | + case 0x10: | ||
1266 | + /* normal read */ | ||
1267 | + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); | ||
1268 | + break; | ||
1269 | + case 0xf8: | ||
1270 | + /* read all data */ | ||
1271 | + ide_atapi_cmd_read(s, lba, nb_sectors, 2352); | ||
1272 | + break; | ||
1273 | + default: | ||
1274 | + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | ||
1275 | + ASC_INV_FIELD_IN_CMD_PACKET); | ||
1276 | + break; | ||
1277 | + } | ||
925 | } | 1278 | } |
926 | break; | 1279 | break; |
927 | case GPCMD_SEEK: | 1280 | case GPCMD_SEEK: |
@@ -995,6 +1348,12 @@ static void ide_atapi_cmd(IDEState *s) | @@ -995,6 +1348,12 @@ static void ide_atapi_cmd(IDEState *s) | ||
995 | buf[3] = 0x01; | 1348 | buf[3] = 0x01; |
996 | ide_atapi_cmd_reply(s, 12, max_len); | 1349 | ide_atapi_cmd_reply(s, 12, max_len); |
997 | break; | 1350 | break; |
1351 | + case 2: | ||
1352 | + len = cdrom_read_toc_raw(s, buf, msf, start_track); | ||
1353 | + if (len < 0) | ||
1354 | + goto error_cmd; | ||
1355 | + ide_atapi_cmd_reply(s, len, max_len); | ||
1356 | + break; | ||
998 | default: | 1357 | default: |
999 | error_cmd: | 1358 | error_cmd: |
1000 | ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, | 1359 | ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, |
@@ -1169,6 +1528,18 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1169,6 +1528,18 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
1169 | n = s->req_nb_sectors; | 1528 | n = s->req_nb_sectors; |
1170 | ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); | 1529 | ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); |
1171 | break; | 1530 | break; |
1531 | + case WIN_READDMA: | ||
1532 | + case WIN_READDMA_ONCE: | ||
1533 | + if (!s->bs) | ||
1534 | + goto abort_cmd; | ||
1535 | + ide_sector_read_dma(s); | ||
1536 | + break; | ||
1537 | + case WIN_WRITEDMA: | ||
1538 | + case WIN_WRITEDMA_ONCE: | ||
1539 | + if (!s->bs) | ||
1540 | + goto abort_cmd; | ||
1541 | + ide_sector_write_dma(s); | ||
1542 | + break; | ||
1172 | case WIN_READ_NATIVE_MAX: | 1543 | case WIN_READ_NATIVE_MAX: |
1173 | ide_set_sector(s, s->nb_sectors - 1); | 1544 | ide_set_sector(s, s->nb_sectors - 1); |
1174 | s->status = READY_STAT; | 1545 | s->status = READY_STAT; |
@@ -1185,6 +1556,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1185,6 +1556,7 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
1185 | /* XXX: valid for CDROM ? */ | 1556 | /* XXX: valid for CDROM ? */ |
1186 | switch(s->feature) { | 1557 | switch(s->feature) { |
1187 | case 0x02: /* write cache enable */ | 1558 | case 0x02: /* write cache enable */ |
1559 | + case 0x03: /* set transfer mode */ | ||
1188 | case 0x82: /* write cache disable */ | 1560 | case 0x82: /* write cache disable */ |
1189 | case 0xaa: /* read look-ahead enable */ | 1561 | case 0xaa: /* read look-ahead enable */ |
1190 | case 0x55: /* read look-ahead disable */ | 1562 | case 0x55: /* read look-ahead disable */ |
@@ -1216,9 +1588,10 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -1216,9 +1588,10 @@ static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
1216 | case WIN_PACKETCMD: | 1588 | case WIN_PACKETCMD: |
1217 | if (!s->is_cdrom) | 1589 | if (!s->is_cdrom) |
1218 | goto abort_cmd; | 1590 | goto abort_cmd; |
1219 | - /* DMA or overlapping commands not supported */ | ||
1220 | - if ((s->feature & 0x03) != 0) | 1591 | + /* overlapping commands not supported */ |
1592 | + if (s->feature & 0x02) | ||
1221 | goto abort_cmd; | 1593 | goto abort_cmd; |
1594 | + s->atapi_dma = s->feature & 1; | ||
1222 | s->nsector = 1; | 1595 | s->nsector = 1; |
1223 | ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, | 1596 | ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, |
1224 | ide_atapi_cmd); | 1597 | ide_atapi_cmd); |
@@ -1549,11 +1922,6 @@ void isa_ide_init(int iobase, int iobase2, int irq, | @@ -1549,11 +1922,6 @@ void isa_ide_init(int iobase, int iobase2, int irq, | ||
1549 | /***********************************************************/ | 1922 | /***********************************************************/ |
1550 | /* PCI IDE definitions */ | 1923 | /* PCI IDE definitions */ |
1551 | 1924 | ||
1552 | -typedef struct PCIIDEState { | ||
1553 | - PCIDevice dev; | ||
1554 | - IDEState ide_if[4]; | ||
1555 | -} PCIIDEState; | ||
1556 | - | ||
1557 | static void ide_map(PCIDevice *pci_dev, int region_num, | 1925 | static void ide_map(PCIDevice *pci_dev, int region_num, |
1558 | uint32_t addr, uint32_t size, int type) | 1926 | uint32_t addr, uint32_t size, int type) |
1559 | { | 1927 | { |
@@ -1578,6 +1946,155 @@ static void ide_map(PCIDevice *pci_dev, int region_num, | @@ -1578,6 +1946,155 @@ static void ide_map(PCIDevice *pci_dev, int region_num, | ||
1578 | } | 1946 | } |
1579 | } | 1947 | } |
1580 | 1948 | ||
1949 | +/* XXX: full callback usage to prepare non blocking I/Os support - | ||
1950 | + error handling */ | ||
1951 | +static void ide_dma_loop(BMDMAState *bm) | ||
1952 | +{ | ||
1953 | + struct { | ||
1954 | + uint32_t addr; | ||
1955 | + uint32_t size; | ||
1956 | + } prd; | ||
1957 | + target_phys_addr_t cur_addr; | ||
1958 | + int len, i, len1; | ||
1959 | + | ||
1960 | + cur_addr = bm->addr; | ||
1961 | + /* at most one page to avoid hanging if erroneous parameters */ | ||
1962 | + for(i = 0; i < 512; i++) { | ||
1963 | + cpu_physical_memory_read(cur_addr, (uint8_t *)&prd, 8); | ||
1964 | + prd.addr = le32_to_cpu(prd.addr); | ||
1965 | + prd.size = le32_to_cpu(prd.size); | ||
1966 | +#ifdef DEBUG_IDE | ||
1967 | + printf("ide: dma: prd: %08x: addr=0x%08x size=0x%08x\n", | ||
1968 | + (int)cur_addr, prd.addr, prd.size); | ||
1969 | +#endif | ||
1970 | + len = prd.size & 0xfffe; | ||
1971 | + if (len == 0) | ||
1972 | + len = 0x10000; | ||
1973 | + while (len > 0) { | ||
1974 | + len1 = bm->dma_cb(bm->ide_if, prd.addr, len); | ||
1975 | + if (len1 == 0) | ||
1976 | + goto the_end; | ||
1977 | + prd.addr += len1; | ||
1978 | + len -= len1; | ||
1979 | + } | ||
1980 | + /* end of transfer */ | ||
1981 | + if (prd.size & 0x80000000) | ||
1982 | + break; | ||
1983 | + cur_addr += 8; | ||
1984 | + } | ||
1985 | + /* end of transfer */ | ||
1986 | + the_end: | ||
1987 | + bm->status &= ~BM_STATUS_DMAING; | ||
1988 | + bm->status |= BM_STATUS_INT; | ||
1989 | + bm->dma_cb = NULL; | ||
1990 | + bm->ide_if = NULL; | ||
1991 | +} | ||
1992 | + | ||
1993 | +static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb) | ||
1994 | +{ | ||
1995 | + BMDMAState *bm = s->bmdma; | ||
1996 | + if(!bm) | ||
1997 | + return; | ||
1998 | + bm->ide_if = s; | ||
1999 | + bm->dma_cb = dma_cb; | ||
2000 | + if (bm->status & BM_STATUS_DMAING) { | ||
2001 | + ide_dma_loop(bm); | ||
2002 | + } | ||
2003 | +} | ||
2004 | + | ||
2005 | +static uint32_t bmdma_cmd_readb(void *opaque, uint32_t addr) | ||
2006 | +{ | ||
2007 | + BMDMAState *bm = opaque; | ||
2008 | + uint32_t val; | ||
2009 | + val = bm->cmd; | ||
2010 | +#ifdef DEBUG_IDE | ||
2011 | + printf("%s: 0x%08x\n", __func__, val); | ||
2012 | +#endif | ||
2013 | + return val; | ||
2014 | +} | ||
2015 | + | ||
2016 | +static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) | ||
2017 | +{ | ||
2018 | + BMDMAState *bm = opaque; | ||
2019 | +#ifdef DEBUG_IDE | ||
2020 | + printf("%s: 0x%08x\n", __func__, val); | ||
2021 | +#endif | ||
2022 | + if (!(val & BM_CMD_START)) { | ||
2023 | + /* XXX: do it better */ | ||
2024 | + bm->status &= ~BM_STATUS_DMAING; | ||
2025 | + bm->cmd = val & 0x09; | ||
2026 | + } else { | ||
2027 | + bm->status |= BM_STATUS_DMAING; | ||
2028 | + bm->cmd = val & 0x09; | ||
2029 | + /* start dma transfer if possible */ | ||
2030 | + if (bm->dma_cb) | ||
2031 | + ide_dma_loop(bm); | ||
2032 | + } | ||
2033 | +} | ||
2034 | + | ||
2035 | +static uint32_t bmdma_status_readb(void *opaque, uint32_t addr) | ||
2036 | +{ | ||
2037 | + BMDMAState *bm = opaque; | ||
2038 | + uint32_t val; | ||
2039 | + val = bm->status; | ||
2040 | +#ifdef DEBUG_IDE | ||
2041 | + printf("%s: 0x%08x\n", __func__, val); | ||
2042 | +#endif | ||
2043 | + return val; | ||
2044 | +} | ||
2045 | + | ||
2046 | +static void bmdma_status_writeb(void *opaque, uint32_t addr, uint32_t val) | ||
2047 | +{ | ||
2048 | + BMDMAState *bm = opaque; | ||
2049 | +#ifdef DEBUG_IDE | ||
2050 | + printf("%s: 0x%08x\n", __func__, val); | ||
2051 | +#endif | ||
2052 | + bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); | ||
2053 | +} | ||
2054 | + | ||
2055 | +static uint32_t bmdma_addr_readl(void *opaque, uint32_t addr) | ||
2056 | +{ | ||
2057 | + BMDMAState *bm = opaque; | ||
2058 | + uint32_t val; | ||
2059 | + val = bm->addr; | ||
2060 | +#ifdef DEBUG_IDE | ||
2061 | + printf("%s: 0x%08x\n", __func__, val); | ||
2062 | +#endif | ||
2063 | + return val; | ||
2064 | +} | ||
2065 | + | ||
2066 | +static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val) | ||
2067 | +{ | ||
2068 | + BMDMAState *bm = opaque; | ||
2069 | +#ifdef DEBUG_IDE | ||
2070 | + printf("%s: 0x%08x\n", __func__, val); | ||
2071 | +#endif | ||
2072 | + bm->addr = val & ~3; | ||
2073 | +} | ||
2074 | + | ||
2075 | +static void bmdma_map(PCIDevice *pci_dev, int region_num, | ||
2076 | + uint32_t addr, uint32_t size, int type) | ||
2077 | +{ | ||
2078 | + PCIIDEState *d = (PCIIDEState *)pci_dev; | ||
2079 | + int i; | ||
2080 | + | ||
2081 | + for(i = 0;i < 2; i++) { | ||
2082 | + BMDMAState *bm = &d->bmdma[i]; | ||
2083 | + d->ide_if[2 * i].bmdma = bm; | ||
2084 | + d->ide_if[2 * i + 1].bmdma = bm; | ||
2085 | + | ||
2086 | + register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); | ||
2087 | + register_ioport_read(addr, 1, 1, bmdma_cmd_readb, bm); | ||
2088 | + | ||
2089 | + register_ioport_write(addr + 2, 1, 1, bmdma_status_writeb, bm); | ||
2090 | + register_ioport_read(addr + 2, 1, 1, bmdma_status_readb, bm); | ||
2091 | + | ||
2092 | + register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); | ||
2093 | + register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); | ||
2094 | + addr += 8; | ||
2095 | + } | ||
2096 | +} | ||
2097 | + | ||
1581 | /* hd_table must contain 4 block drivers */ | 2098 | /* hd_table must contain 4 block drivers */ |
1582 | void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table) | 2099 | void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table) |
1583 | { | 2100 | { |
@@ -1610,6 +2127,8 @@ void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table) | @@ -1610,6 +2127,8 @@ void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table) | ||
1610 | PCI_ADDRESS_SPACE_IO, ide_map); | 2127 | PCI_ADDRESS_SPACE_IO, ide_map); |
1611 | pci_register_io_region((PCIDevice *)d, 3, 0x4, | 2128 | pci_register_io_region((PCIDevice *)d, 3, 0x4, |
1612 | PCI_ADDRESS_SPACE_IO, ide_map); | 2129 | PCI_ADDRESS_SPACE_IO, ide_map); |
2130 | + pci_register_io_region((PCIDevice *)d, 4, 0x10, | ||
2131 | + PCI_ADDRESS_SPACE_IO, bmdma_map); | ||
1613 | 2132 | ||
1614 | pci_conf[0x3d] = 0x01; // interrupt on pin 1 | 2133 | pci_conf[0x3d] = 0x01; // interrupt on pin 1 |
1615 | 2134 | ||
@@ -1640,7 +2159,8 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table) | @@ -1640,7 +2159,8 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table) | ||
1640 | pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage | 2159 | pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage |
1641 | pci_conf[0x0e] = 0x00; // header_type | 2160 | pci_conf[0x0e] = 0x00; // header_type |
1642 | 2161 | ||
1643 | - /* XXX: must add BMDMA support to be fully compliant */ | 2162 | + pci_register_io_region((PCIDevice *)d, 4, 0x10, |
2163 | + PCI_ADDRESS_SPACE_IO, bmdma_map); | ||
1644 | 2164 | ||
1645 | ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]); | 2165 | ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]); |
1646 | ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]); | 2166 | ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]); |