From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LiuH0-0007IF-D7 for qemu-devel@nongnu.org; Sun, 15 Mar 2009 13:37:18 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LiuGv-0007D6-0e for qemu-devel@nongnu.org; Sun, 15 Mar 2009 13:37:17 -0400 Received: from [199.232.76.173] (port=56412 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LiuGu-0007Cr-Sy for qemu-devel@nongnu.org; Sun, 15 Mar 2009 13:37:12 -0400 Received: from smtp1-g21.free.fr ([212.27.42.1]:44111) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LiuGt-0001h4-PL for qemu-devel@nongnu.org; Sun, 15 Mar 2009 13:37:12 -0400 Received: from smtp1-g21.free.fr (localhost [127.0.0.1]) by smtp1-g21.free.fr (Postfix) with ESMTP id 604AD9401DF for ; Sun, 15 Mar 2009 18:37:07 +0100 (CET) Received: from [192.168.0.32] (rob92-10-88-171-126-33.fbx.proxad.net [88.171.126.33]) by smtp1-g21.free.fr (Postfix) with ESMTP id 4ADA59401BC for ; Sun, 15 Mar 2009 18:37:05 +0100 (CET) Message-ID: <49BD3CC1.4040009@reactos.org> Date: Sun, 15 Mar 2009 18:37:05 +0100 From: =?ISO-8859-1?Q?Herv=E9_Poussineau?= MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------090103050307000704080808" Subject: [Qemu-devel] [PATCH] rc4030 chipset: enhancements 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 This is a multi-part message in MIME format. --------------090103050307000704080808 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: quoted-printable Hi, rc4030 chipset contains the DMA controller. Some devices (like the Jazz=20 netcard[1]) need to access the DMA memory without using a DMA channel. The chosen prototype "void (*memory_rw)(void *opaque, target_phys_addr_t=20 addr, uint8_t *buf, int len, int is_write);" is quite similar to=20 cpu_physical_memory_rw(). Document also some registers and remove one hack. I also put all returned functions/pointers by the rc4030 init function=20 to a structure to not add two new output parameters to the init function. Signed-off-by: Herv=E9 Poussineau Changes have been tested on Linux, NetBSD, and Windows NT/MIPS. Herv=E9 [1] patch on the way --------------090103050307000704080808 Content-Type: plain/text; name="rc4030_enhancements.diff" Content-Disposition: inline; filename="rc4030_enhancements.diff" Content-Transfer-Encoding: quoted-printable Index: hw/mips.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- hw/mips.h (revision 6855) +++ hw/mips.h (working copy) @@ -29,9 +29,20 @@ =20 /* rc4030.c */ typedef struct rc4030DMAState *rc4030_dma; -typedef void (*rc4030_dma_function)(void *dma, uint8_t *buf, int len); -qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus, - rc4030_dma **dmas, - rc4030_dma_function *dma_read, rc4030_dma_function= *dma_write); +struct rc4030_pointers +{ + /* DMA memory access */ + void (*memory_rw)(void *opaque, target_phys_addr_t addr, uint8_t *bu= f, int len, int is_write); + void* mem_opaque; =20 + /* DMA channels */ + rc4030_dma *dmas; + void (*dma_read)(void *dma, uint8_t *buf, int len); + void (*dma_write)(void *dma, uint8_t *buf, int len); + + /* IRQ */ + qemu_irq *irqs; +}; +void rc4030_init(qemu_irq timer, qemu_irq jazz_bus, struct rc4030_pointe= rs* pointers); + #endif Index: hw/mips_jazz.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- hw/mips_jazz.c (revision 6855) +++ hw/mips_jazz.c (working copy) @@ -132,9 +132,8 @@ unsigned long bios_offset; int bios_size, n; CPUState *env; - qemu_irq *rc4030, *i8259; - rc4030_dma *dmas; - rc4030_dma_function dma_read, dma_write; + qemu_irq *i8259; + struct rc4030_pointers rc4030; void *scsi_hba; int hd; int s_rtc, s_dma_dummy; @@ -183,8 +182,7 @@ cpu_mips_clock_init(env); =20 /* Chipset */ - rc4030 =3D rc4030_init(env->irq[6], env->irq[3], - &dmas, &dma_read, &dma_write); + rc4030_init(env->irq[6], env->irq[3], &rc4030); s_dma_dummy =3D cpu_register_io_memory(0, dma_dummy_read, dma_dummy_= write, NULL); cpu_register_physical_memory(0x8000d000, 0x00001000, s_dma_dummy); =20 @@ -202,7 +200,7 @@ switch (jazz_model) { case JAZZ_MAGNUM: g364fb_mm_init(phys_ram_base + ram_size, ram_size, vga_ram_size, - 0x40000000, 0x60000000, 0, rc4030[3]); + 0x40000000, 0x60000000, 0, rc4030.irqs[3]); break; case JAZZ_PICA61: isa_vga_mm_init(phys_ram_base + ram_size, ram_size, vga_ram_size= , @@ -217,8 +215,8 @@ =20 /* SCSI adapter */ scsi_hba =3D esp_init(0x80002000, 0, - dma_read, dma_write, dmas[0], - rc4030[5], &esp_reset); + rc4030.dma_read, rc4030.dma_write, rc4030.dmas[0= ], + rc4030.irqs[5], &esp_reset); for (n =3D 0; n < ESP_MAX_DEVS; n++) { hd =3D drive_get_index(IF_SCSI, 0, n); if (hd !=3D -1) { @@ -238,7 +236,7 @@ else fds[n] =3D NULL; } - fdctrl_init(rc4030[1], 0, 1, 0x80003000, fds); + fdctrl_init(rc4030.irqs[1], 0, 1, 0x80003000, fds); =20 /* Real time clock */ rtc_init(0x70, i8259[8], 1980); @@ -246,17 +244,17 @@ cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc); =20 /* Keyboard (i8042) */ - i8042_mm_init(rc4030[6], rc4030[7], 0x80005000, 0x1000, 0x1); + i8042_mm_init(rc4030.irqs[6], rc4030.irqs[7], 0x80005000, 0x1000, 0x= 1); =20 /* Serial ports */ if (serial_hds[0]) - serial_mm_init(0x80006000, 0, rc4030[8], 8000000/16, serial_hds[= 0], 1); + serial_mm_init(0x80006000, 0, rc4030.irqs[8], 8000000/16, serial= _hds[0], 1); if (serial_hds[1]) - serial_mm_init(0x80007000, 0, rc4030[9], 8000000/16, serial_hds[= 1], 1); + serial_mm_init(0x80007000, 0, rc4030.irqs[9], 8000000/16, serial= _hds[1], 1); =20 /* Parallel port */ if (parallel_hds[0]) - parallel_mm_init(0x80008000, 0, rc4030[0], parallel_hds[0]); + parallel_mm_init(0x80008000, 0, rc4030.irqs[0], parallel_hds[0])= ; =20 /* Sound card */ /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */ Index: hw/rc4030.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- hw/rc4030.c (revision 6855) +++ hw/rc4030.c (working copy) @@ -1,7 +1,7 @@ /* * QEMU JAZZ RC4030 chipset * - * Copyright (c) 2007-2008 Herv=E9 Poussineau + * Copyright (c) 2007-2009 Herve Poussineau * * Permission is hereby granted, free of charge, to any person obtaining= a copy * of this software and associated documentation files (the "Software"),= to deal @@ -66,6 +66,7 @@ typedef struct rc4030State { uint32_t config; /* 0x0000: RC4030 config register */ + uint32_t revision; /* 0x0008: RC4030 Revision register */ uint32_t invalid_address_register; /* 0x0010: Invalid Address regist= er */ =20 /* DMA */ @@ -74,17 +75,17 @@ uint32_t dma_tl_limit; /* 0x0020: DMA transl. table limit */ =20 /* cache */ + uint32_t cache_maint; /* 0x0030: Cache Maintenance */ uint32_t remote_failed_address; /* 0x0038: Remote Failed Address */ uint32_t memory_failed_address; /* 0x0040: Memory Failed Address */ uint32_t cache_ptag; /* 0x0048: I/O Cache Physical Tag */ uint32_t cache_ltag; /* 0x0050: I/O Cache Logical Tag */ uint32_t cache_bmask; /* 0x0058: I/O Cache Byte Mask */ - uint32_t cache_bwin; /* 0x0060: I/O Cache Buffer Window */ =20 + uint32_t nmi_interrupt; /* 0x0200: interrupt source */ uint32_t offset210; uint32_t nvram_protect; /* 0x0220: NV ram protect register */ - uint32_t offset238; - uint32_t rem_speed[15]; + uint32_t rem_speed[16]; uint32_t imr_jazz; /* Local bus int enable mask */ uint32_t isr_jazz; /* Local bus int source */ =20 @@ -118,6 +119,10 @@ case 0x0000: val =3D s->config; break; + /* Revision register */ + case 0x0008: + val =3D s->revision; + break; /* Invalid Address register */ case 0x0010: val =3D s->invalid_address_register; @@ -161,6 +166,7 @@ case 0x00d0: case 0x00d8: case 0x00e0: + case 0x00e8: val =3D s->rem_speed[(addr - 0x0070) >> 3]; break; /* DMA channel base address */ @@ -202,7 +208,11 @@ val =3D s->dma_regs[entry][idx]; } break; - /* Offset 0x0208 */ + /* Interrupt source */ + case 0x0200: + val =3D s->nmi_interrupt; + break; + /* Error type */ case 0x0208: val =3D 0; break; @@ -219,9 +229,9 @@ val =3D 0; qemu_irq_lower(s->timer_irq); break; - /* Offset 0x0238 */ + /* EISA interrupt */ case 0x0238: - val =3D s->offset238; + val =3D 7; /* FIXME: should be read from EISA controller */ break; default: RC4030_ERROR("invalid read [" TARGET_FMT_plx "]\n", addr); @@ -275,7 +285,7 @@ break; /* Cache Maintenance */ case 0x0030: - RC4030_ERROR("Cache maintenance not handled yet (val 0x%02x)\n",= val); + s->cache_maint =3D val; break; /* I/O Cache Physical Tag */ case 0x0048: @@ -291,16 +301,10 @@ break; /* I/O Cache Buffer Window */ case 0x0060: - s->cache_bwin =3D val; - /* HACK */ if (s->cache_ltag =3D=3D 0x80000001 && s->cache_bmask =3D=3D 0xf= 0f0f0f) { - target_phys_addr_t dests[] =3D { 4, 0, 8, 0x10 }; - static int current =3D 0; - target_phys_addr_t dest =3D 0 + dests[current]; - uint8_t buf; - current =3D (current + 1) % (ARRAY_SIZE(dests)); - buf =3D s->cache_bwin - 1; - cpu_physical_memory_rw(dest, &buf, 1, 1); + target_phys_addr_t dest =3D s->cache_ptag & ~0x1; + dest +=3D (s->cache_maint & 0x3) << 3; + cpu_physical_memory_rw(dest, (uint8_t*)&val, 4, 1); } break; /* Remote Speed Registers */ @@ -319,6 +323,7 @@ case 0x00d0: case 0x00d8: case 0x00e0: + case 0x00e8: s->rem_speed[(addr - 0x0070) >> 3] =3D val; break; /* DMA channel base address */ @@ -370,6 +375,9 @@ qemu_irq_lower(s->timer_irq); set_next_tick(s); break; + /* EISA interrupt */ + case 0x0238: + break; default: RC4030_ERROR("invalid write of 0x%02x at [" TARGET_FMT_plx "]\n"= , val, addr); break; @@ -580,21 +588,23 @@ int i; =20 s->config =3D 0x410; /* some boards seem to accept 0x104 too */ + s->revision =3D 1; s->invalid_address_register =3D 0; =20 memset(s->dma_regs, 0, sizeof(s->dma_regs)); s->dma_tl_base =3D s->dma_tl_limit =3D 0; =20 s->remote_failed_address =3D s->memory_failed_address =3D 0; + s->cache_maint =3D 0; s->cache_ptag =3D s->cache_ltag =3D 0; - s->cache_bmask =3D s->cache_bwin =3D 0; + s->cache_bmask =3D 0; =20 s->offset210 =3D 0x18186; s->nvram_protect =3D 7; - s->offset238 =3D 7; for (i =3D 0; i < 15; i++) s->rem_speed[i] =3D 7; - s->imr_jazz =3D s->isr_jazz =3D 0; + s->imr_jazz =3D 0x10; /* XXX: required by firmware, but why? */ + s->isr_jazz =3D 0; =20 s->itr =3D 0; =20 @@ -607,7 +617,7 @@ rc4030State* s =3D opaque; int i, j; =20 - if (version_id !=3D 1) + if (version_id !=3D 2) return -EINVAL; =20 s->config =3D qemu_get_be32(f); @@ -617,15 +627,14 @@ s->dma_regs[i][j] =3D qemu_get_be32(f); s->dma_tl_base =3D qemu_get_be32(f); s->dma_tl_limit =3D qemu_get_be32(f); + s->cache_maint =3D qemu_get_be32(f); s->remote_failed_address =3D qemu_get_be32(f); s->memory_failed_address =3D qemu_get_be32(f); s->cache_ptag =3D qemu_get_be32(f); s->cache_ltag =3D qemu_get_be32(f); s->cache_bmask =3D qemu_get_be32(f); - s->cache_bwin =3D qemu_get_be32(f); s->offset210 =3D qemu_get_be32(f); s->nvram_protect =3D qemu_get_be32(f); - s->offset238 =3D qemu_get_be32(f); for (i =3D 0; i < 15; i++) s->rem_speed[i] =3D qemu_get_be32(f); s->imr_jazz =3D qemu_get_be32(f); @@ -650,15 +659,14 @@ qemu_put_be32(f, s->dma_regs[i][j]); qemu_put_be32(f, s->dma_tl_base); qemu_put_be32(f, s->dma_tl_limit); + qemu_put_be32(f, s->cache_maint); qemu_put_be32(f, s->remote_failed_address); qemu_put_be32(f, s->memory_failed_address); qemu_put_be32(f, s->cache_ptag); qemu_put_be32(f, s->cache_ltag); qemu_put_be32(f, s->cache_bmask); - qemu_put_be32(f, s->cache_bwin); qemu_put_be32(f, s->offset210); qemu_put_be32(f, s->nvram_protect); - qemu_put_be32(f, s->offset238); for (i =3D 0; i < 15; i++) qemu_put_be32(f, s->rem_speed[i]); qemu_put_be32(f, s->imr_jazz); @@ -666,44 +674,28 @@ qemu_put_be32(f, s->itr); } =20 -static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, in= t is_write) +static void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, = uint8_t *buf, int len, int is_write) { rc4030State *s =3D opaque; target_phys_addr_t entry_addr; - target_phys_addr_t dma_addr, phys_addr; + target_phys_addr_t phys_addr; dma_pagetable_entry entry; - int index, dev_to_mem; + int index; int ncpy, i; =20 - s->dma_regs[n][DMA_REG_ENABLE] &=3D ~(DMA_FLAG_TC_INTR | DMA_FLAG_ME= M_INTR | DMA_FLAG_ADDR_INTR); - - /* Check DMA channel consistency */ - dev_to_mem =3D (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 !=3D dev_to_mem)) { - s->dma_regs[n][DMA_REG_ENABLE] |=3D DMA_FLAG_MEM_INTR; - return; - } - - if (len > s->dma_regs[n][DMA_REG_COUNT]) - len =3D s->dma_regs[n][DMA_REG_COUNT]; - - dma_addr =3D s->dma_regs[n][DMA_REG_ADDRESS]; i =3D 0; for (;;) { if (i =3D=3D len) { - s->dma_regs[n][DMA_REG_ENABLE] |=3D DMA_FLAG_TC_INTR; break; } =20 - ncpy =3D DMA_PAGESIZE - (dma_addr & (DMA_PAGESIZE - 1)); + ncpy =3D DMA_PAGESIZE - (addr & (DMA_PAGESIZE - 1)); if (ncpy > len - i) ncpy =3D len - i; =20 /* Get DMA translation table entry */ - index =3D dma_addr / DMA_PAGESIZE; + index =3D addr / DMA_PAGESIZE; if (index >=3D s->dma_tl_limit / sizeof(dma_pagetable_entry)) { - s->dma_regs[n][DMA_REG_ENABLE] |=3D DMA_FLAG_MEM_INTR; break; } entry_addr =3D s->dma_tl_base + index * sizeof(dma_pagetable_ent= ry); @@ -712,14 +704,42 @@ cpu_physical_memory_rw(entry_addr, (uint8_t *)&entry, sizeof(ent= ry), 0); =20 /* Read/write data at right place */ - phys_addr =3D entry.frame + (dma_addr & (DMA_PAGESIZE - 1)); + phys_addr =3D entry.frame + (addr & (DMA_PAGESIZE - 1)); cpu_physical_memory_rw(phys_addr, &buf[i], ncpy, is_write); =20 i +=3D ncpy; - dma_addr +=3D ncpy; - s->dma_regs[n][DMA_REG_COUNT] -=3D ncpy; + addr +=3D ncpy; } +} =20 +static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, in= t is_write) +{ + rc4030State *s =3D opaque; + target_phys_addr_t dma_addr; + int dev_to_mem; + + s->dma_regs[n][DMA_REG_ENABLE] &=3D ~(DMA_FLAG_TC_INTR | DMA_FLAG_ME= M_INTR | DMA_FLAG_ADDR_INTR); + + /* Check DMA channel consistency */ + dev_to_mem =3D (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 !=3D dev_to_mem)) { + s->dma_regs[n][DMA_REG_ENABLE] |=3D DMA_FLAG_MEM_INTR; + s->nmi_interrupt |=3D 1 << n; + return; + } + + /* Get start address and len */ + if (len > s->dma_regs[n][DMA_REG_COUNT]) + len =3D s->dma_regs[n][DMA_REG_COUNT]; + dma_addr =3D s->dma_regs[n][DMA_REG_ADDRESS]; + + /* Read/write data at right place */ + rc4030_dma_memory_rw(opaque, dma_addr, buf, len, is_write); + + s->dma_regs[n][DMA_REG_ENABLE] |=3D DMA_FLAG_TC_INTR; + s->dma_regs[n][DMA_REG_COUNT] -=3D len; + #ifdef DEBUG_RC4030_DMA { int i, j; @@ -774,31 +794,30 @@ return s; } =20 -qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus, - rc4030_dma **dmas, - rc4030_dma_function *dma_read, rc4030_dma_function= *dma_write) +void rc4030_init(qemu_irq timer, qemu_irq jazz_bus, struct rc4030_pointe= rs* pointers) { rc4030State *s; int s_chipset, s_jazzio; =20 s =3D qemu_mallocz(sizeof(rc4030State)); =20 - *dmas =3D rc4030_allocate_dmas(s, 4); - *dma_read =3D rc4030_dma_read; - *dma_write =3D rc4030_dma_write; + pointers->memory_rw =3D rc4030_dma_memory_rw; + pointers->mem_opaque =3D s; + pointers->dmas =3D rc4030_allocate_dmas(s, 4); + pointers->dma_read =3D rc4030_dma_read; + pointers->dma_write =3D rc4030_dma_write; + pointers->irqs =3D qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16= ); =20 s->periodic_timer =3D qemu_new_timer(vm_clock, rc4030_periodic_timer= , s); s->timer_irq =3D timer; s->jazz_bus_irq =3D jazz_bus; =20 qemu_register_reset(rc4030_reset, s); - register_savevm("rc4030", 0, 1, rc4030_save, rc4030_load, s); + register_savevm("rc4030", 0, 2, rc4030_save, rc4030_load, s); rc4030_reset(s); =20 s_chipset =3D cpu_register_io_memory(0, rc4030_read, rc4030_write, s= ); cpu_register_physical_memory(0x80000000, 0x300, s_chipset); s_jazzio =3D 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); } --------------090103050307000704080808--