From patchwork Tue Dec 22 17:40:39 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?5q2m55SwID0/SVNPLTIwMjItSlA/Qj9JQnNrUWoxVFRHa2JLRUk9Pz0=?= X-Patchwork-Id: 41621 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A9210B6EEE for ; Wed, 23 Dec 2009 04:49:49 +1100 (EST) Received: from localhost ([127.0.0.1]:59921 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NN8rd-0001fH-RP for incoming@patchwork.ozlabs.org; Tue, 22 Dec 2009 12:49:41 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NN8kr-0007lC-F7 for qemu-devel@nongnu.org; Tue, 22 Dec 2009 12:42:41 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NN8kl-0007if-1J for qemu-devel@nongnu.org; Tue, 22 Dec 2009 12:42:39 -0500 Received: from [199.232.76.173] (port=56247 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NN8kk-0007iM-NI for qemu-devel@nongnu.org; Tue, 22 Dec 2009 12:42:34 -0500 Received: from smtp-vip.mem.interq.net ([210.157.1.50]:22945 helo=smtp01.mem.internal-gmo) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NN8kj-0001zr-Rh for qemu-devel@nongnu.org; Tue, 22 Dec 2009 12:42:34 -0500 Received: (from root@localhost) by smtp01.mem.internal-gmo (8.13.8/8.12.6) id nBMHgHh7021788 for qemu-devel@nongnu.org; Wed, 23 Dec 2009 02:42:17 +0900 (JST) Received: from YOUR-BD18D6DD63.m1.interq.or.jp (ntymns039132.ymns.nt.ftth.ppp.infoweb.ne.jp [121.92.167.132]) by smtp01.mem.internal-gmo with ESMTP id nBMHgGgH021741 for ; (me101664 for with PLAIN) Wed, 23 Dec 2009 02:42:17 +0900 (JST) Message-Id: <200912221740.AA00210@YOUR-BD18D6DD63.m1.interq.or.jp> From: "TAKEDA, toshiya" Date: Wed, 23 Dec 2009 02:40:39 +0900 To: qemu-devel MIME-Version: 1.0 X-Mailer: AL-Mail32 Version 1.13 X-detected-operating-system: by monty-python.gnu.org: Solaris 10 (beta) Subject: [Qemu-devel] [PATCH V4 07/18] support NEC PC-9821 mouse X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: TAKEDA, toshiya --- hw/pc98mouse.c | 266 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 266 insertions(+), 0 deletions(-) create mode 100644 hw/pc98mouse.c diff --git a/hw/pc98mouse.c b/hw/pc98mouse.c new file mode 100644 index 0000000..0868180 --- /dev/null +++ b/hw/pc98mouse.c @@ -0,0 +1,266 @@ +/* + * QEMU NEC PC-9821 mouse + * + * Copyright (c) 2009 TAKEDA, toshiya + * + * 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 "pc.h" +#include "console.h" +#include "qemu-timer.h" +#include "isa.h" +#include "qdev-addr.h" + +static const int64_t mouse_expire[4] = {120, 60, 30, 15}; + +struct MouseState { + int button; + int dx, dy; + int lx, ly; + uint8_t freq; + uint8_t portc; + + QEMUTimer *mouse_timer; + qemu_irq irq; +}; + +typedef struct ISAMouseState { + ISADevice dev; + uint32_t isairq; + struct MouseState state; +} ISAMouseState; + +typedef struct MouseState MouseState; + +/* mouse */ + +static void mouse_timer_handler(void *opaque) +{ + MouseState *s = opaque; + + if (!(s->portc & 0x10)) { + qemu_set_irq(s->irq, 1); + qemu_set_irq(s->irq, 0); + } + + /* set next timer */ + qemu_mod_timer(s->mouse_timer, qemu_get_clock(rt_clock) + + 1000 / mouse_expire[s->freq & 3]); +} + +static void mouse_event_handler(void *opaque, + int dx, int dy, int dz, int buttons_state) +{ + MouseState *s = opaque; + + s->button = buttons_state; + s->dx += dx; + s->dy += dy; +} + +static void mouse_freq_write(void *opaque, uint32_t addr, uint32_t value) +{ + MouseState *s = opaque; + + if(!(value & 0xfc)) { + s->freq = value; + } +} + +static uint32_t mouse_freq_read(void *opaque, uint32_t addr) +{ + MouseState *s = opaque; + + return s->freq & 3; +} + +/* pio */ + +static uint32_t pio_porta_read(void *opaque, uint32_t addr) +{ + MouseState *s = opaque; + uint32_t val = 0; + + if (!(s->button & 1)) { + val |= 0x80; + } + if (!(s->button & 2)) { + val |= 0x40; + } + if (!(s->button & 4)) { + val |= 0x20; + } + switch (s->portc & 0xe0) { + case 0x00: + val |= (s->dx >> 0) & 0x0f; + break; + case 0x20: + val |= (s->dx >> 4) & 0x0f; + break; + case 0x40: + val |= (s->dy >> 0) & 0x0f; + break; + case 0x60: + val |= (s->dy >> 4) & 0x0f; + break; + case 0x80: + val |= (s->lx >> 0) & 0x0f; + break; + case 0xa0: + val |= (s->lx >> 4) & 0x0f; + break; + case 0xc0: + val |= (s->ly >> 0) & 0x0f; + break; + case 0xe0: + val |= (s->ly >> 4) & 0x0f; + break; + } + return val; +} + +static uint32_t pio_portb_read(void *opaque, uint32_t addr) +{ + return 0xff; +} + +static void pio_portc_write(void *opaque, uint32_t addr, uint32_t value) +{ + MouseState *s = opaque; + + if (!(s->portc & 0x80) && (value & 0x80)) { + /* latch mouse count */ + s->lx = s->dx; + s->ly = s->dy; + s->dx = s->dy = 0; + } + s->portc = (uint8_t)value; +} + +static uint32_t pio_portc_read(void *opaque, uint32_t addr) +{ + MouseState *s = opaque; + + return (s->portc & 0xf0) | 0x08; +} + +static void pio_ctrl_write(void *opaque, uint32_t addr, uint32_t value) +{ + MouseState *s = opaque; + + if (!(value & 0x80)) { + /* set/reset portc bit */ + uint8_t portc = s->portc; + uint8_t bit = 1 << ((value >> 1) & 7); + if (value & 1) { + portc |= bit; + } else { + portc &= ~bit; + } + pio_portc_write(s, 0, portc); + } +} + +/* interface */ + +static void pc98_mouse_reset(void *opaque) +{ + MouseState *s = opaque; + + s->button = 0; + s->dx = s->dy = 0; + s->lx = s->ly = -1; + s->freq = 0; + s->portc = 0xf0; + + qemu_mod_timer(s->mouse_timer, qemu_get_clock(rt_clock) + + 1000 / mouse_expire[0]); +} + +static int pc98_mouse_pre_load(void *opaque) +{ + pc98_mouse_reset(opaque); + return 0; +} + +static const VMStateDescription vmstate_mouse = { + .name = "pc98-mouse", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .pre_load = pc98_mouse_pre_load, + .fields = (VMStateField []) { + VMSTATE_INT32(lx, MouseState), + VMSTATE_INT32(ly, MouseState), + VMSTATE_UINT8(freq, MouseState), + VMSTATE_UINT8(portc, MouseState), + VMSTATE_END_OF_LIST() + } +}; + +static int pc98_mouse_initfn(ISADevice *dev) +{ + ISAMouseState *isa = DO_UPCAST(ISAMouseState, dev, dev); + MouseState *s = &isa->state; + + register_ioport_read(0x7fd9, 1, 1, pio_porta_read, s); + register_ioport_read(0x7fdb, 1, 1, pio_portb_read, s); + register_ioport_write(0x7fdd, 1, 1, pio_portc_write, s); + register_ioport_read(0x7fdd, 1, 1, pio_portc_read, s); + register_ioport_write(0x7fdf, 1, 1, pio_ctrl_write, s); + register_ioport_write(0xbfdb, 1, 1, mouse_freq_write, s); + register_ioport_read(0xbfdb, 1, 1, mouse_freq_read, s); + + isa_init_irq(dev, &s->irq, isa->isairq); + + s->mouse_timer = qemu_new_timer(rt_clock, mouse_timer_handler, s); + qemu_add_mouse_event_handler(mouse_event_handler, s, 0, "pc98-mouse"); + + vmstate_register(-1, &vmstate_mouse, s); + pc98_mouse_reset(s); + qemu_register_reset(pc98_mouse_reset, s); + + return 0; +} + +void pc98_mouse_init(void) +{ + ISADevice *dev; + + dev = isa_create("pc98-mouse"); + qdev_init_nofail(&dev->qdev); +} + +static ISADeviceInfo pc98_mouse_info = { + .qdev.name = "pc98-mouse", + .qdev.size = sizeof(ISAMouseState), + .init = pc98_mouse_initfn, + .qdev.props = (Property[]) { + DEFINE_PROP_UINT32("irq", ISAMouseState, isairq, 13), + DEFINE_PROP_END_OF_LIST(), + }, +}; + +static void pc98_mouse_register_devices(void) +{ + isa_qdev_register(&pc98_mouse_info); +} + +device_init(pc98_mouse_register_devices)