1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Generic gameport layer |
4 | * |
5 | * Copyright (c) 1999-2002 Vojtech Pavlik |
6 | * Copyright (c) 2005 Dmitry Torokhov |
7 | */ |
8 | |
9 | |
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
11 | |
12 | #include <linux/stddef.h> |
13 | #include <linux/module.h> |
14 | #include <linux/io.h> |
15 | #include <linux/ioport.h> |
16 | #include <linux/init.h> |
17 | #include <linux/gameport.h> |
18 | #include <linux/slab.h> |
19 | #include <linux/delay.h> |
20 | #include <linux/workqueue.h> |
21 | #include <linux/sched.h> /* HZ */ |
22 | #include <linux/mutex.h> |
23 | #include <linux/timekeeping.h> |
24 | |
25 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>" ); |
26 | MODULE_DESCRIPTION("Generic gameport layer" ); |
27 | MODULE_LICENSE("GPL" ); |
28 | |
29 | static bool use_ktime = true; |
30 | module_param(use_ktime, bool, 0400); |
31 | MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed" ); |
32 | |
33 | /* |
34 | * gameport_mutex protects entire gameport subsystem and is taken |
35 | * every time gameport port or driver registrered or unregistered. |
36 | */ |
37 | static DEFINE_MUTEX(gameport_mutex); |
38 | |
39 | static LIST_HEAD(gameport_list); |
40 | |
41 | static struct bus_type gameport_bus; |
42 | |
43 | static void gameport_add_port(struct gameport *gameport); |
44 | static void gameport_attach_driver(struct gameport_driver *drv); |
45 | static void gameport_reconnect_port(struct gameport *gameport); |
46 | static void gameport_disconnect_port(struct gameport *gameport); |
47 | |
48 | #if defined(__i386__) |
49 | |
50 | #include <linux/i8253.h> |
51 | |
52 | #define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0)) |
53 | #define GET_TIME(x) do { x = get_time_pit(); } while (0) |
54 | |
55 | static unsigned int get_time_pit(void) |
56 | { |
57 | unsigned long flags; |
58 | unsigned int count; |
59 | |
60 | raw_spin_lock_irqsave(&i8253_lock, flags); |
61 | outb_p(0x00, 0x43); |
62 | count = inb_p(0x40); |
63 | count |= inb_p(0x40) << 8; |
64 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
65 | |
66 | return count; |
67 | } |
68 | |
69 | #endif |
70 | |
71 | |
72 | |
73 | /* |
74 | * gameport_measure_speed() measures the gameport i/o speed. |
75 | */ |
76 | |
77 | static int gameport_measure_speed(struct gameport *gameport) |
78 | { |
79 | unsigned int i, t, tx; |
80 | u64 t1, t2, t3; |
81 | unsigned long flags; |
82 | |
83 | if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) |
84 | return 0; |
85 | |
86 | tx = ~0; |
87 | |
88 | for (i = 0; i < 50; i++) { |
89 | local_irq_save(flags); |
90 | t1 = ktime_get_ns(); |
91 | for (t = 0; t < 50; t++) |
92 | gameport_read(gameport); |
93 | t2 = ktime_get_ns(); |
94 | t3 = ktime_get_ns(); |
95 | local_irq_restore(flags); |
96 | udelay(i * 10); |
97 | t = (t2 - t1) - (t3 - t2); |
98 | if (t < tx) |
99 | tx = t; |
100 | } |
101 | |
102 | gameport_close(gameport); |
103 | t = 1000000 * 50; |
104 | if (tx) |
105 | t /= tx; |
106 | return t; |
107 | } |
108 | |
109 | static int old_gameport_measure_speed(struct gameport *gameport) |
110 | { |
111 | #if defined(__i386__) |
112 | |
113 | unsigned int i, t, t1, t2, t3, tx; |
114 | unsigned long flags; |
115 | |
116 | if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) |
117 | return 0; |
118 | |
119 | tx = 1 << 30; |
120 | |
121 | for(i = 0; i < 50; i++) { |
122 | local_irq_save(flags); |
123 | GET_TIME(t1); |
124 | for (t = 0; t < 50; t++) gameport_read(gameport); |
125 | GET_TIME(t2); |
126 | GET_TIME(t3); |
127 | local_irq_restore(flags); |
128 | udelay(i * 10); |
129 | if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t; |
130 | } |
131 | |
132 | gameport_close(gameport); |
133 | return 59659 / (tx < 1 ? 1 : tx); |
134 | |
135 | #elif defined (__x86_64__) |
136 | |
137 | unsigned int i, t; |
138 | unsigned long tx, t1, t2, flags; |
139 | |
140 | if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) |
141 | return 0; |
142 | |
143 | tx = 1 << 30; |
144 | |
145 | for(i = 0; i < 50; i++) { |
146 | local_irq_save(flags); |
147 | t1 = rdtsc(); |
148 | for (t = 0; t < 50; t++) gameport_read(gameport); |
149 | t2 = rdtsc(); |
150 | local_irq_restore(flags); |
151 | udelay(i * 10); |
152 | if (t2 - t1 < tx) tx = t2 - t1; |
153 | } |
154 | |
155 | gameport_close(gameport); |
156 | return (this_cpu_read(cpu_info.loops_per_jiffy) * |
157 | (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx); |
158 | |
159 | #else |
160 | |
161 | unsigned int j, t = 0; |
162 | |
163 | if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW)) |
164 | return 0; |
165 | |
166 | j = jiffies; while (j == jiffies); |
167 | j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); } |
168 | |
169 | gameport_close(gameport); |
170 | return t * HZ / 1000; |
171 | |
172 | #endif |
173 | } |
174 | |
175 | void gameport_start_polling(struct gameport *gameport) |
176 | { |
177 | spin_lock(lock: &gameport->timer_lock); |
178 | |
179 | if (!gameport->poll_cnt++) { |
180 | BUG_ON(!gameport->poll_handler); |
181 | BUG_ON(!gameport->poll_interval); |
182 | mod_timer(timer: &gameport->poll_timer, expires: jiffies + msecs_to_jiffies(m: gameport->poll_interval)); |
183 | } |
184 | |
185 | spin_unlock(lock: &gameport->timer_lock); |
186 | } |
187 | EXPORT_SYMBOL(gameport_start_polling); |
188 | |
189 | void gameport_stop_polling(struct gameport *gameport) |
190 | { |
191 | spin_lock(lock: &gameport->timer_lock); |
192 | |
193 | if (!--gameport->poll_cnt) |
194 | del_timer(timer: &gameport->poll_timer); |
195 | |
196 | spin_unlock(lock: &gameport->timer_lock); |
197 | } |
198 | EXPORT_SYMBOL(gameport_stop_polling); |
199 | |
200 | static void gameport_run_poll_handler(struct timer_list *t) |
201 | { |
202 | struct gameport *gameport = from_timer(gameport, t, poll_timer); |
203 | |
204 | gameport->poll_handler(gameport); |
205 | if (gameport->poll_cnt) |
206 | mod_timer(timer: &gameport->poll_timer, expires: jiffies + msecs_to_jiffies(m: gameport->poll_interval)); |
207 | } |
208 | |
209 | /* |
210 | * Basic gameport -> driver core mappings |
211 | */ |
212 | |
213 | static int gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv) |
214 | { |
215 | int error; |
216 | |
217 | gameport->dev.driver = &drv->driver; |
218 | if (drv->connect(gameport, drv)) { |
219 | gameport->dev.driver = NULL; |
220 | return -ENODEV; |
221 | } |
222 | |
223 | error = device_bind_driver(dev: &gameport->dev); |
224 | if (error) { |
225 | dev_warn(&gameport->dev, |
226 | "device_bind_driver() failed for %s (%s) and %s, error: %d\n" , |
227 | gameport->phys, gameport->name, |
228 | drv->description, error); |
229 | drv->disconnect(gameport); |
230 | gameport->dev.driver = NULL; |
231 | return error; |
232 | } |
233 | |
234 | return 0; |
235 | } |
236 | |
237 | static void gameport_find_driver(struct gameport *gameport) |
238 | { |
239 | int error; |
240 | |
241 | error = device_attach(dev: &gameport->dev); |
242 | if (error < 0) |
243 | dev_warn(&gameport->dev, |
244 | "device_attach() failed for %s (%s), error: %d\n" , |
245 | gameport->phys, gameport->name, error); |
246 | } |
247 | |
248 | |
249 | /* |
250 | * Gameport event processing. |
251 | */ |
252 | |
253 | enum gameport_event_type { |
254 | GAMEPORT_REGISTER_PORT, |
255 | GAMEPORT_ATTACH_DRIVER, |
256 | }; |
257 | |
258 | struct gameport_event { |
259 | enum gameport_event_type type; |
260 | void *object; |
261 | struct module *owner; |
262 | struct list_head node; |
263 | }; |
264 | |
265 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ |
266 | static LIST_HEAD(gameport_event_list); |
267 | |
268 | static struct gameport_event *gameport_get_event(void) |
269 | { |
270 | struct gameport_event *event = NULL; |
271 | unsigned long flags; |
272 | |
273 | spin_lock_irqsave(&gameport_event_lock, flags); |
274 | |
275 | if (!list_empty(head: &gameport_event_list)) { |
276 | event = list_first_entry(&gameport_event_list, |
277 | struct gameport_event, node); |
278 | list_del_init(entry: &event->node); |
279 | } |
280 | |
281 | spin_unlock_irqrestore(lock: &gameport_event_lock, flags); |
282 | return event; |
283 | } |
284 | |
285 | static void gameport_free_event(struct gameport_event *event) |
286 | { |
287 | module_put(module: event->owner); |
288 | kfree(objp: event); |
289 | } |
290 | |
291 | static void gameport_remove_duplicate_events(struct gameport_event *event) |
292 | { |
293 | struct gameport_event *e, *next; |
294 | unsigned long flags; |
295 | |
296 | spin_lock_irqsave(&gameport_event_lock, flags); |
297 | |
298 | list_for_each_entry_safe(e, next, &gameport_event_list, node) { |
299 | if (event->object == e->object) { |
300 | /* |
301 | * If this event is of different type we should not |
302 | * look further - we only suppress duplicate events |
303 | * that were sent back-to-back. |
304 | */ |
305 | if (event->type != e->type) |
306 | break; |
307 | |
308 | list_del_init(entry: &e->node); |
309 | gameport_free_event(event: e); |
310 | } |
311 | } |
312 | |
313 | spin_unlock_irqrestore(lock: &gameport_event_lock, flags); |
314 | } |
315 | |
316 | |
317 | static void gameport_handle_events(struct work_struct *work) |
318 | { |
319 | struct gameport_event *event; |
320 | |
321 | mutex_lock(&gameport_mutex); |
322 | |
323 | /* |
324 | * Note that we handle only one event here to give swsusp |
325 | * a chance to freeze kgameportd thread. Gameport events |
326 | * should be pretty rare so we are not concerned about |
327 | * taking performance hit. |
328 | */ |
329 | if ((event = gameport_get_event())) { |
330 | |
331 | switch (event->type) { |
332 | |
333 | case GAMEPORT_REGISTER_PORT: |
334 | gameport_add_port(gameport: event->object); |
335 | break; |
336 | |
337 | case GAMEPORT_ATTACH_DRIVER: |
338 | gameport_attach_driver(drv: event->object); |
339 | break; |
340 | } |
341 | |
342 | gameport_remove_duplicate_events(event); |
343 | gameport_free_event(event); |
344 | } |
345 | |
346 | mutex_unlock(lock: &gameport_mutex); |
347 | } |
348 | |
349 | static DECLARE_WORK(gameport_event_work, gameport_handle_events); |
350 | |
351 | static int gameport_queue_event(void *object, struct module *owner, |
352 | enum gameport_event_type event_type) |
353 | { |
354 | unsigned long flags; |
355 | struct gameport_event *event; |
356 | int retval = 0; |
357 | |
358 | spin_lock_irqsave(&gameport_event_lock, flags); |
359 | |
360 | /* |
361 | * Scan event list for the other events for the same gameport port, |
362 | * starting with the most recent one. If event is the same we |
363 | * do not need add new one. If event is of different type we |
364 | * need to add this event and should not look further because |
365 | * we need to preserve sequence of distinct events. |
366 | */ |
367 | list_for_each_entry_reverse(event, &gameport_event_list, node) { |
368 | if (event->object == object) { |
369 | if (event->type == event_type) |
370 | goto out; |
371 | break; |
372 | } |
373 | } |
374 | |
375 | event = kmalloc(size: sizeof(struct gameport_event), GFP_ATOMIC); |
376 | if (!event) { |
377 | pr_err("Not enough memory to queue event %d\n" , event_type); |
378 | retval = -ENOMEM; |
379 | goto out; |
380 | } |
381 | |
382 | if (!try_module_get(module: owner)) { |
383 | pr_warn("Can't get module reference, dropping event %d\n" , |
384 | event_type); |
385 | kfree(objp: event); |
386 | retval = -EINVAL; |
387 | goto out; |
388 | } |
389 | |
390 | event->type = event_type; |
391 | event->object = object; |
392 | event->owner = owner; |
393 | |
394 | list_add_tail(new: &event->node, head: &gameport_event_list); |
395 | queue_work(wq: system_long_wq, work: &gameport_event_work); |
396 | |
397 | out: |
398 | spin_unlock_irqrestore(lock: &gameport_event_lock, flags); |
399 | return retval; |
400 | } |
401 | |
402 | /* |
403 | * Remove all events that have been submitted for a given object, |
404 | * be it a gameport port or a driver. |
405 | */ |
406 | static void gameport_remove_pending_events(void *object) |
407 | { |
408 | struct gameport_event *event, *next; |
409 | unsigned long flags; |
410 | |
411 | spin_lock_irqsave(&gameport_event_lock, flags); |
412 | |
413 | list_for_each_entry_safe(event, next, &gameport_event_list, node) { |
414 | if (event->object == object) { |
415 | list_del_init(entry: &event->node); |
416 | gameport_free_event(event); |
417 | } |
418 | } |
419 | |
420 | spin_unlock_irqrestore(lock: &gameport_event_lock, flags); |
421 | } |
422 | |
423 | /* |
424 | * Destroy child gameport port (if any) that has not been fully registered yet. |
425 | * |
426 | * Note that we rely on the fact that port can have only one child and therefore |
427 | * only one child registration request can be pending. Additionally, children |
428 | * are registered by driver's connect() handler so there can't be a grandchild |
429 | * pending registration together with a child. |
430 | */ |
431 | static struct gameport *gameport_get_pending_child(struct gameport *parent) |
432 | { |
433 | struct gameport_event *event; |
434 | struct gameport *gameport, *child = NULL; |
435 | unsigned long flags; |
436 | |
437 | spin_lock_irqsave(&gameport_event_lock, flags); |
438 | |
439 | list_for_each_entry(event, &gameport_event_list, node) { |
440 | if (event->type == GAMEPORT_REGISTER_PORT) { |
441 | gameport = event->object; |
442 | if (gameport->parent == parent) { |
443 | child = gameport; |
444 | break; |
445 | } |
446 | } |
447 | } |
448 | |
449 | spin_unlock_irqrestore(lock: &gameport_event_lock, flags); |
450 | return child; |
451 | } |
452 | |
453 | /* |
454 | * Gameport port operations |
455 | */ |
456 | |
457 | static ssize_t gameport_description_show(struct device *dev, struct device_attribute *attr, char *buf) |
458 | { |
459 | struct gameport *gameport = to_gameport_port(dev); |
460 | |
461 | return sprintf(buf, fmt: "%s\n" , gameport->name); |
462 | } |
463 | static DEVICE_ATTR(description, S_IRUGO, gameport_description_show, NULL); |
464 | |
465 | static ssize_t drvctl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
466 | { |
467 | struct gameport *gameport = to_gameport_port(dev); |
468 | struct device_driver *drv; |
469 | int error; |
470 | |
471 | error = mutex_lock_interruptible(&gameport_mutex); |
472 | if (error) |
473 | return error; |
474 | |
475 | if (!strncmp(buf, "none" , count)) { |
476 | gameport_disconnect_port(gameport); |
477 | } else if (!strncmp(buf, "reconnect" , count)) { |
478 | gameport_reconnect_port(gameport); |
479 | } else if (!strncmp(buf, "rescan" , count)) { |
480 | gameport_disconnect_port(gameport); |
481 | gameport_find_driver(gameport); |
482 | } else if ((drv = driver_find(name: buf, bus: &gameport_bus)) != NULL) { |
483 | gameport_disconnect_port(gameport); |
484 | error = gameport_bind_driver(gameport, to_gameport_driver(drv)); |
485 | } else { |
486 | error = -EINVAL; |
487 | } |
488 | |
489 | mutex_unlock(lock: &gameport_mutex); |
490 | |
491 | return error ? error : count; |
492 | } |
493 | static DEVICE_ATTR_WO(drvctl); |
494 | |
495 | static struct attribute *gameport_device_attrs[] = { |
496 | &dev_attr_description.attr, |
497 | &dev_attr_drvctl.attr, |
498 | NULL, |
499 | }; |
500 | ATTRIBUTE_GROUPS(gameport_device); |
501 | |
502 | static void gameport_release_port(struct device *dev) |
503 | { |
504 | struct gameport *gameport = to_gameport_port(dev); |
505 | |
506 | kfree(objp: gameport); |
507 | module_put(THIS_MODULE); |
508 | } |
509 | |
510 | void gameport_set_phys(struct gameport *gameport, const char *fmt, ...) |
511 | { |
512 | va_list args; |
513 | |
514 | va_start(args, fmt); |
515 | vsnprintf(buf: gameport->phys, size: sizeof(gameport->phys), fmt, args); |
516 | va_end(args); |
517 | } |
518 | EXPORT_SYMBOL(gameport_set_phys); |
519 | |
520 | static void gameport_default_trigger(struct gameport *gameport) |
521 | { |
522 | #ifdef CONFIG_HAS_IOPORT |
523 | outb(value: 0xff, port: gameport->io); |
524 | #endif |
525 | } |
526 | |
527 | static unsigned char gameport_default_read(struct gameport *gameport) |
528 | { |
529 | #ifdef CONFIG_HAS_IOPORT |
530 | return inb(port: gameport->io); |
531 | #else |
532 | return 0xff; |
533 | #endif |
534 | } |
535 | |
536 | static void gameport_setup_default_handlers(struct gameport *gameport) |
537 | { |
538 | if ((!gameport->trigger || !gameport->read) && |
539 | !IS_ENABLED(CONFIG_HAS_IOPORT)) |
540 | dev_err(&gameport->dev, |
541 | "I/O port access is required for %s (%s) but is not available\n" , |
542 | gameport->phys, gameport->name); |
543 | |
544 | if (!gameport->trigger) |
545 | gameport->trigger = gameport_default_trigger; |
546 | if (!gameport->read) |
547 | gameport->read = gameport_default_read; |
548 | } |
549 | |
550 | /* |
551 | * Prepare gameport port for registration. |
552 | */ |
553 | static void gameport_init_port(struct gameport *gameport) |
554 | { |
555 | static atomic_t gameport_no = ATOMIC_INIT(-1); |
556 | |
557 | __module_get(THIS_MODULE); |
558 | |
559 | mutex_init(&gameport->drv_mutex); |
560 | device_initialize(dev: &gameport->dev); |
561 | dev_set_name(dev: &gameport->dev, name: "gameport%lu" , |
562 | (unsigned long)atomic_inc_return(v: &gameport_no)); |
563 | gameport->dev.bus = &gameport_bus; |
564 | gameport->dev.release = gameport_release_port; |
565 | if (gameport->parent) |
566 | gameport->dev.parent = &gameport->parent->dev; |
567 | |
568 | gameport_setup_default_handlers(gameport); |
569 | INIT_LIST_HEAD(list: &gameport->node); |
570 | spin_lock_init(&gameport->timer_lock); |
571 | timer_setup(&gameport->poll_timer, gameport_run_poll_handler, 0); |
572 | } |
573 | |
574 | /* |
575 | * Complete gameport port registration. |
576 | * Driver core will attempt to find appropriate driver for the port. |
577 | */ |
578 | static void gameport_add_port(struct gameport *gameport) |
579 | { |
580 | int error; |
581 | |
582 | if (gameport->parent) |
583 | gameport->parent->child = gameport; |
584 | |
585 | gameport->speed = use_ktime ? |
586 | gameport_measure_speed(gameport) : |
587 | old_gameport_measure_speed(gameport); |
588 | |
589 | list_add_tail(new: &gameport->node, head: &gameport_list); |
590 | |
591 | if (gameport->io) |
592 | dev_info(&gameport->dev, "%s is %s, io %#x, speed %dkHz\n" , |
593 | gameport->name, gameport->phys, gameport->io, gameport->speed); |
594 | else |
595 | dev_info(&gameport->dev, "%s is %s, speed %dkHz\n" , |
596 | gameport->name, gameport->phys, gameport->speed); |
597 | |
598 | error = device_add(dev: &gameport->dev); |
599 | if (error) |
600 | dev_err(&gameport->dev, |
601 | "device_add() failed for %s (%s), error: %d\n" , |
602 | gameport->phys, gameport->name, error); |
603 | } |
604 | |
605 | /* |
606 | * gameport_destroy_port() completes deregistration process and removes |
607 | * port from the system |
608 | */ |
609 | static void gameport_destroy_port(struct gameport *gameport) |
610 | { |
611 | struct gameport *child; |
612 | |
613 | child = gameport_get_pending_child(parent: gameport); |
614 | if (child) { |
615 | gameport_remove_pending_events(object: child); |
616 | put_device(dev: &child->dev); |
617 | } |
618 | |
619 | if (gameport->parent) { |
620 | gameport->parent->child = NULL; |
621 | gameport->parent = NULL; |
622 | } |
623 | |
624 | if (device_is_registered(dev: &gameport->dev)) |
625 | device_del(dev: &gameport->dev); |
626 | |
627 | list_del_init(entry: &gameport->node); |
628 | |
629 | gameport_remove_pending_events(object: gameport); |
630 | put_device(dev: &gameport->dev); |
631 | } |
632 | |
633 | /* |
634 | * Reconnect gameport port and all its children (re-initialize attached devices) |
635 | */ |
636 | static void gameport_reconnect_port(struct gameport *gameport) |
637 | { |
638 | do { |
639 | if (!gameport->drv || !gameport->drv->reconnect || gameport->drv->reconnect(gameport)) { |
640 | gameport_disconnect_port(gameport); |
641 | gameport_find_driver(gameport); |
642 | /* Ok, old children are now gone, we are done */ |
643 | break; |
644 | } |
645 | gameport = gameport->child; |
646 | } while (gameport); |
647 | } |
648 | |
649 | /* |
650 | * gameport_disconnect_port() unbinds a port from its driver. As a side effect |
651 | * all child ports are unbound and destroyed. |
652 | */ |
653 | static void gameport_disconnect_port(struct gameport *gameport) |
654 | { |
655 | struct gameport *s, *parent; |
656 | |
657 | if (gameport->child) { |
658 | /* |
659 | * Children ports should be disconnected and destroyed |
660 | * first, staring with the leaf one, since we don't want |
661 | * to do recursion |
662 | */ |
663 | for (s = gameport; s->child; s = s->child) |
664 | /* empty */; |
665 | |
666 | do { |
667 | parent = s->parent; |
668 | |
669 | device_release_driver(dev: &s->dev); |
670 | gameport_destroy_port(gameport: s); |
671 | } while ((s = parent) != gameport); |
672 | } |
673 | |
674 | /* |
675 | * Ok, no children left, now disconnect this port |
676 | */ |
677 | device_release_driver(dev: &gameport->dev); |
678 | } |
679 | |
680 | /* |
681 | * Submits register request to kgameportd for subsequent execution. |
682 | * Note that port registration is always asynchronous. |
683 | */ |
684 | void __gameport_register_port(struct gameport *gameport, struct module *owner) |
685 | { |
686 | gameport_init_port(gameport); |
687 | gameport_queue_event(object: gameport, owner, event_type: GAMEPORT_REGISTER_PORT); |
688 | } |
689 | EXPORT_SYMBOL(__gameport_register_port); |
690 | |
691 | /* |
692 | * Synchronously unregisters gameport port. |
693 | */ |
694 | void gameport_unregister_port(struct gameport *gameport) |
695 | { |
696 | mutex_lock(&gameport_mutex); |
697 | gameport_disconnect_port(gameport); |
698 | gameport_destroy_port(gameport); |
699 | mutex_unlock(lock: &gameport_mutex); |
700 | } |
701 | EXPORT_SYMBOL(gameport_unregister_port); |
702 | |
703 | |
704 | /* |
705 | * Gameport driver operations |
706 | */ |
707 | |
708 | static ssize_t description_show(struct device_driver *drv, char *buf) |
709 | { |
710 | struct gameport_driver *driver = to_gameport_driver(drv); |
711 | return sprintf(buf, fmt: "%s\n" , driver->description ? driver->description : "(none)" ); |
712 | } |
713 | static DRIVER_ATTR_RO(description); |
714 | |
715 | static struct attribute *gameport_driver_attrs[] = { |
716 | &driver_attr_description.attr, |
717 | NULL |
718 | }; |
719 | ATTRIBUTE_GROUPS(gameport_driver); |
720 | |
721 | static int gameport_driver_probe(struct device *dev) |
722 | { |
723 | struct gameport *gameport = to_gameport_port(dev); |
724 | struct gameport_driver *drv = to_gameport_driver(dev->driver); |
725 | |
726 | drv->connect(gameport, drv); |
727 | return gameport->drv ? 0 : -ENODEV; |
728 | } |
729 | |
730 | static void gameport_driver_remove(struct device *dev) |
731 | { |
732 | struct gameport *gameport = to_gameport_port(dev); |
733 | struct gameport_driver *drv = to_gameport_driver(dev->driver); |
734 | |
735 | drv->disconnect(gameport); |
736 | } |
737 | |
738 | static void gameport_attach_driver(struct gameport_driver *drv) |
739 | { |
740 | int error; |
741 | |
742 | error = driver_attach(drv: &drv->driver); |
743 | if (error) |
744 | pr_err("driver_attach() failed for %s, error: %d\n" , |
745 | drv->driver.name, error); |
746 | } |
747 | |
748 | int __gameport_register_driver(struct gameport_driver *drv, struct module *owner, |
749 | const char *mod_name) |
750 | { |
751 | int error; |
752 | |
753 | drv->driver.bus = &gameport_bus; |
754 | drv->driver.owner = owner; |
755 | drv->driver.mod_name = mod_name; |
756 | |
757 | /* |
758 | * Temporarily disable automatic binding because probing |
759 | * takes long time and we are better off doing it in kgameportd |
760 | */ |
761 | drv->ignore = true; |
762 | |
763 | error = driver_register(drv: &drv->driver); |
764 | if (error) { |
765 | pr_err("driver_register() failed for %s, error: %d\n" , |
766 | drv->driver.name, error); |
767 | return error; |
768 | } |
769 | |
770 | /* |
771 | * Reset ignore flag and let kgameportd bind the driver to free ports |
772 | */ |
773 | drv->ignore = false; |
774 | error = gameport_queue_event(object: drv, NULL, event_type: GAMEPORT_ATTACH_DRIVER); |
775 | if (error) { |
776 | driver_unregister(drv: &drv->driver); |
777 | return error; |
778 | } |
779 | |
780 | return 0; |
781 | } |
782 | EXPORT_SYMBOL(__gameport_register_driver); |
783 | |
784 | void gameport_unregister_driver(struct gameport_driver *drv) |
785 | { |
786 | struct gameport *gameport; |
787 | |
788 | mutex_lock(&gameport_mutex); |
789 | |
790 | drv->ignore = true; /* so gameport_find_driver ignores it */ |
791 | gameport_remove_pending_events(object: drv); |
792 | |
793 | start_over: |
794 | list_for_each_entry(gameport, &gameport_list, node) { |
795 | if (gameport->drv == drv) { |
796 | gameport_disconnect_port(gameport); |
797 | gameport_find_driver(gameport); |
798 | /* we could've deleted some ports, restart */ |
799 | goto start_over; |
800 | } |
801 | } |
802 | |
803 | driver_unregister(drv: &drv->driver); |
804 | |
805 | mutex_unlock(lock: &gameport_mutex); |
806 | } |
807 | EXPORT_SYMBOL(gameport_unregister_driver); |
808 | |
809 | static int gameport_bus_match(struct device *dev, struct device_driver *drv) |
810 | { |
811 | struct gameport_driver *gameport_drv = to_gameport_driver(drv); |
812 | |
813 | return !gameport_drv->ignore; |
814 | } |
815 | |
816 | static struct bus_type gameport_bus = { |
817 | .name = "gameport" , |
818 | .dev_groups = gameport_device_groups, |
819 | .drv_groups = gameport_driver_groups, |
820 | .match = gameport_bus_match, |
821 | .probe = gameport_driver_probe, |
822 | .remove = gameport_driver_remove, |
823 | }; |
824 | |
825 | static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv) |
826 | { |
827 | mutex_lock(&gameport->drv_mutex); |
828 | gameport->drv = drv; |
829 | mutex_unlock(lock: &gameport->drv_mutex); |
830 | } |
831 | |
832 | int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode) |
833 | { |
834 | if (gameport->open) { |
835 | if (gameport->open(gameport, mode)) { |
836 | return -1; |
837 | } |
838 | } else { |
839 | if (mode != GAMEPORT_MODE_RAW) |
840 | return -1; |
841 | } |
842 | |
843 | gameport_set_drv(gameport, drv); |
844 | return 0; |
845 | } |
846 | EXPORT_SYMBOL(gameport_open); |
847 | |
848 | void gameport_close(struct gameport *gameport) |
849 | { |
850 | del_timer_sync(timer: &gameport->poll_timer); |
851 | gameport->poll_handler = NULL; |
852 | gameport->poll_interval = 0; |
853 | gameport_set_drv(gameport, NULL); |
854 | if (gameport->close) |
855 | gameport->close(gameport); |
856 | } |
857 | EXPORT_SYMBOL(gameport_close); |
858 | |
859 | static int __init gameport_init(void) |
860 | { |
861 | int error; |
862 | |
863 | error = bus_register(bus: &gameport_bus); |
864 | if (error) { |
865 | pr_err("failed to register gameport bus, error: %d\n" , error); |
866 | return error; |
867 | } |
868 | |
869 | |
870 | return 0; |
871 | } |
872 | |
873 | static void __exit gameport_exit(void) |
874 | { |
875 | bus_unregister(bus: &gameport_bus); |
876 | |
877 | /* |
878 | * There should not be any outstanding events but work may |
879 | * still be scheduled so simply cancel it. |
880 | */ |
881 | cancel_work_sync(work: &gameport_event_work); |
882 | } |
883 | |
884 | subsys_initcall(gameport_init); |
885 | module_exit(gameport_exit); |
886 | |