aboutsummaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-10-04 21:23:09 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2004-10-04 21:23:09 +0000
commit8d5f07fa3bd3433e779d13eb1cda4fbb07acb67f (patch)
tree05ba111ca75cbc1f5080dd4745659cb11cb7d5a5 /hw
parent023fcb9507b0d98d8dc98ffaa407e66d84bb6ea4 (diff)
sparc merge (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1098 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r--hw/iommu.c83
-rw-r--r--hw/lance.c42
-rw-r--r--hw/m48t08.c4
-rw-r--r--hw/m48t08.h2
-rw-r--r--hw/magic-load.c385
-rw-r--r--hw/sched.c150
-rw-r--r--hw/sun4m.c77
-rw-r--r--hw/tcx.c81
8 files changed, 369 insertions, 455 deletions
diff --git a/hw/iommu.c b/hw/iommu.c
index f00bb78b0..a9249c4ba 100644
--- a/hw/iommu.c
+++ b/hw/iommu.c
@@ -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;
}
diff --git a/hw/lance.c b/hw/lance.c
index e461adead..25ad8c45b 100644
--- a/hw/lance.c
+++ b/hw/lance.c
@@ -24,11 +24,7 @@
#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);
diff --git a/hw/m48t08.c b/hw/m48t08.c
index c5b6e7a72..46ec66557 100644
--- a/hw/m48t08.c
+++ b/hw/m48t08.c
@@ -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++) {
diff --git a/hw/m48t08.h b/hw/m48t08.h
index 2a754b698..9b44bc0d1 100644
--- a/hw/m48t08.h
+++ b/hw/m48t08.h
@@ -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__) */
diff --git a/hw/magic-load.c b/hw/magic-load.c
index 7365183da..06a5f743a 100644
--- a/hw/magic-load.c
+++ b/hw/magic-load.c
@@ -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);
}
diff --git a/hw/sched.c b/hw/sched.c
index c9a685d44..2ab966de4 100644
--- a/hw/sched.c
+++ b/hw/sched.c
@@ -1,5 +1,5 @@
/*
- * QEMU interrupt controller & timer emulation
+ * QEMU interrupt controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
@@ -22,11 +22,7 @@
* 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;
}
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 05dbd56a5..80305e09c 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -28,12 +28,26 @@
#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);
}
diff --git a/hw/tcx.c b/hw/tcx.c
index d9b91c68f..7f979946f 100644
--- 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)
@@ -33,38 +30,32 @@
#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;
+}
+
+
+