# Makefile for GeekOS kernel, userspace, and tools
 # Copyright (c) 2004,2005 David H. Hovemeyer <daveho@cs.umd.edu>
-# $Revision: 1.34 $
+# $Revision: 1.35 $
 
 # This is free software.  You are permitted to use,
 # redistribute, and modify it as specified in the file "COPYING".
 
 VMM_OBJS := $(VMM_C_OBJS) $(VMM_ASM_OBJS)
 
-DEVICE_C_SRCS :=  keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c
+DEVICE_C_SRCS :=  generic.c keyboard.c nvram.c timer.c simple_pic.c 8259a.c 8254.c
 
 DEVICE_C_OBJS := $(DEVICE_C_SRCS:%.c=devices/%.o)
 
 
+++ /dev/null
-geekos/idt.o: ../src/geekos/idt.c ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/idt.h \
-  ../include/geekos/int.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/io.h ../include/geekos/debug.h
-geekos/int.o: ../src/geekos/int.c ../include/geekos/idt.h \
-  ../include/geekos/int.h ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/io.h ../include/geekos/debug.h \
-  ../include/geekos/cpu.h
-geekos/trap.o: ../src/geekos/trap.c ../include/geekos/idt.h \
-  ../include/geekos/int.h ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/kthread.h \
-  ../include/geekos/list.h ../include/geekos/trap.h \
-  ../include/geekos/serial.h ../include/geekos/irq.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/io.h ../include/geekos/debug.h
-geekos/irq.o: ../src/geekos/irq.c ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/idt.h ../include/geekos/int.h \
-  ../include/geekos/defs.h ../include/geekos/io.h ../include/geekos/irq.h \
-  ../include/geekos/debug.h ../include/geekos/serial.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
-geekos/io.o: ../src/geekos/io.c ../include/geekos/io.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h
-geekos/blockdev.o: ../src/geekos/blockdev.c ../include/geekos/errno.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/malloc.h ../include/geekos/int.h \
-  ../include/geekos/kassert.h ../include/geekos/defs.h \
-  ../include/geekos/kthread.h ../include/geekos/list.h \
-  ../include/geekos/synch.h ../include/geekos/blockdev.h \
-  ../include/geekos/fileio.h
-geekos/ide.o: ../src/geekos/ide.c ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/int.h \
-  ../include/geekos/kassert.h ../include/geekos/screen.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/io.h ../include/geekos/errno.h \
-  ../include/geekos/malloc.h ../include/geekos/timer.h \
-  ../include/geekos/kthread.h ../include/geekos/list.h \
-  ../include/geekos/blockdev.h ../include/geekos/fileio.h \
-  ../include/geekos/ide.h
-geekos/keyboard.o: ../src/geekos/keyboard.c ../include/geekos/kthread.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/list.h ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/fmtout.h \
-  ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/irq.h ../include/geekos/int.h \
-  ../include/geekos/defs.h ../include/geekos/io.h \
-  ../include/geekos/keyboard.h
-geekos/screen.o: ../src/geekos/screen.c \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/kassert.h ../include/geekos/screen.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  ../include/geekos/io.h ../include/geekos/int.h ../include/geekos/defs.h \
-  ../include/geekos/debug.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
-geekos/timer.o: ../src/geekos/timer.c \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/limits.h \
-  ../include/geekos/io.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/int.h ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/fmtout.h \
-  ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/irq.h \
-  ../include/geekos/kthread.h ../include/geekos/list.h \
-  ../include/geekos/timer.h ../include/geekos/serial.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/debug.h
-geekos/mem.o: ../src/geekos/mem.c ../include/geekos/defs.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/kassert.h ../include/geekos/screen.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/bootinfo.h ../include/geekos/gdt.h \
-  ../include/geekos/int.h ../include/geekos/malloc.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/mem.h ../include/geekos/list.h \
-  ../include/geekos/paging.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/io.h \
-  ../include/geekos/debug.h
-geekos/crc32.o: ../src/geekos/crc32.c ../include/geekos/crc32.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/kassert.h ../include/geekos/screen.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/serial.h ../include/geekos/irq.h \
-  ../include/geekos/int.h ../include/geekos/defs.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  ../include/geekos/io.h ../include/geekos/debug.h
-geekos/gdt.o: ../src/geekos/gdt.c ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/segment.h ../include/geekos/int.h \
-  ../include/geekos/defs.h ../include/geekos/tss.h \
-  ../include/geekos/gdt.h ../include/libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/debug.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h ../include/geekos/io.h
-geekos/tss.o: ../src/geekos/tss.c ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/gdt.h \
-  ../include/geekos/segment.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/tss.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/int.h ../include/geekos/io.h \
-  ../include/geekos/debug.h
-geekos/segment.o: ../src/geekos/segment.c ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/tss.h ../include/geekos/segment.h
-geekos/bget.o: ../src/geekos/bget.c ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/kassert.h ../include/geekos/screen.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/bget.h
-geekos/malloc.o: ../src/geekos/malloc.c ../include/geekos/screen.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/int.h ../include/geekos/kassert.h \
-  ../include/geekos/defs.h ../include/geekos/bget.h \
-  ../include/geekos/malloc.h
-geekos/synch.o: ../src/geekos/synch.c ../include/geekos/kthread.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/list.h ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/fmtout.h \
-  ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/int.h ../include/geekos/defs.h \
-  ../include/geekos/synch.h
-geekos/kthread.o: ../src/geekos/kthread.c ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/int.h \
-  ../include/geekos/mem.h ../include/geekos/list.h \
-  ../include/geekos/paging.h ../include/geekos/bootinfo.h \
-  ../include/geekos/symbol.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/kthread.h ../include/geekos/malloc.h \
-  ../include/geekos/serial.h ../include/geekos/irq.h \
-  ../include/geekos/io.h ../include/geekos/debug.h
-geekos/serial.o: ../src/geekos/serial.c ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/int.h \
-  ../include/geekos/kassert.h ../include/geekos/screen.h \
-  ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/io.h ../include/geekos/reboot.h \
-  ../include/geekos/gdt.h ../include/geekos/idt.h
-geekos/reboot.o: ../src/geekos/reboot.c ../include/geekos/reboot.h \
-  ../include/libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
-geekos/paging.o: ../src/geekos/paging.c ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/int.h ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/idt.h \
-  ../include/geekos/kthread.h ../include/geekos/list.h \
-  ../include/geekos/mem.h ../include/geekos/paging.h \
-  ../include/geekos/bootinfo.h ../include/geekos/malloc.h \
-  ../include/geekos/gdt.h ../include/geekos/segment.h \
-  ../include/geekos/crc32.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/io.h \
-  ../include/geekos/debug.h
-geekos/debug.o: ../src/geekos/debug.c ../include/geekos/debug.h \
-  ../include/geekos/serial.h ../include/geekos/irq.h \
-  ../include/geekos/int.h ../include/geekos/kassert.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/defs.h ../include/geekos/string.h \
-  ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/io.h
-geekos/main.o: ../src/geekos/main.c ../include/geekos/bootinfo.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/screen.h ../include/geekos/ktypes.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/geekos/mem.h ../include/geekos/defs.h \
-  ../include/geekos/list.h ../include/geekos/kassert.h \
-  ../include/geekos/paging.h ../include/geekos/crc32.h \
-  ../include/geekos/tss.h ../include/geekos/int.h \
-  ../include/geekos/kthread.h ../include/geekos/trap.h \
-  ../include/geekos/timer.h ../include/geekos/keyboard.h \
-  ../include/geekos/io.h ../include/geekos/serial.h \
-  ../include/geekos/irq.h ../include/geekos/reboot.h \
-  ../include/geekos/ide.h ../include/geekos/malloc.h \
-  ../include/geekos/debug.h ../include/geekos/vm.h \
-  ../include/geekos/gdt.h ../include/geekos/vmm_stubs.h
-common/fmtout.o: ../src/common/fmtout.c \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
-  ../include/geekos/string.h ../include/geekos/../libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/limits.h \
-  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h
-common/string.o: ../src/common/string.c ../include/libc/fmtout.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
-  ../include/libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
-common/memmove.o: ../src/common/memmove.c ../include/libc/string.h \
-  /home/jarusl/vmm-dev/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
 
--- /dev/null
+#ifndef __GENERIC_H
+#define __GENERIC_H
+
+#include <palacios/vm_dev.h>
+
+//
+// The generic device simply hooks ranges of ports, addresses, and irqs
+// if they are not already hooked
+//
+// for each hooked port, it simply executes reads and writes and the same physical port,
+// for each hooked memory range, it simply executes reads and writes on the same
+//    physical memory addresses
+// for each hooked irq, it simply injects the irq into the VM
+//
+// These operations are also logged to serial (optionaly)
+//
+// If you attach a generic device *last*, you can capture all ops that are not
+// already hooked, and capture a log of VM activity with respect to them.
+//
+// The effects of using the generic device should be identical to 
+// doing passthrough I/O, but with logging, and, of course, slower
+//
+
+
+// A port range is low..high, inclusive
+typedef uint_t generic_port_range_type[2];
+// A memory range is low..high, inclusive
+typedef void *generic_address_range_type[2];
+// An interrupt ory map range is low..high, inclusive
+typedef uint_t generic_irq_range_type[2];
+
+struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
+                                uint_t                     num_port_ranges,
+                                generic_address_range_type addess_ranges[],
+                                uint_t                     num_address_ranges,
+                                generic_irq_range_type     irq_ranges[],
+                                uint_t                     num_irqranges);
+
+#endif
 
 
 #include <palacios/vm_dev.h>
 
-
+//
+// The underlying driver needs to call this on each key that
+// it wants to inject into the VMM for delivery to a VM
+//
+void deliver_key_to_vmm(uchar_t status, uchar_t scancode);
 
 struct vm_device *create_keyboard();
 
 
--- /dev/null
+#include <devices/generic.h>
+#include <geekos/io.h>
+#include <palacios/vmm.h>
+#include <palacios/vmm_types.h>
+
+
+
+#define GENERIC_DEBUG 1
+
+#if GENERIC_DEBUG
+#define GENERIC_DEBUG_PRINT(first, rest...) do { SerialPrint(first, ## rest ); } while (0) 
+#else
+#define GENERIC_DEBUG_PRINT(first, rest...)
+#endif
+
+
+#define PORT_HOOKS 1
+#define MEM_HOOKS  0   // not yet implmented in device model
+#define IRQ_HOOKS  0   // not yet implemented in device model
+
+extern struct vmm_os_hooks *os_hooks;
+
+extern void SerialPrint(const char *format, ...);
+
+
+
+struct generic_internal {
+  generic_port_range_type    *port_ranges;
+  uint_t                     num_port_ranges;
+  generic_address_range_type *address_ranges;
+  uint_t                     num_address_ranges;
+  generic_irq_range_type     *irq_ranges;
+  uint_t                     num_irq_ranges;
+};
+
+
+  
+    
+
+
+
+
+int generic_reset_device(struct vm_device * dev)
+{
+  GENERIC_DEBUG_PRINT("generic: reset device\n");
+ 
+  return 0;
+
+}
+
+
+
+
+
+int generic_start_device(struct vm_device *dev)
+{
+  GENERIC_DEBUG_PRINT("generic: start device\n");
+  return 0;
+}
+
+
+int generic_stop_device(struct vm_device *dev)
+{
+  GENERIC_DEBUG_PRINT("generic: stop device\n");
+  return 0;
+}
+
+
+
+
+int generic_write_port(ushort_t port,
+                      void * src, 
+                      uint_t length,
+                      struct vm_device * dev)
+{
+  uint_t i;
+
+  GENERIC_DEBUG_PRINT("generic: writing 0x");
+  for (i=0;i<length;i++) { 
+    GENERIC_DEBUG_PRINT("%x",((uchar_t*)src)[i]);
+  }
+  GENERIC_DEBUG_PRINT(" to port 0x%x ... ",port);
+  for (i=0;i<length;i++) { 
+    Out_Byte(port,((uchar_t*)src)[i]);
+  }
+  GENERIC_DEBUG_PRINT(" done\n");
+  
+  return length;
+}
+
+int generic_read_port(ushort_t port,
+                     void * src, 
+                     uint_t length,
+                     struct vm_device * dev)
+{
+  uint_t i;
+
+  GENERIC_DEBUG_PRINT("generic: reading 0x%x bytes from port 0x%x ...",length,port);
+  for (i=0;i<length;i++) { 
+    ((uchar_t*)src)[i] =In_Byte(port);
+  }
+  GENERIC_DEBUG_PRINT(" done ... read 0x");
+  for (i=0;i<length;i++) { 
+    GENERIC_DEBUG_PRINT("%x",((uchar_t*)src)[i]);
+  }
+  GENERIC_DEBUG_PRINT("\n");
+
+  return length;
+}
+
+
+
+int generic_interrupt(uint_t irq,
+                     struct vm_device * dev) 
+{
+  PrintDebug("generic: interrupt 0x%x - injecting into VM\n",irq);
+
+  dev->vm->vm_ops.raise_irq(dev->vm,irq,0);
+
+  return 0;
+
+}
+
+
+int generic_init_device(struct vm_device * dev) 
+{
+  struct generic_internal *state = (struct generic_internal *) dev->private_data;
+  uint_t i,j;
+
+  GENERIC_DEBUG_PRINT("generic: init_device\n");
+
+  // Would read state here
+
+  generic_reset_device(dev);
+
+  for (i=0;i<state->num_port_ranges;i++) { 
+    GENERIC_DEBUG_PRINT("generic: hooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
+#if PORT_HOOKS
+    for (j=state->port_ranges[i][0]; j<=state->port_ranges[i][1];j++) { 
+      if (dev_hook_io(dev, j, &generic_read_port, &generic_write_port)) { 
+       GENERIC_DEBUG_PRINT("generic: can't hook port 0x%x (already hooked?)\n",j);
+      }
+    }
+#else
+    GENERIC_DEBUG_PRINT("generic: hooking ports not supported\n");
+#endif
+
+  }
+
+  for (i=0;i<state->num_address_ranges;i++) { 
+    GENERIC_DEBUG_PRINT("generic: hooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]); 
+#if MEM_HOOKS
+    if (dev_hook_mem(dev, state->address_ranges[i][0],state->address_ranges[i][1])) {
+      GENERIC_DEBUG_PRINT("generic: Can't hook addresses 0x%x to 0x%x (already hooked?)\n",
+                 state->address_ranges[i][0],state->address_ranges[i][1]); 
+    }
+#else
+    GENERIC_DEBUG_PRINT("generic: hooking addresses not supported\n");
+#endif
+
+  }
+
+  for (i=0;i<state->num_irq_ranges;i++) { 
+    GENERIC_DEBUG_PRINT("generic: hooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
+#if IRQ_HOOKS
+    for (j=state->irq_ranges[i][0]; j<=state->irq_ranges[i][1];j++) { 
+      if (dev_hook_irq(dev, j,  &generic_interrupt)) { 
+       GENERIC_DEBUG_PRINT("generic: can't hook irq  0x%x (already hooked?)\n",j);
+      }
+    }
+#else
+    GENERIC_DEBUG_PRINT("generic: hooking irqs not supported\n");
+#endif
+  }
+
+  return 0;
+}
+
+int generic_deinit_device(struct vm_device *dev)
+{
+  struct generic_internal *state = (struct generic_internal *) dev->private_data;
+  uint_t i,j;
+
+  GENERIC_DEBUG_PRINT("generic: deinit_device\n");
+
+  for (i=0;i<state->num_irq_ranges;i++) { 
+    GENERIC_DEBUG_PRINT("generic: unhooking irqs 0x%x to 0x%x\n",state->irq_ranges[i][0],state->irq_ranges[i][1]);
+#if IRQ_HOOKS
+    for (j=state->irq_ranges[i][0]; j<=state->irq_ranges[i][1];j++) { 
+      if (dev_unhook_irq(dev, j)) {
+       GENERIC_DEBUG_PRINT("generic: can't unhook irq 0x%x (already unhooked?)\n",j);
+      }
+    }
+#else
+    GENERIC_DEBUG_PRINT("generic: unhooking irqs not supported\n");
+#endif
+
+  }
+
+  for (i=0;i<state->num_address_ranges;i++) { 
+    GENERIC_DEBUG_PRINT("generic: unhooking addresses 0x%x to 0x%x\n",state->address_ranges[i][0],state->address_ranges[i][1]); 
+#if MEM_HOOKS
+    if (dev_unhook_mem(dev, state->address_ranges[i][0],state->address_ranges[i][1])) {
+      GENERIC_DEBUG_PRINT("generic: Can't unhook addresses 0x%x to 0x%x (already unhooked?)\n",
+                 state->address_ranges[i][0],state->address_ranges[i][1]); 
+    }
+#else
+    GENERIC_DEBUG_PRINT("generic: unhooking addresses not supported\n");
+#endif
+  }
+
+  for (i=0;i<state->num_port_ranges;i++) { 
+    GENERIC_DEBUG_PRINT("generic: unhooking ports 0x%x to 0x%x\n",state->port_ranges[i][0],state->port_ranges[i][1]);
+#if PORT_HOOKS
+    for (j=state->port_ranges[i][0]; j<=state->port_ranges[i][1];j++) { 
+      if (dev_unhook_io(dev, j)) {
+       GENERIC_DEBUG_PRINT("generic: can't unhook port 0x%x (already unhooked?)\n",j);
+      }
+    }
+#else
+    GENERIC_DEBUG_PRINT("generic: unhooking ports not supported\n");
+#endif
+
+  }
+
+  generic_reset_device(dev);
+  return 0;
+}
+
+
+
+
+
+static struct vm_device_ops dev_ops = { 
+  .init = generic_init_device, 
+  .deinit = generic_deinit_device,
+  .reset = generic_reset_device,
+  .start = generic_start_device,
+  .stop = generic_stop_device,
+};
+
+
+
+
+struct vm_device *create_generic(generic_port_range_type    port_ranges[], 
+                                uint_t                     num_port_ranges,
+                                generic_address_range_type address_ranges[],
+                                uint_t                     num_address_ranges,
+                                generic_irq_range_type     irq_ranges[],
+                                uint_t                     num_irq_ranges)
+{
+  struct generic_internal * generic_state = os_hooks->malloc(sizeof(struct generic_internal));
+
+
+  generic_state->num_port_ranges=num_port_ranges;
+  if (num_port_ranges>0) { 
+    generic_state->port_ranges = os_hooks->malloc(sizeof(generic_address_range_type)*num_port_ranges);
+    memcpy(generic_state->port_ranges,port_ranges,sizeof(generic_port_range_type)*num_port_ranges);
+  } else {
+    generic_state->port_ranges=NULL;
+  }
+
+  generic_state->num_address_ranges=num_address_ranges;
+  if (num_address_ranges>0) { 
+    generic_state->address_ranges = os_hooks->malloc(sizeof(generic_address_range_type)*num_address_ranges);
+    memcpy(generic_state->address_ranges,address_ranges,sizeof(generic_address_range_type)*num_address_ranges);
+  } else {
+    generic_state->address_ranges=NULL;
+  }
+  generic_state->num_irq_ranges=num_irq_ranges;
+  if (num_irq_ranges>0) { 
+    generic_state->irq_ranges = os_hooks->malloc(sizeof(generic_address_range_type)*num_irq_ranges);
+    memcpy(generic_state->irq_ranges,irq_ranges,sizeof(generic_irq_range_type)*num_port_ranges);
+  } else {
+    generic_state->irq_ranges=NULL;
+  }
+
+
+  struct vm_device *device = create_device("GENERIC", &dev_ops, generic_state);
+
+  return device;
+}
 
 #include <palacios/vmm.h>
 #include <palacios/vmm_types.h>
 
+#define KEYBOARD_DEBUG 1
+
+#if KEYBOARD_DEBUG
+#define KEYBOARD_DEBUG_PRINT(first, rest...) do { SerialPrint(first, ## rest ); } while (0) 
+#else
+#define KEYBOARD_DEBUG_PRINT(first, rest...)
+#endif
+
+
 extern struct vmm_os_hooks *os_hooks;
 
 extern void SerialPrint(const char *format, ...);
 
 
 
+// The currently targetted keyboard
+static struct vm_device *thekeyboard=NULL;
+
+
 struct keyboard_internal {
-  int x;
-  // figure this out later - it should be the internal state of the keyboard buffer and
-  // the emulated status, etc.
-  // which should be fed from the underlying OS and drained via this interface
+  // read* is what is seen when reads are done from the VM
+  uchar_t read_status;
+  uchar_t read_scancode;
+  // write* is where we put the writes from the VM
+  uchar_t write_status;
+  uchar_t write_scancode;
+
+  uchar_t status_byte;      //  for on-board uC
+
+  uchar_t input_queue;      //  input queue is for communication *to* the on-board uC
+  uint_t  input_queue_len;  //  num items queued
+  uchar_t output_queue;     //  output queue is for communcation *from* the on-board uC
+  uint_t  output_queue_len; //  num items queued 
 };
 
 
+static struct vm_device *demultiplex_injected_key(uchar_t status, uchar_t scancode)
+{
+  // this currently does nothing
+  return thekeyboard;
+}
 
+int keyboard_interrupt(uint_t irq,struct vm_device * dev);
 
-int keyboard_reset_device(struct vm_device * dev)
+void deliver_key_to_vmm(uchar_t status, uchar_t scancode)
 {
-  //  struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
+  struct vm_device *dev = demultiplex_injected_key(status,scancode);
+
+  struct keyboard_internal *state = (struct keyboard_internal *)dev->private_data;
+
+  KEYBOARD_DEBUG_PRINT("keyboard: injected status 0x%x, and scancode 0x%x\n", status,scancode);
   
-  SerialPrint("keyboard: reset device\n");
+  // This is wrong - the read status should be some combination of the 
+  // status/scancode within the VM, and that of the actual device
+  state->read_status=status;
+  state->read_scancode=scancode;
+
+  keyboard_interrupt(KEYBOARD_IRQ,dev);
+
+}
 
+int keyboard_reset_device(struct vm_device * dev)
+{
+  struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
+  
+  memset(data,0,sizeof(struct keyboard_internal));
+  
+  KEYBOARD_DEBUG_PRINT("keyboard: reset device\n");
  
   return 0;
 
 
 int keyboard_start_device(struct vm_device *dev)
 {
-  SerialPrint("keyboard: start device\n");
+  KEYBOARD_DEBUG_PRINT("keyboard: start device\n");
   return 0;
 }
 
 
 int keyboard_stop_device(struct vm_device *dev)
 {
-  SerialPrint("keyboard: stop device\n");
+  KEYBOARD_DEBUG_PRINT("keyboard: stop device\n");
   return 0;
 }
 
                                uint_t length,
                                struct vm_device * dev)
 {
-  //struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
+  struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
 
   if (length==1) { 
     uchar_t data = *((uchar_t*)src); 
-    PrintDebug("keyboard: write of 0x%x to control port\n",data);
-    Out_Byte(KEYBOARD_CONTROL_REG,data);
+    KEYBOARD_DEBUG_PRINT("keyboard: write of 0x%x to control port\n",data);
+    state->write_status=data;
     return 1;
   } else {
-    PrintDebug("keyboard: unknown size write to control port!\n");
+    KEYBOARD_DEBUG_PRINT("keyboard: unknown size write to control port!\n");
     return -1;
   }
 }
                               uint_t length,
                               struct vm_device * dev)
 {
-  //struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
+  struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
 
   if (length==1) { 
     uchar_t data;
-    PrintDebug("keyboard: read from control port: ");
-    data=In_Byte(KEYBOARD_CONTROL_REG);
-    PrintDebug("0x%x\n",data);
-    memcpy(dest,&data,1);
+    KEYBOARD_DEBUG_PRINT("keyboard: read from control port: ");
+    data=state->read_status;
+    KEYBOARD_DEBUG_PRINT("0x%x\n",data);
+    memcpy(dest,&data,length);
     return 1;
   } else {
-    PrintDebug("keyboard: unknown size read from control port!\n");
+    KEYBOARD_DEBUG_PRINT("keyboard: unknown size read from control port!\n");
     return -1;
   }
 }
                             uint_t length,
                             struct vm_device * dev)
 {
-  //struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
+  struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
 
   if (length==1) { 
     uchar_t data = *((uchar_t*)src); 
-    PrintDebug("keyboard: write of 0x%x to data port\n",data);
-    Out_Byte(KEYBOARD_DATA_REG,data);
+    KEYBOARD_DEBUG_PRINT("keyboard: write of 0x%x to data port\n",data);
+    state->write_scancode=data;
     return 1;
   } else {
-    PrintDebug("keyboard: unknown size write to data port!\n");
+    KEYBOARD_DEBUG_PRINT("keyboard: unknown size write to data port!\n");
     return -1;
   }
 }
                            uint_t length,
                            struct vm_device * dev)
 {
-  //struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
+  struct keyboard_internal *state = (struct keyboard_internal *) dev->private_data;
 
   if (length==1) { 
     uchar_t data;
-    PrintDebug("keyboard: read from data port: ");
-    data=In_Byte(KEYBOARD_DATA_REG);
-    PrintDebug("0x%x\n",data);
+    KEYBOARD_DEBUG_PRINT("keyboard: read from data port: ");
+    data=state->read_scancode;
+    KEYBOARD_DEBUG_PRINT("0x%x\n",data);
     memcpy(dest,&data,1);
     return 1;
   } else {
-    PrintDebug("keyboard: unknown size read from data port!\n");
+    KEYBOARD_DEBUG_PRINT("keyboard: unknown size read from data port!\n");
     return -1;
   }
 }
 int keyboard_interrupt(uint_t irq,
                       struct vm_device * dev) 
 {
-  PrintDebug("keyboard: interrupt\n");
+  KEYBOARD_DEBUG_PRINT("keyboard: interrupt\n");
+
+  dev->vm->vm_ops.raise_irq(dev->vm,irq,0);
+
   return 0;
-  // Inject ?
+
 }
 
 
  
   //  struct keyboard_internal *data = (struct keyboard_internal *) dev->private_data;
 
-  SerialPrint("keyboard: init_device\n");
+  KEYBOARD_DEBUG_PRINT("keyboard: init_device\n");
 
   // Would read state here
 
   dev_hook_io(dev, KEYBOARD_DATA_REG, &keyboard_read_data_port, &keyboard_write_data_port);
   dev_hook_io(dev, KEYBOARD_CONTROL_REG, &keyboard_read_control_port, &keyboard_write_control_port);
   
-  // hook irq
-  // currently assume this is done in vm.c?
-  //dev_hook_irq(dev,KEYBOARD_IRQ,&keyboard_interrupt);
-
+  //
+  // We do not hook the IRQ here.  Instead, the underlying device driver
+  // is responsible to call us back
+  // 
 
   return 0;
 }
 int keyboard_deinit_device(struct vm_device *dev)
 {
 
-
-  //dev_unhook_irq(dev,KEYBOARD_IRQ);
   dev_unhook_io(dev, KEYBOARD_DATA_REG);
   dev_unhook_io(dev, KEYBOARD_CONTROL_REG);
 
 
 
 struct vm_device *create_keyboard() {
+  
+  if (thekeyboard!=NULL) { 
+    KEYBOARD_DEBUG_PRINT("keyboard: creating >1 keyboard device.  This will probably fail!\n");
+  }
+  
   struct keyboard_internal * keyboard_state = os_hooks->malloc(sizeof(struct keyboard_internal));
 
   struct vm_device *device = create_device("KEYBOARD", &dev_ops, keyboard_state);
 
+  thekeyboard=device;
+  
   return device;
 }
 
 /*
  * Keyboard driver
  * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
 #include <geekos/io.h>
 #include <geekos/keyboard.h>
 
+
+static enum {TARGET_GEEKOS,TARGET_VMM} target=TARGET_GEEKOS;
+
+extern void deliver_key_to_vmm(uchar_t status, uchar_t scancode);
+
 /* ----------------------------------------------------------------------
  * Private data and functions
  * ---------------------------------------------------------------------- */
  */
 static void Keyboard_Interrupt_Handler(struct Interrupt_State* state)
 {
+  uchar_t raw_status, raw_scancode;
+
     uchar_t status, scanCode;
     unsigned flag = 0;
     bool release = false, shift;
     Keycode keycode;
+    bool flagchange;
 
     Begin_IRQ(state);
 
-    //    Print("Keybaord\n");
+    Print("Keyboard\n");
 
     status = In_Byte(KB_CMD);
+    
+    raw_status=status;
+
     IO_Delay();
 
     if ((status & KB_OUTPUT_FULL) != 0) {
-       /* There is a byte available */
-       scanCode = In_Byte(KB_DATA);
-       IO_Delay();
-/*
- *     Print("code=%x%s\n", scanCode, (scanCode&0x80) ? " [release]" : "");
- */
-
-       if (scanCode & KB_KEY_RELEASE) {
-           release = true;
-           scanCode &= ~(KB_KEY_RELEASE);
-       }
-
-       if (scanCode >= SCAN_TABLE_SIZE) {
-           Print("Unknown scan code: %x\n", scanCode);
+      /* There is a byte available */
+      scanCode = In_Byte(KB_DATA);
+      raw_scancode=scanCode;
+      Print("Keyboard: status=0x%x, scancode=0x%x\n", raw_status, raw_scancode);
+      IO_Delay();
+      /*
+       *       Print("code=%x%s\n", scanCode, (scanCode&0x80) ? " [release]" : "");
+       */
+       
+      if (scanCode & KB_KEY_RELEASE) {
+       release = true;
+       scanCode &= ~(KB_KEY_RELEASE);
+      }
+      
+      if (scanCode >= SCAN_TABLE_SIZE) {
+       Print("Unknown scan code: %x\n", scanCode);
+       goto done;
+      }
+      
+      /* Process the key */
+      shift = ((s_shiftState & SHIFT_MASK) != 0);
+      keycode = shift ? s_scanTableWithShift[scanCode] : s_scanTableNoShift[scanCode];
+
+      flagchange=false;
+      
+      /* Update shift, control and alt state */
+      switch (keycode) {
+      case KEY_LSHIFT:
+       flag = LEFT_SHIFT;
+       break;
+      case KEY_RSHIFT:
+       flag = RIGHT_SHIFT;
+       break;
+      case KEY_LCTRL:
+       flag = LEFT_CTRL;
+       break;
+      case KEY_RCTRL:
+       flag = RIGHT_CTRL;
+       break;
+      case KEY_LALT:
+       flag = LEFT_ALT;
+       break;
+      case KEY_RALT:
+       flag = RIGHT_ALT;
+       break;
+      default:
+       goto noflagchange;
+      }
+      
+      if (release)
+       s_shiftState &= ~(flag);
+      else
+       s_shiftState |= flag;
+      
+      /*
+       * Shift, control and alt keys don't have to be
+       * queued, flags will be set!
+       */
+      // huh?
+      flagchange=true;
+      goto skip_flagchange;
+      
+noflagchange:
+      /* Format the new keycode */
+      if (shift)
+       keycode |= KEY_SHIFT_FLAG;
+      if ((s_shiftState & CTRL_MASK) != 0)
+       keycode |= KEY_CTRL_FLAG;
+      if ((s_shiftState & ALT_MASK) != 0)
+       keycode |= KEY_ALT_FLAG;
+      if (release)
+       keycode |= KEY_RELEASE_FLAG;
+      
+      
+skip_flagchange:
+
+      if (target==TARGET_GEEKOS) { 
+       if (raw_scancode==0xc4) {  // F10 release
+         Print("Switching keyboard to VMM\n");
+         target=TARGET_VMM;
+       } else {
+         if (flagchange) {
            goto done;
+         }
+         /* Put the keycode in the buffer */
+         Enqueue_Keycode(keycode);
+         
+         /* Wake up event consumers */
+         Wake_Up(&s_waitQueue);
+         
+         /*
+          * Pick a new thread upon return from interrupt
+          * (hopefully the one waiting for the keyboard event)
+          */
+         g_needReschedule = true;
        }
-
-       /* Process the key */
-       shift = ((s_shiftState & SHIFT_MASK) != 0);
-       keycode = shift ? s_scanTableWithShift[scanCode] : s_scanTableNoShift[scanCode];
-
-       /* Update shift, control and alt state */
-       switch (keycode) {
-       case KEY_LSHIFT:
-           flag = LEFT_SHIFT;
-           break;
-       case KEY_RSHIFT:
-           flag = RIGHT_SHIFT;
-           break;
-       case KEY_LCTRL:
-           flag = LEFT_CTRL;
-           break;
-       case KEY_RCTRL:
-           flag = RIGHT_CTRL;
-           break;
-       case KEY_LALT:
-           flag = LEFT_ALT;
-           break;
-       case KEY_RALT:
-           flag = RIGHT_ALT;
-           break;
-       default:
-           goto noflagchange;
+      } else if (target==TARGET_VMM) { 
+       if (raw_scancode==0xc4) {   // F10 release
+         Print("Switching keyboard to GeekOS\n");
+         target=TARGET_GEEKOS;
+       } else {
+         deliver_key_to_vmm(raw_status,raw_scancode);
        }
-
-       if (release)
-           s_shiftState &= ~(flag);
-       else
-           s_shiftState |= flag;
-                       
-       /*
-        * Shift, control and alt keys don't have to be
-        * queued, flags will be set!
-        */
-       goto done;
-
-noflagchange:
-       /* Format the new keycode */
-       if (shift)
-           keycode |= KEY_SHIFT_FLAG;
-       if ((s_shiftState & CTRL_MASK) != 0)
-           keycode |= KEY_CTRL_FLAG;
-       if ((s_shiftState & ALT_MASK) != 0)
-           keycode |= KEY_ALT_FLAG;
-       if (release)
-           keycode |= KEY_RELEASE_FLAG;
-               
-       /* Put the keycode in the buffer */
-       Enqueue_Keycode(keycode);
-
-       /* Wake up event consumers */
-       Wake_Up(&s_waitQueue);
-
-       /*
-        * Pick a new thread upon return from interrupt
-        * (hopefully the one waiting for the keyboard event)
-        */
-       g_needReschedule = true;
+      }
     }
 
-done:
+ done:
     End_IRQ(state);
+      
 }
 
 /* ----------------------------------------------------------------------
 
 #include <geekos/vm.h>
 #include <geekos/screen.h>
 
+#include <devices/generic.h>
 #include <devices/nvram.h>
 #include <devices/timer.h>
 #include <devices/simple_pic.h>
       hook_io_port(&(vm_info.io_map), 0x403, &IO_Read, &IO_Write_to_Serial, NULL);
 
       {
+       
        struct vm_device * nvram = create_nvram();
        //struct vm_device * timer = create_timer();
        struct vm_device * pic = create_pic();
        //struct vm_device * keyboard = create_keyboard();
        struct vm_device * pit = create_pit();
 
+       //generic_port_range_type range = {0,1024} ; // hook first 1024 ports if not already hooked
+
+       //struct vm_device * generic = create_generic(&range,1,NULL,0,NULL,0);
+       
+
        attach_device(&(vm_info), nvram);
        //attach_device(&(vm_info), timer);
        attach_device(&(vm_info), pic);
        attach_device(&(vm_info), pit);
        //attach_device(&(vm_info), keyboard);
 
+       // Important that this be attached last!
+       //attach_device(&(vm_info), generic);
+
        PrintDebugDevMgr(&(vm_info.dev_mgr));
       }