sparc fixes (Blue Swirl)

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1326 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2005-03-13 09:43:36 +00:00
parent b756921ad1
commit 6f7e9aec5e
12 changed files with 1564 additions and 489 deletions

View File

@ -338,7 +338,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_BASE_ARCH), sparc)
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
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 esp.o
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o

1
TODO
View File

@ -3,7 +3,6 @@ short term:
- debug option in 'configure' script + disable -fomit-frame-pointer
- Precise VGA timings for old games/demos (malc patch)
- merge PIC spurious interrupt patch
- merge VNC keyboard patch
- merge Solaris patch
- warning for OS/2: must not use 128 MB memory (merge bochs cmos patch ?)
- config file (at least for windows/Mac OS X)

192
hw/esp.c Normal file
View File

@ -0,0 +1,192 @@
/*
* QEMU ESP emulation
*
* Copyright (c) 2005 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"
/* debug ESP card */
#define DEBUG_ESP
#ifdef DEBUG_ESP
#define DPRINTF(fmt, args...) \
do { printf("ESP: " fmt , ##args); } while (0)
#else
#define DPRINTF(fmt, args...)
#endif
#define ESPDMA_REGS 4
#define ESPDMA_MAXADDR (ESPDMA_REGS * 4 - 1)
#define ESP_MAXREG 0x3f
typedef struct ESPState {
BlockDriverState **bd;
uint8_t regs[ESP_MAXREG];
int irq;
uint32_t espdmaregs[ESPDMA_REGS];
} ESPState;
static void esp_reset(void *opaque)
{
ESPState *s = opaque;
memset(s->regs, 0, ESP_MAXREG);
s->regs[0x0e] = 0x4; // Indicate fas100a
memset(s->espdmaregs, 0, ESPDMA_REGS * 4);
}
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESP_MAXREG) >> 2;
switch (saddr) {
default:
break;
}
DPRINTF("esp: read reg[%d]: 0x%2.2x\n", saddr, s->regs[saddr]);
return s->regs[saddr];
}
static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESP_MAXREG) >> 2;
DPRINTF("esp: write reg[%d]: 0x%2.2x -> 0x%2.2x\n", saddr, s->regs[saddr], val);
switch (saddr) {
case 3:
// Command
switch(val & 0x7f) {
case 0:
DPRINTF("esp: NOP (%2.2x)\n", val);
break;
case 2:
DPRINTF("esp: Chip reset (%2.2x)\n", val);
esp_reset(s);
break;
case 3:
DPRINTF("esp: Bus reset (%2.2x)\n", val);
break;
case 0x1a:
DPRINTF("esp: Set ATN (%2.2x)\n", val);
break;
case 0x42:
DPRINTF("esp: Select with ATN (%2.2x)\n", val);
s->regs[4] = 0x1a; // Status: TCNT | TDONE | CMD
s->regs[5] = 0x20; // Intr: Disconnect, nobody there
s->regs[6] = 0x4; // Seq: Cmd done
pic_set_irq(s->irq, 1);
break;
}
break;
case 4 ... 7:
case 9 ... 0xf:
break;
default:
s->regs[saddr] = val;
break;
}
}
static CPUReadMemoryFunc *esp_mem_read[3] = {
esp_mem_readb,
esp_mem_readb,
esp_mem_readb,
};
static CPUWriteMemoryFunc *esp_mem_write[3] = {
esp_mem_writeb,
esp_mem_writeb,
esp_mem_writeb,
};
static uint32_t espdma_mem_readl(void *opaque, target_phys_addr_t addr)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESPDMA_MAXADDR) >> 2;
return s->espdmaregs[saddr];
}
static void espdma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
ESPState *s = opaque;
uint32_t saddr;
saddr = (addr & ESPDMA_MAXADDR) >> 2;
s->espdmaregs[saddr] = val;
}
static CPUReadMemoryFunc *espdma_mem_read[3] = {
espdma_mem_readl,
espdma_mem_readl,
espdma_mem_readl,
};
static CPUWriteMemoryFunc *espdma_mem_write[3] = {
espdma_mem_writel,
espdma_mem_writel,
espdma_mem_writel,
};
static void esp_save(QEMUFile *f, void *opaque)
{
ESPState *s = opaque;
}
static int esp_load(QEMUFile *f, void *opaque, int version_id)
{
ESPState *s = opaque;
if (version_id != 1)
return -EINVAL;
return 0;
}
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr)
{
ESPState *s;
int esp_io_memory, espdma_io_memory;
s = qemu_mallocz(sizeof(ESPState));
if (!s)
return;
s->bd = bd;
s->irq = irq;
esp_io_memory = cpu_register_io_memory(0, esp_mem_read, esp_mem_write, s);
cpu_register_physical_memory(espaddr, ESP_MAXREG*4, esp_io_memory);
espdma_io_memory = cpu_register_io_memory(0, espdma_mem_read, espdma_mem_write, s);
cpu_register_physical_memory(espdaddr, 16, espdma_io_memory);
esp_reset(s);
register_savevm("esp", espaddr, 1, esp_save, esp_load, s);
qemu_register_reset(esp_reset, s);
}

View File

@ -94,21 +94,6 @@ typedef struct fdrive_t {
uint8_t ro; /* Is read-only */
} fdrive_t;
#ifdef TARGET_SPARC
/* XXX: suppress those hacks */
#define DMA_read_memory(a,b,c,d)
#define DMA_write_memory(a,b,c,d)
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
{
}
#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 */
@ -423,6 +408,12 @@ static uint32_t fdctrl_read (void *opaque, uint32_t reg)
uint32_t retval;
switch (reg & 0x07) {
#ifdef TARGET_SPARC
case 0x00:
// Identify to Linux as S82078B
retval = fdctrl_read_statusB(fdctrl);
break;
#endif
case 0x01:
retval = fdctrl_read_statusB(fdctrl);
break;
@ -577,6 +568,14 @@ static void fdctrl_reset_irq (fdctrl_t *fdctrl)
static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
{
#ifdef TARGET_SPARC
// Sparc mutation
if (!fdctrl->dma_en) {
fdctrl->state &= ~FD_CTRL_BUSY;
fdctrl->int_status = status;
return;
}
#endif
if (~(fdctrl->state & FD_CTRL_INTR)) {
pic_set_irq(fdctrl->irq_lvl, 1);
fdctrl->state |= FD_CTRL_INTR;
@ -980,11 +979,11 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
len = dma_len - fdctrl->data_pos;
if (len + rel_pos > FD_SECTOR_LEN)
len = FD_SECTOR_LEN - rel_pos;
FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x %02x "
"(%d-0x%08x 0x%08x)\n", len, size, fdctrl->data_pos,
FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x "
"(%d-0x%08x 0x%08x)\n", len, dma_len, fdctrl->data_pos,
fdctrl->data_len, fdctrl->cur_drv, cur_drv->head,
cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
fd_sector(cur_drv) * 512, addr);
fd_sector(cur_drv) * 512);
if (fdctrl->data_dir != FD_DIR_WRITE ||
len < FD_SECTOR_LEN || rel_pos != 0) {
/* READ & SCAN commands and realign to a sector for WRITE */
@ -1045,7 +1044,7 @@ static int fdctrl_transfer_handler (void *opaque, int nchan,
FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
cur_drv->head, cur_drv->track, cur_drv->sect,
fd_sector(cur_drv),
fdctrl->data_pos - size);
fdctrl->data_pos - len);
/* XXX: cur_drv->sect >= cur_drv->last_sect should be an
error in fact */
if (cur_drv->sect >= cur_drv->last_sect ||

View File

@ -36,7 +36,10 @@
// 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_FB 0x50000000 /* TCX frame buffer */
#define PHYS_JJ_ESPDMA 0x78400000 /* ESP DMA controller */
#define PHYS_JJ_ESP 0x78800000 /* ESP SCSI */
#define PHYS_JJ_ESP_IRQ 18
#define PHYS_JJ_LEDMA 0x78400010 /* Lance DMA controller */
#define PHYS_JJ_LE 0x78C00000 /* Lance ethernet */
#define PHYS_JJ_LE_IRQ 16
@ -50,7 +53,6 @@
#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
@ -61,32 +63,86 @@ uint64_t cpu_get_tsc()
return qemu_get_clock(vm_clock);
}
void DMA_run() {}
int DMA_get_channel_mode (int nchan)
{
return 0;
}
int DMA_read_memory (int nchan, void *buf, int pos, int size)
{
return 0;
}
int DMA_write_memory (int nchan, void *buf, int pos, int size)
{
return 0;
}
void DMA_hold_DREQ (int nchan) {}
void DMA_release_DREQ (int nchan) {}
void DMA_schedule(int nchan) {}
void DMA_run (void) {}
void DMA_init (int high_page_enable) {}
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
{
}
static void nvram_set_word (m48t08_t *nvram, uint32_t addr, uint16_t value)
{
m48t08_write(nvram, addr++, (value >> 8) & 0xff);
m48t08_write(nvram, addr++, value & 0xff);
}
static void nvram_set_lword (m48t08_t *nvram, uint32_t addr, uint32_t value)
{
m48t08_write(nvram, addr++, value >> 24);
m48t08_write(nvram, addr++, (value >> 16) & 0xff);
m48t08_write(nvram, addr++, (value >> 8) & 0xff);
m48t08_write(nvram, addr++, value & 0xff);
}
static void nvram_set_string (m48t08_t *nvram, uint32_t addr,
const unsigned char *str, uint32_t max)
{
unsigned int i;
for (i = 0; i < max && str[i] != '\0'; i++) {
m48t08_write(nvram, addr + i, str[i]);
}
m48t08_write(nvram, addr + max - 1, '\0');
}
static m48t08_t *nvram;
static void nvram_init(m48t08_t *nvram, uint8_t *macaddr, const char *cmdline)
extern int nographic;
static void nvram_init(m48t08_t *nvram, uint8_t *macaddr, const char *cmdline,
int boot_device, uint32_t RAM_size,
uint32_t kernel_size,
int width, int height, int depth)
{
unsigned char tmp = 0;
int i, j;
i = 0x40;
// Try to match PPC NVRAM
nvram_set_string(nvram, 0x00, "QEMU_BIOS", 16);
nvram_set_lword(nvram, 0x10, 0x00000001); /* structure v1 */
// NVRAM_size, arch not applicable
m48t08_write(nvram, 0x2F, nographic & 0xff);
nvram_set_lword(nvram, 0x30, RAM_size);
m48t08_write(nvram, 0x34, boot_device & 0xff);
nvram_set_lword(nvram, 0x38, KERNEL_LOAD_ADDR);
nvram_set_lword(nvram, 0x3C, kernel_size);
if (cmdline) {
uint32_t cmdline_len;
strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
m48t08_write(nvram, i++, CMDLINE_ADDR >> 24);
m48t08_write(nvram, i++, (CMDLINE_ADDR >> 16) & 0xff);
m48t08_write(nvram, i++, (CMDLINE_ADDR >> 8) & 0xff);
m48t08_write(nvram, i++, CMDLINE_ADDR & 0xff);
cmdline_len = strlen(cmdline);
m48t08_write(nvram, i++, cmdline_len >> 24);
m48t08_write(nvram, i++, (cmdline_len >> 16) & 0xff);
m48t08_write(nvram, i++, (cmdline_len >> 8) & 0xff);
m48t08_write(nvram, i++, cmdline_len & 0xff);
nvram_set_lword(nvram, 0x40, CMDLINE_ADDR);
nvram_set_lword(nvram, 0x44, strlen(cmdline));
}
// initrd_image, initrd_size passed differently
nvram_set_word(nvram, 0x54, width);
nvram_set_word(nvram, 0x56, height);
nvram_set_word(nvram, 0x58, depth);
// Sun4m specific use
i = 0x1fd8;
m48t08_write(nvram, i++, 0x01);
m48t08_write(nvram, i++, 0x80); /* Sun4m OBP */
@ -155,7 +211,7 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
char buf[1024];
int ret, linux_boot;
unsigned int i;
unsigned long vram_size = 0x100000, prom_offset, initrd_size;
long vram_size = 0x100000, prom_offset, initrd_size, kernel_size;
linux_boot = (kernel_filename != NULL);
@ -164,14 +220,14 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
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);
tcx = tcx_init(ds, PHYS_JJ_TCX_FB, phys_ram_base + ram_size, ram_size, vram_size, graphic_width, graphic_height);
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);
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline);
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);
esp_init(bs_table, PHYS_JJ_ESP_IRQ, PHYS_JJ_ESP, PHYS_JJ_ESPDMA);
prom_offset = ram_size + vram_size;
@ -189,13 +245,14 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
prom_offset | IO_MEM_ROM);
kernel_size = 0;
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) {
kernel_size = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0)
kernel_size = load_image(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
@ -222,4 +279,5 @@ void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
}
}
}
nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, kernel_cmdline, boot_device, ram_size, kernel_size, graphic_width, graphic_height, graphic_depth);
}

129
hw/tcx.c
View File

@ -1,7 +1,7 @@
/*
* QEMU Sun4m System Emulator
* QEMU TCX Frame buffer
*
* Copyright (c) 2003-2004 Fabrice Bellard
* Copyright (c) 2003-2005 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
@ -25,29 +25,16 @@
#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
#define TCX_DAC_NREGS 16
typedef struct TCXState {
uint32_t addr;
DisplayState *ds;
uint8_t *vram;
unsigned long vram_offset;
uint16_t width, height;
uint8_t r[256], g[256], b[256];
uint8_t dac_index, dac_state;
} TCXState;
static void tcx_draw_line32(TCXState *s1, uint8_t *d,
@ -58,9 +45,9 @@ static void tcx_draw_line32(TCXState *s1, uint8_t *d,
for(x = 0; x < width; x++) {
val = *s++;
*d++ = s1->r[val];
*d++ = s1->g[val];
*d++ = s1->b[val];
*d++ = s1->g[val];
*d++ = s1->r[val];
d++;
}
}
@ -73,9 +60,9 @@ static void tcx_draw_line24(TCXState *s1, uint8_t *d,
for(x = 0; x < width; x++) {
val = *s++;
*d++ = s1->r[val];
*d++ = s1->g[val];
*d++ = s1->b[val];
*d++ = s1->g[val];
*d++ = s1->r[val];
}
}
@ -104,12 +91,12 @@ void tcx_update_display(void *opaque)
if (ts->ds->depth == 0)
return;
page = ts->vram_offset + YOFF*MAXX;
page = ts->vram_offset;
y_start = -1;
page_min = 0x7fffffff;
page_max = -1;
d = ts->ds->data;
s = ts->vram + YOFF*MAXX + XOFF;
s = ts->vram;
dd = ts->ds->linesize;
ds = 1024;
@ -128,7 +115,7 @@ void tcx_update_display(void *opaque)
return;
}
for(y = 0; y < YSZ; y += 4, page += TARGET_PAGE_SIZE) {
for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
if (y_start < 0)
y_start = y;
@ -136,23 +123,23 @@ void tcx_update_display(void *opaque)
page_min = page;
if (page > page_max)
page_max = page;
f(ts, d, s, XSZ);
f(ts, d, s, ts->width);
d += dd;
s += ds;
f(ts, d, s, XSZ);
f(ts, d, s, ts->width);
d += dd;
s += ds;
f(ts, d, s, XSZ);
f(ts, d, s, ts->width);
d += dd;
s += ds;
f(ts, d, s, XSZ);
f(ts, d, s, ts->width);
d += dd;
s += ds;
} else {
if (y_start >= 0) {
/* flush to display */
dpy_update(ts->ds, 0, y_start,
XSZ, y - y_start);
ts->width, y - y_start);
y_start = -1;
}
d += dd * 4;
@ -162,7 +149,7 @@ void tcx_update_display(void *opaque)
if (y_start >= 0) {
/* flush to display */
dpy_update(ts->ds, 0, y_start,
XSZ, y - y_start);
ts->width, y - y_start);
}
/* reset modified pages */
if (page_max != -1) {
@ -187,9 +174,13 @@ static void tcx_save(QEMUFile *f, void *opaque)
qemu_put_be32s(f, (uint32_t *)&s->addr);
qemu_put_be32s(f, (uint32_t *)&s->vram);
qemu_put_be16s(f, (uint16_t *)&s->height);
qemu_put_be16s(f, (uint16_t *)&s->width);
qemu_put_buffer(f, s->r, 256);
qemu_put_buffer(f, s->g, 256);
qemu_put_buffer(f, s->b, 256);
qemu_put_8s(f, &s->dac_index);
qemu_put_8s(f, &s->dac_state);
}
static int tcx_load(QEMUFile *f, void *opaque, int version_id)
@ -201,9 +192,13 @@ static int tcx_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be32s(f, (uint32_t *)&s->addr);
qemu_get_be32s(f, (uint32_t *)&s->vram);
qemu_get_be16s(f, (uint16_t *)&s->height);
qemu_get_be16s(f, (uint16_t *)&s->width);
qemu_get_buffer(f, s->r, 256);
qemu_get_buffer(f, s->g, 256);
qemu_get_buffer(f, s->b, 256);
qemu_get_8s(f, &s->dac_index);
qemu_get_8s(f, &s->dac_state);
return 0;
}
@ -219,12 +214,66 @@ static void tcx_reset(void *opaque)
memset(s->vram, 0, MAXX*MAXY);
cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,
VGA_DIRTY_FLAG);
s->dac_index = 0;
s->dac_state = 0;
}
static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
{
return 0;
}
static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
TCXState *s = opaque;
uint32_t saddr;
saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;
switch (saddr) {
case 0:
s->dac_index = val >> 24;
s->dac_state = 0;
break;
case 1:
switch (s->dac_state) {
case 0:
s->r[s->dac_index] = val >> 24;
s->dac_state++;
break;
case 1:
s->g[s->dac_index] = val >> 24;
s->dac_state++;
break;
case 2:
s->b[s->dac_index] = val >> 24;
default:
s->dac_state = 0;
break;
}
break;
default:
break;
}
return;
}
static CPUReadMemoryFunc *tcx_dac_read[3] = {
tcx_dac_readl,
tcx_dac_readl,
tcx_dac_readl,
};
static CPUWriteMemoryFunc *tcx_dac_write[3] = {
tcx_dac_writel,
tcx_dac_writel,
tcx_dac_writel,
};
void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
unsigned long vram_offset, int vram_size)
unsigned long vram_offset, int vram_size, int width, int height)
{
TCXState *s;
int io_memory;
s = qemu_mallocz(sizeof(TCXState));
if (!s)
@ -233,13 +282,17 @@ void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
s->addr = addr;
s->vram = vram_base;
s->vram_offset = vram_offset;
s->width = width;
s->height = height;
cpu_register_physical_memory(addr, vram_size, vram_offset);
cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset);
io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory);
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);
dpy_resize(s->ds, width, height);
return s;
}
@ -253,11 +306,11 @@ void tcx_screen_dump(void *opaque, const char *filename)
f = fopen(filename, "wb");
if (!f)
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++) {
fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
d1 = s->vram;
for(y = 0; y < s->height; y++) {
d = d1;
for(x = 0; x < XSZ; x++) {
for(x = 0; x < s->width; x++) {
v = *d;
fputc(s->r[v], f);
fputc(s->g[v], f);

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -138,6 +138,7 @@ int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot
}
*access_index = ((rw & 1) << 2) | (rw & 2) | (is_user? 0 : 1);
*physical = 0xfffff000;
/* SPARC reference MMU table walk: Context table->L1->L2->PTE */
/* Context base + context number */
@ -210,7 +211,7 @@ int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot
/* check access */
access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
error_code = access_table[*access_index][access_perms];
if (error_code)
if (error_code && !(env->mmuregs[0] & MMU_NF))
return error_code;
/* the page can be put in the TLB */
@ -225,7 +226,7 @@ int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot
/* Even if large ptes, we map only one 4KB page in the cache to
avoid filling it too fast */
*physical = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
return 0;
return error_code;
}
/* Perform address translation */
@ -251,17 +252,14 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
env->mmuregs[4] = address; /* Fault address register */
if ((env->mmuregs[0] & MMU_NF) || env->psret == 0) {
#if 0
// No fault
// No fault mode: if a mapping is available, just override
// permissions. If no mapping is available, redirect accesses to
// neverland. Fake/overridden mappings will be flushed when
// switching to normal mode.
vaddr = address & TARGET_PAGE_MASK;
paddr = 0xfffff000;
prot = PAGE_READ | PAGE_WRITE;
ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
return ret;
#else
cpu_abort(env, "MMU no fault case no handled");
return 0;
#endif
} else {
if (rw & 2)
env->exception_index = TT_TFAULT;
@ -316,8 +314,8 @@ void do_interrupt(int intno)
count, intno,
env->pc,
env->npc, env->regwptr[6]);
#if 1
cpu_dump_state(env, logfile, fprintf, 0);
#if 0
{
int i;
uint8_t *ptr;

View File

@ -164,7 +164,9 @@ void helper_st_asi(int asi, int size, int sign)
case 0:
env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
if ((oldreg & MMU_E) != (env->mmuregs[reg] & MMU_E))
// Mappings generated during no-fault mode or MMU
// disabled mode are invalid in normal mode
if (oldreg != env->mmuregs[reg])
tlb_flush(env, 1);
break;
case 2:

10
vl.c
View File

@ -2733,7 +2733,9 @@ void help(void)
"-full-screen start in full screen\n"
#ifdef TARGET_PPC
"-prep Simulate a PREP system (default is PowerMAC)\n"
"-g WxH[xDEPTH] Set the initial VGA graphic mode\n"
#endif
#if defined(TARGET_PPC) || defined(TARGET_SPARC)
"-g WxH[xDEPTH] Set the initial graphical resolution and depth\n"
#endif
"\n"
"Network options:\n"
@ -2916,6 +2918,8 @@ const QEMUOption qemu_options[] = {
#endif
#ifdef TARGET_PPC
{ "prep", 0, QEMU_OPTION_prep },
#endif
#if defined(TARGET_PPC) || defined(TARGET_SPARC)
{ "g", 1, QEMU_OPTION_g },
#endif
{ "localtime", 0, QEMU_OPTION_localtime },
@ -3179,6 +3183,10 @@ int main(int argc, char **argv)
case QEMU_OPTION_boot:
boot_device = optarg[0];
if (boot_device != 'a' &&
#ifdef TARGET_SPARC
// Network boot
boot_device != 'n' &&
#endif
boot_device != 'c' && boot_device != 'd') {
fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
exit(1);

5
vl.h
View File

@ -714,7 +714,7 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
/* tcx.c */
void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
unsigned long vram_offset, int vram_size);
unsigned long vram_offset, int vram_size, int width, int height);
void tcx_update_display(void *opaque);
void tcx_invalidate_display(void *opaque);
void tcx_screen_dump(void *opaque, const char *filename);
@ -736,6 +736,9 @@ void slavio_timer_init(uint32_t addr1, int irq1, uint32_t addr2, int irq2);
SerialState *slavio_serial_init(int base, int irq, CharDriverState *chr1, CharDriverState *chr2);
void slavio_serial_ms_kbd_init(int base, int irq);
/* esp.c */
void esp_init(BlockDriverState **bd, int irq, uint32_t espaddr, uint32_t espdaddr);
/* NVRAM helpers */
#include "hw/m48t59.h"