2005-02-11 07:05:43

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 0/10] Convert gameport to driver model/sysfs

Hi,

This series of patches adds a new "gameport" bus to the driver model.
It is implemented very similarly to "serio" bus and also allows
individual drivers to be manually bound/disconnected from a port
by manipulating port's "drvctl" attribute.

01-gameport-renames1.patch
- rename gameport->driver to gameport->port_data in preparation
to sysfs integration to avoid confusion with real drivers.

02-gameport-renames2.patch
- more renames in gameport in preparations to sysfs integration,
gameport_dev renamed to gameport_driver, gameport_[un]register_device
renamed to gameport_[un]register_driver

03-gameport-connect-mandatory.patch
- make connect and disconnect mandatory as these call gameport_open
and gameport_close which actually bind driver and port together.

04-gameport-dynalloc-prepare.patch
- sysfs/kobjects requires objects be allocated synamically. Prepare
to dynamic gameport allocation, create gameport_allocate_port and
gameport_free_port; dynamically allocated ports are freed by core
upon release. Also add gameport_set_name and gameport_set_phys
to ease transition.

05-gameport-dynalloc-input.patch
- convert drivers in input/gameport to dynamic gameport allocation.

06-gameport-dynalloc-sound-oss.patch
- convert drivers in sound/oss to dynamic gameport allocation.

07-gameport-dynalloc-sound-alsa.patch
- convert drivers in sound/pci to dynamic gameport allocation.

08-gameport-drivers-sysfs.patch
- add "gameport" bus and have joystick gameport drivers register
themselves on this bus.

09-gameport-devices-sysfs.patch
- complete gameport sysfs integration. Gameports are registered on
the "gameport" bus.

10-gameport-drvdata.patch
- Get rid of gameport->private, use driver-specific data in device
structure, access through gameport_get/set_drvdata helpers.

The changes can also be pulled from my tree (which has Vojtech's
input tree as a parent):

bk pull bk://dtor.bkbits.net/input

I am CC-ing ALSA list as the changes touch quite a few sound drivers.

Comments/testing is appreciated.

--
Dmitry


2005-02-11 07:06:30

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 1/10] Gameport: rename driver to port_data


===================================================================


[email protected], 2005-02-11 01:09:43-05:00, [email protected]
Input: rename gameport->driver to gameport->port_data in preparation
to sysfs integration.

Signed-off-by: Dmitry Torokhov <[email protected]>


drivers/input/gameport/lightning.c | 8 ++++----
drivers/input/gameport/vortex.c | 10 +++++-----
drivers/input/joystick/a3d.c | 8 ++++----
include/linux/gameport.h | 4 ++--
sound/oss/trident.c | 10 +++++-----
sound/pci/au88x0/au88x0_game.c | 15 +++++++--------
6 files changed, 27 insertions(+), 28 deletions(-)


===================================================================



diff -Nru a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
--- a/drivers/input/gameport/lightning.c 2005-02-11 01:34:39 -05:00
+++ b/drivers/input/gameport/lightning.c 2005-02-11 01:34:39 -05:00
@@ -79,7 +79,7 @@

static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct l4 *l4 = gameport->driver;
+ struct l4 *l4 = gameport->port_data;
unsigned char status;
int i, result = -1;

@@ -112,7 +112,7 @@

static int l4_open(struct gameport *gameport, int mode)
{
- struct l4 *l4 = gameport->driver;
+ struct l4 *l4 = gameport->port_data;
if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
return -1;
outb(L4_SELECT_ANALOG, L4_PORT);
@@ -190,7 +190,7 @@
{
int i, t;
int cal[4];
- struct l4 *l4 = gameport->driver;
+ struct l4 *l4 = gameport->port_data;

if (l4_getcal(l4->port, cal))
return -1;
@@ -252,7 +252,7 @@
sprintf(l4->phys, "isa%04x/gameport%d", L4_PORT, 4 * i + j);

gameport = &l4->gameport;
- gameport->driver = l4;
+ gameport->port_data = l4;
gameport->open = l4_open;
gameport->cooked_read = l4_cooked_read;
gameport->calibrate = l4_calibrate;
diff -Nru a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
--- a/drivers/input/gameport/vortex.c 2005-02-11 01:34:39 -05:00
+++ b/drivers/input/gameport/vortex.c 2005-02-11 01:34:39 -05:00
@@ -62,19 +62,19 @@

static unsigned char vortex_read(struct gameport *gameport)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;
return readb(vortex->io + VORTEX_LEG);
}

static void vortex_trigger(struct gameport *gameport)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;
writeb(0xff, vortex->io + VORTEX_LEG);
}

static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;
int i;

*buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf;
@@ -89,7 +89,7 @@

static int vortex_open(struct gameport *gameport, int mode)
{
- struct vortex *vortex = gameport->driver;
+ struct vortex *vortex = gameport->port_data;

switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -120,7 +120,7 @@

pci_set_drvdata(dev, vortex);

- vortex->gameport.driver = vortex;
+ vortex->gameport.port_data = vortex;
vortex->gameport.fuzz = 64;

vortex->gameport.read = vortex_read;
diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
--- a/drivers/input/joystick/a3d.c 2005-02-11 01:34:39 -05:00
+++ b/drivers/input/joystick/a3d.c 2005-02-11 01:34:39 -05:00
@@ -197,7 +197,7 @@

static int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct a3d *a3d = gameport->driver;
+ struct a3d *a3d = gameport->port_data;
int i;
for (i = 0; i < 4; i++)
axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
@@ -212,7 +212,7 @@

static int a3d_adc_open(struct gameport *gameport, int mode)
{
- struct a3d *a3d = gameport->driver;
+ struct a3d *a3d = gameport->port_data;
if (mode != GAMEPORT_MODE_COOKED)
return -1;
if (!a3d->used++)
@@ -226,7 +226,7 @@

static void a3d_adc_close(struct gameport *gameport)
{
- struct a3d *a3d = gameport->driver;
+ struct a3d *a3d = gameport->port_data;
if (!--a3d->used)
del_timer(&a3d->timer);
}
@@ -336,7 +336,7 @@
a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);

- a3d->adc.driver = a3d;
+ a3d->adc.port_data = a3d;
a3d->adc.open = a3d_adc_open;
a3d->adc.close = a3d_adc_close;
a3d->adc.cooked_read = a3d_adc_cooked_read;
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h 2005-02-11 01:34:39 -05:00
+++ b/include/linux/gameport.h 2005-02-11 01:34:39 -05:00
@@ -17,8 +17,8 @@

struct gameport {

- void *private; /* Private pointer for joystick drivers */
- void *driver; /* Private pointer for gameport drivers */
+ void *private; /* Private pointer for joystick drivers */
+ void *port_data; /* Private pointer for gameport drivers */
char *name;
char *phys;

diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c 2005-02-11 01:34:39 -05:00
+++ b/sound/oss/trident.c 2005-02-11 01:34:39 -05:00
@@ -4257,21 +4257,21 @@
static unsigned char
trident_game_read(struct gameport *gameport)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;
return inb(TRID_REG(card, T4D_GAME_LEG));
}

static void
trident_game_trigger(struct gameport *gameport)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;
outb(0xff, TRID_REG(card, T4D_GAME_LEG));
}

static int
trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;
int i;

*buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf;
@@ -4288,7 +4288,7 @@
static int
trident_game_open(struct gameport *gameport, int mode)
{
- struct trident_card *card = gameport->driver;
+ struct trident_card *card = gameport->port_data;

switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -4368,7 +4368,7 @@
card->banks[BANK_B].addresses = &bank_b_addrs;
card->banks[BANK_B].bitmap = 0UL;

- card->gameport.driver = card;
+ card->gameport.port_data = card;
card->gameport.fuzz = 64;
card->gameport.read = trident_game_read;
card->gameport.trigger = trident_game_trigger;
diff -Nru a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
--- a/sound/pci/au88x0/au88x0_game.c 2005-02-11 01:34:39 -05:00
+++ b/sound/pci/au88x0/au88x0_game.c 2005-02-11 01:34:39 -05:00
@@ -44,20 +44,20 @@

static unsigned char vortex_game_read(struct gameport *gameport)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport->port_data;
return hwread(vortex->mmio, VORTEX_GAME_LEGACY);
}

static void vortex_game_trigger(struct gameport *gameport)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport->port_data;
hwwrite(vortex->mmio, VORTEX_GAME_LEGACY, 0xff);
}

static int
vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport->port_data;
int i;

*buttons = (~hwread(vortex->mmio, VORTEX_GAME_LEGACY) >> 4) & 0xf;
@@ -73,7 +73,7 @@

static int vortex_game_open(struct gameport *gameport, int mode)
{
- vortex_t *vortex = gameport->driver;
+ vortex_t *vortex = gameport->port_data;

switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -96,11 +96,10 @@

static int vortex_gameport_register(vortex_t * vortex)
{
- if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL) {
+ if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL)
return -1;
- };
-
- vortex->gameport->driver = vortex;
+
+ vortex->gameport->port_data = vortex;
vortex->gameport->fuzz = 64;

vortex->gameport->read = vortex_game_read;

2005-02-11 07:09:51

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 2/10] Gameport: rename gameport_dev to gameport_driver


===================================================================


[email protected], 2005-02-11 01:09:59-05:00, [email protected]
Input: more renames in gameport in preparations to sysfs integration
- gameport_dev -> gameport_driver
- gameport_[un]register_device -> gameport_[un]register_driver

Signed-off-by: Dmitry Torokhov <[email protected]>


drivers/input/gameport/gameport.c | 52 ++++++++++++++++++------------------
drivers/input/joystick/a3d.c | 10 +++---
drivers/input/joystick/adi.c | 10 +++---
drivers/input/joystick/analog.c | 18 ++++++------
drivers/input/joystick/cobra.c | 10 +++---
drivers/input/joystick/gf2k.c | 10 +++---
drivers/input/joystick/grip.c | 10 +++---
drivers/input/joystick/grip_mp.c | 10 +++---
drivers/input/joystick/guillemot.c | 10 +++---
drivers/input/joystick/interact.c | 10 +++---
drivers/input/joystick/joydump.c | 12 ++++----
drivers/input/joystick/sidewinder.c | 10 +++---
drivers/input/joystick/tmdc.c | 10 +++---
include/linux/gameport.h | 12 ++++----
14 files changed, 97 insertions(+), 97 deletions(-)


===================================================================



diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- a/drivers/input/gameport/gameport.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/gameport/gameport.c 2005-02-11 01:34:53 -05:00
@@ -25,15 +25,15 @@

EXPORT_SYMBOL(gameport_register_port);
EXPORT_SYMBOL(gameport_unregister_port);
-EXPORT_SYMBOL(gameport_register_device);
-EXPORT_SYMBOL(gameport_unregister_device);
+EXPORT_SYMBOL(gameport_register_driver);
+EXPORT_SYMBOL(gameport_unregister_driver);
EXPORT_SYMBOL(gameport_open);
EXPORT_SYMBOL(gameport_close);
EXPORT_SYMBOL(gameport_rescan);
EXPORT_SYMBOL(gameport_cooked_read);

static LIST_HEAD(gameport_list);
-static LIST_HEAD(gameport_dev_list);
+static LIST_HEAD(gameport_driver_list);

#ifdef __i386__

@@ -100,61 +100,61 @@
#endif
}

-static void gameport_find_dev(struct gameport *gameport)
+static void gameport_find_driver(struct gameport *gameport)
{
- struct gameport_dev *dev;
+ struct gameport_driver *drv;

- list_for_each_entry(dev, &gameport_dev_list, node) {
- if (gameport->dev)
+ list_for_each_entry(drv, &gameport_driver_list, node) {
+ if (gameport->drv)
break;
- if (dev->connect)
- dev->connect(gameport, dev);
+ if (drv->connect)
+ drv->connect(gameport, drv);
}
}

void gameport_rescan(struct gameport *gameport)
{
gameport_close(gameport);
- gameport_find_dev(gameport);
+ gameport_find_driver(gameport);
}

void gameport_register_port(struct gameport *gameport)
{
list_add_tail(&gameport->node, &gameport_list);
gameport->speed = gameport_measure_speed(gameport);
- gameport_find_dev(gameport);
+ gameport_find_driver(gameport);
}

void gameport_unregister_port(struct gameport *gameport)
{
list_del_init(&gameport->node);
- if (gameport->dev && gameport->dev->disconnect)
- gameport->dev->disconnect(gameport);
+ if (gameport->drv && gameport->drv->disconnect)
+ gameport->drv->disconnect(gameport);
}

-void gameport_register_device(struct gameport_dev *dev)
+void gameport_register_driver(struct gameport_driver *drv)
{
struct gameport *gameport;

- list_add_tail(&dev->node, &gameport_dev_list);
+ list_add_tail(&drv->node, &gameport_driver_list);
list_for_each_entry(gameport, &gameport_list, node)
- if (!gameport->dev && dev->connect)
- dev->connect(gameport, dev);
+ if (!gameport->drv && drv->connect)
+ drv->connect(gameport, drv);
}

-void gameport_unregister_device(struct gameport_dev *dev)
+void gameport_unregister_driver(struct gameport_driver *drv)
{
struct gameport *gameport;

- list_del_init(&dev->node);
+ list_del_init(&drv->node);
list_for_each_entry(gameport, &gameport_list, node) {
- if (gameport->dev == dev && dev->disconnect)
- dev->disconnect(gameport);
- gameport_find_dev(gameport);
+ if (gameport->drv == drv && drv->disconnect)
+ drv->disconnect(gameport);
+ gameport_find_driver(gameport);
}
}

-int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
+int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
{
if (gameport->open) {
if (gameport->open(gameport, mode))
@@ -164,17 +164,17 @@
return -1;
}

- if (gameport->dev)
+ if (gameport->drv)
return -1;

- gameport->dev = dev;
+ gameport->drv = drv;

return 0;
}

void gameport_close(struct gameport *gameport)
{
- gameport->dev = NULL;
+ gameport->drv = NULL;
if (gameport->close)
gameport->close(gameport);
}
diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
--- a/drivers/input/joystick/a3d.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/a3d.c 2005-02-11 01:34:53 -05:00
@@ -258,7 +258,7 @@
* a3d_connect() probes for A3D joysticks.
*/

-static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct a3d *a3d;
unsigned char data[A3D_MAX_LENGTH];
@@ -275,7 +275,7 @@
a3d->timer.data = (long) a3d;
a3d->timer.function = a3d_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);
@@ -385,20 +385,20 @@
kfree(a3d);
}

-static struct gameport_dev a3d_dev = {
+static struct gameport_driver a3d_drv = {
.connect = a3d_connect,
.disconnect = a3d_disconnect,
};

static int __init a3d_init(void)
{
- gameport_register_device(&a3d_dev);
+ gameport_register_driver(&a3d_drv);
return 0;
}

static void __exit a3d_exit(void)
{
- gameport_unregister_device(&a3d_dev);
+ gameport_unregister_driver(&a3d_drv);
}

module_init(a3d_init);
diff -Nru a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
--- a/drivers/input/joystick/adi.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/adi.c 2005-02-11 01:34:53 -05:00
@@ -475,7 +475,7 @@
* adi_connect() probes for Logitech ADI joysticks.
*/

-static void adi_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void adi_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct adi_port *port;
int i;
@@ -491,7 +491,7 @@
port->timer.data = (long) port;
port->timer.function = adi_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
kfree(port);
return;
}
@@ -544,20 +544,20 @@
* The gameport device structure.
*/

-static struct gameport_dev adi_dev = {
+static struct gameport_driver adi_drv = {
.connect = adi_connect,
.disconnect = adi_disconnect,
};

static int __init adi_init(void)
{
- gameport_register_device(&adi_dev);
+ gameport_register_driver(&adi_drv);
return 0;
}

static void __exit adi_exit(void)
{
- gameport_unregister_device(&adi_dev);
+ gameport_unregister_driver(&adi_drv);
}

module_init(adi_init);
diff -Nru a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
--- a/drivers/input/joystick/analog.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/analog.c 2005-02-11 01:34:53 -05:00
@@ -587,7 +587,7 @@
return -!(analog[0].mask || analog[1].mask);
}

-static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, struct analog_port *port)
+static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port)
{
int i, t, u, v;

@@ -597,7 +597,7 @@
port->timer.data = (long) port;
port->timer.function = analog_timer;

- if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+ if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {

analog_calibrate_timer(port);

@@ -632,7 +632,7 @@
gameport_close(gameport);
}

- if (!gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
+ if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {

for (i = 0; i < ANALOG_INIT_RETRIES; i++)
if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
@@ -645,13 +645,13 @@
return 0;
}

- if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
return 0;

return -1;
}

-static void analog_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void analog_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct analog_port *port;
int i;
@@ -660,7 +660,7 @@
return;
memset(port, 0, sizeof(struct analog_port));

- if (analog_init_port(gameport, dev, port)) {
+ if (analog_init_port(gameport, drv, port)) {
kfree(port);
return;
}
@@ -741,7 +741,7 @@
* The gameport device structure.
*/

-static struct gameport_dev analog_dev = {
+static struct gameport_driver analog_drv = {
.connect = analog_connect,
.disconnect = analog_disconnect,
};
@@ -749,13 +749,13 @@
static int __init analog_init(void)
{
analog_parse_options();
- gameport_register_device(&analog_dev);
+ gameport_register_driver(&analog_drv);
return 0;
}

static void __exit analog_exit(void)
{
- gameport_unregister_device(&analog_dev);
+ gameport_unregister_driver(&analog_drv);
}

module_init(analog_init);
diff -Nru a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
--- a/drivers/input/joystick/cobra.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/cobra.c 2005-02-11 01:34:53 -05:00
@@ -158,7 +158,7 @@
del_timer(&cobra->timer);
}

-static void cobra_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct cobra *cobra;
unsigned int data[2];
@@ -175,7 +175,7 @@
cobra->timer.data = (long) cobra;
cobra->timer.function = cobra_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

cobra->exists = cobra_read_packet(gameport, data);
@@ -236,20 +236,20 @@
kfree(cobra);
}

-static struct gameport_dev cobra_dev = {
+static struct gameport_driver cobra_drv = {
.connect = cobra_connect,
.disconnect = cobra_disconnect,
};

static int __init cobra_init(void)
{
- gameport_register_device(&cobra_dev);
+ gameport_register_driver(&cobra_drv);
return 0;
}

static void __exit cobra_exit(void)
{
- gameport_unregister_device(&cobra_dev);
+ gameport_unregister_driver(&cobra_drv);
}

module_init(cobra_init);
diff -Nru a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
--- a/drivers/input/joystick/gf2k.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/gf2k.c 2005-02-11 01:34:53 -05:00
@@ -238,7 +238,7 @@
* gf2k_connect() probes for Genius id joysticks.
*/

-static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct gf2k *gf2k;
unsigned char data[GF2K_LENGTH];
@@ -255,7 +255,7 @@
gf2k->timer.data = (long) gf2k;
gf2k->timer.function = gf2k_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

gf2k_trigger_seq(gameport, gf2k_seq_reset);
@@ -346,20 +346,20 @@
kfree(gf2k);
}

-static struct gameport_dev gf2k_dev = {
+static struct gameport_driver gf2k_drv = {
.connect = gf2k_connect,
.disconnect = gf2k_disconnect,
};

static int __init gf2k_init(void)
{
- gameport_register_device(&gf2k_dev);
+ gameport_register_driver(&gf2k_drv);
return 0;
}

static void __exit gf2k_exit(void)
{
- gameport_unregister_device(&gf2k_dev);
+ gameport_unregister_driver(&gf2k_drv);
}

module_init(gf2k_init);
diff -Nru a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
--- a/drivers/input/joystick/grip.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/grip.c 2005-02-11 01:34:53 -05:00
@@ -298,7 +298,7 @@
del_timer(&grip->timer);
}

-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip *grip;
unsigned int data[GRIP_LENGTH_XT];
@@ -315,7 +315,7 @@
grip->timer.data = (long) grip;
grip->timer.function = grip_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

for (i = 0; i < 2; i++) {
@@ -409,20 +409,20 @@
kfree(grip);
}

-static struct gameport_dev grip_dev = {
+static struct gameport_driver grip_drv = {
.connect = grip_connect,
.disconnect = grip_disconnect,
};

static int __init grip_init(void)
{
- gameport_register_device(&grip_dev);
+ gameport_register_driver(&grip_drv);
return 0;
}

static void __exit grip_exit(void)
{
- gameport_unregister_device(&grip_dev);
+ gameport_unregister_driver(&grip_drv);
}

module_init(grip_init);
diff -Nru a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
--- a/drivers/input/joystick/grip_mp.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/grip_mp.c 2005-02-11 01:34:53 -05:00
@@ -616,7 +616,7 @@
mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
}

-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip_mp *grip;

@@ -629,7 +629,7 @@
grip->timer.data = (long) grip;
grip->timer.function = grip_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;
if (!multiport_init(grip))
goto fail2;
@@ -654,20 +654,20 @@
kfree(grip);
}

-static struct gameport_dev grip_dev = {
+static struct gameport_driver grip_drv = {
.connect = grip_connect,
.disconnect = grip_disconnect,
};

static int grip_init(void)
{
- gameport_register_device(&grip_dev);
+ gameport_register_driver(&grip_drv);
return 0;
}

static void grip_exit(void)
{
- gameport_unregister_device(&grip_dev);
+ gameport_unregister_driver(&grip_drv);
}

module_init(grip_init);
diff -Nru a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
--- a/drivers/input/joystick/guillemot.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/guillemot.c 2005-02-11 01:34:53 -05:00
@@ -179,7 +179,7 @@
* guillemot_connect() probes for Guillemot joysticks.
*/

-static void guillemot_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct guillemot *guillemot;
u8 data[GUILLEMOT_MAX_LENGTH];
@@ -196,7 +196,7 @@
guillemot->timer.data = (long) guillemot;
guillemot->timer.function = guillemot_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

i = guillemot_read_packet(gameport, data);
@@ -266,20 +266,20 @@
kfree(guillemot);
}

-static struct gameport_dev guillemot_dev = {
+static struct gameport_driver guillemot_drv = {
.connect = guillemot_connect,
.disconnect = guillemot_disconnect,
};

static int __init guillemot_init(void)
{
- gameport_register_device(&guillemot_dev);
+ gameport_register_driver(&guillemot_drv);
return 0;
}

static void __exit guillemot_exit(void)
{
- gameport_unregister_device(&guillemot_dev);
+ gameport_unregister_driver(&guillemot_drv);
}

module_init(guillemot_init);
diff -Nru a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
--- a/drivers/input/joystick/interact.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/interact.c 2005-02-11 01:34:53 -05:00
@@ -209,7 +209,7 @@
* interact_connect() probes for InterAct joysticks.
*/

-static void interact_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void interact_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct interact *interact;
__u32 data[3];
@@ -226,7 +226,7 @@
interact->timer.data = (long) interact;
interact->timer.function = interact_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);
@@ -294,20 +294,20 @@
kfree(interact);
}

-static struct gameport_dev interact_dev = {
+static struct gameport_driver interact_drv = {
.connect = interact_connect,
.disconnect = interact_disconnect,
};

static int __init interact_init(void)
{
- gameport_register_device(&interact_dev);
+ gameport_register_driver(&interact_drv);
return 0;
}

static void __exit interact_exit(void)
{
- gameport_unregister_device(&interact_dev);
+ gameport_unregister_driver(&interact_drv);
}

module_init(interact_init);
diff -Nru a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
--- a/drivers/input/joystick/joydump.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/joydump.c 2005-02-11 01:34:53 -05:00
@@ -46,7 +46,7 @@
unsigned char data;
};

-static void __devinit joydump_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void __devinit joydump_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct joydump *buf; /* all entries */
struct joydump *dump, *prev; /* one entry each */
@@ -59,11 +59,11 @@
printk(KERN_INFO "joydump: | Dumping gameport%s.\n", gameport->phys);
printk(KERN_INFO "joydump: | Speed: %4d kHz. |\n", gameport->speed);

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {

printk(KERN_INFO "joydump: | Raw mode not available - trying cooked. |\n");

- if (gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {

printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n");
printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
@@ -147,20 +147,20 @@
gameport_close(gameport);
}

-static struct gameport_dev joydump_dev = {
+static struct gameport_driver joydump_drv = {
.connect = joydump_connect,
.disconnect = joydump_disconnect,
};

static int __init joydump_init(void)
{
- gameport_register_device(&joydump_dev);
+ gameport_register_driver(&joydump_drv);
return 0;
}

static void __exit joydump_exit(void)
{
- gameport_unregister_device(&joydump_dev);
+ gameport_unregister_driver(&joydump_drv);
}

module_init(joydump_init);
diff -Nru a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
--- a/drivers/input/joystick/sidewinder.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/sidewinder.c 2005-02-11 01:34:53 -05:00
@@ -569,7 +569,7 @@
* sw_connect() probes for SideWinder type joysticks.
*/

-static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void sw_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct sw *sw;
int i, j, k, l;
@@ -595,7 +595,7 @@
sw->timer.data = (long) sw;
sw->timer.function = sw_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

dbg("Init 0: Opened %s, io %#x, speed %d",
@@ -760,20 +760,20 @@
kfree(sw);
}

-static struct gameport_dev sw_dev = {
+static struct gameport_driver sw_drv = {
.connect = sw_connect,
.disconnect = sw_disconnect,
};

static int __init sw_init(void)
{
- gameport_register_device(&sw_dev);
+ gameport_register_driver(&sw_drv);
return 0;
}

static void __exit sw_exit(void)
{
- gameport_unregister_device(&sw_dev);
+ gameport_unregister_driver(&sw_drv);
}

module_init(sw_init);
diff -Nru a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
--- a/drivers/input/joystick/tmdc.c 2005-02-11 01:34:53 -05:00
+++ b/drivers/input/joystick/tmdc.c 2005-02-11 01:34:53 -05:00
@@ -242,7 +242,7 @@
* tmdc_probe() probes for ThrustMaster type joysticks.
*/

-static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
+static void tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct models {
unsigned char id;
@@ -275,7 +275,7 @@
tmdc->timer.data = (long) tmdc;
tmdc->timer.function = tmdc_timer;

- if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+ if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
goto fail1;

if (!(tmdc->exists = tmdc_read_packet(gameport, data)))
@@ -362,20 +362,20 @@
kfree(tmdc);
}

-static struct gameport_dev tmdc_dev = {
+static struct gameport_driver tmdc_drv = {
.connect = tmdc_connect,
.disconnect = tmdc_disconnect,
};

static int __init tmdc_init(void)
{
- gameport_register_device(&tmdc_dev);
+ gameport_register_driver(&tmdc_drv);
return 0;
}

static void __exit tmdc_exit(void)
{
- gameport_unregister_device(&tmdc_dev);
+ gameport_unregister_driver(&tmdc_drv);
}

module_init(tmdc_init);
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h 2005-02-11 01:34:53 -05:00
+++ b/include/linux/gameport.h 2005-02-11 01:34:53 -05:00
@@ -35,23 +35,23 @@
int (*open)(struct gameport *, int);
void (*close)(struct gameport *);

- struct gameport_dev *dev;
+ struct gameport_driver *drv;

struct list_head node;
};

-struct gameport_dev {
+struct gameport_driver {

void *private;
char *name;

- void (*connect)(struct gameport *, struct gameport_dev *dev);
+ void (*connect)(struct gameport *, struct gameport_driver *drv);
void (*disconnect)(struct gameport *);

struct list_head node;
};

-int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode);
+int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode);
void gameport_close(struct gameport *gameport);
void gameport_rescan(struct gameport *gameport);

@@ -63,8 +63,8 @@
static inline void gameport_unregister_port(struct gameport *gameport) { return; }
#endif

-void gameport_register_device(struct gameport_dev *dev);
-void gameport_unregister_device(struct gameport_dev *dev);
+void gameport_register_driver(struct gameport_driver *drv);
+void gameport_unregister_driver(struct gameport_driver *drv);

#define GAMEPORT_MODE_DISABLED 0
#define GAMEPORT_MODE_RAW 1

2005-02-11 07:09:52

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 3/10] Gameport: connect() is mandatory


===================================================================


[email protected], 2005-02-11 01:18:29-05:00, [email protected]
Input: make connect and disconnect methods mandatory for gameport
drivers since that's where gameport_{open|close} are called
from to actually bind driver to a port.

Signed-off-by: Dmitry Torokhov <[email protected]>


gameport.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)


===================================================================



diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- a/drivers/input/gameport/gameport.c 2005-02-11 01:35:40 -05:00
+++ b/drivers/input/gameport/gameport.c 2005-02-11 01:35:40 -05:00
@@ -107,8 +107,7 @@
list_for_each_entry(drv, &gameport_driver_list, node) {
if (gameport->drv)
break;
- if (drv->connect)
- drv->connect(gameport, drv);
+ drv->connect(gameport, drv);
}
}

@@ -128,7 +127,7 @@
void gameport_unregister_port(struct gameport *gameport)
{
list_del_init(&gameport->node);
- if (gameport->drv && gameport->drv->disconnect)
+ if (gameport->drv)
gameport->drv->disconnect(gameport);
}

@@ -138,7 +137,7 @@

list_add_tail(&drv->node, &gameport_driver_list);
list_for_each_entry(gameport, &gameport_list, node)
- if (!gameport->drv && drv->connect)
+ if (!gameport->drv)
drv->connect(gameport, drv);
}

@@ -148,7 +147,7 @@

list_del_init(&drv->node);
list_for_each_entry(gameport, &gameport_list, node) {
- if (gameport->drv == drv && drv->disconnect)
+ if (gameport->drv == drv)
drv->disconnect(gameport);
gameport_find_driver(gameport);
}

2005-02-11 07:09:53

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 4/10] Gameport: prepare to dynamic allocation


===================================================================


[email protected], 2005-02-11 01:18:48-05:00, [email protected]
Input: prepare for dynamic gameport allocation:
- provide functions to allocate and free gameports;
- provide functions to properly set name and phys;
- dynamically allocated gameports are automatically
announced in kernel logs and freed when unregistered.

Signed-off-by: Dmitry Torokhov <[email protected]>


drivers/input/gameport/gameport.c | 24 ++++++++++++++++++++++++
include/linux/gameport.h | 38 +++++++++++++++++++++++++++++++-------
2 files changed, 55 insertions(+), 7 deletions(-)


===================================================================



diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- a/drivers/input/gameport/gameport.c 2005-02-11 01:36:13 -05:00
+++ b/drivers/input/gameport/gameport.c 2005-02-11 01:36:13 -05:00
@@ -31,6 +31,8 @@
EXPORT_SYMBOL(gameport_close);
EXPORT_SYMBOL(gameport_rescan);
EXPORT_SYMBOL(gameport_cooked_read);
+EXPORT_SYMBOL(gameport_set_name);
+EXPORT_SYMBOL(gameport_set_phys);

static LIST_HEAD(gameport_list);
static LIST_HEAD(gameport_driver_list);
@@ -117,10 +119,30 @@
gameport_find_driver(gameport);
}

+void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ gameport->phys = gameport->phys_buf;
+ vsnprintf(gameport->phys_buf, sizeof(gameport->phys_buf), fmt, args);
+ va_end(args);
+}
+
void gameport_register_port(struct gameport *gameport)
{
list_add_tail(&gameport->node, &gameport_list);
gameport->speed = gameport_measure_speed(gameport);
+
+ if (gameport->dyn_alloc) {
+ if (gameport->io)
+ printk(KERN_INFO "gameport: %s is %s, io %#x, speed %d kHz\n",
+ gameport->name, gameport->phys, gameport->io, gameport->speed);
+ else
+ printk(KERN_INFO "gameport: %s is %s, speed %d kHz\n",
+ gameport->name, gameport->phys, gameport->speed);
+ }
+
gameport_find_driver(gameport);
}

@@ -129,6 +151,8 @@
list_del_init(&gameport->node);
if (gameport->drv)
gameport->drv->disconnect(gameport);
+ if (gameport->dyn_alloc)
+ kfree(gameport);
}

void gameport_register_driver(struct gameport_driver *drv)
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h 2005-02-11 01:36:13 -05:00
+++ b/include/linux/gameport.h 2005-02-11 01:36:13 -05:00
@@ -12,15 +12,16 @@
#include <asm/io.h>
#include <linux/input.h>
#include <linux/list.h>
-
-struct gameport;
+#include <linux/device.h>

struct gameport {

void *private; /* Private pointer for joystick drivers */
void *port_data; /* Private pointer for gameport drivers */
char *name;
+ char name_buf[32];
char *phys;
+ char phys_buf[32];

struct input_id id;

@@ -36,8 +37,12 @@
void (*close)(struct gameport *);

struct gameport_driver *drv;
+ struct device dev;

struct list_head node;
+
+ /* temporary, till sysfs transition is complete */
+ int dyn_alloc;
};

struct gameport_driver {
@@ -55,13 +60,32 @@
void gameport_close(struct gameport *gameport);
void gameport_rescan(struct gameport *gameport);

-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+static inline struct gameport *gameport_allocate_port(void)
+{
+ struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);
+
+ if (gameport)
+ gameport->dyn_alloc = 1;
+
+ return gameport;
+}
+
+static inline void gameport_free_port(struct gameport *gameport)
+{
+ kfree(gameport);
+}
+
+static inline void gameport_set_name(struct gameport *gameport, const char *name)
+{
+ gameport->name = gameport->name_buf;
+ strlcpy(gameport->name, name, sizeof(gameport->name_buf));
+}
+
+void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
void gameport_register_port(struct gameport *gameport);
void gameport_unregister_port(struct gameport *gameport);
-#else
-static inline void gameport_register_port(struct gameport *gameport) { return; }
-static inline void gameport_unregister_port(struct gameport *gameport) { return; }
-#endif

void gameport_register_driver(struct gameport_driver *drv);
void gameport_unregister_driver(struct gameport_driver *drv);

2005-02-11 07:16:53

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 5/10] Gameport: convert input/gameport to dynamic allocation


===================================================================


[email protected], 2005-02-11 01:19:36-05:00, [email protected]
Input: convert input/gameport to dynamic gameport allocation.

Signed-off-by: Dmitry Torokhov <[email protected]>


drivers/input/gameport/cs461x.c | 29 +----
drivers/input/gameport/emu10k1-gp.c | 40 ++++----
drivers/input/gameport/fm801-gp.c | 57 +++++------
drivers/input/gameport/lightning.c | 176 ++++++++++++++++++++++--------------
drivers/input/gameport/ns558.c | 120 +++++++++++-------------
drivers/input/gameport/vortex.c | 68 ++++++-------
drivers/input/joystick/a3d.c | 59 +++++-------
include/linux/gameport.h | 3
8 files changed, 286 insertions(+), 266 deletions(-)


===================================================================



diff -Nru a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
--- a/drivers/input/gameport/cs461x.c 2005-02-11 01:38:07 -05:00
+++ b/drivers/input/gameport/cs461x.c 2005-02-11 01:38:07 -05:00
@@ -120,9 +120,6 @@
static unsigned long ba0_addr;
static unsigned int __iomem *ba0;

-static char phys[32];
-static char name[] = "CS416x Gameport";
-
#ifdef CS461X_FULL_MAP
static unsigned long ba1_addr;
static union ba1_t {
@@ -160,10 +157,10 @@
static int cs461x_free(struct pci_dev *pdev)
{
struct gameport *port = pci_get_drvdata(pdev);
- if(port){
+
+ if (port)
gameport_unregister_port(port);
- kfree(port);
- }
+
if (ba0) iounmap(ba0);
#ifdef CS461X_FULL_MAP
if (ba1.name.data0) iounmap(ba1.name.data0);
@@ -267,18 +264,17 @@
return -ENOMEM;
}
#else
- if (ba0 == NULL){
+ if (ba0 == NULL) {
cs461x_free(pdev);
return -ENOMEM;
}
#endif

- if (!(port = kmalloc(sizeof(struct gameport), GFP_KERNEL))) {
- printk(KERN_ERR "Memory allocation failed.\n");
+ if (!(port = gameport_allocate_port())) {
+ printk(KERN_ERR "cs461x: Memory allocation failed\n");
cs461x_free(pdev);
return -ENOMEM;
}
- memset(port, 0, sizeof(struct gameport));

pci_set_drvdata(pdev, port);

@@ -287,21 +283,14 @@
port->read = cs461x_gameport_read;
port->cooked_read = cs461x_gameport_cooked_read;

- sprintf(phys, "pci%s/gameport0", pci_name(pdev));
-
- port->name = name;
- port->phys = phys;
- port->id.bustype = BUS_PCI;
- port->id.vendor = pdev->vendor;
- port->id.product = pdev->device;
+ gameport_set_name(port, "CS416x");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
+ port->dev.parent = &pdev->dev;

cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);

gameport_register_port(port);
-
- printk(KERN_INFO "gameport: %s on pci%s speed %d kHz\n",
- name, pci_name(pdev), port->speed);

return 0;
}
diff -Nru a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
--- a/drivers/input/gameport/emu10k1-gp.c 2005-02-11 01:38:07 -05:00
+++ b/drivers/input/gameport/emu10k1-gp.c 2005-02-11 01:38:07 -05:00
@@ -44,13 +44,13 @@

struct emu {
struct pci_dev *dev;
- struct gameport gameport;
+ struct gameport *gameport;
+ int io;
int size;
- char phys[32];
};

static struct pci_device_id emu_tbl[] = {
-
+
{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
{ 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
@@ -64,6 +64,7 @@
{
int ioport, iolen;
struct emu *emu;
+ struct gameport *port;

if (pci_enable_device(pdev))
return -EBUSY;
@@ -74,31 +75,29 @@
if (!request_region(ioport, iolen, "emu10k1-gp"))
return -EBUSY;

- if (!(emu = kmalloc(sizeof(struct emu), GFP_KERNEL))) {
- printk(KERN_ERR "emu10k1-gp: Memory allocation failed.\n");
+ emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!emu || !port) {
+ printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
release_region(ioport, iolen);
+ kfree(emu);
+ gameport_free_port(port);
return -ENOMEM;
}
- memset(emu, 0, sizeof(struct emu));
-
- sprintf(emu->phys, "pci%s/gameport0", pci_name(pdev));

+ emu->io = ioport;
emu->size = iolen;
emu->dev = pdev;
+ emu->gameport = port;

- emu->gameport.io = ioport;
- emu->gameport.name = pci_name(pdev);
- emu->gameport.phys = emu->phys;
- emu->gameport.id.bustype = BUS_PCI;
- emu->gameport.id.vendor = pdev->vendor;
- emu->gameport.id.product = pdev->device;
+ gameport_set_name(port, "EMU10K1");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
+ port->dev.parent = &pdev->dev;
+ port->io = ioport;

pci_set_drvdata(pdev, emu);

- gameport_register_port(&emu->gameport);
-
- printk(KERN_INFO "gameport: pci%s speed %d kHz\n",
- pci_name(pdev), emu->gameport.speed);
+ gameport_register_port(port);

return 0;
}
@@ -106,8 +105,9 @@
static void __devexit emu_remove(struct pci_dev *pdev)
{
struct emu *emu = pci_get_drvdata(pdev);
- gameport_unregister_port(&emu->gameport);
- release_region(emu->gameport.io, emu->size);
+
+ gameport_unregister_port(emu->gameport);
+ release_region(emu->io, emu->size);
kfree(emu);
}

diff -Nru a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
--- a/drivers/input/gameport/fm801-gp.c 2005-02-11 01:38:07 -05:00
+++ b/drivers/input/gameport/fm801-gp.c 2005-02-11 01:38:07 -05:00
@@ -37,10 +37,8 @@
#define HAVE_COOKED

struct fm801_gp {
- struct gameport gameport;
+ struct gameport *gameport;
struct resource *res_port;
- char phys[32];
- char name[32];
};

#ifdef HAVE_COOKED
@@ -83,40 +81,42 @@
static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
{
struct fm801_gp *gp;
+ struct gameport *port;

- if (! (gp = kmalloc(sizeof(*gp), GFP_KERNEL))) {
- printk("cannot malloc for fm801-gp\n");
- return -1;
+ gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!gp || !port) {
+ printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
+ kfree(gp);
+ gameport_free_port(port);
+ return -ENOMEM;
}
- memset(gp, 0, sizeof(*gp));

- gp->gameport.open = fm801_gp_open;
+ pci_enable_device(pci);
+
+ port->open = fm801_gp_open;
#ifdef HAVE_COOKED
- gp->gameport.cooked_read = fm801_gp_cooked_read;
+ port->cooked_read = fm801_gp_cooked_read;
#endif
-
- pci_enable_device(pci);
- gp->gameport.io = pci_resource_start(pci, 0);
- if ((gp->res_port = request_region(gp->gameport.io, 0x10, "FM801 GP")) == NULL) {
- printk("unable to grab region 0x%x-0x%x\n", gp->gameport.io, gp->gameport.io + 0x0f);
+ gameport_set_name(port, "FM801");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(pci));
+ port->dev.parent = &pci->dev;
+ port->io = pci_resource_start(pci, 0);
+
+ gp->gameport = port;
+ gp->res_port = request_region(port->io, 0x10, "FM801 GP");
+ if (!gp->res_port) {
kfree(gp);
- return -1;
+ gameport_free_port(port);
+ printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
+ port->io, port->io + 0x0f);
+ return -EBUSY;
}

- gp->gameport.phys = gp->phys;
- gp->gameport.name = gp->name;
- gp->gameport.id.bustype = BUS_PCI;
- gp->gameport.id.vendor = pci->vendor;
- gp->gameport.id.product = pci->device;
-
pci_set_drvdata(pci, gp);

- outb(0x60, gp->gameport.io + 0x0d); /* enable joystick 1 and 2 */
-
- gameport_register_port(&gp->gameport);
-
- printk(KERN_INFO "gameport: at pci%s speed %d kHz\n",
- pci_name(pci), gp->gameport.speed);
+ outb(0x60, port->io + 0x0d); /* enable joystick 1 and 2 */
+ gameport_register_port(port);

return 0;
}
@@ -124,8 +124,9 @@
static void __devexit fm801_gp_remove(struct pci_dev *pci)
{
struct fm801_gp *gp = pci_get_drvdata(pci);
+
if (gp) {
- gameport_unregister_port(&gp->gameport);
+ gameport_unregister_port(gp->gameport);
release_resource(gp->res_port);
kfree(gp);
}
diff -Nru a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
--- a/drivers/input/gameport/lightning.c 2005-02-11 01:38:07 -05:00
+++ b/drivers/input/gameport/lightning.c 2005-02-11 01:38:07 -05:00
@@ -53,13 +53,12 @@
MODULE_DESCRIPTION("PDPI Lightning 4 gamecard driver");
MODULE_LICENSE("GPL");

-static struct l4 {
- struct gameport gameport;
+struct l4 {
+ struct gameport *gameport;
unsigned char port;
- char phys[32];
-} *l4_port[8];
+};

-static char l4_name[] = "PDPI Lightning 4";
+static struct l4 l4_ports[8];

/*
* l4_wait_ready() waits for the L4 to become ready.
@@ -67,10 +66,10 @@

static int l4_wait_ready(void)
{
- unsigned int t;
- t = L4_TIMEOUT;
+ unsigned int t = L4_TIMEOUT;
+
while ((inb(L4_PORT) & L4_BUSY) && t > 0) t--;
- return -(t<=0);
+ return -(t <= 0);
}

/*
@@ -113,6 +112,7 @@
static int l4_open(struct gameport *gameport, int mode)
{
struct l4 *l4 = gameport->port_data;
+
if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
return -1;
outb(L4_SELECT_ANALOG, L4_PORT);
@@ -129,24 +129,29 @@

outb(L4_SELECT_ANALOG, L4_PORT);
outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+ if (inb(L4_PORT) & L4_BUSY)
+ goto out;

- if (inb(L4_PORT) & L4_BUSY) goto fail;
outb(L4_CMD_GETCAL, L4_PORT);
+ if (l4_wait_ready())
+ goto out;

- if (l4_wait_ready()) goto fail;
- if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+ if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
+ goto out;

- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
outb(port & 3, L4_PORT);

for (i = 0; i < 4; i++) {
- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
cal[i] = inb(L4_PORT);
}

result = 0;

-fail: outb(L4_SELECT_ANALOG, L4_PORT);
+out: outb(L4_SELECT_ANALOG, L4_PORT);
return result;
}

@@ -160,24 +165,29 @@

outb(L4_SELECT_ANALOG, L4_PORT);
outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+ if (inb(L4_PORT) & L4_BUSY)
+ goto out;

- if (inb(L4_PORT) & L4_BUSY) goto fail;
outb(L4_CMD_SETCAL, L4_PORT);
+ if (l4_wait_ready())
+ goto out;

- if (l4_wait_ready()) goto fail;
- if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+ if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
+ goto out;

- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
outb(port & 3, L4_PORT);

for (i = 0; i < 4; i++) {
- if (l4_wait_ready()) goto fail;
+ if (l4_wait_ready())
+ goto out;
outb(cal[i], L4_PORT);
}

result = 0;

-fail: outb(L4_SELECT_ANALOG, L4_PORT);
+out: outb(L4_SELECT_ANALOG, L4_PORT);
return result;
}

@@ -209,73 +219,102 @@
return 0;
}

-static int __init l4_init(void)
+static int __init l4_create_ports(int card_no)
{
- int cal[4] = {255,255,255,255};
- int i, j, rev, cards = 0;
- struct gameport *gameport;
struct l4 *l4;
+ struct gameport *port;
+ int i, idx;

- if (!request_region(L4_PORT, 1, "lightning"))
- return -1;
+ for (i = 0; i < 4; i++) {

- for (i = 0; i < 2; i++) {
+ idx = card_no * 4 + i;
+ l4 = &l4_ports[idx];

- outb(L4_SELECT_ANALOG, L4_PORT);
- outb(L4_SELECT_DIGITAL + i, L4_PORT);
+ if (!(l4->gameport = port = gameport_allocate_port())) {
+ printk(KERN_ERR "lightning: Memory allocation failed\n");
+ while (--i >= 0) {
+ gameport_free_port(l4->gameport);
+ l4->gameport = NULL;
+ }
+ return -ENOMEM;
+ }
+ l4->port = idx;

- if (inb(L4_PORT) & L4_BUSY) continue;
- outb(L4_CMD_ID, L4_PORT);
+ port->port_data = l4;
+ port->open = l4_open;
+ port->cooked_read = l4_cooked_read;
+ port->calibrate = l4_calibrate;

- if (l4_wait_ready()) continue;
- if (inb(L4_PORT) != L4_SELECT_DIGITAL + i) continue;
+ gameport_set_name(port, "PDPI Lightning 4");
+ gameport_set_phys(port, "isa%04x/gameport%d", L4_PORT, idx);

- if (l4_wait_ready()) continue;
- if (inb(L4_PORT) != L4_ID) continue;
+ if (idx == 0)
+ port->io = L4_PORT;
+ }

- if (l4_wait_ready()) continue;
- rev = inb(L4_PORT);
+ return 0;
+}

- if (!rev) continue;
+static int __init l4_add_card(int card_no)
+{
+ int cal[4] = { 255, 255, 255, 255 };
+ int i, rev, result;
+ struct l4 *l4;

- if (!(l4_port[i * 4] = kmalloc(sizeof(struct l4) * 4, GFP_KERNEL))) {
- printk(KERN_ERR "lightning: Out of memory allocating ports.\n");
- continue;
- }
- memset(l4_port[i * 4], 0, sizeof(struct l4) * 4);
+ outb(L4_SELECT_ANALOG, L4_PORT);
+ outb(L4_SELECT_DIGITAL + card_no, L4_PORT);

- for (j = 0; j < 4; j++) {
+ if (inb(L4_PORT) & L4_BUSY)
+ return -1;
+ outb(L4_CMD_ID, L4_PORT);

- l4 = l4_port[i * 4 + j] = l4_port[i * 4] + j;
- l4->port = i * 4 + j;
+ if (l4_wait_ready())
+ return -1;

- sprintf(l4->phys, "isa%04x/gameport%d", L4_PORT, 4 * i + j);
+ if (inb(L4_PORT) != L4_SELECT_DIGITAL + card_no)
+ return -1;

- gameport = &l4->gameport;
- gameport->port_data = l4;
- gameport->open = l4_open;
- gameport->cooked_read = l4_cooked_read;
- gameport->calibrate = l4_calibrate;
+ if (l4_wait_ready())
+ return -1;
+ if (inb(L4_PORT) != L4_ID)
+ return -1;

- gameport->name = l4_name;
- gameport->phys = l4->phys;
- gameport->id.bustype = BUS_ISA;
+ if (l4_wait_ready())
+ return -1;
+ rev = inb(L4_PORT);

- if (!i && !j)
- gameport->io = L4_PORT;
+ if (!rev)
+ return -1;

- if (rev > 0x28) /* on 2.9+ the setcal command works correctly */
- l4_setcal(l4->port, cal);
+ result = l4_create_ports(card_no);
+ if (result)
+ return result;

- gameport_register_port(gameport);
- }
+ printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
+ card_no ? "secondary" : "primary", rev >> 4, rev, L4_PORT);

- printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
- i ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
+ for (i = 0; i < 4; i++) {
+ l4 = &l4_ports[card_no * 4 + i];

- cards++;
+ if (rev > 0x28) /* on 2.9+ the setcal command works correctly */
+ l4_setcal(l4->port, cal);
+ gameport_register_port(l4->gameport);
}

+ return 0;
+}
+
+static int __init l4_init(void)
+{
+ int i, cards = 0;
+
+ if (!request_region(L4_PORT, 1, "lightning"))
+ return -1;
+
+ for (i = 0; i < 2; i++)
+ if (l4_add_card(i) == 0)
+ cards++;
+
outb(L4_SELECT_ANALOG, L4_PORT);

if (!cards) {
@@ -289,13 +328,14 @@
static void __exit l4_exit(void)
{
int i;
- int cal[4] = {59, 59, 59, 59};
+ int cal[4] = { 59, 59, 59, 59 };

for (i = 0; i < 8; i++)
- if (l4_port[i]) {
- l4_setcal(l4_port[i]->port, cal);
- gameport_unregister_port(&l4_port[i]->gameport);
+ if (l4_ports[i].gameport) {
+ l4_setcal(l4_ports[i].port, cal);
+ gameport_unregister_port(l4_ports[i].gameport);
}
+
outb(L4_SELECT_ANALOG, L4_PORT);
release_region(L4_PORT, 1);
}
diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
--- a/drivers/input/gameport/ns558.c 2005-02-11 01:38:07 -05:00
+++ b/drivers/input/gameport/ns558.c 2005-02-11 01:38:07 -05:00
@@ -49,12 +49,11 @@

struct ns558 {
int type;
+ int io;
int size;
struct pnp_dev *dev;
+ struct gameport *gameport;
struct list_head node;
- struct gameport gameport;
- char phys[32];
- char name[32];
};

static LIST_HEAD(ns558_list);
@@ -65,18 +64,19 @@
* A joystick must be attached for this to work.
*/

-static void ns558_isa_probe(int io)
+static int ns558_isa_probe(int io)
{
int i, j, b;
unsigned char c, u, v;
- struct ns558 *port;
+ struct ns558 *ns558;
+ struct gameport *port;

/*
* No one should be using this address.
*/

if (!request_region(io, 1, "ns558-isa"))
- return;
+ return -EBUSY;

/*
* We must not be able to write arbitrary values to the port.
@@ -87,8 +87,8 @@
outb(~c & ~3, io);
if (~(u = v = inb(io)) & 3) {
outb(c, io);
- i = 0;
- goto out;
+ release_region(io, 1);
+ return -ENODEV;
}
/*
* After a trigger, there must be at least some bits changing.
@@ -98,8 +98,8 @@

if (u == v) {
outb(c, io);
- i = 0;
- goto out;
+ release_region(io, 1);
+ return -ENODEV;
}
msleep(3);
/*
@@ -110,8 +110,8 @@
for (i = 0; i < 1000; i++)
if ((u ^ inb(io)) & 0xf) {
outb(c, io);
- i = 0;
- goto out;
+ release_region(io, 1);
+ return -ENODEV;
}
/*
* And now find the number of mirrors of the port.
@@ -119,7 +119,7 @@

for (i = 1; i < 5; i++) {

- release_region(io & (-1 << (i-1)), (1 << (i-1)));
+ release_region(io & (-1 << (i - 1)), (1 << (i - 1)));

if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
break; /* Don't disturb anyone */
@@ -139,34 +139,33 @@

if (i != 4) {
if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
- return;
+ return -EBUSY;
}

- if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
+ ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!ns558 || !port) {
printk(KERN_ERR "ns558: Memory allocation failed.\n");
- goto out;
+ release_region(io & (-1 << i), (1 << i));
+ kfree(ns558);
+ gameport_free_port(port);
+ return -ENOMEM;
}
- memset(port, 0, sizeof(struct ns558));
-
- port->size = (1 << i);
- port->gameport.io = io;
- port->gameport.phys = port->phys;
- port->gameport.name = port->name;
- port->gameport.id.bustype = BUS_ISA;

- sprintf(port->phys, "isa%04x/gameport0", io & (-1 << i));
- sprintf(port->name, "NS558 ISA");
+ memset(ns558, 0, sizeof(struct ns558));
+ ns558->io = io;
+ ns558->size = 1 << i;
+ ns558->gameport = port;
+
+ port->io = io;
+ gameport_set_name(port, "NS558 ISA Gameport");
+ gameport_set_phys(port, "isa%04x/gameport0", io & (-1 << i));

- gameport_register_port(&port->gameport);
+ gameport_register_port(port);

- printk(KERN_INFO "gameport: NS558 ISA at %#x", port->gameport.io);
- if (port->size > 1) printk(" size %d", port->size);
- printk(" speed %d kHz\n", port->gameport.speed);
+ list_add(&ns558->node, &ns558_list);

- list_add(&port->node, &ns558_list);
- return;
-out:
- release_region(io & (-1 << i), (1 << i));
+ return 0;
}

#ifdef CONFIG_PNP
@@ -202,45 +201,42 @@
static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
{
int ioport, iolen;
- struct ns558 *port;
+ struct ns558 *ns558;
+ struct gameport *port;

if (!pnp_port_valid(dev, 0)) {
printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n");
return -ENODEV;
}

- ioport = pnp_port_start(dev,0);
- iolen = pnp_port_len(dev,0);
+ ioport = pnp_port_start(dev, 0);
+ iolen = pnp_port_len(dev, 0);

if (!request_region(ioport, iolen, "ns558-pnp"))
return -EBUSY;

- if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
- printk(KERN_ERR "ns558: Memory allocation failed.\n");
+ ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!ns558 || !port) {
+ printk(KERN_ERR "ns558: Memory allocation failed\n");
+ kfree(ns558);
+ gameport_free_port(port);
return -ENOMEM;
}
- memset(port, 0, sizeof(struct ns558));
-
- port->size = iolen;
- port->dev = dev;
-
- port->gameport.io = ioport;
- port->gameport.phys = port->phys;
- port->gameport.name = port->name;
- port->gameport.id.bustype = BUS_ISAPNP;
- port->gameport.id.version = 0x100;
-
- sprintf(port->phys, "pnp%s/gameport0", dev->dev.bus_id);
- sprintf(port->name, "%s", "NS558 PnP Gameport");

- gameport_register_port(&port->gameport);
+ ns558->io = ioport;
+ ns558->size = iolen;
+ ns558->dev = dev;
+ ns558->gameport = port;
+
+ gameport_set_name(port, "NS558 PnP Gameport");
+ gameport_set_phys(port, "pnp%s/gameport0", dev->dev.bus_id);
+ port->dev.parent = &dev->dev;
+ port->io = ioport;

- printk(KERN_INFO "gameport: NS558 PnP at pnp%s io %#x",
- dev->dev.bus_id, port->gameport.io);
- if (iolen > 1) printk(" size %d", iolen);
- printk(" speed %d kHz\n", port->gameport.speed);
+ gameport_register_port(port);

- list_add_tail(&port->node, &ns558_list);
+ list_add_tail(&ns558->node, &ns558_list);
return 0;
}

@@ -279,12 +275,12 @@

static void __exit ns558_exit(void)
{
- struct ns558 *port;
+ struct ns558 *ns558;

- list_for_each_entry(port, &ns558_list, node) {
- gameport_unregister_port(&port->gameport);
- release_region(port->gameport.io & ~(port->size - 1), port->size);
- kfree(port);
+ list_for_each_entry(ns558, &ns558_list, node) {
+ gameport_unregister_port(ns558->gameport);
+ release_region(ns558->io & ~(ns558->size - 1), ns558->size);
+ kfree(ns558);
}

if (pnp_registered)
diff -Nru a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
--- a/drivers/input/gameport/vortex.c 2005-02-11 01:38:07 -05:00
+++ b/drivers/input/gameport/vortex.c 2005-02-11 01:38:07 -05:00
@@ -53,11 +53,10 @@
#define VORTEX_DATA_WAIT 20 /* 20 ms */

struct vortex {
- struct gameport gameport;
+ struct gameport *gameport;
struct pci_dev *dev;
- unsigned char __iomem *base;
- unsigned char __iomem *io;
- char phys[32];
+ unsigned char __iomem *base;
+ unsigned char __iomem *io;
};

static unsigned char vortex_read(struct gameport *gameport)
@@ -109,30 +108,17 @@
static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct vortex *vortex;
+ struct gameport *port;
int i;

- if (!(vortex = kmalloc(sizeof(struct vortex), GFP_KERNEL)))
- return -1;
- memset(vortex, 0, sizeof(struct vortex));
-
- vortex->dev = dev;
- sprintf(vortex->phys, "pci%s/gameport0", pci_name(dev));
-
- pci_set_drvdata(dev, vortex);
-
- vortex->gameport.port_data = vortex;
- vortex->gameport.fuzz = 64;
-
- vortex->gameport.read = vortex_read;
- vortex->gameport.trigger = vortex_trigger;
- vortex->gameport.cooked_read = vortex_cooked_read;
- vortex->gameport.open = vortex_open;
-
- vortex->gameport.name = pci_name(dev);
- vortex->gameport.phys = vortex->phys;
- vortex->gameport.id.bustype = BUS_PCI;
- vortex->gameport.id.vendor = dev->vendor;
- vortex->gameport.id.product = dev->device;
+ vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL);
+ port = gameport_allocate_port();
+ if (!vortex || !port) {
+ printk(KERN_ERR "vortex: Memory allocation failed.\n");
+ kfree(vortex);
+ gameport_free_port(port);
+ return -ENOMEM;
+ }

for (i = 0; i < 6; i++)
if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
@@ -140,14 +126,26 @@

pci_enable_device(dev);

+ vortex->dev = dev;
+ vortex->gameport = port;
vortex->base = ioremap(pci_resource_start(vortex->dev, i),
pci_resource_len(vortex->dev, i));
vortex->io = vortex->base + id->driver_data;

- gameport_register_port(&vortex->gameport);
+ pci_set_drvdata(dev, vortex);
+
+ port->port_data = vortex;
+ port->fuzz = 64;

- printk(KERN_INFO "gameport at pci%s speed %d kHz\n",
- pci_name(dev), vortex->gameport.speed);
+ gameport_set_name(port, "AU88x0");
+ gameport_set_phys(port, "pci%s/gameport0", pci_name(dev));
+ port->dev.parent = &dev->dev;
+ port->read = vortex_read;
+ port->trigger = vortex_trigger;
+ port->cooked_read = vortex_cooked_read;
+ port->open = vortex_open;
+
+ gameport_register_port(port);

return 0;
}
@@ -155,15 +153,17 @@
static void __devexit vortex_remove(struct pci_dev *dev)
{
struct vortex *vortex = pci_get_drvdata(dev);
- gameport_unregister_port(&vortex->gameport);
+
+ gameport_unregister_port(vortex->gameport);
iounmap(vortex->base);
kfree(vortex);
}

-static struct pci_device_id vortex_id_table[] =
-{{ 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
- { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
- { 0 }};
+static struct pci_device_id vortex_id_table[] = {
+ { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
+ { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
+ { 0 }
+};

static struct pci_driver vortex_driver = {
.name = "vortex_gameport",
diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
--- a/drivers/input/joystick/a3d.c 2005-02-11 01:38:07 -05:00
+++ b/drivers/input/joystick/a3d.c 2005-02-11 01:38:07 -05:00
@@ -55,7 +55,7 @@

struct a3d {
struct gameport *gameport;
- struct gameport adc;
+ struct gameport *adc;
struct input_dev dev;
struct timer_list timer;
int axes[4];
@@ -66,7 +66,6 @@
int reads;
int bads;
char phys[32];
- char adcphys[32];
};

/*
@@ -261,6 +260,7 @@
static void a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct a3d *a3d;
+ struct gameport *adc;
unsigned char data[A3D_MAX_LENGTH];
int i;

@@ -292,7 +292,6 @@
}

sprintf(a3d->phys, "%s/input0", gameport->phys);
- sprintf(a3d->adcphys, "%s/gameport0", gameport->phys);

if (a3d->mode == A3D_MODE_PXL) {

@@ -315,16 +314,11 @@
a3d_read(a3d, data);

for (i = 0; i < 4; i++) {
- if (i < 2) {
- a3d->dev.absmin[axes[i]] = 48;
- a3d->dev.absmax[axes[i]] = a3d->dev.abs[axes[i]] * 2 - 48;
- a3d->dev.absflat[axes[i]] = 8;
- } else {
- a3d->dev.absmin[axes[i]] = 2;
- a3d->dev.absmax[axes[i]] = 253;
- }
- a3d->dev.absmin[ABS_HAT0X + i] = -1;
- a3d->dev.absmax[ABS_HAT0X + i] = 1;
+ if (i < 2)
+ input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8);
+ else
+ input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0);
+ input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0);
}

} else {
@@ -336,23 +330,23 @@
a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);

- a3d->adc.port_data = a3d;
- a3d->adc.open = a3d_adc_open;
- a3d->adc.close = a3d_adc_close;
- a3d->adc.cooked_read = a3d_adc_cooked_read;
- a3d->adc.fuzz = 1;
-
- a3d->adc.name = a3d_names[a3d->mode];
- a3d->adc.phys = a3d->adcphys;
- a3d->adc.id.bustype = BUS_GAMEPORT;
- a3d->adc.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
- a3d->adc.id.product = a3d->mode;
- a3d->adc.id.version = 0x0100;
-
a3d_read(a3d, data);

- gameport_register_port(&a3d->adc);
- printk(KERN_INFO "gameport: %s on %s\n", a3d_names[a3d->mode], gameport->phys);
+ if (!(a3d->adc = adc = gameport_allocate_port()))
+ printk(KERN_ERR "a3d: Not enough memory for ADC port\n");
+ else {
+ adc->port_data = a3d;
+ adc->open = a3d_adc_open;
+ adc->close = a3d_adc_close;
+ adc->cooked_read = a3d_adc_cooked_read;
+ adc->fuzz = 1;
+
+ gameport_set_name(adc, a3d_names[a3d->mode]);
+ gameport_set_phys(adc, "%s/gameport0", gameport->phys);
+ adc->dev.parent = &gameport->dev;
+
+ gameport_register_port(adc);
+ }
}

a3d->dev.private = a3d;
@@ -370,17 +364,20 @@
printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);

return;
+
fail2: gameport_close(gameport);
fail1: kfree(a3d);
}

static void a3d_disconnect(struct gameport *gameport)
{
-
struct a3d *a3d = gameport->private;
+
input_unregister_device(&a3d->dev);
- if (a3d->mode < A3D_MODE_PXL)
- gameport_unregister_port(&a3d->adc);
+ if (a3d->adc) {
+ gameport_unregister_port(a3d->adc);
+ a3d->adc = NULL;
+ }
gameport_close(gameport);
kfree(a3d);
}
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h 2005-02-11 01:38:07 -05:00
+++ b/include/linux/gameport.h 2005-02-11 01:38:07 -05:00
@@ -10,7 +10,6 @@
*/

#include <asm/io.h>
-#include <linux/input.h>
#include <linux/list.h>
#include <linux/device.h>

@@ -22,8 +21,6 @@
char name_buf[32];
char *phys;
char phys_buf[32];
-
- struct input_id id;

int io;
int speed;

2005-02-11 07:19:53

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 6/10] Gameport: convert sound/oss to dynamic allocation


===================================================================


[email protected], 2005-02-11 01:20:08-05:00, [email protected]
Input: convert sound/oss to dynamic gameport allocation.

Signed-off-by: Dmitry Torokhov <[email protected]>


cmpci.c | 100 ++++++++++++++++++++++++++++++++++++++---------------------
es1370.c | 34 ++++++++++++--------
es1371.c | 52 ++++++++++++++++++------------
esssolo1.c | 47 ++++++++++++++++++++-------
mad16.c | 47 ++++++++++++++++++---------
sonicvibes.c | 49 +++++++++++++++++++++-------
trident.c | 39 +++++++++++++++++------
7 files changed, 249 insertions(+), 119 deletions(-)


===================================================================



diff -Nru a/sound/oss/cmpci.c b/sound/oss/cmpci.c
--- a/sound/oss/cmpci.c 2005-02-11 01:38:28 -05:00
+++ b/sound/oss/cmpci.c 2005-02-11 01:38:28 -05:00
@@ -426,7 +426,7 @@
struct address_info mpu_data;
#endif
#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
- struct gameport gameport;
+ struct gameport *gameport;
#endif

int chip_version;
@@ -468,17 +468,17 @@

static LIST_HEAD(devs);

-static int mpuio = 0;
-static int fmio = 0;
-static int joystick = 0;
-static int spdif_inverse = 0;
-static int spdif_loop = 0;
-static int spdif_out = 0;
-static int use_line_as_rear = 0;
-static int use_line_as_bass = 0;
-static int use_mic_as_bass = 0;
-static int mic_boost = 0;
-static int hw_copy = 0;
+static int mpuio;
+static int fmio;
+static int joystick;
+static int spdif_inverse;
+static int spdif_loop;
+static int spdif_out;
+static int use_line_as_rear;
+static int use_line_as_bass;
+static int use_mic_as_bass;
+static int mic_boost;
+static int hw_copy;
module_param(mpuio, int, 0);
module_param(fmio, int, 0);
module_param(joystick, bool, 0);
@@ -2984,6 +2984,51 @@
return ChipVersion;
}

+#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
+static int __devinit cm_create_gameport(struct cm_state *s, int io_port)
+{
+ struct gameport *gp;
+
+ if (!request_region(io_port, CM_EXTENT_GAME, "cmpci GAME")) {
+ printk(KERN_ERR "cmpci: gameport io ports 0x%#x in use\n", io_port);
+ return -EBUSY;
+ }
+
+ if (!(s->gameport = gp = gameport_allocate_port())) {
+ printk(KERN_ERR "cmpci: can not allocate memory for gameport\n");
+ release_region(io_port, CM_EXTENT_GAME);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "C-Media GP");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+ gp->dev.parent = &s->dev->dev;
+ gp->io = io_port;
+
+ /* enable joystick */
+ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02);
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static void __devexit cm_free_gameport(struct cm_state *s)
+{
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+
+ gameport_unregister_port(s->gameport);
+ s->gameport = NULL;
+ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
+ release_region(gpio, CM_EXTENT_GAME);
+ }
+}
+#else
+static inline int cm_create_gameport(struct cm_state *s, int io_port) { return -ENOSYS; }
+static inline void cm_free_gameport(struct cm_state *s) { }
+#endif
+
#define echo_option(x)\
if (x) strcat(options, "" #x " ")

@@ -3229,22 +3274,11 @@
}
skip_mpu:
#endif
-#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
- /* enable joystick */
- if (joystick) {
- s->gameport.io = 0x200;
- if (!request_region(s->gameport.io, CM_EXTENT_GAME, "cmpci GAME")) {
- printk(KERN_ERR "cmpci: gameport io ports in use\n");
- s->gameport.io = 0;
- } else {
- maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02);
- gameport_register_port(&s->gameport);
- }
- } else {
- maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
- s->gameport.io = 0;
- }
-#endif
+ /* disable joystick port */
+ maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
+ if (joystick)
+ cm_create_gameport(s, 0x200);
+
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
/* put it into driver list */
@@ -3278,13 +3312,9 @@

if (!s)
return;
-#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, CM_EXTENT_GAME);
- maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
- }
-#endif
+
+ cm_free_gameport(s);
+
#ifdef CONFIG_SOUND_CMPCI_FM
if (s->iosynth) {
/* disable FM */
diff -Nru a/sound/oss/es1370.c b/sound/oss/es1370.c
--- a/sound/oss/es1370.c 2005-02-11 01:38:28 -05:00
+++ b/sound/oss/es1370.c 2005-02-11 01:38:28 -05:00
@@ -384,7 +384,7 @@
unsigned char obuf[MIDIOUTBUF];
} midi;

- struct gameport gameport;
+ struct gameport *gameport;
struct semaphore sem;
};

@@ -2556,6 +2556,7 @@
static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct es1370_state *s;
+ struct gameport *gp = NULL;
mm_segment_t fs;
int i, val, ret;

@@ -2604,12 +2605,17 @@
/* note: setting CTRL_SERR_DIS is reported to break
* mic bias setting (by [email protected]) */
s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
- s->gameport.io = 0;
- if (!request_region(0x200, JOY_EXTENT, "es1370"))
+ if (!request_region(0x200, JOY_EXTENT, "es1370")) {
printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
- else {
+ } else if (!(s->gameport = gp = gameport_allocate_port())) {
+ printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
+ release_region(0x200, JOY_EXTENT);
+ } else {
+ gameport_set_name(gp, "ESS1370");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+ gp->dev.parent = &s->dev->dev;
+ gp->io = 0x200;
s->ctrl |= CTRL_JYSTK_EN;
- s->gameport.io = 0x200;
}
if (lineout[devindex])
s->ctrl |= CTRL_XCTL0;
@@ -2665,9 +2671,10 @@
mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
}
set_fs(fs);
+
/* register gameport */
- if (s->gameport.io)
- gameport_register_port(&s->gameport);
+ if (gp)
+ gameport_register_port(gp);

/* store it in the driver field */
pci_set_drvdata(pcidev, s);
@@ -2689,8 +2696,10 @@
err_dev1:
printk(KERN_ERR "es1370: cannot register misc device\n");
free_irq(s->irq, s);
- if (s->gameport.io)
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ release_region(s->gameport->io, JOY_EXTENT);
+ gameport_free_port(s->gameport);
+ }
err_irq:
release_region(s->io, ES1370_EXTENT);
err_region:
@@ -2709,9 +2718,10 @@
outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq(s->irq);
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, JOY_EXTENT);
}
release_region(s->io, ES1370_EXTENT);
unregister_sound_dsp(s->dev_audio);
diff -Nru a/sound/oss/es1371.c b/sound/oss/es1371.c
--- a/sound/oss/es1371.c 2005-02-11 01:38:28 -05:00
+++ b/sound/oss/es1371.c 2005-02-11 01:38:28 -05:00
@@ -453,7 +453,7 @@
unsigned char obuf[MIDIOUTBUF];
} midi;

- struct gameport gameport;
+ struct gameport *gameport;
struct semaphore sem;
};

@@ -2786,12 +2786,12 @@
{ PCI_ANY_ID, PCI_ANY_ID }
};

-
static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct es1371_state *s;
+ struct gameport *gp;
mm_segment_t fs;
- int i, val, res = -1;
+ int i, gpio, val, res = -1;
int idx;
unsigned long tmo;
signed long tmo2;
@@ -2849,8 +2849,8 @@
printk(KERN_ERR PFX "irq %u in use\n", s->irq);
goto err_irq;
}
- printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u joystick %#x\n",
- s->rev, s->io, s->irq, s->gameport.io);
+ printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n",
+ s->rev, s->io, s->irq);
/* register devices */
if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0)
goto err_dev1;
@@ -2881,16 +2881,23 @@
printk(KERN_INFO PFX "Enabling internal amplifier.\n");
}
}
- s->gameport.io = 0;
- for (i = 0x218; i >= 0x200; i -= 0x08) {
- if (request_region(i, JOY_EXTENT, "es1371")) {
- s->ctrl |= CTRL_JYSTK_EN | (((i >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
- s->gameport.io = i;
+
+ for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
+ if (request_region(gpio, JOY_EXTENT, "es1371"))
break;
- }
- }
- if (!s->gameport.io)
+
+ if (gpio < 0x200) {
printk(KERN_ERR PFX "no free joystick address found\n");
+ } else if (!(s->gameport = gp = gameport_allocate_port())) {
+ printk(KERN_ERR PFX "can not allocate memory for gameport\n");
+ release_region(gpio, JOY_EXTENT);
+ } else {
+ gameport_set_name(gp, "ESS1371 Gameport");
+ gameport_set_phys(gp, "isa%04x/gameport0", gpio);
+ gp->dev.parent = &s->dev->dev;
+ gp->io = gpio;
+ s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+ }

s->sctrl = 0;
cssr = 0;
@@ -2960,9 +2967,11 @@
set_fs(fs);
/* turn on S/PDIF output driver if requested */
outl(cssr, s->io+ES1371_REG_STATUS);
+
/* register gameport */
- if (s->gameport.io)
- gameport_register_port(&s->gameport);
+ if (s->gameport)
+ gameport_register_port(s->gameport);
+
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
/* put it into driver list */
@@ -2973,8 +2982,10 @@
return 0;

err_gp:
- if (s->gameport.io)
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ release_region(s->gameport->io, JOY_EXTENT);
+ gameport_free_port(s->gameport);
+ }
#ifdef ES1371_DEBUG
if (s->ps)
remove_proc_entry("es1371", NULL);
@@ -3013,9 +3024,10 @@
outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
synchronize_irq(s->irq);
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, JOY_EXTENT);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, JOY_EXTENT);
}
release_region(s->io, ES1371_EXTENT);
unregister_sound_dsp(s->dev_audio);
diff -Nru a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
--- a/sound/oss/esssolo1.c 2005-02-11 01:38:28 -05:00
+++ b/sound/oss/esssolo1.c 2005-02-11 01:38:28 -05:00
@@ -226,7 +226,7 @@
unsigned char obuf[MIDIOUTBUF];
} midi;

- struct gameport gameport;
+ struct gameport *gameport;
};

/* --------------------------------------------------------------------- */
@@ -2280,9 +2280,36 @@
return 0;
}

+static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port)
+{
+ struct gameport *gp;
+
+ if (!request_region(io_port, GAMEPORT_EXTENT, "ESS Solo1")) {
+ printk(KERN_ERR "solo1: gameport io ports are in use\n");
+ return -EBUSY;
+ }
+
+ s->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "solo1: can not allocate memory for gameport\n");
+ release_region(io_port, GAMEPORT_EXTENT);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ESS Solo1 Gameport");
+ gameport_set_phys(gp, "isa%04x/gameport0", io_port);
+ gp->dev.parent = &s->dev->dev;
+ gp->io = io_port;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
struct solo1_state *s;
+ int gpio;
int ret;

if ((ret=pci_enable_device(pcidev)))
@@ -2323,7 +2350,7 @@
s->vcbase = pci_resource_start(pcidev, 2);
s->ddmabase = s->vcbase + DDMABASE_OFFSET;
s->mpubase = pci_resource_start(pcidev, 3);
- s->gameport.io = pci_resource_start(pcidev, 4);
+ gpio = pci_resource_start(pcidev, 4);
s->irq = pcidev->irq;
ret = -EBUSY;
if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) {
@@ -2342,15 +2369,10 @@
printk(KERN_ERR "solo1: io ports in use\n");
goto err_region4;
}
- if (s->gameport.io && !request_region(s->gameport.io, GAMEPORT_EXTENT, "ESS Solo1")) {
- printk(KERN_ERR "solo1: gameport io ports in use\n");
- s->gameport.io = 0;
- }
if ((ret=request_irq(s->irq,solo1_interrupt,SA_SHIRQ,"ESS Solo1",s))) {
printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
goto err_irq;
}
- printk(KERN_INFO "solo1: joystick port at %#x\n", s->gameport.io+1);
/* register devices */
if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0) {
ret = s->dev_audio;
@@ -2373,7 +2395,7 @@
goto err;
}
/* register gameport */
- gameport_register_port(&s->gameport);
+ solo1_register_gameport(s, gpio);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
return 0;
@@ -2390,8 +2412,6 @@
printk(KERN_ERR "solo1: initialisation error\n");
free_irq(s->irq, s);
err_irq:
- if (s->gameport.io)
- release_region(s->gameport.io, GAMEPORT_EXTENT);
release_region(s->mpubase, MPUBASE_EXTENT);
err_region4:
release_region(s->ddmabase, DDMABASE_EXTENT);
@@ -2417,9 +2437,10 @@
synchronize_irq(s->irq);
pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, GAMEPORT_EXTENT);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, GAMEPORT_EXTENT);
}
release_region(s->iobase, IOBASE_EXTENT);
release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
diff -Nru a/sound/oss/mad16.c b/sound/oss/mad16.c
--- a/sound/oss/mad16.c 2005-02-11 01:38:28 -05:00
+++ b/sound/oss/mad16.c 2005-02-11 01:38:28 -05:00
@@ -52,7 +52,7 @@

static int mad16_conf;
static int mad16_cdsel;
-static struct gameport gameport;
+static struct gameport *gameport;
static DEFINE_SPINLOCK(lock);

#define C928 1
@@ -902,7 +902,30 @@
-1, -1, -1, -1
};

-static int __init init_mad16(void)
+static int __devinit mad16_register_gameport(int io_port)
+{
+ if (!request_region(io_port, 1, "mad16 gameport")) {
+ printk(KERN_ERR "mad16: gameport address 0x%#x already in use\n", io_port);
+ return -EBUSY;
+ }
+
+ gameport = gameport_allocate_port();
+ if (!gameport) {
+ printk(KERN_ERR "mad16: can not allocate memory for gameport\n");
+ release_region(io_port, 1);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gameport, "MAD16 Gameport");
+ gameport_set_phys(gameport, "isa%04x/gameport0", io_port);
+ gameport->io = io_port;
+
+ gameport_register_port(gameport);
+
+ return 0;
+}
+
+static int __devinit init_mad16(void)
{
int dmatype = 0;

@@ -1027,17 +1050,9 @@

found_mpu = probe_mad16_mpu(&cfg_mpu);

- if (joystick == 1) {
- /* register gameport */
- if (!request_region(0x201, 1, "mad16 gameport"))
- printk(KERN_ERR "mad16: gameport address 0x201 already in use\n");
- else {
- printk(KERN_ERR "mad16: gameport enabled at 0x201\n");
- gameport.io = 0x201;
- gameport_register_port(&gameport);
- }
- }
- else printk(KERN_ERR "mad16: gameport disabled.\n");
+ if (joystick)
+ mad16_register_gameport(0x201);
+
return 0;
}

@@ -1045,10 +1060,10 @@
{
if (found_mpu)
unload_mad16_mpu(&cfg_mpu);
- if (gameport.io) {
+ if (gameport) {
/* the gameport was initialized so we must free it up */
- gameport_unregister_port(&gameport);
- gameport.io = 0;
+ gameport_unregister_port(gameport);
+ gameport = NULL;
release_region(0x201, 1);
}
unload_mad16(&cfg);
diff -Nru a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
--- a/sound/oss/sonicvibes.c 2005-02-11 01:38:28 -05:00
+++ b/sound/oss/sonicvibes.c 2005-02-11 01:38:28 -05:00
@@ -365,7 +365,7 @@
unsigned char obuf[MIDIOUTBUF];
} midi;

- struct gameport gameport;
+ struct gameport *gameport;
};

/* --------------------------------------------------------------------- */
@@ -2485,12 +2485,39 @@
#define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \
(pci_resource_flags((dev), (num)) & IORESOURCE_IO))

+static int __devinit sv_register_gameport(struct sv_state *s, int io_port)
+{
+ struct gameport *gp;
+
+ if (!request_region(io_port, SV_EXTENT_GAME, "S3 SonicVibes Gameport")) {
+ printk(KERN_ERR "sv: gameport io ports are in use\n");
+ return -EBUSY;
+ }
+
+ s->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "sv: can not allocate memory for gameport\n");
+ release_region(io_port, SV_EXTENT_GAME);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "S3 SonicVibes Gameport");
+ gameport_set_phys(gp, "isa%04x/gameport0", io_port);
+ gp->dev.parent = &s->dev->dev;
+ gp->io = io_port;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
{
static char __initdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller";
struct sv_state *s;
mm_segment_t fs;
int i, val, ret;
+ int gpio;
char *ddmaname;
unsigned ddmanamelen;

@@ -2546,11 +2573,11 @@
s->iomidi = pci_resource_start(pcidev, RESOURCE_MIDI);
s->iodmaa = pci_resource_start(pcidev, RESOURCE_DDMA);
s->iodmac = pci_resource_start(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA;
- s->gameport.io = pci_resource_start(pcidev, RESOURCE_GAME);
+ gpio = pci_resource_start(pcidev, RESOURCE_GAME);
pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9); /* enable and use extended mode */
pci_write_config_dword(pcidev, 0x48, s->iodmac | 9); /* enable */
printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#x %#x %#x\n",
- s->iosb, s->ioenh, s->iosynth, s->iomidi, s->gameport.io, s->iodmaa, s->iodmac);
+ s->iosb, s->ioenh, s->iosynth, s->iomidi, gpio, s->iodmaa, s->iodmac);
s->irq = pcidev->irq;

/* hack */
@@ -2577,10 +2604,7 @@
printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
goto err_region1;
}
- if (s->gameport.io && !request_region(s->gameport.io, SV_EXTENT_GAME, "ESS Solo1")) {
- printk(KERN_ERR "sv: gameport io ports in use\n");
- s->gameport.io = 0;
- }
+
/* initialize codec registers */
outb(0x80, s->ioenh + SV_CODEC_CONTROL); /* assert reset */
udelay(50);
@@ -2639,7 +2663,7 @@
}
set_fs(fs);
/* register gameport */
- gameport_register_port(&s->gameport);
+ sv_register_gameport(s, gpio);
/* store it in the driver field */
pci_set_drvdata(pcidev, s);
/* put it into driver list */
@@ -2659,8 +2683,6 @@
printk(KERN_ERR "sv: cannot register misc device\n");
free_irq(s->irq, s);
err_irq:
- if (s->gameport.io)
- release_region(s->gameport.io, SV_EXTENT_GAME);
release_region(s->iosynth, SV_EXTENT_SYNTH);
err_region1:
release_region(s->iomidi, SV_EXTENT_MIDI);
@@ -2689,9 +2711,10 @@
/*outb(0, s->iodmaa + SV_DMA_RESET);*/
/*outb(0, s->iodmac + SV_DMA_RESET);*/
free_irq(s->irq, s);
- if (s->gameport.io) {
- gameport_unregister_port(&s->gameport);
- release_region(s->gameport.io, SV_EXTENT_GAME);
+ if (s->gameport) {
+ int gpio = s->gameport->io;
+ gameport_unregister_port(s->gameport);
+ release_region(gpio, SV_EXTENT_GAME);
}
release_region(s->iodmac, SV_EXTENT_DMA);
release_region(s->iodmaa, SV_EXTENT_DMA);
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c 2005-02-11 01:38:28 -05:00
+++ b/sound/oss/trident.c 2005-02-11 01:38:28 -05:00
@@ -441,7 +441,7 @@
struct timer_list timer;

/* Game port support */
- struct gameport gameport;
+ struct gameport *gameport;
};

enum dmabuf_mode {
@@ -4305,6 +4305,31 @@
return 0;
}

+static int __devinit
+trident_register_gameport(struct trident_card *card)
+{
+ struct gameport *gp;
+
+ card->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "trident: can not allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "Trident 4DWave");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev));
+ gp->read = trident_game_read;
+ gp->trigger = trident_game_trigger;
+ gp->cooked_read = trident_game_cooked_read;
+ gp->open = trident_game_open;
+ gp->fuzz = 64;
+ gp->port_data = card;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
/* install the driver, we do not allocate hardware channel nor DMA buffer */
/* now, they are defered until "ACCESS" time (in prog_dmabuf called by */
/* open/read/write/ioctl/mmap) */
@@ -4368,13 +4393,6 @@
card->banks[BANK_B].addresses = &bank_b_addrs;
card->banks[BANK_B].bitmap = 0UL;

- card->gameport.port_data = card;
- card->gameport.fuzz = 64;
- card->gameport.read = trident_game_read;
- card->gameport.trigger = trident_game_trigger;
- card->gameport.cooked_read = trident_game_cooked_read;
- card->gameport.open = trident_game_open;
-
init_MUTEX(&card->open_sem);
spin_lock_init(&card->lock);
init_timer(&card->timer);
@@ -4508,7 +4526,7 @@
trident_enable_loop_interrupts(card);

/* Register gameport */
- gameport_register_port(&card->gameport);
+ trident_register_gameport(card);

out:
return rc;
@@ -4551,7 +4569,8 @@
}

/* Unregister gameport */
- gameport_unregister_port(&card->gameport);
+ if (card->gameport)
+ gameport_unregister_port(card->gameport);

/* Kill interrupts, and SP/DIF */
trident_disable_loop_interrupts(card);

2005-02-11 07:27:14

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 7/10] Gameport: convert sound/alsa to dynamic allocation


===================================================================


[email protected], 2005-02-11 01:20:30-05:00, [email protected]
Input: convert sound/pci to dynamic gameport allocation.

Signed-off-by: Dmitry Torokhov <[email protected]>


include/sound/cs46xx.h | 4 -
include/sound/trident.h | 4 -
include/sound/ymfpci.h | 14 +--
sound/pci/als4000.c | 111 +++++++++++++++++++----------
sound/pci/au88x0/au88x0.c | 7 -
sound/pci/au88x0/au88x0.h | 2
sound/pci/au88x0/au88x0_game.c | 49 ++++++------
sound/pci/azt3328.c | 111 +++++++++++++++++------------
sound/pci/cmipci.c | 104 ++++++++++++++++++---------
sound/pci/cs4281.c | 91 ++++++++++++-----------
sound/pci/cs46xx/cs46xx_lib.c | 81 ++++++++++-----------
sound/pci/ens1370.c | 122 +++++++++++++++++++++----------
sound/pci/es1938.c | 52 ++++++++++---
sound/pci/es1968.c | 76 ++++++++++++++-----
sound/pci/sonicvibes.c | 55 +++++++++++---
sound/pci/trident/trident.c | 2
sound/pci/trident/trident_main.c | 87 ++++++++++------------
sound/pci/via82xx.c | 89 +++++++++++++++++------
sound/pci/ymfpci/ymfpci.c | 149 ++++++++++++++++++++++++---------------
sound/pci/ymfpci/ymfpci_main.c | 9 --
20 files changed, 761 insertions(+), 458 deletions(-)


===================================================================



diff -Nru a/include/sound/cs46xx.h b/include/sound/cs46xx.h
--- a/include/sound/cs46xx.h 2005-02-11 01:39:33 -05:00
+++ b/include/sound/cs46xx.h 2005-02-11 01:39:33 -05:00
@@ -1720,7 +1720,7 @@
snd_kcontrol_t *eapd_switch; /* for amplifier hack */
int accept_valid; /* accept mmap valid (for OSS) */

- struct snd_cs46xx_gameport *gameport;
+ struct gameport *gameport;

#ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
int current_gpio;
@@ -1751,6 +1751,6 @@
int snd_cs46xx_mixer(cs46xx_t *chip);
int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
int snd_cs46xx_start_dsp(cs46xx_t *chip);
-void snd_cs46xx_gameport(cs46xx_t *chip);
+int snd_cs46xx_gameport(cs46xx_t *chip);

#endif /* __SOUND_CS46XX_H */
diff -Nru a/include/sound/trident.h b/include/sound/trident.h
--- a/include/sound/trident.h 2005-02-11 01:39:33 -05:00
+++ b/include/sound/trident.h 2005-02-11 01:39:33 -05:00
@@ -448,7 +448,7 @@

spinlock_t reg_lock;

- struct snd_trident_gameport *gameport;
+ struct gameport *gameport;
};

int snd_trident_create(snd_card_t * card,
@@ -457,7 +457,7 @@
int pcm_spdif_device,
int max_wavetable_size,
trident_t ** rtrident);
-void snd_trident_gameport(trident_t *trident);
+int snd_trident_create_gameport(trident_t *trident);

int snd_trident_pcm(trident_t * trident, int device, snd_pcm_t **rpcm);
int snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_t **rpcm);
diff -Nru a/include/sound/ymfpci.h b/include/sound/ymfpci.h
--- a/include/sound/ymfpci.h 2005-02-11 01:39:33 -05:00
+++ b/include/sound/ymfpci.h 2005-02-11 01:39:33 -05:00
@@ -198,6 +198,10 @@
#define YMFPCI_LEGACY2_IMOD (1 << 15) /* legacy IRQ mode */
/* SIEN:IMOD 0:0 = legacy irq, 0:1 = INTA, 1:0 = serialized IRQ */

+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK
+#endif
+
/*
*
*/
@@ -311,9 +315,8 @@
struct resource *mpu_res;

unsigned short old_legacy_ctrl;
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
- struct resource *joystick_res;
- struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
#endif

struct snd_dma_buffer work_ptr;
@@ -381,6 +384,7 @@
struct pci_dev *pci,
unsigned short old_legacy_ctrl,
ymfpci_t ** rcodec);
+void snd_ymfpci_free_gameport(ymfpci_t *chip);

int snd_ymfpci_pcm(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
int snd_ymfpci_pcm2(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
@@ -388,9 +392,5 @@
int snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
int snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch);
int snd_ymfpci_timer(ymfpci_t *chip, int device);
-
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK
-#endif

#endif /* __SOUND_YMFPCI_H */
diff -Nru a/sound/pci/als4000.c b/sound/pci/als4000.c
--- a/sound/pci/als4000.c 2005-02-11 01:39:34 -05:00
+++ b/sound/pci/als4000.c 2005-02-11 01:39:34 -05:00
@@ -104,8 +104,7 @@
struct pci_dev *pci;
unsigned long gcr;
#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
} snd_card_als4000_t;

@@ -566,21 +565,80 @@
spin_unlock_irq(&chip->reg_lock);
}

+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev)
+{
+ struct gameport *gp;
+ struct resource *r;
+ int io_port;
+
+ if (joystick_port[dev] == 0)
+ return -ENODEV;
+
+ if (joystick_port[dev] == 1) { /* auto-detect */
+ for (io_port = 0x200; io_port <= 0x218; io_port += 8) {
+ r = request_region(io_port, 8, "ALS4000 gameport");
+ if (r)
+ break;
+ }
+ } else {
+ io_port = joystick_port[dev];
+ r = request_region(io_port, 8, "ALS4000 gameport");
+ }
+
+ if (!r) {
+ printk(KERN_WARNING "als4000: cannot reserve joystick ports\n");
+ return -EBUSY;
+ }
+
+ acard->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "als4000: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ALS4000 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
+ gp->dev.parent = &acard->pci->dev;
+ gp->io = io_port;
+ gp->port_data = r;
+
+ /* Enable legacy joystick port */
+ snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1);
+
+ gameport_register_port(acard->gameport);
+
+ return 0;
+}
+
+static void snd_als4000_free_gameport(snd_card_als4000_t *acard)
+{
+ if (acard->gameport) {
+ struct resource *r = acard->gameport->port_data;
+
+ gameport_unregister_port(acard->gameport);
+ acard->gameport = NULL;
+
+ snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev) { return -ENOSYS; }
+static inline void snd_als4000_free_gameport(snd_card_als4000_t *acard) { }
+#endif
+
static void snd_card_als4000_free( snd_card_t *card )
{
snd_card_als4000_t * acard = (snd_card_als4000_t *)card->private_data;
+
/* make sure that interrupts are disabled */
snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0);
/* free resources */
-#ifdef SUPPORT_JOYSTICK
- if (acard->res_joystick) {
- if (acard->gameport.io)
- gameport_unregister_port(&acard->gameport);
- snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */
- release_resource(acard->res_joystick);
- kfree_nocheck(acard->res_joystick);
- }
-#endif
+ snd_als4000_free_gameport(acard);
pci_release_regions(acard->pci);
pci_disable_device(acard->pci);
}
@@ -596,7 +654,6 @@
opl3_t *opl3;
unsigned short word;
int err;
- int joystick = 0;

if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -640,26 +697,9 @@
acard->gcr = gcr;
card->private_free = snd_card_als4000_free;

- /* disable all legacy ISA stuff except for joystick */
-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] == 1) {
- /* auto-detect */
- long p;
- for (p = 0x200; p <= 0x218; p += 8) {
- if ((acard->res_joystick = request_region(p, 8, "ALS4000 gameport")) != NULL) {
- joystick_port[dev] = p;
- break;
- }
- }
- } else if (joystick_port[dev] > 0)
- acard->res_joystick = request_region(joystick_port[dev], 8, "ALS4000 gameport");
- if (acard->res_joystick)
- joystick = joystick_port[dev];
- else
- joystick = 0;
-#endif
- snd_als4000_set_addr(gcr, 0, 0, 0, joystick);
-
+ /* disable all legacy ISA stuff */
+ snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0);
+
if ((err = snd_sbdsp_create(card,
gcr + 0x10,
pci->irq,
@@ -711,12 +751,7 @@
}
}

-#ifdef SUPPORT_JOYSTICK
- if (acard->res_joystick) {
- acard->gameport.io = joystick;
- gameport_register_port(&acard->gameport);
- }
-#endif
+ snd_als4000_create_gameport(acard, dev);

if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff -Nru a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
--- a/sound/pci/au88x0/au88x0.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/au88x0/au88x0.c 2005-02-11 01:39:33 -05:00
@@ -290,10 +290,9 @@
snd_card_free(card);
return err;
}
- if ((err = vortex_gameport_register(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
+
+ vortex_gameport_register(chip);
+
#if 0
if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH,
sizeof(snd_vortex_synth_arg_t), &wave) < 0
diff -Nru a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
--- a/sound/pci/au88x0/au88x0.h 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/au88x0/au88x0.h 2005-02-11 01:39:33 -05:00
@@ -272,7 +272,7 @@

/* Driver stuff. */
static int __devinit vortex_gameport_register(vortex_t * card);
-static int __devexit vortex_gameport_unregister(vortex_t * card);
+static void vortex_gameport_unregister(vortex_t * card);
#ifndef CHIP_AU8820
static int __devinit vortex_eq_init(vortex_t * vortex);
static int __devexit vortex_eq_free(vortex_t * vortex);
diff -Nru a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
--- a/sound/pci/au88x0/au88x0_game.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/au88x0/au88x0_game.c 2005-02-11 01:39:33 -05:00
@@ -94,39 +94,42 @@
return 0;
}

-static int vortex_gameport_register(vortex_t * vortex)
+static int __devinit vortex_gameport_register(vortex_t * vortex)
{
- if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL)
- return -1;
+ struct gameport *gp;

- vortex->gameport->port_data = vortex;
- vortex->gameport->fuzz = 64;
+ vortex->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "vortex: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ };
+
+ gameport_set_name(gp, "AU88x0 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev));
+ gp->dev.parent = &vortex->pci_dev->dev;
+
+ gp->read = vortex_game_read;
+ gp->trigger = vortex_game_trigger;
+ gp->cooked_read = vortex_game_cooked_read;
+ gp->open = vortex_game_open;
+
+ gp->port_data = vortex;
+ gp->fuzz = 64;
+
+ gameport_register_port(gp);

- vortex->gameport->read = vortex_game_read;
- vortex->gameport->trigger = vortex_game_trigger;
- vortex->gameport->cooked_read = vortex_game_cooked_read;
- vortex->gameport->open = vortex_game_open;
-
- gameport_register_port((struct gameport *)vortex->gameport);
-
-/* printk(KERN_INFO "gameport%d: %s at speed %d kHz\n",
- vortex->gameport->number, vortex->pci_dev->name, vortex->gameport->speed);
-*/
return 0;
}

-static int vortex_gameport_unregister(vortex_t * vortex)
+static void vortex_gameport_unregister(vortex_t * vortex)
{
- if (vortex->gameport != NULL) {
+ if (vortex->gameport) {
gameport_unregister_port(vortex->gameport);
- kfree(vortex->gameport);
+ vortex->gameport = NULL;
}
- return 0;
}

#else
-
-static inline int vortex_gameport_register(vortex_t * vortex) { return 0; }
-static inline int vortex_gameport_unregister(vortex_t * vortex) { return 0; }
-
+static inline int vortex_gameport_register(vortex_t * vortex) { return -ENOSYS; }
+static inline void vortex_gameport_unregister(vortex_t * vortex) { }
#endif
diff -Nru a/sound/pci/azt3328.c b/sound/pci/azt3328.c
--- a/sound/pci/azt3328.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/azt3328.c 2005-02-11 01:39:33 -05:00
@@ -160,19 +160,19 @@
#endif

static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-#ifdef SUPPORT_JOYSTICK
-static int joystick[SNDRV_CARDS];
-#endif
-
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard.");
+
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard.");
+
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
+
#ifdef SUPPORT_JOYSTICK
+static int joystick[SNDRV_CARDS];
module_param_array(joystick, bool, NULL, 0444);
MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard.");
#endif
@@ -189,8 +189,7 @@
unsigned long mixer_port;

#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif

struct pci_dev *pci;
@@ -1222,6 +1221,63 @@

/******************************************************************/

+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev)
+{
+ struct gameport *gp;
+ struct resource *r;
+
+ if (!joystick[dev])
+ return -ENODEV;
+
+ if (!(r = request_region(0x200, 8, "AZF3328 gameport"))) {
+ printk(KERN_WARNING "azt3328: cannot reserve joystick ports\n");
+ return -EBUSY;
+ }
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "azt3328: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "AZF3328 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+ gp->io = 0x200;
+ gp->port_data = r;
+
+ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+ snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY);
+
+ gameport_register_port(chip->gameport);
+
+ return 0;
+}
+
+static void snd_azf3328_free_joystick(azf3328_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = chip->gameport->port_data;
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ /* disable gameport */
+ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+ snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; }
+static inline void snd_azf3328_free_joystick(azf3328_t *chip) { }
+#endif
+
+/******************************************************************/
+
static int snd_azf3328_free(azf3328_t *chip)
{
if (chip->irq < 0)
@@ -1236,16 +1292,7 @@

synchronize_irq(chip->irq);
__end_hw:
-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick) {
- gameport_unregister_port(&chip->gameport);
- /* disable gameport */
- snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
- snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
- release_resource(chip->res_joystick);
- kfree_nocheck(chip->res_joystick);
- }
-#endif
+ snd_azf3328_free_joystick(chip);
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
pci_release_regions(chip->pci);
@@ -1373,28 +1420,6 @@
return 0;
}

-#ifdef SUPPORT_JOYSTICK
-static void __devinit snd_azf3328_config_joystick(azf3328_t *chip, int joystick)
-{
- unsigned char val;
-
- if (joystick == 1) {
- if ((chip->res_joystick = request_region(0x200, 8, "AZF3328 gameport")) != NULL)
- chip->gameport.io = 0x200;
- }
-
- val = inb(chip->io2_port + IDX_IO2_LEGACY_ADDR);
- if (chip->res_joystick)
- val |= LEGACY_JOY;
- else
- val &= ~LEGACY_JOY;
-
- outb(val, chip->io2_port + IDX_IO2_LEGACY_ADDR);
- if (chip->res_joystick)
- gameport_register_port(&chip->gameport);
-}
-#endif
-
static int __devinit snd_azf3328_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -1465,9 +1490,9 @@
"azt3328: Feel free to contact [email protected] for bug reports etc.!\n");
#endif

-#ifdef SUPPORT_JOYSTICK
- snd_azf3328_config_joystick(chip, joystick[dev]);
-#endif
+ if (snd_azf3328_config_joystick(chip, dev) < 0)
+ snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+ snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);

pci_set_drvdata(pci, card);
dev++;
diff -Nru a/sound/pci/cmipci.c b/sound/pci/cmipci.c
--- a/sound/pci/cmipci.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/cmipci.c 2005-02-11 01:39:33 -05:00
@@ -471,8 +471,7 @@
snd_rawmidi_t *rmidi;

#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif

spinlock_t reg_lock;
@@ -2522,6 +2521,71 @@
strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC");
}

+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev)
+{
+ static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
+ struct gameport *gp;
+ struct resource *r = NULL;
+ int i, io_port = 0;
+
+ if (joystick_port[dev] == 0)
+ return -ENODEV;
+
+ if (joystick_port[dev] == 1) { /* auto-detect */
+ for (i = 0; ports[i]; i++) {
+ io_port = ports[i];
+ r = request_region(io_port, 1, "CMIPCI gameport");
+ if (r)
+ break;
+ }
+ } else {
+ io_port = joystick_port[dev];
+ r = request_region(io_port, 1, "CMIPCI gameport");
+ }
+
+ if (!r) {
+ printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n");
+ return -EBUSY;
+ }
+
+ cm->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+ gameport_set_name(gp, "C-Media Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci));
+ gp->dev.parent = &cm->pci->dev;
+ gp->io = io_port;
+ gp->port_data = r;
+
+ snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
+
+ gameport_register_port(cm->gameport);
+
+ return 0;
+}
+
+static void snd_cmipci_free_gameport(cmipci_t *cm)
+{
+ if (cm->gameport) {
+ struct resource *r = cm->gameport->port_data;
+
+ gameport_unregister_port(cm->gameport);
+ cm->gameport = NULL;
+
+ snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snd_cmipci_create_gameport(cmipci_t *cm, int dev) { return -ENOSYS; }
+static inline void snd_cmipci_free_gameport(cmipci_t *cm) { }
+#endif

static int snd_cmipci_free(cmipci_t *cm)
{
@@ -2541,14 +2605,8 @@

free_irq(cm->irq, (void *)cm);
}
-#ifdef SUPPORT_JOYSTICK
- if (cm->res_joystick) {
- gameport_unregister_port(&cm->gameport);
- snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- release_resource(cm->res_joystick);
- kfree_nocheck(cm->res_joystick);
- }
-#endif
+
+ snd_cmipci_free_gameport(cm);
pci_release_regions(cm->pci);
pci_disable_device(cm->pci);
kfree(cm);
@@ -2757,31 +2815,9 @@
snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K|CM_SPDF_AC97);
#endif /* USE_VAR48KRATE */

-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] > 0) {
- if (joystick_port[dev] == 1) { /* auto-detect */
- static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
- int i;
- for (i = 0; ports[i]; i++) {
- joystick_port[dev] = ports[i];
- cm->res_joystick = request_region(ports[i], 1, "CMIPCI gameport");
- if (cm->res_joystick)
- break;
- }
- } else {
- cm->res_joystick = request_region(joystick_port[dev], 1, "CMIPCI gameport");
- }
- }
- if (cm->res_joystick) {
- cm->gameport.io = joystick_port[dev];
- snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- gameport_register_port(&cm->gameport);
- } else {
- if (joystick_port[dev] > 0)
- printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n");
+ if (snd_cmipci_create_gameport(cm, dev) < 0)
snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
- }
-#endif
+
snd_card_set_dev(card, &pci->dev);

*rcmipci = cm;
diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c
--- a/sound/pci/cs4281.c 2005-02-11 01:39:34 -05:00
+++ b/sound/pci/cs4281.c 2005-02-11 01:39:34 -05:00
@@ -495,7 +495,7 @@
unsigned int midcr;
unsigned int uartm;

- struct snd_cs4281_gameport *gameport;
+ struct gameport *gameport;

#ifdef CONFIG_PM
u32 suspend_regs[SUSPEND_REGISTERS];
@@ -1238,38 +1238,29 @@

#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))

-typedef struct snd_cs4281_gameport {
- struct gameport info;
- cs4281_t *chip;
-} cs4281_gameport_t;
-
static void snd_cs4281_gameport_trigger(struct gameport *gameport)
{
- cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
- cs4281_t *chip;
- snd_assert(gp, return);
- chip = gp->chip;
+ cs4281_t *chip = gameport->port_data;
+
+ snd_assert(chip, return);
snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
}

static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
{
- cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
- cs4281_t *chip;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ cs4281_t *chip = gameport->port_data;
+
+ snd_assert(chip, return 0);
return snd_cs4281_peekBA0(chip, BA0_JSPT);
}

#ifdef COOKED_MODE
static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
- cs4281_t *chip;
+ cs4281_t *chip = gameport->port_data;
unsigned js1, js2, jst;

- snd_assert(gp, return 0);
- chip = gp->chip;
+ snd_assert(chip, return 0);

js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
@@ -1282,10 +1273,12 @@
axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;

- for(jst=0;jst<4;++jst)
- if(axes[jst]==0xFFFF) axes[jst] = -1;
+ for (jst = 0; jst < 4; ++jst)
+ if (axes[jst] == 0xFFFF) axes[jst] = -1;
return 0;
}
+#else
+#define snd_cs4281_gameport_cooked_read NULL
#endif

static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
@@ -1303,31 +1296,43 @@
return 0;
}

-static void __devinit snd_cs4281_gameport(cs4281_t *chip)
+static int __devinit snd_cs4281_create_gameport(cs4281_t *chip)
{
- cs4281_gameport_t *gp;
- gp = kmalloc(sizeof(*gp), GFP_KERNEL);
- if (! gp) {
- snd_printk(KERN_ERR "cannot allocate gameport area\n");
- return;
- }
- memset(gp, 0, sizeof(*gp));
- gp->info.open = snd_cs4281_gameport_open;
- gp->info.read = snd_cs4281_gameport_read;
- gp->info.trigger = snd_cs4281_gameport_trigger;
-#ifdef COOKED_MODE
- gp->info.cooked_read = snd_cs4281_gameport_cooked_read;
-#endif
- gp->chip = chip;
- chip->gameport = gp;
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "cs4281: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "CS4281 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+ gp->open = snd_cs4281_gameport_open;
+ gp->read = snd_cs4281_gameport_read;
+ gp->trigger = snd_cs4281_gameport_trigger;
+ gp->cooked_read = snd_cs4281_gameport_cooked_read;
+ gp->port_data = chip;

snd_cs4281_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
snd_cs4281_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
- gameport_register_port(&gp->info);
+
+ gameport_register_port(gp);
+
+ return 0;
}

+static void snd_cs4281_free_gameport(cs4281_t *chip)
+{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
+}
#else
-#define snd_cs4281_gameport(chip) /*NOP*/
+static inline int snd_cs4281_gameport(cs4281_t *chip) { return -ENOSYS; }
+static inline void snd_cs4281_gameport_free(cs4281_t *chip) { }
#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */


@@ -1337,12 +1342,8 @@

static int snd_cs4281_free(cs4281_t *chip)
{
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (chip->gameport) {
- gameport_unregister_port(&chip->gameport->info);
- kfree(chip->gameport);
- }
-#endif
+ snd_cs4281_free_gameport(chip);
+
if (chip->irq >= 0)
synchronize_irq(chip->irq);

@@ -1990,7 +1991,7 @@
snd_card_free(card);
return err;
}
- snd_cs4281_gameport(chip);
+ snd_cs4281_create_gameport(chip);
strcpy(card->driver, "CS4281");
strcpy(card->shortname, "Cirrus Logic CS4281");
sprintf(card->longname, "%s at 0x%lx, irq %d",
diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
--- a/sound/pci/cs46xx/cs46xx_lib.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/cs46xx/cs46xx_lib.c 2005-02-11 01:39:33 -05:00
@@ -2690,37 +2690,28 @@

#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))

-typedef struct snd_cs46xx_gameport {
- struct gameport info;
- cs46xx_t *chip;
-} cs46xx_gameport_t;
-
static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
{
- cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
- cs46xx_t *chip;
- snd_assert(gp, return);
- chip = gp->chip;
+ cs46xx_t *chip = gameport->port_data;
+
+ snd_assert(chip, return);
snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF);
}

static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
{
- cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
- cs46xx_t *chip;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ cs46xx_t *chip = gameport->port_data;
+
+ snd_assert(chip, return 0);
return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
}

static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
- cs46xx_t *chip;
+ cs46xx_t *chip = gameport->port_data;
unsigned js1, js2, jst;
-
- snd_assert(gp, return 0);
- chip = gp->chip;
+
+ snd_assert(chip, return 0);

js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
@@ -2751,33 +2742,44 @@
return 0;
}

-void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
+int __devinit snd_cs46xx_gameport(cs46xx_t *chip)
{
- cs46xx_gameport_t *gp;
- gp = kmalloc(sizeof(*gp), GFP_KERNEL);
- if (! gp) {
- snd_printk("cannot allocate gameport area\n");
- return;
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n");
+ return -ENOMEM;
}
- memset(gp, 0, sizeof(*gp));
- gp->info.open = snd_cs46xx_gameport_open;
- gp->info.read = snd_cs46xx_gameport_read;
- gp->info.trigger = snd_cs46xx_gameport_trigger;
- gp->info.cooked_read = snd_cs46xx_gameport_cooked_read;
- gp->chip = chip;
- chip->gameport = gp;
+
+ gameport_set_name(gp, "CS46xx Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+ gp->port_data = chip;
+
+ gp->open = snd_cs46xx_gameport_open;
+ gp->read = snd_cs46xx_gameport_read;
+ gp->trigger = snd_cs46xx_gameport_trigger;
+ gp->cooked_read = snd_cs46xx_gameport_cooked_read;

snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
- gameport_register_port(&gp->info);
-}

-#else
+ gameport_register_port(gp);

-void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
-{
+ return 0;
}

+static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip)
+{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
+}
+#else
+int __devinit snd_cs46xx_gameport(cs46xx_t *chip) { return -ENOSYS; }
+static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip) { }
#endif /* CONFIG_GAMEPORT */

/*
@@ -2893,12 +2895,7 @@
if (chip->active_ctrl)
chip->active_ctrl(chip, 1);

-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (chip->gameport) {
- gameport_unregister_port(&chip->gameport->info);
- kfree(chip->gameport);
- }
-#endif
+ snd_cs46xx_remove_gameport(chip);

if (chip->amplifier_ctrl)
chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c
--- a/sound/pci/ens1370.c 2005-02-11 01:39:34 -05:00
+++ b/sound/pci/ens1370.c 2005-02-11 01:39:34 -05:00
@@ -430,7 +430,7 @@
#endif

#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
+ struct gameport *gameport;
#endif
};

@@ -1734,43 +1734,99 @@
#endif /* CHIP1370 */

#ifdef SUPPORT_JOYSTICK
-static int snd_ensoniq_joystick(ensoniq_t *ensoniq, long port)
-{
+
#ifdef CHIP1371
- if (port == 1) { /* auto-detect */
- for (port = 0x200; port <= 0x218; port += 8)
- if (request_region(port, 8, "ens137x: gameport"))
+static int __devinit snd_ensoniq_get_joystick_port(int dev)
+{
+ switch (joystick_port[dev]) {
+ case 0: /* disabled */
+ case 1: /* auto-detect */
+ case 0x200:
+ case 0x208:
+ case 0x210:
+ case 0x218:
+ return joystick_port[dev];
+
+ default:
+ printk(KERN_ERR "ens1371: invalid joystick port %#x", joystick_port[dev]);
+ return 0;
+ }
+}
+#else
+static inline int snd_ensoniq_get_joystick_port(int dev)
+{
+ return joystick[dev] ? 0x200 : 0;
+}
+#endif
+
+static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev)
+{
+ struct gameport *gp;
+ int io_port;
+
+ io_port = snd_ensoniq_get_joystick_port(dev);
+
+ switch (io_port) {
+ case 0:
+ return -ENOSYS;
+
+ case 1: /* auto_detect */
+ for (io_port = 0x200; io_port <= 0x218; io_port += 8)
+ if (request_region(io_port, 8, "ens137x: gameport"))
break;
- if (port > 0x218) {
- snd_printk("no gameport available\n");
+ if (io_port > 0x218) {
+ printk(KERN_WARNING "ens137x: no gameport ports available\n");
return -EBUSY;
}
- } else
-#endif
- {
- if (!request_region(port, 8, "ens137x: gameport")) {
- snd_printk("gameport io port 0x%03x in use", ensoniq->gameport.io);
+ break;
+
+ default:
+ if (!request_region(io_port, 8, "ens137x: gameport")) {
+ printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", io_port);
return -EBUSY;
}
+ break;
}
- ensoniq->gameport.io = port;
+
+ ensoniq->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "ens137x: cannot allocate memory for gameport\n");
+ release_region(io_port, 8);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ES137x");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(ensoniq->pci));
+ gp->dev.parent = &ensoniq->pci->dev;
+ gp->io = io_port;
+
ensoniq->ctrl |= ES_JYSTK_EN;
#ifdef CHIP1371
ensoniq->ctrl &= ~ES_1371_JOY_ASELM;
- ensoniq->ctrl |= ES_1371_JOY_ASEL((ensoniq->gameport.io - 0x200) / 8);
+ ensoniq->ctrl |= ES_1371_JOY_ASEL((io_port - 0x200) / 8);
#endif
outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- gameport_register_port(&ensoniq->gameport);
+
+ gameport_register_port(ensoniq->gameport);
+
return 0;
}

-static void snd_ensoniq_joystick_free(ensoniq_t *ensoniq)
+static void snd_ensoniq_free_gameport(ensoniq_t *ensoniq)
{
- gameport_unregister_port(&ensoniq->gameport);
- ensoniq->ctrl &= ~ES_JYSTK_EN;
- outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
- release_region(ensoniq->gameport.io, 8);
+ if (ensoniq->gameport) {
+ int port = ensoniq->gameport->io;
+
+ gameport_unregister_port(ensoniq->gameport);
+ ensoniq->gameport = NULL;
+ ensoniq->ctrl &= ~ES_JYSTK_EN;
+ outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+ release_region(port, 8);
+ }
}
+#else
+static inline int snd_ensoniq_create_gameport(ensoniq_t *ensoniq, long port) { return -ENOSYS; }
+static inline void snd_ensoniq_free_gameport(ensoniq_t *ensoniq) { }
#endif /* SUPPORT_JOYSTICK */

/*
@@ -1810,10 +1866,7 @@

static int snd_ensoniq_free(ensoniq_t *ensoniq)
{
-#ifdef SUPPORT_JOYSTICK
- if (ensoniq->ctrl & ES_JYSTK_EN)
- snd_ensoniq_joystick_free(ensoniq);
-#endif
+ snd_ensoniq_free_gameport(ensoniq);
if (ensoniq->irq < 0)
goto __hw_end;
#ifdef CHIP1370
@@ -2313,22 +2366,9 @@
snd_card_free(card);
return err;
}
-#ifdef SUPPORT_JOYSTICK
-#ifdef CHIP1371
- switch (joystick_port[dev]) {
- case 1: /* auto-detect */
- case 0x200:
- case 0x208:
- case 0x210:
- case 0x218:
- snd_ensoniq_joystick(ensoniq, joystick_port[dev]);
- break;
- }
-#else
- if (joystick[dev])
- snd_ensoniq_joystick(ensoniq, 0x200);
-#endif
-#endif /* SUPPORT_JOYSTICK */
+
+ snd_ensoniq_create_gameport(ensoniq, dev);
+
strcpy(card->driver, DRIVER_NAME);

strcpy(card->shortname, "Ensoniq AudioPCI");
diff -Nru a/sound/pci/es1938.c b/sound/pci/es1938.c
--- a/sound/pci/es1938.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/es1938.c 2005-02-11 01:39:33 -05:00
@@ -72,6 +72,10 @@
"{ESS,ES1969},"
"{TerraTec,128i PCI}}");

+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
#ifndef PCI_VENDOR_ID_ESS
#define PCI_VENDOR_ID_ESS 0x125d
#endif
@@ -237,8 +241,8 @@
spinlock_t mixer_lock;
snd_info_entry_t *proc_entry;

-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
#endif
#ifdef CONFIG_PM
unsigned char saved_regs[SAVED_REG_SIZE];
@@ -1418,6 +1422,39 @@
}
#endif /* CONFIG_PM */

+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_es1938_create_gameport(es1938_t *chip)
+{
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "es1938: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "ES1938");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+ gp->io = chip->game_port;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static void snd_es1938_free_gameport(es1938_t *chip)
+{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
+}
+#else
+static inline int snd_es1938_create_gameport(es1938_t *chip) { return -ENOSYS; }
+static inline void snd_es1938_free_gameport(es1938_t *chip) { }
+#endif /* SUPPORT_JOYSTICK */
+
static int snd_es1938_free(es1938_t *chip)
{
/* disable irqs */
@@ -1425,10 +1462,8 @@
if (chip->rmidi)
snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0);

-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (chip->gameport.io)
- gameport_unregister_port(&chip->gameport);
-#endif
+ snd_es1938_free_gameport(chip);
+
if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
pci_release_regions(chip->pci);
@@ -1698,10 +1733,7 @@
snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0x40);
}

-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- chip->gameport.io = chip->game_port;
- gameport_register_port(&chip->gameport);
-#endif
+ snd_es1938_create_gameport(chip);

if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff -Nru a/sound/pci/es1968.c b/sound/pci/es1968.c
--- a/sound/pci/es1968.c 2005-02-11 01:39:34 -05:00
+++ b/sound/pci/es1968.c 2005-02-11 01:39:34 -05:00
@@ -605,8 +605,7 @@
#endif

#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
};

@@ -2450,6 +2449,59 @@
}
#endif /* CONFIG_PM */

+#ifdef SUPPORT_JOYSTICK
+#define JOYSTICK_ADDR 0x200
+static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev)
+{
+ struct gameport *gp;
+ struct resource *r;
+ u16 val;
+
+ if (!joystick[dev])
+ return -ENODEV;
+
+ r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport");
+ if (!r)
+ return -EBUSY;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "es1968: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ pci_read_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, &val);
+ pci_write_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04);
+
+ gameport_set_name(gp, "ES1968 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+ gp->io = JOYSTICK_ADDR;
+
+ gameport_register_port(gp);
+
+ return 0;
+}
+
+static void snd_es1968_free_gameport(es1968_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = chip->gameport->port_data;
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snd_es1968_create_gameport(es1968_t *chip, int dev) { return -ENOSYS; }
+static inline void snd_es1968_free_gameport(es1968_t *chip) { }
+#endif
+
static int snd_es1968_free(es1968_t *chip)
{
if (chip->io_port) {
@@ -2460,13 +2512,7 @@

if (chip->irq >= 0)
free_irq(chip->irq, (void *)chip);
-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick) {
- gameport_unregister_port(&chip->gameport);
- release_resource(chip->res_joystick);
- kfree_nocheck(chip->res_joystick);
- }
-#endif
+ snd_es1968_free_gameport(chip);
snd_es1968_set_acpi(chip, ACPI_D3);
chip->master_switch = NULL;
chip->master_volume = NULL;
@@ -2693,17 +2739,7 @@
}
}

-#ifdef SUPPORT_JOYSTICK
-#define JOYSTICK_ADDR 0x200
- if (joystick[dev] &&
- (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport")) != NULL) {
- u16 val;
- pci_read_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, &val);
- pci_write_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04);
- chip->gameport.io = JOYSTICK_ADDR;
- gameport_register_port(&chip->gameport);
- }
-#endif
+ snd_es1968_create_gameport(chip, dev);

snd_es1968_start_irq(chip);

diff -Nru a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
--- a/sound/pci/sonicvibes.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/sonicvibes.c 2005-02-11 01:39:33 -05:00
@@ -46,6 +46,10 @@
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");

+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
#ifndef PCI_VENDOR_ID_S3
#define PCI_VENDOR_ID_S3 0x5333
#endif
@@ -242,8 +246,8 @@
snd_kcontrol_t *master_mute;
snd_kcontrol_t *master_volume;

-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+ struct gameport *gameport;
#endif
};

@@ -1163,15 +1167,47 @@

*/

+#ifdef SUPPORT_JOYSTICK
static snd_kcontrol_new_t snd_sonicvibes_game_control __devinitdata =
SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);

-static int snd_sonicvibes_free(sonicvibes_t *sonic)
+static int __devinit snd_sonicvibes_create_gameport(sonicvibes_t *sonic)
{
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (sonic->gameport.io)
- gameport_unregister_port(&sonic->gameport);
+ struct gameport *gp;
+
+ sonic->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "SonicVibes Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci));
+ gp->dev.parent = &sonic->pci->dev;
+ gp->io = sonic->game_port;
+
+ gameport_register_port(gp);
+
+ snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
+
+ return 0;
+}
+
+static void snd_sonicvibes_free_gameport(sonicvibes_t *sonic)
+{
+ if (sonic->gameport) {
+ gameport_unregister_port(sonic->gameport);
+ sonic->gameport = NULL;
+ }
+}
+#else
+static inline int snd_sonicvibes_create_gameport(sonicvibes_t *sonic) { return -ENOSYS; }
+static inline void snd_sonicvibes_free_gameport(sonicvibes_t *sonic) { }
#endif
+
+static int snd_sonicvibes_free(sonicvibes_t *sonic)
+{
+ snd_sonicvibes_free_gameport(sonic);
pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
if (sonic->irq >= 0)
@@ -1332,7 +1368,6 @@
snd_sonicvibes_debug(sonic);
#endif
sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
- snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));

if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) {
snd_sonicvibes_free(sonic);
@@ -1459,10 +1494,8 @@
snd_card_free(card);
return err;
}
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- sonic->gameport.io = sonic->game_port;
- gameport_register_port(&sonic->gameport);
-#endif
+
+ snd_sonicvibes_create_gameport(sonic);

if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff -Nru a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
--- a/sound/pci/trident/trident.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/trident/trident.c 2005-02-11 01:39:33 -05:00
@@ -157,7 +157,7 @@
}
#endif

- snd_trident_gameport(trident);
+ snd_trident_create_gameport(trident);

if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff -Nru a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
--- a/sound/pci/trident/trident_main.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/trident/trident_main.c 2005-02-11 01:39:33 -05:00
@@ -3110,37 +3110,28 @@

#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))

-typedef struct snd_trident_gameport {
- struct gameport info;
- trident_t *chip;
-} trident_gameport_t;
-
static unsigned char snd_trident_gameport_read(struct gameport *gameport)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
- snd_assert(gp, return 0);
- chip = gp->chip;
+ trident_t *chip = gameport->port_data;
+
+ snd_assert(chip, return 0);
return inb(TRID_REG(chip, GAMEPORT_LEGACY));
}

static void snd_trident_gameport_trigger(struct gameport *gameport)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
- snd_assert(gp, return);
- chip = gp->chip;
+ trident_t *chip = gameport->port_data;
+
+ snd_assert(chip, return 0);
outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
}

static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
+ trident_t *chip = gameport->port_data;
int i;

- snd_assert(gp, return 0);
- chip = gp->chip;
+ snd_assert(chip, return 0);

*buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;

@@ -3154,10 +3145,9 @@

static int snd_trident_gameport_open(struct gameport *gameport, int mode)
{
- trident_gameport_t *gp = (trident_gameport_t *)gameport;
- trident_t *chip;
- snd_assert(gp, return -1);
- chip = gp->chip;
+ trident_t *chip = gameport->port_data;
+
+ snd_assert(chip, return 0);

switch (mode) {
case GAMEPORT_MODE_COOKED:
@@ -3173,30 +3163,42 @@
}
}

-void __devinit snd_trident_gameport(trident_t *chip)
+int __devinit snd_trident_create_gameport(trident_t *chip)
{
- trident_gameport_t *gp;
- gp = kmalloc(sizeof(*gp), GFP_KERNEL);
- if (! gp) {
- snd_printk("cannot allocate gameport area\n");
- return;
- }
- memset(gp, 0, sizeof(*gp));
- gp->chip = chip;
- gp->info.fuzz = 64;
- gp->info.read = snd_trident_gameport_read;
- gp->info.trigger = snd_trident_gameport_trigger;
- gp->info.cooked_read = snd_trident_gameport_cooked_read;
- gp->info.open = snd_trident_gameport_open;
- chip->gameport = gp;
+ struct gameport *gp;
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "trident: cannot allocate memory for gameport\n");
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "Trident 4DWave");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+
+ gp->port_data = chip;
+ gp->fuzz = 64;
+ gp->read = snd_trident_gameport_read;
+ gp->trigger = snd_trident_gameport_trigger;
+ gp->cooked_read = snd_trident_gameport_cooked_read;
+ gp->open = snd_trident_gameport_open;

- gameport_register_port(&gp->info);
+ gameport_register_port(gp);
+
+ return 0;
}

-#else
-void __devinit snd_trident_gameport(trident_t *chip)
+static inline void snd_trident_free_gameport(trident_t *chip)
{
+ if (chip->gameport) {
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ }
}
+#else
+int __devinit snd_trident_create_gameport(trident_t *chip) { return -ENOSYS; }
+static inline void snd_trident_free_gameport(trident_t *chip) { }
#endif /* CONFIG_GAMEPORT */

/*
@@ -3661,12 +3663,7 @@

static int snd_trident_free(trident_t *trident)
{
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
- if (trident->gameport) {
- gameport_unregister_port(&trident->gameport->info);
- kfree(trident->gameport);
- }
-#endif
+ snd_trident_free_gameport(trident);
snd_trident_disable_eso(trident);
// Disable S/PDIF out
if (trident->device == TRIDENT_DEVICE_ID_NX)
diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c
--- a/sound/pci/via82xx.c 2005-02-11 01:39:34 -05:00
+++ b/sound/pci/via82xx.c 2005-02-11 01:39:34 -05:00
@@ -394,8 +394,7 @@
snd_info_entry_t *proc_entry;

#ifdef SUPPORT_JOYSTICK
- struct gameport gameport;
- struct resource *res_joystick;
+ struct gameport *gameport;
#endif
};

@@ -1635,11 +1634,70 @@
return 0;
}

+#ifdef SUPPORT_JOYSTICK
+#define JOYSTICK_ADDR 0x200
+static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy)
+{
+ struct gameport *gp;
+ struct resource *r;
+
+ if (!joystick[dev])
+ return -ENODEV;
+
+ r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");
+ if (!r) {
+ printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n", JOYSTICK_ADDR);
+ return -EBUSY;
+ }
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+ gameport_set_name(gp, "VIA686 Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+ gp->io = JOYSTICK_ADDR;
+ gp->port_data = r;
+
+ /* Enable legacy joystick port */
+ *legacy |= VIA_FUNC_ENABLE_GAME;
+ pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, *legacy);
+
+ gameport_register_port(chip->gameport);
+
+ return 0;
+}
+
+static void snd_via686_free_gameport(via82xx_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = chip->gameport->port_data;
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy)
+{
+ return -ENOSYS;
+}
+static inline void snd_via686_free_gameport(via82xx_t *chip) { }
+#endif
+
+
/*
*
*/

-static int snd_via8233_init_misc(via82xx_t *chip, int dev)
+static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev)
{
int i, err, caps;
unsigned char val;
@@ -1671,7 +1729,7 @@
return 0;
}

-static int snd_via686_init_misc(via82xx_t *chip, int dev)
+static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev)
{
unsigned char legacy, legacy_cfg;
int rev_h = 0;
@@ -1718,15 +1776,6 @@
mpu_port[dev] = 0;
}

-#ifdef SUPPORT_JOYSTICK
-#define JOYSTICK_ADDR 0x200
- if (joystick[dev] &&
- (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport")) != NULL) {
- legacy |= VIA_FUNC_ENABLE_GAME;
- chip->gameport.io = JOYSTICK_ADDR;
- }
-#endif
-
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);
pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);
if (chip->mpu_res) {
@@ -1741,10 +1790,7 @@
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);
}

-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick)
- gameport_register_port(&chip->gameport);
-#endif
+ snd_via686_create_gameport(chip, dev, &legacy);

#ifdef CONFIG_PM
chip->legacy_saved = legacy;
@@ -1973,14 +2019,9 @@
kfree_nocheck(chip->mpu_res);
}
pci_release_regions(chip->pci);
+
if (chip->chip_type == TYPE_VIA686) {
-#ifdef SUPPORT_JOYSTICK
- if (chip->res_joystick) {
- gameport_unregister_port(&chip->gameport);
- release_resource(chip->res_joystick);
- kfree_nocheck(chip->res_joystick);
- }
-#endif
+ snd_via686_free_gameport(chip);
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
}
diff -Nru a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
--- a/sound/pci/ymfpci/ymfpci.c 2005-02-11 01:39:33 -05:00
+++ b/sound/pci/ymfpci/ymfpci.c 2005-02-11 01:39:33 -05:00
@@ -79,6 +79,96 @@

MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);

+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev,
+ int legacy_ctrl, int legacy_ctrl2)
+{
+ struct gameport *gp;
+ struct resource *r = NULL;
+ int io_port = joystick_port[dev];
+
+ if (!io_port)
+ return -ENODEV;
+
+ if (chip->pci->device >= 0x0010) { /* YMF 744/754 */
+
+ if (io_port == 1) {
+ /* auto-detect */
+ if (!(io_port = pci_resource_start(chip->pci, 2)))
+ return -ENODEV;
+ }
+ } else {
+ if (io_port == 1) {
+ /* auto-detect */
+ for (io_port = 0x201; io_port <= 0x205; io_port++) {
+ if (io_port == 0x203)
+ continue;
+ if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL)
+ break;
+ }
+ if (!r) {
+ printk(KERN_ERR "ymfpci: no gameport ports available\n");
+ return -EBUSY;
+ }
+ }
+ switch (io_port) {
+ case 0x201: legacy_ctrl2 |= 0 << 6; break;
+ case 0x202: legacy_ctrl2 |= 1 << 6; break;
+ case 0x204: legacy_ctrl2 |= 2 << 6; break;
+ case 0x205: legacy_ctrl2 |= 3 << 6; break;
+ default:
+ printk(KERN_ERR "ymfpci: invalid joystick port %#x", io_port);
+ return -EINVAL;
+ }
+ }
+
+ if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) {
+ printk(KERN_ERR "ymfpci: joystick port %#x is in use.\n", io_port);
+ return -EBUSY;
+ }
+
+ chip->gameport = gp = gameport_allocate_port();
+ if (!gp) {
+ printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n");
+ release_resource(r);
+ kfree_nocheck(r);
+ return -ENOMEM;
+ }
+
+
+ gameport_set_name(gp, "Yamaha YMF Gameport");
+ gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+ gp->dev.parent = &chip->pci->dev;
+ gp->io = io_port;
+
+ if (chip->pci->device >= 0x0010) /* YMF 744/754 */
+ pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
+
+ pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN);
+ pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
+
+ gameport_register_port(chip->gameport);
+
+ return 0;
+}
+
+void snd_ymfpci_free_gameport(ymfpci_t *chip)
+{
+ if (chip->gameport) {
+ struct resource *r = chip->gameport->port_data;
+
+ gameport_unregister_port(chip->gameport);
+ chip->gameport = NULL;
+
+ release_resource(r);
+ kfree_nocheck(r);
+ }
+}
+#else
+static inline int snc_ymfpci_create_gameport(ymfpci_t *chip, int dev, int l, int l2) { return -ENOSYS; }
+void snd_ymfpci_free_gameport(ymfpci_t *chip) { }
+#endif /* SUPPORT_JOYSTICK */
+
static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
const struct pci_device_id *pci_id)
{
@@ -86,9 +176,6 @@
snd_card_t *card;
struct resource *fm_res = NULL;
struct resource *mpu_res = NULL;
-#ifdef SUPPORT_JOYSTICK
- struct resource *joystick_res = NULL;
-#endif
ymfpci_t *chip;
opl3_t *opl3;
char *str;
@@ -138,17 +225,6 @@
legacy_ctrl |= YMFPCI_LEGACY_MEN;
pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
}
-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] == 1) {
- /* auto-detect */
- joystick_port[dev] = pci_resource_start(pci, 2);
- }
- if (joystick_port[dev] > 0 &&
- (joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport")) != NULL) {
- legacy_ctrl |= YMFPCI_LEGACY_JPEN;
- pci_write_config_word(pci, PCIR_DSXG_JOYBASE, joystick_port[dev]);
- }
-#endif
} else {
switch (fm_port[dev]) {
case 0x388: legacy_ctrl2 |= 0; break;
@@ -178,34 +254,6 @@
legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO;
mpu_port[dev] = 0;
}
-#ifdef SUPPORT_JOYSTICK
- if (joystick_port[dev] == 1) {
- /* auto-detect */
- long p;
- for (p = 0x201; p <= 0x205; p++) {
- if (p == 0x203) continue;
- if ((joystick_res = request_region(p, 1, "YMFPCI gameport")) != NULL)
- break;
- }
- if (joystick_res)
- joystick_port[dev] = p;
- }
- switch (joystick_port[dev]) {
- case 0x201: legacy_ctrl2 |= 0 << 6; break;
- case 0x202: legacy_ctrl2 |= 1 << 6; break;
- case 0x204: legacy_ctrl2 |= 2 << 6; break;
- case 0x205: legacy_ctrl2 |= 3 << 6; break;
- default: joystick_port[dev] = 0; break;
- }
- if (! joystick_res && joystick_port[dev] > 0)
- joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport");
- if (joystick_res) {
- legacy_ctrl |= YMFPCI_LEGACY_JPEN;
- } else {
- legacy_ctrl2 &= ~YMFPCI_LEGACY2_JSIO;
- joystick_port[dev] = 0;
- }
-#endif
}
if (mpu_res) {
legacy_ctrl |= YMFPCI_LEGACY_MIEN;
@@ -226,19 +274,10 @@
release_resource(fm_res);
kfree_nocheck(fm_res);
}
-#ifdef SUPPORT_JOYSTICK
- if (joystick_res) {
- release_resource(joystick_res);
- kfree_nocheck(joystick_res);
- }
-#endif
return err;
}
chip->fm_res = fm_res;
chip->mpu_res = mpu_res;
-#ifdef SUPPORT_JOYSTICK
- chip->joystick_res = joystick_res;
-#endif
strcpy(card->driver, str);
sprintf(card->shortname, "Yamaha DS-XG (%s)", str);
sprintf(card->longname, "%s at 0x%lx, irq %i",
@@ -292,12 +331,8 @@
return err;
}
}
-#ifdef SUPPORT_JOYSTICK
- if (chip->joystick_res) {
- chip->gameport.io = joystick_port[dev];
- gameport_register_port(&chip->gameport);
- }
-#endif
+
+ snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2);

if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff -Nru a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
--- a/sound/pci/ymfpci/ymfpci_main.c 2005-02-11 01:39:34 -05:00
+++ b/sound/pci/ymfpci/ymfpci_main.c 2005-02-11 01:39:34 -05:00
@@ -2079,14 +2079,7 @@
release_resource(chip->fm_res);
kfree_nocheck(chip->fm_res);
}
-#ifdef SUPPORT_JOYSTICK
- if (chip->joystick_res) {
- if (chip->gameport.io)
- gameport_unregister_port(&chip->gameport);
- release_resource(chip->joystick_res);
- kfree_nocheck(chip->joystick_res);
- }
-#endif
+ snd_ymfpci_free_gameport(chip);
if (chip->reg_area_virt)
iounmap(chip->reg_area_virt);
if (chip->work_ptr.area)

2005-02-11 07:32:46

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 8/10] Gameport: add "gameport" sysfs bus, add drivers


===================================================================


[email protected], 2005-02-11 01:21:02-05:00, [email protected]
Input: integrate gameport drivers info dribver model/sysfs,
create "gameport" bus. drivers' connect() routines
now return error code instead of void.

Signed-off-by: Dmitry Torokhov <[email protected]>


drivers/Makefile | 2
drivers/input/gameport/gameport.c | 39 ++++++++++++++++++
drivers/input/joystick/a3d.c | 44 ++++++++++++++-------
drivers/input/joystick/adi.c | 63 ++++++++++++++----------------
drivers/input/joystick/analog.c | 52 +++++++++++++++---------
drivers/input/joystick/cobra.c | 42 ++++++++++++--------
drivers/input/joystick/gf2k.c | 42 +++++++++++++-------
drivers/input/joystick/grip.c | 61 +++++++++++++----------------
drivers/input/joystick/grip_mp.c | 56 +++++++++++++++++---------
drivers/input/joystick/guillemot.c | 53 ++++++++++++++-----------
drivers/input/joystick/interact.c | 32 +++++++++++----
drivers/input/joystick/joydump.c | 20 ++++++---
drivers/input/joystick/sidewinder.c | 75 +++++++++++++++++++++++++-----------
drivers/input/joystick/tmdc.c | 53 +++++++++++++------------
include/linux/gameport.h | 6 +-
15 files changed, 407 insertions(+), 233 deletions(-)


===================================================================



diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile 2005-02-11 01:40:01 -05:00
+++ b/drivers/Makefile 2005-02-11 01:40:01 -05:00
@@ -47,8 +47,8 @@
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_USB_GADGET) += usb/gadget/
-obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_GAMEPORT) += input/gameport/
+obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_W1) += w1/
diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- a/drivers/input/gameport/gameport.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/gameport/gameport.c 2005-02-11 01:40:01 -05:00
@@ -37,6 +37,10 @@
static LIST_HEAD(gameport_list);
static LIST_HEAD(gameport_driver_list);

+static struct bus_type gameport_bus = {
+ .name = "gameport",
+};
+
#ifdef __i386__

#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
@@ -146,6 +150,21 @@
gameport_find_driver(gameport);
}

+/*
+ * Gameport driver operations
+ */
+
+static ssize_t gameport_driver_show_description(struct device_driver *drv, char *buf)
+{
+ struct gameport_driver *driver = to_gameport_driver(drv);
+ return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
+}
+
+static struct driver_attribute gameport_driver_attrs[] = {
+ __ATTR(description, S_IRUGO, gameport_driver_show_description, NULL),
+ __ATTR_NULL
+};
+
void gameport_unregister_port(struct gameport *gameport)
{
list_del_init(&gameport->node);
@@ -159,6 +178,9 @@
{
struct gameport *gameport;

+ drv->driver.bus = &gameport_bus;
+ driver_register(&drv->driver);
+
list_add_tail(&drv->node, &gameport_driver_list);
list_for_each_entry(gameport, &gameport_list, node)
if (!gameport->drv)
@@ -175,6 +197,7 @@
drv->disconnect(gameport);
gameport_find_driver(gameport);
}
+ driver_unregister(&drv->driver);
}

int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
@@ -201,3 +224,19 @@
if (gameport->close)
gameport->close(gameport);
}
+
+static int __init gameport_init(void)
+{
+ gameport_bus.drv_attrs = gameport_driver_attrs;
+ bus_register(&gameport_bus);
+
+ return 0;
+}
+
+static void __exit gameport_exit(void)
+{
+ bus_unregister(&gameport_bus);
+}
+
+module_init(gameport_init);
+module_exit(gameport_exit);
diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
--- a/drivers/input/joystick/a3d.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/a3d.c 2005-02-11 01:40:01 -05:00
@@ -35,8 +35,10 @@
#include <linux/gameport.h>
#include <linux/input.h>

+#define DRIVER_DESC "FP-Gaming Assasin 3D joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("FP-Gaming Assasin 3D joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define A3D_MAX_START 400 /* 400 us */
@@ -108,7 +110,9 @@
static int a3d_csum(char *data, int count)
{
int i, csum = 0;
- for (i = 0; i < count - 2; i++) csum += data[i];
+
+ for (i = 0; i < count - 2; i++)
+ csum += data[i];
return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
}

@@ -138,7 +142,7 @@

a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;

- return;
+ break;

case A3D_MODE_PXL:

@@ -168,7 +172,7 @@

input_sync(dev);

- return;
+ break;
}
}

@@ -181,6 +185,7 @@
{
struct a3d *a3d = (void *) private;
unsigned char data[A3D_MAX_LENGTH];
+
a3d->reads++;
if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length
|| data[0] != a3d->mode || a3d_csum(data, a3d->length))
@@ -198,6 +203,7 @@
{
struct a3d *a3d = gameport->port_data;
int i;
+
for (i = 0; i < 4; i++)
axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
*buttons = a3d->buttons;
@@ -226,6 +232,7 @@
static void a3d_adc_close(struct gameport *gameport)
{
struct a3d *a3d = gameport->port_data;
+
if (!--a3d->used)
del_timer(&a3d->timer);
}
@@ -237,6 +244,7 @@
static int a3d_open(struct input_dev *dev)
{
struct a3d *a3d = dev->private;
+
if (!a3d->used++)
mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
return 0;
@@ -249,6 +257,7 @@
static void a3d_close(struct input_dev *dev)
{
struct a3d *a3d = dev->private;
+
if (!--a3d->used)
del_timer(&a3d->timer);
}
@@ -257,16 +266,16 @@
* a3d_connect() probes for A3D joysticks.
*/

-static void a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct a3d *a3d;
struct gameport *adc;
unsigned char data[A3D_MAX_LENGTH];
int i;
+ int err;

- if (!(a3d = kmalloc(sizeof(struct a3d), GFP_KERNEL)))
- return;
- memset(a3d, 0, sizeof(struct a3d));
+ if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = a3d;

@@ -275,19 +284,23 @@
a3d->timer.data = (long) a3d;
a3d->timer.function = a3d_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);

- if (!i || a3d_csum(data, i))
+ if (!i || a3d_csum(data, i)) {
+ err = -ENODEV;
goto fail2;
+ }

a3d->mode = data[0];

if (!a3d->mode || a3d->mode > 5) {
printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
"(%s, id=%d), contact <[email protected]>\n", gameport->phys, a3d->mode);
+ err = -ENODEV;
goto fail2;
}

@@ -363,10 +376,11 @@
input_register_device(&a3d->dev);
printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);

- return;
+ return 0;

fail2: gameport_close(gameport);
fail1: kfree(a3d);
+ return err;
}

static void a3d_disconnect(struct gameport *gameport)
@@ -383,8 +397,12 @@
}

static struct gameport_driver a3d_drv = {
- .connect = a3d_connect,
- .disconnect = a3d_disconnect,
+ .driver = {
+ .name = "adc",
+ },
+ .description = DRIVER_DESC,
+ .connect = a3d_connect,
+ .disconnect = a3d_disconnect,
};

static int __init a3d_init(void)
diff -Nru a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
--- a/drivers/input/joystick/adi.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/adi.c 2005-02-11 01:40:01 -05:00
@@ -37,8 +37,10 @@
#include <linux/gameport.h>
#include <linux/init.h>

+#define DRIVER_DESC "Logitech ADI joystick family driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Logitech ADI joystick family driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

/*
@@ -439,35 +441,23 @@
{
int i, t, x;

- if (!adi->length) return;
+ if (!adi->length)
+ return;

for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {

t = adi->abs[i];
x = adi->dev.abs[t];

- if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) {
- if (i < adi->axes10) x = 512; else x = 128;
- }
-
- if (i < adi->axes10) {
- adi->dev.absmax[t] = x * 2 - 64;
- adi->dev.absmin[t] = 64;
- adi->dev.absfuzz[t] = 2;
- adi->dev.absflat[t] = 16;
- continue;
- }
-
- if (i < adi->axes10 + adi->axes8) {
- adi->dev.absmax[t] = x * 2 - 48;
- adi->dev.absmin[t] = 48;
- adi->dev.absfuzz[t] = 1;
- adi->dev.absflat[t] = 16;
- continue;
- }
+ if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
+ x = i < adi->axes10 ? 512 : 128;

- adi->dev.absmax[t] = 1;
- adi->dev.absmin[t] = -1;
+ if (i < adi->axes10)
+ input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
+ else if (i < adi->axes10 + adi->axes8)
+ input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
+ else
+ input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
}
}

@@ -475,14 +465,14 @@
* adi_connect() probes for Logitech ADI joysticks.
*/

-static void adi_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct adi_port *port;
int i;
+ int err;

- if (!(port = kmalloc(sizeof(struct adi_port), GFP_KERNEL)))
- return;
- memset(port, 0, sizeof(struct adi_port));
+ if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = port;

@@ -491,9 +481,10 @@
port->timer.data = (long) port;
port->timer.function = adi_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err) {
kfree(port);
- return;
+ return err;
}

adi_init_digital(gameport);
@@ -510,7 +501,7 @@
if (!port->adi[0].length && !port->adi[1].length) {
gameport_close(gameport);
kfree(port);
- return;
+ return -ENODEV;
}

msleep(ADI_INIT_DELAY);
@@ -526,13 +517,15 @@
printk(KERN_INFO "input: %s [%s] on %s\n",
port->adi[i].name, port->adi[i].cname, gameport->phys);
}
+
+ return 0;
}

static void adi_disconnect(struct gameport *gameport)
{
int i;
-
struct adi_port *port = gameport->private;
+
for (i = 0; i < 2; i++)
if (port->adi[i].length > 0)
input_unregister_device(&port->adi[i].dev);
@@ -545,8 +538,12 @@
*/

static struct gameport_driver adi_drv = {
- .connect = adi_connect,
- .disconnect = adi_disconnect,
+ .driver = {
+ .name = "adi",
+ },
+ .description = DRIVER_DESC,
+ .connect = adi_connect,
+ .disconnect = adi_disconnect,
};

static int __init adi_init(void)
diff -Nru a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
--- a/drivers/input/joystick/analog.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/analog.c 2005-02-11 01:40:01 -05:00
@@ -40,8 +40,10 @@
#include <linux/gameport.h>
#include <asm/timex.h>

+#define DRIVER_DESC "Analog joystick and gamepad driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Analog joystick and gamepad driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

/*
@@ -608,7 +610,8 @@
port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;

for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
- if (!analog_cooked_read(port)) break;
+ if (!analog_cooked_read(port))
+ break;
msleep(ANALOG_MAX_TIME);
}

@@ -617,11 +620,13 @@
msleep(ANALOG_MAX_TIME);
t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
gameport_trigger(gameport);
- while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++;
+ while ((gameport_read(port->gameport) & port->mask) && (u < t))
+ u++;
udelay(ANALOG_SAITEK_DELAY);
t = gameport_time(gameport, ANALOG_SAITEK_TIME);
gameport_trigger(gameport);
- while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++;
+ while ((gameport_read(port->gameport) & port->mask) && (v < t))
+ v++;

if (v < (u >> 1)) { /* FIXME - more than one port */
analog_options[0] |= /* FIXME - more than one port */
@@ -638,49 +643,51 @@
if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
break;
for (i = 0; i < 4; i++)
- if (port->axes[i] != -1) port->mask |= 1 << i;
+ if (port->axes[i] != -1)
+ port->mask |= 1 << i;

port->fuzz = gameport->fuzz;
port->cooked = 1;
return 0;
}

- if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
- return 0;
-
- return -1;
+ return gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
}

-static void analog_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int analog_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct analog_port *port;
int i;
+ int err;

- if (!(port = kmalloc(sizeof(struct analog_port), GFP_KERNEL)))
- return;
- memset(port, 0, sizeof(struct analog_port));
+ if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
+ return - ENOMEM;

- if (analog_init_port(gameport, drv, port)) {
+ err = analog_init_port(gameport, drv, port);
+ if (err) {
kfree(port);
- return;
+ return err;
}

- if (analog_init_masks(port)) {
+ err = analog_init_masks(port);
+ if (err) {
gameport_close(gameport);
kfree(port);
- return;
+ return err;
}

for (i = 0; i < 2; i++)
if (port->analog[i].mask)
analog_init_device(port, port->analog + i, i);
+
+ return 0;
}

static void analog_disconnect(struct gameport *gameport)
{
int i;
-
struct analog_port *port = gameport->private;
+
for (i = 0; i < 2; i++)
if (port->analog[i].mask)
input_unregister_device(&port->analog[i].dev);
@@ -742,14 +749,19 @@
*/

static struct gameport_driver analog_drv = {
- .connect = analog_connect,
- .disconnect = analog_disconnect,
+ .driver = {
+ .name = "analog",
+ },
+ .description = DRIVER_DESC,
+ .connect = analog_connect,
+ .disconnect = analog_disconnect,
};

static int __init analog_init(void)
{
analog_parse_options();
gameport_register_driver(&analog_drv);
+
return 0;
}

diff -Nru a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
--- a/drivers/input/joystick/cobra.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/cobra.c 2005-02-11 01:40:01 -05:00
@@ -35,8 +35,10 @@
#include <linux/gameport.h>
#include <linux/input.h>

+#define DRIVER_DESC "Creative Labs Blaster GamePad Cobra driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Creative Labs Blaster GamePad Cobra driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define COBRA_MAX_STROBE 45 /* 45 us max wait for first strobe */
@@ -158,15 +160,15 @@
del_timer(&cobra->timer);
}

-static void cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct cobra *cobra;
unsigned int data[2];
int i, j;
+ int err;

- if (!(cobra = kmalloc(sizeof(struct cobra), GFP_KERNEL)))
- return;
- memset(cobra, 0, sizeof(struct cobra));
+ if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = cobra;

@@ -175,7 +177,8 @@
cobra->timer.data = (long) cobra;
cobra->timer.function = cobra_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

cobra->exists = cobra_read_packet(gameport, data);
@@ -187,8 +190,10 @@
cobra->exists &= ~(1 << i);
}

- if (!cobra->exists)
+ if (!cobra->exists) {
+ err = -ENODEV;
goto fail2;
+ }

for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1) {
@@ -207,28 +212,29 @@
cobra->dev[i].id.version = 0x0100;

cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
- cobra->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+
+ input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
+ input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);

for (j = 0; cobra_btn[j]; j++)
set_bit(cobra_btn[j], cobra->dev[i].keybit);

- cobra->dev[i].absmin[ABS_X] = -1; cobra->dev[i].absmax[ABS_X] = 1;
- cobra->dev[i].absmin[ABS_Y] = -1; cobra->dev[i].absmax[ABS_Y] = 1;
-
- input_register_device(cobra->dev + i);
+ input_register_device(&cobra->dev[i]);
printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
}

- return;
+ return 0;
+
fail2: gameport_close(gameport);
fail1: kfree(cobra);
+ return err;
}

static void cobra_disconnect(struct gameport *gameport)
{
int i;
-
struct cobra *cobra = gameport->private;
+
for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1)
input_unregister_device(cobra->dev + i);
@@ -237,8 +243,12 @@
}

static struct gameport_driver cobra_drv = {
- .connect = cobra_connect,
- .disconnect = cobra_disconnect,
+ .driver = {
+ .name = "cobra",
+ },
+ .description = DRIVER_DESC,
+ .connect = cobra_connect,
+ .disconnect = cobra_disconnect,
};

static int __init cobra_init(void)
diff -Nru a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
--- a/drivers/input/joystick/gf2k.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/gf2k.c 2005-02-11 01:40:01 -05:00
@@ -36,8 +36,10 @@
#include <linux/input.h>
#include <linux/gameport.h>

+#define DRIVER_DESC "Genius Flight 2000 joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Genius Flight 2000 joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define GF2K_START 400 /* The time we wait for the first bit [400 us] */
@@ -238,15 +240,14 @@
* gf2k_connect() probes for Genius id joysticks.
*/

-static void gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct gf2k *gf2k;
unsigned char data[GF2K_LENGTH];
- int i;
+ int i, err;

- if (!(gf2k = kmalloc(sizeof(struct gf2k), GFP_KERNEL)))
- return;
- memset(gf2k, 0, sizeof(struct gf2k));
+ if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = gf2k;

@@ -255,7 +256,8 @@
gf2k->timer.data = (long) gf2k;
gf2k->timer.function = gf2k_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

gf2k_trigger_seq(gameport, gf2k_seq_reset);
@@ -266,16 +268,22 @@

msleep(GF2K_TIMEOUT);

- if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12)
+ if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12) {
+ err = -ENODEV;
goto fail2;
+ }

- if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5)))
+ if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5))) {
+ err = -ENODEV;
goto fail2;
+ }

#ifdef RESET_WORKS
if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
- (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5))))
+ (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) {
+ err = -ENODEV;
goto fail2;
+ }
#else
gf2k->id = 6;
#endif
@@ -283,6 +291,7 @@
if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
printk(KERN_WARNING "gf2k.c: Not yet supported joystick on %s. [id: %d type:%s]\n",
gameport->phys, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
+ err = -ENODEV;
goto fail2;
}

@@ -333,22 +342,29 @@
input_register_device(&gf2k->dev);
printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);

- return;
+ return 0;
+
fail2: gameport_close(gameport);
fail1: kfree(gf2k);
+ return err;
}

static void gf2k_disconnect(struct gameport *gameport)
{
struct gf2k *gf2k = gameport->private;
+
input_unregister_device(&gf2k->dev);
gameport_close(gameport);
kfree(gf2k);
}

static struct gameport_driver gf2k_drv = {
- .connect = gf2k_connect,
- .disconnect = gf2k_disconnect,
+ .driver = {
+ .name = "gf2k",
+ },
+ .description = DRIVER_DESC,
+ .connect = gf2k_connect,
+ .disconnect = gf2k_disconnect,
};

static int __init gf2k_init(void)
diff -Nru a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
--- a/drivers/input/joystick/grip.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/grip.c 2005-02-11 01:40:01 -05:00
@@ -35,8 +35,10 @@
#include <linux/gameport.h>
#include <linux/input.h>

+#define DRIVER_DESC "Gravis GrIP protocol joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Gravis GrIP protocol joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define GRIP_MODE_GPP 1
@@ -298,15 +300,15 @@
del_timer(&grip->timer);
}

-static void grip_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip *grip;
unsigned int data[GRIP_LENGTH_XT];
int i, j, t;
+ int err;

- if (!(grip = kmalloc(sizeof(struct grip), GFP_KERNEL)))
- return;
- memset(grip, 0, sizeof(struct grip));
+ if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = grip;

@@ -315,7 +317,8 @@
grip->timer.data = (long) grip;
grip->timer.function = grip_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

for (i = 0; i < 2; i++) {
@@ -337,8 +340,10 @@
}
}

- if (!grip->mode[0] && !grip->mode[1])
+ if (!grip->mode[0] && !grip->mode[1]) {
+ err = -ENODEV;
goto fail2;
+ }

for (i = 0; i < 2; i++)
if (grip->mode[i]) {
@@ -361,47 +366,35 @@

for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {

- set_bit(t, grip->dev[i].absbit);
-
- if (j < grip_cen[grip->mode[i]]) {
- grip->dev[i].absmin[t] = 14;
- grip->dev[i].absmax[t] = 52;
- grip->dev[i].absfuzz[t] = 1;
- grip->dev[i].absflat[t] = 2;
- continue;
- }
-
- if (j < grip_anx[grip->mode[i]]) {
- grip->dev[i].absmin[t] = 3;
- grip->dev[i].absmax[t] = 57;
- grip->dev[i].absfuzz[t] = 1;
- continue;
- }
-
- grip->dev[i].absmin[t] = -1;
- grip->dev[i].absmax[t] = 1;
+ if (j < grip_cen[grip->mode[i]])
+ input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
+ else if (j < grip_anx[grip->mode[i]])
+ input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
+ else
+ input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
}

for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
if (t > 0)
set_bit(t, grip->dev[i].keybit);

- input_register_device(grip->dev + i);
-
printk(KERN_INFO "input: %s on %s\n",
grip_name[grip->mode[i]], gameport->phys);
+ input_register_device(grip->dev + i);
}

- return;
+ return 0;
+
fail2: gameport_close(gameport);
fail1: kfree(grip);
+ return err;
}

static void grip_disconnect(struct gameport *gameport)
{
+ struct grip *grip = gameport->private;
int i;

- struct grip *grip = gameport->private;
for (i = 0; i < 2; i++)
if (grip->mode[i])
input_unregister_device(grip->dev + i);
@@ -410,8 +403,12 @@
}

static struct gameport_driver grip_drv = {
- .connect = grip_connect,
- .disconnect = grip_disconnect,
+ .driver = {
+ .name = "grip",
+ },
+ .description = DRIVER_DESC,
+ .connect = grip_connect,
+ .disconnect = grip_disconnect,
};

static int __init grip_init(void)
diff -Nru a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
--- a/drivers/input/joystick/grip_mp.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/grip_mp.c 2005-02-11 01:40:01 -05:00
@@ -20,8 +20,10 @@
#include <linux/delay.h>
#include <linux/proc_fs.h>

+#define DRIVER_DESC "Gravis Grip Multiport driver"
+
MODULE_AUTHOR("Brian Bonnlander");
-MODULE_DESCRIPTION("Gravis Grip Multiport driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#ifdef GRIP_DEBUG
@@ -477,9 +479,9 @@
}

if (dig_mode)
- dbg("multiport_init(): digital mode achieved.\n");
+ dbg("multiport_init(): digital mode activated.\n");
else {
- dbg("multiport_init(): unable to achieve digital mode.\n");
+ dbg("multiport_init(): unable to activate digital mode.\n");
return 0;
}

@@ -551,6 +553,7 @@
static int grip_open(struct input_dev *dev)
{
struct grip_mp *grip = dev->private;
+
if (!grip->used++)
mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
return 0;
@@ -563,6 +566,7 @@
static void grip_close(struct input_dev *dev)
{
struct grip_mp *grip = dev->private;
+
if (!--grip->used)
del_timer(&grip->timer);
}
@@ -585,11 +589,8 @@
grip->dev[slot].id.version = 0x0100;
grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);

- for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++) {
- set_bit(t, grip->dev[slot].absbit);
- grip->dev[slot].absmin[t] = -1;
- grip->dev[slot].absmax[t] = 1;
- }
+ for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
+ input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);

for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
if (t > 0)
@@ -612,41 +613,52 @@
static void grip_timer(unsigned long private)
{
struct grip_mp *grip = (void*) private;
+
get_and_report_mp_state(grip);
mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
}

-static void grip_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct grip_mp *grip;
+ int err;
+
+ if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
+ return -ENOMEM;

- if (!(grip = kmalloc(sizeof(struct grip_mp), GFP_KERNEL)))
- return;
- memset(grip, 0, sizeof(struct grip_mp));
gameport->private = grip;
grip->gameport = gameport;
init_timer(&grip->timer);
grip->timer.data = (long) grip;
grip->timer.function = grip_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;
- if (!multiport_init(grip))
+
+ if (!multiport_init(grip)) {
+ err = -ENODEV;
goto fail2;
- if (!grip->mode[0] && !grip->mode[1] && /* nothing plugged in */
- !grip->mode[2] && !grip->mode[3])
+ }
+
+ if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
+ /* nothing plugged in */
+ err = -ENODEV;
goto fail2;
- return;
+ }
+
+ return 0;

fail2: gameport_close(gameport);
fail1: kfree(grip);
+ return err;
}

static void grip_disconnect(struct gameport *gameport)
{
int i;
-
struct grip_mp *grip = gameport->private;
+
for (i = 0; i < 4; i++)
if (grip->registered[i])
input_unregister_device(grip->dev + i);
@@ -655,17 +667,21 @@
}

static struct gameport_driver grip_drv = {
+ .driver = {
+ .name = "grip_mp",
+ },
+ .description = DRIVER_DESC,
.connect = grip_connect,
.disconnect = grip_disconnect,
};

-static int grip_init(void)
+static int __init grip_init(void)
{
gameport_register_driver(&grip_drv);
return 0;
}

-static void grip_exit(void)
+static void __exit grip_exit(void)
{
gameport_unregister_driver(&grip_drv);
}
diff -Nru a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
--- a/drivers/input/joystick/guillemot.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/guillemot.c 2005-02-11 01:40:01 -05:00
@@ -36,8 +36,10 @@
#include <linux/gameport.h>
#include <linux/input.h>

+#define DRIVER_DESC "Guillemot Digital joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Guillemot Digital joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define GUILLEMOT_MAX_START 600 /* 600 us */
@@ -159,6 +161,7 @@
static int guillemot_open(struct input_dev *dev)
{
struct guillemot *guillemot = dev->private;
+
if (!guillemot->used++)
mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME);
return 0;
@@ -171,6 +174,7 @@
static void guillemot_close(struct input_dev *dev)
{
struct guillemot *guillemot = dev->private;
+
if (!--guillemot->used)
del_timer(&guillemot->timer);
}
@@ -179,15 +183,15 @@
* guillemot_connect() probes for Guillemot joysticks.
*/

-static void guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct guillemot *guillemot;
u8 data[GUILLEMOT_MAX_LENGTH];
int i, t;
+ int err;

- if (!(guillemot = kmalloc(sizeof(struct guillemot), GFP_KERNEL)))
- return;
- memset(guillemot, 0, sizeof(struct guillemot));
+ if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = guillemot;

@@ -196,13 +200,16 @@
guillemot->timer.data = (long) guillemot;
guillemot->timer.function = guillemot_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

i = guillemot_read_packet(gameport, data);

- if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa)
+ if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa) {
+ err = -ENODEV;
goto fail2;
+ }

for (i = 0; guillemot_type[i].name; i++)
if (guillemot_type[i].id == data[11])
@@ -211,6 +218,7 @@
if (!guillemot_type[i].name) {
printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n",
gameport->phys, data[12], data[13], data[11], data[14], data[15]);
+ err = -ENODEV;
goto fail2;
}

@@ -231,19 +239,13 @@

guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);

- for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++) {
- set_bit(t, guillemot->dev.absbit);
- guillemot->dev.absmin[t] = 0;
- guillemot->dev.absmax[t] = 255;
- }
+ for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
+ input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);

- if (guillemot->type->hat)
- for (i = 0; i < 2; i++) {
- t = ABS_HAT0X + i;
- set_bit(t, guillemot->dev.absbit);
- guillemot->dev.absmin[t] = -1;
- guillemot->dev.absmax[t] = 1;
- }
+ if (guillemot->type->hat) {
+ input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
+ input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
+ }

for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
set_bit(t, guillemot->dev.keybit);
@@ -252,14 +254,17 @@
printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
guillemot->type->name, data[14], data[15], gameport->phys);

- return;
+ return 0;
+
fail2: gameport_close(gameport);
fail1: kfree(guillemot);
+ return err;
}

static void guillemot_disconnect(struct gameport *gameport)
{
struct guillemot *guillemot = gameport->private;
+
printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
input_unregister_device(&guillemot->dev);
gameport_close(gameport);
@@ -267,8 +272,12 @@
}

static struct gameport_driver guillemot_drv = {
- .connect = guillemot_connect,
- .disconnect = guillemot_disconnect,
+ .driver = {
+ .name = "guillemot",
+ },
+ .description = DRIVER_DESC,
+ .connect = guillemot_connect,
+ .disconnect = guillemot_disconnect,
};

static int __init guillemot_init(void)
diff -Nru a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
--- a/drivers/input/joystick/interact.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/interact.c 2005-02-11 01:40:01 -05:00
@@ -39,8 +39,10 @@
#include <linux/gameport.h>
#include <linux/input.h>

+#define DRIVER_DESC "InterAct digital joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("InterAct digital joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define INTERACT_MAX_START 400 /* 400 us */
@@ -189,6 +191,7 @@
static int interact_open(struct input_dev *dev)
{
struct interact *interact = dev->private;
+
if (!interact->used++)
mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
return 0;
@@ -201,6 +204,7 @@
static void interact_close(struct input_dev *dev)
{
struct interact *interact = dev->private;
+
if (!--interact->used)
del_timer(&interact->timer);
}
@@ -209,15 +213,15 @@
* interact_connect() probes for InterAct joysticks.
*/

-static void interact_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct interact *interact;
__u32 data[3];
int i, t;
+ int err;

- if (!(interact = kmalloc(sizeof(struct interact), GFP_KERNEL)))
- return;
- memset(interact, 0, sizeof(struct interact));
+ if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = interact;

@@ -226,12 +230,14 @@
interact->timer.data = (long) interact;
interact->timer.function = interact_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);

if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
+ err = -ENODEV;
goto fail2;
}

@@ -242,6 +248,7 @@
if (!interact_type[i].length) {
printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
gameport->phys, i, data[0], data[1], data[2]);
+ err = -ENODEV;
goto fail2;
}

@@ -281,22 +288,29 @@
printk(KERN_INFO "input: %s on %s\n",
interact_type[interact->type].name, gameport->phys);

- return;
+ return 0;
+
fail2: gameport_close(gameport);
fail1: kfree(interact);
+ return err;
}

static void interact_disconnect(struct gameport *gameport)
{
struct interact *interact = gameport->private;
+
input_unregister_device(&interact->dev);
gameport_close(gameport);
kfree(interact);
}

static struct gameport_driver interact_drv = {
- .connect = interact_connect,
- .disconnect = interact_disconnect,
+ .driver = {
+ .name = "interact",
+ },
+ .description = DRIVER_DESC,
+ .connect = interact_connect,
+ .disconnect = interact_disconnect,
};

static int __init interact_init(void)
diff -Nru a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
--- a/drivers/input/joystick/joydump.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/joydump.c 2005-02-11 01:40:01 -05:00
@@ -35,8 +35,10 @@
#include <linux/delay.h>
#include <linux/init.h>

+#define DRIVER_DESC "Gameport data dumper module"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Gameport data dumper module");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define BUF_SIZE 256
@@ -46,7 +48,7 @@
unsigned char data;
};

-static void __devinit joydump_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int joydump_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct joydump *buf; /* all entries */
struct joydump *dump, *prev; /* one entry each */
@@ -67,7 +69,7 @@

printk(KERN_INFO "joydump: | Cooked not available either. Failing. |\n");
printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
- return;
+ return -ENODEV;
}

gameport_cooked_read(gameport, axes, &buttons);
@@ -140,16 +142,22 @@

jd_end:
printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
+
+ return 0;
}

-static void __devexit joydump_disconnect(struct gameport *gameport)
+static void joydump_disconnect(struct gameport *gameport)
{
gameport_close(gameport);
}

static struct gameport_driver joydump_drv = {
- .connect = joydump_connect,
- .disconnect = joydump_disconnect,
+ .driver = {
+ .name = "joydump",
+ },
+ .description = DRIVER_DESC,
+ .connect = joydump_connect,
+ .disconnect = joydump_disconnect,
};

static int __init joydump_init(void)
diff -Nru a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
--- a/drivers/input/joystick/sidewinder.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/sidewinder.c 2005-02-11 01:40:01 -05:00
@@ -36,8 +36,10 @@
#include <linux/input.h>
#include <linux/gameport.h>

+#define DRIVER_DESC "Microsoft SideWinder joystick family driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("Microsoft SideWinder joystick family driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

/*
@@ -160,7 +162,8 @@
v = gameport_read(gameport);
} while (!(~v & u & 0x10) && (bitout > 0)); /* Wait for first falling edge on clock */

- if (bitout > 0) bitout = strobe; /* Extend time if not timed out */
+ if (bitout > 0)
+ bitout = strobe; /* Extend time if not timed out */

while ((timeout > 0 || bitout > 0) && (i < length)) {

@@ -266,6 +269,7 @@
static int sw_parity(__u64 t)
{
int x = t ^ (t >> 32);
+
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
@@ -307,7 +311,8 @@

case SW_ID_3DP:

- if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8) return -1;
+ if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
+ return -1;

input_report_abs(dev, ABS_X, (GB( 3,3) << 7) | GB(16,7));
input_report_abs(dev, ABS_Y, (GB( 0,3) << 7) | GB(24,7));
@@ -331,7 +336,8 @@

for (i = 0; i < sw->number; i ++) {

- if (sw_parity(GB(i*15,15))) return -1;
+ if (sw_parity(GB(i*15,15)))
+ return -1;

input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
@@ -347,7 +353,8 @@
case SW_ID_PP:
case SW_ID_FFP:

- if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8) return -1;
+ if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
+ return -1;

input_report_abs(dev, ABS_X, GB( 9,10));
input_report_abs(dev, ABS_Y, GB(19,10));
@@ -366,7 +373,8 @@

case SW_ID_FSP:

- if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8) return -1;
+ if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
+ return -1;

input_report_abs(dev, ABS_X, GB( 0,10));
input_report_abs(dev, ABS_Y, GB(16,10));
@@ -389,7 +397,8 @@

case SW_ID_FFW:

- if (!sw_parity(GB(0,33))) return -1;
+ if (!sw_parity(GB(0,33)))
+ return -1;

input_report_abs(dev, ABS_RX, GB( 0,10));
input_report_abs(dev, ABS_RUDDER, GB(10, 6));
@@ -466,7 +475,8 @@
sw->length = 66;
}

- if (sw->fail < SW_FAIL) return -1; /* Not enough, don't reinitialize yet */
+ if (sw->fail < SW_FAIL)
+ return -1; /* Not enough, don't reinitialize yet */

printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"
" - reinitializing joystick.\n", sw->gameport->phys);
@@ -491,13 +501,15 @@
struct sw *sw = (void *) private;

sw->reads++;
- if (sw_read(sw)) sw->bads++;
+ if (sw_read(sw))
+ sw->bads++;
mod_timer(&sw->timer, jiffies + SW_REFRESH);
}

static int sw_open(struct input_dev *dev)
{
struct sw *sw = dev->private;
+
if (!sw->used++)
mod_timer(&sw->timer, jiffies + SW_REFRESH);
return 0;
@@ -506,6 +518,7 @@
static void sw_close(struct input_dev *dev)
{
struct sw *sw = dev->private;
+
if (!--sw->used)
del_timer(&sw->timer);
}
@@ -561,7 +574,10 @@
{
int i;
unsigned char xor = 0;
- for (i = 1; i < len; i++) xor |= (buf[i - 1] ^ buf[i]) & 6;
+
+ for (i = 1; i < len; i++)
+ xor |= (buf[i - 1] ^ buf[i]) & 6;
+
return !!xor * 2 + 1;
}

@@ -569,10 +585,11 @@
* sw_connect() probes for SideWinder type joysticks.
*/

-static void sw_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
{
struct sw *sw;
int i, j, k, l;
+ int err;
unsigned char *buf = NULL; /* [SW_LENGTH] */
unsigned char *idbuf = NULL; /* [SW_LENGTH] */
unsigned char m = 1;
@@ -580,13 +597,13 @@

comment[0] = 0;

- if (!(sw = kmalloc(sizeof(struct sw), GFP_KERNEL))) return;
- memset(sw, 0, sizeof(struct sw));
-
+ sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
buf = kmalloc(SW_LENGTH, GFP_KERNEL);
idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
- if (!buf || !idbuf)
+ if (!sw || !buf || !idbuf) {
+ err = -ENOMEM;
goto fail1;
+ }

gameport->private = sw;

@@ -595,7 +612,8 @@
sw->timer.data = (long) sw;
sw->timer.function = sw_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

dbg("Init 0: Opened %s, io %#x, speed %d",
@@ -611,7 +629,10 @@
i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
udelay(SW_TIMEOUT);
dbg("Init 1b: Length %d.", i);
- if (!i) goto fail2; /* No data -> FAIL */
+ if (!i) { /* No data -> FAIL */
+ err = -ENODEV;
+ goto fail2;
+ }
}

j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Read ID. This initializes the stick */
@@ -622,7 +643,10 @@
udelay(SW_TIMEOUT);
i = sw_read_packet(gameport, buf, SW_LENGTH, 0); /* Retry reading packet */
dbg("Init 2b: Mode %d. Length %d.", m, i);
- if (!i) goto fail2;
+ if (!i) {
+ err = -ENODEV;
+ goto fail2;
+ }
udelay(SW_TIMEOUT);
j = sw_read_packet(gameport, idbuf, SW_LENGTH, i); /* Retry reading ID */
dbg("Init 2c: ID Length %d.", j);
@@ -686,13 +710,14 @@
}
}

- } while (k && (sw->type == -1));
+ } while (k && sw->type == -1);

if (sw->type == -1) {
printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
"on %s, contact <[email protected]>\n", gameport->phys);
sw_print_packet("ID", j * 3, idbuf, 3);
sw_print_packet("Data", i * m, buf, m);
+ err = -ENODEV;
goto fail2;
}

@@ -742,11 +767,13 @@
sw->name, comment, gameport->phys, m, l, k);
}

- return;
+ return 0;
+
fail2: gameport_close(gameport);
fail1: kfree(sw);
kfree(buf);
kfree(idbuf);
+ return err;
}

static void sw_disconnect(struct gameport *gameport)
@@ -761,8 +788,12 @@
}

static struct gameport_driver sw_drv = {
- .connect = sw_connect,
- .disconnect = sw_disconnect,
+ .driver = {
+ .name = "sidewinder",
+ },
+ .description = DRIVER_DESC,
+ .connect = sw_connect,
+ .disconnect = sw_disconnect,
};

static int __init sw_init(void)
diff -Nru a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
--- a/drivers/input/joystick/tmdc.c 2005-02-11 01:40:01 -05:00
+++ b/drivers/input/joystick/tmdc.c 2005-02-11 01:40:01 -05:00
@@ -39,8 +39,10 @@
#include <linux/gameport.h>
#include <linux/input.h>

+#define DRIVER_DESC "ThrustMaster DirectConnect joystick driver"
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
-MODULE_DESCRIPTION("ThrustMaster DirectConnect joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

#define TMDC_MAX_START 400 /* 400 us */
@@ -242,9 +244,9 @@
* tmdc_probe() probes for ThrustMaster type joysticks.
*/

-static void tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
+static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
{
- struct models {
+ static struct models {
unsigned char id;
char *name;
char abs;
@@ -263,10 +265,10 @@
unsigned char data[2][TMDC_MAX_LENGTH];
struct tmdc *tmdc;
int i, j, k, l, m;
+ int err;

- if (!(tmdc = kmalloc(sizeof(struct tmdc), GFP_KERNEL)))
- return;
- memset(tmdc, 0, sizeof(struct tmdc));
+ if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
+ return -ENOMEM;

gameport->private = tmdc;

@@ -275,11 +277,14 @@
tmdc->timer.data = (long) tmdc;
tmdc->timer.function = tmdc_timer;

- if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW))
+ err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+ if (err)
goto fail1;

- if (!(tmdc->exists = tmdc_read_packet(gameport, data)))
+ if (!(tmdc->exists = tmdc_read_packet(gameport, data))) {
+ err = -ENODEV;
goto fail2;
+ }

for (j = 0; j < 2; j++)
if (tmdc->exists & (1 << j)) {
@@ -321,20 +326,13 @@

tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);

- for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
- if (tmdc->abs[j][i] < 0) continue;
- set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
- tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
- tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
- tmdc->dev[j].absfuzz[tmdc->abs[j][i]] = 2;
- tmdc->dev[j].absflat[tmdc->abs[j][i]] = 4;
- }
+ for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
+ if (tmdc->abs[j][i] >= 0)
+ input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
+
+ for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
+ input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);

- for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++) {
- set_bit(tmdc_abs_hat[i], tmdc->dev[j].absbit);
- tmdc->dev[j].absmin[tmdc_abs_hat[i]] = -1;
- tmdc->dev[j].absmax[tmdc_abs_hat[i]] = 1;
- }

for (k = l = 0; k < 4; k++) {
for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
@@ -346,15 +344,18 @@
printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
}

- return;
+ return 0;
+
fail2: gameport_close(gameport);
fail1: kfree(tmdc);
+ return err;
}

static void tmdc_disconnect(struct gameport *gameport)
{
struct tmdc *tmdc = gameport->private;
int i;
+
for (i = 0; i < 2; i++)
if (tmdc->exists & (1 << i))
input_unregister_device(tmdc->dev + i);
@@ -363,8 +364,12 @@
}

static struct gameport_driver tmdc_drv = {
- .connect = tmdc_connect,
- .disconnect = tmdc_disconnect,
+ .driver = {
+ .name = "tmdc",
+ },
+ .description = DRIVER_DESC,
+ .connect = tmdc_connect,
+ .disconnect = tmdc_disconnect,
};

static int __init tmdc_init(void)
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h 2005-02-11 01:40:01 -05:00
+++ b/include/linux/gameport.h 2005-02-11 01:40:01 -05:00
@@ -45,13 +45,15 @@
struct gameport_driver {

void *private;
- char *name;
+ char *description;

- void (*connect)(struct gameport *, struct gameport_driver *drv);
+ int (*connect)(struct gameport *, struct gameport_driver *drv);
void (*disconnect)(struct gameport *);

+ struct device_driver driver;
struct list_head node;
};
+#define to_gameport_driver(d) container_of(d, struct gameport_driver, driver)

int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode);
void gameport_close(struct gameport *gameport);

2005-02-11 07:35:59

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 9/10] Gameport: complete sysfs integration


===================================================================


[email protected], 2005-02-11 01:21:32-05:00, [email protected]
Input: complete gameport sysfs integration, ports are now
devices in driver model. Implemented similarly to serio.

Signed-off-by: Dmitry Torokhov <[email protected]>


drivers/input/gameport/gameport.c | 586 ++++++++++++++++++++++++++++++++++----
include/linux/gameport.h | 64 ++--
2 files changed, 579 insertions(+), 71 deletions(-)


===================================================================



diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- a/drivers/input/gameport/gameport.c 2005-02-11 01:40:19 -05:00
+++ b/drivers/input/gameport/gameport.c 2005-02-11 01:40:19 -05:00
@@ -2,6 +2,7 @@
* Generic gameport layer
*
* Copyright (c) 1999-2002 Vojtech Pavlik
+ * Copyright (c) 2005 Dmitry Torokhov
*/

/*
@@ -10,22 +11,27 @@
* the Free Software Foundation.
*/

-#include <asm/io.h>
+#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/gameport.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/slab.h>
-#include <linux/stddef.h>
#include <linux/delay.h>

+/*#include <asm/io.h>*/
+
MODULE_AUTHOR("Vojtech Pavlik <[email protected]>");
MODULE_DESCRIPTION("Generic gameport layer");
MODULE_LICENSE("GPL");

-EXPORT_SYMBOL(gameport_register_port);
+EXPORT_SYMBOL(__gameport_register_port);
EXPORT_SYMBOL(gameport_unregister_port);
-EXPORT_SYMBOL(gameport_register_driver);
+EXPORT_SYMBOL(__gameport_register_driver);
EXPORT_SYMBOL(gameport_unregister_driver);
EXPORT_SYMBOL(gameport_open);
EXPORT_SYMBOL(gameport_close);
@@ -34,13 +40,23 @@
EXPORT_SYMBOL(gameport_set_name);
EXPORT_SYMBOL(gameport_set_phys);

+/*
+ * gameport_sem protects entire gameport subsystem and is taken
+ * every time gameport port or driver registrered or unregistered.
+ */
+static DECLARE_MUTEX(gameport_sem);
+
static LIST_HEAD(gameport_list);
-static LIST_HEAD(gameport_driver_list);

static struct bus_type gameport_bus = {
.name = "gameport",
};

+static void gameport_add_port(struct gameport *gameport);
+static void gameport_destroy_port(struct gameport *gameport);
+static void gameport_reconnect_port(struct gameport *gameport);
+static void gameport_disconnect_port(struct gameport *gameport);
+
#ifdef __i386__

#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
@@ -106,21 +122,325 @@
#endif
}

+
+/*
+ * Basic gameport -> driver core mappings
+ */
+
+static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
+{
+ down_write(&gameport_bus.subsys.rwsem);
+
+ gameport->dev.driver = &drv->driver;
+ if (drv->connect(gameport, drv)) {
+ gameport->dev.driver = NULL;
+ goto out;
+ }
+ device_bind_driver(&gameport->dev);
+out:
+ up_write(&gameport_bus.subsys.rwsem);
+}
+
+static void gameport_release_driver(struct gameport *gameport)
+{
+ down_write(&gameport_bus.subsys.rwsem);
+ device_release_driver(&gameport->dev);
+ up_write(&gameport_bus.subsys.rwsem);
+}
+
static void gameport_find_driver(struct gameport *gameport)
{
- struct gameport_driver *drv;
+ down_write(&gameport_bus.subsys.rwsem);
+ device_attach(&gameport->dev);
+ up_write(&gameport_bus.subsys.rwsem);
+}
+
+
+/*
+ * Gameport event processing.
+ */
+
+enum gameport_event_type {
+ GAMEPORT_RESCAN,
+ GAMEPORT_RECONNECT,
+ GAMEPORT_REGISTER_PORT,
+ GAMEPORT_REGISTER_DRIVER,
+};
+
+struct gameport_event {
+ enum gameport_event_type type;
+ void *object;
+ struct module *owner;
+ struct list_head node;
+};
+
+static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */
+static LIST_HEAD(gameport_event_list);
+static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
+static DECLARE_COMPLETION(gameport_exited);
+static int gameport_pid;
+
+static void gameport_queue_event(void *object, struct module *owner,
+ enum gameport_event_type event_type)
+{
+ unsigned long flags;
+ struct gameport_event *event;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);

- list_for_each_entry(drv, &gameport_driver_list, node) {
- if (gameport->drv)
+ /*
+ * Scan event list for the other events for the same gameport port,
+ * starting with the most recent one. If event is the same we
+ * do not need add new one. If event is of different type we
+ * need to add this event and should not look further because
+ * we need to preseve sequence of distinct events.
+ */
+ list_for_each_entry_reverse(event, &gameport_event_list, node) {
+ if (event->object == object) {
+ if (event->type == event_type)
+ goto out;
break;
- drv->connect(gameport, drv);
- }
+ }
+ }
+
+ if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
+ if (!try_module_get(owner)) {
+ printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
+ goto out;
+ }
+
+ event->type = event_type;
+ event->object = object;
+ event->owner = owner;
+
+ list_add_tail(&event->node, &gameport_event_list);
+ wake_up(&gameport_wait);
+ } else {
+ printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type);
+ }
+out:
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
}

-void gameport_rescan(struct gameport *gameport)
+static void gameport_free_event(struct gameport_event *event)
{
- gameport_close(gameport);
- gameport_find_driver(gameport);
+ module_put(event->owner);
+ kfree(event);
+}
+
+static void gameport_remove_duplicate_events(struct gameport_event *event)
+{
+ struct list_head *node, *next;
+ struct gameport_event *e;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ list_for_each_safe(node, next, &gameport_event_list) {
+ e = list_entry(node, struct gameport_event, node);
+ if (event->object == e->object) {
+ /*
+ * If this event is of different type we should not
+ * look further - we only suppress duplicate events
+ * that were sent back-to-back.
+ */
+ if (event->type != e->type)
+ break;
+
+ list_del_init(node);
+ gameport_free_event(e);
+ }
+ }
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+}
+
+
+static struct gameport_event *gameport_get_event(void)
+{
+ struct gameport_event *event;
+ struct list_head *node;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ if (list_empty(&gameport_event_list)) {
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+ return NULL;
+ }
+
+ node = gameport_event_list.next;
+ event = list_entry(node, struct gameport_event, node);
+ list_del_init(node);
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+
+ return event;
+}
+
+static void gameport_handle_events(void)
+{
+ struct gameport_event *event;
+ struct gameport_driver *gameport_drv;
+
+ down(&gameport_sem);
+
+ while ((event = gameport_get_event())) {
+
+ switch (event->type) {
+ case GAMEPORT_REGISTER_PORT:
+ gameport_add_port(event->object);
+ break;
+
+ case GAMEPORT_RECONNECT:
+ gameport_reconnect_port(event->object);
+ break;
+
+ case GAMEPORT_RESCAN:
+ gameport_disconnect_port(event->object);
+ gameport_find_driver(event->object);
+ break;
+
+ case GAMEPORT_REGISTER_DRIVER:
+ gameport_drv = event->object;
+ driver_register(&gameport_drv->driver);
+ break;
+
+ default:
+ break;
+ }
+
+ gameport_remove_duplicate_events(event);
+ gameport_free_event(event);
+ }
+
+ up(&gameport_sem);
+}
+
+/*
+ * Remove all events that have been submitted for a given gameport port.
+ */
+static void gameport_remove_pending_events(struct gameport *gameport)
+{
+ struct list_head *node, *next;
+ struct gameport_event *event;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ list_for_each_safe(node, next, &gameport_event_list) {
+ event = list_entry(node, struct gameport_event, node);
+ if (event->object == gameport) {
+ list_del_init(node);
+ gameport_free_event(event);
+ }
+ }
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+}
+
+/*
+ * Destroy child gameport port (if any) that has not been fully registered yet.
+ *
+ * Note that we rely on the fact that port can have only one child and therefore
+ * only one child registration request can be pending. Additionally, children
+ * are registered by driver's connect() handler so there can't be a grandchild
+ * pending registration together with a child.
+ */
+static struct gameport *gameport_get_pending_child(struct gameport *parent)
+{
+ struct gameport_event *event;
+ struct gameport *gameport, *child = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gameport_event_lock, flags);
+
+ list_for_each_entry(event, &gameport_event_list, node) {
+ if (event->type == GAMEPORT_REGISTER_PORT) {
+ gameport = event->object;
+ if (gameport->parent == parent) {
+ child = gameport;
+ break;
+ }
+ }
+ }
+
+ spin_unlock_irqrestore(&gameport_event_lock, flags);
+ return child;
+}
+
+static int gameport_thread(void *nothing)
+{
+ lock_kernel();
+ daemonize("kgameportd");
+ allow_signal(SIGTERM);
+
+ do {
+ gameport_handle_events();
+ wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
+ try_to_freeze(PF_FREEZE);
+ } while (!signal_pending(current));
+
+ printk(KERN_DEBUG "gameport: kgameportd exiting\n");
+
+ unlock_kernel();
+ complete_and_exit(&gameport_exited, 0);
+}
+
+
+/*
+ * Gameport port operations
+ */
+
+static ssize_t gameport_show_description(struct device *dev, char *buf)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+ return sprintf(buf, "%s\n", gameport->name);
+}
+
+static ssize_t gameport_rebind_driver(struct device *dev, const char *buf, size_t count)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+ struct device_driver *drv;
+ int retval;
+
+ retval = down_interruptible(&gameport_sem);
+ if (retval)
+ return retval;
+
+ retval = count;
+ if (!strncmp(buf, "none", count)) {
+ gameport_disconnect_port(gameport);
+ } else if (!strncmp(buf, "reconnect", count)) {
+ gameport_reconnect_port(gameport);
+ } else if (!strncmp(buf, "rescan", count)) {
+ gameport_disconnect_port(gameport);
+ gameport_find_driver(gameport);
+ } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) {
+ gameport_disconnect_port(gameport);
+ gameport_bind_driver(gameport, to_gameport_driver(drv));
+ put_driver(drv);
+ } else {
+ retval = -EINVAL;
+ }
+
+ up(&gameport_sem);
+
+ return retval;
+}
+
+static struct device_attribute gameport_device_attrs[] = {
+ __ATTR(description, S_IRUGO, gameport_show_description, NULL),
+ __ATTR(drvctl, S_IWUSR, NULL, gameport_rebind_driver),
+ __ATTR_NULL
+};
+
+static void gameport_release_port(struct device *dev)
+{
+ struct gameport *gameport = to_gameport_port(dev);
+
+ kfree(gameport);
+ module_put(THIS_MODULE);
}

void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
@@ -128,29 +448,162 @@
va_list args;

va_start(args, fmt);
- gameport->phys = gameport->phys_buf;
- vsnprintf(gameport->phys_buf, sizeof(gameport->phys_buf), fmt, args);
+ vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
va_end(args);
}

-void gameport_register_port(struct gameport *gameport)
+/*
+ * Prepare gameport port for registration.
+ */
+static void gameport_init_port(struct gameport *gameport)
{
- list_add_tail(&gameport->node, &gameport_list);
+ static atomic_t gameport_no = ATOMIC_INIT(0);
+
+ __module_get(THIS_MODULE);
+
+ init_MUTEX(&gameport->drv_sem);
+ device_initialize(&gameport->dev);
+ snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
+ "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
+ gameport->dev.bus = &gameport_bus;
+ gameport->dev.release = gameport_release_port;
+ if (gameport->parent)
+ gameport->dev.parent = &gameport->parent->dev;
+}
+
+/*
+ * Complete gameport port registration.
+ * Driver core will attempt to find appropriate driver for the port.
+ */
+static void gameport_add_port(struct gameport *gameport)
+{
+ if (gameport->parent)
+ gameport->parent->child = gameport;
+
gameport->speed = gameport_measure_speed(gameport);

- if (gameport->dyn_alloc) {
- if (gameport->io)
- printk(KERN_INFO "gameport: %s is %s, io %#x, speed %d kHz\n",
- gameport->name, gameport->phys, gameport->io, gameport->speed);
- else
- printk(KERN_INFO "gameport: %s is %s, speed %d kHz\n",
- gameport->name, gameport->phys, gameport->speed);
+ list_add_tail(&gameport->node, &gameport_list);
+
+ if (gameport->io)
+ printk(KERN_INFO "gameport: %s is %s, io %#x, speed %dkHz\n",
+ gameport->name, gameport->phys, gameport->io, gameport->speed);
+ else
+ printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
+ gameport->name, gameport->phys, gameport->speed);
+
+ device_add(&gameport->dev);
+ gameport->registered = 1;
+}
+
+/*
+ * gameport_destroy_port() completes deregistration process and removes
+ * port from the system
+ */
+static void gameport_destroy_port(struct gameport *gameport)
+{
+ struct gameport *child;
+
+ child = gameport_get_pending_child(gameport);
+ if (child) {
+ gameport_remove_pending_events(child);
+ put_device(&child->dev);
}

- gameport_find_driver(gameport);
+ if (gameport->parent) {
+ gameport->parent->child = NULL;
+ gameport->parent = NULL;
+ }
+
+ if (gameport->registered) {
+ device_del(&gameport->dev);
+ list_del_init(&gameport->node);
+ gameport->registered = 0;
+ }
+
+ gameport_remove_pending_events(gameport);
+ put_device(&gameport->dev);
}

/*
+ * Reconnect gameport port and all its children (re-initialize attached devices)
+ */
+static void gameport_reconnect_port(struct gameport *gameport)
+{
+ do {
+ if (!gameport->drv || !gameport->drv->reconnect || gameport->drv->reconnect(gameport)) {
+ gameport_disconnect_port(gameport);
+ gameport_find_driver(gameport);
+ /* Ok, old children are now gone, we are done */
+ break;
+ }
+ gameport = gameport->child;
+ } while (gameport);
+}
+
+/*
+ * gameport_disconnect_port() unbinds a port from its driver. As a side effect
+ * all child ports are unbound and destroyed.
+ */
+static void gameport_disconnect_port(struct gameport *gameport)
+{
+ struct gameport *s, *parent;
+
+ if (gameport->child) {
+ /*
+ * Children ports should be disconnected and destroyed
+ * first, staring with the leaf one, since we don't want
+ * to do recursion
+ */
+ for (s = gameport; s->child; s = s->child)
+ /* empty */;
+
+ do {
+ parent = s->parent;
+
+ gameport_release_driver(s);
+ gameport_destroy_port(s);
+ } while ((s = parent) != gameport);
+ }
+
+ /*
+ * Ok, no children left, now disconnect this port
+ */
+ gameport_release_driver(gameport);
+}
+
+void gameport_rescan(struct gameport *gameport)
+{
+ gameport_queue_event(gameport, NULL, GAMEPORT_RESCAN);
+}
+
+void gameport_reconnect(struct gameport *gameport)
+{
+ gameport_queue_event(gameport, NULL, GAMEPORT_RECONNECT);
+}
+
+/*
+ * Submits register request to kgameportd for subsequent execution.
+ * Note that port registration is always asynchronous.
+ */
+void __gameport_register_port(struct gameport *gameport, struct module *owner)
+{
+ gameport_init_port(gameport);
+ gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
+}
+
+/*
+ * Synchronously unregisters gameport port.
+ */
+void gameport_unregister_port(struct gameport *gameport)
+{
+ down(&gameport_sem);
+ gameport_disconnect_port(gameport);
+ gameport_destroy_port(gameport);
+ up(&gameport_sem);
+}
+
+
+/*
* Gameport driver operations
*/

@@ -165,69 +618,100 @@
__ATTR_NULL
};

-void gameport_unregister_port(struct gameport *gameport)
+static int gameport_driver_probe(struct device *dev)
{
- list_del_init(&gameport->node);
- if (gameport->drv)
- gameport->drv->disconnect(gameport);
- if (gameport->dyn_alloc)
- kfree(gameport);
+ struct gameport *gameport = to_gameport_port(dev);
+ struct gameport_driver *drv = to_gameport_driver(dev->driver);
+
+ drv->connect(gameport, drv);
+ return gameport->drv ? 0 : -ENODEV;
}

-void gameport_register_driver(struct gameport_driver *drv)
+static int gameport_driver_remove(struct device *dev)
{
- struct gameport *gameport;
+ struct gameport *gameport = to_gameport_port(dev);
+ struct gameport_driver *drv = to_gameport_driver(dev->driver);

- drv->driver.bus = &gameport_bus;
- driver_register(&drv->driver);
+ drv->disconnect(gameport);
+ return 0;
+}

- list_add_tail(&drv->node, &gameport_driver_list);
- list_for_each_entry(gameport, &gameport_list, node)
- if (!gameport->drv)
- drv->connect(gameport, drv);
+void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
+{
+ drv->driver.bus = &gameport_bus;
+ drv->driver.probe = gameport_driver_probe;
+ drv->driver.remove = gameport_driver_remove;
+ gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
}

void gameport_unregister_driver(struct gameport_driver *drv)
{
struct gameport *gameport;

- list_del_init(&drv->node);
+ down(&gameport_sem);
+ drv->ignore = 1; /* so gameport_find_driver ignores it */
+
+start_over:
list_for_each_entry(gameport, &gameport_list, node) {
- if (gameport->drv == drv)
- drv->disconnect(gameport);
- gameport_find_driver(gameport);
+ if (gameport->drv == drv) {
+ gameport_disconnect_port(gameport);
+ gameport_find_driver(gameport);
+ /* we could've deleted some ports, restart */
+ goto start_over;
+ }
}
+
driver_unregister(&drv->driver);
+ up(&gameport_sem);
+}
+
+static int gameport_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct gameport_driver *gameport_drv = to_gameport_driver(drv);
+
+ return !gameport_drv->ignore;
+}
+
+static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
+{
+ down(&gameport->drv_sem);
+ gameport->drv = drv;
+ up(&gameport->drv_sem);
}

int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
{
+
if (gameport->open) {
- if (gameport->open(gameport, mode))
+ if (gameport->open(gameport, mode)) {
return -1;
+ }
} else {
if (mode != GAMEPORT_MODE_RAW)
return -1;
}

- if (gameport->drv)
- return -1;
-
- gameport->drv = drv;
-
+ gameport_set_drv(gameport, drv);
return 0;
}

void gameport_close(struct gameport *gameport)
{
- gameport->drv = NULL;
+ gameport_set_drv(gameport, NULL);
if (gameport->close)
gameport->close(gameport);
}

static int __init gameport_init(void)
{
+ if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) {
+ printk(KERN_ERR "gameport: Failed to start kgameportd\n");
+ return -1;
+ }
+
+ gameport_bus.dev_attrs = gameport_device_attrs;
gameport_bus.drv_attrs = gameport_driver_attrs;
+ gameport_bus.match = gameport_bus_match;
bus_register(&gameport_bus);

return 0;
@@ -236,6 +720,8 @@
static void __exit gameport_exit(void)
{
bus_unregister(&gameport_bus);
+ kill_proc(gameport_pid, SIGTERM, 1);
+ wait_for_completion(&gameport_exited);
}

module_init(gameport_init);
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h 2005-02-11 01:40:19 -05:00
+++ b/include/linux/gameport.h 2005-02-11 01:40:19 -05:00
@@ -17,10 +17,8 @@

void *private; /* Private pointer for joystick drivers */
void *port_data; /* Private pointer for gameport drivers */
- char *name;
- char name_buf[32];
- char *phys;
- char phys_buf[32];
+ char name[32];
+ char phys[32];

int io;
int speed;
@@ -33,14 +31,17 @@
int (*open)(struct gameport *, int);
void (*close)(struct gameport *);

+ struct gameport *parent, *child;
+
struct gameport_driver *drv;
+ struct semaphore drv_sem; /* protects serio->drv so attributes can pin driver */
+
struct device dev;
+ unsigned int registered; /* port has been fully registered with driver core */

struct list_head node;
-
- /* temporary, till sysfs transition is complete */
- int dyn_alloc;
};
+#define to_gameport_port(d) container_of(d, struct gameport, dev)

struct gameport_driver {

@@ -48,10 +49,12 @@
char *description;

int (*connect)(struct gameport *, struct gameport_driver *drv);
+ int (*reconnect)(struct gameport *);
void (*disconnect)(struct gameport *);

struct device_driver driver;
- struct list_head node;
+
+ unsigned int ignore;
};
#define to_gameport_driver(d) container_of(d, struct gameport_driver, driver)

@@ -59,13 +62,18 @@
void gameport_close(struct gameport *gameport);
void gameport_rescan(struct gameport *gameport);

+void __gameport_register_port(struct gameport *gameport, struct module *owner);
+static inline void gameport_register_port(struct gameport *gameport)
+{
+ __gameport_register_port(gameport, THIS_MODULE);
+}
+
+void gameport_unregister_port(struct gameport *gameport);
+
static inline struct gameport *gameport_allocate_port(void)
{
struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);

- if (gameport)
- gameport->dyn_alloc = 1;
-
return gameport;
}

@@ -76,17 +84,31 @@

static inline void gameport_set_name(struct gameport *gameport, const char *name)
{
- gameport->name = gameport->name_buf;
- strlcpy(gameport->name, name, sizeof(gameport->name_buf));
+ strlcpy(gameport->name, name, sizeof(gameport->name));
}

void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));

-void gameport_register_port(struct gameport *gameport);
-void gameport_unregister_port(struct gameport *gameport);
+/*
+ * Use the following fucntions to pin gameport's driver in process context
+ */
+static inline int gameport_pin_driver(struct gameport *gameport)
+{
+ return down_interruptible(&gameport->drv_sem);
+}
+
+static inline void gameport_unpin_driver(struct gameport *gameport)
+{
+ up(&gameport->drv_sem);
+}
+
+void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
+static inline void gameport_register_driver(struct gameport_driver *drv)
+{
+ __gameport_register_driver(drv, THIS_MODULE);
+}

-void gameport_register_driver(struct gameport_driver *drv);
void gameport_unregister_driver(struct gameport_driver *drv);

#define GAMEPORT_MODE_DISABLED 0
@@ -104,7 +126,7 @@
#define GAMEPORT_ID_VENDOR_GRAVIS 0x0009
#define GAMEPORT_ID_VENDOR_GUILLEMOT 0x000a

-static __inline__ void gameport_trigger(struct gameport *gameport)
+static inline void gameport_trigger(struct gameport *gameport)
{
if (gameport->trigger)
gameport->trigger(gameport);
@@ -112,7 +134,7 @@
outb(0xff, gameport->io);
}

-static __inline__ unsigned char gameport_read(struct gameport *gameport)
+static inline unsigned char gameport_read(struct gameport *gameport)
{
if (gameport->read)
return gameport->read(gameport);
@@ -120,7 +142,7 @@
return inb(gameport->io);
}

-static __inline__ int gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+static inline int gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
{
if (gameport->cooked_read)
return gameport->cooked_read(gameport, axes, buttons);
@@ -128,7 +150,7 @@
return -1;
}

-static __inline__ int gameport_calibrate(struct gameport *gameport, int *axes, int *max)
+static inline int gameport_calibrate(struct gameport *gameport, int *axes, int *max)
{
if (gameport->calibrate)
return gameport->calibrate(gameport, axes, max);
@@ -136,7 +158,7 @@
return -1;
}

-static __inline__ int gameport_time(struct gameport *gameport, int time)
+static inline int gameport_time(struct gameport *gameport, int time)
{
return (time * gameport->speed) / 1000;
}

2005-02-11 07:39:53

by Dmitry Torokhov

[permalink] [raw]
Subject: [PATCH 10/10] Gameport: replace ->private with gameport_get/set_drvdata


===================================================================


[email protected], 2005-02-11 01:23:40-05:00, [email protected]
Input: remove gameport->private in favor of using driver-specific data
in device structure, add gameport_get/set_drvdata to access it.

Signed-off-by: Dmitry Torokhov <[email protected]>


drivers/input/joystick/a3d.c | 10 ++++++----
drivers/input/joystick/adi.c | 7 ++++---
drivers/input/joystick/analog.c | 7 +++++--
drivers/input/joystick/cobra.c | 10 ++++++----
drivers/input/joystick/gf2k.c | 10 ++++++----
drivers/input/joystick/grip.c | 10 ++++++----
drivers/input/joystick/grip_mp.c | 9 ++++++---
drivers/input/joystick/guillemot.c | 9 +++++----
drivers/input/joystick/interact.c | 10 ++++++----
drivers/input/joystick/sidewinder.c | 10 ++++++----
drivers/input/joystick/tmdc.c | 10 ++++++----
include/linux/gameport.h | 15 ++++++++++++++-
12 files changed, 76 insertions(+), 41 deletions(-)


===================================================================



diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
--- a/drivers/input/joystick/a3d.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/a3d.c 2005-02-11 01:41:08 -05:00
@@ -277,13 +277,13 @@
if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = a3d;
-
a3d->gameport = gameport;
init_timer(&a3d->timer);
a3d->timer.data = (long) a3d;
a3d->timer.function = a3d_timer;

+ gameport_set_drvdata(gameport, a3d);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -379,13 +379,14 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(a3d);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(a3d);
return err;
}

static void a3d_disconnect(struct gameport *gameport)
{
- struct a3d *a3d = gameport->private;
+ struct a3d *a3d = gameport_get_drvdata(gameport);

input_unregister_device(&a3d->dev);
if (a3d->adc) {
@@ -393,6 +394,7 @@
a3d->adc = NULL;
}
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(a3d);
}

diff -Nru a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
--- a/drivers/input/joystick/adi.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/adi.c 2005-02-11 01:41:08 -05:00
@@ -474,13 +474,13 @@
if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = port;
-
port->gameport = gameport;
init_timer(&port->timer);
port->timer.data = (long) port;
port->timer.function = adi_timer;

+ gameport_set_drvdata(gameport, port);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err) {
kfree(port);
@@ -524,12 +524,13 @@
static void adi_disconnect(struct gameport *gameport)
{
int i;
- struct adi_port *port = gameport->private;
+ struct adi_port *port = gameport_get_drvdata(gameport);

for (i = 0; i < 2; i++)
if (port->adi[i].length > 0)
input_unregister_device(&port->adi[i].dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(port);
}

diff -Nru a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
--- a/drivers/input/joystick/analog.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/analog.c 2005-02-11 01:41:08 -05:00
@@ -593,12 +593,13 @@
{
int i, t, u, v;

- gameport->private = port;
port->gameport = gameport;
init_timer(&port->timer);
port->timer.data = (long) port;
port->timer.function = analog_timer;

+ gameport_set_drvdata(gameport, port);
+
if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {

analog_calibrate_timer(port);
@@ -672,6 +673,7 @@
err = analog_init_masks(port);
if (err) {
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(port);
return err;
}
@@ -686,12 +688,13 @@
static void analog_disconnect(struct gameport *gameport)
{
int i;
- struct analog_port *port = gameport->private;
+ struct analog_port *port = gameport_get_drvdata(gameport);

for (i = 0; i < 2; i++)
if (port->analog[i].mask)
input_unregister_device(&port->analog[i].dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
port->gameport->phys);
diff -Nru a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
--- a/drivers/input/joystick/cobra.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/cobra.c 2005-02-11 01:41:08 -05:00
@@ -170,13 +170,13 @@
if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = cobra;
-
cobra->gameport = gameport;
init_timer(&cobra->timer);
cobra->timer.data = (long) cobra;
cobra->timer.function = cobra_timer;

+ gameport_set_drvdata(gameport, cobra);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -226,19 +226,21 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(cobra);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(cobra);
return err;
}

static void cobra_disconnect(struct gameport *gameport)
{
+ struct cobra *cobra = gameport_get_drvdata(gameport);
int i;
- struct cobra *cobra = gameport->private;

for (i = 0; i < 2; i++)
if ((cobra->exists >> i) & 1)
input_unregister_device(cobra->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(cobra);
}

diff -Nru a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
--- a/drivers/input/joystick/gf2k.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/gf2k.c 2005-02-11 01:41:08 -05:00
@@ -249,13 +249,13 @@
if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = gf2k;
-
gf2k->gameport = gameport;
init_timer(&gf2k->timer);
gf2k->timer.data = (long) gf2k;
gf2k->timer.function = gf2k_timer;

+ gameport_set_drvdata(gameport, gf2k);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -345,16 +345,18 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(gf2k);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(gf2k);
return err;
}

static void gf2k_disconnect(struct gameport *gameport)
{
- struct gf2k *gf2k = gameport->private;
+ struct gf2k *gf2k = gameport_get_drvdata(gameport);

input_unregister_device(&gf2k->dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(gf2k);
}

diff -Nru a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
--- a/drivers/input/joystick/grip.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/grip.c 2005-02-11 01:41:08 -05:00
@@ -310,13 +310,13 @@
if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = grip;
-
grip->gameport = gameport;
init_timer(&grip->timer);
grip->timer.data = (long) grip;
grip->timer.function = grip_timer;

+ gameport_set_drvdata(gameport, grip);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -386,19 +386,21 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(grip);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(grip);
return err;
}

static void grip_disconnect(struct gameport *gameport)
{
- struct grip *grip = gameport->private;
+ struct grip *grip = gameport_get_drvdata(gameport);
int i;

for (i = 0; i < 2; i++)
if (grip->mode[i])
input_unregister_device(grip->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(grip);
}

diff -Nru a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
--- a/drivers/input/joystick/grip_mp.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/grip_mp.c 2005-02-11 01:41:08 -05:00
@@ -626,12 +626,13 @@
if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = grip;
grip->gameport = gameport;
init_timer(&grip->timer);
grip->timer.data = (long) grip;
grip->timer.function = grip_timer;

+ gameport_set_drvdata(gameport, grip);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -650,19 +651,21 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(grip);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(grip);
return err;
}

static void grip_disconnect(struct gameport *gameport)
{
+ struct grip_mp *grip = gameport_get_drvdata(gameport);
int i;
- struct grip_mp *grip = gameport->private;

for (i = 0; i < 4; i++)
if (grip->registered[i])
input_unregister_device(grip->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(grip);
}

diff -Nru a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
--- a/drivers/input/joystick/guillemot.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/guillemot.c 2005-02-11 01:41:08 -05:00
@@ -193,13 +193,13 @@
if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = guillemot;
-
guillemot->gameport = gameport;
init_timer(&guillemot->timer);
guillemot->timer.data = (long) guillemot;
guillemot->timer.function = guillemot_timer;

+ gameport_set_drvdata(gameport, guillemot);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -257,13 +257,14 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(guillemot);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(guillemot);
return err;
}

static void guillemot_disconnect(struct gameport *gameport)
{
- struct guillemot *guillemot = gameport->private;
+ struct guillemot *guillemot = gameport_get_drvdata(gameport);

printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
input_unregister_device(&guillemot->dev);
diff -Nru a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
--- a/drivers/input/joystick/interact.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/interact.c 2005-02-11 01:41:08 -05:00
@@ -223,13 +223,13 @@
if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = interact;
-
interact->gameport = gameport;
init_timer(&interact->timer);
interact->timer.data = (long) interact;
interact->timer.function = interact_timer;

+ gameport_set_drvdata(gameport, interact);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -291,16 +291,18 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(interact);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(interact);
return err;
}

static void interact_disconnect(struct gameport *gameport)
{
- struct interact *interact = gameport->private;
+ struct interact *interact = gameport_get_drvdata(gameport);

input_unregister_device(&interact->dev);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(interact);
}

diff -Nru a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
--- a/drivers/input/joystick/sidewinder.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/sidewinder.c 2005-02-11 01:41:08 -05:00
@@ -605,13 +605,13 @@
goto fail1;
}

- gameport->private = sw;
-
sw->gameport = gameport;
init_timer(&sw->timer);
sw->timer.data = (long) sw;
sw->timer.function = sw_timer;

+ gameport_set_drvdata(gameport, sw);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -770,7 +770,8 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(sw);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(sw);
kfree(buf);
kfree(idbuf);
return err;
@@ -778,12 +779,13 @@

static void sw_disconnect(struct gameport *gameport)
{
+ struct sw *sw = gameport_get_drvdata(gameport);
int i;

- struct sw *sw = gameport->private;
for (i = 0; i < sw->number; i++)
input_unregister_device(sw->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(sw);
}

diff -Nru a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
--- a/drivers/input/joystick/tmdc.c 2005-02-11 01:41:08 -05:00
+++ b/drivers/input/joystick/tmdc.c 2005-02-11 01:41:08 -05:00
@@ -270,13 +270,13 @@
if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
return -ENOMEM;

- gameport->private = tmdc;
-
tmdc->gameport = gameport;
init_timer(&tmdc->timer);
tmdc->timer.data = (long) tmdc;
tmdc->timer.function = tmdc_timer;

+ gameport_set_drvdata(gameport, tmdc);
+
err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
if (err)
goto fail1;
@@ -347,19 +347,21 @@
return 0;

fail2: gameport_close(gameport);
-fail1: kfree(tmdc);
+fail1: gameport_set_drvdata(gameport, NULL);
+ kfree(tmdc);
return err;
}

static void tmdc_disconnect(struct gameport *gameport)
{
- struct tmdc *tmdc = gameport->private;
+ struct tmdc *tmdc = gameport_get_drvdata(gameport);
int i;

for (i = 0; i < 2; i++)
if (tmdc->exists & (1 << i))
input_unregister_device(tmdc->dev + i);
gameport_close(gameport);
+ gameport_set_drvdata(gameport, NULL);
kfree(tmdc);
}

diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h 2005-02-11 01:41:08 -05:00
+++ b/include/linux/gameport.h 2005-02-11 01:41:08 -05:00
@@ -15,7 +15,6 @@

struct gameport {

- void *private; /* Private pointer for joystick drivers */
void *port_data; /* Private pointer for gameport drivers */
char name[32];
char phys[32];
@@ -89,6 +88,20 @@

void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)));
+
+/*
+ * Use the following fucntions to manipulate gameport's per-port
+ * driver-specific data.
+ */
+static inline void *gameport_get_drvdata(struct gameport *gameport)
+{
+ return dev_get_drvdata(&gameport->dev);
+}
+
+static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
+{
+ dev_set_drvdata(&gameport->dev, data);
+}

/*
* Use the following fucntions to pin gameport's driver in process context

2005-02-11 08:11:13

by Vojtech Pavlik

[permalink] [raw]
Subject: Re: [PATCH 0/10] Convert gameport to driver model/sysfs

On Fri, Feb 11, 2005 at 01:58:47AM -0500, Dmitry Torokhov wrote:

> This series of patches adds a new "gameport" bus to the driver model.
> It is implemented very similarly to "serio" bus and also allows
> individual drivers to be manually bound/disconnected from a port
> by manipulating port's "drvctl" attribute.

Good work! I'm pulling it into my tree. And test.

> The changes can also be pulled from my tree (which has Vojtech's
> input tree as a parent):
>
> bk pull bk://dtor.bkbits.net/input
>
> I am CC-ing ALSA list as the changes touch quite a few sound drivers.
>
> Comments/testing is appreciated.


--
Vojtech Pavlik
SuSE Labs, SuSE CR