The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/isa/joy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  */
   29 #include "joy.h"
   30 
   31 #if NJOY > 0
   32 
   33 #include <sys/errno.h>
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/conf.h>
   37 #include <sys/kernel.h>
   38 #ifdef DEVFS
   39 #include <sys/devfsext.h>
   40 #endif /*DEVFS*/
   41 
   42 #include <machine/clock.h>
   43 #include <machine/joystick.h>
   44 
   45 #include <i386/isa/isa.h>
   46 #include <i386/isa/isa_device.h>
   47 #include <i386/isa/timerreg.h>
   48 
   49 /* The game port can manage 4 buttons and 4 variable resistors (usually 2
   50  * joysticks, each with 2 buttons and 2 pots.) via the port at address 0x201.
   51  * Getting the state of the buttons is done by reading the game port:
   52  * buttons 1-4 correspond to bits 4-7 and resistors 1-4 (X1, Y1, X2, Y2)
   53  * to bits 0-3.
   54  * if button 1 (resp 2, 3, 4) is pressed, the bit 4 (resp 5, 6, 7) is set to 0
   55  * to get the value of a resistor, write the value 0xff at port and
   56  * wait until the corresponding bit returns to 0.
   57  */
   58 
   59 
   60 /* the formulae below only work if u is  ``not too large''. See also
   61  * the discussion in microtime.s */
   62 #define usec2ticks(u)   (((u) * 19549)>>14)
   63 #define ticks2usec(u)   (((u) * 3433)>>12)
   64 
   65 
   66 #define joypart(d) minor(d)&1
   67 #define UNIT(d) minor(d)>>1&3
   68 #ifndef JOY_TIMEOUT
   69 #define JOY_TIMEOUT   2000 /* 2 milliseconds */
   70 #endif
   71 
   72 static struct {
   73     int port;
   74     int x_off[2], y_off[2];
   75     int timeout[2];
   76 #ifdef  DEVFS
   77     void        *devfs_token;
   78 #endif
   79 } joy[NJOY];
   80 
   81 
   82 static int joyprobe (struct isa_device *);
   83 static int joyattach (struct isa_device *);
   84 
   85 struct isa_driver joydriver = {joyprobe, joyattach, "joy"};
   86 
   87 #define CDEV_MAJOR 51
   88 static  d_open_t        joyopen;
   89 static  d_close_t       joyclose;
   90 static  d_read_t        joyread;
   91 static  d_ioctl_t       joyioctl;
   92 
   93 static struct cdevsw joy_cdevsw = 
   94         { joyopen,      joyclose,       joyread,        nowrite,        /*51*/
   95           joyioctl,     nostop,         nullreset,      nodevtotty,/*joystick */
   96           seltrue,      nommap,         NULL,   "joy",  NULL,   -1 };
   97 
   98 static int get_tick __P((void));
   99 
  100 
  101 static int
  102 joyprobe (struct isa_device *dev)
  103 {
  104 #ifdef WANT_JOYSTICK_CONNECTED
  105     outb (dev->id_iobase, 0xff);
  106     DELAY (10000); /*  10 ms delay */
  107     return (inb (dev->id_iobase) & 0x0f) != 0x0f;
  108 #else
  109     return 1;
  110 #endif
  111 }
  112 
  113 static int
  114 joyattach (struct isa_device *dev)
  115 {
  116     int unit = dev->id_unit;
  117 
  118     joy[unit].port = dev->id_iobase;
  119     joy[unit].timeout[0] = joy[unit].timeout[1] = 0;
  120     printf("joy%d: joystick\n", unit);
  121 #ifdef  DEVFS
  122     joy[dev->id_unit].devfs_token = 
  123                 devfs_add_devswf(&joy_cdevsw, 0, DV_CHR, 0, 0, 
  124                                  0600, "joy%d", unit);
  125 #endif
  126     return 1;
  127 }
  128 
  129 static  int
  130 joyopen (dev_t dev, int flags, int fmt, struct proc *p)
  131 {
  132     int unit = UNIT (dev);
  133     int i = joypart (dev);
  134 
  135     if (joy[unit].timeout[i])
  136         return EBUSY;
  137     joy[unit].x_off[i] = joy[unit].y_off[i] = 0;
  138     joy[unit].timeout[i] = JOY_TIMEOUT;
  139     return 0;
  140 }
  141 static  int
  142 joyclose (dev_t dev, int flags, int fmt, struct proc *p)
  143 {
  144     int unit = UNIT (dev);
  145     int i = joypart (dev);
  146 
  147     joy[unit].timeout[i] = 0;
  148     return 0;
  149 }
  150 
  151 static  int
  152 joyread (dev_t dev, struct uio *uio, int flag)
  153 {
  154     int unit = UNIT(dev);
  155     int port = joy[unit].port;
  156     int i, t0, t1;
  157     int state = 0, x = 0, y = 0;
  158     struct joystick c;
  159 
  160     disable_intr ();
  161     outb (port, 0xff);
  162     t0 = get_tick ();
  163     t1 = t0;
  164     i = usec2ticks(joy[unit].timeout[joypart(dev)]);
  165     while (t0-t1 < i) {
  166         state = inb (port);
  167         if (joypart(dev) == 1)
  168             state >>= 2;
  169         t1 = get_tick ();
  170         if (t1 > t0)
  171             t1 -= timer0_max_count;
  172         if (!x && !(state & 0x01))
  173             x = t1;
  174         if (!y && !(state & 0x02))
  175             y =  t1;
  176         if (x && y)
  177             break;
  178     }
  179     enable_intr ();
  180     c.x = x ? joy[unit].x_off[joypart(dev)] + ticks2usec(t0-x) : 0x80000000;
  181     c.y = y ? joy[unit].y_off[joypart(dev)] + ticks2usec(t0-y) : 0x80000000;
  182     state >>= 4;
  183     c.b1 = ~state & 1;
  184     c.b2 = ~(state >> 1) & 1;
  185     return uiomove ((caddr_t)&c, sizeof(struct joystick), uio);
  186 }
  187 
  188 static  int
  189 joyioctl (dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)
  190 {
  191     int unit = UNIT (dev);
  192     int i = joypart (dev);
  193     int x;
  194 
  195     switch (cmd) {
  196     case JOY_SETTIMEOUT:
  197         x = *(int *) data;
  198         if (x < 1 || x > 10000) /* 10ms maximum! */
  199             return EINVAL;
  200         joy[unit].timeout[i] = x;
  201         break;
  202     case JOY_GETTIMEOUT:
  203         *(int *) data = joy[unit].timeout[i];
  204         break;
  205     case JOY_SET_X_OFFSET:
  206         joy[unit].x_off[i] = *(int *) data;
  207         break;
  208     case JOY_SET_Y_OFFSET:
  209         joy[unit].y_off[i] = *(int *) data;
  210         break;
  211     case JOY_GET_X_OFFSET:
  212         *(int *) data = joy[unit].x_off[i];
  213         break;
  214     case JOY_GET_Y_OFFSET:
  215         *(int *) data = joy[unit].y_off[i];
  216         break;
  217     default:
  218         return ENXIO;
  219     }
  220     return 0;
  221 }
  222 
  223 static int
  224 get_tick ()
  225 {
  226     int low, high;
  227 
  228     outb (TIMER_MODE, TIMER_SEL0);
  229     low = inb (TIMER_CNTR0);
  230     high = inb (TIMER_CNTR0);
  231 
  232     return (high << 8) | low;
  233 }
  234 
  235 
  236 static joy_devsw_installed = 0;
  237 
  238 static void     joy_drvinit(void *unused)
  239 {
  240         dev_t dev;
  241 
  242         if( ! joy_devsw_installed ) {
  243                 dev = makedev(CDEV_MAJOR,0);
  244                 cdevsw_add(&dev,&joy_cdevsw,NULL);
  245                 joy_devsw_installed = 1;
  246         }
  247 }
  248 
  249 SYSINIT(joydev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,joy_drvinit,NULL)
  250 
  251 #ifdef JOY_MODULE
  252 
  253 #include <sys/exec.h>
  254 #include <sys/sysent.h>
  255 #include <sys/sysproto.h>
  256 #include <sys/lkm.h>
  257 
  258 MOD_DEV (joy, LM_DT_CHAR, CDEV_MAJOR, &joy_cdevsw);
  259 
  260 static struct isa_device dev = {0, &joydriver, IO_GAME, 0, -1, (caddr_t) 0, 0, 0, 0, 0, 0, 0, 0,  0, 1, 0, 0};
  261 
  262 int 
  263 joy_load (struct lkm_table *lkmtp, int cmd)
  264 {
  265     if (joyprobe (&dev)) {
  266         joyattach (&dev);
  267 /*          joy_drvinit (0);*/
  268         uprintf ("Joystick driver loaded\n");
  269         return 0;
  270     } else {
  271         uprintf ("Joystick driver: probe failed\n");
  272         return 1;
  273     }
  274 }
  275 
  276 int
  277 joy_unload (struct lkm_table *lkmtp, int cmd)
  278 {
  279     uprintf ("Joystick driver unloaded\n");
  280     return 0;
  281 }
  282 int
  283 joy_stat (struct lkm_table *lkmtp, int cmd)
  284 {
  285     return 0;
  286 }
  287 int
  288 joy_mod (struct lkm_table *lkmtp, int cmd, int ver)
  289 {
  290     DISPATCH(lkmtp, cmd, ver, joy_load, joy_unload, joy_stat);
  291 }
  292 
  293 #endif /* JOY_MODULE */
  294 
  295 
  296 #endif /* NJOY > 0 */

Cache object: a51a36f495e2d9a04d4c7a22aff5dd7f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.