Revision 98087450 hw/ide.c
b/hw/ide.c | ||
---|---|---|
299 | 299 |
int irq; |
300 | 300 |
openpic_t *openpic; |
301 | 301 |
PCIDevice *pci_dev; |
302 |
struct BMDMAState *bmdma; |
|
302 | 303 |
int drive_serial; |
303 | 304 |
/* ide regs */ |
304 | 305 |
uint8_t feature; |
... | ... | |
321 | 322 |
int elementary_transfer_size; |
322 | 323 |
int io_buffer_index; |
323 | 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 | 330 |
int req_nb_sectors; /* number of sectors per interrupt */ |
326 | 331 |
EndTransferFunc *end_transfer_func; |
327 | 332 |
uint8_t *data_ptr; |
... | ... | |
329 | 334 |
uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; |
330 | 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 | 365 |
static void padstr(char *str, const char *src, int len) |
333 | 366 |
{ |
334 | 367 |
int i, v; |
... | ... | |
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 | 643 |
static void ide_sector_write(IDEState *s) |
558 | 644 |
{ |
559 | 645 |
int64_t sector_num; |
... | ... | |
582 | 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 | 727 |
static void ide_atapi_cmd_ok(IDEState *s) |
586 | 728 |
{ |
587 | 729 |
s->error = 0; |
... | ... | |
627 | 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 | 807 |
/* The whole ATAPI transfer logic is handled in this function */ |
631 | 808 |
static void ide_atapi_cmd_reply_end(IDEState *s) |
632 | 809 |
{ |
... | ... | |
648 | 825 |
#endif |
649 | 826 |
} else { |
650 | 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 | 830 |
s->lba++; |
654 | 831 |
s->io_buffer_index = 0; |
655 | 832 |
} |
656 | 833 |
if (s->elementary_transfer_size > 0) { |
657 | 834 |
/* there are some data left to transmit in this elementary |
658 | 835 |
transfer */ |
659 |
size = 2048 - s->io_buffer_index;
|
|
836 |
size = s->cd_sector_size - s->io_buffer_index;
|
|
660 | 837 |
if (size > s->elementary_transfer_size) |
661 | 838 |
size = s->elementary_transfer_size; |
662 | 839 |
ide_transfer_start(s, s->io_buffer + s->io_buffer_index, |
... | ... | |
685 | 862 |
s->elementary_transfer_size = size; |
686 | 863 |
/* we cannot transmit more than one sector at a time */ |
687 | 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 | 868 |
ide_transfer_start(s, s->io_buffer + s->io_buffer_index, |
692 | 869 |
size, ide_atapi_cmd_reply_end); |
... | ... | |
716 | 893 |
} |
717 | 894 |
|
718 | 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 | 899 |
s->lba = lba; |
725 |
s->packet_transfer_size = nb_sectors * 2048;
|
|
900 |
s->packet_transfer_size = nb_sectors * sector_size;
|
|
726 | 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 | 905 |
s->status = READY_STAT; |
730 | 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 | 976 |
/* same toc as bochs. Return -1 if error or the toc length */ |
977 |
/* XXX: check this */ |
|
734 | 978 |
static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) |
735 | 979 |
{ |
736 | 980 |
uint8_t *q; |
... | ... | |
739 | 983 |
if (start_track > 1 && start_track != 0xaa) |
740 | 984 |
return -1; |
741 | 985 |
q = buf + 2; |
742 |
*q++ = 1; |
|
743 |
*q++ = 1; |
|
986 |
*q++ = 1; /* first session */
|
|
987 |
*q++ = 1; /* last session */
|
|
744 | 988 |
if (start_track <= 1) { |
745 | 989 |
*q++ = 0; /* reserved */ |
746 | 990 |
*q++ = 0x14; /* ADR, control */ |
... | ... | |
765 | 1009 |
nb_sectors = s->nb_sectors >> 2; |
766 | 1010 |
if (msf) { |
767 | 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 | 1014 |
} else { |
772 | 1015 |
cpu_to_ube32(q, nb_sectors); |
773 | 1016 |
q += 4; |
... | ... | |
777 | 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 | 1092 |
static void ide_atapi_cmd(IDEState *s) |
781 | 1093 |
{ |
782 | 1094 |
const uint8_t *packet; |
... | ... | |
921 | 1233 |
ASC_LOGICAL_BLOCK_OOR); |
922 | 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 | 1279 |
break; |
927 | 1280 |
case GPCMD_SEEK: |
... | ... | |
995 | 1348 |
buf[3] = 0x01; |
996 | 1349 |
ide_atapi_cmd_reply(s, 12, max_len); |
997 | 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 | 1357 |
default: |
999 | 1358 |
error_cmd: |
1000 | 1359 |
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, |
... | ... | |
1169 | 1528 |
n = s->req_nb_sectors; |
1170 | 1529 |
ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); |
1171 | 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 | 1543 |
case WIN_READ_NATIVE_MAX: |
1173 | 1544 |
ide_set_sector(s, s->nb_sectors - 1); |
1174 | 1545 |
s->status = READY_STAT; |
... | ... | |
1185 | 1556 |
/* XXX: valid for CDROM ? */ |
1186 | 1557 |
switch(s->feature) { |
1187 | 1558 |
case 0x02: /* write cache enable */ |
1559 |
case 0x03: /* set transfer mode */ |
|
1188 | 1560 |
case 0x82: /* write cache disable */ |
1189 | 1561 |
case 0xaa: /* read look-ahead enable */ |
1190 | 1562 |
case 0x55: /* read look-ahead disable */ |
... | ... | |
1216 | 1588 |
case WIN_PACKETCMD: |
1217 | 1589 |
if (!s->is_cdrom) |
1218 | 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 | 1593 |
goto abort_cmd; |
1594 |
s->atapi_dma = s->feature & 1; |
|
1222 | 1595 |
s->nsector = 1; |
1223 | 1596 |
ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, |
1224 | 1597 |
ide_atapi_cmd); |
... | ... | |
1549 | 1922 |
/***********************************************************/ |
1550 | 1923 |
/* PCI IDE definitions */ |
1551 | 1924 |
|
1552 |
typedef struct PCIIDEState { |
|
1553 |
PCIDevice dev; |
|
1554 |
IDEState ide_if[4]; |
|
1555 |
} PCIIDEState; |
|
1556 |
|
|
1557 | 1925 |
static void ide_map(PCIDevice *pci_dev, int region_num, |
1558 | 1926 |
uint32_t addr, uint32_t size, int type) |
1559 | 1927 |
{ |
... | ... | |
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 | 2098 |
/* hd_table must contain 4 block drivers */ |
1582 | 2099 |
void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table) |
1583 | 2100 |
{ |
... | ... | |
1610 | 2127 |
PCI_ADDRESS_SPACE_IO, ide_map); |
1611 | 2128 |
pci_register_io_region((PCIDevice *)d, 3, 0x4, |
1612 | 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 | 2133 |
pci_conf[0x3d] = 0x01; // interrupt on pin 1 |
1615 | 2134 |
|
... | ... | |
1640 | 2159 |
pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage |
1641 | 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 | 2165 |
ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]); |
1646 | 2166 |
ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]); |
Also available in: Unified diff