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