NetBSD/sys/arch/arm26/ioc/arckbd.c

737 lines
19 KiB
C
Raw Normal View History

/* $NetBSD: arckbd.c,v 1.3 2000/08/22 21:22:48 bjh21 Exp $ */
2000-05-10 01:55:44 +04:00
/*-
* Copyright (c) 1998, 1999, 2000 Ben Harris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* This file is part of NetBSD/arm26 -- a port of NetBSD to ARM2/3 machines. */
/*
* arckbd.c - Archimedes keyboard driver
*/
/*
* Most of the information used to write this driver came from the
* A3000 Technical Reference Manual (ISBN 1-85250-074-3).
*
* We keep a queue of one command in the softc for use by the recieve
* interrupt handler in case it finds the KART is already transmitting
* a command (presumably as a consequence of a user request) when it
* wants to. I think this is safe in all cases, and it will never
* happen more than once at a time (I hope).
*/
#include <sys/param.h>
__RCSID("$NetBSD: arckbd.c,v 1.3 2000/08/22 21:22:48 bjh21 Exp $");
2000-05-10 01:55:44 +04:00
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/proc.h>
#include <sys/syslog.h>
#include <sys/systm.h>
#include <machine/bus.h>
#include <machine/intr.h>
2000-05-10 01:55:44 +04:00
#include <machine/irq.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wskbdvar.h>
#include <dev/wscons/wsksymdef.h>
#include <dev/wscons/wsmousevar.h>
#include <arch/arm26/iobus/iocreg.h>
#include <arch/arm26/iobus/iocvar.h>
#include <arch/arm26/ioc/arckbdreg.h>
#include <arch/arm26/ioc/arckbdvar.h>
#include "locators.h"
/* #define ARCKBD_DEBUG */
enum arckbd_state {
AS_HRST, AS_RAK1, AS_RAK2, /* reset protocol */
AS_IDLE, /* idle, waiting for data */
AS_KDDA, AS_KUDA, AS_MDAT /* Receiving two-byte message */
};
static const char *arckbd_statenames[] = {
"hrst", "rak1", "rak2", "idle", "kdda", "kuda", "mdat"
};
static int arckbd_match __P((struct device *parent, struct cfdata *cf, void *aux));
static void arckbd_attach __P((struct device *parent, struct device *self, void *aux));
static kbd_t arckbd_pick_layout __P((int kbid));
static int arcwskbd_match __P((struct device *parent, struct cfdata *cf, void *aux));
static void arcwskbd_attach __P((struct device *parent, struct device *self, void *aux));
static int arcwsmouse_match __P((struct device *parent, struct cfdata *cf, void *aux));
static void arcwsmouse_attach __P((struct device *parent, struct device *self, void *aux));
static int arckbd_rint __P((void *self));
static int arckbd_xint __P((void *self));
static void arckbd_mousemoved __P((struct device *self, int byte1, int byte2));
static void arckbd_keyupdown __P((struct device *self, int byte1, int byte2));
static int arckbd_send __P((struct device *self, int data, enum arckbd_state newstate, int waitok));
static int arckbd_enable __P((void *cookie, int on));
static int arckbd_led_encode __P((int));
static int arckbd_led_decode __P((int));
static void arckbd_set_leds __P((void *cookie, int new_state));
static int arckbd_ioctl __P((void *cookie, u_long cmd, caddr_t data, int flag, struct proc *p));
static void arckbd_getc __P((void *cookie, u_int *typep, int *valuep));
static void arckbd_pollc __P((void *cookie, int poll));
static int arcmouse_enable __P((void *cookie));
static int arcmouse_ioctl __P((void *cookie, u_long cmd, caddr_t data, int flag, struct proc *p));
static void arcmouse_disable __P((void *cookie));
struct arckbd_softc {
struct device sc_dev;
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
u_int sc_mouse_buttons;
enum arckbd_state sc_state;
u_char sc_byteone;
u_char sc_kbid;
struct device *sc_wskbddev;
struct device *sc_wsmousedev;
struct wskbd_mapdata sc_mapdata;
int sc_cmdqueue; /* Single-command queue */
enum arckbd_state sc_statequeue;
int sc_cmdqueued;
int sc_flags;
int sc_leds;
u_int sc_poll_type;
int sc_poll_value;
struct irq_handler *sc_xirq;
struct irq_handler *sc_rirq;
};
#define AKF_WANTKBD 0x01
#define AKF_WANTMOUSE 0x02
#define AKF_SENTRQID 0x04
#define AKF_SENTLEDS 0x08
#define AKF_POLLING 0x10
struct cfattach arckbd_ca = {
sizeof(struct arckbd_softc), arckbd_match, arckbd_attach
};
/*
* Internal devices used because arckbd can't be both a wskbddev and a
* wsmousedev. I suspect the right way to do this is through an
* "attach wskbd at arckbd with wskbd_arckbd" type thing, but we can't
* as the size of a wskbd_softc isn't public. Come to think of it,
* this isn't very evil -- I just don't like having yet another line
* of configuration.
*/
struct cfattach arcwskbd_ca = {
sizeof(struct device), arcwskbd_match, arcwskbd_attach
};
struct cfattach arcwsmouse_ca = {
sizeof(struct device), arcwsmouse_match, arcwsmouse_attach
};
struct arckbd_attach_args {
enum { ARCKBD_KBDDEV, ARCKBD_MOUSEDEV } aka_devtype;
struct wskbddev_attach_args aka_wskbdargs;
struct wsmousedev_attach_args aka_wsmouseargs;
};
extern struct cfdriver arckbd_cd, arcwskbd_cd, arcwsmouse_cd;
static struct wskbd_accessops arckbd_accessops = {
arckbd_enable, arckbd_set_leds, arckbd_ioctl
};
static struct wskbd_consops arckbd_consops = {
arckbd_getc, arckbd_pollc
};
static struct wsmouse_accessops arcmouse_accessops = {
arcmouse_enable, arcmouse_ioctl, arcmouse_disable
};
/* ARGSUSED */
static int
arckbd_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
/* Assume presence for now */
return 1;
}
static void
arckbd_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct arckbd_softc *sc = (void *)self;
struct ioc_attach_args *ioc = aux;
bus_space_tag_t bst;
bus_space_handle_t bsh;
struct arckbd_attach_args aka;
bst = sc->sc_bst = ioc->ioc_fast_t;
bsh = sc->sc_bsh = ioc->ioc_fast_h;
printf("\n");
sc->sc_rirq = ioc_irq_establish(sc->sc_dev.dv_parent, IOC_IRQ_SRX,
IPL_TTY, arckbd_rint, self);
printf("%s: interrupting at %s (rx)", self->dv_xname,
irq_string(sc->sc_rirq));
sc->sc_xirq = ioc_irq_establish(sc->sc_dev.dv_parent, IOC_IRQ_STX,
IPL_TTY, arckbd_xint, self);
printf(" and %s (tx)", irq_string(sc->sc_xirq));
irq_enable(sc->sc_rirq);
/* Initialisation of IOC KART per IOC Data Sheet section 6.2.3. */
/* Set up IOC counter 3 */
/* k_BAUD = 1/((latch+1)*16) MHz */
ioc_counter_start(parent, 3, 62500 / ARCKBD_BAUD - 1);
/* Read from Rx register and discard. */
(void)bus_space_read_1(bst, bsh, 0);
/* Kick the keyboard into life */
arckbd_send(self, ARCKBD_HRST, AS_HRST, 0);
sc->sc_mapdata = arckbd_mapdata_default;
sc->sc_mapdata.layout = KB_UK; /* Reasonable default */
/* XXX set the LEDs to a known state? (or will wskbd do this?) */
/* Attach the wskbd console */
arckbd_cnattach(self);
printf("\n");
/* Attach the dummy drivers */
aka.aka_wskbdargs.console = 1; /* XXX FIXME */
aka.aka_wskbdargs.keymap = &sc->sc_mapdata;
aka.aka_wskbdargs.accessops = &arckbd_accessops;
aka.aka_wskbdargs.accesscookie = self;
aka.aka_wsmouseargs.accessops = &arcmouse_accessops;
aka.aka_wsmouseargs.accesscookie = self;
aka.aka_devtype = ARCKBD_KBDDEV;
config_found(self, &aka, NULL);
aka.aka_devtype = ARCKBD_MOUSEDEV;
config_found(self, &aka, NULL);
}
static kbd_t
arckbd_pick_layout(kbid)
int kbid;
{
int i;
for (i = 0; arckbd_kbidtab[i].kbid != 0; i++) {
if (arckbd_kbidtab[i].kbid == kbid)
return arckbd_kbidtab[i].layout;
}
return KB_UK;
}
/* ARGSUSED */
static int
arcwskbd_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
struct arckbd_attach_args *aka = aux;
if (aka->aka_devtype == ARCKBD_KBDDEV)
return 1;
return 0;
}
/* ARGSUSED */
static int
arcwsmouse_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
struct arckbd_attach_args *aka = aux;
if (aka->aka_devtype == ARCKBD_MOUSEDEV)
return 1;
return 0;
}
static void
arcwskbd_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct arckbd_attach_args *aka = aux;
struct arckbd_softc *sc = (void *)parent;
printf("\n");
sc->sc_wskbddev = config_found(self, &(aka->aka_wskbdargs),
wskbddevprint);
}
static void
arcwsmouse_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
struct arckbd_attach_args *aka = aux;
struct arckbd_softc *sc = (void *)parent;
printf("\n");
sc->sc_wsmousedev = config_found(self, &(aka->aka_wsmouseargs),
wsmousedevprint);
}
/*
* We don't really _need_ a console keyboard before
* autoconfiguration's finished, so for now this function's written to
* be called from arckbd_attach. The console functions should still
* try not to rely on much, and perhaps one day we should make it
* happen in consinit instead.
*/
void
arckbd_cnattach(self)
struct device *self;
{
struct arckbd_softc *sc = (void*)self;
wskbd_cnattach(&arckbd_consops, sc, &arckbd_mapdata_default);
}
static void
arckbd_getc(cookie, typep, valuep)
void *cookie;
u_int *typep;
int *valuep;
{
struct arckbd_softc *sc = cookie;
int s;
if (!(sc->sc_flags & AKF_POLLING))
panic("%s: arckbd_getc called with polling disabled",
sc->sc_dev.dv_xname);
while (sc->sc_poll_type == 0) {
if (ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX))
arckbd_xint(&sc->sc_dev);
if (ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_SRX))
arckbd_rint(&sc->sc_dev);
}
s = spltty();
*typep = sc->sc_poll_type;
*valuep = sc->sc_poll_value;
sc->sc_poll_type = 0;
sc->sc_poll_value = 0;
splx(s);
}
static void
arckbd_pollc(cookie, poll)
void *cookie;
int poll;
{
struct arckbd_softc *sc = cookie;
int s;
s = spltty();
if (poll) {
sc->sc_flags |= AKF_POLLING;
irq_disable(sc->sc_rirq);
irq_disable(sc->sc_xirq);
} else {
sc->sc_flags &= ~AKF_POLLING;
irq_enable(sc->sc_rirq);
irq_enable(sc->sc_xirq);
}
splx(s);
}
static int
arckbd_send(self, data, newstate, waitok)
struct device *self;
int data, waitok;
enum arckbd_state newstate;
{
struct arckbd_softc *sc = (void *)self;
int s, res;
bus_space_tag_t bst = sc->sc_bst;
bus_space_handle_t bsh = sc->sc_bsh;
s = spltty();
if (waitok) {
while (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX))
if ((sc->sc_flags & AKF_POLLING) == 0) {
res = tsleep(arckbd_send, PWAIT, "kbdsend", 0);
if (res != 0)
return res;
}
} else if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) {
if (sc->sc_cmdqueued)
panic("%s: queue overflow", sc->sc_dev.dv_xname);
else {
sc->sc_cmdqueue = data;
sc->sc_statequeue = newstate;
sc->sc_cmdqueued = 1;
return 0;
}
}
bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_WRITE);
bus_space_write_1(bst, bsh, 0, data);
bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_WRITE);
sc->sc_state = newstate;
#ifdef ARCKBD_DEBUG
log(LOG_DEBUG, "%s: sent 0x%02x. now in state %s\n",
sc->sc_dev.dv_xname, data, arckbd_statenames[newstate]);
#endif
wakeup(&sc->sc_state);
splx(s);
if ((sc->sc_flags & AKF_POLLING) == 0)
irq_enable(sc->sc_xirq);
return 0;
}
static int
arckbd_xint(cookie)
void *cookie;
{
struct arckbd_softc *sc = cookie;
if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_STX)) {
printf("%s: Stray tx interrupt\n", sc->sc_dev.dv_xname);
return IRQ_NOT_HANDLED;
}
irq_disable(sc->sc_xirq);
/* First, process queued commands (acks from the last receive) */
if (sc->sc_cmdqueued) {
sc->sc_cmdqueued = 0;
arckbd_send(&sc->sc_dev, sc->sc_cmdqueue, sc->sc_statequeue, 0);
} else if (sc->sc_state == AS_IDLE) {
/* Do things that need doing after a reset */
if (!(sc->sc_flags & AKF_SENTRQID)) {
arckbd_send(&sc->sc_dev, ARCKBD_RQID, AS_IDLE, 0);
sc->sc_flags |= AKF_SENTRQID;
} else if (!(sc->sc_flags & AKF_SENTLEDS)) {
arckbd_send(&sc->sc_dev, ARCKBD_LEDS | sc->sc_leds,
AS_IDLE, 0);
sc->sc_flags |= AKF_SENTLEDS;
}
} else if ((sc->sc_flags & AKF_POLLING) == 0)
wakeup(&arckbd_send);
return IRQ_HANDLED;
}
static int
arckbd_rint(cookie)
void *cookie;
{
struct device *self = cookie;
struct arckbd_softc *sc = (void *)self;
bus_space_tag_t bst = sc->sc_bst;
bus_space_handle_t bsh = sc->sc_bsh;
int data;
if (!ioc_irq_status(sc->sc_dev.dv_parent, IOC_IRQ_SRX)) {
printf("%s: Stray rx interrupt\n", sc->sc_dev.dv_xname);
return IRQ_NOT_HANDLED;
}
bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_READ);
data = bus_space_read_1(bst, bsh, 0);
bus_space_barrier(bst, bsh, 0, 1, BUS_BARRIER_READ);
/* Reset protocol */
#ifdef ARCKBD_DEBUG
log(LOG_DEBUG, "%s: got 0x%02x in state %s\n", self->dv_xname, data,
arckbd_statenames[sc->sc_state]);
#endif
if (data == ARCKBD_HRST && sc->sc_state == AS_HRST)
arckbd_send(self, ARCKBD_RAK1, AS_RAK1, 0);
else if (data == ARCKBD_RAK1 &&
(sc->sc_state == AS_RAK1 || sc->sc_state == AS_HRST))
arckbd_send(self, ARCKBD_RAK2, AS_RAK2, 0);
else if (data == ARCKBD_RAK2 && sc->sc_state == AS_RAK2)
arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
/*
* Note that for data messages, we acknowledge first and
* _then_ process the data. This is important because the
* processing may end up trying to use the keyboard in polled
* mode (e.g. through DDB) and we'd like its state to be
* self-consistent.
*/
/* Mouse data */
else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_IDLE) {
arckbd_send(self, ARCKBD_BACK, AS_MDAT, 0);
sc->sc_byteone = data;
} else if (ARCKBD_IS_MDAT(data) && sc->sc_state == AS_MDAT) {
arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
arckbd_mousemoved(self, sc->sc_byteone, data);
}
/* Key down data */
else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_IDLE) {
arckbd_send(self, ARCKBD_BACK, AS_KDDA, 0);
sc->sc_byteone = data;
} else if (ARCKBD_IS_KDDA(data) && sc->sc_state == AS_KDDA) {
arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
arckbd_keyupdown(self, sc->sc_byteone, data);
}
/* Key up data */
else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_IDLE) {
arckbd_send(self, ARCKBD_BACK, AS_KUDA, 0);
sc->sc_byteone = data;
} else if (ARCKBD_IS_KUDA(data) && sc->sc_state == AS_KUDA) {
arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
arckbd_keyupdown(self, sc->sc_byteone, data);
}
/* Other cruft */
else if (ARCKBD_IS_KBID(data)) {
arckbd_send(self, ARCKBD_SMAK, AS_IDLE, 0);
if (sc->sc_kbid != data) {
printf("%s: layout %d\n",
self->dv_xname, data & ~ARCKBD_KBID);
sc->sc_kbid = data;
}
} else if (ARCKBD_IS_PDAT(data))
/* unused -- ignore it */;
else {
/* Protocol error */
log(LOG_WARNING, "%s: protocol error: got 0x%02x in state %s\n",
self->dv_xname, data, arckbd_statenames[sc->sc_state]);
arckbd_send(self, ARCKBD_HRST, AS_HRST, 0);
}
return IRQ_HANDLED;
}
static void
arckbd_mousemoved(self, byte1, byte2)
struct device *self;
int byte1, byte2;
{
struct arckbd_softc *sc = (void *)self;
int dx, dy;
if (sc->sc_wsmousedev != NULL) {
/* deltas are 7-bit signed */
dx = byte1 < 0x40 ? byte1 : byte1 - 0x80;
dy = byte2 < 0x40 ? byte2 : byte2 - 0x80;
wsmouse_input(sc->sc_wsmousedev,
sc->sc_mouse_buttons, dx, dy, 0,
WSMOUSE_INPUT_DELTA);
}
}
static void
arckbd_keyupdown(self, byte1, byte2)
struct device *self;
int byte1, byte2;
{
struct arckbd_softc *sc = (void *)self;
u_int type;
int value;
if ((byte1 & 0x0f) == 7) {
/* Mouse button event */
/*
* This is all very silly, as the wsmouse driver then
* differentiates the button state to see if there's
* an event worth passing to the user.
*
* Oh well, at least NetBSD and Acorn number their
* mouse buttons the same way.
*/
if (ARCKBD_IS_KDDA(byte1))
sc->sc_mouse_buttons |= (1 << (byte2 & 0x0f));
else
sc->sc_mouse_buttons &= ~(1 << (byte2 & 0x0f));
if (sc->sc_wsmousedev != NULL)
wsmouse_input(sc->sc_wsmousedev, sc->sc_mouse_buttons,
0, 0, 0, WSMOUSE_INPUT_DELTA);
} else {
type = ARCKBD_IS_KDDA(byte1) ?
WSCONS_EVENT_KEY_DOWN : WSCONS_EVENT_KEY_UP;
value = ((byte1 & 0x0f) << 4) | (byte2 & 0x0f);
if (sc->sc_flags & AKF_POLLING) {
sc->sc_poll_type = type;
sc->sc_poll_value = value;
} else if (sc->sc_wskbddev != NULL)
wskbd_input(sc->sc_wskbddev, type, value);
}
}
/*
* Keyboard access functions
*/
static int
arckbd_enable(cookie, on)
void *cookie;
int on;
{
struct arckbd_softc *sc = cookie;
if (on) {
sc->sc_flags |= AKF_WANTKBD;
/* XXX send RQMP? */
} else
sc->sc_flags &= ~ AKF_WANTKBD;
return 0;
}
static int
arckbd_led_encode(wsleds)
int wsleds;
{
int arcleds;
arcleds = 0;
if (wsleds & WSKBD_LED_CAPS)
arcleds |= ARCKBD_LEDS_CAPSLOCK;
if (wsleds & WSKBD_LED_NUM)
arcleds |= ARCKBD_LEDS_NUMLOCK;
if (wsleds & WSKBD_LED_SCROLL)
arcleds |= ARCKBD_LEDS_SCROLLLOCK;
/* No "compose" LED */
return arcleds;
}
static int
arckbd_led_decode(arcleds)
int arcleds;
{
int wsleds;
wsleds = 0;
if (arcleds & ARCKBD_LEDS_CAPSLOCK)
wsleds |= WSKBD_LED_CAPS;
if (arcleds & ARCKBD_LEDS_NUMLOCK)
wsleds |= WSKBD_LED_NUM;
if (arcleds & ARCKBD_LEDS_SCROLLLOCK)
wsleds |= WSKBD_LED_SCROLL;
/* No "compose" LED */
return wsleds;
}
/*
* Set the LEDs to the requested state.
*
* Be warned: This function gets called from interrupts.
*/
static void
arckbd_set_leds(cookie, new_state)
void *cookie;
int new_state;
{
struct arckbd_softc *sc = cookie;
int s;
s = spltty();
sc->sc_leds = arckbd_led_encode(new_state);
if (arckbd_send(cookie, ARCKBD_LEDS | sc->sc_leds, AS_IDLE, 0) == 0)
sc->sc_flags |= AKF_SENTLEDS;
splx(s);
}
/* ARGSUSED */
static int
arckbd_ioctl(cookie, cmd, data, flag, p)
void *cookie;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
struct arckbd_softc *sc = cookie;
switch (cmd) {
case WSKBDIO_GTYPE:
*(int *)data = WSKBD_TYPE_ARCHIMEDES;
return 0;
case WSKBDIO_SETLEDS:
arckbd_set_leds(sc, *(int *)data);
return 0;
case WSKBDIO_GETLEDS:
*(int *)data = arckbd_led_decode(sc->sc_leds);
return 0;
}
return -1;
}
/*
* Mouse access functions
*/
static int
arcmouse_enable(cookie)
void *cookie;
{
struct arckbd_softc *sc = cookie;
sc->sc_flags |= AKF_WANTMOUSE;
/* XXX send RQMP */
return 0;
}
/* ARGSUSED */
static int
arcmouse_ioctl(cookie, cmd, data, flag, p)
void *cookie;
u_long cmd;
caddr_t data;
int flag;
struct proc *p;
{
/* struct arckbd_softc *sc = cookie; */
switch (cmd) {
case WSMOUSEIO_GTYPE:
*(int *)data = WSMOUSE_TYPE_ARCHIMEDES;
return 0;
}
return -1;
}
static void
arcmouse_disable(cookie)
void *cookie;
{
struct arckbd_softc *sc = cookie;
sc->sc_flags &= ~AKF_WANTMOUSE;
}