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 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 355 static uint8_t lsi_reg_readb(LSIState *s, int offset);
342 356 static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val);
343 357 static void lsi_execute_script(LSIState *s);
... ... @@ -477,8 +491,11 @@ static void lsi_do_dma(LSIState *s, int out)
477 491 count = s->current_dma_len;
478 492  
479 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 496 addr |= ((uint64_t)s->dnad64 << 32);
  497 + else if (s->dbms)
  498 + addr |= ((uint64_t)s->dbms << 32);
482 499 else if (s->sbms)
483 500 addr |= ((uint64_t)s->sbms << 32);
484 501  
... ... @@ -888,6 +905,8 @@ again:
888 905 }
889 906 s->dbc = insn & 0xffffff;
890 907 s->rbc = s->dbc;
  908 + /* ??? Set ESA. */
  909 + s->ia = s->dsp - 8;
891 910 if (insn & (1 << 29)) {
892 911 /* Indirect addressing. */
893 912 addr = read_dword(s, addr);
... ... @@ -895,6 +914,8 @@ again:
895 914 uint32_t buf[2];
896 915 int32_t offset;
897 916 /* Table indirect addressing. */
  917 +
  918 + /* 32-bit Table indirect */
898 919 offset = sxt24(addr);
899 920 cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8);
900 921 /* byte count is stored in bits 0:23 only */
... ... @@ -906,6 +927,44 @@ again:
906 927 * table, bits [31:24] */
907 928 if (lsi_dma_40bit(s))
908 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 969 if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) {
911 970 DPRINTF("Wrong phase got %d expected %d\n",
... ... @@ -915,8 +974,6 @@ again:
915 974 }
916 975 s->dnad = addr;
917 976 s->dnad64 = addr_high;
918   - /* ??? Set ESA. */
919   - s->ia = s->dsp - 8;
920 977 switch (s->sstat1 & 0x7) {
921 978 case PHASE_DO:
922 979 s->waiting = 2;
... ...