summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.target2
-rw-r--r--TODO1
-rw-r--r--hw/esp.c192
-rw-r--r--hw/fdc.c37
-rw-r--r--hw/sun4m.c110
-rw-r--r--hw/tcx.c129
-rw-r--r--pc-bios/proll.elfbin133338 -> 41236 bytes
-rw-r--r--pc-bios/proll.patch1545
-rw-r--r--target-sparc/helper.c18
-rw-r--r--target-sparc/op_helper.c4
-rw-r--r--vl.c10
-rw-r--r--vl.h5
12 files changed, 1564 insertions, 489 deletions
diff --git a/Makefile.target b/Makefile.target
index 5c82e38a6..68563299e 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -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
diff --git a/TODO b/TODO
index cd3895054..088c26c69 100644
--- a/TODO
+++ b/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)
diff --git a/hw/esp.c b/hw/esp.c
new file mode 100644
index 000000000..2456c345f
--- /dev/null
+++ b/hw/esp.c
@@ -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);
+}
+
diff --git a/hw/fdc.c b/hw/fdc.c
index fc6b50257..3890ace12 100644
--- a/hw/fdc.c
+++ b/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 ||
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 0af062d96..b186b23f1 100644
--- a/hw/sun4m.c
+++ b/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);
}
diff --git a/hw/tcx.c b/hw/tcx.c
index 6c4df7c89..c0fddf31d 100644
--- a/hw/tcx.c
+++ b/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);
diff --git a/pc-bios/proll.elf b/pc-bios/proll.elf
index e274b0d19..f960c83e6 100644
--- a/pc-bios/proll.elf
+++ b/pc-bios/proll.elf
Binary files differ
diff --git a/pc-bios/proll.patch b/pc-bios/proll.patch
index 18a157512..5f2e027d4 100644
--- a/pc-bios/proll.patch
+++ b/pc-bios/proll.patch
@@ -1,6 +1,6 @@
-diff -ruN proll_18.orig/Makefile proll-patch4/Makefile
+diff -ruN proll_18.orig/Makefile proll-patch7/Makefile
--- proll_18.orig/Makefile 2002-09-13 14:16:59.000000000 +0000
-+++ proll-patch4/Makefile 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/Makefile 2004-11-13 15:50:49.000000000 +0000
@@ -4,6 +4,7 @@
make -C krups-ser all
make -C espresso all
@@ -14,17 +14,143 @@ diff -ruN proll_18.orig/Makefile proll-patch4/Makefile
make -C espresso clean
make -C espresso-ser clean
+ make -C qemu clean
-diff -ruN proll_18.orig/qemu/head.S proll-patch4/qemu/head.S
+diff -ruN proll_18.orig/qemu/Makefile proll-patch7/qemu/Makefile
+--- proll_18.orig/qemu/Makefile 1970-01-01 00:00:00.000000000 +0000
++++ proll-patch7/qemu/Makefile 2005-03-02 16:41:50.000000000 +0000
+@@ -0,0 +1,122 @@
++#
++# proll:
++# qemu/Makefile - make PROLL for QEMU
++# $Id: proll.patch,v 1.3 2005-03-13 09:43:36 bellard Exp $
++#
++# Copyright 1999 Pete Zaitcev
++# This is Free Software is licensed under terms of GNU General Public License.
++#
++
++CC = gcc
++
++#CROSS = /usr/local/sparc/bin/sparc-sun-linux-
++CROSS = sparc-unknown-linux-gnu-
++
++CROSSCC = $(CROSS)gcc
++CROSSLD = $(CROSS)ld
++CROSSNM = $(CROSS)nm
++
++RM = /bin/rm -f
++ELFTOAOUT = elftoaout
++
++#
++SRC = ../src
++
++# Due to remapping algorithm PROLBASE should be algned on PMD.
++# We make PROLBASE a define instead of using _start because we
++# want to shift it to form a PGD entry. A relocatable label will not work.
++# Linux kernel expects us to be at LINUX_OPPROM_BEGVM <asm-sparc/openprom.h>.
++PROLBASE = 0xffd00000
++PROLRODATA = 0xffd07000
++PROLDATA = 0xffd09000
++PROLSIZE = 240*1024
++
++# Linux
++# Fixed %g6 is for arch/sparc/kernel/head.S, it seems ok w/o -ffixed-g6.
++# Kernel uses -fcall-used-g5 -fcall-used-g7, we probably do not need them.
++# __ANSI__ is supposed to be on by default but it is not.
++CFLAGS = -O2 -Wall -DPROLBASE=$(PROLBASE) -DPROLDATA=$(PROLDATA) -DPROLRODATA=$(PROLRODATA) -D__ANSI__=1 -I$(SRC) -mcpu=hypersparc -g -DQEMU
++ASFLAGS = -D__ASSEMBLY__ -I$(SRC) -DPROLRODATA=$(PROLRODATA) -DPROLDATA=$(PROLDATA) -DPROLSIZE=$(PROLSIZE) -g
++# Solaris or Linux/i386 cross compilation
++#CFLAGS = -Iinclude -O
++
++LDFLAGS = -N -Ttext $(PROLBASE) --section-start .rodata=$(PROLRODATA) -Tdata $(PROLDATA) -Tbss $(PROLDATA)
++
++ALL = proll.aout
++PROLLEXE = proll.elf
++
++OBJS = head.o wuf.o wof.o main.o $(CONSOLE) \
++ printf.o le.o system_qemu.o iommu.o \
++ arp.o netinit.o bootp.o packet.o tftp.o udp.o sched_4m.o openprom.o \
++ vconsole.o hconsole.o rconsole.o vcons_zs.o
++
++all: $(ALL)
++
++$(PROLLEXE): $(OBJS)
++ $(CROSSLD) $(LDFLAGS) -o $(PROLLEXE) $(OBJS)
++
++head.o: head.S $(SRC)/phys_jj.h \
++ $(SRC)/asi.h $(SRC)/psr.h $(SRC)/crs.h
++ $(CROSSCC) $(ASFLAGS) -DPROLBASE=$(PROLBASE) -o $*.o -c $*.S
++
++main.o: main.c $(SRC)/asi.h $(SRC)/pgtsrmmu.h $(SRC)/iommu.h \
++ $(SRC)/phys_jj.h $(SRC)/vconsole.h $(SRC)/version.h $(SRC)/general.h \
++ $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h
++ $(CROSSCC) $(CFLAGS) -c $*.c
++openprom.o: openprom.c $(SRC)/openprom.h $(SRC)/general.h $(SRC)/romlib.h \
++ $(SRC)/vconsole.h $(SRC)/system.h $(SRC)/phys_jj.h
++ $(CROSSCC) $(CFLAGS) -c $*.c
++
++system_qemu.o: system_qemu.c $(SRC)/vconsole.h $(SRC)/pgtsrmmu.h \
++ $(SRC)/timer.h $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/asi.h \
++ $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h $(SRC)/crs.h
++ $(CROSSCC) $(CFLAGS) -c $*.c
++iommu.o: $(SRC)/iommu.c $(SRC)/pgtsrmmu.h $(SRC)/phys_jj.h $(SRC)/iommu.h \
++ $(SRC)/vconsole.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/asi.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++vconsole.o: $(SRC)/vconsole.c $(SRC)/vconsole.h $(SRC)/hconsole.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++vcons_zs.o: $(SRC)/vcons_zs.c $(SRC)/vconsole.h $(SRC)/system.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++hconsole.o: $(SRC)/hconsole.c $(SRC)/hconsole.h $(SRC)/rconsole.h $(SRC)/phys_jj.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++rconsole.o: $(SRC)/rconsole.c $(SRC)/rconsole.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++printf.o: $(SRC)/printf.c
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++le.o: $(SRC)/le.c $(SRC)/dma.h $(SRC)/system.h $(SRC)/netpriv.h $(SRC)/romlib.h $(SRC)/general.h $(SRC)/net.h $(SRC)/phys_jj.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++
++arp.o: $(SRC)/arp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++netinit.o: $(SRC)/netinit.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++tftp.o: $(SRC)/tftp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/tftp.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++udp.o: $(SRC)/udp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++packet.o: $(SRC)/packet.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++sched_4m.o: $(SRC)/sched_4m.c $(SRC)/system.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/phys_jj.h
++ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
++bootp.o: $(SRC)/bootp.c $(SRC)/general.h $(SRC)/net.h \
++ $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/bootp.h
++ $(CROSSCC) $(CFLAGS) -DNOBPEXT=1 -c $(SRC)/$*.c
++
++wuf.o: $(SRC)/wuf.S
++ $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
++wof.o: $(SRC)/wof.S
++ $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
++
++#genlab.o: genlab.c
++# $(CC) -c $*.c
++#
++#genlab: genlab.o
++# $(CC) -o genlab genlab.o
++
++clean:
++ $(RM) $(OBJS)
++ $(RM) $(PROLLEXE) proll.aout
++
++proll.aout: $(PROLLEXE)
++ $(ELFTOAOUT) -o proll.aout $(PROLLEXE)
+diff -ruN proll_18.orig/qemu/head.S proll-patch7/qemu/head.S
--- proll_18.orig/qemu/head.S 1970-01-01 00:00:00.000000000 +0000
-+++ proll-patch4/qemu/head.S 2004-11-13 15:50:49.000000000 +0000
-@@ -0,0 +1,515 @@
++++ proll-patch7/qemu/head.S 2005-03-02 15:30:47.000000000 +0000
+@@ -0,0 +1,539 @@
+/**
+ ** Standalone startup code for Linux PROM emulator.
+ ** Copyright 1999 Pete A. Zaitcev
+ ** This code is licensed under GNU General Public License.
+ **/
+/*
-+ * $Id: proll.patch,v 1.2 2004-12-19 23:18:01 bellard Exp $
++ * $Id: proll.patch,v 1.3 2005-03-13 09:43:36 bellard Exp $
+ */
+
+#include <psr.h>
@@ -167,6 +293,31 @@ diff -ruN proll_18.orig/qemu/head.S proll-patch4/qemu/head.S
+_start:
+start:
+ .globl spill_window_entry, fill_window_entry
++
++#define EXPORT_TRAP(trap) \
++ .globl trap; \
++ .type trap,function; \
++ .size trap, 16
++
++EXPORT_TRAP(t_zero)
++EXPORT_TRAP(t_wovf)
++EXPORT_TRAP(t_wunf)
++EXPORT_TRAP(t_irq1)
++EXPORT_TRAP(t_irq2)
++EXPORT_TRAP(t_irq3)
++EXPORT_TRAP(t_irq4)
++EXPORT_TRAP(t_irq5)
++EXPORT_TRAP(t_irq6)
++EXPORT_TRAP(t_irq7)
++EXPORT_TRAP(t_irq8)
++EXPORT_TRAP(t_irq9)
++EXPORT_TRAP(t_irq10)
++EXPORT_TRAP(t_irq11)
++EXPORT_TRAP(t_irq12)
++EXPORT_TRAP(t_irq13)
++EXPORT_TRAP(t_irq14)
++EXPORT_TRAP(t_irq15)
++
+C_LABEL(trapbase):
+t_zero: b goprol; nop; nop; nop;
+t_tflt: SRMMU_TFAULT /* Inst. Access Exception */
@@ -294,6 +445,8 @@ diff -ruN proll_18.orig/qemu/head.S proll-patch4/qemu/head.S
+
+goprol:
+ ! %g1 contains end of memory
++ set PHYS_JJ_EEPROM + 0x30, %g1
++ lda [%g1] ASI_M_BYPASS, %g1
+ ! map PROLDATA to PROLBASE+PROLSIZE to end of ram
+ set PROLSIZE+0x1000-PROLDATA+PROLBASE, %g2 ! add 0x1000 for temp tables
+ sub %g1, %g2, %g2 ! start of private memory
@@ -397,9 +550,6 @@ diff -ruN proll_18.orig/qemu/head.S proll-patch4/qemu/head.S
+ bl 1b
+ add %o0, 0x4, %o0
+
-+ sethi %hi( C_LABEL(ram_size) ), %o0
-+ st %g3, [%o0 + %lo( C_LABEL(ram_size) )]
-+
+ mov 2, %g1
+ wr %g1, 0x0, %wim ! make window 1 invalid
+ WRITE_PAUSE
@@ -533,10 +683,10 @@ diff -ruN proll_18.orig/qemu/head.S proll-patch4/qemu/head.S
+C_LABEL(ldb_bypass):
+ retl
+ lduba [%o0] ASI_M_BYPASS, %o0
-diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+diff -ruN proll_18.orig/qemu/main.c proll-patch7/qemu/main.c
--- proll_18.orig/qemu/main.c 1970-01-01 00:00:00.000000000 +0000
-+++ proll-patch4/qemu/main.c 2004-11-23 19:05:34.000000000 +0000
-@@ -0,0 +1,178 @@
++++ proll-patch7/qemu/main.c 2005-03-02 20:08:23.000000000 +0000
+@@ -0,0 +1,173 @@
+/**
+ ** Proll (PROM replacement)
+ ** Copyright 1999 Pete Zaitcev
@@ -558,8 +708,11 @@ diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+#include <arpa.h>
+#include <system.h> /* our own prototypes */
+
++void *init_openprom_qemu(int bankc, struct bank *bankv, unsigned hiphybas, const char *cmdline, char boot_device, int nographic);
++int vcon_zs_init(struct vconterm *t, unsigned int a0);
++int vcon_zs_write(struct vconterm *t, char *data, int leng);
++
+static void init_idprom(void);
-+static void makepages_q(struct phym *t, unsigned int highbase);
+
+struct vconterm dp0;
+struct mem cmem; /* Current memory, virtual */
@@ -567,20 +720,48 @@ diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+struct phym pmem; /* Current phys. mem. */
+struct iommu ciommu; /* Our IOMMU on sun4m */
+
-+static char *hw_idprom;
-+int ignore_fault, fault_ignored, ram_size;
++static struct {
++ const char id[16];
++ unsigned int version;
++ char pad1[0x1c]; // Pad to 0x30
++ unsigned int ram_size;
++ char boot_device;
++ unsigned int load_addr, kernel_size;
++ unsigned int cmdline, cmdline_len;
++ char pad2[0x0c]; // Pad to 0x54
++ unsigned short width, height, depth;
++} *hw_idprom;
++
++int ignore_fault, fault_ignored;
++void *printk_fn;
++unsigned int q_height, q_width;
+
+/*
+ */
+void prolmain()
+{
-+ //static const char fname[14] = "00000000.PROL";
++ static char fname[14];
+ static struct banks bb;
+ unsigned int hiphybas;
+ const void *romvec;
++ unsigned int ram_size;
++ char nographic;
++
++ nographic = ldb_bypass(PHYS_JJ_EEPROM + 0x2F);
++ if (!nographic) {
++ q_width = ldh_bypass(PHYS_JJ_EEPROM + 0x54);
++ q_height = ldh_bypass(PHYS_JJ_EEPROM + 0x56);
++ vcon_init(&dp0, PHYS_JJ_TCX_FB);
++ printk_fn = vcon_write;
++ }
++ else {
++ vcon_zs_init(&dp0, 0x71100000);
++ printk_fn = vcon_zs_write;
++ }
++
+
-+ vcon_init(&dp0, PHYS_JJ_TCX_FB);
+ printk("PROLL %s QEMU\n", PROLL_VERSION_STRING);
++ ram_size = ld_bypass(PHYS_JJ_EEPROM + 0x30);
+ printk("%d MB total\n", ram_size/(1024*1024));
+
+ bb.nbanks = 1;
@@ -590,7 +771,7 @@ diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+ hiphybas = ram_size - PROLSIZE;
+
+ mem_init(&cmem, (char *) &_end, (char *)(PROLBASE+PROLSIZE));
-+ makepages_q(&pmem, hiphybas);
++ makepages(&pmem, hiphybas);
+ init_mmu_swift((unsigned int)pmem.pctp - PROLBASE + hiphybas);
+
+ mem_init(&cio, (char *)(PROLBASE+PROLSIZE),
@@ -601,38 +782,46 @@ diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+ /*
+ */
+ init_idprom();
++ printk("NVRAM: id %s version %d\n", hw_idprom->id, hw_idprom->version);
++ if (!nographic)
++ printk("Prom console: TCX %dx%d\n", q_width, q_height);
++ else
++ printk("Prom console: serial\n");
+ sched_init();
+ le_probe();
+ init_net();
+
-+#if 0
-+#if 0 /* RARP */
-+ if (rarp() != 0) fatal();
-+ /* printrarp(); */
-+ xtoa(myipaddr, fname, 8);
-+ if (load(servaddr, fname) != 0) fatal();
-+#else
-+ if (bootp() != 0) fatal();
-+ /*
-+ * boot_rec.bp_file cannot be used because system PROM
-+ * uses it to locate ourselves. If we load from boot_rec.bp_file,
-+ * we will loop reloading PROLL over and over again.
-+ * Thus we use traditional PROLL scheme HEXIPADDR.PROL (single L).
-+ */
-+ xtoa(myipaddr, fname, 8);
-+ if (load(boot_rec.bp_siaddr, fname) != 0) fatal();
-+#endif
-+#endif
++ printk("Boot device: %c\n", hw_idprom->boot_device);
++ if (hw_idprom->boot_device == 'n') {
++ if (bootp() != 0) fatal();
++ /*
++ * boot_rec.bp_file cannot be used because system PROM
++ * uses it to locate ourselves. If we load from boot_rec.bp_file,
++ * we will loop reloading PROLL over and over again.
++ * Thus we use traditional PROLL scheme HEXIPADDR.PROL (single L).
++ */
++ xtoa(myipaddr, fname, 8);
++ fname[9] = '.';
++ fname[10] = 'P';
++ fname[11] = 'R';
++ fname[12] = 'O';
++ fname[13] = 'L';
++ fname[14] = 0;
++
++ if (load(boot_rec.bp_siaddr, fname) != 0) fatal();
++ }
+
-+ romvec = init_openprom(bb.nbanks, bb.bankv, hiphybas);
++ romvec = init_openprom_qemu(bb.nbanks, bb.bankv, hiphybas,
++ (void *)hw_idprom->cmdline, hw_idprom->boot_device, nographic);
+
+ printk("Memory used: virt 0x%x:0x%x[%dK] iomap 0x%x:0x%x\n",
+ PROLBASE, (int)cmem.curp, ((unsigned) cmem.curp - PROLBASE)/1024,
+ (int)cio.start, (int)cio.curp);
-+ //set_timeout(5); while (!chk_timeout()) { } /* P3: let me read */
+
+ {
-+ void (*entry)(const void *, int, int, int, int) = (void (*)(const void*, int, int, int, int)) LOADBASE;
++ void (*entry)(const void *, int, int, int, int) = (void *) hw_idprom->load_addr;
++ printk("Kernel loaded at 0x%x, size %dK, command line = '%s'\n",
++ *entry, hw_idprom->kernel_size/1024, hw_idprom->cmdline);
+ entry(romvec, 0, 0, 0, 0);
+ }
+
@@ -652,14 +841,12 @@ diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+ */
+void udelay(unsigned long usecs)
+{
-+ int i, n;
-+ n = usecs*50;
-+ for (i = 0; i < n; i++) { }
++ // Qemu hardware is perfect and does not need any delays!
+}
+
+static void init_idprom()
+{
-+ char *va_prom;
++ void *va_prom;
+
+ if ((va_prom = map_io(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE)) == NULL) {
+ printk("init_idprom: cannot map eeprom\n");
@@ -673,175 +860,10 @@ diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c
+ hw_idprom = va_prom;
+}
+
-+/*
-+ * Make CPU page tables.
-+ * Returns pointer to context table.
-+ * Here we ignore memory allocation errors which "should not happen"
-+ * because we cannot print anything anyways if memory initialization fails.
-+ */
-+void makepages_q(struct phym *t, unsigned int highbase)
-+{
-+ unsigned int *ctp, *l1, pte;
-+ int i;
-+ unsigned int pa, va;
-+
-+ ctp = mem_zalloc(&cmem, NCTX_SWIFT*sizeof(int), NCTX_SWIFT*sizeof(int));
-+ l1 = mem_zalloc(&cmem, 256*sizeof(int), 256*sizeof(int));
-+
-+ pte = SRMMU_ET_PTD | (((unsigned int)l1 - PROLBASE + highbase) >> 4);
-+ for (i = 0; i < NCTX_SWIFT; i++) {
-+ ctp[i] = pte;
-+ }
-+
-+ pa = PROLBASE;
-+ for (va = PROLBASE; va < PROLDATA; va += PAGE_SIZE) {
-+ map_page(l1, va, pa, 0, highbase);
-+ pa += PAGE_SIZE;
-+ }
-+ pa = highbase + PROLDATA - PROLBASE;
-+ for (va = PROLDATA; va < PROLBASE + PROLSIZE; va += PAGE_SIZE) {
-+ map_page(l1, va, pa, 0, highbase);
-+ pa += PAGE_SIZE;
-+ }
-+
-+ /* We need to start from LOADBASE, but kernel wants PAGE_SIZE. */
-+ pa = 0;
-+ for (va = 0; va < LOWMEMSZ; va += PAGE_SIZE) {
-+ map_page(l1, va, pa, 0, highbase);
-+ pa += PAGE_SIZE;
-+ }
-+
-+ t->pctp = ctp;
-+ t->pl1 = l1;
-+ t->pbas = highbase;
-+}
-diff -ruN proll_18.orig/qemu/Makefile proll-patch4/qemu/Makefile
---- proll_18.orig/qemu/Makefile 1970-01-01 00:00:00.000000000 +0000
-+++ proll-patch4/qemu/Makefile 2004-11-13 15:50:49.000000000 +0000
-@@ -0,0 +1,119 @@
-+#
-+# proll:
-+# qemu/Makefile - make PROLL for QEMU
-+# $Id: proll.patch,v 1.2 2004-12-19 23:18:01 bellard Exp $
-+#
-+# Copyright 1999 Pete Zaitcev
-+# This is Free Software is licensed under terms of GNU General Public License.
-+#
-+
-+CC = gcc
-+
-+#CROSS = /usr/local/sparc/bin/sparc-sun-linux-
-+CROSS = sparc-unknown-linux-gnu-
-+
-+CROSSCC = $(CROSS)gcc
-+CROSSLD = $(CROSS)ld
-+CROSSNM = $(CROSS)nm
-+
-+RM = /bin/rm -f
-+ELFTOAOUT = elftoaout
-+
-+#
-+SRC = ../src
-+
-+# Due to remapping algorithm PROLBASE should be algned on PMD.
-+# We make PROLBASE a define instead of using _start because we
-+# want to shift it to form a PGD entry. A relocatable label will not work.
-+# Linux kernel expects us to be at LINUX_OPPROM_BEGVM <asm-sparc/openprom.h>.
-+PROLBASE = 0xffd00000
-+PROLRODATA = 0xffd07000
-+PROLDATA = 0xffd09000
-+PROLSIZE = (240*1024)
-+
-+# Linux
-+# Fixed %g6 is for arch/sparc/kernel/head.S, it seems ok w/o -ffixed-g6.
-+# Kernel uses -fcall-used-g5 -fcall-used-g7, we probably do not need them.
-+# __ANSI__ is supposed to be on by default but it is not.
-+CFLAGS = -O2 -Wall -DPROLBASE=$(PROLBASE) -DPROLDATA=$(PROLDATA) -DPROLRODATA=$(PROLRODATA) -D__ANSI__=1 -I$(SRC) -mcpu=hypersparc -g
-+ASFLAGS = -D__ASSEMBLY__ -I$(SRC) -DPROLRODATA=$(PROLRODATA) -DPROLDATA=$(PROLDATA) -DPROLSIZE=$(PROLSIZE) -g
-+# Solaris or Linux/i386 cross compilation
-+#CFLAGS = -Iinclude -O
-+
-+LDFLAGS = -N -Ttext $(PROLBASE) --section-start .rodata=$(PROLRODATA) -Tdata $(PROLDATA) -Tbss $(PROLDATA)
-+
-+ALL = proll.aout
-+PROLLEXE = proll.elf
-+
-+OBJS = head.o wuf.o wof.o main.o vconsole.o hconsole.o rconsole.o \
-+ printf.o le.o system.o iommu.o \
-+ arp.o netinit.o bootp.o packet.o tftp.o udp.o sched_4m.o openprom.o
-+
-+all: $(ALL)
-+
-+$(PROLLEXE): $(OBJS)
-+ $(CROSSLD) $(LDFLAGS) -o $(PROLLEXE) $(OBJS)
-+
-+head.o: head.S $(SRC)/phys_jj.h \
-+ $(SRC)/asi.h $(SRC)/psr.h $(SRC)/crs.h
-+ $(CROSSCC) $(ASFLAGS) -DPROLBASE=$(PROLBASE) -o $*.o -c $*.S
-+
-+main.o: main.c $(SRC)/asi.h $(SRC)/pgtsrmmu.h $(SRC)/iommu.h \
-+ $(SRC)/phys_jj.h $(SRC)/vconsole.h $(SRC)/version.h $(SRC)/general.h \
-+ $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h
-+ $(CROSSCC) $(CFLAGS) -c $*.c
-+openprom.o: openprom.c $(SRC)/openprom.h $(SRC)/general.h $(SRC)/romlib.h \
-+ $(SRC)/vconsole.h $(SRC)/system.h $(SRC)/phys_jj.h
-+ $(CROSSCC) $(CFLAGS) -c $*.c
-+
-+system.o: $(SRC)/system.c $(SRC)/vconsole.h $(SRC)/pgtsrmmu.h \
-+ $(SRC)/timer.h $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/asi.h \
-+ $(SRC)/netpriv.h $(SRC)/arpa.h $(SRC)/system.h $(SRC)/crs.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+iommu.o: $(SRC)/iommu.c $(SRC)/pgtsrmmu.h $(SRC)/phys_jj.h $(SRC)/iommu.h \
-+ $(SRC)/vconsole.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/asi.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+vconsole.o: $(SRC)/vconsole.c $(SRC)/vconsole.h $(SRC)/hconsole.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+hconsole.o: $(SRC)/hconsole.c $(SRC)/hconsole.h $(SRC)/rconsole.h $(SRC)/phys_jj.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+rconsole.o: $(SRC)/rconsole.c $(SRC)/rconsole.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+printf.o: $(SRC)/printf.c
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+le.o: $(SRC)/le.c $(SRC)/dma.h $(SRC)/system.h $(SRC)/netpriv.h $(SRC)/romlib.h $(SRC)/general.h $(SRC)/net.h $(SRC)/phys_jj.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+
-+arp.o: $(SRC)/arp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+netinit.o: $(SRC)/netinit.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+tftp.o: $(SRC)/tftp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/tftp.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+udp.o: $(SRC)/udp.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h $(SRC)/arp.h $(SRC)/ip.h $(SRC)/udp.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+packet.o: $(SRC)/packet.c $(SRC)/general.h $(SRC)/net.h $(SRC)/romlib.h $(SRC)/netpriv.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+sched_4m.o: $(SRC)/sched_4m.c $(SRC)/system.h $(SRC)/general.h $(SRC)/romlib.h $(SRC)/phys_jj.h
-+ $(CROSSCC) $(CFLAGS) -c $(SRC)/$*.c
-+bootp.o: $(SRC)/bootp.c $(SRC)/general.h $(SRC)/net.h \
-+ $(SRC)/arpa.h $(SRC)/romlib.h $(SRC)/system.h $(SRC)/bootp.h
-+ $(CROSSCC) $(CFLAGS) -DNOBPEXT=1 -c $(SRC)/$*.c
-+
-+wuf.o: $(SRC)/wuf.S
-+ $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
-+wof.o: $(SRC)/wof.S
-+ $(CROSSCC) $(ASFLAGS) -o $*.o -c $(SRC)/$*.S
-+
-+#genlab.o: genlab.c
-+# $(CC) -c $*.c
-+#
-+#genlab: genlab.o
-+# $(CC) -o genlab genlab.o
-+
-+clean:
-+ $(RM) $(OBJS)
-+ $(RM) $(PROLLEXE) proll.aout
-+
-+proll.aout: $(PROLLEXE)
-+ $(ELFTOAOUT) -o proll.aout $(PROLLEXE)
-diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+diff -ruN proll_18.orig/qemu/openprom.c proll-patch7/qemu/openprom.c
--- proll_18.orig/qemu/openprom.c 1970-01-01 00:00:00.000000000 +0000
-+++ proll-patch4/qemu/openprom.c 2004-11-23 19:14:05.000000000 +0000
-@@ -0,0 +1,596 @@
++++ proll-patch7/qemu/openprom.c 2005-03-02 20:09:57.000000000 +0000
+@@ -0,0 +1,646 @@
+/*
+ * PROM interface support
+ * Copyright 1996 The Australian National University.
@@ -858,6 +880,8 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+#include <vconsole.h>
+#include "phys_jj.h"
+
++//#define DEBUG_OBP
++
+struct property {
+ const char *name;
+ const char *value;
@@ -908,6 +932,7 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+static const struct property propv_sbus[] = {
+ {"name", "sbus", 5},
+ {"ranges", (char*)&prop_sbus_ranges[0], sizeof(prop_sbus_ranges)},
++ {"device_type", "hierarchical", sizeof("hierarchical") },
+ {NULL, NULL, -1}
+};
+
@@ -1005,6 +1030,7 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+static const struct property propv_obio[] = {
+ {"name", "obio", 5 },
+ {"ranges", (char*)&prop_obio_ranges[0], sizeof(prop_obio_ranges) },
++ {"device_type", "hierarchical", sizeof("hierarchical") },
+ {NULL, NULL, -1}
+};
+
@@ -1056,29 +1082,35 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+ {NULL, NULL, -1}
+};
+
-+static const int prop_zs_intr[] = { 0x26, 0x0 };
++static const int prop_zs_intr[] = { 12, 0x0 };
+static const int prop_zs_reg[] = {
-+ 0x4, 0x00000000, 0x0000000f,
++ 0x0, 0x00000000, 0x00000008,
+};
-+static const int prop_zs_slave[] = { 0x1 };
++static const int prop_zs_addr = { 0x70000000 };
++static const int prop_zs_slave[] = { 1 };
+static const struct property propv_obio_zs[] = {
+ {"name", "zs", sizeof("zs")},
+ {"reg", (char*)&prop_zs_reg[0], sizeof(prop_zs_reg) },
-+ {"reg", (char*)&prop_zs_slave[0], sizeof(prop_zs_slave) },
++ {"slave", (char*)&prop_zs_slave[0], sizeof(prop_zs_slave) },
+ {"device_type", "serial", sizeof("serial") },
++ {"intr", (char*)&prop_zs_intr[0], sizeof(prop_zs_intr) },
++ // {"address", (char*)&prop_zs_addr, sizeof(prop_zs_addr) },
+ {NULL, NULL, -1}
+};
+
-+static const int prop_zs1_intr[] = { 0x26, 0x0 };
++static const int prop_zs1_intr[] = { 12, 0x0 };
+static const int prop_zs1_reg[] = {
-+ 0x4, 0x00100000, 0x0000000f,
++ 0x0, 0x00100000, 0x00000008,
+};
-+static const int prop_zs1_slave[] = { 0x0 };
++static const int prop_zs1_addr = { 0x70100000 };
++static const int prop_zs1_slave[] = { 0 };
+static const struct property propv_obio_zs1[] = {
+ {"name", "zs", sizeof("zs")},
+ {"reg", (char*)&prop_zs1_reg[0], sizeof(prop_zs1_reg) },
-+ {"reg", (char*)&prop_zs1_slave[0], sizeof(prop_zs1_slave) },
++ {"slave", (char*)&prop_zs1_slave[0], sizeof(prop_zs1_slave) },
+ {"device_type", "serial", sizeof("serial") },
++ {"intr", (char*)&prop_zs1_intr[0], sizeof(prop_zs1_intr) },
++ // {"address", (char*)&prop_zs1_addr, sizeof(prop_zs1_addr) },
+ {NULL, NULL, -1}
+};
+
@@ -1106,24 +1138,110 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+ {NULL, NULL, -1}
+};
+
++static const int prop_espdma_reg[] = {
++ 0x4, 0x08400000, 0x00000010,
++};
++// Disabled, not implemented yet
++static const struct property propv_sbus_espdma[] = {
++ {"name", "xxxespdma", sizeof("xxxespdma")},
++ {"reg", (char*)&prop_espdma_reg[0], sizeof(prop_espdma_reg) },
++ {NULL, NULL, -1}
++};
++
++static const int prop_esp_reg[] = {
++ 0x4, 0x08800000, 0x00000040,
++};
++static const int prop_esp_intr[] = { 0x24, 0x0 };
++static const struct property propv_sbus_espdma_esp[] = {
++ {"name", "esp", sizeof("esp")},
++ {"reg", (char*)&prop_esp_reg[0], sizeof(prop_esp_reg) },
++ {"intr", (char*)&prop_esp_intr[0], sizeof(prop_esp_intr) },
++ {NULL, NULL, -1}
++};
++
++static const int prop_bpp_reg[] = {
++ 0x4, 0x0c800000, 0x0000001c,
++};
++static const int prop_bpp_intr[] = { 0x33, 0x0 };
++static const struct property propv_sbus_bpp[] = {
++ {"name", "SUNW,bpp", sizeof("SUNW,bpp")},
++ {"reg", (char*)&prop_bpp_reg[0], sizeof(prop_bpp_reg) },
++ {"intr", (char*)&prop_bpp_intr[0], sizeof(prop_bpp_intr) },
++ {NULL, NULL, -1}
++};
++
++static const int prop_fd_intr[] = { 0x2b, 0x0 };
++static const int prop_fd_reg[] = {
++ 0x0, 0x00400000, 0x0000000f,
++};
++static const struct property propv_obio_fd[] = {
++ {"name", "SUNW,fdtwo", sizeof("SUNW,fdtwo")},
++ {"reg", (char*)&prop_fd_reg[0], sizeof(prop_fd_reg) },
++ {"device_type", "block", sizeof("block") },
++ {"intr", (char*)&prop_fd_intr[0], sizeof(prop_fd_intr) },
++ {NULL, NULL, -1}
++};
++
++static const int prop_pw_intr[] = { 0x22, 0x0 };
++static const int prop_pw_reg[] = {
++ 0x0, 0x00910000, 0x00000001,
++};
++static const struct property propv_obio_pw[] = {
++ {"name", "power", sizeof("power")},
++ {"reg", (char*)&prop_pw_reg[0], sizeof(prop_pw_reg) },
++ {"intr", (char*)&prop_pw_intr[0], sizeof(prop_pw_intr) },
++ {NULL, NULL, -1}
++};
++
++static const int prop_cf_reg[] = {
++ 0x0, 0x00800000, 0x00000001,
++};
++static const struct property propv_obio_cf[] = {
++ {"name", "slavioconfig", sizeof("slavioconfig")},
++ {"reg", (char*)&prop_cf_reg[0], sizeof(prop_cf_reg) },
++ {NULL, NULL, -1}
++};
++
+static const struct node nodes[] = {
+ { &null_properties, 1, 0 }, /* 0 = big brother of root */
+ { propv_root, 0, 2 }, /* 1 "/" */
-+ { propv_iommu, 8, 3 }, /* 2 "/iommu" */
++ { propv_iommu, 11, 3 }, /* 2 "/iommu" */
+ { propv_sbus, 0, 4 }, /* 3 "/iommu/sbus" */
+ { propv_sbus_tcx, 5, 0 }, /* 4 "/iommu/sbus/SUNW,tcx" */
+ { propv_sbus_ledma, 7, 6 }, /* 5 "/iommu/sbus/ledma" */
+ { propv_sbus_ledma_le, 0, 0 }, /* 6 "/iommu/sbus/ledma/le" */
-+ { propv_sbus_cs4231, 0, 0 }, /* 7 "/iommu/sbus/SUNW,CS4231 */
-+ { propv_cpu, 9, 0 }, /* 8 "/STP1012PGA" */
-+ { propv_obio, 0, 10 }, /* 9 "/obio" */
-+ { propv_obio_int, 11, 0 }, /* 10 "/obio/interrupt" */
-+ { propv_obio_cnt, 12, 0 }, /* 11 "/obio/counter" */
-+ { propv_obio_eep, 13, 0 }, /* 12 "/obio/eeprom" */
++ { propv_sbus_cs4231, 8, 0 }, /* 7 "/iommu/sbus/SUNW,CS4231 */
++ { propv_sbus_bpp, 9, 0 }, /* 8 "/iommu/sbus/SUNW,bpp */
++ { propv_sbus_espdma, 0, 10 }, /* 9 "/iommu/sbus/espdma" */
++ { propv_sbus_espdma_esp, 0, 0 }, /* 10 "/iommu/sbus/espdma/esp" */
++ { propv_cpu, 12, 0 }, /* 11 "/STP1012PGA" */
++ { propv_obio, 0, 13 }, /* 12 "/obio" */
++ { propv_obio_int, 14, 0 }, /* 13 "/obio/interrupt" */
++ { propv_obio_cnt, 15, 0 }, /* 14 "/obio/counter" */
++ { propv_obio_eep, 16, 0 }, /* 15 "/obio/eeprom" */
++ { propv_obio_auxio, 17, 0 }, /* 16 "/obio/auxio" */
++ { propv_obio_zs, 18, 0 }, /* 17 "/obio/zs@0,0" */
++ { propv_obio_zs1, 19, 0 }, /* 18 "/obio/zs@0,100000" */
++ { propv_obio_fd, 20, 0 }, /* 19 "/obio/SUNW,fdtwo" */
++ { propv_obio_pw, 21, 0 }, /* 20 "/obio/power" */
++ { propv_obio_cf, 0, 0 }, /* 21 "/obio/slavioconfig@0,800000" */
++#if 0
+ { propv_obio_su, 14, 0 }, /* 13 "/obio/su" */
-+ { propv_obio_auxio, 0, 0 }, /* 14 "/obio/auxio" */
-+ { propv_obio_zs, 0, 0 }, /* 14 "/obio/zs@0,0" */
-+ { propv_obio_zs1, 0, 0 }, /* 14 "/obio/zs@0,100000" */
++ { propv_cpu, 18, 0 }, /* 17 "/STP1012PGA" */
++ { propv_cpu, 19, 0 }, /* 18 "/STP1012PGA" */
++
++ { propv_cpu, 20, 0 }, /* 19 "/STP1012PGA" */
++ { propv_cpu, 21, 0 }, /* 20 "/STP1012PGA" */
++ { propv_cpu, 22, 0 }, /* 21 "/STP1012PGA" */
++ { propv_cpu, 23, 0 }, /* 22 "/STP1012PGA" */
++ { propv_cpu, 24, 0 }, /* 23 "/STP1012PGA" */
++ { propv_cpu, 25, 0 }, /* 24 "/STP1012PGA" */
++ { propv_cpu, 26, 0 }, /* 25 "/STP1012PGA" */
++ { propv_cpu, 27, 0 }, /* 26 "/STP1012PGA" */
++ { propv_cpu, 28, 0 }, /* 27 "/STP1012PGA" */
++ { propv_cpu, 29, 0 }, /* 28 "/STP1012PGA" */
++ { propv_cpu, 30, 0 }, /* 29 "/STP1012PGA" */
++#endif
+};
+
+static struct linux_mlist_v0 totphys[MAX_BANKS];
@@ -1144,24 +1262,11 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+ obp_nextprop /* char * (*no_nextprop)(int node, char *name); */
+};
+
-+static const char arg_nfsroot[] = "console=ttyS0 ip=bootp root=nfs";
-+
-+static const struct linux_arguments_v0 obp_arg = {
-+ { "le()", arg_nfsroot, NULL, NULL, NULL, NULL, NULL, NULL },
-+ { "" },
-+ { 'l', 'e' }, 0, 0, 0, NULL,
-+ NULL
-+};
++static struct linux_arguments_v0 obp_arg;
+static const struct linux_arguments_v0 * const obp_argp = &obp_arg;
+
-+static const void * const synch_hook = NULL;
-+#if 0
-+static const char obp_stdin = PROMDEV_KBD;
-+static const char obp_stdout = PROMDEV_SCREEN;
-+#else
-+static const char obp_stdin = PROMDEV_TTYA;
-+static const char obp_stdout = PROMDEV_TTYA;
-+#endif
++static void (*synch_hook)(void);
++static char obp_stdin, obp_stdout;
+
+static int obp_nbgetchar(void);
+static int obp_nbputchar(int ch);
@@ -1181,88 +1286,11 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+ if (ptab1 != 0) mem_tablewalk(ptab1, va);
+}
+
-+#ifdef ORIG
-+static const struct linux_romvec romvec0 = {
-+ LINUX_OPPROM_MAGIC, /* pv_magic_cookie */
-+ 0, /* pv_romvers - Format selector! */
-+ 77, /* pv_plugin_revision */
-+ 0x10203, /* pv_printrev */
-+ { /* pv_v0mem */
-+ &ptphys, /* v0_totphys */
-+ &ptmap, /* v0_prommap */
-+ &ptavail /* v0_available */
-+ },
-+ &nodeops0, /* struct linux_nodeops *pv_nodeops; */
-+ (void*)doublewalk, /* P3 */ /* char **pv_bootstr; */
-+ { /* struct linux_dev_v0_funcs pv_v0devops; */
-+ &obp_devopen, /* v0_devopen */
-+ &obp_devclose, /* v0_devclose */
-+ &obp_rdblkdev, /* v0_rdblkdev */
-+ NULL, /* v0_wrblkdev */
-+ NULL, /* v0_wrnetdev */
-+ NULL, /* v0_rdnetdev */
-+ NULL, /* v0_rdchardev */
-+ NULL, /* v0_wrchardev */
-+ NULL /* v0_seekdev */
-+ },
-+ &obp_stdin, /* char *pv_stdin */
-+ &obp_stdout, /* char *pv_stdout; */
-+ obp_nbgetchar, /* int (*pv_getchar)(void); */
-+ obp_nbputchar, /* void (*pv_putchar)(int ch); */
-+ obp_nbgetchar, /* int (*pv_nbgetchar)(void); */
-+ obp_nbputchar, /* int (*pv_nbputchar)(int ch); */
-+ NULL, /* void (*pv_putstr)(char *str, int len); */
-+ obp_reboot, /* void (*pv_reboot)(char *bootstr); */
-+ NULL, /* void (*pv_printf)(__const__ char *fmt, ...); */
-+ obp_abort, /* void (*pv_abort)(void); */
-+ NULL, /* __volatile__ int *pv_ticks; */
-+ obp_halt, /* void (*pv_halt)(void); */
-+ (void *)&synch_hook, /* void (**pv_synchook)(void); */
-+
-+#if 0
-+ /* Evaluate a forth string, not different proto for V0 and V2->up. */
-+ union {
-+ void (*v0_eval)(int len, char *str);
-+ void (*v2_eval)(char *str);
-+ } pv_fortheval;
-+#endif
-+ { 0 }, /* pv_fortheval */
-+
-+ &obp_argp, /* struct linux_arguments_v0 **pv_v0bootargs; */
-+ NULL, /* pv_enaddr */
-+ { /* pv_v2bootargs */
-+ NULL, /* char **bootpath; */
-+ NULL, /* char **bootargs; */
-+ NULL, /* fd_stdin; */
-+ NULL, /* fd_stdout */
-+ },
-+ { /* pv_v2devops */
-+ NULL, /* v2_inst2pkg */
-+ NULL, /* v2_dumb_mem_alloc */
-+ NULL, /* v2_dumb_mem_free */
-+ NULL, /* v2_dumb_mmap */
-+ NULL, /* v2_dumb_munmap */
-+ NULL, /* v2_dev_open */
-+ NULL, /* v2_dev_close */
-+ NULL, /* v2_dev_read */
-+ NULL, /* v2_dev_write */
-+ NULL, /* v2_dev_seek */
-+ NULL, /* v2_wheee2 */
-+ NULL, /* v2_wheee3 */
-+ },
-+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* filler[15] */
-+ NULL, /* pv_setctxt */
-+ NULL, /* v3_cpustart */
-+ NULL, /* v3_cpustop */
-+ NULL, /* v3_cpuidle */
-+ NULL /* v3_cpuresume */
-+};
-+#endif
-+
+static struct linux_romvec romvec0;
+
+void *
-+init_openprom(int bankc, struct bank *bankv, unsigned hiphybas)
++init_openprom_qemu(int bankc, struct bank *bankv, unsigned hiphybas,
++ const char *cmdline, char boot_device, int nographic)
+{
+ int i;
+
@@ -1316,10 +1344,13 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+ romvec0.pv_v0mem.v0_available = &ptavail;
+ romvec0.pv_nodeops = &nodeops0;
+ romvec0.pv_bootstr = (void *)doublewalk;
++ romvec0.pv_v0devops.v0_devopen = &obp_devopen;
++ romvec0.pv_v0devops.v0_devclose = &obp_devclose;
++ romvec0.pv_v0devops.v0_rdblkdev = &obp_rdblkdev;
+ romvec0.pv_stdin = &obp_stdin;
+ romvec0.pv_stdout = &obp_stdout;
+ romvec0.pv_getchar = obp_nbgetchar;
-+ romvec0.pv_putchar = obp_nbputchar;
++ romvec0.pv_putchar = (void (*)(int))obp_nbputchar;
+ romvec0.pv_nbgetchar = obp_nbgetchar;
+ romvec0.pv_nbputchar = obp_nbputchar;
+ romvec0.pv_reboot = obp_reboot;
@@ -1327,6 +1358,27 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+ romvec0.pv_halt = obp_halt;
+ romvec0.pv_synchook = &synch_hook;
+ romvec0.pv_v0bootargs = &obp_argp;
++ switch(boot_device) {
++ default:
++ case 'a':
++ obp_arg.argv[0] = "fd()";
++ break;
++ case 'c':
++ obp_arg.argv[0] = "sd()";
++ break;
++ case 'n':
++ obp_arg.argv[0] = "le()";
++ break;
++ }
++ obp_arg.argv[1] = cmdline;
++
++ if (nographic) {
++ obp_stdin = PROMDEV_TTYA;
++ obp_stdout = PROMDEV_TTYA;
++ } else {
++ obp_stdin = PROMDEV_KBD;
++ obp_stdout = PROMDEV_SCREEN;
++ }
+ return &romvec0;
+}
+
@@ -1342,18 +1394,32 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+
+static int obp_nextnode(int node)
+{
++#ifdef DEBUG_OBP
++ printk("obp_nextnode(%d) = %d\n", node, nodes[node].sibling);
++#endif
+ return nodes[node].sibling;
+}
+
+static int obp_child(int node)
+{
++#ifdef DEBUG_OBP
++ printk("obp_child(%d) = %d\n", node, nodes[node].child);
++#endif
+ return nodes[node].child;
+}
+
+static int obp_proplen(int node, char *name)
+{
+ const struct property *prop = find_property(node,name);
-+ if (prop) return prop->length;
++ if (prop) {
++#ifdef DEBUG_OBP
++ printk("obp_proplen(%d, %s) = %d\n", node, name, prop->length);
++#endif
++ return prop->length;
++ }
++#ifdef DEBUG_OBP
++ printk("obp_proplen(%d, %s) (no prop)\n", node, name);
++#endif
+ return -1;
+}
+
@@ -1364,47 +1430,47 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+ prop = find_property(node,name);
+ if (prop) {
+ memcpy(value,prop->value,prop->length);
-+ //printk("obp_getprop '%s'= %s\n", name, value);
++#ifdef DEBUG_OBP
++ printk("obp_getprop(%d, %s) = %s\n", node, name, value);
++#endif
+ return prop->length;
+ }
-+ //printk("obp_getprop: not found\n");
++#ifdef DEBUG_OBP
++ printk("obp_getprop(%d, %s): not found\n", node, name);
++#endif
+ return -1;
+}
+
+static int obp_setprop(int node, char *name, char *value, int len)
+{
++#ifdef DEBUG_OBP
++ printk("obp_setprop(%d, %s) = %s (%d)\n", node, name, value, len);
++#endif
+ return -1;
+}
+
+static const char *obp_nextprop(int node,char *name)
+{
+ const struct property *prop = find_property(node,name);
-+ if (prop) return prop[1].name;
++ if (prop) {
++#ifdef DEBUG_OBP
++ printk("obp_nextprop(%d, %s) = %s\n", node, name, prop[1].name);
++#endif
++ return prop[1].name;
++ }
++#ifdef DEBUG_OBP
++ printk("obp_nextprop(%d, %s): not found\n", node, name);
++#endif
+ return NULL;
+}
+
-+#if 0
-+static unsigned char calc_idprom_cksum(struct idprom *idprom)
-+{
-+ unsigned char cksum, i, *ptr = (unsigned char *)idprom;
-+
-+ for (i = cksum = 0; i <= 0x0E; i++)
-+ cksum ^= *ptr++;
-+
-+ return cksum;
-+}
-+#endif
-+
+static int obp_nbgetchar(void) {
-+ return -1;
++ extern struct vconterm dp0;
++ return vcon_getch(&dp0);
+}
+
+static int obp_nbputchar(int ch) {
-+ extern struct vconterm dp0;
-+ char buf = ch;
-+
-+ /* We do not use printk() in order to reduce stack depth. */
-+ vcon_write(&dp0, &buf, 1);
++ printk("%c", ch);
+ return 0;
+}
+
@@ -1424,23 +1490,449 @@ diff -ruN proll_18.orig/qemu/openprom.c proll-patch4/qemu/openprom.c
+}
+
+static int obp_devopen(char *str) {
-+ //printk("open %s\n", str);
++#ifdef DEBUG_OBP
++ printk("open %s\n", str);
++#endif
+ return 0;
+}
+
+static int obp_devclose(int dev_desc) {
-+ //printk("close %d\n", dev_desc);
++#ifdef DEBUG_OBP
++ printk("close %d\n", dev_desc);
++#endif
+ return 0;
+}
+
+static int obp_rdblkdev(int dev_desc, int num_blks, int blk_st, char *buf) {
-+ //printk("rdblkdev: fd %d, num_blks %d, blk_st %d, buf 0x%x\n", dev_desc, num_blks, blk_st, buf);
++#ifdef DEBUG_OBP
++ printk("rdblkdev: fd %d, num_blks %d, blk_st %d, buf 0x%x\n", dev_desc, num_blks, blk_st, buf);
++#endif
+ //buf[8] = 'L';
+ return num_blks;
+}
-diff -ruN proll_18.orig/src/arp.c proll-patch4/src/arp.c
+diff -ruN proll_18.orig/qemu/system_qemu.c proll-patch7/qemu/system_qemu.c
+--- proll_18.orig/qemu/system_qemu.c 1970-01-01 00:00:00.000000000 +0000
++++ proll-patch7/qemu/system_qemu.c 2005-03-02 16:10:20.000000000 +0000
+@@ -0,0 +1,416 @@
++/**
++ ** Proll (PROM replacement)
++ ** system.c: shared miscallenea.
++ ** Copyright 1999 Pete Zaitcev
++ ** This code is licensed under GNU General Public License.
++ **/
++#include <stdarg.h>
++#include <asi.h>
++#include <crs.h>
++#ifndef NULL
++#define NULL ((void*)0)
++#endif
++
++#include "pgtsrmmu.h"
++
++#include "vconsole.h"
++#include <timer.h> /* Local copy of 2.2 style include */
++#include <general.h> /* __P() */
++#include <net.h> /* init_net() */
++#include <romlib.h> /* we are a provider for part of this. */
++#include <netpriv.h> /* myipaddr */
++#include <arpa.h>
++#include <system.h> /* our own prototypes */
++
++/*
++ * We export this.
++ */
++char idprom[IDPROM_SIZE];
++
++
++/*
++ * Create an I/O mapping to pa[size].
++ * Returns va of the mapping or 0 if unsuccessful.
++ */
++void *
++map_io(unsigned pa, int size)
++{
++ void *va;
++ unsigned int npages;
++ unsigned int off;
++ unsigned int mva;
++
++ off = pa & (PAGE_SIZE-1);
++ npages = (off + size + (PAGE_SIZE-1)) / PAGE_SIZE;
++ pa &= ~(PAGE_SIZE-1);
++
++ va = mem_alloc(&cio, npages*PAGE_SIZE, PAGE_SIZE);
++ if (va == 0) return va;
++
++ mva = (unsigned int) va;
++ /* printk("map_io: va 0x%x pa 0x%x off 0x%x npages %d\n", va, pa, off, npages); */ /* P3 */
++ while (npages-- != 0) {
++ map_page(pmem.pl1, mva, pa, 1, pmem.pbas);
++ mva += PAGE_SIZE;
++ pa += PAGE_SIZE;
++ }
++
++ return (void *)((unsigned int)va + off);
++}
++
++/*
++ * Tablewalk routine used for testing.
++ * Returns PTP/PTE.
++ */
++unsigned int
++proc_tablewalk(int ctx, unsigned int va)
++{
++ unsigned int pa1;
++
++ __asm__ __volatile__ ("lda [%1] %2, %0" :
++ "=r" (pa1) :
++ "r" (AC_M_CTPR), "i" (ASI_M_MMUREGS));
++ /* printk(" ctpr %x ctx %x\n", pa1, ctx); */ /* P3 */
++ pa1 <<= 4;
++ pa1 = ld_bypass(pa1 + (ctx << 2));
++ if ((pa1 & 0x03) == 0) goto invalid;
++ return mem_tablewalk((pa1 & 0xFFFFFFF0) << 4, va);
++
++invalid:
++ printk(" invalid %x\n", pa1);
++ return 0;
++}
++
++/*
++ * Walk the tables in memory, starting at physical address pa.
++ */
++unsigned int
++mem_tablewalk(unsigned int pa, unsigned int va)
++{
++ unsigned int pa1;
++
++ printk("pa %x va %x", pa, va);
++ pa1 = ld_bypass(pa + (((va&0xFF000000)>>24) << 2));
++ if ((pa1 & 0x03) == 0) goto invalid;
++ printk(" l1 %x", pa1);
++ pa1 <<= 4; pa1 &= 0xFFFFFF00;
++ pa1 = ld_bypass(pa1 + (((va&0x00FC0000)>>18) << 2));
++ if ((pa1 & 0x03) == 0) goto invalid;
++ printk(" l2 %x", pa1);
++ pa1 <<= 4; pa1 &= 0xFFFFFF00;
++ pa1 = ld_bypass(pa1 + (((va&0x0003F000)>>12) << 2));
++ if ((pa1 & 0x03) == 0) goto invalid;
++ printk(" l3 %x", pa1);
++ printk(" off %x\n", va&0x00000FFF);
++ return pa1;
++invalid:
++ printk(" invalid %x\n", pa1);
++ return 0;
++}
++
++/*
++ * Make CPU page tables.
++ * Returns pointer to context table.
++ * Here we ignore memory allocation errors which "should not happen"
++ * because we cannot print anything anyways if memory initialization fails.
++ */
++void makepages(struct phym *t, unsigned int highbase)
++{
++ unsigned int *ctp, *l1, pte;
++ int i;
++ unsigned int pa, va;
++
++ ctp = mem_zalloc(&cmem, NCTX_SWIFT*sizeof(int), NCTX_SWIFT*sizeof(int));
++ l1 = mem_zalloc(&cmem, 256*sizeof(int), 256*sizeof(int));
++
++ pte = SRMMU_ET_PTD | (((unsigned int)l1 - PROLBASE + highbase) >> 4);
++ for (i = 0; i < NCTX_SWIFT; i++) {
++ ctp[i] = pte;
++ }
++
++ pa = PROLBASE;
++ for (va = PROLBASE; va < PROLDATA; va += PAGE_SIZE) {
++ map_page(l1, va, pa, 0, highbase);
++ pa += PAGE_SIZE;
++ }
++ pa = highbase + PROLDATA - PROLBASE;
++ for (va = PROLDATA; va < PROLBASE + PROLSIZE; va += PAGE_SIZE) {
++ map_page(l1, va, pa, 0, highbase);
++ pa += PAGE_SIZE;
++ }
++
++ /* We need to start from LOADBASE, but kernel wants PAGE_SIZE. */
++ pa = 0;
++ for (va = 0; va < LOWMEMSZ; va += PAGE_SIZE) {
++ map_page(l1, va, pa, 0, highbase);
++ pa += PAGE_SIZE;
++ }
++
++ t->pctp = ctp;
++ t->pl1 = l1;
++ t->pbas = highbase;
++}
++
++/*
++ * Create a memory mapping from va to epa in page table pgd.
++ * highbase is used for v2p translation.
++ */
++int
++map_page(unsigned int *pgd, unsigned int va,
++ unsigned int epa, int type, unsigned int highbase)
++{
++ unsigned int pte;
++ unsigned int *p;
++ unsigned int pa;
++
++ pte = pgd[((va)>>SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD-1)];
++ if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
++ p = mem_zalloc(&cmem, SRMMU_PTRS_PER_PMD*sizeof(int),
++ SRMMU_PTRS_PER_PMD*sizeof(int));
++ if (p == 0) goto drop;
++ pte = SRMMU_ET_PTD |
++ (((unsigned int)p - PROLBASE + highbase) >> 4);
++ pgd[((va)>>SRMMU_PGDIR_SHIFT) & (SRMMU_PTRS_PER_PGD-1)] = pte;
++ /* barrier() */
++ }
++
++ pa = ((pte & 0xFFFFFFF0) << 4);
++ pa += (((va)>>SRMMU_PMD_SHIFT & (SRMMU_PTRS_PER_PMD-1)) << 2);
++ pte = ld_bypass(pa);
++ if ((pte & SRMMU_ET_MASK) == SRMMU_ET_INVALID) {
++ p = mem_zalloc(&cmem, SRMMU_PTRS_PER_PTE*sizeof(int),
++ SRMMU_PTRS_PER_PTE*sizeof(int));
++ if (p == 0) goto drop;
++ pte = SRMMU_ET_PTD |
++ (((unsigned int)p - PROLBASE + highbase) >> 4);
++ st_bypass(pa, pte);
++ }
++
++ pa = ((pte & 0xFFFFFFF0) << 4);
++ pa += (((va)>>PAGE_SHIFT & (SRMMU_PTRS_PER_PTE-1)) << 2);
++
++ pte = SRMMU_ET_PTE | ((epa & PAGE_MASK) >> 4);
++ if (type) { /* I/O */
++ pte |= SRMMU_REF;
++ /* SRMMU cannot make Supervisor-only, but not exectutable */
++ pte |= SRMMU_PRIV;
++ } else { /* memory */
++ pte |= SRMMU_REF|SRMMU_CACHE;
++ pte |= SRMMU_PRIV; /* Supervisor only access */
++ }
++ st_bypass(pa, pte);
++ return 0;
++
++drop:
++ return -1;
++}
++
++/*
++ * Switch page tables.
++ */
++void
++init_mmu_swift(unsigned int ctp_phy)
++{
++ unsigned int addr;
++
++ /*
++ * Flush cache
++ */
++ for (addr = 0; addr < 0x2000; addr += 0x10) {
++ __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
++ "r" (addr), "i" (ASI_M_DATAC_TAG));
++ __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
++ "r" (addr<<1), "i" (ASI_M_TXTC_TAG));
++ }
++
++ /*
++ * Switch ctx table
++ */
++ ctp_phy >>= 4;
++ /* printk("done flushing, switching to %x\n", ctp_phy); */
++ __asm__ __volatile__ ("sta %0, [%1] %2\n\t" : :
++ "r" (ctp_phy), "r" (AC_M_CTPR), "i" (ASI_M_MMUREGS));
++
++ /*
++ * Flush old page table references
++ */
++ __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : :
++ "r" (0x400), "i" (ASI_M_FLUSH_PROBE) : "memory");
++}
++
++/*
++ * add_timer, del_timer
++ * This should go into sched.c, but we have it split for different archs.
++ */
++struct timer_list_head {
++ struct timer_list *head, *tail;
++};
++
++static struct timer_list_head timers; /* Anonymous heap of timers */
++
++void add_timer(struct timer_list *timer) {
++ struct timer_list *p;
++ if (timer->prev != NULL || timer->next != NULL) {
++ printk("bug: kernel timer added twice at 0x%x.\n",
++ __builtin_return_address(0));
++ return;
++ }
++ if ((p = timers.tail) != NULL) {
++ timer->prev = p;
++ p->next = timer;
++ timers.tail = timer;
++ } else {
++ timers.head = timer;
++ timers.tail = timer;
++ }
++ return;
++}
++
++int del_timer(struct timer_list *timer) {
++ struct timer_list *p;
++ int ret;
++
++ if (timers.head == timer) timers.head = timer->next;
++ if (timers.tail == timer) timers.tail = timer->prev;
++ if ((p = timer->prev) != NULL) p->next = timer->next;
++ if ((p = timer->next) != NULL) p->prev = timer->prev;
++ ret = timer->next != 0 || timer->prev != 0;
++ timer->next = NULL;
++ timer->prev = NULL;
++ return ret;
++}
++
++void run_timers() {
++ struct timer_list *p;
++
++ p = timers.head;
++ while (p != NULL) {
++ if (p->expires < jiffies) {
++ del_timer(p); /* XXX make nonstatic member */
++ (*p->function)(p->data);
++ p = timers.head;
++ } else {
++ p = p->next;
++ }
++ }
++}
++
++/*
++ * Allocate memory. This is reusable.
++ */
++void mem_init(struct mem *t, char *begin, char *limit)
++{
++ t->start = begin;
++ t->uplim = limit;
++ t->curp = begin;
++}
++
++void mem_fini(struct mem *t)
++{
++ t->curp = 0;
++}
++
++void *mem_alloc(struct mem *t, int size, int align)
++{
++ char *p;
++
++ p = (char *)((((unsigned int)t->curp) + (align-1)) & ~(align-1));
++ if (p >= t->uplim || p + size > t->uplim) return 0;
++ t->curp = p + size;
++ return p;
++}
++
++void *mem_zalloc(struct mem *t, int size, int align)
++{
++ char *p;
++
++ if ((p = mem_alloc(t, size, align)) != 0) bzero(p, size);
++ return p;
++}
++
++/*
++ * Library functions
++ */
++void bzero(void *s, int len) {
++ while (len--) *((char *)s)++ = 0;
++}
++
++void bcopy(const void *f, void *t, int len) {
++ while (len--) *((char *)t)++ = *((char *)f)++;
++}
++
++/* Comparison is 7-bit */
++int bcmp(const void *s1, const void *s2, int len)
++{
++ int i;
++ char ch;
++
++ while (len--) {
++ ch = *((char *)s1)++;
++ if ((i = ch - *((char *)s2)++) != 0)
++ return i;
++ if (ch == 0)
++ return 0;
++ }
++ return 0;
++}
++
++int strlen(const char *s) {
++ const char *p;
++ for (p = s; *p != 0; p++) { }
++ return p - s;
++}
++
++extern void *printk_fn;
++
++void printk(char *fmt, ...)
++{
++ struct prf_fp {
++ void *xfp;
++ void (*write)(void *, char *, int);
++ } prfa;
++ extern void prf(struct prf_fp *, char *fmt, va_list adx);
++ va_list x1;
++
++ va_start(x1, fmt);
++ prfa.xfp = &dp0;
++ prfa.write = printk_fn;
++ prf(&prfa, fmt, x1);
++ va_end(x1);
++}
++
++void fatal()
++{
++ printk("fatal.");
++loop: goto loop;
++}
++
++/*
++ * Get the highest bit number from the mask.
++ */
++int highc(int mask, int size)
++{
++ int m1;
++
++ m1 = 1 << size;
++ while (size != 0) {
++ size--;
++ m1 >>= 1;
++ if (m1 & mask) break;
++ }
++ return size;
++}
++
++/*
++ */
++unsigned int ld_bp_swap(unsigned int ptr) {
++ unsigned int n;
++ n = ld_bypass(ptr);
++ n = (n>>24 & 0xFF) | (n>>8 & 0xFF00) | ((n&0xFF00) << 8) | (n<<24);
++ return n;
++}
++
++void st_bp_swap(unsigned int ptr, unsigned int n) {
++ n = (n>>24 & 0xFF) | (n>>8 & 0xFF00) | ((n&0xFF00) << 8) | (n<<24);
++ st_bypass(ptr, n);
++};
+diff -ruN proll_18.orig/src/arp.c proll-patch7/src/arp.c
--- proll_18.orig/src/arp.c 2001-12-24 05:12:31.000000000 +0000
-+++ proll-patch4/src/arp.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/arp.c 2004-11-13 15:50:49.000000000 +0000
@@ -45,7 +45,7 @@
#endif
static struct arp_cache arp_list[ARPNUM]; /* ARP address cache */
@@ -1475,9 +1967,9 @@ diff -ruN proll_18.orig/src/arp.c proll-patch4/src/arp.c
+ def_gw = IP_ANY;
return(TRUE);
}
-diff -ruN proll_18.orig/src/arp.h proll-patch4/src/arp.h
+diff -ruN proll_18.orig/src/arp.h proll-patch7/src/arp.h
--- proll_18.orig/src/arp.h 1999-03-18 03:39:43.000000000 +0000
-+++ proll-patch4/src/arp.h 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/arp.h 2004-11-13 15:50:49.000000000 +0000
@@ -104,7 +104,7 @@
extern int init_arp __P((void));
@@ -1487,24 +1979,35 @@ diff -ruN proll_18.orig/src/arp.h proll-patch4/src/arp.h
/* Add a new antry to the ARP cache */
extern void addcache __P((unsigned char *ha, t_ipaddr ip));
-diff -ruN proll_18.orig/src/hconsole.c proll-patch4/src/hconsole.c
+diff -ruN proll_18.orig/src/hconsole.c proll-patch7/src/hconsole.c
--- proll_18.orig/src/hconsole.c 2002-07-23 05:52:48.000000000 +0000
-+++ proll-patch4/src/hconsole.c 2004-11-13 15:50:49.000000000 +0000
-@@ -42,7 +42,11 @@
++++ proll-patch7/src/hconsole.c 2005-03-02 17:03:09.000000000 +0000
+@@ -29,6 +29,10 @@
+ struct raster r_master; /* For a case of resize, whole fb */
+ struct raster r_0; /* malloc() erzatz */
+
++#ifdef QEMU
++extern unsigned int q_height, q_width;
++#endif
++
+ int hcon_init(struct hconsole *t, unsigned int a0)
+ {
+ struct raster *q, *r;
+@@ -42,7 +46,11 @@
* No probing sequence or argument passing, hardcode everything. XXX
*/
raster8_cons_a(q, 768, 1024, (char *)a0);
-+#if 1
++#ifndef QEMU
raster_cons_2(r, q, 768-(24*11)-1, 1024-(8*80)-1, (24*11), (8*80));
+#else
-+ raster_cons_2(r, q, 0, 0, 768, 1024);
++ raster_cons_2(r, q, 0, 0, q_height, q_width);
+#endif
t->r_ = r;
t->r0_ = q;
t->f_ = &f_master;
-diff -ruN proll_18.orig/src/lat7_2.bm proll-patch4/src/lat7_2.bm
+diff -ruN proll_18.orig/src/lat7_2.bm proll-patch7/src/lat7_2.bm
--- proll_18.orig/src/lat7_2.bm 1999-02-27 05:48:54.000000000 +0000
-+++ proll-patch4/src/lat7_2.bm 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/lat7_2.bm 2004-11-13 15:50:49.000000000 +0000
@@ -1,6 +1,6 @@
#define lat7_2_width 128
#define lat7_2_height 88
@@ -1513,9 +2016,9 @@ diff -ruN proll_18.orig/src/lat7_2.bm proll-patch4/src/lat7_2.bm
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x12, 0x1e, 0x0c, 0x02, 0x70, 0x18,
0x22, 0x22, 0x18, 0x00, 0x00, 0x18, 0x18, 0xff, 0x18, 0x00, 0x12, 0x02,
-diff -ruN proll_18.orig/src/lat7_2_swapped.bm proll-patch4/src/lat7_2_swapped.bm
+diff -ruN proll_18.orig/src/lat7_2_swapped.bm proll-patch7/src/lat7_2_swapped.bm
--- proll_18.orig/src/lat7_2_swapped.bm 1970-01-01 00:00:00.000000000 +0000
-+++ proll-patch4/src/lat7_2_swapped.bm 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/lat7_2_swapped.bm 2004-11-13 15:50:49.000000000 +0000
@@ -0,0 +1,121 @@
+#define lat7_2_width 128
+#define lat7_2_height 88
@@ -1638,9 +2141,9 @@ diff -ruN proll_18.orig/src/lat7_2_swapped.bm proll-patch4/src/lat7_2_swapped.bm
+ 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x42, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
-diff -ruN proll_18.orig/src/le.c proll-patch4/src/le.c
+diff -ruN proll_18.orig/src/le.c proll-patch7/src/le.c
--- proll_18.orig/src/le.c 2002-07-23 05:52:49.000000000 +0000
-+++ proll-patch4/src/le.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/le.c 2004-11-13 15:50:49.000000000 +0000
@@ -185,8 +185,6 @@
unsigned short rap; /* register address port */
};
@@ -1650,9 +2153,9 @@ diff -ruN proll_18.orig/src/le.c proll-patch4/src/le.c
/* The Lance uses 24 bit addresses */
/* On the Sun4c the DVMA will provide the remaining bytes for us */
/* On the Sun4m we have to instruct the ledma to provide them */
-diff -ruN proll_18.orig/src/netinit.c proll-patch4/src/netinit.c
+diff -ruN proll_18.orig/src/netinit.c proll-patch7/src/netinit.c
--- proll_18.orig/src/netinit.c 2002-09-13 21:53:33.000000000 +0000
-+++ proll-patch4/src/netinit.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/netinit.c 2004-11-13 15:50:49.000000000 +0000
@@ -49,13 +49,20 @@
unsigned char myhwaddr[ETH_ALEN]; /* my own hardware addr */
t_ipaddr myipaddr; /* my own IP address */
@@ -1696,9 +2199,9 @@ diff -ruN proll_18.orig/src/netinit.c proll-patch4/src/netinit.c
fatal();
}
}
-diff -ruN proll_18.orig/src/netpriv.h proll-patch4/src/netpriv.h
+diff -ruN proll_18.orig/src/netpriv.h proll-patch7/src/netpriv.h
--- proll_18.orig/src/netpriv.h 1999-04-27 05:39:37.000000000 +0000
-+++ proll-patch4/src/netpriv.h 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/netpriv.h 2004-11-13 15:50:49.000000000 +0000
@@ -130,10 +130,9 @@
*
*/
@@ -1720,9 +2223,9 @@ diff -ruN proll_18.orig/src/netpriv.h proll-patch4/src/netpriv.h
/* Empty read buffer */
extern void empty_buf __P((void));
-diff -ruN proll_18.orig/src/openprom.h proll-patch4/src/openprom.h
+diff -ruN proll_18.orig/src/openprom.h proll-patch7/src/openprom.h
--- proll_18.orig/src/openprom.h 2002-07-14 02:26:30.000000000 +0000
-+++ proll-patch4/src/openprom.h 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/openprom.h 2004-11-13 15:50:49.000000000 +0000
@@ -54,20 +54,20 @@
};
@@ -1784,9 +2287,9 @@ diff -ruN proll_18.orig/src/openprom.h proll-patch4/src/openprom.h
};
/* More fun PROM structures for device probing. */
-diff -ruN proll_18.orig/src/packet.c proll-patch4/src/packet.c
+diff -ruN proll_18.orig/src/packet.c proll-patch7/src/packet.c
--- proll_18.orig/src/packet.c 2000-02-11 04:56:45.000000000 +0000
-+++ proll-patch4/src/packet.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/packet.c 2004-11-13 15:50:49.000000000 +0000
@@ -41,7 +41,7 @@
int aligner;
} wbuf;
@@ -1814,9 +2317,9 @@ diff -ruN proll_18.orig/src/packet.c proll-patch4/src/packet.c
{
struct sk_buff *skb;
unsigned char *s;
-diff -ruN proll_18.orig/src/printf.c proll-patch4/src/printf.c
+diff -ruN proll_18.orig/src/printf.c proll-patch7/src/printf.c
--- proll_18.orig/src/printf.c 1999-03-19 07:03:59.000000000 +0000
-+++ proll-patch4/src/printf.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/printf.c 2004-11-13 15:50:49.000000000 +0000
@@ -19,7 +19,7 @@
static void printn(struct prf_fp *, unsigned long, unsigned int);
static void putchar(char, struct prf_fp *);
@@ -1844,9 +2347,9 @@ diff -ruN proll_18.orig/src/printf.c proll-patch4/src/printf.c
putchar(c,filog);
} else if (c == 'l' || c == 'O') {
printn(filog, (long)va_arg(adx,long), c=='l'?10:8);
-diff -ruN proll_18.orig/src/rconsole.c proll-patch4/src/rconsole.c
+diff -ruN proll_18.orig/src/rconsole.c proll-patch7/src/rconsole.c
--- proll_18.orig/src/rconsole.c 1999-01-16 07:16:55.000000000 +0000
-+++ proll-patch4/src/rconsole.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/rconsole.c 2004-11-13 15:50:49.000000000 +0000
@@ -28,12 +28,18 @@
* move to California. Only plain lat7 survived.
* I recreated lat7-1 changes in lat7-2. --zaitcev
@@ -1901,9 +2404,9 @@ diff -ruN proll_18.orig/src/rconsole.c proll-patch4/src/rconsole.c
p->nchars_ = LAT7_NCHARS;
p->width_ = LAT7_WIDTH;
p->height_ = LAT7_HEIGHT;
-diff -ruN proll_18.orig/src/rconsole.h proll-patch4/src/rconsole.h
+diff -ruN proll_18.orig/src/rconsole.h proll-patch7/src/rconsole.h
--- proll_18.orig/src/rconsole.h 1999-01-16 05:00:59.000000000 +0000
-+++ proll-patch4/src/rconsole.h 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/rconsole.h 2004-11-13 15:50:49.000000000 +0000
@@ -13,10 +13,10 @@
*/
@@ -1917,9 +2420,9 @@ diff -ruN proll_18.orig/src/rconsole.h proll-patch4/src/rconsole.h
int nchars_; /* 128 for ASCII ... 65536 for Unicode */
int width_; /* [Pixels]. Maximum size is 16. */
int height_; /* [Pixels == scan lines]. */
-diff -ruN proll_18.orig/src/romlib.h proll-patch4/src/romlib.h
+diff -ruN proll_18.orig/src/romlib.h proll-patch7/src/romlib.h
--- proll_18.orig/src/romlib.h 1999-04-20 04:26:45.000000000 +0000
-+++ proll-patch4/src/romlib.h 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/romlib.h 2004-11-13 15:50:49.000000000 +0000
@@ -73,12 +73,12 @@
#define memcpy(dst, src, len) bcopy(src, dst, len)
#define memcmp(x1, x2, len) bcmp(x1, x2, len)
@@ -1936,9 +2439,9 @@ diff -ruN proll_18.orig/src/romlib.h proll-patch4/src/romlib.h
/*
-diff -ruN proll_18.orig/src/sched_4m.c proll-patch4/src/sched_4m.c
+diff -ruN proll_18.orig/src/sched_4m.c proll-patch7/src/sched_4m.c
--- proll_18.orig/src/sched_4m.c 1999-04-27 05:48:51.000000000 +0000
-+++ proll-patch4/src/sched_4m.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/sched_4m.c 2004-11-13 15:50:49.000000000 +0000
@@ -108,7 +108,7 @@
static int set_bolt; /* Tick counter limit */
static struct handsc hndv[16];
@@ -1948,9 +2451,9 @@ diff -ruN proll_18.orig/src/sched_4m.c proll-patch4/src/sched_4m.c
0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
-diff -ruN proll_18.orig/src/swap.c proll-patch4/src/swap.c
+diff -ruN proll_18.orig/src/swap.c proll-patch7/src/swap.c
--- proll_18.orig/src/swap.c 1970-01-01 00:00:00.000000000 +0000
-+++ proll-patch4/src/swap.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/swap.c 2004-11-13 15:50:49.000000000 +0000
@@ -0,0 +1,21 @@
+// Convert the lat7 font so that no conversion is needed at runtime.
+#define ORIG
@@ -1973,9 +2476,9 @@ diff -ruN proll_18.orig/src/swap.c proll-patch4/src/swap.c
+ }
+ printf("\n");
+}
-diff -ruN proll_18.orig/src/system.c proll-patch4/src/system.c
+diff -ruN proll_18.orig/src/system.c proll-patch7/src/system.c
--- proll_18.orig/src/system.c 2002-07-23 05:52:49.000000000 +0000
-+++ proll-patch4/src/system.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/system.c 2004-11-13 15:50:49.000000000 +0000
@@ -298,8 +298,8 @@
}
@@ -2028,9 +2531,9 @@ diff -ruN proll_18.orig/src/system.c proll-patch4/src/system.c
void fatal()
{
printk("fatal.");
-diff -ruN proll_18.orig/src/system.h proll-patch4/src/system.h
+diff -ruN proll_18.orig/src/system.h proll-patch7/src/system.h
--- proll_18.orig/src/system.h 2002-09-13 21:53:32.000000000 +0000
-+++ proll-patch4/src/system.h 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/system.h 2004-11-13 15:50:49.000000000 +0000
@@ -16,7 +16,7 @@
#define IOMAPSIZE (1*1024*1024) /* 1 Meg maximum: we do not map framebuffer. */
#define NCTX_SWIFT 0x100
@@ -2040,9 +2543,9 @@ diff -ruN proll_18.orig/src/system.h proll-patch4/src/system.h
#ifndef __ASSEMBLY__
struct bank {
-diff -ruN proll_18.orig/src/udp.c proll-patch4/src/udp.c
+diff -ruN proll_18.orig/src/udp.c proll-patch7/src/udp.c
--- proll_18.orig/src/udp.c 2001-12-24 05:12:53.000000000 +0000
-+++ proll-patch4/src/udp.c 2004-11-13 15:50:49.000000000 +0000
++++ proll-patch7/src/udp.c 2004-11-13 15:50:49.000000000 +0000
@@ -81,7 +81,7 @@
int source;
int dest;
@@ -2062,3 +2565,263 @@ diff -ruN proll_18.orig/src/udp.c proll-patch4/src/udp.c
/* Register IP packet type and set write buffer pointer */
if ((writebuf = reg_type(htons(ETH_P_IP), ip_recv)) == NULL)
return(FALSE);
+diff -ruN proll_18.orig/src/vcons_zs.c proll-patch7/src/vcons_zs.c
+--- proll_18.orig/src/vcons_zs.c 1970-01-01 00:00:00.000000000 +0000
++++ proll-patch7/src/vcons_zs.c 2005-03-02 12:07:41.000000000 +0000
+@@ -0,0 +1,68 @@
++/**
++ ** Console over 'zs' (Zilog serial port)
++ ** Copyright 1999 Pete Zaitcev
++ ** This code is licensed under GNU General Public License.
++ **/
++
++#include "vconsole.h"
++#include <system.h>
++
++#define ZS_DATA 0x02
++
++int vcon_zs_init(struct vconterm *t, unsigned int a0)
++{
++
++ t->impl = (void *) a0;
++
++ t->vc_x = 0; t->vc_y = 0;
++ t->backp = 0; t->backc = 0;
++
++ stb_bypass(a0, 3); // reg 3
++ stb_bypass(a0, 1); // enable rx
++
++ stb_bypass(a0, 5); // reg 5
++ stb_bypass(a0, 8); // enable tx
++
++ return 0;
++}
++
++int vcon_zs_putch(struct vconterm *t, char c)
++{
++ unsigned zs_ptr = (unsigned) t->impl;
++
++ //while ((ldb_bypass(zs_ptr + ZS_LSR) & 0x60) != 0x60) { }
++ stb_bypass(zs_ptr + ZS_DATA, c);
++ return 0;
++}
++
++int vcon_zs_write(struct vconterm *t, char *data, int leng)
++{
++ while (leng != 0) {
++ leng--;
++ vcon_zs_putch(t, *data++);
++ }
++ return leng;
++}
++
++int vcon_zs_read(struct vconterm *t, char *data, int leng)
++{
++ unsigned zs_ptr = (unsigned) t->impl;
++
++ while ((ldb_bypass(zs_ptr) & 1) != 1) { }
++ *data = ldb_bypass(zs_ptr + ZS_DATA);
++ return 0;
++}
++
++int vcon_zs_getch(struct vconterm *t)
++{
++ unsigned zs_ptr = (unsigned) t->impl;
++
++ while ((ldb_bypass(zs_ptr) & 1) != 1) { }
++ return ldb_bypass(zs_ptr + ZS_DATA);
++}
++
++void vcon_zs_fini(struct vconterm *t)
++{
++ /* violent crash in the end */
++ ;
++}
+diff -ruN proll_18.orig/src/vconsole.c proll-patch7/src/vconsole.c
+--- proll_18.orig/src/vconsole.c 1999-11-08 03:10:28.000000000 +0000
++++ proll-patch7/src/vconsole.c 2005-03-02 14:29:05.000000000 +0000
+@@ -13,6 +13,10 @@
+
+ struct hconsole hcons0;
+
++enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
++ EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
++ ESpalette };
++
+ int vcon_init(struct vconterm *t, unsigned int a0)
+ {
+ struct hconsole *hconp;
+@@ -25,11 +29,49 @@
+
+ t->vc_x = 0; t->vc_y = 0;
+ t->backp = 0; t->backc = 0;
++ t->vc_state = ESnormal;
+
+ hcon_clear(hconp, 0, 0, hconp->ydim_, hconp->xdim_);
+ return 0;
+ }
+
++/*
++ * gotoxy() must verify all boundaries, because the arguments
++ * might also be negative. If the given position is out of
++ * bounds, the cursor is placed at the nearest margin.
++ */
++static void gotoxy(struct vconterm *vc, int new_x, int new_y)
++{
++ int max_x, max_y;
++ struct hconsole *hconp = vc->impl;
++
++ max_x = hcon_qxdim(hconp);
++ max_y = hcon_qydim(hconp);
++
++ if (new_x < 0)
++ vc->vc_x = 0;
++ else {
++ if (new_x >= max_x)
++ vc->vc_x = max_x - 1;
++ else
++ vc->vc_x = new_x;
++ }
++
++ if (new_y < 0)
++ vc->vc_y = 0;
++ else if (new_y >= max_y)
++ vc->vc_y = max_y - 1;
++ else
++ vc->vc_y = new_y;
++
++}
++
++/* for absolute user moves, when decom is set */
++static void gotoxay(struct vconterm *t, int new_x, int new_y)
++{
++ gotoxy(t, new_x, new_y);
++}
++
+ int vcon_write(struct vconterm *t, char *data, int leng)
+ {
+ int l = leng;
+@@ -40,29 +82,84 @@
+ if (l <= 0) break;
+ c = *data++; --l;
+
+- switch (c) {
+- case 0x07: /* Bell */
+- vcon_i_backflush(t);
+- break;
+- case 0x0A: /* Linefeed */
+- vcon_i_backflush(t);
+- vcon_i_cursfeed(t);
++ switch(t->vc_state) {
++ case ESesc:
++ t->vc_state = ESnormal;
++ switch (c) {
++ case '[':
++ t->vc_state = ESsquare;
++ break;
++ case 'M':
++ hcon_scroll(hconp, 0, hcon_qydim(hconp), SM_UP, 1);
++ break;
++ }
+ break;
+- case 0x0D: /* Return */
+- vcon_i_backflush(t);
+- t->vc_x = 0;
++ case ESsquare:
++ for(t->vc_npar = 0 ; t->vc_npar < NPAR ; t->vc_npar++)
++ t->vc_par[t->vc_npar] = 0;
++ t->vc_npar = 0;
++ t->vc_state = ESgetpars;
++ case ESgetpars:
++ if (c==';' && t->vc_npar<NPAR-1) {
++ t->vc_npar++;
++ break;
++ } else if (c>='0' && c<='9') {
++ t->vc_par[t->vc_npar] *= 10;
++ t->vc_par[t->vc_npar] += c-'0';
++ break;
++ } else t->vc_state=ESgotpars;
++ case ESgotpars:
++ t->vc_state = ESnormal;
++ switch(c) {
++ case 'H': case 'f':
++ if (t->vc_par[0]) t->vc_par[0]--;
++ if (t->vc_par[1]) t->vc_par[1]--;
++ gotoxay(t, t->vc_par[1], t->vc_par[0]);
++ break;
++ case 'M':
++ hcon_scroll(hconp, 0, hcon_qydim(hconp), SM_UP, 1);
++ break;
++ }
+ break;
+ default:
+- if (t->backp == 0) {
+- t->backc = 1;
+- t->backp = data-1;
+- } else {
+- t->backc++;
+- }
+- if (t->vc_x + t->backc >= hcon_qxdim(hconp)) {
++ t->vc_state = ESnormal;
++ switch (c) {
++ case 0x07: /* Bell */
++ vcon_i_backflush(t);
++ break;
++ case 0x08: /* BS */
++ vcon_i_backflush(t);
++ if (t->vc_x > 0)
++ t->vc_x--;
++ break;
++ case 0x0A: /* Linefeed */
+ vcon_i_backflush(t);
+- t->vc_x = 0;
+ vcon_i_cursfeed(t);
++ break;
++ case 0x0D: /* Return */
++ vcon_i_backflush(t);
++ t->vc_x = 0;
++ break;
++ case 24: case 26:
++ vcon_i_backflush(t);
++ t->vc_state = ESnormal;
++ break;
++ case 27:
++ vcon_i_backflush(t);
++ t->vc_state = ESesc;
++ break;
++ default:
++ if (t->backp == 0) {
++ t->backc = 1;
++ t->backp = data-1;
++ } else {
++ t->backc++;
++ }
++ if (t->vc_x + t->backc >= hcon_qxdim(hconp)) {
++ vcon_i_backflush(t);
++ t->vc_x = 0;
++ vcon_i_cursfeed(t);
++ }
+ }
+ }
+ }
+diff -ruN proll_18.orig/src/vconsole.h proll-patch7/src/vconsole.h
+--- proll_18.orig/src/vconsole.h 1999-11-08 00:58:13.000000000 +0000
++++ proll-patch7/src/vconsole.h 2005-03-02 12:40:12.000000000 +0000
+@@ -6,6 +6,8 @@
+ #ifndef VCONSOLE_H
+ #define VCONSOLE_H
+
++#define NPAR 16
++
+ struct vconterm {
+ void *impl;
+
+@@ -13,6 +15,8 @@
+ int backc; /* Same, count */
+
+ int vc_x, vc_y; /* XXX Make vcon_xxx() to use cellmap->xpos_ */
++ int vc_state;
++ unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current escape sequence */
+ };
+
+ int vcon_init(struct vconterm *t, unsigned int a0);
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index bf28a3675..e6891ccbb 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -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;
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 4c65c64d6..9cb3de49a 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -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:
diff --git a/vl.c b/vl.c
index 9efb4f7da..a815a50fa 100644
--- a/vl.c
+++ b/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);
diff --git a/vl.h b/vl.h
index c8404e10e..5091ca14e 100644
--- a/vl.h
+++ b/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"