Annotation of qemu/roms/seabios/src/mouse.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.