Commit b25cf5893f5ad07c2b8eada28250fc9cb8fb7e2a
1 parent
426cd5d6
Add 40-bit DMA support to LSI scsi emulation (Ryan Harper)
This patch fixes Linux machines configured with > 4G of ram and using a SCSI device. 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@5750 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
32 additions
and
4 deletions
hw/lsi53c895a.c
@@ -143,6 +143,14 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args);} while (0) | @@ -143,6 +143,14 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ##args);} while (0) | ||
143 | #define LSI_CCNTL0_PMJCTL 0x40 | 143 | #define LSI_CCNTL0_PMJCTL 0x40 |
144 | #define LSI_CCNTL0_ENPMJ 0x80 | 144 | #define LSI_CCNTL0_ENPMJ 0x80 |
145 | 145 | ||
146 | +#define LSI_CCNTL1_EN64DBMV 0x01 | ||
147 | +#define LSI_CCNTL1_EN64TIBMV 0x02 | ||
148 | +#define LSI_CCNTL1_64TIMOD 0x04 | ||
149 | +#define LSI_CCNTL1_DDAC 0x08 | ||
150 | +#define LSI_CCNTL1_ZMOD 0x80 | ||
151 | + | ||
152 | +#define LSI_CCNTL1_40BIT (LSI_CCNTL1_EN64TIBMV|LSI_CCNTL1_64TIMOD) | ||
153 | + | ||
146 | #define PHASE_DO 0 | 154 | #define PHASE_DO 0 |
147 | #define PHASE_DI 1 | 155 | #define PHASE_DI 1 |
148 | #define PHASE_CMD 2 | 156 | #define PHASE_CMD 2 |
@@ -323,6 +331,13 @@ static void lsi_soft_reset(LSIState *s) | @@ -323,6 +331,13 @@ static void lsi_soft_reset(LSIState *s) | ||
323 | s->csbc = 0; | 331 | s->csbc = 0; |
324 | } | 332 | } |
325 | 333 | ||
334 | +static int lsi_dma_40bit(LSIState *s) | ||
335 | +{ | ||
336 | + if ((s->ccntl1 & LSI_CCNTL1_40BIT) == LSI_CCNTL1_40BIT) | ||
337 | + return 1; | ||
338 | + return 0; | ||
339 | +} | ||
340 | + | ||
326 | static uint8_t lsi_reg_readb(LSIState *s, int offset); | 341 | static uint8_t lsi_reg_readb(LSIState *s, int offset); |
327 | static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); | 342 | static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); |
328 | static void lsi_execute_script(LSIState *s); | 343 | static void lsi_execute_script(LSIState *s); |
@@ -449,7 +464,7 @@ static void lsi_resume_script(LSIState *s) | @@ -449,7 +464,7 @@ static void lsi_resume_script(LSIState *s) | ||
449 | static void lsi_do_dma(LSIState *s, int out) | 464 | static void lsi_do_dma(LSIState *s, int out) |
450 | { | 465 | { |
451 | uint32_t count; | 466 | uint32_t count; |
452 | - uint32_t addr; | 467 | + target_phys_addr_t addr; |
453 | 468 | ||
454 | if (!s->current_dma_len) { | 469 | if (!s->current_dma_len) { |
455 | /* Wait until data is available. */ | 470 | /* Wait until data is available. */ |
@@ -460,9 +475,14 @@ static void lsi_do_dma(LSIState *s, int out) | @@ -460,9 +475,14 @@ static void lsi_do_dma(LSIState *s, int out) | ||
460 | count = s->dbc; | 475 | count = s->dbc; |
461 | if (count > s->current_dma_len) | 476 | if (count > s->current_dma_len) |
462 | count = s->current_dma_len; | 477 | count = s->current_dma_len; |
463 | - DPRINTF("DMA addr=0x%08x len=%d\n", s->dnad, count); | ||
464 | 478 | ||
465 | addr = s->dnad; | 479 | addr = s->dnad; |
480 | + if (lsi_dma_40bit(s)) | ||
481 | + addr |= ((uint64_t)s->dnad64 << 32); | ||
482 | + else if (s->sbms) | ||
483 | + addr |= ((uint64_t)s->sbms << 32); | ||
484 | + | ||
485 | + DPRINTF("DMA addr=0x%" TARGET_FMT_plx " len=%d\n", addr, count); | ||
466 | s->csbc += count; | 486 | s->csbc += count; |
467 | s->dnad += count; | 487 | s->dnad += count; |
468 | s->dbc -= count; | 488 | s->dbc -= count; |
@@ -839,7 +859,7 @@ static void lsi_wait_reselect(LSIState *s) | @@ -839,7 +859,7 @@ static void lsi_wait_reselect(LSIState *s) | ||
839 | static void lsi_execute_script(LSIState *s) | 859 | static void lsi_execute_script(LSIState *s) |
840 | { | 860 | { |
841 | uint32_t insn; | 861 | uint32_t insn; |
842 | - uint32_t addr; | 862 | + uint32_t addr, addr_high; |
843 | int opcode; | 863 | int opcode; |
844 | int insn_processed = 0; | 864 | int insn_processed = 0; |
845 | 865 | ||
@@ -848,6 +868,7 @@ again: | @@ -848,6 +868,7 @@ again: | ||
848 | insn_processed++; | 868 | insn_processed++; |
849 | insn = read_dword(s, s->dsp); | 869 | insn = read_dword(s, s->dsp); |
850 | addr = read_dword(s, s->dsp + 4); | 870 | addr = read_dword(s, s->dsp + 4); |
871 | + addr_high = 0; | ||
851 | DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr); | 872 | DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr); |
852 | s->dsps = addr; | 873 | s->dsps = addr; |
853 | s->dcmd = insn >> 24; | 874 | s->dcmd = insn >> 24; |
@@ -870,9 +891,15 @@ again: | @@ -870,9 +891,15 @@ again: | ||
870 | /* Table indirect addressing. */ | 891 | /* Table indirect addressing. */ |
871 | offset = sxt24(addr); | 892 | offset = sxt24(addr); |
872 | cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); | 893 | cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); |
873 | - s->dbc = cpu_to_le32(buf[0]); | 894 | + /* byte count is stored in bits 0:23 only */ |
895 | + s->dbc = cpu_to_le32(buf[0]) & 0xffffff; | ||
874 | s->rbc = s->dbc; | 896 | s->rbc = s->dbc; |
875 | addr = cpu_to_le32(buf[1]); | 897 | addr = cpu_to_le32(buf[1]); |
898 | + | ||
899 | + /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of | ||
900 | + * table, bits [31:24] */ | ||
901 | + if (lsi_dma_40bit(s)) | ||
902 | + addr_high = cpu_to_le32(buf[0]) >> 24; | ||
876 | } | 903 | } |
877 | if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { | 904 | if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { |
878 | DPRINTF("Wrong phase got %d expected %d\n", | 905 | DPRINTF("Wrong phase got %d expected %d\n", |
@@ -881,6 +908,7 @@ again: | @@ -881,6 +908,7 @@ again: | ||
881 | break; | 908 | break; |
882 | } | 909 | } |
883 | s->dnad = addr; | 910 | s->dnad = addr; |
911 | + s->dnad64 = addr_high; | ||
884 | /* ??? Set ESA. */ | 912 | /* ??? Set ESA. */ |
885 | s->ia = s->dsp - 8; | 913 | s->ia = s->dsp - 8; |
886 | switch (s->sstat1 & 0x7) { | 914 | switch (s->sstat1 & 0x7) { |