linux-old/drivers/char/joystick/gameport.c
<<
>>
Prefs
   1/*
   2 * $Id: gameport.c,v 1.5 2000/05/29 10:54:53 vojtech Exp $
   3 *
   4 *  Copyright (c) 1999-2000 Vojtech Pavlik
   5 *
   6 *  Sponsored by SuSE
   7 */
   8
   9/*
  10 * Generic gameport layer
  11 */
  12
  13/*
  14 * This program is free software; you can redistribute it and/or modify
  15 * it under the terms of the GNU General Public License as published by
  16 * the Free Software Foundation; either version 2 of the License, or 
  17 * (at your option) any later version.
  18 * 
  19 * This program is distributed in the hope that it will be useful,
  20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22 * GNU General Public License for more details.
  23 * 
  24 * You should have received a copy of the GNU General Public License
  25 * along with this program; if not, write to the Free Software
  26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  27 * 
  28 * Should you need to contact me, the author, you can do so either by
  29 * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
  30 * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
  31 */
  32
  33#include <asm/io.h>
  34#include <linux/module.h>
  35#include <linux/ioport.h>
  36#include <linux/init.h>
  37#include <linux/gameport.h>
  38#include <linux/slab.h>
  39#include <linux/isapnp.h>
  40#include <linux/stddef.h>
  41#include <linux/delay.h>
  42
  43MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
  44MODULE_LICENSE("GPL");
  45
  46EXPORT_SYMBOL(gameport_register_port);
  47EXPORT_SYMBOL(gameport_unregister_port);
  48EXPORT_SYMBOL(gameport_register_device);
  49EXPORT_SYMBOL(gameport_unregister_device);
  50EXPORT_SYMBOL(gameport_open);
  51EXPORT_SYMBOL(gameport_close);
  52EXPORT_SYMBOL(gameport_rescan);
  53EXPORT_SYMBOL(gameport_cooked_read);
  54
  55static struct gameport *gameport_list;
  56static struct gameport_dev *gameport_dev;
  57static int gameport_number;
  58
  59/*
  60 * gameport_measure_speed() measures the gameport i/o speed.
  61 */
  62
  63static int gameport_measure_speed(struct gameport *gameport)
  64{
  65#if defined(__i386__) || defined(__x86_64__)
  66
  67#define GET_TIME(x)     do { outb(0, 0x43); x = inb(0x40); x |= inb(0x40) << 8; } while (0)
  68#define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193180L/HZ:0))
  69
  70        unsigned int i, t, t1, t2, t3, tx;
  71        unsigned long flags;
  72
  73        if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
  74                return 0;
  75
  76        tx = 1 << 30;
  77
  78        for(i = 0; i < 50; i++) {
  79                save_flags(flags);      /* Yes, all CPUs */
  80                cli();
  81                GET_TIME(t1);
  82                for(t = 0; t < 50; t++) gameport_read(gameport);
  83                GET_TIME(t2);
  84                GET_TIME(t3);
  85                restore_flags(flags);
  86                udelay(i * 10);
  87                if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
  88        }
  89
  90        return 59659 / (tx < 1 ? 1 : tx);
  91
  92#else
  93
  94        unsigned int j, t = 0;
  95
  96        j = jiffies; while (j == jiffies);
  97        j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
  98
  99        return t * HZ / 1000;
 100
 101#endif
 102
 103        gameport_close(gameport);
 104}
 105
 106static void gameport_find_dev(struct gameport *gameport)
 107{
 108        struct gameport_dev *dev = gameport_dev;
 109
 110        while (dev && !gameport->dev) {
 111                if (dev->connect)
 112                        dev->connect(gameport, dev);
 113                dev = dev->next;
 114        }
 115}
 116
 117void gameport_rescan(struct gameport *gameport)
 118{
 119        gameport_close(gameport);
 120        gameport_find_dev(gameport);
 121}
 122
 123void gameport_register_port(struct gameport *gameport)
 124{
 125        gameport->number = gameport_number++;
 126        gameport->next = gameport_list; 
 127        gameport_list = gameport;
 128
 129        gameport->speed = gameport_measure_speed(gameport);
 130
 131        gameport_find_dev(gameport);
 132}
 133
 134void gameport_unregister_port(struct gameport *gameport)
 135{
 136        struct gameport **gameportptr = &gameport_list;
 137
 138        while (*gameportptr && (*gameportptr != gameport)) gameportptr = &((*gameportptr)->next);
 139        *gameportptr = (*gameportptr)->next;
 140
 141        if (gameport->dev && gameport->dev->disconnect)
 142                gameport->dev->disconnect(gameport);
 143
 144        gameport_number--;
 145}
 146
 147void gameport_register_device(struct gameport_dev *dev)
 148{
 149        struct gameport *gameport = gameport_list;
 150
 151        dev->next = gameport_dev;       
 152        gameport_dev = dev;
 153
 154        while (gameport) {
 155                if (!gameport->dev && dev->connect)
 156                        dev->connect(gameport, dev);
 157                gameport = gameport->next;
 158        }
 159}
 160
 161void gameport_unregister_device(struct gameport_dev *dev)
 162{
 163        struct gameport_dev **devptr = &gameport_dev;
 164        struct gameport *gameport = gameport_list;
 165
 166        while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next);
 167        *devptr = (*devptr)->next;
 168
 169        while (gameport) {
 170                if (gameport->dev == dev && dev->disconnect)
 171                        dev->disconnect(gameport);
 172                gameport_find_dev(gameport);
 173                gameport = gameport->next;
 174        }
 175}
 176
 177int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
 178{
 179        if (gameport->open) {
 180                if (gameport->open(gameport, mode))
 181                        return -1;
 182        } else {
 183                if (mode != GAMEPORT_MODE_RAW)
 184                        return -1;
 185        }
 186
 187        if (gameport->dev)
 188                return -1;
 189
 190        gameport->dev = dev;
 191        
 192        return 0;
 193}
 194
 195void gameport_close(struct gameport *gameport)
 196{
 197        gameport->dev = NULL;
 198        if (gameport->close) gameport->close(gameport);
 199}
 200
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.