Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Generic gameport layer
  3  *
  4  * Copyright (c) 1999-2002 Vojtech Pavlik
  5  */
  6 
  7 /*
  8  * This program is free software; you can redistribute it and/or modify it
  9  * under the terms of the GNU General Public License version 2 as published by
 10  * the Free Software Foundation.
 11  */
 12 
 13 #include <asm/io.h>
 14 #include <linux/module.h>
 15 #include <linux/ioport.h>
 16 #include <linux/init.h>
 17 #include <linux/gameport.h>
 18 #include <linux/slab.h>
 19 #include <linux/stddef.h>
 20 #include <linux/delay.h>
 21 
 22 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 23 MODULE_DESCRIPTION("Generic gameport layer");
 24 MODULE_LICENSE("GPL");
 25 
 26 EXPORT_SYMBOL(gameport_register_port);
 27 EXPORT_SYMBOL(gameport_unregister_port);
 28 EXPORT_SYMBOL(gameport_register_device);
 29 EXPORT_SYMBOL(gameport_unregister_device);
 30 EXPORT_SYMBOL(gameport_open);
 31 EXPORT_SYMBOL(gameport_close);
 32 EXPORT_SYMBOL(gameport_rescan);
 33 EXPORT_SYMBOL(gameport_cooked_read);
 34 
 35 static LIST_HEAD(gameport_list);
 36 static LIST_HEAD(gameport_dev_list);
 37 
 38 #ifdef __i386__
 39 
 40 #define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193182/HZ:0))
 41 #define GET_TIME(x)     do { x = get_time_pit(); } while (0)
 42 
 43 static unsigned int get_time_pit(void)
 44 {
 45         extern spinlock_t i8253_lock;
 46         unsigned long flags;
 47         unsigned int count;
 48 
 49         spin_lock_irqsave(&i8253_lock, flags);
 50         outb_p(0x00, 0x43);
 51         count = inb_p(0x40);
 52         count |= inb_p(0x40) << 8;
 53         spin_unlock_irqrestore(&i8253_lock, flags);
 54 
 55         return count;
 56 }
 57 
 58 #endif
 59 
 60 /*
 61  * gameport_measure_speed() measures the gameport i/o speed.
 62  */
 63 
 64 static int gameport_measure_speed(struct gameport *gameport)
 65 {
 66 #ifdef __i386__
 67 
 68         unsigned int i, t, t1, t2, t3, tx;
 69         unsigned long flags;
 70 
 71         if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
 72                 return 0;
 73 
 74         tx = 1 << 30;
 75 
 76         for(i = 0; i < 50; i++) {
 77                 local_irq_save(flags);
 78                 GET_TIME(t1);
 79                 for(t = 0; t < 50; t++) gameport_read(gameport);
 80                 GET_TIME(t2);
 81                 GET_TIME(t3);
 82                 local_irq_restore(flags);
 83                 udelay(i * 10);
 84                 if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
 85         }
 86 
 87         gameport_close(gameport);
 88         return 59659 / (tx < 1 ? 1 : tx);
 89 
 90 #else
 91 
 92         unsigned int j, t = 0;
 93 
 94         j = jiffies; while (j == jiffies);
 95         j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
 96 
 97         gameport_close(gameport);
 98         return t * HZ / 1000;
 99 
100 #endif
101 }
102 
103 static void gameport_find_dev(struct gameport *gameport)
104 {
105         struct gameport_dev *dev;
106 
107         list_for_each_entry(dev, &gameport_dev_list, node) {
108                 if (gameport->dev)
109                         break;
110                 if (dev->connect)
111                         dev->connect(gameport, dev);
112         }
113 }
114 
115 void gameport_rescan(struct gameport *gameport)
116 {
117         gameport_close(gameport);
118         gameport_find_dev(gameport);
119 }
120 
121 void gameport_register_port(struct gameport *gameport)
122 {
123         list_add_tail(&gameport->node, &gameport_list);
124         gameport->speed = gameport_measure_speed(gameport);
125         gameport_find_dev(gameport);
126 }
127 
128 void gameport_unregister_port(struct gameport *gameport)
129 {
130         list_del_init(&gameport->node);
131         if (gameport->dev && gameport->dev->disconnect)
132                 gameport->dev->disconnect(gameport);
133 }
134 
135 void gameport_register_device(struct gameport_dev *dev)
136 {
137         struct gameport *gameport;
138 
139         list_add_tail(&dev->node, &gameport_dev_list);
140         list_for_each_entry(gameport, &gameport_list, node)
141                 if (!gameport->dev && dev->connect)
142                         dev->connect(gameport, dev);
143 }
144 
145 void gameport_unregister_device(struct gameport_dev *dev)
146 {
147         struct gameport *gameport;
148 
149         list_del_init(&dev->node);
150         list_for_each_entry(gameport, &gameport_list, node) {
151                 if (gameport->dev == dev && dev->disconnect)
152                         dev->disconnect(gameport);
153                 gameport_find_dev(gameport);
154         }
155 }
156 
157 int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
158 {
159         if (gameport->open) {
160                 if (gameport->open(gameport, mode))
161                         return -1;
162         } else {
163                 if (mode != GAMEPORT_MODE_RAW)
164                         return -1;
165         }
166 
167         if (gameport->dev)
168                 return -1;
169 
170         gameport->dev = dev;
171 
172         return 0;
173 }
174 
175 void gameport_close(struct gameport *gameport)
176 {
177         gameport->dev = NULL;
178         if (gameport->close)
179                 gameport->close(gameport);
180 }
181 
  This page was automatically generated by the LXR engine.