[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
TP360CE: NetBSD-1.0 and XFree86-3.1 files
Enclosed in this mail is a PS/2 mouse driver(*) for NetBSD-1.0 that
seems to work with the Trackpoint device on a TP360CE. Enclosed is
also the config file I used to build the kernel, and the XF86Config
file for XFree86-3.1. Everything seems to run just fine.
(*) Thanks to Keith Moore and Charles Hannum who provided me with
valuable information.
-- Arne
| Arne Helme, arne@acm.org, arne@pegasus.esprit.ec.org (finger) |
| PHONE: +31-53-893735, FAX: +31-53-333895, HOME: +31-53-326377 |
| WWW : http://www.pegasus.esprit.ec.org/people/arne/index.html |
| Inf/SPA, Univ. of Twente, P.O.Box 217, 7500 AE Enschede, Netherlands |
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# TP360CE
# XF86Config
# pms.c
#
echo x - TP360CE
sed 's/^X//' >TP360CE << 'END-of-TP360CE'
X############################ -*- Mode: Makefile -*- ###########################
X## TP360CE -- NetBSD-1.0 configuration file for IBM ThinkPad 360CE
X##
X## Author : Arne Helme
X## Created On : Sun Nov 20 19:31:09 1994
X## Last Modified By: Arne Helme
X## Last Modified On: Thu Jan 26 11:45:58 1995
X## Status : Unknown, Use with caution!
X##
X## $Locker$
X## $Log$
X###############################################################################
X
Xmachine "i386"
Xident "TP360CE"
Xcpu "I486_CPU"
Xtimezone 0 dst 0
Xmaxusers 5
Xoptions SWAPPAGER,VNODEPAGER,DEVPAGER
Xoptions FIFO
Xoptions SYSVMSG
Xoptions SYSVSEM
Xoptions SYSVSHM
Xoptions FFS
Xoptions INET,NFSCLIENT,NFSSERVER
Xoptions "COMPAT_43"
Xoptions "TCP_COMPAT_42"
Xoptions XSERVER,UCONSOLE
Xoptions MSDOSFS
Xoptions KERNFS
Xoptions "COMPAT_NOMID"
Xoptions "COMPAT_09"
Xoptions "MACHINE_NONCONTIG"
Xoptions KTRACE
Xoptions "IBM_TRACKPOINT"
X
Xconfig netbsd root on wd0 swap on wd0
X
Xcontroller isa0
X
Xdevice pc0 at isa? port "IO_KBD" irq 1
Xdevice com0 at isa? port "IO_COM1" irq 4
X
Xdevice lpt0 at isa? port "IO_LPT1" irq 7
Xdevice lpt2 at isa? port "IO_LPT3"
X
X#device pms0 at isa? port "IO_KBD" irq 12
X#device pms0 at isa? port "IO_KBD" irq 5
X#device pms0 at isa? port "IO_KBD" tty irq 12 vector pmsintr
Xdevice pms0 at isa? port "IO_KBD" irq 12
X
Xcontroller wdc0 at isa? port "IO_WD1" irq 14
Xdisk wd0 at wdc0 drive ?
X
Xcontroller fdc0 at isa? port "IO_FD1" irq 6 drq 2
Xdisk fd0 at fdc0 drive ?
X
Xdevice npx0 at isa? port "IO_NPX" irq 13
X
Xpseudo-device log 1
Xpseudo-device loop 1
Xpseudo-device pty 16
Xpseudo-device sl 1
Xpseudo-device tun 1
Xpseudo-device bpfilter 1
END-of-TP360CE
echo x - XF86Config
sed 's/^X//' >XF86Config << 'END-of-XF86Config'
XSection "Files"
X RgbPath "/usr/X11R6/lib/X11/rgb/"
X FontPath "/usr/X11R6/lib/X11/fonts/misc/"
X FontPath "/usr/X11R6/lib/X11/fonts/75dpi/"
XEndSection
X
XSection "Keyboard"
X Protocol "Standard"
X AutoRepeat 500 5
X ServerNumLock
XEndSection
X
XSection "Pointer"
X Protocol "BusMouse"
X Device "/dev/pms0"
X Emulate3Buttons
XEndSection
X
XSection "Monitor"
X Identifier "LCD Screen"
X VendorName "IBM"
X ModelName "Unknown"
X
X# Bandwidth 90
X HorizSync 35.40
X VertRefresh 67.43
X
X Mode "640x480"
X DotClock 28.32
X HTimings 640 664 760 800
X VTimings 480 491 493 525
X EndMode
XEndSection
X
X
XSection "Device"
X Identifier "WD90C24"
X VendorName "Western Digital"
X BoardName "RocketChip"
X Chipset "wd90c30"
X VideoRam 1024
X Clocks 28.32 28.32 28.32 28.32 28.32 28.32 28.32 28.32
X Clocks 28.32 28.32 28.32 28.32 28.32 28.32 28.32 28.32
X Clocks 49.84
XEndSection
X
X
XSection "Screen"
X Driver "svga"
X Device "WD90C24"
X Monitor "LCD Screen"
X Subsection "Display"
X Depth 8
X Modes "640x480"
X ViewPort 0 0
X Virtual 640 480
X EndSubsection
XEndSection
X
END-of-XF86Config
echo x - pms.c
sed 's/^X//' >pms.c << 'END-of-pms.c'
X/*-
X * Copyright (c) 1994 Charles Hannum.
X * Copyright (c) 1992, 1993 Erik Forsberg.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X *
X * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
X * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
X * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
X * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
X * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
X * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
X * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
X * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
X * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
X * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
X *
X * $Id: pms.c,v 1.9.2.2 1994/07/19 17:01:52 cgd Exp $
X */
X
X/*
X * XXXX
X * This is a hack. This driver should really be combined with the
X * keyboard driver, since they go through the same buffer and use the
X * same I/O ports. Frobbing the mouse and keyboard at the same time
X * may result in dropped characters and/or corrupted mouse events.
X */
X
X#include "pms.h"
X#if NPMS > 1
X#error Only one PS/2 style mouse may be configured into your system.
X#endif
X
X#include <sys/param.h>
X#include <sys/kernel.h>
X#include <sys/systm.h>
X#include <sys/buf.h>
X#include <sys/malloc.h>
X#include <sys/ioctl.h>
X#include <sys/tty.h>
X#include <sys/file.h>
X#include <sys/select.h>
X#include <sys/proc.h>
X#include <sys/vnode.h>
X#include <sys/device.h>
X
X#include <machine/cpu.h>
X#include <machine/pio.h>
X#include <machine/mouse.h>
X
X#include <i386/isa/isavar.h>
X
X#define PMS_DATA 0 /* offset for data port, read-write */
X#define PMS_CNTRL 4 /* offset for control port, write-only */
X#define PMS_STATUS 4 /* offset for status port, read-only */
X#define PMS_NPORTS 8
X
X/* status bits */
X#define PMS_OBUF_FULL 0x01
X#define PMS_IBUF_FULL 0x02
X
X/* controller commands */
X#define PMS_INT_ENABLE 0x47 /* enable controller interrupts */
X#define PMS_INT_DISABLE 0x65 /* disable controller interrupts */
X#define PMS_AUX_ENABLE 0xa7 /* enable auxiliary port */
X#define PMS_AUX_DISABLE 0xa8 /* disable auxiliary port */
X#define PMS_MAGIC_1 0xa9 /* XXX */
X#define PMS_MAGIC_2 0xaa /* XXX */
X
X#define PMS_8042_CMD 0x65
X
X/* mouse commands */
X#define PMS_SET_SCALE11 0xe6 /* set scaling 1:1 */
X#define PMS_SET_SCALE21 0xe7 /* set scaling 2:1 */
X#define PMS_SET_RES 0xe8 /* set resolution */
X#define PMS_GET_SCALE 0xe9 /* get scaling factor */
X#define PMS_SET_STREAM 0xea /* set streaming mode */
X#define PMS_SET_SAMPLE 0xf3 /* set sampling rate */
X#define PMS_DEV_ENABLE 0xf4 /* mouse on */
X#define PMS_DEV_DISABLE 0xf5 /* mouse off */
X#define PMS_RESET 0xff /* reset */
X
X#define PMS_CHUNK 128 /* chunk size for read */
X#define PMS_BSIZE 1020 /* buffer size */
X
Xstruct pms_softc { /* driver status information */
X struct device sc_dev;
X struct intrhand sc_ih;
X
X struct clist sc_q;
X struct selinfo sc_rsel;
X u_short sc_iobase; /* I/O port base */
X u_char sc_state; /* mouse driver state */
X#define PMS_OPEN 0x01 /* device is open */
X#define PMS_ASLP 0x02 /* waiting for mouse data */
X u_char sc_status; /* mouse button status */
X int sc_x, sc_y; /* accumulated motion in the X,Y axis */
X};
X
Xint pmsprobe();
Xvoid pmsattach();
Xint pmsintr __P((struct pms_softc *));
X
Xstruct cfdriver pmscd = {\
X NULL, "pms", pmsprobe, pmsattach, DV_TTY, sizeof(struct pms_softc)
X};
X
X#define PMSUNIT(dev) (minor(dev))
X
Xstatic inline void
Xpms_flush(iobase)
X u_short iobase;
X{
X u_char c;
X while (c = inb(iobase+PMS_STATUS) & 0x03)
X if ((c & PMS_OBUF_FULL) == PMS_OBUF_FULL) {
X /* XXX - delay is needed to prevent some keyboards from
X wedging when the system boots */
X delay(6);
X (void) inb(iobase+PMS_DATA);
X }
X}
X
Xstatic inline void
Xpms_dev_cmd(iobase, value)
X u_short iobase;
X u_char value;
X{
X pms_flush(iobase);
X outb(iobase+PMS_CNTRL, 0xd4);
X pms_flush(iobase);
X outb(iobase+PMS_DATA, value);
X}
X
Xstatic inline void
Xpms_aux_cmd(iobase, value)
X u_short iobase;
X u_char value;
X{
X pms_flush(iobase);
X outb(iobase+PMS_CNTRL, value);
X}
X
Xstatic inline void
Xpms_pit_cmd(iobase, value)
X u_short iobase;
X u_char value;
X{
X pms_flush(iobase);
X outb(iobase+PMS_CNTRL, 0x60);
X pms_flush(iobase);
X outb(iobase+PMS_DATA, value);
X}
X
Xint
Xpmsprobe(parent, self, aux)
X struct device *parent, *self;
X void *aux;
X{
X struct isa_attach_args *ia = aux;
X u_short iobase = ia->ia_iobase;
X u_char x;
X
X pms_dev_cmd(iobase, PMS_RESET);
X pms_aux_cmd(iobase, PMS_MAGIC_1);
X#ifndef IBM_TRACKPOINT
X pms_aux_cmd(iobase, PMS_MAGIC_2);
X#endif /* IBM_TRACKPOINT */
X x = inb(iobase+PMS_DATA);
X pms_pit_cmd(iobase, PMS_INT_DISABLE);
X if (x & 0x04)
X return 0;
X
X ia->ia_iosize = PMS_NPORTS;
X ia->ia_msize = 0;
X
X return 1;
X}
X
Xvoid
Xpmsattach(parent, self, aux)
X struct device *parent, *self;
X void *aux;
X{
X struct pms_softc *sc = (void *)self;
X struct isa_attach_args *ia = aux;
X u_short iobase = ia->ia_iobase;
X
X printf("\n");
X
X /* Other initialization was done by pmsprobe. */
X sc->sc_iobase = iobase;
X sc->sc_state = 0;
X
X sc->sc_ih.ih_fun = pmsintr;
X sc->sc_ih.ih_arg = sc;
X sc->sc_ih.ih_level = IPL_NONE;
X intr_establish(ia->ia_irq, &sc->sc_ih);
X}
X
Xint
Xpmsopen(dev, flag)
X dev_t dev;
X int flag;
X{
X int unit = PMSUNIT(dev);
X struct pms_softc *sc;
X
X if (unit >= pmscd.cd_ndevs)
X return ENXIO;
X sc = pmscd.cd_devs[unit];
X if (!sc)
X return ENXIO;
X
X if (sc->sc_state & PMS_OPEN)
X return EBUSY;
X
X if (clalloc(&sc->sc_q, PMS_BSIZE, 0) == -1)
X return ENOMEM;
X
X sc->sc_state |= PMS_OPEN;
X sc->sc_status = 0;
X sc->sc_x = sc->sc_y = 0;
X
X /* Enable interrupts. */
X pms_dev_cmd(sc->sc_iobase, PMS_DEV_ENABLE);
X pms_aux_cmd(sc->sc_iobase, PMS_AUX_ENABLE);
X#if 0
X pms_dev_cmd(sc->sc_iobase, PMS_SET_RES);
X pms_dev_cmd(sc->sc_iobase, 3); /* 8 counts/mm */
X pms_dev_cmd(sc->sc_iobase, PMS_SET_SCALE21);
X pms_dev_cmd(sc->sc_iobase, PMS_SET_SAMPLE);
X pms_dev_cmd(sc->sc_iobase, 100); /* 100 samples/sec */
X pms_dev_cmd(sc->sc_iobase, PMS_SET_STREAM);
X#endif
X pms_pit_cmd(sc->sc_iobase, PMS_INT_ENABLE);
X
X return 0;
X}
X
Xint
Xpmsclose(dev, flag)
X dev_t dev;
X int flag;
X{
X struct pms_softc *sc = pmscd.cd_devs[PMSUNIT(dev)];
X
X /* Disable interrupts. */
X#ifdef IBM_TRACKPOINT
X /* The following piece of code prevents the keyboard from
X locking up on IBM ThinkPads with TrackPoint mouse device. */
X pms_pit_cmd(sc->sc_iobase, PMS_INT_DISABLE);
X while (inb (sc->sc_iobase + PMS_STATUS) & 0x03) {
X if (inb (sc->sc_iobase + PMS_STATUS) & 0x02 == 0x02)
X inb (sc->sc_iobase + PMS_DATA);
X }
X#else /* not IBM_TRACKPOINT */
X pms_dev_cmd(sc->sc_iobase, PMS_DEV_DISABLE);
X pms_pit_cmd(sc->sc_iobase, PMS_INT_DISABLE);
X pms_aux_cmd(sc->sc_iobase, PMS_AUX_DISABLE);
X#endif /* not IBM_TRACKPOINT */
X
X sc->sc_state &= ~PMS_OPEN;
X
X clfree(&sc->sc_q);
X
X return 0;
X}
X
Xint
Xpmsread(dev, uio, flag)
X dev_t dev;
X struct uio *uio;
X int flag;
X{
X struct pms_softc *sc = pmscd.cd_devs[PMSUNIT(dev)];
X int s;
X int error;
X size_t length;
X u_char buffer[PMS_CHUNK];
X
X /* Block until mouse activity occured. */
X
X s = spltty();
X while (sc->sc_q.c_cc == 0) {
X if (flag & IO_NDELAY) {
X splx(s);
X return EWOULDBLOCK;
X }
X sc->sc_state |= PMS_ASLP;
X if (error = tsleep((caddr_t)sc, PZERO | PCATCH, "pmsrea", 0)) {
X sc->sc_state &= ~PMS_ASLP;
X splx(s);
X return error;
X }
X }
X splx(s);
X
X /* Transfer as many chunks as possible. */
X
X while (sc->sc_q.c_cc > 0 && uio->uio_resid > 0) {
X length = min(sc->sc_q.c_cc, uio->uio_resid);
X if (length > sizeof(buffer))
X length = sizeof(buffer);
X
X /* Remove a small chunk from the input queue. */
X (void) q_to_b(&sc->sc_q, buffer, length);
X
X /* Copy the data to the user process. */
X if (error = uiomove(buffer, length, uio))
X break;
X }
X
X return error;
X}
X
Xint
Xpmsioctl(dev, cmd, addr, flag)
X dev_t dev;
X int cmd;
X caddr_t addr;
X int flag;
X{
X struct pms_softc *sc = pmscd.cd_devs[PMSUNIT(dev)];
X struct mouseinfo info;
X int s;
X int error;
X
X switch (cmd) {
X case MOUSEIOCREAD:
X s = spltty();
X
X info.status = sc->sc_status;
X if (sc->sc_x || sc->sc_y)
X info.status |= MOVEMENT;
X
X if (sc->sc_x > 127)
X info.xmotion = 127;
X else if (sc->sc_x < -127)
X /* Bounding at -127 avoids a bug in XFree86. */
X info.xmotion = -127;
X else
X info.xmotion = sc->sc_x;
X
X if (sc->sc_y > 127)
X info.ymotion = 127;
X else if (sc->sc_y < -127)
X info.ymotion = -127;
X else
X info.ymotion = sc->sc_y;
X
X /* Reset historical information. */
X sc->sc_x = sc->sc_y = 0;
X sc->sc_status &= ~BUTCHNGMASK;
X ndflush(&sc->sc_q, sc->sc_q.c_cc);
X
X splx(s);
X error = copyout(&info, addr, sizeof(struct mouseinfo));
X break;
X
X default:
X error = EINVAL;
X break;
X }
X
X return error;
X}
X
X/* Masks for the first byte of a packet */
X#define PS2LBUTMASK 0x01
X#define PS2RBUTMASK 0x02
X#define PS2MBUTMASK 0x04
X
Xint
Xpmsintr(sc)
X struct pms_softc *sc;
X{
X u_short iobase = sc->sc_iobase;
X static int state = 0;
X static u_char buttons;
X u_char changed;
X static char dx, dy;
X u_char buffer[5];
X
X if ((sc->sc_state & PMS_OPEN) == 0) {
X /* Interrupts are not expected. Discard the byte. */
X (void) inb(iobase + PMS_DATA);
X return 0;
X }
X
X switch (state) {
X
X case 0:
X buttons = inb(iobase + PMS_DATA);
X if ((buttons & 0xc0) == 0)
X ++state;
X break;
X
X case 1:
X dx = inb(iobase + PMS_DATA);
X /* Bounding at -127 avoids a bug in XFree86. */
X dx = (dx == -128) ? -127 : dx;
X ++state;
X break;
X
X case 2:
X dy = inb(iobase + PMS_DATA);
X dy = (dy == -128) ? -127 : dy;
X state = 0;
X
X buttons = ((buttons & PS2LBUTMASK) << 2) |
X ((buttons & (PS2RBUTMASK | PS2MBUTMASK)) >> 1);
X changed = ((buttons ^ sc->sc_status) & BUTSTATMASK) << 3;
X sc->sc_status = buttons | (sc->sc_status & ~BUTSTATMASK) | changed;
X
X if (dx || dy || changed) {
X /* Update accumulated movements. */
X sc->sc_x += dx;
X sc->sc_y += dy;
X
X /* Add this event to the queue. */
X buffer[0] = 0x80 | (buttons ^ BUTSTATMASK);
X buffer[1] = dx;
X buffer[2] = dy;
X buffer[3] = buffer[4] = 0;
X (void) b_to_q(buffer, sizeof buffer, &sc->sc_q);
X
X if (sc->sc_state & PMS_ASLP) {
X sc->sc_state &= ~PMS_ASLP;
X wakeup((caddr_t)sc);
X }
X selwakeup(&sc->sc_rsel);
X }
X
X break;
X }
X
X return -1;
X}
X
Xint
Xpmsselect(dev, rw, p)
X dev_t dev;
X int rw;
X struct proc *p;
X{
X struct pms_softc *sc = pmscd.cd_devs[PMSUNIT(dev)];
X int s;
X int ret;
X
X if (rw == FWRITE)
X return 0;
X
X s = spltty();
X if (!sc->sc_q.c_cc) {
X selrecord(p, &sc->sc_rsel);
X ret = 0;
X } else
X ret = 1;
X splx(s);
X
X return ret;
X}
END-of-pms.c
exit