Commit dd8edf0122a605631420547f251fe636932dc4aa

Authored by aliguori
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;