--- /dev/null
+/*
+ * Acess2
+ * PS2 Keyboard Driver
+ */
+#include <acess.h>
+#include <modules.h>
+#include <fs_devfs.h>
+#include <tpl_drv_common.h>
+#include <tpl_drv_keyboard.h>
+#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;
+ }
+}
--- /dev/null
+\r
+#ifndef _KBDUS_H\r
+#define _KBDUS_H\r
+\r
+// - BASE (NO PREFIX)\r
+Uint32 gpKBDUS1[256] = {\r
+/*00*/ 0, KEY_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t',\r
+/*10*/ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', KEY_LCTRL, 'a', 's',\r
+/*20*/ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`', KEY_LSHIFT,'\\', 'z', 'x', 'c', 'v',\r
+/*30*/ 'b', 'n', 'm', ',', '.', '/', KEY_RSHIFT, KEY_KPSTAR,\r
+ KEY_LALT, ' ', KEY_CAPSLOCK, KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,\r
+/*40*/ KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_NUMLOCK, KEY_SCROLLLOCK, KEY_KPHOME,\r
+ KEY_KPUP, KEY_KPPGUP, KEY_KPMINUS, KEY_KPLEFT, KEY_KP5, KEY_KPRIGHT, KEY_KPPLUS, KEY_KPEND,\r
+/*50*/ KEY_KPDOWN, KEY_KPPGDN, KEY_KPINS, KEY_KPDEL, 0, 0, 0, KEY_F11,\r
+ KEY_F12, 0, 0, 0, 0, 0, 0, 0,\r
+/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+// - 0xE0 Prefixed\r
+Uint32 gpKBDUS2[256] = {\r
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
+/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F\r
+/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_KPENTER, KEY_RCTRL, 0, 0,\r
+/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*30*/ 0, 0, 0, 0, 0, KEY_KPSLASH, 0, 0, KEY_RALT, 0, 0, 0, 0, 0, 0, 0,\r
+/*40*/ 0, 0, 0, 0, 0, 0, 0, KEY_HOME,\r
+ KEY_UP, KEY_PGUP, 0, KEY_LEFT, 0, KEY_RIGHT, 0, KEY_END,\r
+/*50*/ KEY_DOWN, KEY_PGDOWN, KEY_INS, KEY_DEL, 0, 0, 0, 0,\r
+ 0, 0, KEY_WIN, 0, 0, KEY_MENU, 0, 0,\r
+/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+// - 0xE1 Prefixed\r
+Uint32 gpKBDUS3[256] = {\r
+// 0 1 2 3 4 5 6 7 8 9 A B C D E F\r
+/*00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0-F\r
+/*10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_PAUSE, 0, 0,\r
+/*20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*A0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*B0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*C0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*D0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*E0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\r
+/*F0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\r
+};\r
+\r
+\r
+Uint32 *gpKBDUS[3] = { gpKBDUS1, gpKBDUS2, gpKBDUS3 };\r
+\r
+#endif\r
--- /dev/null
+/*\r
+ * Acess2 Mouse Driver\r
+ */\r
+#define DEBUG 0\r
+#include <acess.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include <fs_devfs.h>\r
+#include <tpl_drv_common.h>\r
+#include <tpl_drv_joystick.h>\r
+\r
+// == CONSTANTS ==\r
+#define PS2_IO_PORT 0x60\r
+#define MOUSE_BUFFER_SIZE (sizeof(t_mouse_fsdata))\r
+#define MOUSE_SENS_BASE 5\r
+\r
+// == PROTOTYPES ==\r
+// - Internal -\r
+ int PS2Mouse_Install(char **Arguments);\r
+void PS2Mouse_IRQ(int Num);\r
+static void mouseSendCommand(Uint8 cmd);\r
+static void enableMouse();\r
+// - Filesystem -\r
+static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);\r
+static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data);\r
+\r
+typedef struct {\r
+ int x, y, buttons, unk;\r
+} t_mouse_fsdata;\r
+\r
+// == GLOBALS ==\r
+ int giMouse_Sensitivity = 1;\r
+t_mouse_fsdata gMouse_Data = {0, 0, 0, 0};\r
+ int giMouse_MaxX = 640, giMouse_MaxY = 480;\r
+ int giMouse_Cycle = 0; // IRQ Position\r
+Uint8 gaMouse_Bytes[4] = {0,0,0,0};\r
+tDevFS_Driver gMouse_DriverStruct = {\r
+ NULL, "ps2mouse",\r
+ {\r
+ .NumACLs = 1, .ACLs = &gVFS_ACL_EveryoneRX,\r
+ .Read = PS2Mouse_Read, .IOCtl = PS2Mouse_IOCtl\r
+ }\r
+};\r
+\r
+// == CODE ==\r
+int Mouse_Install(char **Arguments)\r
+{\r
+ // Initialise Mouse Controller\r
+ IRQ_AddHandler(12, PS2Mouse_IRQ); // Set IRQ\r
+ giMouse_Cycle = 0; // Set Current Cycle position\r
+ enableMouse(); // Enable the mouse\r
+ \r
+ DevFS_AddDevice(&gMouse_DriverStruct);\r
+ \r
+ return MODULE_ERR_OK;\r
+}\r
+\r
+/* Handle Mouse Interrupt\r
+ */\r
+void PS2Mouse_IRQ(int Num)\r
+{\r
+ Uint8 flags;\r
+ int dx, dy;\r
+ //int log2x, log2y;\r
+ \r
+ gaMouse_Bytes[giMouse_Cycle] = inb(0x60);\r
+ if(giMouse_Cycle == 0 && !(gaMouse_Bytes[giMouse_Cycle] & 0x8))\r
+ return;\r
+ giMouse_Cycle++;\r
+ if(giMouse_Cycle == 3)\r
+ giMouse_Cycle = 0;\r
+ else\r
+ return;\r
+ \r
+ if(giMouse_Cycle > 0)\r
+ return;\r
+ \r
+ // Read Flags\r
+ flags = gaMouse_Bytes[0];\r
+ if(flags & 0xC0) // X/Y Overflow\r
+ return;\r
+ \r
+ #if DEBUG\r
+ //LogF(" PS2Mouse_Irq: flags = 0x%x\n", flags);\r
+ #endif\r
+ \r
+ // Calculate dX and dY\r
+ dx = (int) ( gaMouse_Bytes[1] | (flags & 0x10 ? ~0x00FF : 0) );\r
+ dy = (int) ( gaMouse_Bytes[2] | (flags & 0x20 ? ~0x00FF : 0) );\r
+ dy = -dy; // Y is negated\r
+ LOG("RAW dx=%i, dy=%i\n", dx, dy);\r
+ dx = dx*MOUSE_SENS_BASE/giMouse_Sensitivity;\r
+ dy = dy*MOUSE_SENS_BASE/giMouse_Sensitivity;\r
+ \r
+ //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2x) : "a" ((Uint)gaMouse_Bytes[1]));\r
+ //__asm__ __volatile__ ("bsr %%eax, %%ecx" : "=c" (log2y) : "a" ((Uint)gaMouse_Bytes[2]));\r
+ //LogF(" PS2Mouse_Irq: dx=%i, log2x = %i\n", dx, log2x);\r
+ //LogF(" PS2Mouse_Irq: dy=%i, log2y = %i\n", dy, log2y);\r
+ //dx *= log2x;\r
+ //dy *= log2y;\r
+ \r
+ // Set Buttons\r
+ gMouse_Data.buttons = flags & 0x7; //Buttons (3 only)\r
+ \r
+ // Update X and Y Positions\r
+ gMouse_Data.x += (int)dx;\r
+ gMouse_Data.y += (int)dy;\r
+ \r
+ // Constrain Positions\r
+ if(gMouse_Data.x < 0) gMouse_Data.x = 0;\r
+ if(gMouse_Data.y < 0) gMouse_Data.y = 0;\r
+ if(gMouse_Data.x >= giMouse_MaxX) gMouse_Data.x = giMouse_MaxX-1;\r
+ if(gMouse_Data.y >= giMouse_MaxY) gMouse_Data.y = giMouse_MaxY-1; \r
+}\r
+\r
+/* Read mouse state (coordinates)\r
+ */\r
+static Uint64 PS2Mouse_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+ if(Length < MOUSE_BUFFER_SIZE)\r
+ return -1;\r
+\r
+ memcpy(Buffer, &gMouse_Data, MOUSE_BUFFER_SIZE);\r
+ \r
+ return MOUSE_BUFFER_SIZE;\r
+}\r
+\r
+static const char *csaIOCtls[] = {DRV_IOCTLNAMES, NULL};\r
+/* Handle messages to the device\r
+ */\r
+static int PS2Mouse_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
+{\r
+ struct {\r
+ int Num;\r
+ int Value;\r
+ } *info = Data;\r
+ switch(ID)\r
+ {\r
+ BASE_IOCTLS(DRV_TYPE_JOYSTICK, "PS2Mouse", 0x100, csaIOCtls);\r
+ \r
+ case JOY_IOCTL_GETSETAXISLIMIT:\r
+ if(!info) return 0;\r
+ switch(info->Num)\r
+ {\r
+ case 0: // X\r
+ if(info->Value != -1)\r
+ giMouse_MaxX = info->Value;\r
+ return giMouse_MaxX;\r
+ case 1: // Y\r
+ if(info->Value != -1)\r
+ giMouse_MaxY = info->Value;\r
+ return giMouse_MaxY;\r
+ }\r
+ return 0;\r
+ \r
+ default:\r
+ return 0;\r
+ }\r
+}\r
+\r
+//== Internal Functions ==\r
+static inline void mouseOut64(Uint8 data)\r
+{\r
+ int timeout=100000;\r
+ while( timeout-- && inb(0x64) & 2 ); // Wait for Flag to clear\r
+ outb(0x64, data); // Send Command\r
+}\r
+static inline void mouseOut60(Uint8 data)\r
+{\r
+ int timeout=100000;\r
+ while( timeout-- && inb(0x64) & 2 ); // Wait for Flag to clear\r
+ outb(0x60, data); // Send Command\r
+}\r
+static inline Uint8 mouseIn60()\r
+{\r
+ int timeout=100000;\r
+ while( timeout-- && (inb(0x64) & 1) == 0); // Wait for Flag to set\r
+ return inb(0x60);\r
+}\r
+static void mouseSendCommand(Uint8 cmd)\r
+{\r
+ mouseOut64(0xD4);\r
+ mouseOut60(cmd);\r
+}\r
+\r
+static void enableMouse()\r
+{\r
+ Uint8 status;\r
+ Log_Log("PS2 Mouse", "Enabling Mouse...");\r
+ \r
+ // Enable AUX PS/2\r
+ mouseOut64(0xA8);\r
+ \r
+ // Enable AUX PS/2 (Compaq Status Byte)\r
+ mouseOut64(0x20); // Send Command\r
+ status = mouseIn60(); // Get Status\r
+ status &= 0xDF; status |= 0x02; // Alter Flags (Set IRQ12 (2) and Clear Disable Mouse Clock (20))\r
+ mouseOut64(0x60); // Send Command\r
+ mouseOut60(status); // Set Status\r
+ \r
+ //mouseSendCommand(0xF6); // Set Default Settings\r
+ mouseSendCommand(0xF4); // Enable Packets\r
+}\r