From: Jack Lange Date: Tue, 31 Mar 2009 20:42:42 +0000 (-0500) Subject: Merge branch 'devel' into ide X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=ee177da9b30ebf340c63fb5b9d535c729f90134d;hp=4b8b4ad83c037fa685a3bb8f3a681cf0b617ae9c Merge branch 'devel' into ide Conflicts: misc/test_vm/build/Makefile palacios/build/Makefile --- diff --git a/misc/test_vm/build/Makefile b/misc/test_vm/build/Makefile index 62c901d..c38b9f4 100644 --- a/misc/test_vm/build/Makefile +++ b/misc/test_vm/build/Makefile @@ -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 diff --git a/misc/test_vm/build/depend.mak b/misc/test_vm/build/depend.mak index e69de29..052def9 100644 --- a/misc/test_vm/build/depend.mak +++ b/misc/test_vm/build/depend.mak @@ -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 diff --git a/misc/test_vm/include/geekos/io.h b/misc/test_vm/include/geekos/io.h index bd23614..230300b 100644 --- a/misc/test_vm/include/geekos/io.h +++ b/misc/test_vm/include/geekos/io.h @@ -1,7 +1,7 @@ /* * x86 port IO routines * Copyright (c) 2001, David H. Hovemeyer - * $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 */ diff --git a/misc/test_vm/include/geekos/paging.h b/misc/test_vm/include/geekos/paging.h index 11b7531..72e9c73 100644 --- a/misc/test_vm/include/geekos/paging.h +++ b/misc/test_vm/include/geekos/paging.h @@ -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); diff --git a/misc/test_vm/include/geekos/screen.h b/misc/test_vm/include/geekos/screen.h index 241fc6f..8bd39a5 100644 --- a/misc/test_vm/include/geekos/screen.h +++ b/misc/test_vm/include/geekos/screen.h @@ -11,6 +11,7 @@ #define GEEKOS_SCREEN_H #include +#include #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 */ diff --git a/misc/test_vm/include/geekos/serial.h b/misc/test_vm/include/geekos/serial.h index 4ebe0b0..9b7b133 100644 --- a/misc/test_vm/include/geekos/serial.h +++ b/misc/test_vm/include/geekos/serial.h @@ -10,51 +10,9 @@ #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); diff --git a/misc/test_vm/src/geekos/crc32.c b/misc/test_vm/src/geekos/crc32.c index 0165c3b..2107e07 100644 --- a/misc/test_vm/src/geekos/crc32.c +++ b/misc/test_vm/src/geekos/crc32.c @@ -8,7 +8,7 @@ #include #include -#include +#include #define POLYNOMIAL (ulong_t)0xedb88320 static ulong_t crc_table[256]; diff --git a/misc/test_vm/src/geekos/idt.c b/misc/test_vm/src/geekos/idt.c index 5e23989..1000996 100644 --- a/misc/test_vm/src/geekos/idt.c +++ b/misc/test_vm/src/geekos/idt.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include /* ---------------------------------------------------------------------- * 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 #include #include -#include +#include +#include #include @@ -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); } diff --git a/misc/test_vm/src/geekos/io.c b/misc/test_vm/src/geekos/io.c index 70b9f50..1310cdc 100644 --- a/misc/test_vm/src/geekos/io.c +++ b/misc/test_vm/src/geekos/io.c @@ -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. */ diff --git a/misc/test_vm/src/geekos/kthread.c b/misc/test_vm/src/geekos/kthread.c index e2a6df2..7ccec20 100644 --- a/misc/test_vm/src/geekos/kthread.c +++ b/misc/test_vm/src/geekos/kthread.c @@ -16,7 +16,7 @@ #include #include #include -#include +#include /* ---------------------------------------------------------------------- * Private data diff --git a/misc/test_vm/src/geekos/main.c b/misc/test_vm/src/geekos/main.c index 9d48319..177771a 100644 --- a/misc/test_vm/src/geekos/main.c +++ b/misc/test_vm/src/geekos/main.c @@ -9,6 +9,7 @@ * redistribute, and modify it as specified in the file "COPYING". */ +#include #include #include #include @@ -26,10 +27,15 @@ #include #include #include - +#include +#include #include + +#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); diff --git a/misc/test_vm/src/geekos/paging.c b/misc/test_vm/src/geekos/paging.c index d82f785..1a9778e 100644 --- a/misc/test_vm/src/geekos/paging.c +++ b/misc/test_vm/src/geekos/paging.c @@ -22,7 +22,7 @@ //#include #include #include -#include +#include /* ---------------------------------------------------------------------- @@ -39,40 +39,40 @@ * 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 %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;i1 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"); diff --git a/misc/test_vm/src/geekos/screen.c b/misc/test_vm/src/geekos/screen.c index 9c78dde..077112f 100644 --- a/misc/test_vm/src/geekos/screen.c +++ b/misc/test_vm/src/geekos/screen.c @@ -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); +} diff --git a/misc/test_vm/src/geekos/serial.c b/misc/test_vm/src/geekos/serial.c index 68ef275..0729501 100644 --- a/misc/test_vm/src/geekos/serial.c +++ b/misc/test_vm/src/geekos/serial.c @@ -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); +} diff --git a/misc/test_vm/src/geekos/timer.c b/misc/test_vm/src/geekos/timer.c index b3120d3..2ac3a51 100644 --- a/misc/test_vm/src/geekos/timer.c +++ b/misc/test_vm/src/geekos/timer.c @@ -15,7 +15,7 @@ #include #include -#include +#include #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; diff --git a/misc/test_vm/src/geekos/trap.c b/misc/test_vm/src/geekos/trap.c index 2085a99..7932c9a 100644 --- a/misc/test_vm/src/geekos/trap.c +++ b/misc/test_vm/src/geekos/trap.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include /* * 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); diff --git a/misc/test_vm/src/geekos/tss.c b/misc/test_vm/src/geekos/tss.c index b97a844..2cdb968 100644 --- a/misc/test_vm/src/geekos/tss.c +++ b/misc/test_vm/src/geekos/tss.c @@ -19,7 +19,7 @@ #include #include -#include +#include /* * We use one TSS in GeekOS. diff --git a/palacios/build/Makefile b/palacios/build/Makefile index 9479e2b..f243949 100644 --- a/palacios/build/Makefile +++ b/palacios/build/Makefile @@ -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 = \ diff --git a/palacios/include/devices/ide.h b/palacios/include/devices/ide.h index b667a03..d70ac4b 100644 --- a/palacios/include/devices/ide.h +++ b/palacios/include/devices/ide.h @@ -1,242 +1,62 @@ /* - * 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 - * Copyright (c) 2008, Jack Lange + * + * Copyright (c) 2008, Jack Lange * Copyright (c) 2008, The V3VEE Project - * All rights reserved for original changes - * + * All rights reserved. + * + * Author: Jack Lange + * + * 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 #include -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 diff --git a/palacios/include/devices/pci.h b/palacios/include/devices/pci.h index 003096c..79718a7 100644 --- a/palacios/include/devices/pci.h +++ b/palacios/include/devices/pci.h @@ -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; diff --git a/palacios/src/devices/apic.c b/palacios/src/devices/apic.c index 407d3af..92e6683 100644 --- a/palacios/src/devices/apic.c +++ b/palacios/src/devices/apic.c @@ -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 index 0000000..7635998 --- /dev/null +++ b/palacios/src/devices/atapi-types.h @@ -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 + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * 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 + +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 index 0000000..5af6729 --- /dev/null +++ b/palacios/src/devices/atapi.h @@ -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 + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * 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 index 0000000..3ae9966 --- /dev/null +++ b/palacios/src/devices/ide-types.h @@ -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 + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * 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 + + +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 index 0000000..a9d88aa --- /dev/null +++ b/palacios/src/devices/ide.c @@ -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 + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#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; +} diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index 1cad975..a0e9e4e 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -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 diff --git a/palacios/src/devices/ramdisk.c b/palacios/src/devices/ramdisk.c index 6c18c31..04602f7 100644 --- a/palacios/src/devices/ramdisk.c +++ b/palacios/src/devices/ramdisk.c @@ -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; } diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index c0c713e..be73f33 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -33,8 +33,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -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) {