Commit dd8edf0122a605631420547f251fe636932dc4aa
1 parent
ab57d967
Add 64-bit Block Move support (Direct & Table Indirect) (Ryan Harper)
This patch adds support for 64-bit Block Move instructions. There are multiple modes for 64-bit Block moves, direct, indirect, and table indirect. This patch implements Direct and Table indirect moves which are needed by 64-bit windows and SYM_CONF_DMA_ADDRESSING_MODE=2 for the Linux sym53c8xx_2 driver respectively. Two helper functions are included to check which mode the guest is using. For 64-bit direct moves, we fetch a 3rd DWORD and store the value in the DBMS register. For Table Indirect moves, we look into the table for which register contains the upper 32-bits of the 64-bit address. This selector value indicates which register to pull the value from and into dnad64 register. Finally, lsi_do_dma is updated to use the approriate register to build a 64-bit DMA address if required. With this patch, Windows XP x64, 2003 SP2 x64, can now install to scsi devices. Linux SYM_CONF_DMA_ADDRESSING_MODE=2 need a quirk fixup in Patch 4 to function properly. Signed-off-by: Ryan Harper <ryanh@us.ibm.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5969 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
60 additions
and
3 deletions
hw/lsi53c895a.c
@@ -338,6 +338,20 @@ static int lsi_dma_40bit(LSIState *s) | @@ -338,6 +338,20 @@ static int lsi_dma_40bit(LSIState *s) | ||
338 | return 0; | 338 | return 0; |
339 | } | 339 | } |
340 | 340 | ||
341 | +static int lsi_dma_ti64bit(LSIState *s) | ||
342 | +{ | ||
343 | + if ((s->ccntl1 & LSI_CCNTL1_EN64TIBMV) == LSI_CCNTL1_EN64TIBMV) | ||
344 | + return 1; | ||
345 | + return 0; | ||
346 | +} | ||
347 | + | ||
348 | +static int lsi_dma_64bit(LSIState *s) | ||
349 | +{ | ||
350 | + if ((s->ccntl1 & LSI_CCNTL1_EN64DBMV) == LSI_CCNTL1_EN64DBMV) | ||
351 | + return 1; | ||
352 | + return 0; | ||
353 | +} | ||
354 | + | ||
341 | static uint8_t lsi_reg_readb(LSIState *s, int offset); | 355 | static uint8_t lsi_reg_readb(LSIState *s, int offset); |
342 | static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); | 356 | static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); |
343 | static void lsi_execute_script(LSIState *s); | 357 | static void lsi_execute_script(LSIState *s); |
@@ -477,8 +491,11 @@ static void lsi_do_dma(LSIState *s, int out) | @@ -477,8 +491,11 @@ static void lsi_do_dma(LSIState *s, int out) | ||
477 | count = s->current_dma_len; | 491 | count = s->current_dma_len; |
478 | 492 | ||
479 | addr = s->dnad; | 493 | addr = s->dnad; |
480 | - if (lsi_dma_40bit(s)) | 494 | + /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */ |
495 | + if (lsi_dma_40bit(s) || lsi_dma_ti64bit(s)) | ||
481 | addr |= ((uint64_t)s->dnad64 << 32); | 496 | addr |= ((uint64_t)s->dnad64 << 32); |
497 | + else if (s->dbms) | ||
498 | + addr |= ((uint64_t)s->dbms << 32); | ||
482 | else if (s->sbms) | 499 | else if (s->sbms) |
483 | addr |= ((uint64_t)s->sbms << 32); | 500 | addr |= ((uint64_t)s->sbms << 32); |
484 | 501 | ||
@@ -888,6 +905,8 @@ again: | @@ -888,6 +905,8 @@ again: | ||
888 | } | 905 | } |
889 | s->dbc = insn & 0xffffff; | 906 | s->dbc = insn & 0xffffff; |
890 | s->rbc = s->dbc; | 907 | s->rbc = s->dbc; |
908 | + /* ??? Set ESA. */ | ||
909 | + s->ia = s->dsp - 8; | ||
891 | if (insn & (1 << 29)) { | 910 | if (insn & (1 << 29)) { |
892 | /* Indirect addressing. */ | 911 | /* Indirect addressing. */ |
893 | addr = read_dword(s, addr); | 912 | addr = read_dword(s, addr); |
@@ -895,6 +914,8 @@ again: | @@ -895,6 +914,8 @@ again: | ||
895 | uint32_t buf[2]; | 914 | uint32_t buf[2]; |
896 | int32_t offset; | 915 | int32_t offset; |
897 | /* Table indirect addressing. */ | 916 | /* Table indirect addressing. */ |
917 | + | ||
918 | + /* 32-bit Table indirect */ | ||
898 | offset = sxt24(addr); | 919 | offset = sxt24(addr); |
899 | cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); | 920 | cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); |
900 | /* byte count is stored in bits 0:23 only */ | 921 | /* byte count is stored in bits 0:23 only */ |
@@ -906,6 +927,44 @@ again: | @@ -906,6 +927,44 @@ again: | ||
906 | * table, bits [31:24] */ | 927 | * table, bits [31:24] */ |
907 | if (lsi_dma_40bit(s)) | 928 | if (lsi_dma_40bit(s)) |
908 | addr_high = cpu_to_le32(buf[0]) >> 24; | 929 | addr_high = cpu_to_le32(buf[0]) >> 24; |
930 | + else if (lsi_dma_ti64bit(s)) { | ||
931 | + int selector = (cpu_to_le32(buf[0]) >> 24) & 0x1f; | ||
932 | + switch (selector) { | ||
933 | + case 0 ... 0x0f: | ||
934 | + /* offset index into scratch registers since | ||
935 | + * TI64 mode can use registers C to R */ | ||
936 | + addr_high = s->scratch[2 + selector]; | ||
937 | + break; | ||
938 | + case 0x10: | ||
939 | + addr_high = s->mmrs; | ||
940 | + break; | ||
941 | + case 0x11: | ||
942 | + addr_high = s->mmws; | ||
943 | + break; | ||
944 | + case 0x12: | ||
945 | + addr_high = s->sfs; | ||
946 | + break; | ||
947 | + case 0x13: | ||
948 | + addr_high = s->drs; | ||
949 | + break; | ||
950 | + case 0x14: | ||
951 | + addr_high = s->sbms; | ||
952 | + break; | ||
953 | + case 0x15: | ||
954 | + addr_high = s->dbms; | ||
955 | + break; | ||
956 | + default: | ||
957 | + BADF("Illegal selector specified (0x%x > 0x15)" | ||
958 | + " for 64-bit DMA block move", selector); | ||
959 | + break; | ||
960 | + } | ||
961 | + } | ||
962 | + } else if (lsi_dma_64bit(s)) { | ||
963 | + /* fetch a 3rd dword if 64-bit direct move is enabled and | ||
964 | + only if we're not doing table indirect or indirect addressing */ | ||
965 | + s->dbms = read_dword(s, s->dsp); | ||
966 | + s->dsp += 4; | ||
967 | + s->ia = s->dsp - 12; | ||
909 | } | 968 | } |
910 | if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { | 969 | if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { |
911 | DPRINTF("Wrong phase got %d expected %d\n", | 970 | DPRINTF("Wrong phase got %d expected %d\n", |
@@ -915,8 +974,6 @@ again: | @@ -915,8 +974,6 @@ again: | ||
915 | } | 974 | } |
916 | s->dnad = addr; | 975 | s->dnad = addr; |
917 | s->dnad64 = addr_high; | 976 | s->dnad64 = addr_high; |
918 | - /* ??? Set ESA. */ | ||
919 | - s->ia = s->dsp - 8; | ||
920 | switch (s->sstat1 & 0x7) { | 977 | switch (s->sstat1 & 0x7) { |
921 | case PHASE_DO: | 978 | case PHASE_DO: |
922 | s->waiting = 2; | 979 | s->waiting = 2; |