File:  [DragonFly] / src / sys / dev / misc / joy / joy.c
Revision 1.6: download - view: text, annotated - select for diffs
Thu May 13 23:49:16 2004 UTC (10 years, 7 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*-
    2:  * Copyright (c) 1995 Jean-Marc Zucconi
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer
   10:  *    in this position and unchanged.
   11:  * 2. Redistributions in binary form must reproduce the above copyright
   12:  *    notice, this list of conditions and the following disclaimer in the
   13:  *    documentation and/or other materials provided with the distribution.
   14:  * 3. The name of the author may not be used to endorse or promote products
   15:  *    derived from this software withough specific prior written permission
   16:  *
   17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27:  *
   28:  * $FreeBSD: src/sys/isa/joy.c,v 1.38.2.1 2001/09/01 05:55:31 murray Exp $
   29:  * $DragonFly: src/sys/dev/misc/joy/joy.c,v 1.6 2004/05/13 23:49:16 dillon Exp $
   30:  */
   31: 
   32: #include <sys/param.h>
   33: #include <sys/systm.h>
   34: #include <sys/conf.h>
   35: #include <sys/uio.h>
   36: #include <sys/kernel.h>
   37: #include <sys/module.h>
   38: #include <sys/bus.h>
   39: #include <machine/bus.h>
   40: #include <machine/resource.h>
   41: #include <sys/rman.h>
   42: #include <sys/time.h>
   43: #include <sys/joystick.h>
   44: 
   45: #include <bus/isa/isavar.h>
   46: #include "isa_if.h"
   47: 
   48: /* The game port can manage 4 buttons and 4 variable resistors (usually 2
   49:  * joysticks, each with 2 buttons and 2 pots.) via the port at address 0x201.
   50:  * Getting the state of the buttons is done by reading the game port:
   51:  * buttons 1-4 correspond to bits 4-7 and resistors 1-4 (X1, Y1, X2, Y2)
   52:  * to bits 0-3.
   53:  * if button 1 (resp 2, 3, 4) is pressed, the bit 4 (resp 5, 6, 7) is set to 0
   54:  * to get the value of a resistor, write the value 0xff at port and
   55:  * wait until the corresponding bit returns to 0.
   56:  */
   57: 
   58: #define joypart(d) (minor(d)&1)
   59: #define UNIT(d) ((minor(d)>>1)&3)
   60: #ifndef JOY_TIMEOUT
   61: #define JOY_TIMEOUT   2000 /* 2 milliseconds */
   62: #endif
   63: 
   64: struct joy_softc {
   65:     bus_space_tag_t  bt;
   66:     bus_space_handle_t port;
   67:     int x_off[2], y_off[2];
   68:     int timeout[2];
   69: };
   70: 
   71: #define JOY_SOFTC(unit) (struct joy_softc *) \
   72:         devclass_get_softc(joy_devclass,(unit))
   73: 
   74: static int joy_probe (device_t);
   75: static int joy_attach (device_t);
   76: 
   77: #define CDEV_MAJOR 51
   78: static	d_open_t	joyopen;
   79: static	d_close_t	joyclose;
   80: static	d_read_t	joyread;
   81: static	d_ioctl_t	joyioctl;
   82: 
   83: static struct cdevsw joy_cdevsw = {
   84: 	/* name */	"joy",
   85: 	/* maj */	CDEV_MAJOR,
   86: 	/* flags */	0,
   87: 	/* port */	NULL,
   88: 	/* clone */	NULL,
   89: 
   90: 	/* open */	joyopen,
   91: 	/* close */	joyclose,
   92: 	/* read */	joyread,
   93: 	/* write */	nowrite,
   94: 	/* ioctl */	joyioctl,
   95: 	/* poll */	nopoll,
   96: 	/* mmap */	nommap,
   97: 	/* strategy */	nostrategy,
   98: 	/* dump */	nodump,
   99: 	/* psize */	nopsize
  100: };
  101: 
  102: devclass_t joy_devclass;
  103: 
  104: static struct isa_pnp_id joy_ids[] = {
  105:     {0x0100630e, "CSC0001 PnP Joystick"},	/* CSC0001 */
  106:     {0x0101630e, "CSC0101 PnP Joystick"},	/* CSC0101 */
  107:     {0x01100002, "ALS0110 PnP Joystick"},	/* @P@1001 */
  108:     {0x01200002, "ALS0120 PnP Joystick"},	/* @P@2001 */
  109:     {0x01007316, "ESS0001 PnP Joystick"},	/* ESS0001 */
  110:     {0x2fb0d041, "Generic PnP Joystick"},	/* PNPb02f */
  111:     {0x2200a865, "YMH0022 PnP Joystick"},	/* YMH0022 */
  112:     {0x82719304, NULL},    			/* ADS7182 */
  113:     {0}
  114: };
  115: 
  116: static int
  117: joy_probe (device_t dev)
  118: {
  119:     if (ISA_PNP_PROBE(device_get_parent(dev), dev, joy_ids) == ENXIO)
  120:         return ENXIO;
  121: #ifdef WANT_JOYSTICK_CONNECTED
  122: #ifdef notyet
  123:     outb (dev->id_iobase, 0xff);
  124:     DELAY (10000); /*  10 ms delay */
  125:     return (inb (dev->id_iobase) & 0x0f) != 0x0f;
  126: #endif
  127: #else
  128:     return 0;
  129: #endif
  130: }
  131: 
  132: static int
  133: joy_attach (device_t dev)
  134: {
  135:     int	unit = device_get_unit(dev);
  136:     int rid = 0;
  137:     struct resource *res;
  138:     struct joy_softc *joy = device_get_softc(dev);
  139: 
  140:     res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE);
  141:     if (res == NULL)
  142:         return ENXIO;
  143:     joy->bt = rman_get_bustag(res);
  144:     joy->port = rman_get_bushandle(res);
  145:     joy->timeout[0] = joy->timeout[1] = 0;
  146:     make_dev(&joy_cdevsw, 0, 0, 0, 0600, "joy%d", unit);
  147:     return 0;
  148: }
  149: 
  150: static device_method_t joy_methods[] = {
  151:     DEVMETHOD(device_probe,	joy_probe),
  152:     DEVMETHOD(device_attach,	joy_attach),
  153:     { 0, 0 }
  154: };
  155: 
  156: static driver_t joy_isa_driver = {
  157:     "joy",
  158:     joy_methods,
  159:     sizeof (struct joy_softc)
  160: };
  161: 
  162: DRIVER_MODULE(joy, isa, joy_isa_driver, joy_devclass, 0, 0);
  163: 
  164: static int
  165: joyopen(dev_t dev, int flags, int fmt, d_thread_t *td)
  166: {
  167:     int i = joypart (dev);
  168:     struct joy_softc *joy = JOY_SOFTC(UNIT(dev));
  169: 
  170:     if (joy->timeout[i])
  171: 	return EBUSY;
  172:     joy->x_off[i] = joy->y_off[i] = 0;
  173:     joy->timeout[i] = JOY_TIMEOUT;
  174:     return 0;
  175: }
  176: 
  177: static int
  178: joyclose(dev_t dev, int flags, int fmt, d_thread_t *td)
  179: {
  180:     int i = joypart (dev);
  181:     struct joy_softc *joy = JOY_SOFTC(UNIT(dev));
  182: 
  183:     joy->timeout[i] = 0;
  184:     return 0;
  185: }
  186: 
  187: static int
  188: joyread(dev_t dev, struct uio *uio, int flag)
  189: {
  190:     struct joy_softc *joy = JOY_SOFTC(UNIT(dev));
  191:     bus_space_handle_t port = joy->port;
  192:     bus_space_tag_t bt = joy->bt;
  193:     struct timespec t, start, end;
  194:     int state = 0;
  195:     struct timespec x, y;
  196:     struct joystick c;
  197: #ifndef i386
  198:     int s;
  199: 
  200:     s = splhigh();
  201: #else
  202:     disable_intr ();
  203: #endif
  204:     bus_space_write_1 (bt, port, 0, 0xff);
  205:     nanotime(&start);
  206:     end.tv_sec = 0;
  207:     end.tv_nsec = joy->timeout[joypart(dev)] * 1000;
  208:     timespecadd(&end, &start);
  209:     t = start;
  210:     timespecclear(&x);
  211:     timespecclear(&y);
  212:     while (timespeccmp(&t, &end, <)) {
  213: 	state = bus_space_read_1 (bt, port, 0);
  214: 	if (joypart(dev) == 1)
  215: 	    state >>= 2;
  216: 	nanotime(&t);
  217: 	if (!timespecisset(&x) && !(state & 0x01))
  218: 	    x = t;
  219: 	if (!timespecisset(&y) && !(state & 0x02))
  220: 	    y = t;
  221: 	if (timespecisset(&x) && timespecisset(&y))
  222: 	    break;
  223:     }
  224: #ifndef i386
  225:     splx(s);
  226: #else
  227:     enable_intr ();
  228: #endif
  229:     if (timespecisset(&x)) {
  230: 	timespecsub(&x, &start);
  231: 	c.x = joy->x_off[joypart(dev)] + x.tv_nsec / 1000;
  232:     } else
  233: 	c.x = 0x80000000;
  234:     if (timespecisset(&y)) {
  235: 	timespecsub(&y, &start);
  236: 	c.y = joy->y_off[joypart(dev)] + y.tv_nsec / 1000;
  237:     } else
  238: 	c.y = 0x80000000;
  239:     state >>= 4;
  240:     c.b1 = ~state & 1;
  241:     c.b2 = ~(state >> 1) & 1;
  242:     return uiomove ((caddr_t)&c, sizeof(struct joystick), uio);
  243: }
  244: 
  245: static int
  246: joyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, d_thread_t *td)
  247: {
  248:     struct joy_softc *joy = JOY_SOFTC(UNIT(dev));
  249:     int i = joypart (dev);
  250:     int x;
  251: 
  252:     switch (cmd) {
  253:     case JOY_SETTIMEOUT:
  254: 	x = *(int *) data;
  255: 	if (x < 1 || x > 10000) /* 10ms maximum! */
  256: 	    return EINVAL;
  257: 	joy->timeout[i] = x;
  258: 	break;
  259:     case JOY_GETTIMEOUT:
  260: 	*(int *) data = joy->timeout[i];
  261: 	break;
  262:     case JOY_SET_X_OFFSET:
  263: 	joy->x_off[i] = *(int *) data;
  264: 	break;
  265:     case JOY_SET_Y_OFFSET:
  266: 	joy->y_off[i] = *(int *) data;
  267: 	break;
  268:     case JOY_GET_X_OFFSET:
  269: 	*(int *) data = joy->x_off[i];
  270: 	break;
  271:     case JOY_GET_Y_OFFSET:
  272: 	*(int *) data = joy->y_off[i];
  273: 	break;
  274:     default:
  275: 	return ENXIO;
  276:     }
  277:     return 0;
  278: }