All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] MIPS: DMA support for RC4030 chipset [v3]
@ 2008-12-13 14:19 Hervé Poussineau
  2008-12-16 15:54 ` Aurelien Jarno
  0 siblings, 1 reply; 2+ messages in thread
From: Hervé Poussineau @ 2008-12-13 14:19 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 663 bytes --]

Hi,

Attached patch implements DMA support to RC4030 chipset and simplifies 
jazz IO part (at 0xf0000000), where registers contain 16 bit values.
The patch also wires DMA transfers for the SCSI adapter in the Jazz 
emulation (Mips Magnum 4000 and Acer Pica 61).

Changes since v1:
- Support reuse of esp callback functions up to DMA engine
- Don't keep in memory the DMA table, but read it when needed

Changes since v2:
- Don't use cpu_single_env in the DMA transfer function, as it is NULL 
in the aio path
- Multiple improvements to the DMA transfer function: report errors to 
the caller, support for non contiguous physical pages...

Hervé

[-- Attachment #2: rc4030_dma_v3.diff --]
[-- Type: plain/text, Size: 19522 bytes --]

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [Qemu-devel] [PATCH] MIPS: DMA support for RC4030 chipset [v3]
  2008-12-13 14:19 [Qemu-devel] [PATCH] MIPS: DMA support for RC4030 chipset [v3] Hervé Poussineau
@ 2008-12-16 15:54 ` Aurelien Jarno
  0 siblings, 0 replies; 2+ messages in thread
From: Aurelien Jarno @ 2008-12-16 15:54 UTC (permalink / raw)
  To: Hervé Poussineau; +Cc: qemu-devel

On Sat, Dec 13, 2008 at 03:19:58PM +0100, Hervé Poussineau wrote:
> Hi,
>
> Attached patch implements DMA support to RC4030 chipset and simplifies  
> jazz IO part (at 0xf0000000), where registers contain 16 bit values.
> The patch also wires DMA transfers for the SCSI adapter in the Jazz  
> emulation (Mips Magnum 4000 and Acer Pica 61).
>
> Changes since v1:
> - Support reuse of esp callback functions up to DMA engine
> - Don't keep in memory the DMA table, but read it when needed
>
> Changes since v2:
> - Don't use cpu_single_env in the DMA transfer function, as it is NULL  
> in the aio path
> - Multiple improvements to the DMA transfer function: report errors to  
> the caller, support for non contiguous physical pages...

This patches introduces some new warnings:
/home/aurel32/git/qemu/hw/rc4030.c: In function ‘rc4030_readl’:
/home/aurel32/git/qemu/hw/rc4030.c:229: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 4 has type ‘target_phys_addr_t’
/home/aurel32/git/qemu/hw/rc4030.c: In function ‘rc4030_writel’:
/home/aurel32/git/qemu/hw/rc4030.c:376: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 5 has type ‘target_phys_addr_t’
/home/aurel32/git/qemu/hw/rc4030.c: In function ‘jazzio_readw’:
/home/aurel32/git/qemu/hw/rc4030.c:503: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 4 has type ‘target_phys_addr_t’
/home/aurel32/git/qemu/hw/rc4030.c: In function ‘jazzio_writew’:
/home/aurel32/git/qemu/hw/rc4030.c:541: warning: format ‘%08x’ expects type ‘unsigned int’, but argument 5 has type ‘target_phys_addr_t’

Also, please include a Signed-off.

Please find my other comments inline.

> Index: hw/mips.h
> ===================================================================
> --- hw/mips.h	(revision 6000)
> +++ hw/mips.h	(working copy)
> @@ -27,6 +27,10 @@
>  extern void cpu_mips_clock_init(CPUState *);
>  
>  /* rc4030.c */
> -qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus);
> +typedef struct rc4030DMAState *rc4030_dma;
> +typedef void (*rc4030_dma_function)(void *dma, uint8_t *buf, int len);
> +qemu_irq *rc4030_init(CPUState *env, qemu_irq timer, qemu_irq jazz_bus,
> +                      rc4030_dma **dmas,
> +                      rc4030_dma_function *dma_read, rc4030_dma_function *dma_write);
>  
>  #endif
> Index: hw/mips_jazz.c
> ===================================================================
> --- hw/mips_jazz.c	(revision 6000)
> +++ hw/mips_jazz.c	(working copy)
> @@ -75,6 +75,24 @@
>      rtc_writeb,
>  };
>  
> +static void dma_dummy_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
> +{
> +    /* Nothing to do. That is only to ensure that
> +     * the current DMA acknowledge cycle is completed. */
> +}
> +
> +static CPUReadMemoryFunc *dma_dummy_read[3] = {
> +    NULL,
> +    NULL,
> +    NULL,
> +};
> +
> +static CPUWriteMemoryFunc *dma_dummy_write[3] = {
> +    dma_dummy_writeb,
> +    dma_dummy_writeb,
> +    dma_dummy_writeb,
> +};
> +
>  #ifdef HAS_AUDIO
>  static void audio_init(qemu_irq *pic)
>  {
> @@ -102,16 +120,6 @@
>  }
>  #endif
>  
> -static void espdma_memory_read(void *opaque, uint8_t *buf, int len)
> -{
> -    printf("espdma_memory_read(buf %p, len %d) not implemented\n", buf, len);
> -}
> -
> -static void espdma_memory_write(void *opaque, uint8_t *buf, int len)
> -{
> -    printf("espdma_memory_write(buf %p, len %d) not implemented\n", buf, len);
> -}
> -
>  #define MAGNUM_BIOS_SIZE_MAX 0x7e000
>  #define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
>  
> @@ -125,10 +133,11 @@
>      int bios_size, n;
>      CPUState *env;
>      qemu_irq *rc4030, *i8259;
> +    rc4030_dma *dmas;
> +    rc4030_dma_function dma_read, dma_write;
>      void *scsi_hba;
>      int hd;
> -    int s_rtc;
> -    PITState *pit;
> +    int s_rtc, s_dma_dummy;
>      BlockDriverState *fds[MAX_FD];
>      qemu_irq esp_reset;
>  
> @@ -153,7 +162,9 @@
>  
>      /* load the BIOS image. */
>      bios_offset = ram_size + vga_ram_size;
> -    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
> +    if (bios_name == NULL)
> +        bios_name = BIOS_FILENAME;
> +    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
>      bios_size = load_image(buf, phys_ram_base + bios_offset);
>      if (bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) {
>          fprintf(stderr, "qemu: Could not load MIPS bios '%s'\n",
> @@ -171,12 +182,14 @@
>      cpu_mips_clock_init(env);
>  
>      /* Chipset */
> -    rc4030 = rc4030_init(env->irq[6], env->irq[3]);
> +    rc4030 = rc4030_init(env, env->irq[6], env->irq[3],
> +                         &dmas, &dma_read, &dma_write);
> +    s_dma_dummy = cpu_register_io_memory(0, dma_dummy_read, dma_dummy_write, NULL);
> +    cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy);
>  
>      /* ISA devices */
>      i8259 = i8259_init(env->irq[4]);
> -    pit = pit_init(0x40, i8259[0]);
> -    pcspk_init(pit);

Is this wanted? This does not appear in the description and seems unrelated.

> +    DMA_init(0);
>  
>      /* ISA IO space at 0x90000000 */
>      isa_mmio_init(0x90000000, 0x01000000);
> @@ -200,7 +213,7 @@
>  
>      /* SCSI adapter */
>      scsi_hba = esp_init(0x80002000, 0,
> -                        espdma_memory_read, espdma_memory_write, NULL,
> +                        dma_read, dma_write, dmas[0],
>                          rc4030[5], &esp_reset);
>      for (n = 0; n < ESP_MAX_DEVS; n++) {
>          hd = drive_get_index(IF_SCSI, 0, n);
> @@ -278,6 +291,7 @@
>      .init = mips_magnum_init,
>      .ram_require = MAGNUM_BIOS_SIZE + VGA_RAM_SIZE,
>      .nodisk_ok = 1,
> +    .use_scsi = 1,
>  };
>  
>  QEMUMachine mips_pica61_machine = {
> @@ -286,4 +300,5 @@
>      .init = mips_pica61_init,
>      .ram_require = MAGNUM_BIOS_SIZE + VGA_RAM_SIZE,
>      .nodisk_ok = 1,
> +    .use_scsi = 1,
>  };
> Index: hw/rc4030.c
> ===================================================================
> --- hw/rc4030.c	(revision 6000)
> +++ hw/rc4030.c	(working copy)
> @@ -26,21 +26,53 @@
>  #include "mips.h"
>  #include "qemu-timer.h"
>  
> +/********************************************************/
> +/* debug rc4030 */
> +
>  //#define DEBUG_RC4030
> +//#define DEBUG_RC4030_DMA
>  
>  #ifdef DEBUG_RC4030
> +#define DPRINTF(fmt, args...) \
> +do { printf("rc4030: " fmt , ##args); } while (0)
>  static const char* irq_names[] = { "parallel", "floppy", "sound", "video",
>              "network", "scsi", "keyboard", "mouse", "serial0", "serial1" };
> +#else
> +#define DPRINTF(fmt, args...)
>  #endif
>  
> +#define RC4030_ERROR(fmt, args...) \
> +do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ##args); } while (0)
> +
> +/********************************************************/
> +/* rc4030 emulation                                     */
> +
> +typedef struct dma_pagetable_entry {
> +    int32_t frame;
> +    int32_t owner;
> +} __attribute__((packed)) dma_pagetable_entry;
> +
> +#define DMA_PAGESIZE    4096
> +#define DMA_REG_ENABLE  1
> +#define DMA_REG_COUNT   2
> +#define DMA_REG_ADDRESS 3
> +
> +#define DMA_FLAG_ENABLE     0x0001
> +#define DMA_FLAG_MEM_TO_DEV 0x0002
> +#define DMA_FLAG_TC_INTR    0x0100
> +#define DMA_FLAG_MEM_INTR   0x0200
> +#define DMA_FLAG_ADDR_INTR  0x0400
> +
>  typedef struct rc4030State
>  {
> +    CPUState *env;
> +
>      uint32_t config; /* 0x0000: RC4030 config register */
>      uint32_t invalid_address_register; /* 0x0010: Invalid Address register */
>  
>      /* DMA */
>      uint32_t dma_regs[8][4];
> -    uint32_t dma_tl_base; /* 0x0018: DMA transl. table base */
> +    target_phys_addr_t dma_tl_base; /* 0x0018: DMA transl. table base */
>      uint32_t dma_tl_limit; /* 0x0020: DMA transl. table limit */
>  
>      /* cache */
> @@ -51,7 +83,6 @@
>      uint32_t cache_bmask; /* 0x0058: I/O Cache Byte Mask */
>      uint32_t cache_bwin; /* 0x0060: I/O Cache Buffer Window */
>  
> -    uint32_t offset208;
>      uint32_t offset210;
>      uint32_t nvram_protect; /* 0x0220: NV ram protect register */
>      uint32_t offset238;
> @@ -63,7 +94,6 @@
>      QEMUTimer *periodic_timer;
>      uint32_t itr; /* Interval timer reload */
>  
> -    uint32_t dummy32;
>      qemu_irq timer_irq;
>      qemu_irq jazz_bus_irq;
>  } rc4030State;
> @@ -165,7 +195,7 @@
>      case 0x01d0:
>      case 0x01d8:
>      case 0x01e0:
> -    case 0x1e8:
> +    case 0x01e8:
>      case 0x01f0:
>      case 0x01f8:
>          {
> @@ -176,7 +206,7 @@
>          break;
>      /* Offset 0x0208 */
>      case 0x0208:
> -        val = s->offset208;
> +        val = 0;
>          break;
>      /* Offset 0x0210 */
>      case 0x0210:
> @@ -188,7 +218,7 @@
>          break;
>      /* Interval timer count */
>      case 0x0230:
> -        val = s->dummy32;
> +        val = 0;
>          qemu_irq_lower(s->timer_irq);
>          break;
>      /* Offset 0x0238 */
> @@ -196,17 +226,13 @@
>          val = s->offset238;
>          break;
>      default:
> -#ifdef DEBUG_RC4030
> -        printf("rc4030: invalid read [" TARGET_FMT_lx "]\n", addr);
> -#endif
> +        RC4030_ERROR("invalid read [" TARGET_FMT_lx "]\n", addr);
>          val = 0;
>          break;
>      }
>  
> -#ifdef DEBUG_RC4030
>      if ((addr & ~3) != 0x230)
> -        printf("rc4030: read 0x%02x at " TARGET_FMT_lx "\n", val, addr);
> -#endif
> +        DPRINTF("read 0x%02x at " TARGET_FMT_lx "\n", val, addr);
>  
>      return val;
>  }
> @@ -231,9 +257,7 @@
>      rc4030State *s = opaque;
>      addr &= 0x3fff;
>  
> -#ifdef DEBUG_RC4030
> -    printf("rc4030: write 0x%02x at " TARGET_FMT_lx "\n", val, addr);
> -#endif
> +    DPRINTF("write 0x%02x at " TARGET_FMT_lx "\n", val, addr);
>  
>      switch (addr & ~0x3) {
>      /* Global config register */
> @@ -242,12 +266,19 @@
>          break;
>      /* DMA transl. table base */
>      case 0x0018:
> -        s->dma_tl_base = val;
> +        s->dma_tl_base = (int32_t)val;
>          break;
>      /* DMA transl. table limit */
>      case 0x0020:
>          s->dma_tl_limit = val;
>          break;
> +    /* DMA transl. table invalidated */
> +    case 0x0028:
> +        break;
> +    /* Cache Maintenance */
> +    case 0x0030:
> +        RC4030_ERROR("Cache maintenance not handled yet (val 0x%02x)\n", val);
> +        break;
>      /* I/O Cache Physical Tag */
>      case 0x0048:
>          s->cache_ptag = val;
> @@ -269,7 +300,7 @@
>              static int current = 0;
>              target_phys_addr_t dest = 0 + dests[current];
>              uint8_t buf;
> -            current = (current + 1) % (sizeof(dests)/sizeof(dests[0]));
> +            current = (current + 1) % ARRAY_SIZE(dests);
>              buf = s->cache_bwin - 1;
>              cpu_physical_memory_rw(dest, &buf, 1, 1);
>          }
> @@ -322,7 +353,7 @@
>      case 0x01d0:
>      case 0x01d8:
>      case 0x01e0:
> -    case 0x1e8:
> +    case 0x01e8:
>      case 0x01f0:
>      case 0x01f8:
>          {
> @@ -342,9 +373,7 @@
>          set_next_tick(s);
>          break;
>      default:
> -#ifdef DEBUG_RC4030
> -        printf("rc4030: invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
> -#endif
> +        RC4030_ERROR("invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
>          break;
>      }
>  }
> @@ -402,8 +431,8 @@
>  #ifdef DEBUG_RC4030
>      if (s->isr_jazz != 0) {
>          uint32_t irq = 0;
> -        printf("jazz pending:");
> -        for (irq = 0; irq < sizeof(irq_names)/sizeof(irq_names[0]); irq++) {
> +        DPRINTF("pending irqs:");
> +        for (irq = 0; irq < ARRAY_SIZE(irq_names); irq++) {
>              if (s->isr_jazz & (1 << irq)) {
>                  printf(" %s", irq_names[irq]);
>                  if (!(s->imr_jazz & (1 << irq))) {
> @@ -442,7 +471,7 @@
>      qemu_irq_raise(s->timer_irq);
>  }
>  
> -static uint32_t int_readb(void *opaque, target_phys_addr_t addr)
> +static uint32_t jazzio_readw(void *opaque, target_phys_addr_t addr)
>  {
>      rc4030State *s = opaque;
>      uint32_t val;
> @@ -450,14 +479,14 @@
>      addr &= 0xfff;
>  
>      switch (addr) {
> +    /* Local bus int source */
>      case 0x00: {
> -        /* Local bus int source */
>          uint32_t pending = s->isr_jazz & s->imr_jazz;
>          val = 0;
>          irq = 0;
>          while (pending) {
>              if (pending & 1) {
> -                //printf("returning irq %s\n", irq_names[irq]);
> +                DPRINTF("returning irq %s\n", irq_names[irq]);
>                  val = (irq + 1) << 2;
>                  break;
>              }
> @@ -466,100 +495,93 @@
>          }
>          break;
>      }
> +    /* Local bus int enable mask */
> +    case 0x02:
> +        val = s->imr_jazz;
> +        break;
>      default:
> -#ifdef DEBUG_RC4030
> -            printf("rc4030: (interrupt controller) invalid read [" TARGET_FMT_lx "]\n", addr);
> -#endif
> -            val = 0;
> +        RC4030_ERROR("(jazz io controller) invalid read [" TARGET_FMT_lx "]\n", addr);
> +        val = 0;
>      }
>  
> -#ifdef DEBUG_RC4030
> -    printf("rc4030: (interrupt controller) read 0x%02x at " TARGET_FMT_lx "\n", val, addr);
> -#endif
> +    DPRINTF("(jazz io controller) read 0x%04x at " TARGET_FMT_lx "\n", val, addr);
>  
>      return val;
>  }
>  
> -static uint32_t int_readw(void *opaque, target_phys_addr_t addr)
> +static uint32_t jazzio_readb(void *opaque, target_phys_addr_t addr)
>  {
>      uint32_t v;
> -    v = int_readb(opaque, addr);
> -    v |= int_readb(opaque, addr + 1) << 8;
> -    return v;
> +    v = jazzio_readw(opaque, addr & ~0x1);
> +    return (v >> (8 * (addr & 0x1))) & 0xff;
>  }
>  
> -static uint32_t int_readl(void *opaque, target_phys_addr_t addr)
> +static uint32_t jazzio_readl(void *opaque, target_phys_addr_t addr)
>  {
>      uint32_t v;
> -    v = int_readb(opaque, addr);
> -    v |= int_readb(opaque, addr + 1) << 8;
> -    v |= int_readb(opaque, addr + 2) << 16;
> -    v |= int_readb(opaque, addr + 3) << 24;
> +    v = jazzio_readw(opaque, addr);
> +    v |= jazzio_readw(opaque, addr + 2) << 16;
>      return v;
>  }
>  
> -static void int_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
> +static void jazzio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
>  {
>      rc4030State *s = opaque;
>      addr &= 0xfff;
>  
> -#ifdef DEBUG_RC4030
> -    printf("rc4030: (interrupt controller) write 0x%02x at " TARGET_FMT_lx "\n", val, addr);
> -#endif
> +    DPRINTF("(jazz io controller) write 0x%04x at " TARGET_FMT_lx "\n", val, addr);
>  
>      switch (addr) {
>      /* Local bus int enable mask */
>      case 0x02:
> -        s->imr_jazz = (s->imr_jazz & 0xff00) | (val << 0); update_jazz_irq(s);
> +        s->imr_jazz = val;
> +        update_jazz_irq(s);
>          break;
> -    case 0x03:
> -        s->imr_jazz = (s->imr_jazz & 0x00ff) | (val << 8); update_jazz_irq(s);
> -        break;
>      default:
> -#ifdef DEBUG_RC4030
> -        printf("rc4030: (interrupt controller) invalid write of 0x%02x at [" TARGET_FMT_lx "]\n", val, addr);
> -#endif
> +        RC4030_ERROR("(jazz io controller) invalid write of 0x%04x at [" TARGET_FMT_lx "]\n", val, addr);
>          break;
>      }
>  }
>  
> -static void int_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
> +static void jazzio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
>  {
> -    int_writeb(opaque, addr, val & 0xff);
> -    int_writeb(opaque, addr + 1, (val >> 8) & 0xff);
> +    uint32_t old_val = jazzio_readw(opaque, addr & ~0x1);
> +
> +    switch (addr & 1) {
> +    case 0:
> +        val = val | (old_val & 0xff00);
> +        break;
> +    case 1:
> +        val = (val << 8) | (old_val & 0x00ff);
> +        break;
> +    }
> +    jazzio_writew(opaque, addr & ~0x1, val);
>  }
>  
> -static void int_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
> +static void jazzio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
>  {
> -    int_writeb(opaque, addr, val & 0xff);
> -    int_writeb(opaque, addr + 1, (val >> 8) & 0xff);
> -    int_writeb(opaque, addr + 2, (val >> 16) & 0xff);
> -    int_writeb(opaque, addr + 3, (val >> 24) & 0xff);
> +    jazzio_writew(opaque, addr, val & 0xffff);
> +    jazzio_writew(opaque, addr + 2, (val >> 16) & 0xffff);
>  }
>  
> -static CPUReadMemoryFunc *int_read[3] = {
> -    int_readb,
> -    int_readw,
> -    int_readl,
> +static CPUReadMemoryFunc *jazzio_read[3] = {
> +    jazzio_readb,
> +    jazzio_readw,
> +    jazzio_readl,
>  };
>  
> -static CPUWriteMemoryFunc *int_write[3] = {
> -    int_writeb,
> -    int_writew,
> -    int_writel,
> +static CPUWriteMemoryFunc *jazzio_write[3] = {
> +    jazzio_writeb,
> +    jazzio_writew,
> +    jazzio_writel,
>  };
>  
> -#define G364_512KB_RAM (0x0)
> -#define G364_2MB_RAM   (0x1)
> -#define G364_8MB_RAM   (0x2)
> -#define G364_32MB_RAM  (0x3)
> -
>  static void rc4030_reset(void *opaque)
>  {
>      rc4030State *s = opaque;
>      int i;
>  
> -    s->config = (G364_2MB_RAM << 8) | 0x04;
> +    s->config = 0x104;

Why this change? This make the resultint code less readable.

>      s->invalid_address_register = 0;
>  
>      memset(s->dma_regs, 0, sizeof(s->dma_regs));
> @@ -569,7 +591,6 @@
>      s->cache_ptag = s->cache_ltag = 0;
>      s->cache_bmask = s->cache_bwin = 0;
>  
> -    s->offset208 = 0;
>      s->offset210 = 0x18186;
>      s->nvram_protect = 7;
>      s->offset238 = 7;
> @@ -578,21 +599,140 @@
>      s->imr_jazz = s->isr_jazz = 0;
>  
>      s->itr = 0;
> -    s->dummy32 = 0;
>  
>      qemu_irq_lower(s->timer_irq);
>      qemu_irq_lower(s->jazz_bus_irq);
>  }
>  
> -qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus)
> +static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write)
>  {
> +    rc4030State *s = opaque;
> +    target_phys_addr_t entry_addr;
> +    target_phys_addr_t dma_addr, phys_addr;
> +    dma_pagetable_entry entry;
> +    int index, dev_to_mem;
> +    int ncpy, i;
> +
> +    s->dma_regs[n][DMA_REG_ENABLE] &= ~(DMA_FLAG_TC_INTR | DMA_FLAG_MEM_INTR | DMA_FLAG_ADDR_INTR);
> +
> +    /* Check DMA channel consistency */
> +    dev_to_mem = (s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_MEM_TO_DEV) ? 0 : 1;
> +    if (!(s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_ENABLE) ||
> +        (is_write != dev_to_mem)) {
> +        s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;
> +        return;
> +    }
> +
> +    if (len > s->dma_regs[n][DMA_REG_COUNT])
> +        len = s->dma_regs[n][DMA_REG_COUNT];
> +
> +    dma_addr = s->dma_regs[n][DMA_REG_ADDRESS];
> +    i = 0;
> +    for (;;) {
> +        if (i == len) {
> +            s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_TC_INTR;
> +            break;
> +        }
> +
> +        ncpy = DMA_PAGESIZE - (dma_addr & (DMA_PAGESIZE - 1));
> +        if (ncpy > len - i)
> +            ncpy = len - i;
> +
> +        /* Get DMA translation table entry */
> +        index = dma_addr / DMA_PAGESIZE;
> +        if (index >= s->dma_tl_limit / sizeof(dma_pagetable_entry)) {
> +            s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;
> +            break;
> +        }
> +        entry_addr = s->dma_tl_base + index * sizeof(dma_pagetable_entry);
> +        /* HACK: Qemu has no function to read from a virtual or physical address */

cpu_physical_memory_rw is able to read/write from a physical address.

> +        if (entry_addr > ram_size) {

Where does this condition come from?

> +            if (cpu_memory_rw_debug(s->env, entry_addr, (uint8_t *)&entry, sizeof(entry), 0) < 0) {

This looks very hackish especially given this function use the current
mode of the CPU (supervisor/kernel/user) to do the memory access. You
can use env->tlb->map_address() to do virtual->physical address
translation.

> +                s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;
> +                break;
> +            }
> +        } else
> +            cpu_physical_memory_rw(entry_addr, (uint8_t *)&entry, sizeof(entry), 0);
> +
> +        /* Read/write data at right place */
> +        phys_addr = entry.frame + (dma_addr & (DMA_PAGESIZE - 1));
> +        cpu_physical_memory_rw(phys_addr, &buf[i], ncpy, is_write);
> +
> +        i += ncpy;
> +        dma_addr += ncpy;
> +        s->dma_regs[n][DMA_REG_COUNT] -= ncpy;
> +    }
> +
> +#ifdef DEBUG_RC4030_DMA
> +    {
> +        int i, j;
> +        printf("rc4030 dma: Copying %d bytes %s host %p\n",
> +            len, is_write ? "from" : "to", buf);
> +        for (i = 0; i < len; i += 16) {
> +            int n = min(16, len - i);
> +            for (j = 0; j < n; j++)
> +                printf("%02x ", buf[i + j]);
> +            while (j++ < 16)
> +                printf("   ");
> +            printf("| ");
> +            for (j = 0; j < n; j++)
> +                printf("%c", isprint(buf[i + j]) ? buf[i + j] : '.');
> +            printf("\n");
> +        }
> +    }
> +#endif
> +}
> +
> +struct rc4030DMAState {
> +    void *opaque;
> +    int n;
> +};
> +
> +static void rc4030_dma_read(void *dma, uint8_t *buf, int len)
> +{
> +    rc4030_dma s = dma;
> +    rc4030_do_dma(s->opaque, s->n, buf, len, 0);
> +}
> +
> +static void rc4030_dma_write(void *dma, uint8_t *buf, int len)
> +{
> +    rc4030_dma s = dma;
> +    rc4030_do_dma(s->opaque, s->n, buf, len, 1);
> +}
> +
> +static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
> +{
> +    rc4030_dma *s;
> +    struct rc4030DMAState *p;
> +    int i;
> +
> +    s = (rc4030_dma *)qemu_mallocz(sizeof(rc4030_dma) * n);
> +    p = (struct rc4030DMAState *)qemu_mallocz(sizeof(struct rc4030DMAState) * n);
> +    for (i = 0; i < n; i++) {
> +        p->opaque = opaque;
> +        p->n = i;
> +        s[i] = p;
> +        p++;
> +    }
> +    return s;
> +}
> +
> +qemu_irq *rc4030_init(CPUState *env, qemu_irq timer, qemu_irq jazz_bus,
> +                      rc4030_dma **dmas,
> +                      rc4030_dma_function *dma_read, rc4030_dma_function *dma_write)
> +{
>      rc4030State *s;
> -    int s_chipset, s_int;
> +    int s_chipset, s_jazzio;
>  
>      s = qemu_mallocz(sizeof(rc4030State));
>      if (!s)
>          return NULL;
>  
> +    *dmas = rc4030_allocate_dmas(s, 4);
> +    *dma_read = rc4030_dma_read;
> +    *dma_write = rc4030_dma_write;
> +
> +    s->env = env;
>      s->periodic_timer = qemu_new_timer(vm_clock, rc4030_periodic_timer, s);
>      s->timer_irq = timer;
>      s->jazz_bus_irq = jazz_bus;
> @@ -602,8 +742,8 @@
>  
>      s_chipset = cpu_register_io_memory(0, rc4030_read, rc4030_write, s);
>      cpu_register_physical_memory(0x80000000, 0x300, s_chipset);
> -    s_int = cpu_register_io_memory(0, int_read, int_write, s);
> -    cpu_register_physical_memory(0xf0000000, 0x00001000, s_int);
> +    s_jazzio = cpu_register_io_memory(0, jazzio_read, jazzio_write, s);
> +    cpu_register_physical_memory(0xf0000000, 0x00001000, s_jazzio);
>  
>      return qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16);
>  }
> 
> 

-- 
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   aurel32@debian.org         | aurelien@aurel32.net
   `-    people.debian.org/~aurel32 | www.aurel32.net

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2008-12-16 15:54 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-12-13 14:19 [Qemu-devel] [PATCH] MIPS: DMA support for RC4030 chipset [v3] Hervé Poussineau
2008-12-16 15:54 ` Aurelien Jarno

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.