SPARC merge

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1179 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard
2004-12-19 23:18:01 +00:00
parent 9772c73bbc
commit e80cfcfc88
37 changed files with 4507 additions and 1155 deletions
+2 -2
View File
@@ -50,7 +50,7 @@ install: all
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/proll.elf \
pc-bios/linux_boot.bin "$(datadir)"
mkdir -p "$(docdir)"
install -m 644 qemu-doc.html qemu-tech.html "$(docdir)"
@@ -107,7 +107,7 @@ tarbin:
$(datadir)/vgabios.bin \
$(datadir)/vgabios-cirrus.bin \
$(datadir)/ppc_rom.bin \
$(datadir)/proll.bin \
$(datadir)/proll.elf \
$(datadir)/linux_boot.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
+2 -1
View File
@@ -175,6 +175,7 @@ endif
ifeq ($(CONFIG_DARWIN),yes)
OP_CFLAGS+= -mdynamic-no-pic
LIBS+=-lmx
endif
#########################################################
@@ -300,7 +301,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 mixeng.o
endif
ifeq ($(TARGET_ARCH), sparc)
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t08.o magic-load.o slavio_intctl.o slavio_timer.o slavio_serial.o fdc.o
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
+1 -1
View File
@@ -261,7 +261,7 @@ int cpu_exec(CPUState *env1)
}
#elif defined(TARGET_SPARC)
if (interrupt_request & CPU_INTERRUPT_HARD) {
do_interrupt(0, 0, 0, 0, 0);
do_interrupt(env->interrupt_index, 0, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
//do_interrupt(0, 0, 0, 0, 0);
+16 -14
View File
@@ -9,9 +9,7 @@
#include "disas.h"
/* Filled in by elfload.c. Simplistic, but will do for now. */
unsigned int disas_num_syms;
void *disas_symtab;
const char *disas_strtab;
struct syminfo *syminfos = NULL;
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
@@ -203,19 +201,23 @@ const char *lookup_symbol(void *orig_addr)
{
unsigned int i;
/* Hack, because we know this is x86. */
Elf32_Sym *sym = disas_symtab;
Elf32_Sym *sym;
struct syminfo *s;
for (s = syminfos; s; s = s->next) {
sym = s->disas_symtab;
for (i = 0; i < s->disas_num_syms; i++) {
if (sym[i].st_shndx == SHN_UNDEF
|| sym[i].st_shndx >= SHN_LORESERVE)
continue;
for (i = 0; i < disas_num_syms; i++) {
if (sym[i].st_shndx == SHN_UNDEF
|| sym[i].st_shndx >= SHN_LORESERVE)
continue;
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
continue;
if (ELF_ST_TYPE(sym[i].st_info) != STT_FUNC)
continue;
if ((long)orig_addr >= sym[i].st_value
&& (long)orig_addr < sym[i].st_value + sym[i].st_size)
return disas_strtab + sym[i].st_name;
if ((long)orig_addr >= sym[i].st_value
&& (long)orig_addr < sym[i].st_value + sym[i].st_size)
return s->disas_strtab + sym[i].st_name;
}
}
return "";
}
+7 -3
View File
@@ -9,7 +9,11 @@ void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags);
const char *lookup_symbol(void *orig_addr);
/* Filled in by elfload.c. Simplistic, but will do for now. */
extern unsigned int disas_num_syms;
extern void *disas_symtab; /* FIXME: includes are a mess --RR */
extern const char *disas_strtab;
extern struct syminfo {
unsigned int disas_num_syms;
void *disas_symtab;
const char *disas_strtab;
struct syminfo *next;
} *syminfos;
#endif /* _QEMU_DISAS_H */
+6 -13
View File
@@ -298,11 +298,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
registers[64] = tswapl(env->y);
tmp = (0<<28) | (4<<24) | env->psr \
| (env->psrs? PSR_S : 0) \
| (env->psrs? PSR_PS : 0) \
| (env->psret? PSR_ET : 0) \
| env->cwp;
tmp = GET_PSR(env);
registers[65] = tswapl(tmp);
registers[66] = tswapl(env->wim);
registers[67] = tswapl(env->tbr);
@@ -317,7 +313,7 @@ static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *registers = (uint32_t *)mem_buf, tmp;
uint32_t *registers = (uint32_t *)mem_buf;
int i;
/* fill in g0..g7 */
@@ -334,12 +330,7 @@ static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
}
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */
env->y = tswapl(registers[64]);
tmp = tswapl(registers[65]);
env->psr = tmp & ~PSR_ICC;
env->psrs = (tmp & PSR_S)? 1 : 0;
env->psrps = (tmp & PSR_PS)? 1 : 0;
env->psret = (tmp & PSR_ET)? 1 : 0;
env->cwp = (tmp & PSR_CWP);
PUT_PSR(env, tswapl(registers[65]));
env->wim = tswapl(registers[66]);
env->tbr = tswapl(registers[67]);
env->pc = tswapl(registers[68]);
@@ -495,8 +486,10 @@ static void gdb_vm_stopped(void *opaque, int reason)
/* disable single step if it was enable */
cpu_single_step(cpu_single_env, 0);
if (reason == EXCP_DEBUG)
if (reason == EXCP_DEBUG) {
tb_flush(cpu_single_env);
ret = SIGTRAP;
}
else
ret = 0;
snprintf(buf, sizeof(buf), "S%02x", ret);
+29 -6
View File
@@ -21,6 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* The controller is used in Sun4m systems in a slightly different
* way. There are changes in DOR register and DMA is not available.
*/
#include "vl.h"
/********************************************************/
@@ -90,6 +94,16 @@ typedef struct fdrive_t {
uint8_t ro; /* Is read-only */
} fdrive_t;
#ifdef TARGET_SPARC
#define DMA_read_memory(a,b,c,d)
#define DMA_write_memory(a,b,c,d)
#define DMA_register_channel(a,b,c)
#define DMA_hold_DREQ(a)
#define DMA_release_DREQ(a)
#define DMA_get_channel_mode(a) (0)
#define DMA_schedule(a)
#endif
static void fd_init (fdrive_t *drv, BlockDriverState *bs)
{
/* Drive */
@@ -455,6 +469,18 @@ static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
}
}
static CPUReadMemoryFunc *fdctrl_mem_read[3] = {
fdctrl_read,
fdctrl_read,
fdctrl_read,
};
static CPUWriteMemoryFunc *fdctrl_mem_write[3] = {
fdctrl_write,
fdctrl_write,
fdctrl_write,
};
static void fd_change_cb (void *opaque)
{
fdrive_t *drv = opaque;
@@ -473,7 +499,7 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
BlockDriverState **fds)
{
fdctrl_t *fdctrl;
// int io_mem;
int io_mem;
int i;
FLOPPY_DPRINTF("init controller\n");
@@ -504,11 +530,8 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
fdctrl_reset(fdctrl, 0);
fdctrl->state = FD_CTRL_ACTIVE;
if (mem_mapped) {
FLOPPY_ERROR("memory mapped floppy not supported by now !\n");
#if 0
io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write);
cpu_register_physical_memory(base, 0x08, io_mem);
#endif
io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write, fdctrl);
cpu_register_physical_memory(io_base, 0x08, io_mem);
} else {
register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);
register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);
+45 -9
View File
@@ -117,8 +117,6 @@ typedef struct IOMMUState {
uint32_t iostart;
} IOMMUState;
static IOMMUState *ps;
static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
{
IOMMUState *s = opaque;
@@ -187,25 +185,61 @@ static CPUWriteMemoryFunc *iommu_mem_write[3] = {
iommu_mem_writew,
};
uint32_t iommu_translate(uint32_t addr)
uint32_t iommu_translate_local(void *opaque, uint32_t addr)
{
uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
IOMMUState *s = opaque;
uint32_t *iopte = (void *)(s->regs[1] << 4), pa;
iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
iopte += ((addr - s->iostart) >> PAGE_SHIFT);
cpu_physical_memory_read((uint32_t)iopte, (void *) &pa, 4);
bswap32s(&pa);
pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
return pa + (addr & PAGE_MASK);
}
void iommu_init(uint32_t addr)
static void iommu_save(QEMUFile *f, void *opaque)
{
IOMMUState *s = opaque;
int i;
qemu_put_be32s(f, &s->addr);
for (i = 0; i < sizeof(struct iommu_regs); i += 4)
qemu_put_be32s(f, &s->regs[i]);
qemu_put_be32s(f, &s->iostart);
}
static int iommu_load(QEMUFile *f, void *opaque, int version_id)
{
IOMMUState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->addr);
for (i = 0; i < sizeof(struct iommu_regs); i += 4)
qemu_put_be32s(f, &s->regs[i]);
qemu_get_be32s(f, &s->iostart);
return 0;
}
static void iommu_reset(void *opaque)
{
IOMMUState *s = opaque;
memset(s->regs, 0, sizeof(struct iommu_regs));
s->iostart = 0;
}
void *iommu_init(uint32_t addr)
{
IOMMUState *s;
int iommu_io_memory;
s = qemu_mallocz(sizeof(IOMMUState));
if (!s)
return;
return NULL;
s->addr = addr;
@@ -213,6 +247,8 @@ void iommu_init(uint32_t addr)
cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
iommu_io_memory);
ps = s;
register_savevm("iommu", addr, 1, iommu_save, iommu_load, s);
qemu_register_reset(iommu_reset, s);
return s;
}
+74 -53
View File
@@ -147,6 +147,7 @@ struct lance_init_block {
};
#define LEDMA_REGS 4
#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1)
#if 0
/* Structure to describe the current status of DMA registers on the Sparc */
struct sparc_dma_registers {
@@ -157,32 +158,28 @@ 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;
uint16_t regs[LE_MAXREG];
uint8_t phys[6]; /* mac address */
int irq;
LEDMAState *ledma;
unsigned int rxptr, txptr;
uint32_t ledmaregs[LEDMA_REGS];
} LANCEState;
static unsigned int rxptr, txptr;
static void lance_send(void *opaque);
static void lance_reset(LANCEState *s)
static void lance_reset(void *opaque)
{
LANCEState *s = opaque;
memcpy(s->phys, s->nd->macaddr, 6);
rxptr = 0;
txptr = 0;
s->rxptr = 0;
s->txptr = 0;
memset(s->regs, 0, LE_MAXREG * 2);
s->regs[LE_CSR0] = LE_C0_STOP;
memset(s->ledmaregs, 0, LEDMA_REGS * 4);
}
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
@@ -190,7 +187,7 @@ static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
LANCEState *s = opaque;
uint32_t saddr;
saddr = addr - s->paddr;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
return s->regs[s->addr];
@@ -208,7 +205,7 @@ static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val
uint32_t saddr;
uint16_t reg;
saddr = addr - s->paddr;
saddr = addr & LE_MAXREG;
switch (saddr >> 1) {
case LE_RDP:
switch(s->addr) {
@@ -292,7 +289,7 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
static int lance_can_receive(void *opaque)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
int i;
uint16_t temp;
@@ -303,7 +300,7 @@ static int lance_can_receive(void *opaque)
ib = (void *) iommu_translate(dmaptr);
for (i = 0; i < RX_RING_SIZE; i++) {
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
temp &= 0xff;
if (temp == (LE_R1_OWN)) {
#ifdef DEBUG_LANCE
@@ -323,7 +320,7 @@ static int lance_can_receive(void *opaque)
static void lance_receive(void *opaque, const uint8_t *buf, int size)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_rxptr, j;
uint16_t temp;
@@ -333,23 +330,23 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
ib = (void *) iommu_translate(dmaptr);
old_rxptr = rxptr;
for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
old_rxptr = s->rxptr;
for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
if (temp == (LE_R1_OWN)) {
rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK;
temp = size;
bswap16s(&temp);
cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2);
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp, 2);
#if 0
cpu_physical_memory_write(&ib->rx_buf[i], buf, size);
cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size);
#else
for (j = 0; j < size; j++) {
cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
cpu_physical_memory_write(((uint32_t)&ib->rx_buf[i]) + j, &buf[j], 1);
}
#endif
temp = LE_R1_POK;
cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
pic_set_irq(s->irq, 1);
@@ -364,7 +361,7 @@ static void lance_receive(void *opaque, const uint8_t *buf, int size)
static void lance_send(void *opaque)
{
LANCEState *s = opaque;
void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
uint32_t dmaptr = s->leptr + s->ledmaregs[3];
struct lance_init_block *ib;
unsigned int i, old_txptr, j;
uint16_t temp;
@@ -375,18 +372,18 @@ static void lance_send(void *opaque)
ib = (void *) iommu_translate(dmaptr);
old_txptr = txptr;
for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
old_txptr = s->txptr;
for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
if (temp == (LE_T1_POK|LE_T1_OWN)) {
cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2);
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp, 2);
bswap16s(&temp);
temp = (~temp) + 1;
#if 0
cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp);
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp);
#else
for (j = 0; j < temp; j++) {
cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i] + j, &pkt_buf[j], 1);
}
#endif
@@ -395,8 +392,8 @@ static void lance_send(void *opaque)
#endif
qemu_send_packet(s->nd, pkt_buf, temp);
temp = LE_T1_POK;
cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
txptr = (txptr + 1) & TX_RING_MOD_MASK;
cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK;
s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
}
}
@@ -404,24 +401,20 @@ static void lance_send(void *opaque)
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
{
LEDMAState *s = opaque;
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
if (saddr < LEDMA_REGS)
return s->regs[saddr];
else
return 0;
saddr = (addr & LEDMA_MAXADDR) >> 2;
return s->ledmaregs[saddr];
}
static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
LEDMAState *s = opaque;
LANCEState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
if (saddr < LEDMA_REGS)
s->regs[saddr] = val;
saddr = (addr & LEDMA_MAXADDR) >> 2;
s->ledmaregs[saddr] = val;
}
static CPUReadMemoryFunc *ledma_mem_read[3] = {
@@ -436,33 +429,61 @@ static CPUWriteMemoryFunc *ledma_mem_write[3] = {
ledma_mem_writel,
};
static void lance_save(QEMUFile *f, void *opaque)
{
LANCEState *s = opaque;
int i;
qemu_put_be32s(f, &s->leptr);
qemu_put_be16s(f, &s->addr);
for (i = 0; i < LE_MAXREG; i ++)
qemu_put_be16s(f, &s->regs[i]);
qemu_put_buffer(f, s->phys, 6);
qemu_put_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_put_be32s(f, &s->ledmaregs[i]);
}
static int lance_load(QEMUFile *f, void *opaque, int version_id)
{
LANCEState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->leptr);
qemu_get_be16s(f, &s->addr);
for (i = 0; i < LE_MAXREG; i ++)
qemu_get_be16s(f, &s->regs[i]);
qemu_get_buffer(f, s->phys, 6);
qemu_get_be32s(f, &s->irq);
for (i = 0; i < LEDMA_REGS; i ++)
qemu_get_be32s(f, &s->ledmaregs[i]);
return 0;
}
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(leaddr, 8, lance_io_memory);
led = qemu_mallocz(sizeof(LEDMAState));
if (!led)
return;
s->ledma = led;
led->addr = ledaddr;
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s);
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
lance_reset(s);
qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
register_savevm("lance", leaddr, 1, lance_save, lance_load, s);
qemu_register_reset(lance_reset, s);
}
+63 -98
View File
@@ -32,19 +32,14 @@
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
#define NVRAM_MAX_MEM 0xfff0
#define NVRAM_MAX_MEM 0x1ff0
#define NVRAM_MAXADDR 0x1fff
struct m48t08_t {
/* Hardware parameters */
int mem_index;
uint32_t mem_base;
uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* NVRAM storage */
uint8_t lock;
uint16_t addr;
uint8_t *buffer;
};
@@ -83,14 +78,13 @@ static void set_time (m48t08_t *NVRAM, struct tm *tm)
}
/* Direct access to NVRAM */
void m48t08_write (m48t08_t *NVRAM, uint32_t val)
void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val)
{
struct tm tm;
int tmp;
if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
switch (NVRAM->addr) {
addr &= NVRAM_MAXADDR;
switch (addr) {
case 0x1FF8:
/* control */
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
@@ -167,25 +161,18 @@ void m48t08_write (m48t08_t *NVRAM, uint32_t val)
}
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < NVRAM_MAX_MEM ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
NVRAM->buffer[NVRAM->addr] = val & 0xFF;
}
NVRAM->buffer[addr] = val & 0xFF;
break;
}
}
uint32_t m48t08_read (m48t08_t *NVRAM)
uint8_t m48t08_read (m48t08_t *NVRAM, uint32_t addr)
{
struct tm tm;
uint32_t retval = 0xFF;
uint8_t retval = 0xFF;
switch (NVRAM->addr) {
addr &= NVRAM_MAXADDR;
switch (addr) {
case 0x1FF8:
/* control */
goto do_read;
@@ -225,65 +212,36 @@ uint32_t m48t08_read (m48t08_t *NVRAM)
retval = toBCD(tm.tm_year);
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < NVRAM_MAX_MEM ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
do_read:
retval = NVRAM->buffer[NVRAM->addr];
}
do_read:
retval = NVRAM->buffer[addr];
break;
}
if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
return retval;
}
void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr)
{
NVRAM->addr = addr;
}
void m48t08_toggle_lock (m48t08_t *NVRAM, int lock)
{
NVRAM->lock ^= 1 << lock;
}
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM)
NVRAM->buffer[addr] = value;
m48t08_write(NVRAM, addr, value);
}
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
NVRAM->buffer[addr] = value >> 8;
NVRAM->buffer[addr + 1] = value;
}
m48t08_write(NVRAM, addr, value);
m48t08_write(NVRAM, addr + 1, value >> 8);
}
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t08_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
NVRAM->buffer[addr] = value >> 24;
NVRAM->buffer[addr + 1] = value >> 16;
NVRAM->buffer[addr + 2] = value >> 8;
NVRAM->buffer[addr + 3] = value;
}
m48t08_write(NVRAM, addr, value);
m48t08_write(NVRAM, addr + 1, value >> 8);
m48t08_write(NVRAM, addr + 2, value >> 16);
m48t08_write(NVRAM, addr + 3, value >> 24);
}
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
@@ -291,10 +249,7 @@ static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM)
retval = NVRAM->buffer[addr];
retval = m48t08_read(NVRAM, addr);
return retval;
}
@@ -303,12 +258,8 @@ static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
retval = NVRAM->buffer[addr] << 8;
retval |= NVRAM->buffer[addr + 1];
}
retval = m48t08_read(NVRAM, addr) << 8;
retval |= m48t08_read(NVRAM, addr + 1);
return retval;
}
@@ -317,14 +268,10 @@ static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
m48t08_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < NVRAM_MAX_MEM) {
retval = NVRAM->buffer[addr] << 24;
retval |= NVRAM->buffer[addr + 1] << 16;
retval |= NVRAM->buffer[addr + 2] << 8;
retval |= NVRAM->buffer[addr + 3];
}
retval = m48t08_read(NVRAM, addr) << 24;
retval |= m48t08_read(NVRAM, addr + 1) << 16;
retval |= m48t08_read(NVRAM, addr + 2) << 8;
retval |= m48t08_read(NVRAM, addr + 3);
return retval;
}
@@ -340,12 +287,42 @@ static CPUReadMemoryFunc *nvram_read[] = {
&nvram_readl,
};
static void nvram_save(QEMUFile *f, void *opaque)
{
m48t08_t *s = opaque;
qemu_put_be32s(f, (uint32_t *)&s->time_offset);
qemu_put_be32s(f, (uint32_t *)&s->stop_time);
qemu_put_buffer(f, s->buffer, 0x2000);
}
static int nvram_load(QEMUFile *f, void *opaque, int version_id)
{
m48t08_t *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, (uint32_t *)&s->time_offset);
qemu_get_be32s(f, (uint32_t *)&s->stop_time);
qemu_get_buffer(f, s->buffer, 0x2000);
return 0;
}
static void m48t08_reset(void *opaque)
{
m48t08_t *s = opaque;
s->time_offset = 0;
s->stop_time = 0;
}
/* Initialisation routine */
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size)
{
m48t08_t *s;
int i;
unsigned char tmp = 0;
int mem_index;
s = qemu_mallocz(sizeof(m48t08_t));
if (!s)
@@ -355,25 +332,13 @@ m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
qemu_free(s);
return NULL;
}
s->size = size;
s->mem_base = mem_base;
s->addr = 0;
if (mem_base != 0) {
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
cpu_register_physical_memory(mem_base, 0x2000, mem_index);
}
s->lock = 0;
i = 0x1fd8;
s->buffer[i++] = 0x01;
s->buffer[i++] = 0x80; /* Sun4m OBP */
memcpy(&s->buffer[i], macaddr, 6);
/* Calculate checksum */
for (i = 0x1fd8; i < 0x1fe7; i++) {
tmp ^= s->buffer[i];
}
s->buffer[0x1fe7] = tmp;
register_savevm("nvram", mem_base, 1, nvram_save, nvram_load, s);
qemu_register_reset(m48t08_reset, s);
return s;
}
+3 -5
View File
@@ -3,10 +3,8 @@
typedef struct m48t08_t m48t08_t;
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, uint8_t *macaddr);
void m48t08_write (m48t08_t *NVRAM, uint32_t addr, uint8_t val);
uint8_t m48t08_read (m48t08_t *NVRAM, uint32_t addr);
m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size);
#endif /* !defined (__M48T08_H__) */
+98 -81
View File
@@ -1,5 +1,54 @@
#include "vl.h"
#include "disas.h"
#include "exec-all.h"
struct exec
{
uint32_t a_info; /* Use macros N_MAGIC, etc for access */
uint32_t a_text; /* length of text, in bytes */
uint32_t a_data; /* length of data, in bytes */
uint32_t a_bss; /* length of uninitialized data area, in bytes */
uint32_t a_syms; /* length of symbol table data in file, in bytes */
uint32_t a_entry; /* start address */
uint32_t a_trsize; /* length of relocation info for text, in bytes */
uint32_t a_drsize; /* length of relocation info for data, in bytes */
};
#ifdef BSWAP_NEEDED
static void bswap_ahdr(struct exec *e)
{
bswap32s(&e->a_info);
bswap32s(&e->a_text);
bswap32s(&e->a_data);
bswap32s(&e->a_bss);
bswap32s(&e->a_syms);
bswap32s(&e->a_entry);
bswap32s(&e->a_trsize);
bswap32s(&e->a_drsize);
}
#else
#define bswap_ahdr(x) do { } while (0)
#endif
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
#define OMAGIC 0407
#define NMAGIC 0410
#define ZMAGIC 0413
#define QMAGIC 0314
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
#define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
(N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
#define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
#define N_DATADDR(x) \
(N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB
@@ -103,27 +152,27 @@ static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint3
return NULL;
}
static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
static void *find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
{
int retval;
retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
if (retval < 0)
return -1;
return NULL;
retval = read(fd, shdr, sizeof(*shdr));
if (retval < 0)
return -1;
return NULL;
bswap_shdr(shdr);
if (shdr->sh_type == SHT_STRTAB)
return qemu_malloc(shdr->sh_size);;
return 0;
return NULL;
}
static int read_program(int fd, struct elf_phdr *phdr, void *dst)
static int read_program(int fd, struct elf_phdr *phdr, void *dst, uint32_t entry)
{
int retval;
retval = lseek(fd, 0x4000, SEEK_SET);
retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
if (retval < 0)
return -1;
return read(fd, dst, phdr->p_filesz);
@@ -178,6 +227,7 @@ static void load_symbols(struct elfhdr *ehdr, int fd)
{
struct elf_shdr symtab, strtab;
struct elf_sym *syms;
struct syminfo *s;
int nsyms, i;
char *str;
@@ -196,20 +246,19 @@ static void load_symbols(struct elfhdr *ehdr, int fd)
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;
s = qemu_mallocz(sizeof(*s));
s->disas_symtab = syms;
s->disas_num_syms = nsyms;
s->disas_strtab = str;
s->next = syminfos;
syminfos = s;
return;
error_freesyms:
qemu_free(syms);
return;
}
int load_elf(const char * filename, uint8_t *addr)
int load_elf(const char *filename, uint8_t *addr)
{
struct elfhdr ehdr;
struct elf_phdr phdr;
@@ -227,12 +276,13 @@ int load_elf(const char * filename, uint8_t *addr)
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)
|| (ehdr.e_machine != EM_SPARC
&& ehdr.e_machine != EM_SPARC32PLUS))
goto error;
if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
goto error;
retval = read_program(fd, &phdr, addr);
retval = read_program(fd, &phdr, addr, ehdr.e_entry);
if (retval < 0)
goto error;
@@ -245,17 +295,45 @@ int load_elf(const char * filename, uint8_t *addr)
return -1;
}
int load_kernel(const char *filename, uint8_t *addr)
int load_aout(const char *filename, uint8_t *addr)
{
int fd, size;
int fd, size, ret;
struct exec e;
uint32_t magic;
fd = open(filename, O_RDONLY | O_BINARY);
if (fd < 0)
return -1;
/* load 32 bit code */
size = read(fd, addr, 16 * 1024 * 1024);
size = read(fd, &e, sizeof(e));
if (size < 0)
goto fail;
bswap_ahdr(&e);
magic = N_MAGIC(e);
switch (magic) {
case ZMAGIC:
case QMAGIC:
case OMAGIC:
lseek(fd, N_TXTOFF(e), SEEK_SET);
size = read(fd, addr, e.a_text + e.a_data);
if (size < 0)
goto fail;
break;
case NMAGIC:
lseek(fd, N_TXTOFF(e), SEEK_SET);
size = read(fd, addr, e.a_text);
if (size < 0)
goto fail;
ret = read(fd, addr + N_DATADDR(e), e.a_data);
if (ret < 0)
goto fail;
size += ret;
break;
default:
goto fail;
}
close(fd);
return size;
fail:
@@ -263,64 +341,3 @@ int load_kernel(const char *filename, uint8_t *addr)
return -1;
}
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 (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",
s->saved_kfn);
}
s->magic_state = 1; /* No more magic */
tb_flush();
return bswap32(ret);
}
return 0;
}
static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
}
static CPUReadMemoryFunc *magic_mem_read[3] = {
magic_mem_readl,
magic_mem_readl,
magic_mem_readl,
};
static CPUWriteMemoryFunc *magic_mem_write[3] = {
magic_mem_writel,
magic_mem_writel,
magic_mem_writel,
};
void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
{
int 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);
}
-268
View File
@@ -1,268 +0,0 @@
/*
* QEMU interrupt controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
//#define DEBUG_IRQ_COUNT
/* These registers are used for sending/receiving irqs from/to
* different cpu's.
*/
struct sun4m_intreg_percpu {
unsigned int tbt; /* Intrs pending for this cpu, by PIL. */
/* These next two registers are WRITE-ONLY and are only
* "on bit" sensitive, "off bits" written have NO affect.
*/
unsigned int clear; /* Clear this cpus irqs here. */
unsigned int set; /* Set this cpus irqs here. */
};
/*
* djhr
* Actually the clear and set fields in this struct are misleading..
* according to the SLAVIO manual (and the same applies for the SEC)
* the clear field clears bits in the mask which will ENABLE that IRQ
* the set field sets bits in the mask to DISABLE the IRQ.
*
* Also the undirected_xx address in the SLAVIO is defined as
* RESERVED and write only..
*
* DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
* sun4m machines, for MP the layout makes more sense.
*/
struct sun4m_intreg_master {
unsigned int tbt; /* IRQ's that are pending, see sun4m masks. */
unsigned int irqs; /* Master IRQ bits. */
/* Again, like the above, two these registers are WRITE-ONLY. */
unsigned int clear; /* Clear master IRQ's by setting bits here. */
unsigned int set; /* Set master IRQ's by setting bits here. */
/* This register is both READ and WRITE. */
unsigned int undirected_target; /* Which cpu gets undirected irqs. */
};
#define SUN4M_INT_ENABLE 0x80000000
#define SUN4M_INT_E14 0x00000080
#define SUN4M_INT_E10 0x00080000
#define SUN4M_HARD_INT(x) (0x000000001 << (x))
#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */
#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */
#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */
#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */
#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */
#define SUN4M_INT_REALTIME 0x00080000 /* system timer */
#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */
#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */
#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */
#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */
#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */
#define SUN4M_INT_SBUS(x) (1 << (x+7))
#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;
} SCHEDState;
static SCHEDState *ps;
#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 - s->addr) >> 2;
switch (saddr) {
case 0:
return s->intreg_pending;
break;
default:
break;
}
return 0;
}
static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
SCHEDState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
case 0:
s->intreg_pending = val;
break;
case 1: // clear
s->intreg_enabled &= ~val;
break;
case 2: // set
s->intreg_enabled |= val;
break;
default:
break;
}
}
static CPUReadMemoryFunc *intreg_mem_read[3] = {
intreg_mem_readl,
intreg_mem_readl,
intreg_mem_readl,
};
static CPUWriteMemoryFunc *intreg_mem_write[3] = {
intreg_mem_writel,
intreg_mem_writel,
intreg_mem_writel,
};
static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
{
SCHEDState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addrg) >> 2;
switch (saddr) {
case 0:
return s->intregm_pending;
break;
case 1:
return s->intregm_enabled;
break;
default:
break;
}
return 0;
}
static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
SCHEDState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addrg) >> 2;
switch (saddr) {
case 0:
s->intregm_pending = val;
break;
case 1:
s->intregm_enabled = val;
break;
case 2: // clear
s->intregm_enabled &= ~val;
break;
case 3: // set
s->intregm_enabled |= val;
break;
default:
break;
}
}
static CPUReadMemoryFunc *intregm_mem_read[3] = {
intregm_mem_readl,
intregm_mem_readl,
intregm_mem_readl,
};
static CPUWriteMemoryFunc *intregm_mem_write[3] = {
intregm_mem_writel,
intregm_mem_writel,
intregm_mem_writel,
};
void pic_info(void)
{
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);
}
void irq_info(void)
{
#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 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,
};
void pic_set_irq(int irq, int level)
{
if (irq < 16) {
unsigned int mask = intr_to_mask[irq];
ps->intreg_pending |= 1 << irq;
if (ps->intregm_enabled & mask) {
cpu_single_env->interrupt_index = irq;
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
}
}
#ifdef DEBUG_IRQ_COUNT
if (level == 1)
irq_count[irq]++;
#endif
}
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(addr, 3, intreg_io_memory);
intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
cpu_register_physical_memory(addrg, 5, intregm_io_memory);
ps = s;
}
+299
View File
@@ -0,0 +1,299 @@
/*
* QEMU Sparc SLAVIO interrupt controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
//#define DEBUG_IRQ_COUNT
/*
* Registers of interrupt controller in sun4m.
*
* This is the interrupt controller part of chip STP2001 (Slave I/O), also
* produced as NCR89C105. See
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
*
* There is a system master controller and one for each cpu.
*
*/
#define MAX_CPUS 16
typedef struct SLAVIO_INTCTLState {
uint32_t intreg_pending[MAX_CPUS];
uint32_t intregm_pending;
uint32_t intregm_disabled;
uint32_t target_cpu;
#ifdef DEBUG_IRQ_COUNT
uint64_t irq_count[32];
#endif
} SLAVIO_INTCTLState;
#define INTCTL_MAXADDR 0xf
#define INTCTLM_MAXADDR 0xf
// per-cpu interrupt controller
static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
{
SLAVIO_INTCTLState *s = opaque;
uint32_t saddr;
int cpu;
cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
saddr = (addr & INTCTL_MAXADDR) >> 2;
switch (saddr) {
case 0:
return s->intreg_pending[cpu];
default:
break;
}
return 0;
}
static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
SLAVIO_INTCTLState *s = opaque;
uint32_t saddr;
int cpu;
cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
saddr = (addr & INTCTL_MAXADDR) >> 2;
switch (saddr) {
case 1: // clear pending softints
if (val & 0x4000)
val |= 80000000;
val &= 0xfffe0000;
s->intreg_pending[cpu] &= ~val;
break;
case 2: // set softint
val &= 0xfffe0000;
s->intreg_pending[cpu] |= val;
break;
default:
break;
}
}
static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
slavio_intctl_mem_readl,
slavio_intctl_mem_readl,
slavio_intctl_mem_readl,
};
static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
slavio_intctl_mem_writel,
slavio_intctl_mem_writel,
slavio_intctl_mem_writel,
};
// master system interrupt controller
static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
{
SLAVIO_INTCTLState *s = opaque;
uint32_t saddr;
saddr = (addr & INTCTLM_MAXADDR) >> 2;
switch (saddr) {
case 0:
return s->intregm_pending;
case 1:
return s->intregm_disabled;
case 4:
return s->target_cpu;
default:
break;
}
return 0;
}
static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
SLAVIO_INTCTLState *s = opaque;
uint32_t saddr;
saddr = (addr & INTCTLM_MAXADDR) >> 2;
switch (saddr) {
case 2: // clear (enable)
// Force unused bits
val |= 0x7fb2007f;
s->intregm_disabled &= ~val;
break;
case 3: // set (disable, clear pending)
// Force unused bits
val &= ~0x7fb2007f;
s->intregm_disabled |= val;
s->intregm_pending &= ~val;
break;
case 4:
s->target_cpu = val & (MAX_CPUS - 1);
break;
default:
break;
}
}
static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
slavio_intctlm_mem_readl,
slavio_intctlm_mem_readl,
slavio_intctlm_mem_readl,
};
static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
slavio_intctlm_mem_writel,
slavio_intctlm_mem_writel,
slavio_intctlm_mem_writel,
};
void slavio_pic_info(void *opaque)
{
SLAVIO_INTCTLState *s = opaque;
int i;
for (i = 0; i < MAX_CPUS; i++) {
term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
}
term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
}
void slavio_irq_info(void *opaque)
{
#ifndef DEBUG_IRQ_COUNT
term_printf("irq statistic code not compiled.\n");
#else
SLAVIO_INTCTLState *s = opaque;
int i;
int64_t count;
term_printf("IRQ statistics:\n");
for (i = 0; i < 32; i++) {
count = s->irq_count[i];
if (count > 0)
term_printf("%2d: %lld\n", i, count);
}
#endif
}
static const uint32_t intbit_to_level[32] = {
2, 3, 5, 7, 9, 11, 0, 14, 3, 5, 7, 9, 11, 13, 12, 12,
6, 0, 4, 10, 8, 0, 11, 0, 0, 0, 0, 0, 15, 0, 0, 0,
};
/*
* "irq" here is the bit number in the system interrupt register to
* separate serial and keyboard interrupts sharing a level.
*/
void slavio_pic_set_irq(void *opaque, int irq, int level)
{
SLAVIO_INTCTLState *s = opaque;
if (irq < 32) {
uint32_t mask = 1 << irq;
uint32_t pil = intbit_to_level[irq];
if (pil > 0) {
if (level) {
s->intregm_pending |= mask;
s->intreg_pending[s->target_cpu] |= 1 << pil;
}
else {
s->intregm_pending &= ~mask;
s->intreg_pending[s->target_cpu] &= ~(1 << pil);
}
if (level &&
!(s->intregm_disabled & mask) &&
!(s->intregm_disabled & 0x80000000) &&
(pil == 15 || (pil > cpu_single_env->psrpil && cpu_single_env->psret == 1))) {
#ifdef DEBUG_IRQ_COUNT
if (level == 1)
s->irq_count[pil]++;
#endif
cpu_single_env->interrupt_index = TT_EXTINT | pil;
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
}
}
}
}
static void slavio_intctl_save(QEMUFile *f, void *opaque)
{
SLAVIO_INTCTLState *s = opaque;
int i;
for (i = 0; i < MAX_CPUS; i++) {
qemu_put_be32s(f, &s->intreg_pending[i]);
}
qemu_put_be32s(f, &s->intregm_pending);
qemu_put_be32s(f, &s->intregm_disabled);
qemu_put_be32s(f, &s->target_cpu);
}
static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
{
SLAVIO_INTCTLState *s = opaque;
int i;
if (version_id != 1)
return -EINVAL;
for (i = 0; i < MAX_CPUS; i++) {
qemu_get_be32s(f, &s->intreg_pending[i]);
}
qemu_get_be32s(f, &s->intregm_pending);
qemu_get_be32s(f, &s->intregm_disabled);
qemu_get_be32s(f, &s->target_cpu);
return 0;
}
static void slavio_intctl_reset(void *opaque)
{
SLAVIO_INTCTLState *s = opaque;
int i;
for (i = 0; i < MAX_CPUS; i++) {
s->intreg_pending[i] = 0;
}
s->intregm_disabled = 0xffffffff;
s->intregm_pending = 0;
s->target_cpu = 0;
}
void *slavio_intctl_init(uint32_t addr, uint32_t addrg)
{
int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
SLAVIO_INTCTLState *s;
s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
if (!s)
return NULL;
for (i = 0; i < MAX_CPUS; i++) {
slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
}
slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
cpu_register_physical_memory(addrg, INTCTLM_MAXADDR, slavio_intctlm_io_memory);
register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
qemu_register_reset(slavio_intctl_reset, s);
slavio_intctl_reset(s);
return s;
}
+364
View File
@@ -0,0 +1,364 @@
/*
* QEMU Sparc SLAVIO serial port emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
//#define DEBUG_SERIAL
/* debug keyboard */
//#define DEBUG_KBD
/* debug keyboard : only mouse */
//#define DEBUG_MOUSE
/*
* This is the serial port, mouse and keyboard part of chip STP2001
* (Slave I/O), also produced as NCR89C105. See
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
*
* The serial ports implement full AMD AM8530 or Zilog Z8530 chips,
* mouse and keyboard ports don't implement all functions and they are
* only asynchronous. There is no DMA.
*
*/
typedef struct ChannelState {
int irq;
int reg;
int rxint, txint;
uint8_t rx, tx, wregs[16], rregs[16];
CharDriverState *chr;
} ChannelState;
struct SerialState {
struct ChannelState chn[2];
};
#define SERIAL_MAXADDR 7
static void slavio_serial_update_irq(ChannelState *s)
{
if ((s->wregs[1] & 1) && // interrupts enabled
(((s->wregs[1] & 2) && s->txint == 1) || // tx ints enabled, pending
((((s->wregs[1] & 0x18) == 8) || ((s->wregs[1] & 0x18) == 0x10)) &&
s->rxint == 1) || // rx ints enabled, pending
((s->wregs[15] & 0x80) && (s->rregs[0] & 0x80)))) { // break int e&p
pic_set_irq(s->irq, 1);
} else {
pic_set_irq(s->irq, 0);
}
}
static void slavio_serial_reset_chn(ChannelState *s)
{
int i;
s->reg = 0;
for (i = 0; i < SERIAL_MAXADDR; i++) {
s->rregs[i] = 0;
s->wregs[i] = 0;
}
s->wregs[4] = 4;
s->wregs[9] = 0xc0;
s->wregs[11] = 8;
s->wregs[14] = 0x30;
s->wregs[15] = 0xf8;
s->rregs[0] = 0x44;
s->rregs[1] = 6;
s->rx = s->tx = 0;
s->rxint = s->txint = 0;
}
static void slavio_serial_reset(void *opaque)
{
SerialState *s = opaque;
slavio_serial_reset_chn(&s->chn[0]);
slavio_serial_reset_chn(&s->chn[1]);
}
static void slavio_serial_mem_writeb(void *opaque, uint32_t addr, uint32_t val)
{
SerialState *ser = opaque;
ChannelState *s;
uint32_t saddr;
int newreg, channel;
val &= 0xff;
saddr = (addr & 3) >> 1;
channel = (addr & SERIAL_MAXADDR) >> 2;
s = &ser->chn[channel];
switch (saddr) {
case 0:
newreg = 0;
switch (s->reg) {
case 0:
newreg = val & 7;
val &= 0x38;
switch (val) {
case 8:
s->reg |= 0x8;
break;
case 0x20:
s->rxint = 0;
break;
case 0x28:
s->txint = 0;
break;
default:
break;
}
break;
case 1 ... 8:
case 10 ... 15:
s->wregs[s->reg] = val;
break;
case 9:
switch (val & 0xc0) {
case 0:
default:
break;
case 0x40:
slavio_serial_reset_chn(&ser->chn[1]);
return;
case 0x80:
slavio_serial_reset_chn(&ser->chn[0]);
return;
case 0xc0:
slavio_serial_reset(ser);
return;
}
break;
default:
break;
}
if (s->reg == 0)
s->reg = newreg;
else
s->reg = 0;
break;
case 1:
if (s->wregs[5] & 8) { // tx enabled
s->tx = val;
if (s->chr)
qemu_chr_write(s->chr, &s->tx, 1);
s->txint = 1;
}
break;
default:
break;
}
}
static uint32_t slavio_serial_mem_readb(void *opaque, uint32_t addr)
{
SerialState *ser = opaque;
ChannelState *s;
uint32_t saddr;
uint32_t ret;
int channel;
saddr = (addr & 3) >> 1;
channel = (addr & SERIAL_MAXADDR) >> 2;
s = &ser->chn[channel];
switch (saddr) {
case 0:
ret = s->rregs[s->reg];
s->reg = 0;
return ret;
case 1:
s->rregs[0] &= ~1;
return s->rx;
default:
break;
}
return 0;
}
static int serial_can_receive(void *opaque)
{
ChannelState *s = opaque;
if (((s->wregs[3] & 1) == 0) // Rx not enabled
|| ((s->rregs[0] & 1) == 1)) // char already available
return 0;
else
return 1;
}
static void serial_receive_byte(ChannelState *s, int ch)
{
s->rregs[0] |= 1;
s->rx = ch;
s->rxint = 1;
slavio_serial_update_irq(s);
}
static void serial_receive_break(ChannelState *s)
{
s->rregs[0] |= 0x80;
slavio_serial_update_irq(s);
}
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
{
ChannelState *s = opaque;
serial_receive_byte(s, buf[0]);
}
static void serial_event(void *opaque, int event)
{
ChannelState *s = opaque;
if (event == CHR_EVENT_BREAK)
serial_receive_break(s);
}
static CPUReadMemoryFunc *slavio_serial_mem_read[3] = {
slavio_serial_mem_readb,
slavio_serial_mem_readb,
slavio_serial_mem_readb,
};
static CPUWriteMemoryFunc *slavio_serial_mem_write[3] = {
slavio_serial_mem_writeb,
slavio_serial_mem_writeb,
slavio_serial_mem_writeb,
};
static void slavio_serial_save_chn(QEMUFile *f, ChannelState *s)
{
qemu_put_be32s(f, &s->irq);
qemu_put_be32s(f, &s->reg);
qemu_put_be32s(f, &s->rxint);
qemu_put_be32s(f, &s->txint);
qemu_put_8s(f, &s->rx);
qemu_put_8s(f, &s->tx);
qemu_put_buffer(f, s->wregs, 16);
qemu_put_buffer(f, s->rregs, 16);
}
static void slavio_serial_save(QEMUFile *f, void *opaque)
{
SerialState *s = opaque;
slavio_serial_save_chn(f, &s->chn[0]);
slavio_serial_save_chn(f, &s->chn[1]);
}
static int slavio_serial_load_chn(QEMUFile *f, ChannelState *s, int version_id)
{
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->irq);
qemu_get_be32s(f, &s->reg);
qemu_get_be32s(f, &s->rxint);
qemu_get_be32s(f, &s->txint);
qemu_get_8s(f, &s->rx);
qemu_get_8s(f, &s->tx);
qemu_get_buffer(f, s->wregs, 16);
qemu_get_buffer(f, s->rregs, 16);
return 0;
}
static int slavio_serial_load(QEMUFile *f, void *opaque, int version_id)
{
SerialState *s = opaque;
int ret;
ret = slavio_serial_load_chn(f, &s->chn[0], version_id);
if (ret != 0)
return ret;
ret = slavio_serial_load_chn(f, &s->chn[1], version_id);
return ret;
}
SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2)
{
int slavio_serial_io_memory;
SerialState *s;
s = qemu_mallocz(sizeof(SerialState));
if (!s)
return NULL;
s->chn[0].irq = irq;
s->chn[1].irq = irq;
s->chn[0].chr = chr1;
s->chn[1].chr = chr2;
slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
if (chr1) {
qemu_chr_add_read_handler(chr1, serial_can_receive, serial_receive1, &s->chn[0]);
qemu_chr_add_event_handler(chr1, serial_event);
}
if (chr2) {
qemu_chr_add_read_handler(chr2, serial_can_receive, serial_receive1, &s->chn[1]);
qemu_chr_add_event_handler(chr2, serial_event);
}
register_savevm("slavio_serial", base, 1, slavio_serial_save, slavio_serial_load, s);
qemu_register_reset(slavio_serial_reset, s);
slavio_serial_reset(s);
return s;
}
static void sunkbd_event(void *opaque, int ch)
{
ChannelState *s = opaque;
// XXX: PC -> Sun Type 5 translation?
serial_receive_byte(s, ch);
}
static void sunmouse_event(void *opaque,
int dx, int dy, int dz, int buttons_state)
{
ChannelState *s = opaque;
int ch;
// XXX
ch = 0x42;
serial_receive_byte(s, ch);
}
void slavio_serial_ms_kbd_init(int base, int irq)
{
int slavio_serial_io_memory;
SerialState *s;
s = qemu_mallocz(sizeof(SerialState));
if (!s)
return;
s->chn[0].irq = irq;
s->chn[1].irq = irq;
s->chn[0].chr = NULL;
s->chn[1].chr = NULL;
slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s);
cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
qemu_add_kbd_event_handler(sunkbd_event, &s->chn[0]);
qemu_add_mouse_event_handler(sunmouse_event, &s->chn[1]);
qemu_register_reset(slavio_serial_reset, s);
slavio_serial_reset(s);
}
+289
View File
@@ -0,0 +1,289 @@
/*
* QEMU Sparc SLAVIO timer controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
//#define DEBUG_TIMER
/*
* Registers of hardware timer in sun4m.
*
* This is the timer/counter part of chip STP2001 (Slave I/O), also
* produced as NCR89C105. See
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
*
* The 31-bit counter is incremented every 500ns by bit 9. Bits 8..0
* are zero. Bit 31 is 1 when count has been reached.
*
*/
typedef struct SLAVIO_TIMERState {
uint32_t limit, count, counthigh;
int64_t count_load_time;
int64_t expire_time;
int64_t stop_time, tick_offset;
QEMUTimer *irq_timer;
int irq;
int reached, stopped;
int mode; // 0 = processor, 1 = user, 2 = system
} SLAVIO_TIMERState;
#define TIMER_MAXADDR 0x1f
#define CNT_FREQ 2000000
#define MAX_CPUS 16
// Update count, set irq, update expire_time
static void slavio_timer_get_out(SLAVIO_TIMERState *s)
{
int out;
int64_t diff, ticks, count;
uint32_t limit;
// There are three clock tick units: CPU ticks, register units
// (nanoseconds), and counter ticks (500 ns).
if (s->mode == 1 && s->stopped)
ticks = s->stop_time;
else
ticks = qemu_get_clock(vm_clock) - s->tick_offset;
out = (ticks >= s->expire_time);
if (out)
s->reached = 0x80000000;
if (!s->limit)
limit = 0x7fffffff;
else
limit = s->limit;
// Convert register units to counter ticks
limit = limit >> 9;
// Convert cpu ticks to counter ticks
diff = muldiv64(ticks - s->count_load_time, CNT_FREQ, ticks_per_sec);
// Calculate what the counter should be, convert to register
// units
count = diff % limit;
s->count = count << 9;
s->counthigh = count >> 22;
// Expire time: CPU ticks left to next interrupt
// Convert remaining counter ticks to CPU ticks
s->expire_time = ticks + muldiv64(limit - count, ticks_per_sec, CNT_FREQ);
#ifdef DEBUG_TIMER
term_printf("timer: irq %d limit %d reached %d d %lld count %d s->c %x diff %lld stopped %d mode %d\n", s->irq, limit, s->reached?1:0, (ticks-s->count_load_time), count, s->count, s->expire_time - ticks, s->stopped, s->mode);
#endif
if (s->mode != 1)
pic_set_irq(s->irq, out);
}
// timer callback
static void slavio_timer_irq(void *opaque)
{
SLAVIO_TIMERState *s = opaque;
if (!s->irq_timer)
return;
slavio_timer_get_out(s);
if (s->mode != 1)
qemu_mod_timer(s->irq_timer, s->expire_time);
}
static uint32_t slavio_timer_mem_readl(void *opaque, target_phys_addr_t addr)
{
SLAVIO_TIMERState *s = opaque;
uint32_t saddr;
saddr = (addr & TIMER_MAXADDR) >> 2;
switch (saddr) {
case 0:
// read limit (system counter mode) or read most signifying
// part of counter (user mode)
if (s->mode != 1) {
// clear irq
pic_set_irq(s->irq, 0);
s->count_load_time = qemu_get_clock(vm_clock);
s->reached = 0;
return s->limit;
}
else {
slavio_timer_get_out(s);
return s->counthigh & 0x7fffffff;
}
case 1:
// read counter and reached bit (system mode) or read lsbits
// of counter (user mode)
slavio_timer_get_out(s);
if (s->mode != 1)
return (s->count & 0x7fffffff) | s->reached;
else
return s->count;
case 3:
// read start/stop status
return s->stopped;
case 4:
// read user/system mode
return s->mode & 1;
default:
return 0;
}
}
static void slavio_timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
SLAVIO_TIMERState *s = opaque;
uint32_t saddr;
saddr = (addr & TIMER_MAXADDR) >> 2;
switch (saddr) {
case 0:
// set limit, reset counter
s->count_load_time = qemu_get_clock(vm_clock);
// fall through
case 2:
// set limit without resetting counter
if (!val)
s->limit = 0x7fffffff;
else
s->limit = val & 0x7fffffff;
slavio_timer_irq(s);
break;
case 3:
// start/stop user counter
if (s->mode == 1) {
if (val & 1) {
s->stop_time = qemu_get_clock(vm_clock);
s->stopped = 1;
}
else {
if (s->stopped)
s->tick_offset += qemu_get_clock(vm_clock) - s->stop_time;
s->stopped = 0;
}
}
break;
case 4:
// bit 0: user (1) or system (0) counter mode
if (s->mode == 0 || s->mode == 1)
s->mode = val & 1;
break;
default:
break;
}
}
static CPUReadMemoryFunc *slavio_timer_mem_read[3] = {
slavio_timer_mem_readl,
slavio_timer_mem_readl,
slavio_timer_mem_readl,
};
static CPUWriteMemoryFunc *slavio_timer_mem_write[3] = {
slavio_timer_mem_writel,
slavio_timer_mem_writel,
slavio_timer_mem_writel,
};
static void slavio_timer_save(QEMUFile *f, void *opaque)
{
SLAVIO_TIMERState *s = opaque;
qemu_put_be32s(f, &s->limit);
qemu_put_be32s(f, &s->count);
qemu_put_be32s(f, &s->counthigh);
qemu_put_be64s(f, &s->count_load_time);
qemu_put_be64s(f, &s->expire_time);
qemu_put_be64s(f, &s->stop_time);
qemu_put_be64s(f, &s->tick_offset);
qemu_put_be32s(f, &s->irq);
qemu_put_be32s(f, &s->reached);
qemu_put_be32s(f, &s->stopped);
qemu_put_be32s(f, &s->mode);
}
static int slavio_timer_load(QEMUFile *f, void *opaque, int version_id)
{
SLAVIO_TIMERState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, &s->limit);
qemu_get_be32s(f, &s->count);
qemu_get_be32s(f, &s->counthigh);
qemu_get_be64s(f, &s->count_load_time);
qemu_get_be64s(f, &s->expire_time);
qemu_get_be64s(f, &s->stop_time);
qemu_get_be64s(f, &s->tick_offset);
qemu_get_be32s(f, &s->irq);
qemu_get_be32s(f, &s->reached);
qemu_get_be32s(f, &s->stopped);
qemu_get_be32s(f, &s->mode);
return 0;
}
static void slavio_timer_reset(void *opaque)
{
SLAVIO_TIMERState *s = opaque;
s->limit = 0;
s->count = 0;
s->count_load_time = qemu_get_clock(vm_clock);;
s->stop_time = s->count_load_time;
s->tick_offset = 0;
s->reached = 0;
s->mode &= 2;
s->stopped = 1;
slavio_timer_get_out(s);
}
static void slavio_timer_init_internal(uint32_t addr, int irq, int mode)
{
int slavio_timer_io_memory;
SLAVIO_TIMERState *s;
s = qemu_mallocz(sizeof(SLAVIO_TIMERState));
if (!s)
return;
s->irq = irq;
s->mode = mode;
s->irq_timer = qemu_new_timer(vm_clock, slavio_timer_irq, s);
slavio_timer_io_memory = cpu_register_io_memory(0, slavio_timer_mem_read,
slavio_timer_mem_write, s);
cpu_register_physical_memory(addr, TIMER_MAXADDR, slavio_timer_io_memory);
register_savevm("slavio_timer", addr, 1, slavio_timer_save, slavio_timer_load, s);
qemu_register_reset(slavio_timer_reset, s);
slavio_timer_reset(s);
}
void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2)
{
int i;
for (i = 0; i < MAX_CPUS; i++) {
slavio_timer_init_internal(addr1 + i * TARGET_PAGE_SIZE, irq1, 0);
}
slavio_timer_init_internal(addr2, irq2, 2);
}
+117 -46
View File
@@ -25,29 +25,32 @@
#include "m48t08.h"
#define KERNEL_LOAD_ADDR 0x00004000
#define MMU_CONTEXT_TBL 0x00003000
#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
#define PROM_ADDR 0xffd04000
#define PROM_ADDR 0xffd00000
#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_EEPROM 0x71200000 /* m48t08 */
#define PHYS_JJ_IDPROM_OFF 0x1FD8
#define PHYS_JJ_EEPROM_SIZE 0x2000
#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
// IRQs are not PIL ones, but master interrupt controller register
// bits
#define PHYS_JJ_IOMMU 0x10000000 /* I/O MMU */
#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_LEDMA 0x78400010 /* Lance DMA controller */
#define PHYS_JJ_LE 0x78C00000 /* Lance ethernet */
#define PHYS_JJ_LE_IRQ 16
#define PHYS_JJ_CLOCK 0x71D00000 /* Per-CPU timer/counter, L14 */
#define PHYS_JJ_CLOCK_IRQ 7
#define PHYS_JJ_CLOCK1 0x71D10000 /* System timer/counter, L10 */
#define PHYS_JJ_CLOCK1_IRQ 19
#define PHYS_JJ_INTR0 0x71E00000 /* Per-CPU interrupt control registers */
#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
#define PHYS_JJ_MS_KBD 0x71000000 /* Mouse and keyboard */
#define PHYS_JJ_MS_KBD_IRQ 14
#define PHYS_JJ_SER 0x71100000 /* Serial */
#define PHYS_JJ_SER_IRQ 15
#define PHYS_JJ_SCSI_IRQ 18
#define PHYS_JJ_FDC 0x71400000 /* Floppy */
#define PHYS_JJ_FLOPPY_IRQ 22
/* TSC handling */
@@ -57,13 +60,73 @@ uint64_t cpu_get_tsc()
}
void DMA_run() {}
void SB16_run() {}
int serial_can_receive(SerialState *s) { return 0; }
void serial_receive_byte(SerialState *s, int ch) {}
void serial_receive_break(SerialState *s) {}
static m48t08_t *nvram;
static void nvram_init(m48t08_t *nvram, uint8_t *macaddr)
{
unsigned char tmp = 0;
int i, j;
i = 0x1fd8;
m48t08_write(nvram, i++, 0x01);
m48t08_write(nvram, i++, 0x80); /* Sun4m OBP */
j = 0;
m48t08_write(nvram, i++, macaddr[j++]);
m48t08_write(nvram, i++, macaddr[j++]);
m48t08_write(nvram, i++, macaddr[j++]);
m48t08_write(nvram, i++, macaddr[j++]);
m48t08_write(nvram, i++, macaddr[j++]);
m48t08_write(nvram, i, macaddr[j]);
/* Calculate checksum */
for (i = 0x1fd8; i < 0x1fe7; i++) {
tmp ^= m48t08_read(nvram, i);
}
m48t08_write(nvram, 0x1fe7, tmp);
}
static void *slavio_intctl;
void pic_info()
{
slavio_pic_info(slavio_intctl);
}
void irq_info()
{
slavio_irq_info(slavio_intctl);
}
void pic_set_irq(int irq, int level)
{
slavio_pic_set_irq(slavio_intctl, irq, level);
}
static void *tcx;
void vga_update_display()
{
tcx_update_display(tcx);
}
void vga_invalidate_display()
{
tcx_invalidate_display(tcx);
}
void vga_screen_dump(const char *filename)
{
tcx_screen_dump(tcx, filename);
}
static void *iommu;
uint32_t iommu_translate(uint32_t addr)
{
return iommu_translate_local(iommu, addr);
}
/* Sun4m hardware initialisation */
void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
DisplayState *ds, const char **fd_filename, int snapshot,
@@ -72,42 +135,50 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
{
char buf[1024];
int ret, linux_boot;
unsigned long bios_offset;
unsigned long vram_size = 0x100000, prom_offset;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, 0);
bios_offset = ram_size;
iommu_init(PHYS_JJ_IOMMU);
sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
tcx_init(ds, PHYS_JJ_TCX_FB);
iommu = iommu_init(PHYS_JJ_IOMMU);
slavio_intctl = slavio_intctl_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size);
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);
nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE);
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr);
slavio_timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ, PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
slavio_serial_ms_kbd_init(PHYS_JJ_MS_KBD, PHYS_JJ_MS_KBD_IRQ);
slavio_serial_init(PHYS_JJ_SER, PHYS_JJ_SER_IRQ, serial_hds[0], serial_hds[1]);
fdctrl_init(PHYS_JJ_FLOPPY_IRQ, 0, 1, PHYS_JJ_FDC, fd_table);
/* We load Proll as the kernel and start it. It will issue a magic
IO to load the real kernel */
if (linux_boot) {
prom_offset = ram_size + vram_size;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
ret = load_elf(buf, phys_ram_base + prom_offset);
if (ret < 0) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
ret = load_kernel(buf,
phys_ram_base + KERNEL_LOAD_ADDR);
ret = load_image(buf, phys_ram_base + prom_offset);
}
if (ret < 0) {
fprintf(stderr, "qemu: could not load prom '%s'\n",
buf);
exit(1);
}
cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
prom_offset | IO_MEM_ROM);
if (linux_boot) {
ret = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (ret < 0)
ret = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (ret < 0)
ret = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (ret < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
buf);
exit(1);
kernel_filename);
exit(1);
}
}
/* 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);
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);
stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2);
}
+198 -123
View File
@@ -25,179 +25,254 @@
#define MAXX 1024
#define MAXY 768
/*
* Proll uses only small part of display, we need to switch to full
* display when we get linux framebuffer console or X11 running. For
* now it's just slower and awkward.
*/
#if 1
#define XSZ (8*80)
#define YSZ (24*11)
#define XOFF (MAXX-XSZ)
#define YOFF (MAXY-YSZ)
#else
#define XSZ MAXX
#define YSZ MAXY
#define XOFF 0
#define YOFF 0
#endif
typedef struct TCXState {
uint32_t addr;
DisplayState *ds;
uint8_t *vram;
unsigned long vram_offset;
uint8_t r[256], g[256], b[256];
} TCXState;
static TCXState *ts;
void vga_update_display()
static void tcx_draw_line32(TCXState *s1, uint8_t *d,
const uint8_t *s, int width)
{
dpy_update(ts->ds, 0, 0, XSZ, YSZ);
int x;
uint8_t val;
for(x = 0; x < width; x++) {
val = *s++;
*d++ = s1->r[val];
*d++ = s1->g[val];
*d++ = s1->b[val];
d++;
}
}
void vga_invalidate_display() {}
static void tcx_draw_line24(TCXState *s1, uint8_t *d,
const uint8_t *s, int width)
{
int x;
uint8_t val;
static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
for(x = 0; x < width; x++) {
val = *s++;
*d++ = s1->r[val];
*d++ = s1->g[val];
*d++ = s1->b[val];
}
}
static void tcx_draw_line8(TCXState *s1, uint8_t *d,
const uint8_t *s, int width)
{
int x;
uint8_t val;
for(x = 0; x < width; x++) {
val = *s++;
/* XXX translate between palettes? */
*d++ = val;
}
}
/* Fixed line length 1024 allows us to do nice tricks not possible on
VGA... */
void tcx_update_display(void *opaque)
{
TCXState *ts = opaque;
uint32_t page;
int y, page_min, page_max, y_start, dd, ds;
uint8_t *d, *s;
void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);
if (ts->ds->depth == 0)
return;
#ifdef LD_BYPASS_OK
page = ts->vram_offset + YOFF*MAXX;
#else
page = ts->addr + YOFF*MAXX;
#endif
y_start = -1;
page_min = 0x7fffffff;
page_max = -1;
d = ts->ds->data;
s = ts->vram + YOFF*MAXX + XOFF;
dd = ts->ds->linesize;
ds = 1024;
switch (ts->ds->depth) {
case 32:
f = tcx_draw_line32;
break;
case 24:
f = tcx_draw_line24;
break;
default:
case 8:
f = tcx_draw_line8;
break;
case 0:
return;
}
for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) {
if (cpu_physical_memory_is_dirty(page)) {
if (y_start < 0)
y_start = y;
if (page < page_min)
page_min = page;
if (page > page_max)
page_max = page;
f(ts, d, s, XSZ);
d += dd;
s += ds;
f(ts, d, s, XSZ);
d += dd;
s += ds;
f(ts, d, s, XSZ);
d += dd;
s += ds;
f(ts, d, s, XSZ);
d += dd;
s += ds;
} else {
if (y_start >= 0) {
/* flush to display */
dpy_update(ts->ds, 0, y_start,
XSZ, y - y_start);
y_start = -1;
}
d += dd * 4;
s += ds * 4;
}
}
if (y_start >= 0) {
/* flush to display */
dpy_update(ts->ds, 0, y_start,
XSZ, y - y_start);
}
/* reset modified pages */
if (page_max != -1) {
cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
}
}
void tcx_invalidate_display(void *opaque)
{
TCXState *s = opaque;
uint32_t saddr;
unsigned int x, y;
int i;
saddr = addr - s->addr - YOFF*MAXX - XOFF;
y = saddr / MAXX;
x = saddr - y * MAXX;
if (x < XSZ && y < YSZ) {
return s->vram[y * XSZ + x];
for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
#ifdef LD_BYPASS_OK
cpu_physical_memory_set_dirty(s->vram_offset + i);
#else
cpu_physical_memory_set_dirty(s->addr + i);
#endif
}
}
static void tcx_save(QEMUFile *f, void *opaque)
{
TCXState *s = opaque;
qemu_put_be32s(f, (uint32_t *)&s->addr);
qemu_put_be32s(f, (uint32_t *)&s->vram);
qemu_put_buffer(f, s->r, 256);
qemu_put_buffer(f, s->g, 256);
qemu_put_buffer(f, s->b, 256);
}
static int tcx_load(QEMUFile *f, void *opaque, int version_id)
{
TCXState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_be32s(f, (uint32_t *)&s->addr);
qemu_get_be32s(f, (uint32_t *)&s->vram);
qemu_get_buffer(f, s->r, 256);
qemu_get_buffer(f, s->g, 256);
qemu_get_buffer(f, s->b, 256);
return 0;
}
static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = tcx_mem_readb(opaque, addr) << 8;
v |= tcx_mem_readb(opaque, addr + 1);
#else
v = tcx_mem_readb(opaque, addr);
v |= tcx_mem_readb(opaque, addr + 1) << 8;
#endif
return v;
}
static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = tcx_mem_readb(opaque, addr) << 24;
v |= tcx_mem_readb(opaque, addr + 1) << 16;
v |= tcx_mem_readb(opaque, addr + 2) << 8;
v |= tcx_mem_readb(opaque, addr + 3);
#else
v = tcx_mem_readb(opaque, addr);
v |= tcx_mem_readb(opaque, addr + 1) << 8;
v |= tcx_mem_readb(opaque, addr + 2) << 16;
v |= tcx_mem_readb(opaque, addr + 3) << 24;
#endif
return v;
}
static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
static void tcx_reset(void *opaque)
{
TCXState *s = opaque;
uint32_t saddr;
unsigned int x, y;
char *sptr;
saddr = addr - s->addr - YOFF*MAXX - XOFF;
y = saddr / MAXX;
x = saddr - y * MAXX;
if (x < XSZ && y < YSZ) {
sptr = s->ds->data;
if (sptr) {
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;
}
}
static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff);
tcx_mem_writeb(opaque, addr + 1, val & 0xff);
#else
tcx_mem_writeb(opaque, addr, val & 0xff);
tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
/* Initialize palette */
memset(s->r, 0, 256);
memset(s->g, 0, 256);
memset(s->b, 0, 256);
s->r[255] = s->g[255] = s->b[255] = 255;
memset(s->vram, 0, MAXX*MAXY);
#ifdef LD_BYPASS_OK
cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY - 1);
#endif
}
static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff);
tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
tcx_mem_writeb(opaque, addr + 3, val & 0xff);
#else
tcx_mem_writeb(opaque, addr, val & 0xff);
tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
#endif
}
static CPUReadMemoryFunc *tcx_mem_read[3] = {
tcx_mem_readb,
tcx_mem_readw,
tcx_mem_readl,
};
static CPUWriteMemoryFunc *tcx_mem_write[3] = {
tcx_mem_writeb,
tcx_mem_writew,
tcx_mem_writel,
};
void tcx_init(DisplayState *ds, uint32_t addr)
void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
unsigned long vram_offset, int vram_size)
{
TCXState *s;
int tcx_io_memory;
s = qemu_mallocz(sizeof(TCXState));
if (!s)
return;
return NULL;
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(addr, 0x100000,
tcx_io_memory);
s->vram = qemu_mallocz(XSZ*YSZ);
s->vram = vram_base;
s->vram_offset = vram_offset;
cpu_register_physical_memory(addr, vram_size, vram_offset);
register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
qemu_register_reset(tcx_reset, s);
tcx_reset(s);
dpy_resize(s->ds, XSZ, YSZ);
return s;
}
void vga_screen_dump(const char *filename)
void tcx_screen_dump(void *opaque, const char *filename)
{
TCXState *s = ts;
TCXState *s = opaque;
FILE *f;
uint8_t *d, *d1;
unsigned int v;
uint8_t *d, *d1, 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;
return;
fprintf(f, "P6\n%d %d\n%d\n", XSZ, YSZ, 255);
d1 = s->vram + YOFF*MAXX + XOFF;
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);
fputc(s->r[v], f);
fputc(s->g[v], f);
fputc(s->b[v], f);
d++;
}
d1 += XSZ;
d1 += MAXX;
}
fclose(f);
return;
-97
View File
@@ -1,97 +0,0 @@
/*
* QEMU Sparc timer controller emulation
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "vl.h"
/*
* 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;
};
typedef struct TIMERState {
uint32_t addr;
uint32_t timer_regs[2];
int irq;
} TIMERState;
static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
{
TIMERState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
return s->timer_regs[saddr];
break;
}
return 0;
}
static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
TIMERState *s = opaque;
uint32_t saddr;
saddr = (addr - s->addr) >> 2;
switch (saddr) {
default:
s->timer_regs[saddr] = val;
break;
}
}
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,
};
void timer_init(uint32_t addr, int irq)
{
int timer_io_memory;
TIMERState *s;
s = qemu_mallocz(sizeof(TIMERState));
if (!s)
return;
s->addr = addr;
s->irq = irq;
timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
cpu_register_physical_memory(addr, 2, timer_io_memory);
}
+10 -6
View File
@@ -841,6 +841,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
unsigned int i;
struct elf_shdr sechdr, symtab, strtab;
char *strings;
struct syminfo *s;
lseek(fd, hdr->e_shoff, SEEK_SET);
for (i = 0; i < hdr->e_shnum; i++) {
@@ -866,24 +867,27 @@ static void load_symbols(struct elfhdr *hdr, int fd)
found:
/* Now know where the strtab and symtab are. Snarf them. */
disas_symtab = malloc(symtab.sh_size);
disas_strtab = strings = malloc(strtab.sh_size);
if (!disas_symtab || !disas_strtab)
s = malloc(sizeof(*s));
s->disas_symtab = malloc(symtab.sh_size);
s->disas_strtab = strings = malloc(strtab.sh_size);
if (!s->disas_symtab || !s->disas_strtab)
return;
lseek(fd, symtab.sh_offset, SEEK_SET);
if (read(fd, disas_symtab, symtab.sh_size) != symtab.sh_size)
if (read(fd, s->disas_symtab, symtab.sh_size) != symtab.sh_size)
return;
#ifdef BSWAP_NEEDED
for (i = 0; i < symtab.sh_size / sizeof(struct elf_sym); i++)
bswap_sym(disas_symtab + sizeof(struct elf_sym)*i);
bswap_sym(s->disas_symtab + sizeof(struct elf_sym)*i);
#endif
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);
s->disas_num_syms = symtab.sh_size / sizeof(struct elf_sym);
s->next = syminfos;
syminfos = s;
}
static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,

Some files were not shown because too many files have changed in this diff Show More