diff options
Diffstat (limited to 'c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c')
-rw-r--r-- | c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c | 1077 |
1 files changed, 0 insertions, 1077 deletions
diff --git a/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c b/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c deleted file mode 100644 index b148c0f389..0000000000 --- a/c/src/lib/libbsp/powerpc/ppcn_60x/console/i8042.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * This file contains the PS2 keyboard driver for the i8042 - * - * Note that this driver will only handle a single i8042 device - * - * COPYRIGHT (c) 1998 by Radstone Technology - * - * - * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY - * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK - * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. - * - * You are hereby granted permission to use, copy, modify, and distribute - * this file, provided that this notice, plus the above copyright notice - * and disclaimer, appears in all copies. Radstone Technology will provide - * no support for this code. - * - * This driver uses the termios pseudo driver. - * - * $Id$ - */ - -#include <rtems.h> -#include <bsp.h> -#include <rtems/libio.h> -#include <libchip/serial.h> -#include <rtems/ringbuf.h> - -#include "console.h" -#include "i8042_p.h" -#include "vga_p.h" - -/* - * UK style keyboard - */ -char pcUKNormalLookup[] = "1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;\'" - "`\0#zxcvbnm,./\0*\0 \0\0\0\0\0\0\0\0\0\0\0\0" - "\000789-456+1230.\0\0\\"; -char pcUKShiftedLookup[]= "!\"£$%^&*()_+\b\tQWERTYUIOP{}\n\0ASDFGHJKL:" - "@\0\0~ZXCVBNM<>?\0*\0 \0\0\0\0\0\0\0\0\0\0\0" - "\0\000789-456+1230.\0\0|"; -/* - * US style keyboard - */ -char pcUSNormalLookup[] = "1234567890-=\b\tqwertyuiop[]\n\0asdfghjkl;\'" - "`\0\\zxcvbnm,./\0*\0 \0\0\0\0\0\0\0\0\0\0\0" - "\0\000789-456+1230.\0\0\\"; -char pcUSShiftedLookup[]= "!@#$%^&*()_+\b\tQWERTYUIOP{}\n\0ASDFGHJKL:@~" - "\0|ZXCVBNM<>?\0*\0 \0\0\0\0\0\0\0\0\0\0\0\0" - "\000789-456+1230.\0\0|"; - -static char *pcNormalLookup; -static char *pcShiftedLookup; - -/* - * This is exported to vga.c to provide flow control - */ -volatile boolean bScrollLock=FALSE; - -/* - * If multiple devices are to be supported then a private copy of - * the following will be required for each instance - */ -static boolean bCtrlPressed=FALSE; -static boolean bAltPressed=FALSE; -static boolean bAltGrPressed=FALSE; -static boolean bLShiftPressed=FALSE; -static boolean bRShiftPressed=FALSE; -static boolean bCapsLock=FALSE; -static boolean bNumLock=FALSE; -static boolean bTwoCode=FALSE; - -#if CONSOLE_USE_INTERRUPTS -static volatile Ring_buffer_t KbdOutputBuffer; -static volatile boolean bProcessInterruptInput=FALSE; -static boolean bInterruptsEnabled=FALSE; -static volatile boolean bReceivedAck=TRUE; - -static void i8042_process( - int minor -); - -static void i8042_scan_code( - int minor, - uint8_t ucScan -); -#endif - -static volatile Ring_buffer_t KbdInputBuffer; - -/* - * The following routines enable an interrupt driver to switch - * to polled mode as required for command processing - */ -void i8042_polled_on( - int minor -) -{ -#if CONSOLE_USE_INTERRUPTS - bProcessInterruptInput=FALSE; -#endif -} - -void i8042_polled_off( - int minor -) -{ -#if CONSOLE_USE_INTERRUPTS - uint32_t Irql; - uint8_t ucScan; - - /* - * Make sure we have processed everything outstanding - */ - rtems_interrupt_disable(Irql); - while(!Ring_buffer_Is_empty(&KbdInputBuffer)) - { - rtems_interrupt_enable(Irql); - Ring_buffer_Remove_character(&KbdInputBuffer, - ucScan); - i8042_scan_code(minor, ucScan); - rtems_interrupt_disable(Irql); - } - bProcessInterruptInput=TRUE; - rtems_interrupt_enable(Irql); -#endif -} - -/* - * Send data to the keyboard - */ -static rtems_status_code -i8042_outbyte_raw( - int minor, - uint8_t ucData -) -{ - uint32_t i; - uint8_t Status; - -#if CONSOLE_USE_INTERRUPTS - uint32_t Irql; - - if(bInterruptsEnabled) - { - Ring_buffer_Add_character(&KbdOutputBuffer, - ucData); - if(!Console_Port_Data[minor].bActive) - { - /* - * Wake up the device - */ - rtems_interrupt_disable(Irql); - Console_Port_Data[minor].bActive=TRUE; - i8042_process(minor); - rtems_interrupt_enable(Irql); - - } - return RTEMS_SUCCESSFUL; - } -#endif - for (i=0; i<KBD_TIMEOUT; i++) - { - inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); - if((Status & KBD_IBF_MASK)==0) - { - outport_byte(Console_Port_Tbl[minor].ulDataPort, - ucData); - return RTEMS_SUCCESSFUL; - } - } - return RTEMS_TIMEOUT; -} - -/* - * Read data from the keyboard - */ -static rtems_status_code -i8042_inbyte_polled( - int minor, - uint8_t *pucData -) -{ - uint8_t Status; - - inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); - if(Status & KBD_OBF_MASK) - { - inport_byte(Console_Port_Tbl[minor].ulDataPort, - *pucData); - return RTEMS_SUCCESSFUL; - } - return RTEMS_TIMEOUT; -} - -/* - * Blocking read data from the keyboard - */ -static rtems_status_code -i8042_inbyte_raw( - int minor, - uint8_t *pucData -) -{ - int i; - -#if CONSOLE_USE_INTERRUPTS - if(bInterruptsEnabled) - { - i=0; - while(Ring_buffer_Is_empty(&KbdInputBuffer)) - { - rtems_task_wake_after(RTEMS_YIELD_PROCESSOR); - if(i++==KBD_TIMEOUT) - { - return RTEMS_TIMEOUT; - } - } - Ring_buffer_Remove_character(&KbdInputBuffer, - *pucData); - } - else -#endif - { - for (i=0; i<KBD_TIMEOUT; i++) - { - if(i8042_inbyte_polled(minor, pucData)== - RTEMS_SUCCESSFUL) - { - return RTEMS_SUCCESSFUL; - } - /* - * Wait for a character to be recieved - */ - } - - return RTEMS_TIMEOUT; - } - - return RTEMS_SUCCESSFUL; -} - -#if CONSOLE_USE_INTERRUPTS - -/* - * Send a command to the keyboard controller - */ -static rtems_status_code -i8042_outbyte_cmd_polled( - int minor, - uint8_t ucCommand -) -{ - uint32_t i; - uint8_t Status; - - /* - * This routine may be called when no clock driver is available - * so the timeout is dependant on the ISA bus timing used to access - * the i8042 which will not vary (much) across platforms. - */ - for (i=0; i<KBD_TIMEOUT; i++) - { - inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); - if((Status & KBD_IBF_MASK)==0) - { - outport_byte(Console_Port_Tbl[minor].ulCtrlPort1, - ucCommand); - return RTEMS_SUCCESSFUL; - } - } - return RTEMS_TIMEOUT; -} -#endif - -void EnqueueKbdChar( - int minor, - char cChar -) -{ -#if CONSOLE_USE_INTERRUPTS - rtems_termios_enqueue_raw_characters( - Console_Port_Data[minor].termios_data, - &cChar, - 1); -#else - Ring_buffer_Add_character(&KbdInputBuffer, cChar); -#endif -} -/* - * Process second code in a two code sequence - */ -static void i8042_process_two_code( - int minor, - uint8_t ucScan, - boolean bMakenBreak -) -{ - char cASCIICtrlCode; - char cASCIICode; - - cASCIICtrlCode='\0'; - cASCIICode='\0'; - - switch(ucScan) - { - case KEY_ALT: - { - bAltGrPressed=bMakenBreak; - break; - } - - case KEY_CONTROL: - { - bCtrlPressed=bMakenBreak; - break; - } - - case KEY_INSERT: - { - cASCIICtrlCode='@'; - break; - } - - case KEY_DELETE: - { - cASCIICode=ASCII_DEL; - break; - } - - case KEY_LEFT_ARROW: - { - cASCIICtrlCode='D'; - break; - } - - case KEY_HOME: - { - cASCIICtrlCode='H'; - break; - } - - case KEY_END: - { - cASCIICtrlCode='K'; - break; - } - - case KEY_UP_ARROW: - { - cASCIICtrlCode='A'; - break; - } - - case KEY_DOWN_ARROW: - { - cASCIICtrlCode='B'; - break; - } - - case KEY_PAGE_UP: - { - cASCIICtrlCode='?'; - break; - } - - case KEY_PAGE_DOWN: - { - cASCIICtrlCode='/'; - break; - } - - case KEY_RIGHT_ARROW: - { - cASCIICtrlCode='C'; - break; - } - - case KEY_KEYPAD_SLASH: - { - cASCIICode='/'; - break; - } - - case KEY_KEYPAD_ENTER: - { - cASCIICode=ASCII_CR; - break; - } - - case KEY_PRINT_SCREEN: - { - cASCIICode=ASCII_SYSRQ; - break; - } - - default: - { - /* - * Ignore this code - */ - break; - } - } - - if(bMakenBreak && cASCIICode) - { - EnqueueKbdChar(minor, cASCIICode); - } - else if(bMakenBreak && cASCIICtrlCode) - { - EnqueueKbdChar(minor, ASCII_CSI); - EnqueueKbdChar(minor, cASCIICtrlCode); - } -} - -static boolean i8042_process_qualifiers( - uint8_t ucScan, - boolean bMakenBreak -) -{ - boolean bProcessed; - - /* - * Check for scan codes for shift, control, or alt keys. - */ - bProcessed=TRUE; - - switch (ucScan) - { - case KEY_LEFT_SHIFT: - { - bLShiftPressed=bMakenBreak; - break; - } - - case KEY_RIGHT_SHIFT: - { - bRShiftPressed=bMakenBreak; - break; - } - - case KEY_CONTROL: - { - bCtrlPressed=bMakenBreak; - break; - } - - case KEY_ALT: - { - bAltPressed=bMakenBreak; - break; - } - - default: - { - /* - * Something else needs to process this code - */ - bProcessed=FALSE; - break; - } - } - - return(bProcessed); -} - -static boolean i8042_process_top_row( - int minor, - uint8_t ucScan -) -{ - boolean bProcessed; - char cASCIIFnCode; -#if CONSOLE_USE_INTERRUPTS==0 - uint8_t ucKeyboardAck; -#endif - - /* - * Check for keys on the top row - */ - bProcessed=TRUE; - cASCIIFnCode='\0'; - - switch (ucScan) - { - case KEY_ESC: - { - EnqueueKbdChar(minor, ASCII_ESC); - break; - } - - case KEY_F1: - { - cASCIIFnCode='P'; - break; - } - - case KEY_F2: - { - cASCIIFnCode='Q'; - break; - } - - case KEY_F3: - { - cASCIIFnCode='w'; - break; - } - - case KEY_F4: - { - cASCIIFnCode='x'; - break; - } - - case KEY_F5: - { - cASCIIFnCode='t'; - break; - } - - case KEY_F6: - { - cASCIIFnCode='u'; - break; - } - - case KEY_F7: - { - cASCIIFnCode='q'; - break; - } - - case KEY_F8: - { - cASCIIFnCode='r'; - break; - } - - case KEY_F9: - { - cASCIIFnCode='p'; - break; - } - - case KEY_F10: - { - cASCIIFnCode='M'; - break; - } - - case KEY_F11: - { - cASCIIFnCode='A'; - break; - } - - case KEY_F12: - { - cASCIIFnCode='B'; - break; - } - - case KEY_SYS_REQUEST: - { - EnqueueKbdChar(minor, ASCII_SYSRQ); - break; - } - - case KEY_CAPS_LOCK: - case KEY_NUM_LOCK: - case KEY_SCROLL_LOCK: - { - switch(ucScan) - { - case KEY_CAPS_LOCK: - { - bCapsLock=!bCapsLock; - break; - } - - case KEY_NUM_LOCK: - { - bNumLock=!bNumLock; - break; - } - - case KEY_SCROLL_LOCK: - { -#if CONSOLE_USE_INTERRUPTS - bScrollLock=!bScrollLock; -#endif - break; - } - } - - i8042_outbyte_raw(minor, KBD_CMD_SET_LEDS); -#if CONSOLE_USE_INTERRUPTS==0 - i8042_inbyte_raw(minor, &ucKeyboardAck); -#endif - i8042_outbyte_raw(minor, - (bCapsLock ? KBD_LED_CAPS : 0) | - (bNumLock ? KBD_LED_NUM : 0) | - (bScrollLock ? KBD_LED_SCROLL : 0)); -#if CONSOLE_USE_INTERRUPTS==0 - i8042_inbyte_raw(minor, &ucKeyboardAck); -#endif - - break; - } - - default: - { - /* - * Something else needs to process this code - */ - bProcessed=FALSE; - break; - } - } - - if(cASCIIFnCode) - { - EnqueueKbdChar(minor, ASCII_CSI); - EnqueueKbdChar(minor, 'O'); - EnqueueKbdChar(minor, cASCIIFnCode); - } - - return(bProcessed); -} - -static boolean i8042_process_keypad( - int minor, - uint8_t ucScan -) -{ - char cASCIICtrlCode; - - /* - * Process keys on the keypad - */ - cASCIICtrlCode='\0'; - - switch(ucScan) - { - case KEY_UP_ARROW: - { - cASCIICtrlCode='A'; - break; - } - - case KEY_DOWN_ARROW: - { - cASCIICtrlCode='B'; - break; - } - - case KEY_RIGHT_ARROW: - { - cASCIICtrlCode='C'; - break; - } - - case KEY_LEFT_ARROW: - { - cASCIICtrlCode='D'; - break; - } - - case KEY_HOME: - { - cASCIICtrlCode='H'; - break; - } - - case KEY_END: - { - cASCIICtrlCode='K'; - break; - } - - case KEY_PAGE_UP: - { - cASCIICtrlCode='?'; - break; - } - - case KEY_PAGE_DOWN: - { - cASCIICtrlCode='/'; - break; - } - - case KEY_INSERT: - { - cASCIICtrlCode='@'; - break; - } - - case KEY_DELETE: - { - /* - * This is a special case not requiring an ASCII_CSI - */ - EnqueueKbdChar(minor, ASCII_DEL); - return(TRUE); - } - - default: - { - /* - * Something else needs to process this code - */ - break; - } - } - - if(cASCIICtrlCode) - { - EnqueueKbdChar(minor, ASCII_CSI); - EnqueueKbdChar(minor, cASCIICtrlCode); - return(TRUE); - } - else - { - return(FALSE); - } -} - -/* - * This routine translates the keyboard scan code into an - * ASCII character (or sequence) and queues it - */ -static void i8042_scan_code( - int minor, - uint8_t ucScan -) -{ - char cChar; - boolean bMakenBreak; - - /* - * Check for code 0xe0, which introduces a two key sequence. - */ - - if(ucScan==KEY_TWO_KEY) - { - bTwoCode=TRUE; - return; - } - - /* - * Bit 7 of scan code indicates make or break - */ - if(ucScan & 0x80) - { - bMakenBreak=FALSE; - ucScan&=0x7f; - } - else - { - bMakenBreak=TRUE; - } - - /* - * If we are in a multikey sequence then process the second keypress - */ - if(bTwoCode) - { - i8042_process_two_code(minor, ucScan, bMakenBreak); - - /* - * Revert to prcessing single key sequences - */ - bTwoCode=FALSE; - return; - } - - if(i8042_process_qualifiers(ucScan, bMakenBreak)) - { - /* - * We are all done - */ - return; - } - - /* - * The remaining keys are only processed for make - */ - if(!bMakenBreak) - { - return; - } - - if(i8042_process_top_row(minor, ucScan)) - { - /* - * We are all done - */ - return; - } - - if(!bNumLock && i8042_process_keypad(minor, ucScan)) - { - /* - * We are all done - */ - return; - } - - /* - * Process "normal" keys - */ - - cChar=0; - - /* - * Check to see if the scan code corresponds to an ASCII - * character. - */ - if(((ucScan >= 16) && (ucScan <= 25)) || - ((ucScan >= 30) && (ucScan <= 38)) || - ((ucScan >= 44) && (ucScan <= 50))) - { - if(bCtrlPressed) - { - cChar=pcNormalLookup[ucScan - 2]-'a'+1; - } - else - { - if(((bLShiftPressed || bRShiftPressed) && !bCapsLock) || - (!(bLShiftPressed || bRShiftPressed) && bCapsLock)) - { - cChar=pcShiftedLookup[ucScan - 2]; - } - else - { - cChar=pcNormalLookup[ucScan - 2]; - } - } - } - else if((ucScan > 1) && (ucScan <= 0x56)) - { - /* - * Its ASCII but not alpha, so don't shift on CapsLock. - */ - if(bLShiftPressed || bRShiftPressed) - { - cChar=pcShiftedLookup[ucScan - 2]; - } - else - { - cChar=pcNormalLookup[ucScan - 2]; - } - } - - /* - * If we got a character then queue it - */ - if(cChar) - { - EnqueueKbdChar(minor, cChar); - } -} - -/* - * Console Device Driver Entry Points - */ -boolean i8042_probe(int minor) -{ - uint8_t ucKeyboardAck; - uint8_t ucKeyboardID1, ucKeyboardID2; - - if(!vga_probe(minor)) - { - /* - * There is no VGA adaptor so fail probe - */ - return(FALSE); - } - - Ring_buffer_Initialize(&KbdInputBuffer); -#if CONSOLE_USE_INTERRUPTS - Ring_buffer_Initialize(&KbdOutputBuffer); -#endif - - i8042_polled_on(minor); - /* - * Determine keyboard type - */ - i8042_outbyte_raw(minor, KBD_CMD_READ_ID); - ucKeyboardAck=0; - if((i8042_inbyte_raw(minor, &ucKeyboardAck)==RTEMS_TIMEOUT) || - (ucKeyboardAck==KBD_CMD_RESEND)) - { - /* - * No or incorrect keyboard response so fail probe - */ - return(FALSE); - } - - i8042_inbyte_raw(minor, &ucKeyboardID1); - i8042_inbyte_raw(minor, &ucKeyboardID2); - if((ucKeyboardID1==0xab) && (ucKeyboardID2==0x41)) - { - pcNormalLookup=&pcUKNormalLookup[0]; - pcShiftedLookup=&pcUKShiftedLookup[0]; - } - else - { - pcNormalLookup=&pcUSNormalLookup[0]; - pcShiftedLookup=&pcUSShiftedLookup[0]; - } - i8042_polled_off(minor); - - return(TRUE); -} - -void i8042_init(int minor) -{ - uint8_t ucKeyboardAck; - - vga_init(minor); - - i8042_polled_on(minor); - /* - * Switch all LEDs off - */ - i8042_outbyte_raw(minor, KBD_CMD_SET_LEDS); - i8042_inbyte_raw(minor, &ucKeyboardAck); - i8042_outbyte_raw(minor, 0); - i8042_inbyte_raw(minor, &ucKeyboardAck); - /* - * Select scan code set 1 - */ - i8042_outbyte_raw(minor, KBD_CMD_SEL_SCAN_CODE); - i8042_inbyte_raw(minor, &ucKeyboardAck); - i8042_outbyte_raw(minor, 1); - i8042_inbyte_raw(minor, &ucKeyboardAck); - i8042_polled_off(minor); -} - -/* PAGE - * - * i8042_inbyte_nonblocking_polled - * - * Console Termios polling input entry point. - */ - -int i8042_inbyte_nonblocking_polled( - int minor -) -{ - uint8_t ucScan; - char ucData; - - if(i8042_inbyte_polled(minor, &ucScan)==RTEMS_SUCCESSFUL) - { - i8042_scan_code(minor, ucScan); - } - - if(!Ring_buffer_Is_empty(&KbdInputBuffer)) - { - Ring_buffer_Remove_character(&KbdInputBuffer, - ucData); - return(ucData); - } - - return(-1); -} - -#if CONSOLE_USE_INTERRUPTS -/* - * i8042_isr - * - * This routine is the console interrupt handler for the keyboard - * - * Input parameters: - * vector - vector number - * - * Output parameters: NONE - * - * Return values: NONE - */ -static void i8042_process( - int minor -) -{ - uint8_t Status; - uint8_t ucData; - - inport_byte(Console_Port_Tbl[minor].ulCtrlPort1, Status); - - if(Status & KBD_OBF_MASK) - { - inport_byte(Console_Port_Tbl[minor].ulDataPort, ucData); - - if(bProcessInterruptInput) - { - /* - * Every byte written to the keyboard should be followed - * by an acknowledge - */ - if(ucData==KBD_CMD_ACK) - { - bReceivedAck=TRUE; - } - else - { - i8042_scan_code(minor, ucData); - } - } - else - { - /* - * Store the scan code into the ring buffer where it - * can be read using i8042_inbyte_raw() - */ - Ring_buffer_Add_character(&KbdInputBuffer, ucData); - } - } - - if(((Status & KBD_IBF_MASK)==0) && - bReceivedAck) - { - if(Ring_buffer_Is_empty(&KbdOutputBuffer)) - { - Console_Port_Data[minor].bActive=FALSE; - } - else - { - Ring_buffer_Remove_character(&KbdOutputBuffer, - ucData); - outport_byte(Console_Port_Tbl[minor].ulDataPort, - ucData); - bReceivedAck=FALSE; - } - } -} - -static rtems_isr i8042_isr( - rtems_vector_number vector -) -{ - int minor; - - for(minor=0;minor<Console_Port_Count;minor++) - { - if(vector==Console_Port_Tbl[minor].ulIntVector) - { - i8042_process(minor); - } - } -} - -void i8042_initialize_interrupts(int minor) -{ - i8042_init(minor); - - Console_Port_Data[minor].bActive=FALSE; - - set_vector(i8042_isr, - Console_Port_Tbl[minor].ulIntVector, - 1); - - i8042_outbyte_cmd_polled(minor, KBD_CTR_WRITE_COMMAND); - i8042_outbyte_raw(minor, KBD_CMD_ENABLE_KBD_INT); - - /* - * At this point interrupts should spring into life - */ - bInterruptsEnabled=TRUE; -} - -#endif /* CONSOLE_USE_INTERRUPTS */ |