Annotation of qemu/hw/syborg_keyboard.c, revision 1.1.1.6

1.1       root        1: /*
                      2:  * Syborg keyboard controller.
                      3:  *
                      4:  * Copyright (c) 2008 CodeSourcery
                      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: 
                     25: #include "sysbus.h"
                     26: #include "console.h"
                     27: #include "syborg.h"
                     28: 
                     29: //#define DEBUG_SYBORG_KEYBOARD
                     30: 
                     31: #ifdef DEBUG_SYBORG_KEYBOARD
                     32: #define DPRINTF(fmt, ...) \
                     33: do { printf("syborg_keyboard: " fmt , ##args); } while (0)
                     34: #define BADF(fmt, ...) \
                     35: do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
                     36:     exit(1);} while (0)
                     37: #else
                     38: #define DPRINTF(fmt, ...) do {} while(0)
                     39: #define BADF(fmt, ...) \
                     40: do { fprintf(stderr, "syborg_keyboard: error: " fmt , ## __VA_ARGS__); \
                     41: } while (0)
                     42: #endif
                     43: 
                     44: enum {
                     45:     KBD_ID          = 0,
                     46:     KBD_DATA        = 1,
                     47:     KBD_FIFO_COUNT  = 2,
                     48:     KBD_INT_ENABLE  = 3,
                     49:     KBD_FIFO_SIZE   = 4
                     50: };
                     51: 
                     52: typedef struct {
                     53:     SysBusDevice busdev;
1.1.1.5   root       54:     uint32_t int_enabled;
1.1       root       55:     int extension_bit;
                     56:     uint32_t fifo_size;
                     57:     uint32_t *key_fifo;
1.1.1.5   root       58:     uint32_t read_pos, read_count;
1.1       root       59:     qemu_irq irq;
                     60: } SyborgKeyboardState;
                     61: 
                     62: static void syborg_keyboard_update(SyborgKeyboardState *s)
                     63: {
                     64:     int level = s->read_count && s->int_enabled;
                     65:     DPRINTF("Update IRQ %d\n", level);
                     66:     qemu_set_irq(s->irq, level);
                     67: }
                     68: 
                     69: static uint32_t syborg_keyboard_read(void *opaque, target_phys_addr_t offset)
                     70: {
                     71:     SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
                     72:     int c;
                     73: 
                     74:     DPRINTF("reg read %d\n", (int)offset);
                     75:     offset &= 0xfff;
                     76:     switch (offset >> 2) {
                     77:     case KBD_ID:
                     78:         return SYBORG_ID_KEYBOARD;
                     79:     case KBD_FIFO_COUNT:
                     80:         return s->read_count;
                     81:     case KBD_DATA:
                     82:         if (s->read_count == 0) {
                     83:             c = -1;
                     84:             DPRINTF("FIFO underflow\n");
                     85:         } else {
                     86:             c = s->key_fifo[s->read_pos];
                     87:             DPRINTF("FIFO read 0x%x\n", c);
                     88:             s->read_count--;
                     89:             s->read_pos++;
                     90:             if (s->read_pos == s->fifo_size)
                     91:                 s->read_pos = 0;
                     92:         }
                     93:         syborg_keyboard_update(s);
                     94:         return c;
                     95:     case KBD_INT_ENABLE:
                     96:         return s->int_enabled;
                     97:     case KBD_FIFO_SIZE:
                     98:         return s->fifo_size;
                     99:     default:
                    100:         cpu_abort(cpu_single_env, "syborg_keyboard_read: Bad offset %x\n",
                    101:                   (int)offset);
                    102:         return 0;
                    103:     }
                    104: }
                    105: 
                    106: static void syborg_keyboard_write(void *opaque, target_phys_addr_t offset,
                    107:                                   uint32_t value)
                    108: {
                    109:     SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
                    110: 
                    111:     DPRINTF("reg write %d\n", (int)offset);
                    112:     offset &= 0xfff;
                    113:     switch (offset >> 2) {
                    114:     case KBD_INT_ENABLE:
                    115:         s->int_enabled = value;
                    116:         syborg_keyboard_update(s);
                    117:         break;
                    118:     default:
                    119:         cpu_abort(cpu_single_env, "syborg_keyboard_write: Bad offset %x\n",
                    120:                   (int)offset);
                    121:     }
                    122: }
                    123: 
1.1.1.2   root      124: static CPUReadMemoryFunc * const syborg_keyboard_readfn[] = {
1.1       root      125:      syborg_keyboard_read,
                    126:      syborg_keyboard_read,
                    127:      syborg_keyboard_read
                    128: };
                    129: 
1.1.1.2   root      130: static CPUWriteMemoryFunc * const syborg_keyboard_writefn[] = {
1.1       root      131:      syborg_keyboard_write,
                    132:      syborg_keyboard_write,
                    133:      syborg_keyboard_write
                    134: };
                    135: 
                    136: static void syborg_keyboard_event(void *opaque, int keycode)
                    137: {
                    138:     SyborgKeyboardState *s = (SyborgKeyboardState *)opaque;
                    139:     int slot;
                    140:     uint32_t val;
                    141: 
                    142:     /* Strip off 0xe0 prefixes and reconstruct the full scancode.  */
                    143:     if (keycode == 0xe0 && !s->extension_bit) {
                    144:         DPRINTF("Extension bit\n");
                    145:         s->extension_bit = 0x80;
                    146:         return;
                    147:     }
                    148:     val = (keycode & 0x7f) | s->extension_bit;
                    149:     if (keycode & 0x80)
                    150:         val |= 0x80000000u;
                    151:     s->extension_bit = 0;
                    152: 
                    153:     DPRINTF("FIFO push 0x%x\n", val);
                    154:     slot = s->read_pos + s->read_count;
                    155:     if (slot >= s->fifo_size)
                    156:         slot -= s->fifo_size;
                    157: 
                    158:     if (s->read_count < s->fifo_size) {
                    159:         s->read_count++;
                    160:         s->key_fifo[slot] = val;
                    161:     } else {
                    162:         fprintf(stderr, "syborg_keyboard error! FIFO overflow\n");
                    163:     }
                    164: 
                    165:     syborg_keyboard_update(s);
                    166: }
                    167: 
1.1.1.5   root      168: static const VMStateDescription vmstate_syborg_keyboard = {
                    169:     .name = "syborg_keyboard",
                    170:     .version_id = 1,
                    171:     .minimum_version_id = 1,
                    172:     .minimum_version_id_old = 1,
                    173:     .fields      = (VMStateField[]) {
                    174:         VMSTATE_UINT32_EQUAL(fifo_size, SyborgKeyboardState),
                    175:         VMSTATE_UINT32(int_enabled, SyborgKeyboardState),
                    176:         VMSTATE_UINT32(read_pos, SyborgKeyboardState),
                    177:         VMSTATE_UINT32(read_count, SyborgKeyboardState),
                    178:         VMSTATE_VARRAY_UINT32(key_fifo, SyborgKeyboardState, fifo_size, 1,
                    179:                               vmstate_info_uint32, uint32),
                    180:         VMSTATE_END_OF_LIST()
1.1       root      181:     }
1.1.1.5   root      182: };
1.1       root      183: 
1.1.1.2   root      184: static int syborg_keyboard_init(SysBusDevice *dev)
1.1       root      185: {
                    186:     SyborgKeyboardState *s = FROM_SYSBUS(SyborgKeyboardState, dev);
                    187:     int iomemtype;
                    188: 
                    189:     sysbus_init_irq(dev, &s->irq);
                    190:     iomemtype = cpu_register_io_memory(syborg_keyboard_readfn,
1.1.1.4   root      191:                                        syborg_keyboard_writefn, s,
                    192:                                        DEVICE_NATIVE_ENDIAN);
1.1       root      193:     sysbus_init_mmio(dev, 0x1000, iomemtype);
                    194:     if (s->fifo_size <= 0) {
                    195:         fprintf(stderr, "syborg_keyboard: fifo too small\n");
                    196:         s->fifo_size = 16;
                    197:     }
1.1.1.6 ! root      198:     s->key_fifo = g_malloc0(s->fifo_size * sizeof(s->key_fifo[0]));
1.1       root      199: 
                    200:     qemu_add_kbd_event_handler(syborg_keyboard_event, s);
                    201: 
1.1.1.5   root      202:     vmstate_register(&dev->qdev, -1, &vmstate_syborg_keyboard, s);
1.1.1.2   root      203:     return 0;
1.1       root      204: }
                    205: 
                    206: static SysBusDeviceInfo syborg_keyboard_info = {
                    207:     .init = syborg_keyboard_init,
                    208:     .qdev.name  = "syborg,keyboard",
                    209:     .qdev.size  = sizeof(SyborgKeyboardState),
                    210:     .qdev.props = (Property[]) {
1.1.1.2   root      211:         DEFINE_PROP_UINT32("fifo-size", SyborgKeyboardState, fifo_size, 16),
                    212:         DEFINE_PROP_END_OF_LIST(),
1.1       root      213:     }
                    214: };
                    215: 
                    216: static void syborg_keyboard_register_devices(void)
                    217: {
                    218:     sysbus_register_withprop(&syborg_keyboard_info);
                    219: }
                    220: 
                    221: device_init(syborg_keyboard_register_devices)

unix.superglobalmegacorp.com