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]); |