sparc merge (Blue Swirl)
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 4 Oct 2004 21:23:09 +0000 (21:23 +0000)
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 4 Oct 2004 21:23:09 +0000 (21:23 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1098 c046a42c-6fe2-441c-8c8c-71466251a162

23 files changed:
Makefile
Makefile.target
gdbstub.c
hw/iommu.c
hw/lance.c
hw/m48t08.c
hw/m48t08.h
hw/magic-load.c
hw/sched.c
hw/sun4m.c
hw/tcx.c
monitor.c
pc-bios/README
pc-bios/proll.bin [new file with mode: 0644]
pc-bios/proll.patch [new file with mode: 0644]
target-sparc/cpu.h
target-sparc/exec.h
target-sparc/helper.c
target-sparc/op.c
target-sparc/op_helper.c
target-sparc/op_mem.h
tests/Makefile
vl.h

index f80db8b..d4d8028 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-include config-host.mak
+-include config-host.mak
 
 CFLAGS=-Wall -O2 -g -fno-strict-aliasing 
 ifdef CONFIG_DARWIN
@@ -14,8 +14,9 @@ TOOLS=qemu-img
 ifdef CONFIG_STATIC
 LDFLAGS+=-static
 endif
+DOCS=qemu-doc.html qemu-tech.html qemu.1
 
-all: dyngen$(EXESUF) $(TOOLS) qemu-doc.html qemu-tech.html qemu.1
+all: dyngen$(EXESUF) $(TOOLS) $(DOCS)
        for d in $(TARGET_DIRS); do \
        $(MAKE) -C $$d $@ || exit 1 ; \
         done
@@ -29,14 +30,14 @@ dyngen$(EXESUF): dyngen.c
 clean:
 # avoid old build problems by removing potentially incorrect old files
        rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h 
-       rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod
+       rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod *~ */*~
        $(MAKE) -C tests clean
        for d in $(TARGET_DIRS); do \
        $(MAKE) -C $$d $@ || exit 1 ; \
         done
 
 distclean: clean
-       rm -f config-host.mak config-host.h
+       rm -f config-host.mak config-host.h $(DOCS)
        for d in $(TARGET_DIRS); do \
        rm -rf $$d || exit 1 ; \
         done
@@ -50,6 +51,7 @@ endif
        install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
                        pc-bios/vgabios-cirrus.bin \
                        pc-bios/ppc_rom.bin \
+                       pc-bios/proll.bin \
                        pc-bios/linux_boot.bin "$(datadir)"
        mkdir -p "$(docdir)"
        install -m 644 qemu-doc.html  qemu-tech.html "$(docdir)"
@@ -99,6 +101,7 @@ tarbin:
        $(datadir)/vgabios.bin \
        $(datadir)/vgabios-cirrus.bin \
        $(datadir)/ppc_rom.bin \
+       $(datadir)/proll.bin \
        $(datadir)/linux_boot.bin \
        $(docdir)/qemu-doc.html \
        $(docdir)/qemu-tech.html \
index ff07be8..6ac8d9f 100644 (file)
@@ -279,7 +279,7 @@ VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
 VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o
 endif
 ifeq ($(TARGET_ARCH), sparc)
-VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o
+VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
 endif
 ifdef CONFIG_GDBSTUB
 VL_OBJS+=gdbstub.o 
index e15216a..2491c2c 100644 (file)
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -387,6 +387,9 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             env->eip = addr;
 #elif defined (TARGET_PPC)
             env->nip = addr;
+#elif defined (TARGET_SPARC)
+            env->pc = addr;
+            env->npc = addr + 4;
 #endif
         }
         vm_start();
@@ -398,6 +401,9 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             env->eip = addr;
 #elif defined (TARGET_PPC)
             env->nip = addr;
+#elif defined (TARGET_SPARC)
+            env->pc = addr;
+            env->npc = addr + 4;
 #endif
         }
         cpu_single_step(env, 1);
index f00bb78..a9249c4 100644 (file)
@@ -107,29 +107,24 @@ struct iommu_regs {
 #define IOPTE_VALID         0x00000002 /* IOPTE is valid */
 #define IOPTE_WAZ           0x00000001 /* Write as zeros */
 
-#define PHYS_JJ_IOMMU  0x10000000      /* First page of sun4m IOMMU */
 #define PAGE_SHIFT      12
 #define PAGE_SIZE       (1 << PAGE_SHIFT)
 #define PAGE_MASK      (PAGE_SIZE - 1)
 
 typedef struct IOMMUState {
+    uint32_t addr;
     uint32_t regs[sizeof(struct iommu_regs)];
+    uint32_t iostart;
 } IOMMUState;
 
 static IOMMUState *ps;
 
-static int iommu_io_memory;
-
-static void iommu_reset(IOMMUState *s)
-{
-}
-
 static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
 {
     IOMMUState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_IOMMU) >> 2;
+    saddr = (addr - s->addr) >> 2;
     switch (saddr) {
     default:
        return s->regs[saddr];
@@ -143,8 +138,37 @@ static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
     IOMMUState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_IOMMU) >> 2;
+    saddr = (addr - s->addr) >> 2;
     switch (saddr) {
+    case 0:
+       switch (val & IOMMU_CTRL_RNGE) {
+       case IOMMU_RNGE_16MB:
+           s->iostart = 0xff000000;
+           break;
+       case IOMMU_RNGE_32MB:
+           s->iostart = 0xfe000000;
+           break;
+       case IOMMU_RNGE_64MB:
+           s->iostart = 0xfc000000;
+           break;
+       case IOMMU_RNGE_128MB:
+           s->iostart = 0xf8000000;
+           break;
+       case IOMMU_RNGE_256MB:
+           s->iostart = 0xf0000000;
+           break;
+       case IOMMU_RNGE_512MB:
+           s->iostart = 0xe0000000;
+           break;
+       case IOMMU_RNGE_1GB:
+           s->iostart = 0xc0000000;
+           break;
+       default:
+       case IOMMU_RNGE_2GB:
+           s->iostart = 0x80000000;
+           break;
+       }
+       /* Fall through */
     default:
        s->regs[saddr] = val;
        break;
@@ -165,57 +189,30 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
 
 uint32_t iommu_translate(uint32_t addr)
 {
-    uint32_t *iopte = (void *)(ps->regs[1] << 4), pa, iostart;
-
-    switch (ps->regs[0] & IOMMU_CTRL_RNGE) {
-    case IOMMU_RNGE_16MB:
-       iostart = 0xff000000;
-       break;
-    case IOMMU_RNGE_32MB:
-       iostart = 0xfe000000;
-       break;
-    case IOMMU_RNGE_64MB:
-       iostart = 0xfc000000;
-       break;
-    case IOMMU_RNGE_128MB:
-       iostart = 0xf8000000;
-       break;
-    case IOMMU_RNGE_256MB:
-       iostart = 0xf0000000;
-       break;
-    case IOMMU_RNGE_512MB:
-       iostart = 0xe0000000;
-       break;
-    case IOMMU_RNGE_1GB:
-       iostart = 0xc0000000;
-       break;
-    default:
-    case IOMMU_RNGE_2GB:
-       iostart = 0x80000000;
-       break;
-    }
+    uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
 
-    iopte += ((addr - iostart) >> PAGE_SHIFT);
+    iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
     cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
     bswap32s(&pa);
     pa = (pa & IOPTE_PAGE) << 4;               /* Loose higher bits of 36 */
-    //return pa + PAGE_SIZE;
     return pa + (addr & PAGE_MASK);
 }
 
-void iommu_init()
+void iommu_init(uint32_t addr)
 {
     IOMMUState *s;
+    int iommu_io_memory;
 
     s = qemu_mallocz(sizeof(IOMMUState));
     if (!s)
         return;
 
+    s->addr = addr;
+
     iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
-    cpu_register_physical_memory(PHYS_JJ_IOMMU, sizeof(struct iommu_regs),
+    cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
                                  iommu_io_memory);
     
-    iommu_reset(s);
     ps = s;
 }
 
index e461ade..25ad8c4 100644 (file)
 #include "vl.h"
 
 /* debug LANCE card */
-#define DEBUG_LANCE
-
-#define PHYS_JJ_IOMMU  0x10000000      /* First page of sun4m IOMMU */
-#define PHYS_JJ_LEDMA   0x78400010      /* ledma, off by 10 from unused SCSI */
-#define PHYS_JJ_LE      0x78C00000      /* LANCE, typical sun4m */
+//#define DEBUG_LANCE
 
 #ifndef LANCE_LOG_TX_BUFFERS
 #define LANCE_LOG_TX_BUFFERS 4
@@ -162,10 +158,12 @@ struct sparc_dma_registers {
 #endif
 
 typedef struct LEDMAState {
+    uint32_t addr;
     uint32_t regs[LEDMA_REGS];
 } LEDMAState;
 
 typedef struct LANCEState {
+    uint32_t paddr;
     NetDriverState *nd;
     uint32_t leptr;
     uint16_t addr;
@@ -175,8 +173,6 @@ typedef struct LANCEState {
     LEDMAState *ledma;
 } LANCEState;
 
-static int lance_io_memory;
-
 static unsigned int rxptr, txptr;
 
 static void lance_send(void *opaque);
@@ -194,7 +190,7 @@ static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
     LANCEState *s = opaque;
     uint32_t saddr;
 
-    saddr = addr - PHYS_JJ_LE;
+    saddr = addr - s->paddr;
     switch (saddr >> 1) {
     case LE_RDP:
        return s->regs[s->addr];
@@ -210,9 +206,9 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
 {
     LANCEState *s = opaque;
     uint32_t saddr;
-    uint16_t clear, reg;
+    uint16_t reg;
 
-    saddr = addr - PHYS_JJ_LE;
+    saddr = addr - s->paddr;
     switch (saddr >> 1) {
     case LE_RDP:
        switch(s->addr) {
@@ -406,14 +402,12 @@ static void lance_send(void *opaque)
     }
 }
 
-static int ledma_io_memory;
-
 static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
 {
     LEDMAState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_LEDMA) >> 2;
+    saddr = (addr - s->addr) >> 2;
     if (saddr < LEDMA_REGS)
        return s->regs[saddr];
     else
@@ -425,7 +419,7 @@ static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val
     LEDMAState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_LEDMA) >> 2;
+    saddr = (addr - s->addr) >> 2;
     if (saddr < LEDMA_REGS)
        s->regs[saddr] = val;
 }
@@ -442,29 +436,31 @@ static CPUWriteMemoryFunc *ledma_mem_write[3] = {
     ledma_mem_writel,
 };
 
-void lance_init(NetDriverState *nd, int irq)
+void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
 {
     LANCEState *s;
     LEDMAState *led;
+    int lance_io_memory, ledma_io_memory;
 
     s = qemu_mallocz(sizeof(LANCEState));
     if (!s)
         return;
 
+    s->paddr = leaddr;
+    s->nd = nd;
+    s->irq = irq;
+
     lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
-    cpu_register_physical_memory(PHYS_JJ_LE, 8,
-                                 lance_io_memory);
+    cpu_register_physical_memory(leaddr, 8, lance_io_memory);
+
     led = qemu_mallocz(sizeof(LEDMAState));
     if (!led)
         return;
 
-    ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
-    cpu_register_physical_memory(PHYS_JJ_LEDMA, 16,
-                                 ledma_io_memory);
-
-    s->nd = nd;
     s->ledma = led;
-    s->irq = irq;
+    led->addr = ledaddr;
+    ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
+    cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
 
     lance_reset(s);
     qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
index c5b6e7a..46ec665 100644 (file)
@@ -341,7 +341,7 @@ static CPUReadMemoryFunc *nvram_read[] = {
 };
 
 /* Initialisation routine */
-m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
+m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
 {
     m48t08_t *s;
     int i;
@@ -367,7 +367,7 @@ m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
     i = 0x1fd8;
     s->buffer[i++] = 0x01;
     s->buffer[i++] = 0x80; /* Sun4m OBP */
-    /* XXX: Ethernet address, etc */
+    memcpy(&s->buffer[i], macaddr, 6);
 
     /* Calculate checksum */
     for (i = 0x1fd8; i < 0x1fe7; i++) {
index 2a754b6..9b44bc0 100644 (file)
@@ -7,6 +7,6 @@ void m48t08_write (m48t08_t *NVRAM, uint32_t val);
 uint32_t m48t08_read (m48t08_t *NVRAM);
 void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr);
 void m48t08_toggle_lock (m48t08_t *NVRAM, int lock);
-m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size);
+m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr);
 
 #endif /* !defined (__M48T08_H__) */
index 7365183..06a5f74 100644 (file)
@@ -1,41 +1,12 @@
-/* This is the Linux kernel elf-loading code, ported into user space */
 #include "vl.h"
 #include "disas.h"
 
-/* XXX: this code is not used as it is under the GPL license. Please
-   remove or recode it */
-//#define USE_ELF_LOADER
-
-#ifdef USE_ELF_LOADER
-/* should probably go in elf.h */
-#ifndef ELIBBAD
-#define ELIBBAD 80
-#endif
-
-
-#define ELF_START_MMAP 0x80000000
-
-#define elf_check_arch(x) ( (x) == EM_SPARC )
-
 #define ELF_CLASS   ELFCLASS32
 #define ELF_DATA    ELFDATA2MSB
 #define ELF_ARCH    EM_SPARC
 
 #include "elf.h"
 
-/*
- * This structure is used to hold the arguments that are 
- * used when loading binaries.
- */
-struct linux_binprm {
-        char buf[128];
-       int fd;
-};
-
-#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
-#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
-#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
-
 #ifdef BSWAP_NEEDED
 static void bswap_ehdr(Elf32_Ehdr *ehdr)
 {
@@ -87,186 +58,192 @@ static void bswap_sym(Elf32_Sym *sym)
     bswap32s(&sym->st_size);
     bswap16s(&sym->st_shndx);
 }
+#else
+#define bswap_ehdr(e) do { } while (0)
+#define bswap_phdr(e) do { } while (0)
+#define bswap_shdr(e) do { } while (0)
+#define bswap_sym(e) do { } while (0)
 #endif
 
-static int prepare_binprm(struct linux_binprm *bprm)
+static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type)
 {
-    int retval;
-
-    memset(bprm->buf, 0, sizeof(bprm->buf));
-    retval = lseek(bprm->fd, 0L, SEEK_SET);
-    if(retval >= 0) {
-        retval = read(bprm->fd, bprm->buf, 128);
-    }
-    if(retval < 0) {
-       perror("prepare_binprm");
-       exit(-1);
-       /* return(-errno); */
-    }
-    else {
-       return(retval);
+    int i, retval;
+
+    retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
+    if (retval < 0)
+       return -1;
+
+    for (i = 0; i < ehdr->e_phnum; i++) {
+       retval = read(fd, phdr, sizeof(*phdr));
+       if (retval < 0)
+           return -1;
+       bswap_phdr(phdr);
+       if (phdr->p_type == type)
+           return 0;
     }
+    return -1;
 }
 
-/* Best attempt to load symbols from this ELF object. */
-static void load_symbols(struct elfhdr *hdr, int fd)
+static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
 {
-    unsigned int i;
-    struct elf_shdr sechdr, symtab, strtab;
-    char *strings;
-
-    lseek(fd, hdr->e_shoff, SEEK_SET);
-    for (i = 0; i < hdr->e_shnum; i++) {
-       if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
-           return;
-#ifdef BSWAP_NEEDED
-       bswap_shdr(&sechdr);
-#endif
-       if (sechdr.sh_type == SHT_SYMTAB) {
-           symtab = sechdr;
-           lseek(fd, hdr->e_shoff
-                 + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
-           if (read(fd, &strtab, sizeof(strtab))
-               != sizeof(strtab))
-               return;
-#ifdef BSWAP_NEEDED
-           bswap_shdr(&strtab);
-#endif
-           goto found;
-       }
+    int i, retval;
+
+    retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
+    if (retval < 0)
+       return NULL;
+
+    for (i = 0; i < ehdr->e_shnum; i++) {
+       retval = read(fd, shdr, sizeof(*shdr));
+       if (retval < 0)
+           return NULL;
+       bswap_shdr(shdr);
+       if (shdr->sh_type == type)
+           return qemu_malloc(shdr->sh_size);
     }
-    return; /* Shouldn't happen... */
-
- found:
-    /* Now know where the strtab and symtab are.  Snarf them. */
-    disas_symtab = qemu_malloc(symtab.sh_size);
-    disas_strtab = strings = qemu_malloc(strtab.sh_size);
-    if (!disas_symtab || !disas_strtab)
-       return;
-       
-    lseek(fd, symtab.sh_offset, SEEK_SET);
-    if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size)
-       return;
+    return NULL;
+}
 
-#ifdef BSWAP_NEEDED
-    for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++)
-       bswap_sym(disas_symtab + sizeof(struct elf_sym)*i);
-#endif
+static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
+{
+    int retval;
 
-    lseek(fd, strtab.sh_offset, SEEK_SET);
-    if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
-       return;
-    disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
+    retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
+    if (retval < 0)
+       return -1;
+
+    retval = read(fd, shdr, sizeof(*shdr));
+    if (retval < 0)
+       return -1;
+    bswap_shdr(shdr);
+    if (shdr->sh_type == SHT_STRTAB)
+       return qemu_malloc(shdr->sh_size);;
+    return 0;
 }
 
-static int load_elf_binary(struct linux_binprm * bprm, uint8_t *addr)
+static int read_program(int fd, struct elf_phdr *phdr, void *dst)
 {
-    struct elfhdr elf_ex;
-    unsigned long startaddr = addr;
-    int i;
-    struct elf_phdr * elf_ppnt;
-    struct elf_phdr *elf_phdata;
     int retval;
+    retval = lseek(fd, 0x4000, SEEK_SET);
+    if (retval < 0)
+       return -1;
+    return read(fd, dst, phdr->p_filesz);
+}
 
-    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
-#ifdef BSWAP_NEEDED
-    bswap_ehdr(&elf_ex);
-#endif
+static int read_section(int fd, struct elf_shdr *s, void *dst)
+{
+    int retval;
 
-    if (elf_ex.e_ident[0] != 0x7f ||
-       strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
-       return  -ENOEXEC;
-    }
+    retval = lseek(fd, s->sh_offset, SEEK_SET);
+    if (retval < 0)
+       return -1;
+    retval = read(fd, dst, s->sh_size);
+    if (retval < 0)
+       return -1;
+    return 0;
+}
 
-    /* First of all, some simple consistency checks */
-    if (! elf_check_arch(elf_ex.e_machine)) {
-       return -ENOEXEC;
-    }
+static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
+{
+    void *dst;
+
+    dst = find_shdr(ehdr, fd, shdr, type);
+    if (!dst)
+       goto error;
+
+    if (read_section(fd, shdr, dst))
+       goto error;
+    return dst;
+ error:
+    qemu_free(dst);
+    return NULL;
+}
 
-    /* Now read in all of the header information */
-    elf_phdata = (struct elf_phdr *)qemu_malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
-    if (elf_phdata == NULL) {
-       return -ENOMEM;
-    }
+static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
+{
+    void *dst;
+
+    dst = find_strtab(ehdr, fd, shdr, symtab);
+    if (!dst)
+       goto error;
+
+    if (read_section(fd, shdr, dst))
+       goto error;
+    return dst;
+ error:
+    qemu_free(dst);
+    return NULL;
+}
 
-    retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
-    if(retval > 0) {
-       retval = read(bprm->fd, (char *) elf_phdata, 
-                               elf_ex.e_phentsize * elf_ex.e_phnum);
-    }
+static void load_symbols(struct elfhdr *ehdr, int fd)
+{
+    struct elf_shdr symtab, strtab;
+    struct elf_sym *syms;
+    int nsyms, i;
+    char *str;
+
+    /* Symbol table */
+    syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB);
+    if (!syms)
+       return;
 
-    if (retval < 0) {
-       perror("load_elf_binary");
-       exit(-1);
-       qemu_free (elf_phdata);
-       return -errno;
-    }
+    nsyms = symtab.sh_size / sizeof(struct elf_sym);
+    for (i = 0; i < nsyms; i++)
+       bswap_sym(&syms[i]);
+
+    /* String table */
+    str = process_strtab(ehdr, fd, &strtab, &symtab);
+    if (!str)
+       goto error_freesyms;
+
+    /* Commit */
+    if (disas_symtab)
+       qemu_free(disas_symtab); /* XXX Merge with old symbols? */
+    if (disas_strtab)
+       qemu_free(disas_strtab);
+    disas_symtab = syms;
+    disas_num_syms = nsyms;
+    disas_strtab = str;
+    return;
+ error_freesyms:
+    qemu_free(syms);
+    return;
+}
 
-#ifdef BSWAP_NEEDED
-    elf_ppnt = elf_phdata;
-    for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
-        bswap_phdr(elf_ppnt);
-    }
-#endif
-    elf_ppnt = elf_phdata;
-
-    /* Now we do a little grungy work by mmaping the ELF image into
-     * the correct location in memory.  At this point, we assume that
-     * the image should be loaded at fixed address, not at a variable
-     * address.
-     */
-
-    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
-        unsigned long error, offset, len;
-        
-       if (elf_ppnt->p_type != PT_LOAD)
-            continue;
-#if 0        
-        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
-                            elf_prot,
-                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
-                            bprm->fd,
-                            (elf_ppnt->p_offset - 
-                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
-#endif
-       //offset = elf_ppnt->p_offset - TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr);
-       offset = 0x4000;
-       lseek(bprm->fd, offset, SEEK_SET);
-       len = elf_ppnt->p_filesz + TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr);
-       error = read(bprm->fd, addr, len); 
-
-        if (error == -1) {
-            perror("mmap");
-            exit(-1);
-        }
-       addr += len;
-    }
+int load_elf(const char * filename, uint8_t *addr)
+{
+    struct elfhdr ehdr;
+    struct elf_phdr phdr;
+    int retval, fd;
 
-    qemu_free(elf_phdata);
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if (fd < 0)
+       goto error;
 
-    load_symbols(&elf_ex, bprm->fd);
+    retval = read(fd, &ehdr, sizeof(ehdr));
+    if (retval < 0)
+       goto error;
 
-    return addr-startaddr;
-}
+    bswap_ehdr(&ehdr);
 
-int elf_exec(const char * filename, uint8_t *addr)
-{
-        struct linux_binprm bprm;
-        int retval;
+    if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
+       || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
+       || ehdr.e_machine != EM_SPARC)
+       goto error;
 
-        retval = open(filename, O_RDONLY);
-        if (retval < 0)
-            return retval;
-        bprm.fd = retval;
+    if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
+       goto error;
+    retval = read_program(fd, &phdr, addr);
+    if (retval < 0)
+       goto error;
 
-        retval = prepare_binprm(&bprm);
+    load_symbols(&ehdr, fd);
 
-        if(retval>=0) {
-           retval = load_elf_binary(&bprm, addr);
-       }
-       return retval;
+    close(fd);
+    return retval;
+ error:
+    close(fd);
+    return -1;
 }
-#endif
 
 int load_kernel(const char *filename, uint8_t *addr)
 {
@@ -286,28 +263,31 @@ int load_kernel(const char *filename, uint8_t *addr)
     return -1;
 }
 
-static char saved_kfn[1024];
-static uint32_t saved_addr;
-static int magic_state;
+typedef struct MAGICState {
+    uint32_t addr;
+    uint32_t saved_addr;
+    int magic_state;
+    char saved_kfn[1024];
+} MAGICState;
 
 static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
 {
     int ret;
+    MAGICState *s = opaque;
 
-    if (magic_state == 0) {
-#ifdef USE_ELF_LOADER
-        ret = elf_exec(saved_kfn, saved_addr);
-#else
-        ret = load_kernel(saved_kfn, (uint8_t *)saved_addr);
-#endif
+    if (s->magic_state == 0) {
+        ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr);
+       if (ret < 0)
+           ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr);
         if (ret < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n", 
-                    saved_kfn);
+                    s->saved_kfn);
         }
-       magic_state = 1; /* No more magic */
+       s->magic_state = 1; /* No more magic */
        tb_flush();
+       return bswap32(ret);
     }
-    return ret;
+    return 0;
 }
 
 static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
@@ -327,15 +307,20 @@ static CPUWriteMemoryFunc *magic_mem_write[3] = {
     magic_mem_writel,
 };
 
-void magic_init(const char *kfn, int kloadaddr)
+void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
 {
     int magic_io_memory;
-
-    strcpy(saved_kfn, kfn);
-    saved_addr = kloadaddr;
-    magic_state = 0;
-    magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, 0);
-    cpu_register_physical_memory(0x20000000, 4,
-                                 magic_io_memory);
+    MAGICState *s;
+
+    s = qemu_mallocz(sizeof(MAGICState));
+    if (!s)
+        return;
+
+    strcpy(s->saved_kfn, kfn);
+    s->saved_addr = kloadaddr;
+    s->magic_state = 0;
+    s->addr = addr;
+    magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, s);
+    cpu_register_physical_memory(addr, 4, magic_io_memory);
 }
 
index c9a685d..2ab966d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * QEMU interrupt controller & timer emulation
+ * QEMU interrupt controller emulation
  * 
  * Copyright (c) 2003-2004 Fabrice Bellard
  * 
  * THE SOFTWARE.
  */
 #include "vl.h"
-
-#define PHYS_JJ_CLOCK  0x71D00000
-#define PHYS_JJ_CLOCK1 0x71D10000
-#define PHYS_JJ_INTR0  0x71E00000      /* CPU0 interrupt control registers */
-#define PHYS_JJ_INTR_G 0x71E10000      /* Master interrupt control registers */
+//#define DEBUG_IRQ_COUNT
 
 /* These registers are used for sending/receiving irqs from/to
  * different cpu's.
@@ -63,18 +59,6 @@ struct sun4m_intreg_master {
        /* This register is both READ and WRITE. */
        unsigned int undirected_target;  /* Which cpu gets undirected irqs. */
 };
-/*
- * Registers of hardware timer in sun4m.
- */
-struct sun4m_timer_percpu {
-       volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
-       volatile unsigned int l14_cur_count;
-};
-
-struct sun4m_timer_global {
-        volatile unsigned int l10_timer_limit;
-        volatile unsigned int l10_cur_count;
-};
 
 #define SUN4M_INT_ENABLE        0x80000000
 #define SUN4M_INT_E14           0x00000080
@@ -101,29 +85,25 @@ struct sun4m_timer_global {
 #define SUN4M_INT_VME(x)        (1 << (x))
 
 typedef struct SCHEDState {
+    uint32_t addr, addrg;
     uint32_t intreg_pending;
     uint32_t intreg_enabled;
     uint32_t intregm_pending;
     uint32_t intregm_enabled;
-    uint32_t timer_regs[2];
-    uint32_t timerm_regs[2];
 } SCHEDState;
 
 static SCHEDState *ps;
 
-static int intreg_io_memory, intregm_io_memory,
-    timer_io_memory, timerm_io_memory;
-
-static void sched_reset(SCHEDState *s)
-{
-}
+#ifdef DEBUG_IRQ_COUNT
+static uint64_t irq_count[32];
+#endif
 
 static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
 {
     SCHEDState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_INTR0) >> 2;
+    saddr = (addr - s->addr) >> 2;
     switch (saddr) {
     case 0:
        return s->intreg_pending;
@@ -139,7 +119,7 @@ static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
     SCHEDState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_INTR0) >> 2;
+    saddr = (addr - s->addr) >> 2;
     switch (saddr) {
     case 0:
        s->intreg_pending = val;
@@ -172,7 +152,7 @@ static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
     SCHEDState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_INTR_G) >> 2;
+    saddr = (addr - s->addrg) >> 2;
     switch (saddr) {
     case 0:
        return s->intregm_pending;
@@ -191,7 +171,7 @@ static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t v
     SCHEDState *s = opaque;
     uint32_t saddr;
 
-    saddr = (addr - PHYS_JJ_INTR_G) >> 2;
+    saddr = (addr - s->addrg) >> 2;
     switch (saddr) {
     case 0:
        s->intregm_pending = val;
@@ -222,87 +202,29 @@ static CPUWriteMemoryFunc *intregm_mem_write[3] = {
     intregm_mem_writel,
 };
 
-static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
+void pic_info(void)
 {
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - PHYS_JJ_CLOCK) >> 2;
-    switch (saddr) {
-    default:
-       return s->timer_regs[saddr];
-       break;
-    }
-    return 0;
+    term_printf("per-cpu: pending 0x%08x, enabled 0x%08x\n", ps->intreg_pending, ps->intreg_enabled);
+    term_printf("master: pending 0x%08x, enabled 0x%08x\n", ps->intregm_pending, ps->intregm_enabled);
 }
 
-static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+void irq_info(void)
 {
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - PHYS_JJ_CLOCK) >> 2;
-    switch (saddr) {
-    default:
-       s->timer_regs[saddr] = val;
-       break;
+#ifndef DEBUG_IRQ_COUNT
+    term_printf("irq statistic code not compiled.\n");
+#else
+    int i;
+    int64_t count;
+
+    term_printf("IRQ statistics:\n");
+    for (i = 0; i < 32; i++) {
+        count = irq_count[i];
+        if (count > 0)
+            term_printf("%2d: %lld\n", i, count);
     }
+#endif
 }
 
-static CPUReadMemoryFunc *timer_mem_read[3] = {
-    timer_mem_readl,
-    timer_mem_readl,
-    timer_mem_readl,
-};
-
-static CPUWriteMemoryFunc *timer_mem_write[3] = {
-    timer_mem_writel,
-    timer_mem_writel,
-    timer_mem_writel,
-};
-
-static uint32_t timerm_mem_readl(void *opaque, target_phys_addr_t addr)
-{
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
-    switch (saddr) {
-    default:
-       return s->timerm_regs[saddr];
-       break;
-    }
-    return 0;
-}
-
-static void timerm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-    SCHEDState *s = opaque;
-    uint32_t saddr;
-
-    saddr = (addr - PHYS_JJ_CLOCK1) >> 2;
-    switch (saddr) {
-    default:
-       s->timerm_regs[saddr] = val;
-       break;
-    }
-}
-
-static CPUReadMemoryFunc *timerm_mem_read[3] = {
-    timerm_mem_readl,
-    timerm_mem_readl,
-    timerm_mem_readl,
-};
-
-static CPUWriteMemoryFunc *timerm_mem_write[3] = {
-    timerm_mem_writel,
-    timerm_mem_writel,
-    timerm_mem_writel,
-};
-
-void pic_info() {}
-void irq_info() {}
-
 static const unsigned int intr_to_mask[16] = {
        0,      0,      0,      0,      0,      0, SUN4M_INT_ETHERNET,  0,
        0,      0,      0,      0,      0,      0,      0,      0,
@@ -318,29 +240,29 @@ void pic_set_irq(int irq, int level)
            cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
        }
     }
+#ifdef DEBUG_IRQ_COUNT
+    if (level == 1)
+       irq_count[irq]++;
+#endif
 }
 
-void sched_init()
+void sched_init(uint32_t addr, uint32_t addrg)
 {
+    int intreg_io_memory, intregm_io_memory;
     SCHEDState *s;
 
     s = qemu_mallocz(sizeof(SCHEDState));
     if (!s)
         return;
+    s->addr = addr;
+    s->addrg = addrg;
 
     intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s);
-    cpu_register_physical_memory(PHYS_JJ_INTR0, 3, intreg_io_memory);
+    cpu_register_physical_memory(addr, 3, intreg_io_memory);
 
     intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
-    cpu_register_physical_memory(PHYS_JJ_INTR_G, 5, intregm_io_memory);
-
-    timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
-    cpu_register_physical_memory(PHYS_JJ_CLOCK, 2, timer_io_memory);
-
-    timerm_io_memory = cpu_register_io_memory(0, timerm_mem_read, timerm_mem_write, s);
-    cpu_register_physical_memory(PHYS_JJ_CLOCK1, 2, timerm_io_memory);
+    cpu_register_physical_memory(addrg, 5, intregm_io_memory);
 
-    sched_reset(s);
     ps = s;
 }
 
index 05dbd56..80305e0 100644 (file)
 #define MMU_CONTEXT_TBL      0x00003000
 #define MMU_L1PTP            (MMU_CONTEXT_TBL + 0x0400)
 #define MMU_L2PTP            (MMU_CONTEXT_TBL + 0x0800)
-#define ROMVEC_DATA          (MMU_CONTEXT_TBL + 0x1800)
 #define PROM_ADDR           0xffd04000
-#define PROM_FILENAME       "proll.bin"
+#define PROM_FILENAMEB      "proll.bin"
+#define PROM_FILENAMEE      "proll.elf"
+#define PROLL_MAGIC_ADDR 0x20000000
 #define PHYS_JJ_EEPROM 0x71200000      /* [2000] MK48T08 */
 #define PHYS_JJ_IDPROM_OFF     0x1FD8
 #define PHYS_JJ_EEPROM_SIZE    0x2000
+#define PHYS_JJ_IOMMU  0x10000000      /* First page of sun4m IOMMU */
+#define PHYS_JJ_TCX_FB 0x50800000      /* Start address, frame buffer body */
+#define PHYS_JJ_TCX_0E 0x5E000000      /* Top address, one byte used. */
+#define PHYS_JJ_IOMMU  0x10000000      /* First page of sun4m IOMMU */
+#define PHYS_JJ_LEDMA   0x78400010      /* ledma, off by 10 from unused SCSI */
+#define PHYS_JJ_LE      0x78C00000      /* LANCE, typical sun4m */
+#define PHYS_JJ_LE_IRQ  6
+#define PHYS_JJ_CLOCK  0x71D00000
+#define PHYS_JJ_CLOCK_IRQ  10
+#define PHYS_JJ_CLOCK1 0x71D10000
+#define PHYS_JJ_CLOCK1_IRQ  14
+#define PHYS_JJ_INTR0  0x71E00000      /* CPU0 interrupt control registers */
+#define PHYS_JJ_INTR_G 0x71E10000      /* Master interrupt control registers */
 
 /* TSC handling */
 
@@ -44,8 +58,6 @@ uint64_t cpu_get_tsc()
 
 void DMA_run() {}
 void SB16_run() {}
-void vga_invalidate_display() {}
-void vga_screen_dump(const char *filename) {}
 int serial_can_receive(SerialState *s) { return 0; }
 void serial_receive_byte(SerialState *s, int ch) {}
 void serial_receive_break(SerialState *s) {}
@@ -59,7 +71,7 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
              const char *initrd_filename)
 {
     char buf[1024];
-    int ret, linux_boot, bios_size;
+    int ret, linux_boot;
     unsigned long bios_offset;
 
     linux_boot = (kernel_filename != NULL);
@@ -68,32 +80,21 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
     cpu_register_physical_memory(0, ram_size, 0);
     bios_offset = ram_size;
 
-    iommu_init();
-    sched_init();
-    tcx_init(ds);
-    lance_init(&nd_table[0], 6);
-    nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
-
-    magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
-
-#if 0
-    snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
-    bios_size = get_image_size(buf);
-    ret = load_image(buf, phys_ram_base + bios_offset);
-    if (ret != bios_size) {
-        fprintf(stderr, "qemu: could not load prom '%s'\n", buf);
-        exit(1);
-    }
-    cpu_register_physical_memory(PROM_ADDR, 
-                                 bios_size, bios_offset | IO_MEM_ROM);
-#endif
+    iommu_init(PHYS_JJ_IOMMU);
+    sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
+    tcx_init(ds, PHYS_JJ_TCX_FB);
+    lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
+    nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE, &nd_table[0].macaddr);
+    timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ);
+    timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
+    magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR, PROLL_MAGIC_ADDR);
 
     /* We load Proll as the kernel and start it. It will issue a magic
        IO to load the real kernel */
     if (linux_boot) {
-       snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAME);
+       snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
         ret = load_kernel(buf, 
-                          phys_ram_base + KERNEL_LOAD_ADDR);
+                      phys_ram_base + KERNEL_LOAD_ADDR);
         if (ret < 0) {
             fprintf(stderr, "qemu: could not load kernel '%s'\n", 
                     buf);
@@ -103,28 +104,10 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
     /* Setup a MMU entry for entire address space */
     stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
     stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
-#if 0
-    stl_raw(phys_ram_base + MMU_L1PTP + (0x50 << 2), (MMU_L2PTP >> 4) | 1); // frame buffer at 50..
-#endif
+    stl_raw(phys_ram_base + MMU_L1PTP + (0x01 << 2), (MMU_L2PTP >> 4) | 1); // 01.. == 00..
     stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
+    stl_raw(phys_ram_base + MMU_L1PTP + (0xf0 << 2), (MMU_L2PTP >> 4) | 1); // f0.. == 00..
     /* 3 = U:RWX S:RWX */
     stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
-#if 0
-    stl_raw(phys_ram_base + MMU_L2PTP + 0x84, (PHYS_JJ_TCX_FB >> 4) \
-           | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
-    stl_raw(phys_ram_base + MMU_L2PTP + 0x88, (PHYS_JJ_TCX_FB >> 4) \
-           | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
-    stl_raw(phys_ram_base + MMU_L2PTP + 0x140, (PHYS_JJ_TCX_FB >> 4) \
-           | (3 << PTE_ACCESS_SHIFT) | 2); // frame buf
-    // "Empirical constant"
-    stl_raw(phys_ram_base + ROMVEC_DATA, 0x10010407);
-
-    // Version: V3 prom
-    stl_raw(phys_ram_base + ROMVEC_DATA + 4, 3);
-
-    stl_raw(phys_ram_base + ROMVEC_DATA + 0x1c, ROMVEC_DATA+0x400);
-    stl_raw(phys_ram_base + ROMVEC_DATA + 0x400, ROMVEC_DATA+0x404);
-    stl_raw(phys_ram_base + ROMVEC_DATA + 0x404, 0x81c3e008); // retl
-    stl_raw(phys_ram_base + ROMVEC_DATA + 0x408, 0x01000000); // nop
-#endif
+    stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2);
 }
index d9b91c6..7f97994 100644 (file)
--- a/hw/tcx.c
+++ b/hw/tcx.c
@@ -23,9 +23,6 @@
  */
 #include "vl.h"
 
-#define PHYS_JJ_TCX_FB 0x50800000      /* Start address, frame buffer body */
-#define PHYS_JJ_TCX_0E 0x5E000000      /* Top address, one byte used. */
-
 #define MAXX 1024
 #define MAXY 768
 #define XSZ (8*80)
 #define XOFF (MAXX-XSZ)
 #define YOFF (MAXY-YSZ)
 
-#define DEBUG_VGA_MEM
-
 typedef struct TCXState {
-    uint8_t *vram_ptr;
-    unsigned long vram_offset;
-    unsigned int vram_size;
+    uint32_t addr;
     DisplayState *ds;
+    uint8_t *vram;
 } TCXState;
 
 static TCXState *ts;
 
-static int tcx_io_memory;
-
 void vga_update_display()
 {
     dpy_update(ts->ds, 0, 0, XSZ, YSZ);
 }
 
+void vga_invalidate_display() {}
+
 static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
 {
     TCXState *s = opaque;
     uint32_t saddr;
     unsigned int x, y;
-    char *sptr;
 
-    saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
+    saddr = addr - s->addr - YOFF*MAXX - XOFF;
     y = saddr / MAXX;
     x = saddr - y * MAXX;
-    if (x < MAXX && y < MAXY) {
-       sptr =  s->ds->data;
-       if (sptr)
-           return sptr[y * s->ds->linesize + x*4];
+    if (x < XSZ && y < YSZ) {
+       return s->vram[y * XSZ + x];
     }
     return 0;
 }
@@ -99,7 +90,6 @@ static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
     return v;
 }
 
-/* called for accesses between 0xa0000 and 0xc0000 */
 static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 {
     TCXState *s = opaque;
@@ -107,17 +97,24 @@ static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
     unsigned int x, y;
     char *sptr;
 
-    saddr = addr - PHYS_JJ_TCX_FB - YOFF*MAXX - XOFF;
+    saddr = addr - s->addr - YOFF*MAXX - XOFF;
     y = saddr / MAXX;
     x = saddr - y * MAXX;
-    if (x < MAXX && y < MAXY) {
+    if (x < XSZ && y < YSZ) {
        sptr =  s->ds->data;
        if (sptr) {
-           sptr[y * s->ds->linesize + x*4] = val;
-           sptr[y * s->ds->linesize + x*4+1] = val;
-           sptr[y * s->ds->linesize + x*4+2] = val;
-           cpu_physical_memory_set_dirty(addr);
+           if (s->ds->depth == 24 || s->ds->depth == 32) {
+               /* XXX need to do CLUT translation */
+               sptr[y * s->ds->linesize + x*4] = val & 0xff;
+               sptr[y * s->ds->linesize + x*4+1] = val & 0xff;
+               sptr[y * s->ds->linesize + x*4+2] = val & 0xff;
+           }
+           else if (s->ds->depth == 8) {
+               sptr[y * s->ds->linesize + x] = val & 0xff;
+           }
        }
+       cpu_physical_memory_set_dirty(addr);
+       s->vram[y * XSZ + x] = val & 0xff;
     }
 }
 
@@ -159,18 +156,52 @@ static CPUWriteMemoryFunc *tcx_mem_write[3] = {
     tcx_mem_writel,
 };
 
-void tcx_init(DisplayState *ds)
+void tcx_init(DisplayState *ds, uint32_t addr)
 {
     TCXState *s;
+    int tcx_io_memory;
 
     s = qemu_mallocz(sizeof(TCXState));
     if (!s)
         return;
     s->ds = ds;
+    s->addr = addr;
     ts = s;
     tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
-    cpu_register_physical_memory(PHYS_JJ_TCX_FB, 0x100000, 
+    cpu_register_physical_memory(addr, 0x100000, 
                                  tcx_io_memory);
+    s->vram = qemu_mallocz(XSZ*YSZ);
     dpy_resize(s->ds, XSZ, YSZ);
 }
 
+void vga_screen_dump(const char *filename)
+{
+    TCXState *s = ts;
+    FILE *f;
+    uint8_t *d, *d1;
+    unsigned int v;
+    int y, x;
+
+    f = fopen(filename, "wb");
+    if (!f)
+        return -1;
+    fprintf(f, "P6\n%d %d\n%d\n",
+            XSZ, YSZ, 255);
+    d1 = s->vram;
+    for(y = 0; y < YSZ; y++) {
+        d = d1;
+        for(x = 0; x < XSZ; x++) {
+            v = *d;
+            fputc((v) & 0xff, f);
+            fputc((v) & 0xff, f);
+            fputc((v) & 0xff, f);
+            d++;
+        }
+        d1 += XSZ;
+    }
+    fclose(f);
+    return;
+}
+
+
+
index 15b54d3..c39f3b2 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -952,11 +952,7 @@ static int monitor_get_tbl (struct MonitorDef *md, int val)
 #if defined(TARGET_SPARC)
 static int monitor_get_psr (struct MonitorDef *md, int val)
 {
-    return (0<<28) | (4<<24) | cpu_single_env->psr     \
-       | (cpu_single_env->psrs? PSR_S : 0)             \
-       | (cpu_single_env->psrs? PSR_PS : 0)            \
-       | (cpu_single_env->psret? PSR_ET : 0)           \
-       | cpu_single_env->cwp;
+    return GET_PSR(cpu_single_env);
 }
 
 static int monitor_get_reg(struct MonitorDef *md, int val)
index 31f91f3..a10a9f0 100644 (file)
@@ -6,3 +6,8 @@
 
 - The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is
   available at http://site.voila.fr/jmayer/OpenHackWare/index.htm.
+
+- Proll is a GPL'd boot PROM for Sparc JavaStations
+  (http://people.redhat.com/zaitcev/linux/).
+  Applying proll.patch allows circumventing some bugs and enables
+  faster kernel load through a hack.
diff --git a/pc-bios/proll.bin b/pc-bios/proll.bin
new file mode 100644 (file)
index 0000000..0489cc2
Binary files /dev/null and b/pc-bios/proll.bin differ
diff --git a/pc-bios/proll.patch b/pc-bios/proll.patch
new file mode 100644 (file)
index 0000000..b0860e2
--- /dev/null
@@ -0,0 +1,50 @@
+diff -ru proll_18.orig/mrcoffee/main.c proll_18/mrcoffee/main.c
+--- proll_18.orig/mrcoffee/main.c      2002-09-13 16:16:59.000000000 +0200
++++ proll_18/mrcoffee/main.c   2004-09-26 11:52:23.000000000 +0200
+@@ -101,6 +101,7 @@
+       le_probe();
+       init_net();
++#ifdef ORIG
+ #if 0 /* RARP */
+       if (rarp() != 0) fatal();
+       /* printrarp(); */
+@@ -117,13 +118,20 @@
+       xtoa(myipaddr, fname, 8);
+       if (load(boot_rec.bp_siaddr, fname) != 0) fatal();
+ #endif
++#endif
+       romvec = init_openprom(bb.nbanks, bb.bankv, hiphybas);
+       printk("Memory used: virt 0x%x:0x%x[%dK] iomap 0x%x:0x%x\n",
+           PROLBASE, (int)cmem.curp, ((unsigned) cmem.curp - PROLBASE)/1024,
+           (int)cio.start, (int)cio.curp);
++#ifdef ORIG
+       set_timeout(5);  while (!chk_timeout()) { }  /* P3: let me read */
++#else
++      printk("loading kernel:");
++      i = ld_bypass(0x20000000);
++      printk(" done, size %d\n", i);
++#endif
+       {
+               void (*entry)(void *, int) = (void (*)(void*, int)) LOADBASE;
+diff -ru proll_18.orig/mrcoffee/openprom.c proll_18/mrcoffee/openprom.c
+--- proll_18.orig/mrcoffee/openprom.c  2002-09-13 16:17:03.000000000 +0200
++++ proll_18/mrcoffee/openprom.c       2004-09-21 21:27:16.000000000 +0200
+@@ -144,10 +144,14 @@
+ };
+ static int cpu_nctx = NCTX_SWIFT;
++static int cpu_cache_line_size = 0x20;
++static int cpu_cache_nlines = 0x200;
+ static struct property propv_cpu[] = {
+       {"name",        "STP1012PGA", sizeof("STP1012PGA") },
+       {"device_type", "cpu", 4 },
+       {"mmu-nctx",    (char*)&cpu_nctx, sizeof(int)},
++      {"cache-line-size",     (char*)&cpu_cache_line_size, sizeof(int)},
++      {"cache-nlines",        (char*)&cpu_cache_nlines, sizeof(int)},
+       {NULL, NULL, -1}
+ };
index 4c23b92..03698df 100644 (file)
@@ -76,6 +76,7 @@
 #define PTE_ENTRYTYPE_MASK 3
 #define PTE_ACCESS_MASK    0x1c
 #define PTE_ACCESS_SHIFT   2
+#define PTE_PPN_SHIFT      7
 #define PTE_ADDR_MASK      0xffffff00
 
 #define PG_ACCESSED_BIT        5
index f9fcf53..cea9616 100644 (file)
@@ -23,13 +23,16 @@ void helper_flush(target_ulong addr);
 void helper_ld_asi(int asi, int size, int sign);
 void helper_st_asi(int asi, int size, int sign);
 void helper_rett(void);
-void helper_stfsr(void);
+void helper_ldfsr(void);
 void set_cwp(int new_cwp);
 void do_fabss(void);
 void do_fsqrts(void);
 void do_fsqrtd(void);
 void do_fcmps(void);
 void do_fcmpd(void);
+void do_ldd_kernel(uint32_t addr);
+void do_ldd_user(uint32_t addr);
+void do_ldd_raw(uint32_t addr);
 void do_interrupt(int intno, int is_int, int error_code, 
                   unsigned int next_eip, int is_hw);
 void raise_exception_err(int exception_index, int error_code);
index ae70595..63d08e7 100644 (file)
 
 #define DEBUG_PCALL
 
-#if 0
-#define raise_exception_err(a, b)\
-do {\
-    fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
-    (raise_exception_err)(a, b);\
-} while (0)
-#endif
-
 /* Sparc MMU emulation */
 int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
                               int is_user, int is_softmmu);
 
-
 /* thread support */
 
 spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
@@ -48,15 +39,6 @@ void cpu_unlock(void)
     spin_unlock(&global_cpu_lock);
 }
 
-#if 0
-void cpu_loop_exit(void)
-{
-    /* NOTE: the register at this point must be saved by hand because
-       longjmp restore them */
-    longjmp(env->jmp_env, 1);
-}
-#endif
-
 #if !defined(CONFIG_USER_ONLY) 
 
 #define MMUSUFFIX _mmu
@@ -258,7 +240,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
     env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2;
     env->mmuregs[4] = address; /* Fault address register */
 
-    if (env->mmuregs[0] & MMU_NF) // No fault
+    if (env->mmuregs[0] & MMU_NF || env->psret == 0) // No fault
        return 0;
 
     env->exception_index = exception;
@@ -306,7 +288,7 @@ void do_interrupt(int intno, int is_int, int error_code,
        fprintf(logfile, "%6d: v=%02x e=%04x i=%d pc=%08x npc=%08x SP=%08x\n",
                     count, intno, error_code, is_int,
                     env->pc,
-                    env->npc, env->gregs[7]);
+                    env->npc, env->regwptr[6]);
 #if 0
        cpu_sparc_dump_state(env, logfile, 0);
        {
index a2d3746..042fd61 100644 (file)
@@ -474,92 +474,6 @@ void OPPROTO op_sra(void)
     T0 = ((int32_t) T0) >> T1;
 }
 
-#if 0
-void OPPROTO op_st(void)
-{
-    stl((void *) T0, T1);
-}
-
-void OPPROTO op_stb(void)
-{
-    stb((void *) T0, T1);
-}
-
-void OPPROTO op_sth(void)
-{
-    stw((void *) T0, T1);
-}
-
-void OPPROTO op_std(void)
-{
-    stl((void *) T0, T1);
-    stl((void *) (T0 + 4), T2);
-}
-
-void OPPROTO op_ld(void)
-{
-    T1 = ldl((void *) T0);
-}
-
-void OPPROTO op_ldub(void)
-{
-    T1 = ldub((void *) T0);
-}
-
-void OPPROTO op_lduh(void)
-{
-    T1 = lduw((void *) T0);
-}
-
-void OPPROTO op_ldsb(void)
-{
-    T1 = ldsb((void *) T0);
-}
-
-void OPPROTO op_ldsh(void)
-{
-    T1 = ldsw((void *) T0);
-}
-
-void OPPROTO op_ldstub(void)
-{
-    T1 = ldub((void *) T0);
-    stb((void *) T0, 0xff);    /* XXX: Should be Atomically */
-}
-
-void OPPROTO op_swap(void)
-{
-    unsigned int tmp = ldl((void *) T0);
-    stl((void *) T0, T1);      /* XXX: Should be Atomically */
-    T1 = tmp;
-}
-
-void OPPROTO op_ldd(void)
-{
-    T1 = ldl((void *) T0);
-    T0 = ldl((void *) (T0 + 4));
-}
-
-void OPPROTO op_stf(void)
-{
-    stfl((void *) T0, FT0);
-}
-
-void OPPROTO op_stdf(void)
-{
-    stfq((void *) T0, DT0);
-}
-
-void OPPROTO op_ldf(void)
-{
-    FT0 = ldfl((void *) T0);
-}
-
-void OPPROTO op_lddf(void)
-{
-    DT0 = ldfq((void *) T0);
-}
-#else
 /* Load and store */
 #define MEMSUFFIX _raw
 #include "op_mem.h"
@@ -570,19 +484,16 @@ void OPPROTO op_lddf(void)
 #define MEMSUFFIX _kernel
 #include "op_mem.h"
 #endif
-#endif
 
 void OPPROTO op_ldfsr(void)
 {
     env->fsr = *((uint32_t *) &FT0);
-    FORCE_RET();
+    helper_ldfsr();
 }
 
 void OPPROTO op_stfsr(void)
 {
     *((uint32_t *) &FT0) = env->fsr;
-    helper_stfsr();
-    FORCE_RET();
 }
 
 void OPPROTO op_wry(void)
@@ -609,16 +520,17 @@ void OPPROTO op_wrwim(void)
 void OPPROTO op_rdpsr(void)
 {
     T0 = GET_PSR(env);
-    FORCE_RET();
 }
 
 void OPPROTO op_wrpsr(void)
 {
+    int cwp;
     env->psr = T0 & ~PSR_ICC;
     env->psrs = (T0 & PSR_S)? 1 : 0;
     env->psrps = (T0 & PSR_PS)? 1 : 0;
     env->psret = (T0 & PSR_ET)? 1 : 0;
-    env->cwp = (T0 & PSR_CWP);
+    cwp = (T0 & PSR_CWP) & (NWINDOWS - 1);
+    set_cwp(cwp);
     FORCE_RET();
 }
 
index 253bcff..909639a 100644 (file)
@@ -104,6 +104,27 @@ void OPPROTO helper_st_asi(int asi, int size, int sign)
     }
 }
 
+#if 0
+void do_ldd_raw(uint32_t addr)
+{
+    T1 = ldl_raw((void *) addr);
+    T0 = ldl_raw((void *) (addr + 4));
+}
+
+#if !defined(CONFIG_USER_ONLY)
+void do_ldd_user(uint32_t addr)
+{
+    T1 = ldl_user((void *) addr);
+    T0 = ldl_user((void *) (addr + 4));
+}
+void do_ldd_kernel(uint32_t addr)
+{
+    T1 = ldl_kernel((void *) addr);
+    T0 = ldl_kernel((void *) (addr + 4));
+}
+#endif
+#endif
+
 void OPPROTO helper_rett()
 {
     int cwp;
@@ -116,7 +137,7 @@ void OPPROTO helper_rett()
     env->psrs = env->psrps;
 }
 
-void helper_stfsr(void)
+void helper_ldfsr(void)
 {
     switch (env->fsr & FSR_RD_MASK) {
     case FSR_RD_NEAREST:
index 9c839a0..2ae74f2 100644 (file)
@@ -43,8 +43,12 @@ void OPPROTO glue(op_swap, MEMSUFFIX)(void)
 
 void OPPROTO glue(op_ldd, MEMSUFFIX)(void)
 {
+#if 1
     T1 = glue(ldl, MEMSUFFIX)((void *) T0);
     T0 = glue(ldl, MEMSUFFIX)((void *) (T0 + 4));
+#else
+    glue(do_ldd, MEMSUFFIX)(T0);
+#endif
 }
 
 /***                         Floating-point store                          ***/
index 1142dea..c0ee7b2 100644 (file)
@@ -1,4 +1,4 @@
-include ../config-host.mak
+-include ../config-host.mak
 
 CFLAGS=-Wall -O2 -g
 LDFLAGS=
diff --git a/vl.h b/vl.h
index 8ebb268..f25bbaa 100644 (file)
--- a/vl.h
+++ b/vl.h
@@ -673,20 +673,23 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
              const char *initrd_filename);
 
 /* iommu.c */
-void iommu_init();
+void iommu_init(uint32_t addr);
 uint32_t iommu_translate(uint32_t addr);
 
 /* lance.c */
-void lance_init(NetDriverState *nd, int irq);
+void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
 
 /* tcx.c */
-void tcx_init(DisplayState *ds);
+void tcx_init(DisplayState *ds, uint32_t addr);
 
 /* sched.c */
 void sched_init();
 
 /* magic-load.c */
-void magic_init(const char *kfn, int kloadaddr);
+void magic_init(const char *kfn, int kloadaddr, uint32_t addr);
+
+/* timer.c */
+void timer_init(uint32_t addr, int irq);
 
 /* NVRAM helpers */
 #include "hw/m48t59.h"