grml...
[seabios.git] / src / mouse.c
index b57a7e7ba1630e0d047adb583bd0ff060b09ebd0..e26cf694ca5bcc37791d533c564071f1ee863efd 100644 (file)
@@ -3,23 +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" // 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_hwirq(12, entry_74);
+}
+
+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
@@ -29,25 +37,13 @@ mouse_setup()
 #define RET_ENEEDRESEND  0x04
 #define RET_ENOHANDLER   0x05
 
-static int
-disable_mouse(u16 ebda_seg)
-{
-    u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
-    ps2ctr |= I8042_CTR_AUXDIS;
-    ps2ctr &= ~I8042_CTR_AUXINT;
-    SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
-
-    return aux_command(PSMOUSE_CMD_DISABLE, NULL);
-}
-
 // Disable Mouse
 static void
 mouse_15c20000(struct bregs *regs)
 {
-    u16 ebda_seg = get_ebda_seg();
-    int ret = disable_mouse(ebda_seg);
+    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);
 }
@@ -56,21 +52,15 @@ mouse_15c20000(struct bregs *regs)
 static void
 mouse_15c20001(struct bregs *regs)
 {
-    u16 ebda_seg = get_ebda_seg();
-    u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
+    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_EBDA2(ebda_seg, ps2ctr);
-    ps2ctr &= ~I8042_CTR_AUXDIS;
-    ps2ctr |= I8042_CTR_AUXINT;
-    SET_EBDA2(ebda_seg, 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);
 }
@@ -78,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
@@ -97,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 && ret != 2) {
-        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];
@@ -113,13 +103,13 @@ mouse_15c202(struct bregs *regs)
 {
     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_GLOBAL(sample_rates[regs->bh]);
-    int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
+    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);
 }
@@ -134,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);
 }
@@ -150,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];
@@ -164,7 +154,7 @@ static void
 mouse_15c205(struct bregs *regs)
 {
     if (regs->bh != 3) {
-        set_code_fail(regs, RET_EINTERFACE);
+        set_code_invalid(regs, RET_EINTERFACE);
         return;
     }
     u16 ebda_seg = get_ebda_seg();
@@ -180,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];
@@ -195,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);
 }
@@ -206,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);
 }
@@ -216,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...
@@ -235,14 +225,14 @@ mouse_15c206(struct bregs *regs)
 static void
 mouse_15c207(struct bregs *regs)
 {
-    u32 farptr = (regs->es << 16) | regs->bx;
+    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) {
+    if (! farptr.segoff) {
         /* remove handler */
         if ((mouse_flags_2 & 0x80) != 0) {
             mouse_flags_2 &= ~0x80;
-            disable_mouse(ebda_seg);
+            mouse_command(PSMOUSE_CMD_DISABLE, NULL);
         }
     } else {
         /* install handler */
@@ -256,7 +246,7 @@ mouse_15c207(struct bregs *regs)
 static void
 mouse_15c2XX(struct bregs *regs)
 {
-    set_code_fail(regs, RET_EINVFUNCTION);
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
 }
 
 void
@@ -264,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;
@@ -284,9 +272,12 @@ handle_15c2(struct bregs *regs)
     }
 }
 
-static void
+void noinline
 process_mouse(u8 data)
 {
+    if (!CONFIG_MOUSE)
+        return;
+
     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);
@@ -305,16 +296,19 @@ process_mouse(u8 data)
         return;
     }
 
-    //BX_DEBUG_INT74("int74_function: make_farcall=1\n");
     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);
 
-    u32 func = GET_EBDA2(ebda_seg, far_call_pointer);
+    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);
 
-    irq_enable();
     asm volatile(
+        "pushl %%ebp\n"
+        "sti\n"
+
         "pushl %0\n"
         "pushw %w1\n"  // status
         "pushw %w2\n"  // X
@@ -322,32 +316,11 @@ process_mouse(u8 data)
         "pushw $0\n"   // Z
         "lcallw *8(%%esp)\n"
         "addl $12, %%esp\n"
+
+        "cli\n"
         "cld\n"
+        "popl %%ebp"
+        : "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y)
         :
-        : "r"(func), "r"(status), "r"(X), "r"(Y)
-        : "cc"
-        );
-    irq_disable();
-}
-
-// INT74h : PS/2 mouse hardware interrupt
-void VISIBLE16
-handle_74()
-{
-    debug_isr(DEBUG_ISR_74);
-    if (! CONFIG_PS2_MOUSE)
-        goto done;
-
-    u8 v = inb(PORT_PS2_STATUS);
-    if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
-        != (I8042_STR_OBF|I8042_STR_AUXDATA)) {
-        dprintf(1, "mouse irq but no mouse data.\n");
-        goto done;
-    }
-    v = inb(PORT_PS2_DATA);
-
-    process_mouse(v);
-
-done:
-    eoi_pic2();
+        : "edi", "esi", "cc", "memory");
 }