Kevin O'Connor | 4b60c00 | 2008-02-25 22:29:55 -0500 | [diff] [blame] | 1 | // 16bit code to handle mouse events. |
| 2 | // |
| 3 | // Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net> |
| 4 | // Copyright (C) 2002 MandrakeSoft S.A. |
| 5 | // |
Kevin O'Connor | b1b7c2a | 2009-01-15 20:52:58 -0500 | [diff] [blame] | 6 | // This file may be distributed under the terms of the GNU LGPLv3 license. |
Kevin O'Connor | 4b60c00 | 2008-02-25 22:29:55 -0500 | [diff] [blame] | 7 | |
Kevin O'Connor | 9521e26 | 2008-07-04 13:04:29 -0400 | [diff] [blame] | 8 | #include "biosvar.h" // GET_EBDA |
Kevin O'Connor | 9521e26 | 2008-07-04 13:04:29 -0400 | [diff] [blame] | 9 | #include "bregs.h" // struct bregs |
Kevin O'Connor | 5d369d8 | 2013-09-02 20:48:46 -0400 | [diff] [blame] | 10 | #include "hw/ps2port.h" // ps2_mouse_command |
| 11 | #include "hw/usb-hid.h" // usb_mouse_command |
Kevin O'Connor | 2d2fa31 | 2013-09-14 21:55:26 -0400 | [diff] [blame] | 12 | #include "output.h" // dprintf |
Kevin O'Connor | 1208543 | 2014-09-30 09:17:14 -0400 | [diff] [blame] | 13 | #include "stacks.h" // stack_hop_back |
Kevin O'Connor | 2d2fa31 | 2013-09-14 21:55:26 -0400 | [diff] [blame] | 14 | #include "util.h" // mouse_init |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 15 | |
Kevin O'Connor | f54c150 | 2008-06-14 15:56:16 -0400 | [diff] [blame] | 16 | void |
Kevin O'Connor | d83c87b | 2013-01-21 01:14:12 -0500 | [diff] [blame] | 17 | mouse_init(void) |
Kevin O'Connor | f54c150 | 2008-06-14 15:56:16 -0400 | [diff] [blame] | 18 | { |
Kevin O'Connor | 5787748 | 2009-12-09 21:00:41 -0500 | [diff] [blame] | 19 | if (! CONFIG_MOUSE) |
Kevin O'Connor | f54c150 | 2008-06-14 15:56:16 -0400 | [diff] [blame] | 20 | return; |
| 21 | dprintf(3, "init mouse\n"); |
| 22 | // pointing device installed |
Kevin O'Connor | e51316d | 2012-06-10 09:09:22 -0400 | [diff] [blame] | 23 | set_equipment_flags(0x04, 0x04); |
Kevin O'Connor | f54c150 | 2008-06-14 15:56:16 -0400 | [diff] [blame] | 24 | } |
| 25 | |
Kevin O'Connor | d488a76 | 2012-05-28 14:34:49 -0400 | [diff] [blame] | 26 | static int |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 27 | mouse_command(int command, u8 *param) |
| 28 | { |
Kevin O'Connor | 0e88576 | 2010-05-01 22:14:40 -0400 | [diff] [blame] | 29 | if (usb_mouse_active()) |
Kevin O'Connor | 1208543 | 2014-09-30 09:17:14 -0400 | [diff] [blame] | 30 | return usb_mouse_command(command, param); |
| 31 | return ps2_mouse_command(command, param); |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 32 | } |
| 33 | |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 34 | #define RET_SUCCESS 0x00 |
| 35 | #define RET_EINVFUNCTION 0x01 |
| 36 | #define RET_EINVINPUT 0x02 |
| 37 | #define RET_EINTERFACE 0x03 |
| 38 | #define RET_ENEEDRESEND 0x04 |
| 39 | #define RET_ENOHANDLER 0x05 |
| 40 | |
| 41 | // Disable Mouse |
| 42 | static void |
| 43 | mouse_15c20000(struct bregs *regs) |
| 44 | { |
Kevin O'Connor | 9ead6fc | 2011-05-07 14:19:29 -0400 | [diff] [blame] | 45 | int ret = mouse_command(PSMOUSE_CMD_DISABLE, NULL); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 46 | if (ret) |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 47 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 48 | else |
| 49 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 50 | } |
| 51 | |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 52 | // Enable Mouse |
| 53 | static void |
| 54 | mouse_15c20001(struct bregs *regs) |
| 55 | { |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 56 | u16 ebda_seg = get_ebda_seg(); |
| 57 | u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 58 | if ((mouse_flags_2 & 0x80) == 0) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 59 | set_code_invalid(regs, RET_ENOHANDLER); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 60 | return; |
| 61 | } |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 62 | |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 63 | int ret = mouse_command(PSMOUSE_CMD_ENABLE, NULL); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 64 | if (ret) |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 65 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 66 | else |
Kevin O'Connor | 6c78122 | 2008-03-09 12:19:23 -0400 | [diff] [blame] | 67 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | static void |
| 71 | mouse_15c200XX(struct bregs *regs) |
| 72 | { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 73 | set_code_unimplemented(regs, RET_EINVFUNCTION); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | // Disable/Enable Mouse |
| 77 | static void |
| 78 | mouse_15c200(struct bregs *regs) |
| 79 | { |
| 80 | switch (regs->bh) { |
| 81 | case 0x00: mouse_15c20000(regs); break; |
| 82 | case 0x01: mouse_15c20001(regs); break; |
| 83 | default: mouse_15c200XX(regs); break; |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | // Reset Mouse |
| 88 | static void |
| 89 | mouse_15c201(struct bregs *regs) |
| 90 | { |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 91 | u8 param[2]; |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 92 | int ret = mouse_command(PSMOUSE_CMD_RESET_BAT, param); |
Kevin O'Connor | b44a852 | 2009-01-17 23:30:01 -0500 | [diff] [blame] | 93 | if (ret) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 94 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 95 | return; |
| 96 | } |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 97 | regs->bl = param[0]; |
| 98 | regs->bh = param[1]; |
Kevin O'Connor | 6c78122 | 2008-03-09 12:19:23 -0400 | [diff] [blame] | 99 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | // Set Sample Rate |
| 103 | static void |
| 104 | mouse_15c202(struct bregs *regs) |
| 105 | { |
Kevin O'Connor | 0234cd9 | 2009-01-04 12:20:02 -0500 | [diff] [blame] | 106 | static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200}; |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 107 | if (regs->bh >= ARRAY_SIZE(sample_rates)) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 108 | set_code_invalid(regs, RET_EINVINPUT); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 109 | return; |
| 110 | } |
Kevin O'Connor | 15157a3 | 2008-12-13 11:10:37 -0500 | [diff] [blame] | 111 | u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]); |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 112 | int ret = mouse_command(PSMOUSE_CMD_SETRATE, &mouse_data1); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 113 | if (ret) |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 114 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 115 | else |
| 116 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 117 | } |
| 118 | |
| 119 | // Set Resolution |
| 120 | static void |
| 121 | mouse_15c203(struct bregs *regs) |
| 122 | { |
| 123 | // BH: |
| 124 | // 0 = 25 dpi, 1 count per millimeter |
| 125 | // 1 = 50 dpi, 2 counts per millimeter |
| 126 | // 2 = 100 dpi, 4 counts per millimeter |
| 127 | // 3 = 200 dpi, 8 counts per millimeter |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 128 | if (regs->bh >= 4) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 129 | set_code_invalid(regs, RET_EINVINPUT); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 130 | return; |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 131 | } |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 132 | u8 param = regs->bh; |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 133 | int ret = mouse_command(PSMOUSE_CMD_SETRES, ¶m); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 134 | if (ret) |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 135 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 136 | else |
| 137 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | // Get Device ID |
| 141 | static void |
| 142 | mouse_15c204(struct bregs *regs) |
| 143 | { |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 144 | u8 param[2]; |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 145 | int ret = mouse_command(PSMOUSE_CMD_GETID, param); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 146 | if (ret) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 147 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 148 | return; |
| 149 | } |
| 150 | regs->bh = param[0]; |
Kevin O'Connor | 6c78122 | 2008-03-09 12:19:23 -0400 | [diff] [blame] | 151 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | // Initialize Mouse |
| 155 | static void |
| 156 | mouse_15c205(struct bregs *regs) |
| 157 | { |
| 158 | if (regs->bh != 3) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 159 | set_code_invalid(regs, RET_EINTERFACE); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 160 | return; |
| 161 | } |
Kevin O'Connor | 0881537 | 2008-12-29 21:16:31 -0500 | [diff] [blame] | 162 | u16 ebda_seg = get_ebda_seg(); |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 163 | SET_EBDA(ebda_seg, mouse_flag1, 0x00); |
| 164 | SET_EBDA(ebda_seg, mouse_flag2, regs->bh); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 165 | |
| 166 | // Reset Mouse |
| 167 | mouse_15c201(regs); |
| 168 | } |
| 169 | |
| 170 | // Return Status |
| 171 | static void |
| 172 | mouse_15c20600(struct bregs *regs) |
| 173 | { |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 174 | u8 param[3]; |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 175 | int ret = mouse_command(PSMOUSE_CMD_GETINFO, param); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 176 | if (ret) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 177 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 178 | return; |
| 179 | } |
| 180 | regs->bl = param[0]; |
| 181 | regs->cl = param[1]; |
| 182 | regs->dl = param[2]; |
Kevin O'Connor | 6c78122 | 2008-03-09 12:19:23 -0400 | [diff] [blame] | 183 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 184 | } |
| 185 | |
| 186 | // Set Scaling Factor to 1:1 |
| 187 | static void |
| 188 | mouse_15c20601(struct bregs *regs) |
| 189 | { |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 190 | int ret = mouse_command(PSMOUSE_CMD_SETSCALE11, NULL); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 191 | if (ret) |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 192 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 193 | else |
| 194 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | // Set Scaling Factor to 2:1 |
| 198 | static void |
| 199 | mouse_15c20602(struct bregs *regs) |
| 200 | { |
Kevin O'Connor | dd5a8a6 | 2010-05-01 19:59:34 -0400 | [diff] [blame] | 201 | int ret = mouse_command(PSMOUSE_CMD_SETSCALE21, NULL); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 202 | if (ret) |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 203 | set_code_invalid(regs, RET_ENEEDRESEND); |
Kevin O'Connor | 3b89719 | 2008-07-20 10:08:59 -0400 | [diff] [blame] | 204 | else |
| 205 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | static void |
| 209 | mouse_15c206XX(struct bregs *regs) |
| 210 | { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 211 | set_code_unimplemented(regs, RET_EINVFUNCTION); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 212 | } |
| 213 | |
| 214 | // Return Status & Set Scaling Factor... |
| 215 | static void |
| 216 | mouse_15c206(struct bregs *regs) |
| 217 | { |
| 218 | switch (regs->bh) { |
| 219 | case 0x00: mouse_15c20600(regs); break; |
| 220 | case 0x01: mouse_15c20601(regs); break; |
| 221 | case 0x02: mouse_15c20602(regs); break; |
| 222 | default: mouse_15c206XX(regs); break; |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | // Set Mouse Handler Address |
| 227 | static void |
| 228 | mouse_15c207(struct bregs *regs) |
| 229 | { |
Kevin O'Connor | 9f98542 | 2009-09-09 11:34:39 -0400 | [diff] [blame] | 230 | struct segoff_s farptr = SEGOFF(regs->es, regs->bx); |
Kevin O'Connor | 0881537 | 2008-12-29 21:16:31 -0500 | [diff] [blame] | 231 | u16 ebda_seg = get_ebda_seg(); |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 232 | u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2); |
Kevin O'Connor | 9f98542 | 2009-09-09 11:34:39 -0400 | [diff] [blame] | 233 | if (! farptr.segoff) { |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 234 | /* remove handler */ |
| 235 | if ((mouse_flags_2 & 0x80) != 0) { |
| 236 | mouse_flags_2 &= ~0x80; |
Kevin O'Connor | 9ead6fc | 2011-05-07 14:19:29 -0400 | [diff] [blame] | 237 | mouse_command(PSMOUSE_CMD_DISABLE, NULL); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 238 | } |
| 239 | } else { |
| 240 | /* install handler */ |
| 241 | mouse_flags_2 |= 0x80; |
| 242 | } |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 243 | SET_EBDA(ebda_seg, mouse_flag2, mouse_flags_2); |
| 244 | SET_EBDA(ebda_seg, far_call_pointer, farptr); |
Kevin O'Connor | 6c78122 | 2008-03-09 12:19:23 -0400 | [diff] [blame] | 245 | set_code_success(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | static void |
| 249 | mouse_15c2XX(struct bregs *regs) |
| 250 | { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 251 | set_code_unimplemented(regs, RET_EINVFUNCTION); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 252 | } |
| 253 | |
| 254 | void |
| 255 | handle_15c2(struct bregs *regs) |
| 256 | { |
Kevin O'Connor | c65a380 | 2008-03-02 13:58:23 -0500 | [diff] [blame] | 257 | //debug_stub(regs); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 258 | |
Kevin O'Connor | 5787748 | 2009-12-09 21:00:41 -0500 | [diff] [blame] | 259 | if (! CONFIG_MOUSE) { |
Kevin O'Connor | dfefeb5 | 2009-12-13 13:04:17 -0500 | [diff] [blame] | 260 | set_code_invalid(regs, RET_EUNSUPPORTED); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 261 | return; |
| 262 | } |
| 263 | |
| 264 | switch (regs->al) { |
| 265 | case 0x00: mouse_15c200(regs); break; |
| 266 | case 0x01: mouse_15c201(regs); break; |
| 267 | case 0x02: mouse_15c202(regs); break; |
| 268 | case 0x03: mouse_15c203(regs); break; |
| 269 | case 0x04: mouse_15c204(regs); break; |
| 270 | case 0x05: mouse_15c205(regs); break; |
| 271 | case 0x06: mouse_15c206(regs); break; |
| 272 | case 0x07: mouse_15c207(regs); break; |
| 273 | default: mouse_15c2XX(regs); break; |
| 274 | } |
| 275 | } |
| 276 | |
Kevin O'Connor | 8056825 | 2014-09-29 19:39:31 -0400 | [diff] [blame] | 277 | void VISIBLE16 |
Kevin O'Connor | 7e1baf2 | 2014-09-29 19:23:45 -0400 | [diff] [blame] | 278 | invoke_mouse_handler(void) |
Kevin O'Connor | ecdc655 | 2012-05-28 14:25:15 -0400 | [diff] [blame] | 279 | { |
Kevin O'Connor | 8056825 | 2014-09-29 19:39:31 -0400 | [diff] [blame] | 280 | if (!CONFIG_MOUSE) |
| 281 | return; |
Kevin O'Connor | 7e1baf2 | 2014-09-29 19:23:45 -0400 | [diff] [blame] | 282 | if (need_hop_back()) { |
Kevin O'Connor | b4cca86 | 2015-10-09 11:53:02 -0400 | [diff] [blame] | 283 | stack_hop_back(invoke_mouse_handler, 0, 0); |
Kevin O'Connor | 7e1baf2 | 2014-09-29 19:23:45 -0400 | [diff] [blame] | 284 | return; |
| 285 | } |
Kevin O'Connor | 8056825 | 2014-09-29 19:39:31 -0400 | [diff] [blame] | 286 | ASSERT16(); |
Kevin O'Connor | 7e1baf2 | 2014-09-29 19:23:45 -0400 | [diff] [blame] | 287 | u16 ebda_seg = get_ebda_seg(); |
Kevin O'Connor | ecdc655 | 2012-05-28 14:25:15 -0400 | [diff] [blame] | 288 | u16 status = GET_EBDA(ebda_seg, mouse_data[0]); |
| 289 | u16 X = GET_EBDA(ebda_seg, mouse_data[1]); |
| 290 | u16 Y = GET_EBDA(ebda_seg, mouse_data[2]); |
| 291 | |
| 292 | struct segoff_s func = GET_EBDA(ebda_seg, far_call_pointer); |
| 293 | dprintf(16, "mouse farcall s=%04x x=%04x y=%04x func=%04x:%04x\n" |
| 294 | , status, X, Y, func.seg, func.offset); |
| 295 | |
| 296 | asm volatile( |
| 297 | "pushl %%ebp\n" |
| 298 | "sti\n" |
| 299 | |
| 300 | "pushl %0\n" |
| 301 | "pushw %w1\n" // status |
| 302 | "pushw %w2\n" // X |
| 303 | "pushw %w3\n" // Y |
| 304 | "pushw $0\n" // Z |
| 305 | "lcallw *8(%%esp)\n" |
| 306 | "addl $12, %%esp\n" |
| 307 | |
| 308 | "cli\n" |
| 309 | "cld\n" |
| 310 | "popl %%ebp" |
| 311 | : "+a"(func.segoff), "+c"(status), "+d"(X), "+b"(Y) |
| 312 | : |
| 313 | : "edi", "esi", "cc", "memory"); |
| 314 | } |
| 315 | |
Kevin O'Connor | ac7eb5e | 2012-05-28 14:42:16 -0400 | [diff] [blame] | 316 | void |
Kevin O'Connor | 0234cd9 | 2009-01-04 12:20:02 -0500 | [diff] [blame] | 317 | process_mouse(u8 data) |
Kevin O'Connor | 4b60c00 | 2008-02-25 22:29:55 -0500 | [diff] [blame] | 318 | { |
Kevin O'Connor | 5787748 | 2009-12-09 21:00:41 -0500 | [diff] [blame] | 319 | if (!CONFIG_MOUSE) |
| 320 | return; |
| 321 | |
Kevin O'Connor | 0881537 | 2008-12-29 21:16:31 -0500 | [diff] [blame] | 322 | u16 ebda_seg = get_ebda_seg(); |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 323 | u8 mouse_flags_1 = GET_EBDA(ebda_seg, mouse_flag1); |
| 324 | u8 mouse_flags_2 = GET_EBDA(ebda_seg, mouse_flag2); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 325 | |
Kevin O'Connor | 65e6342 | 2008-07-19 14:12:32 -0400 | [diff] [blame] | 326 | if (! (mouse_flags_2 & 0x80)) |
| 327 | // far call handler not installed |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 328 | return; |
| 329 | |
| 330 | u8 package_count = mouse_flags_2 & 0x07; |
| 331 | u8 index = mouse_flags_1 & 0x07; |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 332 | SET_EBDA(ebda_seg, mouse_data[index], data); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 333 | |
| 334 | if ((index+1) < package_count) { |
| 335 | mouse_flags_1++; |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 336 | SET_EBDA(ebda_seg, mouse_flag1, mouse_flags_1); |
Kevin O'Connor | 4d6dbc6 | 2008-03-02 08:43:44 -0500 | [diff] [blame] | 337 | return; |
| 338 | } |
| 339 | |
Kevin O'Connor | 4bc4997 | 2012-05-13 22:58:08 -0400 | [diff] [blame] | 340 | SET_EBDA(ebda_seg, mouse_flag1, 0); |
Kevin O'Connor | 7e1baf2 | 2014-09-29 19:23:45 -0400 | [diff] [blame] | 341 | invoke_mouse_handler(); |
Kevin O'Connor | 4b60c00 | 2008-02-25 22:29:55 -0500 | [diff] [blame] | 342 | } |