886 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Generic gameport layer4 *5 * Copyright (c) 1999-2002 Vojtech Pavlik6 * Copyright (c) 2005 Dmitry Torokhov7 */8 9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt11 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 25MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");26MODULE_DESCRIPTION("Generic gameport layer");27MODULE_LICENSE("GPL");28 29static bool use_ktime = true;30module_param(use_ktime, bool, 0400);31MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed");32 33/*34 * gameport_mutex protects entire gameport subsystem and is taken35 * every time gameport port or driver registrered or unregistered.36 */37static DEFINE_MUTEX(gameport_mutex);38 39static LIST_HEAD(gameport_list);40 41static const struct bus_type gameport_bus;42 43static void gameport_add_port(struct gameport *gameport);44static void gameport_attach_driver(struct gameport_driver *drv);45static void gameport_reconnect_port(struct gameport *gameport);46static 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 55static 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#endif70 71 72 73/*74 * gameport_measure_speed() measures the gameport i/o speed.75 */76 77static 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 109static 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#else160 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#endif173}174 175void gameport_start_polling(struct gameport *gameport)176{177 spin_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(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));183 }184 185 spin_unlock(&gameport->timer_lock);186}187EXPORT_SYMBOL(gameport_start_polling);188 189void gameport_stop_polling(struct gameport *gameport)190{191 spin_lock(&gameport->timer_lock);192 193 if (!--gameport->poll_cnt)194 del_timer(&gameport->poll_timer);195 196 spin_unlock(&gameport->timer_lock);197}198EXPORT_SYMBOL(gameport_stop_polling);199 200static 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(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));207}208 209/*210 * Basic gameport -> driver core mappings211 */212 213static 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(&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 237static void gameport_find_driver(struct gameport *gameport)238{239 int error;240 241 error = device_attach(&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 253enum gameport_event_type {254 GAMEPORT_REGISTER_PORT,255 GAMEPORT_ATTACH_DRIVER,256};257 258struct gameport_event {259 enum gameport_event_type type;260 void *object;261 struct module *owner;262 struct list_head node;263};264 265static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */266static LIST_HEAD(gameport_event_list);267 268static 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(&gameport_event_list)) {276 event = list_first_entry(&gameport_event_list,277 struct gameport_event, node);278 list_del_init(&event->node);279 }280 281 spin_unlock_irqrestore(&gameport_event_lock, flags);282 return event;283}284 285static void gameport_free_event(struct gameport_event *event)286{287 module_put(event->owner);288 kfree(event);289}290 291static 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 not302 * look further - we only suppress duplicate events303 * that were sent back-to-back.304 */305 if (event->type != e->type)306 break;307 308 list_del_init(&e->node);309 gameport_free_event(e);310 }311 }312 313 spin_unlock_irqrestore(&gameport_event_lock, flags);314}315 316 317static 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 swsusp325 * a chance to freeze kgameportd thread. Gameport events326 * should be pretty rare so we are not concerned about327 * 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(event->object);335 break;336 337 case GAMEPORT_ATTACH_DRIVER:338 gameport_attach_driver(event->object);339 break;340 }341 342 gameport_remove_duplicate_events(event);343 gameport_free_event(event);344 }345 346 mutex_unlock(&gameport_mutex);347}348 349static DECLARE_WORK(gameport_event_work, gameport_handle_events);350 351static 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 we363 * do not need add new one. If event is of different type we364 * need to add this event and should not look further because365 * 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(sizeof(*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(owner)) {383 pr_warn("Can't get module reference, dropping event %d\n",384 event_type);385 kfree(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(&event->node, &gameport_event_list);395 queue_work(system_long_wq, &gameport_event_work);396 397out:398 spin_unlock_irqrestore(&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 */406static 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(&event->node);416 gameport_free_event(event);417 }418 }419 420 spin_unlock_irqrestore(&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 therefore427 * only one child registration request can be pending. Additionally, children428 * are registered by driver's connect() handler so there can't be a grandchild429 * pending registration together with a child.430 */431static 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(&gameport_event_lock, flags);450 return child;451}452 453/*454 * Gameport port operations455 */456 457static 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, "%s\n", gameport->name);462}463static DEVICE_ATTR(description, S_IRUGO, gameport_description_show, NULL);464 465static 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(buf, &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(&gameport_mutex);490 491 return error ? error : count;492}493static DEVICE_ATTR_WO(drvctl);494 495static struct attribute *gameport_device_attrs[] = {496 &dev_attr_description.attr,497 &dev_attr_drvctl.attr,498 NULL,499};500ATTRIBUTE_GROUPS(gameport_device);501 502static void gameport_release_port(struct device *dev)503{504 struct gameport *gameport = to_gameport_port(dev);505 506 kfree(gameport);507 module_put(THIS_MODULE);508}509 510void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)511{512 va_list args;513 514 va_start(args, fmt);515 vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);516 va_end(args);517}518EXPORT_SYMBOL(gameport_set_phys);519 520static void gameport_default_trigger(struct gameport *gameport)521{522#ifdef CONFIG_HAS_IOPORT523 outb(0xff, gameport->io);524#endif525}526 527static unsigned char gameport_default_read(struct gameport *gameport)528{529#ifdef CONFIG_HAS_IOPORT530 return inb(gameport->io);531#else532 return 0xff;533#endif534}535 536static 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 */553static 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(&gameport->dev);561 dev_set_name(&gameport->dev, "gameport%lu",562 (unsigned long)atomic_inc_return(&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(&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 */578static 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(&gameport->node, &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 else595 dev_info(&gameport->dev, "%s is %s, speed %dkHz\n",596 gameport->name, gameport->phys, gameport->speed);597 598 error = device_add(&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 removes607 * port from the system608 */609static void gameport_destroy_port(struct gameport *gameport)610{611 struct gameport *child;612 613 child = gameport_get_pending_child(gameport);614 if (child) {615 gameport_remove_pending_events(child);616 put_device(&child->dev);617 }618 619 if (gameport->parent) {620 gameport->parent->child = NULL;621 gameport->parent = NULL;622 }623 624 if (device_is_registered(&gameport->dev))625 device_del(&gameport->dev);626 627 list_del_init(&gameport->node);628 629 gameport_remove_pending_events(gameport);630 put_device(&gameport->dev);631}632 633/*634 * Reconnect gameport port and all its children (re-initialize attached devices)635 */636static 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 effect651 * all child ports are unbound and destroyed.652 */653static 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 destroyed660 * first, staring with the leaf one, since we don't want661 * to do recursion662 */663 for (s = gameport; s->child; s = s->child)664 /* empty */;665 666 do {667 parent = s->parent;668 669 device_release_driver(&s->dev);670 gameport_destroy_port(s);671 } while ((s = parent) != gameport);672 }673 674 /*675 * Ok, no children left, now disconnect this port676 */677 device_release_driver(&gameport->dev);678}679 680/*681 * Submits register request to kgameportd for subsequent execution.682 * Note that port registration is always asynchronous.683 */684void __gameport_register_port(struct gameport *gameport, struct module *owner)685{686 gameport_init_port(gameport);687 gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);688}689EXPORT_SYMBOL(__gameport_register_port);690 691/*692 * Synchronously unregisters gameport port.693 */694void 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(&gameport_mutex);700}701EXPORT_SYMBOL(gameport_unregister_port);702 703 704/*705 * Gameport driver operations706 */707 708static ssize_t description_show(struct device_driver *drv, char *buf)709{710 struct gameport_driver *driver = to_gameport_driver(drv);711 return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");712}713static DRIVER_ATTR_RO(description);714 715static struct attribute *gameport_driver_attrs[] = {716 &driver_attr_description.attr,717 NULL718};719ATTRIBUTE_GROUPS(gameport_driver);720 721static 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 730static 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 738static void gameport_attach_driver(struct gameport_driver *drv)739{740 int error;741 742 error = driver_attach(&drv->driver);743 if (error)744 pr_err("driver_attach() failed for %s, error: %d\n",745 drv->driver.name, error);746}747 748int __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 probing759 * takes long time and we are better off doing it in kgameportd760 */761 drv->ignore = true;762 763 error = driver_register(&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 ports772 */773 drv->ignore = false;774 error = gameport_queue_event(drv, NULL, GAMEPORT_ATTACH_DRIVER);775 if (error) {776 driver_unregister(&drv->driver);777 return error;778 }779 780 return 0;781}782EXPORT_SYMBOL(__gameport_register_driver);783 784void 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(drv);792 793start_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->driver);804 805 mutex_unlock(&gameport_mutex);806}807EXPORT_SYMBOL(gameport_unregister_driver);808 809static int gameport_bus_match(struct device *dev, const struct device_driver *drv)810{811 const struct gameport_driver *gameport_drv = to_gameport_driver(drv);812 813 return !gameport_drv->ignore;814}815 816static const 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 825static 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(&gameport->drv_mutex);830}831 832int 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}846EXPORT_SYMBOL(gameport_open);847 848void gameport_close(struct gameport *gameport)849{850 del_timer_sync(&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}857EXPORT_SYMBOL(gameport_close);858 859static int __init gameport_init(void)860{861 int error;862 863 error = bus_register(&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 873static void __exit gameport_exit(void)874{875 bus_unregister(&gameport_bus);876 877 /*878 * There should not be any outstanding events but work may879 * still be scheduled so simply cancel it.880 */881 cancel_work_sync(&gameport_event_work);882}883 884subsys_initcall(gameport_init);885module_exit(gameport_exit);886