|
|
1.1 ! root 1: // 16bit code to handle mouse events. ! 2: // ! 3: // Copyright (C) 2008 Kevin O'Connor <[email protected]> ! 4: // Copyright (C) 2002 MandrakeSoft S.A. ! 5: // ! 6: // This file may be distributed under the terms of the GNU LGPLv3 license. ! 7: ! 8: #include "biosvar.h" // GET_EBDA ! 9: #include "util.h" // debug_isr ! 10: #include "pic.h" // eoi_pic2 ! 11: #include "bregs.h" // struct bregs ! 12: #include "ps2port.h" // aux_command ! 13: ! 14: void ! 15: mouse_setup() ! 16: { ! 17: if (! CONFIG_MOUSE) ! 18: return; ! 19: dprintf(3, "init mouse\n"); ! 20: // pointing device installed ! 21: SETBITS_BDA(equipment_list_flags, 0x04); ! 22: } ! 23: ! 24: #define RET_SUCCESS 0x00 ! 25: #define RET_EINVFUNCTION 0x01 ! 26: #define RET_EINVINPUT 0x02 ! 27: #define RET_EINTERFACE 0x03 ! 28: #define RET_ENEEDRESEND 0x04 ! 29: #define RET_ENOHANDLER 0x05 ! 30: ! 31: static int ! 32: disable_mouse(u16 ebda_seg) ! 33: { ! 34: u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr); ! 35: ps2ctr |= I8042_CTR_AUXDIS; ! 36: ps2ctr &= ~I8042_CTR_AUXINT; ! 37: SET_EBDA2(ebda_seg, ps2ctr, ps2ctr); ! 38: ! 39: return aux_command(PSMOUSE_CMD_DISABLE, NULL); ! 40: } ! 41: ! 42: // Disable Mouse ! 43: static void ! 44: mouse_15c20000(struct bregs *regs) ! 45: { ! 46: u16 ebda_seg = get_ebda_seg(); ! 47: int ret = disable_mouse(ebda_seg); ! 48: if (ret) ! 49: set_code_invalid(regs, RET_ENEEDRESEND); ! 50: else ! 51: set_code_success(regs); ! 52: } ! 53: ! 54: // Enable Mouse ! 55: static void ! 56: mouse_15c20001(struct bregs *regs) ! 57: { ! 58: u16 ebda_seg = get_ebda_seg(); ! 59: u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2); ! 60: if ((mouse_flags_2 & 0x80) == 0) { ! 61: set_code_invalid(regs, RET_ENOHANDLER); ! 62: return; ! 63: } ! 64: ! 65: u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr); ! 66: ps2ctr &= ~I8042_CTR_AUXDIS; ! 67: ps2ctr |= I8042_CTR_AUXINT; ! 68: SET_EBDA2(ebda_seg, ps2ctr, ps2ctr); ! 69: ! 70: int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL); ! 71: if (ret) ! 72: set_code_invalid(regs, RET_ENEEDRESEND); ! 73: else ! 74: set_code_success(regs); ! 75: } ! 76: ! 77: static void ! 78: mouse_15c200XX(struct bregs *regs) ! 79: { ! 80: set_code_unimplemented(regs, RET_EINVFUNCTION); ! 81: } ! 82: ! 83: // Disable/Enable Mouse ! 84: static void ! 85: mouse_15c200(struct bregs *regs) ! 86: { ! 87: switch (regs->bh) { ! 88: case 0x00: mouse_15c20000(regs); break; ! 89: case 0x01: mouse_15c20001(regs); break; ! 90: default: mouse_15c200XX(regs); break; ! 91: } ! 92: } ! 93: ! 94: // Reset Mouse ! 95: static void ! 96: mouse_15c201(struct bregs *regs) ! 97: { ! 98: u8 param[2]; ! 99: int ret = aux_command(PSMOUSE_CMD_RESET_BAT, param); ! 100: if (ret) { ! 101: set_code_invalid(regs, RET_ENEEDRESEND); ! 102: return; ! 103: } ! 104: regs->bl = param[0]; ! 105: regs->bh = param[1]; ! 106: set_code_success(regs); ! 107: } ! 108: ! 109: // Set Sample Rate ! 110: static void ! 111: mouse_15c202(struct bregs *regs) ! 112: { ! 113: static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200}; ! 114: if (regs->bh >= ARRAY_SIZE(sample_rates)) { ! 115: set_code_invalid(regs, RET_EINVINPUT); ! 116: return; ! 117: } ! 118: u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]); ! 119: int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1); ! 120: if (ret) ! 121: set_code_invalid(regs, RET_ENEEDRESEND); ! 122: else ! 123: set_code_success(regs); ! 124: } ! 125: ! 126: // Set Resolution ! 127: static void ! 128: mouse_15c203(struct bregs *regs) ! 129: { ! 130: // BH: ! 131: // 0 = 25 dpi, 1 count per millimeter ! 132: // 1 = 50 dpi, 2 counts per millimeter ! 133: // 2 = 100 dpi, 4 counts per millimeter ! 134: // 3 = 200 dpi, 8 counts per millimeter ! 135: if (regs->bh >= 4) { ! 136: set_code_invalid(regs, RET_EINVINPUT); ! 137: return; ! 138: } ! 139: u8 param = regs->bh; ! 140: int ret = aux_command(PSMOUSE_CMD_SETRES, ¶m); ! 141: if (ret) ! 142: set_code_invalid(regs, RET_ENEEDRESEND); ! 143: else ! 144: set_code_success(regs); ! 145: } ! 146: ! 147: // Get Device ID ! 148: static void ! 149: mouse_15c204(struct bregs *regs) ! 150: { ! 151: u8 param[2]; ! 152: int ret = aux_command(PSMOUSE_CMD_GETID, param); ! 153: if (ret) { ! 154: set_code_invalid(regs, RET_ENEEDRESEND); ! 155: return; ! 156: } ! 157: regs->bh = param[0]; ! 158: set_code_success(regs); ! 159: } ! 160: ! 161: // Initialize Mouse ! 162: static void ! 163: mouse_15c205(struct bregs *regs) ! 164: { ! 165: if (regs->bh != 3) { ! 166: set_code_invalid(regs, RET_EINTERFACE); ! 167: return; ! 168: } ! 169: u16 ebda_seg = get_ebda_seg(); ! 170: SET_EBDA2(ebda_seg, mouse_flag1, 0x00); ! 171: SET_EBDA2(ebda_seg, mouse_flag2, regs->bh); ! 172: ! 173: // Reset Mouse ! 174: mouse_15c201(regs); ! 175: } ! 176: ! 177: // Return Status ! 178: static void ! 179: mouse_15c20600(struct bregs *regs) ! 180: { ! 181: u8 param[3]; ! 182: int ret = aux_command(PSMOUSE_CMD_GETINFO, param); ! 183: if (ret) { ! 184: set_code_invalid(regs, RET_ENEEDRESEND); ! 185: return; ! 186: } ! 187: regs->bl = param[0]; ! 188: regs->cl = param[1]; ! 189: regs->dl = param[2]; ! 190: set_code_success(regs); ! 191: } ! 192: ! 193: // Set Scaling Factor to 1:1 ! 194: static void ! 195: mouse_15c20601(struct bregs *regs) ! 196: { ! 197: int ret = aux_command(PSMOUSE_CMD_SETSCALE11, NULL); ! 198: if (ret) ! 199: set_code_invalid(regs, RET_ENEEDRESEND); ! 200: else ! 201: set_code_success(regs); ! 202: } ! 203: ! 204: // Set Scaling Factor to 2:1 ! 205: static void ! 206: mouse_15c20602(struct bregs *regs) ! 207: { ! 208: int ret = aux_command(PSMOUSE_CMD_SETSCALE21, NULL); ! 209: if (ret) ! 210: set_code_invalid(regs, RET_ENEEDRESEND); ! 211: else ! 212: set_code_success(regs); ! 213: } ! 214: ! 215: static void ! 216: mouse_15c206XX(struct bregs *regs) ! 217: { ! 218: set_code_unimplemented(regs, RET_EINVFUNCTION); ! 219: } ! 220: ! 221: // Return Status & Set Scaling Factor... ! 222: static void ! 223: mouse_15c206(struct bregs *regs) ! 224: { ! 225: switch (regs->bh) { ! 226: case 0x00: mouse_15c20600(regs); break; ! 227: case 0x01: mouse_15c20601(regs); break; ! 228: case 0x02: mouse_15c20602(regs); break; ! 229: default: mouse_15c206XX(regs); break; ! 230: } ! 231: } ! 232: ! 233: // Set Mouse Handler Address ! 234: static void ! 235: mouse_15c207(struct bregs *regs) ! 236: { ! 237: struct segoff_s farptr = SEGOFF(regs->es, regs->bx); ! 238: u16 ebda_seg = get_ebda_seg(); ! 239: u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2); ! 240: if (! farptr.segoff) { ! 241: /* remove handler */ ! 242: if ((mouse_flags_2 & 0x80) != 0) { ! 243: mouse_flags_2 &= ~0x80; ! 244: disable_mouse(ebda_seg); ! 245: } ! 246: } else { ! 247: /* install handler */ ! 248: mouse_flags_2 |= 0x80; ! 249: } ! 250: SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2); ! 251: SET_EBDA2(ebda_seg, far_call_pointer, farptr); ! 252: set_code_success(regs); ! 253: } ! 254: ! 255: static void ! 256: mouse_15c2XX(struct bregs *regs) ! 257: { ! 258: set_code_unimplemented(regs, RET_EINVFUNCTION); ! 259: } ! 260: ! 261: void ! 262: handle_15c2(struct bregs *regs) ! 263: { ! 264: //debug_stub(regs); ! 265: ! 266: if (! CONFIG_MOUSE) { ! 267: set_code_invalid(regs, RET_EUNSUPPORTED); ! 268: return; ! 269: } ! 270: ! 271: switch (regs->al) { ! 272: case 0x00: mouse_15c200(regs); break; ! 273: case 0x01: mouse_15c201(regs); break; ! 274: case 0x02: mouse_15c202(regs); break; ! 275: case 0x03: mouse_15c203(regs); break; ! 276: case 0x04: mouse_15c204(regs); break; ! 277: case 0x05: mouse_15c205(regs); break; ! 278: case 0x06: mouse_15c206(regs); break; ! 279: case 0x07: mouse_15c207(regs); break; ! 280: default: mouse_15c2XX(regs); break; ! 281: } ! 282: } ! 283: ! 284: void ! 285: process_mouse(u8 data) ! 286: { ! 287: if (!CONFIG_MOUSE) ! 288: return; ! 289: ! 290: u16 ebda_seg = get_ebda_seg(); ! 291: u8 mouse_flags_1 = GET_EBDA2(ebda_seg, mouse_flag1); ! 292: u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2); ! 293: ! 294: if (! (mouse_flags_2 & 0x80)) ! 295: // far call handler not installed ! 296: return; ! 297: ! 298: u8 package_count = mouse_flags_2 & 0x07; ! 299: u8 index = mouse_flags_1 & 0x07; ! 300: SET_EBDA2(ebda_seg, mouse_data[index], data); ! 301: ! 302: if ((index+1) < package_count) { ! 303: mouse_flags_1++; ! 304: SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1); ! 305: return; ! 306: } ! 307: ! 308: //BX_DEBUG_INT74("int74_function: make_farcall=1\n"); ! 309: u16 status = GET_EBDA2(ebda_seg, mouse_data[0]); ! 310: u16 X = GET_EBDA2(ebda_seg, mouse_data[1]); ! 311: u16 Y = GET_EBDA2(ebda_seg, mouse_data[2]); ! 312: SET_EBDA2(ebda_seg, mouse_flag1, 0); ! 313: ! 314: struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer); ! 315: ! 316: asm volatile( ! 317: "sti\n" ! 318: ! 319: "pushl %0\n" ! 320: "pushw %w1\n" // status ! 321: "pushw %w2\n" // X ! 322: "pushw %w3\n" // Y ! 323: "pushw $0\n" // Z ! 324: "lcallw *8(%%esp)\n" ! 325: "addl $12, %%esp\n" ! 326: ! 327: "cli\n" ! 328: "cld\n" ! 329: : ! 330: : "r"(func.segoff), "r"(status), "r"(X), "r"(Y) ! 331: : "cc" ! 332: ); ! 333: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.