/* Copyright (c) 1996-1997 Swiss Federal Institute of Technology, Computer Engineering and Networks Laboratory. All rights reserved. TOPSY - A Teachable Operating System. Implementation of a tiny and simple micro kernel for teaching purposes. Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without written agreement is hereby granted, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE SWISS FEDERAL INSTITUTE OF TECHNOLOGY, COMPUTER ENGINEERING AND NETWORKS LABORATORY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE SWISS FEDERAL INSTITUTE OF TECHNOLOGY, COMPUTER ENGINEERING AND NETWORKS LABORATORY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SWISS FEDERAL INSTITUTE OF TECHNOLOGY, COMPUTER ENGINEERING AND NETWORKS LABORATORY, SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE SWISS FEDERAL INSTITUTE OF TECHNOLOGY, COMPUTER ENGINEERING AND NETWORKS LABORATORY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. File: $Source: /usr/drwho/vault/cvs/topsy/Topsy/IO/Drivers/ia32/Keyboard.c.bak,v $ Author(s): Lukas Ruf, lr@lpr.ch Affiliation: ETH Zuerich, TIK Version: $Revision: 1.1 $ Creation Date: Last Date of Change: $Date: 1999/06/06 20:58:23 $ by: $Author: jeker $ $Log: Keyboard.c.bak,v $ Revision 1.1 1999/06/06 20:58:23 jeker putting everything together for Topsy 2.0 Revision 1.1 1999/05/13 17:05:29 jeker Initial revision */ #include "keyboard.h" #include "SupportAsm.h" #include "Video.h" #include "Topsy.h" #include "TMHalAsm.h" #include "video.h" #define KEYECHO TRUE #define KEYDEBUG FALSE #define KEYGETDEBUG FALSE /* Translate Break-Key PrtScr to unqiue "Hardware Make/Break Code" according coding scheme of my keyboard handling. See MakeKey.TBL, resp. Documentation to Keyboard-Handling These codes are not used in the standard MF-II 102-Keyboard */ /* selfmade MAKE CODEs */ #define kBREAK_MAKE_CODE 90 #define kPRTSCR_MAKE_CODE 91 #define kENTER_MAKE_CODE 92 #define kHOME_MAKE_CODE 94 #define kUP_MAKE_CODE 95 #define kPGUP_MAKE_CODE 98 #define kLEFT_MAKE_CODE 99 #define kRIGHT_MAKE_CODE 100 #define kEND_MAKE_CODE 101 #define kDOWN_MAKE_CODE 102 #define kPGDN_MAKE_CODE 103 #define kINSERT_MAKE_CODE 104 #define kDELETE_MAKE_CODE 105 /* MAKE CODES specially handled */ #define KEYCTRL 29 #define KEYLEFTSHIFT 42 #define KEYRIGHTSHIFT 54 #define KEYALT 56 #define KEYCAPSLOCK 58 #define KEYNUMLOCK 69 #define KEYSCROLLLOCK 70 #define KEYALTSYSRQ 84 #define KEYEXT2SIGN 0xE1 #define KEYEXTSIGN 0xE0 #define KBBSIZE 0x80 /* module global variables */ static unsigned char kLEDSetting = 0x00; static unsigned char KBB[KBBSIZE]; static unsigned int KBBHead; static unsigned int KBBTail; /* This variable performs the mutex :-) */ static unsigned int KeyBoardLock; #define HEADLOCK 0 /* set bit 0 */ #define TAILLOCK 1 /* set bit 1 */ #define K_SCLLOCK 1 /* SCROLL LOCK - LED */ #define K_NUMLOCK 2 /* NUM LOCK - LED */ #define K_CPSLOCK 4 /* CAPS LOCK - LED */ static unsigned char *K_LHWMap; /* Scan Code to Logical HW Key Code Map (7b -> 7b) */ static unsigned char *K_LKCMap; /* Logical HW Key Code to ASCII Map (10b -> 8b) */ static unsigned short *K_LMSMap; /* Key Message Map (10b -> 16b) */ /* Keyboard-Variables: */ static char KeyExt2Cnt; /* Counter for two extended bytes */ static BOOL KeyExt2Set; /* 0xE1 */ static BOOL KeyExtSet; /* 0xE0 */ static BOOL KeyAltDown; static BOOL KeyCtrlDown; static BOOL KeyShiftDown; static BOOL KeyCapsSet; static BOOL KeyNumLockSet; static BOOL KeyScrollSet; BOOL _IsKeypressed() { return KBBHead > KBBTail; } BOOL _GetChar(char *pCharToGet) { BOOL xret = FALSE; *pCharToGet = 0; if (_IsKeypressed()) { __mutex(&KeyBoardLock,TAILLOCK); *pCharToGet = (char)KBB[KBBTail % KBBSIZE]; KBBTail++; __demutex(&KeyBoardLock,TAILLOCK); if (KEYGETDEBUG) kprintc(*pCharToGet); xret = TRUE; } return xret; } static void SetKeyLED(BOOL pSet, unsigned char pPos) { if (pSet) kLEDSetting |= pPos; else kLEDSetting &= !pPos; kLEDSetting &= 7; /* make sure only lower 3 bits are set */ __outb(0xED,0x60); while (__inb(0x64) & 0x02) ; /* wait until CPU->Keyboard Buffer empty */ __outb(kLEDSetting,0x60); return; } /*********************/ /* KEYBOARD HANDLERS */ /*********************/ static void KeyInit() { /* Initialize Keyboard Variables */ KeyExt2Set = FALSE; /* ATTENTION Byte Marker (PrtScr) */ KeyExtSet = FALSE; KeyAltDown = FALSE; /* ALT Key is not pressed */ KeyCtrlDown = FALSE; /* CTRL */ KeyShiftDown = FALSE; /* SHIFT */ KeyCapsSet = FALSE; /* CAPS LOCK is not set */ KeyNumLockSet = FALSE; /* NUM LOCK */ KeyScrollSet = FALSE; /* SCROLL LOCK */ K_LHWMap = __addrHWKeyTrl(); /* Assign Address via function, as direct */ K_LKCMap = __addrKeyAscTrl(); /* assignment has not worked properly ??? */ K_LMSMap = __addrKeyMsgTrl(); KBBHead = 0; KBBTail = 0; KeyBoardLock = 0; return; } void KeyboardInit() { KeyInit(); __enable_IRQ(0x21); __endOf_IRQ(0x21); return; } unsigned long KeyModifier(unsigned char pRawKey) { BOOL xbreak, xerr; unsigned long xret = 1; if (KEYDEBUG) Debug("KeyModifier called: 0x%x (%i) -- ",pRawKey,(int)pRawKey); if (KeyAltDown && KeyCtrlDown && (pRawKey == 0x53)) /* Alt-Ctrl-Delete */ __reboot(); if (pRawKey == 0xFA) { /* if (KEYDEBUG) Debug("(=ACK)\n"); */ return 0x00; } if (KeyExt2Set) { /* 1st byte after 0xE1 */ /* Break was pressed -> 0xE1 0x1D 0x45 */ /* or released -> 0xE1 0x9D 0xC5 */ xerr = FALSE; switch (pRawKey & 0x7F) { case 0x1D : KeyExt2Cnt = 1; break; case 0x45 : KeyExt2Cnt = 2; break; default : xerr = TRUE; } if (KEYDEBUG) Debug(" \"Break\" "); KeyExt2Set = (KeyExt2Cnt < 2); if (KeyExt2Set) xret = 0; /* disable key output until all bytes passed */ else pRawKey = kBREAK_MAKE_CODE | (pRawKey & 0x80); if (xerr) { printf(" Warning !!! Unknown Raw Key Code 0x%x\n",(int)pRawKey); xret = 0; } } else if (KeyExtSet) { /* byte after 0xE0 */ /* PrtScr Press: -> 0xE0 0x2A 0xE0 0x37 --> Repeated only "0xE0 0x37" */ /* Release: -> 0xE0 0xB7 0xE0 0xAA */ /* Ctrl-PrtScr : -> 0xE0 0x37 */ /* Release: -> 0xE0 0xB7 */ if ((pRawKey & 0x7F) == 0x2A) /* discard envelopping 0xE0 0x2A resp. 0xAA */ xret = 0; else /* translate extended keycodes to unique Topsy HW KeyCode !! */ switch (pRawKey & 0x7F) { case 0x28 : /* NumPad Enter */ pRawKey = kENTER_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"NumPad Enter\" "); break; case 0x37 : /* PrtScr */ pRawKey = kPRTSCR_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"PrtScr\" "); break; case 0x46 : /* Break (resp. Ctrl-Break) */ pRawKey = kBREAK_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Break\" "); break; case 0x47 : /* Middle Home */ pRawKey = kHOME_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Home\" "); break; case 0x48 : /* Middle Up */ pRawKey = kUP_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Up\" "); break; case 0x49 : /* Middle PgUp */ pRawKey = kPGUP_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"PgUp\" "); break; case 0x4B : /* Middle Left */ pRawKey = kLEFT_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Left\" "); break; case 0x4D : /* Middle Right */ pRawKey = kRIGHT_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Right\" "); break; case 0x4F : /* Middle End */ pRawKey = kEND_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"End\" "); break; case 0x50 : /* Middle Down */ pRawKey = kDOWN_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Down\" "); break; case 0x51 : /* Middle PgDn */ pRawKey = kPGDN_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"PgDn\" "); break; case 0x52 : /* Middle Insert */ pRawKey = kINSERT_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Insert\" "); break; case 0x53 : /* Middle Delete */ pRawKey = kDELETE_MAKE_CODE | (pRawKey & 0x80); if (KEYDEBUG) Debug(" \"Delete\" "); break; } KeyExtSet = FALSE; } if (xret && !KeyExt2Set) { KeyExtSet = (pRawKey == 0xE0); KeyExt2Set= (pRawKey == 0xE1); xbreak = ((pRawKey & 0x80) == 0x80); /* is it break code */ xret = 0; if (!KeyExtSet && !KeyExt2Set) if (xbreak) switch (pRawKey & 0x7F) { case KEYALT : /* left or right ALT Key */ KeyAltDown = FALSE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyALT released "); break; case KEYCTRL: /* left or right CTRL Key */ KeyCtrlDown = FALSE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyCTRL released "); break; case KEYRIGHTSHIFT : /* right SHIFT Key */ KeyShiftDown = FALSE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyRIGHTSHIFT released "); break; case KEYLEFTSHIFT : /* left SHIFT Key */ KeyShiftDown = FALSE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyLEFTSHIFT released "); break; } else switch (pRawKey) { case KEYALT : /* left or right ALT Key */ KeyAltDown = TRUE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyALT pressed "); break; case KEYCTRL: /* left or right CTRL Key */ KeyCtrlDown = TRUE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyCTRL pressed "); break; case KEYRIGHTSHIFT : /* right SHIFT Key */ KeyShiftDown = TRUE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyRIGHTSHIFT pressed "); break; case KEYLEFTSHIFT : /* left SHIFT Key */ KeyShiftDown = TRUE; /* Toggle Flag */ if (KEYDEBUG) Debug(" KeyLEFTSHIFT pressed "); break; case KEYCAPSLOCK : KeyCapsSet = (KeyCapsSet) ? FALSE : TRUE; SetKeyLED(KeyCapsSet,K_CPSLOCK); if (KEYDEBUG) Debug(" CapsLock Toggled "); break; case KEYNUMLOCK : /* NumLock */ KeyNumLockSet = (KeyNumLockSet) ? FALSE : TRUE; SetKeyLED(KeyNumLockSet,K_NUMLOCK); if (KEYDEBUG) Debug(" NumLock Toggled "); break; case KEYSCROLLLOCK : /* Scroll Lock Key */ KeyScrollSet = (KeyScrollSet) ? FALSE : TRUE; SetKeyLED(KeyScrollSet,K_SCLLOCK); if (KEYDEBUG) Debug(" Scroll Lock toggled "); break; case KEYALTSYSRQ : /* Alt-PrtScr == Alt-SysRq */ xret = kPRTSCR_MAKE_CODE; if (KEYDEBUG) Debug(" \"Alt-PrtScr\" "); break; case kBREAK_MAKE_CODE : case kPRTSCR_MAKE_CODE : case kENTER_MAKE_CODE : case kHOME_MAKE_CODE : case kUP_MAKE_CODE : case kPGUP_MAKE_CODE : case kLEFT_MAKE_CODE : case kRIGHT_MAKE_CODE : case kEND_MAKE_CODE : case kDOWN_MAKE_CODE : case kPGDN_MAKE_CODE : case kINSERT_MAKE_CODE : case kDELETE_MAKE_CODE : xret = (pRawKey & 0x7F); if (KEYDEBUG) Debug(" \"Selfmade\" MAKE CODE processed "); break; default : xret = 1; } else KeyExt2Cnt = 0; } if (KEYDEBUG) Debug(" --> xret = 0x%x\n",(int)xret); __printchar((24*80+79-6)*2,0x1E,KeyAltDown ? 'A' : ' '); /* ALT */ __printchar((24*80+79-5)*2,0x1E,KeyCtrlDown ? 'C' : ' '); /* CTRL */ __printchar((24*80+79-4)*2,0x1E,KeyShiftDown ? 'S' : ' '); /* SHIFT */ __printchar((24*80+79-3)*2,0x1E,KeyCapsSet ? 'L' : ' '); /* Caps Lock */ __printchar((24*80+79-2)*2,0x1E,KeyScrollSet ? 'R' : ' '); /* Scroll Lock */ __printchar((24*80+79-1)*2,0x1E,KeyNumLockSet ? 'N' : ' '); /* Num Lock */ return xret; } static void KeyIntoBuffer(unsigned char pASCII) { if (KEYDEBUG) Debug("KeyIntoBuffer: %c\n",(char)pASCII); __mutex(&KeyBoardLock,HEADLOCK); if (KEYECHO) { if (pASCII==13) kprintc(10); else kprintc(pASCII); } KBB[KBBHead % KBBSIZE] = pASCII; KBBHead++; __demutex(&KeyBoardLock,HEADLOCK); return; } /* return from SCANCODE an "eineindeutig", continously ranged 7b-Keycode */ /* -> so called Logical HW Key (=7b) */ static unsigned char KeyMappedCode(unsigned long pSCANCODE) { unsigned char xc; if (KEYDEBUG) Debug("-> KeyMappedCode: %i -- ",pSCANCODE); xc = K_LHWMap[pSCANCODE & 0x7F]; if (KEYDEBUG) Debug("<- KeyMappedCode: %i \n",(int)xc); return xc; } /* Translate Logical HW Key into KEYCODE depending on Modifier state */ /* -> so called Key Code (=10b) */ static unsigned short KeyGetCode(unsigned char pLHWKey) { unsigned short xret = 0; BOOL oldState = KeyShiftDown; if (KeyCapsSet && (pLHWKey >= 61) && (pLHWKey <= 86)) KeyShiftDown = TRUE; xret = pLHWKey + (unsigned short)KeyAltDown*0x200 + (unsigned short)KeyCtrlDown*0x100 + (unsigned short)KeyShiftDown*0x80; KeyShiftDown = oldState; return xret; } static unsigned char KeyASCIICode(unsigned short pKeyCode) { unsigned char xc; if (KEYDEBUG) Debug("-> KeyASCIICode: %i -- ",(int)pKeyCode); xc = K_LKCMap[pKeyCode & 0x3FF]; if (KEYDEBUG) Debug("<- KeyASCIICode: %i \n",(int)xc); return xc; } static void KeyMsgSender(unsigned short pKeyMsg) { /* Send Message K_LMSMap[pKeyMsg & 0x3FF];*/ return; } void _KeyboardISR() { unsigned long lksl, lkmr; unsigned short lkoc; unsigned char lksb; lksb = __inb(0x60); /* read Keyboard; */ lksl = lksb; /* convert to long */ lkmr = KeyModifier(lksb); /* handle key struck */ if (lkmr != 0) { /* if "normal" key was pressed */ if (lkmr != 1) lksl = lkmr; /* if "selfmade" SCAN CODE */ lksb = KeyMappedCode(lksl); /* get code mapped to continous ranges (1st translation) ( -> unequivocal code (7b)) */ if (lksb < 0x80) { lkoc = KeyGetCode(lksb); /* get one of 1024 Topsy Key Codes (2nd translation, considers modifiers) (7b -> 10b) */ lksb = KeyASCIICode(lkoc); /* translate Topsy Key Code to ASCII (10b -> 8b) */ if ((lksb > 0x00) && (lksb < 0xFF)) /* 0x00 = abort, 0xFF = send associated message */ KeyIntoBuffer(lksb); /* insert ascii code into keyboard buffer */ else KeyMsgSender(lkoc); /* or send an associated message to running process */ } } return ; } /**********************************************************/ /* END OF KEYBOARD HANDLING */ /**********************************************************/