grml...
[seabios.git] / src / mouse.c
index 08beafe6ae34b1598b6dc6b633981a56400decaa..e26cf694ca5bcc37791d533c564071f1ee863efd 100644 (file)
@@ -3,94 +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
-
-static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n";
+#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 void
-set_kbd_command_byte(u8 command_byte)
-{
-    if (inb(PORT_PS2_STATUS) & 0x02)
-        BX_PANIC(panic_msg_keyb_buffer_full, "setkbdcomm");
-    outb(0xD4, PORT_PS2_STATUS);
-
-    outb(0x60, PORT_PS2_STATUS); // write command byte
-    outb(command_byte, PORT_PS2_DATA);
-}
-
-static u8
-inhibit_mouse_int_and_events()
-{
-    // Turn off IRQ generation and aux data line
-    if (inb(PORT_PS2_STATUS) & 0x02)
-        BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse");
-    outb(0x20, PORT_PS2_STATUS); // get command byte
-    while ((inb(PORT_PS2_STATUS) & 0x01) != 0x01)
-        ;
-    u8 prev_command_byte = inb(PORT_PS2_DATA);
-    u8 command_byte = prev_command_byte;
-    //while ( (inb(PORT_PS2_STATUS) & 0x02) );
-    if ( inb(PORT_PS2_STATUS) & 0x02 )
-        BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse");
-    command_byte &= 0xfd; // turn off IRQ 12 generation
-    command_byte |= 0x20; // disable mouse serial clock line
-    outb(0x60, PORT_PS2_STATUS); // write command byte
-    outb(command_byte, PORT_PS2_DATA);
-    return prev_command_byte;
-}
-
-static void
-enable_mouse_int_and_events()
-{
-    // Turn on IRQ generation and aux data line
-    if ( inb(PORT_PS2_STATUS) & 0x02 )
-        BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse");
-    outb(0x20, PORT_PS2_STATUS); // get command byte
-    while ((inb(PORT_PS2_STATUS) & 0x01) != 0x01)
-        ;
-    u8 command_byte = inb(PORT_PS2_DATA);
-    //while ( (inb(PORT_PS2_STATUS) & 0x02) );
-    if (inb(PORT_PS2_STATUS) & 0x02)
-        BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse");
-    command_byte |= 0x02; // turn on IRQ 12 generation
-    command_byte &= 0xdf; // enable mouse serial clock line
-    outb(0x60, PORT_PS2_STATUS); // write command byte
-    outb(command_byte, PORT_PS2_DATA);
-}
-
-static void
-send_to_mouse_ctrl(u8 sendbyte)
-{
-    // wait for chance to write to ctrl
-    if (inb(PORT_PS2_STATUS) & 0x02)
-        BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse");
-    outb(0xD4, PORT_PS2_STATUS);
-    outb(sendbyte, PORT_PS2_DATA);
 }
 
-static void
-get_mouse_data(u8 *data)
+static inline int
+mouse_command(int command, u8 *param)
 {
-    while ((inb(PORT_PS2_STATUS) & 0x21) != 0x21)
-        ;
-    *data = inb(PORT_PS2_DATA);
+    if (usb_mouse_active())
+        return usb_mouse_command(command, param);
+    return ps2_mouse_command(command, param);
 }
 
 #define RET_SUCCESS      0x00
@@ -104,41 +41,34 @@ get_mouse_data(u8 *data)
 static void
 mouse_15c20000(struct bregs *regs)
 {
-    inhibit_mouse_int_and_events(); // disable IRQ12 and packets
-    send_to_mouse_ctrl(0xF5); // disable mouse command
-    u8 mouse_data1;
-    get_mouse_data(&mouse_data1);
-    set_code_success(regs);
+    int ret = mouse_command(PSMOUSE_CMD_DISABLE, NULL);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
+        set_code_success(regs);
 }
 
-#define BX_DEBUG_INT15(args...)
-
 // Enable Mouse
 static void
 mouse_15c20001(struct bregs *regs)
 {
     u8 mouse_flags_2 = GET_EBDA(mouse_flag2);
     if ((mouse_flags_2 & 0x80) == 0) {
-        BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n");
-        set_code_fail(regs, RET_ENOHANDLER);
+        set_code_invalid(regs, RET_ENOHANDLER);
         return;
     }
-    inhibit_mouse_int_and_events(); // disable IRQ12 and packets
-    send_to_mouse_ctrl(0xF4); // enable mouse command
-    u8 mouse_data1;
-    get_mouse_data(&mouse_data1);
-    if (mouse_data1 == 0xFA) {
-        enable_mouse_int_and_events(); // turn IRQ12 and packet generation on
+
+    int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL);
+    if (ret)
+        set_code_invalid(regs, RET_ENEEDRESEND);
+    else
         set_code_success(regs);
-        return;
-    }
-    set_code_fail(regs, RET_ENEEDRESEND);
 }
 
 static void
 mouse_15c200XX(struct bregs *regs)
 {
-    set_code_fail(regs, RET_EINVFUNCTION);
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
 }
 
 // Disable/Enable Mouse
@@ -156,24 +86,14 @@ mouse_15c200(struct bregs *regs)
 static void
 mouse_15c201(struct bregs *regs)
 {
-    inhibit_mouse_int_and_events(); // disable IRQ12 and packets
-    send_to_mouse_ctrl(0xFF); // reset mouse command
-    u8 mouse_data1, mouse_data2, mouse_data3;
-    get_mouse_data(&mouse_data3);
-    // if no mouse attached, it will return RESEND
-    if (mouse_data3 == 0xfe) {
-        set_code_fail(regs, RET_ENEEDRESEND);
+    u8 param[2];
+    int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param);
+    if (ret) {
+        set_code_invalid(regs, RET_ENEEDRESEND);
         return;
     }
-    if (mouse_data3 != 0xfa)
-        BX_PANIC("Mouse reset returned %02x (should be ack)\n"
-                 , (unsigned)mouse_data3);
-    get_mouse_data(&mouse_data1);
-    get_mouse_data(&mouse_data2);
-    // turn IRQ12 and packet generation on
-    enable_mouse_int_and_events();
-    regs->bl = mouse_data1;
-    regs->bh = mouse_data2;
+    regs->bl = param[0];
+    regs->bh = param[1];
     set_code_success(regs);
 }
 
@@ -181,19 +101,17 @@ mouse_15c201(struct bregs *regs)
 static void
 mouse_15c202(struct bregs *regs)
 {
-    if (regs->bh >= 7) {
-        set_code_fail(regs, RET_EUNSUPPORTED);
+    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 = regs->bh * 20;
-    if (!mouse_data1)
-        mouse_data1 = 10;
-    send_to_mouse_ctrl(0xF3); // set sample rate command
-    u8 mouse_data2;
-    get_mouse_data(&mouse_data2);
-    send_to_mouse_ctrl(mouse_data1);
-    get_mouse_data(&mouse_data2);
-    set_code_success(regs);
+    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
@@ -205,38 +123,29 @@ mouse_15c203(struct bregs *regs)
     //      1 =  50 dpi, 2 counts per millimeter
     //      2 = 100 dpi, 4 counts per millimeter
     //      3 = 200 dpi, 8 counts per millimeter
-    u8 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
     if (regs->bh >= 4) {
-        set_code_fail(regs, RET_EUNSUPPORTED);
-        goto done;
+        set_code_invalid(regs, RET_EINVINPUT);
+        return;
     }
-    send_to_mouse_ctrl(0xE8); // set resolution command
-    u8 mouse_data1;
-    get_mouse_data(&mouse_data1);
-    if (mouse_data1 != 0xfa)
-        BX_PANIC("Mouse status returned %02x (should be ack)\n"
-                 , (unsigned)mouse_data1);
-    send_to_mouse_ctrl(regs->bh);
-    get_mouse_data(&mouse_data1);
-    if (mouse_data1 != 0xfa)
-        BX_PANIC("Mouse status returned %02x (should be ack)\n"
-                 , (unsigned)mouse_data1);
-    set_code_success(regs);
-
-done:
-    set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
+    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)
 {
-    inhibit_mouse_int_and_events(); // disable IRQ12 and packets
-    send_to_mouse_ctrl(0xF2); // get mouse ID command
-    u8 mouse_data1, mouse_data2;
-    get_mouse_data(&mouse_data1);
-    get_mouse_data(&mouse_data2);
-    regs->bh = mouse_data2;
+    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);
 }
 
@@ -245,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);
@@ -259,55 +169,44 @@ mouse_15c205(struct bregs *regs)
 static void
 mouse_15c20600(struct bregs *regs)
 {
-    u8 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
-    send_to_mouse_ctrl(0xE9); // get mouse info command
-    u8 mouse_data1, mouse_data2, mouse_data3;
-    get_mouse_data(&mouse_data1);
-    if (mouse_data1 != 0xfa)
-        BX_PANIC("Mouse status returned %02x (should be ack)\n"
-                 , (unsigned)mouse_data1);
-    get_mouse_data(&mouse_data1);
-    get_mouse_data(&mouse_data2);
-    get_mouse_data(&mouse_data3);
-    regs->bl = mouse_data1;
-    regs->cl = mouse_data2;
-    regs->dl = mouse_data3;
+    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_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
-}
-
-static void
-set_scaling(struct bregs *regs, u8 cmd)
-{
-    u8 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets
-    send_to_mouse_ctrl(0xE6);
-    u8 mouse_data1;
-    get_mouse_data(&mouse_data1);
-    if (mouse_data1 != 0xFA)
-        set_code_fail(regs, RET_EUNSUPPORTED);
-    else
-        set_code_success(regs);
-    set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable
 }
 
 // Set Scaling Factor to 1:1
 static void
 mouse_15c20601(struct bregs *regs)
 {
-    set_scaling(regs, 0xE6);
+    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)
 {
-    set_scaling(regs, 0xE7);
+    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)
 {
-    BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", regs->bh);
+    set_code_unimplemented(regs, RET_EINVFUNCTION);
 }
 
 // Return Status & Set Scaling Factor...
@@ -326,27 +225,28 @@ mouse_15c206(struct bregs *regs)
 static void
 mouse_15c207(struct bregs *regs)
 {
-    u32 farptr = (regs->es << 16) | regs->bx;
-    SET_EBDA(far_call_pointer, farptr);
-    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;
-            inhibit_mouse_int_and_events(); // disable IRQ12 and packets
+            mouse_command(PSMOUSE_CMD_DISABLE, NULL);
         }
     } else {
         /* install handler */
         mouse_flags_2 |= 0x80;
     }
-    SET_EBDA(mouse_flag2, mouse_flags_2);
+    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
@@ -354,8 +254,8 @@ 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;
     }
 
@@ -372,42 +272,43 @@ 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)
+    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) != 0x80)
+    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_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);
-    // check if far call handler installed
-    if (! (mouse_flags_2 & 0x80))
-        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);
 
-    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
@@ -415,22 +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);
-
-    irq_enable();
-    int74_function();
-    irq_disable();
-
-    eoi_pic2();
+        : "edi", "esi", "cc", "memory");
 }