patch-2.2.14 linux/drivers/char/joystick/joy-console.c

Next file: linux/drivers/char/joystick/joy-creative.c
Previous file: linux/drivers/char/joystick/joy-assassin.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.13/linux/drivers/char/joystick/joy-console.c linux/drivers/char/joystick/joy-console.c
@@ -1,14 +1,19 @@
 /*
- * joy-console.c  Version 0.11V
+ *  joy-console.c  Version 0.14V
  *
- * Copyright (c) 1998 Andree Borrmann
+ *  Copyright (c) 1998 Andree Borrmann
+ *  Copyright (c) 1999 John Dahlstrom
+ *  Copyright (c) 1999 David Kuder
+ *  Copyright (c) 1999 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
  */
 
 /*
  * This is a module for the Linux joystick driver, supporting
- * console (NES, SNES, Multi1, Multi2, PSX) gamepads connected
- * via parallel port. Up to five such controllers can be
- * connected to one parallel port.
+ * console (NES, SNES, N64, Multi1, Multi2, PSX) gamepads 
+ * connected via parallel port. Up to five such controllers 
+ * can be connected to one parallel port.
  */
 
 /*
@@ -25,6 +30,10 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
  */
 
 #include <asm/io.h>
@@ -36,12 +45,13 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 
-MODULE_AUTHOR("Andree Borrmann <A.Borrmann@tu-bs.de>");
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 MODULE_PARM(js_console, "2-6i");
-MODULE_PARM(js_console2,"2-6i");
-MODULE_PARM(js_console3,"2-6i");
+MODULE_PARM(js_console_2,"2-6i");
+MODULE_PARM(js_console_3,"2-6i");
 
 
 #define JS_NO_PAD	0
@@ -51,29 +61,29 @@
 #define JS_MULTI_STICK	4
 #define JS_MULTI2_STICK	5
 #define JS_PSX_PAD	6
-
-#define JS_MAX_PAD	JS_PSX_PAD
+#define JS_N64_PAD	7	
+#define JS_N64_PAD_DPP	8	/* DirectPad Pro compatible layout */
+ 
+#define JS_MAX_PAD	JS_N64_PAD_DPP
 
 struct js_console_info {
-#ifdef USE_PARPORT
 	struct pardevice *port;	/* parport device */
-#else
-	int port;		/* hw port */
-#endif
 	int pads;		/* total number of pads */
+	int pad_to_device[5];   /* pad to js device mapping (js0, js1, etc.) */
 	int snes;		/* SNES pads */
 	int nes;		/* NES pads */
+	int n64;		/* N64 pads */
+	int n64_dpp;		/* bits indicate N64 pads treated 14 button, 2 axis */
 	int multi;		/* Multi joysticks */
 	int multi2;		/* Multi joysticks with 2 buttons */
-	int psx;		/* Normal PSX controllers */
-	int negcon;		/* PSX NEGCON controllers */
+	int psx;		/* PSX controllers */
 };
 
 static struct js_port* js_console_port = NULL;
 
 static int js_console[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int js_console2[] __initdata = { -1, 0, 0, 0, 0, 0 };
-static int js_console3[] __initdata = { -1, 0, 0, 0, 0, 0 };
+static int js_console_2[] __initdata = { -1, 0, 0, 0, 0, 0 };
+static int js_console_3[] __initdata = { -1, 0, 0, 0, 0, 0 };
 
 static int status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 };
 
@@ -109,7 +119,7 @@
 #define JS_SNES_L	10
 #define JS_SNES_R	11
 
-#define JS_NES_POWER	0xf8
+#define JS_NES_POWER	0xfc
 #define JS_NES_CLOCK	0x01
 #define JS_NES_LATCH	0x02
 
@@ -123,17 +133,99 @@
 {
 	int i;
 
-	JS_PAR_DATA_OUT(JS_NES_POWER + JS_NES_CLOCK + JS_NES_LATCH, info->port);
+	JS_PAR_DATA_OUT(JS_NES_POWER | JS_NES_CLOCK | JS_NES_LATCH, info->port);
 	udelay(JS_NES_DELAY * 2);
-	JS_PAR_DATA_OUT(JS_NES_POWER + JS_NES_CLOCK, info->port);
+	JS_PAR_DATA_OUT(JS_NES_POWER | JS_NES_CLOCK, info->port);
 
 	for (i = 0; i < length; i++) {
 		udelay(JS_NES_DELAY);
 		JS_PAR_DATA_OUT(JS_NES_POWER, info->port);
 		data[i] = JS_PAR_STATUS(info->port) ^ ~JS_PAR_STATUS_INVERT;
 		udelay(JS_NES_DELAY);
-		JS_PAR_DATA_OUT(JS_NES_POWER + JS_NES_CLOCK, info->port);
+		JS_PAR_DATA_OUT(JS_NES_POWER | JS_NES_CLOCK, info->port);
+	}
+}
+
+/*
+ * N64 support.
+ */
+
+#define JS_N64_A	0
+#define JS_N64_B	1
+#define JS_N64_Z	2
+#define JS_N64_START	3
+#define JS_N64_UP	4
+#define JS_N64_DOWN	5
+#define JS_N64_LEFT	6
+#define JS_N64_RIGHT	7
+#define JS_N64_UNUSED1	8
+#define JS_N64_UNUSED2	9
+#define JS_N64_L	10
+#define JS_N64_R	11
+#define JS_N64_CU	12
+#define JS_N64_CD	13
+#define JS_N64_CL	14
+#define JS_N64_CR	15
+#define JS_N64_X	23			/* 16 - 23, signed 8-bit int */
+#define JS_N64_Y	31			/* 24 - 31, signed 8-bit int */
+
+#define JS_N64_LENGTH		32		/* N64 bit length, not including stop bit */
+#define JS_N64_REQUEST_LENGTH	37		/* transmit request sequence is 9 bits long */
+#define JS_N64_DELAY		133		/* delay between transmit request, and response ready (us) */
+#define JS_N64_REQUEST		0x1dd1111111ULL /* the request data command (encoded for 000000011) */
+#define JS_N64_DWS		3		/* delay between write segments (required for sound playback because of ISA DMA) */
+						/* JS_N64_DWS > 24 is known to fail */ 
+#define JS_N64_POWER_W		0xe2		/* power during write (transmit request) */
+#define JS_N64_POWER_R		0xfd		/* power during read */
+#define JS_N64_OUT		0x1d		/* output bits to the 4 pads */
+						/* Reading the main axes of any N64 pad is known to fail if the corresponding bit */
+						/* in JS_N64_OUT is pulled low on the output port (by any routine) for more */
+						/* than 0.123 consecutive ms */
+#define JS_N64_CLOCK		0x02		/* clock bits for read */
+
+/* 
+ * js_n64_read_packet() reads an N64 packet. 
+ * Each pad uses one bit per byte. So all pads connected to this port are read in parallel.
+ */
+
+static void js_n64_read_packet(struct js_console_info *info, unsigned char *data)
+{
+	int i;
+	unsigned long flags;
+
+/*
+ * Request the pad to transmit data
+ */
+
+	save_flags(flags);
+	cli();
+	for (i = 0; i < JS_N64_REQUEST_LENGTH; i++) {
+		JS_PAR_DATA_OUT(JS_N64_POWER_W | ((JS_N64_REQUEST >> i) & 1 ? JS_N64_OUT : 0), info->port);
+		udelay(JS_N64_DWS);
 	}
+	restore_flags(flags);
+
+/*
+ * Wait for the pad response to be loaded into the 33-bit register of the adapter
+ */
+
+	udelay(JS_N64_DELAY);
+
+/*
+ * Grab data (ignoring the last bit, which is a stop bit)
+ */
+
+	for (i = 0; i < JS_N64_LENGTH; i++) {
+		JS_PAR_DATA_OUT(JS_N64_POWER_R, info->port);
+		data[i] = JS_PAR_STATUS(info->port);
+		JS_PAR_DATA_OUT(JS_N64_POWER_R | JS_N64_CLOCK, info->port);
+	 }
+
+/*
+ * We must wait ~0.2 ms here for the controller to reinitialize before the next read request.
+ * No worries as long as js_console_read is polled less frequently than this.
+ */
+
 }
 
 /*
@@ -161,7 +253,9 @@
 	for (i = 0; i < length; i++) {
 		JS_PAR_DATA_OUT(~(1 << i), info->port);
 		data[i] = JS_PAR_STATUS(info->port) ^ ~JS_PAR_STATUS_INVERT;
+		printk(" %d", data[i]);
 	}
+	printk("\n");
 }
 
 /*
@@ -169,27 +263,28 @@
  */
 
 #define JS_PSX_DELAY	10
+#define JS_PSX_LENGTH	8    /* talk to the controller in bytes */
 
-#define JS_PSX_LENGTH	8
-
-#define JS_PSX_NORMAL	0x41
-#define JS_PSX_NEGCON	0x23
-#define JS_PSX_MOUSE	0x12
-
-#define JS_PSX_SELBUT	0x01
+#define JS_PSX_NORMAL	0x41 /* Standard Digital controller */
+#define JS_PSX_NEGCON	0x23 /* NegCon pad */
+#define JS_PSX_MOUSE	0x12 /* PSX Mouse */
+#define JS_PSX_ANALOGR	0x73 /* Analog controller in Red mode */
+#define JS_PSX_ANALOGG	0x53 /* Analog controller in Green mode */
+
+#define JS_PSX_JOYR	0x02 /* These are for the Analog/Dual Shock controller in RED mode */
+#define JS_PSX_JOYL	0x04 /* I'm not sure the exact purpose of these but its in the docs */
+#define JS_PSX_SELBUT	0x01 /* Standard buttons on almost all PSX controllers. */
 #define JS_PSX_START	0x08
-#define JS_PSX_UP	0x10
+#define JS_PSX_UP	0x10 /* Digital direction pad */
 #define JS_PSX_RIGHT	0x20
 #define JS_PSX_DOWN	0x40
 #define JS_PSX_LEFT	0x80
 
-#define JS_PSX_CLOCK	0x01
-#define JS_PSX_COMMAND	0x02
-#define JS_PSX_POWER	0xf8
-#define JS_PSX_NOPOWER	0x04
-#define JS_PSX_SELECT	0x08
-
-#define JS_PSX_CTRL_OUT(X,Y)	JS_PAR_CTRL_OUT((X)^0x0f, Y)
+#define JS_PSX_CLOCK	0x04 /* Pin 3 */
+#define JS_PSX_COMMAND	0x01 /* Pin 1 */
+#define JS_PSX_POWER	0xf8 /* Pins 5-9 */
+#define JS_PSX_SELECT	0x02 /* Pin 2 */
+#define JS_PSX_NOPOWER  0x04
 
 /*
  * js_psx_command() writes 8bit command and reads 8bit data from
@@ -202,11 +297,11 @@
 
 	cmd = (b&1)?JS_PSX_COMMAND:0;
 	for (i=0; i<8; i++) {
-		JS_PSX_CTRL_OUT(cmd, info->port);
+		JS_PAR_DATA_OUT(cmd | JS_PSX_POWER, info->port);
 		udelay(JS_PSX_DELAY);
 		ret |= ((JS_PAR_STATUS(info->port) ^ JS_PAR_STATUS_INVERT ) & info->psx) ? (1<<i) : 0;
 		cmd = (b&1)?JS_PSX_COMMAND:0;
-		JS_PSX_CTRL_OUT(JS_PSX_CLOCK | cmd, info->port);
+		JS_PAR_DATA_OUT(cmd | JS_PSX_CLOCK | JS_PSX_POWER, info->port);
 		udelay(JS_PSX_DELAY);
 		b >>= 1;
 	}
@@ -228,7 +323,7 @@
 
 	JS_PAR_DATA_OUT(JS_PSX_POWER, info->port);
 
-	JS_PSX_CTRL_OUT(JS_PSX_CLOCK | JS_PSX_SELECT, info->port);	/* Select pad */
+	JS_PAR_DATA_OUT(JS_PSX_CLOCK | JS_PSX_SELECT | JS_PSX_POWER, info->port);	/* Select pad */
 	udelay(JS_PSX_DELAY*2);
 	js_psx_command(info, 0x01);					/* Access pad */
 	ret = js_psx_command(info, 0x42);				/* Get device id */
@@ -237,7 +332,7 @@
 			data[i]=js_psx_command(info, 0);
 	else ret = -1;
 
-	JS_PSX_CTRL_OUT(JS_PSX_SELECT | JS_PSX_CLOCK, info->port);
+	JS_PAR_DATA_OUT(JS_PSX_SELECT | JS_PSX_CLOCK | JS_PSX_POWER, info->port);
 	__restore_flags(flags);
 
 	return ret;
@@ -248,14 +343,14 @@
  * js_console_read() reads and analyzes console pads data.
  */
 
-#define JS_MAX_LENGTH JS_SNES_LENGTH
+#define JS_MAX_LENGTH JS_N64_LENGTH
 
 static int js_console_read(void *xinfo, int **axes, int **buttons)
 {
 	struct js_console_info *info = xinfo;
 	unsigned char data[JS_MAX_LENGTH];
 
-	int i, s;
+	int i, j, s;
 	int n = 0;
 
 /*
@@ -268,24 +363,68 @@
 
 		for (i = 0; i < 5; i++) {
 			s = status_bit[i];
+			n = info->pad_to_device[i];
 			if (info->nes & s) {
 				axes[n][0] = (data[JS_SNES_RIGHT]&s?1:0) - (data[JS_SNES_LEFT]&s?1:0);
 				axes[n][1] = (data[JS_SNES_DOWN] &s?1:0) - (data[JS_SNES_UP]  &s?1:0);
 
-				buttons[n][0] = ((data[JS_NES_A]    &s)?1:0) | ((data[JS_NES_B]     &s)?2:0)
-					      | ((data[JS_NES_START]&s)?4:0) | ((data[JS_NES_SELECT]&s)?8:0);
-
-				n++;
+				buttons[n][0] = (data[JS_NES_A]    &s?1:0) | (data[JS_NES_B]     &s?2:0)
+					      | (data[JS_NES_START]&s?4:0) | (data[JS_NES_SELECT]&s?8:0);
 			} else
 			if (info->snes & s) {
 				axes[n][0] = (data[JS_SNES_RIGHT]&s?1:0) - (data[JS_SNES_LEFT]&s?1:0);
 				axes[n][1] = (data[JS_SNES_DOWN] &s?1:0) - (data[JS_SNES_UP]  &s?1:0);
 
-				buttons[n][0] = ((data[JS_SNES_A]    &s)?0x01:0) | ((data[JS_SNES_B]     &s)?0x02:0)
-					      | ((data[JS_SNES_X]    &s)?0x04:0) | ((data[JS_SNES_Y]     &s)?0x08:0)
-					      | ((data[JS_SNES_L]    &s)?0x10:0) | ((data[JS_SNES_R]     &s)?0x20:0)
-					      | ((data[JS_SNES_START]&s)?0x40:0) | ((data[JS_SNES_SELECT]&s)?0x80:0);
-				n++;
+				buttons[n][0] = (data[JS_SNES_A]    &s?0x01:0) | (data[JS_SNES_B]     &s?0x02:0)
+					      | (data[JS_SNES_X]    &s?0x04:0) | (data[JS_SNES_Y]     &s?0x08:0)
+					      | (data[JS_SNES_L]    &s?0x10:0) | (data[JS_SNES_R]     &s?0x20:0)
+					      | (data[JS_SNES_START]&s?0x40:0) | (data[JS_SNES_SELECT]&s?0x80:0);
+			}
+		}
+	}
+
+/*
+ * N64 pads
+ */
+
+	if (info->n64) {
+		if ( (info->nes || info->snes) && (info->n64 & status_bit[0]) ) {
+					/* SNES/NES compatibility */
+			udelay(240);	/* 200 us delay + 20% tolerance */
+		}
+
+		js_n64_read_packet(info, data);
+
+		for (i = 0; i < 5; i++) {
+			s = status_bit[i];
+			n = info->pad_to_device[i];
+			if (info->n64 & s & ~(data[JS_N64_UNUSED1] | data[JS_N64_UNUSED2])) {
+
+				buttons[n][0] = ( ((data[JS_N64_A]&s) ? 0x01:0) | ((data[JS_N64_B] & s ) ? 0x02:0) 
+						| ((data[JS_N64_Z]&s) ? 0x04:0) | ((data[JS_N64_L] & s ) ? 0x08:0) 
+						| ((data[JS_N64_R]&s) ? 0x10:0) | ((data[JS_N64_START]&s)? 0x20:0)
+						| ((data[JS_N64_CU]&s)? 0x40:0) | ((data[JS_N64_CR]&s)   ? 0x80:0)
+						| ((data[JS_N64_CD]&s)?0x100:0) | ((data[JS_N64_CL]&s)   ?0x200:0) );
+
+				if (info->n64_dpp & s) { 
+					buttons[n][0] |= ((data[JS_N64_LEFT]&s) ? 0x400:0) | ((data[JS_N64_UP] & s)? 0x800:0)
+							|((data[JS_N64_RIGHT]&s)?0x1000:0) | ((data[JS_N64_DOWN]&s)?0x2000:0);
+				} else {
+					axes[n][2] = (data[JS_N64_RIGHT]&s?1:0) - (data[JS_N64_LEFT]&s?1:0);
+					axes[n][3] = (data[JS_N64_DOWN] &s?1:0) - (data[JS_N64_UP]  &s?1:0);
+				}
+
+						/* build int from bits of signed 8-bit int's */
+				j = 7;
+				axes[n][0] = (data[JS_N64_X - j] & s) ? ~0x7f : 0;
+				axes[n][1] = (data[JS_N64_Y - j] & s) ? ~0x7f : 0;
+				while ( j-- > 0 ) {
+					axes[n][0] |= (data[JS_N64_X - j] & s) ? (1 << j) : 0; 
+					axes[n][1] |= (data[JS_N64_Y - j] & s) ? (1 << j) : 0; 
+				}
+						/* flip Y-axis for conformity */
+				axes[n][1] = -axes[n][1];
+
 			}
 		}
 	}
@@ -300,21 +439,18 @@
 
 		for (i = 0; i < 5; i++) {
 			s = status_bit[i];
+			n = info->pad_to_device[i];
 			if (info->multi & s) {
 				axes[n][0] = (data[JS_MULTI_RIGHT]&s?1:0) - (data[JS_MULTI_LEFT]&s?1:0);
 				axes[n][1] = (data[JS_MULTI_DOWN] &s?1:0) - (data[JS_MULTI_UP]  &s?1:0);
 
 				buttons[n][0] = (data[JS_MULTI_BUTTON]&s)?1:0;
-
-				n++;
 			} else
 			if (info->multi2 & s) {
 				axes[n][0] = (data[JS_MULTI_RIGHT]&s?1:0) - (data[JS_MULTI_LEFT]&s?1:0);
 				axes[n][1] = (data[JS_MULTI_DOWN] &s?1:0) - (data[JS_MULTI_UP]  &s?1:0);
 
 				buttons[n][0] = (data[JS_MULTI_BUTTON]&s)?1:0 | (data[JS_MULTI_BUTTON2]&s)?2:0;
-
-				n++;
 			}
 		}
 	}
@@ -323,18 +459,44 @@
  * PSX controllers
  */
 
-	if (info->psx && (js_psx_read_packet(info, 2, data) == JS_PSX_NORMAL)) {	/* FIXME? >1 PSX pads? */
+	if (info->psx) {
+
+		for ( i = 0; i < 5; i++ )
+	       		if ( info->psx & status_bit[i] ) {
+				n = info->pad_to_device[i];
+				break;
+			}
+
+		buttons[n][0] = 0;
+
+ 		switch (js_psx_read_packet(info, 6, data)) {
 
-		axes[n][0] = (data[0]&JS_PSX_RIGHT?0:1) - (data[0]&JS_PSX_LEFT?0:1);
-		axes[n][1] = (data[0]&JS_PSX_DOWN ?0:1) - (data[0]&JS_PSX_UP  ?0:1);
+			case JS_PSX_ANALOGR:
 
-		buttons[n][0] = ((~data[1]&0xf)<<4) | ((~data[1]&0xf0)>>4) |
-				(data[0]&JS_PSX_START?0:0x200) | (data[0]&JS_PSX_SELBUT?0:0x100);
+				buttons[n][0] |= (data[0]&JS_PSX_JOYL?0:0x800) | (data[0]&JS_PSX_JOYR?0:0x400);
 
-		n++;
+			case JS_PSX_ANALOGG:
+	
+				axes[n][2] = data[2];
+				axes[n][3] = data[3];
+				axes[n][4] = data[4];
+				axes[n][5] = data[5];
+
+			case JS_PSX_NORMAL:
+			case JS_PSX_NEGCON:
+
+				axes[n][0] = (data[0]&JS_PSX_RIGHT?0:1) - (data[0]&JS_PSX_LEFT?0:1);
+				axes[n][1] = (data[0]&JS_PSX_DOWN ?0:1) - (data[0]&JS_PSX_UP  ?0:1);
+
+				buttons[n][0] |= ((~data[1]&0xf)<<4) | ((~data[1]&0xf0)>>4) |
+					(data[0]&JS_PSX_START?0:0x200) | (data[0]&JS_PSX_SELBUT?0:0x100);
+		
+				break;
+
+		}
 	}
 
-	return -(n != info->pads);
+	return 0;
 }
 
 /*
@@ -343,10 +505,8 @@
 
 int js_console_open(struct js_dev *dev)
 {
-#ifdef USE_PARPORT
 	struct js_console_info *info = dev->port->info;
 	if (!MOD_IN_USE && parport_claim(info->port)) return -EBUSY;
-#endif
 	MOD_INC_USE_COUNT;
 	return 0;
 }
@@ -357,13 +517,9 @@
 
 int js_console_close(struct js_dev *dev)
 {
-#ifdef USE_PARPORT
 	struct js_console_info *info = dev->port->info;
-#endif
 	MOD_DEC_USE_COUNT;
-#ifdef USE_PARPORT
 	if (!MOD_IN_USE) parport_release(info->port);
-#endif
 	return 0;
 }
 
@@ -373,16 +529,12 @@
 	struct js_console_info *info;
 	int i;
 
-	while (js_console_port != NULL) {
+	while (js_console_port) {
 		for (i = 0; i < js_console_port->ndevs; i++)
-			if (js_console_port->devs[i] != NULL)
+			if (js_console_port->devs[i])
 				js_unregister_device(js_console_port->devs[i]);
 		info = js_console_port->info;
-#ifdef USE_PARPORT
 		parport_unregister_device(info->port);
-#else
-		release_region(info->port, 3);
-#endif
 		js_console_port = js_unregister_port(js_console_port);
 	}
 }
@@ -393,7 +545,7 @@
  * console gamepads.
  */
 
-static void __init js_console_init_corr(int num_axes, struct js_corr *corr)
+static void __init js_console_init_corr(int num_axes, int type, struct js_corr *corr)
 {
 	int i;
 
@@ -405,6 +557,28 @@
 		corr[i].coef[2] = (1 << 29);
 		corr[i].coef[3] = (1 << 29);
 	}
+
+	if (type == JS_N64_PAD || type == JS_N64_PAD_DPP) {
+		for (i = 0; i < 2; i++) {
+			corr[i].type = JS_CORR_BROKEN;
+			corr[i].prec = 0;
+			corr[i].coef[0] = 0;
+			corr[i].coef[1] = 0;
+			corr[i].coef[2] = (1 << 22);
+			corr[i].coef[3] = (1 << 22);
+		}
+	}
+
+	if (type == JS_PSX_ANALOGG || type == JS_PSX_ANALOGR) {
+		for (i = 2; i < 6; i++)  {
+			corr[i].type = JS_CORR_BROKEN;
+			corr[i].prec = 0;
+			corr[i].coef[0] = 127 - 2;
+			corr[i].coef[1] = 128 + 2;
+			corr[i].coef[2] = (1 << 29) / (127 - 4);
+			corr[i].coef[3] = (1 << 29) / (127 - 4);
+		}
+	}
 }
 
 /*
@@ -415,45 +589,40 @@
 static struct js_port __init *js_console_probe(int *config, struct js_port *port)
 {
 	char *name[5];
-	int i, psx, axes[5], buttons[5];
+	int i, psx, axes[5], buttons[5], type[5];
 	unsigned char data[2];			/* used for PSX probe */
 	struct js_console_info info;
+	struct parport *pp;
 
 	memset(&info, 0, sizeof(struct js_console_info));
 
 	if (config[0] < 0) return port;
 
-#ifdef USE_PARPORT
-	{
-		struct parport *pp;
-
-		if (config[0] > 0x10)
-			for (pp=parport_enumerate(); pp != NULL && (pp->base!=config[0]); pp=pp->next);
-		else
-			for (pp=parport_enumerate(); pp != NULL && (config[0]>0); pp=pp->next) config[0]--;
-
-		if (pp == NULL) {
-			printk(KERN_ERR "joy-console: no such parport\n");
-			return port;
-		}
+	if (config[0] > 0x10)
+		for (pp=parport_enumerate(); pp && (pp->base!=config[0]); pp=pp->next);
+	else
+		for (pp=parport_enumerate(); pp && (config[0]>0); pp=pp->next) config[0]--;
 
-		info.port = parport_register_device(pp, "joystick (console)", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
-		if (!info.port)
-			return port;
+	if (!pp) {
+		printk(KERN_ERR "joy-console: no such parport\n");
+		return port;
 	}
 
+	info.port = parport_register_device(pp, "joystick (console)", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
+	if (!info.port)
+		return port;
+
 	if (parport_claim(info.port))
 	{
 		parport_unregister_device(info.port);	/* port currently not available ... */
 		return port;
 	}
-#else
-	info.port = config[0];
-	if (check_region(info.port, 3)) return port;
-	request_region(info.port, 3, "joystick (console pad)");
-#endif
 
-	for (i = 0; i < 5; i++)
+	for (i = 0; i < 5; i++) {
+
+		type[info.pads] = config[i+1];
+		info.pad_to_device[i] = info.pads;
+
 		switch(config[i+1]) {
 
 			case JS_NO_PAD:
@@ -478,6 +647,23 @@
 				info.pads++;
 				break;
 
+			case JS_N64_PAD:
+				axes[info.pads]    = 4;
+				buttons[info.pads] = 10;
+				name[info.pads]    = "N64 pad";
+				info.n64 |= status_bit[i];
+				info.pads++;
+				break;
+
+			case JS_N64_PAD_DPP:
+				axes[info.pads]    = 2;
+				buttons[info.pads] = 14;
+				name[info.pads]    = "N64 pad (DPP mode)";
+				info.n64 |= status_bit[i];
+				info.n64_dpp |= status_bit[i];
+				info.pads++;
+				break;
+				
 			case JS_MULTI_STICK:
 
 				axes[info.pads]    = 2;
@@ -497,31 +683,58 @@
 				break;
 
 			case JS_PSX_PAD:
-
+				
 				info.psx |= status_bit[i];
 				psx = js_psx_read_packet(&info, 2, data);
 				psx = js_psx_read_packet(&info, 2, data);
 				info.psx &= ~status_bit[i];
 
+				type[i] = psx;
+
 				switch(psx) {
 					case JS_PSX_NORMAL:
 						axes[info.pads]    = 2;
 						buttons[info.pads] = 10;
-						name[info.pads]    = "PSX controller";
+						name[info.pads]    = "PSX pad";
 						info.psx |= status_bit[i];
 						info.pads++;
 						break;
+
+					case JS_PSX_ANALOGR:
+						axes[info.pads]    = 6;
+						buttons[info.pads] = 12;
+						name[info.pads]    = "Analog Red PSX pad";
+						info.psx |= status_bit[i];
+						info.pads++;
+						break;
+
+					case JS_PSX_ANALOGG:
+						axes[info.pads]    = 6;
+						buttons[info.pads] = 10;
+						name[info.pads]    = "Analog Green PSX pad";
+						info.psx |= status_bit[i];
+						info.pads++;
+						break;
+
 					case JS_PSX_NEGCON:
-						printk(KERN_WARNING "joy-console: NegCon not yet supported...\n");
+						axes[info.pads]    = 2;
+						buttons[info.pads] = 10;
+						name[info.pads]    = "NegCon PSX pad";
+						info.psx |= status_bit[i];
+						info.pads++;
 						break;
+
 					case JS_PSX_MOUSE:
-						printk(KERN_WARNING "joy-console: PSX mouse not supported...\n");
+						printk(KERN_WARNING "joy-psx: PSX mouse not supported...\n");
 						break;
+
 					case -1:
-						printk(KERN_ERR "joy-console: no PSX controller found...\n");
+						printk(KERN_ERR "joy-psx: no PSX controller found...\n");
 						break;
+
 					default:
-						printk(KERN_WARNING "joy-console: unknown PSX controller 0x%x\n", psx);
+						printk(KERN_WARNING "joy-psx: PSX controller unknown: 0x%x,"
+							" please report to <vojtech@suse.cz>.\n", psx);
 				}
 				break;
 
@@ -529,52 +742,53 @@
 
 				printk(KERN_WARNING "joy-console: pad type %d unknown\n", config[i+1]);
 		}
+	}
 
 	if (!info.pads) {
-#ifdef USE_PARPORT
 		parport_release(info.port);
 		parport_unregister_device(info.port);
-#else
-		release_region(info.port, 3);
-#endif
 		return port;
 	}
 
 	port = js_register_port(port, &info, info.pads, sizeof(struct js_console_info), js_console_read);
 
 	for (i = 0; i < info.pads; i++) {
-#ifdef USE_PARPORT
 		printk(KERN_INFO "js%d: %s on %s\n",
 			js_register_device(port, i, axes[i], buttons[i], name[i], js_console_open, js_console_close),
 			name[i], info.port->port->name);
-#else
-		printk(KERN_INFO "js%d: %s at %#x\n",
-			js_register_device(port, i, axes[i], buttons[i], name[i], js_console_open, js_console_close),
-			name[i], info.port);
-#endif
 
-		js_console_init_corr(axes[i], port->corr[i]);
+		js_console_init_corr(axes[i], type[i], port->corr[i]);
 	}
 
-#ifdef USE_PARPORT
 	parport_release(info.port);
-#endif
 	return port;
 }
 
 #ifndef MODULE
-void __init js_console_setup(char *str, int *ints)
+int __init js_console_setup(SETUP_PARAM)
 {
 	int i;
-
-	if (!strcmp(str,"js_console"))
-		for (i = 0; i <= ints[0] && i < 6; i++) js_console[i] = ints[i+1];
-	if (!strcmp(str,"js_console2"))
-		for (i = 0; i <= ints[0] && i < 6; i++) js_console2[i] = ints[i+1];
-	if (!strcmp(str,"js_console3"))
-		for (i = 0; i <= ints[0] && i < 6; i++) js_console3[i] = ints[i+1];
-
+	SETUP_PARSE(6);
+	for (i = 0; i <= ints[0] && i < 6; i++) js_console[i] = ints[i+1];
+	return 1;
 }
+int __init js_console_setup_2(SETUP_PARAM)
+{
+	int i;
+	SETUP_PARSE(6);
+	for (i = 0; i <= ints[0] && i < 6; i++) js_console_2[i] = ints[i+1];
+	return 1;
+}
+int __init js_console_setup_3(SETUP_PARAM)
+{
+	int i;
+	SETUP_PARSE(6);
+	for (i = 0; i <= ints[0] && i < 6; i++) js_console_3[i] = ints[i+1];
+	return 1;
+}
+__setup("js_console=", js_console_setup);
+__setup("js_console_2=", js_console_setup_2);
+__setup("js_console_3=", js_console_setup_3);
 #endif
 
 #ifdef MODULE
@@ -584,8 +798,8 @@
 #endif
 {
 	js_console_port = js_console_probe(js_console, js_console_port);
-	js_console_port = js_console_probe(js_console2, js_console_port);
-	js_console_port = js_console_probe(js_console3, js_console_port);
+	js_console_port = js_console_probe(js_console_2, js_console_port);
+	js_console_port = js_console_probe(js_console_3, js_console_port);
 
 	if (js_console_port) return 0;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)