diff options
Diffstat (limited to 'hw')
53 files changed, 0 insertions, 14976 deletions
diff --git a/hw/android_arm.c b/hw/android_arm.c deleted file mode 100644 index efc8ba1..0000000 --- a/hw/android_arm.c +++ /dev/null @@ -1,175 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "hw.h" -#include "boards.h" -#include "devices.h" -#include "net.h" -#include "arm_pic.h" -#include "sysemu.h" -#include "goldfish_device.h" -#include "android/globals.h" -#include "audio/audio.h" -#include "arm-misc.h" - -#define ARM_CPU_SAVE_VERSION 1 - -int android_audio_enabled; -char* audio_input_source = NULL; - -void goldfish_memlog_init(uint32_t base); - -static struct goldfish_device event0_device = { - .name = "goldfish_events", - .id = 0, - .size = 0x1000, - .irq_count = 1 -}; - -static struct goldfish_device nand_device = { - .name = "goldfish_nand", - .id = 0, - .size = 0x1000 -}; - -static struct goldfish_device trace_device = { - .name = "qemu_trace", - .id = -1, - .size = 0x1000 -}; - -/* Board init. */ - -#define TEST_SWITCH 1 -#if TEST_SWITCH -uint32_t switch_test_write(void *opaque, uint32_t state) -{ - goldfish_switch_set_state(opaque, state); - return state; -} -#endif - -static void android_arm_init(ram_addr_t ram_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - const char *cpu_model) -{ - CPUState *env; - qemu_irq *cpu_pic; - qemu_irq *goldfish_pic; - int i; - struct arm_boot_info info; - - if (!cpu_model) - cpu_model = "arm926"; - - env = cpu_init(cpu_model); - - register_savevm( "cpu", 0, ARM_CPU_SAVE_VERSION, cpu_save, cpu_load, env ); - - cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); - - cpu_pic = arm_pic_init_cpu(env); - goldfish_pic = goldfish_interrupt_init(0xff000000, cpu_pic[ARM_PIC_CPU_IRQ], cpu_pic[ARM_PIC_CPU_FIQ]); - goldfish_device_init(goldfish_pic, 0xff010000, 0x7f0000, 10, 22); - - goldfish_device_bus_init(0xff001000, 1); - - goldfish_timer_and_rtc_init(0xff003000, 3); - - goldfish_tty_add(serial_hds[0], 0, 0xff002000, 4); - for(i = 1; i < MAX_SERIAL_PORTS; i++) { - //printf("android_arm_init serial %d %x\n", i, serial_hds[i]); - if(serial_hds[i]) { - goldfish_tty_add(serial_hds[i], i, 0, 0); - } - } - - for(i = 0; i < MAX_NICS; i++) { - if (nd_table[i].vlan) { - if (nd_table[i].model == NULL - || strcmp(nd_table[i].model, "smc91c111") == 0) { - struct goldfish_device *smc_device; - smc_device = qemu_mallocz(sizeof(*smc_device)); - smc_device->name = "smc91x"; - smc_device->id = i; - smc_device->size = 0x1000; - smc_device->irq_count = 1; - goldfish_add_device_no_io(smc_device); - smc91c111_init(&nd_table[i], smc_device->base, goldfish_pic[smc_device->irq]); - } else { - fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd_table[0].model); - exit (1); - } - } - } - - goldfish_fb_init(ds, 0); -#ifdef HAS_AUDIO - if (android_audio_enabled) { - AUD_init(); - goldfish_audio_init(0xff004000, 0, audio_input_source); - } -#endif - { - int idx = drive_get_index( IF_IDE, 0, 0 ); - if (idx >= 0) - goldfish_mmc_init(0xff005000, 0, drives_table[idx].bdrv); - } - - goldfish_memlog_init(0xff006000); - - if (android_hw->hw_battery) - goldfish_battery_init(); - - goldfish_add_device_no_io(&event0_device); - events_dev_init(event0_device.base, goldfish_pic[event0_device.irq]); - -#ifdef CONFIG_NAND - goldfish_add_device_no_io(&nand_device); - nand_dev_init(nand_device.base); -#endif -#ifdef CONFIG_TRACE - extern const char *trace_filename; - if(trace_filename != NULL) { - goldfish_add_device_no_io(&trace_device); - trace_dev_init(trace_device.base); - } -#endif - -#if TEST_SWITCH - { - void *sw; - sw = goldfish_switch_add("test", NULL, NULL, 0); - goldfish_switch_set_state(sw, 1); - goldfish_switch_add("test2", switch_test_write, sw, 1); - } -#endif - - memset(&info, 0, sizeof info); - info.ram_size = ram_size; - info.kernel_filename = kernel_filename; - info.kernel_cmdline = kernel_cmdline; - info.initrd_filename = initrd_filename; - info.nb_cpus = 1; - info.board_id = 1441; - - arm_load_kernel(env, &info); -} - -QEMUMachine android_arm_machine = { - "android_arm", - "ARM Android Emulator", - android_arm_init, - NULL -}; diff --git a/hw/arm-misc.h b/hw/arm-misc.h deleted file mode 100644 index 707e699..0000000 --- a/hw/arm-misc.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Misc ARM declarations - * - * Copyright (c) 2006 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the LGPL. - * - */ - -#ifndef ARM_MISC_H -#define ARM_MISC_H 1 - -#include "cpu.h" - -/* The CPU is also modeled as an interrupt controller. */ -#define ARM_PIC_CPU_IRQ 0 -#define ARM_PIC_CPU_FIQ 1 -qemu_irq *arm_pic_init_cpu(CPUState *env); - -/* armv7m.c */ -qemu_irq *armv7m_init(int flash_size, int sram_size, - const char *kernel_filename, const char *cpu_model); - -/* arm_boot.c */ -struct arm_boot_info { - int ram_size; - const char *kernel_filename; - const char *kernel_cmdline; - const char *initrd_filename; - target_phys_addr_t loader_start; - int nb_cpus; - int board_id; - int (*atag_board)(struct arm_boot_info *info, void *p); -}; -void arm_load_kernel(CPUState *env, struct arm_boot_info *info); - -/* armv7m_nvic.c */ - -/* Multiplication factor to convert from system clock ticks to qemu timer - ticks. */ -int system_clock_scale; -qemu_irq *armv7m_nvic_init(CPUState *env); - -/* stellaris_enent.c */ -void stellaris_enet_init(NICInfo *nd, uint32_t base, qemu_irq irq); - -#endif /* !ARM_MISC_H */ - diff --git a/hw/arm_boot.c b/hw/arm_boot.c deleted file mode 100644 index 5990961..0000000 --- a/hw/arm_boot.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * ARM kernel loader. - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the GPL. - */ - -#include "hw.h" -#include "arm-misc.h" -#include "sysemu.h" - -#define KERNEL_ARGS_ADDR 0x100 -#define KERNEL_LOAD_ADDR 0x00010000 -#define INITRD_LOAD_ADDR 0x00800000 - -/* The worlds second smallest bootloader. Set r0-r2, then jump to kernel. */ -static uint32_t bootloader[] = { - 0xe3a00000, /* mov r0, #0 */ - 0xe3a01000, /* mov r1, #0x?? */ - 0xe3811c00, /* orr r1, r1, #0x??00 */ - 0xe59f2000, /* ldr r2, [pc, #0] */ - 0xe59ff000, /* ldr pc, [pc, #0] */ - 0, /* Address of kernel args. Set by integratorcp_init. */ - 0 /* Kernel entry point. Set by integratorcp_init. */ -}; - -/* Entry point for secondary CPUs. Enable interrupt controller and - Issue WFI until start address is written to system controller. */ -static uint32_t smpboot[] = { - 0xe3a00201, /* mov r0, #0x10000000 */ - 0xe3800601, /* orr r0, r0, #0x001000000 */ - 0xe3a01001, /* mov r1, #1 */ - 0xe5801100, /* str r1, [r0, #0x100] */ - 0xe3a00201, /* mov r0, #0x10000000 */ - 0xe3800030, /* orr r0, #0x30 */ - 0xe320f003, /* wfi */ - 0xe5901000, /* ldr r1, [r0] */ - 0xe3110003, /* tst r1, #3 */ - 0x1afffffb, /* bne <wfi> */ - 0xe12fff11 /* bx r1 */ -}; - -static void main_cpu_reset(void *opaque) -{ - CPUState *env = opaque; - - cpu_reset(env); - if (env->boot_info) - arm_load_kernel(env, env->boot_info); - - /* TODO: Reset secondary CPUs. */ -} - -static void set_kernel_args(struct arm_boot_info *info, - int initrd_size, void *base) -{ - uint32_t *p; - - p = (uint32_t *)(base + KERNEL_ARGS_ADDR); - /* ATAG_CORE */ - stl_raw(p++, 5); - stl_raw(p++, 0x54410001); - stl_raw(p++, 1); - stl_raw(p++, 0x1000); - stl_raw(p++, 0); - /* ATAG_MEM */ - /* TODO: handle multiple chips on one ATAG list */ - stl_raw(p++, 4); - stl_raw(p++, 0x54410002); - stl_raw(p++, info->ram_size); - stl_raw(p++, info->loader_start); - if (initrd_size) { - /* ATAG_INITRD2 */ - stl_raw(p++, 4); - stl_raw(p++, 0x54420005); - stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR); - stl_raw(p++, initrd_size); - } - if (info->kernel_cmdline && *info->kernel_cmdline) { - /* ATAG_CMDLINE */ - int cmdline_size; - - cmdline_size = strlen(info->kernel_cmdline); - memcpy(p + 2, info->kernel_cmdline, cmdline_size + 1); - cmdline_size = (cmdline_size >> 2) + 1; - stl_raw(p++, cmdline_size + 2); - stl_raw(p++, 0x54410009); - p += cmdline_size; - } - if (info->atag_board) { - /* ATAG_BOARD */ - int atag_board_len; - - atag_board_len = (info->atag_board(info, p + 2) + 3) >> 2; - stl_raw(p++, 2 + atag_board_len); - stl_raw(p++, 0x414f4d50); - p += atag_board_len; - } - /* ATAG_END */ - stl_raw(p++, 0); - stl_raw(p++, 0); -} - -static void set_kernel_args_old(struct arm_boot_info *info, - int initrd_size, void *base) -{ - uint32_t *p; - unsigned char *s; - - /* see linux/include/asm-arm/setup.h */ - p = (uint32_t *)(base + KERNEL_ARGS_ADDR); - /* page_size */ - stl_raw(p++, 4096); - /* nr_pages */ - stl_raw(p++, info->ram_size / 4096); - /* ramdisk_size */ - stl_raw(p++, 0); -#define FLAG_READONLY 1 -#define FLAG_RDLOAD 4 -#define FLAG_RDPROMPT 8 - /* flags */ - stl_raw(p++, FLAG_READONLY | FLAG_RDLOAD | FLAG_RDPROMPT); - /* rootdev */ - stl_raw(p++, (31 << 8) | 0); /* /dev/mtdblock0 */ - /* video_num_cols */ - stl_raw(p++, 0); - /* video_num_rows */ - stl_raw(p++, 0); - /* video_x */ - stl_raw(p++, 0); - /* video_y */ - stl_raw(p++, 0); - /* memc_control_reg */ - stl_raw(p++, 0); - /* unsigned char sounddefault */ - /* unsigned char adfsdrives */ - /* unsigned char bytes_per_char_h */ - /* unsigned char bytes_per_char_v */ - stl_raw(p++, 0); - /* pages_in_bank[4] */ - stl_raw(p++, 0); - stl_raw(p++, 0); - stl_raw(p++, 0); - stl_raw(p++, 0); - /* pages_in_vram */ - stl_raw(p++, 0); - /* initrd_start */ - if (initrd_size) - stl_raw(p++, info->loader_start + INITRD_LOAD_ADDR); - else - stl_raw(p++, 0); - /* initrd_size */ - stl_raw(p++, initrd_size); - /* rd_start */ - stl_raw(p++, 0); - /* system_rev */ - stl_raw(p++, 0); - /* system_serial_low */ - stl_raw(p++, 0); - /* system_serial_high */ - stl_raw(p++, 0); - /* mem_fclk_21285 */ - stl_raw(p++, 0); - /* zero unused fields */ - memset(p, 0, 256 + 1024 - - (p - ((uint32_t *)(base + KERNEL_ARGS_ADDR)))); - s = base + KERNEL_ARGS_ADDR + 256 + 1024; - if (info->kernel_cmdline) - strcpy (s, info->kernel_cmdline); - else - stb_raw(s, 0); -} - -void arm_load_kernel(CPUState *env, struct arm_boot_info *info) -{ - int kernel_size; - int initrd_size; - int n; - int is_linux = 0; - uint64_t elf_entry; - target_ulong entry; - uint32_t pd; - void *loader_phys; - - /* Load the kernel. */ - if (!info->kernel_filename) { - fprintf(stderr, "Kernel image must be specified\n"); - exit(1); - } - - if (!env->boot_info) { - if (info->nb_cpus == 0) - info->nb_cpus = 1; - env->boot_info = info; - qemu_register_reset(main_cpu_reset, env); - } - - pd = cpu_get_physical_page_desc(info->loader_start); - loader_phys = phys_ram_base + (pd & TARGET_PAGE_MASK) + - (info->loader_start & ~TARGET_PAGE_MASK); - - /* Assume that raw images are linux kernels, and ELF images are not. */ - kernel_size = load_elf(info->kernel_filename, 0, &elf_entry, NULL, NULL); - entry = elf_entry; - if (kernel_size < 0) { - kernel_size = load_uboot(info->kernel_filename, &entry, &is_linux); - } - if (kernel_size < 0) { - kernel_size = load_image(info->kernel_filename, - loader_phys + KERNEL_LOAD_ADDR); - entry = info->loader_start + KERNEL_LOAD_ADDR; - is_linux = 1; - } - if (kernel_size < 0) { - fprintf(stderr, "qemu: could not load kernel '%s'\n", - info->kernel_filename); - exit(1); - } - if (!is_linux) { - /* Jump to the entry point. */ - env->regs[15] = entry & 0xfffffffe; - env->thumb = entry & 1; - } else { - if (info->initrd_filename) { - initrd_size = load_image(info->initrd_filename, - loader_phys + INITRD_LOAD_ADDR); - if (initrd_size < 0) { - fprintf(stderr, "qemu: could not load initrd '%s'\n", - info->initrd_filename); - exit(1); - } - } else { - initrd_size = 0; - } - bootloader[1] |= info->board_id & 0xff; - bootloader[2] |= (info->board_id >> 8) & 0xff; - bootloader[5] = info->loader_start + KERNEL_ARGS_ADDR; - bootloader[6] = entry; - for (n = 0; n < sizeof(bootloader) / 4; n++) - stl_raw(loader_phys + (n * 4), bootloader[n]); - if (info->nb_cpus > 1) - for (n = 0; n < sizeof(smpboot) / 4; n++) - stl_raw(loader_phys + info->ram_size + (n * 4), smpboot[n]); - if (old_param) - set_kernel_args_old(info, initrd_size, loader_phys); - else - set_kernel_args(info, initrd_size, loader_phys); - } -} diff --git a/hw/arm_gic.c b/hw/arm_gic.c deleted file mode 100644 index 54e99f4..0000000 --- a/hw/arm_gic.c +++ /dev/null @@ -1,747 +0,0 @@ -/* - * ARM Generic/Distributed Interrupt Controller - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the GPL. - */ - -/* This file contains implementation code for the RealView EB interrupt - controller, MPCore distributed interrupt controller and ARMv7-M - Nested Vectored Interrupt Controller. */ - -//#define DEBUG_GIC - -#ifdef DEBUG_GIC -#define DPRINTF(fmt, args...) \ -do { printf("arm_gic: " fmt , ##args); } while (0) -#else -#define DPRINTF(fmt, args...) do {} while(0) -#endif - -#ifdef NVIC -static const uint8_t gic_id[] = -{ 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 }; -#define GIC_DIST_OFFSET 0 -/* The NVIC has 16 internal vectors. However these are not exposed - through the normal GIC interface. */ -#define GIC_BASE_IRQ 32 -#else -static const uint8_t gic_id[] = -{ 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; -#define GIC_DIST_OFFSET 0x1000 -#define GIC_BASE_IRQ 0 -#endif - -typedef struct gic_irq_state -{ - /* ??? The documentation seems to imply the enable bits are global, even - for per-cpu interrupts. This seems strange. */ - unsigned enabled:1; - unsigned pending:NCPU; - unsigned active:NCPU; - unsigned level:1; - unsigned model:1; /* 0 = N:N, 1 = 1:N */ - unsigned trigger:1; /* nonzero = edge triggered. */ -} gic_irq_state; - -#define ALL_CPU_MASK ((1 << NCPU) - 1) - -#define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1 -#define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0 -#define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled -#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm) -#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm) -#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0) -#define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm) -#define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm) -#define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0) -#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1 -#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0 -#define GIC_TEST_MODEL(irq) s->irq_state[irq].model -#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm) -#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm) -#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0) -#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1 -#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0 -#define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger -#define GIC_GET_PRIORITY(irq, cpu) \ - (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32]) -#ifdef NVIC -#define GIC_TARGET(irq) 1 -#else -#define GIC_TARGET(irq) s->irq_target[irq] -#endif - -typedef struct gic_state -{ - uint32_t base; - qemu_irq parent_irq[NCPU]; - int enabled; - int cpu_enabled[NCPU]; - - gic_irq_state irq_state[GIC_NIRQ]; -#ifndef NVIC - int irq_target[GIC_NIRQ]; -#endif - int priority1[32][NCPU]; - int priority2[GIC_NIRQ - 32]; - int last_active[GIC_NIRQ][NCPU]; - - int priority_mask[NCPU]; - int running_irq[NCPU]; - int running_priority[NCPU]; - int current_pending[NCPU]; - - qemu_irq *in; -#ifdef NVIC - void *nvic; -#endif -} gic_state; - -/* TODO: Many places that call this routine could be optimized. */ -/* Update interrupt status after enabled or pending bits have been changed. */ -static void gic_update(gic_state *s) -{ - int best_irq; - int best_prio; - int irq; - int level; - int cpu; - int cm; - - for (cpu = 0; cpu < NCPU; cpu++) { - cm = 1 << cpu; - s->current_pending[cpu] = 1023; - if (!s->enabled || !s->cpu_enabled[cpu]) { - qemu_irq_lower(s->parent_irq[cpu]); - return; - } - best_prio = 0x100; - best_irq = 1023; - for (irq = 0; irq < GIC_NIRQ; irq++) { - if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) { - if (GIC_GET_PRIORITY(irq, cpu) < best_prio) { - best_prio = GIC_GET_PRIORITY(irq, cpu); - best_irq = irq; - } - } - } - level = 0; - if (best_prio <= s->priority_mask[cpu]) { - s->current_pending[cpu] = best_irq; - if (best_prio < s->running_priority[cpu]) { - DPRINTF("Raised pending IRQ %d\n", best_irq); - level = 1; - } - } - qemu_set_irq(s->parent_irq[cpu], level); - } -} - -static void __attribute__((unused)) -gic_set_pending_private(gic_state *s, int cpu, int irq) -{ - int cm = 1 << cpu; - - if (GIC_TEST_PENDING(irq, cm)) - return; - - DPRINTF("Set %d pending cpu %d\n", irq, cpu); - GIC_SET_PENDING(irq, cm); - gic_update(s); -} - -/* Process a change in an external IRQ input. */ -static void gic_set_irq(void *opaque, int irq, int level) -{ - gic_state *s = (gic_state *)opaque; - /* The first external input line is internal interrupt 32. */ - irq += 32; - if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK)) - return; - - if (level) { - GIC_SET_LEVEL(irq, ALL_CPU_MASK); - if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) { - DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq)); - GIC_SET_PENDING(irq, GIC_TARGET(irq)); - } - } else { - GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK); - } - gic_update(s); -} - -static void gic_set_running_irq(gic_state *s, int cpu, int irq) -{ - s->running_irq[cpu] = irq; - if (irq == 1023) { - s->running_priority[cpu] = 0x100; - } else { - s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu); - } - gic_update(s); -} - -static uint32_t gic_acknowledge_irq(gic_state *s, int cpu) -{ - int new_irq; - int cm = 1 << cpu; - new_irq = s->current_pending[cpu]; - if (new_irq == 1023 - || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) { - DPRINTF("ACK no pending IRQ\n"); - return 1023; - } - s->last_active[new_irq][cpu] = s->running_irq[cpu]; - /* Clear pending flags for both level and edge triggered interrupts. - Level triggered IRQs will be reasserted once they become inactive. */ - GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm); - gic_set_running_irq(s, cpu, new_irq); - DPRINTF("ACK %d\n", new_irq); - return new_irq; -} - -static void gic_complete_irq(gic_state * s, int cpu, int irq) -{ - int update = 0; - int cm = 1 << cpu; - DPRINTF("EOI %d\n", irq); - if (s->running_irq[cpu] == 1023) - return; /* No active IRQ. */ - if (irq != 1023) { - /* Mark level triggered interrupts as pending if they are still - raised. */ - if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq) - && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) { - DPRINTF("Set %d pending mask %x\n", irq, cm); - GIC_SET_PENDING(irq, cm); - update = 1; - } - } - if (irq != s->running_irq[cpu]) { - /* Complete an IRQ that is not currently running. */ - int tmp = s->running_irq[cpu]; - while (s->last_active[tmp][cpu] != 1023) { - if (s->last_active[tmp][cpu] == irq) { - s->last_active[tmp][cpu] = s->last_active[irq][cpu]; - break; - } - tmp = s->last_active[tmp][cpu]; - } - if (update) { - gic_update(s); - } - } else { - /* Complete the current running IRQ. */ - gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]); - } -} - -static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset) -{ - gic_state *s = (gic_state *)opaque; - uint32_t res; - int irq; - int i; - int cpu; - int cm; - int mask; - - cpu = gic_get_current_cpu(); - cm = 1 << cpu; - offset -= s->base + GIC_DIST_OFFSET; - if (offset < 0x100) { -#ifndef NVIC - if (offset == 0) - return s->enabled; - if (offset == 4) - return ((GIC_NIRQ / 32) - 1) | ((NCPU - 1) << 5); - if (offset < 0x08) - return 0; -#endif - goto bad_reg; - } else if (offset < 0x200) { - /* Interrupt Set/Clear Enable. */ - if (offset < 0x180) - irq = (offset - 0x100) * 8; - else - irq = (offset - 0x180) * 8; - irq += GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - res = 0; - for (i = 0; i < 8; i++) { - if (GIC_TEST_ENABLED(irq + i)) { - res |= (1 << i); - } - } - } else if (offset < 0x300) { - /* Interrupt Set/Clear Pending. */ - if (offset < 0x280) - irq = (offset - 0x200) * 8; - else - irq = (offset - 0x280) * 8; - irq += GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - res = 0; - mask = (irq < 32) ? cm : ALL_CPU_MASK; - for (i = 0; i < 8; i++) { - if (GIC_TEST_PENDING(irq + i, mask)) { - res |= (1 << i); - } - } - } else if (offset < 0x400) { - /* Interrupt Active. */ - irq = (offset - 0x300) * 8 + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - res = 0; - mask = (irq < 32) ? cm : ALL_CPU_MASK; - for (i = 0; i < 8; i++) { - if (GIC_TEST_ACTIVE(irq + i, mask)) { - res |= (1 << i); - } - } - } else if (offset < 0x800) { - /* Interrupt Priority. */ - irq = (offset - 0x400) + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - res = GIC_GET_PRIORITY(irq, cpu); -#ifndef NVIC - } else if (offset < 0xc00) { - /* Interrupt CPU Target. */ - irq = (offset - 0x800) + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - if (irq >= 29 && irq <= 31) { - res = cm; - } else { - res = GIC_TARGET(irq); - } - } else if (offset < 0xf00) { - /* Interrupt Configuration. */ - irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - res = 0; - for (i = 0; i < 4; i++) { - if (GIC_TEST_MODEL(irq + i)) - res |= (1 << (i * 2)); - if (GIC_TEST_TRIGGER(irq + i)) - res |= (2 << (i * 2)); - } -#endif - } else if (offset < 0xfe0) { - goto bad_reg; - } else /* offset >= 0xfe0 */ { - if (offset & 3) { - res = 0; - } else { - res = gic_id[(offset - 0xfe0) >> 2]; - } - } - return res; -bad_reg: - cpu_abort(cpu_single_env, "gic_dist_readb: Bad offset %x\n", (int)offset); - return 0; -} - -static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset) -{ - uint32_t val; - val = gic_dist_readb(opaque, offset); - val |= gic_dist_readb(opaque, offset + 1) << 8; - return val; -} - -static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset) -{ - uint32_t val; -#ifdef NVIC - gic_state *s = (gic_state *)opaque; - uint32_t addr; - addr = offset - s->base; - if (addr < 0x100 || addr > 0xd00) - return nvic_readl(s->nvic, addr); -#endif - val = gic_dist_readw(opaque, offset); - val |= gic_dist_readw(opaque, offset + 2) << 16; - return val; -} - -static void gic_dist_writeb(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - gic_state *s = (gic_state *)opaque; - int irq; - int i; - int cpu; - - cpu = gic_get_current_cpu(); - offset -= s->base + GIC_DIST_OFFSET; - if (offset < 0x100) { -#ifdef NVIC - goto bad_reg; -#else - if (offset == 0) { - s->enabled = (value & 1); - DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis"); - } else if (offset < 4) { - /* ignored. */ - } else { - goto bad_reg; - } -#endif - } else if (offset < 0x180) { - /* Interrupt Set Enable. */ - irq = (offset - 0x100) * 8 + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - if (irq < 16) - value = 0xff; - for (i = 0; i < 8; i++) { - if (value & (1 << i)) { - int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq); - if (!GIC_TEST_ENABLED(irq + i)) - DPRINTF("Enabled IRQ %d\n", irq + i); - GIC_SET_ENABLED(irq + i); - /* If a raised level triggered IRQ enabled then mark - is as pending. */ - if (GIC_TEST_LEVEL(irq + i, mask) - && !GIC_TEST_TRIGGER(irq + i)) { - DPRINTF("Set %d pending mask %x\n", irq + i, mask); - GIC_SET_PENDING(irq + i, mask); - } - } - } - } else if (offset < 0x200) { - /* Interrupt Clear Enable. */ - irq = (offset - 0x180) * 8 + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - if (irq < 16) - value = 0; - for (i = 0; i < 8; i++) { - if (value & (1 << i)) { - if (GIC_TEST_ENABLED(irq + i)) - DPRINTF("Disabled IRQ %d\n", irq + i); - GIC_CLEAR_ENABLED(irq + i); - } - } - } else if (offset < 0x280) { - /* Interrupt Set Pending. */ - irq = (offset - 0x200) * 8 + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - if (irq < 16) - irq = 0; - - for (i = 0; i < 8; i++) { - if (value & (1 << i)) { - GIC_SET_PENDING(irq + i, GIC_TARGET(irq)); - } - } - } else if (offset < 0x300) { - /* Interrupt Clear Pending. */ - irq = (offset - 0x280) * 8 + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - for (i = 0; i < 8; i++) { - /* ??? This currently clears the pending bit for all CPUs, even - for per-CPU interrupts. It's unclear whether this is the - corect behavior. */ - if (value & (1 << i)) { - GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK); - } - } - } else if (offset < 0x400) { - /* Interrupt Active. */ - goto bad_reg; - } else if (offset < 0x800) { - /* Interrupt Priority. */ - irq = (offset - 0x400) + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - if (irq < 32) { - s->priority1[irq][cpu] = value; - } else { - s->priority2[irq - 32] = value; - } -#ifndef NVIC - } else if (offset < 0xc00) { - /* Interrupt CPU Target. */ - irq = (offset - 0x800) + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - if (irq < 29) - value = 0; - else if (irq < 32) - value = ALL_CPU_MASK; - s->irq_target[irq] = value & ALL_CPU_MASK; - } else if (offset < 0xf00) { - /* Interrupt Configuration. */ - irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ; - if (irq >= GIC_NIRQ) - goto bad_reg; - if (irq < 32) - value |= 0xaa; - for (i = 0; i < 4; i++) { - if (value & (1 << (i * 2))) { - GIC_SET_MODEL(irq + i); - } else { - GIC_CLEAR_MODEL(irq + i); - } - if (value & (2 << (i * 2))) { - GIC_SET_TRIGGER(irq + i); - } else { - GIC_CLEAR_TRIGGER(irq + i); - } - } -#endif - } else { - /* 0xf00 is only handled for 32-bit writes. */ - goto bad_reg; - } - gic_update(s); - return; -bad_reg: - cpu_abort(cpu_single_env, "gic_dist_writeb: Bad offset %x\n", (int)offset); -} - -static void gic_dist_writew(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - gic_dist_writeb(opaque, offset, value & 0xff); - gic_dist_writeb(opaque, offset + 1, value >> 8); -} - -static void gic_dist_writel(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - gic_state *s = (gic_state *)opaque; -#ifdef NVIC - uint32_t addr; - addr = offset - s->base; - if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) { - nvic_writel(s->nvic, addr, value); - return; - } -#endif - if (offset - s->base == GIC_DIST_OFFSET + 0xf00) { - int cpu; - int irq; - int mask; - - cpu = gic_get_current_cpu(); - irq = value & 0x3ff; - switch ((value >> 24) & 3) { - case 0: - mask = (value >> 16) & ALL_CPU_MASK; - break; - case 1: - mask = 1 << cpu; - break; - case 2: - mask = ALL_CPU_MASK ^ (1 << cpu); - break; - default: - DPRINTF("Bad Soft Int target filter\n"); - mask = ALL_CPU_MASK; - break; - } - GIC_SET_PENDING(irq, mask); - gic_update(s); - return; - } - gic_dist_writew(opaque, offset, value & 0xffff); - gic_dist_writew(opaque, offset + 2, value >> 16); -} - -static CPUReadMemoryFunc *gic_dist_readfn[] = { - gic_dist_readb, - gic_dist_readw, - gic_dist_readl -}; - -static CPUWriteMemoryFunc *gic_dist_writefn[] = { - gic_dist_writeb, - gic_dist_writew, - gic_dist_writel -}; - -#ifndef NVIC -static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset) -{ - switch (offset) { - case 0x00: /* Control */ - return s->cpu_enabled[cpu]; - case 0x04: /* Priority mask */ - return s->priority_mask[cpu]; - case 0x08: /* Binary Point */ - /* ??? Not implemented. */ - return 0; - case 0x0c: /* Acknowledge */ - return gic_acknowledge_irq(s, cpu); - case 0x14: /* Runing Priority */ - return s->running_priority[cpu]; - case 0x18: /* Highest Pending Interrupt */ - return s->current_pending[cpu]; - default: - cpu_abort(cpu_single_env, "gic_cpu_read: Bad offset %x\n", - (int)offset); - return 0; - } -} - -static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value) -{ - switch (offset) { - case 0x00: /* Control */ - s->cpu_enabled[cpu] = (value & 1); - DPRINTF("CPU %sabled\n", s->cpu_enabled ? "En" : "Dis"); - break; - case 0x04: /* Priority mask */ - s->priority_mask[cpu] = (value & 0xff); - break; - case 0x08: /* Binary Point */ - /* ??? Not implemented. */ - break; - case 0x10: /* End Of Interrupt */ - return gic_complete_irq(s, cpu, value & 0x3ff); - default: - cpu_abort(cpu_single_env, "gic_cpu_write: Bad offset %x\n", - (int)offset); - return; - } - gic_update(s); -} -#endif - -static void gic_reset(gic_state *s) -{ - int i; - memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state)); - for (i = 0 ; i < NCPU; i++) { - s->priority_mask[i] = 0xf0; - s->current_pending[i] = 1023; - s->running_irq[i] = 1023; - s->running_priority[i] = 0x100; -#ifdef NVIC - /* The NVIC doesn't have per-cpu interfaces, so enable by default. */ - s->cpu_enabled[i] = 1; -#else - s->cpu_enabled[i] = 0; -#endif - } - for (i = 0; i < 16; i++) { - GIC_SET_ENABLED(i); - GIC_SET_TRIGGER(i); - } -#ifdef NVIC - /* The NVIC is always enabled. */ - s->enabled = 1; -#else - s->enabled = 0; -#endif -} - -static void gic_save(QEMUFile *f, void *opaque) -{ - gic_state *s = (gic_state *)opaque; - int i; - int j; - - qemu_put_be32(f, s->enabled); - for (i = 0; i < NCPU; i++) { - qemu_put_be32(f, s->cpu_enabled[i]); -#ifndef NVIC - qemu_put_be32(f, s->irq_target[i]); -#endif - for (j = 0; j < 32; j++) - qemu_put_be32(f, s->priority1[j][i]); - for (j = 0; j < GIC_NIRQ; j++) - qemu_put_be32(f, s->last_active[j][i]); - qemu_put_be32(f, s->priority_mask[i]); - qemu_put_be32(f, s->running_irq[i]); - qemu_put_be32(f, s->running_priority[i]); - qemu_put_be32(f, s->current_pending[i]); - } - for (i = 0; i < GIC_NIRQ - 32; i++) { - qemu_put_be32(f, s->priority2[i]); - } - for (i = 0; i < GIC_NIRQ; i++) { - qemu_put_byte(f, s->irq_state[i].enabled); - qemu_put_byte(f, s->irq_state[i].pending); - qemu_put_byte(f, s->irq_state[i].active); - qemu_put_byte(f, s->irq_state[i].level); - qemu_put_byte(f, s->irq_state[i].model); - qemu_put_byte(f, s->irq_state[i].trigger); - } -} - -static int gic_load(QEMUFile *f, void *opaque, int version_id) -{ - gic_state *s = (gic_state *)opaque; - int i; - int j; - - if (version_id != 1) - return -EINVAL; - - s->enabled = qemu_get_be32(f); - for (i = 0; i < NCPU; i++) { - s->cpu_enabled[i] = qemu_get_be32(f); -#ifndef NVIC - s->irq_target[i] = qemu_get_be32(f); -#endif - for (j = 0; j < 32; j++) - s->priority1[j][i] = qemu_get_be32(f); - for (j = 0; j < GIC_NIRQ; j++) - s->last_active[j][i] = qemu_get_be32(f); - s->priority_mask[i] = qemu_get_be32(f); - s->running_irq[i] = qemu_get_be32(f); - s->running_priority[i] = qemu_get_be32(f); - s->current_pending[i] = qemu_get_be32(f); - } - for (i = 0; i < GIC_NIRQ - 32; i++) { - s->priority2[i] = qemu_get_be32(f); - } - for (i = 0; i < GIC_NIRQ; i++) { - s->irq_state[i].enabled = qemu_get_byte(f); - s->irq_state[i].pending = qemu_get_byte(f); - s->irq_state[i].active = qemu_get_byte(f); - s->irq_state[i].level = qemu_get_byte(f); - s->irq_state[i].model = qemu_get_byte(f); - s->irq_state[i].trigger = qemu_get_byte(f); - } - - return 0; -} - -static gic_state *gic_init(uint32_t base, qemu_irq *parent_irq) -{ - gic_state *s; - int iomemtype; - int i; - - s = (gic_state *)qemu_mallocz(sizeof(gic_state)); - if (!s) - return NULL; - s->in = qemu_allocate_irqs(gic_set_irq, s, GIC_NIRQ); - for (i = 0; i < NCPU; i++) { - s->parent_irq[i] = parent_irq[i]; - } - iomemtype = cpu_register_io_memory(0, gic_dist_readfn, - gic_dist_writefn, s); - cpu_register_physical_memory(base + GIC_DIST_OFFSET, 0x00001000, - iomemtype); - s->base = base; - gic_reset(s); - register_savevm("arm_gic", -1, 1, gic_save, gic_load, s); - return s; -} diff --git a/hw/arm_pic.c b/hw/arm_pic.c deleted file mode 100644 index 1fe55b7..0000000 --- a/hw/arm_pic.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Generic ARM Programmable Interrupt Controller support. - * - * Copyright (c) 2006 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the LGPL - */ - -#include "hw.h" -#include "arm-misc.h" - -/* Stub functions for hardware that doesn't exist. */ -void pic_info(void) -{ -} - -void irq_info(void) -{ -} - - -/* Input 0 is IRQ and input 1 is FIQ. */ -static void arm_pic_cpu_handler(void *opaque, int irq, int level) -{ - CPUState *env = (CPUState *)opaque; - switch (irq) { - case ARM_PIC_CPU_IRQ: - if (level) - cpu_interrupt(env, CPU_INTERRUPT_HARD); - else - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); - break; - case ARM_PIC_CPU_FIQ: - if (level) - cpu_interrupt(env, CPU_INTERRUPT_FIQ); - else - cpu_reset_interrupt(env, CPU_INTERRUPT_FIQ); - break; - default: - cpu_abort(env, "arm_pic_cpu_handler: Bad interrput line %d\n", irq); - } -} - -qemu_irq *arm_pic_init_cpu(CPUState *env) -{ - return qemu_allocate_irqs(arm_pic_cpu_handler, env, 2); -} diff --git a/hw/arm_pic.h b/hw/arm_pic.h deleted file mode 100644 index 7886bcf..0000000 --- a/hw/arm_pic.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Generic ARM Programmable Interrupt Controller support. - * - * Copyright (c) 2006 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the LGPL. - * - * Arm hardware uses a wide variety of interrupt handling hardware. - * This provides a generic framework for connecting interrupt sources and - * inputs. - */ - -#ifndef ARM_INTERRUPT_H -#define ARM_INTERRUPT_H 1 - -#include "irq.h" - -/* The CPU is also modeled as an interrupt controller. */ -#define ARM_PIC_CPU_IRQ 0 -#define ARM_PIC_CPU_FIQ 1 -qemu_irq *arm_pic_init_cpu(CPUState *env); - -#endif /* !ARM_INTERRUPT_H */ - diff --git a/hw/armv7m.c b/hw/armv7m.c deleted file mode 100644 index b2bad3c..0000000 --- a/hw/armv7m.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * ARMV7M System emulation. - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the GPL. - */ - -#include "hw.h" -#include "arm-misc.h" -#include "sysemu.h" - -/* Bitbanded IO. Each word corresponds to a single bit. */ - -/* Get the byte address of the real memory for a bitband acess. */ -static inline uint32_t bitband_addr(uint32_t addr) -{ - uint32_t res; - - res = addr & 0xe0000000; - res |= (addr & 0x1ffffff) >> 5; - return res; - -} - -static uint32_t bitband_readb(void *opaque, target_phys_addr_t offset) -{ - uint8_t v; - cpu_physical_memory_read(bitband_addr(offset), &v, 1); - return (v & (1 << ((offset >> 2) & 7))) != 0; -} - -static void bitband_writeb(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - uint32_t addr; - uint8_t mask; - uint8_t v; - addr = bitband_addr(offset); - mask = (1 << ((offset >> 2) & 7)); - cpu_physical_memory_read(addr, &v, 1); - if (value & 1) - v |= mask; - else - v &= ~mask; - cpu_physical_memory_write(addr, &v, 1); -} - -static uint32_t bitband_readw(void *opaque, target_phys_addr_t offset) -{ - uint32_t addr; - uint16_t mask; - uint16_t v; - addr = bitband_addr(offset) & ~1; - mask = (1 << ((offset >> 2) & 15)); - mask = tswap16(mask); - cpu_physical_memory_read(addr, (uint8_t *)&v, 2); - return (v & mask) != 0; -} - -static void bitband_writew(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - uint32_t addr; - uint16_t mask; - uint16_t v; - addr = bitband_addr(offset) & ~1; - mask = (1 << ((offset >> 2) & 15)); - mask = tswap16(mask); - cpu_physical_memory_read(addr, (uint8_t *)&v, 2); - if (value & 1) - v |= mask; - else - v &= ~mask; - cpu_physical_memory_write(addr, (uint8_t *)&v, 2); -} - -static uint32_t bitband_readl(void *opaque, target_phys_addr_t offset) -{ - uint32_t addr; - uint32_t mask; - uint32_t v; - addr = bitband_addr(offset) & ~3; - mask = (1 << ((offset >> 2) & 31)); - mask = tswap32(mask); - cpu_physical_memory_read(addr, (uint8_t *)&v, 4); - return (v & mask) != 0; -} - -static void bitband_writel(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - uint32_t addr; - uint32_t mask; - uint32_t v; - addr = bitband_addr(offset) & ~3; - mask = (1 << ((offset >> 2) & 31)); - mask = tswap32(mask); - cpu_physical_memory_read(addr, (uint8_t *)&v, 4); - if (value & 1) - v |= mask; - else - v &= ~mask; - cpu_physical_memory_write(addr, (uint8_t *)&v, 4); -} - -static CPUReadMemoryFunc *bitband_readfn[] = { - bitband_readb, - bitband_readw, - bitband_readl -}; - -static CPUWriteMemoryFunc *bitband_writefn[] = { - bitband_writeb, - bitband_writew, - bitband_writel -}; - -static void armv7m_bitband_init(void) -{ - int iomemtype; - - iomemtype = cpu_register_io_memory(0, bitband_readfn, bitband_writefn, - NULL); - cpu_register_physical_memory(0x22000000, 0x02000000, iomemtype); - cpu_register_physical_memory(0x42000000, 0x02000000, iomemtype); -} - -/* Board init. */ -/* Init CPU and memory for a v7-M based board. - flash_size and sram_size are in kb. - Returns the NVIC array. */ - -qemu_irq *armv7m_init(int flash_size, int sram_size, - const char *kernel_filename, const char *cpu_model) -{ - CPUState *env; - qemu_irq *pic; - uint32_t pc; - int image_size; - uint64_t entry; - uint64_t lowaddr; - - flash_size *= 1024; - sram_size *= 1024; - - if (!cpu_model) - cpu_model = "cortex-m3"; - env = cpu_init(cpu_model); - if (!env) { - fprintf(stderr, "Unable to find CPU definition\n"); - exit(1); - } - -#if 0 - /* > 32Mb SRAM gets complicated because it overlaps the bitband area. - We don't have proper commandline options, so allocate half of memory - as SRAM, up to a maximum of 32Mb, and the rest as code. */ - if (ram_size > (512 + 32) * 1024 * 1024) - ram_size = (512 + 32) * 1024 * 1024; - sram_size = (ram_size / 2) & TARGET_PAGE_MASK; - if (sram_size > 32 * 1024 * 1024) - sram_size = 32 * 1024 * 1024; - code_size = ram_size - sram_size; -#endif - - /* Flash programming is done via the SCU, so pretend it is ROM. */ - cpu_register_physical_memory(0, flash_size, IO_MEM_ROM); - cpu_register_physical_memory(0x20000000, sram_size, - flash_size + IO_MEM_RAM); - armv7m_bitband_init(); - - pic = armv7m_nvic_init(env); - - image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL); - if (image_size < 0) { - image_size = load_image(kernel_filename, phys_ram_base); - lowaddr = 0; - } - if (image_size < 0) { - fprintf(stderr, "qemu: could not load kernel '%s'\n", - kernel_filename); - exit(1); - } - - /* If the image was loaded at address zero then assume it is a - regular ROM image and perform the normal CPU reset sequence. - Otherwise jump directly to the entry point. */ - if (lowaddr == 0) { - env->regs[13] = tswap32(*(uint32_t *)phys_ram_base); - pc = tswap32(*(uint32_t *)(phys_ram_base + 4)); - } else { - pc = entry; - } - env->thumb = pc & 1; - env->regs[15] = pc & ~1; - - /* Hack to map an additional page of ram at the top of the address - space. This stops qemu complaining about executing code outside RAM - when returning from an exception. */ - cpu_register_physical_memory(0xfffff000, 0x1000, IO_MEM_RAM + ram_size); - - return pic; -} - diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c deleted file mode 100644 index c55c958..0000000 --- a/hw/armv7m_nvic.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * ARM Nested Vectored Interrupt Controller - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the GPL. - * - * The ARMv7M System controller is fairly tightly tied in with the - * NVIC. Much of that is also implemented here. - */ - -#include "hw.h" -#include "qemu-timer.h" -#include "arm-misc.h" - -/* 32 internal lines (16 used for system exceptions) plus 64 external - interrupt lines. */ -#define GIC_NIRQ 96 -#define NCPU 1 -#define NVIC 1 - -/* Only a single "CPU" interface is present. */ -static inline int -gic_get_current_cpu(void) -{ - return 0; -} - -static uint32_t nvic_readl(void *opaque, uint32_t offset); -static void nvic_writel(void *opaque, uint32_t offset, uint32_t value); - -#include "arm_gic.c" - -typedef struct { - struct { - uint32_t control; - uint32_t reload; - int64_t tick; - QEMUTimer *timer; - } systick; - gic_state *gic; -} nvic_state; - -/* qemu timers run at 1GHz. We want something closer to 1MHz. */ -#define SYSTICK_SCALE 1000ULL - -#define SYSTICK_ENABLE (1 << 0) -#define SYSTICK_TICKINT (1 << 1) -#define SYSTICK_CLKSOURCE (1 << 2) -#define SYSTICK_COUNTFLAG (1 << 16) - -/* Conversion factor from qemu timer to SysTick frequencies. */ -static inline int64_t systick_scale(nvic_state *s) -{ - if (s->systick.control & SYSTICK_CLKSOURCE) - return system_clock_scale; - else - return 1000; -} - -static void systick_reload(nvic_state *s, int reset) -{ - if (reset) - s->systick.tick = qemu_get_clock(vm_clock); - s->systick.tick += (s->systick.reload + 1) * systick_scale(s); - qemu_mod_timer(s->systick.timer, s->systick.tick); -} - -static void systick_timer_tick(void * opaque) -{ - nvic_state *s = (nvic_state *)opaque; - s->systick.control |= SYSTICK_COUNTFLAG; - if (s->systick.control & SYSTICK_TICKINT) { - /* Trigger the interrupt. */ - armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK); - } - if (s->systick.reload == 0) { - s->systick.control &= ~SYSTICK_ENABLE; - } else { - systick_reload(s, 0); - } -} - -/* The external routines use the hardware vector numbering, ie. the first - IRQ is #16. The internal GIC routines use #32 as the first IRQ. */ -void armv7m_nvic_set_pending(void *opaque, int irq) -{ - nvic_state *s = (nvic_state *)opaque; - if (irq >= 16) - irq += 16; - gic_set_pending_private(s->gic, 0, irq); -} - -/* Make pending IRQ active. */ -int armv7m_nvic_acknowledge_irq(void *opaque) -{ - nvic_state *s = (nvic_state *)opaque; - uint32_t irq; - - irq = gic_acknowledge_irq(s->gic, 0); - if (irq == 1023) - cpu_abort(cpu_single_env, "Interrupt but no vector\n"); - if (irq >= 32) - irq -= 16; - return irq; -} - -void armv7m_nvic_complete_irq(void *opaque, int irq) -{ - nvic_state *s = (nvic_state *)opaque; - if (irq >= 16) - irq += 16; - gic_complete_irq(s->gic, 0, irq); -} - -static uint32_t nvic_readl(void *opaque, uint32_t offset) -{ - nvic_state *s = (nvic_state *)opaque; - uint32_t val; - int irq; - - switch (offset) { - case 4: /* Interrupt Control Type. */ - return (GIC_NIRQ / 32) - 1; - case 0x10: /* SysTick Control and Status. */ - val = s->systick.control; - s->systick.control &= ~SYSTICK_COUNTFLAG; - return val; - case 0x14: /* SysTick Reload Value. */ - return s->systick.reload; - case 0x18: /* SysTick Current Value. */ - { - int64_t t; - if ((s->systick.control & SYSTICK_ENABLE) == 0) - return 0; - t = qemu_get_clock(vm_clock); - if (t >= s->systick.tick) - return 0; - val = ((s->systick.tick - (t + 1)) / systick_scale(s)) + 1; - /* The interrupt in triggered when the timer reaches zero. - However the counter is not reloaded until the next clock - tick. This is a hack to return zero during the first tick. */ - if (val > s->systick.reload) - val = 0; - return val; - } - case 0x1c: /* SysTick Calibration Value. */ - return 10000; - case 0xd00: /* CPUID Base. */ - return cpu_single_env->cp15.c0_cpuid; - case 0xd04: /* Interrypt Control State. */ - /* VECTACTIVE */ - val = s->gic->running_irq[0]; - if (val == 1023) { - val = 0; - } else if (val >= 32) { - val -= 16; - } - /* RETTOBASE */ - if (s->gic->running_irq[0] == 1023 - || s->gic->last_active[s->gic->running_irq[0]][0] == 1023) { - val |= (1 << 11); - } - /* VECTPENDING */ - if (s->gic->current_pending[0] != 1023) - val |= (s->gic->current_pending[0] << 12); - /* ISRPENDING */ - for (irq = 32; irq < GIC_NIRQ; irq++) { - if (s->gic->irq_state[irq].pending) { - val |= (1 << 22); - break; - } - } - /* PENDSTSET */ - if (s->gic->irq_state[ARMV7M_EXCP_SYSTICK].pending) - val |= (1 << 26); - /* PENDSVSET */ - if (s->gic->irq_state[ARMV7M_EXCP_PENDSV].pending) - val |= (1 << 28); - /* NMIPENDSET */ - if (s->gic->irq_state[ARMV7M_EXCP_NMI].pending) - val |= (1 << 31); - return val; - case 0xd08: /* Vector Table Offset. */ - return cpu_single_env->v7m.vecbase; - case 0xd0c: /* Application Interrupt/Reset Control. */ - return 0xfa05000; - case 0xd10: /* System Control. */ - /* TODO: Implement SLEEPONEXIT. */ - return 0; - case 0xd14: /* Configuration Control. */ - /* TODO: Implement Configuration Control bits. */ - return 0; - case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */ - irq = offset - 0xd14; - val = 0; - val = s->gic->priority1[irq++][0]; - val = s->gic->priority1[irq++][0] << 8; - val = s->gic->priority1[irq++][0] << 16; - val = s->gic->priority1[irq][0] << 24; - return val; - case 0xd24: /* System Handler Status. */ - val = 0; - if (s->gic->irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0); - if (s->gic->irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1); - if (s->gic->irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3); - if (s->gic->irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7); - if (s->gic->irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8); - if (s->gic->irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10); - if (s->gic->irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11); - if (s->gic->irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12); - if (s->gic->irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13); - if (s->gic->irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14); - if (s->gic->irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15); - if (s->gic->irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16); - if (s->gic->irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17); - if (s->gic->irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18); - return val; - case 0xd28: /* Configurable Fault Status. */ - /* TODO: Implement Fault Status. */ - cpu_abort(cpu_single_env, - "Not implemented: Configurable Fault Status."); - return 0; - case 0xd2c: /* Hard Fault Status. */ - case 0xd30: /* Debug Fault Status. */ - case 0xd34: /* Mem Manage Address. */ - case 0xd38: /* Bus Fault Address. */ - case 0xd3c: /* Aux Fault Status. */ - /* TODO: Implement fault status registers. */ - goto bad_reg; - case 0xd40: /* PFR0. */ - return 0x00000030; - case 0xd44: /* PRF1. */ - return 0x00000200; - case 0xd48: /* DFR0. */ - return 0x00100000; - case 0xd4c: /* AFR0. */ - return 0x00000000; - case 0xd50: /* MMFR0. */ - return 0x00000030; - case 0xd54: /* MMFR1. */ - return 0x00000000; - case 0xd58: /* MMFR2. */ - return 0x00000000; - case 0xd5c: /* MMFR3. */ - return 0x00000000; - case 0xd60: /* ISAR0. */ - return 0x01141110; - case 0xd64: /* ISAR1. */ - return 0x02111000; - case 0xd68: /* ISAR2. */ - return 0x21112231; - case 0xd6c: /* ISAR3. */ - return 0x01111110; - case 0xd70: /* ISAR4. */ - return 0x01310102; - /* TODO: Implement debug registers. */ - default: - bad_reg: - cpu_abort(cpu_single_env, "NVIC: Bad read offset 0x%x\n", offset); - } -} - -static void nvic_writel(void *opaque, uint32_t offset, uint32_t value) -{ - nvic_state *s = (nvic_state *)opaque; - uint32_t oldval; - switch (offset) { - case 0x10: /* SysTick Control and Status. */ - oldval = s->systick.control; - s->systick.control &= 0xfffffff8; - s->systick.control |= value & 7; - if ((oldval ^ value) & SYSTICK_ENABLE) { - int64_t now = qemu_get_clock(vm_clock); - if (value & SYSTICK_ENABLE) { - if (s->systick.tick) { - s->systick.tick += now; - qemu_mod_timer(s->systick.timer, s->systick.tick); - } else { - systick_reload(s, 1); - } - } else { - qemu_del_timer(s->systick.timer); - s->systick.tick -= now; - if (s->systick.tick < 0) - s->systick.tick = 0; - } - } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) { - /* This is a hack. Force the timer to be reloaded - when the reference clock is changed. */ - systick_reload(s, 1); - } - break; - case 0x14: /* SysTick Reload Value. */ - s->systick.reload = value; - break; - case 0x18: /* SysTick Current Value. Writes reload the timer. */ - systick_reload(s, 1); - s->systick.control &= ~SYSTICK_COUNTFLAG; - break; - case 0xd04: /* Interrupt Control State. */ - if (value & (1 << 31)) { - armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI); - } - if (value & (1 << 28)) { - armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV); - } else if (value & (1 << 27)) { - s->gic->irq_state[ARMV7M_EXCP_PENDSV].pending = 0; - gic_update(s->gic); - } - if (value & (1 << 26)) { - armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK); - } else if (value & (1 << 25)) { - s->gic->irq_state[ARMV7M_EXCP_SYSTICK].pending = 0; - gic_update(s->gic); - } - break; - case 0xd08: /* Vector Table Offset. */ - cpu_single_env->v7m.vecbase = value & 0xffffff80; - break; - case 0xd0c: /* Application Interrupt/Reset Control. */ - if ((value >> 16) == 0x05fa) { - if (value & 2) { - cpu_abort(cpu_single_env, "VECTCLRACTIVE not implemented"); - } - if (value & 5) { - cpu_abort(cpu_single_env, "System reset"); - } - } - break; - case 0xd10: /* System Control. */ - case 0xd14: /* Configuration Control. */ - /* TODO: Implement control registers. */ - goto bad_reg; - case 0xd18: case 0xd1c: case 0xd20: /* System Handler Priority. */ - { - int irq; - irq = offset - 0xd14; - s->gic->priority1[irq++][0] = value & 0xff; - s->gic->priority1[irq++][0] = (value >> 8) & 0xff; - s->gic->priority1[irq++][0] = (value >> 16) & 0xff; - s->gic->priority1[irq][0] = (value >> 24) & 0xff; - gic_update(s->gic); - } - break; - case 0xd24: /* System Handler Control. */ - /* TODO: Real hardware allows you to set/clear the active bits - under some circumstances. We don't implement this. */ - s->gic->irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0; - s->gic->irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0; - s->gic->irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0; - break; - case 0xd28: /* Configurable Fault Status. */ - case 0xd2c: /* Hard Fault Status. */ - case 0xd30: /* Debug Fault Status. */ - case 0xd34: /* Mem Manage Address. */ - case 0xd38: /* Bus Fault Address. */ - case 0xd3c: /* Aux Fault Status. */ - goto bad_reg; - default: - bad_reg: - cpu_abort(cpu_single_env, "NVIC: Bad write offset 0x%x\n", offset); - } -} - -static void nvic_save(QEMUFile *f, void *opaque) -{ - nvic_state *s = (nvic_state *)opaque; - - qemu_put_be32(f, s->systick.control); - qemu_put_be32(f, s->systick.reload); - qemu_put_be64(f, s->systick.tick); - qemu_put_timer(f, s->systick.timer); -} - -static int nvic_load(QEMUFile *f, void *opaque, int version_id) -{ - nvic_state *s = (nvic_state *)opaque; - - if (version_id != 1) - return -EINVAL; - - s->systick.control = qemu_get_be32(f); - s->systick.reload = qemu_get_be32(f); - s->systick.tick = qemu_get_be64(f); - qemu_get_timer(f, s->systick.timer); - - return 0; -} - -qemu_irq *armv7m_nvic_init(CPUState *env) -{ - nvic_state *s; - qemu_irq *parent; - - parent = arm_pic_init_cpu(env); - s = (nvic_state *)qemu_mallocz(sizeof(nvic_state)); - s->gic = gic_init(0xe000e000, &parent[ARM_PIC_CPU_IRQ]); - s->gic->nvic = s; - s->systick.timer = qemu_new_timer(vm_clock, systick_timer_tick, s); - if (env->v7m.nvic) - cpu_abort(env, "CPU can only have one NVIC\n"); - env->v7m.nvic = s; - register_savevm("armv7m_nvic", -1, 1, nvic_save, nvic_load, s); - return s->gic->in; -} diff --git a/hw/audiodev.h b/hw/audiodev.h deleted file mode 100644 index 5f4a211..0000000 --- a/hw/audiodev.h +++ /dev/null @@ -1,17 +0,0 @@ -/* es1370.c */ -int es1370_init (PCIBus *bus, AudioState *s); - -/* sb16.c */ -int SB16_init (AudioState *s, qemu_irq *pic); - -/* adlib.c */ -int Adlib_init (AudioState *s, qemu_irq *pic); - -/* gus.c */ -int GUS_init (AudioState *s, qemu_irq *pic); - -/* ac97.c */ -int ac97_init (PCIBus *buf, AudioState *s); - -/* cs4231a.c */ -int cs4231a_init (AudioState *s, qemu_irq *pic); diff --git a/hw/baum.h b/hw/baum.h deleted file mode 100644 index ac34b30..0000000 --- a/hw/baum.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * QEMU Baum - * - * Copyright (c) 2008 Samuel Thibault - * - * 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. - */ - -/* usb device */ -USBDevice *usb_baum_init(void); - -/* char device */ -CharDriverState *chr_baum_init(void); diff --git a/hw/boards.h b/hw/boards.h deleted file mode 100644 index cfb7c42..0000000 --- a/hw/boards.h +++ /dev/null @@ -1,122 +0,0 @@ -/* Declarations for use by board files for creating devices. */ - -#ifndef HW_BOARDS_H -#define HW_BOARDS_H - -typedef void QEMUMachineInitFunc(ram_addr_t ram_size, int vga_ram_size, - const char *boot_device, DisplayState *ds, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - const char *cpu_model); - -typedef struct QEMUMachine { - const char *name; - const char *desc; - QEMUMachineInitFunc *init; -#define RAMSIZE_FIXED (1 << 0) - ram_addr_t ram_require; - int nodisk_ok; - struct QEMUMachine *next; -} QEMUMachine; - -int qemu_register_machine(QEMUMachine *m); -void register_machines(void); - -/* Axis ETRAX. */ -extern QEMUMachine bareetraxfs_machine; - -/* pc.c */ -extern QEMUMachine pc_machine; -extern QEMUMachine isapc_machine; - -/* ppc.c */ -extern QEMUMachine prep_machine; -extern QEMUMachine core99_machine; -extern QEMUMachine heathrow_machine; -extern QEMUMachine ref405ep_machine; -extern QEMUMachine taihu_machine; - -/* mips_r4k.c */ -extern QEMUMachine mips_machine; - -/* mips_jazz.c */ -extern QEMUMachine mips_magnum_machine; -extern QEMUMachine mips_pica61_machine; - -/* mips_malta.c */ -extern QEMUMachine mips_malta_machine; - -/* mips_mipssim.c */ -extern QEMUMachine mips_mipssim_machine; - -/* shix.c */ -extern QEMUMachine shix_machine; - -/* r2d.c */ -extern QEMUMachine r2d_machine; - -/* sun4m.c */ -extern QEMUMachine ss5_machine, ss10_machine, ss600mp_machine, ss20_machine; -extern QEMUMachine voyager_machine, ss_lx_machine, ss4_machine, scls_machine; -extern QEMUMachine sbook_machine; -extern QEMUMachine ss2_machine; -extern QEMUMachine ss1000_machine, ss2000_machine; - -/* sun4u.c */ -extern QEMUMachine sun4u_machine; -extern QEMUMachine sun4v_machine; - -/* integratorcp.c */ -extern QEMUMachine integratorcp_machine; - -/* versatilepb.c */ -extern QEMUMachine versatilepb_machine; -extern QEMUMachine versatileab_machine; - -/* realview.c */ -extern QEMUMachine realview_machine; - -/* spitz.c */ -extern QEMUMachine akitapda_machine; -extern QEMUMachine spitzpda_machine; -extern QEMUMachine borzoipda_machine; -extern QEMUMachine terrierpda_machine; - -/* palm.c */ -extern QEMUMachine palmte_machine; - -/* nseries.c */ -extern QEMUMachine n800_machine; -extern QEMUMachine n810_machine; - -/* gumstix.c */ -extern QEMUMachine connex_machine; -extern QEMUMachine verdex_machine; - -/* stellaris.c */ -extern QEMUMachine lm3s811evb_machine; -extern QEMUMachine lm3s6965evb_machine; - -/* an5206.c */ -extern QEMUMachine an5206_machine; - -/* mcf5208.c */ -extern QEMUMachine mcf5208evb_machine; - -/* dummy_m68k.c */ -extern QEMUMachine dummy_m68k_machine; - -/* mainstone.c */ -extern QEMUMachine mainstone2_machine; - -/* musicpal.c */ -extern QEMUMachine musicpal_machine; - -/* tosa.c */ -extern QEMUMachine tosapda_machine; - -/* android_arm.c */ -extern QEMUMachine android_arm_machine; - -#endif diff --git a/hw/cdrom.c b/hw/cdrom.c deleted file mode 100644 index 2aa4d3b..0000000 --- a/hw/cdrom.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * QEMU ATAPI CD-ROM Emulator - * - * Copyright (c) 2006 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. - */ - -/* ??? Most of the ATAPI emulation is still in ide.c. It should be moved - here. */ - -#include "qemu-common.h" -#include "scsi-disk.h" - -static void lba_to_msf(uint8_t *buf, int lba) -{ - lba += 150; - buf[0] = (lba / 75) / 60; - buf[1] = (lba / 75) % 60; - buf[2] = lba % 75; -} - -/* same toc as bochs. Return -1 if error or the toc length */ -/* XXX: check this */ -int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track) -{ - uint8_t *q; - int len; - - if (start_track > 1 && start_track != 0xaa) - return -1; - q = buf + 2; - *q++ = 1; /* first session */ - *q++ = 1; /* last session */ - if (start_track <= 1) { - *q++ = 0; /* reserved */ - *q++ = 0x14; /* ADR, control */ - *q++ = 1; /* track number */ - *q++ = 0; /* reserved */ - if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, 0); - q += 3; - } else { - /* sector 0 */ - cpu_to_be32wu((uint32_t *)q, 0); - q += 4; - } - } - /* lead out track */ - *q++ = 0; /* reserved */ - *q++ = 0x16; /* ADR, control */ - *q++ = 0xaa; /* track number */ - *q++ = 0; /* reserved */ - if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, nb_sectors); - q += 3; - } else { - cpu_to_be32wu((uint32_t *)q, nb_sectors); - q += 4; - } - len = q - buf; - cpu_to_be16wu((uint16_t *)buf, len - 2); - return len; -} - -/* mostly same info as PearPc */ -int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num) -{ - uint8_t *q; - int len; - - q = buf + 2; - *q++ = 1; /* first session */ - *q++ = 1; /* last session */ - - *q++ = 1; /* session number */ - *q++ = 0x14; /* data track */ - *q++ = 0; /* track number */ - *q++ = 0xa0; /* lead-in */ - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - *q++ = 0; - *q++ = 1; /* first track */ - *q++ = 0x00; /* disk type */ - *q++ = 0x00; - - *q++ = 1; /* session number */ - *q++ = 0x14; /* data track */ - *q++ = 0; /* track number */ - *q++ = 0xa1; - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - *q++ = 0; - *q++ = 1; /* last track */ - *q++ = 0x00; - *q++ = 0x00; - - *q++ = 1; /* session number */ - *q++ = 0x14; /* data track */ - *q++ = 0; /* track number */ - *q++ = 0xa2; /* lead-out */ - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - if (msf) { - *q++ = 0; /* reserved */ - lba_to_msf(q, nb_sectors); - q += 3; - } else { - cpu_to_be32wu((uint32_t *)q, nb_sectors); - q += 4; - } - - *q++ = 1; /* session number */ - *q++ = 0x14; /* ADR, control */ - *q++ = 0; /* track number */ - *q++ = 1; /* point */ - *q++ = 0; /* min */ - *q++ = 0; /* sec */ - *q++ = 0; /* frame */ - if (msf) { - *q++ = 0; - lba_to_msf(q, 0); - q += 3; - } else { - *q++ = 0; - *q++ = 0; - *q++ = 0; - *q++ = 0; - } - - len = q - buf; - cpu_to_be16wu((uint16_t *)buf, len - 2); - return len; -} - - diff --git a/hw/devices.h b/hw/devices.h deleted file mode 100644 index 45fead9..0000000 --- a/hw/devices.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef QEMU_DEVICES_H -#define QEMU_DEVICES_H - -/* Devices that have nowhere better to go. */ - -/* smc91c111.c */ -void smc91c111_init(NICInfo *, uint32_t, qemu_irq); - -/* ssd0323.c */ -int ssd0323_xfer_ssi(void *opaque, int data); -void *ssd0323_init(DisplayState *ds, qemu_irq *cmd_p); - -/* ads7846.c */ -struct ads7846_state_s; -uint32_t ads7846_read(void *opaque); -void ads7846_write(void *opaque, uint32_t value); -struct ads7846_state_s *ads7846_init(qemu_irq penirq); - -/* tsc210x.c */ -struct uwire_slave_s; -struct mouse_transform_info_s; -struct uwire_slave_s *tsc2102_init(qemu_irq pint, AudioState *audio); -struct uwire_slave_s *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, - qemu_irq dav, AudioState *audio); -struct i2s_codec_s *tsc210x_codec(struct uwire_slave_s *chip); -uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len); -void tsc210x_set_transform(struct uwire_slave_s *chip, - struct mouse_transform_info_s *info); -void tsc210x_key_event(struct uwire_slave_s *chip, int key, int down); - -/* tsc2005.c */ -void *tsc2005_init(qemu_irq pintdav); -uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len); -void tsc2005_set_transform(void *opaque, struct mouse_transform_info_s *info); - -/* stellaris_input.c */ -void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode); - -/* blizzard.c */ -void *s1d13745_init(qemu_irq gpio_int, DisplayState *ds); -void s1d13745_write(void *opaque, int dc, uint16_t value); -void s1d13745_write_block(void *opaque, int dc, - void *buf, size_t len, int pitch); -uint16_t s1d13745_read(void *opaque, int dc); - -/* cbus.c */ -struct cbus_s { - qemu_irq clk; - qemu_irq dat; - qemu_irq sel; -}; -struct cbus_s *cbus_init(qemu_irq dat_out); -void cbus_attach(struct cbus_s *bus, void *slave_opaque); - -void *retu_init(qemu_irq irq, int vilma); -void *tahvo_init(qemu_irq irq, int betty); - -void retu_key_event(void *retu, int state); - -/* tusb6010.c */ -struct tusb_s; -struct tusb_s *tusb6010_init(qemu_irq intr); -int tusb6010_sync_io(struct tusb_s *s); -int tusb6010_async_io(struct tusb_s *s); -void tusb6010_power(struct tusb_s *s, int on); - -/* tc6393xb.c */ -struct tc6393xb_s; -struct tc6393xb_s *tc6393xb_init(uint32_t base, qemu_irq irq); -void tc6393xb_gpio_out_set(struct tc6393xb_s *s, int line, - qemu_irq handler); -qemu_irq *tc6393xb_gpio_in_get(struct tc6393xb_s *s); - -#endif diff --git a/hw/dma.c b/hw/dma.c deleted file mode 100644 index 00c6332..0000000 --- a/hw/dma.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * QEMU DMA emulation - * - * Copyright (c) 2003-2004 Vassili Karpov (malc) - * - * 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 "hw.h" -#include "isa.h" - -/* #define DEBUG_DMA */ - -#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__) -#ifdef DEBUG_DMA -#define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__) -#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__) -#define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__) -#else -#define lwarn(...) -#define linfo(...) -#define ldebug(...) -#endif - -#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) - -struct dma_regs { - int now[2]; - uint16_t base[2]; - uint8_t mode; - uint8_t page; - uint8_t pageh; - uint8_t dack; - uint8_t eop; - DMA_transfer_handler transfer_handler; - void *opaque; -}; - -#define ADDR 0 -#define COUNT 1 - -static struct dma_cont { - uint8_t status; - uint8_t command; - uint8_t mask; - uint8_t flip_flop; - int dshift; - struct dma_regs regs[4]; -} dma_controllers[2]; - -enum { - CMD_MEMORY_TO_MEMORY = 0x01, - CMD_FIXED_ADDRESS = 0x02, - CMD_BLOCK_CONTROLLER = 0x04, - CMD_COMPRESSED_TIME = 0x08, - CMD_CYCLIC_PRIORITY = 0x10, - CMD_EXTENDED_WRITE = 0x20, - CMD_LOW_DREQ = 0x40, - CMD_LOW_DACK = 0x80, - CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS - | CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE - | CMD_LOW_DREQ | CMD_LOW_DACK - -}; - -static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0}; - -static void write_page (void *opaque, uint32_t nport, uint32_t data) -{ - struct dma_cont *d = opaque; - int ichan; - - ichan = channels[nport & 7]; - if (-1 == ichan) { - dolog ("invalid channel %#x %#x\n", nport, data); - return; - } - d->regs[ichan].page = data; -} - -static void write_pageh (void *opaque, uint32_t nport, uint32_t data) -{ - struct dma_cont *d = opaque; - int ichan; - - ichan = channels[nport & 7]; - if (-1 == ichan) { - dolog ("invalid channel %#x %#x\n", nport, data); - return; - } - d->regs[ichan].pageh = data; -} - -static uint32_t read_page (void *opaque, uint32_t nport) -{ - struct dma_cont *d = opaque; - int ichan; - - ichan = channels[nport & 7]; - if (-1 == ichan) { - dolog ("invalid channel read %#x\n", nport); - return 0; - } - return d->regs[ichan].page; -} - -static uint32_t read_pageh (void *opaque, uint32_t nport) -{ - struct dma_cont *d = opaque; - int ichan; - - ichan = channels[nport & 7]; - if (-1 == ichan) { - dolog ("invalid channel read %#x\n", nport); - return 0; - } - return d->regs[ichan].pageh; -} - -static inline void init_chan (struct dma_cont *d, int ichan) -{ - struct dma_regs *r; - - r = d->regs + ichan; - r->now[ADDR] = r->base[ADDR] << d->dshift; - r->now[COUNT] = 0; -} - -static inline int getff (struct dma_cont *d) -{ - int ff; - - ff = d->flip_flop; - d->flip_flop = !ff; - return ff; -} - -static uint32_t read_chan (void *opaque, uint32_t nport) -{ - struct dma_cont *d = opaque; - int ichan, nreg, iport, ff, val, dir; - struct dma_regs *r; - - iport = (nport >> d->dshift) & 0x0f; - ichan = iport >> 1; - nreg = iport & 1; - r = d->regs + ichan; - - dir = ((r->mode >> 5) & 1) ? -1 : 1; - ff = getff (d); - if (nreg) - val = (r->base[COUNT] << d->dshift) - r->now[COUNT]; - else - val = r->now[ADDR] + r->now[COUNT] * dir; - - ldebug ("read_chan %#x -> %d\n", iport, val); - return (val >> (d->dshift + (ff << 3))) & 0xff; -} - -static void write_chan (void *opaque, uint32_t nport, uint32_t data) -{ - struct dma_cont *d = opaque; - int iport, ichan, nreg; - struct dma_regs *r; - - iport = (nport >> d->dshift) & 0x0f; - ichan = iport >> 1; - nreg = iport & 1; - r = d->regs + ichan; - if (getff (d)) { - r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00); - init_chan (d, ichan); - } else { - r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff); - } -} - -static void write_cont (void *opaque, uint32_t nport, uint32_t data) -{ - struct dma_cont *d = opaque; - int iport, ichan = 0; - - iport = (nport >> d->dshift) & 0x0f; - switch (iport) { - case 0x08: /* command */ - if ((data != 0) && (data & CMD_NOT_SUPPORTED)) { - dolog ("command %#x not supported\n", data); - return; - } - d->command = data; - break; - - case 0x09: - ichan = data & 3; - if (data & 4) { - d->status |= 1 << (ichan + 4); - } - else { - d->status &= ~(1 << (ichan + 4)); - } - d->status &= ~(1 << ichan); - break; - - case 0x0a: /* single mask */ - if (data & 4) - d->mask |= 1 << (data & 3); - else - d->mask &= ~(1 << (data & 3)); - break; - - case 0x0b: /* mode */ - { - ichan = data & 3; -#ifdef DEBUG_DMA - { - int op, ai, dir, opmode; - op = (data >> 2) & 3; - ai = (data >> 4) & 1; - dir = (data >> 5) & 1; - opmode = (data >> 6) & 3; - - linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n", - ichan, op, ai, dir, opmode); - } -#endif - d->regs[ichan].mode = data; - break; - } - - case 0x0c: /* clear flip flop */ - d->flip_flop = 0; - break; - - case 0x0d: /* reset */ - d->flip_flop = 0; - d->mask = ~0; - d->status = 0; - d->command = 0; - break; - - case 0x0e: /* clear mask for all channels */ - d->mask = 0; - break; - - case 0x0f: /* write mask for all channels */ - d->mask = data; - break; - - default: - dolog ("unknown iport %#x\n", iport); - break; - } - -#ifdef DEBUG_DMA - if (0xc != iport) { - linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n", - nport, ichan, data); - } -#endif -} - -static uint32_t read_cont (void *opaque, uint32_t nport) -{ - struct dma_cont *d = opaque; - int iport, val; - - iport = (nport >> d->dshift) & 0x0f; - switch (iport) { - case 0x08: /* status */ - val = d->status; - d->status &= 0xf0; - break; - case 0x0f: /* mask */ - val = d->mask; - break; - default: - val = 0; - break; - } - - ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val); - return val; -} - -int DMA_get_channel_mode (int nchan) -{ - return dma_controllers[nchan > 3].regs[nchan & 3].mode; -} - -void DMA_hold_DREQ (int nchan) -{ - int ncont, ichan; - - ncont = nchan > 3; - ichan = nchan & 3; - linfo ("held cont=%d chan=%d\n", ncont, ichan); - dma_controllers[ncont].status |= 1 << (ichan + 4); -} - -void DMA_release_DREQ (int nchan) -{ - int ncont, ichan; - - ncont = nchan > 3; - ichan = nchan & 3; - linfo ("released cont=%d chan=%d\n", ncont, ichan); - dma_controllers[ncont].status &= ~(1 << (ichan + 4)); -} - -static void channel_run (int ncont, int ichan) -{ - int n; - struct dma_regs *r = &dma_controllers[ncont].regs[ichan]; -#ifdef DEBUG_DMA - int dir, opmode; - - dir = (r->mode >> 5) & 1; - opmode = (r->mode >> 6) & 3; - - if (dir) { - dolog ("DMA in address decrement mode\n"); - } - if (opmode != 1) { - dolog ("DMA not in single mode select %#x\n", opmode); - } -#endif - - r = dma_controllers[ncont].regs + ichan; - n = r->transfer_handler (r->opaque, ichan + (ncont << 2), - r->now[COUNT], (r->base[COUNT] + 1) << ncont); - r->now[COUNT] = n; - ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont); -} - -void DMA_run (void) -{ - struct dma_cont *d; - int icont, ichan; - - d = dma_controllers; - - for (icont = 0; icont < 2; icont++, d++) { - for (ichan = 0; ichan < 4; ichan++) { - int mask; - - mask = 1 << ichan; - - if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) - channel_run (icont, ichan); - } - } -} - -void DMA_register_channel (int nchan, - DMA_transfer_handler transfer_handler, - void *opaque) -{ - struct dma_regs *r; - int ichan, ncont; - - ncont = nchan > 3; - ichan = nchan & 3; - - r = dma_controllers[ncont].regs + ichan; - r->transfer_handler = transfer_handler; - r->opaque = opaque; -} - -int DMA_read_memory (int nchan, void *buf, int pos, int len) -{ - struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3]; - target_phys_addr_t addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; - - if (r->mode & 0x20) { - int i; - uint8_t *p = buf; - - cpu_physical_memory_read (addr - pos - len, buf, len); - /* What about 16bit transfers? */ - for (i = 0; i < len >> 1; i++) { - uint8_t b = p[len - i - 1]; - p[i] = b; - } - } - else - cpu_physical_memory_read (addr + pos, buf, len); - - return len; -} - -int DMA_write_memory (int nchan, void *buf, int pos, int len) -{ - struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3]; - target_phys_addr_t addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; - - if (r->mode & 0x20) { - int i; - uint8_t *p = buf; - - cpu_physical_memory_write (addr - pos - len, buf, len); - /* What about 16bit transfers? */ - for (i = 0; i < len; i++) { - uint8_t b = p[len - i - 1]; - p[i] = b; - } - } - else - cpu_physical_memory_write (addr + pos, buf, len); - - return len; -} - -/* request the emulator to transfer a new DMA memory block ASAP */ -void DMA_schedule(int nchan) -{ - CPUState *env = cpu_single_env; - if (env) - cpu_interrupt(env, CPU_INTERRUPT_EXIT); -} - -static void dma_reset(void *opaque) -{ - struct dma_cont *d = opaque; - write_cont (d, (0x0d << d->dshift), 0); -} - -static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len) -{ - dolog ("unregistered DMA channel used nchan=%d dma_pos=%d dma_len=%d\n", - nchan, dma_pos, dma_len); - return dma_pos; -} - -/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */ -static void dma_init2(struct dma_cont *d, int base, int dshift, - int page_base, int pageh_base) -{ - static const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 }; - int i; - - d->dshift = dshift; - for (i = 0; i < 8; i++) { - register_ioport_write (base + (i << dshift), 1, 1, write_chan, d); - register_ioport_read (base + (i << dshift), 1, 1, read_chan, d); - } - for (i = 0; i < LENOFA (page_port_list); i++) { - register_ioport_write (page_base + page_port_list[i], 1, 1, - write_page, d); - register_ioport_read (page_base + page_port_list[i], 1, 1, - read_page, d); - if (pageh_base >= 0) { - register_ioport_write (pageh_base + page_port_list[i], 1, 1, - write_pageh, d); - register_ioport_read (pageh_base + page_port_list[i], 1, 1, - read_pageh, d); - } - } - for (i = 0; i < 8; i++) { - register_ioport_write (base + ((i + 8) << dshift), 1, 1, - write_cont, d); - register_ioport_read (base + ((i + 8) << dshift), 1, 1, - read_cont, d); - } - qemu_register_reset(dma_reset, d); - dma_reset(d); - for (i = 0; i < LENOFA (d->regs); ++i) { - d->regs[i].transfer_handler = dma_phony_handler; - } -} - -static void dma_save (QEMUFile *f, void *opaque) -{ - struct dma_cont *d = opaque; - int i; - - /* qemu_put_8s (f, &d->status); */ - qemu_put_8s (f, &d->command); - qemu_put_8s (f, &d->mask); - qemu_put_8s (f, &d->flip_flop); - qemu_put_be32 (f, d->dshift); - - for (i = 0; i < 4; ++i) { - struct dma_regs *r = &d->regs[i]; - qemu_put_be32 (f, r->now[0]); - qemu_put_be32 (f, r->now[1]); - qemu_put_be16s (f, &r->base[0]); - qemu_put_be16s (f, &r->base[1]); - qemu_put_8s (f, &r->mode); - qemu_put_8s (f, &r->page); - qemu_put_8s (f, &r->pageh); - qemu_put_8s (f, &r->dack); - qemu_put_8s (f, &r->eop); - } -} - -static int dma_load (QEMUFile *f, void *opaque, int version_id) -{ - struct dma_cont *d = opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - /* qemu_get_8s (f, &d->status); */ - qemu_get_8s (f, &d->command); - qemu_get_8s (f, &d->mask); - qemu_get_8s (f, &d->flip_flop); - d->dshift=qemu_get_be32 (f); - - for (i = 0; i < 4; ++i) { - struct dma_regs *r = &d->regs[i]; - r->now[0]=qemu_get_be32 (f); - r->now[1]=qemu_get_be32 (f); - qemu_get_be16s (f, &r->base[0]); - qemu_get_be16s (f, &r->base[1]); - qemu_get_8s (f, &r->mode); - qemu_get_8s (f, &r->page); - qemu_get_8s (f, &r->pageh); - qemu_get_8s (f, &r->dack); - qemu_get_8s (f, &r->eop); - } - return 0; -} - -void DMA_init (int high_page_enable) -{ - dma_init2(&dma_controllers[0], 0x00, 0, 0x80, - high_page_enable ? 0x480 : -1); - dma_init2(&dma_controllers[1], 0xc0, 1, 0x88, - high_page_enable ? 0x488 : -1); - register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]); - register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]); -} diff --git a/hw/goldfish_audio.c b/hw/goldfish_audio.c deleted file mode 100644 index d0a44b5..0000000 --- a/hw/goldfish_audio.c +++ /dev/null @@ -1,533 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "goldfish_device.h" -#include "audio/audio.h" -#include "qemu_debug.h" -#include "android/globals.h" - -#define DEBUG 1 - -#if DEBUG -# define D(...) VERBOSE_PRINT(audio,__VA_ARGS__) -#else -# define D(...) ((void)0) -#endif - -extern void dprint(const char* fmt, ...); - -/* define USE_QEMU_AUDIO_IN to 1 to use QEMU's audio subsystem to - * implement the audio input. if 0, this will try to read a .wav file - * directly... - */ -#define USE_QEMU_AUDIO_IN 1 - -enum { - /* audio status register */ - AUDIO_INT_STATUS = 0x00, - /* set this to enable IRQ */ - AUDIO_INT_ENABLE = 0x04, - /* set these to specify buffer addresses */ - AUDIO_SET_WRITE_BUFFER_1 = 0x08, - AUDIO_SET_WRITE_BUFFER_2 = 0x0C, - /* set number of bytes in buffer to write */ - AUDIO_WRITE_BUFFER_1 = 0x10, - AUDIO_WRITE_BUFFER_2 = 0x14, - - /* true if audio input is supported */ - AUDIO_READ_SUPPORTED = 0x18, - /* buffer to use for audio input */ - AUDIO_SET_READ_BUFFER = 0x1C, - - /* driver writes number of bytes to read */ - AUDIO_START_READ = 0x20, - - /* number of bytes available in read buffer */ - AUDIO_READ_BUFFER_AVAILABLE = 0x24, - - /* AUDIO_INT_STATUS bits */ - - /* this bit set when it is safe to write more bytes to the buffer */ - AUDIO_INT_WRITE_BUFFER_1_EMPTY = 1U << 0, - AUDIO_INT_WRITE_BUFFER_2_EMPTY = 1U << 1, - AUDIO_INT_READ_BUFFER_FULL = 1U << 2, -}; - - -struct goldfish_audio_state { - struct goldfish_device dev; - // pointers to our two write buffers - uint32_t buffer_1, buffer_2; - uint32_t read_buffer; - // buffer flags - uint32_t int_status; - // irq enable mask for int_status - uint32_t int_enable; - -#if USE_QEMU_AUDIO_IN - uint32_t read_pos; - uint32_t read_size; -#else - // path to file or device to use for input - const char* input_source; - // true if input is a wav file - int input_is_wav; - // true if we need to convert stereo -> mono - int input_is_stereo; - // file descriptor to use for input - int input_fd; -#endif - - // number of bytes available in the read buffer - int read_buffer_available; - - // set to 1 or 2 to indicate which buffer we are writing from, or zero if both buffers are empty - int current_buffer; - - // current data to write - uint8* data_1; - uint32_t data_1_length; - uint8* data_2; - uint32_t data_2_length; - - - // for QEMU sound output - QEMUSoundCard card; - SWVoiceOut *voice; -#if USE_QEMU_AUDIO_IN - SWVoiceIn* voicein; -#endif -}; - -/* update this whenever you change the goldfish_audio_state structure */ -#define AUDIO_STATE_SAVE_VERSION 1 - -#define QFIELD_STRUCT struct goldfish_audio_state -QFIELD_BEGIN(audio_state_fields) - QFIELD_INT32(buffer_1), - QFIELD_INT32(buffer_2), - QFIELD_INT32(read_buffer), - QFIELD_INT32(int_status), - QFIELD_INT32(int_enable), -#if USE_QEMU_AUDIO_IN - QFIELD_INT32(read_pos), - QFIELD_INT32(read_size), -#endif - QFIELD_INT32(read_buffer_available), - QFIELD_INT32(current_buffer), - QFIELD_INT32(data_1_length), - QFIELD_INT32(data_2_length), -QFIELD_END - -static void audio_state_save( QEMUFile* f, void* opaque ) -{ - struct goldfish_audio_state* s = opaque; - - qemu_put_struct(f, audio_state_fields, s); - - /* we can't write data_1 and data_2 directly */ - qemu_put_be32( f, s->data_1 - phys_ram_base ); - qemu_put_be32( f, s->data_2 - phys_ram_base ); -} - -static int audio_state_load( QEMUFile* f, void* opaque, int version_id ) -{ - struct goldfish_audio_state* s = opaque; - int ret; - - if (version_id != AUDIO_STATE_SAVE_VERSION) - return -1; - - ret = qemu_get_struct(f, audio_state_fields, s); - if (!ret) { - s->data_1 = qemu_get_be32(f) + phys_ram_base; - s->data_2 = qemu_get_be32(f) + phys_ram_base; - } - return -1; -} - -static void enable_audio(struct goldfish_audio_state *s, int enable) -{ - // enable or disable the output voice - if (s->voice != NULL) - AUD_set_active_out(s->voice, (enable & (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY)) != 0); - - if (s->voicein) - AUD_set_active_in (s->voicein, (enable & AUDIO_INT_READ_BUFFER_FULL) != 0); - // reset buffer information - s->data_1_length = 0; - s->data_2_length = 0; - s->current_buffer = 0; - s->read_pos = 0; -} - -#if USE_QEMU_AUDIO_IN -static void start_read(struct goldfish_audio_state *s, uint32_t count) -{ - //printf( "... goldfish audio start_read, count=%d\n", count ); - s->read_size = count; - s->read_buffer_available = 0; - s->read_pos = 0; -} -#else -static void start_read(struct goldfish_audio_state *s, uint32_t count) -{ - uint8 wav_header[44]; - int result; - - if (!s->input_source) return; - - if (s->input_fd < 0) { - s->input_fd = open(s->input_source, O_BINARY | O_RDONLY); - - if (s->input_fd < 0) { - fprintf(stderr, "goldfish_audio could not open %s for audio input\n", s->input_source); - s->input_source = NULL; // set to to avoid endless retries - return; - } - - // skip WAV header if we have a WAV file - if (s->input_is_wav) { - if (read(s->input_fd, wav_header, sizeof(wav_header)) != sizeof(wav_header)) { - fprintf(stderr, "goldfish_audio could not read WAV file header %s\n", s->input_source); - s->input_fd = -1; - s->input_source = NULL; // set to to avoid endless retries - return; - } - - // is the WAV file stereo? - s->input_is_stereo = (wav_header[22] == 2); - } else { - // assume input from an audio device is stereo - s->input_is_stereo = 1; - } - } - - uint8* buffer = (uint8*)phys_ram_base + s->read_buffer; - if (s->input_is_stereo) { - // need to read twice as much data - count *= 2; - } - -try_again: - result = read(s->input_fd, buffer, count); - if (result == 0 && s->input_is_wav) { - // end of file, so seek back to the beginning - lseek(s->input_fd, sizeof(wav_header), SEEK_SET); - goto try_again; - } - - if (result > 0 && s->input_is_stereo) { - // we need to convert stereo to mono - uint8* src = (uint8*)buffer; - uint8* dest = src; - int count = result/2; - while (count-- > 0) { - int sample1 = src[0] | (src[1] << 8); - int sample2 = src[2] | (src[3] << 8); - int sample = (sample1 + sample2) >> 1; - dst[0] = (uint8_t) sample; - dst[1] = (uint8_t)(sample >> 8); - src += 4; - dst += 2; - } - - // we reduced the number of bytes by 2 - result /= 2; - } - - s->read_buffer_available = (result > 0 ? result : 0); - s->int_status |= AUDIO_INT_READ_BUFFER_FULL; - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); -} -#endif - -static uint32_t goldfish_audio_read(void *opaque, target_phys_addr_t offset) -{ - uint32_t ret; - struct goldfish_audio_state *s = opaque; - offset -= s->dev.base; - switch(offset) { - case AUDIO_INT_STATUS: - // return current buffer status flags - ret = s->int_status & s->int_enable; - if(ret) { - goldfish_device_set_irq(&s->dev, 0, 0); - } - return ret; - - case AUDIO_READ_SUPPORTED: -#if USE_QEMU_AUDIO_IN - D("%s: AUDIO_READ_SUPPORTED returns %d", __FUNCTION__, - (s->voicein != NULL)); - return (s->voicein != NULL); -#else - return (s->input_source ? 1 : 0); -#endif - - case AUDIO_READ_BUFFER_AVAILABLE: - D("%s: AUDIO_READ_BUFFER_AVAILABLE returns %d", __FUNCTION__, - s->read_buffer_available); - return s->read_buffer_available; - - default: - cpu_abort (cpu_single_env, "goldfish_audio_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_audio_write(void *opaque, target_phys_addr_t offset, uint32_t val) -{ - struct goldfish_audio_state *s = opaque; - offset -= s->dev.base; - - switch(offset) { - case AUDIO_INT_ENABLE: - /* enable buffer empty interrupts */ - D("%s: AUDIO_INT_ENABLE %d", __FUNCTION__, val ); - enable_audio(s, val); - s->int_enable = val; - s->int_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY); - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - break; - case AUDIO_SET_WRITE_BUFFER_1: - /* save pointer to buffer 1 */ - s->buffer_1 = val; - break; - case AUDIO_SET_WRITE_BUFFER_2: - /* save pointer to buffer 2 */ - s->buffer_2 = val; - break; - case AUDIO_WRITE_BUFFER_1: - /* record that data in buffer 1 is ready to write */ - if (s->current_buffer == 0) s->current_buffer = 1; - s->data_1 = phys_ram_base + s->buffer_1; - s->data_1_length = val; - s->int_status &= ~AUDIO_INT_WRITE_BUFFER_1_EMPTY; - break; - case AUDIO_WRITE_BUFFER_2: - /* record that data in buffer 2 is ready to write */ - if (s->current_buffer == 0) s->current_buffer = 2; - s->data_2 = phys_ram_base + s->buffer_2; - s->data_2_length = val; - s->int_status &= ~AUDIO_INT_WRITE_BUFFER_2_EMPTY; - break; - - case AUDIO_SET_READ_BUFFER: - /* save pointer to the read buffer */ - s->read_buffer = val; - D( "%s: AUDIO_SET_READ_BUFFER %p", __FUNCTION__, (void*)val ); - break; - - case AUDIO_START_READ: - D( "%s: AUDIO_START_READ %d", __FUNCTION__, val ); - start_read(s, val); - s->int_status &= ~AUDIO_INT_READ_BUFFER_FULL; - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - break; - - default: - cpu_abort (cpu_single_env, "goldfish_audio_write: Bad offset %x\n", offset); - } -} - -static void goldfish_audio_callback(void *opaque, int free) -{ - struct goldfish_audio_state *s = opaque; - int new_status = 0; - - /* loop until free is zero or both buffers are empty */ - while (free && s->current_buffer) { - - /* write data in buffer 1 */ - while (free && s->current_buffer == 1) { - int write = s->data_1_length; - if (write > free) write = free; - - int written = AUD_write(s->voice, s->data_1, write); - if (written) { - D("%s: sent %d bytes to audio output", __FUNCTION__, write); - s->data_1 += written; - s->data_1_length -= written; - free -= written; - - if (s->data_1_length == 0) { - new_status |= AUDIO_INT_WRITE_BUFFER_1_EMPTY; - s->current_buffer = (s->data_2_length ? 2 : 0); - } - } else { - break; - } - } - - /* write data in buffer 2 */ - while (free && s->current_buffer == 2) { - int write = s->data_2_length; - if (write > free) write = free; - - int written = AUD_write(s->voice, s->data_2, write); - if (written) { - D("%s: sent %d bytes to audio output", __FUNCTION__, write); - s->data_2 += written; - s->data_2_length -= written; - free -= written; - - if (s->data_2_length == 0) { - new_status |= AUDIO_INT_WRITE_BUFFER_2_EMPTY; - s->current_buffer = (s->data_1_length ? 1 : 0); - } - } else { - break; - } - } - } - - if (new_status && new_status != s->int_status) { - s->int_status |= new_status; - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - } -} - -#if USE_QEMU_AUDIO_IN -static void -goldfish_audio_in_callback(void *opaque, int avail) -{ - struct goldfish_audio_state *s = opaque; - int new_status = 0; - - if (s->read_pos >= s->read_size) - return; - - if (0 && s->read_size > 0) - D("%s: in %d (pos=%d size=%d)", __FUNCTION__, - avail, s->read_pos, s->read_size ); - - while (avail > 0) { - int pos = s->read_pos; - int missing = s->read_size - pos; - uint8* buffer = (uint8*)phys_ram_base + s->read_buffer + pos; - int read; - int avail2 = (avail > missing) ? missing : avail; - - read = AUD_read(s->voicein, buffer, avail2); - if (read == 0) - break; - - if (avail2 > 0) - D("%s: AUD_read(%d) returned %d", __FUNCTION__, avail2, read); - - s->read_buffer_available += read; - - avail -= read; - pos += read; - if (pos == s->read_size) { - new_status |= AUDIO_INT_READ_BUFFER_FULL; - D("%s: AUDIO_INT_READ_BUFFER_FULL available=%d", __FUNCTION__, s->read_buffer_available); - } - s->read_pos = pos; - } - - if (new_status && new_status != s->int_status) { - s->int_status |= new_status; - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - } -} -#endif /* USE_QEMU_AUDIO_IN */ - -static CPUReadMemoryFunc *goldfish_audio_readfn[] = { - goldfish_audio_read, - goldfish_audio_read, - goldfish_audio_read -}; - -static CPUWriteMemoryFunc *goldfish_audio_writefn[] = { - goldfish_audio_write, - goldfish_audio_write, - goldfish_audio_write -}; - -void goldfish_audio_init(uint32_t base, int id, const char* input_source) -{ - struct goldfish_audio_state *s; - audsettings_t as; - - /* nothing to do if no audio input and output */ - if (!android_hw->hw_audioOutput && !android_hw->hw_audioInput) - return; - - s = (struct goldfish_audio_state *)qemu_mallocz(sizeof(*s)); - s->dev.name = "goldfish_audio"; - s->dev.id = id; - s->dev.base = base; - s->dev.size = 0x1000; - s->dev.irq_count = 1; - -#ifndef USE_QEMU_AUDIO_IN - s->input_fd = -1; - if (input_source) { - s->input_source = input_source; - char* extension = strrchr(input_source, '.'); - if (extension && strcasecmp(extension, ".wav") == 0) { - s->input_is_wav = 1; - } - } -#endif - - AUD_register_card( &glob_audio_state, "goldfish_audio", &s->card); - - as.freq = 44100; - as.nchannels = 2; - as.fmt = AUD_FMT_S16; - as.endianness = AUDIO_HOST_ENDIANNESS; - - if (android_hw->hw_audioOutput) { - s->voice = AUD_open_out ( - &s->card, - s->voice, - "goldfish_audio", - s, - goldfish_audio_callback, - &as - ); - if (!s->voice) { - dprint("warning: opening audio output failed\n"); - return; - } - } - -#if USE_QEMU_AUDIO_IN - as.freq = 8000; - as.nchannels = 1; - as.fmt = AUD_FMT_S16; - as.endianness = AUDIO_HOST_ENDIANNESS; - - if (android_hw->hw_audioInput) { - s->voicein = AUD_open_in ( - &s->card, - NULL, - "goldfish_audio_in", - s, - goldfish_audio_in_callback, - &as - ); - if (!s->voicein) { - dprint("warning: opening audio input failed\n"); - } - } -#endif - - goldfish_device_add(&s->dev, goldfish_audio_readfn, goldfish_audio_writefn, s); - - register_savevm( "audio_state", 0, AUDIO_STATE_SAVE_VERSION, - audio_state_save, audio_state_load, s ); -} - diff --git a/hw/goldfish_battery.c b/hw/goldfish_battery.c deleted file mode 100644 index d9ef785..0000000 --- a/hw/goldfish_battery.c +++ /dev/null @@ -1,261 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "goldfish_device.h" -#include "power_supply.h" - - -enum { - /* status register */ - BATTERY_INT_STATUS = 0x00, - /* set this to enable IRQ */ - BATTERY_INT_ENABLE = 0x04, - - BATTERY_AC_ONLINE = 0x08, - BATTERY_STATUS = 0x0C, - BATTERY_HEALTH = 0x10, - BATTERY_PRESENT = 0x14, - BATTERY_CAPACITY = 0x18, - - BATTERY_STATUS_CHANGED = 1U << 0, - AC_STATUS_CHANGED = 1U << 1, - BATTERY_INT_MASK = BATTERY_STATUS_CHANGED | AC_STATUS_CHANGED, -}; - - -struct goldfish_battery_state { - struct goldfish_device dev; - // IRQs - uint32_t int_status; - // irq enable mask for int_status - uint32_t int_enable; - - int ac_online; - int status; - int health; - int present; - int capacity; -}; - -/* update this each time you update the battery_state struct */ -#define BATTERY_STATE_SAVE_VERSION 1 - -#define QFIELD_STRUCT struct goldfish_battery_state -QFIELD_BEGIN(goldfish_battery_fields) - QFIELD_INT32(int_status), - QFIELD_INT32(int_enable), - QFIELD_INT32(ac_online), - QFIELD_INT32(status), - QFIELD_INT32(health), - QFIELD_INT32(present), - QFIELD_INT32(capacity), -QFIELD_END - -static void goldfish_battery_save(QEMUFile* f, void* opaque) -{ - struct goldfish_battery_state* s = opaque; - - qemu_put_struct(f, goldfish_battery_fields, s); -} - -static int goldfish_battery_load(QEMUFile* f, void* opaque, int version_id) -{ - struct goldfish_battery_state* s = opaque; - - if (version_id != BATTERY_STATE_SAVE_VERSION) - return -1; - - return qemu_get_struct(f, goldfish_battery_fields, s); -} - -static struct goldfish_battery_state *battery_state; - -static uint32_t goldfish_battery_read(void *opaque, target_phys_addr_t offset) -{ - uint32_t ret; - struct goldfish_battery_state *s = opaque; - offset -= s->dev.base; - switch(offset) { - case BATTERY_INT_STATUS: - // return current buffer status flags - ret = s->int_status & s->int_enable; - if (ret) { - goldfish_device_set_irq(&s->dev, 0, 0); - s->int_status = 0; - } - return ret; - - case BATTERY_INT_ENABLE: - return s->int_enable; - case BATTERY_AC_ONLINE: - return s->ac_online; - case BATTERY_STATUS: - return s->status; - case BATTERY_HEALTH: - return s->health; - case BATTERY_PRESENT: - return s->present; - case BATTERY_CAPACITY: - return s->capacity; - - default: - cpu_abort (cpu_single_env, "goldfish_battery_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_battery_write(void *opaque, target_phys_addr_t offset, uint32_t val) -{ - struct goldfish_battery_state *s = opaque; - offset -= s->dev.base; - - switch(offset) { - case BATTERY_INT_ENABLE: - /* enable interrupts */ - s->int_enable = val; -// s->int_status = (AUDIO_INT_WRITE_BUFFER_1_EMPTY | AUDIO_INT_WRITE_BUFFER_2_EMPTY); -// goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - break; - - default: - cpu_abort (cpu_single_env, "goldfish_audio_write: Bad offset %x\n", offset); - } -} - -static CPUReadMemoryFunc *goldfish_battery_readfn[] = { - goldfish_battery_read, - goldfish_battery_read, - goldfish_battery_read -}; - - -static CPUWriteMemoryFunc *goldfish_battery_writefn[] = { - goldfish_battery_write, - goldfish_battery_write, - goldfish_battery_write -}; - -void goldfish_battery_init() -{ - struct goldfish_battery_state *s; - - s = (struct goldfish_battery_state *)qemu_mallocz(sizeof(*s)); - s->dev.name = "goldfish-battery"; - s->dev.base = 0; // will be allocated dynamically - s->dev.size = 0x1000; - s->dev.irq_count = 1; - - // default values for the battery - s->ac_online = 1; - s->status = POWER_SUPPLY_STATUS_CHARGING; - s->health = POWER_SUPPLY_HEALTH_GOOD; - s->present = 1; // battery is present - s->capacity = 50; // 50% charged - - battery_state = s; - - goldfish_device_add(&s->dev, goldfish_battery_readfn, goldfish_battery_writefn, s); - - register_savevm( "battery_state", 0, BATTERY_STATE_SAVE_VERSION, - goldfish_battery_save, goldfish_battery_load, s); -} - -void goldfish_battery_set_prop(int ac, int property, int value) -{ - int new_status = (ac ? AC_STATUS_CHANGED : BATTERY_STATUS_CHANGED); - - if (ac) { - switch (property) { - case POWER_SUPPLY_PROP_ONLINE: - battery_state->ac_online = value; - break; - } - } else { - switch (property) { - case POWER_SUPPLY_PROP_STATUS: - battery_state->status = value; - break; - case POWER_SUPPLY_PROP_HEALTH: - battery_state->health = value; - break; - case POWER_SUPPLY_PROP_PRESENT: - battery_state->present = value; - break; - case POWER_SUPPLY_PROP_CAPACITY: - battery_state->capacity = value; - break; - } - } - - if (new_status != battery_state->int_status) { - battery_state->int_status |= new_status; - goldfish_device_set_irq(&battery_state->dev, 0, (battery_state->int_status & battery_state->int_enable)); - } -} - -void goldfish_battery_display(void (* callback)(void *data, const char* string), void *data) -{ - char buffer[100]; - char* value; - - sprintf(buffer, "AC: %s\r\n", (battery_state->ac_online ? "online" : "offline")); - callback(data, buffer); - - switch (battery_state->status) { - case POWER_SUPPLY_STATUS_CHARGING: - value = "Charging"; - break; - case POWER_SUPPLY_STATUS_DISCHARGING: - value = "Discharging"; - break; - case POWER_SUPPLY_STATUS_NOT_CHARGING: - value = "Not charging"; - break; - case POWER_SUPPLY_STATUS_FULL: - value = "Full"; - break; - default: - value = "Unknown"; - break; - } - sprintf(buffer, "status: %s\r\n", value); - callback(data, buffer); - - switch (battery_state->health) { - case POWER_SUPPLY_HEALTH_GOOD: - value = "Good"; - break; - case POWER_SUPPLY_HEALTH_OVERHEAT: - value = "Overhead"; - break; - case POWER_SUPPLY_HEALTH_DEAD: - value = "Dead"; - break; - case POWER_SUPPLY_HEALTH_OVERVOLTAGE: - value = "Overvoltage"; - break; - case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE: - value = "Unspecified failure"; - break; - default: - value = "Unknown"; - break; - } - sprintf(buffer, "health: %s\r\n", value); - callback(data, buffer); - - sprintf(buffer, "present: %s\r\n", (battery_state->present ? "true" : "false")); - callback(data, buffer); - - sprintf(buffer, "capacity: %d\r\n", battery_state->capacity); - callback(data, buffer); -} diff --git a/hw/goldfish_device.c b/hw/goldfish_device.c deleted file mode 100644 index 2c9dd6e..0000000 --- a/hw/goldfish_device.c +++ /dev/null @@ -1,200 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "arm_pic.h" -#include "goldfish_device.h" - -#define PDEV_BUS_OP_DONE (0x00) -#define PDEV_BUS_OP_REMOVE_DEV (0x04) -#define PDEV_BUS_OP_ADD_DEV (0x08) - -#define PDEV_BUS_OP_INIT (0x00) - -#define PDEV_BUS_OP (0x00) -#define PDEV_BUS_GET_NAME (0x04) -#define PDEV_BUS_NAME_LEN (0x08) -#define PDEV_BUS_ID (0x0c) -#define PDEV_BUS_IO_BASE (0x10) -#define PDEV_BUS_IO_SIZE (0x14) -#define PDEV_BUS_IRQ (0x18) -#define PDEV_BUS_IRQ_COUNT (0x1c) - -struct bus_state { - struct goldfish_device dev; - struct goldfish_device *current; -}; - -qemu_irq *goldfish_pic; -static struct goldfish_device *first_device; -static struct goldfish_device *last_device; -uint32_t goldfish_free_base; -uint32_t goldfish_free_irq; - -void goldfish_device_set_irq(struct goldfish_device *dev, int irq, int level) -{ - if(irq >= dev->irq_count) - cpu_abort (cpu_single_env, "goldfish_device_set_irq: Bad irq %d >= %d\n", irq, dev->irq_count); - else - qemu_set_irq(goldfish_pic[dev->irq + irq], level); -} - -int goldfish_add_device_no_io(struct goldfish_device *dev) -{ - if(dev->base == 0) { - dev->base = goldfish_free_base; - goldfish_free_base += dev->size; - } - if(dev->irq == 0 && dev->irq_count > 0) { - dev->irq = goldfish_free_irq; - goldfish_free_irq += dev->irq_count; - } - //printf("goldfish_add_device: %s, base %x %x, irq %d %d\n", - // dev->name, dev->base, dev->size, dev->irq, dev->irq_count); - dev->next = NULL; - if(last_device) { - last_device->next = dev; - } - else { - first_device = dev; - } - last_device = dev; - return 0; -} - -int goldfish_device_add(struct goldfish_device *dev, - CPUReadMemoryFunc **mem_read, - CPUWriteMemoryFunc **mem_write, - void *opaque) -{ - int iomemtype; - goldfish_add_device_no_io(dev); - iomemtype = cpu_register_io_memory(0, mem_read, - mem_write, opaque); - cpu_register_physical_memory(dev->base, dev->size, iomemtype); - return 0; -} - -static uint32_t goldfish_bus_read(void *opaque, target_phys_addr_t offset) -{ - struct bus_state *s = (struct bus_state *)opaque; - offset -= s->dev.base; - - switch (offset) { - case PDEV_BUS_OP: - if(s->current) { - s->current->reported_state = 1; - s->current = s->current->next; - } - else { - s->current = first_device; - } - while(s->current && s->current->reported_state == 1) - s->current = s->current->next; - if(s->current) - return PDEV_BUS_OP_ADD_DEV; - else { - goldfish_device_set_irq(&s->dev, 0, 0); - return PDEV_BUS_OP_DONE; - } - - case PDEV_BUS_NAME_LEN: - return s->current ? strlen(s->current->name) : 0; - case PDEV_BUS_ID: - return s->current ? s->current->id : 0; - case PDEV_BUS_IO_BASE: - return s->current ? s->current->base : 0; - case PDEV_BUS_IO_SIZE: - return s->current ? s->current->size : 0; - case PDEV_BUS_IRQ: - return s->current ? s->current->irq : 0; - case PDEV_BUS_IRQ_COUNT: - return s->current ? s->current->irq_count : 0; - default: - cpu_abort (cpu_single_env, "goldfish_bus_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_bus_op_init(struct bus_state *s) -{ - struct goldfish_device *dev = first_device; - while(dev) { - dev->reported_state = 0; - dev = dev->next; - } - s->current = NULL; - goldfish_device_set_irq(&s->dev, 0, first_device != NULL); -} - -static void goldfish_bus_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - struct bus_state *s = (struct bus_state *)opaque; - offset -= s->dev.base; - - switch(offset) { - case PDEV_BUS_OP: - switch(value) { - case PDEV_BUS_OP_INIT: - goldfish_bus_op_init(s); - break; - default: - cpu_abort (cpu_single_env, "goldfish_bus_write: Bad PDEV_BUS_OP value %x\n", value); - }; - break; - case PDEV_BUS_GET_NAME: - if(s->current) - pmemcpy(value, s->current->name, strlen(s->current->name)); - break; - default: - cpu_abort (cpu_single_env, "goldfish_bus_write: Bad offset %x\n", offset); - } -} - -static CPUReadMemoryFunc *goldfish_bus_readfn[] = { - goldfish_bus_read, - goldfish_bus_read, - goldfish_bus_read -}; - -static CPUWriteMemoryFunc *goldfish_bus_writefn[] = { - goldfish_bus_write, - goldfish_bus_write, - goldfish_bus_write -}; - - -static struct bus_state bus_state = { - .dev = { - .name = "goldfish_device_bus", - .id = -1, - .base = 0x10001000, - .size = 0x1000, - .irq = 1, - .irq_count = 1, - } -}; - -void goldfish_device_init(qemu_irq *pic, uint32_t base, uint32_t size, uint32_t irq, uint32_t irq_count) -{ - goldfish_pic = pic; - goldfish_free_base = base; - goldfish_free_irq = irq; -} - -int goldfish_device_bus_init(uint32_t base, uint32_t irq) -{ - bus_state.dev.base = base; - bus_state.dev.irq = irq; - - return goldfish_device_add(&bus_state.dev, goldfish_bus_readfn, goldfish_bus_writefn, &bus_state); -} - diff --git a/hw/goldfish_device.h b/hw/goldfish_device.h deleted file mode 100644 index abe102e..0000000 --- a/hw/goldfish_device.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#ifndef GOLDFISH_DEVICE_H -#define GOLDFISH_DEVICE_H - -struct goldfish_device { - struct goldfish_device *next; - struct goldfish_device *prev; - uint32_t reported_state; - void *cookie; - const char *name; - uint32_t id; - uint32_t base; // filled in by goldfish_device_add if 0 - uint32_t size; - uint32_t irq; // filled in by goldfish_device_add if 0 - uint32_t irq_count; -}; - - -void goldfish_device_set_irq(struct goldfish_device *dev, int irq, int level); -int goldfish_device_add(struct goldfish_device *dev, - CPUReadMemoryFunc **mem_read, - CPUWriteMemoryFunc **mem_write, - void *opaque); - -int goldfish_add_device_no_io(struct goldfish_device *dev); - -void goldfish_device_init(qemu_irq *pic, uint32_t base, uint32_t size, uint32_t irq, uint32_t irq_count); -int goldfish_device_bus_init(uint32_t base, uint32_t irq); - -// device init functions: -qemu_irq *goldfish_interrupt_init(uint32_t base, qemu_irq parent_irq, qemu_irq parent_fiq); -void goldfish_timer_and_rtc_init(uint32_t timerbase, int timerirq); -int goldfish_tty_add(CharDriverState *cs, int id, uint32_t base, int irq); -void goldfish_fb_init(DisplayState *ds, int id); -void goldfish_audio_init(uint32_t base, int id, const char* input_source); -void goldfish_battery_init(); -void goldfish_battery_set_prop(int ac, int property, int value); -void goldfish_battery_display(void (* callback)(void *data, const char* string), void *data); -void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs); -void *goldfish_switch_add(char *name, uint32_t (*writefn)(void *opaque, uint32_t state), void *writeopaque, int id); -void goldfish_switch_set_state(void *opaque, uint32_t state); - -// these do not add a device -void trace_dev_init(uint32_t base); -void events_dev_init(uint32_t base, qemu_irq irq); -void nand_dev_init(uint32_t base); - -#endif diff --git a/hw/goldfish_events_device.c b/hw/goldfish_events_device.c deleted file mode 100644 index 4cb2904..0000000 --- a/hw/goldfish_events_device.c +++ /dev/null @@ -1,423 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "android/hw-events.h" -#include "irq.h" - -#if 0 -// From kernel... -#define EV_SYN 0x00 -#define EV_KEY 0x01 -#define EV_REL 0x02 -#define EV_ABS 0x03 -#define EV_MSC 0x04 -#define EV_SW 0x05 -#define EV_LED 0x11 -#define EV_SND 0x12 -#define EV_REP 0x14 -#define EV_FF 0x15 -#define EV_PWR 0x16 -#define EV_FF_STATUS 0x17 -#define EV_MAX 0x1f - -#define BTN_MISC 0x100 -#define BTN_0 0x100 -#define BTN_1 0x101 -#define BTN_2 0x102 -#define BTN_3 0x103 -#define BTN_4 0x104 -#define BTN_5 0x105 -#define BTN_6 0x106 -#define BTN_7 0x107 -#define BTN_8 0x108 -#define BTN_9 0x109 - -#define BTN_MOUSE 0x110 -#define BTN_LEFT 0x110 -#define BTN_RIGHT 0x111 -#define BTN_MIDDLE 0x112 -#define BTN_SIDE 0x113 -#define BTN_EXTRA 0x114 -#define BTN_FORWARD 0x115 -#define BTN_BACK 0x116 -#define BTN_TASK 0x117 - -#define BTN_JOYSTICK 0x120 -#define BTN_TRIGGER 0x120 -#define BTN_THUMB 0x121 -#define BTN_THUMB2 0x122 -#define BTN_TOP 0x123 -#define BTN_TOP2 0x124 -#define BTN_PINKIE 0x125 -#define BTN_BASE 0x126 -#define BTN_BASE2 0x127 -#define BTN_BASE3 0x128 -#define BTN_BASE4 0x129 -#define BTN_BASE5 0x12a -#define BTN_BASE6 0x12b -#define BTN_DEAD 0x12f - -#define BTN_GAMEPAD 0x130 -#define BTN_A 0x130 -#define BTN_B 0x131 -#define BTN_C 0x132 -#define BTN_X 0x133 -#define BTN_Y 0x134 -#define BTN_Z 0x135 -#define BTN_TL 0x136 -#define BTN_TR 0x137 -#define BTN_TL2 0x138 -#define BTN_TR2 0x139 -#define BTN_SELECT 0x13a -#define BTN_START 0x13b -#define BTN_MODE 0x13c -#define BTN_THUMBL 0x13d -#define BTN_THUMBR 0x13e - -#define BTN_DIGI 0x140 -#define BTN_TOOL_PEN 0x140 -#define BTN_TOOL_RUBBER 0x141 -#define BTN_TOOL_BRUSH 0x142 -#define BTN_TOOL_PENCIL 0x143 -#define BTN_TOOL_AIRBRUSH 0x144 -#define BTN_TOOL_FINGER 0x145 -#define BTN_TOOL_MOUSE 0x146 -#define BTN_TOOL_LENS 0x147 -#define BTN_TOUCH 0x14a -#define BTN_STYLUS 0x14b -#define BTN_STYLUS2 0x14c -#define BTN_TOOL_DOUBLETAP 0x14d -#define BTN_TOOL_TRIPLETAP 0x14e - -#define BTN_WHEEL 0x150 -#define BTN_GEAR_DOWN 0x150 -#define BTN_GEAR_UP 0x151 - -#define REL_X 0x00 -#define REL_Y 0x01 - -#define ABS_X 0x00 -#define ABS_Y 0x01 -#define ABS_Z 0x02 -#define ABS_RX 0x03 -#define ABS_RY 0x04 -#define ABS_RZ 0x05 -#define ABS_THROTTLE 0x06 -#define ABS_RUDDER 0x07 -#define ABS_WHEEL 0x08 -#define ABS_GAS 0x09 -#define ABS_BRAKE 0x0a -#define ABS_HAT0X 0x10 -#define ABS_HAT0Y 0x11 -#define ABS_HAT1X 0x12 -#define ABS_HAT1Y 0x13 -#define ABS_HAT2X 0x14 -#define ABS_HAT2Y 0x15 -#define ABS_HAT3X 0x16 -#define ABS_HAT3Y 0x17 -#define ABS_PRESSURE 0x18 -#define ABS_DISTANCE 0x19 -#define ABS_TILT_X 0x1a -#define ABS_TILT_Y 0x1b -#define ABS_TOOL_WIDTH 0x1c -#define ABS_VOLUME 0x20 -#define ABS_MISC 0x28 -#define ABS_MAX 0x3f -#endif - -#define MAX_EVENTS 256*4 - -enum { - REG_READ = 0x00, - REG_SET_PAGE = 0x00, - REG_LEN = 0x04, - REG_DATA = 0x08, - - PAGE_NAME = 0x00000, - PAGE_EVBITS = 0x10000, - PAGE_ABSDATA = 0x20000 | EV_ABS, -}; - -typedef struct -{ - uint32_t base; - qemu_irq irq; - int pending; - int page; - - unsigned events[MAX_EVENTS]; - unsigned first; - unsigned last; - - const char *name; - struct { - size_t len; - uint8_t *bits; - } ev_bits[EV_MAX + 1]; - int32_t *abs_info; - size_t abs_info_count; -} events_state; - -/* modify this each time you change the events_device structure. you - * will also need to upadte events_state_load and events_state_save - */ -#define EVENTS_STATE_SAVE_VERSION 1 - -#undef QFIELD_STRUCT -#define QFIELD_STRUCT events_state - -QFIELD_BEGIN(events_state_fields) - QFIELD_INT32(pending), - QFIELD_INT32(page), - QFIELD_BUFFER(events), - QFIELD_INT32(first), - QFIELD_INT32(last), -QFIELD_END - -static void events_state_save(QEMUFile* f, void* opaque) -{ - events_state* s = opaque; - - qemu_put_struct(f, events_state_fields, s); -} - -static int events_state_load(QEMUFile* f, void* opaque, int version_id) -{ - events_state* s = opaque; - - if (version_id != EVENTS_STATE_SAVE_VERSION) - return -1; - - return qemu_get_struct(f, events_state_fields, s); -} - -extern const char* android_skin_keycharmap; - -static void enqueue_event(events_state *s, unsigned int type, unsigned int code, int value) -{ - int enqueued = s->last - s->first; - - if (enqueued < 0) - enqueued += MAX_EVENTS; - - if (enqueued + 3 >= MAX_EVENTS-1) { - fprintf(stderr, "##KBD: Full queue, lose event\n"); - return; - } - - if(s->first == s->last){ - qemu_irq_raise(s->irq); - } - - //fprintf(stderr, "##KBD: type=%d code=%d value=%d\n", type, code, value); - - s->events[s->last] = type; - s->last = (s->last + 1) & (MAX_EVENTS-1); - s->events[s->last] = code; - s->last = (s->last + 1) & (MAX_EVENTS-1); - s->events[s->last] = value; - s->last = (s->last + 1) & (MAX_EVENTS-1); -} - -static unsigned dequeue_event(events_state *s) -{ - unsigned n; - - if(s->first == s->last) { - return 0; - } - - n = s->events[s->first]; - - s->first = (s->first + 1) & (MAX_EVENTS - 1); - - if(s->first == s->last) { - qemu_irq_lower(s->irq); - } - - return n; -} - -static int get_page_len(events_state *s) -{ - int page = s->page; - if (page == PAGE_NAME) - return strlen(s->name); - if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX) - return s->ev_bits[page - PAGE_EVBITS].len; - if (page == PAGE_ABSDATA) - return s->abs_info_count * sizeof(s->abs_info[0]); - return 0; -} - -static int get_page_data(events_state *s, int offset) -{ - int page_len = get_page_len(s); - int page = s->page; - if (offset > page_len) - return 0; - if (page == PAGE_NAME) - return s->name[offset]; - if (page >= PAGE_EVBITS && page <= PAGE_EVBITS + EV_MAX) - return s->ev_bits[page - PAGE_EVBITS].bits[offset]; - if (page == PAGE_ABSDATA) - return s->abs_info[offset / sizeof(s->abs_info[0])]; - return 0; -} - -static uint32_t events_read(void *x, target_phys_addr_t off) -{ - events_state *s = (events_state *) x; - int offset = off - s->base; - if (offset == REG_READ) - return dequeue_event(s); - else if (offset == REG_LEN) - return get_page_len(s); - else if (offset >= REG_DATA) - return get_page_data(s, offset - REG_DATA); - return 0; // this shouldn't happen, if the driver does the right thing -} - -static void events_write(void *x, target_phys_addr_t off, uint32_t val) -{ - events_state *s = (events_state *) x; - int offset = off - s->base; - if (offset == REG_SET_PAGE) - s->page = val; -} - -static CPUReadMemoryFunc *events_readfn[] = { - events_read, - events_read, - events_read -}; - -static CPUWriteMemoryFunc *events_writefn[] = { - events_write, - events_write, - events_write -}; - -static void events_put_keycode(void *x, int keycode) -{ - events_state *s = (events_state *) x; - - enqueue_event(s, EV_KEY, keycode&0x1ff, (keycode&0x200) ? 1 : 0); -} - -static void events_put_mouse(void *opaque, int dx, int dy, int dz, int buttons_state) -{ - events_state *s = (events_state *) opaque; - if (dz == 0) { - enqueue_event(s, EV_ABS, ABS_X, dx); - enqueue_event(s, EV_ABS, ABS_Y, dy); - enqueue_event(s, EV_ABS, ABS_Z, dz); - enqueue_event(s, EV_KEY, BTN_TOUCH, buttons_state&1); - } else { - enqueue_event(s, EV_REL, REL_X, dx); - enqueue_event(s, EV_REL, REL_Y, dy); - } - enqueue_event(s, EV_SYN, 0, 0); -} - -static void events_put_generic(void* opaque, int type, int code, int value) -{ - events_state *s = (events_state *) opaque; - - enqueue_event(s, type, code, value); -} - -static int events_set_bits(events_state *s, int type, int bitl, int bith) -{ - uint8_t *bits; - uint8_t maskl, maskh; - int il, ih; - il = bitl / 8; - ih = bith / 8; - if (ih >= s->ev_bits[type].len) { - bits = qemu_mallocz(ih + 1); - if (bits == NULL) - return -ENOMEM; - memcpy(bits, s->ev_bits[type].bits, s->ev_bits[type].len); - qemu_free(s->ev_bits[type].bits); - s->ev_bits[type].bits = bits; - s->ev_bits[type].len = ih + 1; - } - else - bits = s->ev_bits[type].bits; - maskl = 0xffU << (bitl & 7); - maskh = 0xffU >> (7 - (bith & 7)); - if (il >= ih) - maskh &= maskl; - else { - bits[il] |= maskl; - while (++il < ih) - bits[il] = 0xff; - } - bits[ih] |= maskh; - return 0; -} - -#if 0 -static int events_set_abs_info(events_state *s, int axis, int32_t min, int32_t max, int32_t fuzz, int32_t flat) -{ - int32_t *info; - if (axis * 4 >= s->abs_info_count) { - info = qemu_mallocz((axis + 1) * 4 * sizeof(int32_t)); - if (info == NULL) - return -ENOMEM; - memcpy(info, s->abs_info, s->abs_info_count); - qemu_free(s->abs_info); - s->abs_info = info; - s->abs_info_count = (axis + 1) * 4; - } - else - info = s->abs_info; - info += axis * 4; - *info++ = min; - *info++ = max; - *info++ = fuzz; - *info++ = flat; -} -#endif - -void events_dev_init(uint32_t base, qemu_irq irq) -{ - events_state *s; - int iomemtype; - - s = (events_state *) qemu_mallocz(sizeof(events_state)); - s->name = android_skin_keycharmap; - events_set_bits(s, EV_SYN, EV_SYN, EV_ABS); - events_set_bits(s, EV_SYN, EV_SW, EV_SW); - events_set_bits(s, EV_KEY, 1, 0x1ff); - events_set_bits(s, EV_REL, REL_X, REL_Y); - events_set_bits(s, EV_ABS, ABS_X, ABS_Z); - events_set_bits(s, EV_SW, 0, 0); - iomemtype = cpu_register_io_memory(0, events_readfn, events_writefn, s); - - cpu_register_physical_memory(base, 0xfff, iomemtype); - - qemu_add_kbd_event_handler(events_put_keycode, s); - qemu_add_mouse_event_handler(events_put_mouse, s, 1); - qemu_add_generic_event_handler(events_put_generic, s); - - s->base = base; - s->irq = irq; - - s->first = 0; - s->last = 0; - - register_savevm( "events_state", 0, EVENTS_STATE_SAVE_VERSION, - events_state_save, events_state_load, s ); -} - diff --git a/hw/goldfish_fb.c b/hw/goldfish_fb.c deleted file mode 100644 index 71cede2..0000000 --- a/hw/goldfish_fb.c +++ /dev/null @@ -1,405 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "android/android.h" -#include "goldfish_device.h" -#include "framebuffer.h" - -enum { - FB_GET_WIDTH = 0x00, - FB_GET_HEIGHT = 0x04, - FB_INT_STATUS = 0x08, - FB_INT_ENABLE = 0x0c, - FB_SET_BASE = 0x10, - FB_SET_ROTATION = 0x14, - FB_SET_BLANK = 0x18, - FB_GET_PHYS_WIDTH = 0x1c, - FB_GET_PHYS_HEIGHT = 0x20, - - FB_INT_VSYNC = 1U << 0, - FB_INT_BASE_UPDATE_DONE = 1U << 1 -}; - -struct goldfish_fb_state { - struct goldfish_device dev; - QFrameBuffer* qfbuff; - uint32_t fb_base; - uint32_t base_valid : 1; - uint32_t need_update : 1; - uint32_t need_int : 1; - uint32_t set_rotation : 2; - uint32_t blank : 1; - uint32_t int_status; - uint32_t int_enable; - int rotation; /* 0, 1, 2 or 3 */ -}; - -#define GOLDFISH_FB_SAVE_VERSION 1 - -static void goldfish_fb_save(QEMUFile* f, void* opaque) -{ - struct goldfish_fb_state* s = opaque; - - QFrameBuffer* q = s->qfbuff; - - qemu_put_be32(f, q->width); - qemu_put_be32(f, q->height); - qemu_put_be32(f, q->pitch); - qemu_put_byte(f, q->rotation); - - qemu_put_be32(f, s->fb_base); - qemu_put_byte(f, s->base_valid); - qemu_put_byte(f, s->need_update); - qemu_put_byte(f, s->need_int); - qemu_put_byte(f, s->set_rotation); - qemu_put_byte(f, s->blank); - qemu_put_be32(f, s->int_status); - qemu_put_be32(f, s->int_enable); - qemu_put_be32(f, s->rotation); -} - -static int goldfish_fb_load(QEMUFile* f, void* opaque, int version_id) -{ - struct goldfish_fb_state* s = opaque; - - QFrameBuffer* q = s->qfbuff; - int ret = -1; - int ds_w, ds_h, ds_pitch, ds_rot; - - if (version_id != GOLDFISH_FB_SAVE_VERSION) - goto Exit; - - ds_w = qemu_get_be32(f); - ds_h = qemu_get_be32(f); - ds_pitch = qemu_get_be32(f); - ds_rot = qemu_get_byte(f); - - if (q->width != ds_w || - q->height != ds_h || - q->pitch != ds_pitch || - q->rotation != ds_rot ) - { - /* XXX: We should be able to force a resize/rotation from here ? */ - fprintf(stderr, "%s: framebuffer dimensions mismatch\n", __FUNCTION__); - goto Exit; - } - - s->fb_base = qemu_get_be32(f); - s->base_valid = qemu_get_byte(f); - s->need_update = qemu_get_byte(f); - s->need_int = qemu_get_byte(f); - s->set_rotation = qemu_get_byte(f); - s->blank = qemu_get_byte(f); - s->int_status = qemu_get_be32(f); - s->int_enable = qemu_get_be32(f); - s->rotation = qemu_get_be32(f); - - /* force a refresh */ - s->need_update = 1; - - ret = 0; -Exit: - return ret; -} - - -#define STATS 0 - -#if STATS -static int stats_counter; -static long stats_total; -static int stats_full_updates; -static long stats_total_full_updates; -#endif - -static void goldfish_fb_update_display(void *opaque) -{ - struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque; - uint32_t addr; - uint32_t base; - - uint8_t* dst_line; - uint8_t* src_line; - int y_first, y_last = 0; - int full_update = 0; - int width, height, pitch; - - base = s->fb_base; - if(base == 0) - return; - - if((s->int_enable & FB_INT_VSYNC) && !(s->int_status & FB_INT_VSYNC)) { - s->int_status |= FB_INT_VSYNC; - goldfish_device_set_irq(&s->dev, 0, 1); - } - - y_first = -1; - addr = base; - if(s->need_update) { - full_update = 1; - if(s->need_int) { - s->int_status |= FB_INT_BASE_UPDATE_DONE; - if(s->int_enable & FB_INT_BASE_UPDATE_DONE) - goldfish_device_set_irq(&s->dev, 0, 1); - } - s->need_int = 0; - s->need_update = 0; - } - - src_line = phys_ram_base + base; - dst_line = s->qfbuff->pixels; - pitch = s->qfbuff->pitch; - width = s->qfbuff->width; - height = s->qfbuff->height; - -#if STATS - if (full_update) - stats_full_updates += 1; - if (++stats_counter == 120) { - stats_total += stats_counter; - stats_total_full_updates += stats_full_updates; - - printf( "full update stats: peak %.2f %% total %.2f %%\n", - stats_full_updates*100.0/stats_counter, - stats_total_full_updates*100.0/stats_total ); - - stats_counter = 0; - stats_full_updates = 0; - } -#endif /* STATS */ - - if (s->blank) - { - memset( dst_line, 0, height*pitch ); - y_first = 0; - y_last = height-1; - } - else if (full_update) - { - int yy; - - for (yy = 0; yy < height; yy++, dst_line += pitch, src_line += width*2) - { - uint16_t* src = (uint16_t*) src_line; - uint16_t* dst = (uint16_t*) dst_line; - int nn; - - for (nn = 0; nn < width; nn++) { - unsigned spix = src[nn]; - unsigned dpix = dst[nn]; -#if WORDS_BIGENDIAN - spix = ((spix << 8) | (spix >> 8)) & 0xffff; -#else - if (spix != dpix) - break; -#endif - } - - if (nn == width) - continue; - -#if WORDS_BIGENDIAN - for ( ; nn < width; nn++ ) { - unsigned spix = src[nn]; - dst[nn] = (uint16_t)((spix << 8) | (spix >> 8)); - } -#else - memcpy( dst+nn, src+nn, (width-nn)*2 ); -#endif - - y_first = (y_first < 0) ? yy : y_first; - y_last = yy; - } - } - else /* not a full update, should not happen very often with Android */ - { - int yy; - - for (yy = 0; yy < height; yy++, dst_line += pitch, src_line += width*2) - { - uint16_t* src = (uint16_t*) src_line; - uint16_t* dst = (uint16_t*) dst_line; - int len = width*2; -#if WORDS_BIGENDIAN - int nn; -#endif - int dirty = 0; - - while (len > 0) { - int len2 = TARGET_PAGE_SIZE - (addr & (TARGET_PAGE_SIZE-1)); - - if (len2 > len) - len2 = len; - - dirty |= cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG); - addr += len2; - len -= len2; - } - - if (!dirty) - continue; - -#if WORDS_BIGENDIAN - for (nn = 0; nn < width; nn++ ) { - unsigned spix = src[nn]; - dst[nn] = (uint16_t)((spix << 8) | (spix >> 8)); - } -#else - memcpy( dst, src, width*2 ); -#endif - - y_first = (y_first < 0) ? yy : y_first; - y_last = yy; - } - } - - if (y_first < 0) - return; - - y_last += 1; - //printf("goldfish_fb_update_display %d %d, base %x\n", first, last, base); - - cpu_physical_memory_reset_dirty(base + y_first * width * 2, - base + y_last * width * 2, - VGA_DIRTY_FLAG); - - qframebuffer_update( s->qfbuff, 0, y_first, width, y_last-y_first ); -} - -static void goldfish_fb_invalidate_display(void * opaque) -{ - // is this called? - struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque; - s->need_update = 1; -} - -static void goldfish_fb_detach_display(void* opaque) -{ - struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque; - s->qfbuff = NULL; -} - -static uint32_t goldfish_fb_read(void *opaque, target_phys_addr_t offset) -{ - uint32_t ret; - struct goldfish_fb_state *s = opaque; - offset -= s->dev.base; - switch(offset) { - case FB_GET_WIDTH: - ret = s->qfbuff->width; - //printf("FB_GET_WIDTH => %d\n", ret); - return ret; - - case FB_GET_HEIGHT: - ret = s->qfbuff->height; - //printf( "FB_GET_HEIGHT = %d\n", ret); - return ret; - - case FB_INT_STATUS: - ret = s->int_status & s->int_enable; - if(ret) { - s->int_status &= ~ret; - goldfish_device_set_irq(&s->dev, 0, 0); - } - return ret; - - case FB_GET_PHYS_WIDTH: - ret = s->qfbuff->phys_width_mm; - //printf( "FB_GET_PHYS_WIDTH => %d\n", ret ); - return ret; - - case FB_GET_PHYS_HEIGHT: - ret = s->qfbuff->phys_height_mm; - //printf( "FB_GET_PHYS_HEIGHT => %d\n", ret ); - return ret; - - default: - cpu_abort (cpu_single_env, "goldfish_fb_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_fb_write(void *opaque, target_phys_addr_t offset, - uint32_t val) -{ - struct goldfish_fb_state *s = opaque; - offset -= s->dev.base; - switch(offset) { - case FB_INT_ENABLE: - s->int_enable = val; - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - break; - case FB_SET_BASE: { - int need_resize = !s->base_valid; - s->fb_base = val; - s->int_status &= ~FB_INT_BASE_UPDATE_DONE; - s->need_update = 1; - s->need_int = 1; - s->base_valid = 1; - if(s->set_rotation != s->rotation) { - //printf("FB_SET_BASE: rotation : %d => %d\n", s->rotation, s->set_rotation); - s->rotation = s->set_rotation; - need_resize = 1; - } - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - if (need_resize) { - //printf("FB_SET_BASE: need resize (rotation=%d)\n", s->rotation ); - qframebuffer_rotate( s->qfbuff, s->rotation ); - } - } break; - case FB_SET_ROTATION: - //printf( "FB_SET_ROTATION %d\n", val); - s->set_rotation = val; - break; - case FB_SET_BLANK: - s->blank = val; - s->need_update = 1; - break; - default: - cpu_abort (cpu_single_env, "goldfish_fb_write: Bad offset %x\n", offset); - } -} - -static CPUReadMemoryFunc *goldfish_fb_readfn[] = { - goldfish_fb_read, - goldfish_fb_read, - goldfish_fb_read -}; - -static CPUWriteMemoryFunc *goldfish_fb_writefn[] = { - goldfish_fb_write, - goldfish_fb_write, - goldfish_fb_write -}; - -void goldfish_fb_init(DisplayState *ds, int id) -{ - struct goldfish_fb_state *s; - - s = (struct goldfish_fb_state *)qemu_mallocz(sizeof(*s)); - s->dev.name = "goldfish_fb"; - s->dev.id = id; - s->dev.size = 0x1000; - s->dev.irq_count = 1; - - s->qfbuff = qframebuffer_fifo_get(); - qframebuffer_set_producer( s->qfbuff, s, - goldfish_fb_update_display, - goldfish_fb_invalidate_display, - goldfish_fb_detach_display ); - - goldfish_device_add(&s->dev, goldfish_fb_readfn, goldfish_fb_writefn, s); - - register_savevm( "goldfish_fb", 0, GOLDFISH_FB_SAVE_VERSION, - goldfish_fb_save, goldfish_fb_load, s); -} - diff --git a/hw/goldfish_interrupt.c b/hw/goldfish_interrupt.c deleted file mode 100644 index 2cba649..0000000 --- a/hw/goldfish_interrupt.c +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "arm_pic.h" -#include "goldfish_device.h" -#include "irq.h" - -enum { - INTERRUPT_STATUS = 0x00, // number of pending interrupts - INTERRUPT_NUMBER = 0x04, - INTERRUPT_DISABLE_ALL = 0x08, - INTERRUPT_DISABLE = 0x0c, - INTERRUPT_ENABLE = 0x10 -}; - -struct goldfish_int_state { - struct goldfish_device dev; - uint32_t level; - uint32_t pending_count; - uint32_t irq_enabled; - uint32_t fiq_enabled; - qemu_irq parent_irq; - qemu_irq parent_fiq; -}; - -#define GOLDFISH_INT_SAVE_VERSION 1 - -#define QFIELD_STRUCT struct goldfish_int_state -QFIELD_BEGIN(goldfish_int_fields) - QFIELD_INT32(level), - QFIELD_INT32(pending_count), - QFIELD_INT32(irq_enabled), - QFIELD_INT32(fiq_enabled), -QFIELD_END - -static void goldfish_int_save(QEMUFile* f, void* opaque) -{ - struct goldfish_int_state* s = opaque; - - qemu_put_struct(f, goldfish_int_fields, s); -} - -static int goldfish_int_load(QEMUFile* f, void* opaque, int version_id) -{ - struct goldfish_int_state* s = opaque; - - if (version_id != GOLDFISH_INT_SAVE_VERSION) - return -1; - - return qemu_get_struct(f, goldfish_int_fields, s); -} - -static void goldfish_int_update(struct goldfish_int_state *s) -{ - uint32_t flags; - - flags = (s->level & s->irq_enabled); - qemu_set_irq(s->parent_irq, flags != 0); - - flags = (s->level & s->fiq_enabled); - qemu_set_irq(s->parent_fiq, flags != 0); -} - -static void goldfish_int_set_irq(void *opaque, int irq, int level) -{ - struct goldfish_int_state *s = (struct goldfish_int_state *)opaque; - uint32_t mask = (1U << irq); - - if(level) { - if(!(s->level & mask)) { - if(s->irq_enabled & mask) - s->pending_count++; - s->level |= mask; - } - } - else { - if(s->level & mask) { - if(s->irq_enabled & mask) - s->pending_count--; - s->level &= ~mask; - } - } - goldfish_int_update(s); -} - -static uint32_t goldfish_int_read(void *opaque, target_phys_addr_t offset) -{ - struct goldfish_int_state *s = (struct goldfish_int_state *)opaque; - offset -= s->dev.base; - - switch (offset) { - case INTERRUPT_STATUS: /* IRQ_STATUS */ - return s->pending_count; - case INTERRUPT_NUMBER: { - int i; - uint32_t pending = s->level & s->irq_enabled; - for(i = 0; i < 32; i++) { - if(pending & (1U << i)) - return i; - } - return 0; - } - default: - cpu_abort (cpu_single_env, "goldfish_int_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_int_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - struct goldfish_int_state *s = (struct goldfish_int_state *)opaque; - uint32_t mask = (1U << value); - offset -= s->dev.base; - - switch (offset) { - case INTERRUPT_DISABLE_ALL: - s->pending_count = 0; - s->level = 0; - break; - - case INTERRUPT_DISABLE: - if(s->irq_enabled & mask) { - if(s->level & mask) - s->pending_count--; - s->irq_enabled &= ~mask; - } - break; - case INTERRUPT_ENABLE: - if(!(s->irq_enabled & mask)) { - s->irq_enabled |= mask; - if(s->level & mask) - s->pending_count++; - } - break; - - default: - cpu_abort (cpu_single_env, "goldfish_int_write: Bad offset %x\n", offset); - return; - } - goldfish_int_update(s); -} - -static CPUReadMemoryFunc *goldfish_int_readfn[] = { - goldfish_int_read, - goldfish_int_read, - goldfish_int_read -}; - -static CPUWriteMemoryFunc *goldfish_int_writefn[] = { - goldfish_int_write, - goldfish_int_write, - goldfish_int_write -}; - -qemu_irq* goldfish_interrupt_init(uint32_t base, qemu_irq parent_irq, qemu_irq parent_fiq) -{ - int ret; - struct goldfish_int_state *s; - qemu_irq* qi; - - s = qemu_mallocz(sizeof(*s)); - qi = qemu_allocate_irqs(goldfish_int_set_irq, s, 32); - s->dev.name = "goldfish_interrupt_controller"; - s->dev.id = -1; - s->dev.base = base; - s->dev.size = 0x1000; - s->parent_irq = parent_irq; - s->parent_fiq = parent_fiq; - - ret = goldfish_device_add(&s->dev, goldfish_int_readfn, goldfish_int_writefn, s); - if(ret) { - qemu_free(s); - return NULL; - } - - register_savevm( "goldfish_int", 0, GOLDFISH_INT_SAVE_VERSION, - goldfish_int_save, goldfish_int_load, s); - - return qi; -} - diff --git a/hw/goldfish_memlog.c b/hw/goldfish_memlog.c deleted file mode 100644 index 98fcffc..0000000 --- a/hw/goldfish_memlog.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include <unistd.h> -#include <fcntl.h> -#include <string.h> - -#include "qemu_file.h" -#include "goldfish_device.h" -#include "audio/audio.h" - -extern void dprint(const char* fmt, ...); - -int fd = -1; - -static uint32_t memlog_read(void *opaque, target_phys_addr_t offset) -{ - struct goldfish_device *dev = opaque; - offset -= dev->base; - - return 0; -} - -unsigned info[8]; - -static void memlog_write(void *opaque, target_phys_addr_t offset, uint32_t val) -{ - char buf[128]; - struct goldfish_device *dev = opaque; - offset -= dev->base; - - info[offset / 4] = val; - - if (offset == 0) { - /* write PID and VADDR to logfile */ - sprintf(buf,"%08x %08x\n", info[0], info[1]); - write(fd, buf, strlen(buf)); - } -} - - -static CPUReadMemoryFunc *memlog_readfn[] = { - memlog_read, - memlog_read, - memlog_read -}; - -static CPUWriteMemoryFunc *memlog_writefn[] = { - memlog_write, - memlog_write, - memlog_write -}; - -struct goldfish_device memlog_dev; - -void goldfish_memlog_init(uint32_t base) -{ - struct goldfish_device *dev = &memlog_dev; - - dev->name = "goldfish_memlog"; - dev->id = 0; - dev->base = base; - dev->size = 0x1000; - dev->irq_count = 0; - - fd = open("mem.log", /* O_CREAT | */ O_TRUNC | O_WRONLY, 0644); - - goldfish_device_add(dev, memlog_readfn, memlog_writefn, dev); -} - diff --git a/hw/goldfish_mmc.c b/hw/goldfish_mmc.c deleted file mode 100644 index 272f403..0000000 --- a/hw/goldfish_mmc.c +++ /dev/null @@ -1,468 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "goldfish_device.h" -#include "mmc.h" -#include "sd.h" -#include "block.h" - -enum { - /* status register */ - MMC_INT_STATUS = 0x00, - /* set this to enable IRQ */ - MMC_INT_ENABLE = 0x04, - /* set this to specify buffer address */ - MMC_SET_BUFFER = 0x08, - - /* MMC command number */ - MMC_CMD = 0x0C, - - /* MMC argument */ - MMC_ARG = 0x10, - - /* MMC response (or R2 bits 0 - 31) */ - MMC_RESP_0 = 0x14, - - /* MMC R2 response bits 32 - 63 */ - MMC_RESP_1 = 0x18, - - /* MMC R2 response bits 64 - 95 */ - MMC_RESP_2 = 0x1C, - - /* MMC R2 response bits 96 - 127 */ - MMC_RESP_3 = 0x20, - - MMC_BLOCK_LENGTH = 0x24, - MMC_BLOCK_COUNT = 0x28, - - /* MMC state flags */ - MMC_STATE = 0x2C, - - /* MMC_INT_STATUS bits */ - - MMC_STAT_END_OF_CMD = 1U << 0, - MMC_STAT_END_OF_DATA = 1U << 1, - MMC_STAT_STATE_CHANGE = 1U << 2, - - /* MMC_STATE bits */ - MMC_STATE_INSERTED = 1U << 0, - MMC_STATE_READ_ONLY = 1U << 1, -}; - - -struct goldfish_mmc_state { - struct goldfish_device dev; - BlockDriverState *bs; - // pointer to our buffer - uint8_t* buffer; - // offsets for read and write operations - uint32_t read_offset, write_offset; - // buffer status flags - uint32_t int_status; - // irq enable mask for int_status - uint32_t int_enable; - - // MMC command argument - uint32_t arg; - uint32_t resp[4]; - - uint32_t block_length; - uint32_t block_count; - int is_SDHC; -}; - -#define GOLDFISH_MMC_SAVE_VERSION 1 -#define QFIELD_STRUCT struct goldfish_mmc_state -QFIELD_BEGIN(goldfish_mmc_fields) - QFIELD_INT32(read_offset), - QFIELD_INT32(write_offset), - QFIELD_INT32(int_status), - QFIELD_INT32(int_enable), - QFIELD_INT32(arg), - QFIELD_INT32(resp[0]), - QFIELD_INT32(resp[1]), - QFIELD_INT32(resp[2]), - QFIELD_INT32(resp[3]), - QFIELD_INT32(block_length), - QFIELD_INT32(block_count), - QFIELD_INT32(is_SDHC), -QFIELD_END - -static void goldfish_mmc_save(QEMUFile* f, void* opaque) -{ - struct goldfish_mmc_state* s = opaque; - - qemu_put_be32(f, s->buffer - phys_ram_base); - qemu_put_struct(f, goldfish_mmc_fields, s); -} - -static int goldfish_mmc_load(QEMUFile* f, void* opaque, int version_id) -{ - struct goldfish_mmc_state* s = opaque; - - if (version_id != GOLDFISH_MMC_SAVE_VERSION) - return -1; - - s->buffer = qemu_get_be32(f) + phys_ram_base; - return qemu_get_struct(f, goldfish_mmc_fields, s); -} - -struct mmc_opcode { - const char* name; - int cmd; -} mmc_opcodes[] = { - { "MMC_GO_IDLE_STATE", 0 }, - { "MMC_SEND_OP_COND", 1 }, - { "MMC_ALL_SEND_CID", 2 }, - { "MMC_SET_RELATIVE_ADDR", 3 }, - { "MMC_SET_DSR", 4 }, - { "MMC_SWITCH", 6 }, - { "MMC_SELECT_CARD", 7 }, - { "MMC_SEND_EXT_CSD", 8 }, - { "MMC_SEND_CSD", 9 }, - { "MMC_SEND_CID", 10 }, - { "MMC_READ_DAT_UNTIL_STOP", 11 }, - { "MMC_STOP_TRANSMISSION", 12 }, - { "MMC_SEND_STATUS", 13 }, - { "MMC_GO_INACTIVE_STATE", 15 }, - { "MMC_SET_BLOCKLEN", 16 }, - { "MMC_READ_SINGLE_BLOCK", 17 }, - { "MMC_READ_MULTIPLE_BLOCK", 18 }, - { "MMC_WRITE_DAT_UNTIL_STOP", 20 }, - { "MMC_SET_BLOCK_COUNT", 23 }, - { "MMC_WRITE_BLOCK", 24 }, - { "MMC_WRITE_MULTIPLE_BLOCK", 25 }, - { "MMC_PROGRAM_CID", 26 }, - { "MMC_PROGRAM_CSD", 27 }, - { "MMC_SET_WRITE_PROT", 28 }, - { "MMC_CLR_WRITE_PROT", 29 }, - { "MMC_SEND_WRITE_PROT", 30 }, - { "MMC_ERASE_GROUP_START", 35 }, - { "MMC_ERASE_GROUP_END", 36 }, - { "MMC_ERASE", 38 }, - { "MMC_FAST_IO", 39 }, - { "MMC_GO_IRQ_STATE", 40 }, - { "MMC_LOCK_UNLOCK", 42 }, - { "MMC_APP_CMD", 55 }, - { "MMC_GEN_CMD", 56 }, - { "SD_APP_OP_COND", 41 }, - { "SD_APP_SEND_SCR", 51 }, - { "UNKNOWN", -1 } -}; - -#if 0 -static const char* get_command_name(int command) -{ - struct mmc_opcode* opcode = mmc_opcodes; - - while (opcode->cmd != command && opcode->cmd != -1) opcode++; - return opcode->name; -} -#endif - -static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd, uint32_t arg) -{ - int result; - int new_status = MMC_STAT_END_OF_CMD; - int opcode = cmd & 63; - -// fprintf(stderr, "goldfish_mmc_do_command opcode: %s (0x%04X), arg: %d\n", get_command_name(opcode), cmd, arg); - - s->resp[0] = 0; - s->resp[1] = 0; - s->resp[2] = 0; - s->resp[3] = 0; - -#define SET_R1_CURRENT_STATE(s) ((s << 9) & 0x00001E00) /* sx, b (4 bits) */ - - switch (opcode) { - case MMC_SEND_CSD: { - int64_t sector_count = 0; - uint64_t capacity; - uint8_t exponent; - uint32_t m; - - bdrv_get_geometry(s->bs, (uint64_t*)§or_count); - capacity = sector_count * 512; - if (capacity > 2147483648U) { - // if storages is > 2 gig, then emulate SDHC card - s->is_SDHC = 1; - - // CSD bits borrowed from a real SDHC card, with capacity bits zeroed out - s->resp[3] = 0x400E0032; - s->resp[2] = 0x5B590000; - s->resp[1] = 0x00007F80; - s->resp[0] = 0x0A4040DF; - - // stuff in the real capacity - // m = UNSTUFF_BITS(resp, 48, 22); - m = (uint32_t)(capacity / (512*1024)) - 1; - // m must fit into 22 bits - if (m & 0xFFC00000) { - fprintf(stderr, "SD card too big (%lld bytes). Maximum SDHC card size is 128 gigabytes.\n", capacity); - abort(); - } - - // low 16 bits go in high end of resp[1] - s->resp[1] |= ((m & 0x0000FFFF) << 16); - // high 6 bits go in low end of resp[2] - s->resp[2] |= (m >> 16); - } else { - // emulate standard SD card - s->is_SDHC = 0; - - // CSD bits borrowed from a real SD card, with capacity bits zeroed out - s->resp[3] = 0x00260032; - s->resp[2] = 0x5F5A8000; - s->resp[1] = 0x3EF84FFF; - s->resp[0] = 0x928040CB; - - // stuff in the real capacity - // e = UNSTUFF_BITS(resp, 47, 3); - // m = UNSTUFF_BITS(resp, 62, 12); - // csd->capacity = (1 + m) << (e + 2); - // need to reverse the formula and calculate e and m - exponent = 0; - capacity = sector_count * 512; - if (capacity > 2147483648U) { - fprintf(stderr, "SD card too big (%lld bytes). Maximum SD card size is 2 gigabytes.\n", capacity); - abort(); - } - capacity >>= 10; // convert to Kbytes - while (capacity > 4096) { - // (capacity - 1) must fit into 12 bits - exponent++; - capacity >>= 1; - } - capacity -= 1; - exponent -= 2; - if (exponent > 7) - cpu_abort(cpu_single_env, "exponent %d too big\n", exponent); - - s->resp[2] |= (((uint32_t)capacity >> 2) & 0x3FF); // high 10 bits to bottom of resp[2] - s->resp[1] |= (((uint32_t)capacity & 3) << 30); // low 2 bits to top of resp[1] - s->resp[1] |= (exponent << (47 - 32)); - } - break; - } - - case MMC_SEND_EXT_CSD: - s->resp[0] = arg; - break; - - case MMC_APP_CMD: - s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336 - break; - - case SD_APP_OP_COND: - s->resp[0] = 0x80FF8000; - break; - - case SD_APP_SEND_SCR: - { - uint32_t* scr = (uint32_t*)s->buffer; - scr[0] = 0x00002502; - scr[1] = 0x00000000; - s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336 - new_status |= MMC_STAT_END_OF_DATA; - break; - } - case MMC_SET_RELATIVE_ADDR: - s->resp[0] = -518519520; - break; - - case MMC_ALL_SEND_CID: - s->resp[3] = 55788627; - s->resp[2] = 1429221959; - s->resp[1] = -2147479692; - s->resp[0] = -436179883; - break; - - case MMC_SELECT_CARD: - s->resp[0] = SET_R1_CURRENT_STATE(3) | R1_READY_FOR_DATA; // 1792 - break; - - case MMC_SWITCH: - if (arg == 0x00FFFFF1 || arg == 0x80FFFFF1) { - uint8_t* switchbuf = s->buffer; - memset(switchbuf, 0, 64); - switchbuf[13] = 2; - new_status |= MMC_STAT_END_OF_DATA; - } - s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA | R1_APP_CMD; //2336 - break; - - case MMC_SET_BLOCKLEN: - s->block_length = arg; - s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304 - break; - - case MMC_READ_SINGLE_BLOCK: - s->block_count = 1; - // fall through - case MMC_READ_MULTIPLE_BLOCK: { - if (s->is_SDHC) { - // arg is block offset - } else { - // arg is byte offset - if (arg & 511) fprintf(stderr, "offset %d is not multiple of 512 when reading\n", arg); - arg /= s->block_length; - } - result = bdrv_read(s->bs, arg, s->buffer, s->block_count); - new_status |= MMC_STAT_END_OF_DATA; - s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304 - break; - } - - case MMC_WRITE_BLOCK: - s->block_count = 1; - // fall through - case MMC_WRITE_MULTIPLE_BLOCK: { - if (s->is_SDHC) { - // arg is block offset - } else { - // arg is byte offset - if (arg & 511) fprintf(stderr, "offset %d is not multiple of 512 when writing\n", arg); - arg /= s->block_length; - } - // arg is byte offset - result = bdrv_write(s->bs, arg, s->buffer, s->block_count); -// bdrv_flush(s->bs); - new_status |= MMC_STAT_END_OF_DATA; - s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304 - break; - } - - case MMC_STOP_TRANSMISSION: - s->resp[0] = SET_R1_CURRENT_STATE(5) | R1_READY_FOR_DATA; // 2816 - break; - - case MMC_SEND_STATUS: - s->resp[0] = SET_R1_CURRENT_STATE(4) | R1_READY_FOR_DATA; // 2304 - break; - } - - s->int_status |= new_status; - - if ((s->int_status & s->int_enable)) { - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - } -} - -static uint32_t goldfish_mmc_read(void *opaque, target_phys_addr_t offset) -{ - uint32_t ret; - struct goldfish_mmc_state *s = opaque; - - offset -= s->dev.base; - switch(offset) { - case MMC_INT_STATUS: - // return current buffer status flags - return s->int_status & s->int_enable; - case MMC_RESP_0: - return s->resp[0]; - case MMC_RESP_1: - return s->resp[1]; - case MMC_RESP_2: - return s->resp[2]; - case MMC_RESP_3: - return s->resp[3]; - case MMC_STATE: { - ret = MMC_STATE_INSERTED; - if (bdrv_is_read_only(s->bs)) { - ret |= MMC_STATE_READ_ONLY; - } - return ret; - } - default: - cpu_abort(cpu_single_env, "goldfish_mmc_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_mmc_write(void *opaque, target_phys_addr_t offset, uint32_t val) -{ - struct goldfish_mmc_state *s = opaque; - int status, old_status; - - offset -= s->dev.base; - - switch(offset) { - - case MMC_INT_STATUS: - status = s->int_status; - old_status = status; - status &= ~val; - s->int_status = status; - if(status != old_status) { - goldfish_device_set_irq(&s->dev, 0, status); - } - break; - - case MMC_INT_ENABLE: - /* enable buffer interrupts */ - s->int_enable = val; - s->int_status = 0; - goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); - break; - case MMC_SET_BUFFER: - /* save pointer to buffer 1 */ - s->buffer = phys_ram_base + val; - break; - case MMC_CMD: - goldfish_mmc_do_command(s, val, s->arg); - break; - case MMC_ARG: - s->arg = val; - break; - case MMC_BLOCK_LENGTH: - s->block_length = val + 1; - break; - case MMC_BLOCK_COUNT: - s->block_count = val + 1; - break; - - default: - cpu_abort (cpu_single_env, "goldfish_mmc_write: Bad offset %x\n", offset); - } -} - -static CPUReadMemoryFunc *goldfish_mmc_readfn[] = { - goldfish_mmc_read, - goldfish_mmc_read, - goldfish_mmc_read -}; - -static CPUWriteMemoryFunc *goldfish_mmc_writefn[] = { - goldfish_mmc_write, - goldfish_mmc_write, - goldfish_mmc_write -}; - -void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs) -{ - struct goldfish_mmc_state *s; - - s = (struct goldfish_mmc_state *)qemu_mallocz(sizeof(*s)); - s->dev.name = "goldfish_mmc"; - s->dev.id = id; - s->dev.base = base; - s->dev.size = 0x1000; - s->dev.irq_count = 1; - s->bs = bs; - - goldfish_device_add(&s->dev, goldfish_mmc_readfn, goldfish_mmc_writefn, s); - - register_savevm( "goldfish_mmc", 0, GOLDFISH_MMC_SAVE_VERSION, - goldfish_mmc_save, goldfish_mmc_load, s); -} - diff --git a/hw/goldfish_nand.c b/hw/goldfish_nand.c deleted file mode 100644 index 61b075e..0000000 --- a/hw/goldfish_nand.c +++ /dev/null @@ -1,636 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "goldfish_nand_reg.h" -#include "goldfish_nand.h" -#include "android/utils/tempfile.h" -#include "qemu_debug.h" -#include "android/android.h" - -#define DEBUG 1 -#if DEBUG -# define D(...) VERBOSE_PRINT(nand,__VA_ARGS__) -# define D_ACTIVE VERBOSE_CHECK(nand) -# define T(...) VERBOSE_PRINT(nand_limits,__VA_ARGS__) -# define T_ACTIVE VERBOSE_CHECK(nand_limits) -#else -# define D(...) ((void)0) -# define D_ACTIVE 0 -# define T(...) ((void)0) -# define T_ACTIVE 0 -#endif - -/* lseek uses 64-bit offsets on Darwin. */ -/* prefer lseek64 on Linux */ -#ifdef __APPLE__ -# define llseek lseek -#elif defined(__linux__) -# define llseek lseek64 -#endif - -#define XLOG xlog - -static void -xlog( const char* format, ... ) -{ - va_list args; - va_start(args, format); - fprintf(stderr, "NAND: "); - vfprintf(stderr, format, args); - va_end(args); -} - -typedef struct { - char* devname; - size_t devname_len; - char* data; - int fd; - uint32_t flags; - uint32_t page_size; - uint32_t extra_size; - uint32_t erase_size; - uint64_t size; -} nand_dev; - -nand_threshold android_nand_write_threshold; -nand_threshold android_nand_read_threshold; - -#ifdef CONFIG_NAND_THRESHOLD - -/* update a threshold, return 1 if limit is hit, 0 otherwise */ -static void -nand_threshold_update( nand_threshold* t, uint32_t len ) -{ - if (t->counter < t->limit) { - uint64_t avail = t->limit - t->counter; - if (avail > len) - avail = len; - - if (t->counter == 0) { - T("%s: starting threshold counting to %lld", - __FUNCTION__, t->limit); - } - t->counter += avail; - if (t->counter >= t->limit) { - /* threshold reach, send a signal to an external process */ - T( "%s: sending signal %d to pid %d !", - __FUNCTION__, t->signal, t->pid ); - - kill( t->pid, t->signal ); - } - } - return; -} - -#define NAND_UPDATE_READ_THRESHOLD(len) \ - nand_threshold_update( &android_nand_read_threshold, (uint32_t)(len) ) - -#define NAND_UPDATE_WRITE_THRESHOLD(len) \ - nand_threshold_update( &android_nand_write_threshold, (uint32_t)(len) ) - -#else /* !NAND_THRESHOLD */ - -#define NAND_UPDATE_READ_THRESHOLD(len) \ - do {} while (0) - -#define NAND_UPDATE_WRITE_THRESHOLD(len) \ - do {} while (0) - -#endif /* !NAND_THRESHOLD */ - -static nand_dev *nand_devs = NULL; -static uint32_t nand_dev_count = 0; - -typedef struct { - uint32_t base; - - // register state - uint32_t dev; - uint32_t addr_low; - uint32_t addr_high; - uint32_t transfer_size; - uint32_t data; - uint32_t result; -} nand_dev_state; - -/* update this everytime you change the nand_dev_state structure */ -#define NAND_DEV_STATE_SAVE_VERSION 1 - -#define QFIELD_STRUCT nand_dev_state -QFIELD_BEGIN(nand_dev_state_fields) - QFIELD_INT32(dev), - QFIELD_INT32(addr_low), - QFIELD_INT32(addr_high), - QFIELD_INT32(transfer_size), - QFIELD_INT32(data), - QFIELD_INT32(result), -QFIELD_END - -static void nand_dev_state_save(QEMUFile* f, void* opaque) -{ - nand_dev_state* s = opaque; - - qemu_put_struct(f, nand_dev_state_fields, s); -} - -static int nand_dev_state_load(QEMUFile* f, void* opaque, int version_id) -{ - nand_dev_state* s = opaque; - - if (version_id != NAND_DEV_STATE_SAVE_VERSION) - return -1; - - return qemu_get_struct(f, nand_dev_state_fields, s); -} - - -static int do_read(int fd, void* buf, size_t size) -{ - int ret; - do { - ret = read(fd, buf, size); - } while (ret < 0 && errno == EINTR); - - return ret; -} - -static int do_write(int fd, const void* buf, size_t size) -{ - int ret; - do { - ret = write(fd, buf, size); - } while (ret < 0 && errno == EINTR); - - return ret; -} - -static uint32_t nand_dev_read_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) -{ - uint32_t len = total_len; - size_t read_len = dev->erase_size; - int eof = 0; - - NAND_UPDATE_READ_THRESHOLD(total_len); - - lseek(dev->fd, addr, SEEK_SET); - while(len > 0) { - if(read_len < dev->erase_size) { - memset(dev->data, 0xff, dev->erase_size); - read_len = dev->erase_size; - eof = 1; - } - if(len < read_len) - read_len = len; - if(!eof) { - read_len = do_read(dev->fd, dev->data, read_len); - } - pmemcpy(data, dev->data, read_len); - data += read_len; - len -= read_len; - } - return total_len; -} - -static uint32_t nand_dev_write_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) -{ - uint32_t len = total_len; - size_t write_len = dev->erase_size; - int ret; - - NAND_UPDATE_WRITE_THRESHOLD(total_len); - - lseek(dev->fd, addr, SEEK_SET); - while(len > 0) { - if(len < write_len) - write_len = len; - vmemcpy(data, dev->data, write_len); - ret = do_write(dev->fd, dev->data, write_len); - if(ret < write_len) { - XLOG("nand_dev_write_file, write failed: %s\n", strerror(errno)); - break; - } - data += write_len; - len -= write_len; - } - return total_len - len; -} - -static uint32_t nand_dev_erase_file(nand_dev *dev, uint64_t addr, uint32_t total_len) -{ - uint32_t len = total_len; - size_t write_len = dev->erase_size; - int ret; - - lseek(dev->fd, addr, SEEK_SET); - memset(dev->data, 0xff, dev->erase_size); - while(len > 0) { - if(len < write_len) - write_len = len; - ret = do_write(dev->fd, dev->data, write_len); - if(ret < write_len) { - XLOG( "nand_dev_write_file, write failed: %s\n", strerror(errno)); - break; - } - len -= write_len; - } - return total_len - len; -} - -/* this is a huge hack required to make the PowerPC emulator binary usable - * on Mac OS X. If you define this function as 'static', the emulated kernel - * will panic when attempting to mount the /data partition. - * - * worse, if you do *not* define the function as static on Linux-x86, the - * emulated kernel will also panic !? - * - * I still wonder if this is a compiler bug, or due to some nasty thing the - * emulator does with CPU registers during execution of the translated code. - */ -#if !(defined __APPLE__ && defined __powerpc__) -static -#endif -uint32_t nand_dev_do_cmd(nand_dev_state *s, uint32_t cmd) -{ - uint32_t size; - uint64_t addr; - nand_dev *dev; - - addr = s->addr_low | ((uint64_t)s->addr_high << 32); - size = s->transfer_size; - if(s->dev >= nand_dev_count) - return 0; - dev = nand_devs + s->dev; - - switch(cmd) { - case NAND_CMD_GET_DEV_NAME: - if(size > dev->devname_len) - size = dev->devname_len; - pmemcpy(s->data, dev->devname, size); - return size; - case NAND_CMD_READ: - if(addr >= dev->size) - return 0; - if(size + addr > dev->size) - size = dev->size - addr; - if(dev->fd >= 0) - return nand_dev_read_file(dev, s->data, addr, size); - pmemcpy(s->data, &dev->data[addr], size); - return size; - case NAND_CMD_WRITE: - if(dev->flags & NAND_DEV_FLAG_READ_ONLY) - return 0; - if(addr >= dev->size) - return 0; - if(size + addr > dev->size) - size = dev->size - addr; - if(dev->fd >= 0) - return nand_dev_write_file(dev, s->data, addr, size); - vmemcpy(s->data, &dev->data[addr], size); - return size; - case NAND_CMD_ERASE: - if(dev->flags & NAND_DEV_FLAG_READ_ONLY) - return 0; - if(addr >= dev->size) - return 0; - if(size + addr > dev->size) - size = dev->size - addr; - if(dev->fd >= 0) - return nand_dev_erase_file(dev, addr, size); - memset(&dev->data[addr], 0xff, size); - return size; - case NAND_CMD_BLOCK_BAD_GET: // no bad block support - return 0; - case NAND_CMD_BLOCK_BAD_SET: - if(dev->flags & NAND_DEV_FLAG_READ_ONLY) - return 0; - return 0; - default: - cpu_abort(cpu_single_env, "nand_dev_do_cmd: Bad command %x\n", cmd); - return 0; - } -} - -/* I/O write */ -static void nand_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - nand_dev_state *s = (nand_dev_state *)opaque; - - offset -= s->base; - switch (offset) { - case NAND_DEV: - s->dev = value; - if(s->dev >= nand_dev_count) { - cpu_abort(cpu_single_env, "nand_dev_write: Bad dev %x\n", value); - } - break; - case NAND_ADDR_HIGH: - s->addr_high = value; - break; - case NAND_ADDR_LOW: - s->addr_low = value; - break; - case NAND_TRANSFER_SIZE: - s->transfer_size = value; - break; - case NAND_DATA: - s->data = value; - break; - case NAND_COMMAND: - s->result = nand_dev_do_cmd(s, value); - break; - default: - cpu_abort(cpu_single_env, "nand_dev_write: Bad offset %x\n", offset); - break; - } -} - -/* I/O read */ -static uint32_t nand_dev_read(void *opaque, target_phys_addr_t offset) -{ - nand_dev_state *s = (nand_dev_state *)opaque; - nand_dev *dev; - - offset -= s->base; - switch (offset) { - case NAND_VERSION: - return NAND_VERSION_CURRENT; - case NAND_NUM_DEV: - return nand_dev_count; - case NAND_RESULT: - return s->result; - } - - if(s->dev >= nand_dev_count) - return 0; - - dev = nand_devs + s->dev; - - switch (offset) { - case NAND_DEV_FLAGS: - return dev->flags; - - case NAND_DEV_NAME_LEN: - return dev->devname_len; - - case NAND_DEV_PAGE_SIZE: - return dev->page_size; - - case NAND_DEV_EXTRA_SIZE: - return dev->extra_size; - - case NAND_DEV_ERASE_SIZE: - return dev->erase_size; - - case NAND_DEV_SIZE_LOW: - return (uint32_t)dev->size; - - case NAND_DEV_SIZE_HIGH: - return (uint32_t)(dev->size >> 32); - - default: - cpu_abort(cpu_single_env, "nand_dev_read: Bad offset %x\n", offset); - return 0; - } -} - -static CPUReadMemoryFunc *nand_dev_readfn[] = { - nand_dev_read, - nand_dev_read, - nand_dev_read -}; - -static CPUWriteMemoryFunc *nand_dev_writefn[] = { - nand_dev_write, - nand_dev_write, - nand_dev_write -}; - -/* initialize the QFB device */ -void nand_dev_init(uint32_t base) -{ - int iomemtype; - static int instance_id = 0; - nand_dev_state *s; - - s = (nand_dev_state *)qemu_mallocz(sizeof(nand_dev_state)); - iomemtype = cpu_register_io_memory(0, nand_dev_readfn, nand_dev_writefn, s); - cpu_register_physical_memory(base, 0x00000fff, iomemtype); - s->base = base; - - register_savevm( "nand_dev", instance_id++, NAND_DEV_STATE_SAVE_VERSION, - nand_dev_state_save, nand_dev_state_load, s); -} - -static int arg_match(const char *a, const char *b, size_t b_len) -{ - while(*a && b_len--) { - if(*a++ != *b++) - return 0; - } - return b_len == 0; -} - -void nand_add_dev(const char *arg) -{ - uint64_t dev_size = 0; - const char *next_arg; - const char *value; - size_t arg_len, value_len; - nand_dev *new_devs, *dev; - char *devname = NULL; - size_t devname_len = 0; - char *initfilename = NULL; - char *rwfilename = NULL; - int initfd = -1; - int rwfd = -1; - int read_only = 0; - int pad; - ssize_t read_size; - uint32_t page_size = 2048; - uint32_t extra_size = 64; - uint32_t erase_pages = 64; - - while(arg) { - next_arg = strchr(arg, ','); - value = strchr(arg, '='); - if(next_arg != NULL) { - arg_len = next_arg - arg; - next_arg++; - if(value >= next_arg) - value = NULL; - } - else - arg_len = strlen(arg); - if(value != NULL) { - size_t new_arg_len = value - arg; - value_len = arg_len - new_arg_len - 1; - arg_len = new_arg_len; - value++; - } - else - value_len = 0; - - if(devname == NULL) { - if(value != NULL) - goto bad_arg_and_value; - devname_len = arg_len; - devname = malloc(arg_len); - if(devname == NULL) - goto out_of_memory; - memcpy(devname, arg, arg_len); - } - else if(value == NULL) { - if(arg_match("readonly", arg, arg_len)) { - read_only = 1; - } - else { - XLOG("bad arg: %.*s\n", arg_len, arg); - exit(1); - } - } - else { - if(arg_match("size", arg, arg_len)) { - char *ep; - dev_size = strtoull(value, &ep, 0); - if(ep != value + value_len) - goto bad_arg_and_value; - } - else if(arg_match("pagesize", arg, arg_len)) { - char *ep; - page_size = strtoul(value, &ep, 0); - if(ep != value + value_len) - goto bad_arg_and_value; - } - else if(arg_match("extrasize", arg, arg_len)) { - char *ep; - extra_size = strtoul(value, &ep, 0); - if(ep != value + value_len) - goto bad_arg_and_value; - } - else if(arg_match("erasepages", arg, arg_len)) { - char *ep; - erase_pages = strtoul(value, &ep, 0); - if(ep != value + value_len) - goto bad_arg_and_value; - } - else if(arg_match("initfile", arg, arg_len)) { - initfilename = malloc(value_len + 1); - if(initfilename == NULL) - goto out_of_memory; - memcpy(initfilename, value, value_len); - initfilename[value_len] = '\0'; - } - else if(arg_match("file", arg, arg_len)) { - rwfilename = malloc(value_len + 1); - if(rwfilename == NULL) - goto out_of_memory; - memcpy(rwfilename, value, value_len); - rwfilename[value_len] = '\0'; - } - else { - goto bad_arg_and_value; - } - } - - arg = next_arg; - } - - if (rwfilename == NULL) { - /* we create a temporary file to store everything */ - TempFile* tmp = tempfile_create(); - - if (tmp == NULL) { - XLOG("could not create temp file for %.*s NAND disk image: %s", - devname_len, devname, strerror(errno)); - exit(1); - } - rwfilename = (char*) tempfile_path(tmp); - if (VERBOSE_CHECK(init)) - dprint( "mapping '%.*s' NAND image to %s", devname_len, devname, rwfilename); - } - - if(rwfilename) { - rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR)); - if(rwfd < 0 && read_only) { - XLOG("could not open file %s, %s\n", rwfilename, strerror(errno)); - exit(1); - } - /* this could be a writable temporary file. use atexit_close_fd to ensure - * that it is properly cleaned up at exit on Win32 - */ - if (!read_only) - atexit_close_fd(rwfd); - } - - if(initfilename) { - initfd = open(initfilename, O_BINARY | O_RDONLY); - if(initfd < 0) { - XLOG("could not open file %s, %s\n", initfilename, strerror(errno)); - exit(1); - } - if(dev_size == 0) { - dev_size = lseek(initfd, 0, SEEK_END); - lseek(initfd, 0, SEEK_SET); - } - } - - new_devs = realloc(nand_devs, sizeof(nand_devs[0]) * (nand_dev_count + 1)); - if(new_devs == NULL) - goto out_of_memory; - nand_devs = new_devs; - dev = &new_devs[nand_dev_count]; - - dev->page_size = page_size; - dev->extra_size = extra_size; - dev->erase_size = erase_pages * (page_size + extra_size); - pad = dev_size % dev->erase_size; - if (pad != 0) { - dev_size += (dev->erase_size - pad); - XLOG("rounding devsize up to a full eraseunit, now %llx\n", dev_size); - } - dev->devname = devname; - dev->devname_len = devname_len; - dev->size = dev_size; - dev->data = malloc(dev->erase_size); - if(dev->data == NULL) - goto out_of_memory; - dev->flags = read_only ? NAND_DEV_FLAG_READ_ONLY : 0; - - if (initfd >= 0) { - do { - read_size = do_read(initfd, dev->data, dev->erase_size); - if(read_size < 0) { - XLOG("could not read file %s, %s\n", initfilename, strerror(errno)); - exit(1); - } - if(do_write(rwfd, dev->data, read_size) != read_size) { - XLOG("could not write file %s, %s\n", initfilename, strerror(errno)); - exit(1); - } - } while(read_size == dev->erase_size); - close(initfd); - } - dev->fd = rwfd; - - nand_dev_count++; - - return; - -out_of_memory: - XLOG("out of memory\n"); - exit(1); - -bad_arg_and_value: - XLOG("bad arg: %.*s=%.*s\n", arg_len, arg, value_len, value); - exit(1); -} - diff --git a/hw/goldfish_nand.h b/hw/goldfish_nand.h deleted file mode 100644 index dcc59d8..0000000 --- a/hw/goldfish_nand.h +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#ifndef NAND_DEVICE_H -#define NAND_DEVICE_H - -void nand_dev_init(uint32_t base); -void nand_add_dev(const char *arg); - -typedef struct { - uint64_t limit; - uint64_t counter; - int pid; - int signal; -} nand_threshold; - -extern nand_threshold android_nand_read_threshold; -extern nand_threshold android_nand_write_threshold; - -#endif diff --git a/hw/goldfish_nand_reg.h b/hw/goldfish_nand_reg.h deleted file mode 100644 index ea91461..0000000 --- a/hw/goldfish_nand_reg.h +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#ifndef NAND_DEVICE_REG_H -#define NAND_DEVICE_REG_H - -enum nand_cmd { - NAND_CMD_GET_DEV_NAME, // Write device name for NAND_DEV to NAND_DATA (vaddr) - NAND_CMD_READ, - NAND_CMD_WRITE, - NAND_CMD_ERASE, - NAND_CMD_BLOCK_BAD_GET, // NAND_RESULT is 1 if block is bad, 0 if it is not - NAND_CMD_BLOCK_BAD_SET -}; - -enum nand_dev_flags { - NAND_DEV_FLAG_READ_ONLY = 0x00000001 -}; - -#define NAND_VERSION_CURRENT (1) - -enum nand_reg { - // Global - NAND_VERSION = 0x000, - NAND_NUM_DEV = 0x004, - NAND_DEV = 0x008, - - // Dev info - NAND_DEV_FLAGS = 0x010, - NAND_DEV_NAME_LEN = 0x014, - NAND_DEV_PAGE_SIZE = 0x018, - NAND_DEV_EXTRA_SIZE = 0x01c, - NAND_DEV_ERASE_SIZE = 0x020, - NAND_DEV_SIZE_LOW = 0x028, - NAND_DEV_SIZE_HIGH = 0x02c, - - // Command - NAND_RESULT = 0x040, - NAND_COMMAND = 0x044, - NAND_DATA = 0x048, - NAND_TRANSFER_SIZE = 0x04c, - NAND_ADDR_LOW = 0x050, - NAND_ADDR_HIGH = 0x054, -}; - -#endif diff --git a/hw/goldfish_switch.c b/hw/goldfish_switch.c deleted file mode 100644 index 8a12d66..0000000 --- a/hw/goldfish_switch.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "goldfish_device.h" - -enum { - SW_NAME_LEN = 0x00, - SW_NAME_PTR = 0x04, - SW_FLAGS = 0x08, - SW_STATE = 0x0c, - SW_INT_STATUS = 0x10, - SW_INT_ENABLE = 0x14, - - SW_FLAGS_OUTPUT = 1U << 0 -}; - - -struct switch_state { - struct goldfish_device dev; - char *name; - uint32_t state; - uint32_t state_changed : 1; - uint32_t int_enable : 1; - uint32_t (*writefn)(void *opaque, uint32_t state); - void *writeopaque; -}; - -#define GOLDFISH_SWITCH_SAVE_VERSION 1 - -static void goldfish_switch_save(QEMUFile* f, void* opaque) -{ - struct switch_state* s = opaque; - - qemu_put_be32(f, s->state); - qemu_put_byte(f, s->state_changed); - qemu_put_byte(f, s->int_enable); -} - -static int goldfish_switch_load(QEMUFile* f, void* opaque, int version_id) -{ - struct switch_state* s = opaque; - - if (version_id != GOLDFISH_SWITCH_SAVE_VERSION) - return -1; - - s->state = qemu_get_be32(f); - s->state_changed = qemu_get_byte(f); - s->int_enable = qemu_get_byte(f); - - return 0; -} - -static uint32_t goldfish_switch_read(void *opaque, target_phys_addr_t offset) -{ - struct switch_state *s = (struct switch_state *)opaque; - offset -= s->dev.base; - - //printf("goldfish_switch_read %x %x\n", offset, size); - - switch (offset) { - case SW_NAME_LEN: - return strlen(s->name); - case SW_FLAGS: - return s->writefn ? SW_FLAGS_OUTPUT : 0; - case SW_STATE: - return s->state; - case SW_INT_STATUS: - if(s->state_changed && s->int_enable) { - s->state_changed = 0; - goldfish_device_set_irq(&s->dev, 0, 0); - return 1; - } - return 0; - default: - cpu_abort (cpu_single_env, "goldfish_switch_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_switch_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - struct switch_state *s = (struct switch_state *)opaque; - offset -= s->dev.base; - - //printf("goldfish_switch_read %x %x %x\n", offset, value, size); - - switch(offset) { - case SW_NAME_PTR: - pmemcpy(value, s->name, strlen(s->name)); - break; - - case SW_STATE: - if(s->writefn) { - uint32_t new_state; - new_state = s->writefn(s->writeopaque, value); - if(new_state != s->state) { - goldfish_switch_set_state(s, new_state); - } - } - else - cpu_abort (cpu_single_env, "goldfish_switch_write: write to SW_STATE on input\n"); - break; - - case SW_INT_ENABLE: - value &= 1; - if(s->state_changed && s->int_enable != value) - goldfish_device_set_irq(&s->dev, 0, value); - s->int_enable = value; - break; - - default: - cpu_abort (cpu_single_env, "goldfish_switch_write: Bad offset %x\n", offset); - } -} - -static CPUReadMemoryFunc *goldfish_switch_readfn[] = { - goldfish_switch_read, - goldfish_switch_read, - goldfish_switch_read -}; - -static CPUWriteMemoryFunc *goldfish_switch_writefn[] = { - goldfish_switch_write, - goldfish_switch_write, - goldfish_switch_write -}; - -void goldfish_switch_set_state(void *opaque, uint32_t state) -{ - struct switch_state *s = opaque; - s->state_changed = 1; - s->state = state; - if(s->int_enable) - goldfish_device_set_irq(&s->dev, 0, 1); -} - -void *goldfish_switch_add(char *name, uint32_t (*writefn)(void *opaque, uint32_t state), void *writeopaque, int id) -{ - int ret; - struct switch_state *s; - - s = qemu_mallocz(sizeof(*s)); - s->dev.name = "goldfish-switch"; - s->dev.id = id; - s->dev.size = 0x1000; - s->dev.irq_count = 1; - s->name = name; - s->writefn = writefn; - s->writeopaque = writeopaque; - - - ret = goldfish_device_add(&s->dev, goldfish_switch_readfn, goldfish_switch_writefn, s); - if(ret) { - qemu_free(s); - return NULL; - } - - register_savevm( "goldfish_switch", 0, GOLDFISH_SWITCH_SAVE_VERSION, - goldfish_switch_save, goldfish_switch_load, s); - - return s; -} - diff --git a/hw/goldfish_timer.c b/hw/goldfish_timer.c deleted file mode 100644 index 73f1455..0000000 --- a/hw/goldfish_timer.c +++ /dev/null @@ -1,256 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu-timer.h" -#include "cpu.h" -#include "arm_pic.h" -#include "goldfish_device.h" - -enum { - TIMER_TIME_LOW = 0x00, // get low bits of current time and update TIMER_TIME_HIGH - TIMER_TIME_HIGH = 0x04, // get high bits of time at last TIMER_TIME_LOW read - TIMER_ALARM_LOW = 0x08, // set low bits of alarm and activate it - TIMER_ALARM_HIGH = 0x0c, // set high bits of next alarm - TIMER_CLEAR_INTERRUPT = 0x10, - TIMER_CLEAR_ALARM = 0x14 -}; - -struct timer_state { - struct goldfish_device dev; - uint32_t alarm_low; - int32_t alarm_high; - int64_t now; - int armed; - QEMUTimer *timer; -}; - -#define GOLDFISH_TIMER_SAVE_VERSION 1 - -static void goldfish_timer_save(QEMUFile* f, void* opaque) -{ - struct timer_state* s = opaque; - - qemu_put_be64(f, s->now); /* in case the kernel is in the middle of a timer read */ - qemu_put_byte(f, s->armed); - if (s->armed) { - int64_t now = qemu_get_clock(vm_clock); - int64_t alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000); - qemu_put_be64(f, alarm-now); - } -} - -static int goldfish_timer_load(QEMUFile* f, void* opaque, int version_id) -{ - struct timer_state* s = opaque; - - if (version_id != GOLDFISH_TIMER_SAVE_VERSION) - return -1; - - s->now = qemu_get_be64(f); - s->armed = qemu_get_byte(f); - if (s->armed) { - int64_t now = qemu_get_clock(vm_clock); - int64_t diff = qemu_get_be64(f); - int64_t alarm = now + diff; - - if (alarm <= now) { - goldfish_device_set_irq(&s->dev, 0, 1); - s->armed = 0; - } else { - qemu_mod_timer(s->timer, alarm); - } - } - return 0; -} - -static uint32_t goldfish_timer_read(void *opaque, target_phys_addr_t offset) -{ - struct timer_state *s = (struct timer_state *)opaque; - offset -= s->dev.base; - switch(offset) { - case TIMER_TIME_LOW: - s->now = muldiv64(qemu_get_clock(vm_clock), 1000000000, ticks_per_sec); - return s->now; - case TIMER_TIME_HIGH: - return s->now >> 32; - default: - cpu_abort (cpu_single_env, "goldfish_timer_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_timer_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - struct timer_state *s = (struct timer_state *)opaque; - int64_t alarm, now; - offset -= s->dev.base; - switch(offset) { - case TIMER_ALARM_LOW: - s->alarm_low = value; - alarm = muldiv64(s->alarm_low | (int64_t)s->alarm_high << 32, ticks_per_sec, 1000000000); - now = qemu_get_clock(vm_clock); - if (alarm <= now) { - goldfish_device_set_irq(&s->dev, 0, 1); - } else { - qemu_mod_timer(s->timer, alarm); - s->armed = 1; - } - break; - case TIMER_ALARM_HIGH: - s->alarm_high = value; - //printf("alarm_high %d\n", s->alarm_high); - break; - case TIMER_CLEAR_ALARM: - qemu_del_timer(s->timer); - s->armed = 0; - /* fall through */ - case TIMER_CLEAR_INTERRUPT: - goldfish_device_set_irq(&s->dev, 0, 0); - break; - default: - cpu_abort (cpu_single_env, "goldfish_timer_write: Bad offset %x\n", offset); - } -} - -static void goldfish_timer_tick(void *opaque) -{ - struct timer_state *s = (struct timer_state *)opaque; - - s->armed = 0; - goldfish_device_set_irq(&s->dev, 0, 1); -} - -struct rtc_state { - struct goldfish_device dev; - uint32_t alarm_low; - int32_t alarm_high; - int64_t now; -}; - -/* we save the RTC for the case where the kernel is in the middle of a rtc_read - * (i.e. it has read the low 32-bit of s->now, but not the high 32-bits yet */ -#define GOLDFISH_RTC_SAVE_VERSION 1 - -static void goldfish_rtc_save(QEMUFile* f, void* opaque) -{ - struct rtc_state* s = opaque; - - qemu_put_be64(f, s->now); -} - -static int goldfish_rtc_load(QEMUFile* f, void* opaque, int version_id) -{ - struct rtc_state* s = opaque; - - if (version_id != GOLDFISH_RTC_SAVE_VERSION) - return -1; - - /* this is an old value that is not correct. but that's ok anyway */ - s->now = qemu_get_be64(f); - return 0; -} - -static uint32_t goldfish_rtc_read(void *opaque, target_phys_addr_t offset) -{ - struct rtc_state *s = (struct rtc_state *)opaque; - offset -= s->dev.base; - switch(offset) { - case 0x0: - s->now = (int64_t)time(NULL) * 1000000000; - return s->now; - case 0x4: - return s->now >> 32; - default: - cpu_abort (cpu_single_env, "goldfish_rtc_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_rtc_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - struct rtc_state *s = (struct rtc_state *)opaque; - int64_t alarm; - offset -= s->dev.base; - switch(offset) { - case 0x8: - s->alarm_low = value; - alarm = s->alarm_low | (int64_t)s->alarm_high << 32; - //printf("next alarm at %lld, tps %lld\n", alarm, ticks_per_sec); - //qemu_mod_timer(s->timer, alarm); - break; - case 0xc: - s->alarm_high = value; - //printf("alarm_high %d\n", s->alarm_high); - break; - case 0x10: - goldfish_device_set_irq(&s->dev, 0, 0); - break; - default: - cpu_abort (cpu_single_env, "goldfish_rtc_write: Bad offset %x\n", offset); - } -} - -static struct timer_state timer_state = { - .dev = { - .name = "goldfish_timer", - .id = -1, - .size = 0x1000, - .irq_count = 1, - } -}; - -static struct timer_state rtc_state = { - .dev = { - .name = "goldfish_rtc", - .id = -1, - .size = 0x1000, - .irq_count = 1, - } -}; - -static CPUReadMemoryFunc *goldfish_timer_readfn[] = { - goldfish_timer_read, - goldfish_timer_read, - goldfish_timer_read -}; - -static CPUWriteMemoryFunc *goldfish_timer_writefn[] = { - goldfish_timer_write, - goldfish_timer_write, - goldfish_timer_write -}; - -static CPUReadMemoryFunc *goldfish_rtc_readfn[] = { - goldfish_rtc_read, - goldfish_rtc_read, - goldfish_rtc_read -}; - -static CPUWriteMemoryFunc *goldfish_rtc_writefn[] = { - goldfish_rtc_write, - goldfish_rtc_write, - goldfish_rtc_write -}; - -void goldfish_timer_and_rtc_init(uint32_t timerbase, int timerirq) -{ - timer_state.dev.base = timerbase; - timer_state.dev.irq = timerirq; - timer_state.timer = qemu_new_timer(vm_clock, goldfish_timer_tick, &timer_state); - goldfish_device_add(&timer_state.dev, goldfish_timer_readfn, goldfish_timer_writefn, &timer_state); - register_savevm( "goldfish_timer", 0, GOLDFISH_TIMER_SAVE_VERSION, - goldfish_timer_save, goldfish_timer_load, &timer_state); - - goldfish_device_add(&rtc_state.dev, goldfish_rtc_readfn, goldfish_rtc_writefn, &rtc_state); - register_savevm( "goldfish_rtc", 0, GOLDFISH_RTC_SAVE_VERSION, - goldfish_rtc_save, goldfish_rtc_load, &rtc_state); -} - diff --git a/hw/goldfish_trace.c b/hw/goldfish_trace.c deleted file mode 100644 index ad0eba5..0000000 --- a/hw/goldfish_trace.c +++ /dev/null @@ -1,251 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -/* - * Virtual hardware for bridging the FUSE kernel module - * in the emulated OS and outside file system - */ -#include "qemu_file.h" -#include "goldfish_trace.h" - -//#define DEBUG 1 - -extern void cpu_loop_exit(void); - -extern int tracing; - -/* for execve */ -static char path[CLIENT_PAGE_SIZE]; -static char arg[CLIENT_PAGE_SIZE]; -static unsigned long vstart; // VM start -static unsigned long vend; // VM end -static unsigned long eoff; // offset in EXE file -static unsigned cmdlen; // cmdline length -static unsigned pid; // PID (really thread id) -static unsigned tgid; // thread group id (really process id) -static unsigned long dsaddr; // dynamic symbol address -static unsigned long unmap_start; // start address to unmap - -/* for context switch */ -//static unsigned long cs_pid; // context switch PID - -/* I/O write */ -static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - trace_dev_state *s = (trace_dev_state *)opaque; - - offset -= s->base; - switch (offset >> 2) { - case TRACE_DEV_REG_SWITCH: // context switch, switch to pid - trace_switch(value); -#ifdef DEBUG - printf("QEMU.trace: kernel, context switch %u\n", value); -#endif - break; - case TRACE_DEV_REG_TGID: // save the tgid for the following fork/clone - tgid = value; -#ifdef DEBUG - printf("QEMU.trace: kernel, tgid %u\n", value); -#endif - break; - case TRACE_DEV_REG_FORK: // fork, fork new pid - trace_fork(tgid, value); -#ifdef DEBUG - printf("QEMU.trace: kernel, fork %u\n", value); -#endif - break; - case TRACE_DEV_REG_CLONE: // fork, clone new pid (i.e. thread) - trace_clone(tgid, value); -#ifdef DEBUG - printf("QEMU.trace: kernel, clone %u\n", value); -#endif - break; - case TRACE_DEV_REG_EXECVE_VMSTART: // execve, vstart - vstart = value; - break; - case TRACE_DEV_REG_EXECVE_VMEND: // execve, vend - vend = value; - break; - case TRACE_DEV_REG_EXECVE_OFFSET: // execve, offset in EXE - eoff = value; - break; - case TRACE_DEV_REG_EXECVE_EXEPATH: // init exec, path of EXE - vstrcpy(value, path, CLIENT_PAGE_SIZE); - trace_init_exec(vstart, vend, eoff, path); -#ifdef DEBUG - printf("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, path); -#endif - path[0] = 0; - break; - case TRACE_DEV_REG_CMDLINE_LEN: // execve, process cmdline length - cmdlen = value; - break; - case TRACE_DEV_REG_CMDLINE: // execve, process cmdline - vmemcpy(value, arg, cmdlen); - trace_execve(arg, cmdlen); -#ifdef DEBUG - { - int i; - for (i = 0; i < cmdlen; i ++) - if (i != cmdlen - 1 && arg[i] == 0) - arg[i] = ' '; - printf("QEMU.trace: kernel, execve %s[%d]\n", arg, cmdlen); - } -#endif - arg[0] = 0; - break; - case TRACE_DEV_REG_EXIT: // exit, exit current process with exit code - trace_exit(value); -#ifdef DEBUG - printf("QEMU.trace: kernel, exit %x\n", value); -#endif - break; - case TRACE_DEV_REG_NAME: // record thread name - vstrcpy(value, path, CLIENT_PAGE_SIZE); - - // Remove the trailing newline if it exists - int len = strlen(path); - if (path[len - 1] == '\n') { - path[len - 1] = 0; - } - trace_name(path); -#ifdef DEBUG - printf("QEMU.trace: kernel, name %s\n", path); -#endif - break; - case TRACE_DEV_REG_MMAP_EXEPATH: // mmap, path of EXE, the others are same as execve - vstrcpy(value, path, CLIENT_PAGE_SIZE); - trace_mmap(vstart, vend, eoff, path); -#ifdef DEBUG - printf("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, path); -#endif - path[0] = 0; - break; - case TRACE_DEV_REG_INIT_PID: // init, name the pid that starts before device registered - pid = value; - break; - case TRACE_DEV_REG_INIT_NAME: // init, the comm of the init pid - vstrcpy(value, path, CLIENT_PAGE_SIZE); - trace_init_name(tgid, pid, path); -#ifdef DEBUG - printf("QEMU.trace: kernel, init name %u [%s]\n", pid, path); -#endif - path[0] = 0; - break; - - case TRACE_DEV_REG_DYN_SYM_ADDR: // dynamic symbol address - dsaddr = value; - break; - case TRACE_DEV_REG_DYN_SYM: // add dynamic symbol - vstrcpy(value, arg, CLIENT_PAGE_SIZE); - trace_dynamic_symbol_add(dsaddr, arg); -#ifdef DEBUG - printf("QEMU.trace: dynamic symbol %lx:%s\n", dsaddr, arg); -#endif - arg[0] = 0; - break; - case TRACE_DEV_REG_REMOVE_ADDR: // remove dynamic symbol addr - trace_dynamic_symbol_remove(value); -#ifdef DEBUG - printf("QEMU.trace: dynamic symbol remove %lx\n", dsaddr); -#endif - arg[0] = 0; - break; - - case TRACE_DEV_REG_PRINT_STR: // print string - vstrcpy(value, arg, CLIENT_PAGE_SIZE); - printf("%s", arg); - arg[0] = 0; - break; - case TRACE_DEV_REG_PRINT_NUM_DEC: // print number in decimal - printf("%d", value); - break; - case TRACE_DEV_REG_PRINT_NUM_HEX: // print number in hexical - printf("%x", value); - break; - - case TRACE_DEV_REG_STOP_EMU: // stop the VM execution - // To ensure that the number of instructions executed in this - // block is correct, we pretend that there was an exception. - trace_exception(0); - - cpu_single_env->exception_index = EXCP_HLT; - cpu_single_env->halted = 1; - qemu_system_shutdown_request(); - cpu_loop_exit(); - break; - - case TRACE_DEV_REG_ENABLE: // tracing enable: 0 = stop, 1 = start - if (value == 1) - start_tracing(); - else if (value == 0) { - stop_tracing(); - - // To ensure that the number of instructions executed in this - // block is correct, we pretend that there was an exception. - trace_exception(0); - } - break; - - case TRACE_DEV_REG_UNMAP_START: - unmap_start = value; - break; - case TRACE_DEV_REG_UNMAP_END: - trace_munmap(unmap_start, value); - break; - - default: - cpu_abort(cpu_single_env, "trace_dev_write: Bad offset %x\n", offset); - break; - } -} - -/* I/O read */ -static uint32_t trace_dev_read(void *opaque, target_phys_addr_t offset) -{ - trace_dev_state *s = (trace_dev_state *)opaque; - - offset -= s->base; - switch (offset >> 2) { - case TRACE_DEV_REG_ENABLE: // tracing enable - return tracing; - default: - cpu_abort(cpu_single_env, "trace_dev_read: Bad offset %x\n", offset); - return 0; - } - return 0; -} - -static CPUReadMemoryFunc *trace_dev_readfn[] = { - trace_dev_read, - trace_dev_read, - trace_dev_read -}; - -static CPUWriteMemoryFunc *trace_dev_writefn[] = { - trace_dev_write, - trace_dev_write, - trace_dev_write -}; - -/* initialize the trace device */ -void trace_dev_init(uint32_t base) -{ - int iomemtype; - trace_dev_state *s; - - s = (trace_dev_state *)qemu_mallocz(sizeof(trace_dev_state)); - iomemtype = cpu_register_io_memory(0, trace_dev_readfn, trace_dev_writefn, s); - cpu_register_physical_memory(base, 0x00000fff, iomemtype); - s->base = base; - - path[0] = arg[0] = '\0'; -} diff --git a/hw/goldfish_trace.h b/hw/goldfish_trace.h deleted file mode 100644 index 44190ee..0000000 --- a/hw/goldfish_trace.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#ifndef _TRACE_DEV_H_ -#define _TRACE_DEV_H_ - -#define CLIENT_PAGE_SIZE 4096 - -/* trace device registers */ -#define TRACE_DEV_REG_SWITCH 0 -#define TRACE_DEV_REG_FORK 1 -#define TRACE_DEV_REG_EXECVE_PID 2 -#define TRACE_DEV_REG_EXECVE_VMSTART 3 -#define TRACE_DEV_REG_EXECVE_VMEND 4 -#define TRACE_DEV_REG_EXECVE_OFFSET 5 -#define TRACE_DEV_REG_EXECVE_EXEPATH 6 -#define TRACE_DEV_REG_EXIT 7 -#define TRACE_DEV_REG_CMDLINE 8 -#define TRACE_DEV_REG_CMDLINE_LEN 9 -#define TRACE_DEV_REG_MMAP_EXEPATH 10 -#define TRACE_DEV_REG_INIT_PID 11 -#define TRACE_DEV_REG_INIT_NAME 12 -#define TRACE_DEV_REG_CLONE 13 -#define TRACE_DEV_REG_UNMAP_START 14 -#define TRACE_DEV_REG_UNMAP_END 15 -#define TRACE_DEV_REG_NAME 16 -#define TRACE_DEV_REG_TGID 17 -#define TRACE_DEV_REG_DYN_SYM 50 -#define TRACE_DEV_REG_DYN_SYM_ADDR 51 -#define TRACE_DEV_REG_REMOVE_ADDR 52 -#define TRACE_DEV_REG_PRINT_STR 60 -#define TRACE_DEV_REG_PRINT_NUM_DEC 61 -#define TRACE_DEV_REG_PRINT_NUM_HEX 62 -#define TRACE_DEV_REG_STOP_EMU 90 -#define TRACE_DEV_REG_ENABLE 100 - -/* the virtual trace device state */ -typedef struct { - uint32_t base; -} trace_dev_state; - -/* - * interfaces for copy from virtual space - * from target-arm/op_helper.c - */ -extern target_phys_addr_t v2p(target_ulong ptr, int is_user); -extern void vmemcpy(target_ulong ptr, char *buf, int size); -extern void pmemcpy(target_ulong ptr, const char* buf, int size); -extern void vstrcpy(target_ulong ptr, char *buf, int max); - -/* - * interfaces to trace module to signal kernel events - */ -extern void trace_switch(int pid); -extern void trace_fork(int tgid, int pid); -extern void trace_clone(int tgid, int pid); -extern void trace_execve(const char *arg, int len); -extern void trace_exit(int exitcode); -extern void trace_mmap(unsigned long vstart, unsigned long vend, - unsigned long offset, const char *path); -extern void trace_munmap(unsigned long vstart, unsigned long vend); -extern void trace_dynamic_symbol_add(unsigned long vaddr, const char *name); -extern void trace_dynamic_symbol_remove(unsigned long vaddr); -extern void trace_init_name(int tgid, int pid, const char *name); -extern void trace_init_exec(unsigned long start, unsigned long end, - unsigned long offset, const char *exe); -extern void start_tracing(void); -extern void stop_tracing(void); -extern void trace_exception(uint32 target_pc); - -#endif diff --git a/hw/goldfish_tty.c b/hw/goldfish_tty.c deleted file mode 100644 index aa62d75..0000000 --- a/hw/goldfish_tty.c +++ /dev/null @@ -1,226 +0,0 @@ -/* Copyright (C) 2007-2008 The Android Open Source Project -** -** This software is licensed under the terms of the GNU General Public -** License version 2, as published by the Free Software Foundation, and -** may be copied, distributed, and modified under those terms. -** -** 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. -*/ -#include "qemu_file.h" -#include "qemu-char.h" -#include "goldfish_device.h" - -enum { - TTY_PUT_CHAR = 0x00, - TTY_BYTES_READY = 0x04, - TTY_CMD = 0x08, - - TTY_DATA_PTR = 0x10, - TTY_DATA_LEN = 0x14, - - TTY_CMD_INT_DISABLE = 0, - TTY_CMD_INT_ENABLE = 1, - TTY_CMD_WRITE_BUFFER = 2, - TTY_CMD_READ_BUFFER = 3, -}; - -struct tty_state { - struct goldfish_device dev; - CharDriverState *cs; - uint32_t ptr; - uint32_t ptr_len; - uint32_t ready; - uint8_t data[128]; - uint32_t data_count; -}; - -#define GOLDFISH_TTY_SAVE_VERSION 1 - -static void goldfish_tty_save(QEMUFile* f, void* opaque) -{ - struct tty_state* s = opaque; - - qemu_put_be32( f, s->ptr ); - qemu_put_be32( f, s->ptr_len ); - qemu_put_byte( f, s->ready ); - qemu_put_byte( f, s->data_count ); - qemu_put_buffer( f, s->data, s->data_count ); -} - -static int goldfish_tty_load(QEMUFile* f, void* opaque, int version_id) -{ - struct tty_state* s = opaque; - - if (version_id != GOLDFISH_TTY_SAVE_VERSION) - return -1; - - s->ptr = qemu_get_be32(f); - s->ptr_len = qemu_get_be32(f); - s->ready = qemu_get_byte(f); - s->data_count = qemu_get_byte(f); - qemu_get_buffer(f, s->data, s->data_count); - - return 0; -} - -static uint32_t goldfish_tty_read(void *opaque, target_phys_addr_t offset) -{ - struct tty_state *s = (struct tty_state *)opaque; - offset -= s->dev.base; - - //printf("goldfish_tty_read %x %x\n", offset, size); - - switch (offset) { - case TTY_BYTES_READY: - return s->data_count; - default: - cpu_abort (cpu_single_env, "goldfish_tty_read: Bad offset %x\n", offset); - return 0; - } -} - -static void goldfish_tty_write(void *opaque, target_phys_addr_t offset, uint32_t value) -{ - struct tty_state *s = (struct tty_state *)opaque; - offset -= s->dev.base; - - //printf("goldfish_tty_read %x %x %x\n", offset, value, size); - - switch(offset) { - case TTY_PUT_CHAR: { - uint8_t ch = value; - if(s->cs) - qemu_chr_write(s->cs, &ch, 1); - } break; - - case TTY_CMD: - switch(value) { - case TTY_CMD_INT_DISABLE: - if(s->ready) { - if(s->data_count > 0) - goldfish_device_set_irq(&s->dev, 0, 0); - s->ready = 0; - } - break; - - case TTY_CMD_INT_ENABLE: - if(!s->ready) { - if(s->data_count > 0) - goldfish_device_set_irq(&s->dev, 0, 1); - s->ready = 1; - } - break; - - case TTY_CMD_WRITE_BUFFER: - if(s->cs) { - int len; - target_ulong buf; - - buf = s->ptr; - len = s->ptr_len; - - while(len) { - int page_remain = TARGET_PAGE_SIZE - (buf & ~TARGET_PAGE_MASK); - int to_write = len; - uint8_t *phys = (uint8_t *)v2p(buf, 0); - if(to_write > page_remain) - to_write = page_remain; - qemu_chr_write(s->cs, phys, to_write); - buf += to_write; - len -= to_write; - } - //printf("goldfish_tty_write: got %d bytes from %x\n", s->ptr_len, s->ptr); - } - break; - - case TTY_CMD_READ_BUFFER: - if(s->ptr_len > s->data_count) - cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count); - pmemcpy(s->ptr, s->data, s->ptr_len); - //printf("goldfish_tty_write: read %d bytes to %x\n", s->ptr_len, s->ptr); - if(s->data_count > s->ptr_len) - memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len); - s->data_count -= s->ptr_len; - if(s->data_count == 0 && s->ready) - goldfish_device_set_irq(&s->dev, 0, 0); - break; - - default: - cpu_abort (cpu_single_env, "goldfish_tty_write: Bad command %x\n", value); - }; - break; - - case TTY_DATA_PTR: - s->ptr = value; - break; - - case TTY_DATA_LEN: - s->ptr_len = value; - break; - - default: - cpu_abort (cpu_single_env, "goldfish_tty_write: Bad offset %x\n", offset); - } -} - -static int tty_can_receive(void *opaque) -{ - struct tty_state *s = opaque; - - return (sizeof(s->data) - s->data_count); -} - -static void tty_receive(void *opaque, const uint8_t *buf, int size) -{ - struct tty_state *s = opaque; - - memcpy(s->data + s->data_count, buf, size); - s->data_count += size; - if(s->data_count > 0 && s->ready) - goldfish_device_set_irq(&s->dev, 0, 1); -} - -static CPUReadMemoryFunc *goldfish_tty_readfn[] = { - goldfish_tty_read, - goldfish_tty_read, - goldfish_tty_read -}; - -static CPUWriteMemoryFunc *goldfish_tty_writefn[] = { - goldfish_tty_write, - goldfish_tty_write, - goldfish_tty_write -}; - -int goldfish_tty_add(CharDriverState *cs, int id, uint32_t base, int irq) -{ - int ret; - struct tty_state *s; - static int instance_id = 0; - - s = qemu_mallocz(sizeof(*s)); - s->dev.name = "goldfish_tty"; - s->dev.id = id; - s->dev.base = base; - s->dev.size = 0x1000; - s->dev.irq = irq; - s->dev.irq_count = 1; - s->cs = cs; - - if(cs) { - qemu_chr_add_handlers(cs, tty_can_receive, tty_receive, NULL, s); - } - - ret = goldfish_device_add(&s->dev, goldfish_tty_readfn, goldfish_tty_writefn, s); - if(ret) { - qemu_free(s); - } else { - register_savevm( "goldfish_tty", instance_id++, GOLDFISH_TTY_SAVE_VERSION, - goldfish_tty_save, goldfish_tty_load, s); - } - return ret; -} - diff --git a/hw/hw.h b/hw/hw.h deleted file mode 100644 index 06e24cb..0000000 --- a/hw/hw.h +++ /dev/null @@ -1,110 +0,0 @@ -/* Declarations for use by hardware emulation. */ -#ifndef QEMU_HW_H -#define QEMU_HW_H - -#include "qemu-common.h" -#include "irq.h" -#include "cpu.h" - -/* VM Load/Save */ - -QEMUFile *qemu_fopen(const char *filename, const char *mode); -void qemu_fflush(QEMUFile *f); -void qemu_fclose(QEMUFile *f); -void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); -void qemu_put_byte(QEMUFile *f, int v); -void qemu_put_be16(QEMUFile *f, unsigned int v); -void qemu_put_be32(QEMUFile *f, unsigned int v); -void qemu_put_be64(QEMUFile *f, uint64_t v); -int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size); -int qemu_get_byte(QEMUFile *f); -unsigned int qemu_get_be16(QEMUFile *f); -unsigned int qemu_get_be32(QEMUFile *f); -uint64_t qemu_get_be64(QEMUFile *f); - -static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) -{ - qemu_put_be64(f, *pv); -} - -static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv) -{ - qemu_put_be32(f, *pv); -} - -static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv) -{ - qemu_put_be16(f, *pv); -} - -static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv) -{ - qemu_put_byte(f, *pv); -} - -static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv) -{ - *pv = qemu_get_be64(f); -} - -static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv) -{ - *pv = qemu_get_be32(f); -} - -static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv) -{ - *pv = qemu_get_be16(f); -} - -static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv) -{ - *pv = qemu_get_byte(f); -} - -#ifdef NEED_CPU_H -#if TARGET_LONG_BITS == 64 -#define qemu_put_betl qemu_put_be64 -#define qemu_get_betl qemu_get_be64 -#define qemu_put_betls qemu_put_be64s -#define qemu_get_betls qemu_get_be64s -#else -#define qemu_put_betl qemu_put_be32 -#define qemu_get_betl qemu_get_be32 -#define qemu_put_betls qemu_put_be32s -#define qemu_get_betls qemu_get_be32s -#endif -#endif - -int64_t qemu_ftell(QEMUFile *f); -int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence); - -typedef void SaveStateHandler(QEMUFile *f, void *opaque); -typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); - -int register_savevm(const char *idstr, - int instance_id, - int version_id, - SaveStateHandler *save_state, - LoadStateHandler *load_state, - void *opaque); - -typedef void QEMUResetHandler(void *opaque); - -void qemu_register_reset(QEMUResetHandler *func, void *opaque); - -/* handler to set the boot_device for a specific type of QEMUMachine */ -/* return 0 if success */ -typedef int QEMUBootSetHandler(const char *boot_device); -extern QEMUBootSetHandler *qemu_boot_set_handler; -void qemu_register_boot_set(QEMUBootSetHandler *func); - -/* These should really be in isa.h, but are here to make pc.h happy. */ -typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); -typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); - - -/* ANDROID: copy memory from the QEMU buffer to simulated virtual space */ -extern void pmemcpy(target_ulong ptr, const char *buf, int size); - -#endif diff --git a/hw/irq.c b/hw/irq.c deleted file mode 100644 index eca707d..0000000 --- a/hw/irq.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * QEMU IRQ/GPIO common code. - * - * Copyright (c) 2007 CodeSourcery. - * - * 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 "qemu-common.h" -#include "irq.h" - -struct IRQState { - qemu_irq_handler handler; - void *opaque; - int n; -}; - -void qemu_set_irq(qemu_irq irq, int level) -{ - if (!irq) - return; - - irq->handler(irq->opaque, irq->n, level); -} - -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n) -{ - qemu_irq *s; - struct IRQState *p; - int i; - - s = (qemu_irq *)qemu_mallocz(sizeof(qemu_irq) * n); - p = (struct IRQState *)qemu_mallocz(sizeof(struct IRQState) * n); - for (i = 0; i < n; i++) { - p->handler = handler; - p->opaque = opaque; - p->n = i; - s[i] = p; - p++; - } - return s; -} - -static void qemu_notirq(void *opaque, int line, int level) -{ - struct IRQState *irq = opaque; - - irq->handler(irq->opaque, irq->n, !level); -} - -qemu_irq qemu_irq_invert(qemu_irq irq) -{ - /* The default state for IRQs is low, so raise the output now. */ - qemu_irq_raise(irq); - return qemu_allocate_irqs(qemu_notirq, irq, 1)[0]; -} diff --git a/hw/irq.h b/hw/irq.h deleted file mode 100644 index 0880ad2..0000000 --- a/hw/irq.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef QEMU_IRQ_H -#define QEMU_IRQ_H - -/* Generic IRQ/GPIO pin infrastructure. */ - -/* FIXME: Rmove one of these. */ -typedef void (*qemu_irq_handler)(void *opaque, int n, int level); -typedef void SetIRQFunc(void *opaque, int irq_num, int level); - -void qemu_set_irq(qemu_irq irq, int level); - -static inline void qemu_irq_raise(qemu_irq irq) -{ - qemu_set_irq(irq, 1); -} - -static inline void qemu_irq_lower(qemu_irq irq) -{ - qemu_set_irq(irq, 0); -} - -static inline void qemu_irq_pulse(qemu_irq irq) -{ - qemu_set_irq(irq, 1); - qemu_set_irq(irq, 0); -} - -/* Returns an array of N IRQs. */ -qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n); - -/* Returns a new IRQ with opposite polarity. */ -qemu_irq qemu_irq_invert(qemu_irq irq); - -#endif diff --git a/hw/isa.h b/hw/isa.h deleted file mode 100644 index 222e4f3..0000000 --- a/hw/isa.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef HW_ISA_H -#define HW_ISA_H -/* ISA bus */ - -extern target_phys_addr_t isa_mem_base; - -int register_ioport_read(int start, int length, int size, - IOPortReadFunc *func, void *opaque); -int register_ioport_write(int start, int length, int size, - IOPortWriteFunc *func, void *opaque); -void isa_unassign_ioport(int start, int length); - -void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size); - -/* dma.c */ -int DMA_get_channel_mode (int nchan); -int DMA_read_memory (int nchan, void *buf, int pos, int size); -int DMA_write_memory (int nchan, void *buf, int pos, int size); -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); -#endif diff --git a/hw/mmc.h b/hw/mmc.h deleted file mode 100644 index 3ae3ea9..0000000 --- a/hw/mmc.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Header for MultiMediaCard (MMC) - * - * Copyright 2002 Hewlett-Packard Company - * - * Use consistent with the GNU GPL is permitted, - * provided that this copyright notice is - * preserved in its entirety in all copies and derived works. - * - * HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED, - * AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS - * FITNESS FOR ANY PARTICULAR PURPOSE. - * - * Many thanks to Alessandro Rubini and Jonathan Corbet! - * - * Based strongly on code by: - * - * Author: Yong-iL Joh <tolkien@mizi.com> - * Date : $Date: 2002/06/18 12:37:30 $ - * - * Author: Andrew Christian - * 15 May 2002 - */ - -#ifndef MMC_MMC_H -#define MMC_MMC_H - -/* Standard MMC commands (4.1) type argument response */ - /* class 1 */ -#define MMC_GO_IDLE_STATE 0 /* bc */ -#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ -#define MMC_ALL_SEND_CID 2 /* bcr R2 */ -#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ -#define MMC_SET_DSR 4 /* bc [31:16] RCA */ -#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ -#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ -#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ -#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ -#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ -#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ -#define MMC_STOP_TRANSMISSION 12 /* ac R1b */ -#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */ -#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */ - - /* class 2 */ -#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ -#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ -#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ - - /* class 3 */ -#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ - - /* class 4 */ -#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */ -#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */ -#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */ -#define MMC_PROGRAM_CID 26 /* adtc R1 */ -#define MMC_PROGRAM_CSD 27 /* adtc R1 */ - - /* class 6 */ -#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */ -#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */ -#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */ - - /* class 5 */ -#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */ -#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */ -#define MMC_ERASE 38 /* ac R1b */ - - /* class 9 */ -#define MMC_FAST_IO 39 /* ac <Complex> R4 */ -#define MMC_GO_IRQ_STATE 40 /* bcr R5 */ - - /* class 7 */ -#define MMC_LOCK_UNLOCK 42 /* adtc R1b */ - - /* class 8 */ -#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */ -#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */ - -/* - * MMC_SWITCH argument format: - * - * [31:26] Always 0 - * [25:24] Access Mode - * [23:16] Location of target Byte in EXT_CSD - * [15:08] Value Byte - * [07:03] Always 0 - * [02:00] Command Set - */ - -/* - MMC status in R1 - Type - e : error bit - s : status bit - r : detected and set for the actual command response - x : detected and set during command execution. the host must poll - the card by sending status command in order to read these bits. - Clear condition - a : according to the card state - b : always related to the previous command. Reception of - a valid command will clear it (with a delay of one command) - c : clear by read - */ - -#define R1_OUT_OF_RANGE (1 << 31) /* er, c */ -#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */ -#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */ -#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */ -#define R1_ERASE_PARAM (1 << 27) /* ex, c */ -#define R1_WP_VIOLATION (1 << 26) /* erx, c */ -#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */ -#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */ -#define R1_COM_CRC_ERROR (1 << 23) /* er, b */ -#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */ -#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */ -#define R1_CC_ERROR (1 << 20) /* erx, c */ -#define R1_ERROR (1 << 19) /* erx, c */ -#define R1_UNDERRUN (1 << 18) /* ex, c */ -#define R1_OVERRUN (1 << 17) /* ex, c */ -#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */ -#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */ -#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */ -#define R1_ERASE_RESET (1 << 13) /* sr, c */ -#define R1_STATUS(x) (x & 0xFFFFE000) -#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */ -#define R1_READY_FOR_DATA (1 << 8) /* sx, a */ -#define R1_APP_CMD (1 << 5) /* sr, c */ - - -/* - * OCR bits are mostly in host.h - */ -#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */ - -/* - * Card Command Classes (CCC) - */ -#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */ - /* (CMD0,1,2,3,4,7,9,10,12,13,15) */ -#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */ - /* (CMD11) */ -#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */ - /* (CMD16,17,18) */ -#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */ - /* (CMD20) */ -#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */ - /* (CMD16,24,25,26,27) */ -#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */ - /* (CMD32,33,34,35,36,37,38,39) */ -#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */ - /* (CMD28,29,30) */ -#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */ - /* (CMD16,CMD42) */ -#define CCC_APP_SPEC (1<<8) /* (8) Application specific */ - /* (CMD55,56,57,ACMD*) */ -#define CCC_IO_MODE (1<<9) /* (9) I/O mode */ - /* (CMD5,39,40,52,53) */ -#define CCC_SWITCH (1<<10) /* (10) High speed switch */ - /* (CMD6,34,35,36,37,50) */ - /* (11) Reserved */ - /* (CMD?) */ - -/* - * CSD field definitions - */ - -#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ -#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ -#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */ -#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */ - -#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ -#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ -#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ -#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */ -#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ - -/* - * EXT_CSD fields - */ - -#define EXT_CSD_BUS_WIDTH 183 /* R/W */ -#define EXT_CSD_HS_TIMING 185 /* R/W */ -#define EXT_CSD_CARD_TYPE 196 /* RO */ -#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */ - -/* - * EXT_CSD field definitions - */ - -#define EXT_CSD_CMD_SET_NORMAL (1<<0) -#define EXT_CSD_CMD_SET_SECURE (1<<1) -#define EXT_CSD_CMD_SET_CPSECURE (1<<2) - -#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ -#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ - -#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ -#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ -#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ - -/* - * MMC_SWITCH access modes - */ - -#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ -#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ -#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ -#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ - -#endif /* MMC_MMC_PROTOCOL_H */ - diff --git a/hw/pc.h b/hw/pc.h deleted file mode 100644 index 2862849..0000000 --- a/hw/pc.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef HW_PC_H -#define HW_PC_H -/* PC-style peripherals (also used by other machines). */ - -/* serial.c */ - -SerialState *serial_init(int base, qemu_irq irq, int baudbase, - CharDriverState *chr); -SerialState *serial_mm_init (target_phys_addr_t base, int it_shift, - qemu_irq irq, int baudbase, - CharDriverState *chr, int ioregister); -uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr); -void serial_mm_writeb (void *opaque, target_phys_addr_t addr, uint32_t value); -uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr); -void serial_mm_writew (void *opaque, target_phys_addr_t addr, uint32_t value); -uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr); -void serial_mm_writel (void *opaque, target_phys_addr_t addr, uint32_t value); - -/* parallel.c */ - -typedef struct ParallelState ParallelState; -ParallelState *parallel_init(int base, qemu_irq irq, CharDriverState *chr); -ParallelState *parallel_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq, CharDriverState *chr); - -/* i8259.c */ - -typedef struct PicState2 PicState2; -extern PicState2 *isa_pic; -void pic_set_irq(int irq, int level); -void pic_set_irq_new(void *opaque, int irq, int level); -qemu_irq *i8259_init(qemu_irq parent_irq); -void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func, - void *alt_irq_opaque); -int pic_read_irq(PicState2 *s); -void pic_update_irq(PicState2 *s); -uint32_t pic_intack_read(PicState2 *s); -void pic_info(void); -void irq_info(void); - -/* APIC */ -typedef struct IOAPICState IOAPICState; - -int apic_init(CPUState *env); -int apic_accept_pic_intr(CPUState *env); -void apic_deliver_pic_intr(CPUState *env, int level); -int apic_get_interrupt(CPUState *env); -IOAPICState *ioapic_init(void); -void ioapic_set_irq(void *opaque, int vector, int level); - -/* i8254.c */ - -#define PIT_FREQ 1193182 - -typedef struct PITState PITState; - -PITState *pit_init(int base, qemu_irq irq); -void pit_set_gate(PITState *pit, int channel, int val); -int pit_get_gate(PITState *pit, int channel); -int pit_get_initial_count(PITState *pit, int channel); -int pit_get_mode(PITState *pit, int channel); -int pit_get_out(PITState *pit, int channel, int64_t current_time); - -/* vmport.c */ -void vmport_init(void); -void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque); - -/* vmmouse.c */ -void *vmmouse_init(void *m); - -/* pckbd.c */ - -void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base); -void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, - target_phys_addr_t base, int it_shift); - -/* mc146818rtc.c */ - -typedef struct RTCState RTCState; - -RTCState *rtc_init(int base, qemu_irq irq); -RTCState *rtc_mm_init(target_phys_addr_t base, int it_shift, qemu_irq irq); -void rtc_set_memory(RTCState *s, int addr, int val); -void rtc_set_date(RTCState *s, const struct tm *tm); - -/* pc.c */ -extern int fd_bootchk; - -void ioport_set_a20(int enable); -int ioport_get_a20(void); - -/* acpi.c */ -extern int acpi_enabled; -i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq); -void piix4_smbus_register_device(SMBusDevice *dev, uint8_t addr); -void acpi_bios_init(void); - -/* pcspk.c */ -void pcspk_init(PITState *); -int pcspk_audio_init(AudioState *, qemu_irq *pic); - -/* piix_pci.c */ -PCIBus *i440fx_init(PCIDevice **pi440fx_state, qemu_irq *pic); -void i440fx_set_smm(PCIDevice *d, int val); -int piix3_init(PCIBus *bus, int devfn); -void i440fx_init_memory_mappings(PCIDevice *d); - -int piix4_init(PCIBus *bus, int devfn); - -/* vga.c */ - -#ifndef TARGET_SPARC -#define VGA_RAM_SIZE (8192 * 1024) -#else -#define VGA_RAM_SIZE (9 * 1024 * 1024) -#endif - -int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size); -int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size, - unsigned long vga_bios_offset, int vga_bios_size); -int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size, - target_phys_addr_t vram_base, target_phys_addr_t ctrl_base, - int it_shift); - -/* cirrus_vga.c */ -void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size); -void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size); - -/* ide.c */ -void isa_ide_init(int iobase, int iobase2, qemu_irq irq, - BlockDriverState *hd0, BlockDriverState *hd1); -void pci_cmd646_ide_init(PCIBus *bus, BlockDriverState **hd_table, - int secondary_ide_enabled); -void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, - qemu_irq *pic); -void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn, - qemu_irq *pic); - -/* ne2000.c */ - -void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd); - -#endif diff --git a/hw/pci.c b/hw/pci.c deleted file mode 100644 index 5f7004a..0000000 --- a/hw/pci.c +++ /dev/null @@ -1,701 +0,0 @@ -/* - * QEMU PCI bus manager - * - * Copyright (c) 2004 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 "hw.h" -#include "pci.h" -#include "console.h" -#include "net.h" - -//#define DEBUG_PCI - -struct PCIBus { - int bus_num; - int devfn_min; - pci_set_irq_fn set_irq; - pci_map_irq_fn map_irq; - uint32_t config_reg; /* XXX: suppress */ - /* low level pic */ - SetIRQFunc *low_set_irq; - qemu_irq *irq_opaque; - PCIDevice *devices[256]; - PCIDevice *parent_dev; - PCIBus *next; - /* The bus IRQ state is the logical OR of the connected devices. - Keep a count of the number of devices with raised IRQs. */ - int nirq; - int irq_count[]; -}; - -static void pci_update_mappings(PCIDevice *d); -static void pci_set_irq(void *opaque, int irq_num, int level); - -target_phys_addr_t pci_mem_base; -static int pci_irq_index; -static PCIBus *first_bus; - -static void pcibus_save(QEMUFile *f, void *opaque) -{ - PCIBus *bus = (PCIBus *)opaque; - int i; - - qemu_put_be32(f, bus->nirq); - for (i = 0; i < bus->nirq; i++) - qemu_put_be32(f, bus->irq_count[i]); -} - -static int pcibus_load(QEMUFile *f, void *opaque, int version_id) -{ - PCIBus *bus = (PCIBus *)opaque; - int i, nirq; - - if (version_id != 1) - return -EINVAL; - - nirq = qemu_get_be32(f); - if (bus->nirq != nirq) { - fprintf(stderr, "pcibus_load: nirq mismatch: src=%d dst=%d\n", - nirq, bus->nirq); - return -EINVAL; - } - - for (i = 0; i < nirq; i++) - bus->irq_count[i] = qemu_get_be32(f); - - return 0; -} - -PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - qemu_irq *pic, int devfn_min, int nirq) -{ - PCIBus *bus; - static int nbus = 0; - - bus = qemu_mallocz(sizeof(PCIBus) + (nirq * sizeof(int))); - bus->set_irq = set_irq; - bus->map_irq = map_irq; - bus->irq_opaque = pic; - bus->devfn_min = devfn_min; - bus->nirq = nirq; - first_bus = bus; - register_savevm("PCIBUS", nbus++, 1, pcibus_save, pcibus_load, bus); - return bus; -} - -static PCIBus *pci_register_secondary_bus(PCIDevice *dev, pci_map_irq_fn map_irq) -{ - PCIBus *bus; - bus = qemu_mallocz(sizeof(PCIBus)); - bus->map_irq = map_irq; - bus->parent_dev = dev; - bus->next = dev->bus->next; - dev->bus->next = bus; - return bus; -} - -int pci_bus_num(PCIBus *s) -{ - return s->bus_num; -} - -void pci_device_save(PCIDevice *s, QEMUFile *f) -{ - int i; - - qemu_put_be32(f, 2); /* PCI device version */ - qemu_put_buffer(f, s->config, 256); - for (i = 0; i < 4; i++) - qemu_put_be32(f, s->irq_state[i]); -} - -int pci_device_load(PCIDevice *s, QEMUFile *f) -{ - uint32_t version_id; - int i; - - version_id = qemu_get_be32(f); - if (version_id > 2) - return -EINVAL; - qemu_get_buffer(f, s->config, 256); - pci_update_mappings(s); - - if (version_id >= 2) - for (i = 0; i < 4; i ++) - s->irq_state[i] = qemu_get_be32(f); - - return 0; -} - -/* -1 for devfn means auto assign */ -PCIDevice *pci_register_device(PCIBus *bus, const char *name, - int instance_size, int devfn, - PCIConfigReadFunc *config_read, - PCIConfigWriteFunc *config_write) -{ - PCIDevice *pci_dev; - - if (pci_irq_index >= PCI_DEVICES_MAX) - return NULL; - - if (devfn < 0) { - for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { - if (!bus->devices[devfn]) - goto found; - } - return NULL; - found: ; - } - pci_dev = qemu_mallocz(instance_size); - if (!pci_dev) - return NULL; - pci_dev->bus = bus; - pci_dev->devfn = devfn; - pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); - memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state)); - - if (!config_read) - config_read = pci_default_read_config; - if (!config_write) - config_write = pci_default_write_config; - pci_dev->config_read = config_read; - pci_dev->config_write = config_write; - pci_dev->irq_index = pci_irq_index++; - bus->devices[devfn] = pci_dev; - pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, 4); - return pci_dev; -} - -void pci_register_io_region(PCIDevice *pci_dev, int region_num, - uint32_t size, int type, - PCIMapIORegionFunc *map_func) -{ - PCIIORegion *r; - uint32_t addr; - - if ((unsigned int)region_num >= PCI_NUM_REGIONS) - return; - r = &pci_dev->io_regions[region_num]; - r->addr = -1; - r->size = size; - r->type = type; - r->map_func = map_func; - if (region_num == PCI_ROM_SLOT) { - addr = 0x30; - } else { - addr = 0x10 + region_num * 4; - } - *(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type); -} - -static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr) -{ - return addr + pci_mem_base; -} - -static void pci_update_mappings(PCIDevice *d) -{ - PCIIORegion *r; - int cmd, i; - uint32_t last_addr, new_addr, config_ofs; - - cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND)); - for(i = 0; i < PCI_NUM_REGIONS; i++) { - r = &d->io_regions[i]; - if (i == PCI_ROM_SLOT) { - config_ofs = 0x30; - } else { - config_ofs = 0x10 + i * 4; - } - if (r->size != 0) { - if (r->type & PCI_ADDRESS_SPACE_IO) { - if (cmd & PCI_COMMAND_IO) { - new_addr = le32_to_cpu(*(uint32_t *)(d->config + - config_ofs)); - new_addr = new_addr & ~(r->size - 1); - last_addr = new_addr + r->size - 1; - /* NOTE: we have only 64K ioports on PC */ - if (last_addr <= new_addr || new_addr == 0 || - last_addr >= 0x10000) { - new_addr = -1; - } - } else { - new_addr = -1; - } - } else { - if (cmd & PCI_COMMAND_MEMORY) { - new_addr = le32_to_cpu(*(uint32_t *)(d->config + - config_ofs)); - /* the ROM slot has a specific enable bit */ - if (i == PCI_ROM_SLOT && !(new_addr & 1)) - goto no_mem_map; - new_addr = new_addr & ~(r->size - 1); - last_addr = new_addr + r->size - 1; - /* NOTE: we do not support wrapping */ - /* XXX: as we cannot support really dynamic - mappings, we handle specific values as invalid - mappings. */ - if (last_addr <= new_addr || new_addr == 0 || - last_addr == -1) { - new_addr = -1; - } - } else { - no_mem_map: - new_addr = -1; - } - } - /* now do the real mapping */ - if (new_addr != r->addr) { - if (r->addr != -1) { - if (r->type & PCI_ADDRESS_SPACE_IO) { - int class; - /* NOTE: specific hack for IDE in PC case: - only one byte must be mapped. */ - class = d->config[0x0a] | (d->config[0x0b] << 8); - if (class == 0x0101 && r->size == 4) { - isa_unassign_ioport(r->addr + 2, 1); - } else { - isa_unassign_ioport(r->addr, r->size); - } - } else { - cpu_register_physical_memory(pci_to_cpu_addr(r->addr), - r->size, - IO_MEM_UNASSIGNED); - } - } - r->addr = new_addr; - if (r->addr != -1) { - r->map_func(d, i, r->addr, r->size, r->type); - } - } - } - } -} - -uint32_t pci_default_read_config(PCIDevice *d, - uint32_t address, int len) -{ - uint32_t val; - - switch(len) { - default: - case 4: - if (address <= 0xfc) { - val = le32_to_cpu(*(uint32_t *)(d->config + address)); - break; - } - /* fall through */ - case 2: - if (address <= 0xfe) { - val = le16_to_cpu(*(uint16_t *)(d->config + address)); - break; - } - /* fall through */ - case 1: - val = d->config[address]; - break; - } - return val; -} - -void pci_default_write_config(PCIDevice *d, - uint32_t address, uint32_t val, int len) -{ - int can_write, i; - uint32_t end, addr; - - if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || - (address >= 0x30 && address < 0x34))) { - PCIIORegion *r; - int reg; - - if ( address >= 0x30 ) { - reg = PCI_ROM_SLOT; - }else{ - reg = (address - 0x10) >> 2; - } - r = &d->io_regions[reg]; - if (r->size == 0) - goto default_config; - /* compute the stored value */ - if (reg == PCI_ROM_SLOT) { - /* keep ROM enable bit */ - val &= (~(r->size - 1)) | 1; - } else { - val &= ~(r->size - 1); - val |= r->type; - } - *(uint32_t *)(d->config + address) = cpu_to_le32(val); - pci_update_mappings(d); - return; - } - default_config: - /* not efficient, but simple */ - addr = address; - for(i = 0; i < len; i++) { - /* default read/write accesses */ - switch(d->config[0x0e]) { - case 0x00: - case 0x80: - switch(addr) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0e: - case 0x10 ... 0x27: /* base */ - case 0x30 ... 0x33: /* rom */ - case 0x3d: - can_write = 0; - break; - default: - can_write = 1; - break; - } - break; - default: - case 0x01: - switch(addr) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0e: - case 0x38 ... 0x3b: /* rom */ - case 0x3d: - can_write = 0; - break; - default: - can_write = 1; - break; - } - break; - } - if (can_write) { - d->config[addr] = val; - } - if (++addr > 0xff) - break; - val >>= 8; - } - - end = address + len; - if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) { - /* if the command register is modified, we must modify the mappings */ - pci_update_mappings(d); - } -} - -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len) -{ - PCIBus *s = opaque; - PCIDevice *pci_dev; - int config_addr, bus_num; - -#if defined(DEBUG_PCI) && 0 - printf("pci_data_write: addr=%08x val=%08x len=%d\n", - addr, val, len); -#endif - bus_num = (addr >> 16) & 0xff; - while (s && s->bus_num != bus_num) - s = s->next; - if (!s) - return; - pci_dev = s->devices[(addr >> 8) & 0xff]; - if (!pci_dev) - return; - config_addr = addr & 0xff; -#if defined(DEBUG_PCI) - printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n", - pci_dev->name, config_addr, val, len); -#endif - pci_dev->config_write(pci_dev, config_addr, val, len); -} - -uint32_t pci_data_read(void *opaque, uint32_t addr, int len) -{ - PCIBus *s = opaque; - PCIDevice *pci_dev; - int config_addr, bus_num; - uint32_t val; - - bus_num = (addr >> 16) & 0xff; - while (s && s->bus_num != bus_num) - s= s->next; - if (!s) - goto fail; - pci_dev = s->devices[(addr >> 8) & 0xff]; - if (!pci_dev) { - fail: - switch(len) { - case 1: - val = 0xff; - break; - case 2: - val = 0xffff; - break; - default: - case 4: - val = 0xffffffff; - break; - } - goto the_end; - } - config_addr = addr & 0xff; - val = pci_dev->config_read(pci_dev, config_addr, len); -#if defined(DEBUG_PCI) - printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", - pci_dev->name, config_addr, val, len); -#endif - the_end: -#if defined(DEBUG_PCI) && 0 - printf("pci_data_read: addr=%08x val=%08x len=%d\n", - addr, val, len); -#endif - return val; -} - -/***********************************************************/ -/* generic PCI irq support */ - -/* 0 <= irq_num <= 3. level must be 0 or 1 */ -static void pci_set_irq(void *opaque, int irq_num, int level) -{ - PCIDevice *pci_dev = (PCIDevice *)opaque; - PCIBus *bus; - int change; - - change = level - pci_dev->irq_state[irq_num]; - if (!change) - return; - - pci_dev->irq_state[irq_num] = level; - for (;;) { - bus = pci_dev->bus; - irq_num = bus->map_irq(pci_dev, irq_num); - if (bus->set_irq) - break; - pci_dev = bus->parent_dev; - } - bus->irq_count[irq_num] += change; - bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); -} - -/***********************************************************/ -/* monitor info on PCI */ - -typedef struct { - uint16_t class; - const char *desc; -} pci_class_desc; - -static pci_class_desc pci_class_descriptions[] = -{ - { 0x0100, "SCSI controller"}, - { 0x0101, "IDE controller"}, - { 0x0102, "Floppy controller"}, - { 0x0103, "IPI controller"}, - { 0x0104, "RAID controller"}, - { 0x0106, "SATA controller"}, - { 0x0107, "SAS controller"}, - { 0x0180, "Storage controller"}, - { 0x0200, "Ethernet controller"}, - { 0x0201, "Token Ring controller"}, - { 0x0202, "FDDI controller"}, - { 0x0203, "ATM controller"}, - { 0x0280, "Network controller"}, - { 0x0300, "VGA controller"}, - { 0x0301, "XGA controller"}, - { 0x0302, "3D controller"}, - { 0x0380, "Display controller"}, - { 0x0400, "Video controller"}, - { 0x0401, "Audio controller"}, - { 0x0402, "Phone"}, - { 0x0480, "Multimedia controller"}, - { 0x0500, "RAM controller"}, - { 0x0501, "Flash controller"}, - { 0x0580, "Memory controller"}, - { 0x0600, "Host bridge"}, - { 0x0601, "ISA bridge"}, - { 0x0602, "EISA bridge"}, - { 0x0603, "MC bridge"}, - { 0x0604, "PCI bridge"}, - { 0x0605, "PCMCIA bridge"}, - { 0x0606, "NUBUS bridge"}, - { 0x0607, "CARDBUS bridge"}, - { 0x0608, "RACEWAY bridge"}, - { 0x0680, "Bridge"}, - { 0x0c03, "USB controller"}, - { 0, NULL} -}; - -static void pci_info_device(PCIDevice *d) -{ - int i, class; - PCIIORegion *r; - pci_class_desc *desc; - - term_printf(" Bus %2d, device %3d, function %d:\n", - d->bus->bus_num, d->devfn >> 3, d->devfn & 7); - class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE))); - term_printf(" "); - desc = pci_class_descriptions; - while (desc->desc && class != desc->class) - desc++; - if (desc->desc) { - term_printf("%s", desc->desc); - } else { - term_printf("Class %04x", class); - } - term_printf(": PCI device %04x:%04x\n", - le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))), - le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID)))); - - if (d->config[PCI_INTERRUPT_PIN] != 0) { - term_printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]); - } - if (class == 0x0604) { - term_printf(" BUS %d.\n", d->config[0x19]); - } - for(i = 0;i < PCI_NUM_REGIONS; i++) { - r = &d->io_regions[i]; - if (r->size != 0) { - term_printf(" BAR%d: ", i); - if (r->type & PCI_ADDRESS_SPACE_IO) { - term_printf("I/O at 0x%04x [0x%04x].\n", - r->addr, r->addr + r->size - 1); - } else { - term_printf("32 bit memory at 0x%08x [0x%08x].\n", - r->addr, r->addr + r->size - 1); - } - } - } - if (class == 0x0604 && d->config[0x19] != 0) { - pci_for_each_device(d->config[0x19], pci_info_device); - } -} - -void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d)) -{ - PCIBus *bus = first_bus; - PCIDevice *d; - int devfn; - - while (bus && bus->bus_num != bus_num) - bus = bus->next; - if (bus) { - for(devfn = 0; devfn < 256; devfn++) { - d = bus->devices[devfn]; - if (d) - fn(d); - } - } -} - -void pci_info(void) -{ - pci_for_each_device(0, pci_info_device); -} - -/* Initialize a PCI NIC. */ -void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn) -{ -#if 0 - if (strcmp(nd->model, "ne2k_pci") == 0) { - pci_ne2000_init(bus, nd, devfn); - } else if (strcmp(nd->model, "i82551") == 0) { - pci_i82551_init(bus, nd, devfn); - } else if (strcmp(nd->model, "i82557b") == 0) { - pci_i82557b_init(bus, nd, devfn); - } else if (strcmp(nd->model, "i82559er") == 0) { - pci_i82559er_init(bus, nd, devfn); - } else if (strcmp(nd->model, "rtl8139") == 0) { - pci_rtl8139_init(bus, nd, devfn); - } else if (strcmp(nd->model, "e1000") == 0) { - pci_e1000_init(bus, nd, devfn); - } else if (strcmp(nd->model, "pcnet") == 0) { - pci_pcnet_init(bus, nd, devfn); - } else if (strcmp(nd->model, "?") == 0) { - fprintf(stderr, "qemu: Supported PCI NICs: i82551 i82557b i82559er" - " ne2k_pci pcnet rtl8139 e1000\n"); - exit (1); - } else { - fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model); - exit (1); - } -#endif -} - -typedef struct { - PCIDevice dev; - PCIBus *bus; -} PCIBridge; - -static void pci_bridge_write_config(PCIDevice *d, - uint32_t address, uint32_t val, int len) -{ - PCIBridge *s = (PCIBridge *)d; - - if (address == 0x19 || (address == 0x18 && len > 1)) { - if (address == 0x19) - s->bus->bus_num = val & 0xff; - else - s->bus->bus_num = (val >> 8) & 0xff; -#if defined(DEBUG_PCI) - printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num); -#endif - } - pci_default_write_config(d, address, val, len); -} - -PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id, - pci_map_irq_fn map_irq, const char *name) -{ - PCIBridge *s; - s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge), - devfn, NULL, pci_bridge_write_config); - s->dev.config[0x00] = id >> 16; - s->dev.config[0x01] = id >> 24; - s->dev.config[0x02] = id; // device_id - s->dev.config[0x03] = id >> 8; - s->dev.config[0x04] = 0x06; // command = bus master, pci mem - s->dev.config[0x05] = 0x00; - s->dev.config[0x06] = 0xa0; // status = fast back-to-back, 66MHz, no error - s->dev.config[0x07] = 0x00; // status = fast devsel - s->dev.config[0x08] = 0x00; // revision - s->dev.config[0x09] = 0x00; // programming i/f - s->dev.config[0x0A] = 0x04; // class_sub = PCI to PCI bridge - s->dev.config[0x0B] = 0x06; // class_base = PCI_bridge - s->dev.config[0x0D] = 0x10; // latency_timer - s->dev.config[0x0E] = 0x81; // header_type - s->dev.config[0x1E] = 0xa0; // secondary status - - s->bus = pci_register_secondary_bus(&s->dev, map_irq); - return s->bus; -} diff --git a/hw/pci.h b/hw/pci.h deleted file mode 100644 index e870987..0000000 --- a/hw/pci.h +++ /dev/null @@ -1,142 +0,0 @@ -#ifndef QEMU_PCI_H -#define QEMU_PCI_H - -/* PCI includes legacy ISA access. */ -#include "isa.h" - -/* PCI bus */ - -extern target_phys_addr_t pci_mem_base; - -typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, - uint32_t address, uint32_t data, int len); -typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, - uint32_t address, int len); -typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, - uint32_t addr, uint32_t size, int type); - -#define PCI_ADDRESS_SPACE_MEM 0x00 -#define PCI_ADDRESS_SPACE_IO 0x01 -#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 - -typedef struct PCIIORegion { - uint32_t addr; /* current PCI mapping address. -1 means not mapped */ - uint32_t size; - uint8_t type; - PCIMapIORegionFunc *map_func; -} PCIIORegion; - -#define PCI_ROM_SLOT 6 -#define PCI_NUM_REGIONS 7 - -#define PCI_DEVICES_MAX 64 - -#define PCI_VENDOR_ID 0x00 /* 16 bits */ -#define PCI_DEVICE_ID 0x02 /* 16 bits */ -#define PCI_COMMAND 0x04 /* 16 bits */ -#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ -#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ -#define PCI_CLASS_DEVICE 0x0a /* Device class */ -#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ -#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ -#define PCI_MIN_GNT 0x3e /* 8 bits */ -#define PCI_MAX_LAT 0x3f /* 8 bits */ - -struct PCIDevice { - /* PCI config space */ - uint8_t config[256]; - - /* the following fields are read only */ - PCIBus *bus; - int devfn; - char name[64]; - PCIIORegion io_regions[PCI_NUM_REGIONS]; - - /* do not access the following fields */ - PCIConfigReadFunc *config_read; - PCIConfigWriteFunc *config_write; - /* ??? This is a PC-specific hack, and should be removed. */ - int irq_index; - - /* IRQ objects for the INTA-INTD pins. */ - qemu_irq *irq; - - /* Current IRQ levels. Used internally by the generic PCI code. */ - int irq_state[4]; -}; - -PCIDevice *pci_register_device(PCIBus *bus, const char *name, - int instance_size, int devfn, - PCIConfigReadFunc *config_read, - PCIConfigWriteFunc *config_write); - -void pci_register_io_region(PCIDevice *pci_dev, int region_num, - uint32_t size, int type, - PCIMapIORegionFunc *map_func); - -uint32_t pci_default_read_config(PCIDevice *d, - uint32_t address, int len); -void pci_default_write_config(PCIDevice *d, - uint32_t address, uint32_t val, int len); -void pci_device_save(PCIDevice *s, QEMUFile *f); -int pci_device_load(PCIDevice *s, QEMUFile *f); - -typedef void (*pci_set_irq_fn)(qemu_irq *pic, int irq_num, int level); -typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); -PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - qemu_irq *pic, int devfn_min, int nirq); - -void pci_nic_init(PCIBus *bus, NICInfo *nd, int devfn); -void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len); -uint32_t pci_data_read(void *opaque, uint32_t addr, int len); -int pci_bus_num(PCIBus *s); -void pci_for_each_device(int bus_num, void (*fn)(PCIDevice *d)); - -void pci_info(void); -PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint32_t id, - pci_map_irq_fn map_irq, const char *name); - -/* lsi53c895a.c */ -#define LSI_MAX_DEVS 7 -void lsi_scsi_attach(void *opaque, BlockDriverState *bd, int id); -void *lsi_scsi_init(PCIBus *bus, int devfn); - -/* vmware_vga.c */ -void pci_vmsvga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, - unsigned long vga_ram_offset, int vga_ram_size); - -/* usb-uhci.c */ -void usb_uhci_piix3_init(PCIBus *bus, int devfn); -void usb_uhci_piix4_init(PCIBus *bus, int devfn); - -/* usb-ohci.c */ -void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn); - -/* eepro100.c */ - -void pci_i82551_init(PCIBus *bus, NICInfo *nd, int devfn); -void pci_i82557b_init(PCIBus *bus, NICInfo *nd, int devfn); -void pci_i82559er_init(PCIBus *bus, NICInfo *nd, int devfn); - -/* ne2000.c */ - -void pci_ne2000_init(PCIBus *bus, NICInfo *nd, int devfn); - -/* rtl8139.c */ - -void pci_rtl8139_init(PCIBus *bus, NICInfo *nd, int devfn); - -/* e1000.c */ -void pci_e1000_init(PCIBus *bus, NICInfo *nd, int devfn); - -/* pcnet.c */ -void pci_pcnet_init(PCIBus *bus, NICInfo *nd, int devfn); - -/* prep_pci.c */ -PCIBus *pci_prep_init(qemu_irq *pic); - -/* apb_pci.c */ -PCIBus *pci_apb_init(target_phys_addr_t special_base, target_phys_addr_t mem_base, - qemu_irq *pic); - -#endif diff --git a/hw/pci_host.h b/hw/pci_host.h deleted file mode 100644 index 49a0c59..0000000 --- a/hw/pci_host.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * QEMU Common PCI Host bridge configuration data space access routines. - * - * Copyright (c) 2006 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. - */ - -/* Worker routines for a PCI host controller that uses an {address,data} - register pair to access PCI configuration space. */ - -typedef struct { - uint32_t config_reg; - PCIBus *bus; -} PCIHostState; - -static void pci_host_data_writeb(void* opaque, pci_addr_t addr, uint32_t val) -{ - PCIHostState *s = opaque; - if (s->config_reg & (1u << 31)) - pci_data_write(s->bus, s->config_reg | (addr & 3), val, 1); -} - -static void pci_host_data_writew(void* opaque, pci_addr_t addr, uint32_t val) -{ - PCIHostState *s = opaque; -#ifdef TARGET_WORDS_BIGENDIAN - val = bswap16(val); -#endif - if (s->config_reg & (1u << 31)) - pci_data_write(s->bus, s->config_reg | (addr & 3), val, 2); -} - -static void pci_host_data_writel(void* opaque, pci_addr_t addr, uint32_t val) -{ - PCIHostState *s = opaque; -#ifdef TARGET_WORDS_BIGENDIAN - val = bswap32(val); -#endif - if (s->config_reg & (1u << 31)) - pci_data_write(s->bus, s->config_reg, val, 4); -} - -static uint32_t pci_host_data_readb(void* opaque, pci_addr_t addr) -{ - PCIHostState *s = opaque; - if (!(s->config_reg & (1 << 31))) - return 0xff; - return pci_data_read(s->bus, s->config_reg | (addr & 3), 1); -} - -static uint32_t pci_host_data_readw(void* opaque, pci_addr_t addr) -{ - PCIHostState *s = opaque; - uint32_t val; - if (!(s->config_reg & (1 << 31))) - return 0xffff; - val = pci_data_read(s->bus, s->config_reg | (addr & 3), 2); -#ifdef TARGET_WORDS_BIGENDIAN - val = bswap16(val); -#endif - return val; -} - -static uint32_t pci_host_data_readl(void* opaque, pci_addr_t addr) -{ - PCIHostState *s = opaque; - uint32_t val; - if (!(s->config_reg & (1 << 31))) - return 0xffffffff; - val = pci_data_read(s->bus, s->config_reg | (addr & 3), 4); -#ifdef TARGET_WORDS_BIGENDIAN - val = bswap32(val); -#endif - return val; -} - diff --git a/hw/pcmcia.h b/hw/pcmcia.h deleted file mode 100644 index bfa23ba..0000000 --- a/hw/pcmcia.h +++ /dev/null @@ -1,50 +0,0 @@ -/* PCMCIA/Cardbus */ - -struct pcmcia_socket_s { - qemu_irq irq; - int attached; - const char *slot_string; - const char *card_string; -}; - -void pcmcia_socket_register(struct pcmcia_socket_s *socket); -void pcmcia_socket_unregister(struct pcmcia_socket_s *socket); -void pcmcia_info(void); - -struct pcmcia_card_s { - void *state; - struct pcmcia_socket_s *slot; - int (*attach)(void *state); - int (*detach)(void *state); - const uint8_t *cis; - int cis_len; - - /* Only valid if attached */ - uint8_t (*attr_read)(void *state, uint32_t address); - void (*attr_write)(void *state, uint32_t address, uint8_t value); - uint16_t (*common_read)(void *state, uint32_t address); - void (*common_write)(void *state, uint32_t address, uint16_t value); - uint16_t (*io_read)(void *state, uint32_t address); - void (*io_write)(void *state, uint32_t address, uint16_t value); -}; - -#define CISTPL_DEVICE 0x01 /* 5V Device Information Tuple */ -#define CISTPL_NO_LINK 0x14 /* No Link Tuple */ -#define CISTPL_VERS_1 0x15 /* Level 1 Version Tuple */ -#define CISTPL_JEDEC_C 0x18 /* JEDEC ID Tuple */ -#define CISTPL_JEDEC_A 0x19 /* JEDEC ID Tuple */ -#define CISTPL_CONFIG 0x1a /* Configuration Tuple */ -#define CISTPL_CFTABLE_ENTRY 0x1b /* 16-bit PCCard Configuration */ -#define CISTPL_DEVICE_OC 0x1c /* Additional Device Information */ -#define CISTPL_DEVICE_OA 0x1d /* Additional Device Information */ -#define CISTPL_DEVICE_GEO 0x1e /* Additional Device Information */ -#define CISTPL_DEVICE_GEO_A 0x1f /* Additional Device Information */ -#define CISTPL_MANFID 0x20 /* Manufacture ID Tuple */ -#define CISTPL_FUNCID 0x21 /* Function ID Tuple */ -#define CISTPL_FUNCE 0x22 /* Function Extension Tuple */ -#define CISTPL_END 0xff /* Tuple End */ -#define CISTPL_ENDMARK 0xff - -/* dscm1xxxx.c */ -struct pcmcia_card_s *dscm1xxxx_init(BlockDriverState *bdrv); - diff --git a/hw/power_supply.h b/hw/power_supply.h deleted file mode 100644 index b85edc7..0000000 --- a/hw/power_supply.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Universal power supply monitor class - * - * Copyright © 2007 Anton Vorontsov <cbou@mail.ru> - * Copyright © 2004 Szabolcs Gyurko - * Copyright © 2003 Ian Molton <spyro@f2s.com> - * - * Modified: 2004, Oct Szabolcs Gyurko - * - * You may use this code as per GPL version 2 - */ - -#ifndef __LINUX_POWER_SUPPLY_H__ -#define __LINUX_POWER_SUPPLY_H__ - -/* - * All voltages, currents, charges, energies, time and temperatures in uV, - * µA, µAh, µWh, seconds and tenths of degree Celsius unless otherwise - * stated. It's driver's job to convert its raw values to units in which - * this class operates. - */ - -/* - * For systems where the charger determines the maximum battery capacity - * the min and max fields should be used to present these values to user - * space. Unused/unknown fields will not appear in sysfs. - */ - -enum { - POWER_SUPPLY_STATUS_UNKNOWN = 0, - POWER_SUPPLY_STATUS_CHARGING, - POWER_SUPPLY_STATUS_DISCHARGING, - POWER_SUPPLY_STATUS_NOT_CHARGING, - POWER_SUPPLY_STATUS_FULL, -}; - -enum { - POWER_SUPPLY_HEALTH_UNKNOWN = 0, - POWER_SUPPLY_HEALTH_GOOD, - POWER_SUPPLY_HEALTH_OVERHEAT, - POWER_SUPPLY_HEALTH_DEAD, - POWER_SUPPLY_HEALTH_OVERVOLTAGE, - POWER_SUPPLY_HEALTH_UNSPEC_FAILURE, -}; - -enum { - POWER_SUPPLY_TECHNOLOGY_UNKNOWN = 0, - POWER_SUPPLY_TECHNOLOGY_NiMH, - POWER_SUPPLY_TECHNOLOGY_LION, - POWER_SUPPLY_TECHNOLOGY_LIPO, - POWER_SUPPLY_TECHNOLOGY_LiFe, - POWER_SUPPLY_TECHNOLOGY_NiCd, -}; - -enum { - POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN = 0, - POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL, - POWER_SUPPLY_CAPACITY_LEVEL_LOW, - POWER_SUPPLY_CAPACITY_LEVEL_NORMAL, - POWER_SUPPLY_CAPACITY_LEVEL_HIGH, - POWER_SUPPLY_CAPACITY_LEVEL_FULL, -}; - -enum power_supply_property { - /* Properties of type `int' */ - POWER_SUPPLY_PROP_STATUS = 0, - POWER_SUPPLY_PROP_HEALTH, - POWER_SUPPLY_PROP_PRESENT, - POWER_SUPPLY_PROP_ONLINE, - POWER_SUPPLY_PROP_TECHNOLOGY, - POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, - POWER_SUPPLY_PROP_VOLTAGE_NOW, - POWER_SUPPLY_PROP_VOLTAGE_AVG, - POWER_SUPPLY_PROP_CURRENT_NOW, - POWER_SUPPLY_PROP_CURRENT_AVG, - POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, - POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN, - POWER_SUPPLY_PROP_CHARGE_FULL, - POWER_SUPPLY_PROP_CHARGE_EMPTY, - POWER_SUPPLY_PROP_CHARGE_NOW, - POWER_SUPPLY_PROP_CHARGE_AVG, - POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, - POWER_SUPPLY_PROP_ENERGY_EMPTY_DESIGN, - POWER_SUPPLY_PROP_ENERGY_FULL, - POWER_SUPPLY_PROP_ENERGY_EMPTY, - POWER_SUPPLY_PROP_ENERGY_NOW, - POWER_SUPPLY_PROP_ENERGY_AVG, - POWER_SUPPLY_PROP_CAPACITY, /* in percents! */ - POWER_SUPPLY_PROP_CAPACITY_LEVEL, - POWER_SUPPLY_PROP_TEMP, - POWER_SUPPLY_PROP_TEMP_AMBIENT, - POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW, - POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, - POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, - POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, - /* Properties of type `const char *' */ - POWER_SUPPLY_PROP_MODEL_NAME, - POWER_SUPPLY_PROP_MANUFACTURER, -}; - -enum power_supply_type { - POWER_SUPPLY_TYPE_BATTERY = 0, - POWER_SUPPLY_TYPE_UPS, - POWER_SUPPLY_TYPE_MAINS, - POWER_SUPPLY_TYPE_USB, -}; - -#endif /* __LINUX_POWER_SUPPLY_H__ */ diff --git a/hw/pxa.h b/hw/pxa.h deleted file mode 100644 index 16a68d9..0000000 --- a/hw/pxa.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Intel XScale PXA255/270 processor support. - * - * Copyright (c) 2006 Openedhand Ltd. - * Written by Andrzej Zaborowski <balrog@zabor.org> - * - * This code is licenced under the GNU GPL v2. - */ -#ifndef PXA_H -# define PXA_H "pxa.h" - -/* Interrupt numbers */ -# define PXA2XX_PIC_SSP3 0 -# define PXA2XX_PIC_USBH2 2 -# define PXA2XX_PIC_USBH1 3 -# define PXA2XX_PIC_KEYPAD 4 -# define PXA2XX_PIC_PWRI2C 6 -# define PXA25X_PIC_HWUART 7 -# define PXA27X_PIC_OST_4_11 7 -# define PXA2XX_PIC_GPIO_0 8 -# define PXA2XX_PIC_GPIO_1 9 -# define PXA2XX_PIC_GPIO_X 10 -# define PXA2XX_PIC_I2S 13 -# define PXA26X_PIC_ASSP 15 -# define PXA25X_PIC_NSSP 16 -# define PXA27X_PIC_SSP2 16 -# define PXA2XX_PIC_LCD 17 -# define PXA2XX_PIC_I2C 18 -# define PXA2XX_PIC_ICP 19 -# define PXA2XX_PIC_STUART 20 -# define PXA2XX_PIC_BTUART 21 -# define PXA2XX_PIC_FFUART 22 -# define PXA2XX_PIC_MMC 23 -# define PXA2XX_PIC_SSP 24 -# define PXA2XX_PIC_DMA 25 -# define PXA2XX_PIC_OST_0 26 -# define PXA2XX_PIC_RTC1HZ 30 -# define PXA2XX_PIC_RTCALARM 31 - -/* DMA requests */ -# define PXA2XX_RX_RQ_I2S 2 -# define PXA2XX_TX_RQ_I2S 3 -# define PXA2XX_RX_RQ_BTUART 4 -# define PXA2XX_TX_RQ_BTUART 5 -# define PXA2XX_RX_RQ_FFUART 6 -# define PXA2XX_TX_RQ_FFUART 7 -# define PXA2XX_RX_RQ_SSP1 13 -# define PXA2XX_TX_RQ_SSP1 14 -# define PXA2XX_RX_RQ_SSP2 15 -# define PXA2XX_TX_RQ_SSP2 16 -# define PXA2XX_RX_RQ_ICP 17 -# define PXA2XX_TX_RQ_ICP 18 -# define PXA2XX_RX_RQ_STUART 19 -# define PXA2XX_TX_RQ_STUART 20 -# define PXA2XX_RX_RQ_MMCI 21 -# define PXA2XX_TX_RQ_MMCI 22 -# define PXA2XX_USB_RQ(x) ((x) + 24) -# define PXA2XX_RX_RQ_SSP3 66 -# define PXA2XX_TX_RQ_SSP3 67 - -# define PXA2XX_SDRAM_BASE 0xa0000000 -# define PXA2XX_INTERNAL_BASE 0x5c000000 -# define PXA2XX_INTERNAL_SIZE 0x40000 - -/* pxa2xx_pic.c */ -qemu_irq *pxa2xx_pic_init(target_phys_addr_t base, CPUState *env); - -/* pxa2xx_timer.c */ -void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs); -void pxa27x_timer_init(target_phys_addr_t base, qemu_irq *irqs, qemu_irq irq4); - -/* pxa2xx_gpio.c */ -struct pxa2xx_gpio_info_s; -struct pxa2xx_gpio_info_s *pxa2xx_gpio_init(target_phys_addr_t base, - CPUState *env, qemu_irq *pic, int lines); -qemu_irq *pxa2xx_gpio_in_get(struct pxa2xx_gpio_info_s *s); -void pxa2xx_gpio_out_set(struct pxa2xx_gpio_info_s *s, - int line, qemu_irq handler); -void pxa2xx_gpio_read_notifier(struct pxa2xx_gpio_info_s *s, qemu_irq handler); - -/* pxa2xx_dma.c */ -struct pxa2xx_dma_state_s; -struct pxa2xx_dma_state_s *pxa255_dma_init(target_phys_addr_t base, - qemu_irq irq); -struct pxa2xx_dma_state_s *pxa27x_dma_init(target_phys_addr_t base, - qemu_irq irq); -void pxa2xx_dma_request(struct pxa2xx_dma_state_s *s, int req_num, int on); - -/* pxa2xx_lcd.c */ -struct pxa2xx_lcdc_s; -struct pxa2xx_lcdc_s *pxa2xx_lcdc_init(target_phys_addr_t base, - qemu_irq irq, DisplayState *ds); -void pxa2xx_lcd_vsync_notifier(struct pxa2xx_lcdc_s *s, qemu_irq handler); -void pxa2xx_lcdc_oritentation(void *opaque, int angle); - -/* pxa2xx_mmci.c */ -struct pxa2xx_mmci_s; -struct pxa2xx_mmci_s *pxa2xx_mmci_init(target_phys_addr_t base, - BlockDriverState *bd, qemu_irq irq, void *dma); -void pxa2xx_mmci_handlers(struct pxa2xx_mmci_s *s, qemu_irq readonly, - qemu_irq coverswitch); - -/* pxa2xx_pcmcia.c */ -struct pxa2xx_pcmcia_s; -struct pxa2xx_pcmcia_s *pxa2xx_pcmcia_init(target_phys_addr_t base); -int pxa2xx_pcmcia_attach(void *opaque, struct pcmcia_card_s *card); -int pxa2xx_pcmcia_dettach(void *opaque); -void pxa2xx_pcmcia_set_irq_cb(void *opaque, qemu_irq irq, qemu_irq cd_irq); - -/* pxa2xx_keypad.c */ -struct keymap { - int column; - int row; -}; -struct pxa2xx_keypad_s; -struct pxa2xx_keypad_s *pxa27x_keypad_init(target_phys_addr_t base, - qemu_irq irq); -void pxa27x_register_keypad(struct pxa2xx_keypad_s *kp, struct keymap *map, - int size); - -/* pxa2xx.c */ -struct pxa2xx_ssp_s; -void pxa2xx_ssp_attach(struct pxa2xx_ssp_s *port, - uint32_t (*readfn)(void *opaque), - void (*writefn)(void *opaque, uint32_t value), void *opaque); - -struct pxa2xx_i2c_s; -struct pxa2xx_i2c_s *pxa2xx_i2c_init(target_phys_addr_t base, - qemu_irq irq, uint32_t page_size); -i2c_bus *pxa2xx_i2c_bus(struct pxa2xx_i2c_s *s); - -struct pxa2xx_i2s_s; -struct pxa2xx_fir_s; - -struct pxa2xx_state_s { - CPUState *env; - qemu_irq *pic; - qemu_irq reset; - struct pxa2xx_dma_state_s *dma; - struct pxa2xx_gpio_info_s *gpio; - struct pxa2xx_lcdc_s *lcd; - struct pxa2xx_ssp_s **ssp; - struct pxa2xx_i2c_s *i2c[2]; - struct pxa2xx_mmci_s *mmc; - struct pxa2xx_pcmcia_s *pcmcia[2]; - struct pxa2xx_i2s_s *i2s; - struct pxa2xx_fir_s *fir; - struct pxa2xx_keypad_s *kp; - - /* Power management */ - target_phys_addr_t pm_base; - uint32_t pm_regs[0x40]; - - /* Clock management */ - target_phys_addr_t cm_base; - uint32_t cm_regs[4]; - uint32_t clkcfg; - - /* Memory management */ - target_phys_addr_t mm_base; - uint32_t mm_regs[0x1a]; - - /* Performance monitoring */ - uint32_t pmnc; - - /* Real-Time clock */ - target_phys_addr_t rtc_base; - uint32_t rttr; - uint32_t rtsr; - uint32_t rtar; - uint32_t rdar1; - uint32_t rdar2; - uint32_t ryar1; - uint32_t ryar2; - uint32_t swar1; - uint32_t swar2; - uint32_t piar; - uint32_t last_rcnr; - uint32_t last_rdcr; - uint32_t last_rycr; - uint32_t last_swcr; - uint32_t last_rtcpicr; - int64_t last_hz; - int64_t last_sw; - int64_t last_pi; - QEMUTimer *rtc_hz; - QEMUTimer *rtc_rdal1; - QEMUTimer *rtc_rdal2; - QEMUTimer *rtc_swal1; - QEMUTimer *rtc_swal2; - QEMUTimer *rtc_pi; -}; - -struct pxa2xx_i2s_s { - target_phys_addr_t base; - qemu_irq irq; - struct pxa2xx_dma_state_s *dma; - void (*data_req)(void *, int, int); - - uint32_t control[2]; - uint32_t status; - uint32_t mask; - uint32_t clk; - - int enable; - int rx_len; - int tx_len; - void (*codec_out)(void *, uint32_t); - uint32_t (*codec_in)(void *); - void *opaque; - - int fifo_len; - uint32_t fifo[16]; -}; - -# define PA_FMT "0x%08lx" -# define REG_FMT "0x" TARGET_FMT_plx - -struct pxa2xx_state_s *pxa270_init(unsigned int sdram_size, DisplayState *ds, - const char *revision); -struct pxa2xx_state_s *pxa255_init(unsigned int sdram_size, DisplayState *ds); - -/* usb-ohci.c */ -void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn, - qemu_irq irq); - -#endif /* PXA_H */ diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c deleted file mode 100644 index 16b3215..0000000 --- a/hw/scsi-disk.c +++ /dev/null @@ -1,809 +0,0 @@ -/* - * SCSI Device emulation - * - * Copyright (c) 2006 CodeSourcery. - * Based on code by Fabrice Bellard - * - * Written by Paul Brook - * - * This code is licenced under the LGPL. - * - * Note that this file only handles the SCSI architecture model and device - * commands. Emulation of interface/link layer protocols is handled by - * the host adapter emulator. - */ - -//#define DEBUG_SCSI - -#ifdef DEBUG_SCSI -#define DPRINTF(fmt, args...) \ -do { printf("scsi-disk: " fmt , ##args); } while (0) -#else -#define DPRINTF(fmt, args...) do {} while(0) -#endif - -#define BADF(fmt, args...) \ -do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0) - -#include "qemu-common.h" -#include "block.h" -#include "scsi-disk.h" - -#define SENSE_NO_SENSE 0 -#define SENSE_NOT_READY 2 -#define SENSE_HARDWARE_ERROR 4 -#define SENSE_ILLEGAL_REQUEST 5 - -#define SCSI_DMA_BUF_SIZE 65536 - -typedef struct SCSIRequest { - SCSIDeviceState *dev; - uint32_t tag; - /* ??? We should probably keep track of whether the data trasfer is - a read or a write. Currently we rely on the host getting it right. */ - /* Both sector and sector_count are in terms of qemu 512 byte blocks. */ - int sector; - int sector_count; - /* The amounnt of data in the buffer. */ - int buf_len; - uint8_t *dma_buf; - BlockDriverAIOCB *aiocb; - struct SCSIRequest *next; -} SCSIRequest; - -struct SCSIDeviceState -{ - BlockDriverState *bdrv; - SCSIRequest *requests; - /* The qemu block layer uses a fixed 512 byte sector size. - This is the number of 512 byte blocks in a single scsi sector. */ - int cluster_size; - int sense; - int tcq; - /* Completion functions may be called from either scsi_{read,write}_data - or from the AIO completion routines. */ - scsi_completionfn completion; - void *opaque; -}; - -/* Global pool of SCSIRequest structures. */ -static SCSIRequest *free_requests = NULL; - -static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag) -{ - SCSIRequest *r; - - if (free_requests) { - r = free_requests; - free_requests = r->next; - } else { - r = qemu_malloc(sizeof(SCSIRequest)); - r->dma_buf = qemu_memalign(512, SCSI_DMA_BUF_SIZE); - } - r->dev = s; - r->tag = tag; - r->sector_count = 0; - r->buf_len = 0; - r->aiocb = NULL; - - r->next = s->requests; - s->requests = r; - return r; -} - -static void scsi_remove_request(SCSIRequest *r) -{ - SCSIRequest *last; - SCSIDeviceState *s = r->dev; - - if (s->requests == r) { - s->requests = r->next; - } else { - last = s->requests; - while (last && last->next != r) - last = last->next; - if (last) { - last->next = r->next; - } else { - BADF("Orphaned request\n"); - } - } - r->next = free_requests; - free_requests = r; -} - -static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag) -{ - SCSIRequest *r; - - r = s->requests; - while (r && r->tag != tag) - r = r->next; - - return r; -} - -/* Helper function for command completion. */ -static void scsi_command_complete(SCSIRequest *r, int sense) -{ - SCSIDeviceState *s = r->dev; - uint32_t tag; - DPRINTF("Command complete tag=0x%x sense=%d\n", r->tag, sense); - s->sense = sense; - tag = r->tag; - scsi_remove_request(r); - s->completion(s->opaque, SCSI_REASON_DONE, tag, sense); -} - -/* Cancel a pending data transfer. */ -static void scsi_cancel_io(SCSIDevice *d, uint32_t tag) -{ - SCSIDeviceState *s = d->state; - SCSIRequest *r; - DPRINTF("Cancel tag=0x%x\n", tag); - r = scsi_find_request(s, tag); - if (r) { - if (r->aiocb) - bdrv_aio_cancel(r->aiocb); - r->aiocb = NULL; - scsi_remove_request(r); - } -} - -static void scsi_read_complete(void * opaque, int ret) -{ - SCSIRequest *r = (SCSIRequest *)opaque; - SCSIDeviceState *s = r->dev; - - if (ret) { - DPRINTF("IO error\n"); - scsi_command_complete(r, SENSE_HARDWARE_ERROR); - return; - } - DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, r->buf_len); - - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len); -} - -/* Read more data from scsi device into buffer. */ -static void scsi_read_data(SCSIDevice *d, uint32_t tag) -{ - SCSIDeviceState *s = d->state; - SCSIRequest *r; - uint32_t n; - - r = scsi_find_request(s, tag); - if (!r) { - BADF("Bad read tag 0x%x\n", tag); - /* ??? This is the wrong error. */ - scsi_command_complete(r, SENSE_HARDWARE_ERROR); - return; - } - if (r->sector_count == (uint32_t)-1) { - DPRINTF("Read buf_len=%d\n", r->buf_len); - r->sector_count = 0; - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->buf_len); - return; - } - DPRINTF("Read sector_count=%d\n", r->sector_count); - if (r->sector_count == 0) { - scsi_command_complete(r, SENSE_NO_SENSE); - return; - } - - n = r->sector_count; - if (n > SCSI_DMA_BUF_SIZE / 512) - n = SCSI_DMA_BUF_SIZE / 512; - - r->buf_len = n * 512; - r->aiocb = bdrv_aio_read(s->bdrv, r->sector, r->dma_buf, n, - scsi_read_complete, r); - if (r->aiocb == NULL) - scsi_command_complete(r, SENSE_HARDWARE_ERROR); - r->sector += n; - r->sector_count -= n; -} - -static void scsi_write_complete(void * opaque, int ret) -{ - SCSIRequest *r = (SCSIRequest *)opaque; - SCSIDeviceState *s = r->dev; - uint32_t len; - - if (ret) { - fprintf(stderr, "scsi-disc: IO write error\n"); - exit(1); - } - - r->aiocb = NULL; - if (r->sector_count == 0) { - scsi_command_complete(r, SENSE_NO_SENSE); - } else { - len = r->sector_count * 512; - if (len > SCSI_DMA_BUF_SIZE) { - len = SCSI_DMA_BUF_SIZE; - } - r->buf_len = len; - DPRINTF("Write complete tag=0x%x more=%d\n", r->tag, len); - s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len); - } -} - -/* Write data to a scsi device. Returns nonzero on failure. - The transfer may complete asynchronously. */ -static int scsi_write_data(SCSIDevice *d, uint32_t tag) -{ - SCSIDeviceState *s = d->state; - SCSIRequest *r; - uint32_t n; - - DPRINTF("Write data tag=0x%x\n", tag); - r = scsi_find_request(s, tag); - if (!r) { - BADF("Bad write tag 0x%x\n", tag); - scsi_command_complete(r, SENSE_HARDWARE_ERROR); - return 1; - } - if (r->aiocb) - BADF("Data transfer already in progress\n"); - n = r->buf_len / 512; - if (n) { - r->aiocb = bdrv_aio_write(s->bdrv, r->sector, r->dma_buf, n, - scsi_write_complete, r); - if (r->aiocb == NULL) - scsi_command_complete(r, SENSE_HARDWARE_ERROR); - r->sector += n; - r->sector_count -= n; - } else { - /* Invoke completion routine to fetch data from host. */ - scsi_write_complete(r, 0); - } - - return 0; -} - -/* Return a pointer to the data buffer. */ -static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag) -{ - SCSIDeviceState *s = d->state; - SCSIRequest *r; - - r = scsi_find_request(s, tag); - if (!r) { - BADF("Bad buffer tag 0x%x\n", tag); - return NULL; - } - return r->dma_buf; -} - -/* Execute a scsi command. Returns the length of the data expected by the - command. This will be Positive for data transfers from the device - (eg. disk reads), negative for transfers to the device (eg. disk writes), - and zero if the command does not transfer any data. */ - -static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag, - uint8_t *buf, int lun) -{ - SCSIDeviceState *s = d->state; - uint64_t nb_sectors; - uint32_t lba; - uint32_t len; - int cmdlen; - int is_write; - uint8_t command; - uint8_t *outbuf; - SCSIRequest *r; - - command = buf[0]; - r = scsi_find_request(s, tag); - if (r) { - BADF("Tag 0x%x already in use\n", tag); - scsi_cancel_io(d, tag); - } - /* ??? Tags are not unique for different luns. We only implement a - single lun, so this should not matter. */ - r = scsi_new_request(s, tag); - outbuf = r->dma_buf; - is_write = 0; - DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]); - switch (command >> 5) { - case 0: - lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16); - len = buf[4]; - cmdlen = 6; - break; - case 1: - case 2: - lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); - len = buf[8] | (buf[7] << 8); - cmdlen = 10; - break; - case 4: - lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); - len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24); - cmdlen = 16; - break; - case 5: - lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); - len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24); - cmdlen = 12; - break; - default: - BADF("Unsupported command length, command %x\n", command); - goto fail; - } -#ifdef DEBUG_SCSI - { - int i; - for (i = 1; i < cmdlen; i++) { - printf(" 0x%02x", buf[i]); - } - printf("\n"); - } -#endif - if (lun || buf[1] >> 5) { - /* Only LUN 0 supported. */ - DPRINTF("Unimplemented LUN %d\n", lun ? lun : buf[1] >> 5); - goto fail; - } - switch (command) { - case 0x0: - DPRINTF("Test Unit Ready\n"); - break; - case 0x03: - DPRINTF("Request Sense (len %d)\n", len); - if (len < 4) - goto fail; - memset(outbuf, 0, 4); - outbuf[0] = 0xf0; - outbuf[1] = 0; - outbuf[2] = s->sense; - r->buf_len = 4; - break; - case 0x12: - DPRINTF("Inquiry (len %d)\n", len); - if (buf[1] & 0x2) { - /* Command support data - optional, not implemented */ - BADF("optional INQUIRY command support request not implemented\n"); - goto fail; - } - else if (buf[1] & 0x1) { - /* Vital product data */ - uint8_t page_code = buf[2]; - if (len < 4) { - BADF("Error: Inquiry (EVPD[%02X]) buffer size %d is " - "less than 4\n", page_code, len); - goto fail; - } - - switch (page_code) { - case 0x00: - { - /* Supported page codes, mandatory */ - DPRINTF("Inquiry EVPD[Supported pages] " - "buffer size %d\n", len); - - r->buf_len = 0; - - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[r->buf_len++] = 5; - } else { - outbuf[r->buf_len++] = 0; - } - - outbuf[r->buf_len++] = 0x00; // this page - outbuf[r->buf_len++] = 0x00; - outbuf[r->buf_len++] = 3; // number of pages - outbuf[r->buf_len++] = 0x00; // list of supported pages (this page) - outbuf[r->buf_len++] = 0x80; // unit serial number - outbuf[r->buf_len++] = 0x83; // device identification - } - break; - case 0x80: - { - /* Device serial number, optional */ - if (len < 4) { - BADF("Error: EVPD[Serial number] Inquiry buffer " - "size %d too small, %d needed\n", len, 4); - goto fail; - } - - DPRINTF("Inquiry EVPD[Serial number] buffer size %d\n", len); - - r->buf_len = 0; - - /* Supported page codes */ - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[r->buf_len++] = 5; - } else { - outbuf[r->buf_len++] = 0; - } - - outbuf[r->buf_len++] = 0x80; // this page - outbuf[r->buf_len++] = 0x00; - outbuf[r->buf_len++] = 0x01; // 1 byte data follow - - outbuf[r->buf_len++] = '0'; // 1 byte data follow - } - - break; - case 0x83: - { - /* Device identification page, mandatory */ - int max_len = 255 - 8; - int id_len = strlen(bdrv_get_device_name(s->bdrv)); - if (id_len > max_len) - id_len = max_len; - - DPRINTF("Inquiry EVPD[Device identification] " - "buffer size %d\n", len); - r->buf_len = 0; - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[r->buf_len++] = 5; - } else { - outbuf[r->buf_len++] = 0; - } - - outbuf[r->buf_len++] = 0x83; // this page - outbuf[r->buf_len++] = 0x00; - outbuf[r->buf_len++] = 3 + id_len; - - outbuf[r->buf_len++] = 0x2; // ASCII - outbuf[r->buf_len++] = 0; // not officially assigned - outbuf[r->buf_len++] = 0; // reserved - outbuf[r->buf_len++] = id_len; // length of data following - - memcpy(&outbuf[r->buf_len], - bdrv_get_device_name(s->bdrv), id_len); - r->buf_len += id_len; - } - break; - default: - BADF("Error: unsupported Inquiry (EVPD[%02X]) " - "buffer size %d\n", page_code, len); - goto fail; - } - /* done with EVPD */ - break; - } - else { - /* Standard INQUIRY data */ - if (buf[2] != 0) { - BADF("Error: Inquiry (STANDARD) page or code " - "is non-zero [%02X]\n", buf[2]); - goto fail; - } - - /* PAGE CODE == 0 */ - if (len < 5) { - BADF("Error: Inquiry (STANDARD) buffer size %d " - "is less than 5\n", len); - goto fail; - } - - if (len < 36) { - BADF("Error: Inquiry (STANDARD) buffer size %d " - "is less than 36 (TODO: only 5 required)\n", len); - } - } - memset(outbuf, 0, 36); - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[0] = 5; - outbuf[1] = 0x80; - memcpy(&outbuf[16], "QEMU CD-ROM ", 16); - } else { - outbuf[0] = 0; - memcpy(&outbuf[16], "QEMU HARDDISK ", 16); - } - memcpy(&outbuf[8], "QEMU ", 8); - memcpy(&outbuf[32], QEMU_VERSION, 4); - /* Identify device as SCSI-3 rev 1. - Some later commands are also implemented. */ - outbuf[2] = 3; - outbuf[3] = 2; /* Format 2 */ - outbuf[4] = 31; - /* Sync data transfer and TCQ. */ - outbuf[7] = 0x10 | (s->tcq ? 0x02 : 0); - r->buf_len = 36; - break; - case 0x16: - DPRINTF("Reserve(6)\n"); - if (buf[1] & 1) - goto fail; - break; - case 0x17: - DPRINTF("Release(6)\n"); - if (buf[1] & 1) - goto fail; - break; - case 0x1a: - case 0x5a: - { - uint8_t *p; - int page; - - page = buf[2] & 0x3f; - DPRINTF("Mode Sense (page %d, len %d)\n", page, len); - p = outbuf; - memset(p, 0, 4); - outbuf[1] = 0; /* Default media type. */ - outbuf[3] = 0; /* Block descriptor length. */ - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - outbuf[2] = 0x80; /* Readonly. */ - } - p += 4; - if (page == 4) { - int cylinders, heads, secs; - - /* Rigid disk device geometry page. */ - p[0] = 4; - p[1] = 0x16; - /* if a geometry hint is available, use it */ - bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs); - p[2] = (cylinders >> 16) & 0xff; - p[3] = (cylinders >> 8) & 0xff; - p[4] = cylinders & 0xff; - p[5] = heads & 0xff; - /* Write precomp start cylinder, disabled */ - p[6] = (cylinders >> 16) & 0xff; - p[7] = (cylinders >> 8) & 0xff; - p[8] = cylinders & 0xff; - /* Reduced current start cylinder, disabled */ - p[9] = (cylinders >> 16) & 0xff; - p[10] = (cylinders >> 8) & 0xff; - p[11] = cylinders & 0xff; - /* Device step rate [ns], 200ns */ - p[12] = 0; - p[13] = 200; - /* Landing zone cylinder */ - p[14] = 0xff; - p[15] = 0xff; - p[16] = 0xff; - /* Medium rotation rate [rpm], 5400 rpm */ - p[20] = (5400 >> 8) & 0xff; - p[21] = 5400 & 0xff; - p += 0x16; - } else if (page == 5) { - int cylinders, heads, secs; - - /* Flexible disk device geometry page. */ - p[0] = 5; - p[1] = 0x1e; - /* Transfer rate [kbit/s], 5Mbit/s */ - p[2] = 5000 >> 8; - p[3] = 5000 & 0xff; - /* if a geometry hint is available, use it */ - bdrv_get_geometry_hint(s->bdrv, &cylinders, &heads, &secs); - p[4] = heads & 0xff; - p[5] = secs & 0xff; - p[6] = s->cluster_size * 2; - p[8] = (cylinders >> 8) & 0xff; - p[9] = cylinders & 0xff; - /* Write precomp start cylinder, disabled */ - p[10] = (cylinders >> 8) & 0xff; - p[11] = cylinders & 0xff; - /* Reduced current start cylinder, disabled */ - p[12] = (cylinders >> 8) & 0xff; - p[13] = cylinders & 0xff; - /* Device step rate [100us], 100us */ - p[14] = 0; - p[15] = 1; - /* Device step pulse width [us], 1us */ - p[16] = 1; - /* Device head settle delay [100us], 100us */ - p[17] = 0; - p[18] = 1; - /* Motor on delay [0.1s], 0.1s */ - p[19] = 1; - /* Motor off delay [0.1s], 0.1s */ - p[20] = 1; - /* Medium rotation rate [rpm], 5400 rpm */ - p[28] = (5400 >> 8) & 0xff; - p[29] = 5400 & 0xff; - p += 0x1e; - } else if ((page == 8 || page == 0x3f)) { - /* Caching page. */ - memset(p,0,20); - p[0] = 8; - p[1] = 0x12; - p[2] = 4; /* WCE */ - p += 20; - } - if ((page == 0x3f || page == 0x2a) - && (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM)) { - /* CD Capabilities and Mechanical Status page. */ - p[0] = 0x2a; - p[1] = 0x14; - p[2] = 3; // CD-R & CD-RW read - p[3] = 0; // Writing not supported - p[4] = 0x7f; /* Audio, composite, digital out, - mode 2 form 1&2, multi session */ - p[5] = 0xff; /* CD DA, DA accurate, RW supported, - RW corrected, C2 errors, ISRC, - UPC, Bar code */ - p[6] = 0x2d | (bdrv_is_locked(s->bdrv)? 2 : 0); - /* Locking supported, jumper present, eject, tray */ - p[7] = 0; /* no volume & mute control, no - changer */ - p[8] = (50 * 176) >> 8; // 50x read speed - p[9] = (50 * 176) & 0xff; - p[10] = 0 >> 8; // No volume - p[11] = 0 & 0xff; - p[12] = 2048 >> 8; // 2M buffer - p[13] = 2048 & 0xff; - p[14] = (16 * 176) >> 8; // 16x read speed current - p[15] = (16 * 176) & 0xff; - p[18] = (16 * 176) >> 8; // 16x write speed - p[19] = (16 * 176) & 0xff; - p[20] = (16 * 176) >> 8; // 16x write speed current - p[21] = (16 * 176) & 0xff; - p += 22; - } - r->buf_len = p - outbuf; - outbuf[0] = r->buf_len - 4; - if (r->buf_len > len) - r->buf_len = len; - } - break; - case 0x1b: - DPRINTF("Start Stop Unit\n"); - break; - case 0x1e: - DPRINTF("Prevent Allow Medium Removal (prevent = %d)\n", buf[4] & 3); - bdrv_set_locked(s->bdrv, buf[4] & 1); - break; - case 0x25: - DPRINTF("Read Capacity\n"); - /* The normal LEN field for this command is zero. */ - memset(outbuf, 0, 8); - bdrv_get_geometry(s->bdrv, &nb_sectors); - /* Returned value is the address of the last sector. */ - if (nb_sectors) { - nb_sectors--; - outbuf[0] = (nb_sectors >> 24) & 0xff; - outbuf[1] = (nb_sectors >> 16) & 0xff; - outbuf[2] = (nb_sectors >> 8) & 0xff; - outbuf[3] = nb_sectors & 0xff; - outbuf[4] = 0; - outbuf[5] = 0; - outbuf[6] = s->cluster_size * 2; - outbuf[7] = 0; - r->buf_len = 8; - } else { - scsi_command_complete(r, SENSE_NOT_READY); - return 0; - } - break; - case 0x08: - case 0x28: - DPRINTF("Read (sector %d, count %d)\n", lba, len); - r->sector = lba * s->cluster_size; - r->sector_count = len * s->cluster_size; - break; - case 0x0a: - case 0x2a: - DPRINTF("Write (sector %d, count %d)\n", lba, len); - r->sector = lba * s->cluster_size; - r->sector_count = len * s->cluster_size; - is_write = 1; - break; - case 0x35: - DPRINTF("Synchronise cache (sector %d, count %d)\n", lba, len); - bdrv_flush(s->bdrv); - break; - case 0x43: - { - int start_track, format, msf, toclen; - - msf = buf[1] & 2; - format = buf[2] & 0xf; - start_track = buf[6]; - bdrv_get_geometry(s->bdrv, &nb_sectors); - DPRINTF("Read TOC (track %d format %d msf %d)\n", start_track, format, msf >> 1); - switch(format) { - case 0: - toclen = cdrom_read_toc(nb_sectors, outbuf, msf, start_track); - break; - case 1: - /* multi session : only a single session defined */ - toclen = 12; - memset(outbuf, 0, 12); - outbuf[1] = 0x0a; - outbuf[2] = 0x01; - outbuf[3] = 0x01; - break; - case 2: - toclen = cdrom_read_toc_raw(nb_sectors, outbuf, msf, start_track); - break; - default: - goto error_cmd; - } - if (toclen > 0) { - if (len > toclen) - len = toclen; - r->buf_len = len; - break; - } - error_cmd: - DPRINTF("Read TOC error\n"); - goto fail; - } - case 0x46: - DPRINTF("Get Configuration (rt %d, maxlen %d)\n", buf[1] & 3, len); - memset(outbuf, 0, 8); - /* ??? This should probably return much more information. For now - just return the basic header indicating the CD-ROM profile. */ - outbuf[7] = 8; // CD-ROM - r->buf_len = 8; - break; - case 0x56: - DPRINTF("Reserve(10)\n"); - if (buf[1] & 3) - goto fail; - break; - case 0x57: - DPRINTF("Release(10)\n"); - if (buf[1] & 3) - goto fail; - break; - case 0xa0: - DPRINTF("Report LUNs (len %d)\n", len); - if (len < 16) - goto fail; - memset(outbuf, 0, 16); - outbuf[3] = 8; - r->buf_len = 16; - break; - default: - DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]); - fail: - scsi_command_complete(r, SENSE_ILLEGAL_REQUEST); - return 0; - } - if (r->sector_count == 0 && r->buf_len == 0) { - scsi_command_complete(r, SENSE_NO_SENSE); - } - len = r->sector_count * 512 + r->buf_len; - if (is_write) { - return -len; - } else { - if (!r->sector_count) - r->sector_count = -1; - return len; - } -} - -static void scsi_destroy(SCSIDevice *d) -{ - qemu_free(d->state); - qemu_free(d); -} - -SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq, - scsi_completionfn completion, void *opaque) -{ - SCSIDevice *d; - SCSIDeviceState *s; - - s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState)); - s->bdrv = bdrv; - s->tcq = tcq; - s->completion = completion; - s->opaque = opaque; - if (bdrv_get_type_hint(s->bdrv) == BDRV_TYPE_CDROM) { - s->cluster_size = 4; - } else { - s->cluster_size = 1; - } - - d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice)); - d->state = s; - d->destroy = scsi_destroy; - d->send_command = scsi_send_command; - d->read_data = scsi_read_data; - d->write_data = scsi_write_data; - d->cancel_io = scsi_cancel_io; - d->get_buf = scsi_get_buf; - - return d; -} diff --git a/hw/scsi-disk.h b/hw/scsi-disk.h deleted file mode 100644 index f42212b..0000000 --- a/hw/scsi-disk.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SCSI_DISK_H -#define SCSI_DISK_H - -/* scsi-disk.c */ -enum scsi_reason { - SCSI_REASON_DONE, /* Command complete. */ - SCSI_REASON_DATA /* Transfer complete, more data required. */ -}; - -typedef struct SCSIDeviceState SCSIDeviceState; -typedef struct SCSIDevice SCSIDevice; -typedef void (*scsi_completionfn)(void *opaque, int reason, uint32_t tag, - uint32_t arg); - -struct SCSIDevice -{ - SCSIDeviceState *state; - void (*destroy)(SCSIDevice *s); - int32_t (*send_command)(SCSIDevice *s, uint32_t tag, uint8_t *buf, - int lun); - void (*read_data)(SCSIDevice *s, uint32_t tag); - int (*write_data)(SCSIDevice *s, uint32_t tag); - void (*cancel_io)(SCSIDevice *s, uint32_t tag); - uint8_t *(*get_buf)(SCSIDevice *s, uint32_t tag); -}; - -SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq, - scsi_completionfn completion, void *opaque); -SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq, - scsi_completionfn completion, void *opaque); - -/* cdrom.c */ -int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track); -int cdrom_read_toc_raw(int nb_sectors, uint8_t *buf, int msf, int session_num); - -#endif diff --git a/hw/sd.h b/hw/sd.h deleted file mode 100644 index f310062..0000000 --- a/hw/sd.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * include/linux/mmc/sd.h - * - * Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved. - * - * 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. - */ - -#ifndef MMC_SD_H -#define MMC_SD_H - -/* SD commands type argument response */ - /* class 0 */ -/* This is basically the same command as for MMC with some quirks. */ -#define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ -#define SD_SEND_IF_COND 8 /* bcr [11:0] See below R7 */ - - /* class 10 */ -#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ - - /* Application commands */ -#define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ -#define SD_APP_SEND_NUM_WR_BLKS 22 /* adtc R1 */ -#define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ -#define SD_APP_SEND_SCR 51 /* adtc R1 */ - -/* - * SD_SWITCH argument format: - * - * [31] Check (0) or switch (1) - * [30:24] Reserved (0) - * [23:20] Function group 6 - * [19:16] Function group 5 - * [15:12] Function group 4 - * [11:8] Function group 3 - * [7:4] Function group 2 - * [3:0] Function group 1 - */ - -/* - * SD_SEND_IF_COND argument format: - * - * [31:12] Reserved (0) - * [11:8] Host Voltage Supply Flags - * [7:0] Check Pattern (0xAA) - */ - -/* - * SCR field definitions - */ - -#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ -#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ -#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */ - -/* - * SD bus widths - */ -#define SD_BUS_WIDTH_1 0 -#define SD_BUS_WIDTH_4 2 - -/* - * SD_SWITCH mode - */ -#define SD_SWITCH_CHECK 0 -#define SD_SWITCH_SET 1 - -/* - * SD_SWITCH function groups - */ -#define SD_SWITCH_GRP_ACCESS 0 - -/* - * SD_SWITCH access modes - */ -#define SD_SWITCH_ACCESS_DEF 0 -#define SD_SWITCH_ACCESS_HS 1 - -#endif - diff --git a/hw/smc91c111.c b/hw/smc91c111.c deleted file mode 100644 index 410051d..0000000 --- a/hw/smc91c111.c +++ /dev/null @@ -1,715 +0,0 @@ -/* - * SMSC 91C111 Ethernet interface emulation - * - * Copyright (c) 2005 CodeSourcery, LLC. - * Written by Paul Brook - * - * This code is licenced under the GPL - */ - -#include "hw.h" -#include "net.h" -#include "devices.h" -/* For crc32 */ -#include <zlib.h> - -/* Number of 2k memory pages available. */ -#define NUM_PACKETS 4 - -typedef struct { - uint32_t base; - VLANClientState *vc; - uint16_t tcr; - uint16_t rcr; - uint16_t cr; - uint16_t ctr; - uint16_t gpr; - uint16_t ptr; - uint16_t ercv; - qemu_irq irq; - int bank; - int packet_num; - int tx_alloc; - /* Bitmask of allocated packets. */ - int allocated; - int tx_fifo_len; - int tx_fifo[NUM_PACKETS]; - int rx_fifo_len; - int rx_fifo[NUM_PACKETS]; - int tx_fifo_done_len; - int tx_fifo_done[NUM_PACKETS]; - /* Packet buffer memory. */ - uint8_t data[NUM_PACKETS][2048]; - uint8_t int_level; - uint8_t int_mask; - uint8_t macaddr[6]; -} smc91c111_state; - -#define RCR_SOFT_RST 0x8000 -#define RCR_STRIP_CRC 0x0200 -#define RCR_RXEN 0x0100 - -#define TCR_EPH_LOOP 0x2000 -#define TCR_NOCRC 0x0100 -#define TCR_PAD_EN 0x0080 -#define TCR_FORCOL 0x0004 -#define TCR_LOOP 0x0002 -#define TCR_TXEN 0x0001 - -#define INT_MD 0x80 -#define INT_ERCV 0x40 -#define INT_EPH 0x20 -#define INT_RX_OVRN 0x10 -#define INT_ALLOC 0x08 -#define INT_TX_EMPTY 0x04 -#define INT_TX 0x02 -#define INT_RCV 0x01 - -#define CTR_AUTO_RELEASE 0x0800 -#define CTR_RELOAD 0x0002 -#define CTR_STORE 0x0001 - -#define RS_ALGNERR 0x8000 -#define RS_BRODCAST 0x4000 -#define RS_BADCRC 0x2000 -#define RS_ODDFRAME 0x1000 -#define RS_TOOLONG 0x0800 -#define RS_TOOSHORT 0x0400 -#define RS_MULTICAST 0x0001 - -/* Update interrupt status. */ -static void smc91c111_update(smc91c111_state *s) -{ - int level; - - if (s->tx_fifo_len == 0) - s->int_level |= INT_TX_EMPTY; - if (s->tx_fifo_done_len != 0) - s->int_level |= INT_TX; - level = (s->int_level & s->int_mask) != 0; - qemu_set_irq(s->irq, level); -} - -/* Try to allocate a packet. Returns 0x80 on failure. */ -static int smc91c111_allocate_packet(smc91c111_state *s) -{ - int i; - if (s->allocated == (1 << NUM_PACKETS) - 1) { - return 0x80; - } - - for (i = 0; i < NUM_PACKETS; i++) { - if ((s->allocated & (1 << i)) == 0) - break; - } - s->allocated |= 1 << i; - return i; -} - - -/* Process a pending TX allocate. */ -static void smc91c111_tx_alloc(smc91c111_state *s) -{ - s->tx_alloc = smc91c111_allocate_packet(s); - if (s->tx_alloc == 0x80) - return; - s->int_level |= INT_ALLOC; - smc91c111_update(s); -} - -/* Remove and item from the RX FIFO. */ -static void smc91c111_pop_rx_fifo(smc91c111_state *s) -{ - int i; - - s->rx_fifo_len--; - if (s->rx_fifo_len) { - for (i = 0; i < s->rx_fifo_len; i++) - s->rx_fifo[i] = s->rx_fifo[i + 1]; - s->int_level |= INT_RCV; - } else { - s->int_level &= ~INT_RCV; - } - smc91c111_update(s); -} - -/* Remove an item from the TX completion FIFO. */ -static void smc91c111_pop_tx_fifo_done(smc91c111_state *s) -{ - int i; - - if (s->tx_fifo_done_len == 0) - return; - s->tx_fifo_done_len--; - for (i = 0; i < s->tx_fifo_done_len; i++) - s->tx_fifo_done[i] = s->tx_fifo_done[i + 1]; -} - -/* Release the memory allocated to a packet. */ -static void smc91c111_release_packet(smc91c111_state *s, int packet) -{ - s->allocated &= ~(1 << packet); - if (s->tx_alloc == 0x80) - smc91c111_tx_alloc(s); -} - -/* Flush the TX FIFO. */ -static void smc91c111_do_tx(smc91c111_state *s) -{ - int i; - int len; - int control; - int add_crc; - int packetnum; - uint8_t *p; - - if ((s->tcr & TCR_TXEN) == 0) - return; - if (s->tx_fifo_len == 0) - return; - for (i = 0; i < s->tx_fifo_len; i++) { - packetnum = s->tx_fifo[i]; - p = &s->data[packetnum][0]; - /* Set status word. */ - *(p++) = 0x01; - *(p++) = 0x40; - len = *(p++); - len |= ((int)*(p++)) << 8; - len -= 6; - control = p[len + 1]; - if (control & 0x20) - len++; - /* ??? This overwrites the data following the buffer. - Don't know what real hardware does. */ - if (len < 64 && (s->tcr & TCR_PAD_EN)) { - memset(p + len, 0, 64 - len); - len = 64; - } -#if 0 - /* The card is supposed to append the CRC to the frame. However - none of the other network traffic has the CRC appended. - Suspect this is low level ethernet detail we don't need to worry - about. */ - add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0; - if (add_crc) { - uint32_t crc; - - crc = crc32(~0, p, len); - memcpy(p + len, &crc, 4); - len += 4; - } -#else - add_crc = 0; -#endif - if (s->ctr & CTR_AUTO_RELEASE) - /* Race? */ - smc91c111_release_packet(s, packetnum); - else if (s->tx_fifo_done_len < NUM_PACKETS) - s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum; - qemu_send_packet(s->vc, p, len); - } - s->tx_fifo_len = 0; - smc91c111_update(s); -} - -/* Add a packet to the TX FIFO. */ -static void smc91c111_queue_tx(smc91c111_state *s, int packet) -{ - if (s->tx_fifo_len == NUM_PACKETS) - return; - s->tx_fifo[s->tx_fifo_len++] = packet; - smc91c111_do_tx(s); -} - -static void smc91c111_reset(smc91c111_state *s) -{ - s->bank = 0; - s->tx_fifo_len = 0; - s->tx_fifo_done_len = 0; - s->rx_fifo_len = 0; - s->allocated = 0; - s->packet_num = 0; - s->tx_alloc = 0; - s->tcr = 0; - s->rcr = 0; - s->cr = 0xa0b1; - s->ctr = 0x1210; - s->ptr = 0; - s->ercv = 0x1f; - s->int_level = INT_TX_EMPTY; - s->int_mask = 0; - smc91c111_update(s); -} - -#define SET_LOW(name, val) s->name = (s->name & 0xff00) | val -#define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8) - -static void smc91c111_writeb(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - smc91c111_state *s = (smc91c111_state *)opaque; - - offset -= s->base; - if (offset == 14) { - s->bank = value; - return; - } - if (offset == 15) - return; - switch (s->bank) { - case 0: - switch (offset) { - case 0: /* TCR */ - SET_LOW(tcr, value); - return; - case 1: - SET_HIGH(tcr, value); - return; - case 4: /* RCR */ - SET_LOW(rcr, value); - return; - case 5: - SET_HIGH(rcr, value); - if (s->rcr & RCR_SOFT_RST) - smc91c111_reset(s); - return; - case 10: case 11: /* RPCR */ - /* Ignored */ - return; - } - break; - - case 1: - switch (offset) { - case 0: /* CONFIG */ - SET_LOW(cr, value); - return; - case 1: - SET_HIGH(cr,value); - return; - case 2: case 3: /* BASE */ - case 4: case 5: case 6: case 7: case 8: case 9: /* IA */ - /* Not implemented. */ - return; - case 10: /* Genral Purpose */ - SET_LOW(gpr, value); - return; - case 11: - SET_HIGH(gpr, value); - return; - case 12: /* Control */ - if (value & 1) - fprintf(stderr, "smc91c111:EEPROM store not implemented\n"); - if (value & 2) - fprintf(stderr, "smc91c111:EEPROM reload not implemented\n"); - value &= ~3; - SET_LOW(ctr, value); - return; - case 13: - SET_HIGH(ctr, value); - return; - } - break; - - case 2: - switch (offset) { - case 0: /* MMU Command */ - switch (value >> 5) { - case 0: /* no-op */ - break; - case 1: /* Allocate for TX. */ - s->tx_alloc = 0x80; - s->int_level &= ~INT_ALLOC; - smc91c111_update(s); - smc91c111_tx_alloc(s); - break; - case 2: /* Reset MMU. */ - s->allocated = 0; - s->tx_fifo_len = 0; - s->tx_fifo_done_len = 0; - s->rx_fifo_len = 0; - s->tx_alloc = 0; - break; - case 3: /* Remove from RX FIFO. */ - smc91c111_pop_rx_fifo(s); - break; - case 4: /* Remove from RX FIFO and release. */ - if (s->rx_fifo_len > 0) { - smc91c111_release_packet(s, s->rx_fifo[0]); - } - smc91c111_pop_rx_fifo(s); - break; - case 5: /* Release. */ - smc91c111_release_packet(s, s->packet_num); - break; - case 6: /* Add to TX FIFO. */ - smc91c111_queue_tx(s, s->packet_num); - break; - case 7: /* Reset TX FIFO. */ - s->tx_fifo_len = 0; - s->tx_fifo_done_len = 0; - break; - } - return; - case 1: - /* Ignore. */ - return; - case 2: /* Packet Number Register */ - s->packet_num = value; - return; - case 3: case 4: case 5: - /* Should be readonly, but linux writes to them anyway. Ignore. */ - return; - case 6: /* Pointer */ - SET_LOW(ptr, value); - return; - case 7: - SET_HIGH(ptr, value); - return; - case 8: case 9: case 10: case 11: /* Data */ - { - int p; - int n; - - if (s->ptr & 0x8000) - n = s->rx_fifo[0]; - else - n = s->packet_num; - p = s->ptr & 0x07ff; - if (s->ptr & 0x4000) { - s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff); - } else { - p += (offset & 3); - } - s->data[n][p] = value; - } - return; - case 12: /* Interrupt ACK. */ - s->int_level &= ~(value & 0xd6); - if (value & INT_TX) - smc91c111_pop_tx_fifo_done(s); - smc91c111_update(s); - return; - case 13: /* Interrupt mask. */ - s->int_mask = value; - smc91c111_update(s); - return; - } - break;; - - case 3: - switch (offset) { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - /* Multicast table. */ - /* Not implemented. */ - return; - case 8: case 9: /* Management Interface. */ - /* Not implemented. */ - return; - case 12: /* Early receive. */ - s->ercv = value & 0x1f; - case 13: - /* Ignore. */ - return; - } - break; - } - cpu_abort (cpu_single_env, "smc91c111_write: Bad reg %d:%x\n", - s->bank, (int)offset); -} - -static uint32_t smc91c111_readb(void *opaque, target_phys_addr_t offset) -{ - smc91c111_state *s = (smc91c111_state *)opaque; - - offset -= s->base; - if (offset == 14) { - return s->bank; - } - if (offset == 15) - return 0x33; - switch (s->bank) { - case 0: - switch (offset) { - case 0: /* TCR */ - return s->tcr & 0xff; - case 1: - return s->tcr >> 8; - case 2: /* EPH Status */ - return 0; - case 3: - return 0x40; - case 4: /* RCR */ - return s->rcr & 0xff; - case 5: - return s->rcr >> 8; - case 6: /* Counter */ - case 7: - /* Not implemented. */ - return 0; - case 8: /* Memory size. */ - return NUM_PACKETS; - case 9: /* Free memory available. */ - { - int i; - int n; - n = 0; - for (i = 0; i < NUM_PACKETS; i++) { - if (s->allocated & (1 << i)) - n++; - } - return n; - } - case 10: case 11: /* RPCR */ - /* Not implemented. */ - return 0; - } - break; - - case 1: - switch (offset) { - case 0: /* CONFIG */ - return s->cr & 0xff; - case 1: - return s->cr >> 8; - case 2: case 3: /* BASE */ - /* Not implemented. */ - return 0; - case 4: case 5: case 6: case 7: case 8: case 9: /* IA */ - return s->macaddr[offset - 4]; - case 10: /* General Purpose */ - return s->gpr & 0xff; - case 11: - return s->gpr >> 8; - case 12: /* Control */ - return s->ctr & 0xff; - case 13: - return s->ctr >> 8; - } - break; - - case 2: - switch (offset) { - case 0: case 1: /* MMUCR Busy bit. */ - return 0; - case 2: /* Packet Number. */ - return s->packet_num; - case 3: /* Allocation Result. */ - return s->tx_alloc; - case 4: /* TX FIFO */ - if (s->tx_fifo_done_len == 0) - return 0x80; - else - return s->tx_fifo_done[0]; - case 5: /* RX FIFO */ - if (s->rx_fifo_len == 0) - return 0x80; - else - return s->rx_fifo[0]; - case 6: /* Pointer */ - return s->ptr & 0xff; - case 7: - return (s->ptr >> 8) & 0xf7; - case 8: case 9: case 10: case 11: /* Data */ - { - int p; - int n; - - if (s->ptr & 0x8000) - n = s->rx_fifo[0]; - else - n = s->packet_num; - p = s->ptr & 0x07ff; - if (s->ptr & 0x4000) { - s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff); - } else { - p += (offset & 3); - } - return s->data[n][p]; - } - case 12: /* Interrupt status. */ - return s->int_level; - case 13: /* Interrupt mask. */ - return s->int_mask; - } - break; - - case 3: - switch (offset) { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - /* Multicast table. */ - /* Not implemented. */ - return 0; - case 8: /* Management Interface. */ - /* Not implemented. */ - return 0x30; - case 9: - return 0x33; - case 10: /* Revision. */ - return 0x91; - case 11: - return 0x33; - case 12: - return s->ercv; - case 13: - return 0; - } - break; - } - cpu_abort (cpu_single_env, "smc91c111_read: Bad reg %d:%x\n", - s->bank, (int)offset); - return 0; -} - -static void smc91c111_writew(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - smc91c111_writeb(opaque, offset, value & 0xff); - smc91c111_writeb(opaque, offset + 1, value >> 8); -} - -static void smc91c111_writel(void *opaque, target_phys_addr_t offset, - uint32_t value) -{ - smc91c111_state *s = (smc91c111_state *)opaque; - /* 32-bit writes to offset 0xc only actually write to the bank select - register (offset 0xe) */ - if (offset != s->base + 0xc) - smc91c111_writew(opaque, offset, value & 0xffff); - smc91c111_writew(opaque, offset + 2, value >> 16); -} - -static uint32_t smc91c111_readw(void *opaque, target_phys_addr_t offset) -{ - uint32_t val; - val = smc91c111_readb(opaque, offset); - val |= smc91c111_readb(opaque, offset + 1) << 8; - return val; -} - -static uint32_t smc91c111_readl(void *opaque, target_phys_addr_t offset) -{ - uint32_t val; - val = smc91c111_readw(opaque, offset); - val |= smc91c111_readw(opaque, offset + 2) << 16; - return val; -} - -static int smc91c111_can_receive(void *opaque) -{ - smc91c111_state *s = (smc91c111_state *)opaque; - - if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) - return 1; - if (s->allocated == (1 << NUM_PACKETS) - 1) - return 0; - return 1; -} - -static void smc91c111_receive(void *opaque, const uint8_t *buf, int size) -{ - smc91c111_state *s = (smc91c111_state *)opaque; - int status; - int packetsize; - uint32_t crc; - int packetnum; - uint8_t *p; - - if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) - return; - /* Short packets are padded with zeros. Receiving a packet - < 64 bytes long is considered an error condition. */ - if (size < 64) - packetsize = 64; - else - packetsize = (size & ~1); - packetsize += 6; - crc = (s->rcr & RCR_STRIP_CRC) == 0; - if (crc) - packetsize += 4; - /* TODO: Flag overrun and receive errors. */ - if (packetsize > 2048) - return; - packetnum = smc91c111_allocate_packet(s); - if (packetnum == 0x80) - return; - s->rx_fifo[s->rx_fifo_len++] = packetnum; - - p = &s->data[packetnum][0]; - /* ??? Multicast packets? */ - status = 0; - if (size > 1518) - status |= RS_TOOLONG; - if (size & 1) - status |= RS_ODDFRAME; - *(p++) = status & 0xff; - *(p++) = status >> 8; - *(p++) = packetsize & 0xff; - *(p++) = packetsize >> 8; - memcpy(p, buf, size & ~1); - p += (size & ~1); - /* Pad short packets. */ - if (size < 64) { - int pad; - - if (size & 1) - *(p++) = buf[size - 1]; - pad = 64 - size; - memset(p, 0, pad); - p += pad; - size = 64; - } - /* It's not clear if the CRC should go before or after the last byte in - odd sized packets. Linux disables the CRC, so that's no help. - The pictures in the documentation show the CRC aligned on a 16-bit - boundary before the last odd byte, so that's what we do. */ - if (crc) { - crc = crc32(~0, buf, size); - *(p++) = crc & 0xff; crc >>= 8; - *(p++) = crc & 0xff; crc >>= 8; - *(p++) = crc & 0xff; crc >>= 8; - *(p++) = crc & 0xff; crc >>= 8; - } - if (size & 1) { - *(p++) = buf[size - 1]; - *(p++) = 0x60; - } else { - *(p++) = 0; - *(p++) = 0x40; - } - /* TODO: Raise early RX interrupt? */ - s->int_level |= INT_RCV; - smc91c111_update(s); -} - -static CPUReadMemoryFunc *smc91c111_readfn[] = { - smc91c111_readb, - smc91c111_readw, - smc91c111_readl -}; - -static CPUWriteMemoryFunc *smc91c111_writefn[] = { - smc91c111_writeb, - smc91c111_writew, - smc91c111_writel -}; - -void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq) -{ - smc91c111_state *s; - int iomemtype; - - s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state)); - iomemtype = cpu_register_io_memory(0, smc91c111_readfn, - smc91c111_writefn, s); - cpu_register_physical_memory(base, 16, iomemtype); - s->base = base; - s->irq = irq; - memcpy(s->macaddr, nd->macaddr, 6); - - smc91c111_reset(s); - - s->vc = qemu_new_vlan_client(nd->vlan, smc91c111_receive, - smc91c111_can_receive, s); - /* ??? Save/restore. */ -} diff --git a/hw/usb-hid.c b/hw/usb-hid.c deleted file mode 100644 index 406c9ab..0000000 --- a/hw/usb-hid.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - * QEMU USB HID devices - * - * Copyright (c) 2005 Fabrice Bellard - * Copyright (c) 2007 OpenMoko, Inc. (andrew@openedhand.com) - * - * 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 "hw.h" -#include "console.h" -#include "usb.h" - -/* HID interface requests */ -#define GET_REPORT 0xa101 -#define GET_IDLE 0xa102 -#define GET_PROTOCOL 0xa103 -#define SET_REPORT 0x2109 -#define SET_IDLE 0x210a -#define SET_PROTOCOL 0x210b - -/* HID descriptor types */ -#define USB_DT_HID 0x21 -#define USB_DT_REPORT 0x22 -#define USB_DT_PHY 0x23 - -#define USB_MOUSE 1 -#define USB_TABLET 2 -#define USB_KEYBOARD 3 - -typedef struct USBMouseState { - int dx, dy, dz, buttons_state; - int x, y; - int mouse_grabbed; - QEMUPutMouseEntry *eh_entry; -} USBMouseState; - -typedef struct USBKeyboardState { - uint16_t modifiers; - uint8_t leds; - uint8_t key[16]; - int keys; -} USBKeyboardState; - -typedef struct USBHIDState { - USBDevice dev; - union { - USBMouseState ptr; - USBKeyboardState kbd; - }; - int kind; - int protocol; - int idle; - int changed; -} USBHIDState; - -/* mostly the same values as the Bochs USB Mouse device */ -static const uint8_t qemu_mouse_dev_descriptor[] = { - 0x12, /* u8 bLength; */ - 0x01, /* u8 bDescriptorType; Device */ - 0x00, 0x01, /* u16 bcdUSB; v1.0 */ - - 0x00, /* u8 bDeviceClass; */ - 0x00, /* u8 bDeviceSubClass; */ - 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */ - 0x08, /* u8 bMaxPacketSize0; 8 Bytes */ - - 0x27, 0x06, /* u16 idVendor; */ - 0x01, 0x00, /* u16 idProduct; */ - 0x00, 0x00, /* u16 bcdDevice */ - - 0x03, /* u8 iManufacturer; */ - 0x02, /* u8 iProduct; */ - 0x01, /* u8 iSerialNumber; */ - 0x01 /* u8 bNumConfigurations; */ -}; - -static const uint8_t qemu_mouse_config_descriptor[] = { - /* one configuration */ - 0x09, /* u8 bLength; */ - 0x02, /* u8 bDescriptorType; Configuration */ - 0x22, 0x00, /* u16 wTotalLength; */ - 0x01, /* u8 bNumInterfaces; (1) */ - 0x01, /* u8 bConfigurationValue; */ - 0x04, /* u8 iConfiguration; */ - 0xa0, /* u8 bmAttributes; - Bit 7: must be set, - 6: Self-powered, - 5: Remote wakeup, - 4..0: resvd */ - 50, /* u8 MaxPower; */ - - /* USB 1.1: - * USB 2.0, single TT organization (mandatory): - * one interface, protocol 0 - * - * USB 2.0, multiple TT organization (optional): - * two interfaces, protocols 1 (like single TT) - * and 2 (multiple TT mode) ... config is - * sometimes settable - * NOT IMPLEMENTED - */ - - /* 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; */ - 0x01, /* u8 if_bInterfaceSubClass; */ - 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ - 0x07, /* u8 if_iInterface; */ - - /* HID descriptor */ - 0x09, /* u8 bLength; */ - 0x21, /* u8 bDescriptorType; */ - 0x01, 0x00, /* u16 HID_class */ - 0x00, /* u8 country_code */ - 0x01, /* u8 num_descriptors */ - 0x22, /* u8 type; Report */ - 52, 0, /* 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 */ - 0x04, 0x00, /* u16 ep_wMaxPacketSize; */ - 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ -}; - -static const uint8_t qemu_tablet_config_descriptor[] = { - /* one configuration */ - 0x09, /* u8 bLength; */ - 0x02, /* u8 bDescriptorType; Configuration */ - 0x22, 0x00, /* u16 wTotalLength; */ - 0x01, /* u8 bNumInterfaces; (1) */ - 0x01, /* u8 bConfigurationValue; */ - 0x05, /* u8 iConfiguration; */ - 0xa0, /* u8 bmAttributes; - Bit 7: must be set, - 6: Self-powered, - 5: Remote wakeup, - 4..0: resvd */ - 50, /* u8 MaxPower; */ - - /* USB 1.1: - * USB 2.0, single TT organization (mandatory): - * one interface, protocol 0 - * - * USB 2.0, multiple TT organization (optional): - * two interfaces, protocols 1 (like single TT) - * and 2 (multiple TT mode) ... config is - * sometimes settable - * NOT IMPLEMENTED - */ - - /* 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; */ - 0x01, /* u8 if_bInterfaceSubClass; */ - 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ - 0x07, /* u8 if_iInterface; */ - - /* HID descriptor */ - 0x09, /* u8 bLength; */ - 0x21, /* u8 bDescriptorType; */ - 0x01, 0x00, /* u16 HID_class */ - 0x00, /* u8 country_code */ - 0x01, /* u8 num_descriptors */ - 0x22, /* u8 type; Report */ - 74, 0, /* 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; (255ms -- usb 2.0 spec) */ -}; - -static const uint8_t qemu_keyboard_config_descriptor[] = { - /* one configuration */ - 0x09, /* u8 bLength; */ - USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */ - 0x22, 0x00, /* u16 wTotalLength; */ - 0x01, /* u8 bNumInterfaces; (1) */ - 0x01, /* u8 bConfigurationValue; */ - 0x06, /* u8 iConfiguration; */ - 0xa0, /* u8 bmAttributes; - Bit 7: must be set, - 6: Self-powered, - 5: Remote wakeup, - 4..0: resvd */ - 0x32, /* u8 MaxPower; */ - - /* USB 1.1: - * USB 2.0, single TT organization (mandatory): - * one interface, protocol 0 - * - * USB 2.0, multiple TT organization (optional): - * two interfaces, protocols 1 (like single TT) - * and 2 (multiple TT mode) ... config is - * sometimes settable - * NOT IMPLEMENTED - */ - - /* one interface */ - 0x09, /* u8 if_bLength; */ - USB_DT_INTERFACE, /* 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 */ - 0x01, /* u8 if_bInterfaceProtocol; Keyboard */ - 0x07, /* u8 if_iInterface; */ - - /* HID descriptor */ - 0x09, /* u8 bLength; */ - USB_DT_HID, /* u8 bDescriptorType; */ - 0x11, 0x01, /* u16 HID_class */ - 0x00, /* u8 country_code */ - 0x01, /* u8 num_descriptors */ - USB_DT_REPORT, /* u8 type; Report */ - 0x3f, 0x00, /* u16 len */ - - /* one endpoint (status change endpoint) */ - 0x07, /* u8 ep_bLength; */ - USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */ - USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* u8 ep_bmAttributes; Interrupt */ - 0x08, 0x00, /* u16 ep_wMaxPacketSize; */ - 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ -}; - -static const uint8_t qemu_mouse_hid_report_descriptor[] = { - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x02, /* Usage (Mouse) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xa1, 0x00, /* Collection (Physical) */ - 0x05, 0x09, /* Usage Page (Button) */ - 0x19, 0x01, /* Usage Minimum (1) */ - 0x29, 0x03, /* Usage Maximum (3) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x95, 0x03, /* Report Count (3) */ - 0x75, 0x01, /* Report Size (1) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - 0x95, 0x01, /* Report Count (1) */ - 0x75, 0x05, /* Report Size (5) */ - 0x81, 0x01, /* Input (Constant) */ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x30, /* Usage (X) */ - 0x09, 0x31, /* Usage (Y) */ - 0x09, 0x38, /* Usage (Wheel) */ - 0x15, 0x81, /* Logical Minimum (-0x7f) */ - 0x25, 0x7f, /* Logical Maximum (0x7f) */ - 0x75, 0x08, /* Report Size (8) */ - 0x95, 0x03, /* Report Count (3) */ - 0x81, 0x06, /* Input (Data, Variable, Relative) */ - 0xc0, /* End Collection */ - 0xc0, /* End Collection */ -}; - -static const uint8_t qemu_tablet_hid_report_descriptor[] = { - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x09, 0x01, /* Usage (Pointer) */ - 0xa1, 0x00, /* Collection (Physical) */ - 0x05, 0x09, /* Usage Page (Button) */ - 0x19, 0x01, /* Usage Minimum (1) */ - 0x29, 0x03, /* Usage Maximum (3) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x95, 0x03, /* Report Count (3) */ - 0x75, 0x01, /* Report Size (1) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - 0x95, 0x01, /* Report Count (1) */ - 0x75, 0x05, /* Report Size (5) */ - 0x81, 0x01, /* Input (Constant) */ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x30, /* Usage (X) */ - 0x09, 0x31, /* Usage (Y) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x26, 0xff, 0x7f, /* Logical Maximum (0x7fff) */ - 0x35, 0x00, /* Physical Minimum (0) */ - 0x46, 0xff, 0x7f, /* Physical Maximum (0x7fff) */ - 0x75, 0x10, /* Report Size (16) */ - 0x95, 0x02, /* Report Count (2) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x38, /* Usage (Wheel) */ - 0x15, 0x81, /* Logical Minimum (-0x7f) */ - 0x25, 0x7f, /* Logical Maximum (0x7f) */ - 0x35, 0x00, /* Physical Minimum (same as logical) */ - 0x45, 0x00, /* Physical Maximum (same as logical) */ - 0x75, 0x08, /* Report Size (8) */ - 0x95, 0x01, /* Report Count (1) */ - 0x81, 0x06, /* Input (Data, Variable, Relative) */ - 0xc0, /* End Collection */ - 0xc0, /* End Collection */ -}; - -static const uint8_t qemu_keyboard_hid_report_descriptor[] = { - 0x05, 0x01, /* Usage Page (Generic Desktop) */ - 0x09, 0x06, /* Usage (Keyboard) */ - 0xa1, 0x01, /* Collection (Application) */ - 0x75, 0x01, /* Report Size (1) */ - 0x95, 0x08, /* Report Count (8) */ - 0x05, 0x07, /* Usage Page (Key Codes) */ - 0x19, 0xe0, /* Usage Minimum (224) */ - 0x29, 0xe7, /* Usage Maximum (231) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0x01, /* Logical Maximum (1) */ - 0x81, 0x02, /* Input (Data, Variable, Absolute) */ - 0x95, 0x01, /* Report Count (1) */ - 0x75, 0x08, /* Report Size (8) */ - 0x81, 0x01, /* Input (Constant) */ - 0x95, 0x05, /* Report Count (5) */ - 0x75, 0x01, /* Report Size (1) */ - 0x05, 0x08, /* Usage Page (LEDs) */ - 0x19, 0x01, /* Usage Minimum (1) */ - 0x29, 0x05, /* Usage Maximum (5) */ - 0x91, 0x02, /* Output (Data, Variable, Absolute) */ - 0x95, 0x01, /* Report Count (1) */ - 0x75, 0x03, /* Report Size (3) */ - 0x91, 0x01, /* Output (Constant) */ - 0x95, 0x06, /* Report Count (6) */ - 0x75, 0x08, /* Report Size (8) */ - 0x15, 0x00, /* Logical Minimum (0) */ - 0x25, 0xff, /* Logical Maximum (255) */ - 0x05, 0x07, /* Usage Page (Key Codes) */ - 0x19, 0x00, /* Usage Minimum (0) */ - 0x29, 0xff, /* Usage Maximum (255) */ - 0x81, 0x00, /* Input (Data, Array) */ - 0xc0, /* End Collection */ -}; - -#define USB_HID_USAGE_ERROR_ROLLOVER 0x01 -#define USB_HID_USAGE_POSTFAIL 0x02 -#define USB_HID_USAGE_ERROR_UNDEFINED 0x03 - -/* Indices are QEMU keycodes, values are from HID Usage Table. Indices - * above 0x80 are for keys that come after 0xe0 or 0xe1+0x1d or 0xe1+0x9d. */ -static const uint8_t usb_hid_usage_keys[0x100] = { - 0x00, 0x29, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, - 0x24, 0x25, 0x26, 0x27, 0x2d, 0x2e, 0x2a, 0x2b, - 0x14, 0x1a, 0x08, 0x15, 0x17, 0x1c, 0x18, 0x0c, - 0x12, 0x13, 0x2f, 0x30, 0x28, 0xe0, 0x04, 0x16, - 0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33, - 0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19, - 0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55, - 0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, - 0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f, - 0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59, - 0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44, - 0x45, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, - 0xe8, 0xe9, 0x71, 0x72, 0x73, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, - - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x58, 0xe4, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x46, - 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a, - 0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d, - 0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -static void usb_mouse_event(void *opaque, - int dx1, int dy1, int dz1, int buttons_state) -{ - USBHIDState *hs = opaque; - USBMouseState *s = &hs->ptr; - - s->dx += dx1; - s->dy += dy1; - s->dz += dz1; - s->buttons_state = buttons_state; - hs->changed = 1; -} - -static void usb_tablet_event(void *opaque, - int x, int y, int dz, int buttons_state) -{ - USBHIDState *hs = opaque; - USBMouseState *s = &hs->ptr; - - s->x = x; - s->y = y; - s->dz += dz; - s->buttons_state = buttons_state; - hs->changed = 1; -} - -static void usb_keyboard_event(void *opaque, int keycode) -{ - USBHIDState *hs = opaque; - USBKeyboardState *s = &hs->kbd; - uint8_t hid_code, key; - int i; - - key = keycode & 0x7f; - hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))]; - s->modifiers &= ~(1 << 8); - - hs->changed = 1; - - switch (hid_code) { - case 0x00: - return; - - case 0xe0: - if (s->modifiers & (1 << 9)) { - s->modifiers ^= 3 << 8; - return; - } - case 0xe1 ... 0xe7: - if (keycode & (1 << 7)) { - s->modifiers &= ~(1 << (hid_code & 0x0f)); - return; - } - case 0xe8 ... 0xef: - s->modifiers |= 1 << (hid_code & 0x0f); - return; - } - - if (keycode & (1 << 7)) { - for (i = s->keys - 1; i >= 0; i --) - if (s->key[i] == hid_code) { - s->key[i] = s->key[-- s->keys]; - s->key[s->keys] = 0x00; - return; - } - } else { - for (i = s->keys - 1; i >= 0; i --) - if (s->key[i] == hid_code) - return; - if (s->keys < sizeof(s->key)) - s->key[s->keys ++] = hid_code; - } -} - -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(USBHIDState *hs, uint8_t *buf, int len) -{ - int dx, dy, dz, b, l; - USBMouseState *s = &hs->ptr; - - if (!s->mouse_grabbed) { - s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, hs, - 0, "QEMU USB Mouse"); - s->mouse_grabbed = 1; - } - - dx = int_clamp(s->dx, -127, 127); - dy = int_clamp(s->dy, -127, 127); - dz = int_clamp(s->dz, -127, 127); - - s->dx -= dx; - s->dy -= dy; - s->dz -= dz; - - /* Appears we have to invert the wheel direction */ - dz = 0 - 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; - - l = 0; - if (len > l) - buf[l ++] = b; - if (len > l) - buf[l ++] = dx; - if (len > l) - buf[l ++] = dy; - if (len > l) - buf[l ++] = dz; - return l; -} - -static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len) -{ - int dz, b, l; - USBMouseState *s = &hs->ptr; - - if (!s->mouse_grabbed) { - s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, hs, - 1, "QEMU USB Tablet"); - s->mouse_grabbed = 1; - } - - dz = int_clamp(s->dz, -127, 127); - s->dz -= dz; - - /* Appears we have to invert the wheel direction */ - dz = 0 - 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] = s->x & 0xff; - buf[2] = s->x >> 8; - buf[3] = s->y & 0xff; - buf[4] = s->y >> 8; - buf[5] = dz; - l = 6; - - return l; -} - -static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len) -{ - if (len < 2) - return 0; - - buf[0] = s->modifiers & 0xff; - buf[1] = 0; - if (s->keys > 6) - memset(buf + 2, USB_HID_USAGE_ERROR_ROLLOVER, MIN(8, len) - 2); - else - memcpy(buf + 2, s->key, MIN(8, len) - 2); - - return MIN(8, len); -} - -static int usb_keyboard_write(USBKeyboardState *s, uint8_t *buf, int len) -{ - if (len > 0) { - /* 0x01: Num Lock LED - * 0x02: Caps Lock LED - * 0x04: Scroll Lock LED - * 0x08: Compose LED - * 0x10: Kana LED */ - s->leds = buf[0]; - } - return 0; -} - -static void usb_mouse_handle_reset(USBDevice *dev) -{ - USBHIDState *s = (USBHIDState *)dev; - - s->ptr.dx = 0; - s->ptr.dy = 0; - s->ptr.dz = 0; - s->ptr.x = 0; - s->ptr.y = 0; - s->ptr.buttons_state = 0; - s->protocol = 1; -} - -static void usb_keyboard_handle_reset(USBDevice *dev) -{ - USBHIDState *s = (USBHIDState *)dev; - - qemu_add_kbd_event_handler(usb_keyboard_event, s); - s->protocol = 1; -} - -static int usb_hid_handle_control(USBDevice *dev, int request, int value, - int index, int length, uint8_t *data) -{ - USBHIDState *s = (USBHIDState *)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_mouse_dev_descriptor, - sizeof(qemu_mouse_dev_descriptor)); - ret = sizeof(qemu_mouse_dev_descriptor); - break; - case USB_DT_CONFIG: - if (s->kind == USB_MOUSE) { - memcpy(data, qemu_mouse_config_descriptor, - sizeof(qemu_mouse_config_descriptor)); - ret = sizeof(qemu_mouse_config_descriptor); - } else if (s->kind == USB_TABLET) { - memcpy(data, qemu_tablet_config_descriptor, - sizeof(qemu_tablet_config_descriptor)); - ret = sizeof(qemu_tablet_config_descriptor); - } else if (s->kind == USB_KEYBOARD) { - memcpy(data, qemu_keyboard_config_descriptor, - sizeof(qemu_keyboard_config_descriptor)); - ret = sizeof(qemu_keyboard_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: - /* product description */ - ret = set_usb_string(data, s->dev.devname); - break; - case 3: - /* vendor description */ - ret = set_usb_string(data, "QEMU " QEMU_VERSION); - break; - case 4: - ret = set_usb_string(data, "HID Mouse"); - break; - case 5: - ret = set_usb_string(data, "HID Tablet"); - break; - case 6: - ret = set_usb_string(data, "HID Keyboard"); - break; - case 7: - 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; - /* hid specific requests */ - case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: - switch(value >> 8) { - case 0x22: - if (s->kind == USB_MOUSE) { - memcpy(data, qemu_mouse_hid_report_descriptor, - sizeof(qemu_mouse_hid_report_descriptor)); - ret = sizeof(qemu_mouse_hid_report_descriptor); - } else if (s->kind == USB_TABLET) { - memcpy(data, qemu_tablet_hid_report_descriptor, - sizeof(qemu_tablet_hid_report_descriptor)); - ret = sizeof(qemu_tablet_hid_report_descriptor); - } else if (s->kind == USB_KEYBOARD) { - memcpy(data, qemu_keyboard_hid_report_descriptor, - sizeof(qemu_keyboard_hid_report_descriptor)); - ret = sizeof(qemu_keyboard_hid_report_descriptor); - } - break; - default: - goto fail; - } - break; - case GET_REPORT: - if (s->kind == USB_MOUSE) - ret = usb_mouse_poll(s, data, length); - else if (s->kind == USB_TABLET) - ret = usb_tablet_poll(s, data, length); - else if (s->kind == USB_KEYBOARD) - ret = usb_keyboard_poll(&s->kbd, data, length); - break; - case SET_REPORT: - if (s->kind == USB_KEYBOARD) - ret = usb_keyboard_write(&s->kbd, data, length); - else - goto fail; - break; - case GET_PROTOCOL: - if (s->kind != USB_KEYBOARD) - goto fail; - ret = 1; - data[0] = s->protocol; - break; - case SET_PROTOCOL: - if (s->kind != USB_KEYBOARD) - goto fail; - ret = 0; - s->protocol = value; - break; - case GET_IDLE: - ret = 1; - data[0] = s->idle; - break; - case SET_IDLE: - s->idle = value; - ret = 0; - break; - default: - fail: - ret = USB_RET_STALL; - break; - } - return ret; -} - -static int usb_hid_handle_data(USBDevice *dev, USBPacket *p) -{ - USBHIDState *s = (USBHIDState *)dev; - int ret = 0; - - switch(p->pid) { - case USB_TOKEN_IN: - if (p->devep == 1) { - /* TODO: Implement finite idle delays. */ - if (!(s->changed || s->idle)) - return USB_RET_NAK; - s->changed = 0; - if (s->kind == USB_MOUSE) - ret = usb_mouse_poll(s, p->data, p->len); - else if (s->kind == USB_TABLET) - ret = usb_tablet_poll(s, p->data, p->len); - else if (s->kind == USB_KEYBOARD) - ret = usb_keyboard_poll(&s->kbd, p->data, p->len); - } else { - goto fail; - } - break; - case USB_TOKEN_OUT: - default: - fail: - ret = USB_RET_STALL; - break; - } - return ret; -} - -static void usb_hid_handle_destroy(USBDevice *dev) -{ - USBHIDState *s = (USBHIDState *)dev; - - if (s->kind != USB_KEYBOARD) - qemu_remove_mouse_event_handler(s->ptr.eh_entry); - /* TODO: else */ - qemu_free(s); -} - -USBDevice *usb_tablet_init(void) -{ - USBHIDState *s; - - s = qemu_mallocz(sizeof(USBHIDState)); - if (!s) - return NULL; - s->dev.speed = USB_SPEED_FULL; - s->dev.handle_packet = usb_generic_handle_packet; - - s->dev.handle_reset = usb_mouse_handle_reset; - s->dev.handle_control = usb_hid_handle_control; - s->dev.handle_data = usb_hid_handle_data; - s->dev.handle_destroy = usb_hid_handle_destroy; - s->kind = USB_TABLET; - /* Force poll routine to be run and grab input the first time. */ - s->changed = 1; - - pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Tablet"); - - return (USBDevice *)s; -} - -USBDevice *usb_mouse_init(void) -{ - USBHIDState *s; - - s = qemu_mallocz(sizeof(USBHIDState)); - if (!s) - return NULL; - s->dev.speed = USB_SPEED_FULL; - s->dev.handle_packet = usb_generic_handle_packet; - - s->dev.handle_reset = usb_mouse_handle_reset; - s->dev.handle_control = usb_hid_handle_control; - s->dev.handle_data = usb_hid_handle_data; - s->dev.handle_destroy = usb_hid_handle_destroy; - s->kind = USB_MOUSE; - /* Force poll routine to be run and grab input the first time. */ - s->changed = 1; - - pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Mouse"); - - return (USBDevice *)s; -} - -USBDevice *usb_keyboard_init(void) -{ - USBHIDState *s; - - s = qemu_mallocz(sizeof(USBHIDState)); - if (!s) - return NULL; - s->dev.speed = USB_SPEED_FULL; - s->dev.handle_packet = usb_generic_handle_packet; - - s->dev.handle_reset = usb_keyboard_handle_reset; - s->dev.handle_control = usb_hid_handle_control; - s->dev.handle_data = usb_hid_handle_data; - s->dev.handle_destroy = usb_hid_handle_destroy; - s->kind = USB_KEYBOARD; - - pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Keyboard"); - - return (USBDevice *) s; -} diff --git a/hw/usb-hub.c b/hw/usb-hub.c deleted file mode 100644 index 97c3d05..0000000 --- a/hw/usb-hub.c +++ /dev/null @@ -1,554 +0,0 @@ -/* - * QEMU USB HUB 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 "qemu-common.h" -#include "usb.h" - -//#define DEBUG - -#define MAX_PORTS 8 - -typedef struct USBHubPort { - USBPort port; - uint16_t wPortStatus; - uint16_t wPortChange; -} USBHubPort; - -typedef struct USBHubState { - USBDevice dev; - int nb_ports; - USBHubPort ports[MAX_PORTS]; -} USBHubState; - -#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) -#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) -#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) -#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) -#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) -#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) -#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) - -#define PORT_STAT_CONNECTION 0x0001 -#define PORT_STAT_ENABLE 0x0002 -#define PORT_STAT_SUSPEND 0x0004 -#define PORT_STAT_OVERCURRENT 0x0008 -#define PORT_STAT_RESET 0x0010 -#define PORT_STAT_POWER 0x0100 -#define PORT_STAT_LOW_SPEED 0x0200 -#define PORT_STAT_HIGH_SPEED 0x0400 -#define PORT_STAT_TEST 0x0800 -#define PORT_STAT_INDICATOR 0x1000 - -#define PORT_STAT_C_CONNECTION 0x0001 -#define PORT_STAT_C_ENABLE 0x0002 -#define PORT_STAT_C_SUSPEND 0x0004 -#define PORT_STAT_C_OVERCURRENT 0x0008 -#define PORT_STAT_C_RESET 0x0010 - -#define PORT_CONNECTION 0 -#define PORT_ENABLE 1 -#define PORT_SUSPEND 2 -#define PORT_OVERCURRENT 3 -#define PORT_RESET 4 -#define PORT_POWER 8 -#define PORT_LOWSPEED 9 -#define PORT_HIGHSPEED 10 -#define PORT_C_CONNECTION 16 -#define PORT_C_ENABLE 17 -#define PORT_C_SUSPEND 18 -#define PORT_C_OVERCURRENT 19 -#define PORT_C_RESET 20 -#define PORT_TEST 21 -#define PORT_INDICATOR 22 - -/* same as Linux kernel root hubs */ - -static const uint8_t qemu_hub_dev_descriptor[] = { - 0x12, /* u8 bLength; */ - 0x01, /* u8 bDescriptorType; Device */ - 0x10, 0x01, /* u16 bcdUSB; v1.1 */ - - 0x09, /* u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* u8 bDeviceSubClass; */ - 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */ - 0x08, /* u8 bMaxPacketSize0; 8 Bytes */ - - 0x00, 0x00, /* u16 idVendor; */ - 0x00, 0x00, /* u16 idProduct; */ - 0x01, 0x01, /* u16 bcdDevice */ - - 0x03, /* u8 iManufacturer; */ - 0x02, /* u8 iProduct; */ - 0x01, /* u8 iSerialNumber; */ - 0x01 /* u8 bNumConfigurations; */ -}; - -/* XXX: patch interrupt size */ -static const uint8_t qemu_hub_config_descriptor[] = { - - /* one configuration */ - 0x09, /* u8 bLength; */ - 0x02, /* u8 bDescriptorType; Configuration */ - 0x19, 0x00, /* u16 wTotalLength; */ - 0x01, /* u8 bNumInterfaces; (1) */ - 0x01, /* u8 bConfigurationValue; */ - 0x00, /* u8 iConfiguration; */ - 0xc0, /* u8 bmAttributes; - Bit 7: must be set, - 6: Self-powered, - 5: Remote wakeup, - 4..0: resvd */ - 0x00, /* u8 MaxPower; */ - - /* USB 1.1: - * USB 2.0, single TT organization (mandatory): - * one interface, protocol 0 - * - * USB 2.0, multiple TT organization (optional): - * two interfaces, protocols 1 (like single TT) - * and 2 (multiple TT mode) ... config is - * sometimes settable - * NOT IMPLEMENTED - */ - - /* one interface */ - 0x09, /* u8 if_bLength; */ - 0x04, /* u8 if_bDescriptorType; Interface */ - 0x00, /* u8 if_bInterfaceNumber; */ - 0x00, /* u8 if_bAlternateSetting; */ - 0x01, /* u8 if_bNumEndpoints; */ - 0x09, /* u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* u8 if_bInterfaceSubClass; */ - 0x00, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ - 0x00, /* u8 if_iInterface; */ - - /* 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 */ - 0x02, 0x00, /* u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ - 0xff /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ -}; - -static const uint8_t qemu_hub_hub_descriptor[] = -{ - 0x00, /* u8 bLength; patched in later */ - 0x29, /* u8 bDescriptorType; Hub-descriptor */ - 0x00, /* u8 bNbrPorts; (patched later) */ - 0x0a, /* u16 wHubCharacteristics; */ - 0x00, /* (per-port OC, no power switching) */ - 0x01, /* u8 bPwrOn2pwrGood; 2ms */ - 0x00 /* u8 bHubContrCurrent; 0 mA */ - - /* DeviceRemovable and PortPwrCtrlMask patched in later */ -}; - -static void usb_hub_attach(USBPort *port1, USBDevice *dev) -{ - USBHubState *s = port1->opaque; - USBHubPort *port = &s->ports[port1->index]; - - if (dev) { - if (port->port.dev) - usb_attach(port1, NULL); - - port->wPortStatus |= PORT_STAT_CONNECTION; - port->wPortChange |= PORT_STAT_C_CONNECTION; - if (dev->speed == USB_SPEED_LOW) - port->wPortStatus |= PORT_STAT_LOW_SPEED; - else - port->wPortStatus &= ~PORT_STAT_LOW_SPEED; - port->port.dev = dev; - /* send the attach message */ - usb_send_msg(dev, USB_MSG_ATTACH); - } else { - dev = port->port.dev; - if (dev) { - port->wPortStatus &= ~PORT_STAT_CONNECTION; - port->wPortChange |= PORT_STAT_C_CONNECTION; - if (port->wPortStatus & PORT_STAT_ENABLE) { - port->wPortStatus &= ~PORT_STAT_ENABLE; - port->wPortChange |= PORT_STAT_C_ENABLE; - } - /* send the detach message */ - usb_send_msg(dev, USB_MSG_DETACH); - port->port.dev = NULL; - } - } -} - -static void usb_hub_handle_reset(USBDevice *dev) -{ - /* XXX: do it */ -} - -static int usb_hub_handle_control(USBDevice *dev, int request, int value, - int index, int length, uint8_t *data) -{ - USBHubState *s = (USBHubState *)dev; - int ret; - - 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 EndpointOutRequest | USB_REQ_CLEAR_FEATURE: - if (value == 0 && index != 0x81) { /* clear ep halt */ - 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_hub_dev_descriptor, - sizeof(qemu_hub_dev_descriptor)); - ret = sizeof(qemu_hub_dev_descriptor); - break; - case USB_DT_CONFIG: - memcpy(data, qemu_hub_config_descriptor, - sizeof(qemu_hub_config_descriptor)); - - /* status change endpoint size based on number - * of ports */ - data[22] = (s->nb_ports + 1 + 7) / 8; - - ret = sizeof(qemu_hub_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, "314159"); - break; - case 2: - /* product description */ - ret = set_usb_string(data, "QEMU USB Hub"); - break; - case 3: - /* vendor description */ - ret = set_usb_string(data, "QEMU " QEMU_VERSION); - 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; - /* usb specific requests */ - case GetHubStatus: - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - ret = 4; - break; - case GetPortStatus: - { - unsigned int n = index - 1; - USBHubPort *port; - if (n >= s->nb_ports) - goto fail; - port = &s->ports[n]; - data[0] = port->wPortStatus; - data[1] = port->wPortStatus >> 8; - data[2] = port->wPortChange; - data[3] = port->wPortChange >> 8; - ret = 4; - } - break; - case SetHubFeature: - case ClearHubFeature: - if (value == 0 || value == 1) { - } else { - goto fail; - } - ret = 0; - break; - case SetPortFeature: - { - unsigned int n = index - 1; - USBHubPort *port; - USBDevice *dev; - if (n >= s->nb_ports) - goto fail; - port = &s->ports[n]; - dev = port->port.dev; - switch(value) { - case PORT_SUSPEND: - port->wPortStatus |= PORT_STAT_SUSPEND; - break; - case PORT_RESET: - if (dev) { - usb_send_msg(dev, USB_MSG_RESET); - port->wPortChange |= PORT_STAT_C_RESET; - /* set enable bit */ - port->wPortStatus |= PORT_STAT_ENABLE; - } - break; - case PORT_POWER: - break; - default: - goto fail; - } - ret = 0; - } - break; - case ClearPortFeature: - { - unsigned int n = index - 1; - USBHubPort *port; - USBDevice *dev; - if (n >= s->nb_ports) - goto fail; - port = &s->ports[n]; - dev = port->port.dev; - switch(value) { - case PORT_ENABLE: - port->wPortStatus &= ~PORT_STAT_ENABLE; - break; - case PORT_C_ENABLE: - port->wPortChange &= ~PORT_STAT_C_ENABLE; - break; - case PORT_SUSPEND: - port->wPortStatus &= ~PORT_STAT_SUSPEND; - break; - case PORT_C_SUSPEND: - port->wPortChange &= ~PORT_STAT_C_SUSPEND; - break; - case PORT_C_CONNECTION: - port->wPortChange &= ~PORT_STAT_C_CONNECTION; - break; - case PORT_C_OVERCURRENT: - port->wPortChange &= ~PORT_STAT_C_OVERCURRENT; - break; - case PORT_C_RESET: - port->wPortChange &= ~PORT_STAT_C_RESET; - break; - default: - goto fail; - } - ret = 0; - } - break; - case GetHubDescriptor: - { - unsigned int n, limit, var_hub_size = 0; - memcpy(data, qemu_hub_hub_descriptor, - sizeof(qemu_hub_hub_descriptor)); - data[2] = s->nb_ports; - - /* fill DeviceRemovable bits */ - limit = ((s->nb_ports + 1 + 7) / 8) + 7; - for (n = 7; n < limit; n++) { - data[n] = 0x00; - var_hub_size++; - } - - /* fill PortPwrCtrlMask bits */ - limit = limit + ((s->nb_ports + 7) / 8); - for (;n < limit; n++) { - data[n] = 0xff; - var_hub_size++; - } - - ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size; - data[0] = ret; - break; - } - default: - fail: - ret = USB_RET_STALL; - break; - } - return ret; -} - -static int usb_hub_handle_data(USBDevice *dev, USBPacket *p) -{ - USBHubState *s = (USBHubState *)dev; - int ret; - - switch(p->pid) { - case USB_TOKEN_IN: - if (p->devep == 1) { - USBHubPort *port; - unsigned int status; - int i, n; - n = (s->nb_ports + 1 + 7) / 8; - if (p->len == 1) { /* FreeBSD workaround */ - n = 1; - } else if (n > p->len) { - return USB_RET_BABBLE; - } - status = 0; - for(i = 0; i < s->nb_ports; i++) { - port = &s->ports[i]; - if (port->wPortChange) - status |= (1 << (i + 1)); - } - if (status != 0) { - for(i = 0; i < n; i++) { - p->data[i] = status >> (8 * i); - } - ret = n; - } else { - ret = USB_RET_NAK; /* usb11 11.13.1 */ - } - } else { - goto fail; - } - break; - case USB_TOKEN_OUT: - default: - fail: - ret = USB_RET_STALL; - break; - } - return ret; -} - -static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p) -{ - USBHubPort *port; - USBDevice *dev; - int i, ret; - - for(i = 0; i < s->nb_ports; i++) { - port = &s->ports[i]; - dev = port->port.dev; - if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) { - ret = dev->handle_packet(dev, p); - if (ret != USB_RET_NODEV) { - return ret; - } - } - } - return USB_RET_NODEV; -} - -static int usb_hub_handle_packet(USBDevice *dev, USBPacket *p) -{ - USBHubState *s = (USBHubState *)dev; - -#if defined(DEBUG) && 0 - printf("usb_hub: pid=0x%x\n", pid); -#endif - if (dev->state == USB_STATE_DEFAULT && - dev->addr != 0 && - p->devaddr != dev->addr && - (p->pid == USB_TOKEN_SETUP || - p->pid == USB_TOKEN_OUT || - p->pid == USB_TOKEN_IN)) { - /* broadcast the packet to the devices */ - return usb_hub_broadcast_packet(s, p); - } - return usb_generic_handle_packet(dev, p); -} - -static void usb_hub_handle_destroy(USBDevice *dev) -{ - USBHubState *s = (USBHubState *)dev; - - qemu_free(s); -} - -USBDevice *usb_hub_init(int nb_ports) -{ - USBHubState *s; - USBHubPort *port; - int i; - - if (nb_ports > MAX_PORTS) - return NULL; - s = qemu_mallocz(sizeof(USBHubState)); - if (!s) - return NULL; - s->dev.speed = USB_SPEED_FULL; - s->dev.handle_packet = usb_hub_handle_packet; - - /* generic USB device init */ - s->dev.handle_reset = usb_hub_handle_reset; - s->dev.handle_control = usb_hub_handle_control; - s->dev.handle_data = usb_hub_handle_data; - s->dev.handle_destroy = usb_hub_handle_destroy; - - pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU USB Hub"); - - s->nb_ports = nb_ports; - for(i = 0; i < s->nb_ports; i++) { - port = &s->ports[i]; - qemu_register_usb_port(&port->port, s, i, usb_hub_attach); - port->wPortStatus = PORT_STAT_POWER; - port->wPortChange = 0; - } - return (USBDevice *)s; -} diff --git a/hw/usb-msd.c b/hw/usb-msd.c deleted file mode 100644 index f7ad25e..0000000 --- a/hw/usb-msd.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * USB Mass Storage Device emulation - * - * Copyright (c) 2006 CodeSourcery. - * Written by Paul Brook - * - * This code is licenced under the LGPL. - */ - -#include "qemu-common.h" -#include "usb.h" -#include "block.h" -#include "scsi-disk.h" - -//#define DEBUG_MSD - -#ifdef DEBUG_MSD -#define DPRINTF(fmt, args...) \ -do { printf("usb-msd: " fmt , ##args); } while (0) -#else -#define DPRINTF(fmt, args...) do {} while(0) -#endif - -/* USB requests. */ -#define MassStorageReset 0xff -#define GetMaxLun 0xfe - -enum USBMSDMode { - USB_MSDM_CBW, /* Command Block. */ - USB_MSDM_DATAOUT, /* Tranfer data to device. */ - USB_MSDM_DATAIN, /* Transfer data from device. */ - USB_MSDM_CSW /* Command Status. */ -}; - -typedef struct { - USBDevice dev; - enum USBMSDMode mode; - uint32_t scsi_len; - uint8_t *scsi_buf; - uint32_t usb_len; - uint8_t *usb_buf; - uint32_t data_len; - uint32_t residue; - uint32_t tag; - BlockDriverState *bs; - SCSIDevice *scsi_dev; - int result; - /* For async completion. */ - USBPacket *packet; -} MSDState; - -struct usb_msd_cbw { - uint32_t sig; - uint32_t tag; - uint32_t data_len; - uint8_t flags; - uint8_t lun; - uint8_t cmd_len; - uint8_t cmd[16]; -}; - -struct usb_msd_csw { - uint32_t sig; - uint32_t tag; - uint32_t residue; - uint8_t status; -}; - -static const uint8_t qemu_msd_dev_descriptor[] = { - 0x12, /* u8 bLength; */ - 0x01, /* u8 bDescriptorType; Device */ - 0x00, 0x01, /* u16 bcdUSB; v1.0 */ - - 0x00, /* u8 bDeviceClass; */ - 0x00, /* u8 bDeviceSubClass; */ - 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */ - 0x08, /* u8 bMaxPacketSize0; 8 Bytes */ - - /* Vendor and product id are arbitrary. */ - 0x00, 0x00, /* u16 idVendor; */ - 0x00, 0x00, /* u16 idProduct; */ - 0x00, 0x00, /* u16 bcdDevice */ - - 0x01, /* u8 iManufacturer; */ - 0x02, /* u8 iProduct; */ - 0x03, /* u8 iSerialNumber; */ - 0x01 /* u8 bNumConfigurations; */ -}; - -static const uint8_t qemu_msd_config_descriptor[] = { - - /* one configuration */ - 0x09, /* u8 bLength; */ - 0x02, /* u8 bDescriptorType; Configuration */ - 0x20, 0x00, /* u16 wTotalLength; */ - 0x01, /* u8 bNumInterfaces; (1) */ - 0x01, /* u8 bConfigurationValue; */ - 0x00, /* u8 iConfiguration; */ - 0xc0, /* u8 bmAttributes; - Bit 7: must be set, - 6: Self-powered, - 5: Remote wakeup, - 4..0: resvd */ - 0x00, /* u8 MaxPower; */ - - /* one interface */ - 0x09, /* u8 if_bLength; */ - 0x04, /* u8 if_bDescriptorType; Interface */ - 0x00, /* u8 if_bInterfaceNumber; */ - 0x00, /* u8 if_bAlternateSetting; */ - 0x02, /* u8 if_bNumEndpoints; */ - 0x08, /* u8 if_bInterfaceClass; MASS STORAGE */ - 0x06, /* u8 if_bInterfaceSubClass; SCSI */ - 0x50, /* u8 if_bInterfaceProtocol; Bulk Only */ - 0x00, /* u8 if_iInterface; */ - - /* Bulk-In endpoint */ - 0x07, /* u8 ep_bLength; */ - 0x05, /* u8 ep_bDescriptorType; Endpoint */ - 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x02, /* u8 ep_bmAttributes; Bulk */ - 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ - 0x00, /* u8 ep_bInterval; */ - - /* Bulk-Out endpoint */ - 0x07, /* u8 ep_bLength; */ - 0x05, /* u8 ep_bDescriptorType; Endpoint */ - 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */ - 0x02, /* u8 ep_bmAttributes; Bulk */ - 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ - 0x00 /* u8 ep_bInterval; */ -}; - -static void usb_msd_copy_data(MSDState *s) -{ - uint32_t len; - len = s->usb_len; - if (len > s->scsi_len) - len = s->scsi_len; - if (s->mode == USB_MSDM_DATAIN) { - memcpy(s->usb_buf, s->scsi_buf, len); - } else { - memcpy(s->scsi_buf, s->usb_buf, len); - } - s->usb_len -= len; - s->scsi_len -= len; - s->usb_buf += len; - s->scsi_buf += len; - s->data_len -= len; - if (s->scsi_len == 0) { - if (s->mode == USB_MSDM_DATAIN) { - s->scsi_dev->read_data(s->scsi_dev, s->tag); - } else if (s->mode == USB_MSDM_DATAOUT) { - s->scsi_dev->write_data(s->scsi_dev, s->tag); - } - } -} - -static void usb_msd_send_status(MSDState *s) -{ - struct usb_msd_csw csw; - - csw.sig = cpu_to_le32(0x53425355); - csw.tag = cpu_to_le32(s->tag); - csw.residue = s->residue; - csw.status = s->result; - memcpy(s->usb_buf, &csw, 13); -} - -static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag, - uint32_t arg) -{ - MSDState *s = (MSDState *)opaque; - USBPacket *p = s->packet; - - if (tag != s->tag) { - fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", tag); - } - if (reason == SCSI_REASON_DONE) { - DPRINTF("Command complete %d\n", arg); - s->residue = s->data_len; - s->result = arg != 0; - if (s->packet) { - if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) { - /* A deferred packet with no write data remaining must be - the status read packet. */ - usb_msd_send_status(s); - s->mode = USB_MSDM_CBW; - } else { - if (s->data_len) { - s->data_len -= s->usb_len; - if (s->mode == USB_MSDM_DATAIN) - memset(s->usb_buf, 0, s->usb_len); - s->usb_len = 0; - } - if (s->data_len == 0) - s->mode = USB_MSDM_CSW; - } - s->packet = NULL; - usb_packet_complete(p); - } else if (s->data_len == 0) { - s->mode = USB_MSDM_CSW; - } - return; - } - s->scsi_len = arg; - s->scsi_buf = s->scsi_dev->get_buf(s->scsi_dev, tag); - if (p) { - usb_msd_copy_data(s); - if (s->usb_len == 0) { - /* Set s->packet to NULL before calling usb_packet_complete - because annother request may be issued before - usb_packet_complete returns. */ - DPRINTF("Packet complete %p\n", p); - s->packet = NULL; - usb_packet_complete(p); - } - } -} - -static void usb_msd_handle_reset(USBDevice *dev) -{ - MSDState *s = (MSDState *)dev; - - DPRINTF("Reset\n"); - s->mode = USB_MSDM_CBW; -} - -static int usb_msd_handle_control(USBDevice *dev, int request, int value, - int index, int length, uint8_t *data) -{ - MSDState *s = (MSDState *)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_msd_dev_descriptor, - sizeof(qemu_msd_dev_descriptor)); - ret = sizeof(qemu_msd_dev_descriptor); - break; - case USB_DT_CONFIG: - memcpy(data, qemu_msd_config_descriptor, - sizeof(qemu_msd_config_descriptor)); - ret = sizeof(qemu_msd_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: - /* vendor description */ - ret = set_usb_string(data, "QEMU " QEMU_VERSION); - break; - case 2: - /* product description */ - ret = set_usb_string(data, "QEMU USB HARDDRIVE"); - break; - case 3: - /* serial number */ - ret = set_usb_string(data, "1"); - 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 EndpointOutRequest | USB_REQ_CLEAR_FEATURE: - if (value == 0 && index != 0x81) { /* clear ep halt */ - goto fail; - } - ret = 0; - break; - /* Class specific requests. */ - case MassStorageReset: - /* Reset state ready for the next CBW. */ - s->mode = USB_MSDM_CBW; - ret = 0; - break; - case GetMaxLun: - data[0] = 0; - ret = 1; - break; - default: - fail: - ret = USB_RET_STALL; - break; - } - return ret; -} - -static void usb_msd_cancel_io(USBPacket *p, void *opaque) -{ - MSDState *s = opaque; - s->scsi_dev->cancel_io(s->scsi_dev, s->tag); - s->packet = NULL; - s->scsi_len = 0; -} - -static int usb_msd_handle_data(USBDevice *dev, USBPacket *p) -{ - MSDState *s = (MSDState *)dev; - int ret = 0; - struct usb_msd_cbw cbw; - uint8_t devep = p->devep; - uint8_t *data = p->data; - int len = p->len; - - switch (p->pid) { - case USB_TOKEN_OUT: - if (devep != 2) - goto fail; - - switch (s->mode) { - case USB_MSDM_CBW: - if (len != 31) { - fprintf(stderr, "usb-msd: Bad CBW size"); - goto fail; - } - memcpy(&cbw, data, 31); - if (le32_to_cpu(cbw.sig) != 0x43425355) { - fprintf(stderr, "usb-msd: Bad signature %08x\n", - le32_to_cpu(cbw.sig)); - goto fail; - } - DPRINTF("Command on LUN %d\n", cbw.lun); - if (cbw.lun != 0) { - fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun); - goto fail; - } - s->tag = le32_to_cpu(cbw.tag); - s->data_len = le32_to_cpu(cbw.data_len); - if (s->data_len == 0) { - s->mode = USB_MSDM_CSW; - } else if (cbw.flags & 0x80) { - s->mode = USB_MSDM_DATAIN; - } else { - s->mode = USB_MSDM_DATAOUT; - } - DPRINTF("Command tag 0x%x flags %08x len %d data %d\n", - s->tag, cbw.flags, cbw.cmd_len, s->data_len); - s->residue = 0; - s->scsi_dev->send_command(s->scsi_dev, s->tag, cbw.cmd, 0); - /* ??? Should check that USB and SCSI data transfer - directions match. */ - if (s->residue == 0) { - if (s->mode == USB_MSDM_DATAIN) { - s->scsi_dev->read_data(s->scsi_dev, s->tag); - } else if (s->mode == USB_MSDM_DATAOUT) { - s->scsi_dev->write_data(s->scsi_dev, s->tag); - } - } - ret = len; - break; - - case USB_MSDM_DATAOUT: - DPRINTF("Data out %d/%d\n", len, s->data_len); - if (len > s->data_len) - goto fail; - - s->usb_buf = data; - s->usb_len = len; - if (s->scsi_len) { - usb_msd_copy_data(s); - } - if (s->residue && s->usb_len) { - s->data_len -= s->usb_len; - if (s->data_len == 0) - s->mode = USB_MSDM_CSW; - s->usb_len = 0; - } - if (s->usb_len) { - DPRINTF("Deferring packet %p\n", p); - usb_defer_packet(p, usb_msd_cancel_io, s); - s->packet = p; - ret = USB_RET_ASYNC; - } else { - ret = len; - } - break; - - default: - DPRINTF("Unexpected write (len %d)\n", len); - goto fail; - } - break; - - case USB_TOKEN_IN: - if (devep != 1) - goto fail; - - switch (s->mode) { - case USB_MSDM_DATAOUT: - if (s->data_len != 0 || len < 13) - goto fail; - /* Waiting for SCSI write to complete. */ - usb_defer_packet(p, usb_msd_cancel_io, s); - s->packet = p; - ret = USB_RET_ASYNC; - break; - - case USB_MSDM_CSW: - DPRINTF("Command status %d tag 0x%x, len %d\n", - s->result, s->tag, len); - if (len < 13) - goto fail; - - s->usb_len = len; - s->usb_buf = data; - usb_msd_send_status(s); - s->mode = USB_MSDM_CBW; - ret = 13; - break; - - case USB_MSDM_DATAIN: - DPRINTF("Data in %d/%d\n", len, s->data_len); - if (len > s->data_len) - len = s->data_len; - s->usb_buf = data; - s->usb_len = len; - if (s->scsi_len) { - usb_msd_copy_data(s); - } - if (s->residue && s->usb_len) { - s->data_len -= s->usb_len; - memset(s->usb_buf, 0, s->usb_len); - if (s->data_len == 0) - s->mode = USB_MSDM_CSW; - s->usb_len = 0; - } - if (s->usb_len) { - DPRINTF("Deferring packet %p\n", p); - usb_defer_packet(p, usb_msd_cancel_io, s); - s->packet = p; - ret = USB_RET_ASYNC; - } else { - ret = len; - } - break; - - default: - DPRINTF("Unexpected read (len %d)\n", len); - goto fail; - } - break; - - default: - DPRINTF("Bad token\n"); - fail: - ret = USB_RET_STALL; - break; - } - - return ret; -} - -static void usb_msd_handle_destroy(USBDevice *dev) -{ - MSDState *s = (MSDState *)dev; - - s->scsi_dev->destroy(s->scsi_dev); - bdrv_delete(s->bs); - qemu_free(s); -} - -USBDevice *usb_msd_init(const char *filename) -{ - MSDState *s; - BlockDriverState *bdrv; - BlockDriver *drv = NULL; - const char *p1; - char fmt[32]; - - p1 = strchr(filename, ':'); - if (p1++) { - const char *p2; - - if (strstart(filename, "format=", &p2)) { - int len = MIN(p1 - p2, sizeof(fmt)); - pstrcpy(fmt, len, p2); - - drv = bdrv_find_format(fmt); - if (!drv) { - printf("invalid format %s\n", fmt); - return NULL; - } - } else if (*filename != ':') { - printf("unrecognized USB mass-storage option %s\n", filename); - return NULL; - } - - filename = p1; - } - - if (!*filename) { - printf("block device specification needed\n"); - return NULL; - } - - s = qemu_mallocz(sizeof(MSDState)); - if (!s) - return NULL; - - bdrv = bdrv_new("usb"); - if (bdrv_open2(bdrv, filename, 0, drv) < 0) - goto fail; - if (qemu_key_check(bdrv, filename)) - goto fail; - s->bs = bdrv; - - s->dev.speed = USB_SPEED_FULL; - s->dev.handle_packet = usb_generic_handle_packet; - - s->dev.handle_reset = usb_msd_handle_reset; - s->dev.handle_control = usb_msd_handle_control; - s->dev.handle_data = usb_msd_handle_data; - s->dev.handle_destroy = usb_msd_handle_destroy; - - snprintf(s->dev.devname, sizeof(s->dev.devname), "QEMU USB MSD(%.16s)", - filename); - - s->scsi_dev = scsi_disk_init(bdrv, 0, usb_msd_command_complete, s); - usb_msd_handle_reset((USBDevice *)s); - return (USBDevice *)s; - fail: - qemu_free(s); - return NULL; -} diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c deleted file mode 100644 index 55cb77b..0000000 --- a/hw/usb-ohci.c +++ /dev/null @@ -1,1684 +0,0 @@ -/* - * QEMU USB OHCI Emulation - * Copyright (c) 2004 Gianni Tedesco - * Copyright (c) 2006 CodeSourcery - * Copyright (c) 2006 Openedhand Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: - * o Isochronous transfers - * o Allocate bandwidth in frames properly - * o Disable timers when nothing needs to be done, or remove timer usage - * all together. - * o Handle unrecoverable errors properly - * o BIOS work to boot from USB storage -*/ - -#include "hw.h" -#include "qemu-timer.h" -#include "usb.h" -#include "pci.h" -#include "pxa.h" - -//#define DEBUG_OHCI -/* Dump packet contents. */ -//#define DEBUG_PACKET -//#define DEBUG_ISOCH -/* This causes frames to occur 1000x slower */ -//#define OHCI_TIME_WARP 1 - -#ifdef DEBUG_OHCI -#define dprintf printf -#else -#define dprintf(...) -#endif - -/* Number of Downstream Ports on the root hub. */ - -#define OHCI_MAX_PORTS 15 - -static int64_t usb_frame_time; -static int64_t usb_bit_time; - -typedef struct OHCIPort { - USBPort port; - uint32_t ctrl; -} OHCIPort; - -enum ohci_type { - OHCI_TYPE_PCI, - OHCI_TYPE_PXA -}; - -typedef struct { - qemu_irq irq; - enum ohci_type type; - target_phys_addr_t mem_base; - int mem; - int num_ports; - const char *name; - - QEMUTimer *eof_timer; - int64_t sof_time; - - /* OHCI state */ - /* Control partition */ - uint32_t ctl, status; - uint32_t intr_status; - uint32_t intr; - - /* memory pointer partition */ - uint32_t hcca; - uint32_t ctrl_head, ctrl_cur; - uint32_t bulk_head, bulk_cur; - uint32_t per_cur; - uint32_t done; - int done_count; - - /* Frame counter partition */ - uint32_t fsmps:15; - uint32_t fit:1; - uint32_t fi:14; - uint32_t frt:1; - uint16_t frame_number; - uint16_t padding; - uint32_t pstart; - uint32_t lst; - - /* Root Hub partition */ - uint32_t rhdesc_a, rhdesc_b; - uint32_t rhstatus; - OHCIPort rhport[OHCI_MAX_PORTS]; - - /* PXA27x Non-OHCI events */ - uint32_t hstatus; - uint32_t hmask; - uint32_t hreset; - uint32_t htest; - - /* Active packets. */ - uint32_t old_ctl; - USBPacket usb_packet; - uint8_t usb_buf[8192]; - uint32_t async_td; - int async_complete; - -} OHCIState; - -/* Host Controller Communications Area */ -struct ohci_hcca { - uint32_t intr[32]; - uint16_t frame, pad; - uint32_t done; -}; - -static void ohci_bus_stop(OHCIState *ohci); - -/* Bitfields for the first word of an Endpoint Desciptor. */ -#define OHCI_ED_FA_SHIFT 0 -#define OHCI_ED_FA_MASK (0x7f<<OHCI_ED_FA_SHIFT) -#define OHCI_ED_EN_SHIFT 7 -#define OHCI_ED_EN_MASK (0xf<<OHCI_ED_EN_SHIFT) -#define OHCI_ED_D_SHIFT 11 -#define OHCI_ED_D_MASK (3<<OHCI_ED_D_SHIFT) -#define OHCI_ED_S (1<<13) -#define OHCI_ED_K (1<<14) -#define OHCI_ED_F (1<<15) -#define OHCI_ED_MPS_SHIFT 16 -#define OHCI_ED_MPS_MASK (0x7ff<<OHCI_ED_MPS_SHIFT) - -/* Flags in the head field of an Endpoint Desciptor. */ -#define OHCI_ED_H 1 -#define OHCI_ED_C 2 - -/* Bitfields for the first word of a Transfer Desciptor. */ -#define OHCI_TD_R (1<<18) -#define OHCI_TD_DP_SHIFT 19 -#define OHCI_TD_DP_MASK (3<<OHCI_TD_DP_SHIFT) -#define OHCI_TD_DI_SHIFT 21 -#define OHCI_TD_DI_MASK (7<<OHCI_TD_DI_SHIFT) -#define OHCI_TD_T0 (1<<24) -#define OHCI_TD_T1 (1<<24) -#define OHCI_TD_EC_SHIFT 26 -#define OHCI_TD_EC_MASK (3<<OHCI_TD_EC_SHIFT) -#define OHCI_TD_CC_SHIFT 28 -#define OHCI_TD_CC_MASK (0xf<<OHCI_TD_CC_SHIFT) - -/* Bitfields for the first word of an Isochronous Transfer Desciptor. */ -/* CC & DI - same as in the General Transfer Desciptor */ -#define OHCI_TD_SF_SHIFT 0 -#define OHCI_TD_SF_MASK (0xffff<<OHCI_TD_SF_SHIFT) -#define OHCI_TD_FC_SHIFT 24 -#define OHCI_TD_FC_MASK (7<<OHCI_TD_FC_SHIFT) - -/* Isochronous Transfer Desciptor - Offset / PacketStatusWord */ -#define OHCI_TD_PSW_CC_SHIFT 12 -#define OHCI_TD_PSW_CC_MASK (0xf<<OHCI_TD_PSW_CC_SHIFT) -#define OHCI_TD_PSW_SIZE_SHIFT 0 -#define OHCI_TD_PSW_SIZE_MASK (0xfff<<OHCI_TD_PSW_SIZE_SHIFT) - -#define OHCI_PAGE_MASK 0xfffff000 -#define OHCI_OFFSET_MASK 0xfff - -#define OHCI_DPTR_MASK 0xfffffff0 - -#define OHCI_BM(val, field) \ - (((val) & OHCI_##field##_MASK) >> OHCI_##field##_SHIFT) - -#define OHCI_SET_BM(val, field, newval) do { \ - val &= ~OHCI_##field##_MASK; \ - val |= ((newval) << OHCI_##field##_SHIFT) & OHCI_##field##_MASK; \ - } while(0) - -/* endpoint descriptor */ -struct ohci_ed { - uint32_t flags; - uint32_t tail; - uint32_t head; - uint32_t next; -}; - -/* General transfer descriptor */ -struct ohci_td { - uint32_t flags; - uint32_t cbp; - uint32_t next; - uint32_t be; -}; - -/* Isochronous transfer descriptor */ -struct ohci_iso_td { - uint32_t flags; - uint32_t bp; - uint32_t next; - uint32_t be; - uint16_t offset[8]; -}; - -#define USB_HZ 12000000 - -/* OHCI Local stuff */ -#define OHCI_CTL_CBSR ((1<<0)|(1<<1)) -#define OHCI_CTL_PLE (1<<2) -#define OHCI_CTL_IE (1<<3) -#define OHCI_CTL_CLE (1<<4) -#define OHCI_CTL_BLE (1<<5) -#define OHCI_CTL_HCFS ((1<<6)|(1<<7)) -#define OHCI_USB_RESET 0x00 -#define OHCI_USB_RESUME 0x40 -#define OHCI_USB_OPERATIONAL 0x80 -#define OHCI_USB_SUSPEND 0xc0 -#define OHCI_CTL_IR (1<<8) -#define OHCI_CTL_RWC (1<<9) -#define OHCI_CTL_RWE (1<<10) - -#define OHCI_STATUS_HCR (1<<0) -#define OHCI_STATUS_CLF (1<<1) -#define OHCI_STATUS_BLF (1<<2) -#define OHCI_STATUS_OCR (1<<3) -#define OHCI_STATUS_SOC ((1<<6)|(1<<7)) - -#define OHCI_INTR_SO (1<<0) /* Scheduling overrun */ -#define OHCI_INTR_WD (1<<1) /* HcDoneHead writeback */ -#define OHCI_INTR_SF (1<<2) /* Start of frame */ -#define OHCI_INTR_RD (1<<3) /* Resume detect */ -#define OHCI_INTR_UE (1<<4) /* Unrecoverable error */ -#define OHCI_INTR_FNO (1<<5) /* Frame number overflow */ -#define OHCI_INTR_RHSC (1<<6) /* Root hub status change */ -#define OHCI_INTR_OC (1<<30) /* Ownership change */ -#define OHCI_INTR_MIE (1<<31) /* Master Interrupt Enable */ - -#define OHCI_HCCA_SIZE 0x100 -#define OHCI_HCCA_MASK 0xffffff00 - -#define OHCI_EDPTR_MASK 0xfffffff0 - -#define OHCI_FMI_FI 0x00003fff -#define OHCI_FMI_FSMPS 0xffff0000 -#define OHCI_FMI_FIT 0x80000000 - -#define OHCI_FR_RT (1<<31) - -#define OHCI_LS_THRESH 0x628 - -#define OHCI_RHA_RW_MASK 0x00000000 /* Mask of supported features. */ -#define OHCI_RHA_PSM (1<<8) -#define OHCI_RHA_NPS (1<<9) -#define OHCI_RHA_DT (1<<10) -#define OHCI_RHA_OCPM (1<<11) -#define OHCI_RHA_NOCP (1<<12) -#define OHCI_RHA_POTPGT_MASK 0xff000000 - -#define OHCI_RHS_LPS (1<<0) -#define OHCI_RHS_OCI (1<<1) -#define OHCI_RHS_DRWE (1<<15) -#define OHCI_RHS_LPSC (1<<16) -#define OHCI_RHS_OCIC (1<<17) -#define OHCI_RHS_CRWE (1<<31) - -#define OHCI_PORT_CCS (1<<0) -#define OHCI_PORT_PES (1<<1) -#define OHCI_PORT_PSS (1<<2) -#define OHCI_PORT_POCI (1<<3) -#define OHCI_PORT_PRS (1<<4) -#define OHCI_PORT_PPS (1<<8) -#define OHCI_PORT_LSDA (1<<9) -#define OHCI_PORT_CSC (1<<16) -#define OHCI_PORT_PESC (1<<17) -#define OHCI_PORT_PSSC (1<<18) -#define OHCI_PORT_OCIC (1<<19) -#define OHCI_PORT_PRSC (1<<20) -#define OHCI_PORT_WTC (OHCI_PORT_CSC|OHCI_PORT_PESC|OHCI_PORT_PSSC \ - |OHCI_PORT_OCIC|OHCI_PORT_PRSC) - -#define OHCI_TD_DIR_SETUP 0x0 -#define OHCI_TD_DIR_OUT 0x1 -#define OHCI_TD_DIR_IN 0x2 -#define OHCI_TD_DIR_RESERVED 0x3 - -#define OHCI_CC_NOERROR 0x0 -#define OHCI_CC_CRC 0x1 -#define OHCI_CC_BITSTUFFING 0x2 -#define OHCI_CC_DATATOGGLEMISMATCH 0x3 -#define OHCI_CC_STALL 0x4 -#define OHCI_CC_DEVICENOTRESPONDING 0x5 -#define OHCI_CC_PIDCHECKFAILURE 0x6 -#define OHCI_CC_UNDEXPETEDPID 0x7 -#define OHCI_CC_DATAOVERRUN 0x8 -#define OHCI_CC_DATAUNDERRUN 0x9 -#define OHCI_CC_BUFFEROVERRUN 0xc -#define OHCI_CC_BUFFERUNDERRUN 0xd - -#define OHCI_HRESET_FSBIR (1 << 0) - -/* Update IRQ levels */ -static inline void ohci_intr_update(OHCIState *ohci) -{ - int level = 0; - - if ((ohci->intr & OHCI_INTR_MIE) && - (ohci->intr_status & ohci->intr)) - level = 1; - - qemu_set_irq(ohci->irq, level); -} - -/* Set an interrupt */ -static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr) -{ - ohci->intr_status |= intr; - ohci_intr_update(ohci); -} - -/* Attach or detach a device on a root hub port. */ -static void ohci_attach(USBPort *port1, USBDevice *dev) -{ - OHCIState *s = port1->opaque; - OHCIPort *port = &s->rhport[port1->index]; - uint32_t old_state = port->ctrl; - - if (dev) { - if (port->port.dev) { - usb_attach(port1, NULL); - } - /* set connect status */ - port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC; - - /* update speed */ - if (dev->speed == USB_SPEED_LOW) - port->ctrl |= OHCI_PORT_LSDA; - else - port->ctrl &= ~OHCI_PORT_LSDA; - port->port.dev = dev; - - /* notify of remote-wakeup */ - if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) - ohci_set_interrupt(s, OHCI_INTR_RD); - - /* send the attach message */ - usb_send_msg(dev, USB_MSG_ATTACH); - dprintf("usb-ohci: Attached port %d\n", port1->index); - } else { - /* set connect status */ - if (port->ctrl & OHCI_PORT_CCS) { - port->ctrl &= ~OHCI_PORT_CCS; - port->ctrl |= OHCI_PORT_CSC; - } - /* disable port */ - if (port->ctrl & OHCI_PORT_PES) { - port->ctrl &= ~OHCI_PORT_PES; - port->ctrl |= OHCI_PORT_PESC; - } - dev = port->port.dev; - if (dev) { - /* send the detach message */ - usb_send_msg(dev, USB_MSG_DETACH); - } - port->port.dev = NULL; - dprintf("usb-ohci: Detached port %d\n", port1->index); - } - - if (old_state != port->ctrl) - ohci_set_interrupt(s, OHCI_INTR_RHSC); -} - -/* Reset the controller */ -static void ohci_reset(void *opaque) -{ - OHCIState *ohci = opaque; - OHCIPort *port; - int i; - - ohci_bus_stop(ohci); - ohci->ctl = 0; - ohci->old_ctl = 0; - ohci->status = 0; - ohci->intr_status = 0; - ohci->intr = OHCI_INTR_MIE; - - ohci->hcca = 0; - ohci->ctrl_head = ohci->ctrl_cur = 0; - ohci->bulk_head = ohci->bulk_cur = 0; - ohci->per_cur = 0; - ohci->done = 0; - ohci->done_count = 7; - - /* FSMPS is marked TBD in OCHI 1.0, what gives ffs? - * I took the value linux sets ... - */ - ohci->fsmps = 0x2778; - ohci->fi = 0x2edf; - ohci->fit = 0; - ohci->frt = 0; - ohci->frame_number = 0; - ohci->pstart = 0; - ohci->lst = OHCI_LS_THRESH; - - ohci->rhdesc_a = OHCI_RHA_NPS | ohci->num_ports; - ohci->rhdesc_b = 0x0; /* Impl. specific */ - ohci->rhstatus = 0; - - for (i = 0; i < ohci->num_ports; i++) - { - port = &ohci->rhport[i]; - port->ctrl = 0; - if (port->port.dev) - ohci_attach(&port->port, port->port.dev); - } - if (ohci->async_td) { - usb_cancel_packet(&ohci->usb_packet); - ohci->async_td = 0; - } - dprintf("usb-ohci: Reset %s\n", ohci->name); -} - -/* Get an array of dwords from main memory */ -static inline int get_dwords(uint32_t addr, uint32_t *buf, int num) -{ - int i; - - for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0); - *buf = le32_to_cpu(*buf); - } - - return 1; -} - -/* Put an array of dwords in to main memory */ -static inline int put_dwords(uint32_t addr, uint32_t *buf, int num) -{ - int i; - - for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - uint32_t tmp = cpu_to_le32(*buf); - cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1); - } - - return 1; -} - -/* Get an array of words from main memory */ -static inline int get_words(uint32_t addr, uint16_t *buf, int num) -{ - int i; - - for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - cpu_physical_memory_rw(addr, (uint8_t *)buf, sizeof(*buf), 0); - *buf = le16_to_cpu(*buf); - } - - return 1; -} - -/* Put an array of words in to main memory */ -static inline int put_words(uint32_t addr, uint16_t *buf, int num) -{ - int i; - - for (i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - uint16_t tmp = cpu_to_le16(*buf); - cpu_physical_memory_rw(addr, (uint8_t *)&tmp, sizeof(tmp), 1); - } - - return 1; -} - -static inline int ohci_read_ed(uint32_t addr, struct ohci_ed *ed) -{ - return get_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2); -} - -static inline int ohci_read_td(uint32_t addr, struct ohci_td *td) -{ - return get_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2); -} - -static inline int ohci_read_iso_td(uint32_t addr, struct ohci_iso_td *td) -{ - return (get_dwords(addr, (uint32_t *)td, 4) && - get_words(addr + 16, td->offset, 8)); -} - -static inline int ohci_put_ed(uint32_t addr, struct ohci_ed *ed) -{ - return put_dwords(addr, (uint32_t *)ed, sizeof(*ed) >> 2); -} - -static inline int ohci_put_td(uint32_t addr, struct ohci_td *td) -{ - return put_dwords(addr, (uint32_t *)td, sizeof(*td) >> 2); -} - -static inline int ohci_put_iso_td(uint32_t addr, struct ohci_iso_td *td) -{ - return (put_dwords(addr, (uint32_t *)td, 4) && - put_words(addr + 16, td->offset, 8)); -} - -/* Read/Write the contents of a TD from/to main memory. */ -static void ohci_copy_td(struct ohci_td *td, uint8_t *buf, int len, int write) -{ - uint32_t ptr; - uint32_t n; - - ptr = td->cbp; - n = 0x1000 - (ptr & 0xfff); - if (n > len) - n = len; - cpu_physical_memory_rw(ptr, buf, n, write); - if (n == len) - return; - ptr = td->be & ~0xfffu; - buf += n; - cpu_physical_memory_rw(ptr, buf, len - n, write); -} - -/* Read/Write the contents of an ISO TD from/to main memory. */ -static void ohci_copy_iso_td(uint32_t start_addr, uint32_t end_addr, - uint8_t *buf, int len, int write) -{ - uint32_t ptr; - uint32_t n; - - ptr = start_addr; - n = 0x1000 - (ptr & 0xfff); - if (n > len) - n = len; - cpu_physical_memory_rw(ptr, buf, n, write); - if (n == len) - return; - ptr = end_addr & ~0xfffu; - buf += n; - cpu_physical_memory_rw(ptr, buf, len - n, write); -} - -static void ohci_process_lists(OHCIState *ohci, int completion); - -static void ohci_async_complete_packet(USBPacket *packet, void *opaque) -{ - OHCIState *ohci = opaque; -#ifdef DEBUG_PACKET - dprintf("Async packet complete\n"); -#endif - ohci->async_complete = 1; - ohci_process_lists(ohci, 1); -} - -#define USUB(a, b) ((int16_t)((uint16_t)(a) - (uint16_t)(b))) - -static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed, - int completion) -{ - int dir; - size_t len = 0; - const char *str = NULL; - int pid; - int ret; - int i; - USBDevice *dev; - struct ohci_iso_td iso_td; - uint32_t addr; - uint16_t starting_frame; - int16_t relative_frame_number; - int frame_count; - uint32_t start_offset, next_offset, end_offset = 0; - uint32_t start_addr, end_addr; - - addr = ed->head & OHCI_DPTR_MASK; - - if (!ohci_read_iso_td(addr, &iso_td)) { - printf("usb-ohci: ISO_TD read error at %x\n", addr); - return 0; - } - - starting_frame = OHCI_BM(iso_td.flags, TD_SF); - frame_count = OHCI_BM(iso_td.flags, TD_FC); - relative_frame_number = USUB(ohci->frame_number, starting_frame); - -#ifdef DEBUG_ISOCH - printf("--- ISO_TD ED head 0x%.8x tailp 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "0x%.8x 0x%.8x 0x%.8x 0x%.8x\n" - "frame_number 0x%.8x starting_frame 0x%.8x\n" - "frame_count 0x%.8x relative %d\n" - "di 0x%.8x cc 0x%.8x\n", - ed->head & OHCI_DPTR_MASK, ed->tail & OHCI_DPTR_MASK, - iso_td.flags, iso_td.bp, iso_td.next, iso_td.be, - iso_td.offset[0], iso_td.offset[1], iso_td.offset[2], iso_td.offset[3], - iso_td.offset[4], iso_td.offset[5], iso_td.offset[6], iso_td.offset[7], - ohci->frame_number, starting_frame, - frame_count, relative_frame_number, - OHCI_BM(iso_td.flags, TD_DI), OHCI_BM(iso_td.flags, TD_CC)); -#endif - - if (relative_frame_number < 0) { - dprintf("usb-ohci: ISO_TD R=%d < 0\n", relative_frame_number); - return 1; - } else if (relative_frame_number > frame_count) { - /* ISO TD expired - retire the TD to the Done Queue and continue with - the next ISO TD of the same ED */ - dprintf("usb-ohci: ISO_TD R=%d > FC=%d\n", relative_frame_number, - frame_count); - OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_DATAOVERRUN); - ed->head &= ~OHCI_DPTR_MASK; - ed->head |= (iso_td.next & OHCI_DPTR_MASK); - iso_td.next = ohci->done; - ohci->done = addr; - i = OHCI_BM(iso_td.flags, TD_DI); - if (i < ohci->done_count) - ohci->done_count = i; - ohci_put_iso_td(addr, &iso_td); - return 0; - } - - dir = OHCI_BM(ed->flags, ED_D); - switch (dir) { - case OHCI_TD_DIR_IN: - str = "in"; - pid = USB_TOKEN_IN; - break; - case OHCI_TD_DIR_OUT: - str = "out"; - pid = USB_TOKEN_OUT; - break; - case OHCI_TD_DIR_SETUP: - str = "setup"; - pid = USB_TOKEN_SETUP; - break; - default: - printf("usb-ohci: Bad direction %d\n", dir); - return 1; - } - - if (!iso_td.bp || !iso_td.be) { - printf("usb-ohci: ISO_TD bp 0x%.8x be 0x%.8x\n", iso_td.bp, iso_td.be); - return 1; - } - - start_offset = iso_td.offset[relative_frame_number]; - next_offset = iso_td.offset[relative_frame_number + 1]; - - if (!(OHCI_BM(start_offset, TD_PSW_CC) & 0xe) || - ((relative_frame_number < frame_count) && - !(OHCI_BM(next_offset, TD_PSW_CC) & 0xe))) { - printf("usb-ohci: ISO_TD cc != not accessed 0x%.8x 0x%.8x\n", - start_offset, next_offset); - return 1; - } - - if ((relative_frame_number < frame_count) && (start_offset > next_offset)) { - printf("usb-ohci: ISO_TD start_offset=0x%.8x > next_offset=0x%.8x\n", - start_offset, next_offset); - return 1; - } - - if ((start_offset & 0x1000) == 0) { - start_addr = (iso_td.bp & OHCI_PAGE_MASK) | - (start_offset & OHCI_OFFSET_MASK); - } else { - start_addr = (iso_td.be & OHCI_PAGE_MASK) | - (start_offset & OHCI_OFFSET_MASK); - } - - if (relative_frame_number < frame_count) { - end_offset = next_offset - 1; - if ((end_offset & 0x1000) == 0) { - end_addr = (iso_td.bp & OHCI_PAGE_MASK) | - (end_offset & OHCI_OFFSET_MASK); - } else { - end_addr = (iso_td.be & OHCI_PAGE_MASK) | - (end_offset & OHCI_OFFSET_MASK); - } - } else { - /* Last packet in the ISO TD */ - end_addr = iso_td.be; - } - - if ((start_addr & OHCI_PAGE_MASK) != (end_addr & OHCI_PAGE_MASK)) { - len = (end_addr & OHCI_OFFSET_MASK) + 0x1001 - - (start_addr & OHCI_OFFSET_MASK); - } else { - len = end_addr - start_addr + 1; - } - - if (len && dir != OHCI_TD_DIR_IN) { - ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, len, 0); - } - - if (completion) { - ret = ohci->usb_packet.len; - } else { - ret = USB_RET_NODEV; - for (i = 0; i < ohci->num_ports; i++) { - dev = ohci->rhport[i].port.dev; - if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) - continue; - ohci->usb_packet.pid = pid; - ohci->usb_packet.devaddr = OHCI_BM(ed->flags, ED_FA); - ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN); - ohci->usb_packet.data = ohci->usb_buf; - ohci->usb_packet.len = len; - ohci->usb_packet.complete_cb = ohci_async_complete_packet; - ohci->usb_packet.complete_opaque = ohci; - ret = dev->handle_packet(dev, &ohci->usb_packet); - if (ret != USB_RET_NODEV) - break; - } - - if (ret == USB_RET_ASYNC) { - return 1; - } - } - -#ifdef DEBUG_ISOCH - printf("so 0x%.8x eo 0x%.8x\nsa 0x%.8x ea 0x%.8x\ndir %s len %zu ret %d\n", - start_offset, end_offset, start_addr, end_addr, str, len, ret); -#endif - - /* Writeback */ - if (dir == OHCI_TD_DIR_IN && ret >= 0 && ret <= len) { - /* IN transfer succeeded */ - ohci_copy_iso_td(start_addr, end_addr, ohci->usb_buf, ret, 1); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, - OHCI_CC_NOERROR); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, ret); - } else if (dir == OHCI_TD_DIR_OUT && ret == len) { - /* OUT transfer succeeded */ - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, - OHCI_CC_NOERROR); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, 0); - } else { - if (ret > (ssize_t) len) { - printf("usb-ohci: DataOverrun %d > %zu\n", ret, len); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, - OHCI_CC_DATAOVERRUN); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, - len); - } else if (ret >= 0) { - printf("usb-ohci: DataUnderrun %d\n", ret); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, - OHCI_CC_DATAUNDERRUN); - } else { - switch (ret) { - case USB_RET_NODEV: - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, - OHCI_CC_DEVICENOTRESPONDING); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, - 0); - break; - case USB_RET_NAK: - case USB_RET_STALL: - printf("usb-ohci: got NAK/STALL %d\n", ret); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, - OHCI_CC_STALL); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_SIZE, - 0); - break; - default: - printf("usb-ohci: Bad device response %d\n", ret); - OHCI_SET_BM(iso_td.offset[relative_frame_number], TD_PSW_CC, - OHCI_CC_UNDEXPETEDPID); - break; - } - } - } - - if (relative_frame_number == frame_count) { - /* Last data packet of ISO TD - retire the TD to the Done Queue */ - OHCI_SET_BM(iso_td.flags, TD_CC, OHCI_CC_NOERROR); - ed->head &= ~OHCI_DPTR_MASK; - ed->head |= (iso_td.next & OHCI_DPTR_MASK); - iso_td.next = ohci->done; - ohci->done = addr; - i = OHCI_BM(iso_td.flags, TD_DI); - if (i < ohci->done_count) - ohci->done_count = i; - } - ohci_put_iso_td(addr, &iso_td); - return 1; -} - -/* Service a transport descriptor. - Returns nonzero to terminate processing of this endpoint. */ - -static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) -{ - int dir; - size_t len = 0; - const char *str = NULL; - int pid; - int ret; - int i; - USBDevice *dev; - struct ohci_td td; - uint32_t addr; - int flag_r; - int completion; - - addr = ed->head & OHCI_DPTR_MASK; - /* See if this TD has already been submitted to the device. */ - completion = (addr == ohci->async_td); - if (completion && !ohci->async_complete) { -#ifdef DEBUG_PACKET - dprintf("Skipping async TD\n"); -#endif - return 1; - } - if (!ohci_read_td(addr, &td)) { - fprintf(stderr, "usb-ohci: TD read error at %x\n", addr); - return 0; - } - - dir = OHCI_BM(ed->flags, ED_D); - switch (dir) { - case OHCI_TD_DIR_OUT: - case OHCI_TD_DIR_IN: - /* Same value. */ - break; - default: - dir = OHCI_BM(td.flags, TD_DP); - break; - } - - switch (dir) { - case OHCI_TD_DIR_IN: - str = "in"; - pid = USB_TOKEN_IN; - break; - case OHCI_TD_DIR_OUT: - str = "out"; - pid = USB_TOKEN_OUT; - break; - case OHCI_TD_DIR_SETUP: - str = "setup"; - pid = USB_TOKEN_SETUP; - break; - default: - fprintf(stderr, "usb-ohci: Bad direction\n"); - return 1; - } - if (td.cbp && td.be) { - if ((td.cbp & 0xfffff000) != (td.be & 0xfffff000)) { - len = (td.be & 0xfff) + 0x1001 - (td.cbp & 0xfff); - } else { - len = (td.be - td.cbp) + 1; - } - - if (len && dir != OHCI_TD_DIR_IN && !completion) { - ohci_copy_td(&td, ohci->usb_buf, len, 0); - } - } - - flag_r = (td.flags & OHCI_TD_R) != 0; -#ifdef DEBUG_PACKET - dprintf(" TD @ 0x%.8x %u bytes %s r=%d cbp=0x%.8x be=0x%.8x\n", - addr, len, str, flag_r, td.cbp, td.be); - - if (len > 0 && dir != OHCI_TD_DIR_IN) { - dprintf(" data:"); - for (i = 0; i < len; i++) - printf(" %.2x", ohci->usb_buf[i]); - dprintf("\n"); - } -#endif - if (completion) { - ret = ohci->usb_packet.len; - ohci->async_td = 0; - ohci->async_complete = 0; - } else { - ret = USB_RET_NODEV; - for (i = 0; i < ohci->num_ports; i++) { - dev = ohci->rhport[i].port.dev; - if ((ohci->rhport[i].ctrl & OHCI_PORT_PES) == 0) - continue; - - if (ohci->async_td) { - /* ??? The hardware should allow one active packet per - endpoint. We only allow one active packet per controller. - This should be sufficient as long as devices respond in a - timely manner. - */ -#ifdef DEBUG_PACKET - dprintf("Too many pending packets\n"); -#endif - return 1; - } - ohci->usb_packet.pid = pid; - ohci->usb_packet.devaddr = OHCI_BM(ed->flags, ED_FA); - ohci->usb_packet.devep = OHCI_BM(ed->flags, ED_EN); - ohci->usb_packet.data = ohci->usb_buf; - ohci->usb_packet.len = len; - ohci->usb_packet.complete_cb = ohci_async_complete_packet; - ohci->usb_packet.complete_opaque = ohci; - ret = dev->handle_packet(dev, &ohci->usb_packet); - if (ret != USB_RET_NODEV) - break; - } -#ifdef DEBUG_PACKET - dprintf("ret=%d\n", ret); -#endif - if (ret == USB_RET_ASYNC) { - ohci->async_td = addr; - return 1; - } - } - if (ret >= 0) { - if (dir == OHCI_TD_DIR_IN) { - ohci_copy_td(&td, ohci->usb_buf, ret, 1); -#ifdef DEBUG_PACKET - dprintf(" data:"); - for (i = 0; i < ret; i++) - printf(" %.2x", ohci->usb_buf[i]); - dprintf("\n"); -#endif - } else { - ret = len; - } - } - - /* Writeback */ - if (ret == len || (dir == OHCI_TD_DIR_IN && ret >= 0 && flag_r)) { - /* Transmission succeeded. */ - if (ret == len) { - td.cbp = 0; - } else { - td.cbp += ret; - if ((td.cbp & 0xfff) + ret > 0xfff) { - td.cbp &= 0xfff; - td.cbp |= td.be & ~0xfff; - } - } - td.flags |= OHCI_TD_T1; - td.flags ^= OHCI_TD_T0; - OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_NOERROR); - OHCI_SET_BM(td.flags, TD_EC, 0); - - ed->head &= ~OHCI_ED_C; - if (td.flags & OHCI_TD_T0) - ed->head |= OHCI_ED_C; - } else { - if (ret >= 0) { - dprintf("usb-ohci: Underrun\n"); - OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAUNDERRUN); - } else { - switch (ret) { - case USB_RET_NODEV: - OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DEVICENOTRESPONDING); - case USB_RET_NAK: - dprintf("usb-ohci: got NAK\n"); - return 1; - case USB_RET_STALL: - dprintf("usb-ohci: got STALL\n"); - OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_STALL); - break; - case USB_RET_BABBLE: - dprintf("usb-ohci: got BABBLE\n"); - OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_DATAOVERRUN); - break; - default: - fprintf(stderr, "usb-ohci: Bad device response %d\n", ret); - OHCI_SET_BM(td.flags, TD_CC, OHCI_CC_UNDEXPETEDPID); - OHCI_SET_BM(td.flags, TD_EC, 3); - break; - } - } - ed->head |= OHCI_ED_H; - } - - /* Retire this TD */ - ed->head &= ~OHCI_DPTR_MASK; - ed->head |= td.next & OHCI_DPTR_MASK; - td.next = ohci->done; - ohci->done = addr; - i = OHCI_BM(td.flags, TD_DI); - if (i < ohci->done_count) - ohci->done_count = i; - ohci_put_td(addr, &td); - return OHCI_BM(td.flags, TD_CC) != OHCI_CC_NOERROR; -} - -/* Service an endpoint list. Returns nonzero if active TD were found. */ -static int ohci_service_ed_list(OHCIState *ohci, uint32_t head, int completion) -{ - struct ohci_ed ed; - uint32_t next_ed; - uint32_t cur; - int active; - - active = 0; - - if (head == 0) - return 0; - - for (cur = head; cur; cur = next_ed) { - if (!ohci_read_ed(cur, &ed)) { - fprintf(stderr, "usb-ohci: ED read error at %x\n", cur); - return 0; - } - - next_ed = ed.next & OHCI_DPTR_MASK; - - if ((ed.head & OHCI_ED_H) || (ed.flags & OHCI_ED_K)) { - uint32_t addr; - /* Cancel pending packets for ED that have been paused. */ - addr = ed.head & OHCI_DPTR_MASK; - if (ohci->async_td && addr == ohci->async_td) { - usb_cancel_packet(&ohci->usb_packet); - ohci->async_td = 0; - } - continue; - } - - while ((ed.head & OHCI_DPTR_MASK) != ed.tail) { -#ifdef DEBUG_PACKET - dprintf("ED @ 0x%.8x fa=%u en=%u d=%u s=%u k=%u f=%u mps=%u " - "h=%u c=%u\n head=0x%.8x tailp=0x%.8x next=0x%.8x\n", cur, - OHCI_BM(ed.flags, ED_FA), OHCI_BM(ed.flags, ED_EN), - OHCI_BM(ed.flags, ED_D), (ed.flags & OHCI_ED_S)!= 0, - (ed.flags & OHCI_ED_K) != 0, (ed.flags & OHCI_ED_F) != 0, - OHCI_BM(ed.flags, ED_MPS), (ed.head & OHCI_ED_H) != 0, - (ed.head & OHCI_ED_C) != 0, ed.head & OHCI_DPTR_MASK, - ed.tail & OHCI_DPTR_MASK, ed.next & OHCI_DPTR_MASK); -#endif - active = 1; - - if ((ed.flags & OHCI_ED_F) == 0) { - if (ohci_service_td(ohci, &ed)) - break; - } else { - /* Handle isochronous endpoints */ - if (ohci_service_iso_td(ohci, &ed, completion)) - break; - } - } - - ohci_put_ed(cur, &ed); - } - - return active; -} - -/* Generate a SOF event, and set a timer for EOF */ -static void ohci_sof(OHCIState *ohci) -{ - ohci->sof_time = qemu_get_clock(vm_clock); - qemu_mod_timer(ohci->eof_timer, ohci->sof_time + usb_frame_time); - ohci_set_interrupt(ohci, OHCI_INTR_SF); -} - -/* Process Control and Bulk lists. */ -static void ohci_process_lists(OHCIState *ohci, int completion) -{ - if ((ohci->ctl & OHCI_CTL_CLE) && (ohci->status & OHCI_STATUS_CLF)) { - if (ohci->ctrl_cur && ohci->ctrl_cur != ohci->ctrl_head) - dprintf("usb-ohci: head %x, cur %x\n", - ohci->ctrl_head, ohci->ctrl_cur); - if (!ohci_service_ed_list(ohci, ohci->ctrl_head, completion)) { - ohci->ctrl_cur = 0; - ohci->status &= ~OHCI_STATUS_CLF; - } - } - - if ((ohci->ctl & OHCI_CTL_BLE) && (ohci->status & OHCI_STATUS_BLF)) { - if (!ohci_service_ed_list(ohci, ohci->bulk_head, completion)) { - ohci->bulk_cur = 0; - ohci->status &= ~OHCI_STATUS_BLF; - } - } -} - -/* Do frame processing on frame boundary */ -static void ohci_frame_boundary(void *opaque) -{ - OHCIState *ohci = opaque; - struct ohci_hcca hcca; - - cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 0); - - /* Process all the lists at the end of the frame */ - if (ohci->ctl & OHCI_CTL_PLE) { - int n; - - n = ohci->frame_number & 0x1f; - ohci_service_ed_list(ohci, le32_to_cpu(hcca.intr[n]), 0); - } - - /* Cancel all pending packets if either of the lists has been disabled. */ - if (ohci->async_td && - ohci->old_ctl & (~ohci->ctl) & (OHCI_CTL_BLE | OHCI_CTL_CLE)) { - usb_cancel_packet(&ohci->usb_packet); - ohci->async_td = 0; - } - ohci->old_ctl = ohci->ctl; - ohci_process_lists(ohci, 0); - - /* Frame boundary, so do EOF stuf here */ - ohci->frt = ohci->fit; - - /* XXX: endianness */ - ohci->frame_number = (ohci->frame_number + 1) & 0xffff; - hcca.frame = cpu_to_le32(ohci->frame_number); - - if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { - if (!ohci->done) - abort(); - if (ohci->intr & ohci->intr_status) - ohci->done |= 1; - hcca.done = cpu_to_le32(ohci->done); - ohci->done = 0; - ohci->done_count = 7; - ohci_set_interrupt(ohci, OHCI_INTR_WD); - } - - if (ohci->done_count != 7 && ohci->done_count != 0) - ohci->done_count--; - - /* Do SOF stuff here */ - ohci_sof(ohci); - - /* Writeback HCCA */ - cpu_physical_memory_rw(ohci->hcca, (uint8_t *)&hcca, sizeof(hcca), 1); -} - -/* Start sending SOF tokens across the USB bus, lists are processed in - * next frame - */ -static int ohci_bus_start(OHCIState *ohci) -{ - ohci->eof_timer = qemu_new_timer(vm_clock, - ohci_frame_boundary, - ohci); - - if (ohci->eof_timer == NULL) { - fprintf(stderr, "usb-ohci: %s: qemu_new_timer failed\n", ohci->name); - /* TODO: Signal unrecoverable error */ - return 0; - } - - dprintf("usb-ohci: %s: USB Operational\n", ohci->name); - - ohci_sof(ohci); - - return 1; -} - -/* Stop sending SOF tokens on the bus */ -static void ohci_bus_stop(OHCIState *ohci) -{ - if (ohci->eof_timer) - qemu_del_timer(ohci->eof_timer); - ohci->eof_timer = NULL; -} - -/* Sets a flag in a port status register but only set it if the port is - * connected, if not set ConnectStatusChange flag. If flag is enabled - * return 1. - */ -static int ohci_port_set_if_connected(OHCIState *ohci, int i, uint32_t val) -{ - int ret = 1; - - /* writing a 0 has no effect */ - if (val == 0) - return 0; - - /* If CurrentConnectStatus is cleared we set - * ConnectStatusChange - */ - if (!(ohci->rhport[i].ctrl & OHCI_PORT_CCS)) { - ohci->rhport[i].ctrl |= OHCI_PORT_CSC; - if (ohci->rhstatus & OHCI_RHS_DRWE) { - /* TODO: CSC is a wakeup event */ - } - return 0; - } - - if (ohci->rhport[i].ctrl & val) - ret = 0; - - /* set the bit */ - ohci->rhport[i].ctrl |= val; - - return ret; -} - -/* Set the frame interval - frame interval toggle is manipulated by the hcd only */ -static void ohci_set_frame_interval(OHCIState *ohci, uint16_t val) -{ - val &= OHCI_FMI_FI; - - if (val != ohci->fi) { - dprintf("usb-ohci: %s: FrameInterval = 0x%x (%u)\n", - ohci->name, ohci->fi, ohci->fi); - } - - ohci->fi = val; -} - -static void ohci_port_power(OHCIState *ohci, int i, int p) -{ - if (p) { - ohci->rhport[i].ctrl |= OHCI_PORT_PPS; - } else { - ohci->rhport[i].ctrl &= ~(OHCI_PORT_PPS| - OHCI_PORT_CCS| - OHCI_PORT_PSS| - OHCI_PORT_PRS); - } -} - -/* Set HcControlRegister */ -static void ohci_set_ctl(OHCIState *ohci, uint32_t val) -{ - uint32_t old_state; - uint32_t new_state; - - old_state = ohci->ctl & OHCI_CTL_HCFS; - ohci->ctl = val; - new_state = ohci->ctl & OHCI_CTL_HCFS; - - /* no state change */ - if (old_state == new_state) - return; - - switch (new_state) { - case OHCI_USB_OPERATIONAL: - ohci_bus_start(ohci); - break; - case OHCI_USB_SUSPEND: - ohci_bus_stop(ohci); - dprintf("usb-ohci: %s: USB Suspended\n", ohci->name); - break; - case OHCI_USB_RESUME: - dprintf("usb-ohci: %s: USB Resume\n", ohci->name); - break; - case OHCI_USB_RESET: - ohci_reset(ohci); - dprintf("usb-ohci: %s: USB Reset\n", ohci->name); - break; - } -} - -static uint32_t ohci_get_frame_remaining(OHCIState *ohci) -{ - uint16_t fr; - int64_t tks; - - if ((ohci->ctl & OHCI_CTL_HCFS) != OHCI_USB_OPERATIONAL) - return (ohci->frt << 31); - - /* Being in USB operational state guarnatees sof_time was - * set already. - */ - tks = qemu_get_clock(vm_clock) - ohci->sof_time; - - /* avoid muldiv if possible */ - if (tks >= usb_frame_time) - return (ohci->frt << 31); - - tks = muldiv64(1, tks, usb_bit_time); - fr = (uint16_t)(ohci->fi - tks); - - return (ohci->frt << 31) | fr; -} - - -/* Set root hub status */ -static void ohci_set_hub_status(OHCIState *ohci, uint32_t val) -{ - uint32_t old_state; - - old_state = ohci->rhstatus; - - /* write 1 to clear OCIC */ - if (val & OHCI_RHS_OCIC) - ohci->rhstatus &= ~OHCI_RHS_OCIC; - - if (val & OHCI_RHS_LPS) { - int i; - - for (i = 0; i < ohci->num_ports; i++) - ohci_port_power(ohci, i, 0); - dprintf("usb-ohci: powered down all ports\n"); - } - - if (val & OHCI_RHS_LPSC) { - int i; - - for (i = 0; i < ohci->num_ports; i++) - ohci_port_power(ohci, i, 1); - dprintf("usb-ohci: powered up all ports\n"); - } - - if (val & OHCI_RHS_DRWE) - ohci->rhstatus |= OHCI_RHS_DRWE; - - if (val & OHCI_RHS_CRWE) - ohci->rhstatus &= ~OHCI_RHS_DRWE; - - if (old_state != ohci->rhstatus) - ohci_set_interrupt(ohci, OHCI_INTR_RHSC); -} - -/* Set root hub port status */ -static void ohci_port_set_status(OHCIState *ohci, int portnum, uint32_t val) -{ - uint32_t old_state; - OHCIPort *port; - - port = &ohci->rhport[portnum]; - old_state = port->ctrl; - - /* Write to clear CSC, PESC, PSSC, OCIC, PRSC */ - if (val & OHCI_PORT_WTC) - port->ctrl &= ~(val & OHCI_PORT_WTC); - - if (val & OHCI_PORT_CCS) - port->ctrl &= ~OHCI_PORT_PES; - - ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PES); - - if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PSS)) - dprintf("usb-ohci: port %d: SUSPEND\n", portnum); - - if (ohci_port_set_if_connected(ohci, portnum, val & OHCI_PORT_PRS)) { - dprintf("usb-ohci: port %d: RESET\n", portnum); - usb_send_msg(port->port.dev, USB_MSG_RESET); - port->ctrl &= ~OHCI_PORT_PRS; - /* ??? Should this also set OHCI_PORT_PESC. */ - port->ctrl |= OHCI_PORT_PES | OHCI_PORT_PRSC; - } - - /* Invert order here to ensure in ambiguous case, device is - * powered up... - */ - if (val & OHCI_PORT_LSDA) - ohci_port_power(ohci, portnum, 0); - if (val & OHCI_PORT_PPS) - ohci_port_power(ohci, portnum, 1); - - if (old_state != port->ctrl) - ohci_set_interrupt(ohci, OHCI_INTR_RHSC); - - return; -} - -static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr) -{ - OHCIState *ohci = ptr; - - addr -= ohci->mem_base; - - /* Only aligned reads are allowed on OHCI */ - if (addr & 3) { - fprintf(stderr, "usb-ohci: Mis-aligned read\n"); - return 0xffffffff; - } - - if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { - /* HcRhPortStatus */ - return ohci->rhport[(addr - 0x54) >> 2].ctrl | OHCI_PORT_PPS; - } - - switch (addr >> 2) { - case 0: /* HcRevision */ - return 0x10; - - case 1: /* HcControl */ - return ohci->ctl; - - case 2: /* HcCommandStatus */ - return ohci->status; - - case 3: /* HcInterruptStatus */ - return ohci->intr_status; - - case 4: /* HcInterruptEnable */ - case 5: /* HcInterruptDisable */ - return ohci->intr; - - case 6: /* HcHCCA */ - return ohci->hcca; - - case 7: /* HcPeriodCurrentED */ - return ohci->per_cur; - - case 8: /* HcControlHeadED */ - return ohci->ctrl_head; - - case 9: /* HcControlCurrentED */ - return ohci->ctrl_cur; - - case 10: /* HcBulkHeadED */ - return ohci->bulk_head; - - case 11: /* HcBulkCurrentED */ - return ohci->bulk_cur; - - case 12: /* HcDoneHead */ - return ohci->done; - - case 13: /* HcFmInterval */ - return (ohci->fit << 31) | (ohci->fsmps << 16) | (ohci->fi); - - case 14: /* HcFmRemaining */ - return ohci_get_frame_remaining(ohci); - - case 15: /* HcFmNumber */ - return ohci->frame_number; - - case 16: /* HcPeriodicStart */ - return ohci->pstart; - - case 17: /* HcLSThreshold */ - return ohci->lst; - - case 18: /* HcRhDescriptorA */ - return ohci->rhdesc_a; - - case 19: /* HcRhDescriptorB */ - return ohci->rhdesc_b; - - case 20: /* HcRhStatus */ - return ohci->rhstatus; - - /* PXA27x specific registers */ - case 24: /* HcStatus */ - return ohci->hstatus & ohci->hmask; - - case 25: /* HcHReset */ - return ohci->hreset; - - case 26: /* HcHInterruptEnable */ - return ohci->hmask; - - case 27: /* HcHInterruptTest */ - return ohci->htest; - - default: - fprintf(stderr, "ohci_read: Bad offset %x\n", (int)addr); - return 0xffffffff; - } -} - -static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val) -{ - OHCIState *ohci = ptr; - - addr -= ohci->mem_base; - - /* Only aligned reads are allowed on OHCI */ - if (addr & 3) { - fprintf(stderr, "usb-ohci: Mis-aligned write\n"); - return; - } - - if (addr >= 0x54 && addr < 0x54 + ohci->num_ports * 4) { - /* HcRhPortStatus */ - ohci_port_set_status(ohci, (addr - 0x54) >> 2, val); - return; - } - - switch (addr >> 2) { - case 1: /* HcControl */ - ohci_set_ctl(ohci, val); - break; - - case 2: /* HcCommandStatus */ - /* SOC is read-only */ - val = (val & ~OHCI_STATUS_SOC); - - /* Bits written as '0' remain unchanged in the register */ - ohci->status |= val; - - if (ohci->status & OHCI_STATUS_HCR) - ohci_reset(ohci); - break; - - case 3: /* HcInterruptStatus */ - ohci->intr_status &= ~val; - ohci_intr_update(ohci); - break; - - case 4: /* HcInterruptEnable */ - ohci->intr |= val; - ohci_intr_update(ohci); - break; - - case 5: /* HcInterruptDisable */ - ohci->intr &= ~val; - ohci_intr_update(ohci); - break; - - case 6: /* HcHCCA */ - ohci->hcca = val & OHCI_HCCA_MASK; - break; - - case 8: /* HcControlHeadED */ - ohci->ctrl_head = val & OHCI_EDPTR_MASK; - break; - - case 9: /* HcControlCurrentED */ - ohci->ctrl_cur = val & OHCI_EDPTR_MASK; - break; - - case 10: /* HcBulkHeadED */ - ohci->bulk_head = val & OHCI_EDPTR_MASK; - break; - - case 11: /* HcBulkCurrentED */ - ohci->bulk_cur = val & OHCI_EDPTR_MASK; - break; - - case 13: /* HcFmInterval */ - ohci->fsmps = (val & OHCI_FMI_FSMPS) >> 16; - ohci->fit = (val & OHCI_FMI_FIT) >> 31; - ohci_set_frame_interval(ohci, val); - break; - - case 15: /* HcFmNumber */ - break; - - case 16: /* HcPeriodicStart */ - ohci->pstart = val & 0xffff; - break; - - case 17: /* HcLSThreshold */ - ohci->lst = val & 0xffff; - break; - - case 18: /* HcRhDescriptorA */ - ohci->rhdesc_a &= ~OHCI_RHA_RW_MASK; - ohci->rhdesc_a |= val & OHCI_RHA_RW_MASK; - break; - - case 19: /* HcRhDescriptorB */ - break; - - case 20: /* HcRhStatus */ - ohci_set_hub_status(ohci, val); - break; - - /* PXA27x specific registers */ - case 24: /* HcStatus */ - ohci->hstatus &= ~(val & ohci->hmask); - - case 25: /* HcHReset */ - ohci->hreset = val & ~OHCI_HRESET_FSBIR; - if (val & OHCI_HRESET_FSBIR) - ohci_reset(ohci); - break; - - case 26: /* HcHInterruptEnable */ - ohci->hmask = val; - break; - - case 27: /* HcHInterruptTest */ - ohci->htest = val; - break; - - default: - fprintf(stderr, "ohci_write: Bad offset %x\n", (int)addr); - break; - } -} - -/* Only dword reads are defined on OHCI register space */ -static CPUReadMemoryFunc *ohci_readfn[3]={ - ohci_mem_read, - ohci_mem_read, - ohci_mem_read -}; - -/* Only dword writes are defined on OHCI register space */ -static CPUWriteMemoryFunc *ohci_writefn[3]={ - ohci_mem_write, - ohci_mem_write, - ohci_mem_write -}; - -static void usb_ohci_init(OHCIState *ohci, int num_ports, int devfn, - qemu_irq irq, enum ohci_type type, const char *name) -{ - int i; - - if (usb_frame_time == 0) { -#ifdef OHCI_TIME_WARP - usb_frame_time = ticks_per_sec; - usb_bit_time = muldiv64(1, ticks_per_sec, USB_HZ/1000); -#else - usb_frame_time = muldiv64(1, ticks_per_sec, 1000); - if (ticks_per_sec >= USB_HZ) { - usb_bit_time = muldiv64(1, ticks_per_sec, USB_HZ); - } else { - usb_bit_time = 1; - } -#endif - dprintf("usb-ohci: usb_bit_time=%lli usb_frame_time=%lli\n", - usb_frame_time, usb_bit_time); - } - - ohci->mem = cpu_register_io_memory(0, ohci_readfn, ohci_writefn, ohci); - ohci->name = name; - - ohci->irq = irq; - ohci->type = type; - - ohci->num_ports = num_ports; - for (i = 0; i < num_ports; i++) { - qemu_register_usb_port(&ohci->rhport[i].port, ohci, i, ohci_attach); - } - - ohci->async_td = 0; - qemu_register_reset(ohci_reset, ohci); - ohci_reset(ohci); -} - -typedef struct { - PCIDevice pci_dev; - OHCIState state; -} OHCIPCIState; - -static void ohci_mapfunc(PCIDevice *pci_dev, int i, - uint32_t addr, uint32_t size, int type) -{ - OHCIPCIState *ohci = (OHCIPCIState *)pci_dev; - ohci->state.mem_base = addr; - cpu_register_physical_memory(addr, size, ohci->state.mem); -} - -void usb_ohci_init_pci(struct PCIBus *bus, int num_ports, int devfn) -{ - OHCIPCIState *ohci; - int vid = 0x106b; - int did = 0x003f; - - ohci = (OHCIPCIState *)pci_register_device(bus, "OHCI USB", sizeof(*ohci), - devfn, NULL, NULL); - if (ohci == NULL) { - fprintf(stderr, "usb-ohci: Failed to register PCI device\n"); - return; - } - - ohci->pci_dev.config[0x00] = vid & 0xff; - ohci->pci_dev.config[0x01] = (vid >> 8) & 0xff; - ohci->pci_dev.config[0x02] = did & 0xff; - ohci->pci_dev.config[0x03] = (did >> 8) & 0xff; - ohci->pci_dev.config[0x09] = 0x10; /* OHCI */ - ohci->pci_dev.config[0x0a] = 0x3; - ohci->pci_dev.config[0x0b] = 0xc; - ohci->pci_dev.config[0x3d] = 0x01; /* interrupt pin 1 */ - - usb_ohci_init(&ohci->state, num_ports, devfn, ohci->pci_dev.irq[0], - OHCI_TYPE_PCI, ohci->pci_dev.name); - - pci_register_io_region((struct PCIDevice *)ohci, 0, 256, - PCI_ADDRESS_SPACE_MEM, ohci_mapfunc); -} - -void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn, - qemu_irq irq) -{ - OHCIState *ohci = (OHCIState *)qemu_mallocz(sizeof(OHCIState)); - - usb_ohci_init(ohci, num_ports, devfn, irq, - OHCI_TYPE_PXA, "OHCI USB"); - ohci->mem_base = base; - - cpu_register_physical_memory(ohci->mem_base, 0x1000, ohci->mem); -} diff --git a/hw/usb.c b/hw/usb.c deleted file mode 100644 index c17266d..0000000 --- a/hw/usb.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * QEMU USB emulation - * - * Copyright (c) 2005 Fabrice Bellard - * - * 2008 Generic packet handler rewrite by Max Krasnyansky - * - * 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 "qemu-common.h" -#include "usb.h" - -void usb_attach(USBPort *port, USBDevice *dev) -{ - port->attach(port, dev); -} - -/**********************/ - -/* generic USB device helpers (you are not forced to use them when - writing your USB device driver, but they help handling the - protocol) -*/ - -#define SETUP_STATE_IDLE 0 -#define SETUP_STATE_DATA 1 -#define SETUP_STATE_ACK 2 - -static int do_token_setup(USBDevice *s, USBPacket *p) -{ - int request, value, index; - int ret = 0; - - if (p->len != 8) - return USB_RET_STALL; - - memcpy(s->setup_buf, p->data, 8); - s->setup_len = (s->setup_buf[7] << 8) | s->setup_buf[6]; - s->setup_index = 0; - - request = (s->setup_buf[0] << 8) | s->setup_buf[1]; - value = (s->setup_buf[3] << 8) | s->setup_buf[2]; - index = (s->setup_buf[5] << 8) | s->setup_buf[4]; - - if (s->setup_buf[0] & USB_DIR_IN) { - ret = s->handle_control(s, request, value, index, - s->setup_len, s->data_buf); - if (ret < 0) - return ret; - - if (ret < s->setup_len) - s->setup_len = ret; - s->setup_state = SETUP_STATE_DATA; - } else { - if (s->setup_len == 0) - s->setup_state = SETUP_STATE_ACK; - else - s->setup_state = SETUP_STATE_DATA; - } - - return ret; -} - -static int do_token_in(USBDevice *s, USBPacket *p) -{ - int request, value, index; - int ret = 0; - - if (p->devep != 0) - return s->handle_data(s, p); - - request = (s->setup_buf[0] << 8) | s->setup_buf[1]; - value = (s->setup_buf[3] << 8) | s->setup_buf[2]; - index = (s->setup_buf[5] << 8) | s->setup_buf[4]; - - switch(s->setup_state) { - case SETUP_STATE_ACK: - if (!(s->setup_buf[0] & USB_DIR_IN)) { - s->setup_state = SETUP_STATE_IDLE; - ret = s->handle_control(s, request, value, index, - s->setup_len, s->data_buf); - if (ret > 0) - return 0; - return ret; - } - - /* return 0 byte */ - return 0; - - case SETUP_STATE_DATA: - if (s->setup_buf[0] & USB_DIR_IN) { - int len = s->setup_len - s->setup_index; - if (len > p->len) - len = p->len; - memcpy(p->data, s->data_buf + s->setup_index, len); - s->setup_index += len; - if (s->setup_index >= s->setup_len) - s->setup_state = SETUP_STATE_ACK; - return len; - } - - s->setup_state = SETUP_STATE_IDLE; - return USB_RET_STALL; - - default: - return USB_RET_STALL; - } -} - -static int do_token_out(USBDevice *s, USBPacket *p) -{ - if (p->devep != 0) - return s->handle_data(s, p); - - switch(s->setup_state) { - case SETUP_STATE_ACK: - if (s->setup_buf[0] & USB_DIR_IN) { - s->setup_state = SETUP_STATE_IDLE; - /* transfer OK */ - } else { - /* ignore additional output */ - } - return 0; - - case SETUP_STATE_DATA: - if (!(s->setup_buf[0] & USB_DIR_IN)) { - int len = s->setup_len - s->setup_index; - if (len > p->len) - len = p->len; - memcpy(s->data_buf + s->setup_index, p->data, len); - s->setup_index += len; - if (s->setup_index >= s->setup_len) - s->setup_state = SETUP_STATE_ACK; - return len; - } - - s->setup_state = SETUP_STATE_IDLE; - return USB_RET_STALL; - - default: - return USB_RET_STALL; - } -} - -/* - * Generic packet handler. - * Called by the HC (host controller). - * - * Returns length of the transaction or one of the USB_RET_XXX codes. - */ -int usb_generic_handle_packet(USBDevice *s, USBPacket *p) -{ - switch(p->pid) { - case USB_MSG_ATTACH: - s->state = USB_STATE_ATTACHED; - return 0; - - case USB_MSG_DETACH: - s->state = USB_STATE_NOTATTACHED; - return 0; - - case USB_MSG_RESET: - s->remote_wakeup = 0; - s->addr = 0; - s->state = USB_STATE_DEFAULT; - s->handle_reset(s); - return 0; - } - - /* Rest of the PIDs must match our address */ - if (s->state < USB_STATE_DEFAULT || p->devaddr != s->addr) - return USB_RET_NODEV; - - switch (p->pid) { - case USB_TOKEN_SETUP: - return do_token_setup(s, p); - - case USB_TOKEN_IN: - return do_token_in(s, p); - - case USB_TOKEN_OUT: - return do_token_out(s, p); - - default: - return USB_RET_STALL; - } -} - -/* XXX: fix overflow */ -int set_usb_string(uint8_t *buf, const char *str) -{ - int len, i; - uint8_t *q; - - q = buf; - len = strlen(str); - *q++ = 2 * len + 2; - *q++ = 3; - for(i = 0; i < len; i++) { - *q++ = str[i]; - *q++ = 0; - } - return q - buf; -} - -/* Send an internal message to a USB device. */ -void usb_send_msg(USBDevice *dev, int msg) -{ - USBPacket p; - memset(&p, 0, sizeof(p)); - p.pid = msg; - dev->handle_packet(dev, &p); - - /* This _must_ be synchronous */ -} diff --git a/hw/usb.h b/hw/usb.h deleted file mode 100644 index 1a353bb..0000000 --- a/hw/usb.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * QEMU USB API - * - * 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. - */ -#define USB_TOKEN_SETUP 0x2d -#define USB_TOKEN_IN 0x69 /* device -> host */ -#define USB_TOKEN_OUT 0xe1 /* host -> device */ - -/* specific usb messages, also sent in the 'pid' parameter */ -#define USB_MSG_ATTACH 0x100 -#define USB_MSG_DETACH 0x101 -#define USB_MSG_RESET 0x102 - -#define USB_RET_NODEV (-1) -#define USB_RET_NAK (-2) -#define USB_RET_STALL (-3) -#define USB_RET_BABBLE (-4) -#define USB_RET_ASYNC (-5) - -#define USB_SPEED_LOW 0 -#define USB_SPEED_FULL 1 -#define USB_SPEED_HIGH 2 - -#define USB_STATE_NOTATTACHED 0 -#define USB_STATE_ATTACHED 1 -//#define USB_STATE_POWERED 2 -#define USB_STATE_DEFAULT 3 -//#define USB_STATE_ADDRESS 4 -//#define USB_STATE_CONFIGURED 5 -#define USB_STATE_SUSPENDED 6 - -#define USB_CLASS_AUDIO 1 -#define USB_CLASS_COMM 2 -#define USB_CLASS_HID 3 -#define USB_CLASS_PHYSICAL 5 -#define USB_CLASS_STILL_IMAGE 6 -#define USB_CLASS_PRINTER 7 -#define USB_CLASS_MASS_STORAGE 8 -#define USB_CLASS_HUB 9 -#define USB_CLASS_CDC_DATA 0x0a -#define USB_CLASS_CSCID 0x0b -#define USB_CLASS_CONTENT_SEC 0x0d -#define USB_CLASS_APP_SPEC 0xfe -#define USB_CLASS_VENDOR_SPEC 0xff - -#define USB_DIR_OUT 0 -#define USB_DIR_IN 0x80 - -#define USB_TYPE_MASK (0x03 << 5) -#define USB_TYPE_STANDARD (0x00 << 5) -#define USB_TYPE_CLASS (0x01 << 5) -#define USB_TYPE_VENDOR (0x02 << 5) -#define USB_TYPE_RESERVED (0x03 << 5) - -#define USB_RECIP_MASK 0x1f -#define USB_RECIP_DEVICE 0x00 -#define USB_RECIP_INTERFACE 0x01 -#define USB_RECIP_ENDPOINT 0x02 -#define USB_RECIP_OTHER 0x03 - -#define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) -#define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) -#define InterfaceRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -#define InterfaceOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -#define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) -#define EndpointOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) - -#define USB_REQ_GET_STATUS 0x00 -#define USB_REQ_CLEAR_FEATURE 0x01 -#define USB_REQ_SET_FEATURE 0x03 -#define USB_REQ_SET_ADDRESS 0x05 -#define USB_REQ_GET_DESCRIPTOR 0x06 -#define USB_REQ_SET_DESCRIPTOR 0x07 -#define USB_REQ_GET_CONFIGURATION 0x08 -#define USB_REQ_SET_CONFIGURATION 0x09 -#define USB_REQ_GET_INTERFACE 0x0A -#define USB_REQ_SET_INTERFACE 0x0B -#define USB_REQ_SYNCH_FRAME 0x0C - -#define USB_DEVICE_SELF_POWERED 0 -#define USB_DEVICE_REMOTE_WAKEUP 1 - -#define USB_DT_DEVICE 0x01 -#define USB_DT_CONFIG 0x02 -#define USB_DT_STRING 0x03 -#define USB_DT_INTERFACE 0x04 -#define USB_DT_ENDPOINT 0x05 - -#define USB_ENDPOINT_XFER_CONTROL 0 -#define USB_ENDPOINT_XFER_ISOC 1 -#define USB_ENDPOINT_XFER_BULK 2 -#define USB_ENDPOINT_XFER_INT 3 - -typedef struct USBPort USBPort; -typedef struct USBDevice USBDevice; -typedef struct USBPacket USBPacket; - -/* definition of a USB device */ -struct USBDevice { - void *opaque; - - /* - * Process USB packet. - * Called by the HC (Host Controller). - * - * Returns length of the transaction - * or one of the USB_RET_XXX codes. - */ - int (*handle_packet)(USBDevice *dev, USBPacket *p); - - /* - * Called when device is destroyed. - */ - void (*handle_destroy)(USBDevice *dev); - - int speed; - - /* The following fields are used by the generic USB device - layer. They are here just to avoid creating a new structure - for them. */ - - /* - * Reset the device - */ - void (*handle_reset)(USBDevice *dev); - - /* - * Process control request. - * Called from handle_packet(). - * - * Returns length or one of the USB_RET_ codes. - */ - int (*handle_control)(USBDevice *dev, int request, int value, - int index, int length, uint8_t *data); - - /* - * Process data transfers (both BULK and ISOC). - * Called from handle_packet(). - * - * Returns length or one of the USB_RET_ codes. - */ - int (*handle_data)(USBDevice *dev, USBPacket *p); - - uint8_t addr; - char devname[32]; - - int state; - uint8_t setup_buf[8]; - uint8_t data_buf[1024]; - int remote_wakeup; - int setup_state; - int setup_len; - int setup_index; -}; - -typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev); - -/* USB port on which a device can be connected */ -struct USBPort { - USBDevice *dev; - usb_attachfn attach; - void *opaque; - int index; /* internal port index, may be used with the opaque */ - struct USBPort *next; /* Used internally by qemu. */ -}; - -typedef void USBCallback(USBPacket * packet, void *opaque); - -/* Structure used to hold information about an active USB packet. */ -struct USBPacket { - /* Data fields for use by the driver. */ - int pid; - uint8_t devaddr; - uint8_t devep; - uint8_t *data; - int len; - /* Internal use by the USB layer. */ - USBCallback *complete_cb; - void *complete_opaque; - USBCallback *cancel_cb; - void *cancel_opaque; -}; - -/* Defer completion of a USB packet. The hadle_packet routine should then - return USB_RET_ASYNC. Packets that complete immediately (before - handle_packet returns) should not call this method. */ -static inline void usb_defer_packet(USBPacket *p, USBCallback *cancel, - void * opaque) -{ - p->cancel_cb = cancel; - p->cancel_opaque = opaque; -} - -/* Notify the controller that an async packet is complete. This should only - be called for packets previously deferred with usb_defer_packet, and - should never be called from within handle_packet. */ -static inline void usb_packet_complete(USBPacket *p) -{ - p->complete_cb(p, p->complete_opaque); -} - -/* Cancel an active packet. The packed must have been deferred with - usb_defer_packet, and not yet completed. */ -static inline void usb_cancel_packet(USBPacket * p) -{ - p->cancel_cb(p, p->cancel_opaque); -} - -int usb_device_add_dev(USBDevice *dev); -int usb_device_del_addr(int bus_num, int addr); -void usb_attach(USBPort *port, USBDevice *dev); -int usb_generic_handle_packet(USBDevice *s, USBPacket *p); -int set_usb_string(uint8_t *buf, const char *str); -void usb_send_msg(USBDevice *dev, int msg); - -/* usb hub */ -USBDevice *usb_hub_init(int nb_ports); - -/* usb-linux.c */ -USBDevice *usb_host_device_open(const char *devname); -int usb_host_device_close(const char *devname); -void usb_host_info(void); - -/* usb-hid.c */ -USBDevice *usb_mouse_init(void); -USBDevice *usb_tablet_init(void); -USBDevice *usb_keyboard_init(void); - -/* usb-msd.c */ -USBDevice *usb_msd_init(const char *filename); - -/* usb-net.c */ -USBDevice *usb_net_init(NICInfo *nd); - -/* usb-wacom.c */ -USBDevice *usb_wacom_init(void); - -/* usb-serial.c */ -USBDevice *usb_serial_init(const char *filename); - -/* usb ports of the VM */ - -void qemu_register_usb_port(USBPort *port, void *opaque, int index, - usb_attachfn attach); - -#define VM_USB_HUB_SIZE 8 - -/* usb-musb.c */ -enum musb_irq_source_e { - musb_irq_suspend = 0, - musb_irq_resume, - musb_irq_rst_babble, - musb_irq_sof, - musb_irq_connect, - musb_irq_disconnect, - musb_irq_vbus_request, - musb_irq_vbus_error, - musb_irq_rx, - musb_irq_tx, - musb_set_vbus, - musb_set_session, - __musb_irq_max, -}; - -struct musb_s; -struct musb_s *musb_init(qemu_irq *irqs); -uint32_t musb_core_intr_get(struct musb_s *s); -void musb_core_intr_clear(struct musb_s *s, uint32_t mask); -void musb_set_size(struct musb_s *s, int epnum, int size, int is_tx); |