Newer
Older
UbixOS / sys / isa / atkbd.c
/*-
 * 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 <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 },
/*     */{ 0x71, 0x51, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x77, 0x57, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x65, 0x45, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x72, 0x52, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x74, 0x54, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x79, 0x59, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x75, 0x55, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x69, 0x49, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x6F, 0x4F, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x70, 0x50, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x5B, 0x7B, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x5D, 0x7D, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x0A, 0, 0, 0, 0, 0, 0, 0 },
/*     */{ 0, 0, 0, 0, 0, 0, 0, 0 },
/* a,A */{ 0x61, 0x41, 0x41, 0, 0, 0, 0, 0 },
/*     */{ 0x73, 0x53, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x64, 0x44, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x66, 0x46, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x67, 0x47, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x68, 0x48, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x6A, 0x4A, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x6B, 0x4B, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x6C, 0x4C, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x3B, 0x3A, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x27, 0x22, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x60, 0x7E, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x2A, 0x0, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x5C, 0x3C, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x7A, 0x5A, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x78, 0x58, 0, 0, 0, 0, 0, 0 },
/* c,C */{ 0x63, 0x43, 0x3, 0x9, 0, 0, 0, 0 },
/*     */{ 0x76, 0x56, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x62, 0x42, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x6E, 0x4E, 0, 0, 0, 0, 0, 0 },
/*     */{ 0x6D, 0x4D, 0, 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"
  "  pusha                \n" /* Save all registers           */
  "  push %ss             \n"
  "  push %ds             \n"
  "  push %es             \n"
  "  push %fs             \n"
  "  push %gs             \n"
  "  call keyboardHandler \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"
  "  pop %ss              \n"
  "  popa                 \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() {
  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);
      break;
      case 0x9:
        kprintf("REBOOTING");
        while (inportByte(0x64) & 0x02)
          ;
        outportByte(0x64, 0xFE);
      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);
}

/***

 $Log: atkbd.c,v $
 Revision 1.5  2006/12/05 17:01:15  reddawg
 Modified kpanic

 Revision 1.4  2006/12/05 14:10:21  reddawg
 Workign Distro

 Revision 1.3  2006/12/01 05:12:35  reddawg
 We're almost there... :)

 Revision 1.2  2006/10/19 17:52:17  reddawg
 Working On Userland

 Revision 1.1.1.1  2006/06/01 12:46:12  reddawg
 ubix2

 Revision 1.2  2005/10/12 00:13:37  reddawg
 Removed

 Revision 1.1.1.1  2005/09/26 17:24:01  reddawg
 no message

 Revision 1.29  2004/09/11 21:38:00  reddawg
 Fixed a few problems

 Revision 1.28  2004/09/08 23:19:58  reddawg
 hmm

 Revision 1.27  2004/09/07 21:54:38  reddawg
 ok reverted back to old scheduling for now....

 Revision 1.26  2004/09/06 22:18:52  reddawg
 ok bed time

 Revision 1.25  2004/09/06 22:11:29  reddawg
 tty: now each tty has a stdin....

 Revision 1.24  2004/09/06 15:13:25  reddawg
 Last commit before FreeBSD 6.0

 Revision 1.23  2004/08/21 23:47:50  reddawg
 *** empty log message ***

 Revision 1.22  2004/08/09 12:58:05  reddawg
 let me know when you got the surce

 Revision 1.21  2004/08/06 22:32:16  reddawg
 Ubix Works Again

 Revision 1.19  2004/08/03 18:31:19  reddawg
 virtual terms

 Revision 1.18  2004/07/29 21:32:16  reddawg
 My quick lunchs breaks worth of updates....

 Revision 1.17  2004/07/28 18:45:39  reddawg
 movement of files

 Revision 1.16  2004/07/28 17:07:25  reddawg
 MPI: moved the syscalls

 Revision 1.15  2004/07/26 19:15:49  reddawg
 test code, fixes and the like

 Revision 1.14  2004/07/25 05:32:58  reddawg
 fixed

 Revision 1.13  2004/07/25 05:24:39  reddawg
 atkbd: removed sti... does it still miss keys

 Revision 1.12  2004/07/24 20:00:51  reddawg
 Lots of changes to the vmm subsystem.... Page faults have been adjust to now be blocking on a per thread basis not system wide. This has resulted in no more deadlocks.. also the addition of per thread locking has removed segfaults as a result of COW in which two tasks fault the same COW page and try to modify it.

 Revision 1.11  2004/07/24 15:12:56  reddawg
 Now I'm current

 Revision 1.10  2004/07/23 17:49:58  reddawg
 atkbd: adjust the timing issue on the driver hopefully it will work fine now

 Revision 1.9  2004/07/23 17:37:35  reddawg
 Fix

 Revision 1.8  2004/07/23 09:10:06  reddawg
 ubixfs: cleaned up some functions played with the caching a bit
 vfs:    renamed a bunch of functions
 cleaned up a few misc bugs

 Revision 1.7  2004/07/22 20:53:07  reddawg
 atkbd: fixed problem

 Revision 1.6  2004/07/09 13:34:51  reddawg
 keyboard: keyboardInit to atkbd_init
 Adjusted initialization routines

 Revision 1.5  2004/06/17 14:49:14  reddawg
 atkbd: converted some variables to static

 Revision 1.4  2004/06/04 10:19:42  reddawg
 notes: we compile again, thank g-d anyways i was about to cry

 Revision 1.3  2004/05/19 04:07:42  reddawg
 kmalloc(size,pid) no more it is no kmalloc(size); the way it should of been

 Revision 1.2  2004/05/10 02:23:24  reddawg
 Minor Changes To Source Code To Prepare It For Open Source Release

 Revision 1.1.1.1  2004/04/15 12:07:09  reddawg
 UbixOS v1.0

 Revision 1.19  2004/04/13 16:36:33  reddawg
 Changed our copyright, it is all now under a BSD-Style license

 END
 ***/