xref: /rk3399_rockchip-uboot/drivers/input/ps2mult.c (revision 16b195c82a18cbfd164800f17a1ef9db2e48331a)
1*16b195c8SJean-Christophe PLAGNIOL-VILLARD /***********************************************************************
2*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
3*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * (C) Copyright 2004
4*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * DENX Software Engineering
5*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Wolfgang Denk, wd@denx.de
6*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * All rights reserved.
7*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
8*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * PS/2 multiplexer driver
9*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
10*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Originally from linux source (drivers/char/ps2mult.c)
11*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
12*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Uses simple serial driver (ps2ser.c) to access the multiplexer
13*16b195c8SJean-Christophe PLAGNIOL-VILLARD  * Used by PS/2 keyboard driver (pc_keyb.c)
14*16b195c8SJean-Christophe PLAGNIOL-VILLARD  *
15*16b195c8SJean-Christophe PLAGNIOL-VILLARD  ***********************************************************************/
16*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
17*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <common.h>
18*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
19*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef CONFIG_PS2MULT
20*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
21*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <pc_keyb.h>
22*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <asm/atomic.h>
23*16b195c8SJean-Christophe PLAGNIOL-VILLARD #include <ps2mult.h>
24*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
25*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* #define DEBUG_MULT */
26*16b195c8SJean-Christophe PLAGNIOL-VILLARD /* #define DEBUG_KEYB */
27*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
28*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define KBD_STAT_DEFAULT		(KBD_STAT_SELFTEST | KBD_STAT_UNLOCKED)
29*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
30*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PRINTF(format, args...)		printf("ps2mult.c: " format, ## args)
31*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
32*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_MULT
33*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PRINTF_MULT(format, args...)	printf("PS2MULT: " format, ## args)
34*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
35*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PRINTF_MULT(format, args...)
36*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
37*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
38*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_KEYB
39*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PRINTF_KEYB(format, args...)	printf("KEYB: " format, ## args)
40*16b195c8SJean-Christophe PLAGNIOL-VILLARD #else
41*16b195c8SJean-Christophe PLAGNIOL-VILLARD #define PRINTF_KEYB(format, args...)
42*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
43*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
44*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
45*16b195c8SJean-Christophe PLAGNIOL-VILLARD static ulong start_time;
46*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int init_done = 0;
47*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
48*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int received_escape = 0;
49*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int received_bsync = 0;
50*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int received_selector = 0;
51*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
52*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int kbd_command_active = 0;
53*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int mouse_command_active = 0;
54*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ctl_command_active = 0;
55*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
56*16b195c8SJean-Christophe PLAGNIOL-VILLARD static u_char command_byte = 0;
57*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
58*16b195c8SJean-Christophe PLAGNIOL-VILLARD static void (*keyb_handler)(void *dev_id);
59*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
60*16b195c8SJean-Christophe PLAGNIOL-VILLARD static u_char ps2mult_buf [PS2BUF_SIZE];
61*16b195c8SJean-Christophe PLAGNIOL-VILLARD static atomic_t ps2mult_buf_cnt;
62*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2mult_buf_in_idx;
63*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2mult_buf_out_idx;
64*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
65*16b195c8SJean-Christophe PLAGNIOL-VILLARD static u_char ps2mult_buf_status [PS2BUF_SIZE];
66*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
67*16b195c8SJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_BOARD_EARLY_INIT_R
68*16b195c8SJean-Christophe PLAGNIOL-VILLARD #error #define CONFIG_BOARD_EARLY_INIT_R and call ps2mult_early_init() in board_early_init_r()
69*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
70*16b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2mult_early_init (void)
71*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
72*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	start_time = get_timer(0);
73*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
74*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
75*16b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2mult_send_byte(u_char byte, u_char sel)
76*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
77*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_putc(sel);
78*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
79*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (sel == PS2MULT_KB_SELECTOR) {
80*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF_MULT("0x%02x send KEYBOARD\n", byte);
81*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		kbd_command_active = 1;
82*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} else {
83*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF_MULT("0x%02x send MOUSE\n", byte);
84*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		mouse_command_active = 1;
85*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
86*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
87*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	switch (byte) {
88*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_ESCAPE:
89*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_BSYNC:
90*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_KB_SELECTOR:
91*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_MS_SELECTOR:
92*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_SESSION_START:
93*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_SESSION_END:
94*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2ser_putc(PS2MULT_ESCAPE);
95*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
96*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	default:
97*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
98*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
99*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
100*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_putc(byte);
101*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
102*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
103*16b195c8SJean-Christophe PLAGNIOL-VILLARD static void ps2mult_receive_byte(u_char byte, u_char sel)
104*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
105*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	u_char status = KBD_STAT_DEFAULT;
106*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
107*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if 1 /* Ignore mouse in U-Boot */
108*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (sel == PS2MULT_MS_SELECTOR) return;
109*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
110*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
111*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (sel == PS2MULT_KB_SELECTOR) {
112*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (kbd_command_active) {
113*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			if (!received_bsync) {
114*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				PRINTF_MULT("0x%02x lost KEYBOARD !!!\n", byte);
115*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				return;
116*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			} else {
117*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				kbd_command_active = 0;
118*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				received_bsync = 0;
119*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			}
120*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
121*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF_MULT("0x%02x receive KEYBOARD\n", byte);
122*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		status |= KBD_STAT_IBF | KBD_STAT_OBF;
123*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} else {
124*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (mouse_command_active) {
125*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			if (!received_bsync) {
126*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				PRINTF_MULT("0x%02x lost MOUSE !!!\n", byte);
127*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				return;
128*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			} else {
129*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				mouse_command_active = 0;
130*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				received_bsync = 0;
131*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			}
132*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
133*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF_MULT("0x%02x receive MOUSE\n", byte);
134*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		status |= KBD_STAT_IBF | KBD_STAT_OBF | KBD_STAT_MOUSE_OBF;
135*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
136*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
137*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (atomic_read(&ps2mult_buf_cnt) < PS2BUF_SIZE) {
138*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_buf_status[ps2mult_buf_in_idx] = status;
139*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_buf[ps2mult_buf_in_idx++] = byte;
140*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_buf_in_idx &= (PS2BUF_SIZE - 1);
141*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		atomic_inc(&ps2mult_buf_cnt);
142*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} else {
143*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF("buffer overflow\n");
144*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
145*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
146*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (received_bsync) {
147*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF("unexpected BSYNC\n");
148*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		received_bsync = 0;
149*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
150*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
151*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
152*16b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2mult_callback (int in_cnt)
153*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
154*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int i;
155*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	u_char byte;
156*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	static int keyb_handler_active = 0;
157*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
158*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (!init_done) {
159*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		return;
160*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
161*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
162*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < in_cnt; i ++) {
163*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = ps2ser_getc();
164*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
165*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (received_escape) {
166*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2mult_receive_byte(byte, received_selector);
167*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			received_escape = 0;
168*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		} else switch (byte) {
169*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case PS2MULT_ESCAPE:
170*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			PRINTF_MULT("ESCAPE receive\n");
171*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			received_escape = 1;
172*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
173*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
174*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case PS2MULT_BSYNC:
175*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			PRINTF_MULT("BSYNC receive\n");
176*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			received_bsync = 1;
177*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
178*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
179*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case PS2MULT_KB_SELECTOR:
180*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case PS2MULT_MS_SELECTOR:
181*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			PRINTF_MULT("%s receive\n",
182*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			    byte == PS2MULT_KB_SELECTOR ? "KB_SEL" : "MS_SEL");
183*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			received_selector = byte;
184*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
185*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
186*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case PS2MULT_SESSION_START:
187*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case PS2MULT_SESSION_END:
188*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			PRINTF_MULT("%s receive\n",
189*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			    byte == PS2MULT_SESSION_START ?
190*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			    "SESSION_START" : "SESSION_END");
191*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
192*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
193*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		default:
194*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2mult_receive_byte(byte, received_selector);
195*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
196*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
197*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
198*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (keyb_handler && !keyb_handler_active &&
199*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	    atomic_read(&ps2mult_buf_cnt)) {
200*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		keyb_handler_active = 1;
201*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		keyb_handler(NULL);
202*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		keyb_handler_active = 0;
203*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
204*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
205*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
206*16b195c8SJean-Christophe PLAGNIOL-VILLARD u_char ps2mult_read_status(void)
207*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
208*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	u_char byte;
209*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
210*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (atomic_read(&ps2mult_buf_cnt) == 0) {
211*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2ser_check();
212*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
213*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
214*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (atomic_read(&ps2mult_buf_cnt)) {
215*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = ps2mult_buf_status[ps2mult_buf_out_idx];
216*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} else {
217*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = KBD_STAT_DEFAULT;
218*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
219*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	PRINTF_KEYB("read_status()=0x%02x\n", byte);
220*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return byte;
221*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
222*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
223*16b195c8SJean-Christophe PLAGNIOL-VILLARD u_char ps2mult_read_input(void)
224*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
225*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	u_char byte = 0;
226*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
227*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (atomic_read(&ps2mult_buf_cnt) == 0) {
228*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2ser_check();
229*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
230*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
231*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (atomic_read(&ps2mult_buf_cnt)) {
232*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = ps2mult_buf[ps2mult_buf_out_idx++];
233*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_buf_out_idx &= (PS2BUF_SIZE - 1);
234*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		atomic_dec(&ps2mult_buf_cnt);
235*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
236*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	PRINTF_KEYB("read_input()=0x%02x\n", byte);
237*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return byte;
238*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
239*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
240*16b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2mult_write_output(u_char val)
241*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
242*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int i;
243*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
244*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	PRINTF_KEYB("write_output(0x%02x)\n", val);
245*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
246*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < KBD_TIMEOUT; i++) {
247*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (!kbd_command_active && !mouse_command_active) {
248*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
249*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
250*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
251*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2ser_check();
252*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
253*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
254*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (kbd_command_active) {
255*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF("keyboard command not acknoledged\n");
256*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		kbd_command_active = 0;
257*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
258*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
259*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (mouse_command_active) {
260*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF("mouse command not acknoledged\n");
261*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		mouse_command_active = 0;
262*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
263*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
264*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (ctl_command_active) {
265*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		switch (ctl_command_active) {
266*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case KBD_CCMD_WRITE_MODE:
267*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			  /* Scan code conversion not supported */
268*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			command_byte = val & ~KBD_MODE_KCC;
269*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
270*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
271*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case KBD_CCMD_WRITE_AUX_OBUF:
272*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2mult_receive_byte(val, PS2MULT_MS_SELECTOR);
273*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
274*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
275*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		case KBD_CCMD_WRITE_MOUSE:
276*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2mult_send_byte(val, PS2MULT_MS_SELECTOR);
277*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
278*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
279*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		default:
280*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			PRINTF("invalid controller command\n");
281*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
282*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
283*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
284*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ctl_command_active = 0;
285*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		return;
286*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
287*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
288*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2mult_send_byte(val, PS2MULT_KB_SELECTOR);
289*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
290*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
291*16b195c8SJean-Christophe PLAGNIOL-VILLARD void ps2mult_write_command(u_char val)
292*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
293*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ctl_command_active = 0;
294*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
295*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	PRINTF_KEYB("write_command(0x%02x)\n", val);
296*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
297*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	switch (val) {
298*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_READ_MODE:
299*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_receive_byte(command_byte, PS2MULT_KB_SELECTOR);
300*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
301*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
302*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_WRITE_MODE:
303*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ctl_command_active = val;
304*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
305*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
306*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_MOUSE_DISABLE:
307*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
308*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
309*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_MOUSE_ENABLE:
310*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
311*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
312*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_SELF_TEST:
313*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_receive_byte(0x55, PS2MULT_KB_SELECTOR);
314*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
315*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
316*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_KBD_TEST:
317*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ps2mult_receive_byte(0x00, PS2MULT_KB_SELECTOR);
318*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
319*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
320*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_KBD_DISABLE:
321*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
322*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
323*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_KBD_ENABLE:
324*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
325*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
326*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_WRITE_AUX_OBUF:
327*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ctl_command_active = val;
328*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
329*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
330*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case KBD_CCMD_WRITE_MOUSE:
331*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		ctl_command_active = val;
332*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
333*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
334*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	default:
335*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		PRINTF("invalid controller command\n");
336*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
337*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
338*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
339*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
340*16b195c8SJean-Christophe PLAGNIOL-VILLARD static int ps2mult_getc_w (void)
341*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
342*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int res = -1;
343*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int i;
344*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
345*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	for (i = 0; i < KBD_TIMEOUT; i++) {
346*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (ps2ser_check()) {
347*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			res = ps2ser_getc();
348*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			break;
349*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
350*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		udelay(1000);
351*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
352*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
353*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	switch (res) {
354*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_KB_SELECTOR:
355*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	case PS2MULT_MS_SELECTOR:
356*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		received_selector = res;
357*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
358*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	default:
359*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		break;
360*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
361*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
362*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return res;
363*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
364*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
365*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2mult_init (void)
366*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
367*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int byte;
368*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int kbd_found = 0;
369*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	int mouse_found = 0;
370*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
371*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	while (get_timer(start_time) < CONFIG_PS2MULT_DELAY);
372*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
373*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_init();
374*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
375*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_putc(PS2MULT_SESSION_START);
376*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
377*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_putc(PS2MULT_KB_SELECTOR);
378*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_putc(KBD_CMD_RESET);
379*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
380*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	do {
381*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = ps2mult_getc_w();
382*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} while (byte >= 0 && byte != KBD_REPLY_ACK);
383*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
384*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (byte == KBD_REPLY_ACK) {
385*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = ps2mult_getc_w();
386*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (byte == 0xaa) {
387*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			kbd_found = 1;
388*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			puts("keyboard");
389*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
390*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
391*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
392*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (!kbd_found) {
393*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		while (byte >= 0) {
394*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			byte = ps2mult_getc_w();
395*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
396*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
397*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
398*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if 1 /* detect mouse */
399*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_putc(PS2MULT_MS_SELECTOR);
400*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	ps2ser_putc(AUX_RESET);
401*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
402*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	do {
403*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = ps2mult_getc_w();
404*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} while (byte >= 0 && byte != AUX_ACK);
405*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
406*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (byte == AUX_ACK) {
407*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		byte = ps2mult_getc_w();
408*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (byte == 0xaa) {
409*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			byte = ps2mult_getc_w();
410*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			if (byte == 0x00) {
411*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				mouse_found = 1;
412*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				puts(", mouse");
413*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			}
414*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
415*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
416*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
417*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (!mouse_found) {
418*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		while (byte >= 0) {
419*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			byte = ps2mult_getc_w();
420*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
421*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
422*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
423*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
424*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	if (mouse_found || kbd_found) {
425*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		if (!received_selector) {
426*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			if (mouse_found) {
427*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				received_selector = PS2MULT_MS_SELECTOR;
428*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			} else {
429*16b195c8SJean-Christophe PLAGNIOL-VILLARD 				received_selector = PS2MULT_KB_SELECTOR;
430*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			}
431*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
432*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
433*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		init_done = 1;
434*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	} else {
435*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		puts("No device found");
436*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
437*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
438*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	puts("\n");
439*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
440*16b195c8SJean-Christophe PLAGNIOL-VILLARD #if 0 /* for testing */
441*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	{
442*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		int i;
443*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		u_char key[] = {
444*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			0x1f, 0x12, 0x14, 0x12, 0x31, 0x2f, 0x39,	/* setenv */
445*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			0x1f, 0x14, 0x20, 0x17, 0x31, 0x39,		/* stdin */
446*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			0x1f, 0x12, 0x13, 0x17, 0x1e, 0x26, 0x1c,	/* serial */
447*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		};
448*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
449*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		for (i = 0; i < sizeof (key); i++) {
450*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2mult_receive_byte (key[i],	     PS2MULT_KB_SELECTOR);
451*16b195c8SJean-Christophe PLAGNIOL-VILLARD 			ps2mult_receive_byte (key[i] | 0x80, PS2MULT_KB_SELECTOR);
452*16b195c8SJean-Christophe PLAGNIOL-VILLARD 		}
453*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	}
454*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif
455*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
456*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return init_done ? 0 : -1;
457*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
458*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
459*16b195c8SJean-Christophe PLAGNIOL-VILLARD int ps2mult_request_irq(void (*handler)(void *))
460*16b195c8SJean-Christophe PLAGNIOL-VILLARD {
461*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	keyb_handler = handler;
462*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
463*16b195c8SJean-Christophe PLAGNIOL-VILLARD 	return 0;
464*16b195c8SJean-Christophe PLAGNIOL-VILLARD }
465*16b195c8SJean-Christophe PLAGNIOL-VILLARD 
466*16b195c8SJean-Christophe PLAGNIOL-VILLARD #endif /* CONFIG_PS2MULT */
467