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 | 143 | #define LSI_CCNTL0_PMJCTL 0x40 |
| 144 | 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 | 154 | #define PHASE_DO 0 |
| 147 | 155 | #define PHASE_DI 1 |
| 148 | 156 | #define PHASE_CMD 2 |
| ... | ... | @@ -323,6 +331,13 @@ static void lsi_soft_reset(LSIState *s) |
| 323 | 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 | 341 | static uint8_t lsi_reg_readb(LSIState *s, int offset); |
| 327 | 342 | static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); |
| 328 | 343 | static void lsi_execute_script(LSIState *s); |
| ... | ... | @@ -449,7 +464,7 @@ static void lsi_resume_script(LSIState *s) |
| 449 | 464 | static void lsi_do_dma(LSIState *s, int out) |
| 450 | 465 | { |
| 451 | 466 | uint32_t count; |
| 452 | - uint32_t addr; | |
| 467 | + target_phys_addr_t addr; | |
| 453 | 468 | |
| 454 | 469 | if (!s->current_dma_len) { |
| 455 | 470 | /* Wait until data is available. */ |
| ... | ... | @@ -460,9 +475,14 @@ static void lsi_do_dma(LSIState *s, int out) |
| 460 | 475 | count = s->dbc; |
| 461 | 476 | if (count > s->current_dma_len) |
| 462 | 477 | count = s->current_dma_len; |
| 463 | - DPRINTF("DMA addr=0x%08x len=%d\n", s->dnad, count); | |
| 464 | 478 | |
| 465 | 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 | 486 | s->csbc += count; |
| 467 | 487 | s->dnad += count; |
| 468 | 488 | s->dbc -= count; |
| ... | ... | @@ -839,7 +859,7 @@ static void lsi_wait_reselect(LSIState *s) |
| 839 | 859 | static void lsi_execute_script(LSIState *s) |
| 840 | 860 | { |
| 841 | 861 | uint32_t insn; |
| 842 | - uint32_t addr; | |
| 862 | + uint32_t addr, addr_high; | |
| 843 | 863 | int opcode; |
| 844 | 864 | int insn_processed = 0; |
| 845 | 865 | |
| ... | ... | @@ -848,6 +868,7 @@ again: |
| 848 | 868 | insn_processed++; |
| 849 | 869 | insn = read_dword(s, s->dsp); |
| 850 | 870 | addr = read_dword(s, s->dsp + 4); |
| 871 | + addr_high = 0; | |
| 851 | 872 | DPRINTF("SCRIPTS dsp=%08x opcode %08x arg %08x\n", s->dsp, insn, addr); |
| 852 | 873 | s->dsps = addr; |
| 853 | 874 | s->dcmd = insn >> 24; |
| ... | ... | @@ -870,9 +891,15 @@ again: |
| 870 | 891 | /* Table indirect addressing. */ |
| 871 | 892 | offset = sxt24(addr); |
| 872 | 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 | 896 | s->rbc = s->dbc; |
| 875 | 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 | 904 | if ((s->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { |
| 878 | 905 | DPRINTF("Wrong phase got %d expected %d\n", |
| ... | ... | @@ -881,6 +908,7 @@ again: |
| 881 | 908 | break; |
| 882 | 909 | } |
| 883 | 910 | s->dnad = addr; |
| 911 | + s->dnad64 = addr_high; | |
| 884 | 912 | /* ??? Set ESA. */ |
| 885 | 913 | s->ia = s->dsp - 8; |
| 886 | 914 | switch (s->sstat1 & 0x7) { | ... | ... |