diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-03-13 09:43:36 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-03-13 09:43:36 +0000 |
commit | 6f7e9aec5eb5bdfa57a9e458e391b785c283a007 (patch) | |
tree | 8679501a365f5fa7ee5b4e6fdd8d6a4f6e92f679 /hw | |
parent | b756921ad18c8d293da634ff3b4e950ec8ae3f80 (diff) | |
download | hqemu-6f7e9aec5eb5bdfa57a9e458e391b785c283a007.zip hqemu-6f7e9aec5eb5bdfa57a9e458e391b785c283a007.tar.gz |
sparc fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1326 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'hw')
-rw-r--r-- | hw/esp.c | 192 | ||||
-rw-r--r-- | hw/fdc.c | 37 | ||||
-rw-r--r-- | hw/sun4m.c | 110 | ||||
-rw-r--r-- | hw/tcx.c | 129 |
4 files changed, 385 insertions, 83 deletions
diff --git a/hw/esp.c b/hw/esp.c new file mode 100644 index 0000000..2456c34 --- /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); +} + @@ -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 || @@ -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); } @@ -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); |