Skip to contentSkip to conversation

input: HID devices can have the same logical max and min

PATCH New Vojtech Pavlik 1 participant 11 messages Jun 21, 2003

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/11 input: HID devices can have the same logical max and min

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:32:06-07:00, [email protected]
input: logical maximum and minimum can have the same value in HID.

 hid-core.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

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

drivers/usb/input/hid-core.c +1 -1
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
@@ -215,7 +215,7 @@
 		return -1;
 	}
 
-	if (parser->global.logical_maximum <= parser->global.logical_minimum) {
+	if (parser->global.logical_maximum < parser->global.logical_minimum) {
 		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
 		return -1;
 	}
#1 lore raw

PATCH 2/11 input: Fix misdetection of PS/2 mice as AT keyboards

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:33:11-07:00, [email protected]
input: Fix misdetection of PS2 mice as AT keyboards on non-PC machines
where ATKBD_CMD_RESET_BAT is used.

 atkbd.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

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

drivers/input/keyboard/atkbd.c +6 -2
diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
@@ -89,7 +89,7 @@
 #define ATKBD_CMD_GETID		0x02f2
 #define ATKBD_CMD_ENABLE	0x00f4
 #define ATKBD_CMD_RESET_DIS	0x00f5
-#define ATKBD_CMD_RESET_BAT	0x01ff
+#define ATKBD_CMD_RESET_BAT	0x02ff
 #define ATKBD_CMD_SETALL_MB	0x00f8
 #define ATKBD_CMD_RESEND	0x00fe
 #define ATKBD_CMD_EX_ENABLE	0x10ea
@@ -255,7 +255,8 @@
 
 	while (atkbd->cmdcnt && timeout--) {
 
-		if (atkbd->cmdcnt == 1 && command == ATKBD_CMD_RESET_BAT)
+		if (atkbd->cmdcnt == 1 &&
+		    command == ATKBD_CMD_RESET_BAT && timeout > 100000)
 			timeout = 100000;
 
 		if (atkbd->cmdcnt == 1 && command == ATKBD_CMD_GETID &&
@@ -270,6 +271,9 @@
 	if (param)
 		for (i = 0; i < receive; i++)
 			param[i] = atkbd->cmdbuf[(receive - 1) - i];
+
+	if (command == ATKBD_CMD_RESET_BAT && atkbd->cmdcnt == 1)
+		atkbd->cmdcnt = 0;
 
 	if (atkbd->cmdcnt) {
 		atkbd->cmdcnt = 0;
#2 lore raw

PATCH 3/11 input: Add locking to serio.c

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:34:11-07:00, [email protected]
input: Add locking to serio.c

 serio.c |   13 +++++++++++++
 1 files changed, 13 insertions(+)

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

drivers/input/serio/serio.c +13 -0
diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
@@ -58,6 +58,7 @@
 	struct list_head node;
 };
 
+static DECLARE_MUTEX(serio_sem);
 static LIST_HEAD(serio_list);
 static LIST_HEAD(serio_dev_list);
 static LIST_HEAD(serio_event_list);
@@ -90,9 +91,11 @@
 
 		switch (event->type) {
 			case SERIO_RESCAN :
+				down(&serio_sem);
 				if (event->serio->dev && event->serio->dev->disconnect)
 					event->serio->dev->disconnect(event->serio);
 				serio_find_dev(event->serio);
+				up(&serio_sem);
 				break;
 			default:
 				break;
@@ -153,30 +156,37 @@
 
 void serio_register_port(struct serio *serio)
 {
+	down(&serio_sem);
 	list_add_tail(&serio->node, &serio_list);
 	serio_find_dev(serio);
+	up(&serio_sem);
 }
 
 void serio_unregister_port(struct serio *serio)
 {
+	down(&serio_sem);
 	list_del_init(&serio->node);
 	if (serio->dev && serio->dev->disconnect)
 		serio->dev->disconnect(serio);
+	up(&serio_sem);
 }
 
 void serio_register_device(struct serio_dev *dev)
 {
 	struct serio *serio;
+	down(&serio_sem);
 	list_add_tail(&dev->node, &serio_dev_list);
 	list_for_each_entry(serio, &serio_list, node)
 		if (!serio->dev && dev->connect)
 			dev->connect(serio, dev);
+	up(&serio_sem);
 }
 
 void serio_unregister_device(struct serio_dev *dev)
 {
 	struct serio *serio;
 
+	down(&serio_sem);
 	list_del_init(&dev->node);
 
 	list_for_each_entry(serio, &serio_list, node) {
@@ -184,8 +194,10 @@
 			dev->disconnect(serio);
 		serio_find_dev(serio);
 	}
+	up(&serio_sem);
 }
 
+/* called from serio_dev->connect/disconnect methods under serio_sem */
 int serio_open(struct serio *serio, struct serio_dev *dev)
 {
 	if (serio->open(serio))
@@ -194,6 +206,7 @@
 	return 0;
 }
 
+/* called from serio_dev->connect/disconnect methods under serio_sem */
 void serio_close(struct serio *serio)
 {
 	serio->close(serio);
#3 lore raw

PATCH 4/11 input: Remove unused var from serio struct

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:35:24-07:00, [email protected]
input: remove unused var from serio struct

 serio.h |    1 -
 1 files changed, 1 deletion(-)

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

include/linux/serio.h +0 -1
diff -Nru a/include/linux/serio.h b/include/linux/serio.h
@@ -26,7 +26,6 @@
 	void *driver;
 	char *name;
 	char *phys;
-	int number;
 
 	unsigned short idbus;
 	unsigned short idvendor;
#4 lore raw

PATCH 5/11 input: Gameport was never closed after calibrating

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:36:19-07:00, [email protected]
input: Fix gameport.c - gameport was never closed after calibrating

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

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

drivers/input/gameport/gameport.c +2 -2
diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
@@ -84,6 +84,7 @@
 		if ((t = DELTA(t2,t1) - DELTA(t3,t2)) < tx) tx = t;
 	}
 
+	gameport_close(gameport);
 	return 59659 / (tx < 1 ? 1 : tx);
 
 #else
@@ -93,11 +94,10 @@
 	j = jiffies; while (j == jiffies);
 	j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
 
+	gameport_close(gameport);
 	return t * HZ / 1000;
 
 #endif
-
-	gameport_close(gameport);
 }
 
 static void gameport_find_dev(struct gameport *gameport)
#5 lore raw

PATCH 6/11 input: Add Logitech MX PS2++ support

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:41:52-07:00, [email protected]
input: Add Logitech MX PS2++ support, move Logitech PS2++ code to a
separate source file, always enable Synaptics support. Some more fixes in Synaptics code and documentation.

 drivers/input/mouse/Kconfig        |   17 --
 drivers/input/mouse/Makefile       |    5 
 drivers/input/mouse/logips2pp.c    |  228 +++++++++++++++++++++++++++++++++++++
 drivers/input/mouse/logips2pp.h    |   17 ++
 drivers/input/mouse/psmouse-base.c |  193 +++++++++----------------------
 drivers/input/mouse/psmouse.h      |    2 
 drivers/input/mouse/synaptics.c    |    7 -
 drivers/input/mouse/synaptics.h    |   10 -
 include/linux/input.h              |    1 
 9 files changed, 315 insertions(+), 165 deletions(-)

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

drivers/input/mouse/Kconfig +3 -14
diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
@@ -19,7 +19,9 @@
 	  Say Y here if you have a PS/2 mouse connected to your system. This
 	  includes the standard 2 or 3-button PS/2 mouse, as well as PS/2
 	  mice with wheels and extra buttons, Microsoft, Logitech or Genius
-	  compatible.
+	  compatible. Support for Synaptics TouchPads is also included.
+	  For Synaptics TouchPad support in XFree86 you'll need this XFree86
+	  driver: http://w1.894.telia.com/~u89404340/touchpad/index.html
 
 	  If unsure, say Y.
 
@@ -27,19 +29,6 @@
 	  inserted in and removed from the running kernel whenever you want).
 	  The module will be called psmouse. If you want to compile it as a
 	  module, say M here and read <file:Documentation/modules.txt>.
-
-config MOUSE_PS2_SYNAPTICS
-	bool "Synaptics TouchPad"
-	default n
-	depends on INPUT && INPUT_MOUSE && SERIO && MOUSE_PS2
-	---help---
-	  Say Y here if you have a Synaptics TouchPad connected to your system.
-	  This touchpad is found on many modern laptop computers.
-	  Note that you also need a user space driver to interpret the data
-	  generated by the kernel. A compatible driver for XFree86 is available
-	  from http://...
-
-	  If unsure, say Y.
 
 config MOUSE_SERIAL
 	tristate "Serial mouse"
drivers/input/mouse/Makefile +1 -4
diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
@@ -14,7 +14,4 @@
 obj-$(CONFIG_MOUSE_PS2)		+= psmouse.o
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
 
-psmouse-objs  := psmouse-base.o
-ifeq ($(CONFIG_MOUSE_PS2_SYNAPTICS),y)
-        psmouse-objs += synaptics.o
-endif
+psmouse-objs  := psmouse-base.o logips2pp.o synaptics.o
drivers/input/mouse/logips2pp.c new file +228 -0

228 lines not on this page · raw message

drivers/input/mouse/logips2pp.h new file +17 -0
diff -Nru a/drivers/input/mouse/logips2pp.h b/drivers/input/mouse/logips2pp.h
@@ -0,0 +1,17 @@
+/*
+ * Logitech PS/2++ mouse driver header
+ *
+ * Copyright (c) 2003 Vojtech Pavlik <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _LOGIPS2PP_H
+#define _LOGIPS2PP_H
+struct psmouse;
+void ps2pp_process_packet(struct psmouse *psmouse);
+void ps2pp_set_800dpi(struct psmouse *psmouse);
+int ps2pp_detect_model(struct psmouse *psmouse);
+#endif
drivers/input/mouse/psmouse-base.c +60 -133

255 lines not on this page · raw message

drivers/input/mouse/psmouse.h +2 -0
diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
@@ -46,4 +46,6 @@
 
 int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command);
 
+extern int psmouse_smartscroll;
+
 #endif /* _PSMOUSE_H */
drivers/input/mouse/synaptics.c +3 -4
diff -Nru a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
@@ -171,9 +171,9 @@
 static int query_hardware(struct psmouse *psmouse)
 {
 	struct synaptics_data *priv = psmouse->private;
-	int retries = 3;
+	int retries = 0;
 
-	while ((retries++ <= 3) && synaptics_reset(psmouse))
+	while ((retries++ < 3) && synaptics_reset(psmouse))
 		printk(KERN_ERR "synaptics reset failed\n");
 
 	if (synaptics_identify(psmouse, &priv->identity))
@@ -266,8 +266,7 @@
  *	Functions to interpret the absolute mode packets
  ****************************************************************************/
 
-static void synaptics_parse_hw_state(struct synaptics_data *priv,
-				     struct synaptics_hw_state *hw)
+static void synaptics_parse_hw_state(struct synaptics_data *priv, struct synaptics_hw_state *hw)
 {
 	unsigned char *buf = priv->proto_buf;
 
drivers/input/mouse/synaptics.h +0 -10
diff -Nru a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
@@ -9,20 +9,10 @@
 #ifndef _SYNAPTICS_H
 #define _SYNAPTICS_H
 
-#ifdef CONFIG_MOUSE_PS2_SYNAPTICS
 
 extern void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs);
 extern int synaptics_init(struct psmouse *psmouse);
 extern void synaptics_disconnect(struct psmouse *psmouse);
-
-#else
-
-static inline void synaptics_process_byte(struct psmouse *psmouse, struct pt_regs *regs) {}
-static inline int synaptics_init(struct psmouse *psmouse) { return -1; }
-static inline void synaptics_disconnect(struct psmouse *psmouse) {}
-
-#endif
-
 
 /* synaptics queries */
 #define SYN_QUE_IDENTIFY		0x00
include/linux/input.h +1 -0
diff -Nru a/include/linux/input.h b/include/linux/input.h
@@ -358,6 +358,7 @@
 #define BTN_EXTRA		0x114
 #define BTN_FORWARD		0x115
 #define BTN_BACK		0x116
+#define BTN_TASK		0x117
 
 #define BTN_JOYSTICK		0x120
 #define BTN_TRIGGER		0x120
#6 lore raw

PATCH 7/11 input: Fixes for the uinput userspace

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:43:13-07:00, [email protected]
input: Three fixes for the uinput userspace input device driver.

 uinput.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

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

drivers/input/misc/uinput.c +3 -2
diff -Nru a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
@@ -49,11 +49,11 @@
 
 	udev = (struct uinput_device *)dev->private;
 
-	udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 	udev->buff[udev->head].type = type;
 	udev->buff[udev->head].code = code;
 	udev->buff[udev->head].value = value;
 	do_gettimeofday(&udev->buff[udev->head].time);
+	udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 
 	wake_up_interruptible(&udev->waitq);
 
@@ -82,6 +82,7 @@
 	udev->dev->event = uinput_dev_event;
 	udev->dev->upload_effect = uinput_dev_upload_effect;
 	udev->dev->erase_effect = uinput_dev_erase_effect;
+	udev->dev->private = udev;
 
 	init_waitqueue_head(&(udev->waitq));
 
@@ -264,7 +265,7 @@
 		return -ENODEV;
 
 	while ((udev->head != udev->tail) && 
-	    (retval + sizeof(struct uinput_device) <= count)) {
+	    (retval + sizeof(struct input_event) <= count)) {
 		if (copy_to_user(buffer + retval, &(udev->buff[udev->tail]),
 		    sizeof(struct input_event))) return -EFAULT;
 		udev->tail = (udev->tail + 1) % UINPUT_BUFFER_SIZE;
#7 lore raw

PATCH 8/11 input: Change order of search for beeper devices in keyboard.c

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:44:26-07:00, [email protected]
input: Change order of search for beeper devices in keyboard.c,
so that it is easier to replace a beeper with a different driver

 keyboard.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)

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

drivers/char/keyboard.c +1 -1
diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c
@@ -242,7 +242,7 @@
 	del_timer(&kd_mksound_timer);
 
 	if (hz) {
-		list_for_each(node,&kbd_handler.h_list) {
+		list_for_each_prev(node,&kbd_handler.h_list) {
 			struct input_handle *handle = to_handle_h(node);
 			if (test_bit(EV_SND, handle->dev->evbit)) {
 				if (test_bit(SND_TONE, handle->dev->sndbit)) {
#8 lore raw

PATCH 9/11 input: Fix double kfree of device->rdesc in hid-core

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:45:44-07:00, [email protected]
input: fix double kfree of device->rdesc on hid_parse_parse error
path in hid-core.c

 hid-core.c |    5 -----
 1 files changed, 5 deletions(-)

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

drivers/usb/input/hid-core.c +0 -5
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
@@ -674,7 +674,6 @@
 
 		if (item.format != HID_ITEM_FORMAT_SHORT) {
 			dbg("unexpected long global item");
-			kfree(device->rdesc);
 			kfree(device->collection);
 			hid_free_device(device);
 			kfree(parser);
@@ -684,7 +683,6 @@
 		if (dispatch_type[item.type](parser, &item)) {
 			dbg("item %u %u %u %u parsing failed\n",
 				item.format, (unsigned)item.size, (unsigned)item.type, (unsigned)item.tag);
-			kfree(device->rdesc);
 			kfree(device->collection);
 			hid_free_device(device);
 			kfree(parser);
@@ -694,7 +692,6 @@
 		if (start == end) {
 			if (parser->collection_stack_ptr) {
 				dbg("unbalanced collection at end of report description");
-				kfree(device->rdesc);
 				kfree(device->collection);
 				hid_free_device(device);
 				kfree(parser);
@@ -702,7 +699,6 @@
 			}
 			if (parser->local.delimiter_depth) {
 				dbg("unbalanced delimiter at end of report description");
-				kfree(device->rdesc);
 				kfree(device->collection);
 				hid_free_device(device);
 				kfree(parser);
@@ -714,7 +710,6 @@
 	}
 
 	dbg("item fetching failed at offset %d\n", (int)(end - start));
-	kfree(device->rdesc);
 	kfree(device->collection);
 	hid_free_device(device);
 	kfree(parser);
#9 lore raw

PATCH 10/11 input: Fixes for sidewinder.c

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:48:10-07:00, [email protected]
input: Fixes for sidewinder.c: Workaround for
misbehaving 3DPro joysticks, don't trust FreestylePro 1-bit data packet for data width recognition, invert FreestylePro buttons.

 sidewinder.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

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

drivers/input/joystick/sidewinder.c +6 -5
diff -Nru a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
@@ -378,10 +378,10 @@
 			for (j = 0; j < 6; j++)
 				input_report_key(dev, sw_btn[SW_ID_FSP][j], !GB(j+10,1));
 
-			input_report_key(dev, BTN_TR,     GB(26,1));
-			input_report_key(dev, BTN_START,  GB(27,1));
-			input_report_key(dev, BTN_MODE,   GB(38,1));
-			input_report_key(dev, BTN_SELECT, GB(39,1));
+			input_report_key(dev, BTN_TR,     !GB(26,1));
+			input_report_key(dev, BTN_START,  !GB(27,1));
+			input_report_key(dev, BTN_MODE,   !GB(38,1));
+			input_report_key(dev, BTN_SELECT, !GB(39,1));
 
 			input_sync(dev);
 
@@ -602,7 +602,6 @@
 		gameport->phys, gameport->io, gameport->speed);
 
 	i = sw_read_packet(gameport, buf, SW_LENGTH, 0);		/* Read normal packet */
-	m |= sw_guess_mode(buf, i);					/* Data packet (1-bit) can carry mode info [FSP] */
 	udelay(SW_TIMEOUT);
 	dbg("Init 1: Mode %d. Length %d.", m , i);
 
@@ -676,6 +675,8 @@
 					} else
 					sw->type = SW_ID_PP;
 					break;
+				case 66:
+					sw->bits = 3;
 				case 198:
 					sw->length = 22;
 				case 64:
#10 lore raw

PATCH 11/11 input: Make GC_PSX_DELAY lower and configurable

You can pull this changeset from:
bk://kernel.bkbits.net/vojtech/input

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

[email protected], 2003-06-21 04:49:07-07:00, [email protected]
input: make GC_PSX_DELAY lower (25 usec instead of 60), to burn less
CPU time while reading PSX pads, and make it a module parameter also, for devices which would need the huge value of 60.

 gamecon.c |   18 +++++++++++++-----
 1 files changed, 13 insertions(+), 5 deletions(-)

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

drivers/input/joystick/gamecon.c +13 -5
diff -Nru a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
@@ -46,6 +46,7 @@
 MODULE_PARM(gc, "2-6i");
 MODULE_PARM(gc_2,"2-6i");
 MODULE_PARM(gc_3,"2-6i");
+MODULE_PARM(gc_psx_delay, "i");
 
 #define GC_SNES		1
 #define GC_NES		2
@@ -213,7 +214,7 @@
  *	
  */
 
-#define GC_PSX_DELAY	60		/* 60 usec */
+#define GC_PSX_DELAY	25		/* 25 usec */
 #define GC_PSX_LENGTH	8		/* talk to the controller in bytes */
 
 #define GC_PSX_MOUSE	1		/* Mouse */
@@ -230,6 +231,7 @@
 #define GC_PSX_ID(x)	((x) >> 4)	/* High nibble is device type */
 #define GC_PSX_LEN(x)	((x) & 0xf)	/* Low nibble is length in words */
 
+static int gc_psx_delay = GC_PSX_DELAY;
 static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y };
 static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y,
 				BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR };
@@ -246,10 +248,10 @@
 	for (i = 0; i < 8; i++, b >>= 1) {
 		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
-		udelay(GC_PSX_DELAY);
+		udelay(gc_psx_delay);
 		data |= ((parport_read_status(gc->pd->port) ^ 0x80) & gc->pads[GC_PSX]) ? (1 << i) : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER);
-		udelay(GC_PSX_DELAY);
+		udelay(gc_psx_delay);
 	}
 	return data;
 }
@@ -265,9 +267,9 @@
 	unsigned long flags;
 
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER);	/* Select pad */
-	udelay(GC_PSX_DELAY * 2);
+	udelay(gc_psx_delay * 2);
 	parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER);			/* Deselect, begin command */
-	udelay(GC_PSX_DELAY * 2);
+	udelay(gc_psx_delay * 2);
 
 	local_irq_save(flags);
 
@@ -649,9 +651,15 @@
 	for (i = 0; i <= ints[0] && i < 6; i++) gc_3[i] = ints[i + 1];
 	return 1;
 }
+static int __init gc_psx_setup(char *str)
+{
+        get_option(&str, &gc_psx_delay);
+        return 1;
+}
 __setup("gc=", gc_setup);
 __setup("gc_2=", gc_setup_2);
 __setup("gc_3=", gc_setup_3);
+__setup("gc_psx_delay=", gc_psx_setup);
 #endif
 
 int __init gc_init(void)