grml...
[seabios.git] / src / mouse.c
index 7a74ebad262e360690e60feaf0c0abb8db308b88..e26cf694ca5bcc37791d533c564071f1ee863efd 100644 (file)
@@ -3,24 +3,31 @@
 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
 // Copyright (C) 2002  MandrakeSoft S.A.
 //
-// This file may be distributed under the terms of the GNU GPLv3 license.
+// This file may be distributed under the terms of the GNU LGPLv3 license.
 
 #include "biosvar.h" // GET_EBDA
 #include "util.h" // debug_isr
-#include "pic.h" // unmask_pic2
+#include "pic.h" // eoi_pic2
 #include "bregs.h" // struct bregs
-#include "ps2port.h" // aux_command
+#include "ps2port.h" // ps2_mouse_command
+#include "usb-hid.h" // usb_mouse_command
 
 void
-mouse_setup()
+mouse_setup(void)
 {
-    if (! CONFIG_PS2_MOUSE)
+    if (! CONFIG_MOUSE)
         return;
     dprintf(3, "init mouse\n");
     // pointing device installed
     SETBITS_BDA(equipment_list_flags, 0x04);
-    // Enable IRQ12 (handle_74)
-    unmask_pic2(PIC2_IRQ12);
+}
+
+static inline int
+mouse_command(int command, u8 *param)
+{
+    if (usb_mouse_active())
+        return usb_mouse_command(command, param);
+    return ps2_mouse_command(command, param);
 }
 
 #define RET_SUCCESS      0x00
@@ -30,24 +37,13 @@ mouse_setup()
 #define RET_ENEEDRESEND  0x04
 #define RET_ENOHANDLER   0x05
 
-static int
-disable_mouse()
-{
-    u8 ps2ctr = GET_EBDA(ps2ctr);
-    ps2ctr |= I8042_CTR_AUXDIS;
-    ps2ctr &= ~I8042_CTR_AUXINT;
-    SET_EBDA(ps2ctr, ps2ctr);
-
-    return aux_command(PSMOUSE_CMD_DISABLE, NULL);
-}
-
 // Disable Mouse
 static void
 mouse_15c20000(struct bregs *regs)
 {
-    int ret = disable_mouse();
+    int ret = mouse_command(PSMOUSE_CMD_DISABLE, NULL);
     if (ret)
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
     else
         set_code_success(regs);
 }
@@ -58,18 +54,13 @@ mouse_15c20001(struct bregs *regs)
 {
     u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
     if ((mouse_flags_2 & 0x80) == 0) {
-        set_code_fail(regs, RET_ENOHANDLER);
+        set_code_invalid(regs, RET_ENOHANDLER);
         return;
     }
 
-    u8 ps2ctr = GET_EBDA(ps2ctr);
-    ps2ctr &= ~I8042_CTR_AUXDIS;
-    ps2ctr |= I8042_CTR_AUXINT;
-    SET_EBDA(ps2ctr, ps2ctr);
-
-    int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL);
+    int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
     if (ret)
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
     else
         set_code_success(regs);
 }
@@ -77,7 +68,7 @@ mouse_15c20001(struct bregs *regs)
 static void
 mouse_15c200XX(struct bregs *regs)
 {
-    set_code_fail(regs, RET_EINVFUNCTION);
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
 }
 
 // Disable/Enable Mouse
@@ -96,9 +87,9 @@ static void
 mouse_15c201(struct bregs *regs)
 {
     u8 param[2];
-    int ret = aux_command(PSMOUSE_CMD_RESET_BAT, param);
-    if (ret < 0) {
-        set_code_fail(regs, RET_ENEEDRESEND);
+    int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
+    if (ret) {
+        set_code_invalid(regs, RET_ENEEDRESEND);
         return;
     }
     regs->bl = param[0];
@@ -110,15 +101,15 @@ mouse_15c201(struct bregs *regs)
 static void
 mouse_15c202(struct bregs *regs)
 {
-    static u8 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
+    static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
     if (regs->bh >= ARRAY_SIZE(sample_rates)) {
-        set_code_fail(regs, RET_EINVINPUT);
+        set_code_invalid(regs, RET_EINVINPUT);
         return;
     }
-    u8 mouse_data1 = GET_VAR(CS, sample_rates[regs->bh]);
-    int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
+    u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
+    int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
     if (ret)
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
     else
         set_code_success(regs);
 }
@@ -133,13 +124,13 @@ mouse_15c203(struct bregs *regs)
     //      2 = 100 dpi, 4 counts per millimeter
     //      3 = 200 dpi, 8 counts per millimeter
     if (regs->bh >= 4) {
-        set_code_fail(regs, RET_EINVINPUT);
+        set_code_invalid(regs, RET_EINVINPUT);
         return;
     }
     u8 param = regs->bh;
-    int ret = aux_command(PSMOUSE_CMD_SETRES, &param);
+    int ret = mouse_command(PSMOUSE_CMD_SETRES, &param);
     if (ret)
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
     else
         set_code_success(regs);
 }
@@ -149,9 +140,9 @@ static void
 mouse_15c204(struct bregs *regs)
 {
     u8 param[2];
-    int ret = aux_command(PSMOUSE_CMD_GETID, param);
+    int ret = mouse_command(PSMOUSE_CMD_GETID, param);
     if (ret) {
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
         return;
     }
     regs->bh = param[0];
@@ -163,11 +154,12 @@ static void
 mouse_15c205(struct bregs *regs)
 {
     if (regs->bh != 3) {
-        set_code_fail(regs, RET_EINTERFACE);
+        set_code_invalid(regs, RET_EINTERFACE);
         return;
     }
-    SET_EBDA(mouse_flag1, 0x00);
-    SET_EBDA(mouse_flag2, regs->bh);
+    u16 ebda_seg = get_ebda_seg();
+    SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
+    SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
 
     // Reset Mouse
     mouse_15c201(regs);
@@ -178,9 +170,9 @@ static void
 mouse_15c20600(struct bregs *regs)
 {
     u8 param[3];
-    int ret = aux_command(PSMOUSE_CMD_GETINFO, param);
+    int ret = mouse_command(PSMOUSE_CMD_GETINFO, param);
     if (ret) {
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
         return;
     }
     regs->bl = param[0];
@@ -193,9 +185,9 @@ mouse_15c20600(struct bregs *regs)
 static void
 mouse_15c20601(struct bregs *regs)
 {
-    int ret = aux_command(PSMOUSE_CMD_SETSCALE11, NULL);
+    int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL);
     if (ret)
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
     else
         set_code_success(regs);
 }
@@ -204,9 +196,9 @@ mouse_15c20601(struct bregs *regs)
 static void
 mouse_15c20602(struct bregs *regs)
 {
-    int ret = aux_command(PSMOUSE_CMD_SETSCALE21, NULL);
+    int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL);
     if (ret)
-        set_code_fail(regs, RET_ENEEDRESEND);
+        set_code_invalid(regs, RET_ENEEDRESEND);
     else
         set_code_success(regs);
 }
@@ -214,7 +206,7 @@ mouse_15c20602(struct bregs *regs)
 static void
 mouse_15c206XX(struct bregs *regs)
 {
-    set_code_fail(regs, RET_EINVFUNCTION);
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
 }
 
 // Return Status & Set Scaling Factor...
@@ -233,27 +225,28 @@ mouse_15c206(struct bregs *regs)
 static void
 mouse_15c207(struct bregs *regs)
 {
-    u32 farptr = (regs->es << 16) | regs->bx;
-    u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
-    if (! farptr) {
+    struct segoff_s farptr = SEGOFF(regs->es, regs->bx);
+    u16 ebda_seg = get_ebda_seg();
+    u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
+    if (! farptr.segoff) {
         /* remove handler */
         if ((mouse_flags_2 & 0x80) != 0) {
             mouse_flags_2 &= ~0x80;
-            disable_mouse();
+            mouse_command(PSMOUSE_CMD_DISABLE, NULL);
         }
     } else {
         /* install handler */
         mouse_flags_2 |= 0x80;
     }
-    SET_EBDA(mouse_flag2, mouse_flags_2);
-    SET_EBDA(far_call_pointer, farptr);
+    SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
+    SET_EBDA2(ebda_seg, far_call_pointer, farptr);
     set_code_success(regs);
 }
 
 static void
 mouse_15c2XX(struct bregs *regs)
 {
-    set_code_fail(regs, RET_EINVFUNCTION);
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
 }
 
 void
@@ -261,13 +254,11 @@ handle_15c2(struct bregs *regs)
 {
     //debug_stub(regs);
 
-    if (! CONFIG_PS2_MOUSE) {
-        set_code_fail(regs, RET_EUNSUPPORTED);
+    if (! CONFIG_MOUSE) {
+        set_code_invalid(regs, RET_EUNSUPPORTED);
         return;
     }
 
-    irq_enable();
-
     switch (regs->al) {
     case 0x00: mouse_15c200(regs); break;
     case 0x01: mouse_15c201(regs); break;
@@ -281,18 +272,15 @@ handle_15c2(struct bregs *regs)
     }
 }
 
-static void
-int74_function()
+void noinline
+process_mouse(u8 data)
 {
-    u8 v = inb(PORT_PS2_STATUS);
-    if ((v & 0x21) != 0x21) {
-        dprintf(1, "int74 but no mouse data.\n");
+    if (!CONFIG_MOUSE)
         return;
-    }
-    v = inb(PORT_PS2_DATA);
 
-    u8 mouse_flags_1 = GET_EBDA(mouse_flag1);
-    u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
+    u16 ebda_seg = get_ebda_seg();
+    u8 mouse_flags_1 = GET_EBDA2(ebda_seg, mouse_flag1);
+    u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
 
     if (! (mouse_flags_2 & 0x80))
         // far call handler not installed
@@ -300,22 +288,27 @@ int74_function()
 
     u8 package_count = mouse_flags_2 & 0x07;
     u8 index = mouse_flags_1 & 0x07;
-    SET_EBDA(mouse_data[index], v);
+    SET_EBDA2(ebda_seg, mouse_data[index], data);
 
     if ((index+1) < package_count) {
         mouse_flags_1++;
-        SET_EBDA(mouse_flag1, mouse_flags_1);
+        SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
         return;
     }
 
-    //BX_DEBUG_INT74("int74_function: make_farcall=1\n");
-    u16 status = GET_EBDA(mouse_data[0]);
-    u16 X      = GET_EBDA(mouse_data[1]);
-    u16 Y      = GET_EBDA(mouse_data[2]);
-    SET_EBDA(mouse_flag1, 0);
+    u16 status = GET_EBDA2(ebda_seg, mouse_data[0]);
+    u16 X      = GET_EBDA2(ebda_seg, mouse_data[1]);
+    u16 Y      = GET_EBDA2(ebda_seg, mouse_data[2]);
+    SET_EBDA2(ebda_seg, mouse_flag1, 0);
+
+    struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
+    dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n"
+            , status, X, Y, func.seg, func.offset);
 
-    u32 func = GET_EBDA(far_call_pointer);
     asm volatile(
+        "pushl %%ebp\n"
+        "sti\n"
+
         "pushl %0\n"
         "pushw %w1\n"  // status
         "pushw %w2\n"  // X
@@ -323,25 +316,11 @@ int74_function()
         "pushw $0\n"   // Z
         "lcallw *8(%%esp)\n"
         "addl $12, %%esp\n"
+
+        "cli\n"
         "cld\n"
-        : "+a" (func), "+b" (status), "+c" (X), "+d" (Y)
+        "popl %%ebp"
+        : "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y)
         :
-        : "esi", "edi", "ebp", "cc"
-        );
-}
-
-// INT74h : PS/2 mouse hardware interrupt
-void VISIBLE16
-handle_74()
-{
-    debug_isr(DEBUG_ISR_74);
-    if (! CONFIG_PS2_MOUSE)
-        goto done;
-
-    irq_enable();
-    int74_function();
-    irq_disable();
-
-done:
-    eoi_pic2();
+        : "edi", "esi", "cc", "memory");
 }