diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-10-04 21:23:09 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2004-10-04 21:23:09 +0000 |
commit | 8d5f07fa3bd3433e779d13eb1cda4fbb07acb67f (patch) | |
tree | 05ba111ca75cbc1f5080dd4745659cb11cb7d5a5 /hw | |
parent | 023fcb9507b0d98d8dc98ffaa407e66d84bb6ea4 (diff) | |
download | hqemu-8d5f07fa3bd3433e779d13eb1cda4fbb07acb67f.zip hqemu-8d5f07fa3bd3433e779d13eb1cda4fbb07acb67f.tar.gz |
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.c | 83 | ||||
-rw-r--r-- | hw/lance.c | 42 | ||||
-rw-r--r-- | hw/m48t08.c | 4 | ||||
-rw-r--r-- | hw/m48t08.h | 2 | ||||
-rw-r--r-- | hw/magic-load.c | 385 | ||||
-rw-r--r-- | hw/sched.c | 150 | ||||
-rw-r--r-- | hw/sun4m.c | 77 | ||||
-rw-r--r-- | hw/tcx.c | 81 |
8 files changed, 369 insertions, 455 deletions
@@ -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; } @@ -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 c5b6e7a..46ec665 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 2a754b6..9b44bc0 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 7365183..06a5f74 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); } @@ -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; } @@ -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); } @@ -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; +} + + + |