Commit 9ea0b7a1395e5580a7c5f5e296870fff9c130256

Authored by aurel32
1 parent b09d9d46

rc4030 registers improvements

Attached patch documents some registers and simplifies one hack.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7030 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 70 additions and 49 deletions
hw/rc4030.c
1 /* 1 /*
2 * QEMU JAZZ RC4030 chipset 2 * QEMU JAZZ RC4030 chipset
3 * 3 *
4 - * Copyright (c) 2007-2008 Hervé Poussineau 4 + * Copyright (c) 2007-2009 Herve Poussineau
5 * 5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal 7 * of this software and associated documentation files (the "Software"), to deal
@@ -66,6 +66,7 @@ typedef struct dma_pagetable_entry { @@ -66,6 +66,7 @@ typedef struct dma_pagetable_entry {
66 typedef struct rc4030State 66 typedef struct rc4030State
67 { 67 {
68 uint32_t config; /* 0x0000: RC4030 config register */ 68 uint32_t config; /* 0x0000: RC4030 config register */
  69 + uint32_t revision; /* 0x0008: RC4030 Revision register */
69 uint32_t invalid_address_register; /* 0x0010: Invalid Address register */ 70 uint32_t invalid_address_register; /* 0x0010: Invalid Address register */
70 71
71 /* DMA */ 72 /* DMA */
@@ -74,17 +75,17 @@ typedef struct rc4030State @@ -74,17 +75,17 @@ typedef struct rc4030State
74 uint32_t dma_tl_limit; /* 0x0020: DMA transl. table limit */ 75 uint32_t dma_tl_limit; /* 0x0020: DMA transl. table limit */
75 76
76 /* cache */ 77 /* cache */
  78 + uint32_t cache_maint; /* 0x0030: Cache Maintenance */
77 uint32_t remote_failed_address; /* 0x0038: Remote Failed Address */ 79 uint32_t remote_failed_address; /* 0x0038: Remote Failed Address */
78 uint32_t memory_failed_address; /* 0x0040: Memory Failed Address */ 80 uint32_t memory_failed_address; /* 0x0040: Memory Failed Address */
79 uint32_t cache_ptag; /* 0x0048: I/O Cache Physical Tag */ 81 uint32_t cache_ptag; /* 0x0048: I/O Cache Physical Tag */
80 uint32_t cache_ltag; /* 0x0050: I/O Cache Logical Tag */ 82 uint32_t cache_ltag; /* 0x0050: I/O Cache Logical Tag */
81 uint32_t cache_bmask; /* 0x0058: I/O Cache Byte Mask */ 83 uint32_t cache_bmask; /* 0x0058: I/O Cache Byte Mask */
82 - uint32_t cache_bwin; /* 0x0060: I/O Cache Buffer Window */  
83 84
  85 + uint32_t nmi_interrupt; /* 0x0200: interrupt source */
84 uint32_t offset210; 86 uint32_t offset210;
85 uint32_t nvram_protect; /* 0x0220: NV ram protect register */ 87 uint32_t nvram_protect; /* 0x0220: NV ram protect register */
86 - uint32_t offset238;  
87 - uint32_t rem_speed[15]; 88 + uint32_t rem_speed[16];
88 uint32_t imr_jazz; /* Local bus int enable mask */ 89 uint32_t imr_jazz; /* Local bus int enable mask */
89 uint32_t isr_jazz; /* Local bus int source */ 90 uint32_t isr_jazz; /* Local bus int source */
90 91
@@ -118,6 +119,10 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr) @@ -118,6 +119,10 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr)
118 case 0x0000: 119 case 0x0000:
119 val = s->config; 120 val = s->config;
120 break; 121 break;
  122 + /* Revision register */
  123 + case 0x0008:
  124 + val = s->revision;
  125 + break;
121 /* Invalid Address register */ 126 /* Invalid Address register */
122 case 0x0010: 127 case 0x0010:
123 val = s->invalid_address_register; 128 val = s->invalid_address_register;
@@ -161,6 +166,7 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr) @@ -161,6 +166,7 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr)
161 case 0x00d0: 166 case 0x00d0:
162 case 0x00d8: 167 case 0x00d8:
163 case 0x00e0: 168 case 0x00e0:
  169 + case 0x00e8:
164 val = s->rem_speed[(addr - 0x0070) >> 3]; 170 val = s->rem_speed[(addr - 0x0070) >> 3];
165 break; 171 break;
166 /* DMA channel base address */ 172 /* DMA channel base address */
@@ -202,7 +208,11 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr) @@ -202,7 +208,11 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr)
202 val = s->dma_regs[entry][idx]; 208 val = s->dma_regs[entry][idx];
203 } 209 }
204 break; 210 break;
205 - /* Offset 0x0208 */ 211 + /* Interrupt source */
  212 + case 0x0200:
  213 + val = s->nmi_interrupt;
  214 + break;
  215 + /* Error type */
206 case 0x0208: 216 case 0x0208:
207 val = 0; 217 val = 0;
208 break; 218 break;
@@ -219,9 +229,9 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr) @@ -219,9 +229,9 @@ static uint32_t rc4030_readl(void *opaque, target_phys_addr_t addr)
219 val = 0; 229 val = 0;
220 qemu_irq_lower(s->timer_irq); 230 qemu_irq_lower(s->timer_irq);
221 break; 231 break;
222 - /* Offset 0x0238 */ 232 + /* EISA interrupt */
223 case 0x0238: 233 case 0x0238:
224 - val = s->offset238; 234 + val = 7; /* FIXME: should be read from EISA controller */
225 break; 235 break;
226 default: 236 default:
227 RC4030_ERROR("invalid read [" TARGET_FMT_plx "]\n", addr); 237 RC4030_ERROR("invalid read [" TARGET_FMT_plx "]\n", addr);
@@ -275,7 +285,7 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -275,7 +285,7 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
275 break; 285 break;
276 /* Cache Maintenance */ 286 /* Cache Maintenance */
277 case 0x0030: 287 case 0x0030:
278 - RC4030_ERROR("Cache maintenance not handled yet (val 0x%02x)\n", val); 288 + s->cache_maint = val;
279 break; 289 break;
280 /* I/O Cache Physical Tag */ 290 /* I/O Cache Physical Tag */
281 case 0x0048: 291 case 0x0048:
@@ -291,16 +301,11 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -291,16 +301,11 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
291 break; 301 break;
292 /* I/O Cache Buffer Window */ 302 /* I/O Cache Buffer Window */
293 case 0x0060: 303 case 0x0060:
294 - s->cache_bwin = val;  
295 /* HACK */ 304 /* HACK */
296 if (s->cache_ltag == 0x80000001 && s->cache_bmask == 0xf0f0f0f) { 305 if (s->cache_ltag == 0x80000001 && s->cache_bmask == 0xf0f0f0f) {
297 - target_phys_addr_t dests[] = { 4, 0, 8, 0x10 };  
298 - static int current = 0;  
299 - target_phys_addr_t dest = 0 + dests[current];  
300 - uint8_t buf;  
301 - current = (current + 1) % (ARRAY_SIZE(dests));  
302 - buf = s->cache_bwin - 1;  
303 - cpu_physical_memory_rw(dest, &buf, 1, 1); 306 + target_phys_addr_t dest = s->cache_ptag & ~0x1;
  307 + dest += (s->cache_maint & 0x3) << 3;
  308 + cpu_physical_memory_rw(dest, (uint8_t*)&val, 4, 1);
304 } 309 }
305 break; 310 break;
306 /* Remote Speed Registers */ 311 /* Remote Speed Registers */
@@ -319,6 +324,7 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -319,6 +324,7 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
319 case 0x00d0: 324 case 0x00d0:
320 case 0x00d8: 325 case 0x00d8:
321 case 0x00e0: 326 case 0x00e0:
  327 + case 0x00e8:
322 s->rem_speed[(addr - 0x0070) >> 3] = val; 328 s->rem_speed[(addr - 0x0070) >> 3] = val;
323 break; 329 break;
324 /* DMA channel base address */ 330 /* DMA channel base address */
@@ -370,6 +376,9 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val) @@ -370,6 +376,9 @@ static void rc4030_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
370 qemu_irq_lower(s->timer_irq); 376 qemu_irq_lower(s->timer_irq);
371 set_next_tick(s); 377 set_next_tick(s);
372 break; 378 break;
  379 + /* EISA interrupt */
  380 + case 0x0238:
  381 + break;
373 default: 382 default:
374 RC4030_ERROR("invalid write of 0x%02x at [" TARGET_FMT_plx "]\n", val, addr); 383 RC4030_ERROR("invalid write of 0x%02x at [" TARGET_FMT_plx "]\n", val, addr);
375 break; 384 break;
@@ -580,21 +589,23 @@ static void rc4030_reset(void *opaque) @@ -580,21 +589,23 @@ static void rc4030_reset(void *opaque)
580 int i; 589 int i;
581 590
582 s->config = 0x410; /* some boards seem to accept 0x104 too */ 591 s->config = 0x410; /* some boards seem to accept 0x104 too */
  592 + s->revision = 1;
583 s->invalid_address_register = 0; 593 s->invalid_address_register = 0;
584 594
585 memset(s->dma_regs, 0, sizeof(s->dma_regs)); 595 memset(s->dma_regs, 0, sizeof(s->dma_regs));
586 s->dma_tl_base = s->dma_tl_limit = 0; 596 s->dma_tl_base = s->dma_tl_limit = 0;
587 597
588 s->remote_failed_address = s->memory_failed_address = 0; 598 s->remote_failed_address = s->memory_failed_address = 0;
  599 + s->cache_maint = 0;
589 s->cache_ptag = s->cache_ltag = 0; 600 s->cache_ptag = s->cache_ltag = 0;
590 - s->cache_bmask = s->cache_bwin = 0; 601 + s->cache_bmask = 0;
591 602
592 s->offset210 = 0x18186; 603 s->offset210 = 0x18186;
593 s->nvram_protect = 7; 604 s->nvram_protect = 7;
594 - s->offset238 = 7;  
595 for (i = 0; i < 15; i++) 605 for (i = 0; i < 15; i++)
596 s->rem_speed[i] = 7; 606 s->rem_speed[i] = 7;
597 - s->imr_jazz = s->isr_jazz = 0; 607 + s->imr_jazz = 0x10; /* XXX: required by firmware, but why? */
  608 + s->isr_jazz = 0;
598 609
599 s->itr = 0; 610 s->itr = 0;
600 611
@@ -607,7 +618,7 @@ static int rc4030_load(QEMUFile *f, void *opaque, int version_id) @@ -607,7 +618,7 @@ static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
607 rc4030State* s = opaque; 618 rc4030State* s = opaque;
608 int i, j; 619 int i, j;
609 620
610 - if (version_id != 1) 621 + if (version_id != 2)
611 return -EINVAL; 622 return -EINVAL;
612 623
613 s->config = qemu_get_be32(f); 624 s->config = qemu_get_be32(f);
@@ -617,15 +628,14 @@ static int rc4030_load(QEMUFile *f, void *opaque, int version_id) @@ -617,15 +628,14 @@ static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
617 s->dma_regs[i][j] = qemu_get_be32(f); 628 s->dma_regs[i][j] = qemu_get_be32(f);
618 s->dma_tl_base = qemu_get_be32(f); 629 s->dma_tl_base = qemu_get_be32(f);
619 s->dma_tl_limit = qemu_get_be32(f); 630 s->dma_tl_limit = qemu_get_be32(f);
  631 + s->cache_maint = qemu_get_be32(f);
620 s->remote_failed_address = qemu_get_be32(f); 632 s->remote_failed_address = qemu_get_be32(f);
621 s->memory_failed_address = qemu_get_be32(f); 633 s->memory_failed_address = qemu_get_be32(f);
622 s->cache_ptag = qemu_get_be32(f); 634 s->cache_ptag = qemu_get_be32(f);
623 s->cache_ltag = qemu_get_be32(f); 635 s->cache_ltag = qemu_get_be32(f);
624 s->cache_bmask = qemu_get_be32(f); 636 s->cache_bmask = qemu_get_be32(f);
625 - s->cache_bwin = qemu_get_be32(f);  
626 s->offset210 = qemu_get_be32(f); 637 s->offset210 = qemu_get_be32(f);
627 s->nvram_protect = qemu_get_be32(f); 638 s->nvram_protect = qemu_get_be32(f);
628 - s->offset238 = qemu_get_be32(f);  
629 for (i = 0; i < 15; i++) 639 for (i = 0; i < 15; i++)
630 s->rem_speed[i] = qemu_get_be32(f); 640 s->rem_speed[i] = qemu_get_be32(f);
631 s->imr_jazz = qemu_get_be32(f); 641 s->imr_jazz = qemu_get_be32(f);
@@ -650,15 +660,14 @@ static void rc4030_save(QEMUFile *f, void *opaque) @@ -650,15 +660,14 @@ static void rc4030_save(QEMUFile *f, void *opaque)
650 qemu_put_be32(f, s->dma_regs[i][j]); 660 qemu_put_be32(f, s->dma_regs[i][j]);
651 qemu_put_be32(f, s->dma_tl_base); 661 qemu_put_be32(f, s->dma_tl_base);
652 qemu_put_be32(f, s->dma_tl_limit); 662 qemu_put_be32(f, s->dma_tl_limit);
  663 + qemu_put_be32(f, s->cache_maint);
653 qemu_put_be32(f, s->remote_failed_address); 664 qemu_put_be32(f, s->remote_failed_address);
654 qemu_put_be32(f, s->memory_failed_address); 665 qemu_put_be32(f, s->memory_failed_address);
655 qemu_put_be32(f, s->cache_ptag); 666 qemu_put_be32(f, s->cache_ptag);
656 qemu_put_be32(f, s->cache_ltag); 667 qemu_put_be32(f, s->cache_ltag);
657 qemu_put_be32(f, s->cache_bmask); 668 qemu_put_be32(f, s->cache_bmask);
658 - qemu_put_be32(f, s->cache_bwin);  
659 qemu_put_be32(f, s->offset210); 669 qemu_put_be32(f, s->offset210);
660 qemu_put_be32(f, s->nvram_protect); 670 qemu_put_be32(f, s->nvram_protect);
661 - qemu_put_be32(f, s->offset238);  
662 for (i = 0; i < 15; i++) 671 for (i = 0; i < 15; i++)
663 qemu_put_be32(f, s->rem_speed[i]); 672 qemu_put_be32(f, s->rem_speed[i]);
664 qemu_put_be32(f, s->imr_jazz); 673 qemu_put_be32(f, s->imr_jazz);
@@ -666,44 +675,28 @@ static void rc4030_save(QEMUFile *f, void *opaque) @@ -666,44 +675,28 @@ static void rc4030_save(QEMUFile *f, void *opaque)
666 qemu_put_be32(f, s->itr); 675 qemu_put_be32(f, s->itr);
667 } 676 }
668 677
669 -static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write) 678 +static void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write)
670 { 679 {
671 rc4030State *s = opaque; 680 rc4030State *s = opaque;
672 target_phys_addr_t entry_addr; 681 target_phys_addr_t entry_addr;
673 - target_phys_addr_t dma_addr, phys_addr; 682 + target_phys_addr_t phys_addr;
674 dma_pagetable_entry entry; 683 dma_pagetable_entry entry;
675 - int index, dev_to_mem; 684 + int index;
676 int ncpy, i; 685 int ncpy, i;
677 686
678 - s->dma_regs[n][DMA_REG_ENABLE] &= ~(DMA_FLAG_TC_INTR | DMA_FLAG_MEM_INTR | DMA_FLAG_ADDR_INTR);  
679 -  
680 - /* Check DMA channel consistency */  
681 - dev_to_mem = (s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_MEM_TO_DEV) ? 0 : 1;  
682 - if (!(s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_ENABLE) ||  
683 - (is_write != dev_to_mem)) {  
684 - s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;  
685 - return;  
686 - }  
687 -  
688 - if (len > s->dma_regs[n][DMA_REG_COUNT])  
689 - len = s->dma_regs[n][DMA_REG_COUNT];  
690 -  
691 - dma_addr = s->dma_regs[n][DMA_REG_ADDRESS];  
692 i = 0; 687 i = 0;
693 for (;;) { 688 for (;;) {
694 if (i == len) { 689 if (i == len) {
695 - s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_TC_INTR;  
696 break; 690 break;
697 } 691 }
698 692
699 - ncpy = DMA_PAGESIZE - (dma_addr & (DMA_PAGESIZE - 1)); 693 + ncpy = DMA_PAGESIZE - (addr & (DMA_PAGESIZE - 1));
700 if (ncpy > len - i) 694 if (ncpy > len - i)
701 ncpy = len - i; 695 ncpy = len - i;
702 696
703 /* Get DMA translation table entry */ 697 /* Get DMA translation table entry */
704 - index = dma_addr / DMA_PAGESIZE; 698 + index = addr / DMA_PAGESIZE;
705 if (index >= s->dma_tl_limit / sizeof(dma_pagetable_entry)) { 699 if (index >= s->dma_tl_limit / sizeof(dma_pagetable_entry)) {
706 - s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;  
707 break; 700 break;
708 } 701 }
709 entry_addr = s->dma_tl_base + index * sizeof(dma_pagetable_entry); 702 entry_addr = s->dma_tl_base + index * sizeof(dma_pagetable_entry);
@@ -712,14 +705,42 @@ static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_wri @@ -712,14 +705,42 @@ static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_wri
712 cpu_physical_memory_rw(entry_addr, (uint8_t *)&entry, sizeof(entry), 0); 705 cpu_physical_memory_rw(entry_addr, (uint8_t *)&entry, sizeof(entry), 0);
713 706
714 /* Read/write data at right place */ 707 /* Read/write data at right place */
715 - phys_addr = entry.frame + (dma_addr & (DMA_PAGESIZE - 1)); 708 + phys_addr = entry.frame + (addr & (DMA_PAGESIZE - 1));
716 cpu_physical_memory_rw(phys_addr, &buf[i], ncpy, is_write); 709 cpu_physical_memory_rw(phys_addr, &buf[i], ncpy, is_write);
717 710
718 i += ncpy; 711 i += ncpy;
719 - dma_addr += ncpy;  
720 - s->dma_regs[n][DMA_REG_COUNT] -= ncpy; 712 + addr += ncpy;
  713 + }
  714 +}
  715 +
  716 +static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write)
  717 +{
  718 + rc4030State *s = opaque;
  719 + target_phys_addr_t dma_addr;
  720 + int dev_to_mem;
  721 +
  722 + s->dma_regs[n][DMA_REG_ENABLE] &= ~(DMA_FLAG_TC_INTR | DMA_FLAG_MEM_INTR | DMA_FLAG_ADDR_INTR);
  723 +
  724 + /* Check DMA channel consistency */
  725 + dev_to_mem = (s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_MEM_TO_DEV) ? 0 : 1;
  726 + if (!(s->dma_regs[n][DMA_REG_ENABLE] & DMA_FLAG_ENABLE) ||
  727 + (is_write != dev_to_mem)) {
  728 + s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_MEM_INTR;
  729 + s->nmi_interrupt |= 1 << n;
  730 + return;
721 } 731 }
722 732
  733 + /* Get start address and len */
  734 + if (len > s->dma_regs[n][DMA_REG_COUNT])
  735 + len = s->dma_regs[n][DMA_REG_COUNT];
  736 + dma_addr = s->dma_regs[n][DMA_REG_ADDRESS];
  737 +
  738 + /* Read/write data at right place */
  739 + rc4030_dma_memory_rw(opaque, dma_addr, buf, len, is_write);
  740 +
  741 + s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_TC_INTR;
  742 + s->dma_regs[n][DMA_REG_COUNT] -= len;
  743 +
723 #ifdef DEBUG_RC4030_DMA 744 #ifdef DEBUG_RC4030_DMA
724 { 745 {
725 int i, j; 746 int i, j;
@@ -792,7 +813,7 @@ qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus, @@ -792,7 +813,7 @@ qemu_irq *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
792 s->jazz_bus_irq = jazz_bus; 813 s->jazz_bus_irq = jazz_bus;
793 814
794 qemu_register_reset(rc4030_reset, s); 815 qemu_register_reset(rc4030_reset, s);
795 - register_savevm("rc4030", 0, 1, rc4030_save, rc4030_load, s); 816 + register_savevm("rc4030", 0, 2, rc4030_save, rc4030_load, s);
796 rc4030_reset(s); 817 rc4030_reset(s);
797 818
798 s_chipset = cpu_register_io_memory(0, rc4030_read, rc4030_write, s); 819 s_chipset = cpu_register_io_memory(0, rc4030_read, rc4030_write, s);