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