From: John Hodge Date: Sun, 8 May 2011 14:14:11 +0000 (+0800) Subject: Moved PS2 Keyboard driver out to module tree (still in kernel, but will move once... X-Git-Tag: rel0.10~112 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=44e7e418917b0509d972b3693424a00fda9225a5;p=tpg%2Facess2.git Moved PS2 Keyboard driver out to module tree (still in kernel, but will move once debugged) - Adding a PS2 mouse driver too --- diff --git a/Modules/Input/PS2KbMouse/Makefile b/Modules/Input/PS2KbMouse/Makefile new file mode 100644 index 00000000..e30e472c --- /dev/null +++ b/Modules/Input/PS2KbMouse/Makefile @@ -0,0 +1,7 @@ +# +# + +OBJ = main.o kb.o ps2mouse.o +NAME = PS2KbMouse + +-include ../Makefile.tpl diff --git a/Modules/Input/PS2KbMouse/kb.c b/Modules/Input/PS2KbMouse/kb.c new file mode 100644 index 00000000..507d5757 --- /dev/null +++ b/Modules/Input/PS2KbMouse/kb.c @@ -0,0 +1,293 @@ +/* + * Acess2 + * PS2 Keyboard Driver + */ +#include +#include +#include +#include +#include +#include "kb_kbdus.h" + +// === CONSTANTS === +#define KB_BUFFER_SIZE 1024 +#define USE_KERNEL_MAGIC 1 + +// === IMPORTS === +extern void Threads_ToggleTrace(int TID); +extern void Threads_Dump(void); +extern void Heap_Stats(void); + +// === PROTOTYPES === + int KB_Install(char **Arguments); +void KB_IRQHandler(int IRQNum); +void KB_AddBuffer(char ch); +Uint64 KB_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Dest); +void KB_UpdateLEDs(void); + int KB_IOCtl(tVFS_Node *Node, int Id, void *Data); + +// === GLOBALS === +tDevFS_Driver gKB_DevInfo = { + NULL, "PS2Keyboard", + { + .NumACLs = 0, + .Size = 0, + //.Read = KB_Read, + .IOCtl = KB_IOCtl + } +}; +tKeybardCallback gKB_Callback = NULL; +Uint32 **gpKB_Map = gpKBDUS; +Uint8 gbaKB_States[3][256]; + int gbKB_ShiftState = 0; + int gbKB_CapsState = 0; + int gbKB_KeyUp = 0; + int giKB_KeyLayer = 0; +#if USE_KERNEL_MAGIC + int gbKB_MagicState = 0; + int giKB_MagicAddress = 0; + int giKB_MagicAddressPos = 0; +#endif + +// === CODE === +/** + * \brief Install the keyboard driver + */ +int KB_Install(char **Arguments) +{ + Uint8 temp; + + // Attempt to get around a strange bug in Bochs/Qemu by toggling + // the controller on and off + temp = inb(0x61); + outb(0x61, temp | 0x80); + outb(0x61, temp & 0x7F); + inb(0x60); // Clear keyboard buffer + + IRQ_AddHandler(1, KB_IRQHandler); + DevFS_AddDevice( &gKB_DevInfo ); + //Log("KB_Install: Installed"); + return MODULE_ERR_OK; +} + +/** + * \brief Called on a keyboard IRQ + * \param IRQNum IRQ number (unused) + */ +void KB_IRQHandler(int IRQNum) +{ + Uint8 scancode; + Uint32 ch; + // int keyNum; + + // Check port 0x64 to tell if this is from the aux port + //if( inb(0x64) & 0x20 ) return; + + scancode = inb(0x60); // Read from the keyboard's data buffer + //Log_Debug("Keyboard", "scancode = %02x", scancode); + + // Ignore ACKs + if(scancode == 0xFA) { + // Oh man! This is anarchic (I'm leaving it here to represent + // the mess that Acess once was) + //kb_lastChar = KB_ACK; + return; + } + + // Layer +1 + if(scancode == 0xE0) { + giKB_KeyLayer = 1; + return; + } + // Layer +2 + if(scancode == 0xE1) { + giKB_KeyLayer = 2; + return; + } + + #if KB_ALT_SCANCODES + if(scancode == 0xF0) + { + gbKB_KeyUp = 1; + return; + } + #else + if(scancode & 0x80) + { + scancode &= 0x7F; + gbKB_KeyUp = 1; + } + #endif + + // Translate + ch = gpKB_Map[giKB_KeyLayer][scancode]; + // Check for unknown key + if(!ch && !gbKB_KeyUp) + Log_Warning("Keyboard", "UNK %i %x", giKB_KeyLayer, scancode); + + // Key Up? + if (gbKB_KeyUp) + { + gbKB_KeyUp = 0; + gbaKB_States[giKB_KeyLayer][scancode] = 0; // Unset key state flag + + #if USE_KERNEL_MAGIC + if(ch == KEY_LCTRL) gbKB_MagicState &= ~1; + if(ch == KEY_LALT) gbKB_MagicState &= ~2; + #endif + + if(ch == KEY_LSHIFT) gbKB_ShiftState &= ~1; + if(ch == KEY_RSHIFT) gbKB_ShiftState &= ~2; + + // Call callback + if(ch != 0 && gKB_Callback) + gKB_Callback( ch & 0x80000000 ); + + // Reset Layer + giKB_KeyLayer = 0; + return; + } + + // Set the bit relating to the key + gbaKB_States[giKB_KeyLayer][scancode] = 1; + // Set shift key bits + if(ch == KEY_LSHIFT) gbKB_ShiftState |= 1; + if(ch == KEY_RSHIFT) gbKB_ShiftState |= 2; + + // Check for Caps Lock + if(ch == KEY_CAPSLOCK) { + gbKB_CapsState = !gbKB_CapsState; + KB_UpdateLEDs(); + } + + // Reset Layer + giKB_KeyLayer = 0; + + // Ignore Non-Printable Characters + if(ch == 0) return; + + // --- Check for Kernel Magic Combos + #if USE_KERNEL_MAGIC + if(ch == KEY_LCTRL) { + gbKB_MagicState |= 1; + //Log_Log("Keyboard", "Kernel Magic LCTRL Down\n"); + } + if(ch == KEY_LALT) { + gbKB_MagicState |= 2; + //Log_Log("Keyboard", "Kernel Magic LALT Down\n"); + } + if(gbKB_MagicState == 3) + { + switch(ch) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': case 'a': case 'b': + case 'c': case 'd': case 'e': case 'f': + { + char str[4] = {'0', 'x', ch, 0}; + if(giKB_MagicAddressPos == BITS/4) return; + giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos; + giKB_MagicAddressPos ++; + } + return; + + // Instruction Tracing + case 't': + Log("Toggle instruction tracing on %i\n", giKB_MagicAddress); + Threads_ToggleTrace( giKB_MagicAddress ); + giKB_MagicAddress = 0; giKB_MagicAddressPos = 0; + return; + + // Thread List Dump + case 'p': Threads_Dump(); return; + // Heap Statistics + case 'h': Heap_Stats(); return; + // Dump Structure + case 's': return; + } + } + #endif + + // Capitals required? + if( (gbKB_ShiftState != 0) != (gbKB_CapsState != 0)) + { + // TODO: Move this to the keyboard map header + switch(ch) + { + case 0: break; + case '`': ch = '~'; break; + case '1': ch = '!'; break; + case '2': ch = '@'; break; + case '3': ch = '#'; break; + case '4': ch = '$'; break; + case '5': ch = '%'; break; + case '6': ch = '^'; break; + case '7': ch = '&'; break; + case '8': ch = '*'; break; + case '9': ch = '('; break; + case '0': ch = ')'; break; + case '-': ch = '_'; break; + case '=': ch = '+'; break; + case '[': ch = '{'; break; + case ']': ch = '}'; break; + case '\\': ch = '|'; break; + case ';': ch = ':'; break; + case '\'': ch = '"'; break; + case ',': ch = '<'; break; + case '.': ch = '>'; break; + case '/': ch = '?'; break; + default: + if('a' <= ch && ch <= 'z') + ch -= 0x20; + break; + } + } + + if(gKB_Callback && ch != 0) gKB_Callback(ch); +} + +/** + * \fn void KB_UpdateLEDs(void) + * \brief Updates the status of the keyboard LEDs + */ +void KB_UpdateLEDs(void) +{ + Uint8 leds; + + leds = (gbKB_CapsState ? 4 : 0); + + while( inb(0x64) & 2 ); // Wait for bit 2 to unset + outb(0x60, 0xED); // Send update command + + while( inb(0x64) & 2 ); // Wait for bit 2 to unset + outb(0x60, leds); +} + +/** + * \fn int KB_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \brief Calls an IOCtl Command + */ +int KB_IOCtl(tVFS_Node *Node, int Id, void *Data) +{ + switch(Id) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_KEYBOARD; + case DRV_IOCTL_IDENT: memcpy(Data, "KB\0\0", 4); return 1; + case DRV_IOCTL_VERSION: return 0x100; + case DRV_IOCTL_LOOKUP: return 0; + + // Sets the Keyboard Callback + case KB_IOCTL_SETCALLBACK: + // Sanity Check + if((Uint)Data < KERNEL_BASE) return 0; + // Can only be set once + if(gKB_Callback != NULL) return 0; + // Set Callback + gKB_Callback = Data; + return 1; + + default: + return 0; + } +} diff --git a/Modules/Input/PS2KbMouse/kb_kbdus.h b/Modules/Input/PS2KbMouse/kb_kbdus.h new file mode 100644 index 00000000..441b19a5 --- /dev/null +++ b/Modules/Input/PS2KbMouse/kb_kbdus.h @@ -0,0 +1,73 @@ + +#ifndef _KBDUS_H +#define _KBDUS_H + +// - BASE (NO PREFIX) +Uint32 gpKBDUS1[256] = { +/*00*/ 0, KEY_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', +/*10*/ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', KEY_LCTRL, 'a', 's', +/*20*/ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`', KEY_LSHIFT,'\\', 'z', 'x', 'c', 'v', +/*30*/ 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT, KEY_KPSTAR, + KEY_LALT, ' ', KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, +/*40*/ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KPHOME, + KEY_KPUP, KEY_KPPGUP, KEY_KPMINUS, KEY_KPLEFT, KEY_KP5, KEY_KPRIGHT, KEY_KPPLUS, KEY_KPEND, +/*50*/ KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL, 0, 0, 0, KEY_F11, + KEY_F12, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +// - 0xE0 Prefixed +Uint32 gpKBDUS2[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_KPENTER, KEY_RCTRL, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*30*/ 0, 0, 0, 0, 0, KEY_KPSLASH, 0, 0, KEY_RALT, 0, 0, 0, 0, 0, 0, 0, +/*40*/ 0, 0, 0, 0, 0, 0, 0, KEY_HOME, + KEY_UP, KEY_PGUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END, +/*50*/ KEY_DOWN, KEY_PGDOWN, KEY_INS, KEY_DEL, 0, 0, 0, 0, + 0, 0, KEY_WIN, 0, 0, KEY_MENU, 0, 0, +/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; +// - 0xE1 Prefixed +Uint32 gpKBDUS3[256] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F +/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F +/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PAUSE, 0, 0, +/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +Uint32 *gpKBDUS[3] = { gpKBDUS1, gpKBDUS2, gpKBDUS3 }; + +#endif diff --git a/Modules/Input/PS2KbMouse/main.c b/Modules/Input/PS2KbMouse/main.c new file mode 100644 index 00000000..179bbb18 --- /dev/null +++ b/Modules/Input/PS2KbMouse/main.c @@ -0,0 +1,25 @@ +/* + * Acess2 + * + * PS/2 Keboard / Mouse Driver + */ +#include +#include + +// === IMPORTS === +extern int KB_Install(char **Arguments); +extern int Mouse_Install(char **Arguments); + +// === PROTOTYPES === + int PS2_Install(char **Arguments); + +// === GLOBALS === +MODULE_DEFINE(0, 0x0100, Input_PS2KbMouse, PS2_Install, NULL, NULL); + +// === CODE === +int PS2_Install(char **Arguments) +{ + KB_Install(Arguments); +// Mouse_Install(Arguments); + return MODULE_ERR_OK; +} diff --git a/Modules/Input/PS2KbMouse/ps2mouse.c b/Modules/Input/PS2KbMouse/ps2mouse.c new file mode 100644 index 00000000..e87292ad --- /dev/null +++ b/Modules/Input/PS2KbMouse/ps2mouse.c @@ -0,0 +1,203 @@ +/* + * Acess2 Mouse Driver + */ +#define DEBUG 0 +#include +#include +#include +#include +#include +#include + +// == CONSTANTS == +#define PS2_IO_PORT 0x60 +#define MOUSE_BUFFER_SIZE (sizeof(t_mouse_fsdata)) +#define MOUSE_SENS_BASE 5 + +// == PROTOTYPES == +// - Internal - + int PS2Mouse_Install(char **Arguments); +void PS2Mouse_IRQ(int Num); +static void mouseSendCommand(Uint8 cmd); +static void enableMouse(); +// - Filesystem - +static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); +static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data); + +typedef struct { + int x, y, buttons, unk; +} t_mouse_fsdata; + +// == GLOBALS == + int giMouse_Sensitivity = 1; +t_mouse_fsdata gMouse_Data = {0, 0, 0, 0}; + int giMouse_MaxX = 640, giMouse_MaxY = 480; + int giMouse_Cycle = 0; // IRQ Position +Uint8 gaMouse_Bytes[4] = {0,0,0,0}; +tDevFS_Driver gMouse_DriverStruct = { + NULL, "ps2mouse", + { + .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX, + .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl + } +}; + +// == CODE == +int Mouse_Install(char **Arguments) +{ + // Initialise Mouse Controller + IRQ_AddHandler(12, PS2Mouse_IRQ); // Set IRQ + giMouse_Cycle = 0; // Set Current Cycle position + enableMouse(); // Enable the mouse + + DevFS_AddDevice(&gMouse_DriverStruct); + + return MODULE_ERR_OK; +} + +/* Handle Mouse Interrupt + */ +void PS2Mouse_IRQ(int Num) +{ + Uint8 flags; + int dx, dy; + //int log2x, log2y; + + gaMouse_Bytes[giMouse_Cycle] = inb(0x60); + if(giMouse_Cycle == 0 && !(gaMouse_Bytes[giMouse_Cycle] & 0x8)) + return; + giMouse_Cycle++; + if(giMouse_Cycle == 3) + giMouse_Cycle = 0; + else + return; + + if(giMouse_Cycle > 0) + return; + + // Read Flags + flags = gaMouse_Bytes[0]; + if(flags & 0xC0) // X/Y Overflow + return; + + #if DEBUG + //LogF(" PS2Mouse_Irq: flags = 0x%x\n", flags); + #endif + + // Calculate dX and dY + dx = (int) ( gaMouse_Bytes[1] | (flags & 0x10 ? ~0x00FF : 0) ); + dy = (int) ( gaMouse_Bytes[2] | (flags & 0x20 ? ~0x00FF : 0) ); + dy = -dy; // Y is negated + LOG("RAW dx=%i, dy=%i\n", dx, dy); + dx = dx*MOUSE_SENS_BASE/giMouse_Sensitivity; + dy = dy*MOUSE_SENS_BASE/giMouse_Sensitivity; + + //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2x) : "a" ((Uint)gaMouse_Bytes[1])); + //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2y) : "a" ((Uint)gaMouse_Bytes[2])); + //LogF(" PS2Mouse_Irq: dx=%i, log2x = %i\n", dx, log2x); + //LogF(" PS2Mouse_Irq: dy=%i, log2y = %i\n", dy, log2y); + //dx *= log2x; + //dy *= log2y; + + // Set Buttons + gMouse_Data.buttons = flags & 0x7; //Buttons (3 only) + + // Update X and Y Positions + gMouse_Data.x += (int)dx; + gMouse_Data.y += (int)dy; + + // Constrain Positions + if(gMouse_Data.x < 0) gMouse_Data.x = 0; + if(gMouse_Data.y < 0) gMouse_Data.y = 0; + if(gMouse_Data.x >= giMouse_MaxX) gMouse_Data.x = giMouse_MaxX-1; + if(gMouse_Data.y >= giMouse_MaxY) gMouse_Data.y = giMouse_MaxY-1; +} + +/* Read mouse state (coordinates) + */ +static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) +{ + if(Length < MOUSE_BUFFER_SIZE) + return -1; + + memcpy(Buffer, &gMouse_Data, MOUSE_BUFFER_SIZE); + + return MOUSE_BUFFER_SIZE; +} + +static const char *csaIOCtls[] = {DRV_IOCTLNAMES, NULL}; +/* Handle messages to the device + */ +static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data) +{ + struct { + int Num; + int Value; + } *info = Data; + switch(ID) + { + BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls); + + case JOY_IOCTL_GETSETAXISLIMIT: + if(!info) return 0; + switch(info->Num) + { + case 0: // X + if(info->Value != -1) + giMouse_MaxX = info->Value; + return giMouse_MaxX; + case 1: // Y + if(info->Value != -1) + giMouse_MaxY = info->Value; + return giMouse_MaxY; + } + return 0; + + default: + return 0; + } +} + +//== Internal Functions == +static inline void mouseOut64(Uint8 data) +{ + int timeout=100000; + while( timeout-- && inb(0x64) & 2 ); // Wait for Flag to clear + outb(0x64, data); // Send Command +} +static inline void mouseOut60(Uint8 data) +{ + int timeout=100000; + while( timeout-- && inb(0x64) & 2 ); // Wait for Flag to clear + outb(0x60, data); // Send Command +} +static inline Uint8 mouseIn60() +{ + int timeout=100000; + while( timeout-- && (inb(0x64) & 1) == 0); // Wait for Flag to set + return inb(0x60); +} +static void mouseSendCommand(Uint8 cmd) +{ + mouseOut64(0xD4); + mouseOut60(cmd); +} + +static void enableMouse() +{ + Uint8 status; + Log_Log("PS2 Mouse", "Enabling Mouse..."); + + // Enable AUX PS/2 + mouseOut64(0xA8); + + // Enable AUX PS/2 (Compaq Status Byte) + mouseOut64(0x20); // Send Command + status = mouseIn60(); // Get Status + status &= 0xDF; status |= 0x02; // Alter Flags (Set IRQ12 (2) and Clear Disable Mouse Clock (20)) + mouseOut64(0x60); // Send Command + mouseOut60(status); // Set Status + + //mouseSendCommand(0xF6); // Set Default Settings + mouseSendCommand(0xF4); // Enable Packets +}