Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


imported SEABIOS source tree
[palacios.git] / bios / seabios / src / mouse.c
diff --git a/bios/seabios/src/mouse.c b/bios/seabios/src/mouse.c
new file mode 100644 (file)
index 0000000..e26cf69
--- /dev/null
@@ -0,0 +1,326 @@
+// 16bit code to handle mouse events.
+//
+// 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 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" // ps2_mouse_command
+#include "usb-hid.h" // usb_mouse_command
+
+void
+mouse_setup(void)
+{
+    if (! CONFIG_MOUSE)
+        return;
+    dprintf(3, "init mouse\n");
+    // pointing device installed
+    SETBITS_BDA(equipment_list_flags, 0x04);
+}
+
+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
+#define RET_EINVFUNCTION 0x01
+#define RET_EINVINPUT    0x02
+#define RET_EINTERFACE   0x03
+#define RET_ENEEDRESEND  0x04
+#define RET_ENOHANDLER   0x05
+
+// Disable Mouse
+static void
+mouse_15c20000(struct bregs *regs)
+{
+    int ret = mouse_command(PSMOUSE_CMD_DISABLE, NULL);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
+        set_code_success(regs);
+}
+
+// Enable Mouse
+static void
+mouse_15c20001(struct bregs *regs)
+{
+    u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
+    if ((mouse_flags_2 & 0x80) == 0) {
+        set_code_invalid(regs, RET_ENOHANDLER);
+        return;
+    }
+
+    int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
+        set_code_success(regs);
+}
+
+static void
+mouse_15c200XX(struct bregs *regs)
+{
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
+}
+
+// Disable/Enable Mouse
+static void
+mouse_15c200(struct bregs *regs)
+{
+    switch (regs->bh) {
+    case 0x00: mouse_15c20000(regs); break;
+    case 0x01: mouse_15c20001(regs); break;
+    default:   mouse_15c200XX(regs); break;
+    }
+}
+
+// Reset Mouse
+static void
+mouse_15c201(struct bregs *regs)
+{
+    u8 param[2];
+    int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
+    if (ret) {
+        set_code_invalid(regs, RET_ENEEDRESEND);
+        return;
+    }
+    regs->bl = param[0];
+    regs->bh = param[1];
+    set_code_success(regs);
+}
+
+// Set Sample Rate
+static void
+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_invalid(regs, RET_EINVINPUT);
+        return;
+    }
+    u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
+    int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
+        set_code_success(regs);
+}
+
+// Set Resolution
+static void
+mouse_15c203(struct bregs *regs)
+{
+    // BH:
+    //      0 =  25 dpi, 1 count  per millimeter
+    //      1 =  50 dpi, 2 counts per millimeter
+    //      2 = 100 dpi, 4 counts per millimeter
+    //      3 = 200 dpi, 8 counts per millimeter
+    if (regs->bh >= 4) {
+        set_code_invalid(regs, RET_EINVINPUT);
+        return;
+    }
+    u8 param = regs->bh;
+    int ret = mouse_command(PSMOUSE_CMD_SETRES, &param);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
+        set_code_success(regs);
+}
+
+// Get Device ID
+static void
+mouse_15c204(struct bregs *regs)
+{
+    u8 param[2];
+    int ret = mouse_command(PSMOUSE_CMD_GETID, param);
+    if (ret) {
+        set_code_invalid(regs, RET_ENEEDRESEND);
+        return;
+    }
+    regs->bh = param[0];
+    set_code_success(regs);
+}
+
+// Initialize Mouse
+static void
+mouse_15c205(struct bregs *regs)
+{
+    if (regs->bh != 3) {
+        set_code_invalid(regs, RET_EINTERFACE);
+        return;
+    }
+    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);
+}
+
+// Return Status
+static void
+mouse_15c20600(struct bregs *regs)
+{
+    u8 param[3];
+    int ret = mouse_command(PSMOUSE_CMD_GETINFO, param);
+    if (ret) {
+        set_code_invalid(regs, RET_ENEEDRESEND);
+        return;
+    }
+    regs->bl = param[0];
+    regs->cl = param[1];
+    regs->dl = param[2];
+    set_code_success(regs);
+}
+
+// Set Scaling Factor to 1:1
+static void
+mouse_15c20601(struct bregs *regs)
+{
+    int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
+        set_code_success(regs);
+}
+
+// Set Scaling Factor to 2:1
+static void
+mouse_15c20602(struct bregs *regs)
+{
+    int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
+        set_code_success(regs);
+}
+
+static void
+mouse_15c206XX(struct bregs *regs)
+{
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
+}
+
+// Return Status & Set Scaling Factor...
+static void
+mouse_15c206(struct bregs *regs)
+{
+    switch (regs->bh) {
+    case 0x00: mouse_15c20600(regs); break;
+    case 0x01: mouse_15c20601(regs); break;
+    case 0x02: mouse_15c20602(regs); break;
+    default:   mouse_15c206XX(regs); break;
+    }
+}
+
+// Set Mouse Handler Address
+static void
+mouse_15c207(struct bregs *regs)
+{
+    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;
+            mouse_command(PSMOUSE_CMD_DISABLE, NULL);
+        }
+    } else {
+        /* install handler */
+        mouse_flags_2 |= 0x80;
+    }
+    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_unimplemented(regs, RET_EINVFUNCTION);
+}
+
+void
+handle_15c2(struct bregs *regs)
+{
+    //debug_stub(regs);
+
+    if (! CONFIG_MOUSE) {
+        set_code_invalid(regs, RET_EUNSUPPORTED);
+        return;
+    }
+
+    switch (regs->al) {
+    case 0x00: mouse_15c200(regs); break;
+    case 0x01: mouse_15c201(regs); break;
+    case 0x02: mouse_15c202(regs); break;
+    case 0x03: mouse_15c203(regs); break;
+    case 0x04: mouse_15c204(regs); break;
+    case 0x05: mouse_15c205(regs); break;
+    case 0x06: mouse_15c206(regs); break;
+    case 0x07: mouse_15c207(regs); break;
+    default:   mouse_15c2XX(regs); break;
+    }
+}
+
+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);
+
+    if (! (mouse_flags_2 & 0x80))
+        // far call handler not installed
+        return;
+
+    u8 package_count = mouse_flags_2 & 0x07;
+    u8 index = mouse_flags_1 & 0x07;
+    SET_EBDA2(ebda_seg, mouse_data[index], data);
+
+    if ((index+1) < package_count) {
+        mouse_flags_1++;
+        SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
+        return;
+    }
+
+    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);
+
+    asm volatile(
+        "pushl %%ebp\n"
+        "sti\n"
+
+        "pushl %0\n"
+        "pushw %w1\n"  // status
+        "pushw %w2\n"  // X
+        "pushw %w3\n"  // Y
+        "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)
+        :
+        : "edi", "esi", "cc", "memory");
+}