/*- * Copyright (c) 2002-2018 The UbixOS Project. * All rights reserved. * * This was developed by Christopher W. Olsen for the UbixOS Project. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * * 1) Redistributions of source code must retain the above copyright notice, this list of * conditions, the following disclaimer and the list of authors. * 2) Redistributions in binary form must reproduce the above copyright notice, this list of * conditions, the following disclaimer and the list of authors in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <isa/atkbd.h> #include <isa/8259.h> #include <sys/video.h> #include <sys/idt.h> #include <sys/gdt.h> #include <sys/io.h> #include <sys/shutdown.h> #include <lib/kmalloc.h> #include <lib/kprintf.h> #include <ubixos/sched.h> #include <ubixos/endtask.h> #include <ubixos/tty.h> #include <ubixos/spinlock.h> #include <ubixos/kpanic.h> #include <ubixos/vitals.h> static int atkbd_scan(); static unsigned int keyMap = 0x0; static unsigned int ledStatus = 0x0; static char stdinBuffer[512]; static uInt16 stdinSize; static uInt32 controlKeys = 0x0; static struct spinLock atkbdSpinLock = SPIN_LOCK_INITIALIZER; static unsigned int keyboardMap[255][8] = { /* Ascii, Shift, Ctrl, Alt, Num, Caps, Shift Caps, Shift Num */ { 0, 0, 0, 0, 0, 0, 0, 0 }, /* ESC */{ 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B }, /* 1,! */{ 0x31, 0x21, 0, 0, 0x31, 0x31, 0x21, 0x21 }, /* 2,@ */{ 0x32, 0x40, 0, 0, 0x32, 0x32, 0x40, 0x40 }, /* 3,# */{ 0x33, 0x23, 0, 0, 0x33, 0x33, 0x23, 0x23 }, /* 4,$ */{ 0x34, 0x24, 0, 0, 0x34, 0x34, 0x24, 0x24 }, /* 5,% */{ 0x35, 0x25, 0, 0, 0x35, 0x35, 0x25, 0x25 }, /* 6,^ */{ 0x36, 0x5E, 0, 0, 0x36, 0x36, 0x5E, 0x5E }, /* 7,& */{ 0x37, 0x26, 0, 0, 0x37, 0x37, 0x26, 0x26 }, /* 8,* */{ 0x38, 0x2A, 0, 0, 0x38, 0x38, 0x2A, 0x2A }, /* 9.( */{ 0x39, 0x28, 0, 0, 0x39, 0x39, 0x28, 0x28 }, /* 0,) */{ 0x30, 0x29, 0, 0, 0x30, 0x30, 0x29, 0x29 }, /* -,_ */{ 0x2D, 0x5F, 0, 0, 0x2D, 0x2D, 0x5F, 0x5F }, /* =,+ */{ 0x3D, 0x2B, 0, 0, 0x3D, 0x3D, 0x2B, 0x2B }, /* 14 */{ 0x08, 0x08, 0x8, 0x8, 0x08, 0x08, 0x08, 0x08 }, /* 15 */{ 0x09, 0, 0, 0, 0, 0, 0, 0 }, /* q,Q */{ 0x71, 0x51, 0x11, 0, 0, 0, 0, 0 }, /* w,W */{ 0x77, 0x57, 0x17, 0, 0, 0, 0, 0 }, /* e,E */{ 0x65, 0x45, 0x05, 0, 0, 0, 0, 0 }, /* r,R */{ 0x72, 0x52, 0x18, 0, 0, 0, 0, 0 }, /* t,T */{ 0x74, 0x54, 0x14, 0, 0, 0, 0, 0 }, /* y,Y */{ 0x79, 0x59, 0x19, 0, 0, 0, 0, 0 }, /* u,U */{ 0x75, 0x55, 0x15, 0, 0, 0, 0, 0 }, /* i,I */{ 0x69, 0x49, 0x09, 0, 0, 0, 0, 0 }, /* o,O */{ 0x6F, 0x4F, 0x0F, 0, 0, 0, 0, 0 }, /* p,P */{ 0x70, 0x50, 0x10, 0, 0, 0, 0, 0 }, /* [,{ */{ 0x5B, 0x7B, 0x1B, 0, 0, 0, 0, 0 }, /* ],} */{ 0x5D, 0x7D, 0x1D, 0, 0, 0, 0, 0 }, /* LF */{ 0x0A, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* a,A */{ 0x61, 0x41, 0x01, 0, 0, 0, 0, 0 }, /* s,S */{ 0x73, 0x53, 0x13, 0, 0, 0, 0, 0 }, /* d,D */{ 0x64, 0x44, 0x04, 0, 0, 0, 0, 0 }, /* f,F */{ 0x66, 0x46, 0x06, 0, 0, 0, 0, 0 }, /* g,G */{ 0x67, 0x47, 0x07, 0, 0, 0, 0, 0 }, /* h,H */{ 0x68, 0x48, 0x08, 0, 0, 0, 0, 0 }, /* j,J */{ 0x6A, 0x4A, 0x0A, 0, 0, 0, 0, 0 }, /* k,K */{ 0x6B, 0x4B, 0x0B, 0, 0, 0, 0, 0 }, /* l,L */{ 0x6C, 0x4C, 0x0C, 0, 0, 0, 0, 0 }, /* ;,: */{ 0x3B, 0x3A, 0x00, 0, 0, 0, 0, 0 }, /* '," */{ 0x27, 0x22, 0x00, 0, 0, 0, 0, 0 }, /* `,~ */{ 0x60, 0x7E, 0x00, 0, 0, 0, 0, 0 }, /* * */{ 0x2A, 0x00, 0x00, 0, 0, 0, 0, 0 }, /* \,< */{ 0x5C, 0x3C, 0x00, 0, 0, 0, 0, 0 }, /* z,Z */{ 0x7A, 0x5A, 0x1A, 0, 0, 0, 0, 0 }, /* x,X */{ 0x78, 0x58, 0x18, 0, 0, 0, 0, 0 }, /* c,C */{ 0x63, 0x43, 0x03, 0x9, 0, 0, 0, 0 }, /* v,V */{ 0x76, 0x56, 0x16, 0, 0, 0, 0, 0 }, /* b,B */{ 0x62, 0x42, 0x02, 0, 0, 0, 0, 0 }, /* n,N */{ 0x6E, 0x4E, 0x0E, 0, 0, 0, 0, 0 }, /* m,M */{ 0x6D, 0x4D, 0x0D, 0, 0, 0, 0, 0 }, /* */{ 0x2C, 0x3C, 0, 0, 0, 0, 0, 0 }, /* */{ 0x2E, 0x3E, 0, 0, 0, 0, 0, 0 }, /* */{ 0x2F, 0x3F, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x20, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* F1 */{ 0x3000, 0, 0, 0x3000, 0, 0, 0, 0 }, /* */{ 0x3001, 0, 0, 0x3001, 0, 0, 0, 0 }, /* */{ 0x3002, 0, 0, 0x3002, 0, 0, 0, 0 }, /* */{ 0x3003, 0, 0, 0x3003, 0, 0, 0, 0 }, /* */{ 0x3004, 0, 0, 0x3004, 0, 0, 0, 0 }, /* */{ 0x4000, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4100, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4200, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4300, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4400, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4700, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4800, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4900, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x2D, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4B00, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4C00, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4D00, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x2B, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x4F00, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x5000, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x5100, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x5200, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0x5300, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 }, /* */{ 0, 0, 0, 0, 0, 0, 0, 0 } }; /************************************************************************ Function: int atkbd_init Description: This function is used to turn on the keyboard Notes: 02/20/2004 - Approved for quality ************************************************************************/ int atkbd_init() { /* Insert the IDT vector for the keyboard handler */ setVector(&atkbd_isr, mVec + 0x1, dPresent + dInt + dDpl0); /* Set the LEDS to their defaults */ setLED(); /* Clear Keyboard */ atkbd_scan(); /* Turn on the keyboard vector */ irqEnable(0x1); /* Print out information on keyboard */ kprintf("atkbd0 - Address: [0x%X], Keyboard Buffer: [0x%X], Buffer Size [%i]\n", &atkbd_isr, &stdinBuffer, 512); /* Return so we know everything went well */ return (0x0); } /* * 2-23-2004 mji I think the pusha/popa should be pushal/popal */ asm( ".globl atkbd_isr \n" "atkbd_isr: \n" "push $0x80\n" "push $0x80\n" " pusha \n" /* Save all registers */ " push %ds \n" " push %es \n" " push %fs \n" " push %gs \n" " push %esp \n" " call keyboardHandler \n" " add $0x4,%esp\n" " mov $0x20,%dx \n" " mov $0x20,%ax \n" " outb %al,%dx \n" " pop %gs \n" " pop %fs \n" " pop %es \n" " pop %ds \n" " popa \n" " add $0x8,%esp\n" " iret \n" /* Exit interrupt */ ); static int atkbd_scan() { int code = 0x0; int val = 0x0; code = inportByte(0x60); val = inportByte(0x61); outportByte(0x61, val | 0x80); outportByte(0x61, val); return (code); } void keyboardHandler( struct trapframe *frame ) { int key = 0x0; if( spinTryLock( &atkbdSpinLock ) ) return; key = atkbd_scan( ); if( key > 255 ) return; // Control Key if( key == 0x1D && !( controlKeys & controlKey ) ) { controlKeys |= controlKey; } if( key == 0x80 + 0x1D ) { controlKeys &= (0xFF - controlKey); } // ALT Key if( key == 0x38 && !( controlKeys & altKey ) ) { controlKeys |= altKey; } if( key == 0x80 + 0x38 ) { controlKeys &= (0xFF - altKey); } // Shift Key if( ( key == 0x2A || key == 0x36 ) && !( controlKeys & shiftKey ) ) { controlKeys |= shiftKey; } if( ( key == 0x80 + 0x2A ) || ( key == 0x80 + 0x36 ) ) { controlKeys &= ( 0xFF - shiftKey ); } // Caps Lock if( key == 0x3A ) { ledStatus ^= ledCapslock; setLED(); } // Num Lock if( key == 0x45 ) { ledStatus ^= ledNumlock; setLED(); } // Scroll Lock if( key == 0x46 ) { ledStatus ^= ledScrolllock; setLED(); } /* Pick Which Key Map */ if (controlKeys == 0) { keyMap = 0; } else if (controlKeys == 1) { keyMap = 1; } else if (controlKeys == 2) { keyMap = 2; } else if (controlKeys == 4) { keyMap = 3; } /* If Key Is Not Null Add It To Handler */ if (((uInt) (keyboardMap[key][keyMap]) > 0) && ((uInt32) (keyboardMap[key][keyMap]) < 0xFF)) { switch ((uInt32) keyboardMap[key][keyMap]) { case 8: backSpace(); if (tty_foreground == 0x0) { stdinBuffer[stdinSize] = keyboardMap[key][keyMap]; stdinSize++; } else { tty_foreground->stdin[tty_foreground->stdinSize] = keyboardMap[key][keyMap]; tty_foreground->stdinSize++; } break; case 0x3: //if (tty_foreground != 0x0) // endTask(tty_foreground->owner); //K_PANIC( "CTRL-C pressed\n" ); kprintf("FreePages: [0x%X]\n", systemVitals->freePages); sched_setStatus(tty_foreground->owner, DEAD); break; case 0x0D: kprintf( "FreePages: [0x%X]\n", systemVitals->freePages ); break; case 0x9: sys_shutdown(REBOOT); break; case 0x18: if (tty_foreground->owner == _current->id) die_if_kernel("CTRL-X", frame, frame->tf_eax); break; default: if (tty_foreground == 0x0) { stdinBuffer[stdinSize] = keyboardMap[key][keyMap]; stdinSize++; } else { tty_foreground->stdin[tty_foreground->stdinSize] = keyboardMap[key][keyMap]; tty_foreground->stdinSize++; } break; } } else { switch ((keyboardMap[key][keyMap] >> 8)) { case 0x30: tty_change(keyboardMap[key][keyMap] & 0xFF); //kprintf("Changing Consoles[0x%X:0x%X]\n",_current->id,_current); break; default: break; } } /* Return */ spinUnlock(&atkbdSpinLock); return; } void setLED() { outportByte(0x60, 0xED); while (inportByte(0x64) & 2) ; outportByte(0x60, ledStatus); while (inportByte(0x64) & 2) ; } /* Temp */ int getchar() { //uInt8 retKey = 0x0; int retKey = 0x0; uInt32 i = 0x0; /* if ((stdinSize <= 0) && (tty_foreground == 0x0)) { sched_yield(); } if ((tty_foreground != 0x0) && (tty_foreground->stdinSize <= 0x0)) { sched_yield(); } */ /* if (spinTryLock(&atkbdSpinLock)) return(0x0); */ if (tty_foreground == 0x0) { if (stdinSize == 0x0) { // spinUnlock(&atkbdSpinLock); return (0x0); } retKey = stdinBuffer[0]; stdinSize--; for (i = 0x0; i < stdinSize; i++) { stdinBuffer[i] = stdinBuffer[i + 0x1]; } } else { if (tty_foreground->stdinSize == 0x0) { // spinUnlock(&atkbdSpinLock); return (0x0); } retKey = tty_foreground->stdin[0]; tty_foreground->stdinSize--; for (i = 0x0; i < tty_foreground->stdinSize; i++) { tty_foreground->stdin[i] = tty_foreground->stdin[i + 0x1]; } } //spinUnlock(&atkbdSpinLock); return (retKey); }