From 6f7e9aec5eb5bdfa57a9e458e391b785c283a007 Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 13 Mar 2005 09:43:36 +0000 Subject: [PATCH] sparc fixes (Blue Swirl) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1326 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile.target | 2 +- TODO | 1 - hw/esp.c | 192 ++++ hw/fdc.c | 37 +- hw/sun4m.c | 110 ++- hw/tcx.c | 129 ++- pc-bios/proll.elf | Bin 133338 -> 41236 bytes pc-bios/proll.patch | 1919 ++++++++++++++++++++++++++------------ target-sparc/helper.c | 18 +- target-sparc/op_helper.c | 4 +- vl.c | 10 +- vl.h | 5 +- 12 files changed, 1751 insertions(+), 676 deletions(-) create mode 100644 hw/esp.c diff --git a/Makefile.target b/Makefile.target index 5c82e38a60..68563299e7 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 cd38950544..088c26c69b 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 0000000000..2456c345fd --- /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 fc6b50257f..3890ace120 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 0af062d967..b186b23f13 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 6c4df7c89a..c0fddf31d7 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 e274b0d19361deb2959c9de7d7eb420ab4b14579..f960c83e61a3fea4336aecc7090dca5fb512db66 100644 GIT binary patch delta 8592 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 Ju^*zd{{^xqB!vI~ literal 133338 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∨KO=X!-RtFV^C-f>P$&Zau3 zJ^K%LP$ zvna*wzPOJxEHBR|lCdv;XcQs&E1HYiFAdZ*USP1L$Oi|){zhZ@S+*6#C696pIRszvk3WS*u< z;`&KFHbuu$>RyOsf~zD^iZBHSM^qAaoNBC6F@zL73z6lC;8v(KqyB`%#SO8!HyLvy z<33}!O&<#Wc%$n6DvyF@F0f0&ZHY4ENHUH!HM$3XkoWP*pd+TBG@K` zlJ7n!EsA|?N%tE-(TxTr-(f&Ak&}l@x~D)qN7!Zp>INqbm%{de@WYMv6FFpafXPy9 z04Np4{2@T`p!Hsjoi~1tH8T zJ6c|A#S3=A3e-SYf4OC_{&tgK{q5Gj`a78Y(uG9JZ6$!iy^@$?TLj`|ApD}OmkNXH zU>oZOu+hrZty|5imH*Y6wd7W;8dcmD@5pz;R~u0)&FqTxr*2QzUt&9~KipGH}^|-|x zdqI^nfB^&oZ^&`;lmuIqW-a<|9J4L zoPj(V^J3ENSr$`XZKzg}AO?58 z?%Y3m*DP`_C%#AIUjRE`}}ts@LdQwMrUe(3vJ1y>Fb9@+l2Z zs+BHHV?rB-ZcOp>VA4~%Wg@D@Z7QHg(em*Q%+H2*=f~7fsW4LRc7%oYJM1OlEQZ8S z8Kvqca%fxE`LcFD)}Uolu0?&YGK}wA+yg8yFSO*D#p diff --git a/pc-bios/proll.patch b/pc-bios/proll.patch index 18a157512a..5f2e027d49 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 . ++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 @@ -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 +#include /* 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,259 +860,97 @@ diff -ruN proll_18.orig/qemu/main.c proll-patch4/qemu/main.c + hw_idprom = va_prom; +} + +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-patch7/qemu/openprom.c 2005-03-02 20:09:57.000000000 +0000 +@@ -0,0 +1,646 @@ +/* -+ * 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. ++ * PROM interface support ++ * Copyright 1996 The Australian National University. ++ * Copyright 1996 Fujitsu Laboratories Limited ++ * Copyright 1999 Pete A. Zaitcev ++ * This software may be distributed under the terms of the Gnu ++ * Public License version 2 or later + */ -+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)); ++#include ++#include ++#include ++#include ++#include ++#include "phys_jj.h" + -+ pte = SRMMU_ET_PTD | (((unsigned int)l1 - PROLBASE + highbase) >> 4); -+ for (i = 0; i < NCTX_SWIFT; i++) { -+ ctp[i] = pte; -+ } ++//#define DEBUG_OBP + -+ 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; -+ } ++struct property { ++ const char *name; ++ const char *value; ++ const int length; ++}; + -+ /* 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; -+ } ++struct node { ++ const struct property *properties; ++ /* short */ const int sibling; ++ /* short */ const int child; ++}; + -+ 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. -+# ++static int obp_nextnode(int node); ++static int obp_child(int node); ++static int obp_proplen(int node, char *name); ++static int obp_getprop(int node, char *name, char *val); ++static int obp_setprop(int node, char *name, char *val, int len); ++static const char *obp_nextprop(int node, char *name); + -+CC = gcc ++static char obp_idprom[IDPROM_SIZE]; ++static const struct property null_properties = { NULL, NULL, -1 }; ++static const int prop_true = -1; + -+#CROSS = /usr/local/sparc/bin/sparc-sun-linux- -+CROSS = sparc-unknown-linux-gnu- ++static const struct property propv_root[] = { ++ {"name", "SUNW,JavaStation-1", sizeof("SUNW,JavaStation-1") }, ++ {"idprom", obp_idprom, IDPROM_SIZE}, ++ {"banner-name", "JavaStation", sizeof("JavaStation")}, ++ {"compatible", "sun4m", 6}, ++ {NULL, NULL, -1} ++}; + -+CROSSCC = $(CROSS)gcc -+CROSSLD = $(CROSS)ld -+CROSSNM = $(CROSS)nm ++static const int prop_iommu_reg[] = { ++ 0x0, 0x10000000, 0x00000300, ++}; ++static const struct property propv_iommu[] = { ++ {"name", "iommu", sizeof("iommu")}, ++ {"reg", (char*)&prop_iommu_reg[0], sizeof(prop_iommu_reg) }, ++ {NULL, NULL, -1} ++}; + -+RM = /bin/rm -f -+ELFTOAOUT = elftoaout ++static const int prop_sbus_ranges[] = { ++ 0x0, 0x0, 0x0, 0x30000000, 0x10000000, ++ 0x1, 0x0, 0x0, 0x40000000, 0x10000000, ++ 0x2, 0x0, 0x0, 0x50000000, 0x10000000, ++ 0x3, 0x0, 0x0, 0x60000000, 0x10000000, ++ 0x4, 0x0, 0x0, 0x70000000, 0x10000000, ++}; ++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} ++}; + -+# -+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 . -+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 ---- 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 @@ -+/* -+ * PROM interface support -+ * Copyright 1996 The Australian National University. -+ * Copyright 1996 Fujitsu Laboratories Limited -+ * Copyright 1999 Pete A. Zaitcev -+ * This software may be distributed under the terms of the Gnu -+ * Public License version 2 or later -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include "phys_jj.h" -+ -+struct property { -+ const char *name; -+ const char *value; -+ const int length; -+}; -+ -+struct node { -+ const struct property *properties; -+ /* short */ const int sibling; -+ /* short */ const int child; -+}; -+ -+static int obp_nextnode(int node); -+static int obp_child(int node); -+static int obp_proplen(int node, char *name); -+static int obp_getprop(int node, char *name, char *val); -+static int obp_setprop(int node, char *name, char *val, int len); -+static const char *obp_nextprop(int node, char *name); -+ -+static char obp_idprom[IDPROM_SIZE]; -+static const struct property null_properties = { NULL, NULL, -1 }; -+static const int prop_true = -1; -+ -+static const struct property propv_root[] = { -+ {"name", "SUNW,JavaStation-1", sizeof("SUNW,JavaStation-1") }, -+ {"idprom", obp_idprom, IDPROM_SIZE}, -+ {"banner-name", "JavaStation", sizeof("JavaStation")}, -+ {"compatible", "sun4m", 6}, -+ {NULL, NULL, -1} -+}; -+ -+static const int prop_iommu_reg[] = { -+ 0x0, 0x10000000, 0x00000300, -+}; -+static const struct property propv_iommu[] = { -+ {"name", "iommu", sizeof("iommu")}, -+ {"reg", (char*)&prop_iommu_reg[0], sizeof(prop_iommu_reg) }, -+ {NULL, NULL, -1} -+}; -+ -+static const int prop_sbus_ranges[] = { -+ 0x0, 0x0, 0x0, 0x30000000, 0x10000000, -+ 0x1, 0x0, 0x0, 0x40000000, 0x10000000, -+ 0x2, 0x0, 0x0, 0x50000000, 0x10000000, -+ 0x3, 0x0, 0x0, 0x60000000, 0x10000000, -+ 0x4, 0x0, 0x0, 0x70000000, 0x10000000, -+}; -+static const struct property propv_sbus[] = { -+ {"name", "sbus", 5}, -+ {"ranges", (char*)&prop_sbus_ranges[0], sizeof(prop_sbus_ranges)}, -+ {NULL, NULL, -1} -+}; -+ -+static const int prop_tcx_regs[] = { -+ 0x2, 0x00800000, 0x00100000, -+ 0x2, 0x02000000, 0x00000001, -+ 0x2, 0x04000000, 0x00800000, -+ 0x2, 0x06000000, 0x00800000, -+ 0x2, 0x0a000000, 0x00000001, -+ 0x2, 0x0c000000, 0x00000001, -+ 0x2, 0x0e000000, 0x00000001, -+ 0x2, 0x00700000, 0x00001000, -+ 0x2, 0x00200000, 0x00000004, -+ 0x2, 0x00300000, 0x0000081c, -+ 0x2, 0x00000000, 0x00010000, -+ 0x2, 0x00240000, 0x00000004, -+ 0x2, 0x00280000, 0x00000001, -+}; ++static const int prop_tcx_regs[] = { ++ 0x2, 0x00800000, 0x00100000, ++ 0x2, 0x02000000, 0x00000001, ++ 0x2, 0x04000000, 0x00800000, ++ 0x2, 0x06000000, 0x00800000, ++ 0x2, 0x0a000000, 0x00000001, ++ 0x2, 0x0c000000, 0x00000001, ++ 0x2, 0x0e000000, 0x00000001, ++ 0x2, 0x00700000, 0x00001000, ++ 0x2, 0x00200000, 0x00000004, ++ 0x2, 0x00300000, 0x0000081c, ++ 0x2, 0x00000000, 0x00010000, ++ 0x2, 0x00240000, 0x00000004, ++ 0x2, 0x00280000, 0x00000001, ++}; + +#if 1 /* Zaitcev */ +static const int pixfreq = 0x03dfd240; @@ -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,303 +1262,677 @@ 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); ++static void obp_reboot(char *); ++static void obp_abort(void); ++static void obp_halt(void); ++static int obp_devopen(char *str); ++static int obp_devclose(int dev_desc); ++static int obp_rdblkdev(int dev_desc, int num_blks, int blk_st, char *buf); ++ ++static void doublewalk(unsigned ptab1, unsigned va) ++{ ++unsigned int proc_tablewalk(int ctx, unsigned int va); ++unsigned int mem_tablewalk(unsigned int pa, unsigned int va); ++ ++ proc_tablewalk(0, va); ++ if (ptab1 != 0) mem_tablewalk(ptab1, va); ++} ++ ++static struct linux_romvec romvec0; ++ ++void * ++init_openprom_qemu(int bankc, struct bank *bankv, unsigned hiphybas, ++ const char *cmdline, char boot_device, int nographic) ++{ ++ int i; ++ ++ /* ++ * Avoid data segment allocations ++ */ ++ ptphys = totphys; ++ ptmap = totmap; ++ ptavail = totavail; ++ /* ++ * Form memory descriptors. ++ */ ++ for (i = 0; i < bankc; i++) { ++ totphys[i].theres_more = &totphys[i+1]; ++ totphys[i].start_adr = (char*) bankv[i].start; ++ totphys[i].num_bytes = bankv[i].length; ++ } ++ totphys[i-1].theres_more = 0; ++ ++ /* ++ * XXX Merged in normal PROM when full banks touch. ++ */ ++ for (i = 0; i < bankc; i++) { ++ unsigned bankbase = bankv[i].start; ++ unsigned banksize = bankv[i].length; ++ if (hiphybas > bankbase && ++ hiphybas < bankbase + banksize) { ++ banksize = hiphybas - bankbase; ++ } ++ totavail[i].theres_more = &totavail[i+1]; ++ totavail[i].start_adr = (char*) bankbase; ++ totavail[i].num_bytes = banksize; ++ } ++ totavail[i-1].theres_more = 0; ++ ++ totmap[0].theres_more = 0; ++ totmap[0].start_adr = (char*) PROLBASE; ++ totmap[0].num_bytes = PROLSIZE; ++ ++ /* ++ * idprom ++ */ ++ bcopy(idprom, obp_idprom, IDPROM_SIZE); ++ ++ // Linux wants a R/W romvec table ++ romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC; ++ romvec0.pv_plugin_revision = 77; ++ romvec0.pv_printrev = 0x10203; ++ romvec0.pv_v0mem.v0_totphys = &ptphys; ++ romvec0.pv_v0mem.v0_prommap = &ptmap; ++ 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 = (void (*)(int))obp_nbputchar; ++ romvec0.pv_nbgetchar = obp_nbgetchar; ++ romvec0.pv_nbputchar = obp_nbputchar; ++ romvec0.pv_reboot = obp_reboot; ++ romvec0.pv_abort = obp_abort; ++ 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; ++} ++ ++static const struct property *find_property(int node,char *name) ++{ ++ const struct property *prop = &nodes[node].properties[0]; ++ while (prop && prop->name) { ++ if (bcmp(prop->name, name, 128) == 0) return prop; ++ prop++; ++ } ++ return NULL; ++} ++ ++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) { ++#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; ++} ++ ++static int obp_getprop(int node, char *name, char *value) ++{ ++ const struct property *prop; ++ ++ prop = find_property(node,name); ++ if (prop) { ++ memcpy(value,prop->value,prop->length); ++#ifdef DEBUG_OBP ++ printk("obp_getprop(%d, %s) = %s\n", node, name, value); ++#endif ++ return prop->length; ++ } ++#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) { ++#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; ++} ++ ++static int obp_nbgetchar(void) { ++ extern struct vconterm dp0; ++ return vcon_getch(&dp0); ++} ++ ++static int obp_nbputchar(int ch) { ++ printk("%c", ch); ++ return 0; ++} ++ ++static void obp_reboot(char *str) { ++ printk("rebooting (%s): not implemented, freezing\n", str); ++ for (;;) {} ++} ++ ++static void obp_abort() { ++ printk("abort, freezing\n"); ++ for (;;) {} ++} ++ ++static void obp_halt() { ++ printk("halt, freezing\n"); ++ for (;;) {} ++} ++ ++static int obp_devopen(char *str) { ++#ifdef DEBUG_OBP ++ printk("open %s\n", str); ++#endif ++ return 0; ++} ++ ++static int obp_devclose(int 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) { ++#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/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 ++#include ++#include ++#ifndef NULL ++#define NULL ((void*)0) ++#endif ++ ++#include "pgtsrmmu.h" ++ ++#include "vconsole.h" ++#include /* Local copy of 2.2 style include */ ++#include /* __P() */ ++#include /* init_net() */ ++#include /* we are a provider for part of this. */ ++#include /* myipaddr */ ++#include ++#include /* 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; ++ } + -+static int obp_nbgetchar(void); -+static int obp_nbputchar(int ch); -+static void obp_reboot(char *); -+static void obp_abort(void); -+static void obp_halt(void); -+static int obp_devopen(char *str); -+static int obp_devclose(int dev_desc); -+static int obp_rdblkdev(int dev_desc, int num_blks, int blk_st, char *buf); ++ t->pctp = ctp; ++ t->pl1 = l1; ++ t->pbas = highbase; ++} + -+static void doublewalk(unsigned ptab1, unsigned va) ++/* ++ * 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 proc_tablewalk(int ctx, unsigned int va); -+unsigned int mem_tablewalk(unsigned int pa, unsigned int va); -+ -+ proc_tablewalk(0, va); -+ if (ptab1 != 0) mem_tablewalk(ptab1, va); -+} ++ 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() */ ++ } + -+#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); */ ++ 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); ++ } + -+#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 ++ 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; + -+static struct linux_romvec romvec0; ++drop: ++ return -1; ++} + -+void * -+init_openprom(int bankc, struct bank *bankv, unsigned hiphybas) ++/* ++ * Switch page tables. ++ */ ++void ++init_mmu_swift(unsigned int ctp_phy) +{ -+ int i; ++ unsigned int addr; + + /* -+ * Avoid data segment allocations -+ */ -+ ptphys = totphys; -+ ptmap = totmap; -+ ptavail = totavail; -+ /* -+ * Form memory descriptors. ++ * Flush cache + */ -+ for (i = 0; i < bankc; i++) { -+ totphys[i].theres_more = &totphys[i+1]; -+ totphys[i].start_adr = (char*) bankv[i].start; -+ totphys[i].num_bytes = bankv[i].length; ++ 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)); + } -+ totphys[i-1].theres_more = 0; + + /* -+ * XXX Merged in normal PROM when full banks touch. ++ * Switch ctx table + */ -+ for (i = 0; i < bankc; i++) { -+ unsigned bankbase = bankv[i].start; -+ unsigned banksize = bankv[i].length; -+ if (hiphybas > bankbase && -+ hiphybas < bankbase + banksize) { -+ banksize = hiphybas - bankbase; -+ } -+ totavail[i].theres_more = &totavail[i+1]; -+ totavail[i].start_adr = (char*) bankbase; -+ totavail[i].num_bytes = banksize; -+ } -+ totavail[i-1].theres_more = 0; -+ -+ totmap[0].theres_more = 0; -+ totmap[0].start_adr = (char*) PROLBASE; -+ totmap[0].num_bytes = PROLSIZE; ++ 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)); + + /* -+ * idprom ++ * Flush old page table references + */ -+ bcopy(idprom, obp_idprom, IDPROM_SIZE); -+ -+ // Linux wants a R/W romvec table -+ romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC; -+ romvec0.pv_plugin_revision = 77; -+ romvec0.pv_printrev = 0x10203; -+ romvec0.pv_v0mem.v0_totphys = &ptphys; -+ romvec0.pv_v0mem.v0_prommap = &ptmap; -+ romvec0.pv_v0mem.v0_available = &ptavail; -+ romvec0.pv_nodeops = &nodeops0; -+ romvec0.pv_bootstr = (void *)doublewalk; -+ romvec0.pv_stdin = &obp_stdin; -+ romvec0.pv_stdout = &obp_stdout; -+ romvec0.pv_getchar = obp_nbgetchar; -+ romvec0.pv_putchar = obp_nbputchar; -+ romvec0.pv_nbgetchar = obp_nbgetchar; -+ romvec0.pv_nbputchar = obp_nbputchar; -+ romvec0.pv_reboot = obp_reboot; -+ romvec0.pv_abort = obp_abort; -+ romvec0.pv_halt = obp_halt; -+ romvec0.pv_synchook = &synch_hook; -+ romvec0.pv_v0bootargs = &obp_argp; -+ return &romvec0; ++ __asm__ __volatile__ ("sta %%g0, [%0] %1\n\t" : : ++ "r" (0x400), "i" (ASI_M_FLUSH_PROBE) : "memory"); +} + -+static const struct property *find_property(int node,char *name) -+{ -+ const struct property *prop = &nodes[node].properties[0]; -+ while (prop && prop->name) { -+ if (bcmp(prop->name, name, 128) == 0) return prop; -+ prop++; ++/* ++ * 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; + } -+ return NULL; ++ if ((p = timers.tail) != NULL) { ++ timer->prev = p; ++ p->next = timer; ++ timers.tail = timer; ++ } else { ++ timers.head = timer; ++ timers.tail = timer; ++ } ++ return; +} + -+static int obp_nextnode(int node) -+{ -+ return nodes[node].sibling; ++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; +} + -+static int obp_child(int node) -+{ -+ return nodes[node].child; ++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; ++ } ++ } +} + -+static int obp_proplen(int node, char *name) ++/* ++ * Allocate memory. This is reusable. ++ */ ++void mem_init(struct mem *t, char *begin, char *limit) +{ -+ const struct property *prop = find_property(node,name); -+ if (prop) return prop->length; -+ return -1; ++ t->start = begin; ++ t->uplim = limit; ++ t->curp = begin; +} + -+static int obp_getprop(int node, char *name, char *value) ++void mem_fini(struct mem *t) +{ -+ const struct property *prop; -+ -+ prop = find_property(node,name); -+ if (prop) { -+ memcpy(value,prop->value,prop->length); -+ //printk("obp_getprop '%s'= %s\n", name, value); -+ return prop->length; -+ } -+ //printk("obp_getprop: not found\n"); -+ return -1; ++ t->curp = 0; +} + -+static int obp_setprop(int node, char *name, char *value, int len) ++void *mem_alloc(struct mem *t, int size, int align) +{ -+ return -1; -+} ++ char *p; + -+static const char *obp_nextprop(int node,char *name) -+{ -+ const struct property *prop = find_property(node,name); -+ if (prop) return prop[1].name; -+ return NULL; ++ 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; +} + -+#if 0 -+static unsigned char calc_idprom_cksum(struct idprom *idprom) ++void *mem_zalloc(struct mem *t, int size, int align) +{ -+ unsigned char cksum, i, *ptr = (unsigned char *)idprom; -+ -+ for (i = cksum = 0; i <= 0x0E; i++) -+ cksum ^= *ptr++; ++ char *p; + -+ return cksum; ++ if ((p = mem_alloc(t, size, align)) != 0) bzero(p, size); ++ return p; +} -+#endif + -+static int obp_nbgetchar(void) { -+ return -1; ++/* ++ * Library functions ++ */ ++void bzero(void *s, int len) { ++ while (len--) *((char *)s)++ = 0; +} + -+static int obp_nbputchar(int ch) { -+ extern struct vconterm dp0; -+ char buf = ch; ++void bcopy(const void *f, void *t, int len) { ++ while (len--) *((char *)t)++ = *((char *)f)++; ++} + -+ /* We do not use printk() in order to reduce stack depth. */ -+ vcon_write(&dp0, &buf, 1); ++/* 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; +} + -+static void obp_reboot(char *str) { -+ printk("rebooting (%s): not implemented, freezing\n", str); -+ for (;;) {} ++int strlen(const char *s) { ++ const char *p; ++ for (p = s; *p != 0; p++) { } ++ return p - s; +} + -+static void obp_abort() { -+ printk("abort, freezing\n"); -+ for (;;) {} -+} ++extern void *printk_fn; + -+static void obp_halt() { -+ printk("halt, freezing\n"); -+ for (;;) {} ++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); +} + -+static int obp_devopen(char *str) { -+ //printk("open %s\n", str); -+ return 0; ++void fatal() ++{ ++ printk("fatal."); ++loop: goto loop; +} + -+static int obp_devclose(int dev_desc) { -+ //printk("close %d\n", dev_desc); -+ return 0; ++/* ++ * 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; +} + -+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); -+ //buf[8] = 'L'; -+ return num_blks; ++/* ++ */ ++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; +} -diff -ruN proll_18.orig/src/arp.c proll-patch4/src/arp.c ++ ++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 ++ ++#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_nparvc_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 bf28a36756..e6891ccbb1 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 4c65c64d67..9cb3de49ac 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 9efb4f7daa..a815a50fa8 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 c8404e10e5..5091ca14e7 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" -- 2.39.2