r2300 - in trunk/src/host/qemu-neo1973: . hw linux-user
andrew at sita.openmoko.org
andrew at sita.openmoko.org
Mon Jun 18 22:42:04 CEST 2007
Author: andrew
Date: 2007-06-18 22:41:58 +0200 (Mon, 18 Jun 2007)
New Revision: 2300
Added:
trunk/src/host/qemu-neo1973/hw/mcf5208.c
trunk/src/host/qemu-neo1973/hw/mcf_fec.c
trunk/src/host/qemu-neo1973/hw/mcf_intc.c
trunk/src/host/qemu-neo1973/hw/mcf_uart.c
trunk/src/host/qemu-neo1973/hw/pixel_ops.h
trunk/src/host/qemu-neo1973/hw/usb-wacom.c
trunk/src/host/qemu-neo1973/linux-user/errno_defs.h
trunk/src/host/qemu-neo1973/m68k-semi.c
trunk/src/host/qemu-neo1973/mips.ld
trunk/src/host/qemu-neo1973/mipsel.ld
trunk/src/host/qemu-neo1973/softmmu-semi.h
Removed:
trunk/src/host/qemu-neo1973/linux-user/m68k-semi.c
Log:
Add missing files (thanks to Nesquick for reporting).
Added: trunk/src/host/qemu-neo1973/hw/mcf5208.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mcf5208.c 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/hw/mcf5208.c 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,305 @@
+/*
+ * Motorola ColdFire MCF5208 SoC emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licenced under the GPL
+ */
+#include "vl.h"
+
+#define SYS_FREQ 66000000
+
+#define PCSR_EN 0x0001
+#define PCSR_RLD 0x0002
+#define PCSR_PIF 0x0004
+#define PCSR_PIE 0x0008
+#define PCSR_OVW 0x0010
+#define PCSR_DBG 0x0020
+#define PCSR_DOZE 0x0040
+#define PCSR_PRE_SHIFT 8
+#define PCSR_PRE_MASK 0x0f00
+
+typedef struct {
+ qemu_irq irq;
+ ptimer_state *timer;
+ uint16_t pcsr;
+ uint16_t pmr;
+ uint16_t pcntr;
+} m5208_timer_state;
+
+static void m5208_timer_update(m5208_timer_state *s)
+{
+ if ((s->pcsr & (PCSR_PIE | PCSR_PIF)) == (PCSR_PIE | PCSR_PIF))
+ qemu_irq_raise(s->irq);
+ else
+ qemu_irq_lower(s->irq);
+}
+
+static void m5208_timer_write(m5208_timer_state *s, int offset,
+ uint32_t value)
+{
+ int prescale;
+ int limit;
+ switch (offset) {
+ case 0:
+ /* The PIF bit is set-to-clear. */
+ if (value & PCSR_PIF) {
+ s->pcsr &= ~PCSR_PIF;
+ value &= ~PCSR_PIF;
+ }
+ /* Avoid frobbing the timer if we're just twiddling IRQ bits. */
+ if (((s->pcsr ^ value) & ~PCSR_PIE) == 0) {
+ s->pcsr = value;
+ m5208_timer_update(s);
+ return;
+ }
+
+ if (s->pcsr & PCSR_EN)
+ ptimer_stop(s->timer);
+
+ s->pcsr = value;
+
+ prescale = 1 << ((s->pcsr & PCSR_PRE_MASK) >> PCSR_PRE_SHIFT);
+ ptimer_set_freq(s->timer, (SYS_FREQ / 2) / prescale);
+ if (s->pcsr & PCSR_RLD)
+ limit = s->pmr;
+ else
+ limit = 0xffff;
+ ptimer_set_limit(s->timer, limit, 0);
+
+ if (s->pcsr & PCSR_EN)
+ ptimer_run(s->timer, 0);
+ break;
+ case 2:
+ s->pmr = value;
+ s->pcsr &= ~PCSR_PIF;
+ if ((s->pcsr & PCSR_RLD) == 0) {
+ if (s->pcsr & PCSR_OVW)
+ ptimer_set_count(s->timer, value);
+ } else {
+ ptimer_set_limit(s->timer, value, s->pcsr & PCSR_OVW);
+ }
+ break;
+ case 4:
+ break;
+ default:
+ /* Should never happen. */
+ abort();
+ }
+ m5208_timer_update(s);
+}
+
+static void m5208_timer_trigger(void *opaque)
+{
+ m5208_timer_state *s = (m5208_timer_state *)opaque;
+ s->pcsr |= PCSR_PIF;
+ m5208_timer_update(s);
+}
+
+typedef struct {
+ m5208_timer_state timer[2];
+} m5208_sys_state;
+
+static uint32_t m5208_sys_read(void *opaque, target_phys_addr_t addr)
+{
+ m5208_sys_state *s = (m5208_sys_state *)opaque;
+ switch (addr) {
+ /* PIT0 */
+ case 0xfc080000:
+ return s->timer[0].pcsr;
+ case 0xfc080002:
+ return s->timer[0].pmr;
+ case 0xfc080004:
+ return ptimer_get_count(s->timer[0].timer);
+ /* PIT1 */
+ case 0xfc084000:
+ return s->timer[1].pcsr;
+ case 0xfc084002:
+ return s->timer[1].pmr;
+ case 0xfc084004:
+ return ptimer_get_count(s->timer[1].timer);
+
+ /* SDRAM Controller. */
+ case 0xfc0a8110: /* SDCS0 */
+ {
+ int n;
+ for (n = 0; n < 32; n++) {
+ if (ram_size < (2u << n))
+ break;
+ }
+ return (n - 1) | 0x40000000;
+ }
+ case 0xfc0a8114: /* SDCS1 */
+ return 0;
+
+ default:
+ cpu_abort(cpu_single_env, "m5208_sys_read: Bad offset 0x%x\n",
+ (int)addr);
+ return 0;
+ }
+}
+
+static void m5208_sys_write(void *opaque, target_phys_addr_t addr,
+ uint32_t value)
+{
+ m5208_sys_state *s = (m5208_sys_state *)opaque;
+ switch (addr) {
+ /* PIT0 */
+ case 0xfc080000:
+ case 0xfc080002:
+ case 0xfc080004:
+ m5208_timer_write(&s->timer[0], addr & 0xf, value);
+ return;
+ /* PIT1 */
+ case 0xfc084000:
+ case 0xfc084002:
+ case 0xfc084004:
+ m5208_timer_write(&s->timer[1], addr & 0xf, value);
+ return;
+ default:
+ cpu_abort(cpu_single_env, "m5208_sys_write: Bad offset 0x%x\n",
+ (int)addr);
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *m5208_sys_readfn[] = {
+ m5208_sys_read,
+ m5208_sys_read,
+ m5208_sys_read
+};
+
+static CPUWriteMemoryFunc *m5208_sys_writefn[] = {
+ m5208_sys_write,
+ m5208_sys_write,
+ m5208_sys_write
+};
+
+static void mcf5208_sys_init(qemu_irq *pic)
+{
+ int iomemtype;
+ m5208_sys_state *s;
+ QEMUBH *bh;
+ int i;
+
+ s = (m5208_sys_state *)qemu_mallocz(sizeof(m5208_sys_state));
+ iomemtype = cpu_register_io_memory(0, m5208_sys_readfn,
+ m5208_sys_writefn, s);
+ /* SDRAMC. */
+ cpu_register_physical_memory(0xfc0a8000, 0x00004000, iomemtype);
+ /* Timers. */
+ for (i = 0; i < 2; i++) {
+ bh = qemu_bh_new(m5208_timer_trigger, &s->timer[i]);
+ s->timer[i].timer = ptimer_init(bh);
+ cpu_register_physical_memory(0xfc080000 + 0x4000 * i, 0x00004000,
+ iomemtype);
+ s->timer[i].irq = pic[4 + i];
+ }
+}
+
+static void mcf5208evb_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename, const char *cpu_model)
+{
+ CPUState *env;
+ int kernel_size;
+ uint64_t elf_entry;
+ target_ulong entry;
+ qemu_irq *pic;
+
+ env = cpu_init();
+ if (!cpu_model)
+ cpu_model = "m5208";
+ if (cpu_m68k_set_model(env, cpu_model)) {
+ cpu_abort(env, "Unable to find m68k CPU definition\n");
+ }
+
+ /* Initialize CPU registers. */
+ env->vbr = 0;
+ /* TODO: Configure BARs. */
+
+ /* DRAM at 0x20000000 */
+ cpu_register_physical_memory(0x40000000, ram_size,
+ qemu_ram_alloc(ram_size) | IO_MEM_RAM);
+
+ /* Internal SRAM. */
+ cpu_register_physical_memory(0x80000000, 16384,
+ qemu_ram_alloc(16384) | IO_MEM_RAM);
+
+ /* Internal peripherals. */
+ pic = mcf_intc_init(0xfc048000, env);
+
+ mcf_uart_mm_init(0xfc060000, pic[26], serial_hds[0]);
+ mcf_uart_mm_init(0xfc064000, pic[27], serial_hds[1]);
+ mcf_uart_mm_init(0xfc068000, pic[28], serial_hds[2]);
+
+ mcf5208_sys_init(pic);
+
+ if (nb_nics > 1) {
+ fprintf(stderr, "Too many NICs\n");
+ exit(1);
+ }
+ if (nd_table[0].vlan) {
+ if (nd_table[0].model == NULL
+ || strcmp(nd_table[0].model, "mcf_fec") == 0) {
+ mcf_fec_init(&nd_table[0], 0xfc030000, pic + 36);
+ } else if (strcmp(nd_table[0].model, "?") == 0) {
+ fprintf(stderr, "qemu: Supported NICs: mcf_fec\n");
+ exit (1);
+ } else {
+ fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model);
+ exit (1);
+ }
+ }
+
+ /* 0xfc000000 SCM. */
+ /* 0xfc004000 XBS. */
+ /* 0xfc008000 FlexBus CS. */
+ /* 0xfc030000 FEC. */
+ /* 0xfc040000 SCM + Power management. */
+ /* 0xfc044000 eDMA. */
+ /* 0xfc048000 INTC. */
+ /* 0xfc058000 I2C. */
+ /* 0xfc05c000 QSPI. */
+ /* 0xfc060000 UART0. */
+ /* 0xfc064000 UART0. */
+ /* 0xfc068000 UART0. */
+ /* 0xfc070000 DMA timers. */
+ /* 0xfc080000 PIT0. */
+ /* 0xfc084000 PIT1. */
+ /* 0xfc088000 EPORT. */
+ /* 0xfc08c000 Watchdog. */
+ /* 0xfc090000 clock module. */
+ /* 0xfc0a0000 CCM + reset. */
+ /* 0xfc0a4000 GPIO. */
+ /* 0xfc0a8000 SDRAM controller. */
+
+ /* Load kernel. */
+ if (!kernel_filename) {
+ fprintf(stderr, "Kernel image must be specified\n");
+ exit(1);
+ }
+
+ kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
+ entry = elf_entry;
+ if (kernel_size < 0) {
+ kernel_size = load_uboot(kernel_filename, &entry, NULL);
+ }
+ if (kernel_size < 0) {
+ kernel_size = load_image(kernel_filename, phys_ram_base);
+ entry = 0x20000000;
+ }
+ if (kernel_size < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename);
+ exit(1);
+ }
+
+ env->pc = entry;
+}
+
+QEMUMachine mcf5208evb_machine = {
+ "mcf5208evb",
+ "MCF5206EVB",
+ mcf5208evb_init,
+};
Added: trunk/src/host/qemu-neo1973/hw/mcf_fec.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mcf_fec.c 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/hw/mcf_fec.c 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,456 @@
+/*
+ * ColdFire Fast Ethernet Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licenced under the GPL
+ */
+#include "vl.h"
+/* For crc32 */
+#include <zlib.h>
+
+//#define DEBUG_FEC 1
+
+#ifdef DEBUG_FEC
+#define DPRINTF(fmt, args...) \
+do { printf("mcf_fec: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+#define FEC_MAX_FRAME_SIZE 2032
+
+typedef struct {
+ qemu_irq *irq;
+ VLANClientState *vc;
+ uint32_t irq_state;
+ uint32_t eir;
+ uint32_t eimr;
+ int rx_enabled;
+ uint32_t rx_descriptor;
+ uint32_t tx_descriptor;
+ uint32_t ecr;
+ uint32_t mmfr;
+ uint32_t mscr;
+ uint32_t rcr;
+ uint32_t tcr;
+ uint32_t tfwr;
+ uint32_t rfsr;
+ uint32_t erdsr;
+ uint32_t etdsr;
+ uint32_t emrbr;
+ uint8_t macaddr[6];
+} mcf_fec_state;
+
+#define FEC_INT_HB 0x80000000
+#define FEC_INT_BABR 0x40000000
+#define FEC_INT_BABT 0x20000000
+#define FEC_INT_GRA 0x10000000
+#define FEC_INT_TXF 0x08000000
+#define FEC_INT_TXB 0x04000000
+#define FEC_INT_RXF 0x02000000
+#define FEC_INT_RXB 0x01000000
+#define FEC_INT_MII 0x00800000
+#define FEC_INT_EB 0x00400000
+#define FEC_INT_LC 0x00200000
+#define FEC_INT_RL 0x00100000
+#define FEC_INT_UN 0x00080000
+
+#define FEC_EN 2
+#define FEC_RESET 1
+
+/* Map interrupt flags onto IRQ lines. */
+#define FEC_NUM_IRQ 13
+static const uint32_t mcf_fec_irq_map[FEC_NUM_IRQ] = {
+ FEC_INT_TXF,
+ FEC_INT_TXB,
+ FEC_INT_UN,
+ FEC_INT_RL,
+ FEC_INT_RXF,
+ FEC_INT_RXB,
+ FEC_INT_MII,
+ FEC_INT_LC,
+ FEC_INT_HB,
+ FEC_INT_GRA,
+ FEC_INT_EB,
+ FEC_INT_BABT,
+ FEC_INT_BABR
+};
+
+/* Buffer Descriptor. */
+typedef struct {
+ uint16_t flags;
+ uint16_t length;
+ uint32_t data;
+} mcf_fec_bd;
+
+#define FEC_BD_R 0x8000
+#define FEC_BD_E 0x8000
+#define FEC_BD_O1 0x4000
+#define FEC_BD_W 0x2000
+#define FEC_BD_O2 0x1000
+#define FEC_BD_L 0x0800
+#define FEC_BD_TC 0x0400
+#define FEC_BD_ABC 0x0200
+#define FEC_BD_M 0x0100
+#define FEC_BD_BC 0x0080
+#define FEC_BD_MC 0x0040
+#define FEC_BD_LG 0x0020
+#define FEC_BD_NO 0x0010
+#define FEC_BD_CR 0x0004
+#define FEC_BD_OV 0x0002
+#define FEC_BD_TR 0x0001
+
+static void mcf_fec_read_bd(mcf_fec_bd *bd, uint32_t addr)
+{
+ cpu_physical_memory_read(addr, (uint8_t *)bd, sizeof(*bd));
+ be16_to_cpus(&bd->flags);
+ be16_to_cpus(&bd->length);
+ be32_to_cpus(&bd->data);
+}
+
+static void mcf_fec_write_bd(mcf_fec_bd *bd, uint32_t addr)
+{
+ mcf_fec_bd tmp;
+ tmp.flags = cpu_to_be16(bd->flags);
+ tmp.length = cpu_to_be16(bd->length);
+ tmp.data = cpu_to_be32(bd->data);
+ cpu_physical_memory_write(addr, (uint8_t *)&tmp, sizeof(tmp));
+}
+
+static void mcf_fec_update(mcf_fec_state *s)
+{
+ uint32_t active;
+ uint32_t changed;
+ uint32_t mask;
+ int i;
+
+ active = s->eir & s->eimr;
+ changed = active ^s->irq_state;
+ for (i = 0; i < FEC_NUM_IRQ; i++) {
+ mask = mcf_fec_irq_map[i];
+ if (changed & mask) {
+ DPRINTF("IRQ %d = %d\n", i, (active & mask) != 0);
+ qemu_set_irq(s->irq[i], (active & mask) != 0);
+ }
+ }
+ s->irq_state = active;
+}
+
+static void mcf_fec_do_tx(mcf_fec_state *s)
+{
+ uint32_t addr;
+ mcf_fec_bd bd;
+ int frame_size;
+ int len;
+ uint8_t frame[FEC_MAX_FRAME_SIZE];
+ uint8_t *ptr;
+
+ DPRINTF("do_tx\n");
+ ptr = frame;
+ frame_size = 0;
+ addr = s->tx_descriptor;
+ while (1) {
+ mcf_fec_read_bd(&bd, addr);
+ DPRINTF("tx_bd %x flags %04x len %d data %08x\n",
+ addr, bd.flags, bd.length, bd.data);
+ if ((bd.flags & FEC_BD_R) == 0) {
+ /* Run out of descriptors to transmit. */
+ break;
+ }
+ len = bd.length;
+ if (frame_size + len > FEC_MAX_FRAME_SIZE) {
+ len = FEC_MAX_FRAME_SIZE - frame_size;
+ s->eir |= FEC_INT_BABT;
+ }
+ cpu_physical_memory_read(bd.data, ptr, len);
+ ptr += len;
+ frame_size += len;
+ if (bd.flags & FEC_BD_L) {
+ /* Last buffer in frame. */
+ DPRINTF("Sending packet\n");
+ qemu_send_packet(s->vc, frame, len);
+ ptr = frame;
+ frame_size = 0;
+ s->eir |= FEC_INT_TXF;
+ }
+ s->eir |= FEC_INT_TXB;
+ bd.flags &= ~FEC_BD_R;
+ /* Write back the modified descriptor. */
+ mcf_fec_write_bd(&bd, addr);
+ /* Advance to the next descriptor. */
+ if ((bd.flags & FEC_BD_W) != 0) {
+ addr = s->etdsr;
+ } else {
+ addr += 8;
+ }
+ }
+ s->tx_descriptor = addr;
+}
+
+static void mcf_fec_enable_rx(mcf_fec_state *s)
+{
+ mcf_fec_bd bd;
+
+ mcf_fec_read_bd(&bd, s->rx_descriptor);
+ s->rx_enabled = ((bd.flags & FEC_BD_E) != 0);
+ if (!s->rx_enabled)
+ DPRINTF("RX buffer full\n");
+}
+
+static void mcf_fec_reset(mcf_fec_state *s)
+{
+ s->eir = 0;
+ s->eimr = 0;
+ s->rx_enabled = 0;
+ s->ecr = 0;
+ s->mscr = 0;
+ s->rcr = 0x05ee0001;
+ s->tcr = 0;
+ s->tfwr = 0;
+ s->rfsr = 0x500;
+}
+
+static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr)
+{
+ mcf_fec_state *s = (mcf_fec_state *)opaque;
+ switch (addr & 0x3ff) {
+ case 0x004: return s->eir;
+ case 0x008: return s->eimr;
+ case 0x010: return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
+ case 0x014: return 0; /* TDAR */
+ case 0x024: return s->ecr;
+ case 0x040: return s->mmfr;
+ case 0x044: return s->mscr;
+ case 0x064: return 0; /* MIBC */
+ case 0x084: return s->rcr;
+ case 0x0c4: return s->tcr;
+ case 0x0e4: /* PALR */
+ return (s->macaddr[0] << 24) | (s->macaddr[1] << 16)
+ | (s->macaddr[2] << 8) | s->macaddr[3];
+ break;
+ case 0x0e8: /* PAUR */
+ return (s->macaddr[4] << 24) | (s->macaddr[5] << 16) | 0x8808;
+ case 0x0ec: return 0x10000; /* OPD */
+ case 0x118: return 0;
+ case 0x11c: return 0;
+ case 0x120: return 0;
+ case 0x124: return 0;
+ case 0x144: return s->tfwr;
+ case 0x14c: return 0x600;
+ case 0x150: return s->rfsr;
+ case 0x180: return s->erdsr;
+ case 0x184: return s->etdsr;
+ case 0x188: return s->emrbr;
+ default:
+ cpu_abort(cpu_single_env, "mcf_fec_read: Bad address 0x%x\n",
+ (int)addr);
+ return 0;
+ }
+}
+
+void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ mcf_fec_state *s = (mcf_fec_state *)opaque;
+ switch (addr & 0x3ff) {
+ case 0x004:
+ s->eir &= ~value;
+ break;
+ case 0x008:
+ s->eimr = value;
+ break;
+ case 0x010: /* RDAR */
+ if ((s->ecr & FEC_EN) && !s->rx_enabled) {
+ DPRINTF("RX enable\n");
+ mcf_fec_enable_rx(s);
+ }
+ break;
+ case 0x014: /* TDAR */
+ if (s->ecr & FEC_EN) {
+ mcf_fec_do_tx(s);
+ }
+ break;
+ case 0x024:
+ s->ecr = value;
+ if (value & FEC_RESET) {
+ DPRINTF("Reset\n");
+ mcf_fec_reset(s);
+ }
+ if ((s->ecr & FEC_EN) == 0) {
+ s->rx_enabled = 0;
+ }
+ break;
+ case 0x040:
+ /* TODO: Implement MII. */
+ s->mmfr = value;
+ break;
+ case 0x044:
+ s->mscr = value & 0xfe;
+ break;
+ case 0x064:
+ /* TODO: Implement MIB. */
+ break;
+ case 0x084:
+ s->rcr = value & 0x07ff003f;
+ /* TODO: Implement LOOP mode. */
+ break;
+ case 0x0c4: /* TCR */
+ /* We transmit immediately, so raise GRA immediately. */
+ s->tcr = value;
+ if (value & 1)
+ s->eir |= FEC_INT_GRA;
+ break;
+ case 0x0e4: /* PALR */
+ s->macaddr[0] = value >> 24;
+ s->macaddr[1] = value >> 16;
+ s->macaddr[2] = value >> 8;
+ s->macaddr[3] = value;
+ break;
+ case 0x0e8: /* PAUR */
+ s->macaddr[4] = value >> 24;
+ s->macaddr[5] = value >> 16;
+ break;
+ case 0x0ec:
+ /* OPD */
+ break;
+ case 0x118:
+ case 0x11c:
+ case 0x120:
+ case 0x124:
+ /* TODO: implement MAC hash filtering. */
+ break;
+ case 0x144:
+ s->tfwr = value & 3;
+ break;
+ case 0x14c:
+ /* FRBR writes ignored. */
+ break;
+ case 0x150:
+ s->rfsr = (value & 0x3fc) | 0x400;
+ break;
+ case 0x180:
+ s->erdsr = value & ~3;
+ s->rx_descriptor = s->erdsr;
+ break;
+ case 0x184:
+ s->etdsr = value & ~3;
+ s->tx_descriptor = s->etdsr;
+ break;
+ case 0x188:
+ s->emrbr = value & 0x7f0;
+ break;
+ default:
+ cpu_abort(cpu_single_env, "mcf_fec_write Bad address 0x%x\n",
+ (int)addr);
+ }
+ mcf_fec_update(s);
+}
+
+static int mcf_fec_can_receive(void *opaque)
+{
+ mcf_fec_state *s = (mcf_fec_state *)opaque;
+ return s->rx_enabled;
+}
+
+static void mcf_fec_receive(void *opaque, const uint8_t *buf, int size)
+{
+ mcf_fec_state *s = (mcf_fec_state *)opaque;
+ mcf_fec_bd bd;
+ uint32_t flags = 0;
+ uint32_t addr;
+ uint32_t crc;
+ uint32_t buf_addr;
+ uint8_t *crc_ptr;
+ unsigned int buf_len;
+
+ DPRINTF("do_rx len %d\n", size);
+ if (!s->rx_enabled) {
+ fprintf(stderr, "mcf_fec_receive: Unexpected packet\n");
+ }
+ /* 4 bytes for the CRC. */
+ size += 4;
+ crc = cpu_to_be32(crc32(~0, buf, size));
+ crc_ptr = (uint8_t *)&crc;
+ /* Huge frames are truncted. */
+ if (size > FEC_MAX_FRAME_SIZE) {
+ size = FEC_MAX_FRAME_SIZE;
+ flags |= FEC_BD_TR | FEC_BD_LG;
+ }
+ /* Frames larger than the user limit just set error flags. */
+ if (size > (s->rcr >> 16)) {
+ flags |= FEC_BD_LG;
+ }
+ addr = s->rx_descriptor;
+ while (size > 0) {
+ mcf_fec_read_bd(&bd, addr);
+ if ((bd.flags & FEC_BD_E) == 0) {
+ /* No descriptors available. Bail out. */
+ /* FIXME: This is wrong. We should probably either save the
+ remainder for when more RX buffers are available, or
+ flag an error. */
+ fprintf(stderr, "mcf_fec: Lost end of frame\n");
+ break;
+ }
+ buf_len = (size <= s->emrbr) ? size: s->emrbr;
+ bd.length = buf_len;
+ size -= buf_len;
+ DPRINTF("rx_bd %x length %d\n", addr, bd.length);
+ /* The last 4 bytes are the CRC. */
+ if (size < 4)
+ buf_len += size - 4;
+ buf_addr = bd.data;
+ cpu_physical_memory_write(buf_addr, buf, buf_len);
+ buf += buf_len;
+ if (size < 4) {
+ cpu_physical_memory_write(buf_addr + buf_len, crc_ptr, 4 - size);
+ crc_ptr += 4 - size;
+ }
+ bd.flags &= ~FEC_BD_E;
+ if (size == 0) {
+ /* Last buffer in frame. */
+ bd.flags |= flags | FEC_BD_L;
+ DPRINTF("rx frame flags %04x\n", bd.flags);
+ s->eir |= FEC_INT_RXF;
+ } else {
+ s->eir |= FEC_INT_RXB;
+ }
+ mcf_fec_write_bd(&bd, addr);
+ /* Advance to the next descriptor. */
+ if ((bd.flags & FEC_BD_W) != 0) {
+ addr = s->erdsr;
+ } else {
+ addr += 8;
+ }
+ }
+ s->rx_descriptor = addr;
+ mcf_fec_enable_rx(s);
+ mcf_fec_update(s);
+}
+
+static CPUReadMemoryFunc *mcf_fec_readfn[] = {
+ mcf_fec_read,
+ mcf_fec_read,
+ mcf_fec_read
+};
+
+static CPUWriteMemoryFunc *mcf_fec_writefn[] = {
+ mcf_fec_write,
+ mcf_fec_write,
+ mcf_fec_write
+};
+
+void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
+{
+ mcf_fec_state *s;
+ int iomemtype;
+
+ s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
+ s->irq = irq;
+ iomemtype = cpu_register_io_memory(0, mcf_fec_readfn,
+ mcf_fec_writefn, s);
+ cpu_register_physical_memory(base, 0x400, iomemtype);
+
+ s->vc = qemu_new_vlan_client(nd->vlan, mcf_fec_receive,
+ mcf_fec_can_receive, s);
+ memcpy(s->macaddr, nd->macaddr, 6);
+}
Added: trunk/src/host/qemu-neo1973/hw/mcf_intc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mcf_intc.c 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/hw/mcf_intc.c 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,156 @@
+/*
+ * ColdFire Interrupt Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licenced under the GPL
+ */
+#include "vl.h"
+
+typedef struct {
+ uint64_t ipr;
+ uint64_t imr;
+ uint64_t ifr;
+ uint64_t enabled;
+ uint8_t icr[64];
+ CPUState *env;
+ int active_vector;
+} mcf_intc_state;
+
+static void mcf_intc_update(mcf_intc_state *s)
+{
+ uint64_t active;
+ int i;
+ int best;
+ int best_level;
+
+ active = (s->ipr | s->ifr) & s->enabled & ~s->imr;
+ best_level = 0;
+ best = 64;
+ if (active) {
+ for (i = 0; i < 64; i++) {
+ if ((active & 1) != 0 && s->icr[i] >= best_level) {
+ best_level = s->icr[i];
+ best = i;
+ }
+ active >>= 1;
+ }
+ }
+ s->active_vector = ((best == 64) ? 24 : (best + 64));
+ m68k_set_irq_level(s->env, best_level, s->active_vector);
+}
+
+static uint32_t mcf_intc_read(void *opaque, target_phys_addr_t addr)
+{
+ int offset;
+ mcf_intc_state *s = (mcf_intc_state *)opaque;
+ offset = addr & 0xff;
+ if (offset >= 0x40 && offset < 0x80) {
+ return s->icr[offset - 0x40];
+ }
+ switch (offset) {
+ case 0x00:
+ return (uint32_t)(s->ipr >> 32);
+ case 0x04:
+ return (uint32_t)s->ipr;
+ case 0x08:
+ return (uint32_t)(s->imr >> 32);
+ case 0x0c:
+ return (uint32_t)s->imr;
+ case 0x10:
+ return (uint32_t)(s->ifr >> 32);
+ case 0x14:
+ return (uint32_t)s->ifr;
+ case 0xe0: /* SWIACK. */
+ return s->active_vector;
+ case 0xe1: case 0xe2: case 0xe3: case 0xe4:
+ case 0xe5: case 0xe6: case 0xe7:
+ /* LnIACK */
+ cpu_abort(cpu_single_env, "mcf_intc_read: LnIACK not implemented\n");
+ default:
+ return 0;
+ }
+}
+
+static void mcf_intc_write(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ int offset;
+ mcf_intc_state *s = (mcf_intc_state *)opaque;
+ offset = addr & 0xff;
+ if (offset >= 0x40 && offset < 0x80) {
+ int n = offset - 0x40;
+ s->icr[n] = val;
+ if (val == 0)
+ s->enabled &= ~(1ull << n);
+ else
+ s->enabled |= (1ull << n);
+ mcf_intc_update(s);
+ return;
+ }
+ switch (offset) {
+ case 0x00: case 0x04:
+ /* Ignore IPR writes. */
+ return;
+ case 0x08:
+ s->imr = (s->imr & 0xffffffff) | ((uint64_t)val << 32);
+ break;
+ case 0x0c:
+ s->imr = (s->imr & 0xffffffff00000000ull) | (uint32_t)val;
+ break;
+ default:
+ cpu_abort(cpu_single_env, "mcf_intc_write: Bad write offset %d\n",
+ offset);
+ break;
+ }
+ mcf_intc_update(s);
+}
+
+static void mcf_intc_set_irq(void *opaque, int irq, int level)
+{
+ mcf_intc_state *s = (mcf_intc_state *)opaque;
+ if (irq >= 64)
+ return;
+ if (level)
+ s->ipr |= 1ull << irq;
+ else
+ s->ipr &= ~(1ull << irq);
+ mcf_intc_update(s);
+}
+
+static void mcf_intc_reset(mcf_intc_state *s)
+{
+ s->imr = ~0ull;
+ s->ipr = 0;
+ s->ifr = 0;
+ s->enabled = 0;
+ memset(s->icr, 0, 64);
+ s->active_vector = 24;
+}
+
+static CPUReadMemoryFunc *mcf_intc_readfn[] = {
+ mcf_intc_read,
+ mcf_intc_read,
+ mcf_intc_read
+};
+
+static CPUWriteMemoryFunc *mcf_intc_writefn[] = {
+ mcf_intc_write,
+ mcf_intc_write,
+ mcf_intc_write
+};
+
+qemu_irq *mcf_intc_init(target_phys_addr_t base, CPUState *env)
+{
+ mcf_intc_state *s;
+ int iomemtype;
+
+ s = qemu_mallocz(sizeof(mcf_intc_state));
+ s->env = env;
+ mcf_intc_reset(s);
+
+ iomemtype = cpu_register_io_memory(0, mcf_intc_readfn,
+ mcf_intc_writefn, s);
+ cpu_register_physical_memory(base, 0x100, iomemtype);
+
+ return qemu_allocate_irqs(mcf_intc_set_irq, s, 64);
+}
Added: trunk/src/host/qemu-neo1973/hw/mcf_uart.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/mcf_uart.c 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/hw/mcf_uart.c 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,306 @@
+/*
+ * ColdFire UART emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licenced under the GPL
+ */
+#include "vl.h"
+
+typedef struct {
+ uint8_t mr[2];
+ uint8_t sr;
+ uint8_t isr;
+ uint8_t imr;
+ uint8_t bg1;
+ uint8_t bg2;
+ uint8_t fifo[4];
+ uint8_t tb;
+ int current_mr;
+ int fifo_len;
+ int tx_enabled;
+ int rx_enabled;
+ qemu_irq irq;
+ CharDriverState *chr;
+} mcf_uart_state;
+
+/* UART Status Register bits. */
+#define MCF_UART_RxRDY 0x01
+#define MCF_UART_FFULL 0x02
+#define MCF_UART_TxRDY 0x04
+#define MCF_UART_TxEMP 0x08
+#define MCF_UART_OE 0x10
+#define MCF_UART_PE 0x20
+#define MCF_UART_FE 0x40
+#define MCF_UART_RB 0x80
+
+/* Interrupt flags. */
+#define MCF_UART_TxINT 0x01
+#define MCF_UART_RxINT 0x02
+#define MCF_UART_DBINT 0x04
+#define MCF_UART_COSINT 0x80
+
+/* UMR1 flags. */
+#define MCF_UART_BC0 0x01
+#define MCF_UART_BC1 0x02
+#define MCF_UART_PT 0x04
+#define MCF_UART_PM0 0x08
+#define MCF_UART_PM1 0x10
+#define MCF_UART_ERR 0x20
+#define MCF_UART_RxIRQ 0x40
+#define MCF_UART_RxRTS 0x80
+
+static void mcf_uart_update(mcf_uart_state *s)
+{
+ s->isr &= ~(MCF_UART_TxINT | MCF_UART_RxINT);
+ if (s->sr & MCF_UART_TxRDY)
+ s->isr |= MCF_UART_TxINT;
+ if ((s->sr & ((s->mr[0] & MCF_UART_RxIRQ)
+ ? MCF_UART_FFULL : MCF_UART_RxRDY)) != 0)
+ s->isr |= MCF_UART_RxINT;
+
+ qemu_set_irq(s->irq, (s->isr & s->imr) != 0);
+}
+
+uint32_t mcf_uart_read(void *opaque, target_phys_addr_t addr)
+{
+ mcf_uart_state *s = (mcf_uart_state *)opaque;
+ switch (addr & 0x3f) {
+ case 0x00:
+ return s->mr[s->current_mr];
+ case 0x04:
+ return s->sr;
+ case 0x0c:
+ {
+ uint8_t val;
+ int i;
+
+ if (s->fifo_len == 0)
+ return 0;
+
+ val = s->fifo[0];
+ s->fifo_len--;
+ for (i = 0; i < s->fifo_len; i++)
+ s->fifo[i] = s->fifo[i + 1];
+ s->sr &= ~MCF_UART_FFULL;
+ if (s->fifo_len == 0)
+ s->sr &= ~MCF_UART_RxRDY;
+ mcf_uart_update(s);
+ return val;
+ }
+ case 0x10:
+ /* TODO: Implement IPCR. */
+ return 0;
+ case 0x14:
+ return s->isr;
+ case 0x18:
+ return s->bg1;
+ case 0x1c:
+ return s->bg2;
+ default:
+ return 0;
+ }
+}
+
+/* Update TxRDY flag and set data if present and enabled. */
+static void mcf_uart_do_tx(mcf_uart_state *s)
+{
+ if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
+ if (s->chr)
+ qemu_chr_write(s->chr, (unsigned char *)&s->tb, 1);
+ s->sr |= MCF_UART_TxEMP;
+ }
+ if (s->tx_enabled) {
+ s->sr |= MCF_UART_TxRDY;
+ } else {
+ s->sr &= ~MCF_UART_TxRDY;
+ }
+}
+
+static void mcf_do_command(mcf_uart_state *s, uint8_t cmd)
+{
+ /* Misc command. */
+ switch ((cmd >> 4) & 3) {
+ case 0: /* No-op. */
+ break;
+ case 1: /* Reset mode register pointer. */
+ s->current_mr = 0;
+ break;
+ case 2: /* Reset receiver. */
+ s->rx_enabled = 0;
+ s->fifo_len = 0;
+ s->sr &= ~(MCF_UART_RxRDY | MCF_UART_FFULL);
+ break;
+ case 3: /* Reset transmitter. */
+ s->tx_enabled = 0;
+ s->sr |= MCF_UART_TxEMP;
+ s->sr &= ~MCF_UART_TxRDY;
+ break;
+ case 4: /* Reset error status. */
+ break;
+ case 5: /* Reset break-change interrupt. */
+ s->isr &= ~MCF_UART_DBINT;
+ break;
+ case 6: /* Start break. */
+ case 7: /* Stop break. */
+ break;
+ }
+
+ /* Transmitter command. */
+ switch ((cmd >> 2) & 3) {
+ case 0: /* No-op. */
+ break;
+ case 1: /* Enable. */
+ s->tx_enabled = 1;
+ mcf_uart_do_tx(s);
+ break;
+ case 2: /* Disable. */
+ s->tx_enabled = 0;
+ mcf_uart_do_tx(s);
+ break;
+ case 3: /* Reserved. */
+ fprintf(stderr, "mcf_uart: Bad TX command\n");
+ break;
+ }
+
+ /* Receiver command. */
+ switch (cmd & 3) {
+ case 0: /* No-op. */
+ break;
+ case 1: /* Enable. */
+ s->rx_enabled = 1;
+ break;
+ case 2:
+ s->rx_enabled = 0;
+ break;
+ case 3: /* Reserved. */
+ fprintf(stderr, "mcf_uart: Bad RX command\n");
+ break;
+ }
+}
+
+void mcf_uart_write(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ mcf_uart_state *s = (mcf_uart_state *)opaque;
+ switch (addr & 0x3f) {
+ case 0x00:
+ s->mr[s->current_mr] = val;
+ s->current_mr = 1;
+ break;
+ case 0x04:
+ /* CSR is ignored. */
+ break;
+ case 0x08: /* Command Register. */
+ mcf_do_command(s, val);
+ break;
+ case 0x0c: /* Transmit Buffer. */
+ s->sr &= ~MCF_UART_TxEMP;
+ s->tb = val;
+ mcf_uart_do_tx(s);
+ break;
+ case 0x10:
+ /* ACR is ignored. */
+ break;
+ case 0x14:
+ s->imr = val;
+ break;
+ default:
+ break;
+ }
+ mcf_uart_update(s);
+}
+
+static void mcf_uart_reset(mcf_uart_state *s)
+{
+ s->fifo_len = 0;
+ s->mr[0] = 0;
+ s->mr[1] = 0;
+ s->sr = MCF_UART_TxEMP;
+ s->tx_enabled = 0;
+ s->rx_enabled = 0;
+ s->isr = 0;
+ s->imr = 0;
+}
+
+static void mcf_uart_push_byte(mcf_uart_state *s, uint8_t data)
+{
+ /* Break events overwrite the last byte if the fifo is full. */
+ if (s->fifo_len == 4)
+ s->fifo_len--;
+
+ s->fifo[s->fifo_len] = data;
+ s->fifo_len++;
+ s->sr |= MCF_UART_RxRDY;
+ if (s->fifo_len == 4)
+ s->sr |= MCF_UART_FFULL;
+
+ mcf_uart_update(s);
+}
+
+static void mcf_uart_event(void *opaque, int event)
+{
+ mcf_uart_state *s = (mcf_uart_state *)opaque;
+
+ switch (event) {
+ case CHR_EVENT_BREAK:
+ s->isr |= MCF_UART_DBINT;
+ mcf_uart_push_byte(s, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static int mcf_uart_can_receive(void *opaque)
+{
+ mcf_uart_state *s = (mcf_uart_state *)opaque;
+
+ return s->rx_enabled && (s->sr & MCF_UART_FFULL) == 0;
+}
+
+static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+ mcf_uart_state *s = (mcf_uart_state *)opaque;
+
+ mcf_uart_push_byte(s, buf[0]);
+}
+
+void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
+{
+ mcf_uart_state *s;
+
+ s = qemu_mallocz(sizeof(mcf_uart_state));
+ s->chr = chr;
+ s->irq = irq;
+ if (chr) {
+ qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
+ mcf_uart_event, s);
+ }
+ mcf_uart_reset(s);
+ return s;
+}
+
+
+static CPUReadMemoryFunc *mcf_uart_readfn[] = {
+ mcf_uart_read,
+ mcf_uart_read,
+ mcf_uart_read
+};
+
+static CPUWriteMemoryFunc *mcf_uart_writefn[] = {
+ mcf_uart_write,
+ mcf_uart_write,
+ mcf_uart_write
+};
+
+void mcf_uart_mm_init(target_phys_addr_t base, qemu_irq irq,
+ CharDriverState *chr)
+{
+ mcf_uart_state *s;
+ int iomemtype;
+
+ s = mcf_uart_init(irq, chr);
+ iomemtype = cpu_register_io_memory(0, mcf_uart_readfn,
+ mcf_uart_writefn, s);
+ cpu_register_physical_memory(base, 0x40, iomemtype);
+}
Added: trunk/src/host/qemu-neo1973/hw/pixel_ops.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pixel_ops.h 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/hw/pixel_ops.h 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,53 @@
+static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
+}
+
+static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
+}
+
+static inline unsigned int rgb_to_pixel15bgr(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return ((b >> 3) << 10) | ((g >> 3) << 5) | (r >> 3);
+}
+
+static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+}
+
+static inline unsigned int rgb_to_pixel16bgr(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return ((b >> 3) << 11) | ((g >> 2) << 5) | (r >> 3);
+}
+
+static inline unsigned int rgb_to_pixel24(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return (r << 16) | (g << 8) | b;
+}
+
+static inline unsigned int rgb_to_pixel24bgr(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return (b << 16) | (g << 8) | r;
+}
+
+static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return (r << 16) | (g << 8) | b;
+}
+
+static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g,
+ unsigned int b)
+{
+ return (b << 16) | (g << 8) | r;
+}
Added: trunk/src/host/qemu-neo1973/hw/usb-wacom.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/usb-wacom.c 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/hw/usb-wacom.c 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,412 @@
+/*
+ * Wacom PenPartner USB tablet emulation.
+ *
+ * Copyright (c) 2006 Openedhand Ltd.
+ * Author: Andrzej Zaborowski <balrog at zabor.org>
+ *
+ * Based on hw/usb-hid.c:
+ * 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"
+
+/* Interface requests */
+#define WACOM_GET_REPORT 0x2101
+#define WACOM_SET_REPORT 0x2109
+
+/* HID interface requests */
+#define HID_GET_REPORT 0xa101
+#define HID_GET_IDLE 0xa102
+#define HID_GET_PROTOCOL 0xa103
+#define HID_SET_IDLE 0x210a
+#define HID_SET_PROTOCOL 0x210b
+
+typedef struct USBWacomState {
+ USBDevice dev;
+ QEMUPutMouseEntry *eh_entry;
+ int dx, dy, dz, buttons_state;
+ int x, y;
+ int mouse_grabbed;
+ enum {
+ WACOM_MODE_HID = 1,
+ WACOM_MODE_WACOM = 2,
+ } mode;
+} USBWacomState;
+
+static const uint8_t qemu_wacom_dev_descriptor[] = {
+ 0x12, /* u8 bLength; */
+ 0x01, /* u8 bDescriptorType; Device */
+ 0x10, 0x10, /* u16 bcdUSB; v1.10 */
+
+ 0x00, /* u8 bDeviceClass; */
+ 0x00, /* u8 bDeviceSubClass; */
+ 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
+ 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
+
+ 0x6a, 0x05, /* u16 idVendor; */
+ 0x00, 0x00, /* u16 idProduct; */
+ 0x10, 0x42, /* u16 bcdDevice */
+
+ 0x01, /* u8 iManufacturer; */
+ 0x02, /* u8 iProduct; */
+ 0x00, /* u8 iSerialNumber; */
+ 0x01, /* u8 bNumConfigurations; */
+};
+
+static const uint8_t qemu_wacom_config_descriptor[] = {
+ /* one configuration */
+ 0x09, /* u8 bLength; */
+ 0x02, /* u8 bDescriptorType; Configuration */
+ 0x22, 0x00, /* u16 wTotalLength; */
+ 0x01, /* u8 bNumInterfaces; (1) */
+ 0x01, /* u8 bConfigurationValue; */
+ 0x00, /* u8 iConfiguration; */
+ 0x80, /* u8 bmAttributes;
+ Bit 7: must be set,
+ 6: Self-powered,
+ 5: Remote wakeup,
+ 4..0: resvd */
+ 40, /* u8 MaxPower; */
+
+ /* one interface */
+ 0x09, /* u8 if_bLength; */
+ 0x04, /* u8 if_bDescriptorType; Interface */
+ 0x00, /* u8 if_bInterfaceNumber; */
+ 0x00, /* u8 if_bAlternateSetting; */
+ 0x01, /* u8 if_bNumEndpoints; */
+ 0x03, /* u8 if_bInterfaceClass; HID */
+ 0x01, /* u8 if_bInterfaceSubClass; Boot */
+ 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
+ 0x00, /* u8 if_iInterface; */
+
+ /* HID descriptor */
+ 0x09, /* u8 bLength; */
+ 0x21, /* u8 bDescriptorType; */
+ 0x01, 0x10, /* u16 HID_class */
+ 0x00, /* u8 country_code */
+ 0x01, /* u8 num_descriptors */
+ 0x22, /* u8 type; Report */
+ 0x6e, 0x00, /* u16 len */
+
+ /* one endpoint (status change endpoint) */
+ 0x07, /* u8 ep_bLength; */
+ 0x05, /* u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* u8 ep_bmAttributes; Interrupt */
+ 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
+ 0x0a, /* u8 ep_bInterval; */
+};
+
+static void usb_mouse_event(void *opaque,
+ int dx1, int dy1, int dz1, int buttons_state)
+{
+ USBWacomState *s = opaque;
+
+ s->dx += dx1;
+ s->dy += dy1;
+ s->dz += dz1;
+ s->buttons_state = buttons_state;
+}
+
+static void usb_wacom_event(void *opaque,
+ int x, int y, int dz, int buttons_state)
+{
+ USBWacomState *s = opaque;
+
+ s->x = x;
+ s->y = y;
+ s->dz += dz;
+ s->buttons_state = buttons_state;
+}
+
+static inline int int_clamp(int val, int vmin, int vmax)
+{
+ if (val < vmin)
+ return vmin;
+ else if (val > vmax)
+ return vmax;
+ else
+ return val;
+}
+
+static int usb_mouse_poll(USBWacomState *s, uint8_t *buf, int len)
+{
+ int dx, dy, dz, b, l;
+
+ if (!s->mouse_grabbed) {
+ s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, 0,
+ "QEMU PenPartner tablet");
+ s->mouse_grabbed = 1;
+ }
+
+ dx = int_clamp(s->dx, -128, 127);
+ dy = int_clamp(s->dy, -128, 127);
+ dz = int_clamp(s->dz, -128, 127);
+
+ s->dx -= dx;
+ s->dy -= dy;
+ s->dz -= dz;
+
+ b = 0;
+ if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+ b |= 0x01;
+ if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+ b |= 0x02;
+ if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+ b |= 0x04;
+
+ buf[0] = b;
+ buf[1] = dx;
+ buf[2] = dy;
+ l = 3;
+ if (len >= 4) {
+ buf[3] = dz;
+ l = 4;
+ }
+ return l;
+}
+
+static int usb_wacom_poll(USBWacomState *s, uint8_t *buf, int len)
+{
+ int b;
+
+ if (!s->mouse_grabbed) {
+ s->eh_entry = qemu_add_mouse_event_handler(usb_wacom_event, s, 1,
+ "QEMU PenPartner tablet");
+ s->mouse_grabbed = 1;
+ }
+
+ b = 0;
+ if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+ b |= 0x01;
+ if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+ b |= 0x02;
+ if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+ b |= 0x04;
+
+ if (len < 7)
+ return 0;
+
+ buf[0] = s->mode;
+ buf[5] = 0x00;
+ if (b) {
+ buf[1] = s->x & 0xff;
+ buf[2] = s->x >> 8;
+ buf[3] = s->y & 0xff;
+ buf[4] = s->y >> 8;
+ buf[6] = 0;
+ } else {
+ buf[1] = 0;
+ buf[2] = 0;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[6] = (unsigned char) -127;
+ }
+
+ return 7;
+}
+
+static void usb_wacom_handle_reset(USBDevice *dev)
+{
+ USBWacomState *s = (USBWacomState *) dev;
+
+ s->dx = 0;
+ s->dy = 0;
+ s->dz = 0;
+ s->x = 0;
+ s->y = 0;
+ s->buttons_state = 0;
+ s->mode = WACOM_MODE_HID;
+}
+
+static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
+ int index, int length, uint8_t *data)
+{
+ USBWacomState *s = (USBWacomState *) dev;
+ int ret = 0;
+
+ switch (request) {
+ case DeviceRequest | USB_REQ_GET_STATUS:
+ data[0] = (1 << USB_DEVICE_SELF_POWERED) |
+ (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
+ data[1] = 0x00;
+ ret = 2;
+ break;
+ case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+ if (value == USB_DEVICE_REMOTE_WAKEUP) {
+ dev->remote_wakeup = 0;
+ } else {
+ goto fail;
+ }
+ ret = 0;
+ break;
+ case DeviceOutRequest | USB_REQ_SET_FEATURE:
+ if (value == USB_DEVICE_REMOTE_WAKEUP) {
+ dev->remote_wakeup = 1;
+ } else {
+ goto fail;
+ }
+ ret = 0;
+ break;
+ case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+ dev->addr = value;
+ ret = 0;
+ break;
+ case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+ switch (value >> 8) {
+ case USB_DT_DEVICE:
+ memcpy(data, qemu_wacom_dev_descriptor,
+ sizeof(qemu_wacom_dev_descriptor));
+ ret = sizeof(qemu_wacom_dev_descriptor);
+ break;
+ case USB_DT_CONFIG:
+ memcpy(data, qemu_wacom_config_descriptor,
+ sizeof(qemu_wacom_config_descriptor));
+ ret = sizeof(qemu_wacom_config_descriptor);
+ break;
+ case USB_DT_STRING:
+ switch (value & 0xff) {
+ case 0:
+ /* language ids */
+ data[0] = 4;
+ data[1] = 3;
+ data[2] = 0x09;
+ data[3] = 0x04;
+ ret = 4;
+ break;
+ case 1:
+ /* serial number */
+ ret = set_usb_string(data, "1");
+ break;
+ case 2:
+ ret = set_usb_string(data, "Wacom PenPartner");
+ break;
+ case 3:
+ /* vendor description */
+ ret = set_usb_string(data, "QEMU " QEMU_VERSION);
+ break;
+ case 4:
+ ret = set_usb_string(data, "Wacom Tablet");
+ break;
+ case 5:
+ ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
+ break;
+ default:
+ goto fail;
+ }
+ break;
+ default:
+ goto fail;
+ }
+ break;
+ case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+ data[0] = 1;
+ ret = 1;
+ break;
+ case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+ ret = 0;
+ break;
+ case DeviceRequest | USB_REQ_GET_INTERFACE:
+ data[0] = 0;
+ ret = 1;
+ break;
+ case DeviceOutRequest | USB_REQ_SET_INTERFACE:
+ ret = 0;
+ break;
+ case WACOM_SET_REPORT:
+ qemu_remove_mouse_event_handler(s->eh_entry);
+ s->mouse_grabbed = 0;
+ s->mode = data[0];
+ ret = 0;
+ break;
+ case WACOM_GET_REPORT:
+ data[0] = 0;
+ data[1] = s->mode;
+ ret = 2;
+ break;
+ /* USB HID requests */
+ case HID_GET_REPORT:
+ if (s->mode == WACOM_MODE_HID)
+ ret = usb_mouse_poll(s, data, length);
+ else if (s->mode == WACOM_MODE_WACOM)
+ ret = usb_wacom_poll(s, data, length);
+ break;
+ case HID_SET_IDLE:
+ ret = 0;
+ break;
+ default:
+ fail:
+ ret = USB_RET_STALL;
+ break;
+ }
+ return ret;
+}
+
+static int usb_wacom_handle_data(USBDevice *dev, USBPacket *p)
+{
+ USBWacomState *s = (USBWacomState *) dev;
+ int ret = 0;
+
+ switch (p->pid) {
+ case USB_TOKEN_IN:
+ if (p->devep == 1) {
+ if (s->mode == WACOM_MODE_HID)
+ ret = usb_mouse_poll(s, p->data, p->len);
+ else if (s->mode == WACOM_MODE_WACOM)
+ ret = usb_wacom_poll(s, p->data, p->len);
+ break;
+ }
+ /* Fall through. */
+ case USB_TOKEN_OUT:
+ default:
+ ret = USB_RET_STALL;
+ break;
+ }
+ return ret;
+}
+
+static void usb_wacom_handle_destroy(USBDevice *dev)
+{
+ USBWacomState *s = (USBWacomState *) dev;
+
+ qemu_remove_mouse_event_handler(s->eh_entry);
+ qemu_free(s);
+}
+
+USBDevice *usb_wacom_init(void)
+{
+ USBWacomState *s;
+
+ s = qemu_mallocz(sizeof(USBWacomState));
+ if (!s)
+ return NULL;
+ s->dev.speed = USB_SPEED_FULL;
+ s->dev.handle_packet = usb_generic_handle_packet;
+
+ s->dev.handle_reset = usb_wacom_handle_reset;
+ s->dev.handle_control = usb_wacom_handle_control;
+ s->dev.handle_data = usb_wacom_handle_data;
+ s->dev.handle_destroy = usb_wacom_handle_destroy;
+
+ pstrcpy(s->dev.devname, sizeof(s->dev.devname),
+ "QEMU PenPartner Tablet");
+
+ return (USBDevice *) s;
+}
Added: trunk/src/host/qemu-neo1973/linux-user/errno_defs.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/errno_defs.h 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/linux-user/errno_defs.h 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,142 @@
+/*
+ * Target definitions of errnos. These may be overridden by an
+ * architecture specific header if needed.
+ *
+ * Taken from asm-generic/errno-base.h and asm-generic/errno.h
+ */
+#define TARGET_EPERM 1 /* Operation not permitted */
+#define TARGET_ENOENT 2 /* No such file or directory */
+#define TARGET_ESRCH 3 /* No such process */
+#define TARGET_EINTR 4 /* Interrupted system call */
+#define TARGET_EIO 5 /* I/O error */
+#define TARGET_ENXIO 6 /* No such device or address */
+#define TARGET_E2BIG 7 /* Argument list too long */
+#define TARGET_ENOEXEC 8 /* TARGET_Exec format error */
+#define TARGET_EBADF 9 /* Bad file number */
+#define TARGET_ECHILD 10 /* No child processes */
+#define TARGET_EAGAIN 11 /* Try again */
+#define TARGET_ENOMEM 12 /* Out of memory */
+#define TARGET_EACCES 13 /* Permission denied */
+#define TARGET_EFAULT 14 /* Bad address */
+#define TARGET_ENOTBLK 15 /* Block device required */
+#define TARGET_EBUSY 16 /* Device or resource busy */
+#define TARGET_EEXIST 17 /* File exists */
+#define TARGET_EXDEV 18 /* Cross-device link */
+#define TARGET_ENODEV 19 /* No such device */
+#define TARGET_ENOTDIR 20 /* Not a directory */
+#define TARGET_EISDIR 21 /* Is a directory */
+#define TARGET_EINVAL 22 /* Invalid argument */
+#define TARGET_ENFILE 23 /* File table overflow */
+#define TARGET_EMFILE 24 /* Too many open files */
+#define TARGET_ENOTTY 25 /* Not a typewriter */
+#define TARGET_ETXTBSY 26 /* Text file busy */
+#define TARGET_EFBIG 27 /* File too large */
+#define TARGET_ENOSPC 28 /* No space left on device */
+#define TARGET_ESPIPE 29 /* Illegal seek */
+#define TARGET_EROFS 30 /* Read-only file system */
+#define TARGET_EMLINK 31 /* Too many links */
+#define TARGET_EPIPE 32 /* Broken pipe */
+#define TARGET_EDOM 33 /* Math argument out of domain of func */
+#define TARGET_ERANGE 34 /* Math result not representable */
+
+#define TARGET_EDEADLK 35 /* Resource deadlock would occur */
+#define TARGET_ENAMETOOLONG 36 /* File name too long */
+#define TARGET_ENOLCK 37 /* No record locks available */
+#define TARGET_ENOSYS 38 /* Function not implemented */
+#define TARGET_ENOTEMPTY 39 /* Directory not empty */
+#define TARGET_ELOOP 40 /* Too many symbolic links encountered */
+
+#define TARGET_ENOMSG 42 /* No message of desired type */
+#define TARGET_EIDRM 43 /* Identifier removed */
+#define TARGET_ECHRNG 44 /* Channel number out of range */
+#define TARGET_EL2NSYNC 45 /* Level 2 not synchronized */
+#define TARGET_EL3HLT 46 /* Level 3 halted */
+#define TARGET_EL3RST 47 /* Level 3 reset */
+#define TARGET_ELNRNG 48 /* Link number out of range */
+#define TARGET_EUNATCH 49 /* Protocol driver not attached */
+#define TARGET_ENOCSI 50 /* No CSI structure available */
+#define TARGET_EL2HLT 51 /* Level 2 halted */
+#define TARGET_EBADE 52 /* Invalid exchange */
+#define TARGET_EBADR 53 /* Invalid request descriptor */
+#define TARGET_EXFULL 54 /* TARGET_Exchange full */
+#define TARGET_ENOANO 55 /* No anode */
+#define TARGET_EBADRQC 56 /* Invalid request code */
+#define TARGET_EBADSLT 57 /* Invalid slot */
+
+#define TARGET_EBFONT 59 /* Bad font file format */
+#define TARGET_ENOSTR 60 /* Device not a stream */
+#define TARGET_ENODATA 61 /* No data available */
+#define TARGET_ETIME 62 /* Timer expired */
+#define TARGET_ENOSR 63 /* Out of streams resources */
+#define TARGET_ENONET 64 /* Machine is not on the network */
+#define TARGET_ENOPKG 65 /* Package not installed */
+#define TARGET_EREMOTE 66 /* Object is remote */
+#define TARGET_ENOLINK 67 /* Link has been severed */
+#define TARGET_EADV 68 /* Advertise error */
+#define TARGET_ESRMNT 69 /* Srmount error */
+#define TARGET_ECOMM 70 /* Communication error on send */
+#define TARGET_EPROTO 71 /* Protocol error */
+#define TARGET_EMULTIHOP 72 /* Multihop attempted */
+#define TARGET_EDOTDOT 73 /* RFS specific error */
+#define TARGET_EBADMSG 74 /* Not a data message */
+#define TARGET_EOVERFLOW 75 /* Value too large for defined data type */
+#define TARGET_ENOTUNIQ 76 /* Name not unique on network */
+#define TARGET_EBADFD 77 /* File descriptor in bad state */
+#define TARGET_EREMCHG 78 /* Remote address changed */
+#define TARGET_ELIBACC 79 /* Can not access a needed shared library */
+#define TARGET_ELIBBAD 80 /* Accessing a corrupted shared library */
+#define TARGET_ELIBSCN 81 /* .lib section in a.out corrupted */
+#define TARGET_ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define TARGET_ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define TARGET_EILSEQ 84 /* Illegal byte sequence */
+#define TARGET_ERESTART 85 /* Interrupted system call should be restarted */
+#define TARGET_ESTRPIPE 86 /* Streams pipe error */
+#define TARGET_EUSERS 87 /* Too many users */
+#define TARGET_ENOTSOCK 88 /* Socket operation on non-socket */
+#define TARGET_EDESTADDRREQ 89 /* Destination address required */
+#define TARGET_EMSGSIZE 90 /* Message too long */
+#define TARGET_EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define TARGET_ENOPROTOOPT 92 /* Protocol not available */
+#define TARGET_EPROTONOSUPPORT 93 /* Protocol not supported */
+#define TARGET_ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define TARGET_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define TARGET_EPFNOSUPPORT 96 /* Protocol family not supported */
+#define TARGET_EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define TARGET_EADDRINUSE 98 /* Address already in use */
+#define TARGET_EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define TARGET_ENETDOWN 100 /* Network is down */
+#define TARGET_ENETUNREACH 101 /* Network is unreachable */
+#define TARGET_ENETRESET 102 /* Network dropped connection because of reset */
+#define TARGET_ECONNABORTED 103 /* Software caused connection abort */
+#define TARGET_ECONNRESET 104 /* Connection reset by peer */
+#define TARGET_ENOBUFS 105 /* No buffer space available */
+#define TARGET_EISCONN 106 /* Transport endpoint is already connected */
+#define TARGET_ENOTCONN 107 /* Transport endpoint is not connected */
+#define TARGET_ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define TARGET_ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define TARGET_ETIMEDOUT 110 /* Connection timed out */
+#define TARGET_ECONNREFUSED 111 /* Connection refused */
+#define TARGET_EHOSTDOWN 112 /* Host is down */
+#define TARGET_EHOSTUNREACH 113 /* No route to host */
+#define TARGET_EALREADY 114 /* Operation already in progress */
+#define TARGET_EINPROGRESS 115 /* Operation now in progress */
+#define TARGET_ESTALE 116 /* Stale NFS file handle */
+#define TARGET_EUCLEAN 117 /* Structure needs cleaning */
+#define TARGET_ENOTNAM 118 /* Not a XENIX named type file */
+#define TARGET_ENAVAIL 119 /* No XENIX semaphores available */
+#define TARGET_EISNAM 120 /* Is a named type file */
+#define TARGET_EREMOTEIO 121 /* Remote I/O error */
+#define TARGET_EDQUOT 122 /* Quota exceeded */
+
+#define TARGET_ENOMEDIUM 123 /* No medium found */
+#define TARGET_EMEDIUMTYPE 124 /* Wrong medium type */
+#define TARGET_ECANCELED 125 /* Operation Canceled */
+#define TARGET_ENOKEY 126 /* Required key not available */
+#define TARGET_EKEYEXPIRED 127 /* Key has expired */
+#define TARGET_EKEYREVOKED 128 /* Key has been revoked */
+#define TARGET_EKEYREJECTED 129 /* Key was rejected by service */
+
+/* for robust mutexes */
+#define TARGET_EOWNERDEAD 130 /* Owner died */
+#define TARGET_ENOTRECOVERABLE 131 /* State not recoverable */
+
Deleted: trunk/src/host/qemu-neo1973/linux-user/m68k-semi.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k-semi.c 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k-semi.c 2007-06-18 20:41:58 UTC (rev 2300)
@@ -1,216 +0,0 @@
-/*
- * m68k/ColdFire Semihosting ssycall interface
- *
- * Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <time.h>
-
-#include "qemu.h"
-
-#define HOSTED_EXIT 0
-#define HOSTED_PUTCHAR 1 /* Obsolete */
-#define HOSTED_OPEN 2
-#define HOSTED_CLOSE 3
-#define HOSTED_READ 4
-#define HOSTED_WRITE 5
-#define HOSTED_LSEEK 6
-#define HOSTED_RENAME 7
-#define HOSTED_UNLINK 8
-#define HOSTED_STAT 9
-#define HOSTED_FSTAT 10
-#define HOSTED_GETTIMEOFDAY 11
-#define HOSTED_ISATTY 12
-#define HOSTED_SYSTEM 13
-
-typedef uint32_t gdb_mode_t;
-typedef uint32_t gdb_time_t;
-
-struct m68k_gdb_stat {
- uint32_t gdb_st_dev; /* device */
- uint32_t gdb_st_ino; /* inode */
- gdb_mode_t gdb_st_mode; /* protection */
- uint32_t gdb_st_nlink; /* number of hard links */
- uint32_t gdb_st_uid; /* user ID of owner */
- uint32_t gdb_st_gid; /* group ID of owner */
- uint32_t gdb_st_rdev; /* device type (if inode device) */
- uint64_t gdb_st_size; /* total size, in bytes */
- uint64_t gdb_st_blksize; /* blocksize for filesystem I/O */
- uint64_t gdb_st_blocks; /* number of blocks allocated */
- gdb_time_t gdb_st_atime; /* time of last access */
- gdb_time_t gdb_st_mtime; /* time of last modification */
- gdb_time_t gdb_st_ctime; /* time of last change */
-};
-
-struct gdb_timeval {
- gdb_time_t tv_sec; /* second */
- uint64_t tv_usec; /* microsecond */
-};
-
-#define GDB_O_RDONLY 0x0
-#define GDB_O_WRONLY 0x1
-#define GDB_O_RDWR 0x2
-#define GDB_O_APPEND 0x8
-#define GDB_O_CREAT 0x200
-#define GDB_O_TRUNC 0x400
-#define GDB_O_EXCL 0x800
-
-static int translate_openflags(int flags)
-{
- int hf;
-
- if (flags & GDB_O_WRONLY)
- hf = O_WRONLY;
- else if (flags & GDB_O_RDWR)
- hf = O_RDWR;
- else
- hf = O_RDONLY;
-
- if (flags & GDB_O_APPEND) hf |= O_APPEND;
- if (flags & GDB_O_CREAT) hf |= O_CREAT;
- if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
- if (flags & GDB_O_EXCL) hf |= O_EXCL;
-
- return hf;
-}
-
-static void translate_stat(struct m68k_gdb_stat *p, struct stat *s)
-{
- p->gdb_st_dev = tswap16(s->st_dev);
- p->gdb_st_ino = tswap16(s->st_ino);
- p->gdb_st_mode = tswap32(s->st_mode);
- p->gdb_st_nlink = tswap16(s->st_nlink);
- p->gdb_st_uid = tswap16(s->st_uid);
- p->gdb_st_gid = tswap16(s->st_gid);
- p->gdb_st_rdev = tswap16(s->st_rdev);
- p->gdb_st_size = tswap32(s->st_size);
- p->gdb_st_atime = tswap32(s->st_atime);
- p->gdb_st_mtime = tswap32(s->st_mtime);
- p->gdb_st_ctime = tswap32(s->st_ctime);
- p->gdb_st_blksize = tswap32(s->st_blksize);
- p->gdb_st_blocks = tswap32(s->st_blocks);
-}
-
-static inline uint32_t check_err(CPUM68KState *env, uint32_t code)
-{
- if (code == (uint32_t)-1) {
- env->sr |= CCF_C;
- } else {
- env->sr &= ~CCF_C;
- env->dregs[0] = code;
- }
- return code;
-}
-
-#define ARG(x) tswap32(args[x])
-void do_m68k_semihosting(CPUM68KState *env, int nr)
-{
- uint32_t *args;
-
- args = (uint32_t *)env->dregs[1];
- switch (nr) {
- case HOSTED_EXIT:
- exit(env->dregs[0]);
- case HOSTED_OPEN:
- /* Assume name is NULL terminated. */
- check_err(env, open((char *)ARG(0), translate_openflags(ARG(2)),
- ARG(3)));
- break;
- case HOSTED_CLOSE:
- {
- /* Ignore attempts to close stdin/out/err. */
- int fd = ARG(0);
- if (fd > 2)
- check_err(env, close(fd));
- else
- check_err(env, 0);
- break;
- }
- case HOSTED_READ:
- check_err(env, read(ARG(0), (void *)ARG(1), ARG(2)));
- break;
- case HOSTED_WRITE:
- check_err(env, write(ARG(0), (void *)ARG(1), ARG(2)));
- break;
- case HOSTED_LSEEK:
- {
- uint64_t off;
- off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
- check_err(env, lseek(ARG(0), off, ARG(3)));
- }
- break;
- case HOSTED_RENAME:
- /* Assume names are NULL terminated. */
- check_err(env, rename((char *)ARG(0), (char *)ARG(2)));
- break;
- case HOSTED_UNLINK:
- /* Assume name is NULL terminated. */
- check_err(env, unlink((char *)ARG(0)));
- break;
- case HOSTED_STAT:
- /* Assume name is NULL terminated. */
- {
- struct stat s;
- int rc;
- rc = check_err(env, stat((char *)ARG(0), &s));
- if (rc == 0) {
- translate_stat((struct m68k_gdb_stat *)ARG(2), &s);
- }
- }
- break;
- case HOSTED_FSTAT:
- {
- struct stat s;
- int rc;
- rc = check_err(env, fstat(ARG(0), &s));
- if (rc == 0) {
- translate_stat((struct m68k_gdb_stat *)ARG(1), &s);
- }
- }
- break;
- case HOSTED_GETTIMEOFDAY:
- {
- struct timeval tv;
- struct gdb_timeval *p;
- int rc;
- rc = check_err(env, gettimeofday(&tv, NULL));
- if (rc != 0) {
- p = (struct gdb_timeval *)ARG(0);
- p->tv_sec = tswap32(tv.tv_sec);
- p->tv_usec = tswap64(tv.tv_usec);
- }
- }
- break;
- case HOSTED_ISATTY:
- check_err(env, isatty(ARG(0)));
- break;
- case HOSTED_SYSTEM:
- /* Assume name is NULL terminated. */
- check_err(env, system((char *)ARG(0)));
- break;
- default:
- cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
- }
-}
Added: trunk/src/host/qemu-neo1973/m68k-semi.c
===================================================================
--- trunk/src/host/qemu-neo1973/m68k-semi.c 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/m68k-semi.c 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,359 @@
+/*
+ * m68k/ColdFire Semihosting syscall interface
+ *
+ * Copyright (c) 2005-2007 CodeSourcery.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "cpu.h"
+#if defined(CONFIG_USER_ONLY)
+#include "qemu.h"
+#define SEMIHOSTING_HEAP_SIZE (128 * 1024 * 1024)
+#else
+#include "vl.h"
+#include "softmmu-semi.h"
+#endif
+
+#define HOSTED_EXIT 0
+#define HOSTED_INIT_SIM 1
+#define HOSTED_OPEN 2
+#define HOSTED_CLOSE 3
+#define HOSTED_READ 4
+#define HOSTED_WRITE 5
+#define HOSTED_LSEEK 6
+#define HOSTED_RENAME 7
+#define HOSTED_UNLINK 8
+#define HOSTED_STAT 9
+#define HOSTED_FSTAT 10
+#define HOSTED_GETTIMEOFDAY 11
+#define HOSTED_ISATTY 12
+#define HOSTED_SYSTEM 13
+
+typedef uint32_t gdb_mode_t;
+typedef uint32_t gdb_time_t;
+
+struct m68k_gdb_stat {
+ uint32_t gdb_st_dev; /* device */
+ uint32_t gdb_st_ino; /* inode */
+ gdb_mode_t gdb_st_mode; /* protection */
+ uint32_t gdb_st_nlink; /* number of hard links */
+ uint32_t gdb_st_uid; /* user ID of owner */
+ uint32_t gdb_st_gid; /* group ID of owner */
+ uint32_t gdb_st_rdev; /* device type (if inode device) */
+ uint64_t gdb_st_size; /* total size, in bytes */
+ uint64_t gdb_st_blksize; /* blocksize for filesystem I/O */
+ uint64_t gdb_st_blocks; /* number of blocks allocated */
+ gdb_time_t gdb_st_atime; /* time of last access */
+ gdb_time_t gdb_st_mtime; /* time of last modification */
+ gdb_time_t gdb_st_ctime; /* time of last change */
+} __attribute__((packed));
+
+struct gdb_timeval {
+ gdb_time_t tv_sec; /* second */
+ uint64_t tv_usec; /* microsecond */
+} __attribute__((packed));
+
+#define GDB_O_RDONLY 0x0
+#define GDB_O_WRONLY 0x1
+#define GDB_O_RDWR 0x2
+#define GDB_O_APPEND 0x8
+#define GDB_O_CREAT 0x200
+#define GDB_O_TRUNC 0x400
+#define GDB_O_EXCL 0x800
+
+static int translate_openflags(int flags)
+{
+ int hf;
+
+ if (flags & GDB_O_WRONLY)
+ hf = O_WRONLY;
+ else if (flags & GDB_O_RDWR)
+ hf = O_RDWR;
+ else
+ hf = O_RDONLY;
+
+ if (flags & GDB_O_APPEND) hf |= O_APPEND;
+ if (flags & GDB_O_CREAT) hf |= O_CREAT;
+ if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
+ if (flags & GDB_O_EXCL) hf |= O_EXCL;
+
+ return hf;
+}
+
+static void translate_stat(CPUState *env, target_ulong addr, struct stat *s)
+{
+ struct m68k_gdb_stat *p;
+
+ p = lock_user(addr, sizeof(struct m68k_gdb_stat), 0);
+ p->gdb_st_dev = cpu_to_be32(s->st_dev);
+ p->gdb_st_ino = cpu_to_be32(s->st_ino);
+ p->gdb_st_mode = cpu_to_be32(s->st_mode);
+ p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
+ p->gdb_st_uid = cpu_to_be32(s->st_uid);
+ p->gdb_st_gid = cpu_to_be32(s->st_gid);
+ p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
+ p->gdb_st_size = cpu_to_be64(s->st_size);
+#ifdef _WIN32
+ /* Windows stat is missing some fields. */
+ p->gdb_st_blksize = 0;
+ p->gdb_st_blocks = 0;
+#else
+ p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
+ p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
+#endif
+ p->gdb_st_atime = cpu_to_be32(s->st_atime);
+ p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
+ p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
+ unlock_user(p, addr, sizeof(struct m68k_gdb_stat));
+}
+
+static int m68k_semi_is_fseek;
+
+static void m68k_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
+{
+ target_ulong args;
+
+ args = env->dregs[1];
+ if (m68k_semi_is_fseek) {
+ /* FIXME: We've already lost the high bits of the fseek
+ return value. */
+ tput32(args, 0);
+ args += 4;
+ m68k_semi_is_fseek = 0;
+ }
+ tput32(args, ret);
+ tput32(args + 4, errno);
+}
+
+#define ARG(x) tget32(args + (x) * 4)
+#define PARG(x) ((unsigned long)ARG(x))
+void do_m68k_semihosting(CPUM68KState *env, int nr)
+{
+ uint32_t args;
+ void *p;
+ void *q;
+ uint32_t len;
+ uint32_t result;
+
+ args = env->dregs[1];
+ switch (nr) {
+ case HOSTED_EXIT:
+ exit(env->dregs[0]);
+ case HOSTED_OPEN:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1),
+ ARG(2), ARG(3));
+ return;
+ } else {
+ p = lock_user_string(ARG(0));
+ result = open(p, translate_openflags(ARG(2)), ARG(3));
+ unlock_user(p, ARG(0), 0);
+ }
+ break;
+ case HOSTED_CLOSE:
+ {
+ /* Ignore attempts to close stdin/out/err. */
+ int fd = ARG(0);
+ if (fd > 2) {
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0));
+ return;
+ } else {
+ result = close(fd);
+ }
+ } else {
+ result = 0;
+ }
+ break;
+ }
+ case HOSTED_READ:
+ len = ARG(2);
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x",
+ ARG(0), ARG(1), len);
+ return;
+ } else {
+ p = lock_user(ARG(1), len, 0);
+ result = read(ARG(0), p, len);
+ unlock_user(p, ARG(1), len);
+ }
+ break;
+ case HOSTED_WRITE:
+ len = ARG(2);
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x",
+ ARG(0), ARG(1), len);
+ return;
+ } else {
+ p = lock_user(ARG(1), len, 1);
+ result = write(ARG(0), p, len);
+ unlock_user(p, ARG(0), 0);
+ }
+ break;
+ case HOSTED_LSEEK:
+ {
+ uint64_t off;
+ off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
+ if (use_gdb_syscalls()) {
+ m68k_semi_is_fseek = 1;
+ gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x",
+ ARG(0), off, ARG(3));
+ } else {
+ off = lseek(ARG(0), off, ARG(3));
+ tput32(args, off >> 32);
+ tput32(args + 4, off);
+ tput32(args + 8, errno);
+ }
+ return;
+ }
+ case HOSTED_RENAME:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
+ ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
+ return;
+ } else {
+ p = lock_user_string(ARG(0));
+ q = lock_user_string(ARG(2));
+ result = rename(p, q);
+ unlock_user(p, ARG(0), 0);
+ unlock_user(q, ARG(2), 0);
+ }
+ break;
+ case HOSTED_UNLINK:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "unlink,%s",
+ ARG(0), (int)ARG(1));
+ return;
+ } else {
+ p = lock_user_string(ARG(0));
+ result = unlink(p);
+ unlock_user(p, ARG(0), 0);
+ }
+ break;
+ case HOSTED_STAT:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "stat,%s,%x",
+ ARG(0), (int)ARG(1), ARG(2));
+ return;
+ } else {
+ struct stat s;
+ p = lock_user_string(ARG(0));
+ result = stat(p, &s);
+ unlock_user(p, ARG(0), 0);
+ if (result == 0) {
+ translate_stat(env, ARG(2), &s);
+ }
+ }
+ break;
+ case HOSTED_FSTAT:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x",
+ ARG(0), ARG(1));
+ return;
+ } else {
+ struct stat s;
+ result = fstat(ARG(0), &s);
+ if (result == 0) {
+ translate_stat(env, ARG(1), &s);
+ }
+ }
+ break;
+ case HOSTED_GETTIMEOFDAY:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x",
+ ARG(0), ARG(1));
+ return;
+ } else {
+ qemu_timeval tv;
+ struct gdb_timeval *p;
+ result = qemu_gettimeofday(&tv);
+ if (result != 0) {
+ p = lock_user(ARG(0), sizeof(struct gdb_timeval), 0);
+ p->tv_sec = cpu_to_be32(tv.tv_sec);
+ p->tv_usec = cpu_to_be64(tv.tv_usec);
+ unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
+ }
+ }
+ break;
+ case HOSTED_ISATTY:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0));
+ return;
+ } else {
+ result = isatty(ARG(0));
+ }
+ break;
+ case HOSTED_SYSTEM:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "system,%s",
+ ARG(0), (int)ARG(1));
+ return;
+ } else {
+ p = lock_user_string(ARG(0));
+ result = system(p);
+ unlock_user(p, ARG(0), 0);
+ }
+ break;
+ case HOSTED_INIT_SIM:
+#if defined(CONFIG_USER_ONLY)
+ {
+ TaskState *ts = env->opaque;
+ /* Allocate the heap using sbrk. */
+ if (!ts->heap_limit) {
+ long ret;
+ uint32_t size;
+ uint32_t base;
+
+ base = do_brk(0);
+ size = SEMIHOSTING_HEAP_SIZE;
+ /* Try a big heap, and reduce the size if that fails. */
+ for (;;) {
+ ret = do_brk(base + size);
+ if (ret != -1)
+ break;
+ size >>= 1;
+ }
+ ts->heap_limit = base + size;
+ }
+ /* This call may happen before we have writable memory, so return
+ values directly in registers. */
+ env->dregs[1] = ts->heap_limit;
+ env->aregs[7] = ts->stack_base;
+ }
+#else
+ /* FIXME: This is wrong for boards where RAM does not start at
+ address zero. */
+ env->dregs[1] = ram_size;
+ env->aregs[7] = ram_size;
+#endif
+ return;
+ default:
+ cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
+ result = 0;
+ }
+ tput32(args, result);
+ tput32(args + 4, errno);
+}
Added: trunk/src/host/qemu-neo1973/mips.ld
===================================================================
--- trunk/src/host/qemu-neo1973/mips.ld 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/mips.ld 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,225 @@
+/* Default linker script, for normal executables */
+OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips",
+ "elf32-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(__start)
+SEARCH_DIR("/usr/mips-linux-gnu/lib");
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = 0x0400000); . = 0x0400000 + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .reginfo : { *(.reginfo) }
+ .dynamic : { *(.dynamic) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+ .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
+ .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
+ .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
+ .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
+ .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
+ .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
+ .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
+ .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
+ .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0x47ff041f
+ .plt : { *(.plt) }
+ .text :
+ {
+ _ftext = . ;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.mips16.fn.*) *(.mips16.call.*)
+ } =0x47ff041f
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x47ff041f
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 :
+ {
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+ }
+ .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN (0x40000) - ((0x40000 - .) & (0x40000 - 1)); . = DATA_SEGMENT_ALIGN (0x40000, 0x1000);
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ /* Thread Local Storage sections */
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin*.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin*.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+ . = DATA_SEGMENT_RELRO_END (0, .);
+ .data :
+ {
+ _fdata = . ;
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ . = .;
+ _gp = ALIGN(16) + 0x7ff0;
+ .got : { *(.got.plt) *(.got) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata :
+ {
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ }
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ _edata = .; PROVIDE (edata = .);
+ __bss_start = .;
+ _fbss = .;
+ .sbss :
+ {
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we don't
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
+ }
+ . = ALIGN(32 / 8);
+ . = ALIGN(32 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
Added: trunk/src/host/qemu-neo1973/mipsel.ld
===================================================================
--- trunk/src/host/qemu-neo1973/mipsel.ld 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/mipsel.ld 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,225 @@
+/* Default linker script, for normal executables */
+OUTPUT_FORMAT("elf32-tradlittlemips", "elf32-tradbigmips",
+ "elf32-tradlittlemips")
+OUTPUT_ARCH(mips)
+ENTRY(__start)
+SEARCH_DIR("/usr/mips-linux-gnu/lib");
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = 0x0400000); . = 0x0400000 + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .reginfo : { *(.reginfo) }
+ .dynamic : { *(.dynamic) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
+ .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
+ .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
+ .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) }
+ .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) }
+ .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
+ .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
+ .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
+ .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
+ .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
+ .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) }
+ .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
+ .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) }
+ .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
+ .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) }
+ .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
+ .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) }
+ .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
+ .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
+ .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0x47ff041f
+ .plt : { *(.plt) }
+ .text :
+ {
+ _ftext = . ;
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.mips16.fn.*) *(.mips16.call.*)
+ } =0x47ff041f
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x47ff041f
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .sdata2 :
+ {
+ *(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
+ }
+ .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN (0x40000) - ((0x40000 - .) & (0x40000 - 1)); . = DATA_SEGMENT_ALIGN (0x40000, 0x1000);
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ /* Thread Local Storage sections */
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin*.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin*.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+ . = DATA_SEGMENT_RELRO_END (0, .);
+ .data :
+ {
+ _fdata = . ;
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ . = .;
+ _gp = ALIGN(16) + 0x7ff0;
+ .got : { *(.got.plt) *(.got) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata :
+ {
+ *(.sdata .sdata.* .gnu.linkonce.s.*)
+ }
+ .lit8 : { *(.lit8) }
+ .lit4 : { *(.lit4) }
+ _edata = .; PROVIDE (edata = .);
+ __bss_start = .;
+ _fbss = .;
+ .sbss :
+ {
+ *(.dynsbss)
+ *(.sbss .sbss.* .gnu.linkonce.sb.*)
+ *(.scommon)
+ }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we don't
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
+ }
+ . = ALIGN(32 / 8);
+ . = ALIGN(32 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+ .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
Added: trunk/src/host/qemu-neo1973/softmmu-semi.h
===================================================================
--- trunk/src/host/qemu-neo1973/softmmu-semi.h 2007-06-18 19:00:41 UTC (rev 2299)
+++ trunk/src/host/qemu-neo1973/softmmu-semi.h 2007-06-18 20:41:58 UTC (rev 2300)
@@ -0,0 +1,67 @@
+/*
+ * Helper routines to provide target memory access for semihosting
+ * syscalls in system emulation mode.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * This code is licenced under the GPL
+ */
+
+static inline uint32_t softmmu_tget32(CPUState *env, uint32_t addr)
+{
+ uint32_t val;
+
+ cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
+ return tswap32(val);
+}
+static inline uint32_t softmmu_tget8(CPUState *env, uint32_t addr)
+{
+ uint8_t val;
+
+ cpu_memory_rw_debug(env, addr, &val, 1, 0);
+ return val;
+}
+#define tget32(p) softmmu_tget32(env, p)
+#define tget8(p) softmmu_tget8(env, p)
+
+static inline void softmmu_tput32(CPUState *env, uint32_t addr, uint32_t val)
+{
+ val = tswap32(val);
+ cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 1);
+}
+#define tput32(p, val) softmmu_tput32(env, p, val)
+
+static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
+ int copy)
+{
+ char *p;
+ /* TODO: Make this something that isn't fixed size. */
+ p = malloc(len);
+ if (copy)
+ cpu_memory_rw_debug(env, addr, p, len, 0);
+ return p;
+}
+#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy)
+static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
+{
+ char *p;
+ char *s;
+ uint8_t c;
+ /* TODO: Make this something that isn't fixed size. */
+ s = p = malloc(1024);
+ do {
+ cpu_memory_rw_debug(env, addr, &c, 1, 0);
+ addr++;
+ *(p++) = c;
+ } while (c);
+ return s;
+}
+#define lock_user_string(p) softmmu_lock_user_string(env, p)
+static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr,
+ target_ulong len)
+{
+ if (len)
+ cpu_memory_rw_debug(env, addr, p, len, 1);
+ free(p);
+}
+#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
More information about the commitlog
mailing list