Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Merge branch 'devel' into ide
Jack Lange [Tue, 31 Mar 2009 20:42:42 +0000 (15:42 -0500)]
Conflicts:
misc/test_vm/build/Makefile
palacios/build/Makefile

29 files changed:
misc/test_vm/build/Makefile
misc/test_vm/build/depend.mak
misc/test_vm/include/geekos/io.h
misc/test_vm/include/geekos/paging.h
misc/test_vm/include/geekos/screen.h
misc/test_vm/include/geekos/serial.h
misc/test_vm/src/geekos/crc32.c
misc/test_vm/src/geekos/idt.c
misc/test_vm/src/geekos/int.c
misc/test_vm/src/geekos/io.c
misc/test_vm/src/geekos/kthread.c
misc/test_vm/src/geekos/main.c
misc/test_vm/src/geekos/paging.c
misc/test_vm/src/geekos/screen.c
misc/test_vm/src/geekos/serial.c
misc/test_vm/src/geekos/timer.c
misc/test_vm/src/geekos/trap.c
misc/test_vm/src/geekos/tss.c
palacios/build/Makefile
palacios/include/devices/ide.h
palacios/include/devices/pci.h
palacios/src/devices/apic.c
palacios/src/devices/atapi-types.h [new file with mode: 0644]
palacios/src/devices/atapi.h [new file with mode: 0644]
palacios/src/devices/ide-types.h [new file with mode: 0644]
palacios/src/devices/ide.c [new file with mode: 0644]
palacios/src/devices/pci.c
palacios/src/devices/ramdisk.c
palacios/src/palacios/vmm_config.c

index 62c901d..c38b9f4 100644 (file)
@@ -38,11 +38,14 @@ KERNEL_ENTRY = $(SYM_PFX)Main
 PROJECT_ROOT := ..
 VPATH := $(PROJECT_ROOT)/src
 
-ifeq ($(DEBUG_SERIAL),1)
-JRL_DEBUG := -DDEBUG_SERIAL
-endif
 
 
+ifeq ($(SERIAL_DEBUG), 1)
+JRLDEBUG= -DDEBUG_SERIAL
+else 
+JRLDEBUG= 
+endif
+
 
 # Figure out if we're compiling with cygwin, http://cygwin.com
 SYSTEM_NAME := $(shell uname -s)
@@ -78,6 +81,8 @@ KERNEL_C_SRCS := idt.c int.c trap.c irq.c io.c \
        gdt.c tss.c segment.c \
        bget.c malloc.c \
        synch.c kthread.c \
+       vm_cons.c debug.c \
+       pci.c \
        serial.c  reboot.c \
         paging.c \
        main.c
@@ -174,7 +179,8 @@ NUMSECS := $(PERL) $(PROJECT_ROOT)/scripts/numsecs
 # ----------------------------------------------------------------------
 
 # Flags used for all C source files
-GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(JRL_DEBUG)
+
+GENERAL_OPTS := -O -Wall $(EXTRA_C_OPTS) $(JRLDEBUG)
 CC_GENERAL_OPTS := $(GENERAL_OPTS) -Werror 
 
 # Flags used for kernel C source files
@@ -235,7 +241,6 @@ guest-img: fd.img
        $(PAD) guest.img 1474560
 
 guest-iso: guest-img
-
        mkisofs -pad -b guest.img -R -o guest.iso guest.img
 
 
index e69de29..052def9 100644 (file)
@@ -0,0 +1,268 @@
+geekos/idt.o: ../src/geekos/idt.c ../include/geekos/kassert.h \
+  ../include/geekos/screen.h ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/debug.h \
+  ../include/geekos/string.h ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
+  ../include/geekos/defs.h ../include/geekos/irq.h \
+  ../include/geekos/debug.h ../include/geekos/string.h \
+  ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/debug.h ../include/geekos/string.h \
+  ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
+geekos/irq.o: ../src/geekos/irq.c ../include/geekos/kassert.h \
+  ../include/geekos/screen.h ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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
+geekos/io.o: ../src/geekos/io.c ../include/geekos/io.h \
+  ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
+  ../include/geekos/string.h ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/palacios/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/palacios/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/palacios/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/palacios/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/palacios/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
+geekos/timer.o: ../src/geekos/timer.c \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/limits.h \
+  ../include/geekos/io.h ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/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/palacios/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/debug.h \
+  ../include/geekos/string.h ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
+geekos/mem.o: ../src/geekos/mem.c ../include/geekos/defs.h \
+  ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/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/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/geekos/paging.h ../include/geekos/list.h \
+  ../include/geekos/mem.h
+geekos/crc32.o: ../src/geekos/crc32.c ../include/geekos/crc32.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/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/palacios/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
+geekos/gdt.o: ../src/geekos/gdt.c ../include/geekos/kassert.h \
+  ../include/geekos/screen.h ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
+geekos/tss.o: ../src/geekos/tss.c ../include/geekos/kassert.h \
+  ../include/geekos/screen.h ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/palacios/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
+geekos/segment.o: ../src/geekos/segment.c ../include/geekos/kassert.h \
+  ../include/geekos/screen.h ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
+  ../include/geekos/string.h ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/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/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/palacios/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/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/palacios/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
+geekos/vm_cons.o: ../src/geekos/vm_cons.c ../include/geekos/fmtout.h \
+  ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
+  ../include/geekos/string.h ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/geekos/idt.h ../include/geekos/int.h \
+  ../include/geekos/kassert.h ../include/geekos/screen.h \
+  ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/defs.h ../include/geekos/vm_cons.h \
+  ../include/geekos/io.h
+geekos/debug.o: ../src/geekos/debug.c ../include/geekos/string.h \
+  ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/geekos/debug.h ../include/geekos/fmtout.h \
+  ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
+  ../include/geekos/vm_cons.h ../include/geekos/io.h \
+  ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/screen.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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/palacios/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/palacios/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/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/debug.h
+geekos/main.o: ../src/geekos/main.c ../include/geekos/bootinfo.h \
+  ../include/geekos/string.h ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/geekos/screen.h ../include/geekos/ktypes.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdbool.h \
+  ../include/geekos/fmtout.h ../include/geekos/../libc/fmtout.h \
+  /home/jarusl/palacios/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/vm_cons.h \
+  ../include/geekos/debug.h ../include/geekos/gdt.h
+common/fmtout.o: ../src/common/fmtout.c \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
+  /home/jarusl/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h \
+  ../include/geekos/string.h ../include/geekos/../libc/string.h \
+  /home/jarusl/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stdarg.h \
+  ../include/libc/string.h \
+  /home/jarusl/palacios/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/palacios/devtools/i386/lib/gcc/i386-elf/3.4.6/include/stddef.h
index bd23614..230300b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * x86 port IO routines
  * Copyright (c) 2001, David H. Hovemeyer <daveho@cs.umd.edu>
- * $Revision: 1.1 $
+ * $Revision: 1.2 $
  * 
  * This is free software.  You are permitted to use,
  * redistribute, and modify it as specified in the file "COPYING".
@@ -18,6 +18,9 @@ uchar_t In_Byte(ushort_t port);
 void Out_Word(ushort_t port, ushort_t value);
 ushort_t In_Word(ushort_t port);
 
+void Out_DWord(ushort_t port, uint_t value);
+uint_t In_DWord(ushort_t port);
+
 void IO_Delay(void);
 
 #endif  /* GEEKOS_IO_H */
index 11b7531..72e9c73 100644 (file)
@@ -112,11 +112,11 @@ static __inline__ ulong_t Get_Page_Fault_Address(void)
     return faultAddress;
 }
 
-void SerialPrintPD(pde_t *pde);
-void SerialPrintPT(void *starting_address, pte_t *pte);
-void SerialPrintPDE(void *virtual_address, pde_t *pde);
-void SerialPrintPTE(void *virtual_address,pte_t *pte);
-void SerialDumpPageTables(pde_t *pde);
+void PrintPD(pde_t *pde);
+void PrintPT(void *starting_address, pte_t *pte);
+void PrintPDE(void *virtual_address, pde_t *pde);
+void PrintPTE(void *virtual_address,pte_t *pte);
+void DumpPageTables(pde_t *pde);
 
 pte_t *LookupPage(void *vaddr);
 
index 241fc6f..8bd39a5 100644 (file)
@@ -11,6 +11,7 @@
 #define GEEKOS_SCREEN_H
 
 #include <geekos/ktypes.h>
+#include <geekos/fmtout.h>
 
 #define BLACK   0
 #define BLUE    1
@@ -51,7 +52,7 @@ void Put_Char(int c);
 void Put_String(const char* s);
 void Put_Buf(const char* buf, ulong_t length);
 void Print(const char* fmt, ...) __attribute__ ((format (printf, 1, 2)));
-
+void PrintList(const char * fmt, va_list ap);
 #endif  /* GEEKOS */
 
 #endif  /* GEEKOS_SCREEN_H */
index 4ebe0b0..9b7b133 100644 (file)
 #define DEFAULT_SERIAL_ADDR 0x3F8
 
 
-#ifndef SERIAL_PRINT
-#define SERIAL_PRINT              1
-#endif
-#ifndef SERIAL_PRINT_DEBUG
-#define SERIAL_PRINT_DEBUG        1 
-#endif
-#ifndef SERIAL_PRINT_DEBUG_LEVEL
-#define SERIAL_PRINT_DEBUG_LEVEL  10
-#endif
-
-#define SERIAL_PRINT_MAXBUF       256
-
-#if SERIAL_PRINT                                                
-#define SerialPrint(format, args...)                             \
-do {                                                             \
-  char buf[SERIAL_PRINT_MAXBUF];                                                 \
-  snprintf( buf, SERIAL_PRINT_MAXBUF, format, ## args ) ;                       \
-  SerialPutLineN(buf, SERIAL_PRINT_MAXBUF);                                     \
-} while (0)  
-#else
-#define SerialPrint(format, args...) do {} while (0)
-#endif
-
-
-#define PrintBoth(format, args...) \
-do {  \
-  Print(format, ## args); \
-  SerialPrint(format, ##args); \
- } while (0)
-
-
-#if SERIAL_PRINT_DEBUG
-#define SerialPrintLevel(level, format, args...)                \
-do {                                                             \
-  char buf[SERIAL_PRINT_MAXBUF];                                                 \
-  if (level >= SERIAL_PRINT_DEBUG_LEVEL  ) {                                     \
-    snprintf( buf, SERIAL_PRINT_MAXBUF, format, ## args ) ;            \
-    SerialPutLineN(buf, SERIAL_PRINT_MAXBUF);                          \
-  }                                                                     \
-} while (0)  
-#else
-#define SerialPrintLevel(level, format, args...) do {} while (0)
-#endif
 
+void SerialPrint(const char * format, ...);
+void SerialPrintList(const char * format, va_list ap);
 
 void SerialPutLine(char * line); 
 void SerialPutLineN(char * line, int len);
index 0165c3b..2107e07 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <geekos/crc32.h>
 #include <geekos/kassert.h>
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 #define POLYNOMIAL (ulong_t)0xedb88320
 static ulong_t crc_table[256];
index 5e23989..1000996 100644 (file)
@@ -10,7 +10,7 @@
 #include <geekos/kassert.h>
 #include <geekos/defs.h>
 #include <geekos/idt.h>
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 /* ----------------------------------------------------------------------
  * Private data and functions
@@ -42,37 +42,17 @@ Interrupt_Handler g_interruptTable[ NUM_IDT_ENTRIES ];
 
 
 
-void DumpIDT()
-{
-  int i;
-  Print("IDT Contents:\n");
 
-  for (i=0;i<NUM_IDT_ENTRIES/16;i++) { 
-    if (s_IDT[i].ig.present) { 
-      Print("%d: segmentselector=%u, offset=%u, offsetLow=%u, segmentSelector=%u, reserved=%u, signature=%u, dpl=%u, present=%u, offsetHigh=%u\n",
-           i,
-           s_IDT[i].ig.segmentSelector,
-           (s_IDT[i].ig.offsetHigh<<16) + s_IDT[i].ig.offsetLow,
-           s_IDT[i].ig.offsetLow,
-           s_IDT[i].ig.segmentSelector,
-           s_IDT[i].ig.reserved,
-           s_IDT[i].ig.signature,
-           s_IDT[i].ig.dpl,
-           s_IDT[i].ig.present,
-           s_IDT[i].ig.offsetHigh);
-    }
-  }
-}
 
 
-void SerialDumpIDT()
+void DumpIDT()
 {
   int i;
-  SerialPrint("IDT Contents:\n");
+  PrintBoth("IDT Contents:\n");
 
   for (i=0;i<NUM_IDT_ENTRIES;i++) { 
     if (s_IDT[i].ig.present) { 
-      SerialPrint("%d: segmentselector=%u, offset=%u, offsetLow=%u, segmentSelector=%u, reserved=%u, signature=%u, dpl=%u, present=%u, offsetHigh=%u\n",
+      PrintBoth("%d: segmentselector=%u, offset=%u, offsetLow=%u, segmentSelector=%u, reserved=%u, signature=%u, dpl=%u, present=%u, offsetHigh=%u\n",
            i,
            s_IDT[i].ig.segmentSelector,
            (s_IDT[i].ig.offsetHigh<<16) + s_IDT[i].ig.offsetLow,
@@ -83,7 +63,7 @@ void SerialDumpIDT()
            s_IDT[i].ig.dpl,
            s_IDT[i].ig.present,
            s_IDT[i].ig.offsetHigh);
-      SerialPrint("\n");
+      PrintBoth("\n");
     }
   }
 }
index 2c59a5f..4d32039 100644 (file)
@@ -11,7 +11,8 @@
 #include <geekos/screen.h>
 #include <geekos/kassert.h>
 #include <geekos/int.h>
-#include <geekos/serial.h>
+#include <geekos/irq.h>
+#include <geekos/debug.h>
 
 #include <geekos/cpu.h>
 
@@ -33,8 +34,7 @@ static void Dummy_Interrupt_Handler(struct Interrupt_State* state)
 {
   Begin_IRQ(state);
 
-  Print("Unexpected Interrupt!  Ignoring!\n");
-  SerialPrint("*** Unexpected interrupt! *** Ignoring!\n");
+  PrintBoth("*** Unexpected interrupt! *** Ignoring!\n");
   Dump_Interrupt_State(state);
 
   End_IRQ(state);
@@ -42,19 +42,14 @@ static void Dummy_Interrupt_Handler(struct Interrupt_State* state)
   //  STOP();
 }
 
-#if 0
+
 static void Print_Selector(const char* regName, uint_t value)
 {
-    Print("%s: index=%d, ti=%d, rpl=%d\n",
+    PrintBoth("%s: index=%d, ti=%d, rpl=%d\n",
        regName, value >> 3, (value >> 2) & 1, value & 3);
 }
-#endif
 
-static void SerialPrint_Selector(const char* regName, uint_t value)
-{
-    SerialPrint("%s: index=%d, ti=%d, rpl=%d\n",
-       regName, value >> 3, (value >> 2) & 1, value & 3);
-}
+
 
 /* ----------------------------------------------------------------------
  * Public functions
@@ -100,7 +95,7 @@ void Dump_Interrupt_State(struct Interrupt_State* state)
 {
     uint_t errorCode = state->errorCode;
 
-   SerialPrint("eax=%08x ebx=%08x ecx=%08x edx=%08x\n"
+   PrintBoth("eax=%08x ebx=%08x ecx=%08x edx=%08x\n"
           "esi=%08x edi=%08x ebp=%08x\n"
           "eip=%08x cs=%08x eflags=%08x\n"
           "Interrupt number=%d, error code=%d\n"
@@ -113,11 +108,11 @@ void Dump_Interrupt_State(struct Interrupt_State* state)
     );
     if (Is_User_Interrupt(state)) {
        struct User_Interrupt_State *ustate = (struct User_Interrupt_State*) state;
-       SerialPrint("user esp=%08x, user ss=%08x\n", ustate->espUser, ustate->ssUser);
+       PrintBoth("user esp=%08x, user ss=%08x\n", ustate->espUser, ustate->ssUser);
     }
-    SerialPrint_Selector("cs", state->cs);
-    SerialPrint_Selector("ds", state->ds);
-    SerialPrint_Selector("es", state->es);
-    SerialPrint_Selector("fs", state->fs);
-    SerialPrint_Selector("gs", state->gs);
+    Print_Selector("cs", state->cs);
+    Print_Selector("ds", state->ds);
+    Print_Selector("es", state->es);
+    Print_Selector("fs", state->fs);
+    Print_Selector("gs", state->gs);
 }
index 70b9f50..1310cdc 100644 (file)
@@ -21,14 +21,11 @@ void Out_Byte(ushort_t port, uchar_t value)
     );
 }
 
-extern uchar_t InByteLL(ushort_t port);
-
 /*
  * Read a byte from an I/O port.
  */
 uchar_t In_Byte(ushort_t port)
 {
-  /*
     uchar_t value;
 
     __asm__ __volatile__ (
@@ -38,9 +35,6 @@ uchar_t In_Byte(ushort_t port)
     );
 
     return value;
-  */
-
-  return InByteLL(port);
 }
 
 /*
@@ -56,7 +50,7 @@ void Out_Word(ushort_t port, ushort_t value)
 }
 
 /*
- * Read a byte from an I/O port.
+ * Read a word from an I/O port.
  */
 ushort_t In_Word(ushort_t port)
 {
@@ -72,6 +66,34 @@ ushort_t In_Word(ushort_t port)
 }
 
 /*
+ * Write a double word to an I/O port.
+ */
+void Out_DWord(ushort_t port, uint_t value)
+{
+    __asm__ __volatile__ (
+       "outl %0, %1"
+       :
+       : "a" (value), "Nd" (port)
+    );
+}
+
+/*
+ * Read a double word from an I/O port.
+ */
+uint_t In_DWord(ushort_t port)
+{
+    uint_t value;
+
+    __asm__ __volatile__ (
+       "inl %1, %0"
+       : "=a" (value)
+       : "Nd" (port)
+    );
+
+    return value;
+}
+
+/*
  * Short delay.  May be needed when talking to some
  * (slow) I/O devices.
  */
index e2a6df2..7ccec20 100644 (file)
@@ -16,7 +16,7 @@
 #include <geekos/string.h>
 #include <geekos/kthread.h>
 #include <geekos/malloc.h>
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 /* ----------------------------------------------------------------------
  * Private data
index 9d48319..177771a 100644 (file)
@@ -9,6 +9,7 @@
  * redistribute, and modify it as specified in the file "COPYING".
  */
 
+#include <geekos/debug.h>
 #include <geekos/bootinfo.h>
 #include <geekos/string.h>
 #include <geekos/screen.h>
 #include <geekos/mem.h>
 #include <geekos/paging.h>
 #include <geekos/ide.h>
-
+#include <geekos/vm_cons.h>
+#include <geekos/pci.h>
 #include <geekos/gdt.h>
 
 
+
+#define TEST_PAGING 0
+#define TEST_PCI 1
+
 /*
   static inline unsigned int cpuid_ecx(unsigned int op)
   {
@@ -186,12 +192,10 @@ void Keyboard_Listener(ulong_t arg) {
 
   while ((key_press = Wait_For_Key())) {    
     if (key_press == KEY_F4) {
-      Print("\nToggling Speaker Port\n");
-      SerialPrintLevel(100,"\nToggling Speaker Port\n");
+      PrintBoth("\nToggling Speaker Port\n");
       *doIBuzz = (*doIBuzz + 1) % 2;
     } else if (key_press == KEY_F5) {
-      Print("\nMachine Restart\n");
-      SerialPrintLevel(100,"\nMachine Restart\n");
+      PrintBoth("\nMachine Restart\n");
       machine_real_restart();
     }
   }
@@ -245,6 +249,8 @@ void Main(struct Boot_Info* bootInfo)
   Init_BSS();
   Init_Screen();
   InitSerial();
+
+  Init_VMCons();
   Init_Mem(bootInfo);
   Init_CRC32();
   Init_TSS();
@@ -265,17 +271,17 @@ void Main(struct Boot_Info* bootInfo)
 
 
 
-  SerialPrint("\n\nHello, Welcome to this horrid output-only serial interface\n");
-  SerialPrint("Eventually, this will let us control the VMM\n\n");
+  PrintBoth("\n\nHello, Welcome to this horrid output-only serial interface\n");
+  PrintBoth("Eventually, this will let us control the VMM\n\n");
  
-  SerialPrint("\n\n===>");
+  PrintBoth("\n\n===>");
   
 
 
   
 
   
-  SerialPrintLevel(1000,"Launching Noisemaker and keyboard listener threads\n");
+  PrintBoth("Launching Noisemaker and keyboard listener threads\n");
   
   key_thread = Start_Kernel_Thread(Keyboard_Listener, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
   spkr_thread = Start_Kernel_Thread(Buzzer, (ulong_t)&doIBuzz, PRIORITY_NORMAL, false);
@@ -284,22 +290,31 @@ void Main(struct Boot_Info* bootInfo)
 
 
 
-  SerialPrintLevel(1000,"Next: setup GDT\n");
+  PrintBoth("Next: setup GDT\n");
 
-  {
-    int i = 0;
-    for (i = 0; i < 1024; i++) {
-      uint_t * addr = (uint_t *)0xa00000;
-      uint_t foo = *addr;
 
-      SerialPrint("Read From 0x%x=%d\n", (uint_t)addr, foo);
-    }
+  if (TEST_PAGING) {
+      int i = 0;
+      for (i = 0; i < 1024; i++) {
+         uint_t * addr = (uint_t *)0xa00000;
+         uint_t foo = *addr;
+         
+         PrintBoth("Read From 0x%x=%d\n", (uint_t)addr, foo);
+      }
 
+      
+      //  Invalidate_PG((void *)0x2000);
+      
+      //  VM_Test(bootInfo, 32);  
+      //VM_Test(bootInfo, 1536);
   }
-  //  Invalidate_PG((void *)0x2000);
 
-  //  VM_Test(bootInfo, 32);  
-  //VM_Test(bootInfo, 1536);
+
+  if (TEST_PCI) {
+      Init_PCI();
+
+
+  }
 
   while(1);
   
index d82f785..1a9778e 100644 (file)
@@ -22,7 +22,7 @@
 //#include <geekos/vfs.h>
 #include <geekos/crc32.h>
 #include <geekos/paging.h>
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 
 /* ----------------------------------------------------------------------
  * flag to indicate if debugging paging code
  */
 int debugFaults = 0;
-#define Debug(args...) if (debugFaults) Print(args)
+#define Debug(args...) if (debugFaults) PrintBoth(args)
 
 
 
-void SerialPrintPD(pde_t *pde)
+void PrintPD(pde_t *pde)
 {
   uint_t i;
 
-  SerialPrint("Page Directory at %p:\n",pde);
+  PrintBoth("Page Directory at %p:\n",pde);
   for (i = 0; i < NUM_PAGE_DIR_ENTRIES; i++) { 
     if (pde[i].present) {
       if ((i * PAGE_SIZE * 1024) > 0x40000000) {
-       SerialPrintPDE((void*)(PAGE_SIZE*NUM_PAGE_TABLE_ENTRIES*i),&(pde[i]));
+       PrintPDE((void*)(PAGE_SIZE*NUM_PAGE_TABLE_ENTRIES*i),&(pde[i]));
       }
     }
   }
 }
 
-void SerialPrintPT(void *starting_address, pte_t *pte) 
+void PrintPT(void *starting_address, pte_t *pte) 
 {
   int i;
 
-  SerialPrint("Page Table at %p:\n",pte);
+  PrintBoth("Page Table at %p:\n",pte);
   for (i=0;i<NUM_PAGE_TABLE_ENTRIES;i++) { 
     if (pte[i].present) {
-      SerialPrintPTE(starting_address + PAGE_SIZE*i,&(pte[i]));
+      PrintPTE(starting_address + PAGE_SIZE*i,&(pte[i]));
     }
   }
 }
 
 
-void SerialPrintPDE(void *virtual_address, pde_t *pde)
+void PrintPDE(void *virtual_address, pde_t *pde)
 {
-  SerialPrint("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
+  Print("PDE %p -> %p : present=%x, flags=%x, accessed=%x, reserved=%x, largePages=%x, globalPage=%x, kernelInfo=%x\n",
              virtual_address,
              (void*) (pde->pageTableBaseAddr << PAGE_POWER),
              pde->present,
@@ -84,9 +84,9 @@ void SerialPrintPDE(void *virtual_address, pde_t *pde)
              pde->kernelInfo);
 }
   
-void SerialPrintPTE(void *virtual_address, pte_t *pte)
+void PrintPTE(void *virtual_address, pte_t *pte)
 {
-  SerialPrint("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, kernelInfo=%x\n",
+  PrintBoth("PTE %p -> %p : present=%x, flags=%x, accessed=%x, dirty=%x, pteAttribute=%x, globalPage=%x, kernelInfo=%x\n",
              virtual_address,
              (void*)(pte->pageBaseAddr << PAGE_POWER),
              pte->present,
@@ -99,17 +99,17 @@ void SerialPrintPTE(void *virtual_address, pte_t *pte)
 }
 
 
-void SerialDumpPageTables(pde_t *pde)
+void DumpPageTables(pde_t *pde)
 {
   uint_t i;
   
-  SerialPrint("Dumping the pages starting with the pde page at %p\n",pde);
+  PrintBoth("Dumping the pages starting with the pde page at %p\n",pde);
 
   for (i = 0; i < NUM_PAGE_DIR_ENTRIES; i++) { 
     if (pde[i].present) {
       if ((i * PAGE_SIZE * 1024) >= 0x40000000) {
-       SerialPrintPDE((void *)(PAGE_SIZE * NUM_PAGE_TABLE_ENTRIES * i), &(pde[i]));
-       SerialPrintPT((void *)(PAGE_SIZE * NUM_PAGE_TABLE_ENTRIES * i), (void *)(pde[i].pageTableBaseAddr << PAGE_POWER));
+       PrintPDE((void *)(PAGE_SIZE * NUM_PAGE_TABLE_ENTRIES * i), &(pde[i]));
+       PrintPT((void *)(PAGE_SIZE * NUM_PAGE_TABLE_ENTRIES * i), (void *)(pde[i].pageTableBaseAddr << PAGE_POWER));
       }
     }
   }
@@ -137,20 +137,20 @@ static void Print_Fault_Info(uint_t address, faultcode_t faultCode)
 
     g_freePageCount+=0;
 
-    SerialPrintLevel(100,"Pid %d, Page Fault received, at address %x (%d pages free)\n",
+    PrintBoth("Pid %d, Page Fault received, at address %x (%d pages free)\n",
         g_currentThread->pid, address, g_freePageCount);
     if (faultCode.protectionViolation)
-        SerialPrintLevel(100,"   Protection Violation, ");
+       PrintBoth("   Protection Violation, ");
     else
-        SerialPrintLevel(100,"   Non-present page, ");
+        PrintBoth("   Non-present page, ");
     if (faultCode.writeFault)
-        SerialPrintLevel(100,"Write Fault, ");
+       PrintBoth("Write Fault, ");
     else
-        SerialPrintLevel(100,"Read Fault, ");
+        PrintBoth("Read Fault, ");
     if (faultCode.userModeFault)
-        SerialPrintLevel(100,"in User Mode\n");
+        PrintBoth("in User Mode\n");
     else
-        SerialPrintLevel(100,"in Supervisor Mode\n");
+        PrintBoth("in Supervisor Mode\n");
 }
 
 /*
@@ -167,13 +167,13 @@ static void Print_Fault_Info(uint_t address, faultcode_t faultCode)
 
     /* Get the address that caused the page fault */
     address = Get_Page_Fault_Address();
-    Debug("Page fault @%lx\n", address);
+    PrintBoth("Page fault @%lx\n", address);
 
     /* Get the fault code */
     faultCode = *((faultcode_t *) &(state->errorCode));
 
     /* rest of your handling code here */
-    SerialPrintLevel(100,"Unexpected Page Fault received\n");
+    PrintBoth("Unexpected Page Fault received\n");
     Print_Fault_Info(address, faultCode);
     Dump_Interrupt_State(state);
     /* user faults just kill the process */
@@ -205,24 +205,24 @@ void Init_VM(struct Boot_Info *bootInfo)
   PrintBoth("Intitialing Virtual Memory\n");
 
   if (checkPaging()) { 
-    SerialPrintLevel(100,"Paging is currently ON\n");
+      PrintBoth("Paging is currently ON\n");
     return ;
   }
 
-  SerialPrintLevel(100,"Paging is currently OFF - initializing the pages for a 1-1 map\n");
+  PrintBoth("Paging is currently OFF - initializing the pages for a 1-1 map\n");
   
   numpages=bootInfo->memSizeKB / (PAGE_SIZE/1024);
   numpagetables = numpages / NUM_PAGE_TABLE_ENTRIES + ((numpages % NUM_PAGE_TABLE_ENTRIES) != 0 );
 
-  SerialPrintLevel(100,"We need %d pages, and thus %d page tables, and one page directory\n",numpages, numpagetables);
+  PrintBoth("We need %d pages, and thus %d page tables, and one page directory\n",numpages, numpagetables);
   
   pd = (pde_t*)Alloc_Page();
   
   if (!pd) { 
-    SerialPrintLevel(100,"We are giving up since we can't allocate a page directory!\n");
+      PrintBoth("We are giving up since we can't allocate a page directory!\n");
     return;
   } else {
-    SerialPrintLevel(100,"Our PDE is at physical address %p\n",pd);
+      PrintBoth("Our PDE is at physical address %p\n",pd);
   }
   
   for (i=0;i<NUM_PAGE_DIR_ENTRIES;i++) { 
@@ -238,9 +238,9 @@ void Init_VM(struct Boot_Info *bootInfo)
     } else {
       pt = (pte_t*)Alloc_Page();
       if (!pt) { 
-       SerialPrintLevel(100,"We are giving up since we can't allocate page table %d\n",i);
+         PrintBoth("We are giving up since we can't allocate page table %d\n",i);
       } else {
-       //SerialPrintLevel(100,"Page Table %d is at physical address %p\n",i,pt);
+       //PrintBoth("Page Table %d is at physical address %p\n",i,pt);
       }
       pd[i].present=1;
       pd[i].flags= VM_READ | VM_WRITE | VM_EXEC | VM_USER;
@@ -276,14 +276,14 @@ void Init_VM(struct Boot_Info *bootInfo)
   }
 
 
-  SerialPrintLevel(100,"Done creating 1<->1 initial page tables\n");
-  SerialPrintLevel(100,"Now installing page fault handler\n");
+  PrintBoth("Done creating 1<->1 initial page tables\n");
+  PrintBoth("Now installing page fault handler\n");
   //  SerialDumpPageTables(pd);
   Install_Interrupt_Handler(14,Page_Fault_Handler);
-  SerialPrintLevel(100,"Now turning on the paging bit!\n");
+  PrintBoth("Now turning on the paging bit!\n");
   Enable_Paging(pd);
-  SerialPrintLevel(100,"We are still alive after paging turned on!\n");
-  SerialPrintLevel(100,"checkPaging returns %d\n",checkPaging());
+  PrintBoth("We are still alive after paging turned on!\n");
+  PrintBoth("checkPaging returns %d\n",checkPaging());
 }
 
 
@@ -361,7 +361,7 @@ void VM_Test(struct Boot_Info *bootInfo, uint_t num_test_pages) {
   PrintBoth("Loading CR3\n");
   Set_PDBR(pd);
 
-  SerialDumpPageTables(pd);
+  DumpPageTables(pd);
 
   PrintBoth("Writing to Test Area\n");
 
@@ -369,7 +369,7 @@ void VM_Test(struct Boot_Info *bootInfo, uint_t num_test_pages) {
   uint_t * test_ptr = (uint_t *)two_gig;
   for (i = 0; i < num_test_pages; i++) {
 
-    SerialPrint("Writing %d to %p\n", i, test_ptr);
+    PrintBoth("Writing %d to %p\n", i, test_ptr);
     *test_ptr = (uint_t)i;
     test_ptr += PAGE_SIZE / 4;
   }
@@ -395,7 +395,7 @@ void VM_Test(struct Boot_Info *bootInfo, uint_t num_test_pages) {
   Set_PDBR(pd);
   
   PrintBoth("Page Mapping Reversed\n");
-  SerialDumpPageTables(pd);
+  DumpPageTables(pd);
 
 
   PrintBoth("Page Consistency Check\n");
index 9c78dde..077112f 100644 (file)
@@ -518,6 +518,12 @@ static struct Output_Sink s_outputSink = { &Print_Emit, &Print_Finish };
  * Print to console using printf()-style formatting.
  * Calls into Format_Output in common library.
  */
+
+static __inline__ void PrintInternal(const char * format, va_list ap) {
+    Format_Output(&s_outputSink, format, ap);
+}
+
+
 void Print(const char *fmt, ...)
 {
     va_list args;
@@ -525,9 +531,14 @@ void Print(const char *fmt, ...)
     bool iflag = Begin_Int_Atomic();
 
     va_start(args, fmt);
-    Format_Output(&s_outputSink, fmt, args);
+    PrintInternal(fmt, args);
     va_end(args);
 
     End_Int_Atomic(iflag);
 }
 
+void PrintList(const char * fmt, va_list ap) {
+    bool iflag = Begin_Int_Atomic();
+    PrintInternal(fmt, ap);
+    End_Int_Atomic(iflag);
+}
index 68ef275..0729501 100644 (file)
@@ -38,12 +38,6 @@ static void Serial_Interrupt_Handler(struct Interrupt_State * state) {
   End_IRQ(state);
 }
 
-void InitSerial() {
-  Print("Initialzing Serial\n");
-  Install_IRQ(COM1_IRQ, Serial_Interrupt_Handler);
-  Enable_IRQ(COM1_IRQ);
-  InitSerialAddr(DEFAULT_SERIAL_ADDR);
-}
 
 void InitSerialAddr(unsigned short io_addr) {
   serial_io_addr = io_addr;
@@ -138,3 +132,47 @@ void SerialMemDump(unsigned char *start, int n)
     SerialPrint("\n");
   }
 }
+
+
+static struct Output_Sink serial_output_sink;
+static void Serial_Emit(struct Output_Sink * o, int ch) { 
+  SerialPutChar((unsigned char)ch); 
+}
+static void Serial_Finish(struct Output_Sink * o) { return; }
+
+
+static void __inline__ SerialPrintInternal(const char * format, va_list ap) {
+  Format_Output(&serial_output_sink, format, ap);
+}
+
+
+void SerialPrint(const char * format, ...) {
+  va_list args;
+  bool iflag = Begin_Int_Atomic();
+
+  va_start(args, format);
+  SerialPrintInternal(format, args);
+  va_end(args);
+
+  End_Int_Atomic(iflag);
+}
+
+void SerialPrintList(const char * format, va_list ap) {
+  bool iflag = Begin_Int_Atomic();
+  SerialPrintInternal(format, ap);
+  End_Int_Atomic(iflag);
+
+}
+
+
+
+void InitSerial() {
+  Print("Initialzing Serial\n");
+
+  serial_output_sink.Emit = &Serial_Emit;
+  serial_output_sink.Finish = &Serial_Finish;
+
+  Install_IRQ(COM1_IRQ, Serial_Interrupt_Handler);
+  Enable_IRQ(COM1_IRQ);
+  InitSerialAddr(DEFAULT_SERIAL_ADDR);
+}
index b3120d3..2ac3a51 100644 (file)
@@ -15,7 +15,7 @@
 #include <geekos/kthread.h>
 #include <geekos/timer.h>
 
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 #define HZ 100
 
@@ -69,7 +69,7 @@ static void Timer_Interrupt_Handler(struct Interrupt_State* state)
 
     Begin_IRQ(state);
 
-    SerialPrintLevel(10,"Host Timer Interrupt Handler Running\n");
+    PrintBoth("Host Timer Interrupt Handler Running\n");
 
     /* Update global and per-thread number of ticks */
     ++g_numTicks;
index 2085a99..7932c9a 100644 (file)
@@ -11,7 +11,7 @@
 #include <geekos/kthread.h>
 #include <geekos/defs.h>
 #include <geekos/trap.h>
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 /*
  * TODO: need to add handlers for other exceptions (such as bounds
@@ -25,7 +25,7 @@
 static void GPF_Handler(struct Interrupt_State* state)
 {
     /* Send the thread to the reaper... */
-  SerialPrintLevel(1000,"Exception %d received, killing thread %p\n",state->intNum, g_currentThread);
+    PrintBoth("Exception %d received, killing thread %p\n",state->intNum, g_currentThread);
   Dump_Interrupt_State(state);
   
   Exit(-1);
index b97a844..2cdb968 100644 (file)
@@ -19,7 +19,7 @@
 #include <geekos/string.h>
 #include <geekos/tss.h>
 
-#include <geekos/serial.h>
+#include <geekos/debug.h>
 
 /*
  * We use one TSS in GeekOS.
index 9479e2b..f243949 100644 (file)
@@ -62,7 +62,8 @@ endif
 
 
 ifeq ($(DEBUG_ALL),1)
-  DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_NESTED_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM -DDEBUG_EMULATOR  -DDEBUG_XED -DDEBUG_HALT -DDEBUG_DEV_MGR -DDEBUG_IO -DDEBUG_GENERIC -DDEBUG_RAMDISK
+  DEBUG_SECTIONS:= $(DEBUG_SECTIONS) -DDEBUG_SHADOW_PAGING -DDEBUG_NESTED_PAGING -DDEBUG_CTRL_REGS -DDEBUG_INTERRUPTS -DDEBUG_KEYBOARD -DDEBUG_PIC -DDEBUG_PIT -DDEBUG_NVRAM -DDEBUG_EMULATOR  -DDEBUG_XED -DDEBUG_HALT -DDEBUG_DEV_MGR
+# -DDEBUG_IO -DDEBUG_GENERIC -DDEBUG_IDE
 endif
 
 
@@ -154,19 +155,11 @@ DEBUG_SECTIONS := $(DEBUG_SECTIONS) -UDEBUG_EMULATOR
 endif
 endif
 
-ifeq ($(DEBUG_RAMDISK),1)
-DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_RAMDISK
+ifeq ($(DEBUG_IDE),1)
+DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DDEBUG_IDE
 else 
-ifeq ($(DEBUG_RAMDISK),0) 
-DEBUG_SECTIONS := $(DEBUG_SECTIONS) -UDEBUG_RAMDISK
-endif
-endif
-
-ifeq ($(TRACE_RAMDISK),1)
-DEBUG_SECTIONS := $(DEBUG_SECTIONS) -DTRACE_RAMDISK
-else
-ifeq ($(TRACE_RAMDSK),0)
-DEBUG_SECTIONS := $(DEBUG_SECTIONS) -UTRACE_RAMDISK
+ifeq ($(DEBUG_IDE),0) 
+DEBUG_SECTIONS := $(DEBUG_SECTIONS) -UDEBUG_IDE
 endif
 endif
 
@@ -330,15 +323,17 @@ DEVICES_OBJS := \
        devices/8259a.o \
        devices/8254.o \
        devices/serial.o \
-       devices/ramdisk.o \
-       devices/cdrom.o \
        devices/bochs_debug.o \
        devices/os_debug.o \
        devices/apic.o  \
        devices/io_apic.o \
        devices/pci.o \
        devices/para_net.o \
+       devices/ide.o \
+       devices/ram_cd.o \
 
+#      devices/cdrom.o \
+#      devices/ramdisk.o \
 #      devices/vnic.o \
 
 $(DEVICES_OBJS) :: EXTRA_CFLAGS = \
index b667a03..d70ac4b 100644 (file)
 /* 
- *   Copyright (C) 2002  MandrakeSoft S.A.
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
  *
- *     MandrakeSoft S.A.
- *     43, rue d'Aboukir
- *     75002 Paris - France
- *     http://www.linux-mandrake.com/
- *     http://www.mandrakesoft.com/
- *
- *   This library is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU Lesser General Public
- *   License as published by the Free Software Foundation; either
- *   version 2 of the License, or (at your option) any later version.
- *
- *   This library is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *   Lesser General Public License for more details.
- *
- *  You should have received a copy of the GNU Lesser General Public
- *  License along with this library; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- * Major modifications made for the V3VEE project
- * 
  * The V3VEE Project is a joint project between Northwestern University
  * and the University of New Mexico.  You can find out more at 
  * http://www.v3vee.org
- * 
- * Copyright (c) 2008, Zheng Cui <cuizheng@cs.unm.edu>
- * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
- * All rights reserved for original changes
- * 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
  */
 
 #ifndef __DEVICES_IDE_H__
 #define __DEVICES_IDE_H__
 
 #ifdef __V3VEE__
-
-
-#include <palacios/vmm_types.h>
 #include <palacios/vm_dev.h>
 
-typedef long off_t;
-typedef sint32_t ssize_t;
-typedef unsigned int rd_bool;
-typedef uchar_t Bit8u;
-typedef ushort_t Bit16u;
-typedef uint32_t Bit32u;
-typedef uint64_t Bit64u;
-
-
-
-#define MAX_ATA_CHANNEL 4
-
-typedef enum _sense {
-    SENSE_NONE = 0, 
-    SENSE_NOT_READY = 2, 
-    SENSE_ILLEGAL_REQUEST = 5,
-    SENSE_UNIT_ATTENTION = 6
-} sense_t ;
-
-typedef enum _asc {
-    ASC_INV_FIELD_IN_CMD_PACKET = 0x24,
-    ASC_MEDIUM_NOT_PRESENT = 0x3a,
-    ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39,
-    ASC_LOGICAL_BLOCK_OOR = 0x21
-} asc_t ;
-
-
-
-typedef struct  {
-    unsigned cylinders;
-    unsigned heads;
-    unsigned sectors;
-} device_image_t;
-
-
-
-
-struct interrupt_reason_t {
-    unsigned  c_d : 1; 
-    unsigned  i_o : 1; 
-    unsigned  rel : 1; 
-    unsigned  tag : 5; 
-};
-
-
-struct controller_status {
-    rd_bool busy;
-    rd_bool drive_ready;
-    rd_bool write_fault;
-    rd_bool seek_complete;
-    rd_bool drq;
-    rd_bool corrected_data;
-    rd_bool index_pulse;
-    unsigned int index_pulse_count;
-    rd_bool err;
-};
-
-
-
-
-
-struct  sense_info_t {
-    sense_t sense_key;
-
-    struct  {
-       Bit8u arr[4];
-    } information;
-
-    struct  {
-       Bit8u arr[4];
-    } specific_inf;
-
-    struct  {
-       Bit8u arr[3];
-    } key_spec;
-
-    Bit8u fruc;
-    Bit8u asc;
-    Bit8u ascq;
-};
-
 
-struct  error_recovery_t {
-    unsigned char data[8];
-};
-
-struct  cdrom_t {
-    rd_bool ready;
-    rd_bool locked;
-
-    struct cdrom_ops * cd;
-
-    uint32_t capacity;
-    int next_lba;
-    int remaining_blocks;
-
-    struct  currentStruct {
-       struct error_recovery_t error_recovery;
-    } current;
-
-};
-
-struct  atapi_t {
-    uint8_t command;
-    int drq_bytes;
-    int total_bytes_remaining;
-};
-
-
-typedef enum { IDE_NONE, IDE_DISK, IDE_CDROM } device_type_t;
-
-struct controller_t  {
-    struct controller_status status;
-    Bit8u    error_register;
-    Bit8u    head_no;
-
-    union {
-       Bit8u    sector_count;
-       struct interrupt_reason_t interrupt_reason;
-    };
-
-
-    Bit8u    sector_no;
-
-    union  {
-       Bit16u   cylinder_no;
-       Bit16u   byte_count;
-    };
-
-    Bit8u    buffer[2048]; 
-    Bit32u   buffer_index;
-    Bit32u   drq_index;
-    Bit8u    current_command;
-    Bit8u    sectors_per_block;
-    Bit8u    lba_mode;
-
-    struct vm_device * pci;
+typedef enum {IDE_DISK, IDE_CDROM, IDE_NONE} v3_ide_dev_type_t;
 
-    struct  {
-       rd_bool reset;       // 0=normal, 1=reset controller
-       rd_bool disable_irq;     // 0=allow irq, 1=disable irq
-    } control;
+struct v3_ide_cd_ops {
+    uint32_t (*get_capacity)(void * private_data);
+    // Reads always operate on 2048 byte blocks
+    int (*read)(uint8_t * buf, int lba, void * private_data);
 
-    Bit8u    reset_in_progress;
-    Bit8u    features;
 };
 
 
+struct v3_ide_hd_ops {
+    
 
-
-struct  drive_t {
-    device_image_t  hard_drive;
-    device_type_t device_type;
-    // 512 byte buffer for ID drive command
-    // These words are stored in native word endian format, as
-    // they are fetched and returned via a return(), so
-    // there's no need to keep them in x86 endian format.
-    Bit16u id_drive[256];
-  
-    struct controller_t controller;
-    struct cdrom_t cdrom;
-    struct sense_info_t sense;
-    struct atapi_t atapi;
-  
-    /* JRL */
-    void * private_data;
-
-    Bit8u model_no[41];
-};
-
-
-// FIXME:
-// For each ATA channel we should have one controller struct
-// and an array of two drive structs
-struct  channel_t {
-    struct drive_t drives[2];
-    unsigned drive_select;
-  
-    Bit16u ioaddr1;
-    Bit16u ioaddr2;
-    Bit8u  irq;
-};
-
-
-
-struct  ramdisk_t {
-    struct channel_t channels[MAX_ATA_CHANNEL];
 };
 
 
+int v3_ide_register_cdrom(struct vm_device * ide, 
+                         uint_t bus_num, 
+                         uint_t drive_num, 
+                         char * drive_name,
+                         struct v3_ide_cd_ops * ops, 
+                         void * private_data);
 
+int v3_ide_register_harddisk(struct vm_device * ide, 
+                            uint_t bus_num, 
+                            uint_t drive_num, 
+                            char * drive_name,
+                            struct v3_ide_hd_ops * ops, 
+                            void * private_data);
 
 
 
+struct vm_device * v3_create_ide();
 
 
 
@@ -245,29 +65,3 @@ struct  ramdisk_t {
 
 #endif
 
-#if 0
-
-// FLAT MODE
-// Open a image. Returns non-negative if successful.
-//int open (const char* pathname);
-
-// Open an image with specific flags. Returns non-negative if successful.
-int rd_open (const char* pathname, int flags);
-
-// Close the image.
-void rd_close ();
-
-// Position ourselves. Return the resulting offset from the
-// beginning of the file.
-off_t rd_lseek (off_t offset, int whence);
-
-// Read count bytes to the buffer buf. Return the number of
-// bytes read (count).
-ssize_t rd_read (void* buf, size_t count);
-
-// Write count bytes from buf. Return the number of bytes
-// written (count).
-ssize_t rd_write (const void* buf, size_t count);
-
-
-#endif
index 003096c..79718a7 100644 (file)
@@ -39,9 +39,22 @@ struct pci_device;
 
 struct v3_pci_bar {
     pci_bar_type_t type;
-    int mem_hook;
-    int num_pages;
-    int (*bar_update)(struct pci_device * pci_dev, uint_t bar);
+    
+    union {
+       struct {
+           int num_pages;
+           addr_t default_base_addr;
+           int (*mem_read)(addr_t guest_addr, void * dst, uint_t length, void * private_data);
+           int (*mem_write)(addr_t guest_addr, void * src, uint_t length, void * private_data);
+       };
+
+       struct {
+           int num_ports;
+           uint16_t default_base_port;
+           int (*io_read)(ushort_t port, void * dst, uint_t length, struct vm_device * dev);
+           int (*io_write)(ushort_t port, void * src, uint_t length, struct vm_device * dev);
+       };
+    };
 
     // Internal PCI data
     int updated;
index 407d3af..92e6683 100644 (file)
@@ -290,8 +290,6 @@ static int get_highest_isr(struct apic_state * apic) {
            for (j = 7; j >= 0; j--) {
                uchar_t flag = 0x1 << j;
                if ((*svc_major) & flag) {
-
-
                    return ((i * 8) + j);
                }
            }
@@ -314,8 +312,6 @@ static int get_highest_irr(struct apic_state * apic) {
            for (j = 7; j >= 0; j--) {
                uchar_t flag = 0x1 << j;
                if ((*req_major) & flag) {
-
-
                    return ((i * 8) + j);
                }
            }
diff --git a/palacios/src/devices/atapi-types.h b/palacios/src/devices/atapi-types.h
new file mode 100644 (file)
index 0000000..7635998
--- /dev/null
@@ -0,0 +1,287 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __DEVICES_ATAPI_TYPES_H__
+#define __DEVICES_ATAPI_TYPES_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm_types.h>
+
+typedef enum {
+    ATAPI_SEN_NONE = 0, 
+    ATAPI_SEN_NOT_RDY = 2, 
+    ATAPI_SEN_ILL_REQ = 5,
+    ATAPI_SEN_UNIT_ATTNT = 6
+} atapi_sense_key_t ;
+
+typedef enum  {
+    ASC_INV_CMD_FIELD = 0x24,
+    ASC_MEDIA_NOT_PRESENT = 0x3a,
+    ASC_SAVE_PARAM_NOT_SUPPORTED = 0x39,    
+    ASC_LOG_BLK_OOR = 0x21                  /* LOGICAL BLOCK OUT OF RANGE */
+} atapi_add_sense_code_t ; 
+
+struct atapi_irq_flags {
+    uint8_t c_d    : 1; 
+    uint8_t io_dir : 1; 
+    uint8_t rel    : 1; 
+    uint8_t tag    : 5;
+} __attribute__((packed));
+
+
+
+struct atapi_sense_data {
+    union {
+       uint8_t buf[18];
+       struct {
+           uint8_t header;
+           uint8_t rsvd1;
+           uint8_t sense_key; // atapi_sense_key_t
+           uint8_t info[4];
+           uint8_t read_len; // num bytes past this point
+           uint8_t spec_info[4];
+           uint8_t asc;   // atapi_add_sense_code_t
+           uint8_t ascq; // ??
+           uint8_t fruc; // ??
+           uint8_t key_spec[3];
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+
+struct atapi_read10_cmd {
+    uint8_t atapi_cmd;
+    uint8_t rel_addr       : 1;
+    uint8_t rsvd1          : 2;
+    uint8_t force_access   : 1; // can't use cache for data
+    uint8_t disable_pg_out : 1;
+    uint8_t lun            : 3;
+    uint32_t lba;
+    uint8_t rsvd2;
+    uint16_t xfer_len;
+    uint8_t ctrl;
+} __attribute__((packed));
+
+
+struct atapi_mode_sense_cmd {
+    uint8_t atapi_cmd;  // 0x5a
+    uint8_t rsvd1            : 3;
+    uint8_t disable_blk_desc : 1;
+    uint8_t long_lba_acc     : 1;
+    uint8_t lun              : 3;
+    uint8_t page_code        : 6;
+    uint8_t page_ctrl        : 2;
+    uint8_t sub_page_code;
+    uint8_t rsvd2[3];
+    uint16_t alloc_len;
+    uint8_t link             : 1;
+    uint8_t flag             : 1;
+    uint8_t naca             : 1;
+    uint8_t rsvd3            : 3;
+    uint8_t vendor_specific  : 2;
+} __attribute__((packed));
+
+struct atapi_mode_sense_hdr {
+    uint16_t mode_data_len;
+    uint8_t media_type_code;
+    uint8_t rsvd[2];
+    uint16_t blk_desc_len;
+} __attribute__((packed));
+
+
+struct atapi_rd_capacity_cmd {
+    uint8_t atapi_cmd;  // 0x25
+    uint8_t obsolete         : 1;
+    uint8_t rsvd1            : 4;
+    uint8_t lun              : 3;
+    uint32_t lba;
+    uint16_t rsvd2;
+    uint8_t pmi;
+    uint8_t rsvd3            : 7;
+    uint8_t link             : 1;
+    uint8_t flag             : 1;
+    uint8_t naca             : 1;
+    uint8_t rsvd4            : 3;
+    uint8_t vendor_spec      : 2;
+} __attribute__((packed));
+
+
+struct atapi_rd_capacity_resp {
+    uint32_t lba;
+    uint32_t block_len;
+} __attribute__((packed));
+
+struct atapi_config_cmd {
+    uint8_t atapi_cmd;  // 0x46
+    uint8_t rt               : 2;
+    uint8_t rsvd1            : 3;
+    uint8_t lun              : 3;
+    uint16_t start_feature_num;
+    uint8_t rsvd2[3];
+    uint16_t alloc_len;
+    uint8_t link             : 1;
+    uint8_t flag             : 1;
+    uint8_t naca             : 1;
+    uint8_t rsvd3            : 3;
+    uint8_t vendor_specific  : 2;
+} __attribute__((packed));
+
+struct atapi_config_resp {
+    uint32_t data_len;
+    uint16_t rsvd;
+    uint16_t cur_profile;
+} __attribute__((packed));
+
+
+struct atapi_rd_toc_cmd {
+    uint8_t atapi_cmd;  // 0x43
+    uint8_t rsvd1            : 1;
+    uint8_t msf              : 1;
+    uint8_t rsvd2            : 3;
+    uint8_t lun              : 3;
+    uint8_t format           : 4;
+    uint8_t rsvd3            : 4;
+    uint8_t rsvd4[3];
+    uint8_t track_num;
+    uint16_t alloc_len;
+    uint8_t link             : 1;
+    uint8_t flag             : 1;
+    uint8_t naca             : 1;
+    uint8_t rsvd5            : 3;
+    uint8_t vendor_specific  : 2;
+} __attribute__((packed));
+
+struct atapi_rd_toc_resp {
+    uint16_t data_len;
+    uint8_t first_track_num;
+    uint8_t last_track_num;
+    
+    struct {
+       uint8_t rsvd;
+       uint8_t ctrl         : 4;
+       uint8_t adr          : 4;
+       uint8_t track_num;
+       uint8_t rsvd2;
+       uint32_t start_addr;
+    } track_descs[0] __attribute__((packed)) ;
+
+} __attribute__((packed));
+
+
+struct atapi_error_recovery {
+    uint8_t page_code     : 6;
+    uint8_t rsvd          : 1;
+    uint8_t page_ctrl     : 1;
+    uint8_t page_len;
+    uint8_t dcr           : 1;
+    uint8_t dte           : 1;
+    uint8_t per           : 1;
+    uint8_t rsvd1         : 1;
+    uint8_t rc            : 1;
+    uint8_t tb            : 1;
+    uint8_t arre          : 1;
+    uint8_t awre          : 1;
+    uint8_t rd_retry_cnt;
+    uint8_t correct_spin;
+    uint8_t head_offset;
+    uint8_t data_strobe_offset;
+    uint8_t emcdr         : 2;
+    uint8_t rsvd2         : 6;
+    uint8_t wr_retry_cnt;
+    uint8_t rsvd3;
+    uint16_t recovery_time_limit;
+} __attribute__((packed));
+
+
+struct atapi_cdrom_caps {
+    uint8_t page_code     : 6;
+    uint8_t rsvd          : 1;
+    uint8_t page_ctrl     : 1;
+    uint8_t page_len;
+    uint8_t cdr_rd        : 1;
+    uint8_t cdrw_rd       : 1;
+    uint8_t mthd_2        : 1;
+    uint8_t dvdrom_rd     : 1;
+    uint8_t dvdr_rd       : 1;
+    uint8_t dvdram_rd     : 1;
+    uint8_t rsvd1         : 2;
+    uint8_t cdr_wr        : 1;
+    uint8_t cdrw_wr       : 1;
+    uint8_t tst_wr        : 1;
+    uint8_t rsvd2         : 1;
+    uint8_t dvdr_wr       : 1;
+    uint8_t dvdram_wr     : 1;
+    uint8_t rsvd3         : 2;
+    uint8_t audio_play    : 1;
+    uint8_t composite     : 1;
+    uint8_t digi_port1    : 1;
+    uint8_t digi_port2    : 1;
+    uint8_t mode2_form1   : 1;
+    uint8_t mode2_form2   : 1;
+    uint8_t multisession  : 1;
+    uint8_t BUF           : 1;
+    uint8_t cd_da         : 1;
+    uint8_t cdda_str_acc  : 1;
+    uint8_t rw_supported  : 1;
+    uint8_t rw_dc         : 1;
+    uint8_t c2_ptrs_supp  : 1;
+    uint8_t isrc          : 1;
+    uint8_t upc           : 1;
+    uint8_t rd_bar_cd_cap : 1;
+    uint8_t lock          : 1;
+    uint8_t lock_state    : 1;
+    uint8_t prevent_jmpr  : 1;
+    uint8_t eject         : 1;
+    uint8_t rsvd4         : 1;
+    uint8_t lmt           : 3;
+    uint8_t sep_vol       : 1;
+    uint8_t sep_chnl_mute : 1;
+    uint8_t sdp           : 1;
+    uint8_t sss           : 1;
+    uint8_t side_chg_cap  : 1;
+    uint8_t rw_in_lead_rd : 1;
+    uint8_t rsvd5         : 2;
+    uint16_t obsolete1;
+    uint16_t num_vols_supp;
+    uint16_t lun_buf_size; // in KBytes
+    uint16_t obsolete2;
+    uint8_t obsolete3;
+    uint8_t rsvd6         : 1;
+    uint8_t bckf          : 1;
+    uint8_t rck           : 1;
+    uint8_t lsbf          : 1;
+    uint8_t len           : 2;
+    uint8_t rsvd7         : 2;
+    uint16_t obsolete4[2];
+    uint16_t cp_mgmnt_rev_supp;
+    uint8_t rsvd8;
+    uint8_t rot_ctrl_sel  : 2;
+    uint8_t rsvd9         : 6;
+    uint16_t cur_wr_spd; // KBytes/sec
+    uint16_t num_lun_wr_spd_dsc_tbls;
+    // lun write speed descriptor tables
+} __attribute__((packed));
+
+#endif
+
+#endif
diff --git a/palacios/src/devices/atapi.h b/palacios/src/devices/atapi.h
new file mode 100644 (file)
index 0000000..5af6729
--- /dev/null
@@ -0,0 +1,554 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#define ATAPI_PACKET_SIZE 12
+#define ATAPI_BLOCK_SIZE 2048
+
+#include "atapi-types.h"
+
+
+/* ATAPI sucks...
+ * The OS will write to the cylinder register the number of bytes it wants to read 
+ * however the device can change that value 
+ * 
+ */
+static int atapi_update_req_len(struct vm_device * dev, struct ide_channel * channel, uint_t xfer_len) {
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    //   PrintDebug("Updating request length (pre=%d)\n", drive->req_len);
+
+    if (drive->req_len == 0) {
+       PrintError("ATAPI Error: request of length 0\n");
+       return -1;
+    }
+
+
+    channel->status.busy = 0;
+    channel->status.data_req = 1;
+    channel->status.error = 0;
+
+    drive->irq_flags.io_dir = 1;
+    drive->irq_flags.c_d = 0;
+
+    // make count even
+    if (drive->req_len % 2) {
+       drive->req_len -= 1;
+    }
+
+    // if the device can't return as much as the OS requested
+    if (drive->req_len > xfer_len) {
+       drive->req_len = xfer_len;
+    }
+
+    //    PrintDebug("Updating request length (post=%d)\n", drive->req_len);
+
+    return 0;
+}
+
+
+
+// This is for simple commands that don't need to sanity check the req_len
+static void atapi_setup_cmd_resp(struct vm_device * dev, struct ide_channel * channel, uint_t xfer_len) {
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    drive->transfer_length = xfer_len;
+    drive->transfer_index = 0;
+    drive->req_len = drive->transfer_length;
+
+    drive->irq_flags.io_dir = 1;
+    drive->irq_flags.c_d = 0;
+
+    channel->status.busy = 0;
+    channel->status.data_req = 1;
+    channel->status.error = 0;
+
+    ide_raise_irq(dev, channel);
+}
+
+static void atapi_cmd_error(struct vm_device * dev, struct ide_channel * channel, 
+                    atapi_sense_key_t  sense_key, atapi_add_sense_code_t asc) {
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    // overload error register with ATAPI value
+    channel->error_reg.val = sense_key << 4;
+    
+    channel->status.busy = 0;
+    channel->status.ready = 1;
+    channel->status.write_fault = 0;
+    channel->status.data_req = 0;
+    channel->status.error = 1;
+  
+    drive->cd_state.sense.header = 0xf0;
+    drive->cd_state.sense.rsvd1 = 0x00;
+    drive->cd_state.sense.read_len = 0x0a;
+    drive->cd_state.sense.sense_key = sense_key;
+    drive->cd_state.sense.asc = asc;
+
+
+    drive->irq_flags.io_dir = 1;
+    drive->irq_flags.c_d = 1;
+    drive->irq_flags.rel = 0;
+
+    ide_raise_irq(dev, channel);
+}
+
+
+static void atapi_cmd_nop(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    channel->status.busy = 0;
+    channel->status.ready = 1;
+    channel->status.data_req = 0;
+    channel->status.error = 0;
+
+    drive->irq_flags.io_dir = 1;
+    drive->irq_flags.c_d = 1;
+    drive->irq_flags.rel = 0;
+
+    ide_raise_irq(dev, channel);
+}
+
+
+
+static int atapi_read_chunk(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    int ret = drive->cd_ops->read(drive->data_buf, drive->cd_state.current_lba, drive->private_data);
+
+    if (ret == -1) {
+       PrintError("IDE: Error reading CD block (LBA=%x)\n", drive->cd_state.current_lba);
+       return -1;
+    }
+
+    return 0;
+}
+
+
+static int atapi_update_data_buf(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);    
+    
+    switch (drive->cd_state.atapi_cmd) {
+       case 0x28: // read(10)
+       case 0xa8: // read(12)
+
+           // Update lba address to point to next block
+           drive->cd_state.current_lba++;
+
+           // read the next block
+           return atapi_read_chunk(dev, channel);
+
+       default:
+           PrintError("Unhandled ATAPI command in update buffer %x\n", drive->cd_state.atapi_cmd);
+           return -1;
+    }
+
+    return 0;
+}
+
+static int atapi_read10(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    struct atapi_read10_cmd * cmd = (struct atapi_read10_cmd *)(drive->data_buf);
+    uint32_t lba =  be_to_le_32(cmd->lba);
+    uint16_t xfer_len = be_to_le_16(cmd->xfer_len);
+    
+    /* Check if cd is ready
+     * if not: atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
+     */
+
+    if (xfer_len == 0) {
+       atapi_cmd_nop(dev, channel);
+       return 0;
+    }
+    
+    if ((lba + xfer_len) > drive->cd_ops->get_capacity(drive->private_data)) {
+       atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_LOG_BLK_OOR);
+       ide_raise_irq(dev, channel);
+       return 0;}
+
+    //    PrintDebug("Reading %d blocks from LBA 0x%x\n", xfer_len, lba);
+
+    drive->cd_state.current_lba = lba;
+
+    // Update the request length value in the cylinder registers
+
+    if (atapi_read_chunk(dev, channel) == -1) {
+       PrintError("IDE: Could not read initial chunk from CD\n");
+       return -1;
+    }
+    
+    drive->transfer_length = xfer_len * ATAPI_BLOCK_SIZE;
+    drive->transfer_index = 0;
+
+    // Length of ATAPI buffer sits in cylinder registers
+    // This is weird... The host sets this value to say what it would like to transfer, 
+    // if it is larger than the correct size, the device shrinks it to the correct size
+    if (atapi_update_req_len(dev, channel, ATAPI_BLOCK_SIZE) == -1) {
+       PrintError("Could not update initial request length\n");
+       return -1;
+    }
+
+    ide_raise_irq(dev, channel);
+
+    return 0;
+}
+
+
+
+static void atapi_req_sense(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    memcpy(drive->data_buf, drive->cd_state.sense.buf, sizeof(drive->cd_state.sense.buf));
+   
+    atapi_setup_cmd_resp(dev, channel, 18);
+}
+
+
+
+static int atapi_get_capacity(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    struct atapi_rd_capacity_resp * resp = (struct atapi_rd_capacity_resp *)(drive->data_buf);
+    uint32_t capacity = drive->cd_ops->get_capacity(drive->private_data);
+
+    resp->lba = le_to_be_32(capacity);
+    resp->block_len = le_to_be_32(ATAPI_BLOCK_SIZE);
+
+    atapi_setup_cmd_resp(dev, channel, sizeof(struct atapi_rd_capacity_resp));
+
+    return 0;
+}
+
+static int atapi_get_config(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    struct atapi_config_cmd * cmd = (struct atapi_config_cmd *)(drive->data_buf);
+    uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
+    struct atapi_config_resp * resp = (struct atapi_config_resp *)(drive->data_buf);
+    int xfer_len = 8;
+
+    memset(resp, 0, sizeof(struct atapi_config_resp));
+
+    resp->data_len = le_to_be_32(xfer_len - 4);
+
+    if (alloc_len < xfer_len) {
+       xfer_len = alloc_len;
+    }
+    
+    atapi_setup_cmd_resp(dev, channel, xfer_len);
+    
+    return 0;
+}
+
+
+static int atapi_read_toc(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    struct atapi_rd_toc_cmd * cmd = (struct atapi_rd_toc_cmd *)(drive->data_buf);
+    uint16_t alloc_len = be_to_le_16(cmd->alloc_len);
+    struct atapi_rd_toc_resp * resp = (struct atapi_rd_toc_resp *)(drive->data_buf);
+
+    int xfer_len = 12;
+
+    memset(resp, 0, sizeof(struct atapi_rd_toc_resp));
+    
+    resp->data_len = le_to_be_16(10);
+    resp->first_track_num = 1;
+    resp->last_track_num = 1;
+
+    // we don't handle multi session
+    // we'll just treat it the same as single session
+    if ((cmd->format == 0) || (cmd->format == 1)) {
+       memset(&(resp->track_descs[0]), 0, 8);
+       
+       if (alloc_len < xfer_len) {
+           xfer_len = alloc_len;
+       }
+
+       atapi_setup_cmd_resp(dev, channel, xfer_len);
+    } else {
+       PrintError("Unhandled Format (%d)\n", cmd->format);
+       return -1;
+    }
+
+    return 0;
+}
+
+
+static int atapi_mode_sense_cur_values(struct vm_device * dev, struct ide_channel * channel, 
+                                      struct atapi_mode_sense_cmd * sense_cmd) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    struct atapi_mode_sense_hdr * hdr = (struct atapi_mode_sense_hdr *)(drive->data_buf);
+    uint_t resp_len = sizeof(struct atapi_mode_sense_hdr);
+    uint16_t alloc_len = be_to_le_16(sense_cmd->alloc_len);
+    PrintDebug("Page Code: %x\n", sense_cmd->page_code);
+    PrintDebug("Alloc len: %d\n", alloc_len);
+
+    switch (sense_cmd->page_code) {
+
+       case 0x01: {    // error recovery
+           struct atapi_error_recovery * err = NULL;
+           err = (struct atapi_error_recovery *)(drive->data_buf + 
+                                                 sizeof(struct atapi_mode_sense_hdr));
+
+           memcpy(err, &(drive->cd_state.err_recovery), sizeof(struct atapi_error_recovery));
+
+           resp_len += sizeof(struct atapi_error_recovery);
+
+           hdr->mode_data_len = le_to_be_16(resp_len - 2);
+           
+           break;
+       }
+       case 0x2a: { // CDROM caps and mech. status
+           struct atapi_cdrom_caps * caps = NULL;
+           caps = (struct atapi_cdrom_caps *)(drive->data_buf + sizeof(struct atapi_mode_sense_hdr));
+           
+
+           memset(caps, 0, sizeof(struct atapi_cdrom_caps));
+
+           resp_len += sizeof(struct atapi_cdrom_caps);
+
+           hdr->mode_data_len = le_to_be_16(resp_len - 2);
+
+           caps->page_code = 0x2a;
+           caps->page_len = 0x12;
+           caps->mode2_form1 = 1;
+           caps->mode2_form2 = 1;
+           caps->multisession = 1;
+           caps->isrc = 1;
+           caps->upc = 1;
+
+           /* JRL TODO: These are dynamic caps */
+           caps->lock = 1;
+           caps->lock_state = 0;
+           caps->eject = 1;
+
+           caps->lmt = 1;
+           caps->obsolete1 = le_to_be_16(0x2c2);
+           caps->num_vols_supp = le_to_be_16(2);
+
+           caps->lun_buf_size = le_to_be_16(512);
+           caps->obsolete2 = le_to_be_16(0x2c2);
+
+           break;
+       }
+       case 0x0d:
+       case 0x0e:
+       case 0x3f:
+       default:
+           PrintError("ATAPI: Mode sense Page Code not supported (%x)\n", sense_cmd->page_code);
+           atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
+           ide_raise_irq(dev, channel);
+           return 0;
+    }
+
+
+    // We do this after error checking, because its only valid if everything worked
+    memset(hdr, 0, sizeof(struct atapi_mode_sense_hdr));
+    hdr->media_type_code = 0x70;
+
+    PrintDebug("resp_len=%d\n", resp_len);
+
+    drive->transfer_length = (resp_len > alloc_len) ? alloc_len : resp_len;
+    drive->transfer_index = 0;
+    atapi_update_req_len(dev, channel, drive->transfer_length);
+
+    ide_raise_irq(dev, channel);
+
+    return 0;
+}
+
+
+static int atapi_mode_sense(struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    struct atapi_mode_sense_cmd * sense_cmd = (struct atapi_mode_sense_cmd *)(drive->data_buf);
+
+    switch (sense_cmd->page_ctrl) {
+       case 0x00: // Current values
+           return atapi_mode_sense_cur_values(dev, channel, sense_cmd);
+       case 0x01: // Changeable values
+       case 0x02: // default values
+       case 0x03: // saved values
+       default:
+           PrintError("ATAPI: Mode sense mode not supported (%x)\n", sense_cmd->page_ctrl);
+           return -1;
+    }
+    return 0;
+}
+
+
+static int atapi_handle_packet(struct vm_device * dev, struct ide_channel * channel) {
+   struct ide_drive * drive = get_selected_drive(channel);
+   uint8_t cmd = drive->data_buf[0];
+
+   PrintDebug("IDE: ATAPI Command %x\n", cmd);
+
+   drive->cd_state.atapi_cmd = cmd;
+
+   switch (cmd) {
+       case 0x00: // test unit ready
+          atapi_cmd_nop(dev, channel);
+
+          /* if drive not ready: 
+             atapi_cmd_error(... ATAPI_SEN_NOT_RDY, ASC_MEDIA_NOT_PRESENT)
+          */
+          break;
+       case 0x03: // request sense
+          atapi_req_sense(dev, channel);
+          break;
+
+       case 0x28: // read(10)
+          if (atapi_read10(dev, channel) == -1) {
+              PrintError("IDE: Error in ATAPI read (%x)\n", cmd);
+              return -1;
+          }
+          break;
+
+       case 0x5a: // mode sense
+          if (atapi_mode_sense(dev, channel) == -1) {
+              PrintError("IDE: Error in ATAPI mode sense (%x)\n", cmd);
+              return -1;
+          }
+          break;
+
+
+       case 0x25: // read cdrom capacity
+          if (atapi_get_capacity(dev, channel) == -1) {
+              PrintError("IDE: Error getting CDROM capacity (%x)\n", cmd);
+              return -1;
+          }
+          break;
+
+
+       case 0x43: // read TOC
+          if (atapi_read_toc(dev, channel) == -1) {
+              PrintError("IDE: Error getting CDROM TOC (%x)\n", cmd);
+              return -1;
+          }
+          break;
+
+       case 0x46: // get configuration
+          if (atapi_get_config(dev, channel) == -1) {
+              PrintError("IDE: Error getting CDROM Configuration (%x)\n", cmd);
+              return -1;
+          }
+          break;
+
+       case 0x51: // read disk info
+          // no-op to keep the Linux CD-ROM driver happy
+          PrintDebug("Error: Read disk info no-op to keep the Linux CD-ROM driver happy\n");
+          atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
+          ide_raise_irq(dev, channel);
+          break;
+
+
+
+       case 0xa8: // read(12)
+
+
+       case 0x1b: // start/stop drive
+       case 0xbd: // mechanism status 
+       case 0x12: // inquiry
+
+       case 0xbe: // read cd
+
+
+
+       case 0x2b: // seek
+       case 0x1e: // lock door
+       case 0x42: // read sub-channel
+
+
+          
+       case 0x55: // mode select
+       case 0xa6: // load/unload cd
+       case 0x4b: // pause/resume
+       case 0x45: // play audio
+       case 0x47: // play audio msf
+       case 0xbc: // play cd
+       case 0xb9: // read cd msf
+       case 0x44: // read header
+       case 0xba: // scan
+       case 0xbb: // set cd speed
+       case 0x4e: // stop play/scan
+       case 0x4a: // ???
+       default:
+          PrintError("Unhandled ATAPI command %x\n", cmd);
+          atapi_cmd_error(dev, channel, ATAPI_SEN_ILL_REQ, ASC_INV_CMD_FIELD);
+          ide_raise_irq(dev, channel);
+          return -1;
+   }
+   
+   return 0;
+}
+
+
+static void atapi_identify_device(struct ide_drive * drive) {
+    struct ide_drive_id * drive_id = (struct ide_drive_id *)(drive->data_buf);
+    const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
+    const char* firmware = "ALPHA1  ";
+
+    drive->transfer_length = 512;
+    drive->transfer_index = 0;
+
+
+    memset(drive_id->buf, 0, sizeof(drive_id->buf));
+
+    drive_id->fixed_drive = 1;
+    drive_id->removable_media = 1;
+
+    // Black magic...
+    drive_id->disk_speed1 = 1;
+    drive_id->disk_speed3 = 1;
+
+    drive_id->cdrom_flag = 1;
+
+    // These buffers do not contain a terminating "\0"
+    memcpy(drive_id->serial_num, serial_number, strlen(serial_number));
+    memcpy(drive_id->firmware_rev, firmware, strlen(firmware));
+    memcpy(drive_id->model_num, drive->model, 40);
+
+    // 32 bits access
+    drive_id->dword_io = 1;
+
+    // enable DMA access
+    drive_id->dma_enable = 1;
+
+    // enable LBA access
+    drive_id->lba_enable = 1;
+    
+    drive_id->rw_multiples = 0x80ff;
+
+    // words 64-70, 54-58 valid
+    drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
+
+    // copied from CFA540A
+    //    drive_id->buf[63] = 0x0103; // variable (DMA stuff)
+    drive_id->buf[63] = 0x0000; // variable (DMA stuff)
+    //    drive_id->buf[64] = 0x0001; // PIO
+    drive_id->buf[65] = 0x00b4;
+    drive_id->buf[66] = 0x00b4;
+    drive_id->buf[67] = 0x012c;
+    drive_id->buf[68] = 0x00b4;
+
+    drive_id->buf[71] = 30; // faked
+    drive_id->buf[72] = 30; // faked
+
+    //    drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
+    drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
+
+    drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
+}
diff --git a/palacios/src/devices/ide-types.h b/palacios/src/devices/ide-types.h
new file mode 100644 (file)
index 0000000..3ae9966
--- /dev/null
@@ -0,0 +1,463 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+
+#ifndef __DEVICES_IDE_TYPES_H__
+#define __DEVICES_IDE_TYPES_H__
+
+#ifdef __V3VEE__
+
+#include <palacios/vmm_types.h>
+
+
+struct ide_error_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint_t addr_mark_nf     : 1;
+           uint_t track0_nf        : 1;
+           uint_t abort            : 1;
+           uint_t rsvd0            : 1;
+           uint_t ID_nf            : 1;
+           uint_t rsvd1            : 1;
+           uint_t data_error       : 1;
+           uint_t bad_block        : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+struct ide_drive_head_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint_t head_num      : 4;
+           uint_t drive_sel     : 1;
+           uint_t rsvd1         : 1;
+           uint_t lba_mode      : 1;
+           uint_t rsvd2         : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+struct ide_status_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint_t error         : 1;
+           uint_t index         : 1;
+           uint_t corrected     : 1;
+           uint_t data_req      : 1;
+           uint_t seek_complete : 1;
+           uint_t write_fault   : 1;
+           uint_t ready         : 1;
+           uint_t busy          : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct ide_ctrl_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint_t rsvd0        : 1;
+           uint_t irq_disable   : 1;
+           uint_t soft_reset   : 1;
+           uint_t rsvd1        : 5;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct ide_features_reg {
+    union {
+       uint8_t val;
+       uint8_t dma; // 1 == DMA, 0 = PIO
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+struct ide_dma_cmd_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint8_t start : 1;
+           uint8_t rsvd1 : 2;
+           uint8_t read  : 1;
+           uint8_t rsvd2 : 4;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+
+struct ide_dma_status_reg {
+    union {
+       uint8_t val;
+       struct {
+           uint8_t active  : 1;
+           uint8_t err     : 1;
+           uint8_t int_gen : 1;
+           uint8_t rsvd1   : 4;
+           uint8_t prd_int_status : 1;
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+struct ide_dma_prd {
+    uint32_t base_addr;
+    uint16_t size;
+    uint16_t rsvd           : 15;
+    uint8_t end_of_table    : 1;
+} __attribute__((packed));
+
+
+
+typedef enum {IDE_CTRL_NOT_SPECIFIED, 
+             IDE_CTRL_SINGLE_PORT, 
+             IDE_CTRL_DUAL_PORT, 
+             IDE_CTRL_DUAL_PORT_CACHE} ide_controller_type;
+
+struct ide_drive_id {
+    union {
+       uint16_t buf[256];
+       struct {
+           // 0
+           uint_t rsvd1           : 1;
+           uint_t hard_sectors    : 1;
+           uint_t no_soft_sectors : 1;
+           uint_t no_mfm_enc      : 1;
+           uint_t head_switch_time : 1;
+           uint_t spnd_mot_ctrl   : 1;
+           uint_t fixed_drive     : 1;
+           uint_t removable_media : 1;
+           uint_t disk_speed1     : 1;
+           uint_t disk_speed2     : 1;
+           uint_t disk_speed3     : 1;
+           uint_t rpm_tolerance   : 1;
+           uint_t data_strobe_offset : 1;
+           uint_t track_offset_option : 1;
+           uint_t fmt_speed_tol   : 1;
+           uint_t cdrom_flag      : 1;
+
+           // 1
+           uint16_t num_cylinders;
+
+           // 2
+           uint16_t rsvd2;
+           
+           // 3
+           uint16_t num_heads;
+           // 4
+           uint16_t bytes_per_track;
+           // 5
+           uint16_t bytes_per_sector;
+           // 6
+           uint16_t sectors_per_track;
+
+           // 7
+           uint16_t sector_gap;
+           
+           // 8
+           uint8_t phase_lock_bytes;
+           uint8_t rsvd3;
+
+           // 9
+           uint16_t num_vendor_wds;
+           
+           // 10
+           uint8_t serial_num[20]; // right aligned, padded with 0x20
+           
+           // 20
+           uint16_t controller_type;
+
+           // 21
+           uint16_t buffer_size; // in 512 byte chunks
+           
+           // 22
+           uint16_t num_ecc_bytes;
+
+           // 23
+           uint8_t firmware_rev[8]; // space padded
+
+           // 27
+           uint8_t model_num[40]; // space padded
+           
+           // 47
+           uint16_t rw_multiples;
+
+           // 48
+           uint16_t dword_io;
+
+           // 49
+           uint8_t rsvd4;
+           uint8_t dma_enable : 1;
+           uint8_t lba_enable : 1;
+           uint8_t IORDYsw    : 1;
+           uint8_t IORDYsup   : 1;
+           uint8_t rsvd5      : 4;
+
+           
+           // 50
+           uint16_t rsvd6;
+           
+           // 51
+           uint16_t min_PIO_cycle; // 0=slow, 1=medium, 2=fast
+           // 52
+           uint16_t min_DMA_cycle; // 0=slow, 1=medium, 2=fast
+
+           // 53
+           uint16_t field_valid; //  2:        ultra_ok        word  88
+                                 //  1:        eide_ok         words 64-70
+                                 //  0:        cur_ok          words 54-58
+           // 54
+           uint16_t cur_cyls;
+           // 55 
+           uint16_t cur_heads;
+           // 56
+           uint16_t cur_sectors;
+           // 57
+           uint16_t cur_capacity0;
+           // 58
+           uint16_t cur_capacity1;
+
+           // 59
+           uint8_t cur_mult_sect_cnt;
+           uint8_t mult_sect_valid; // bit0==0: valid
+
+           // 60
+           uint32_t lba_capacity;
+
+           // 62
+           uint16_t dma_lword;
+           // 63
+           uint16_t dma_mword;
+
+           // 64
+           uint16_t eide_pio_modes; // 0: (mode 3), 1: (mode 4)
+           // 65
+           uint16_t eide_dma_min; /* min mword dma cycle time (ns) */
+           // 66 
+           uint16_t eide_dma_time; /* recommended mword dma cycle time (ns) */
+           // 67
+           uint16_t eide_pio; /* min cycle time (ns), no IORDY  */
+           // 68
+           uint16_t eide_pio_iordy; /* min cycle time (ns), with IORDY */
+
+           // 69
+           uint16_t rsvd7[6];
+
+           // 75
+           uint16_t queue_depth;
+
+           // 76
+           uint16_t rsvd8[4];
+
+           // 80
+           uint16_t major_rev_num;
+           // 81
+           uint16_t minor_rev_num;
+           // 82
+           uint16_t cmd_set_1; /*  15: Obsolete
+                                * 14:  NOP command
+                                * 13:  READ_BUFFER
+                                * 12:  WRITE_BUFFER
+                                * 11:  Obsolete
+                                * 10:  Host Protected Area
+                                *  9:  DEVICE Reset
+                                *  8:  SERVICE Interrupt
+                                *  7:  Release Interrupt
+                                *  6:  look-ahead
+                                *  5:  write cache
+                                *  4:  PACKET Command
+                                *  3:  Power Management Feature Set
+                                *  2:  Removable Feature Set
+                                *  1:  Security Feature Set
+                                *  0:  S
+                                */
+
+           // 83
+           uint16_t cmd_set_2; /*  15: Shall be ZERO
+                                * 14:  Shall be ONE
+                                * 13:  FLUSH CACHE EXT
+                                * 12:  FLUSH CACHE
+                                * 11:  Device Configuration Overlay
+                                * 10:  48-bit Address Feature Set
+                                *  9:  Automatic Acoustic Management
+                                *  8:  SET MAX security
+                                *  7:  reserved 1407DT PARTIES
+                                *  6:  SetF sub-command Power-Up
+                                *  5:  Power-Up in Standby Feature Set
+                                *  4:  Removable Media Notification
+                                *  3:  APM Feature Set
+                                *  2:  CFA Feature Set
+                                *  1:  READ/WRITE DMA QUEUED
+                                *  0:  Download MicroCode
+                                */
+
+           // 84
+           uint16_t cfsse;     /*  cmd set-feature supported extensions
+                                * 15:  Shall be ZERO
+                                * 14:  Shall be ONE
+                                * 13:6 reserved
+                                *  5:  General Purpose Logging
+                                *  4:  Streaming Feature Set
+                                *  3:  Media Card Pass Through
+                                *  2:  Media Serial Number Valid
+                                *  1:  SMART selt-test supported
+                                *  0:  SMART error logging
+                                */
+
+           // 85
+           uint16_t cfs_enable_1;      /* command set-feature enabled
+                                        * 15:  Obsolete
+                                        * 14:  NOP command
+                                        * 13:  READ_BUFFER
+                                        * 12:  WRITE_BUFFER
+                                        * 11:  Obsolete
+                                        * 10:  Host Protected Area
+                                        *  9:  DEVICE Reset
+                                        *  8:  SERVICE Interrupt
+                                        *  7:  Release Interrupt
+                                        *  6:  look-ahead
+                                        *  5:  write cache
+                                        *  4:  PACKET Command
+                                        *  3:  Power Management Feature Set
+                                        *  2:  Removable Feature Set
+                                        *  1:  Security Feature Set
+                                        *  0:  SMART Feature Set
+                                        */
+           // 86
+           uint16_t cfs_enable_2;      /* command set-feature enabled
+                                        * 15:  Shall be ZERO
+                                        * 14:  Shall be ONE
+                                        * 13:  FLUSH CACHE EXT
+                                        * 12:  FLUSH CACHE
+                                        * 11:  Device Configuration Overlay
+                                        * 10:  48-bit Address Feature Set
+                                        *  9:  Automatic Acoustic Management
+                                        *  8:  SET MAX security
+                                        *  7:  reserved 1407DT PARTIES
+                                        *  6:  SetF sub-command Power-Up
+                                        *  5:  Power-Up in Standby Feature Set
+                                        *  4:  Removable Media Notification
+                                        *  3:  APM Feature Set
+                                        *  2:  CFA Feature Set
+                                        *  1:  READ/WRITE DMA QUEUED
+                                        *  0:  Download MicroCode
+                                        */
+           // 87
+           uint16_t csf_default;       /* command set-feature default
+                                        * 15:  Shall be ZERO
+                                        * 14:  Shall be ONE
+                                        * 13:6 reserved
+                                        *  5:  General Purpose Logging enabled
+                                        *  4:  Valid CONFIGURE STREAM executed
+                                        *  3:  Media Card Pass Through enabled
+                                        *  2:  Media Serial Number Valid
+                                        *  1:  SMART selt-test supported
+                                        *  0:  SMART error logging
+                                        */
+           // 88
+           uint16_t dma_ultra; 
+           // 89
+           uint16_t trs_euc;           /* time required for security erase */
+           // 90
+           uint16_t trs_Euc;           /* time required for enhanced erase */
+           // 91
+           uint16_t cur_apm_values;    /* current APM values */
+           // 92
+           uint16_t mprc;              /* master password revision code */
+           // 93
+           uint16_t hw_config;         /* hardware config (word 93)
+                                        * 15:  Shall be ZERO
+                                        * 14:  Shall be ONE
+                                        *  0:  Shall be ONE
+                                        */
+           // 94
+           uint16_t acoustic;
+           // 95
+           uint16_t msrqs;             /* min stream request size */
+           // 96
+           uint16_t sxfert;            /* stream transfer time */
+           // 97
+           uint16_t sal;               /* stream access latency */
+           // 98
+           uint32_t spg;               /* stream performance granularity */
+           // 100
+           uint64_t lba_capacity_2; /* 48-bit total number of sectors */
+           // 104
+           uint16_t rsvd9[22];
+
+           // 126
+           uint16_t last_lun;
+           // 127
+           uint16_t feature_set; //  Removable Media Notification
+
+           // 128
+           uint16_t dlf; /* device lock function
+                          * 15:9       reserved
+                          *  8 security level 1:max 0:high
+                          *  7:6       reserved
+                          *  5 enhanced erase
+                          *  4 expire
+                          *  3 frozen
+                          *  2 locked
+                          *  1 en/disabled
+                          *  0 capability
+                          */
+           // 129
+           uint16_t csfo; /* current set features options
+                           * 15:4      reserved
+                           *  3:       auto reassign
+                           *  2:       reverting
+                           *  1:       read-look-ahead
+                           *  0:       write cache
+                           */
+           
+           // 130
+           uint16_t rsvd10[30];
+           
+           // 160
+           uint16_t cfa_power;
+
+           // 161 
+           uint16_t cfa[15];
+           // 176
+           uint16_t cur_media_ser_num[30];
+           // 206
+           uint16_t rsvd11[49];
+           // 255
+           uint16_t integrity; /* 15:8 Checksum
+                                *  7:0 Signature
+                                */
+           
+
+       } __attribute__((packed));
+    } __attribute__((packed));
+} __attribute__((packed));
+
+
+#endif // ! __V3VEE__
+
+#endif
diff --git a/palacios/src/devices/ide.c b/palacios/src/devices/ide.c
new file mode 100644 (file)
index 0000000..a9d88aa
--- /dev/null
@@ -0,0 +1,1131 @@
+/* 
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National 
+ * Science Foundation and the Department of Energy.  
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico.  You can find out more at 
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
+ * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
+ * All rights reserved.
+ *
+ * Author: Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software.  You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <palacios/vmm.h>
+#include <devices/ide.h>
+#include <devices/pci.h>
+#include "ide-types.h"
+#include "atapi-types.h"
+
+#define PRI_DEFAULT_IRQ 14
+#define SEC_DEFAULT_IRQ 15
+
+
+#define PRI_DATA_PORT         0x1f0
+#define PRI_FEATURES_PORT     0x1f1
+#define PRI_SECT_CNT_PORT     0x1f2
+#define PRI_SECT_NUM_PORT     0x1f3
+#define PRI_CYL_LOW_PORT      0x1f4
+#define PRI_CYL_HIGH_PORT     0x1f5
+#define PRI_DRV_SEL_PORT      0x1f6
+#define PRI_CMD_PORT          0x1f7
+#define PRI_CTRL_PORT         0x3f6
+#define PRI_ADDR_REG_PORT     0x3f7
+
+#define SEC_DATA_PORT         0x170
+#define SEC_FEATURES_PORT     0x171
+#define SEC_SECT_CNT_PORT     0x172
+#define SEC_SECT_NUM_PORT     0x173
+#define SEC_CYL_LOW_PORT      0x174
+#define SEC_CYL_HIGH_PORT     0x175
+#define SEC_DRV_SEL_PORT      0x176
+#define SEC_CMD_PORT          0x177
+#define SEC_CTRL_PORT         0x376
+#define SEC_ADDR_REG_PORT     0x377
+
+
+#define PRI_DMA_CMD_PORT      0xc000
+#define PRI_DMA_STATUS_PORT   0xc002
+#define PRI_DMA_PRD_PORT0     0xc004
+#define PRI_DMA_PRD_PORT1     0xc005
+#define PRI_DMA_PRD_PORT2     0xc006
+#define PRI_DMA_PRD_PORT3     0xc007
+
+#define SEC_DMA_CMD_PORT      0xc008
+#define SEC_DMA_STATUS_PORT   0xc00a
+#define SEC_DMA_PRD_PORT0     0xc00c
+#define SEC_DMA_PRD_PORT1     0xc00d
+#define SEC_DMA_PRD_PORT2     0xc00e
+#define SEC_DMA_PRD_PORT3     0xc00f
+
+#define DATA_BUFFER_SIZE 2048
+
+static const char * ide_pri_port_strs[] = {"PRI_DATA", "PRI_FEATURES", "PRI_SECT_CNT", "PRI_SECT_NUM", 
+                                         "PRI_CYL_LOW", "PRI_CYL_HIGH", "PRI_DRV_SEL", "PRI_CMD",
+                                          "PRI_CTRL", "PRI_ADDR_REG"};
+
+
+static const char * ide_sec_port_strs[] = {"SEC_DATA", "SEC_FEATURES", "SEC_SECT_CNT", "SEC_SECT_NUM", 
+                                         "SEC_CYL_LOW", "SEC_CYL_HIGH", "SEC_DRV_SEL", "SEC_CMD",
+                                          "SEC_CTRL", "SEC_ADDR_REG"};
+
+static const char * ide_dma_port_strs[] = {"PRI_DMA_CMD", NULL,
+                                          "PRI_DMA_STATUS", NULL,
+                                          "PRI_DMA_PRD0", "PRI_DMA_PRD1", 
+                                          "PRI_DMA_PRD2", "PRI_DMA_PRD3",
+                                          "SEC_DMA_CMD", NULL,
+                                          "SEC_DMA_STATUS", NULL,
+                                          "SEC_DMA_PRD0","SEC_DMA_PRD1",
+                                          "SEC_DMA_PRD2","SEC_DMA_PRD3"};
+
+
+
+static inline const char * io_port_to_str(uint16_t port) {
+    if ((port >= PRI_DATA_PORT) && (port <= PRI_CMD_PORT)) {
+       return ide_pri_port_strs[port - PRI_DATA_PORT];
+    } else if ((port >= SEC_DATA_PORT) && (port <= SEC_CMD_PORT)) {
+       return ide_sec_port_strs[port - SEC_DATA_PORT];
+    } else if ((port == PRI_CTRL_PORT) || (port == PRI_ADDR_REG_PORT)) {
+       return ide_pri_port_strs[port - PRI_CTRL_PORT + 8];
+    } else if ((port == SEC_CTRL_PORT) || (port == SEC_ADDR_REG_PORT)) {
+       return ide_sec_port_strs[port - SEC_CTRL_PORT + 8];
+    } else if ((port >= PRI_DMA_CMD_PORT) && (port <= SEC_DMA_PRD_PORT3)) {
+       return ide_dma_port_strs[port - PRI_DMA_CMD_PORT];
+    } 
+    return NULL;
+}
+
+
+
+static const char * ide_dev_type_strs[] = {"HARDDISK", "CDROM", "NONE"};
+
+
+static inline const char * device_type_to_str(v3_ide_dev_type_t type) {
+    if (type > 2) {
+       return NULL;
+    }
+
+    return ide_dev_type_strs[type];
+}
+
+
+
+struct ide_cd_state {
+    struct atapi_sense_data sense;
+    uint_t current_lba;
+    uint8_t atapi_cmd;
+    struct atapi_error_recovery err_recovery;
+};
+
+struct ide_hd_state {
+
+};
+
+struct ide_drive {
+    // Command Registers
+
+    v3_ide_dev_type_t drive_type;
+
+    union {
+       struct v3_ide_cd_ops * cd_ops;
+       struct v3_ide_hd_ops * hd_ops;
+    };
+
+
+    union {
+       struct ide_cd_state cd_state;
+       struct ide_hd_state hd_state;
+    };
+
+    char model[41];
+
+    // Where we are in the data transfer
+    uint_t transfer_index;
+
+    // the length of a transfer
+    // calculated for easy access
+    uint_t transfer_length;
+
+
+    // We have a local data buffer that we use for IO port accesses
+    uint8_t data_buf[DATA_BUFFER_SIZE];
+
+
+    void * private_data;
+    
+    union {
+       uint8_t sector_count;             // 0x1f2,0x172
+       struct atapi_irq_flags irq_flags;
+    } __attribute__((packed));
+
+    union {
+       uint8_t sector_num;               // 0x1f3,0x173
+       uint8_t lba0;
+    };
+
+    union {
+       uint16_t cylinder;
+       uint16_t lba12;
+
+
+       struct {
+           uint8_t cylinder_low;       // 0x1f4,0x174
+           uint8_t cylinder_high;      // 0x1f5,0x175
+       } __attribute__((packed));
+
+       struct {
+           uint8_t lba1;
+           uint8_t lba2;
+       } __attribute__((packed));
+
+
+       // The transfer length requested by the CPU 
+       uint16_t req_len;
+    } __attribute__((packed));
+
+    struct ide_dma_cmd_reg dma_cmd;
+    struct ide_dma_status_reg dma_status;
+    uint32_t dma_prd_addr;
+
+};
+
+
+
+struct ide_channel {
+    struct ide_drive drives[2];
+
+    // Command Registers
+    struct ide_error_reg error_reg;     // [read] 0x1f1,0x171
+
+    struct ide_features_reg features;
+
+    struct ide_drive_head_reg drive_head; // 0x1f6,0x176
+
+    struct ide_status_reg status;       // [read] 0x1f7,0x177
+    uint8_t cmd_reg;                // [write] 0x1f7,0x177
+
+    int irq; // this is temporary until we add PCI support
+
+    struct pci_device * pci_dev;
+
+    // Control Registers
+    struct ide_ctrl_reg ctrl_reg; // [write] 0x3f6,0x376
+};
+
+
+
+struct ide_internal {
+    struct ide_channel channels[2];
+    struct vm_device * pci;
+    struct pci_device * busmaster_pci;
+};
+
+
+
+static inline uint16_t be_to_le_16(const uint16_t val) {
+    uint8_t * buf = (uint8_t *)&val;
+    return (buf[0] << 8) | (buf[1]) ;
+}
+
+static inline uint16_t le_to_be_16(const uint16_t val) {
+    return be_to_le_16(val);
+}
+
+
+static inline uint32_t be_to_le_32(const uint32_t val) {
+    uint8_t * buf = (uint8_t *)&val;
+    return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+static inline uint32_t le_to_be_32(const uint32_t val) {
+    return be_to_le_32(val);
+}
+
+
+static inline int get_channel_index(ushort_t port) {
+    if (((port & 0xfff8) == 0x1f0) ||
+       ((port & 0xfffe) == 0x3f6) || 
+       ((port & 0xfff8) == 0xc000)) {
+       return 0;
+    } else if (((port & 0xfff8) == 0x170) ||
+              ((port & 0xfffe) == 0x376) ||
+              ((port & 0xfff8) == 0xc008)) {
+       return 1;
+    }
+
+    return -1;
+}
+
+static inline struct ide_channel * get_selected_channel(struct ide_internal * ide, ushort_t port) {
+    int channel_idx = get_channel_index(port);    
+    return &(ide->channels[channel_idx]);
+}
+
+static inline struct ide_drive * get_selected_drive(struct ide_channel * channel) {
+    return &(channel->drives[channel->drive_head.drive_sel]);
+}
+
+
+static inline int is_lba_enabled(struct ide_channel * channel) {
+    return channel->drive_head.lba_mode;
+}
+
+
+static void ide_raise_irq(struct vm_device * dev, struct ide_channel * channel) {
+    if (channel->ctrl_reg.irq_disable == 0) {
+       v3_raise_irq(dev->vm, channel->irq);
+    }
+}
+
+
+static void drive_reset(struct ide_drive * drive) {
+    drive->sector_count = 0x01;
+    drive->sector_num = 0x01;
+    
+    if (drive->drive_type == IDE_CDROM) {
+       drive->cylinder = 0xeb14;
+    } else {
+       drive->cylinder = 0x0000;
+    }
+
+
+    memset(drive->data_buf, 0, sizeof(drive->data_buf));
+    drive->transfer_index = 0;
+
+    // Send the reset signal to the connected device callbacks
+    //     channel->drives[0].reset();
+    //    channel->drives[1].reset();
+}
+
+static void channel_reset(struct ide_channel * channel) {
+    
+    // set busy and seek complete flags
+    channel->status.val = 0x90;
+
+    // Clear errors
+    channel->error_reg.val = 0x01;
+
+    // clear commands
+    channel->cmd_reg = 0x00;
+
+    channel->ctrl_reg.irq_disable = 0;
+}
+
+static void channel_reset_complete(struct ide_channel * channel) {
+    channel->status.busy = 0;
+    channel->status.ready = 1;
+
+    channel->drive_head.head_num = 0;    
+    
+    drive_reset(&(channel->drives[0]));
+    drive_reset(&(channel->drives[1]));
+}
+
+
+static void ide_abort_command(struct vm_device * dev, struct ide_channel * channel) {
+    channel->status.val = 0x41; // Error + ready
+    channel->error_reg.val = 0x04; // No idea...
+
+    ide_raise_irq(dev, channel);
+}
+
+
+// Include the ATAPI interface handlers
+#include "atapi.h"
+
+
+static int write_dma_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_channel * channel = get_selected_channel(ide, port);
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    if (length != 1) {
+       PrintError("IDE: Invalid Write length on IDE port %x\n", port);
+       return -1;
+    }
+
+    PrintDebug("IDE: Writing DMA Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
+
+    switch (port) {
+       case PRI_DMA_CMD_PORT:
+       case SEC_DMA_CMD_PORT:
+           drive->dma_cmd.val = *(uint8_t *)src;
+           break;
+
+       case PRI_DMA_STATUS_PORT:
+       case SEC_DMA_STATUS_PORT:
+           drive->dma_status.val = *(uint8_t *)src;
+           break;
+
+       case PRI_DMA_PRD_PORT0:
+       case PRI_DMA_PRD_PORT1:
+       case PRI_DMA_PRD_PORT2:
+       case PRI_DMA_PRD_PORT3:
+       case SEC_DMA_PRD_PORT0:
+       case SEC_DMA_PRD_PORT1:
+       case SEC_DMA_PRD_PORT2:
+       case SEC_DMA_PRD_PORT3: {
+           uint_t addr_index = port & 0x3;
+           uint8_t * addr_buf = (uint8_t *)&(drive->dma_prd_addr);
+
+           addr_buf[addr_index] = *(uint8_t *)src;
+           break;
+       }
+       default:
+           PrintError("IDE: Invalid DMA Port (%x)\n", port);
+           return -1;
+    }
+
+    return length;
+}
+
+
+static int read_dma_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_channel * channel = get_selected_channel(ide, port);
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    if (length != 1) {
+       PrintError("IDE: Invalid Write length on IDE port %x\n", port);
+       return -1;
+    }
+
+
+
+    switch (port) {
+       case PRI_DMA_CMD_PORT:
+       case SEC_DMA_CMD_PORT:
+           *(uint8_t *)dst = drive->dma_cmd.val;
+           break;
+
+       case PRI_DMA_STATUS_PORT:
+       case SEC_DMA_STATUS_PORT:
+           *(uint8_t *)dst = drive->dma_status.val;
+           break;
+
+       case PRI_DMA_PRD_PORT0:
+       case PRI_DMA_PRD_PORT1:
+       case PRI_DMA_PRD_PORT2:
+       case PRI_DMA_PRD_PORT3:
+       case SEC_DMA_PRD_PORT0:
+       case SEC_DMA_PRD_PORT1:
+       case SEC_DMA_PRD_PORT2:
+       case SEC_DMA_PRD_PORT3: {
+           uint_t addr_index = port & 0x3;
+           uint8_t * addr_buf = (uint8_t *)&(drive->dma_prd_addr);
+
+           *(uint8_t *)dst = addr_buf[addr_index];
+           break;
+       }
+       default:
+           PrintError("IDE: Invalid DMA Port (%x)\n", port);
+           return -1;
+    }
+
+    PrintDebug("IDE: Reading DMA Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)dst);
+
+    return length;
+}
+
+
+
+static int write_cmd_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_channel * channel = get_selected_channel(ide, port);
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    if (length != 1) {
+       PrintError("Invalid Write Length on IDE command Port %x\n", port);
+       return -1;
+    }
+
+    PrintDebug("IDE: Writing Command Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
+    
+    channel->cmd_reg = *(uint8_t *)src;
+    
+    switch (channel->cmd_reg) {
+       
+       case 0xa0: // ATAPI Command Packet
+           if (drive->drive_type != IDE_CDROM) {
+               ide_abort_command(dev, channel);
+           }
+           
+           drive->sector_count = 1;
+
+           channel->status.busy = 0;
+           channel->status.write_fault = 0;
+           channel->status.data_req = 1;
+           channel->status.error = 0;
+
+           // reset the data buffer...
+           drive->transfer_length = ATAPI_PACKET_SIZE;
+           drive->transfer_index = 0;
+
+           break;
+       case 0xa1: // ATAPI Identify Device Packet
+           atapi_identify_device(drive);
+
+           channel->error_reg.val = 0;
+           channel->status.val = 0x58; // ready, data_req, seek_complete
+           
+           ide_raise_irq(dev, channel);
+           break;
+       case 0xec: // Identify Device
+           if (drive->drive_type != IDE_DISK) {
+               drive_reset(drive);
+
+               // JRL: Should we abort here?
+               ide_abort_command(dev, channel);
+           } else {
+               PrintError("IDE Disks currently not implemented\n");
+               return -1;
+           }
+           break;
+       default:
+           PrintError("Unimplemented IDE command (%x)\n", channel->cmd_reg);
+           return -1;
+    }
+
+    return length;
+}
+
+
+static int write_data_port(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_channel * channel = get_selected_channel(ide, port);
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    //    PrintDebug("IDE: Writing Data Port %x (val=%x, len=%d)\n", 
+    //        port, *(uint32_t *)src, length);
+    
+    memcpy(drive->data_buf + drive->transfer_index, src, length);    
+    drive->transfer_index += length;
+
+    // Transfer is complete, dispatch the command
+    if (drive->transfer_index >= drive->transfer_length) {
+       switch (channel->cmd_reg) {
+           case 0x30: // Write Sectors
+               PrintError("Writing Data not yet implemented\n");
+               return -1;
+               
+           case 0xa0: // ATAPI packet command
+               if (atapi_handle_packet(dev, channel) == -1) {
+                   PrintError("Error handling ATAPI packet\n");
+                   return -1;
+               }
+               break;
+           default:
+               PrintError("Unhandld IDE Command %x\n", channel->cmd_reg);
+               return -1;
+       }
+    }
+
+    return length;
+}
+
+
+static int read_hd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
+    PrintError("Harddrive data port read not implemented\n");
+    return -1;
+}
+
+
+
+static int read_cd_data(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+    int data_offset = drive->transfer_index % DATA_BUFFER_SIZE;
+    int req_offset = drive->transfer_index % drive->req_len;
+    
+    if (drive->cd_state.atapi_cmd != 0x28) {
+        PrintDebug("IDE: Reading CD Data (len=%d) (req_len=%d)\n", length, drive->req_len);
+    }
+
+    if (drive->transfer_index >= drive->transfer_length) {
+       PrintError("Buffer Overrun... (xfer_len=%d) (cur_idx=%d) (post_idx=%d)\n", 
+                  drive->transfer_length, drive->transfer_index, 
+                  drive->transfer_index + length);
+       return -1;
+    }
+
+
+
+    if ((data_offset == 0) && (drive->transfer_index > 0)) {
+       
+       if (drive->drive_type == IDE_CDROM) {
+           if (atapi_update_data_buf(dev, channel) == -1) {
+               PrintError("Could not update CDROM data buffer\n");
+               return -1;
+           } 
+       } else {
+           PrintError("IDE Harddrives not implemented\n");
+           return -1;
+       }
+    }
+
+    memcpy(dst, drive->data_buf + data_offset, length);
+    
+    drive->transfer_index += length;
+
+    if ((req_offset == 0) && (drive->transfer_index > 0)) {
+       if (drive->transfer_index < drive->transfer_length) {
+           // An increment is complete, but there is still more data to be transferred...
+           
+           channel->status.data_req = 1;
+
+           drive->irq_flags.c_d = 0;
+
+           // Update the request length in the cylinder regs
+           if (atapi_update_req_len(dev, channel, drive->transfer_length - drive->transfer_index) == -1) {
+               PrintError("Could not update request length after completed increment\n");
+               return -1;
+           }
+       } else {
+           // This was the final read of the request
+           channel->status.data_req = 0;
+           channel->status.ready = 1;
+           
+           drive->irq_flags.c_d = 1;
+           drive->irq_flags.rel = 0;
+       }
+
+       drive->irq_flags.io_dir = 1;
+       channel->status.busy = 0;
+
+       ide_raise_irq(dev, channel);
+    }
+
+    return length;
+}
+
+
+static int read_drive_id(uint8_t * dst, uint_t length, struct vm_device * dev, struct ide_channel * channel) {
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    channel->status.busy = 0;
+    channel->status.ready = 1;
+    channel->status.write_fault = 0;
+    channel->status.seek_complete = 1;
+    channel->status.corrected = 0;
+    channel->status.error = 0;
+               
+    
+    memcpy(dst, drive->data_buf + drive->transfer_index, length);
+    drive->transfer_index += length;
+    
+    if (drive->transfer_index >= drive->transfer_length) {
+       channel->status.data_req = 0;
+    }
+    
+    return length;
+}
+
+
+static int ide_read_data_port(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_channel * channel = get_selected_channel(ide, port);
+    struct ide_drive * drive = get_selected_drive(channel);
+
+    //    PrintDebug("IDE: Reading Data Port %x (len=%d)\n", port, length);
+
+    if ((channel->cmd_reg == 0xec) ||
+       (channel->cmd_reg == 0xa1)) {
+       return read_drive_id((uint8_t *)dst, length, dev, channel);
+    }
+
+    if (drive->drive_type == IDE_CDROM) {
+       if (read_cd_data((uint8_t *)dst, length, dev, channel) == -1) {
+           PrintError("IDE: Could not read CD Data\n");
+           return -1;
+       }
+    } else if (drive->drive_type == IDE_DISK) {
+       if (read_hd_data((uint8_t *)dst, length, dev, channel) == -1) {
+           PrintError("IDE: Could not read HD Data\n");
+           return -1;
+       }
+    } else {
+       memset((uint8_t *)dst, 0, length);
+    }
+
+    return length;
+}
+
+static int write_port_std(ushort_t port, void * src, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_channel * channel = get_selected_channel(ide, port);
+    struct ide_drive * drive = get_selected_drive(channel);
+           
+    if (length != 1) {
+       PrintError("Invalid Write length on IDE port %x\n", port);
+       return -1;
+    }
+
+    PrintDebug("IDE: Writing Standard Port %x (%s) (val=%x)\n", port, io_port_to_str(port), *(uint8_t *)src);
+
+
+    switch (port) {
+       // reset and interrupt enable
+       case PRI_CTRL_PORT:
+       case SEC_CTRL_PORT: {
+           struct ide_ctrl_reg * tmp_ctrl = (struct ide_ctrl_reg *)src;
+
+           // only reset channel on a 0->1 reset bit transition
+           if ((!channel->ctrl_reg.soft_reset) && (tmp_ctrl->soft_reset)) {
+               channel_reset(channel);
+           } else if ((channel->ctrl_reg.soft_reset) && (!tmp_ctrl->soft_reset)) {
+               channel_reset_complete(channel);
+           }
+
+           channel->ctrl_reg.val = tmp_ctrl->val;          
+           break;
+       }
+       case PRI_FEATURES_PORT:
+       case SEC_FEATURES_PORT:
+           channel->features.val = *(uint8_t *)src;
+           break;
+
+       case PRI_SECT_CNT_PORT:
+       case SEC_SECT_CNT_PORT:
+           drive->sector_count = *(uint8_t *)src;
+           break;
+
+       case PRI_SECT_NUM_PORT:
+       case SEC_SECT_NUM_PORT:
+           drive->sector_num = *(uint8_t *)src;
+
+       case PRI_CYL_LOW_PORT:
+       case SEC_CYL_LOW_PORT:
+           drive->cylinder_low = *(uint8_t *)src;
+           break;
+
+       case PRI_CYL_HIGH_PORT:
+       case SEC_CYL_HIGH_PORT:
+           drive->cylinder_high = *(uint8_t *)src;
+           break;
+
+       case PRI_DRV_SEL_PORT:
+       case SEC_DRV_SEL_PORT: {
+           channel->drive_head.val = *(uint8_t *)src;
+           
+           // make sure the reserved bits are ok..
+           // JRL TODO: check with new ramdisk to make sure this is right...
+           channel->drive_head.val |= 0xa0;
+
+           drive = get_selected_drive(channel);
+
+           // Selecting a non-present device is a no-no
+           if (drive->drive_type == IDE_NONE) {
+               PrintDebug("Attempting to select a non-present drive\n");
+               channel->error_reg.abort = 1;
+               channel->status.error = 1;
+           }
+
+           break;
+       }
+       default:
+           PrintError("IDE: Write to unknown Port %x\n", port);
+           return -1;
+    }
+    return length;
+}
+
+
+static int read_port_std(ushort_t port, void * dst, uint_t length, struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct ide_channel * channel = get_selected_channel(ide, port);
+    struct ide_drive * drive = get_selected_drive(channel);
+    
+    if (length != 1) {
+       PrintError("Invalid Read length on IDE port %x\n", port);
+       return -1;
+    }
+
+    PrintDebug("IDE: Reading Standard Port %x (%s)\n", port, io_port_to_str(port));
+
+
+    if ((port == PRI_ADDR_REG_PORT) ||
+       (port == SEC_ADDR_REG_PORT)) {
+       // unused, return 0xff
+       *(uint8_t *)dst = 0xff;
+       return length;
+    }
+
+
+    // if no drive is present just return 0 + reserved bits
+    if (drive->drive_type == IDE_NONE) {
+       if ((port == PRI_DRV_SEL_PORT) ||
+           (port == SEC_DRV_SEL_PORT)) {
+           *(uint8_t *)dst = 0xa0;
+       } else {
+           *(uint8_t *)dst = 0;
+       }
+
+       return length;
+    }
+
+    switch (port) {
+
+       // This is really the error register.
+       case PRI_FEATURES_PORT:
+       case SEC_FEATURES_PORT:
+           *(uint8_t *)dst = channel->error_reg.val;
+           break;
+           
+       case PRI_SECT_CNT_PORT:
+       case SEC_SECT_CNT_PORT:
+           *(uint8_t *)dst = drive->sector_count;
+           break;
+
+       case PRI_SECT_NUM_PORT:
+       case SEC_SECT_NUM_PORT:
+           *(uint8_t *)dst = drive->sector_num;
+           break;
+
+       case PRI_CYL_LOW_PORT:
+       case SEC_CYL_LOW_PORT:
+           *(uint8_t *)dst = drive->cylinder_low;
+           break;
+
+
+       case PRI_CYL_HIGH_PORT:
+       case SEC_CYL_HIGH_PORT:
+           *(uint8_t *)dst = drive->cylinder_high;
+           break;
+
+       case PRI_DRV_SEL_PORT:
+       case SEC_DRV_SEL_PORT:  // hard disk drive and head register 0x1f6
+           *(uint8_t *)dst = channel->drive_head.val;
+           break;
+
+       case PRI_CTRL_PORT:
+       case SEC_CTRL_PORT:
+       case PRI_CMD_PORT:
+       case SEC_CMD_PORT:
+           // Something about lowering interrupts here....
+           *(uint8_t *)dst = channel->status.val;
+           break;
+
+       default:
+           PrintError("Invalid Port: %x\n", port);
+           return -1;
+    }
+
+    PrintDebug("\tVal=%x\n", *(uint8_t *)dst);
+
+    return length;
+}
+
+
+
+static void init_drive(struct ide_drive * drive) {
+
+    drive->sector_count = 0x01;
+    drive->sector_num = 0x01;
+    drive->cylinder = 0x0000;
+
+    drive->drive_type = IDE_NONE;
+
+    memset(drive->model, 0, sizeof(drive->model));
+
+    drive->transfer_index = 0;
+    drive->transfer_length = 0;
+    memset(drive->data_buf, 0, sizeof(drive->data_buf));
+
+    drive->dma_cmd.val = 0;
+    drive->dma_status.val = 0;
+    drive->dma_prd_addr = 0;
+
+    drive->private_data = NULL;
+    drive->cd_ops = NULL;
+}
+
+static void init_channel(struct ide_channel * channel) {
+    int i = 0;
+
+    channel->error_reg.val = 0x01;
+    channel->drive_head.val = 0x00;
+    channel->status.val = 0x00;
+    channel->cmd_reg = 0x00;
+    channel->ctrl_reg.val = 0x08;
+
+
+    for (i = 0; i < 2; i++) {
+       init_drive(&(channel->drives[i]));
+    }
+
+}
+
+/*
+static int pci_config_update(struct pci_device * pci_dev, uint_t reg_num, int length) {
+    PrintError("IDE does not handle PCI config updates\n");
+    return -1;
+}
+*/
+
+static int init_ide_state(struct vm_device * dev) {
+    struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+    struct v3_pci_bar bars[6];
+    struct pci_device * pci_dev = NULL;
+    int i, j;
+
+    for (i = 0; i < 2; i++) {
+       init_channel(&(ide->channels[i]));
+
+       // JRL: this is a terrible hack...
+       ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
+
+       for (j = 0; j < 6; j++) {
+           bars[j].type = PCI_BAR_NONE;
+       }
+
+
+       bars[4].type = PCI_BAR_IO;
+       bars[4].default_base_port = PRI_DMA_CMD_PORT + (i * 0x8);
+       bars[4].num_ports = 8;
+       bars[4].io_read = read_dma_port;
+       bars[4].io_write = write_dma_port;
+
+       pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
+                                        NULL, NULL, NULL, dev);
+
+       if (pci_dev == NULL) {
+           PrintError("Failed to register IDE BUS %d with PCI\n", i); 
+           return -1;
+       }
+
+       ide->channels[i].pci_dev = pci_dev;
+
+       pci_dev->config_header.vendor_id = 0x1095;
+       pci_dev->config_header.device_id = 0x0646;
+       pci_dev->config_header.revision = 0x8f07;
+       pci_dev->config_header.subclass = 0x01;
+       pci_dev->config_header.class = 0x01;
+    }
+
+
+
+    /* Register PIIX3 Busmaster PCI device */
+    for (j = 0; j < 6; j++) {
+       bars[j].type = PCI_BAR_NONE;
+    }
+
+    pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "PIIX3 IDE", -1, bars,
+                                    NULL, NULL, NULL, dev);
+    
+    
+    ide->busmaster_pci = pci_dev;
+
+    pci_dev->config_header.vendor_id = 0x8086;
+    pci_dev->config_header.device_id = 0x7010;
+    pci_dev->config_header.revision = 0x80;
+    pci_dev->config_header.subclass = 0x01;
+    pci_dev->config_header.class = 0x01;
+
+
+    return 0;
+}
+
+
+
+static int init_ide(struct vm_device * dev) {
+    //struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
+
+    PrintDebug("IDE: Initializing IDE\n");
+
+    if (init_ide_state(dev) == -1) {
+       PrintError("Failed to initialize IDE state\n");
+       return -1;
+    }
+
+
+
+
+    v3_dev_hook_io(dev, PRI_DATA_PORT, 
+                  &ide_read_data_port, &write_data_port);
+    v3_dev_hook_io(dev, PRI_FEATURES_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, PRI_SECT_CNT_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, PRI_SECT_NUM_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, PRI_CYL_LOW_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, PRI_CYL_HIGH_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, PRI_DRV_SEL_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, PRI_CMD_PORT, 
+                  &read_port_std, &write_cmd_port);
+
+    v3_dev_hook_io(dev, SEC_DATA_PORT, 
+                  &ide_read_data_port, &write_data_port);
+    v3_dev_hook_io(dev, SEC_FEATURES_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, SEC_SECT_CNT_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, SEC_SECT_NUM_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, SEC_CYL_LOW_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, SEC_CYL_HIGH_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, SEC_DRV_SEL_PORT, 
+                  &read_port_std, &write_port_std);
+    v3_dev_hook_io(dev, SEC_CMD_PORT, 
+                  &read_port_std, &write_cmd_port);
+  
+
+    v3_dev_hook_io(dev, PRI_CTRL_PORT, 
+                  &read_port_std, &write_port_std);
+
+    v3_dev_hook_io(dev, SEC_CTRL_PORT, 
+                  &read_port_std, &write_port_std);
+  
+
+    v3_dev_hook_io(dev, SEC_ADDR_REG_PORT, 
+                  &read_port_std, &write_port_std);
+
+    v3_dev_hook_io(dev, PRI_ADDR_REG_PORT, 
+                  &read_port_std, &write_port_std);
+
+
+    /*
+
+    v3_dev_hook_io(dev, PRI_DMA_CMD_PORT, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, PRI_DMA_STATUS_PORT, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, PRI_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+
+
+    v3_dev_hook_io(dev, SEC_DMA_CMD_PORT, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, SEC_DMA_STATUS_PORT, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+    v3_dev_hook_io(dev, SEC_DMA_PRD_PORT0, 
+                  &read_dma_port, &write_dma_port);
+    */
+    return 0;
+}
+
+
+static int deinit_ide(struct vm_device * dev) {
+    // unhook io ports....
+    // deregister from PCI?
+    return 0;
+}
+
+
+static struct vm_device_ops dev_ops = {
+    .init = init_ide,
+    .deinit = deinit_ide,
+    .reset = NULL,
+    .start = NULL,
+    .stop = NULL,
+};
+
+
+struct vm_device *  v3_create_ide(struct vm_device * pci) {
+    struct ide_internal * ide  = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));  
+    struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
+
+    ide->pci = pci;
+
+    PrintDebug("IDE: Creating IDE bus x 2\n");
+
+    return device;
+}
+
+
+
+
+
+int v3_ide_register_cdrom(struct vm_device * ide_dev, 
+                         uint_t bus_num, 
+                         uint_t drive_num,
+                         char * dev_name, 
+                         struct v3_ide_cd_ops * ops, 
+                         void * private_data) {
+
+    struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
+    struct ide_channel * channel = NULL;
+    struct ide_drive * drive = NULL;
+
+    V3_ASSERT((bus_num >= 0) && (bus_num < 2));
+    V3_ASSERT((drive_num >= 0) && (drive_num < 2));
+
+    channel = &(ide->channels[bus_num]);
+    drive = &(channel->drives[drive_num]);
+    
+    if (drive->drive_type != IDE_NONE) {
+       PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
+       return -1;
+    }
+
+    strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
+
+    while (strlen((char *)(drive->model)) < 40) {
+       strcat((char*)(drive->model), " ");
+    }
+
+
+    drive->drive_type = IDE_CDROM;
+
+    drive->cd_ops = ops;
+
+    drive->private_data = private_data;
+
+    return 0;
+}
+
+
+int v3_ide_register_harddisk(struct vm_device * ide_dev, 
+                            uint_t bus_num, 
+                            uint_t drive_num, 
+                            char * dev_name, 
+                            struct v3_ide_hd_ops * ops, 
+                            void * private_data) {
+
+    struct ide_internal * ide  = (struct ide_internal *)(ide_dev->private_data);  
+    struct ide_channel * channel = NULL;
+    struct ide_drive * drive = NULL;
+
+    V3_ASSERT((bus_num >= 0) && (bus_num < 2));
+    V3_ASSERT((drive_num >= 0) && (drive_num < 2));
+
+    channel = &(ide->channels[bus_num]);
+    drive = &(channel->drives[drive_num]);
+    
+    if (drive->drive_type != IDE_NONE) {
+       PrintError("Device slot (bus=%d, drive=%d) already occupied\n", bus_num, drive_num);
+       return -1;
+    }
+
+    strncpy(drive->model, dev_name, sizeof(drive->model) - 1);
+
+    drive->drive_type = IDE_DISK;
+
+    drive->hd_ops = ops;
+
+    drive->private_data = private_data;
+
+    return 0;
+}
index 1cad975..a0e9e4e 100644 (file)
@@ -216,7 +216,7 @@ static int addr_port_read(ushort_t port, void * dst, uint_t length, struct vm_de
     int reg_offset = port & 0x3;
     uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset;
 
-    PrintDebug("Reading PCI Address Port (%x): %x\n", port, pci_state->addr_reg.val);
+    PrintDebug("Reading PCI Address Port (%x): %x len=%d\n", port, pci_state->addr_reg.val, length);
 
     if (length == 4) {
        if (reg_offset != 0) {
@@ -276,38 +276,47 @@ static int addr_port_write(ushort_t port, void * src, uint_t length, struct vm_d
 
     PrintDebug("Writing PCI Address Port(%x): %x\n", port, pci_state->addr_reg.val);
 
-
     return length;
 }
 
 
 static int data_port_read(ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) {
-    struct pci_internal * pci_state =  (struct pci_internal *)vmdev->private_data;;
+    struct pci_internal * pci_state =  (struct pci_internal *)(vmdev->private_data);
     struct pci_device * pci_dev = NULL;
     uint_t reg_num = pci_state->addr_reg.reg_num + (port & 0x3);
     int i;
 
+    if (pci_state->addr_reg.bus_num != 0) {
+       int i = 0;
+       for (i = 0; i < length; i++) {
+           *(uint8_t *)dst = 0xff;
+       }
+
+       return length;
+    }
+
     PrintDebug("Reading PCI Data register. bus = %d, dev = %d, reg = %d (%x), cfg_reg = %x\n", 
               pci_state->addr_reg.bus_num, 
               pci_state->addr_reg.dev_num, 
               reg_num, reg_num, 
               pci_state->addr_reg.val);
 
-
     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
     
     if (pci_dev == NULL) {
        for (i = 0; i < length; i++) {
-           *((uint8_t *)dst + i) = 0xff;
+           *(uint8_t *)((uint8_t *)dst + i) = 0xff;
        }
 
        return length;
     }
 
     for (i = 0; i < length; i++) {
-       *((uint8_t *)dst + i) = pci_dev->config_space[reg_num + i];
+       *(uint8_t *)((uint8_t *)dst + i) = pci_dev->config_space[reg_num + i];
     }
-    
+
+    PrintDebug("\tVal=%x, len=%d\n", *(uint32_t *)dst, length);
+
     return length;
 }
 
@@ -343,17 +352,29 @@ static inline int is_cfg_reg_writable(uchar_t header_type, int reg_num) {
 }
 
 
+static int bar_update(struct pci_device * pci, int bar_num) {
+    PrintError("Bar Updates not handled (bar=%d)\n", bar_num);
+    return -1;
+}
+
+
 static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_device * vmdev) {
     struct pci_internal * pci_state = (struct pci_internal *)vmdev->private_data;
     struct pci_device * pci_dev = NULL;
     uint_t reg_num = pci_state->addr_reg.reg_num + (port & 0x3);
     int i;
 
-    PrintDebug("Writing PCI Data register. bus = %d, dev = %d, reg = %d (%x) addr_reg = %x\n", 
+
+    if (pci_state->addr_reg.bus_num != 0) {
+       return length;
+    }
+
+    PrintDebug("Writing PCI Data register. bus = %d, dev = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", 
               pci_state->addr_reg.bus_num, 
               pci_state->addr_reg.dev_num, 
               reg_num, reg_num, 
-              pci_state->addr_reg.val);
+              pci_state->addr_reg.val,
+              *(uint32_t *)src, length);
 
 
     pci_dev = get_device(&(pci_state->bus_list[0]), pci_state->addr_reg.dev_num);
@@ -369,29 +390,29 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
        uint_t cur_reg = reg_num + i;
        
        if (is_cfg_reg_writable(pci_dev->config_header.header_type, cur_reg)) {
-           pci_dev->config_space[cur_reg] = *((uint8_t *)src + i);
+           pci_dev->config_space[cur_reg] = *(uint8_t *)((uint8_t *)src + i);
 
            if ((cur_reg >= 0x10) && (cur_reg < 0x28)) {
                // BAR Reg
                int bar_reg = (cur_reg & ~0x3) - 0x10;
+               
+               pci_dev->bar_update_flag = 1;
+               pci_dev->bar[bar_reg].updated = 1;
+               
+               PrintDebug("Updating BAR register\n");
 
-               if (pci_dev->bar[bar_reg].bar_update) {
-                   pci_dev->bar_update_flag = 1;               
-                   pci_dev->bar[bar_reg].updated = 1;
-               }
            } else if ((cur_reg >= 0x30) && (cur_reg < 0x34)) {
                pci_dev->ext_rom_update_flag = 1;
            } else if (cur_reg == 0x04) {
-             // COMMAND update      
-             uint8_t command = *((uint8_t *)src + i);
-
-             pci_dev->config_space[cur_reg] = command;       
-
-             if (pci_dev->cmd_update) {
-               pci_dev->cmd_update(pci_dev, (command & 0x01), (command & 0x02));
-             }
-            
-
+               // COMMAND update            
+               uint8_t command = *((uint8_t *)src + i);
+               
+               pci_dev->config_space[cur_reg] = command;             
+               
+               if (pci_dev->cmd_update) {
+                   pci_dev->cmd_update(pci_dev, (command & 0x01), (command & 0x02));
+               }
+               
            } else if (cur_reg == 0x0f) {
                // BIST update
                pci_dev->config_header.BIST = 0x00;
@@ -411,9 +432,12 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d
 
                *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask;
 
-               if (pci_dev->bar[i].bar_update) {
-                   pci_dev->bar[i].bar_update(pci_dev, i);
+               // bar_update
+               if (bar_update(pci_dev, i) == -1) {
+                   PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i);
+                   return -1;
                }
+
                pci_dev->bar[i].updated = 0;
            }
        }
@@ -471,9 +495,6 @@ static int init_i440fx(struct vm_device * dev) {
     
     for (i = 0; i < 6; i++) {
        bars[i].type = PCI_BAR_NONE;
-       bars[i].mem_hook = 0;
-       bars[i].num_pages = 0;
-       bars[i].bar_update = NULL;
     }    
 
     pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "i440FX", 0, bars,
@@ -495,43 +516,6 @@ static int init_i440fx(struct vm_device * dev) {
 
 
 
-static void test_devices(struct vm_device * dev) {
-    struct pci_device * pci_dev = NULL;
-    struct v3_pci_bar bars[6];
-    int i;
-    
-    for (i = 0; i < 6; i++) {
-       bars[i].type = PCI_BAR_NONE;
-       bars[i].mem_hook = 0;
-       bars[i].num_pages = 0;
-       bars[i].bar_update = NULL;
-    }    
-
-
-    pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "", 0, bars,
-                                    NULL, NULL, NULL, NULL);
-    
-    pci_dev->config_header.vendor_id = 0x8086;
-    pci_dev->config_header.device_id = 0x0101;
-    pci_dev->config_header.revision = 0x0002;
-    pci_dev->config_header.subclass = 0x01; //  SubClass: host2pci
-    pci_dev->config_header.class = 0x01;    // Class: PCI bridge
-
-    pci_dev = v3_pci_register_device(dev, PCI_STD_DEVICE, 0, "", 0, bars,
-                                    NULL, NULL, NULL, NULL);
-    
-    pci_dev->config_header.vendor_id = 0x8086;
-    pci_dev->config_header.device_id = 0x0101;
-    pci_dev->config_header.revision = 0x0002;
-    pci_dev->config_header.subclass = 0x00; //  SubClass: host2pci
-    pci_dev->config_header.class = 0x02;    // Class: PCI bridge
-    
-
-
-
-}
-
-
 
 static void init_pci_busses(struct pci_internal * pci_state) {
     int i;
@@ -562,8 +546,6 @@ static int pci_init_device(struct vm_device * dev) {
        PrintError("Could not intialize i440fx\n");
        return -1;
     }
-
-    test_devices(dev);
     
     PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header));
     
@@ -601,38 +583,65 @@ static inline int init_bars(struct pci_device * pci_dev) {
     int i = 0;
 
     for (i = 0; i < 6; i++) {
-       int bar_offset = 0x10 + 4 * i;
+       int bar_offset = 0x10 + (4 * i);
 
        if (pci_dev->bar[i].type == PCI_BAR_IO) {
-           pci_dev->bar[i].mask = 0x0000fffd;
-           *(uint32_t *)(pci_dev->config_space + bar_offset) = 0x00000001;
+           int j = 0;
+           pci_dev->bar[i].mask = (~((pci_dev->bar[i].num_ports) - 1)) | 0x01;
+           
+           *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].default_base_port & pci_dev->bar[i].mask;
+           *(uint32_t *)(pci_dev->config_space + bar_offset) |= 0x00000001;
+
+           for (j = 0; j < pci_dev->bar[i].num_ports; j++) {
+               // hook IO
+               if (v3_dev_hook_io(pci_dev->vm_dev, pci_dev->bar[i].default_base_port + j,
+                                  pci_dev->bar[i].io_read, pci_dev->bar[i].io_write) == -1) {
+                   PrintError("Could not hook default io port %x\n", pci_dev->bar[i].default_base_port + j);
+                   return -1;
+               }
+           }
+
        } else if (pci_dev->bar[i].type == PCI_BAR_MEM32) {
            pci_dev->bar[i].mask = ~((pci_dev->bar[i].num_pages << 12) - 1);
            pci_dev->bar[i].mask |= 0xf; // preserve the configuration flags
-            
-           *(uint32_t *)(pci_dev->config_space + bar_offset) = 0x00000008;
-           
-           if (pci_dev->bar[i].mem_hook) {
-               // clear the prefetchable flag...
-               *(uint8_t *)(pci_dev->config_space + bar_offset) &= ~0x00000008;
+
+           *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].default_base_addr & pci_dev->bar[i].mask;
+
+           // hook memory
+           if (pci_dev->bar[i].mem_read) {
+               // full hook
+               v3_hook_full_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr,
+                                pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
+                                pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->vm_dev);
+           } else if (pci_dev->bar[i].mem_write) {
+               // write hook
+               PrintError("Write hooks not supported for PCI devices\n");
+               return -1;
+               /*
+                 v3_hook_write_mem(pci_dev->vm_dev->vm, pci_dev->bar[i].default_base_addr, 
+                 pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB),
+                 pci_dev->bar[i].mem_write, pci_dev->vm_dev);
+               */
+           } else {
+               // set the prefetchable flag...
+               *(uint8_t *)(pci_dev->config_space + bar_offset) |= 0x00000008;
            }
+
        } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) {
            PrintError("16 Bit memory ranges not supported (reg: %d)\n", i);
+           return -1;
        } else if (pci_dev->bar[i].type == PCI_BAR_NONE) {
            *(uint32_t *)(pci_dev->config_space + bar_offset) = 0x00000000;
        } else {
            PrintError("Invalid BAR type for bar #%d\n", i);
            return -1;
        }
-           
-
     }
 
     return 0;
 }
 
 
-
 // if dev_num == -1, auto assign 
 struct pci_device * v3_pci_register_device(struct vm_device * pci,
                                           pci_device_type_t dev_type, 
@@ -700,13 +709,22 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
 
     pci_dev->priv_data = private_data;
 
-    
+
     //copy bars
     for (i = 0; i < 6; i ++){
-      pci_dev->bar[i].type = bars[i].type;
-      pci_dev->bar[i].num_pages = bars[i].num_pages;
-      pci_dev->bar[i].mem_hook = bars[i].mem_hook;
-      pci_dev->bar[i].bar_update = bars[i].bar_update;
+       pci_dev->bar[i].type = bars[i].type;
+
+       if (pci_dev->bar[i].type == PCI_BAR_IO) {
+           pci_dev->bar[i].num_ports = bars[i].num_ports;
+           pci_dev->bar[i].default_base_port = bars[i].default_base_port;
+           pci_dev->bar[i].io_read = bars[i].io_read;
+           pci_dev->bar[i].io_write = bars[i].io_write;
+       } else {
+           pci_dev->bar[i].num_pages = bars[i].num_pages;
+           pci_dev->bar[i].default_base_addr = bars[i].default_base_addr;
+           pci_dev->bar[i].mem_read = bars[i].mem_read;
+           pci_dev->bar[i].mem_write = bars[i].mem_write;
+       }
     }
 
     if (init_bars(pci_dev) == -1) {
@@ -714,13 +732,9 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci,
        return NULL;
     }
 
-    pci_dev->cmd_update = cmd_update;
-    pci_dev->ext_rom_update = ext_rom_update;
-
     // add the device
     add_device_to_bus(bus, pci_dev);
 
-    
 #ifdef DEBUG_PCI
     pci_dump_state(pci_state);
 #endif
index 6c18c31..04602f7 100644 (file)
@@ -498,15 +498,13 @@ static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_de
        case 0xec:    // IDENTIFY DEVICE
        case 0xa1:
            {
-
-
                controller->status.busy = 0;
                controller->status.drive_ready = 1;
                controller->status.write_fault = 0;
                controller->status.seek_complete = 1;
                controller->status.corrected_data = 0;
                controller->status.err = 0;
-      
+               
                /*
                  value32 = controller->buffer[index];
                  index++;
@@ -531,7 +529,7 @@ static int read_data_port(ushort_t port, void * dst, uint_t length, struct vm_de
                if (controller->buffer_index >= 512) {
                    controller->status.drq = 0;
                }
-      
+               
                return length;
            }
        case 0xa0: //send packet cmd 
@@ -2239,14 +2237,6 @@ void rd_identify_ATAPI_drive(struct vm_device * dev, struct channel_t * channel)
        drive->id_drive[i] = 0;
     }
 
-    // now convert the id_drive array (native 256 word format) to
-    // the controller buffer (512 bytes)
-    Bit16u temp16;
-    for (i = 0; i <= 255; i++) {
-       temp16 = drive->id_drive[i];
-       controller->buffer[i * 2] = temp16 & 0x00ff;
-       controller->buffer[i * 2 + 1] = temp16 >> 8;
-    }
 
     return;
 }
index c0c713e..be73f33 100644 (file)
@@ -33,8 +33,8 @@
 #include <devices/8254.h>
 #include <devices/nvram.h>
 #include <devices/generic.h>
-#include <devices/ramdisk.h>
-#include <devices/cdrom.h>
+#include <devices/ide.h>
+#include <devices/ram_cd.h>
 #include <devices/bochs_debug.h>
 #include <devices/os_debug.h>
 #include <devices/apic.h>
@@ -279,11 +279,9 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
 
 
 static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
-    struct vm_device * ramdisk = NULL;
-    struct vm_device * cdrom = NULL;
-#ifdef DEBUG_PCI
+    struct vm_device * ide = NULL;
+    struct vm_device * ram_cd = NULL;
     struct vm_device * pci = v3_create_pci();
-#endif
     struct vm_device * nvram = v3_create_nvram();
     //struct vm_device * timer = v3_create_timer();
     struct vm_device * pic = v3_create_pic();
@@ -301,11 +299,13 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
     int use_ramdisk = config_ptr->use_ramdisk;
     int use_generic = USE_GENERIC;
 
+    ide = v3_create_ide(pci);
 
     if (use_ramdisk) {
        PrintDebug("Creating Ramdisk\n");
-       ramdisk = v3_create_ramdisk();
-       cdrom = v3_create_cdrom(ramdisk, config_ptr->ramdisk, config_ptr->ramdisk_size);
+       ram_cd = v3_create_ram_cd(ide, 0, 0, 
+                                 (addr_t)(config_ptr->ramdisk), 
+                                 config_ptr->ramdisk_size);
     }
     
     
@@ -313,9 +313,8 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
        generic = configure_generic(info, config_ptr);
     }
 
-#ifdef DEBUG_PCI
+
     v3_attach_device(info, pci);
-#endif
 
     v3_attach_device(info, nvram);
     //v3_attach_device(info, timer);
@@ -331,9 +330,10 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_
 
     v3_attach_device(info, para_net);
 
+    v3_attach_device(info, ide);
+
     if (use_ramdisk) {
-       v3_attach_device(info, ramdisk);
-       v3_attach_device(info, cdrom);
+       v3_attach_device(info, ram_cd);
     }
 
     if (use_generic) {