From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1L9kWh-0000UE-6m for qemu-devel@nongnu.org; Mon, 08 Dec 2008 13:08:11 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1L9kWf-0000St-Fe for qemu-devel@nongnu.org; Mon, 08 Dec 2008 13:08:10 -0500 Received: from [199.232.76.173] (port=41571 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1L9kWf-0000So-CU for qemu-devel@nongnu.org; Mon, 08 Dec 2008 13:08:09 -0500 Received: from e38.co.us.ibm.com ([32.97.110.159]:38311) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1L9kWe-00036z-Qp for qemu-devel@nongnu.org; Mon, 08 Dec 2008 13:08:09 -0500 Received: from d03relay02.boulder.ibm.com (d03relay02.boulder.ibm.com [9.17.195.227]) by e38.co.us.ibm.com (8.13.1/8.13.1) with ESMTP id mB8I70D4027779 for ; Mon, 8 Dec 2008 11:07:00 -0700 Received: from d03av04.boulder.ibm.com (d03av04.boulder.ibm.com [9.17.195.170]) by d03relay02.boulder.ibm.com (8.13.8/8.13.8/NCO v9.1) with ESMTP id mB8I7rLZ207278 for ; Mon, 8 Dec 2008 11:08:00 -0700 Received: from d03av04.boulder.ibm.com (loopback [127.0.0.1]) by d03av04.boulder.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id mB8I7qjc003932 for ; Mon, 8 Dec 2008 11:07:52 -0700 From: Ryan Harper Date: Mon, 8 Dec 2008 12:07:48 -0600 Message-Id: <1228759670-31113-3-git-send-email-ryanh@us.ibm.com> In-Reply-To: <1228759670-31113-1-git-send-email-ryanh@us.ibm.com> References: <1228759670-31113-1-git-send-email-ryanh@us.ibm.com> Subject: [Qemu-devel] [PATCH 2/4] Add 64-bit Block Move support (Direct & Table Indirect) Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Ryan Harper , kvm@vger.kernel.org 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 diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index a2162ba..b36c08c 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -338,6 +338,20 @@ static int lsi_dma_40bit(LSIState *s) return 0; } +static int lsi_dma_ti64bit(LSIState *s) +{ + if ((s->ccntl1 & LSI_CCNTL1_EN64TIBMV) == LSI_CCNTL1_EN64TIBMV) + return 1; + return 0; +} + +static int lsi_dma_64bit(LSIState *s) +{ + if ((s->ccntl1 & LSI_CCNTL1_EN64DBMV) == LSI_CCNTL1_EN64DBMV) + return 1; + return 0; +} + static uint8_t lsi_reg_readb(LSIState *s, int offset); static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); static void lsi_execute_script(LSIState *s); @@ -477,8 +491,11 @@ static void lsi_do_dma(LSIState *s, int out) count = s->current_dma_len; addr = s->dnad; - if (lsi_dma_40bit(s)) + /* both 40 and Table Indirect 64-bit DMAs store upper bits in dnad64 */ + if (lsi_dma_40bit(s) || lsi_dma_ti64bit(s)) addr |= ((uint64_t)s->dnad64 << 32); + else if (s->dbms) + addr |= ((uint64_t)s->dbms << 32); else if (s->sbms) addr |= ((uint64_t)s->sbms << 32); @@ -882,6 +899,8 @@ again: } s->dbc = insn & 0xffffff; s->rbc = s->dbc; + /* ??? Set ESA. */ + s->ia = s->dsp - 8; if (insn & (1 << 29)) { /* Indirect addressing. */ addr = read_dword(s, addr); @@ -889,6 +908,8 @@ again: uint32_t buf[2]; int32_t offset; /* Table indirect addressing. */ + + /* 32-bit Table indirect */ offset = sxt24(addr); cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); /* byte count is stored in bits 0:23 only */ @@ -900,6 +921,44 @@ again: * table, bits [31:24] */ if (lsi_dma_40bit(s)) addr_high = cpu_to_le32(buf[0]) >> 24; + else if (lsi_dma_ti64bit(s)) { + int selector = (cpu_to_le32(buf[0]) >> 24) & 0x1f; + switch (selector) { + case 0 ... 0x0f: + /* offset index into scratch registers since + * TI64 mode can use registers C to R */ + addr_high = s->scratch[2 + selector]; + break; + case 0x10: + addr_high = s->mmrs; + break; + case 0x11: + addr_high = s->mmws; + break; + case 0x12: + addr_high = s->sfs; + break; + case 0x13: + addr_high = s->drs; + break; + case 0x14: + addr_high = s->sbms; + break; + case 0x15: + addr_high = s->dbms; + break; + default: + BADF("Illegal selector specified (0x%x > 0x15)" + " for 64-bit DMA block move", selector); + break; + } + } + } else if (lsi_dma_64bit(s)) { + /* fetch a 3rd dword if 64-bit direct move is enabled and + only if we're not doing table indirect or indirect addressing */ + s->dbms = read_dword(s, s->dsp); + s->dsp += 4; + s->ia = s->dsp - 12; } if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { DPRINTF("Wrong phase got %d expected %d\n", @@ -909,8 +968,6 @@ again: } s->dnad = addr; s->dnad64 = addr_high; - /* ??? Set ESA. */ - s->ia = s->dsp - 8; switch (s->sstat1 & 0x7) { case PHASE_DO: s->waiting = 2;