mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 11:23:43 +08:00
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:
parent
b756921ad1
commit
6f7e9aec5e
@ -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
1
TODO
@ -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
192
hw/esp.c
Normal 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);
|
||||
}
|
||||
|
37
hw/fdc.c
37
hw/fdc.c
@ -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 ||
|
||||
|
110
hw/sun4m.c
110
hw/sun4m.c
@ -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
129
hw/tcx.c
@ -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.
1545
pc-bios/proll.patch
1545
pc-bios/proll.patch
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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
10
vl.c
@ -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
5
vl.h
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user