Annotation of qemu/hw/ps2.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU PS/2 keyboard/mouse emulation
        !             3:  * 
        !             4:  * Copyright (c) 2003 Fabrice Bellard
        !             5:  * 
        !             6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             7:  * of this software and associated documentation files (the "Software"), to deal
        !             8:  * in the Software without restriction, including without limitation the rights
        !             9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            10:  * copies of the Software, and to permit persons to whom the Software is
        !            11:  * furnished to do so, subject to the following conditions:
        !            12:  *
        !            13:  * The above copyright notice and this permission notice shall be included in
        !            14:  * all copies or substantial portions of the Software.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            22:  * THE SOFTWARE.
        !            23:  */
        !            24: #include "vl.h"
        !            25: 
        !            26: /* debug PC keyboard */
        !            27: //#define DEBUG_KBD
        !            28: 
        !            29: /* debug PC keyboard : only mouse */
        !            30: //#define DEBUG_MOUSE
        !            31: 
        !            32: /* Keyboard Commands */
        !            33: #define KBD_CMD_SET_LEDS       0xED    /* Set keyboard leds */
        !            34: #define KBD_CMD_ECHO           0xEE
        !            35: #define KBD_CMD_GET_ID                 0xF2    /* get keyboard ID */
        !            36: #define KBD_CMD_SET_RATE       0xF3    /* Set typematic rate */
        !            37: #define KBD_CMD_ENABLE         0xF4    /* Enable scanning */
        !            38: #define KBD_CMD_RESET_DISABLE  0xF5    /* reset and disable scanning */
        !            39: #define KBD_CMD_RESET_ENABLE           0xF6    /* reset and enable scanning */
        !            40: #define KBD_CMD_RESET          0xFF    /* Reset */
        !            41: 
        !            42: /* Keyboard Replies */
        !            43: #define KBD_REPLY_POR          0xAA    /* Power on reset */
        !            44: #define KBD_REPLY_ACK          0xFA    /* Command ACK */
        !            45: #define KBD_REPLY_RESEND       0xFE    /* Command NACK, send the cmd again */
        !            46: 
        !            47: /* Mouse Commands */
        !            48: #define AUX_SET_SCALE11                0xE6    /* Set 1:1 scaling */
        !            49: #define AUX_SET_SCALE21                0xE7    /* Set 2:1 scaling */
        !            50: #define AUX_SET_RES            0xE8    /* Set resolution */
        !            51: #define AUX_GET_SCALE          0xE9    /* Get scaling factor */
        !            52: #define AUX_SET_STREAM         0xEA    /* Set stream mode */
        !            53: #define AUX_POLL               0xEB    /* Poll */
        !            54: #define AUX_RESET_WRAP         0xEC    /* Reset wrap mode */
        !            55: #define AUX_SET_WRAP           0xEE    /* Set wrap mode */
        !            56: #define AUX_SET_REMOTE         0xF0    /* Set remote mode */
        !            57: #define AUX_GET_TYPE           0xF2    /* Get type */
        !            58: #define AUX_SET_SAMPLE         0xF3    /* Set sample rate */
        !            59: #define AUX_ENABLE_DEV         0xF4    /* Enable aux device */
        !            60: #define AUX_DISABLE_DEV                0xF5    /* Disable aux device */
        !            61: #define AUX_SET_DEFAULT                0xF6
        !            62: #define AUX_RESET              0xFF    /* Reset aux device */
        !            63: #define AUX_ACK                        0xFA    /* Command byte ACK. */
        !            64: 
        !            65: #define MOUSE_STATUS_REMOTE     0x40
        !            66: #define MOUSE_STATUS_ENABLED    0x20
        !            67: #define MOUSE_STATUS_SCALE21    0x10
        !            68: 
        !            69: #define PS2_QUEUE_SIZE 256
        !            70: 
        !            71: typedef struct {
        !            72:     uint8_t data[PS2_QUEUE_SIZE];
        !            73:     int rptr, wptr, count;
        !            74: } PS2Queue;
        !            75: 
        !            76: typedef struct {
        !            77:     PS2Queue queue;
        !            78:     int32_t write_cmd;
        !            79:     void (*update_irq)(void *, int);
        !            80:     void *update_arg;
        !            81: } PS2State;
        !            82: 
        !            83: typedef struct {
        !            84:     PS2State common;
        !            85:     int scan_enabled;
        !            86: } PS2KbdState;
        !            87: 
        !            88: typedef struct {
        !            89:     PS2State common;
        !            90:     uint8_t mouse_status;
        !            91:     uint8_t mouse_resolution;
        !            92:     uint8_t mouse_sample_rate;
        !            93:     uint8_t mouse_wrap;
        !            94:     uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
        !            95:     uint8_t mouse_detect_state;
        !            96:     int mouse_dx; /* current values, needed for 'poll' mode */
        !            97:     int mouse_dy;
        !            98:     int mouse_dz;
        !            99:     uint8_t mouse_buttons;
        !           100: } PS2MouseState;
        !           101: 
        !           102: void ps2_queue(void *opaque, int b)
        !           103: {
        !           104:     PS2State *s = (PS2State *)opaque;
        !           105:     PS2Queue *q = &s->queue;
        !           106: 
        !           107:     if (q->count >= PS2_QUEUE_SIZE)
        !           108:         return;
        !           109:     q->data[q->wptr] = b;
        !           110:     if (++q->wptr == PS2_QUEUE_SIZE)
        !           111:         q->wptr = 0;
        !           112:     q->count++;
        !           113:     s->update_irq(s->update_arg, 1);
        !           114: }
        !           115: 
        !           116: static void ps2_put_keycode(void *opaque, int keycode)
        !           117: {
        !           118:     PS2MouseState *s = opaque;
        !           119:     ps2_queue(&s->common, keycode);
        !           120: }
        !           121: 
        !           122: uint32_t ps2_read_data(void *opaque)
        !           123: {
        !           124:     PS2State *s = (PS2State *)opaque;
        !           125:     PS2Queue *q;
        !           126:     int val, index;
        !           127:     
        !           128:     q = &s->queue;
        !           129:     if (q->count == 0) {
        !           130:         /* NOTE: if no data left, we return the last keyboard one
        !           131:            (needed for EMM386) */
        !           132:         /* XXX: need a timer to do things correctly */
        !           133:         index = q->rptr - 1;
        !           134:         if (index < 0)
        !           135:             index = PS2_QUEUE_SIZE - 1;
        !           136:         val = q->data[index];
        !           137:     } else {
        !           138:         val = q->data[q->rptr];
        !           139:         if (++q->rptr == PS2_QUEUE_SIZE)
        !           140:             q->rptr = 0;
        !           141:         q->count--;
        !           142:         /* reading deasserts IRQ */
        !           143:         s->update_irq(s->update_arg, 0);
        !           144:         /* reassert IRQs if data left */
        !           145:         s->update_irq(s->update_arg, q->count != 0);
        !           146:     }
        !           147:     return val;
        !           148: }
        !           149: 
        !           150: static void ps2_reset_keyboard(PS2KbdState *s)
        !           151: {
        !           152:     s->scan_enabled = 1;
        !           153: }
        !           154: 
        !           155: void ps2_write_keyboard(void *opaque, int val)
        !           156: {
        !           157:     PS2KbdState *s = (PS2KbdState *)opaque;
        !           158: 
        !           159:     switch(s->common.write_cmd) {
        !           160:     default:
        !           161:     case -1:
        !           162:         switch(val) {
        !           163:         case 0x00:
        !           164:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           165:             break;
        !           166:         case 0x05:
        !           167:             ps2_queue(&s->common, KBD_REPLY_RESEND);
        !           168:             break;
        !           169:         case KBD_CMD_GET_ID:
        !           170:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           171:             ps2_queue(&s->common, 0xab);
        !           172:             ps2_queue(&s->common, 0x83);
        !           173:             break;
        !           174:         case KBD_CMD_ECHO:
        !           175:             ps2_queue(&s->common, KBD_CMD_ECHO);
        !           176:             break;
        !           177:         case KBD_CMD_ENABLE:
        !           178:             s->scan_enabled = 1;
        !           179:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           180:             break;
        !           181:         case KBD_CMD_SET_LEDS:
        !           182:         case KBD_CMD_SET_RATE:
        !           183:             s->common.write_cmd = val;
        !           184:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           185:             break;
        !           186:         case KBD_CMD_RESET_DISABLE:
        !           187:             ps2_reset_keyboard(s);
        !           188:             s->scan_enabled = 0;
        !           189:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           190:             break;
        !           191:         case KBD_CMD_RESET_ENABLE:
        !           192:             ps2_reset_keyboard(s);
        !           193:             s->scan_enabled = 1;
        !           194:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           195:             break;
        !           196:         case KBD_CMD_RESET:
        !           197:             ps2_reset_keyboard(s);
        !           198:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           199:             ps2_queue(&s->common, KBD_REPLY_POR);
        !           200:             break;
        !           201:         default:
        !           202:             ps2_queue(&s->common, KBD_REPLY_ACK);
        !           203:             break;
        !           204:         }
        !           205:         break;
        !           206:     case KBD_CMD_SET_LEDS:
        !           207:         ps2_queue(&s->common, KBD_REPLY_ACK);
        !           208:         s->common.write_cmd = -1;
        !           209:         break;
        !           210:     case KBD_CMD_SET_RATE:
        !           211:         ps2_queue(&s->common, KBD_REPLY_ACK);
        !           212:         s->common.write_cmd = -1;
        !           213:         break;
        !           214:     }
        !           215: }
        !           216: 
        !           217: static void ps2_mouse_send_packet(PS2MouseState *s)
        !           218: {
        !           219:     unsigned int b;
        !           220:     int dx1, dy1, dz1;
        !           221: 
        !           222:     dx1 = s->mouse_dx;
        !           223:     dy1 = s->mouse_dy;
        !           224:     dz1 = s->mouse_dz;
        !           225:     /* XXX: increase range to 8 bits ? */
        !           226:     if (dx1 > 127)
        !           227:         dx1 = 127;
        !           228:     else if (dx1 < -127)
        !           229:         dx1 = -127;
        !           230:     if (dy1 > 127)
        !           231:         dy1 = 127;
        !           232:     else if (dy1 < -127)
        !           233:         dy1 = -127;
        !           234:     b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
        !           235:     ps2_queue(&s->common, b);
        !           236:     ps2_queue(&s->common, dx1 & 0xff);
        !           237:     ps2_queue(&s->common, dy1 & 0xff);
        !           238:     /* extra byte for IMPS/2 or IMEX */
        !           239:     switch(s->mouse_type) {
        !           240:     default:
        !           241:         break;
        !           242:     case 3:
        !           243:         if (dz1 > 127)
        !           244:             dz1 = 127;
        !           245:         else if (dz1 < -127)
        !           246:                 dz1 = -127;
        !           247:         ps2_queue(&s->common, dz1 & 0xff);
        !           248:         break;
        !           249:     case 4:
        !           250:         if (dz1 > 7)
        !           251:             dz1 = 7;
        !           252:         else if (dz1 < -7)
        !           253:             dz1 = -7;
        !           254:         b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
        !           255:         ps2_queue(&s->common, b);
        !           256:         break;
        !           257:     }
        !           258: 
        !           259:     /* update deltas */
        !           260:     s->mouse_dx -= dx1;
        !           261:     s->mouse_dy -= dy1;
        !           262:     s->mouse_dz -= dz1;
        !           263: }
        !           264: 
        !           265: static void ps2_mouse_event(void *opaque, 
        !           266:                             int dx, int dy, int dz, int buttons_state)
        !           267: {
        !           268:     PS2MouseState *s = opaque;
        !           269: 
        !           270:     /* check if deltas are recorded when disabled */
        !           271:     if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
        !           272:         return;
        !           273: 
        !           274:     s->mouse_dx += dx;
        !           275:     s->mouse_dy -= dy;
        !           276:     s->mouse_dz += dz;
        !           277:     /* XXX: SDL sometimes generates nul events: we delete them */
        !           278:     if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
        !           279:         s->mouse_buttons == buttons_state)
        !           280:        return;
        !           281:     s->mouse_buttons = buttons_state;
        !           282:     
        !           283:     if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
        !           284:         (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) {
        !           285:         for(;;) {
        !           286:             /* if not remote, send event. Multiple events are sent if
        !           287:                too big deltas */
        !           288:             ps2_mouse_send_packet(s);
        !           289:             if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
        !           290:                 break;
        !           291:         }
        !           292:     }
        !           293: }
        !           294: 
        !           295: void ps2_write_mouse(void *opaque, int val)
        !           296: {
        !           297:     PS2MouseState *s = (PS2MouseState *)opaque;
        !           298: #ifdef DEBUG_MOUSE
        !           299:     printf("kbd: write mouse 0x%02x\n", val);
        !           300: #endif
        !           301:     switch(s->common.write_cmd) {
        !           302:     default:
        !           303:     case -1:
        !           304:         /* mouse command */
        !           305:         if (s->mouse_wrap) {
        !           306:             if (val == AUX_RESET_WRAP) {
        !           307:                 s->mouse_wrap = 0;
        !           308:                 ps2_queue(&s->common, AUX_ACK);
        !           309:                 return;
        !           310:             } else if (val != AUX_RESET) {
        !           311:                 ps2_queue(&s->common, val);
        !           312:                 return;
        !           313:             }
        !           314:         }
        !           315:         switch(val) {
        !           316:         case AUX_SET_SCALE11:
        !           317:             s->mouse_status &= ~MOUSE_STATUS_SCALE21;
        !           318:             ps2_queue(&s->common, AUX_ACK);
        !           319:             break;
        !           320:         case AUX_SET_SCALE21:
        !           321:             s->mouse_status |= MOUSE_STATUS_SCALE21;
        !           322:             ps2_queue(&s->common, AUX_ACK);
        !           323:             break;
        !           324:         case AUX_SET_STREAM:
        !           325:             s->mouse_status &= ~MOUSE_STATUS_REMOTE;
        !           326:             ps2_queue(&s->common, AUX_ACK);
        !           327:             break;
        !           328:         case AUX_SET_WRAP:
        !           329:             s->mouse_wrap = 1;
        !           330:             ps2_queue(&s->common, AUX_ACK);
        !           331:             break;
        !           332:         case AUX_SET_REMOTE:
        !           333:             s->mouse_status |= MOUSE_STATUS_REMOTE;
        !           334:             ps2_queue(&s->common, AUX_ACK);
        !           335:             break;
        !           336:         case AUX_GET_TYPE:
        !           337:             ps2_queue(&s->common, AUX_ACK);
        !           338:             ps2_queue(&s->common, s->mouse_type);
        !           339:             break;
        !           340:         case AUX_SET_RES:
        !           341:         case AUX_SET_SAMPLE:
        !           342:             s->common.write_cmd = val;
        !           343:             ps2_queue(&s->common, AUX_ACK);
        !           344:             break;
        !           345:         case AUX_GET_SCALE:
        !           346:             ps2_queue(&s->common, AUX_ACK);
        !           347:             ps2_queue(&s->common, s->mouse_status);
        !           348:             ps2_queue(&s->common, s->mouse_resolution);
        !           349:             ps2_queue(&s->common, s->mouse_sample_rate);
        !           350:             break;
        !           351:         case AUX_POLL:
        !           352:             ps2_queue(&s->common, AUX_ACK);
        !           353:             ps2_mouse_send_packet(s);
        !           354:             break;
        !           355:         case AUX_ENABLE_DEV:
        !           356:             s->mouse_status |= MOUSE_STATUS_ENABLED;
        !           357:             ps2_queue(&s->common, AUX_ACK);
        !           358:             break;
        !           359:         case AUX_DISABLE_DEV:
        !           360:             s->mouse_status &= ~MOUSE_STATUS_ENABLED;
        !           361:             ps2_queue(&s->common, AUX_ACK);
        !           362:             break;
        !           363:         case AUX_SET_DEFAULT:
        !           364:             s->mouse_sample_rate = 100;
        !           365:             s->mouse_resolution = 2;
        !           366:             s->mouse_status = 0;
        !           367:             ps2_queue(&s->common, AUX_ACK);
        !           368:             break;
        !           369:         case AUX_RESET:
        !           370:             s->mouse_sample_rate = 100;
        !           371:             s->mouse_resolution = 2;
        !           372:             s->mouse_status = 0;
        !           373:             s->mouse_type = 0;
        !           374:             ps2_queue(&s->common, AUX_ACK);
        !           375:             ps2_queue(&s->common, 0xaa);
        !           376:             ps2_queue(&s->common, s->mouse_type);
        !           377:             break;
        !           378:         default:
        !           379:             break;
        !           380:         }
        !           381:         break;
        !           382:     case AUX_SET_SAMPLE:
        !           383:         s->mouse_sample_rate = val;
        !           384:         /* detect IMPS/2 or IMEX */
        !           385:         switch(s->mouse_detect_state) {
        !           386:         default:
        !           387:         case 0:
        !           388:             if (val == 200)
        !           389:                 s->mouse_detect_state = 1;
        !           390:             break;
        !           391:         case 1:
        !           392:             if (val == 100)
        !           393:                 s->mouse_detect_state = 2;
        !           394:             else if (val == 200)
        !           395:                 s->mouse_detect_state = 3;
        !           396:             else
        !           397:                 s->mouse_detect_state = 0;
        !           398:             break;
        !           399:         case 2:
        !           400:             if (val == 80) 
        !           401:                 s->mouse_type = 3; /* IMPS/2 */
        !           402:             s->mouse_detect_state = 0;
        !           403:             break;
        !           404:         case 3:
        !           405:             if (val == 80) 
        !           406:                 s->mouse_type = 4; /* IMEX */
        !           407:             s->mouse_detect_state = 0;
        !           408:             break;
        !           409:         }
        !           410:         ps2_queue(&s->common, AUX_ACK);
        !           411:         s->common.write_cmd = -1;
        !           412:         break;
        !           413:     case AUX_SET_RES:
        !           414:         s->mouse_resolution = val;
        !           415:         ps2_queue(&s->common, AUX_ACK);
        !           416:         s->common.write_cmd = -1;
        !           417:         break;
        !           418:     }
        !           419: }
        !           420: 
        !           421: static void ps2_reset(void *opaque)
        !           422: {
        !           423:     PS2State *s = (PS2State *)opaque;
        !           424:     PS2Queue *q;
        !           425:     s->write_cmd = -1;
        !           426:     q = &s->queue;
        !           427:     q->rptr = 0;
        !           428:     q->wptr = 0;
        !           429:     q->count = 0;
        !           430: }
        !           431: 
        !           432: static void ps2_kbd_save(QEMUFile* f, void* opaque)
        !           433: {
        !           434:     PS2KbdState *s = (PS2KbdState*)opaque;
        !           435:     
        !           436:     qemu_put_be32s(f, &s->common.write_cmd);
        !           437:     qemu_put_be32s(f, &s->scan_enabled);
        !           438: }
        !           439: 
        !           440: static void ps2_mouse_save(QEMUFile* f, void* opaque)
        !           441: {
        !           442:     PS2MouseState *s = (PS2MouseState*)opaque;
        !           443:     
        !           444:     qemu_put_be32s(f, &s->common.write_cmd);
        !           445:     qemu_put_8s(f, &s->mouse_status);
        !           446:     qemu_put_8s(f, &s->mouse_resolution);
        !           447:     qemu_put_8s(f, &s->mouse_sample_rate);
        !           448:     qemu_put_8s(f, &s->mouse_wrap);
        !           449:     qemu_put_8s(f, &s->mouse_type);
        !           450:     qemu_put_8s(f, &s->mouse_detect_state);
        !           451:     qemu_put_be32s(f, &s->mouse_dx);
        !           452:     qemu_put_be32s(f, &s->mouse_dy);
        !           453:     qemu_put_be32s(f, &s->mouse_dz);
        !           454:     qemu_put_8s(f, &s->mouse_buttons);
        !           455: }
        !           456: 
        !           457: static int ps2_kbd_load(QEMUFile* f, void* opaque, int version_id)
        !           458: {
        !           459:     PS2KbdState *s = (PS2KbdState*)opaque;
        !           460:     
        !           461:     if (version_id != 1)
        !           462:         return -EINVAL;
        !           463:     qemu_get_be32s(f, &s->common.write_cmd);
        !           464:     qemu_get_be32s(f, &s->scan_enabled);
        !           465:     return 0;
        !           466: }
        !           467: 
        !           468: static int ps2_mouse_load(QEMUFile* f, void* opaque, int version_id)
        !           469: {
        !           470:     PS2MouseState *s = (PS2MouseState*)opaque;
        !           471:     
        !           472:     if (version_id != 1)
        !           473:         return -EINVAL;
        !           474:     qemu_get_be32s(f, &s->common.write_cmd);
        !           475:     qemu_get_8s(f, &s->mouse_status);
        !           476:     qemu_get_8s(f, &s->mouse_resolution);
        !           477:     qemu_get_8s(f, &s->mouse_sample_rate);
        !           478:     qemu_get_8s(f, &s->mouse_wrap);
        !           479:     qemu_get_8s(f, &s->mouse_type);
        !           480:     qemu_get_8s(f, &s->mouse_detect_state);
        !           481:     qemu_get_be32s(f, &s->mouse_dx);
        !           482:     qemu_get_be32s(f, &s->mouse_dy);
        !           483:     qemu_get_be32s(f, &s->mouse_dz);
        !           484:     qemu_get_8s(f, &s->mouse_buttons);
        !           485:     return 0;
        !           486: }
        !           487: 
        !           488: void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg)
        !           489: {
        !           490:     PS2KbdState *s = (PS2KbdState *)qemu_mallocz(sizeof(PS2KbdState));
        !           491: 
        !           492:     s->common.update_irq = update_irq;
        !           493:     s->common.update_arg = update_arg;
        !           494:     ps2_reset(&s->common);
        !           495:     register_savevm("ps2kbd", 0, 1, ps2_kbd_save, ps2_kbd_load, s);
        !           496:     qemu_add_kbd_event_handler(ps2_put_keycode, s);
        !           497:     qemu_register_reset(ps2_reset, &s->common);
        !           498:     return s;
        !           499: }
        !           500: 
        !           501: void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg)
        !           502: {
        !           503:     PS2MouseState *s = (PS2MouseState *)qemu_mallocz(sizeof(PS2MouseState));
        !           504: 
        !           505:     s->common.update_irq = update_irq;
        !           506:     s->common.update_arg = update_arg;
        !           507:     ps2_reset(&s->common);
        !           508:     register_savevm("ps2mouse", 0, 1, ps2_mouse_save, ps2_mouse_load, s);
        !           509:     qemu_add_mouse_event_handler(ps2_mouse_event, s);
        !           510:     qemu_register_reset(ps2_reset, &s->common);
        !           511:     return s;
        !           512: }

unix.superglobalmegacorp.com

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