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