Initial revision
authorRex Jolliff <rex@lvcablemodem.com>
Mon, 5 Oct 1998 04:00:59 +0000 (04:00 +0000)
committerRex Jolliff <rex@lvcablemodem.com>
Mon, 5 Oct 1998 04:00:59 +0000 (04:00 +0000)
svn path=/trunk/; revision=50

160 files changed:
reactos/DIRS [new file with mode: 0644]
reactos/NEWS [new file with mode: 0644]
reactos/README [new file with mode: 0644]
reactos/TODO [new file with mode: 0644]
reactos/apps/common/crt0.c [new file with mode: 0644]
reactos/apps/tests/hello/makefile [new file with mode: 0644]
reactos/apps/tests/hello/test.asm [new file with mode: 0644]
reactos/apps/utils/cmd/cmd.c [new file with mode: 0644]
reactos/apps/utils/cmd/makefile [new file with mode: 0644]
reactos/apps/utils/shell/makefile [new file with mode: 0644]
reactos/apps/utils/shell/shell.c [new file with mode: 0644]
reactos/apps/utils/shell/shell.sym [new file with mode: 0644]
reactos/doc/cacheman.txt [new file with mode: 0644]
reactos/drivers/dd/event/dirs [new file with mode: 0644]
reactos/drivers/dd/event/exe/eventtes.c [new file with mode: 0644]
reactos/drivers/dd/event/exe/makefile [new file with mode: 0644]
reactos/drivers/dd/event/exe/sources [new file with mode: 0644]
reactos/drivers/dd/event/readme.txt [new file with mode: 0644]
reactos/drivers/dd/event/sys/event.c [new file with mode: 0644]
reactos/drivers/dd/event/sys/event.h [new file with mode: 0644]
reactos/drivers/dd/event/sys/event.ini [new file with mode: 0644]
reactos/drivers/dd/event/sys/event.rc [new file with mode: 0644]
reactos/drivers/dd/event/sys/makefile [new file with mode: 0644]
reactos/drivers/dd/event/sys/sources [new file with mode: 0644]
reactos/drivers/dd/ide/ide.c [new file with mode: 0644]
reactos/drivers/dd/ide/ide.h [new file with mode: 0644]
reactos/drivers/dd/ide/idep.h [new file with mode: 0644]
reactos/drivers/dd/ide/makefile [new file with mode: 0644]
reactos/drivers/dd/ide/partitio.h [new file with mode: 0644]
reactos/drivers/dd/keyboard/keyboard.c [new file with mode: 0644]
reactos/drivers/dd/keyboard/keyboard.h [new file with mode: 0644]
reactos/drivers/dd/keyboard/makefile [new file with mode: 0644]
reactos/drivers/dd/mouse/makefile [new file with mode: 0644]
reactos/drivers/dd/mouse/mouse.c [new file with mode: 0644]
reactos/drivers/dd/null/makefile [new file with mode: 0644]
reactos/drivers/dd/null/null.c [new file with mode: 0644]
reactos/drivers/dd/parallel/makefile [new file with mode: 0644]
reactos/drivers/dd/parallel/parallel.c [new file with mode: 0644]
reactos/drivers/dd/parallel/parallel.h [new file with mode: 0644]
reactos/drivers/dd/sdisk/makefile [new file with mode: 0644]
reactos/drivers/dd/sdisk/sdisk.c [new file with mode: 0644]
reactos/drivers/dd/serial/makefile [new file with mode: 0644]
reactos/drivers/dd/serial/serial.c [new file with mode: 0644]
reactos/drivers/dd/sound/dsp.c [new file with mode: 0644]
reactos/drivers/dd/sound/dsp.h [new file with mode: 0644]
reactos/drivers/dd/sound/makefile [new file with mode: 0644]
reactos/drivers/dd/sound/mixer.c [new file with mode: 0644]
reactos/drivers/dd/sound/mixer.h [new file with mode: 0644]
reactos/drivers/dd/sound/sb16.h [new file with mode: 0644]
reactos/drivers/dd/sound/sb_waveout.c [new file with mode: 0644]
reactos/drivers/dd/sound/sound.c [new file with mode: 0644]
reactos/drivers/dd/sound/wave.h [new file with mode: 0644]
reactos/drivers/dd/test/makefile [new file with mode: 0644]
reactos/drivers/dd/test/test.c [new file with mode: 0644]
reactos/drivers/dd/test1/makefile [new file with mode: 0644]
reactos/drivers/dd/test1/test.c [new file with mode: 0644]
reactos/drivers/fs/minix/block.c [new file with mode: 0644]
reactos/drivers/fs/minix/dir.c [new file with mode: 0644]
reactos/drivers/fs/minix/inode.c [new file with mode: 0644]
reactos/drivers/fs/minix/minix.h [new file with mode: 0644]
reactos/drivers/fs/minix/minix.sym [new file with mode: 0644]
reactos/drivers/fs/minix/mount.c [new file with mode: 0644]
reactos/drivers/fs/minix/rw.c [new file with mode: 0644]
reactos/drivers/fs/template/makefile [new file with mode: 0644]
reactos/drivers/fs/template/template.c [new file with mode: 0644]
reactos/drivers/fs/vfat/blockdev.c [new file with mode: 0644]
reactos/drivers/fs/vfat/iface.c [new file with mode: 0644]
reactos/drivers/fs/vfat/makefile [new file with mode: 0644]
reactos/drivers/fs/vfat/vfat.h [new file with mode: 0644]
reactos/iface/native/genntdll [new file with mode: 0644]
reactos/iface/native/genntdll.c [new file with mode: 0644]
reactos/iface/native/makefile [new file with mode: 0644]
reactos/iface/native/sysfuncs.lst [new file with mode: 0644]
reactos/include/ddk/ccfuncs.h [new file with mode: 0644]
reactos/include/ddk/cctypes.h [new file with mode: 0644]
reactos/include/ddk/ntifs.h [new file with mode: 0644]
reactos/include/ddk/sefuncs.h [new file with mode: 0644]
reactos/include/ddk/zwtypes.h [new file with mode: 0644]
reactos/include/internal/asm.inc [new file with mode: 0644]
reactos/include/internal/i386/mmhal.h [new file with mode: 0644]
reactos/include/internal/i386/segment.h [new file with mode: 0644]
reactos/include/internal/mmhal.h [new file with mode: 0644]
reactos/include/kernel32/kernel32.h [new file with mode: 0644]
reactos/include/ntdll/service.h [new file with mode: 0644]
reactos/lib/crtdll/makefile [new file with mode: 0644]
reactos/lib/crtdll/stdio/vsprintf.c [new file with mode: 0644]
reactos/lib/crtdll/stdlib/malloc.c [new file with mode: 0644]
reactos/lib/crtdll/string/memchr.c [new file with mode: 0644]
reactos/lib/crtdll/string/memcmp.c [new file with mode: 0644]
reactos/lib/crtdll/string/memcpy.s [new file with mode: 0644]
reactos/lib/crtdll/string/memmove.s [new file with mode: 0644]
reactos/lib/crtdll/string/memset.s [new file with mode: 0644]
reactos/lib/crtdll/string/strcat.c [new file with mode: 0644]
reactos/lib/crtdll/string/strchr.c [new file with mode: 0644]
reactos/lib/crtdll/string/strcmp.c [new file with mode: 0644]
reactos/lib/crtdll/string/strcoll.c [new file with mode: 0644]
reactos/lib/crtdll/string/strcpy.c [new file with mode: 0644]
reactos/lib/crtdll/string/strcspn.c [new file with mode: 0644]
reactos/lib/crtdll/string/strdup.c [new file with mode: 0644]
reactos/lib/crtdll/string/strlen.c [new file with mode: 0644]
reactos/lib/crtdll/string/strncat.c [new file with mode: 0644]
reactos/lib/crtdll/string/strncmp.c [new file with mode: 0644]
reactos/lib/crtdll/string/strncpy.c [new file with mode: 0644]
reactos/lib/crtdll/string/strpbrk.c [new file with mode: 0644]
reactos/lib/crtdll/string/strrchr.c [new file with mode: 0644]
reactos/lib/crtdll/string/strspn.c [new file with mode: 0644]
reactos/lib/crtdll/string/strstr.c [new file with mode: 0644]
reactos/lib/crtdll/string/strtok.c [new file with mode: 0644]
reactos/lib/crtdll/string/strxfrm.c [new file with mode: 0644]
reactos/lib/kernel32/file/curdir.c [new file with mode: 0644]
reactos/lib/kernel32/internal/dprintf.c [new file with mode: 0644]
reactos/lib/kernel32/internal/vsprintf.c [new file with mode: 0644]
reactos/lib/kernel32/mem/global.c [new file with mode: 0644]
reactos/lib/kernel32/mem/mem.c [new file with mode: 0644]
reactos/lib/kernel32/mem/utils.c [new file with mode: 0644]
reactos/lib/kernel32/misc/error.c [new file with mode: 0644]
reactos/lib/kernel32/string/lstring.c [new file with mode: 0644]
reactos/lib/kernel32/synch/critical.c [new file with mode: 0644]
reactos/lib/mingw32/main.c [new file with mode: 0644]
reactos/lib/mingw32/makefile [new file with mode: 0644]
reactos/lib/ntdll/def/ntdll.def [new file with mode: 0644]
reactos/lib/ntdll/napi.asm [new file with mode: 0644]
reactos/ntoskrnl/cc/block.c [new file with mode: 0644]
reactos/ntoskrnl/cc/cacheman.c [new file with mode: 0644]
reactos/ntoskrnl/cm/registry.c [new file with mode: 0644]
reactos/ntoskrnl/ex/locale.c [new file with mode: 0644]
reactos/ntoskrnl/ex/napi.c [new file with mode: 0644]
reactos/ntoskrnl/ex/power.c [new file with mode: 0644]
reactos/ntoskrnl/ex/stamp.c [new file with mode: 0644]
reactos/ntoskrnl/ex/sysinfo.c [new file with mode: 0644]
reactos/ntoskrnl/io/cleanup.c [new file with mode: 0644]
reactos/ntoskrnl/io/dir.c [new file with mode: 0644]
reactos/ntoskrnl/io/flush.c [new file with mode: 0644]
reactos/ntoskrnl/io/iocomp.c [new file with mode: 0644]
reactos/ntoskrnl/io/lock.c [new file with mode: 0644]
reactos/ntoskrnl/io/mailslot.c [new file with mode: 0644]
reactos/ntoskrnl/io/npipe.c [new file with mode: 0644]
reactos/ntoskrnl/io/page.c [new file with mode: 0644]
reactos/ntoskrnl/ke/apchelp.asm [new file with mode: 0644]
reactos/ntoskrnl/ke/cont.c [new file with mode: 0644]
reactos/ntoskrnl/ke/ldt.c [new file with mode: 0644]
reactos/ntoskrnl/mm/npool.c [new file with mode: 0644]
reactos/ntoskrnl/mm/paging.c [new file with mode: 0644]
reactos/ntoskrnl/mm/ppool.c [new file with mode: 0644]
reactos/ntoskrnl/nt/atom.c [new file with mode: 0644]
reactos/ntoskrnl/nt/channel.c [new file with mode: 0644]
reactos/ntoskrnl/nt/evtpair.c [new file with mode: 0644]
reactos/ntoskrnl/nt/misc.c [new file with mode: 0644]
reactos/ntoskrnl/nt/mutant.c [new file with mode: 0644]
reactos/ntoskrnl/nt/ntevent.c [new file with mode: 0644]
reactos/ntoskrnl/nt/ntsem.c [new file with mode: 0644]
reactos/ntoskrnl/nt/nttimer.c [new file with mode: 0644]
reactos/ntoskrnl/nt/plugplay.c [new file with mode: 0644]
reactos/ntoskrnl/nt/port.c [new file with mode: 0644]
reactos/ntoskrnl/nt/profile.c [new file with mode: 0644]
reactos/ntoskrnl/ob/object.s [new file with mode: 0644]
reactos/ntoskrnl/ps/kill.c [new file with mode: 0644]
reactos/ntoskrnl/ps/tinfo.c [new file with mode: 0644]
rosapps/cmd/cmd.c [new file with mode: 0644]
rosapps/cmd/makefile [new file with mode: 0644]

diff --git a/reactos/DIRS b/reactos/DIRS
new file mode 100644 (file)
index 0000000..9accce1
--- /dev/null
@@ -0,0 +1,21 @@
+DIRECTORIES
+
+system           : compiled versions of the various system components and
+                   libraries
+ntoskrnl          : microkernel source
+ntoskrnl/hal      : hardware abstraction layer source
+ntoskrnl/mm       : memory managment subsystem source
+ntoskrnl/io      : IO manager subsystem source
+include          : win32 headers
+include/internal : kernel private header files
+include/ntdll    : system library private header files
+include/kernel32 : system library private header files
+include/user32   : user interface private header files
+include/gdi32    : graphics interface private header files
+include/ddk      : header files for modules
+lib/ntdll        : NT dll source
+lib/kernel32     : kernel32 source
+doc              : documentation
+loaders/dos      : DOS based loader
+loaders/boot     : boot loader
+services         : various services (device drivers, filesystems etc)
diff --git a/reactos/NEWS b/reactos/NEWS
new file mode 100644 (file)
index 0000000..fb7fa65
--- /dev/null
@@ -0,0 +1,10 @@
+0.0.12:      Added support for multiple processes (not really tested)
+            System calls
+            kernel32 now compiles (only as a static library)
+            Fixed invalid tss bug (hopefully)
+            Added section support
+            Added some of the ZwxxxVirtual calls
+            Added prototype caching functions (only the Minix fsd actually
+             uses them)
+            Added handle access and type checking
+            Prototype APC implementation (no support for user APCs)
diff --git a/reactos/README b/reactos/README
new file mode 100644 (file)
index 0000000..1df8492
--- /dev/null
@@ -0,0 +1,62 @@
+Last updated 30/09/98
+
+-- Compiling
+
+Type 'make' to build the kernel on linux using a djgpp cross compiler, or
+'make -fmakefile.dos' to build the kernel from dos using djgpp. No other 
+configuration are supported at the moment, sorry.
+
+-- Running
+
+To run the kernel start from a clean dos system (no emm386 or windows) and
+run 'boot.bat'. The kernel should boot, print diagnostic messages and begin
+executing a simple user-mode shell. By default the kernel boots with a
+minimum set of drivers but additional ones can be specified as the arguments
+to 'boot.bat'.
+
+-- Problems
+
+This is strictly alpha quality software so expect plenty of those. If you
+are submitting a bug report, please see the section below. If you have a fix 
+for the problem, even better, please send all patches, fixes, enhancements etc 
+to me (David Welch), our coordinator Dennis Winkley or the kernel mailing
+list. (See contact addresses below)
+
+-- Bug Reports
+
+Thank you for taking the time to do this, we can only fix the bugs we know
+about, however please include as much information as possible. Say what you
+were trying to do at the time, what messages (if any) were displayed. If the
+kernel crashed, it should print a message like this
+
+     Exception s(r)
+     CS:EIP    p(q)
+     DS xxxxx ES xxxx FS xxxx
+     ...
+     Frames: xxxxx xxxxx xxxxx
+
+Please include the exception type and error code (s and r). The eip 
+address (q) is specific to your kernel, to be of use in fixing the problem
+it needs to be translated to a function name. Do this by running
+
+      nm --numeric-sort kimage > kernel.sym
+
+kernel.sym should include a list of functions and their address, look for the
+last function with an address less than the eip value. The functions should
+sorted in ascending order by address.
+
+If you suspect the problem is hardware related also include details of what
+hardware devices you have installed.  
+
+-- Contact addresses
+
+Overall coordinator, Jason Filby (jasonfilby@yahoo.com)
+Kernel coordinator, Dennis Winkley (dwinkley@mail.whitworth.edu)
+Me, David Welch (welch@mcmail.com)
+
+Specific components will probably have contact details for the authors in
+the source file, a partial list of those working on the kernel can be found
+on the kernel website. 
+
+-- Additional documentation
+
diff --git a/reactos/TODO b/reactos/TODO
new file mode 100644 (file)
index 0000000..b2d7289
--- /dev/null
@@ -0,0 +1,11 @@
+Hardware resource management
+Deleting namespace objects
+Directory functions
+File sharing
+Event pairs
+Io completion ports
+Cancel io support
+DMA support
+Registry support
+Cache read ahead
+Caching file mapping
diff --git a/reactos/apps/common/crt0.c b/reactos/apps/common/crt0.c
new file mode 100644 (file)
index 0000000..bcb1777
--- /dev/null
@@ -0,0 +1,11 @@
+extern void main(void);
+
+void start(void)
+{
+   main();
+   for(;;);
+}
+
+void __main(void)
+{
+}
diff --git a/reactos/apps/tests/hello/makefile b/reactos/apps/tests/hello/makefile
new file mode 100644 (file)
index 0000000..94dd16c
--- /dev/null
@@ -0,0 +1,7 @@
+all: test.bin
+
+test.bin: test.asm
+       $(LD) -Ttext 0x10000 test.o ../../lib/ntdll/ntdll.a -o test.exe
+       $(OBJCOPY) -O binary test.exe test.bin
+
+include ../../rules.mak
diff --git a/reactos/apps/tests/hello/test.asm b/reactos/apps/tests/hello/test.asm
new file mode 100644 (file)
index 0000000..a5e9306
--- /dev/null
@@ -0,0 +1,11 @@
+BITS 32
+
+EXTERN _NtDisplayString
+
+_main:
+        push dword _string
+       call _NtDisplayString
+l1:
+        jmp l1
+
+_string db 'Hello world from user mode!',0xa,0
diff --git a/reactos/apps/utils/cmd/cmd.c b/reactos/apps/utils/cmd/cmd.c
new file mode 100644 (file)
index 0000000..22211f7
--- /dev/null
@@ -0,0 +1,158 @@
+#include <stdarg.h>
+#include <windows.h>
+
+HANDLE stdin;
+HANDLE stdout;
+
+
+void Console_puts(char* str)
+{
+        ULONG nchar;
+
+        WriteConsole(stdout,
+                     str,
+                     strlen(str),
+                     &nchar,
+                     NULL);
+}
+
+void Console_printf(char* fmt, ...)
+{
+        char buffer[255];
+        va_list vargs;
+
+        va_start(vargs,fmt);
+        vsprintf(buffer,fmt,vargs);
+        Console_puts(buffer);
+        va_end(vargs);
+}
+
+void Console_getline(PCH Prompt, PCH Output, DWORD OutputLength)
+{
+        char ch;
+        DWORD nbytes;
+
+        Console_puts(Prompt);
+
+        ReadConsole(stdin,
+                    Output,
+                    OutputLength,
+                    &nbytes,
+                    NULL);
+        Output[nbytes-2]=0;
+}
+
+void func_cd(char* s)
+{
+        Console_printf("Changing directory to %s\n",s);
+        if (!SetCurrentDirectory(s))
+        {
+                Console_puts("Failed to change to directory\n");
+        }
+}
+
+void func_dir(char* s)
+{
+        HANDLE shandle;
+        WIN32_FIND_DATA FindData;
+
+        shandle = FindFirstFile("*.*",&FindData);
+
+        if (shandle==INVALID_HANDLE_VALUE)
+        {
+                return;
+        }
+        do
+        {
+                Console_printf("Scanning %s\n",FindData.cFileName);
+        } while(FindNextFile(shandle,&FindData));
+}
+
+int is_builtin(char* name, char* args)
+{
+        if (strcmp(name,"dir")==0)
+        {
+                func_dir(args);
+                return(1);
+        }
+        if (strcmp(name,"cd")==0)
+        {
+                func_cd(args);
+                return(1);
+        }
+        return(0);
+}
+
+int process_command(char* str)
+{
+        char* name;
+        char* args;
+        PROCESS_INFORMATION pi;
+        STARTUPINFO si;
+        char process_arg[255];
+
+        if (strcmp(str,"exit")==0)
+        {
+                return(1);
+        }
+
+        name = strtok(str," \t");
+        args = strtok(NULL,"");
+
+        if (is_builtin(name,args))
+        {
+                return(0);
+        }
+        memset(&si,0,sizeof(STARTUPINFO));
+        si.cb=sizeof(STARTUPINFO);
+        si.lpTitle=strdup(name);
+
+        strcpy(process_arg,name);
+        strcat(process_arg," ");
+        if(args!=NULL)
+        {
+                strcat(process_arg,args);
+        }
+        Console_printf("name '%s' process_arg '%s'\n",name,process_arg);
+        if (!CreateProcess(NULL,process_arg,NULL,NULL,FALSE,
+                     CREATE_NEW_CONSOLE,
+                      NULL,NULL,&si,&pi))
+                      {
+                        Console_printf("Failed to execute process\n");
+                      }
+        return(0);
+}
+
+void build_prompt(char* prompt)
+{
+        int len;
+
+        len = GetCurrentDirectory(255,prompt);
+        strcat(prompt,">");
+}
+
+void command_loop()
+{
+        char line[255];
+        char prompt[255];
+        int do_exit = 0;
+
+        while (!do_exit)
+        {
+                build_prompt(prompt);
+                Console_getline(prompt,line,255);
+                Console_printf("Processing command '%s'\n",line);
+                do_exit = process_command(line);
+        }        
+}
+
+int STDCALL WinMain (HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
+{
+        AllocConsole();
+        stdin = GetStdHandle(STD_INPUT_HANDLE);
+        stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+
+        command_loop();
+
+       return 0;
+}
diff --git a/reactos/apps/utils/cmd/makefile b/reactos/apps/utils/cmd/makefile
new file mode 100644 (file)
index 0000000..7e36f73
--- /dev/null
@@ -0,0 +1,12 @@
+all: cmd.bin
+
+OBJECTS = ../common/crt0.o cmd.o
+
+LIBS = ../../lib/mingw32/mingw32.a ../../lib/crtdll/crtdll.a \
+       ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a
+
+cmd.bin: $(OBJECTS)
+       $(LD) -Ttext 0x10000 $(OBJECTS) $(LIBS) -o cmd.exe
+       $(OBJCOPY) -O binary cmd.exe cmd.bin
+
+include ../../rules.mak
diff --git a/reactos/apps/utils/shell/makefile b/reactos/apps/utils/shell/makefile
new file mode 100644 (file)
index 0000000..eed5a53
--- /dev/null
@@ -0,0 +1,9 @@
+all: shell.bin
+
+OBJECTS = ../common/crt0.o shell.o
+
+shell.bin: $(OBJECTS)
+       $(LD) -Ttext 0x10000 $(OBJECTS) ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a -o shell.exe
+       $(OBJCOPY) -O binary shell.exe shell.bin
+
+include ../../rules.mak
diff --git a/reactos/apps/utils/shell/shell.c b/reactos/apps/utils/shell/shell.c
new file mode 100644 (file)
index 0000000..1210c9a
--- /dev/null
@@ -0,0 +1,46 @@
+#include <ddk/ntddk.h>
+#include <stdarg.h>
+
+void debug_printf(char* fmt, ...)
+{
+   va_list args;
+   char buffer[255];
+   
+   va_start(args,fmt);
+   vsprintf(buffer,fmt,args);
+   OutputDebugString(buffer);
+   va_end(args);
+}
+
+void main()
+{
+   KEY_EVENT_RECORD KeyEvent[2];
+   HANDLE FileHandle;
+   DWORD Result;
+   HANDLE DefaultHeap;
+   PVOID Buffer;
+     
+   NtDisplayString("Simple Shell Starting...\n");
+   
+//   DefaultHeap = HeapCreate(0,1024*1024,1024*1024);
+//   Buffer = HeapAlloc(DefaultHeap,0,1024);
+   
+   FileHandle = CreateFile("\\Device\\Keyboard",
+                          FILE_GENERIC_READ,
+                          0,
+                          NULL,
+                          OPEN_EXISTING,
+                          0,
+                          NULL);
+   
+   debug_printf("C:\\");
+   for(;;)
+     {
+       ReadFile(FileHandle,
+                &KeyEvent,
+                sizeof(KeyEvent),
+                &Result,
+                NULL);
+       debug_printf("%c",KeyEvent[0].AsciiChar);
+     }
+}
diff --git a/reactos/apps/utils/shell/shell.sym b/reactos/apps/utils/shell/shell.sym
new file mode 100644 (file)
index 0000000..46314ee
--- /dev/null
@@ -0,0 +1,796 @@
+00000000 a .absolut
+00010000 t .text
+00010000 t ___gnu_compiled_c
+00010000 T _start
+00010000 t gcc2_compiled.
+00010008 t L4
+0001000a T ___main
+00010010 t .text
+00010010 t LC0
+00010010 t ___gnu_compiled_c
+00010010 t gcc2_compiled.
+0001002a t LC1
+0001003c T _main
+00010070 t L18
+00010074 t .text
+00010074 t LC0
+00010074 t ___gnu_compiled_c
+00010074 t gcc2_compiled.
+00010098 t ___HeapCommit
+000100c5 t L124
+000100e2 t L125
+000100e4 t L126
+000100ec t LC1
+00010112 t ___HeapDecommit
+00010145 t L128
+0001015e t ___HeapAlloc
+0001019a t L132
+000101cc t L131
+00010209 t L136
+0001024c t L135
+00010282 t L169
+0001028c t L139
+000102c8 t L142
+000102ce t L168
+000102d6 t ___HeapFreeRest
+000102f4 t L171
+00010341 t L172
+0001035f t L170
+00010367 t LC2
+00010386 t LC3
+000103a7 t LC4
+000103c2 t LC5
+000103e1 t LC6
+00010408 t ___HeapReAlloc
+00010430 t L175
+00010470 t L176
+000104f2 t L178
+00010510 t L244
+00010518 t L181
+000105ca t L185
+0001063e t L184
+0001068c t L215
+000106cd t L216
+000106e0 t L214
+000106ea t L177
+000106ec t L243
+000106f4 t ___HeapFree
+00010712 t L246
+00010775 t L248
+00010785 t L247
+000107d6 t L249
+00010802 t L251
+00010807 t L252
+00010810 t ___HeapAllocSub
+00010840 t L254
+00010882 t L258
+000108b1 t L256
+000108bd t L260
+000108c6 t ___HeapAllocFragment
+000108e4 t L264
+000108f0 t L263
+0001090c t L267
+00010940 t L268
+00010984 t L269
+0001098a t L295
+00010992 t ___HeapReAllocFragment
+000109bc t L297
+000109d8 t L298
+00010a06 t L301
+00010a17 t L302
+00010a28 t L303
+00010a5f t L304
+00010a72 t L299
+00010a74 t L330
+00010a7c t ___HeapFreeFragment
+00010aab t L343
+00010ab8 t L333
+00010ad3 t L335
+00010ae0 t L336
+00010aed t L337
+00010b02 t L334
+00010b26 t L340
+00010b37 t L339
+00010b3c t L342
+00010b44 t ___HeapPrepare
+00010ba2 t L345
+00010bb2 t L346
+00010be0 T ___HeapInit
+00010c23 t LC7
+00010c46 T _HeapCreate
+00010c99 t LC8
+00010cb0 T _HeapDestroy
+00010cea t L350
+00010cf1 t L351
+00010cf8 t LC9
+00010d1a t LC10
+00010d34 T _HeapAlloc
+00010d65 t L353
+00010d82 t L354
+00010d8f t L355
+00010da1 t L356
+00010db8 t LC11
+00010de4 T _HeapReAlloc
+00010e19 t L358
+00010e36 t L359
+00010e47 t L364
+00010e4e t L361
+00010e5a t L360
+00010e6d t L363
+00010e79 t LC12
+00010e9a T _HeapFree
+00010ecb t L366
+00010ee4 t L367
+00010ef2 t L372
+00010efa t L369
+00010f06 t L368
+00010f18 t L371
+00010f24 t LC13
+00010f36 T _GetProcessHeap
+00010f4a t LC14
+00010f68 T _GetProcessHeaps
+00010f8c t L379
+00010fa4 t L382
+00010fab t L384
+00010faf t L381
+00010fb8 t LC15
+00010fcc T _HeapLock
+00010ff3 t LC16
+00011008 T _HeapUnlock
+00011030 T _HeapCompact
+0001104e t L388
+00011056 t L389
+0001106a t L392
+00011092 t L394
+0001109e t LC17
+000110c0 T _HeapSize
+000110f4 t L396
+00011107 t L397
+00011122 t L399
+0001112e t L401
+0001113a t L398
+0001114d t L403
+0001114f t L404
+00011159 t LC18
+000111b2 t LC19
+00011200 t LC20
+0001124f t LC21
+000112a0 t LC22
+000112f5 t LC23
+00011343 t LC24
+0001138b t LC25
+000113b1 t LC26
+000113dc t LC27
+00011420 T _HeapValidate
+00011444 t L406
+0001145e t L408
+0001149a t L411
+000114ce t L413
+000114e8 t L417
+00011504 t L418
+0001151c t L419
+0001152e t L420
+00011546 t L421
+00011552 t L415
+00011568 t L423
+00011588 t L412
+000115a9 t L434
+000115b2 t L426
+000115be t L425
+000115d3 t L433
+000115dc t L428
+000115e5 t L435
+000115ed t L424
+0001160d t L407
+00011625 t L431
+0001162a t L432
+00011634 t .text
+00011634 T _OutputDebugStringA
+00011634 t ___gnu_compiled_c
+00011634 t gcc2_compiled.
+00011644 T _dprintf
+00011670 T _aprintf
+0001169c t .text
+0001169c T _VirtualAllocEx
+0001169c t ___gnu_compiled_c
+0001169c t gcc2_compiled.
+000116c2 t L16
+000116c8 T _VirtualAlloc
+000116e6 T _VirtualFreeEx
+00011708 t L20
+0001170e T _VirtualFree
+0001172a T _VirtualProtect
+00011748 T _VirtualProtectEx
+0001176c t L25
+00011774 t .text
+00011774 T _RtlNtStatusToDosError
+00011774 t ___gnu_compiled_c
+00011774 t gcc2_compiled.
+0001177c T _SetLastError
+0001178c T _GetLastError
+00011796 T ___ErrorReturnFalse
+0001179e T ___ErrorReturnNull
+000117a8 t .text
+000117a8 T _CopyMemory
+000117a8 t ___gnu_compiled_c
+000117a8 t gcc2_compiled.
+000117bc t L5
+000117c7 t L3
+000117d0 t .text
+000117d0 T _DeleteCriticalSection
+000117d0 t ___gnu_compiled_c
+000117d0 t gcc2_compiled.
+000117e2 T _EnterCriticalSection
+000117ea T _InitializeCriticalSection
+00011818 T _LeaveCriticalSection
+00011820 T _TryEntryCriticalSection
+00011828 t .text
+00011828 t ___gnu_compiled_c
+00011828 T _simple_strtoul
+00011828 t gcc2_compiled.
+00011870 t L163
+00011872 t L162
+00011884 t L165
+00011886 t L164
+0001188a t L188
+00011890 t L166
+000118a8 t L174
+000118aa t L173
+000118bc t L176
+000118be t L175
+000118c2 t L189
+000118cf t L180
+000118dc t L177
+000118e9 t L184
+000118f8 t L186
+000118fa t L185
+00011900 t L181
+00011903 t L190
+00011906 t L178
+0001191c t L167
+00011927 t L187
+00011932 t _skip_atoi
+0001193e t L194
+0001194c t L196
+0001195d t LC0
+00011982 t LC1
+000119a8 t _number
+000119cc t L198
+000119d8 t L199
+000119ea t L200
+000119f9 t L201
+00011a14 t L204
+00011a22 t L206
+00011a2d t L252
+00011a2e t L203
+00011a40 t L210
+00011a47 t L209
+00011a5a t L251
+00011a5e t L217
+00011a79 t L214
+00011a81 t L219
+00011a8c t L223
+00011a90 t L253
+00011a97 t L220
+00011aa3 t L225
+00011ab6 t L227
+00011ac8 t L254
+00011ac9 t L226
+00011ad8 t L233
+00011aea t L237
+00011aee t L255
+00011afa t L241
+00011b01 t L256
+00011b0a t L245
+00011b0e t L257
+00011b17 t L247
+00011b1f t LC2
+00011b26 T _vsprintf
+00011b3e t L262
+00011b50 t L264
+00011b72 t L271
+00011bb6 t L266
+00011bbc t L267
+00011bc2 t L268
+00011bc8 t L269
+00011bce t L270
+00011bd8 t L265
+00011bfc t L273
+00011c1a t L274
+00011c4c t L278
+00011c64 t L279
+00011c6a t L277
+00011c85 t L283
+00011c95 t L282
+00011cb8 t L339
+00011d3c t L285
+00011d46 t L289
+00011d4a t L351
+00011d4f t L286
+00011d68 t L293
+00011d76 t L295
+00011d96 t L299
+00011da6 t L296
+00011db0 t L304
+00011dc4 t L306
+00011dd7 t L307
+00011df6 t L312
+00011dfa t L352
+00011e01 t L309
+00011e0e t L317
+00011e1c t L315
+00011e28 t L321
+00011e38 t L323
+00011e46 t L324
+00011e5c t L325
+00011e72 t L328
+00011e7a t L329
+00011e82 t L330
+00011e86 t L331
+00011e8e t L333
+00011e94 t L335
+00011ea0 t L336
+00011ea9 t L350
+00011eae t L337
+00011eb4 t L284
+00011ed6 t L343
+00011ee6 t L342
+00011efc t L346
+00011f06 t L354
+00011f09 t L341
+00011f12 t L353
+00011f1d t L261
+00011f38 t L260
+00011f48 T _sprintf
+00011f5c t .text
+00011f5c T _GetCurrentProcess
+00011f5c t ___gnu_compiled_c
+00011f5c t gcc2_compiled.
+00011f66 T _GetCurrentThread
+00011f70 t .text
+00011f70 T _NtAcceptConnectPort
+00011f70 T _ZwAcceptConnectPort
+00011f7e T _NtAccessCheck
+00011f7e T _ZwAccessCheck
+00011f8c T _NtAccessCheckAndAuditAlarm
+00011f8c T _ZwAccessCheckAndAuditAlarm
+00011f9a T _NtAddAtom
+00011f9a T _ZwAddAtom
+00011fa8 T _NtAdjustGroupsToken
+00011fa8 T _ZwAdjustGroupsToken
+00011fb6 T _NtAdjustPrivilegesToken
+00011fb6 T _ZwAdjustPrivilegesToken
+00011fc4 T _NtAlertResumeThread
+00011fc4 T _ZwAlertResumeThread
+00011fd2 T _NtAlertThread
+00011fd2 T _ZwAlertThread
+00011fe0 T _NtAllocateLocallyUniqueId
+00011fe0 T _ZwAllocateLocallyUniqueId
+00011fee T _NtAllocateUuids
+00011fee T _ZwAllocateUuids
+00011ffc T _NtAllocateVirtualMemory
+00011ffc T _ZwAllocateVirtualMemory
+0001200a T _NtCallbackReturn
+0001200a T _ZwCallbackReturn
+00012018 T _NtCancelIoFile
+00012018 T _ZwCancelIoFile
+00012026 T _NtCancelTimer
+00012026 T _ZwCancelTimer
+00012034 T _NtClearEvent
+00012034 T _ZwClearEvent
+00012042 T _NtClose
+00012042 T _ZwClose
+00012050 T _NtCloseObjectAuditAlarm
+00012050 T _ZwCloseObjectAuditAlarm
+0001205e T _NtCompleteConnectPort
+0001205e T _ZwCompleteConnectPort
+0001206c T _NtConnectPort
+0001206c T _ZwConnectPort
+0001207a T _NtContinue
+0001207a T _ZwContinue
+00012088 T _NtCreateDirectoryObject
+00012088 T _ZwCreateDirectoryObject
+00012096 T _NtCreateEvent
+00012096 T _ZwCreateEvent
+000120a4 T _NtCreateEventPair
+000120a4 T _ZwCreateEventPair
+000120b2 T _NtCreateFile
+000120b2 T _ZwCreateFile
+000120c0 T _NtCreateIoCompletion
+000120c0 T _ZwCreateIoCompletion
+000120ce T _NtCreateKey
+000120ce T _ZwCreateKey
+000120dc T _NtCreateMailslotFile
+000120dc T _ZwCreateMailslotFile
+000120ea T _NtCreateMutant
+000120ea T _ZwCreateMutant
+000120f8 T _NtCreateNamedPipeFile
+000120f8 T _ZwCreateNamedPipeFile
+00012106 T _NtCreatePagingFile
+00012106 T _ZwCreatePagingFile
+00012114 T _NtCreatePort
+00012114 T _ZwCreatePort
+00012122 T _NtCreateProcess
+00012122 T _ZwCreateProcess
+00012130 T _NtCreateProfile
+00012130 T _ZwCreateProfile
+0001213e T _NtCreateSection
+0001213e T _ZwCreateSection
+0001214c T _NtCreateSemaphore
+0001214c T _ZwCreateSemaphore
+0001215a T _NtCreateSymbolicLinkObject
+0001215a T _ZwCreateSymbolicLinkObject
+00012168 T _NtCreateThread
+00012168 T _ZwCreateThread
+00012176 T _NtCreateTimer
+00012176 T _ZwCreateTimer
+00012184 T _NtCreateToken
+00012184 T _ZwCreateToken
+00012192 T _NtDelayExecution
+00012192 T _ZwDelayExecution
+000121a0 T _NtDeleteAtom
+000121a0 T _ZwDeleteAtom
+000121ae T _NtDeleteFile
+000121ae T _ZwDeleteFile
+000121bc T _NtDeleteKey
+000121bc T _ZwDeleteKey
+000121ca T _NtDeleteObjectAuditAlarm
+000121ca T _ZwDeleteObjectAuditAlarm
+000121d8 T _NtDeleteValueKey
+000121d8 T _ZwDeleteValueKey
+000121e6 T _NtDeviceIoControlFile
+000121e6 T _ZwDeviceIoControlFile
+000121f4 T _NtDisplayString
+000121f4 T _ZwDisplayString
+00012202 T _NtDuplicateObject
+00012202 T _ZwDuplicateObject
+00012210 T _NtDuplicateToken
+00012210 T _ZwDuplicateToken
+0001221e T _NtEnumerateKey
+0001221e T _ZwEnumerateKey
+0001222c T _NtEnumerateValueKey
+0001222c T _ZwEnumerateValueKey
+0001223a T _NtExtendSection
+0001223a T _ZwExtendSection
+00012248 T _NtFindAtom
+00012248 T _ZwFindAtom
+00012256 T _NtFlushBuffersFile
+00012256 T _ZwFlushBuffersFile
+00012264 T _NtFlushInstructionCache
+00012264 T _ZwFlushInstructionCache
+00012272 T _NtFlushKey
+00012272 T _ZwFlushKey
+00012280 T _NtFlushVirtualMemory
+00012280 T _ZwFlushVirtualMemory
+0001228e T _NtFlushWriteBuffer
+0001228e T _ZwFlushWriteBuffer
+0001229c T _NtFreeVirtualMemory
+0001229c T _ZwFreeVirtualMemory
+000122aa T _NtFsControlFile
+000122aa T _ZwFsControlFile
+000122b8 T _NtGetContextThread
+000122b8 T _ZwGetContextThread
+000122c6 T _NtGetPlugPlayEvent
+000122c6 T _ZwGetPlugPlayEvent
+000122d4 T _NtGetTickCount
+000122d4 T _ZwGetTickCount
+000122e2 T _NtImpersonateClientOfPort
+000122e2 T _ZwImpersonateClientOfPort
+000122f0 T _NtImpersonateThread
+000122f0 T _ZwImpersonateThread
+000122fe T _NtInitializeRegistry
+000122fe T _ZwInitializeRegistry
+0001230c T _NtListenPort
+0001230c T _ZwListenPort
+0001231a T _NtLoadDriver
+0001231a T _ZwLoadDriver
+00012328 T _NtLoadKey
+00012328 T _ZwLoadKey
+00012336 T _NtLoadKey2
+00012336 T _ZwLoadKey2
+00012344 T _NtLockFile
+00012344 T _ZwLockFile
+00012352 T _NtLockVirtualMemory
+00012352 T _ZwLockVirtualMemory
+00012360 T _NtMakeTemporaryObject
+00012360 T _ZwMakeTemporaryObject
+0001236e T _NtMapViewOfSection
+0001236e T _ZwMapViewOfSection
+0001237c T _NtNotifyChangeDirectoryFile
+0001237c T _ZwNotifyChangeDirectoryFile
+0001238a T _NtNotifyChangeKey
+0001238a T _ZwNotifyChangeKey
+00012398 T _NtOpenDirectoryObject
+00012398 T _ZwOpenDirectoryObject
+000123a6 T _NtOpenEvent
+000123a6 T _ZwOpenEvent
+000123b4 T _NtOpenEventPair
+000123b4 T _ZwOpenEventPair
+000123c2 T _NtOpenFile
+000123c2 T _ZwOpenFile
+000123d0 T _NtOpenIoCompletion
+000123d0 T _ZwOpenIoCompletion
+000123de T _NtOpenKey
+000123de T _ZwOpenKey
+000123ec T _NtOpenMutant
+000123ec T _ZwOpenMutant
+000123fa T _NtOpenObjectAuditAlarm
+000123fa T _ZwOpenObjectAuditAlarm
+00012408 T _NtOpenProcess
+00012408 T _ZwOpenProcess
+00012416 T _NtOpenProcessToken
+00012416 T _ZwOpenProcessToken
+00012424 T _NtOpenSection
+00012424 T _ZwOpenSection
+00012432 T _NtOpenSemaphore
+00012432 T _ZwOpenSemaphore
+00012440 T _NtOpenSymbolicLinkObject
+00012440 T _ZwOpenSymbolicLinkObject
+0001244e T _NtOpenThread
+0001244e T _ZwOpenThread
+0001245c T _NtOpenThreadToken
+0001245c T _ZwOpenThreadToken
+0001246a T _NtOpenTimer
+0001246a T _ZwOpenTimer
+00012478 T _NtPlugPlayControl
+00012478 T _ZwPlugPlayControl
+00012486 T _NtPrivilegeCheck
+00012486 T _ZwPrivilegeCheck
+00012494 T _NtPrivilegedServiceAuditAlarm
+00012494 T _ZwPrivilegedServiceAuditAlarm
+000124a2 T _NtPrivilegeObjectAuditAlarm
+000124a2 T _ZwPrivilegeObjectAuditAlarm
+000124b0 T _NtProtectVirtualMemory
+000124b0 T _ZwProtectVirtualMemory
+000124be T _NtPulseEvent
+000124be T _ZwPulseEvent
+000124cc T _NtQueryInformationAtom
+000124cc T _ZwQueryInformationAtom
+000124da T _NtQueryAttributesFile
+000124da T _ZwQueryAttributesFile
+000124e8 T _NtQueryDefaultLocale
+000124e8 T _ZwQueryDefaultLocale
+000124f6 T _NtQueryDirectoryFile
+000124f6 T _ZwQueryDirectoryFile
+00012504 T _NtQueryDirectoryObject
+00012504 T _ZwQueryDirectoryObject
+00012512 T _NtQueryEaFile
+00012512 T _ZwQueryEaFile
+00012520 T _NtQueryEvent
+00012520 T _ZwQueryEvent
+0001252e T _NtQueryFullAttributesFile
+0001252e T _ZwQueryFullAttributesFile
+0001253c T _NtQueryInformationFile
+0001253c T _ZwQueryInformationFile
+0001254a T _NtQueryIoCompletion
+0001254a T _ZwQueryIoCompletion
+00012558 T _NtQueryInformationPort
+00012558 T _ZwQueryInformationPort
+00012566 T _NtQueryInformationProcess
+00012566 T _ZwQueryInformationProcess
+00012574 T _NtQueryInformationThread
+00012574 T _ZwQueryInformationThread
+00012582 T _NtQueryInformationToken
+00012582 T _ZwQueryInformationToken
+00012590 T _NtQueryIntervalProfile
+00012590 T _ZwQueryIntervalProfile
+0001259e T _NtQueryKey
+0001259e T _ZwQueryKey
+000125ac T _NtQueryMultipleValueKey
+000125ac T _ZwQueryMultipleValueKey
+000125ba T _NtQueryMutant
+000125ba T _ZwQueryMutant
+000125c8 T _NtQueryObject
+000125c8 T _ZwQueryObject
+000125d6 T _NtQueryOleDirectoryFile
+000125d6 T _ZwQueryOleDirectoryFile
+000125e4 T _NtQueryPerformanceCounter
+000125e4 T _ZwQueryPerformanceCounter
+000125f2 T _NtQuerySection
+000125f2 T _ZwQuerySection
+00012600 T _NtQuerySecurityObject
+00012600 T _ZwQuerySecurityObject
+0001260e T _NtQuerySemaphore
+0001260e T _ZwQuerySemaphore
+0001261c T _NtQuerySymbolicLinkObject
+0001261c T _ZwQuerySymbolicLinkObject
+0001262a T _NtQuerySystemEnvironmentValue
+0001262a T _ZwQuerySystemEnvironmentValue
+00012638 T _NtQuerySystemInformation
+00012638 T _ZwQuerySystemInformation
+00012646 T _NtQuerySystemTime
+00012646 T _ZwQuerySystemTime
+00012654 T _NtQueryTimer
+00012654 T _ZwQueryTimer
+00012662 T _NtQueryTimerResolution
+00012662 T _ZwQueryTimerResolution
+00012670 T _NtQueryValueKey
+00012670 T _ZwQueryValueKey
+0001267e T _NtQueryVirtualMemory
+0001267e T _ZwQueryVirtualMemory
+0001268c T _NtQueryVolumeInformationFile
+0001268c T _ZwQueryVolumeInformationFile
+0001269a T _NtQueueApcThread
+0001269a T _ZwQueueApcThread
+000126a8 T _NtRaiseException
+000126a8 T _ZwRaiseException
+000126b6 T _NtRaiseHardError
+000126b6 T _ZwRaiseHardError
+000126c4 T _NtReadFile
+000126c4 T _ZwReadFile
+000126d2 T _NtReadFileScatter
+000126d2 T _ZwReadFileScatter
+000126e0 T _NtReadRequestData
+000126e0 T _ZwReadRequestData
+000126ee T _NtReadVirtualMemory
+000126ee T _ZwReadVirtualMemory
+000126fc T _NtRegisterThreadTerminatePort
+000126fc T _ZwRegisterThreadTerminatePort
+0001270a T _NtReleaseMutant
+0001270a T _ZwReleaseMutant
+00012718 T _NtReleaseSemaphore
+00012718 T _ZwReleaseSemaphore
+00012726 T _NtRemoveIoCompletion
+00012726 T _ZwRemoveIoCompletion
+00012734 T _NtReplaceKey
+00012734 T _ZwReplaceKey
+00012742 T _NtReplyPort
+00012742 T _ZwReplyPort
+00012750 T _NtReplyWaitReceivePort
+00012750 T _ZwReplyWaitReceivePort
+0001275e T _NtReplyWaitReplyPort
+0001275e T _ZwReplyWaitReplyPort
+0001276c T _NtRequestPort
+0001276c T _ZwRequestPort
+0001277a T _NtRequestWaitReplyPort
+0001277a T _ZwRequestWaitReplyPort
+00012788 T _NtResetEvent
+00012788 T _ZwResetEvent
+00012796 T _NtRestoreKey
+00012796 T _ZwRestoreKey
+000127a4 T _NtResumeThread
+000127a4 T _ZwResumeThread
+000127b2 T _NtSaveKey
+000127b2 T _ZwSaveKey
+000127c0 T _NtSetIoCompletion
+000127c0 T _ZwSetIoCompletion
+000127ce T _NtSetContextThread
+000127ce T _ZwSetContextThread
+000127dc T _NtSetDefaultHardErrorPort
+000127dc T _ZwSetDefaultHardErrorPort
+000127ea T _NtSetDefaultLocale
+000127ea T _ZwSetDefaultLocale
+000127f8 T _NtSetEaFile
+000127f8 T _ZwSetEaFile
+00012806 T _NtSetEvent
+00012806 T _ZwSetEvent
+00012814 T _NtSetHighEventPair
+00012814 T _ZwSetHighEventPair
+00012822 T _NtSetHighWaitLowEventPair
+00012822 T _ZwSetHighWaitLowEventPair
+00012830 T _NtSetInformationFile
+00012830 T _ZwSetInformationFile
+0001283e T _NtSetInformationKey
+0001283e T _ZwSetInformationKey
+0001284c T _NtSetInformationObject
+0001284c T _ZwSetInformationObject
+0001285a T _NtSetInformationProcess
+0001285a T _ZwSetInformationProcess
+00012868 T _NtSetInformationThread
+00012868 T _ZwSetInformationThread
+00012876 T _NtSetInformationToken
+00012876 T _ZwSetInformationToken
+00012884 T _NtSetIntervalProfile
+00012884 T _ZwSetIntervalProfile
+00012892 T _NtSetLdtEntries
+00012892 T _ZwSetLdtEntries
+000128a0 T _NtSetLowEventPair
+000128a0 T _ZwSetLowEventPair
+000128ae T _NtSetLowWaitHighEventPair
+000128ae T _ZwSetLowWaitHighEventPair
+000128bc T _NtSetSecurityObject
+000128bc T _ZwSetSecurityObject
+000128ca T _NtSetSystemEnvironmentValue
+000128ca T _ZwSetSystemEnvironmentValue
+000128d8 T _NtSetSystemInformation
+000128d8 T _ZwSetSystemInformation
+000128e6 T _NtSetSystemPowerState
+000128e6 T _ZwSetSystemPowerState
+000128f4 T _NtSetSystemTime
+000128f4 T _ZwSetSystemTime
+00012902 T _NtSetTimer
+00012902 T _ZwSetTimer
+00012910 T _NtSetTimerResolution
+00012910 T _ZwSetTimerResolution
+0001291e T _NtSetValueKey
+0001291e T _ZwSetValueKey
+0001292c T _NtSetVolumeInformationFile
+0001292c T _ZwSetVolumeInformationFile
+0001293a T _NtShutdownSystem
+0001293a T _ZwShutdownSystem
+00012948 T _NtSignalAndWaitForSingleObject
+00012948 T _ZwSignalAndWaitForSingleObject
+00012956 T _NtStartProfile
+00012956 T _ZwStartProfile
+00012964 T _NtStopProfile
+00012964 T _ZwStopProfile
+00012972 T _NtSuspendThread
+00012972 T _ZwSuspendThread
+00012980 T _NtSystemDebugControl
+00012980 T _ZwSystemDebugControl
+0001298e T _NtTerminateProcess
+0001298e T _ZwTerminateProcess
+0001299c T _NtTerminateThread
+0001299c T _ZwTerminateThread
+000129aa T _NtTestAlert
+000129aa T _ZwTestAlert
+000129b8 T _NtUnloadDriver
+000129b8 T _ZwUnloadDriver
+000129c6 T _NtUnloadKey
+000129c6 T _ZwUnloadKey
+000129d4 T _NtUnlockFile
+000129d4 T _ZwUnlockFile
+000129e2 T _NtUnlockVirtualMemory
+000129e2 T _ZwUnlockVirtualMemory
+000129f0 T _NtUnmapViewOfSection
+000129f0 T _ZwUnmapViewOfSection
+000129fe T _NtVdmControl
+000129fe T _ZwVdmControl
+00012a0c T _NtWaitForMultipleObjects
+00012a0c T _ZwWaitForMultipleObjects
+00012a1a T _NtWaitForSingleObject
+00012a1a T _ZwWaitForSingleObject
+00012a28 T _NtWaitHighEventPair
+00012a28 T _ZwWaitHighEventPair
+00012a36 T _NtWaitLowEventPair
+00012a36 T _ZwWaitLowEventPair
+00012a44 T _NtWriteFile
+00012a44 T _ZwWriteFile
+00012a52 T _NtWriteFileGather
+00012a52 T _ZwWriteFileGather
+00012a60 T _NtWriteRequestData
+00012a60 T _ZwWriteRequestData
+00012a6e T _NtWriteVirtualMemory
+00012a6e T _ZwWriteVirtualMemory
+00012a7c T _NtW32Call
+00012a7c T _ZwW32Call
+00012a8a T _NtCreateChannel
+00012a8a T _ZwCreateChannel
+00012a98 T _NtListenChannel
+00012a98 T _ZwListenChannel
+00012aa6 T _NtOpenChannel
+00012aa6 T _ZwOpenChannel
+00012ab4 T _NtReplyWaitSendChannel
+00012ab4 T _ZwReplyWaitSendChannel
+00012ac2 T _NtSendWaitReplyChannel
+00012ac2 T _ZwSendWaitReplyChannel
+00012ad0 T _NtSetContextChannel
+00012ad0 T _ZwSetContextChannel
+00012ade T _NtYieldExecution
+00012ade T _ZwYieldExecution
+00012aec T etext
+00013000 d .data
+00013000 d .data
+00013000 d .data
+00013000 d ___HeapDefaultBuckets
+00013080 b .bss
+00013080 b .bss
+00013080 b .bss
+00013080 b .bss
+00013080 b .bss
+00013080 b .bss
+00013080 d .data
+00013080 d .data
+00013080 d .data
+00013080 d .data
+00013080 d .data
+00013080 d .data
+00013080 d .data
+00013080 b _LastError
+00013080 D _edata
+00013084 b .bss
+00013084 b .bss
+00013084 b .bss
+00013084 b .bss
+00013084 B ___ProcessHeap
+00013088 B end
diff --git a/reactos/doc/cacheman.txt b/reactos/doc/cacheman.txt
new file mode 100644 (file)
index 0000000..7b6d79f
--- /dev/null
@@ -0,0 +1,32 @@
+- Cache Manager
+
+This document describes the current implementation of the cache manager. 
+
+- Description
+
+In its current state the CM (cache manager) only includes primitives to
+cache disk blocks, this is useful for filesystem metadata but it requires an
+additional copy operation when reading files from cache. This will be fixed.
+
+Each disk drive with data in the cache has an associated DCCB (Device Cache
+Control Block) which details all the blocks from the device in memory. If a
+filesystem requires cache services for a device it must call CbInitDccb to
+initialize this structure.
+
+Each block with data from a device has an associated CCB (Cache Control
+Block) with a pointer to the physical memory used to hold the block, and
+various state and locking information. When a filesystem requires a block
+from the device it calls CbAcquireForRead or CbAcquireForWrite which ensure
+the data for the block is uptodate (loading it from disk if necessary) and
+return a pointer to the associated CCB. When a filesystem has finished with
+a block it calls CbReleaseFromRead or CbReleaseFromWrite, it is important to
+call these functions because the CM can only release blocks from the cache
+if they have no active readers or writers. The CM also enforces cache
+consistency by ensuring that while multiple threads can be reading a block
+simultaneously, there is only ever one active writers. 
+
+The CM provides no support for deadlock prevention/detection as it has no
+knowledge of the layout of a a filesystem (nor should it have).
+
+- TODO
+
diff --git a/reactos/drivers/dd/event/dirs b/reactos/drivers/dd/event/dirs
new file mode 100644 (file)
index 0000000..13a6cb5
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS=exe    \
+     sys
diff --git a/reactos/drivers/dd/event/exe/eventtes.c b/reactos/drivers/dd/event/exe/eventtes.c
new file mode 100644 (file)
index 0000000..8086ead
--- /dev/null
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 1996  Microsoft Corporation
+
+Module Name:
+
+    EventTest.c
+
+Abstract:
+
+    Simple console test app demonstrating how a Win32 app can share 
+    an event object with a kernel-mode driver. For more information 
+    on using Event Objects at the application level see the Win32 SDK.
+
+Author:
+
+    Jeff Midkiff    (jeffmi)    23-Jul-96
+
+Enviroment:
+
+    User Mode
+
+Revision History:
+
+--*/
+
+
+//
+// INCLUDES
+//
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <winioctl.h>
+#include <conio.h>
+
+#include "event.h"
+
+
+//
+// MAIN
+//
+void __cdecl 
+main(
+    int argc, 
+    char ** argv
+    )
+{
+    BOOL    bStatus;
+    HANDLE  hDevice;
+    ULONG   ulReturnedLength;
+
+    SET_EVENT setEvent;
+    FLOAT fDelay;
+    
+
+    if ( (argc < 2) || (argv[1] == NULL) ) {
+        printf("event <delay>\n");
+        printf("\twhere <delay> = time to delay the event signal in seconds.\n");
+        exit(0);
+    }
+    sscanf( argv[1], "%f", &fDelay );
+
+    //
+    // open the device
+    //
+    hDevice = CreateFile(
+                "\\\\.\\EVENT",                     // lpFileName
+                GENERIC_READ | GENERIC_WRITE,       // dwDesiredAccess
+                FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode
+                NULL,                               // lpSecurityAttributes
+                OPEN_EXISTING,                      // dwCreationDistribution
+                0,                                  // dwFlagsAndAttributes
+                NULL                                // hTemplateFile
+                );
+                
+    if (hDevice == INVALID_HANDLE_VALUE) {
+        printf("CreateFile error = %d\n", GetLastError() );
+        exit(0);
+    }
+
+
+    //
+    // set the event signal delay
+    //
+    setEvent.DueTime.QuadPart = -((LONGLONG)(fDelay * 10.0E6));// use relative time for this sample
+
+
+    //
+    // test the driver for bad event handles
+    //
+    setEvent.hEvent = NULL;
+    bStatus = DeviceIoControl(
+                        hDevice,                // Handle to device
+                        IOCTL_SET_EVENT,        // IO Control code
+                        &setEvent,              // Input Buffer to driver.
+                        SIZEOF_SETEVENT,        // Length of input buffer in bytes.
+                        NULL,                   // Output Buffer from driver.
+                        0,                      // Length of output buffer in bytes.
+                        &ulReturnedLength,      // Bytes placed in buffer.
+                        NULL                    // synchronous call
+                        );
+    if ( !bStatus ) {
+        printf("Bad handle TEST returned code %d.\n\n", GetLastError() );
+    } else {
+        printf("we should never get here\n");
+        exit(0);
+    }
+
+
+    //
+    // 
+    //
+    setEvent.hEvent = CreateEvent( 
+                            NULL,   // lpEventAttributes
+                            TRUE,   // bManualReset
+                            FALSE,  // bInitialState
+                            NULL    // lpName
+                            );
+
+
+    if ( !setEvent.hEvent ) {
+        printf("CreateEvent error = %d\n", GetLastError() );
+    } else {
+
+        printf("Event HANDLE = 0x%x\n",  setEvent.hEvent );
+        printf("Press any key to exit.\n");
+        while( !_kbhit() ) {
+            bStatus = DeviceIoControl(
+                            hDevice,                // Handle to device
+                            IOCTL_SET_EVENT,        // IO Control code
+                            &setEvent,              // Input Buffer to driver.
+                            SIZEOF_SETEVENT,        // Length of input buffer in bytes.
+                            NULL,                   // Output Buffer from driver.
+                            0,                      // Length of output buffer in bytes.
+                            &ulReturnedLength,      // Bytes placed in buffer.
+                            NULL                    // synchronous call
+                            );
+
+            if ( !bStatus ) {
+                printf("Ioctl failed with code %d\n", GetLastError() );
+                break;
+            } else {
+                printf("Waiting for Event...\n");
+
+                WaitForSingleObject(setEvent.hEvent,
+                                    INFINITE );
+
+                printf("Event signalled.\n\n");
+
+                ResetEvent( setEvent.hEvent);
+                //printf("Event reset.\n");
+            }
+        }
+    }
+
+    //
+    // close the driver
+    //
+    if ( !CloseHandle(hDevice) )     {
+        printf("Failed to close device.\n");
+    }
+
+    exit(0);
+}
+
+
+// EOF
\ No newline at end of file
diff --git a/reactos/drivers/dd/event/exe/makefile b/reactos/drivers/dd/event/exe/makefile
new file mode 100644 (file)
index 0000000..5818975
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/reactos/drivers/dd/event/exe/sources b/reactos/drivers/dd/event/exe/sources
new file mode 100644 (file)
index 0000000..8bbdfe0
--- /dev/null
@@ -0,0 +1,10 @@
+TARGETNAME=event
+TARGETPATH=$(BASEDIR)\lib
+TARGETTYPE=PROGRAM
+
+INCLUDES=..\sys
+
+SOURCES=eventtest.c
+
+UMTYPE=console
+UMBASE=0x100000
diff --git a/reactos/drivers/dd/event/readme.txt b/reactos/drivers/dd/event/readme.txt
new file mode 100644 (file)
index 0000000..c6451aa
--- /dev/null
@@ -0,0 +1,50 @@
+
+This sample demonstrates one way that a Windows NT kernel-mode device driver
+can share and explicitly signal an Event Object with a Win32 application.
+It is composed of two parts, a Windows NT kernel-mode device driver and a Win32 
+console test application. Both are built using the Windows NT DDK.
+
+
+Instructions:
+-------------
+
+1) Build the driver and test application in either the FREE or CHECKED build environment:
+
+        BLD
+
+    Both the driver and application are put in %NTDDK%\LIB\*\FREE | CHECKED on your build machine.
+
+
+2) Copy the newly built driver to your Target machine's %SystemRoot%\system32\drivers
+directory. Copy the newly built application to your target machine.
+Also copy the EVENT.INI file to your Target machine.
+
+
+3) Update the Target machine's Registry by running REGINI.EXE on the EVENT.INI file, i.e.:
+
+        REGINI EVENT.INI
+
+   This adds a driver key under the 
+   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services tree in the Registry.
+   You can verify this by running REGEDIT32.EXE and looking at the \Event key.
+
+
+4) Reboot the Target machine for the Registry changes to take effect.
+Your driver will not load until you reboot.
+
+
+5) Load the driver from the command line:
+
+        NET START EVENT
+
+
+6) Run the test app from the command line:
+
+        EVENT <DELAY>
+
+            where DELAY = time to delay the Event signal in seconds.
+
+
+7) Unload the driver from the command line:
+    
+        NET STOP EVENT
diff --git a/reactos/drivers/dd/event/sys/event.c b/reactos/drivers/dd/event/sys/event.c
new file mode 100644 (file)
index 0000000..e9298e7
--- /dev/null
@@ -0,0 +1,447 @@
+/*++
+
+Copyright (c) 1996  Microsoft Corporation
+
+Module Name:
+
+    Event.c
+
+Abstract:
+
+    This sample demonstrates one way that a Windows NT kernel-mode driver
+    can share and explicitly signal an Event Object with a Win32 application.
+
+    This sample uses the following method:
+        The application creates an event object using CreateEvent().
+        The app passes the event handle to the driver in a private IOCTL.
+        The driver is running in the app's thread context during the IOCTL so 
+        there is a valid user-mode handle at that time.
+        The driver dereferences the user-mode handle into system space & saves 
+        the new system handle for later use.
+        The driver signals the event via KeSetEvent() at IRQL <= DISPATCH_LEVEL.
+        The driver MUST delete any driver references to the event object at 
+        Unload time.
+
+    An alternative method would be to create a named event in the driver via 
+    IoCreateNotificationEvent and then open the event in user mode. This API 
+    however is new to Windows NT 4.0 so you can not use this method in your 
+    NT 3.5x drivers.
+    
+    Note that this sample's event can be signalled (almost) at will from within 
+    the driver. A different event signal can be set when the driver is setup to 
+    do asynchronous I/O, and it is opened with FILE_FLAG_OVERLAPPED, and an 
+    event handle is passed down in an OVERLAPPED struct from the app's Read, 
+    Write, or DeviceIoControl. This different event signal is set by the I/O 
+    Manager when the driver calls IoCompleteRequest on a pending Irp. This type 
+    of Irp completion signal is not the purpose of this sample, hence the lack of
+    Irp queing.
+
+Author:
+
+    Jeff Midkiff    (jeffmi)    23-Jul-96
+
+Enviroment:
+
+    Kernel Mode Only
+
+Revision History:
+
+--*/
+
+
+//
+// INCLUDES
+//
+#include "ntddk.h"
+#include "event.h"
+
+//
+// DEFINES
+//
+#define USER_NAME       L"\\DosDevices\\EVENT"
+#define SYSTEM_NAME     L"\\Device\\EVENT"
+
+//
+// DATA
+//
+typedef struct _DEVICE_EXTENSION {
+    KDPC    Dpc;
+    KTIMER  Timer;
+    HANDLE  hEvent;
+
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+
+//
+// PROTOS
+//
+NTSTATUS
+DriverEntry(
+    IN PDRIVER_OBJECT DriverObject,
+    IN PUNICODE_STRING RegistryPath
+    );
+
+NTSTATUS
+Unload(
+    IN PDRIVER_OBJECT DriverObject
+    );
+
+NTSTATUS
+Dispatch(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    );
+
+VOID
+CustomTimerDPC(
+    IN PKDPC Dpc,
+    IN PVOID DeferredContext,
+    IN PVOID SystemArgument1,
+    IN PVOID SystemArgument2
+    );
+
+\f
+NTSTATUS
+DriverEntry(
+    IN PDRIVER_OBJECT  DriverObject,
+    IN PUNICODE_STRING RegistryPath
+    )
+
+/*++
+
+Routine Description:
+
+    This routine gets called by the system to initialize the driver.
+
+Arguments:
+
+    DriverObject    - the system supplied driver object.
+    RegistryPath    - the system supplied registry path for this driver.
+
+Return Value:
+
+    NTSTATUS
+
+--*/
+
+{
+
+    PDEVICE_OBJECT      pDeviceObject;
+    PDEVICE_EXTENSION   pDeviceExtension;
+
+    UNICODE_STRING      usSystemName;
+    UNICODE_STRING      usUserName;
+
+    NTSTATUS            status;
+
+
+    KdPrint(("Event!DriverEntry - IN\n"));
+
+    //
+    // create the device object
+    //
+    RtlInitUnicodeString( &usSystemName, SYSTEM_NAME );
+
+    status = IoCreateDevice( 
+                DriverObject,               // DriverObject 
+                sizeof( DEVICE_EXTENSION ), // DeviceExtensionSize
+                &usSystemName,              // DeviceName
+                FILE_DEVICE_UNKNOWN,        // DeviceType
+                0,                          // DeviceCharacteristics
+                TRUE,                       // Exclusive
+                &pDeviceObject              // DeviceObject
+                );
+
+    if ( !NT_SUCCESS(status) ) {
+        KdPrint(("\tIoCreateDevice returned 0x%x\n", status));
+
+        return( status );
+    }
+
+    //
+    // Set up dispatch entry points for the driver.
+    //
+    DriverObject->MajorFunction[IRP_MJ_CREATE]          =
+    DriverObject->MajorFunction[IRP_MJ_CLOSE]           =
+    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = Dispatch;
+    DriverObject->DriverUnload = Unload;
+
+    //
+    // Create a symbolic link into user mode for the driver.
+    //
+    RtlInitUnicodeString( &usUserName, USER_NAME );
+    status = IoCreateSymbolicLink( &usUserName, &usSystemName );
+
+    if ( !NT_SUCCESS(status) ) {
+        IoDeleteDevice( pDeviceObject );
+        KdPrint(("\tIoCreateSymbolicLink returned 0x%x\n", status));
+
+        return( status );
+    }
+
+    //
+    // establish user-buffer access method
+    //
+    pDeviceObject->Flags |= DO_BUFFERED_IO;
+
+
+    //
+    // setup the device extension
+    //
+    pDeviceExtension = pDeviceObject->DeviceExtension;
+
+    KeInitializeDpc(
+        &pDeviceExtension->Dpc, // Dpc
+        CustomTimerDPC,         // DeferredRoutine
+        pDeviceObject           // DeferredContext
+        ); 
+
+    KeInitializeTimer(
+        &pDeviceExtension->Timer  // Timer
+        );
+
+    pDeviceExtension->hEvent = NULL;
+
+    KdPrint(("Event!DriverEntry - OUT\n"));
+
+    return( status );
+}
+
+
+\f
+NTSTATUS
+Unload(
+    IN PDRIVER_OBJECT DriverObject
+    )
+
+/*++
+
+Routine Description:
+
+    This routine gets called to remove the driver from the system.
+
+Arguments:
+
+    DriverObject    - the system supplied driver object.
+
+Return Value:
+
+    NTSTATUS
+
+--*/
+
+{
+
+    PDEVICE_OBJECT       pDeviceObject = DriverObject->DeviceObject;
+    PDEVICE_EXTENSION    pDeviceExtension = pDeviceObject->DeviceExtension;
+    UNICODE_STRING       usUserName;
+
+
+    KdPrint(("Event!Unload\n"));
+
+    //
+    // dereference the event object or it will NEVER go away until reboot
+    //
+    if ( pDeviceExtension->hEvent )
+    ObDereferenceObject( pDeviceExtension->hEvent );
+
+    // Delete the user-mode symbolic link.
+    RtlInitUnicodeString( &usUserName, USER_NAME );
+    IoDeleteSymbolicLink( &usUserName );
+
+    // Delete the DeviceObject
+    IoDeleteDevice( pDeviceObject );
+
+    return( STATUS_SUCCESS );
+}
+
+
+\f
+NTSTATUS
+Dispatch(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+    )
+
+/*++
+
+Routine Description:
+
+    This device control dispatcher handles IOCTLs.
+
+Arguments:
+
+    DeviceObject - Context for the activity.
+    Irp          - The device control argument block.
+
+Return Value:
+
+    NTSTATUS
+
+--*/
+
+{
+
+    PDEVICE_EXTENSION   pDeviceExtension;
+    PIO_STACK_LOCATION  pIrpStack;
+    PSET_EVENT          pSetEvent;
+
+    ULONG               ulInformation = 0L;
+    NTSTATUS            status = STATUS_NOT_IMPLEMENTED;
+
+
+    KdPrint(("Event!Dispatch - IN\n"));
+
+    pDeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
+    pIrpStack = IoGetCurrentIrpStackLocation( Irp );
+
+    switch( pIrpStack->MajorFunction )
+    {
+        case IRP_MJ_CREATE:
+        case IRP_MJ_CLOSE:
+            KdPrint(("\t%s\n", (IRP_MJ_CREATE == pIrpStack->MajorFunction) ? "IRP_MJ_CREATE" : "IRP_MJ_CLOSE"));
+
+            status = STATUS_SUCCESS;
+            break;
+
+        case IRP_MJ_DEVICE_CONTROL:
+            switch( pIrpStack->Parameters.DeviceIoControl.IoControlCode )
+            {
+                case IOCTL_SET_EVENT:
+                    KdPrint(("\tIOCTL_SET_EVENT\n"));
+
+                    if ( pIrpStack->Parameters.DeviceIoControl.InputBufferLength <  SIZEOF_SETEVENT ) {
+                        // Parameters are invalid
+                        KdPrint(("\tSTATUS_INVALID_PARAMETER\n"));
+
+                        status = STATUS_INVALID_PARAMETER;
+                    } else {
+                        pSetEvent = (PSET_EVENT)Irp->AssociatedIrp.SystemBuffer;
+                        KdPrint(("\tuser-mode HANDLE = 0x%x\n",  pSetEvent->hEvent ));
+
+                        status = ObReferenceObjectByHandle( pSetEvent->hEvent,
+                                                            SYNCHRONIZE,
+                                                            NULL,
+                                                            KernelMode,
+                                                            &pDeviceExtension->hEvent,
+                                                            NULL
+                                                            );
+                        if ( !NT_SUCCESS(status) ) {
+
+                            KdPrint(("\tUnable to reference User-Mode Event object, Error = 0x%x\n", status));
+
+                        } else {
+                        
+                            KdPrint(("\tkernel-mode HANDLE = 0x%x\n",  pDeviceExtension->hEvent ));
+
+                            //
+                            // Start the timer to run the CustomTimerDPC in DueTime seconds to
+                            // simulate an interrupt (which would queue a DPC).
+                            // The user's event object is signaled in the DPC.
+                            //
+
+                            // ensure relative time for this sample
+                            if ( pSetEvent->DueTime.QuadPart > 0 )
+                                pSetEvent->DueTime.QuadPart = -(pSetEvent->DueTime.QuadPart);
+                            KdPrint(("\tDueTime  = %d\n",  pSetEvent->DueTime.QuadPart ));
+
+                            KeSetTimer(
+                                &pDeviceExtension->Timer,   // Timer
+                                pSetEvent->DueTime,         // DueTime
+                                &pDeviceExtension->Dpc      // Dpc  
+                                );
+
+                           status = STATUS_SUCCESS;
+                        }
+                    }
+                    break;
+
+                default:
+                    // should never hit this
+                    ASSERT(0);
+                    status = STATUS_NOT_IMPLEMENTED;
+                    break;
+
+            } // switch IoControlCode
+            break;
+
+        default:
+            // should never hit this
+            ASSERT(0);
+            status = STATUS_NOT_IMPLEMENTED;
+            break;
+
+    } // switch MajorFunction
+
+
+    //
+    // complete the Irp
+    //
+    Irp->IoStatus.Status = status;
+    Irp->IoStatus.Information = ulInformation;
+    IoCompleteRequest( Irp, IO_NO_INCREMENT );
+
+    KdPrint(("Event!Dispatch - OUT\n"));
+    return status;
+}
+
+
+\f
+VOID
+CustomTimerDPC(
+    IN PKDPC Dpc,
+    IN PVOID DeferredContext,
+    IN PVOID SystemArgument1,
+    IN PVOID SystemArgument2
+    )
+
+/*++
+
+Routine Description:
+
+    This is the DPC associated with this drivers Timer object setup in DriverEntry.
+
+Arguments:
+
+    Dpc             -   our DPC object associated with our Timer
+    DeferredContext -   Context for the DPC that we setup in DriverEntry
+    SystemArgument1 -
+    SystemArgument2 -
+
+Return Value:
+
+    Nothing.
+
+--*/
+
+{
+
+    PDEVICE_OBJECT      pDeviceObject = DeferredContext;
+    PDEVICE_EXTENSION   pDeviceExtension = pDeviceObject->DeviceExtension;
+
+
+    KdPrint(("Event!CustomTimerDPC - IN\n"));
+
+    //
+    // Signal the Event created user-mode
+    //
+    // Note:  
+    // Do not call KeSetEvent from your ISR;
+    // you must call it at IRQL <= DISPATCH_LEVEL.
+    // Your ISR should queue a DPC and the DPC can
+    // then call KeSetEvent on the ISR's behalf.
+    //
+    KeSetEvent((PKEVENT)pDeviceExtension->hEvent,// Event
+                0,                                   // Increment
+                FALSE                                // Wait
+                );
+
+    // there is no Irp to complete here
+
+    KdPrint(("Event!CustomTimerDPC - OUT\n"));
+
+    return;
+}
+
+
+// EOF
\ No newline at end of file
diff --git a/reactos/drivers/dd/event/sys/event.h b/reactos/drivers/dd/event/sys/event.h
new file mode 100644 (file)
index 0000000..e4c4fd9
--- /dev/null
@@ -0,0 +1,43 @@
+/*++
+
+Copyright (c) 1996  Microsoft Corporation
+
+Module Name:
+
+   Event.h
+
+Abstract:
+
+
+Author:
+
+   Jeff Midkiff    (jeffmi)    23-Jul-96
+
+Enviroment:
+
+
+Revision History:
+
+--*/
+
+#ifndef __EVENT__
+#define __EVENT__
+
+
+#include "devioctl.h"
+
+typedef struct _SET_EVENT
+{
+    HANDLE  hEvent;
+    LARGE_INTEGER DueTime; // requested DueTime in 100-nanosecond units
+
+} SET_EVENT, *PSET_EVENT;
+
+#define SIZEOF_SETEVENT sizeof(SET_EVENT)
+
+
+#define IOCTL_SET_EVENT \
+   CTL_CODE( FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS )
+
+
+#endif // __EVENT__
diff --git a/reactos/drivers/dd/event/sys/event.ini b/reactos/drivers/dd/event/sys/event.ini
new file mode 100644 (file)
index 0000000..5f430d6
--- /dev/null
@@ -0,0 +1,7 @@
+; note - the service name matches the driver's file (.sys) name
+
+\Registry\Machine\System\CurrentControlSet\Services\Event
+    Type = REG_DWORD 0x00000001
+    Start = REG_DWORD 0x00000003
+    Group = Extended Base
+    ErrorControl = REG_DWORD 0x00000001
diff --git a/reactos/drivers/dd/event/sys/event.rc b/reactos/drivers/dd/event/sys/event.rc
new file mode 100644 (file)
index 0000000..5ffe2ea
--- /dev/null
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define        VER_FILETYPE                VFT_DRV
+#define        VER_FILESUBTYPE             VFT2_DRV_SYSTEM
+#define VER_FILEDESCRIPTION_STR     "Sample Event Driver"
+#define VER_INTERNALNAME_STR        "event.sys"
+
+#include "common.ver"
+
diff --git a/reactos/drivers/dd/event/sys/makefile b/reactos/drivers/dd/event/sys/makefile
new file mode 100644 (file)
index 0000000..5818975
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/reactos/drivers/dd/event/sys/sources b/reactos/drivers/dd/event/sys/sources
new file mode 100644 (file)
index 0000000..41d1c44
--- /dev/null
@@ -0,0 +1,6 @@
+TARGETNAME=event
+TARGETPATH=$(BASEDIR)\lib
+TARGETTYPE=DRIVER
+
+SOURCES=event.c \
+        event.rc
diff --git a/reactos/drivers/dd/ide/ide.c b/reactos/drivers/dd/ide/ide.c
new file mode 100644 (file)
index 0000000..427800e
--- /dev/null
@@ -0,0 +1,1826 @@
+//
+//  IDE.C - IDE Disk driver 
+//     written by Rex Jolliff
+//     with help from various documentation sources and a few peeks at
+//       linux and freebsd sources.
+// 
+//    This driver supports up to 4 controllers with up to 2 drives each.
+//    The device names are assigned as follows:
+//      \Devices\HarddiskX\Partition0
+//    for the raw device, and 
+//      \Devices\HarddiskX\PartitionY
+//    for partitions
+//    where:
+//      X is computed by counting the available drives from the following
+//          sequence: the controller number (0=0x1f0, 1=0x170, 2=0x1e8, 
+//          3=0x168) * 2 plus the drive number (0,1)
+//      Y is the partition number
+// 
+//     The driver exports the following function:
+// 
+//       DriverEntry() - NT device driver initialization routine
+// 
+//     And the following functions are exported implicitly:
+// 
+//       IDEStartIo() - called to start an I/O request packet
+//       IDEDispatchOpenClose() - Called to open/close the device.  a NOOP
+//       IDEDispatchReadWrite() - Called to read/write the device.
+//       IDEDispatchQueryInformation() - Called to get device information 
+//       IDEDispatchSetInformation() - Called to set device information
+//       IDEDispatchDeviceControl() - Called to execute device control requests
+// 
+//   Modification History:
+//     05/25/98  RJJ  Created.
+//     05/30/98  RJJ  Removed IRQ handler and inserted busy waits
+//                    just to get something working...
+//     07/18/98  RJJ  Made drastic changes so that the driver
+//                    resembles a WinNT driver.
+//     08/05/98  RJJ  Changed to .C extension
+//     09/19/98  RJJ  First release (run for cover!)
+//
+//   Test List:
+//     09/17/98  RJJ  Pri/MST: 14.12X19 WDC AC31000H  Test Passed
+//                    Pri/SLV: None.
+//     
+//
+//   To Do:
+// FIXME: reads/writes that cause multiple calls to setup to device should be tested.
+// FIXME: a timer should be used to watch for device timeouts and errors
+// FIXME: errors should be retried
+// FIXME: a drive reset/recalibrate should be attempted if errors occur
+// FIXME: Use DMA for transfers if drives support it
+// FIXME: should we support unloading of this driver???
+// FIXME: the device information should come from AUTODETECT (via registry)
+// FIXME: really big devices need to be handled correctly
+// FIXME: should get device info from the registry
+// FIXME: should report hardware usage to iomgr
+// FIXME: finish implementation of QueryInformation
+// FIXME: finish implementation of SetInformation
+// FIXME: finish implementation of DeviceControl
+
+#include <ddk/ntddk.h>
+
+//  --------------------------------  This stuff should be defined in NTDDK.H
+
+typedef DISK_GEOMETRY *PDISK_GEOMETRY;
+
+//  -------------------------------------------------------------------------
+
+#include <internal/kernel.h>
+#include <internal/hal/io.h>
+#include <internal/string.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "ide.h"
+#include "idep.h"
+#include "partitio.h"
+
+#define  VERSION  "V0.1.2"
+
+//  -------------------------------------------------------  File Static Data
+
+typedef struct _IDE_CONTROLLER_PARAMETERS 
+{
+  int              CommandPortBase;
+  int              CommandPortSpan;
+  int              ControlPortBase;
+  int              ControlPortSpan;
+  int              Vector;
+  int              IrqL;
+  int              SynchronizeIrqL;
+  KINTERRUPT_MODE  InterruptMode;
+  KAFFINITY        Affinity;
+} IDE_CONTROLLER_PARAMETERS, *PIDE_CONTROLLER_PARAMETERS;
+
+//  NOTE: Do not increase max drives above 2
+
+#define  IDE_MAX_DRIVES       2
+
+#define  IDE_MAX_CONTROLLERS  4
+IDE_CONTROLLER_PARAMETERS Controllers[IDE_MAX_CONTROLLERS] = 
+{
+  {0x01f0, 8, 0x03f0, 8, 14, 14, 15, LevelSensitive, 0xffff},
+  {0x0170, 8, 0x0370, 8, 15, 15, 15, LevelSensitive, 0xffff},
+  {0x01E8, 8, 0x03e8, 8, 11, 11, 15, LevelSensitive, 0xffff},
+  {0x0168, 8, 0x0368, 8, 10, 10, 15, LevelSensitive, 0xffff}
+};
+
+static int TotalPartitions = 0;
+
+//  -----------------------------------------------  Discardable Declarations
+
+#ifdef  ALLOC_PRAGMA
+
+//  make the initialization routines discardable, so that they 
+//  don't waste space
+
+#pragma  alloc_text(init, DriverEntry)
+#pragma  alloc_text(init, IDECreateController)
+#pragma  alloc_text(init, IDECreateDevices)
+#pragma  alloc_text(init, IDECreateDevice)
+#pragma  alloc_text(init, IDEPolledRead)
+
+//  make the PASSIVE_LEVEL routines pageable, so that they don't
+//  waste nonpaged memory
+
+#pragma  alloc_text(page, IDEShutdown)
+#pragma  alloc_text(page, IDEDispatchOpenClose)
+#pragma  alloc_text(page, IDEDispatchRead)
+#pragma  alloc_text(page, IDEDispatchWrite)
+
+#endif  /*  ALLOC_PRAGMA  */
+
+//  ---------------------------------------------------- Forward Declarations
+
+static BOOLEAN  IDECreateController(IN PDRIVER_OBJECT DriverObject, 
+                                    IN PIDE_CONTROLLER_PARAMETERS ControllerParams, 
+                                    IN int ControllerIdx);
+static BOOLEAN  IDEResetController(IN WORD CommandPort, IN WORD ControlPort);
+static BOOLEAN  IDECreateDevices(IN PDRIVER_OBJECT DriverObject, 
+                                 IN PCONTROLLER_OBJECT ControllerObject, 
+                                 IN PIDE_CONTROLLER_EXTENSION ControllerExtension, 
+                                 IN int DriveIdx,
+                                 IN int HarddiskIdx);
+static BOOLEAN  IDEGetDriveIdentification(IN int CommandPort, 
+                                          IN int DriveNum, 
+                                          OUT PIDE_DRIVE_IDENTIFY DrvParms);
+static BOOLEAN  IDEGetPartitionTable(IN int CommandPort, 
+                                     IN int DriveNum, 
+                                     IN int Offset, 
+                                     IN PIDE_DRIVE_IDENTIFY DrvParms,
+                                     PARTITION *PartitionTable);
+static NTSTATUS  IDECreateDevice(IN PDRIVER_OBJECT DriverObject, 
+                                 IN PCHAR DeviceName, 
+                                 OUT PDEVICE_OBJECT *DeviceObject, 
+                                 IN PCONTROLLER_OBJECT ControllerObject, 
+                                 IN int UnitNumber,
+                                 IN char *Win32Alias,
+                                 IN PIDE_DRIVE_IDENTIFY DrvParms, 
+                                 IN DWORD Offset, 
+                                 IN DWORD Size);
+static int IDEPolledRead(IN WORD Address, 
+                         IN BYTE PreComp, 
+                         IN BYTE SectorCnt, 
+                         IN BYTE SectorNum , 
+                         IN BYTE CylinderLow, 
+                         IN BYTE CylinderHigh, 
+                         IN BYTE DrvHead, 
+                         IN BYTE Command, 
+                         OUT BYTE *Buffer);
+
+static  NTSTATUS  IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
+static  NTSTATUS  IDEDispatchReadWrite(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
+static  NTSTATUS  IDEDispatchDeviceControl(IN PDEVICE_OBJECT pDO, IN PIRP Irp);
+static  VOID  IDEStartIo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
+static  IO_ALLOCATION_ACTION IDEAllocateController(IN PDEVICE_OBJECT DeviceObject,
+                                                   IN PIRP Irp, 
+                                                   IN PVOID MapRegisterBase, 
+                                                   IN PVOID Ccontext);
+static  BOOLEAN  IDEStartController(IN OUT PVOID Context);
+static  BOOLEAN  IDEIsr(IN PKINTERRUPT Interrupt, IN PVOID ServiceContext);
+static  VOID  IDEDpcForIsr(IN PKDPC Dpc, 
+                           IN PDEVICE_OBJECT DpcDeviceObject,
+                           IN PIRP DpcIrp, 
+                           IN PVOID DpcContext);
+static  VOID  IDEIoTimer(PDEVICE_OBJECT DeviceObject, PVOID Context);
+//  ----------------------------------------------------------------  Inlines
+
+extern inline void 
+IDESwapBytePairs(char *Buf, 
+                 int Cnt) 
+{
+  char  t;
+  int   i;
+
+  for (i = 0; i < Cnt; i += 2) 
+    {
+      t = Buf[i];
+      Buf[i] = Buf[i+1];
+      Buf[i+1] = t;
+    }
+}
+
+//  -------------------------------------------------------  Public Interface
+
+//    DriverEntry
+//
+//  DESCRIPTION:
+//    This function initializes the driver, locates and claims 
+//    hardware resources, and creates various NT objects needed
+//    to process I/O requests.
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    IN  PDRIVER_OBJECT   DriverObject  System allocated Driver Object
+//                                       for this driver
+//    IN  PUNICODE_STRING  RegistryPath  Name of registry driver service 
+//                                       key
+//
+//  RETURNS:
+//    NTSTATUS  
+
+NTSTATUS 
+DriverEntry(IN PDRIVER_OBJECT DriverObject, 
+            IN PUNICODE_STRING RegistryPath) 
+{
+  BOOLEAN        WeGotSomeDisks;
+  int            ControllerIdx;
+
+  DPRINT("IDE Driver %s\n", VERSION);
+
+    //  Export other driver entry points...
+  DriverObject->DriverStartIo = IDEStartIo;
+  DriverObject->MajorFunction[IRP_MJ_CREATE] = IDEDispatchOpenClose;
+  DriverObject->MajorFunction[IRP_MJ_CLOSE] = IDEDispatchOpenClose;
+  DriverObject->MajorFunction[IRP_MJ_READ] = IDEDispatchReadWrite;
+  DriverObject->MajorFunction[IRP_MJ_WRITE] = IDEDispatchReadWrite;
+//  DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = IDEDispatchQueryInformation;
+//  DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = IDEDispatchSetInformation;
+  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IDEDispatchDeviceControl;
+
+  WeGotSomeDisks = FALSE;
+  for (ControllerIdx = 0; ControllerIdx < IDE_MAX_CONTROLLERS; ControllerIdx++) 
+    {
+      WeGotSomeDisks |= IDECreateController(DriverObject, 
+          &Controllers[ControllerIdx], ControllerIdx);
+    }
+
+  return  WeGotSomeDisks ? STATUS_SUCCESS : STATUS_NO_SUCH_DEVICE;
+}
+
+//  ----------------------------------------------------  Discardable statics
+
+//    IDECreateController
+//
+//  DESCRIPTION:
+//    Creates a controller object and a device object for each valid
+//    device on the controller
+//
+//  RUN LEVEL:
+//    PASSIVE LEVEL
+//
+//  ARGUMENTS:
+//    IN  PDRIVER_OBJECT  DriverObject  The system created driver object
+//    IN  PIDE_CONTROLLER_PARAMETERS    The parameter block for this
+//                    ControllerParams  controller
+//    IN  int            ControllerIdx  The index of this controller
+//
+//  RETURNS:
+//    TRUE   Devices where found on this controller
+//    FALSE  The controller does not respond or there are no devices on it
+//
+
+BOOLEAN  
+IDECreateController(IN PDRIVER_OBJECT DriverObject, 
+                    IN PIDE_CONTROLLER_PARAMETERS ControllerParams, 
+                    IN int ControllerIdx) 
+{
+  BOOLEAN                    CreatedDevices, ThisDriveExists;
+  int                        DriveIdx;
+  NTSTATUS                   RC;
+  PCONTROLLER_OBJECT         ControllerObject;
+  PIDE_CONTROLLER_EXTENSION  ControllerExtension;
+
+    //  Try to reset the controller and return FALSE if it fails
+  if (!IDEResetController(ControllerParams->CommandPortBase,
+      ControllerParams->ControlPortBase)) 
+    {
+      DPRINT("Could not find controller %d at %04lx\n",
+          ControllerIdx, ControllerParams->ControlPortBase);
+      return FALSE;
+    }
+
+  ControllerObject = IoCreateController(sizeof(IDE_CONTROLLER_EXTENSION));
+  if (ControllerObject == NULL) 
+    {
+      DPRINT("Could not create controller object for controller %d\n",
+          ControllerIdx);
+      return FALSE;
+    }
+
+    //  Fill out Controller extension data
+  ControllerExtension = (PIDE_CONTROLLER_EXTENSION)
+      ControllerObject->ControllerExtension;
+  ControllerExtension->Number = ControllerIdx;
+  ControllerExtension->CommandPortBase = ControllerParams->CommandPortBase;
+  ControllerExtension->ControlPortBase = ControllerParams->ControlPortBase;
+  ControllerExtension->Vector = ControllerParams->Vector;
+  ControllerExtension->DMASupported = FALSE;
+  ControllerExtension->ControllerInterruptBug = FALSE;
+  ControllerExtension->OperationInProgress = FALSE;
+
+    //  Initialize the spin lock in the controller extension
+  KeInitializeSpinLock(&ControllerExtension->SpinLock);
+
+    //  Register an interrupt handler for this controller
+  RC = IoConnectInterrupt(&ControllerExtension->Interrupt,
+                          IDEIsr, 
+                          ControllerExtension, 
+                          &ControllerExtension->SpinLock, 
+                          ControllerExtension->Vector, 
+                          ControllerParams->IrqL, 
+                          ControllerParams->SynchronizeIrqL, 
+                          ControllerParams->InterruptMode, 
+                          FALSE, 
+                          ControllerParams->Affinity, 
+                          FALSE);
+  if (!NT_SUCCESS(RC)) 
+    {
+      DPRINT("Could not Connect Interrupt %d\n", ControllerExtension->Vector);
+      IoDeleteController(ControllerObject);
+      return FALSE;
+    }
+
+    //  Create device objects for each raw device (and for partitions) 
+  CreatedDevices = FALSE;
+  for (DriveIdx = 0; DriveIdx < IDE_MAX_DRIVES; DriveIdx++) 
+    {
+      ThisDriveExists = IDECreateDevices(DriverObject, 
+                                         ControllerObject,
+                                         ControllerExtension, 
+                                         DriveIdx, 
+                                         ControllerIdx * 2 + DriveIdx);
+      if (ThisDriveExists) 
+        {
+          CreatedDevices = TRUE;
+        }
+    }
+
+  if (!CreatedDevices) 
+    {
+      DPRINT("Did not find any devices for controller %d\n", ControllerIdx);
+      IoDisconnectInterrupt(ControllerExtension->Interrupt);
+      IoDeleteController(ControllerObject);
+    }
+
+  return  CreatedDevices;
+}
+
+//    IDEResetController
+//
+//  DESCRIPTION:
+//    Reset the controller and report completion status
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    IN  WORD  CommandPort  The address of the command port
+//    IN  WORD  ControlPort  The address of the control port
+//
+//  RETURNS:
+//
+
+BOOLEAN  
+IDEResetController(IN WORD CommandPort, 
+                   IN WORD ControlPort) 
+{
+  int  Retries;
+
+    //  Send the controller reset command
+  IDEWriteDriveControl(ControlPort, IDE_DC_SRST);
+  KeStallExecutionProcessor(50);
+  IDEWriteDriveControl(ControlPort, 0);
+
+    //  Loop on status register waiting for controller ready
+  for (Retries = 0; Retries < IDE_MAX_RESET_RETRIES; Retries++) 
+    {
+      if (!(IDEReadStatus(CommandPort) & IDE_SR_BUSY))
+        break;
+      KeStallExecutionProcessor(10);
+    }
+
+    //  return TRUE if controller came back to life. and
+    //  the registers are initialized correctly
+  return  Retries < IDE_MAX_RESET_RETRIES &&
+          IDEReadError(CommandPort) == 1 &&
+          IDEReadSectorCount(CommandPort) == 1 &&
+          IDEReadSectorNum(CommandPort) == 1 &&
+          IDEReadCylinderLow(CommandPort) == 0 &&
+          IDEReadCylinderHigh(CommandPort) == 0 &&
+          IDEReadDriveHead(CommandPort) == 0;
+}
+
+//    IDECreateDevices
+//
+//  DESCRIPTION:
+//    Create the raw device and any partition devices on this drive
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    IN  PDRIVER_OBJECT  DriverObject  The system created driver object
+//    IN  PCONTROLLER_OBJECT         ControllerObject
+//    IN  PIDE_CONTROLLER_EXTENSION  ControllerExtension
+//                                      The IDE controller extension for
+//                                      this device
+//    IN  int             DriveIdx      The index of the drive on this
+//                                      controller
+//    IN  int             HarddiskIdx   The NT device number for this
+//                                      drive
+//
+//  RETURNS:
+//    TRUE   Drive exists and devices were created
+//    FALSE  no devices were created for this device
+//
+
+BOOLEAN  
+IDECreateDevices(IN PDRIVER_OBJECT DriverObject, 
+                 IN PCONTROLLER_OBJECT ControllerObject,
+                 IN PIDE_CONTROLLER_EXTENSION ControllerExtension,
+                 IN int DriveIdx,
+                 IN int HarddiskIdx) 
+{
+  BOOLEAN                CreatedDevices;
+  char                   RawDeviceName[IDE_MAX_NAME_LENGTH];
+  char                   PrimaryDeviceName[IDE_MAX_NAME_LENGTH];
+  char                   LogicalDeviceName[IDE_MAX_NAME_LENGTH];
+  char                   Win32AliasName[IDE_MAX_NAME_LENGTH];
+  int                    CommandPort, PartitionIdx, PartitionNum;
+  int                    ExtPartitionIdx, ExtOffset;
+  NTSTATUS               RC;
+  IDE_DRIVE_IDENTIFY     DrvParms;
+  PDEVICE_OBJECT         RawDeviceObject;
+  PDEVICE_OBJECT         PrimaryDeviceObject;
+  PDEVICE_OBJECT         LogicalDeviceObject;
+  PIDE_DEVICE_EXTENSION  RawDeviceExtension;
+  PARTITION              PrimaryPartitionTable[4], *p;
+  PARTITION              ExtendedPartitionTable[4], *ep;
+  char                   DeviceDirName[IDE_MAX_NAME_LENGTH + 1];
+  ANSI_STRING            AnsiDeviceDirName;
+  UNICODE_STRING         UnicodeDeviceDirName;
+  OBJECT_ATTRIBUTES      DeviceDirAttributes;
+  HANDLE                 Handle;
+
+    //  Copy I/O port offsets for convenience
+  CommandPort = ControllerExtension->CommandPortBase;
+//  ControlPort = ControllerExtension->ControlPortBase;
+  DPRINT("probing IDE controller %d Addr %04lx Drive %d\n",
+         ControllerExtension->Number, 
+         CommandPort, 
+         DriveIdx);
+
+    //  Get the Drive Identification Data
+  if (!IDEGetDriveIdentification(CommandPort, DriveIdx, &DrvParms)) 
+    {
+      DPRINT("Giving up on drive %d on controller %d...\n", 
+             DriveIdx, 
+             ControllerExtension->Number);
+      return  FALSE;
+    }
+
+  CreatedDevices = FALSE;
+
+    //  Create the harddisk device directory
+  strcpy(DeviceDirName, IDE_NT_ROOTDIR_NAME);
+  strcat(DeviceDirName, IDE_NT_DEVICE_NAME);
+  DeviceDirName[strlen(DeviceDirName) + 1] = '\0';
+  DeviceDirName[strlen(DeviceDirName)] = '0' + HarddiskIdx;
+  RtlInitAnsiString(&AnsiDeviceDirName, DeviceDirName);
+  RC = RtlAnsiStringToUnicodeString(&UnicodeDeviceDirName, 
+                                    &AnsiDeviceDirName, 
+                                    TRUE);
+  if (!NT_SUCCESS(RC))
+    {
+      DPRINT("Could not convert ansi to unicode for device dir\n", 0);
+      return  FALSE;
+    }
+  InitializeObjectAttributes(&DeviceDirAttributes, 
+                             &UnicodeDeviceDirName, 
+                             0, 
+                             NULL, 
+                             NULL);
+  RC = ZwCreateDirectoryObject(&Handle, 0, &DeviceDirAttributes);
+  if (!NT_SUCCESS(RC))
+    {
+      DPRINT("Could not create device dir object\n", 0);
+      return FALSE;
+    }
+  RtlFreeUnicodeString(&UnicodeDeviceDirName);
+
+    //  Create the raw device
+  strcpy(RawDeviceName, IDE_NT_ROOTDIR_NAME);
+  strcat(RawDeviceName, IDE_NT_DEVICE_NAME);
+  RawDeviceName[strlen(RawDeviceName) + 1] = '\0';
+  RawDeviceName[strlen(RawDeviceName)] = '0' + HarddiskIdx;
+  strcat(RawDeviceName, IDE_NT_PARTITION_NAME);
+  RawDeviceName[strlen(RawDeviceName) + 1] = '\0';
+  RawDeviceName[strlen(RawDeviceName)] = '0';
+  RC = IDECreateDevice(DriverObject, 
+                       RawDeviceName, 
+                       &RawDeviceObject, 
+                       ControllerObject, 
+                       DriveIdx,
+                       NULL,
+                       &DrvParms,
+                       0, 
+                       DrvParms.LogicalCyls * DrvParms.LogicalHeads * DrvParms.SectorsPerTrack);
+  if (!NT_SUCCESS(RC)) 
+    {
+      DPRINT("IDECreateDevice call failed for raw device\n",0);
+    } 
+  else 
+    {
+      CreatedDevices = TRUE;
+      RawDeviceExtension = (PIDE_DEVICE_EXTENSION) 
+          RawDeviceObject->DeviceExtension;
+
+        //  Initialze the controller timer here (since it has to be
+        //    tied to a device)...
+      if (DriveIdx == 0) 
+        {
+          ControllerExtension->TimerState = IDETimerIdle;
+          ControllerExtension->TimerCount = 0;
+          ControllerExtension->TimerDevice = RawDeviceObject;
+//          IoInitializeTimer(RawDeviceObject, IDEIoTimer, ControllerExtension);
+        }
+    }
+
+    //  Get Main partition table for device
+  PartitionNum = 1;
+  if (!IDEGetPartitionTable(CommandPort, DriveIdx, 0, &DrvParms, PrimaryPartitionTable)) 
+    {
+      DPRINT("drive %d controller %d: Could not get primary partition table\n", 
+             DriveIdx, 
+             ControllerExtension->Number);
+    } 
+  else 
+    {
+
+        //  build devices for all partitions in table
+      DPRINT("partitions on Harddisk%d:\n", HarddiskIdx);
+      for (PartitionIdx = 0; PartitionIdx < 4; PartitionIdx++) 
+        {
+
+            //  copy partition pointer for convenience
+          p = &PrimaryPartitionTable[PartitionIdx];
+
+            //  if the partition entry is in use, create a device for it
+          if (PartitionIsSupported(p)) 
+            {
+              DPRINT("Harddisk%d type:%02x Offset:%d Size:%d\n",
+                     HarddiskIdx, 
+                     p->PartitionType, 
+                     p->StartingBlock, 
+                     p->SectorCount);
+
+                //  Create Device for partition
+              strcpy(PrimaryDeviceName, IDE_NT_ROOTDIR_NAME);
+              strcat(PrimaryDeviceName, IDE_NT_DEVICE_NAME);
+              PrimaryDeviceName[strlen(PrimaryDeviceName) + 1] = '\0';
+              PrimaryDeviceName[strlen(PrimaryDeviceName)] = '0' + HarddiskIdx;
+              strcat(PrimaryDeviceName, IDE_NT_PARTITION_NAME);
+              PrimaryDeviceName[strlen(PrimaryDeviceName) + 1] = '\0';
+              PrimaryDeviceName[strlen(PrimaryDeviceName)] = '0' + PartitionNum++;
+              strcpy(Win32AliasName, "\\??\\ :");
+              Win32AliasName[4] = 'C' + TotalPartitions;
+              TotalPartitions++;
+              RC = IDECreateDevice(DriverObject, 
+                                   PrimaryDeviceName, 
+                                   &PrimaryDeviceObject, 
+                                   ControllerObject, 
+                                   DriveIdx,
+                                   Win32AliasName,
+                                   &DrvParms,
+                                   p->StartingBlock, 
+                                   p->SectorCount);
+              if (!NT_SUCCESS(RC)) 
+                {
+                  DPRINT("IDECreateDevice call failed\n",0);
+                  break;
+                }
+
+                //  Create devices for logical partitions within an extended partition
+            } 
+          else if (p->PartitionType == PTDosExtended) 
+            {
+              ExtOffset = p->StartingBlock;
+
+                //  Get the Extended partition table
+              if (!IDEGetPartitionTable(CommandPort, 
+                                        DriveIdx, 
+                                        ExtOffset, 
+                                        &DrvParms,
+                                        ExtendedPartitionTable)) 
+                {
+                  DPRINT("Harddisk%d: could not get extended partition table at offset %d", 
+                  HarddiskIdx, ExtOffset);
+                } 
+              else 
+                {
+                  for (ExtPartitionIdx = 0; ExtPartitionIdx < 4; ExtPartitionIdx++) 
+                    {
+                      ep = &ExtendedPartitionTable[ExtPartitionIdx];
+                      if (PartitionIsSupported(ep)) 
+                        {
+                          DPRINT("Harddisk%d: Type:%02x Offset:%d Size:%d\n", 
+                                 HarddiskIdx, 
+                                 ep->PartitionType, 
+                                 ep->StartingBlock + ExtOffset, 
+                                 ep->SectorCount);
+
+                            //  Create device for logical partition
+                          strcpy(LogicalDeviceName, IDE_NT_ROOTDIR_NAME);
+                          strcat(LogicalDeviceName, IDE_NT_DEVICE_NAME);
+                          LogicalDeviceName[strlen(LogicalDeviceName) + 1] = '\0';
+                          LogicalDeviceName[strlen(LogicalDeviceName)] = '0' + HarddiskIdx;
+                          strcat(LogicalDeviceName, IDE_NT_PARTITION_NAME);
+                          LogicalDeviceName[strlen(LogicalDeviceName) + 1] = '\0';
+                          LogicalDeviceName[strlen(LogicalDeviceName)] = '0' + PartitionNum++;
+                          strcpy(Win32AliasName, "\\??\\ :");
+                          Win32AliasName[4] = 'C' + TotalPartitions;
+                          TotalPartitions++;
+                          RC = IDECreateDevice(DriverObject, 
+                                               LogicalDeviceName, 
+                                               &LogicalDeviceObject, 
+                                               ControllerObject, 
+                                               DriveIdx,
+                                               Win32AliasName,
+                                               &DrvParms,
+                                               ep->StartingBlock + ExtOffset, 
+                                               ep->SectorCount);
+                          if (!NT_SUCCESS(RC)) 
+                            {
+                              DPRINT("IDECreateDevice call failed\n",0);
+                              break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+  return  TRUE;
+}
+
+//    IDEGetDriveIdentification
+//
+//  DESCRIPTION:
+//    Get the identification block from the drive
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    IN   int                  CommandPort  Address of the command port
+//    IN   int                  DriveNum     The drive index (0,1)
+//    OUT  PIDE_DRIVE_IDENTIFY  DrvParms     Address to write drive ident block
+//
+//  RETURNS:
+//    TRUE  The drive identification block was retrieved successfully
+//
+
+BOOLEAN  
+IDEGetDriveIdentification(IN int CommandPort, 
+                          IN int DriveNum, 
+                          OUT PIDE_DRIVE_IDENTIFY DrvParms) 
+{
+
+    //  Get the Drive Identify block from drive or die
+  if (IDEPolledRead(CommandPort, 0, 0, 0, 0, 0, (DriveNum ? IDE_DH_DRV1 : 0),
+                    IDE_CMD_IDENT_DRV, (BYTE *)DrvParms) != 0) 
+    {
+      return FALSE;
+    }
+
+    //  Report on drive parameters if debug mode
+  IDESwapBytePairs(DrvParms->SerialNumber, 20);
+  IDESwapBytePairs(DrvParms->FirmwareRev, 8);
+  IDESwapBytePairs(DrvParms->ModelNumber, 40);
+  DPRINT("Config:%04x  Cyls:%5d  Heads:%2d  Sectors/Track:%3d  Gaps:%02d %02d\n", 
+         DrvParms->ConfigBits, 
+         DrvParms->LogicalCyls, 
+         DrvParms->LogicalHeads, 
+         DrvParms->SectorsPerTrack, 
+         DrvParms->InterSectorGap, 
+         DrvParms->InterSectorGapSize);
+  DPRINT("Bytes/PLO:%3d  Vendor Cnt:%2d  Serial number:[%.20s]\n", 
+         DrvParms->BytesInPLO, 
+         DrvParms->VendorUniqueCnt, 
+         DrvParms->SerialNumber);
+  DPRINT("Cntlr type:%2d  BufSiz:%5d  ECC bytes:%3d  Firmware Rev:[%.8s]\n", 
+         DrvParms->ControllerType, 
+         DrvParms->BufferSize * IDE_SECTOR_BUF_SZ, 
+         DrvParms->ECCByteCnt, 
+         DrvParms->FirmwareRev);
+  DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber);
+  DPRINT("RWMult?:%02x  DWrdIO?:%d  LBA:%d  DMA:%d  MinPIO:%d ns  MinDMA:%d ns\n", 
+         (DrvParms->RWMultImplemented) & 0xff, 
+         DrvParms->DWordIOSupported, 
+         (DrvParms->LBADMASupported & 0x0200) ? 1 : 0,
+         (DrvParms->LBADMASupported & 0x0100) ? 1 : 0, 
+         DrvParms->MinPIOTransTime,
+         DrvParms->MinDMATransTime);
+  DPRINT("TM:Cyls:%d  Heads:%d  Sectors/Trk:%d Capacity:%d\n",
+         DrvParms->TMCylinders, 
+         DrvParms->TMHeads, 
+         DrvParms->TMSectorsPerTrk,
+         DrvParms->TMCapacity);
+
+  return TRUE;
+}
+
+//    IDEGetPartitionTable
+//
+//  DESCRIPTION:
+//    Gets the partition table from the device at the given offset if one exists
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    IN   int        CommandPort     Address of command port for controller
+//    IN   int        DriveNum        index of drive (0,1)
+//    IN   int        Offset          Block offset (LBA addressing)
+//    OUT  PARTITION *PartitionTable  address to write partition table
+//
+//  RETURNS:
+//    TRUE  partition table was retrieved successfully
+//
+
+BOOLEAN  
+IDEGetPartitionTable(IN int CommandPort, 
+                     IN int DriveNum, 
+                     IN int Offset, 
+                     IN PIDE_DRIVE_IDENTIFY DrvParms,
+                     OUT PARTITION *PartitionTable) 
+{
+  BYTE  SectorBuf[512], SectorNum, DrvHead, CylinderLow, CylinderHigh;
+  int   RC, SaveOffset;
+
+#ifndef NDEBUG
+  int   i;
+#endif
+
+    //  Get sector at offset
+  SaveOffset = Offset;
+  if (DrvParms->LBADMASupported & 0x0200) 
+    {
+      SectorNum = Offset & 0xff;
+      CylinderLow = (Offset >> 8) & 0xff;
+      CylinderHigh = (Offset >> 16) & 0xff;
+      DrvHead = ((Offset >> 24) & 0x0f) | 
+          (DriveNum ? IDE_DH_DRV1 : 0) |
+          IDE_DH_LBA;
+    } 
+  else 
+    {
+      SectorNum = (Offset % DrvParms->SectorsPerTrack) + 1;
+      Offset /= DrvParms->SectorsPerTrack;
+      DrvHead = (Offset % DrvParms->LogicalHeads) | 
+          (DriveNum ? IDE_DH_DRV1 : 0);
+      Offset /= DrvParms->LogicalHeads;
+      CylinderLow = Offset & 0xff;
+      CylinderHigh = Offset >> 8;
+    }
+  Offset = SaveOffset;
+
+  RC = IDEPolledRead(CommandPort, 
+                     0, 
+                     1, 
+                     SectorNum,
+                     CylinderLow,
+                     CylinderHigh,
+                     DrvHead, 
+                     IDE_CMD_READ_RETRY,
+                     SectorBuf);
+  if (RC != 0) 
+    {
+      DbgPrint("read failed: port %04x drive %d sector %d rc %d\n", 
+             CommandPort, 
+             DriveNum, 
+             Offset, 
+             RC);
+      return  FALSE;
+    } 
+  else if (*((WORD *)(SectorBuf + PART_MAGIC_OFFSET)) != PARTITION_MAGIC) 
+    {
+      DbgPrint("Bad partition magic: port %04x drive %d offset %d magic %d\n", 
+             CommandPort, 
+             DriveNum, 
+             Offset, 
+             *((short *)(SectorBuf + PART_MAGIC_OFFSET)));
+      return  FALSE;
+    }
+  RtlCopyMemory(PartitionTable, SectorBuf + PARTITION_OFFSET, sizeof(PARTITION) * 4);
+
+#ifndef NDEBUG
+  DPRINT("Partition Table for device %d at offset %d on port %x\n", 
+         DriveNum, 
+         Offset,
+         CommandPort);
+  for (i = 0; i < PARTITION_TBL_SIZE; i++)
+    {
+      DPRINT("  %d: flags:%2x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n", 
+             i, 
+             PartitionTable[i].BootFlags,
+             PartitionTable[i].PartitionType,
+             PartitionTable[i].StartingHead,
+             PartitionTable[i].StartingSector,
+             PartitionTable[i].StartingCylinder,
+             PartitionTable[i].EndingHead,
+             PartitionTable[i].EndingSector,
+             PartitionTable[i].EndingCylinder,
+             PartitionTable[i].StartingBlock,
+             PartitionTable[i].SectorCount);
+    }
+#endif
+
+  return  TRUE;
+}
+
+//    IDECreateDevice
+//
+//  DESCRIPTION:
+//    Creates a device by calling IoCreateDevice and a sylbolic link for Win32
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    IN   PDRIVER_OBJECT      DriverObject      The system supplied driver object
+//    IN   PCHAR               DeviceName        The name of the device
+//    OUT  PDEVICE_OBJECT     *DeviceObject      The created device object
+//    IN   PCONTROLLER_OBJECT  ControllerObject  The Controller for the device
+//    IN   BOOLEAN             LBASupported      Does the drive support LBA addressing?
+//    IN   BOOLEAN             DMASupported      Does the drive support DMA?
+//    IN   int                 SectorsPerLogCyl  Sectors per cylinder
+//    IN   int                 SectorsPerLogTrk  Sectors per track
+//    IN   DWORD               Offset            First valid sector for this device
+//    IN   DWORD               Size              Count of valid sectors for this device
+//
+//  RETURNS:
+//    NTSTATUS
+//
+
+NTSTATUS  
+IDECreateDevice(IN PDRIVER_OBJECT DriverObject, 
+                IN PCHAR DeviceName, 
+                OUT PDEVICE_OBJECT *DeviceObject, 
+                IN PCONTROLLER_OBJECT ControllerObject, 
+                IN int UnitNumber,
+                IN char *Win32Alias,
+                IN PIDE_DRIVE_IDENTIFY DrvParms,
+                IN DWORD Offset, 
+                IN DWORD Size) 
+{
+  WORD                   UnicodeBuffer[IDE_MAX_NAME_LENGTH];
+  NTSTATUS               RC;
+  ANSI_STRING            AnsiName, AnsiSymLink;
+  UNICODE_STRING         UnicodeName, SymLink;
+  PIDE_DEVICE_EXTENSION  DeviceExtension;
+
+    // Create a unicode device name
+  RtlInitAnsiString(&AnsiName, DeviceName);
+  UnicodeName.MaximumLength = IDE_MAX_NAME_LENGTH;
+  UnicodeName.Buffer = UnicodeBuffer;
+  RtlAnsiStringToUnicodeString(&UnicodeName, &AnsiName, FALSE);
+
+    // Create the device
+  RC = IoCreateDevice(DriverObject, sizeof(IDE_DEVICE_EXTENSION), 
+      &UnicodeName, FILE_DEVICE_DISK, 0, TRUE, DeviceObject);
+  if (!NT_SUCCESS(RC)) 
+    {
+      DPRINT("IoCreateDevice call failed\n",0);
+      return RC;
+    }
+
+    //  Set the buffering strategy here...
+  (*DeviceObject)->Flags |= DO_DIRECT_IO;
+  (*DeviceObject)->AlignmentRequirement = FILE_WORD_ALIGNMENT;
+
+    //  Fill out Device extension data
+  DeviceExtension = (PIDE_DEVICE_EXTENSION) (*DeviceObject)->DeviceExtension;
+  DeviceExtension->DeviceObject = (*DeviceObject);
+  DeviceExtension->ControllerObject = ControllerObject;
+  DeviceExtension->UnitNumber = UnitNumber;
+  DeviceExtension->LBASupported = (DrvParms->LBADMASupported & 0x0200) ? 1 : 0;
+  DeviceExtension->DMASupported = (DrvParms->LBADMASupported & 0x0100) ? 1 : 0;
+    // FIXME: deal with bizarre sector sizes
+  DeviceExtension->BytesPerSector = 512 /* DrvParms->BytesPerSector */;
+  DeviceExtension->SectorsPerLogCyl = DrvParms->LogicalHeads * 
+      DrvParms->SectorsPerTrack;
+  DeviceExtension->SectorsPerLogTrk = DrvParms->SectorsPerTrack;
+  DeviceExtension->LogicalHeads = DrvParms->LogicalHeads;
+  DeviceExtension->Offset = Offset;
+  DeviceExtension->Size = Size;
+  DPRINT("%s: offset %d size %d \n", 
+         DeviceName, 
+         DeviceExtension->Offset,
+         DeviceExtension->Size);
+
+    // FIXME: Create Win32 symbolic link (destroy device if it fails)
+
+  if (Win32Alias != NULL)
+    {
+      RtlInitAnsiString(&AnsiSymLink, Win32Alias);
+      RtlAnsiStringToUnicodeString(&SymLink, &AnsiSymLink, TRUE);
+      DbgPrint("SymbolicLink (%w -> %w)\n",SymLink.Buffer,UnicodeName.Buffer);
+      IoCreateSymbolicLink(&SymLink, &UnicodeName);
+      RtlFreeUnicodeString(&SymLink);
+    }
+
+    //  Initialize the DPC object here
+  IoInitializeDpcRequest(*DeviceObject, IDEDpcForIsr);
+
+  return  RC;
+}
+
+
+//    IDEPolledRead
+//
+//  DESCRIPTION:
+//    Read a sector of data from the drive in a polled fashion.
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    IN   WORD  Address       Address of command port for drive
+//    IN   BYTE  PreComp       Value to write to precomp register
+//    IN   BYTE  SectorCnt     Value to write to sectorCnt register
+//    IN   BYTE  SectorNum     Value to write to sectorNum register
+//    IN   BYTE  CylinderLow   Value to write to CylinderLow register
+//    IN   BYTE  CylinderHigh  Value to write to CylinderHigh register
+//    IN   BYTE  DrvHead       Value to write to Drive/Head register
+//    IN   BYTE  Command       Value to write to Command register
+//    OUT  BYTE  *Buffer       Buffer for output data
+//
+//  RETURNS:
+//    int  0 is success, non 0 is an error code
+//
+
+static int 
+IDEPolledRead(IN WORD Address, 
+              IN BYTE PreComp, 
+              IN BYTE SectorCnt, 
+              IN BYTE SectorNum , 
+              IN BYTE CylinderLow, 
+              IN BYTE CylinderHigh, 
+              IN BYTE DrvHead, 
+              IN BYTE Command, 
+              OUT BYTE *Buffer) 
+{
+  BYTE   Status;
+  int    RetryCount;
+
+  /*  Wait for STATUS.BUSY to clear  */
+  for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) 
+    {
+      Status = IDEReadStatus(Address);
+      if (!(Status & IDE_SR_BUSY))
+        {
+          break;
+        }
+      KeStallExecutionProcessor(10);
+    }
+  if (RetryCount == IDE_MAX_BUSY_RETRIES) 
+    {
+      return IDE_ER_ABRT;
+    }
+
+  /*  Write Drive/Head to select drive  */
+  IDEWriteDriveHead(Address, IDE_DH_FIXED | DrvHead);
+
+  /*  Wait for STATUS.BUSY to clear and STATUS.DRDY to assert  */
+  for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) 
+    {
+      Status = IDEReadStatus(Address);
+      if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY))
+        {
+          break;
+        }
+      KeStallExecutionProcessor(10);
+    }
+  if (RetryCount == IDE_MAX_BUSY_RETRIES) 
+    {
+      return IDE_ER_ABRT;
+    }
+
+  /*  Issue command to drive  */
+  if (DrvHead & IDE_DH_LBA) 
+    {
+      DPRINT("READ:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
+             DrvHead & IDE_DH_DRV1 ? 1 : 0, 
+             ((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
+             SectorCnt, 
+             Command);
+    } 
+  else 
+    {
+      DPRINT("READ:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
+             DrvHead & IDE_DH_DRV1 ? 1 : 0, 
+             CylinderHigh, 
+             CylinderLow, 
+             DrvHead & 0x0f, 
+             SectorNum, 
+             SectorCnt, 
+             Command);
+    }
+
+  /*  Setup command parameters  */
+  IDEWritePrecomp(Address, PreComp);
+  IDEWriteSectorCount(Address, SectorCnt);
+  IDEWriteSectorNum(Address, SectorNum);
+  IDEWriteCylinderHigh(Address, CylinderHigh);
+  IDEWriteCylinderLow(Address, CylinderLow);
+  IDEWriteDriveHead(Address, IDE_DH_FIXED | DrvHead);
+
+  /*  Issue the command  */
+  IDEWriteCommand(Address, Command);
+  KeStallExecutionProcessor(50);
+
+  while (1) 
+    {
+
+        //  wait for DRQ or error
+      for (RetryCount = 0; RetryCount < IDE_MAX_DRQ_RETRIES; RetryCount++)
+        {
+          Status = IDEReadStatus(Address);
+          if (!(Status & IDE_SR_BUSY)) 
+            {
+              if (Status & IDE_SR_ERR) 
+                {
+                  BYTE  Err = IDEReadError(Address);
+                  return Err;
+                } 
+              else if (Status & IDE_SR_DRQ) 
+                {
+                  break;
+                }
+            }
+          KeStallExecutionProcessor(10);
+        }
+      if (RetryCount >= IDE_MAX_DRQ_RETRIES)
+        {
+          return IDE_ER_ABRT;
+        }
+
+        //  Read data into buffer
+      IDEReadBlock(Address, Buffer);
+      Buffer += IDE_SECTOR_BUF_SZ;
+
+        //  Check for more sectors to read
+      for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES &&
+          (IDEReadStatus(Address) & IDE_SR_DRQ); RetryCount++)
+        ;
+      if (!(IDEReadStatus(Address) & IDE_SR_BUSY)) 
+        {
+          return 0;
+        }
+    }
+}
+
+//  -------------------------------------------  Nondiscardable statics
+
+//    IDEDispatchOpenClose
+//
+//  DESCRIPTION:
+//    Answer requests for Open/Close calls: a null operation
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    Standard dispatch arguments
+//
+//  RETURNS:
+//    NTSTATUS
+//
+
+static  NTSTATUS  
+IDEDispatchOpenClose(IN PDEVICE_OBJECT pDO, 
+                     IN PIRP Irp) 
+{
+  Irp->IoStatus.Status = STATUS_SUCCESS;
+  Irp->IoStatus.Information = FILE_OPENED;
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return STATUS_SUCCESS;
+}
+
+//    IDEDispatchReadWrite
+//
+//  DESCRIPTION:
+//    Answer requests for reads and writes
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    Standard dispatch arguments
+//
+//  RETURNS:
+//    NTSTATUS
+//
+
+static  NTSTATUS  
+IDEDispatchReadWrite(IN PDEVICE_OBJECT pDO, 
+                     IN PIRP Irp) 
+{
+  ULONG                  IrpInsertKey;
+  LARGE_INTEGER          AdjustedOffset, AdjustedExtent, PartitionExtent, InsertKeyLI;
+  PIO_STACK_LOCATION     IrpStack;
+  PIDE_DEVICE_EXTENSION  DeviceExtension;
+
+  IrpStack = IoGetCurrentIrpStackLocation(Irp);
+  DeviceExtension = (PIDE_DEVICE_EXTENSION)pDO->DeviceExtension;
+  DPRINT("MajorFunction %d\n", IrpStack->MajorFunction);
+
+    //  Validate operation parameters
+  AdjustedOffset = RtlEnlargedIntegerMultiply(DeviceExtension->Offset, 
+                                              DeviceExtension->BytesPerSector);
+  AdjustedOffset = RtlLargeIntegerAdd(AdjustedOffset, 
+                                      IrpStack->Parameters.Read.ByteOffset);
+  AdjustedExtent = RtlLargeIntegerAdd(AdjustedOffset, 
+                                      RtlConvertLongToLargeInteger(IrpStack->Parameters.Read.Length));
+    // FIXME: this assumption will fail on drives bigger than 1TB
+  PartitionExtent.HighPart = 0;
+  PartitionExtent.LowPart = DeviceExtension->Offset + DeviceExtension->Size;
+  PartitionExtent = RtlExtendedIntegerMultiply(PartitionExtent, 
+                                               DeviceExtension->BytesPerSector);
+  if (RtlLargeIntegerGreaterThan(AdjustedExtent, PartitionExtent) ||
+      (IrpStack->Parameters.Read.Length & (DeviceExtension->BytesPerSector - 1))) 
+    {
+      DPRINT("Request failed on bad parameters\n",0);
+      Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);
+      return  STATUS_INVALID_PARAMETER;
+    }
+
+    //  Adjust operation to absolute sector offset
+  IrpStack->Parameters.Read.ByteOffset = AdjustedOffset;
+
+    //  Start the packet and insert the request in order of sector offset
+  assert(DeviceExtension->BytesPerSector == 512);
+  InsertKeyLI = RtlLargeIntegerShiftRight(IrpStack->Parameters.Read.ByteOffset, 9); 
+  IrpInsertKey = InsertKeyLI.LowPart;
+  IoStartPacket(DeviceExtension->DeviceObject, Irp, &IrpInsertKey, NULL);
+
+  return  STATUS_PENDING;
+}
+
+//    IDEDispatchDeviceControl
+//
+//  DESCRIPTION:
+//    Answer requests for device control calls
+//
+//  RUN LEVEL:
+//    PASSIVE_LEVEL
+//
+//  ARGUMENTS:
+//    Standard dispatch arguments
+//
+//  RETURNS:
+//    NTSTATUS
+//
+
+static  NTSTATUS  
+IDEDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, 
+                         IN PIRP Irp) 
+{
+  NTSTATUS  RC;
+  ULONG     ControlCode, InputLength, OutputLength;
+  PIO_STACK_LOCATION     IrpStack;
+  PIDE_DEVICE_EXTENSION  DeviceExtension;
+
+  RC = STATUS_SUCCESS;
+  IrpStack = IoGetCurrentIrpStackLocation(Irp);
+  ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
+  InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
+  OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
+  DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    //  A huge switch statement in a Windows program?! who would have thought?
+  switch (ControlCode) 
+    {
+    case IOCTL_DISK_GET_DRIVE_GEOMETRY:
+      if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) 
+        {
+          Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+        } 
+      else 
+        {
+          PDISK_GEOMETRY Geometry;
+
+          Geometry = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
+          Geometry->MediaType = FixedMedia;
+              // FIXME: should report for RawDevice even on partition
+          QUAD_PART(Geometry->Cylinders) = DeviceExtension->Size / 
+              DeviceExtension->SectorsPerLogCyl;
+          Geometry->TracksPerCylinder = DeviceExtension->SectorsPerLogTrk /
+              DeviceExtension->SectorsPerLogCyl;
+          Geometry->SectorsPerTrack = DeviceExtension->SectorsPerLogTrk;
+          Geometry->BytesPerSector = DeviceExtension->BytesPerSector;
+
+          Irp->IoStatus.Status = STATUS_SUCCESS;
+          Irp->IoStatus.Information = sizeof(DISK_GEOMETRY);
+        }
+      break;
+
+    case IOCTL_DISK_GET_PARTITION_INFO:
+    case IOCTL_DISK_SET_PARTITION_INFO:
+    case IOCTL_DISK_GET_DRIVE_LAYOUT:
+    case IOCTL_DISK_SET_DRIVE_LAYOUT:
+    case IOCTL_DISK_VERIFY:
+    case IOCTL_DISK_FORMAT_TRACKS:
+    case IOCTL_DISK_PERFORMANCE:
+    case IOCTL_DISK_IS_WRITABLE:
+    case IOCTL_DISK_LOGGING:
+    case IOCTL_DISK_FORMAT_TRACKS_EX:
+    case IOCTL_DISK_HISTOGRAM_STRUCTURE:
+    case IOCTL_DISK_HISTOGRAM_DATA:
+    case IOCTL_DISK_HISTOGRAM_RESET:
+    case IOCTL_DISK_REQUEST_STRUCTURE:
+    case IOCTL_DISK_REQUEST_DATA:
+
+      //  If we get here, something went wrong.  inform the requestor
+    default:
+      RC = STATUS_INVALID_DEVICE_REQUEST;
+      Irp->IoStatus.Status = RC;
+      Irp->IoStatus.Information = 0;
+      break;
+    }
+
+  IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+  return  RC;
+}
+
+//    IDEStartIo
+//
+//  DESCRIPTION:
+//    Get the next requested I/O packet started
+//
+//  RUN LEVEL:
+//    DISPATCH_LEVEL
+//
+//  ARGUMENTS:
+//    Dispatch routine standard arguments
+//
+//  RETURNS:
+//    NTSTATUS
+//
+
+static  VOID  
+IDEStartIo(IN PDEVICE_OBJECT DeviceObject, 
+           IN PIRP Irp) 
+{
+  LARGE_INTEGER              SectorLI;
+  PIO_STACK_LOCATION         IrpStack;
+  PIDE_DEVICE_EXTENSION      DeviceExtension;
+  KIRQL                      OldIrql;
+  
+  IrpStack = IoGetCurrentIrpStackLocation(Irp);
+  DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+
+    // FIXME: implement the supported functions
+
+  switch (IrpStack->MajorFunction) 
+    {
+    case IRP_MJ_READ:
+    case IRP_MJ_WRITE:
+      DeviceExtension->Operation = IrpStack->MajorFunction;
+      DeviceExtension->BytesRequested = IrpStack->Parameters.Read.Length;
+      assert(DeviceExtension->BytesPerSector == 512);
+      SectorLI = RtlLargeIntegerShiftRight(IrpStack->Parameters.Read.ByteOffset, 9);
+      DeviceExtension->StartingSector = SectorLI.LowPart;
+      if (DeviceExtension->BytesRequested > DeviceExtension->BytesPerSector * 
+          IDE_MAX_SECTORS_PER_XFER) 
+        {
+          DeviceExtension->BytesToTransfer = DeviceExtension->BytesPerSector * 
+              IDE_MAX_SECTORS_PER_XFER;
+        } 
+      else 
+        {
+          DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested;
+        }
+      DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer;
+      DeviceExtension->SectorsTransferred = 0;
+      DeviceExtension->TargetAddress = (BYTE *)MmGetSystemAddressForMdl(Irp->MdlAddress);
+DPRINT("UserBuffer %x MdlAddress %x TargetAddress %x\n", 
+       Irp->UserBuffer, 
+       Irp->MdlAddress, 
+       DeviceExtension->TargetAddress);
+KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+      IoAllocateController(DeviceExtension->ControllerObject,
+          DeviceObject, IDEAllocateController, NULL);
+KeLowerIrql(OldIrql);
+      break;
+
+    default:
+      Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+      Irp->IoStatus.Information = 0;
+      IoCompleteRequest(Irp, IO_NO_INCREMENT);
+      IoStartNextPacket(DeviceObject, FALSE);
+      break;
+    }
+}
+
+//    IDEAllocateController
+
+static IO_ALLOCATION_ACTION 
+IDEAllocateController(IN PDEVICE_OBJECT DeviceObject,
+                      IN PIRP Irp,
+                      IN PVOID MapRegisterBase,
+                      IN PVOID Ccontext) 
+{
+  PIDE_DEVICE_EXTENSION  DeviceExtension;
+  PIDE_CONTROLLER_EXTENSION  ControllerExtension;
+
+  DeviceExtension = (PIDE_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
+  ControllerExtension = (PIDE_CONTROLLER_EXTENSION) 
+      DeviceExtension->ControllerObject->ControllerExtension;
+  ControllerExtension->CurrentIrp = Irp;
+  return KeSynchronizeExecution(ControllerExtension->Interrupt, 
+                                IDEStartController,
+                                DeviceExtension) ? KeepObject : 
+                                  DeallocateObject;
+}
+
+//    IDEStartController
+
+BOOLEAN 
+IDEStartController(IN OUT PVOID Context) 
+{
+  BYTE SectorCnt, SectorNum, CylinderLow, CylinderHigh;
+  BYTE DrvHead, Command;
+  int Retries;
+  ULONG StartingSector;
+  PIDE_DEVICE_EXTENSION DeviceExtension;
+  PIDE_CONTROLLER_EXTENSION ControllerExtension;
+  PIRP Irp;
+
+  DeviceExtension = (PIDE_DEVICE_EXTENSION) Context;
+  ControllerExtension = (PIDE_CONTROLLER_EXTENSION)
+      DeviceExtension->ControllerObject->ControllerExtension;
+  ControllerExtension->OperationInProgress = TRUE;
+  ControllerExtension->DeviceForOperation = DeviceExtension;
+
+    //  Write controller registers to start opteration
+  StartingSector = DeviceExtension->StartingSector;
+  SectorCnt = DeviceExtension->BytesToTransfer / 
+      DeviceExtension->BytesPerSector;
+  if (DeviceExtension->LBASupported) 
+    {
+      SectorNum = StartingSector & 0xff;
+      CylinderLow = (StartingSector >> 8) & 0xff;
+      CylinderHigh = (StartingSector >> 16) & 0xff;
+      DrvHead = ((StartingSector >> 24) & 0x0f) | 
+          (DeviceExtension->UnitNumber ? IDE_DH_DRV1 : 0) |
+          IDE_DH_LBA;
+    } 
+  else 
+    {
+      SectorNum = (StartingSector % DeviceExtension->SectorsPerLogTrk) + 1;
+      StartingSector /= DeviceExtension->SectorsPerLogTrk;
+      DrvHead = (StartingSector % DeviceExtension->LogicalHeads) | 
+          (DeviceExtension->UnitNumber ? IDE_DH_DRV1 : 0);
+      StartingSector /= DeviceExtension->LogicalHeads;
+      CylinderLow = StartingSector & 0xff;
+      CylinderHigh = StartingSector >> 8;
+    }
+  Command = DeviceExtension->Operation == IRP_MJ_READ ? 
+      IDE_CMD_READ_RETRY : IDE_CMD_WRITE_RETRY;
+  if (DrvHead & IDE_DH_LBA) 
+    {
+      DPRINT("%s:DRV=%d:LBA=1:BLK=%08d:SC=%02x:CM=%02x\n",
+             DeviceExtension->Operation == IRP_MJ_READ ? "READ" : "WRITE",
+             DrvHead & IDE_DH_DRV1 ? 1 : 0, 
+             ((DrvHead & 0x0f) << 24) +
+             (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
+             SectorCnt, 
+             Command);
+    } 
+  else 
+    {
+      DPRINT("%s:DRV=%d:LBA=0:CH=%02x:CL=%02x:HD=%01x:SN=%02x:SC=%02x:CM=%02x\n",
+             DeviceExtension->Operation == IRP_MJ_READ ? "READ" : "WRITE",
+             DrvHead & IDE_DH_DRV1 ? 1 : 0, 
+             CylinderHigh, 
+             CylinderLow, 
+             DrvHead & 0x0f, 
+             SectorNum, 
+             SectorCnt, 
+             Command);
+    }
+
+  /*  wait for BUSY to clear  */
+  for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
+    {
+      BYTE  Status = IDEReadStatus(ControllerExtension->CommandPortBase);
+      if (!(Status & IDE_SR_BUSY)) 
+        {
+          break;
+        }
+      KeStallExecutionProcessor(10);
+    }
+  /* FIXME: should reset controller and try again  */
+  if (Retries >= IDE_MAX_BUSY_RETRIES)
+    {
+      Irp = ControllerExtension->CurrentIrp;
+      Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
+      Irp->IoStatus.Information = 0;
+
+      return DeallocateObject;
+    }
+
+  /*  Select the desired drive  */
+  IDEWriteDriveHead(ControllerExtension->CommandPortBase, IDE_DH_FIXED | DrvHead);
+
+  /*  wait for BUSY to clear and DRDY to assert */
+  for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
+    {
+      BYTE  Status = IDEReadStatus(ControllerExtension->CommandPortBase);
+      if (!(Status & IDE_SR_BUSY) && (Status & IDE_SR_DRDY)) 
+        {
+          break;
+        }
+      KeStallExecutionProcessor(10);
+    }
+  /* FIXME: should reset controller and try again  */
+  if (Retries >= IDE_MAX_BUSY_RETRIES)
+    {
+      Irp = ControllerExtension->CurrentIrp;
+      Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
+      Irp->IoStatus.Information = 0;
+
+      return DeallocateObject;
+    }
+
+  /*  Setup command parameters  */
+  IDEWritePrecomp(ControllerExtension->CommandPortBase, 0);
+  IDEWriteSectorCount(ControllerExtension->CommandPortBase, SectorCnt);
+  IDEWriteSectorNum(ControllerExtension->CommandPortBase, SectorNum);
+  IDEWriteCylinderHigh(ControllerExtension->CommandPortBase, CylinderHigh);
+  IDEWriteCylinderLow(ControllerExtension->CommandPortBase, CylinderLow);
+  IDEWriteDriveHead(ControllerExtension->CommandPortBase, IDE_DH_FIXED | DrvHead);
+
+  /*  Issue command to drive  */
+  IDEWriteCommand(ControllerExtension->CommandPortBase, Command);
+
+  if (DeviceExtension->Operation == IRP_MJ_WRITE) 
+    {
+
+        //  Wait for controller ready
+      for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++) 
+        {
+          BYTE  Status = IDEReadStatus(ControllerExtension->CommandPortBase);
+          if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR)) 
+            {
+              break;
+            }
+        }
+      if (Retries >= IDE_MAX_BUSY_RETRIES)
+        {
+          Irp = ControllerExtension->CurrentIrp;
+          Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
+          Irp->IoStatus.Information = 0;
+
+          return DeallocateObject;
+        }
+
+        //  Load the first sector of data into the controller
+      IDEWriteBlock(ControllerExtension->CommandPortBase, DeviceExtension->TargetAddress);
+      DeviceExtension->TargetAddress += IDE_SECTOR_BUF_SZ;
+      DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector;
+    }
+
+  return  TRUE;
+}
+
+//    IDEIsr
+//
+//  DESCIPTION:
+//    Handle interrupts for IDE devices
+//
+//  RUN LEVEL:
+//    DIRQL
+//
+//  ARGUMENTS:
+//    IN  PKINTERRUPT  Interrupt       The interrupt level in effect
+//    IN  PVOID        ServiceContext  The driver supplied context
+//                                     (the controller extension)
+//  RETURNS:
+//    TRUE   This ISR handled the interrupt
+//    FALSE  Another ISR must handle this interrupt
+
+static  BOOLEAN  
+IDEIsr(IN PKINTERRUPT Interrupt, 
+       IN PVOID ServiceContext) 
+{
+  BOOLEAN   IsLastBlock, AnErrorOccured, RequestIsComplete;
+  BYTE     *TargetAddress;
+  int       Retries;
+  NTSTATUS  ErrorStatus;
+  ULONG     ErrorInformation;
+  PIRP  Irp;
+  PIDE_DEVICE_EXTENSION  DeviceExtension;
+  PIDE_CONTROLLER_EXTENSION  ControllerExtension;
+
+  ControllerExtension = (PIDE_CONTROLLER_EXTENSION) ServiceContext;
+
+    //  Read the status port to clear the interrtupt (even if it's not ours).
+  ControllerExtension->DeviceStatus = IDEReadStatus(ControllerExtension->CommandPortBase);
+
+    //  If the interrupt is not ours, get the heck outta dodge.
+  if (!ControllerExtension->OperationInProgress)
+    {
+      return FALSE;
+    }
+
+  DeviceExtension = ControllerExtension->DeviceForOperation;
+  IsLastBlock = FALSE;
+  AnErrorOccured = FALSE;
+  RequestIsComplete = FALSE;
+  ErrorStatus = STATUS_SUCCESS;
+  ErrorInformation = 0;
+
+    //  Handle error condition if it exists
+  if (ControllerExtension->DeviceStatus & IDE_SR_ERR) 
+    {
+      BYTE ErrorReg, SectorCount, SectorNum, CylinderLow, CylinderHigh;
+      BYTE DriveHead;
+
+        //  Log the error
+      ErrorReg = IDEReadError(ControllerExtension->CommandPortBase);
+      CylinderLow = IDEReadCylinderLow(ControllerExtension->CommandPortBase);
+      CylinderHigh = IDEReadCylinderHigh(ControllerExtension->CommandPortBase);
+      DriveHead = IDEReadDriveHead(ControllerExtension->CommandPortBase);
+      SectorCount = IDEReadSectorCount(ControllerExtension->CommandPortBase);
+      SectorNum = IDEReadSectorNum(ControllerExtension->CommandPortBase);
+        // FIXME: should use the NT error logging facility
+      DPRINT("IDE Error: OP:%02x STAT:%02x ERR:%02x CYLLO:%02x CYLHI:%02x SCNT:%02x SNUM:%02x\n", 
+             DeviceExtension->Operation, 
+             ControllerExtension->DeviceStatus, 
+             ErrorReg, 
+             CylinderLow,
+             CylinderHigh, 
+             SectorCount, 
+             SectorNum);
+
+        // FIXME: should retry the command and perhaps recalibrate the drive
+
+        //  Set error status information
+      AnErrorOccured = TRUE;
+      ErrorStatus = STATUS_DISK_OPERATION_FAILED;
+      ErrorInformation = 
+          (((((((CylinderHigh << 8) + CylinderLow) * 
+              DeviceExtension->LogicalHeads) + 
+              (DriveHead % DeviceExtension->LogicalHeads)) * 
+              DeviceExtension->SectorsPerLogTrk) + SectorNum - 1) -
+          DeviceExtension->StartingSector) * DeviceExtension->BytesPerSector;
+    } 
+  else 
+    {
+
+        // Check controller and setup for next transfer
+      switch (DeviceExtension->Operation) 
+        {
+        case  IRP_MJ_READ:
+
+            //  Update controller/device state variables
+          TargetAddress = DeviceExtension->TargetAddress;
+          DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector;
+          DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector;
+          DeviceExtension->SectorsTransferred++;
+
+            //  Remember whether DRQ should be low at end (last block read)
+          IsLastBlock = DeviceExtension->BytesToTransfer == 0;
+
+            //  Wait for DRQ assertion
+          for (Retries = 0; Retries < IDE_MAX_DRQ_RETRIES &&
+              !(IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ);
+              Retries++) 
+            {
+              KeStallExecutionProcessor(10);
+            }
+
+            //  Copy the block of data
+          IDEReadBlock(ControllerExtension->CommandPortBase, TargetAddress);
+
+            //  check DRQ
+          if (IsLastBlock) 
+            {
+              for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
+                  (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_BUSY);
+                  Retries++) 
+                {
+                  KeStallExecutionProcessor(10);
+                }
+
+                //  Check for data overrun
+              if (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ) 
+                {
+                  AnErrorOccured = TRUE;
+                  ErrorStatus = STATUS_DATA_OVERRUN;
+                  ErrorInformation = 0;
+                } 
+              else 
+                {
+
+                    //  Setup next transfer or set RequestIsComplete
+                  if (DeviceExtension->BytesRequested > 
+                      DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER) 
+                    {
+                      DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred;
+                      DeviceExtension->SectorsTransferred = 0;
+                      DeviceExtension->BytesToTransfer = 
+                      DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER;
+                      DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer;
+                    } 
+                  else if (DeviceExtension->BytesRequested > 0) 
+                    {
+                      DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred;
+                      DeviceExtension->SectorsTransferred = 0;
+                      DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested;
+                      DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer;
+                    } 
+                  else
+                    {
+                      RequestIsComplete = TRUE;
+                    }
+                }
+            }
+          break;
+
+        case IRP_MJ_WRITE:
+
+            //  check DRQ
+          if (DeviceExtension->BytesToTransfer == 0) 
+            {
+              for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
+                  (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_BUSY);
+                   Retries++) 
+                {
+                  KeStallExecutionProcessor(10);
+                }
+
+                //  Check for data overrun
+              if (IDEReadStatus(ControllerExtension->CommandPortBase) & IDE_SR_DRQ) 
+                {
+                  AnErrorOccured = TRUE;
+                  ErrorStatus = STATUS_DATA_OVERRUN;
+                  ErrorInformation = 0;
+                } 
+              else 
+                {
+
+                    //  Setup next transfer or set RequestIsComplete
+                  IsLastBlock = TRUE;
+                  if (DeviceExtension->BytesRequested > 
+                      DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER) 
+                    {
+                      DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred;
+                      DeviceExtension->SectorsTransferred = 0;
+                      DeviceExtension->BytesToTransfer = 
+                          DeviceExtension->BytesPerSector * IDE_MAX_SECTORS_PER_XFER;
+                      DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer;
+                    } 
+                  else if (DeviceExtension->BytesRequested > 0) 
+                    {
+                      DeviceExtension->StartingSector += DeviceExtension->SectorsTransferred;
+                      DeviceExtension->SectorsTransferred = 0;
+                      DeviceExtension->BytesToTransfer = DeviceExtension->BytesRequested;
+                      DeviceExtension->BytesRequested -= DeviceExtension->BytesToTransfer;
+                    } 
+                  else 
+                    {
+                      RequestIsComplete = TRUE;
+                    }
+                }
+            } 
+          else 
+            {
+
+                //  Update controller/device state variables
+              TargetAddress = DeviceExtension->TargetAddress;
+              DeviceExtension->TargetAddress += DeviceExtension->BytesPerSector;
+              DeviceExtension->BytesToTransfer -= DeviceExtension->BytesPerSector;
+
+                //  Write block to controller
+              IDEWriteBlock(ControllerExtension->CommandPortBase, TargetAddress);
+            }
+          break;
+        }
+    }
+
+  //  If there was an error or the request is done, complete the packet
+  if (AnErrorOccured || RequestIsComplete) 
+    {
+
+      //  Set the return status and info values
+      Irp = ControllerExtension->CurrentIrp;
+      Irp->IoStatus.Status = ErrorStatus;
+      Irp->IoStatus.Information = ErrorInformation;
+
+      //  Clear out controller fields
+      ControllerExtension->OperationInProgress = FALSE;
+      ControllerExtension->DeviceStatus = 0;
+
+      //  Queue the Dpc to finish up
+      IoRequestDpc(DeviceExtension->DeviceObject, 
+                   Irp, 
+                   ControllerExtension);
+    } 
+  else if (IsLastBlock)
+    {
+      //  Else more data is needed, setup next device I/O
+      IDEStartController((PVOID)DeviceExtension);
+    }
+
+  return TRUE;
+}
+
+//    IDEDpcForIsr
+//  DESCRIPTION:
+//
+//  RUN LEVEL:
+//
+//  ARGUMENTS:
+//    IN PKDPC          Dpc
+//    IN PDEVICE_OBJECT DpcDeviceObject
+//    IN PIRP           DpcIrp
+//    IN PVOID          DpcContext
+//
+static  VOID  
+IDEDpcForIsr(IN PKDPC Dpc, 
+             IN PDEVICE_OBJECT DpcDeviceObject,
+             IN PIRP DpcIrp, 
+             IN PVOID DpcContext)
+{
+  PIDE_CONTROLLER_EXTENSION ControllerExtension;
+  PIDE_DEVICE_EXTENSION DeviceExtension;
+  PIRP Irp;
+  ULONG Operation;
+
+  ControllerExtension = (PIDE_CONTROLLER_EXTENSION) DpcContext;
+  DeviceExtension = ControllerExtension->DeviceForOperation;
+  Irp = ControllerExtension->CurrentIrp;
+  Operation = DeviceExtension->Operation;
+  ControllerExtension->DeviceForOperation = 0;
+  ControllerExtension->CurrentIrp = 0;
+
+  //  Deallocate the controller
+  IoFreeController(DeviceExtension->ControllerObject);
+
+  //  Start the next packet
+  IoStartNextPacketByKey(DeviceExtension->DeviceObject, 
+                         FALSE, 
+                         DeviceExtension->StartingSector);
+
+  //  Issue completion of the current packet
+  IoCompleteRequest(Irp, IO_DISK_INCREMENT);
+
+  //  Flush cache if necessary
+  if (Operation == IRP_MJ_READ) 
+    {
+      KeFlushIoBuffers(Irp->MdlAddress, TRUE, FALSE);
+    }
+}
+
+//    IDEIoTimer
+//  DESCRIPTION:
+//    This function handles timeouts and other time delayed processing
+//
+//  RUN LEVEL:
+//
+//  ARGUMENTS:
+//    IN  PDEVICE_OBJECT  DeviceObject  Device object registered with timer
+//    IN  PVOID           Context       the Controller extension for the
+//                                      controller the device is on
+//
+static  VOID  
+IDEIoTimer(PDEVICE_OBJECT DeviceObject, 
+           PVOID Context) 
+{
+  PIDE_CONTROLLER_EXTENSION  ControllerExtension;
+
+    //  Setup Extension pointer
+  ControllerExtension = (PIDE_CONTROLLER_EXTENSION) Context;
+
+    //  If we're counting down, then count.
+  if (ControllerExtension->TimerCount > 0) 
+    {
+      ControllerExtension->TimerCount--;
+
+      //  Else we'll check the state and process if necessary
+    } 
+  else 
+    {
+      switch (ControllerExtension->TimerState) 
+        {
+          case IDETimerIdle:
+            break;
+        }
+    }
+}
+
+
diff --git a/reactos/drivers/dd/ide/ide.h b/reactos/drivers/dd/ide/ide.h
new file mode 100644 (file)
index 0000000..d6961ed
--- /dev/null
@@ -0,0 +1,209 @@
+//
+//  IDE.H - defines and typedefs for the IDE Driver module.
+//
+
+#ifndef __IDE_H
+#define __IDE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define  IDE_MAXIMUM_DEVICES    8
+
+#define IDE_MAX_NAME_LENGTH     50
+#define IDE_NT_ROOTDIR_NAME     "\\Device"
+#define IDE_NT_DEVICE_NAME      "\\HardDrive"
+#define IDE_NT_PARTITION_NAME   "\\Partition"
+#define IDE_WIN32_DEVICE_NAME   "\\DosDevices\\IDE"
+#define IDE_DRIVER_NAME         "IDEDRIVER"
+
+#define  IDE_SECTOR_BUF_SZ         512
+#define  IDE_MAX_SECTORS_PER_XFER  256
+#define  IDE_MAX_RESET_RETRIES     10000
+#define  IDE_MAX_WRITE_RETRIES     1000
+#define  IDE_MAX_BUSY_RETRIES      100
+#define  IDE_MAX_DRQ_RETRIES       1000
+
+#define  IDE_REG_ALT_STATUS     0x0006
+#define  IDE_REG_DEV_CNTRL      0x0006  /* device control register */
+#define    IDE_DC_SRST            0x04  /* drive reset (both drives) */
+#define    IDE_DC_nIEN            0x02  /* IRQ enable (active low) */
+#define  IDE_REG_DRV_ADDR       0x0007
+#define  IDE_REG_DATA_PORT      0x0000
+#define  IDE_REG_ERROR          0x0001  /* error register */
+#define    IDE_ER_AMNF            0x01  /* addr mark not found */
+#define    IDE_ER_TK0NF           0x02  /* track 0 not found */
+#define    IDE_ER_ABRT            0x04  /* command aborted */
+#define    IDE_ER_MCR             0x08  /* media change requested */
+#define    IDE_ER_IDNF            0x10  /* ID not found */
+#define    IDE_ER_MC              0x20  /* Media changed */
+#define    IDE_ER_UNC             0x40  /* Uncorrectable data error */
+#define  IDE_REG_PRECOMP        0x0001
+#define  IDE_REG_SECTOR_CNT     0x0002
+#define  IDE_REG_SECTOR_NUM     0x0003
+#define  IDE_REG_CYL_LOW        0x0004
+#define  IDE_REG_CYL_HIGH       0x0005
+#define  IDE_REG_DRV_HEAD       0x0006
+#define    IDE_DH_FIXED           0xA0
+#define    IDE_DH_LBA             0x40
+#define    IDE_DH_HDMASK          0x0F
+#define    IDE_DH_DRV0            0x00
+#define    IDE_DH_DRV1            0x10
+#define  IDE_REG_STATUS         0x0007
+#define    IDE_SR_BUSY            0x80
+#define    IDE_SR_DRDY            0x40
+#define    IDE_SR_DRQ             0x08
+#define    IDE_SR_ERR             0x01
+#define  IDE_REG_COMMAND        0x0007
+#define    IDE_CMD_READ           0x20
+#define    IDE_CMD_READ_RETRY     0x21
+#define    IDE_CMD_WRITE          0x30
+#define    IDE_CMD_WRITE_RETRY    0x31
+#define    IDE_CMD_IDENT_DRV      0xEC
+
+//
+//  Access macros for command registers
+//  Each macro takes an address of the command port block, and data
+//
+#define IDEReadError(Address)                (inb_p((Address) + IDE_REG_ERROR))
+#define IDEWritePrecomp(Address, Data)       (outb_p((Address) + IDE_REG_PRECOMP, (Data)))
+#define IDEReadSectorCount(Address)          (inb_p((Address) + IDE_REG_SECTOR_CNT))
+#define IDEWriteSectorCount(Address, Data)   (outb_p((Address) + IDE_REG_SECTOR_CNT, (Data)))
+#define IDEReadSectorNum(Address)            (inb_p((Address) + IDE_REG_SECTOR_NUM))
+#define IDEWriteSectorNum(Address, Data)     (outb_p((Address) + IDE_REG_SECTOR_NUM, (Data)))
+#define IDEReadCylinderLow(Address)          (inb_p((Address) + IDE_REG_CYL_LOW))
+#define IDEWriteCylinderLow(Address, Data)   (outb_p((Address) + IDE_REG_CYL_LOW, (Data)))
+#define IDEReadCylinderHigh(Address)         (inb_p((Address) + IDE_REG_CYL_HIGH))
+#define IDEWriteCylinderHigh(Address, Data)  (outb_p((Address) + IDE_REG_CYL_HIGH, (Data)))
+#define IDEReadDriveHead(Address)            (inb_p((Address) + IDE_REG_DRV_HEAD))
+#define IDEWriteDriveHead(Address, Data)     (outb_p((Address) + IDE_REG_DRV_HEAD, (Data)))
+#define IDEReadStatus(Address)               (inb_p((Address) + IDE_REG_STATUS))
+#define IDEWriteCommand(Address, Data)       (outb_p((Address) + IDE_REG_COMMAND, (Data)))
+#define IDEReadBlock(Address, Buffer)        (insw((Address) + IDE_REG_DATA_PORT, (Buffer), IDE_SECTOR_BUF_SZ / 2))
+#define IDEWriteBlock(Address, Buffer)        (outsw((Address) + IDE_REG_DATA_PORT, (Buffer), IDE_SECTOR_BUF_SZ / 2))
+
+//
+//  Access macros for control registers
+//  Each macro takes an address of the control port blank and data
+//
+#define IDEWriteDriveControl(Address, Data)  (outb_p((Address) + IDE_REG_DEV_CNTRL, (Data)))
+
+//    IDE_DEVICE_EXTENSION
+//
+//  DESCRIPTION:
+//    Extension to be placed in each device object
+//
+//  ACCESS:
+//    Allocated from NON-PAGED POOL
+//    Available at any IRQL
+//
+
+typedef struct _IDE_DEVICE_EXTENSION {
+  PDEVICE_OBJECT         DeviceObject;
+  PCONTROLLER_OBJECT     ControllerObject;
+  struct _IDE_DEVICE_EXTESION  *DiskExtension;
+  int                    UnitNumber;
+  BOOLEAN                LBASupported;
+  BOOLEAN                DMASupported;
+  int                    BytesPerSector;
+  int                    LogicalHeads;
+  int                    SectorsPerLogCyl;
+  int                    SectorsPerLogTrk;
+  int                    Offset;
+  int                    Size;
+
+  int                    Operation;
+  ULONG                  BytesRequested;
+  ULONG                  BytesToTransfer;
+  ULONG                  BytesRemaining;
+  ULONG                  StartingSector;
+  int                    SectorsTransferred;
+  BYTE                  *TargetAddress;
+
+} IDE_DEVICE_EXTENSION, *PIDE_DEVICE_EXTENSION;
+
+//    IDE_TIMER_STATES
+//
+//  DESCRIPTION:
+//    An enumeration containing the states in the timer DFA
+//
+
+typedef enum _IDE_TIMER_STATES {
+  IDETimerIdle
+} IDE_TIMER_STATES;
+
+//    IDE_CONTROLLER_EXTENSION
+//
+//  DESCRIPTION:
+//    Driver-defined structure used to hold miscellaneous controller information.
+//
+//  ACCESS:
+//    Allocated from NON-PAGED POOL
+//    Available at any IRQL
+//
+
+typedef struct _IDE_CONTROLLER_EXTENSION {
+  KSPIN_LOCK             SpinLock;
+  int                    Number;
+  int                    Vector;
+  int                    CommandPortBase;
+  int                    ControlPortBase;
+  BOOLEAN                DMASupported;
+  BOOLEAN                ControllerInterruptBug;
+  PKINTERRUPT            Interrupt;
+
+  BOOLEAN                OperationInProgress;
+  BYTE                   DeviceStatus;
+  PIDE_DEVICE_EXTENSION  DeviceForOperation;
+  PIRP                   CurrentIrp;
+
+  IDE_TIMER_STATES       TimerState;
+  LONG                   TimerCount;
+  PDEVICE_OBJECT         TimerDevice;
+
+} IDE_CONTROLLER_EXTENSION, *PIDE_CONTROLLER_EXTENSION;
+
+//    IDE_DRIVE_IDENTIFY
+
+typedef struct _IDE_DRIVE_IDENTIFY {
+  WORD  ConfigBits;          /*00*/
+  WORD  LogicalCyls;         /*01*/
+  WORD  Reserved02;          /*02*/
+  WORD  LogicalHeads;        /*03*/
+  WORD  BytesPerTrack;       /*04*/
+  WORD  BytesPerSector;      /*05*/
+  WORD  SectorsPerTrack;     /*06*/
+  BYTE   InterSectorGap;      /*07*/
+  BYTE   InterSectorGapSize;
+  BYTE   Reserved08H;         /*08*/
+  BYTE   BytesInPLO;
+  WORD  VendorUniqueCnt;     /*09*/
+  char   SerialNumber[20];    /*10*/
+  WORD  ControllerType;      /*20*/
+  WORD  BufferSize;          /*21*/
+  WORD  ECCByteCnt;          /*22*/
+  char   FirmwareRev[8];      /*23*/
+  char   ModelNumber[40];     /*27*/
+  WORD  RWMultImplemented;   /*47*/
+  WORD  DWordIOSupported;    /*48*/
+  WORD  LBADMASupported;     /*49*/
+  WORD  Reserved50;          /*50*/
+  WORD  MinPIOTransTime;     /*51*/
+  WORD  MinDMATransTime;     /*52*/
+  WORD  TMFieldsValid;       /*53*/
+  WORD  TMCylinders;         /*54*/
+  WORD  TMHeads;             /*55*/
+  WORD  TMSectorsPerTrk;     /*56*/
+  WORD  TMCapacity;          /*57*/
+  WORD  Reserved53[198];     /*58*/
+} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /*  __IDE_H  */
+
+
diff --git a/reactos/drivers/dd/ide/idep.h b/reactos/drivers/dd/ide/idep.h
new file mode 100644 (file)
index 0000000..0052e5a
--- /dev/null
@@ -0,0 +1,20 @@
+
+
+#define IOCTL_DISK_GET_DRIVE_GEOMETRY   CTL_CODE(FILE_DEVICE_DISK,  0, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_GET_PARTITION_INFO   CTL_CODE(FILE_DEVICE_DISK,  1, METHOD_BUFFERED, FILE_READ_ACCESS)
+#define IOCTL_DISK_SET_PARTITION_INFO   CTL_CODE(FILE_DEVICE_DISK,  2, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_DISK_GET_DRIVE_LAYOUT     CTL_CODE(FILE_DEVICE_DISK,  3, METHOD_BUFFERED, FILE_READ_ACCESS)
+#define IOCTL_DISK_SET_DRIVE_LAYOUT     CTL_CODE(FILE_DEVICE_DISK,  4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_DISK_VERIFY               CTL_CODE(FILE_DEVICE_DISK,  5, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_FORMAT_TRACKS        CTL_CODE(FILE_DEVICE_DISK,  6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_DISK_REASSIGN_BLOCKS      CTL_CODE(FILE_DEVICE_DISK,  7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_DISK_PERFORMANCE          CTL_CODE(FILE_DEVICE_DISK,  8, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_IS_WRITABLE          CTL_CODE(FILE_DEVICE_DISK,  9, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_LOGGING              CTL_CODE(FILE_DEVICE_DISK, 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_FORMAT_TRACKS_EX     CTL_CODE(FILE_DEVICE_DISK, 11, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_DISK_HISTOGRAM_STRUCTURE  CTL_CODE(FILE_DEVICE_DISK, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_HISTOGRAM_DATA       CTL_CODE(FILE_DEVICE_DISK, 13, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_HISTOGRAM_RESET      CTL_CODE(FILE_DEVICE_DISK, 14, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_REQUEST_STRUCTURE    CTL_CODE(FILE_DEVICE_DISK, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_DISK_REQUEST_DATA         CTL_CODE(FILE_DEVICE_DISK, 16, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
diff --git a/reactos/drivers/dd/ide/makefile b/reactos/drivers/dd/ide/makefile
new file mode 100644 (file)
index 0000000..aaafa1a
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#
+#
+
+all: ide.o
+
+ide.o: ide.c ide.h idep.h partitio.h
+
+dummy:
+
+include ../../../rules.mak
diff --git a/reactos/drivers/dd/ide/partitio.h b/reactos/drivers/dd/ide/partitio.h
new file mode 100644 (file)
index 0000000..0329667
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+*** Partition.h - defines and structs for harddrive partition info
+***
+***  05/30/98  RJJ  Created
+**/
+
+#ifndef __PARTITION_H
+#define __PARTITION_H
+
+#define  PARTITION_MAGIC    0xaa55
+#define  PART_MAGIC_OFFSET  0x01fe
+#define  PARTITION_OFFSET   0x01be
+#define  PARTITION_TBL_SIZE 4
+#define  PTCHSToLBA(c, h, s, scnt, hcnt) ((s) & 0x3f) + \
+    (scnt) * ( (h) + (hcnt) * ((c) | (((s) & 0xc0) << 2)))
+#define  PTLBAToCHS(lba, c, h, s, scnt, hcnt) ( \
+    (s) = (lba) % (scnt) + 1,  \
+    (lba) /= (scnt), \
+    (h) = (lba) % (hcnt), \
+    (lba) /= (heads), \
+    (c) = (lba) & 0xff, \
+    (s) |= ((lba) >> 2) & 0xc0)
+
+
+typedef enum PartitionTypes {
+  PTEmpty = 0,
+  PTDOS3xPrimary = 1,
+  PT_OLDDOS16Bit = 4,
+  PTDosExtended = 5,
+  PTDos5xPrimary = 6
+} PARTITIONTYPES;
+
+#define PartitionIsSupported(P) ((P)->PartitionType == PTDOS3xPrimary || \
+    (P)->PartitionType == PT_OLDDOS16Bit || (P)->PartitionType == PTDos5xPrimary)
+
+typedef struct Partition {
+  __u8   BootFlags;
+  __u8   StartingHead;
+  __u8   StartingSector;
+  __u8   StartingCylinder;
+  __u8   PartitionType;
+  __u8   EndingHead;
+  __u8   EndingSector;
+  __u8   EndingCylinder;
+  unsigned int  StartingBlock;
+  unsigned int  SectorCount;
+
+} PARTITION;
+
+#endif  // PARTITION_H
+
+
diff --git a/reactos/drivers/dd/keyboard/keyboard.c b/reactos/drivers/dd/keyboard/keyboard.c
new file mode 100644 (file)
index 0000000..d4cc587
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+** File: keyboard.c
+** Description: ReactOS keyboard driver
+** Current version: 0.0.4
+** Last modified: 28 May 1998
+**
+ * 31/08/98: Changed to interrupt driven model
+ * 29/06/98: NT interface by David Welch (welch@mcmail.com)
+ * 
+** Written by Victor Kirhenshtein (sauros@iname.com)
+** Initial attempt by Jason Filby
+**
+** Some parts of this code are based on Linux keyboard driver
+**    written by Johan Myreen.
+**
+**
+** KNOWN BUGS:
+**
+**   * Repeat counter isn't supported
+**
+*/
+
+#undef WIN32_LEAN_AND_MEAN
+#include <internal/mmhal.h>
+#include <internal/hal/io.h>
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+#include <defines.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "keyboard.h"
+
+/*
+ * Driver data
+ */
+
+static KEY_EVENT_RECORD kbdBuffer[KBD_BUFFER_SIZE];
+static int bufHead,bufTail;
+static int keysInBuffer;
+static int extKey;
+static BYTE ledStatus;
+static BYTE capsDown,numDown,scrollDown;
+static DWORD ctrlKeyState;
+static KSPIN_LOCK kbdBufferLock;
+static PKINTERRUPT KbdInterrupt;
+static KDPC KbdDpc;
+
+/*
+ * PURPOSE: Current irp being processed
+ */
+static PIRP CurrentIrp;
+
+/*
+ * PURPOSE: Number of keys that have been read into the current irp's buffer
+ */
+static ULONG KeysRead;
+static ULONG KeysRequired;
+
+/*
+ * Virtual key codes table
+ *
+ * Comments:
+ *   * PrtSc = VK_PRINT
+ *   * Alt+PrtSc (SysRq) = VK_EXECUTE
+ *  * Alt = VK_MENU
+ */
+
+static const WORD vkTable[128]=
+{
+   /* 00 - 07 */ 0, VK_ESCAPE, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6,
+   /* 08 - 0F */ VK_7, VK_8, VK_9, VK_0, 189, 187, VK_BACK, VK_TAB,
+   /* 10 - 17 */ VK_Q, VK_W, VK_E, VK_R, VK_T, VK_Y, VK_U, VK_I,
+   /* 18 - 1F */ VK_O, VK_P, 219, 221, VK_RETURN, VK_CONTROL, VK_A, VK_S,
+   /* 20 - 27 */ VK_D, VK_F, VK_G, VK_H, VK_J, VK_K, VK_L, 186,
+   /* 28 - 2F */ 222, 192, VK_SHIFT, 220, VK_Z, VK_X, VK_C, VK_V,
+   /* 30 - 37 */ VK_B, VK_N, VK_M, 188, 190, 191, VK_SHIFT, VK_MULTIPLY,
+   /* 38 - 3F */ VK_MENU, VK_SPACE, VK_CAPITAL, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
+   /* 40 - 47 */ VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUMLOCK, VK_SCROLL, VK_HOME,
+   /* 48 - 4F */ VK_UP, VK_PRIOR, VK_SUBTRACT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_ADD, VK_END,
+   /* 50 - 57 */ VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE, VK_EXECUTE, 0, 0, VK_F11,
+   /* 58 - 5F */ VK_F12, 0, 0, 91, 92, 93, 0, 0,
+   /* 60 - 67 */ 0, 0, 0, 0, 0, 0, 0, 0,
+   /* 68 - 6F */ 0, 0, 0, 0, 0, 0, 0, 0,
+   /* 70 - 77 */ 0, 0, 0, 0, 0, 0, 0, 0,
+   /* 78 - 7F */ 0, 0, 0, 0, 0, 0, 0, VK_PAUSE
+};
+static const WORD vkKeypadTable[13]=   /* 47 - 53 */
+{
+   VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_SUBTRACT,
+   VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_ADD,
+   VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_DECIMAL
+};
+
+
+/*
+ * ASCII translation tables
+ */
+
+static const BYTE asciiTable1[10]=
+{
+   ')','!','@','#','$','%','^','&','*','('
+};
+static const BYTE asciiTable2[16]=
+{
+   '0','1','2','3','4','5','6','7','8','9','*','+',0,'-','.','/'
+};
+static const BYTE asciiTable3[37]=
+{
+   ';','=',',','-','.','/','`', 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   '[', '\\', ']', '\''
+};
+static const BYTE asciiTable4[37]=
+{
+   ':','+','<','_','>','?','~', 0, 0, 0, 0, 0, 0, 0, 0,
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+   '{', '|', '}', '"'
+};
+
+
+/*
+ * Write data to keyboard
+ */
+
+static void KbdWrite(int addr,BYTE data)
+{
+   BYTE status;
+
+   do
+   {
+      status=inb_p(KBD_CTRL_PORT);     // Wait until input buffer empty
+   } while(status & KBD_IBF);
+   outb_p(addr,data);
+}
+
+
+/*
+ * Read data from port 0x60
+ */
+
+static int KbdReadData(void)
+{
+   int i;
+   BYTE status,data;
+
+   i=500000;
+   do
+   {
+      status=inb_p(KBD_CTRL_PORT);
+      if (!(status & KBD_OBF))      // Check if data available
+         continue;
+      data=inb_p(KBD_DATA_PORT);
+      if (status & (KBD_GTO | KBD_PERR))  // Check for timeout error
+         continue;
+      return data;
+   } while(--i);
+   return -1;     // Timed out
+}
+
+
+/*
+ * Set keyboard LED's
+ */
+
+static void SetKeyboardLEDs(BYTE status)
+{
+   KbdWrite(KBD_DATA_PORT,0xED);
+   if (KbdReadData()!=KBD_ACK)      // Error
+      return;
+   KbdWrite(KBD_DATA_PORT,status);
+   KbdReadData();
+}
+
+
+/*
+ * Process scan code
+ */
+
+static void ProcessScanCode(BYTE scanCode,BOOL isDown)
+{
+   switch(scanCode)
+   {
+      case 0x1D:  // Ctrl
+         if (extKey)
+         {
+            if (isDown)
+               ctrlKeyState|=RIGHT_CTRL_PRESSED;
+            else
+               ctrlKeyState&=~RIGHT_CTRL_PRESSED;
+         }
+         else
+         {
+            if (isDown)
+               ctrlKeyState|=LEFT_CTRL_PRESSED;
+            else
+               ctrlKeyState&=~LEFT_CTRL_PRESSED;
+         }
+         break;
+      case 0x2A:  // Left shift
+      case 0x36:  // Right shift
+         if (isDown)
+            ctrlKeyState|=SHIFT_PRESSED;
+         else
+            ctrlKeyState&=~SHIFT_PRESSED;
+         break;
+      case 0x38:  // Alt
+         if (extKey)
+         {
+            if (isDown)
+               ctrlKeyState|=RIGHT_ALT_PRESSED;
+            else
+               ctrlKeyState&=~RIGHT_ALT_PRESSED;
+         }
+         else
+         {
+            if (isDown)
+               ctrlKeyState|=LEFT_ALT_PRESSED;
+            else
+               ctrlKeyState&=~LEFT_ALT_PRESSED;
+         }
+         break;
+      case 0x3A:  // CapsLock
+         if (ctrlKeyState & CTRL_PRESSED)
+            break;
+         if (isDown)
+         {
+            if (!capsDown)
+            {
+               capsDown=1;
+               if (ctrlKeyState & CAPSLOCK_ON)
+               {
+                  ledStatus&=~KBD_LED_CAPS;
+                  ctrlKeyState&=~CAPSLOCK_ON;
+               }
+               else
+               {
+                  ledStatus|=KBD_LED_CAPS;
+                  ctrlKeyState|=CAPSLOCK_ON;
+               }
+               SetKeyboardLEDs(ledStatus);
+            }
+         }
+         else
+         {
+            capsDown=0;
+         }
+         break;
+      case 0x45:  // NumLock
+         if (ctrlKeyState & CTRL_PRESSED)
+            break;
+         if (isDown)
+         {
+            if (!numDown)
+            {
+               numDown=1;
+               if (ctrlKeyState & NUMLOCK_ON)
+               {
+                  ledStatus&=~KBD_LED_NUM;
+                  ctrlKeyState&=~NUMLOCK_ON;
+               }
+               else
+               {
+                  ledStatus|=KBD_LED_NUM;
+                  ctrlKeyState|=NUMLOCK_ON;
+               }
+               SetKeyboardLEDs(ledStatus);
+            }
+         }
+         else
+         {
+            numDown=0;
+         }
+         break;
+      case 0x46:  // ScrollLock
+         if (ctrlKeyState & CTRL_PRESSED)
+            break;
+         if (isDown)
+         {
+            if (!scrollDown)
+            {
+               scrollDown=1;
+               if (ctrlKeyState & SCROLLLOCK_ON)
+               {
+                  ledStatus&=~KBD_LED_SCROLL;
+                  ctrlKeyState&=~SCROLLLOCK_ON;
+               }
+               else
+               {
+                  ledStatus|=KBD_LED_SCROLL;
+                  ctrlKeyState|=SCROLLLOCK_ON;
+               }
+               SetKeyboardLEDs(ledStatus);
+            }
+         }
+         else
+         {
+            scrollDown=0;
+         }
+         break;
+      default:
+         break;
+   }
+}
+
+
+/*
+ * Translate virtual key code to ASCII
+ */
+
+static BYTE VirtualToAscii(WORD keyCode,BOOL isDown)
+{
+   if ((ctrlKeyState & ALT_PRESSED)&&(ctrlKeyState & CTRL_PRESSED))
+      return 0;                // Ctrl+Alt+char always 0
+   if ((!isDown)&&(ctrlKeyState & ALT_PRESSED))
+      return 0;                // Alt+char is 0 when key is released
+
+   if (ctrlKeyState & CTRL_PRESSED)
+   {
+      if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
+         return keyCode-VK_A+1;
+      switch(keyCode)
+      {
+         case VK_SPACE:
+            return ' ';
+         case VK_BACK:
+            return 127;
+         case VK_RETURN:
+            return 10;                     
+         case 219:                      /* [ */
+            if (ctrlKeyState & SHIFT_PRESSED)
+               return 0;
+            return 27;
+         case 220:         /* \ */
+            if (ctrlKeyState & SHIFT_PRESSED)
+               return 0;
+            return 28;
+         case 221:         /* ] */
+            if (ctrlKeyState & SHIFT_PRESSED)
+               return 0;
+             return 29;
+         default:
+            return 0;
+      }
+   }
+
+   if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
+      if (ctrlKeyState & CAPSLOCK_ON)
+         if (ctrlKeyState & SHIFT_PRESSED)
+            return keyCode-VK_A+'a';
+         else
+            return keyCode-VK_A+'A';
+      else
+         if (ctrlKeyState & SHIFT_PRESSED)
+            return keyCode-VK_A+'A';
+         else
+            return keyCode-VK_A+'a';
+
+   if ((keyCode>=VK_0)&&(keyCode<=VK_9))
+      if (ctrlKeyState & SHIFT_PRESSED)
+         return asciiTable1[keyCode-VK_0];
+      else
+         return keyCode-VK_0+'0';
+
+   if ((keyCode>=VK_NUMPAD0)&&(keyCode<=VK_DIVIDE))
+      return asciiTable2[keyCode-VK_NUMPAD0];
+
+   if ((keyCode>=186)&&(keyCode<=222))
+      if (ctrlKeyState & SHIFT_PRESSED)
+         return asciiTable4[keyCode-186];
+      else
+         return asciiTable3[keyCode-186];
+
+   switch(keyCode)
+   {
+      case VK_SPACE:
+         return ' ';
+      case VK_RETURN:
+         return 13;
+      case VK_BACK:
+         return 8;
+      case VK_TAB:
+         return 9;
+   }
+   return 0;
+}
+
+
+/*
+ * Translate scan code to virtual key code
+ */
+
+static WORD ScanToVirtual(BYTE scanCode)
+{
+   if ((scanCode>=0x47)&&(scanCode<=0x53)&&(ctrlKeyState & NUMLOCK_ON)&&
+       (!extKey)&&(!(ctrlKeyState & SHIFT_PRESSED)))
+      return vkKeypadTable[scanCode-0x47];
+   if ((scanCode==0x35)&&(extKey))             // Gray divide
+      return VK_DIVIDE;
+   if ((scanCode==0x37)&&(extKey))     // Print screen
+      return VK_PRINT;
+   return vkTable[scanCode];
+}
+
+
+/*
+ * Keyboard IRQ handler
+ */
+
+static VOID KbdDpcRoutine(PKDPC Dpc,
+                         PVOID DeferredContext,
+                         PVOID SystemArgument1,
+                         PVOID SystemArgument2)
+{
+   PIRP Irp = (PIRP)SystemArgument2;
+   PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
+   
+   CHECKPOINT;
+   DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n",
+         DeviceObject,Irp);
+   Irp->IoStatus.Status = STATUS_SUCCESS;
+   Irp->IoStatus.Information = 0;
+   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+   IoStartNextPacket(DeviceObject,FALSE);
+}
+
+static unsigned int KeyboardHandler(unsigned int irq)
+{
+   BYTE resp,thisKey;
+   BOOL isDown;
+   static BYTE lastKey;
+   
+   CHECKPOINT;
+   
+   // Read scan code
+   thisKey=inb_p(KBD_DATA_PORT);
+   if ((thisKey==0xE0)||(thisKey==0xE1))   // Extended key
+   {
+      extKey=1;         // Wait for next byte
+      lastKey=thisKey;
+      return 0;
+   }
+
+   isDown=!(thisKey & 0x80);
+   thisKey&=0x7F;
+
+   // The keyboard maintains its own internal caps lock and num lock
+   // statuses.  In caps lock mode E0 AA precedes make code and
+   // E0 2A follow break code.  In num lock mode, E0 2A precedes
+   // make code and E0 AA follow break code.  We maintain our own caps lock
+   // and num lock statuses, so we will just ignore these.
+   // Some keyboards have L-Shift/R-Shift modes instead of caps lock
+   // mode.  If right shift pressed, E0 B6 / E0 36 pairs generated.
+   if (extKey & ((thisKey==0x2A)||(thisKey==0x36)))
+   {
+      extKey=0;
+      return 0;
+   }
+
+   // Check for PAUSE sequence
+   if (extKey && (lastKey==0xE1))
+   {
+      if (thisKey==0x1D)
+         lastKey=0xFF;     // Sequence is OK
+      else
+         extKey=0;
+      return 0;
+   }
+   if (extKey && (lastKey==0xFF))
+   {
+      if (thisKey!=0x45)
+      {
+         extKey=0;         // Bad sequence
+         return 0;
+      }
+      thisKey=0x7F;        // Pseudo-code for PAUSE
+   }
+
+   ProcessScanCode(thisKey,isDown);
+   
+   DPRINT("Key: '%c'\n",VirtualToAscii(ScanToVirtual(thisKey),isDown));
+   
+   if (CurrentIrp!=NULL)
+     {
+       KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
+         CurrentIrp->AssociatedIrp.SystemBuffer;
+       PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(CurrentIrp);
+       
+       CHECKPOINT;
+       
+       rec[KeysRead].bKeyDown=isDown;
+       rec[KeysRead].wRepeatCount=1;
+       rec[KeysRead].wVirtualKeyCode=ScanToVirtual(thisKey);
+       rec[KeysRead].wVirtualScanCode=thisKey;
+       rec[KeysRead].AsciiChar=VirtualToAscii(rec->wVirtualKeyCode,isDown);
+       rec[KeysRead].dwControlKeyState=ctrlKeyState;
+       if (extKey)
+         {
+            rec[KeysRead].dwControlKeyState|=ENHANCED_KEY;
+         }
+       KeysRead++;
+       DPRINT("KeysRequired %d KeysRead %x\n",KeysRequired,KeysRead);
+       if (KeysRead==KeysRequired)
+         {
+            KeInsertQueueDpc(&KbdDpc,stk->DeviceObject,CurrentIrp);
+            CurrentIrp=NULL;
+         }
+       CHECKPOINT;
+       return(TRUE);
+     }
+   
+   // Buffer is full ?
+   if (keysInBuffer==KBD_BUFFER_SIZE)      // Buffer is full
+   {
+      extKey=0;
+      return 0;
+   }
+   kbdBuffer[bufHead].bKeyDown=isDown;
+   kbdBuffer[bufHead].wRepeatCount=1;
+   kbdBuffer[bufHead].wVirtualKeyCode=ScanToVirtual(thisKey);
+   kbdBuffer[bufHead].wVirtualScanCode=thisKey;
+   // kbdBuffer[bufHead].uChar.AsciiChar=TranslateScanCode(thisKey);
+   kbdBuffer[bufHead].AsciiChar=VirtualToAscii(kbdBuffer[bufHead].wVirtualKeyCode,isDown);
+   kbdBuffer[bufHead].dwControlKeyState=ctrlKeyState;
+   if (extKey)
+      kbdBuffer[bufHead].dwControlKeyState|=ENHANCED_KEY;
+   bufHead++;
+   bufHead&=KBD_WRAP_MASK;    // Modulo KBD_BUFFER_SIZE
+   keysInBuffer++;
+   extKey=0;
+}
+
+
+//
+// Initialize keyboard
+//
+static void KeyboardConnectInterrupt(void)
+{
+   ULONG MappedIrq;
+   KIRQL Dirql;
+   KAFFINITY Affinity;
+   NTSTATUS Status;
+   
+   MappedIrq = HalGetInterruptVector(Internal,
+                                    0,
+                                    0,
+                                    KEYBOARD_IRQ,
+                                    &Dirql,
+                                    &Affinity);
+   Status = IoConnectInterrupt(&KbdInterrupt,
+                              KeyboardHandler,
+                              NULL,
+                              NULL,
+                              MappedIrq,
+                              Dirql,
+                              Dirql,
+                              0,
+                              FALSE,
+                              Affinity,
+                              FALSE);
+}
+
+static int InitializeKeyboard(void)
+{
+   // Initialize variables
+   bufHead=0;
+   bufTail=0;
+   keysInBuffer=0;
+   ledStatus=0;
+   capsDown=0;
+   numDown=0;
+   scrollDown=0;
+   ctrlKeyState=0;
+   extKey=0;
+
+   KeyboardConnectInterrupt();
+   KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
+   return 0;
+}
+
+
+/*
+ * Read data from keyboard buffer
+ */
+
+static void dummy(void)
+{
+}
+
+BOOLEAN KbdSynchronizeRoutine(PVOID Context)
+{
+   PIRP Irp = (PIRP)Context;
+   KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
+     Irp->AssociatedIrp.SystemBuffer;
+   PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
+   ULONG NrToRead = stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
+   int i;
+
+   DPRINT("NrToRead %d keysInBuffer %d\n",NrToRead,keysInBuffer);
+   NrToRead = min(NrToRead,keysInBuffer);
+   
+   DPRINT("NrToRead %d stk->Parameters.Read.Length %d\n",
+         NrToRead,stk->Parameters.Read.Length);
+   DPRINT("sizeof(KEY_EVENT_RECORD) %d\n",sizeof(KEY_EVENT_RECORD));
+   for (i=0;i<NrToRead;i++)
+     {
+       memcpy(&rec[i],&kbdBuffer[bufTail],sizeof(KEY_EVENT_RECORD));
+       bufTail++;
+       bufTail&=KBD_WRAP_MASK;
+       keysInBuffer--;
+    }
+   if ((stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD))==NrToRead)
+     {
+       return(TRUE);
+     }
+   
+   KeysRequired=stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
+   KeysRead=NrToRead;
+   CurrentIrp=Irp;
+   
+   return(FALSE);
+}
+
+VOID KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
+
+   DPRINT("KeyboardStartIo(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+
+   DPRINT("stk->Parameters.Read.Length %d\n",stk->Parameters.Read.Length);
+   DPRINT("KeysRequired %d\n",KeysRequired);     
+}
+
+NTSTATUS KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
+   NTSTATUS Status;
+
+   DPRINT("DeviceObject %x\n",DeviceObject);
+   DPRINT("Irp %x\n",Irp);
+
+   switch (stk->MajorFunction)
+     {
+      case IRP_MJ_CREATE:
+      case IRP_MJ_CLOSE:
+        Status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_READ:
+        DPRINT("Handling Read request\n");
+        if (KeSynchronizeExecution(KbdInterrupt,KbdSynchronizeRoutine,Irp))
+           {
+                Status = STATUS_SUCCESS;
+           }
+        else
+           {
+             DPRINT("Queueing packet\n");
+             IoStartPacket(DeviceObject,Irp,NULL,NULL);
+             Status = STATUS_PENDING;
+           }
+       break;
+       
+      default:
+        Status = STATUS_NOT_IMPLEMENTED;
+       break;
+     }
+   
+   if (Status==STATUS_PENDING)
+     {
+       DPRINT("Marking irp pending\n");
+       IoMarkIrpPending(Irp);
+     }
+   else
+     {
+        Irp->IoStatus.Status = Status;
+       Irp->IoStatus.Information = 0;
+       IoCompleteRequest(Irp,IO_NO_INCREMENT);
+     }
+   DPRINT("Status %d\n",Status);
+   return(Status);
+}
+
+/*
+ * Module entry point
+ */
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+{
+   PDEVICE_OBJECT DeviceObject;
+   ANSI_STRING adevice_name;
+   UNICODE_STRING device_name;
+   
+   DbgPrint("Keyboard Driver 0.0.4\n");
+   InitializeKeyboard();
+   
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch;
+   DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch;
+   DriverObject->DriverStartIo = KbdStartIo;
+   
+   RtlInitAnsiString(&adevice_name,"\\Device\\Keyboard");
+   RtlAnsiStringToUnicodeString(&device_name,&adevice_name,TRUE);
+   IoCreateDevice(DriverObject,0,&device_name,FILE_DEVICE_KEYBOARD,0,
+                 TRUE,&DeviceObject);
+   DeviceObject->Flags = DO_BUFFERED_IO;
+   
+   return(STATUS_SUCCESS);
+}
+               
+
diff --git a/reactos/drivers/dd/keyboard/keyboard.h b/reactos/drivers/dd/keyboard/keyboard.h
new file mode 100644 (file)
index 0000000..dbb63f6
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Some defines
+ */
+
+#define KEYBOARD_IRQ       1
+#define KBD_BUFFER_SIZE    32
+#define KBD_WRAP_MASK      0x1F
+
+#define disable()          __asm__("cli\n\t")
+#define enable()           __asm__("sti\n\t")
+
+#define ALT_PRESSED                    (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
+#define CTRL_PRESSED                   (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
+
+
+/*
+ * Keyboard controller ports
+ */
+
+#define KBD_DATA_PORT      0x60
+#define KBD_CTRL_PORT      0x64
+
+
+/*
+ * Controller commands
+ */
+
+#define KBD_READ_MODE      0x20
+#define KBD_WRITE_MODE     0x60
+#define KBD_SELF_TEST      0xAA
+#define KBD_LINE_TEST      0xAB
+#define KBD_CTRL_ENABLE    0xAE
+
+/*
+ * Keyboard commands
+ */
+
+#define KBD_ENABLE         0xF4
+#define KBD_DISABLE        0xF5
+#define KBD_RESET          0xFF
+
+
+/*
+ * Keyboard responces
+ */
+
+#define KBD_ACK            0xFA
+#define KBD_BATCC          0xAA
+
+
+/*
+ * Controller status register bits
+ */
+
+#define KBD_OBF            0x01
+#define KBD_IBF            0x02
+#define KBD_GTO            0x40
+#define KBD_PERR           0x80
+
+
+/*
+ * LED bits
+ */
+
+#define KBD_LED_SCROLL     0x01
+#define KBD_LED_NUM        0x02
+#define KBD_LED_CAPS       0x04
diff --git a/reactos/drivers/dd/keyboard/makefile b/reactos/drivers/dd/keyboard/makefile
new file mode 100644 (file)
index 0000000..77cf518
--- /dev/null
@@ -0,0 +1 @@
+all: keyboard.o 
diff --git a/reactos/drivers/dd/mouse/makefile b/reactos/drivers/dd/mouse/makefile
new file mode 100644 (file)
index 0000000..9fc004a
--- /dev/null
@@ -0,0 +1 @@
+all: mouse.o
diff --git a/reactos/drivers/dd/mouse/mouse.c b/reactos/drivers/dd/mouse/mouse.c
new file mode 100644 (file)
index 0000000..6afb23c
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+
+ ** Mouse driver 0.0.3
+ ** Written by Jason Filby (jasonfilby@yahoo.com)
+ ** For ReactOS (www.sid-dis.com/reactos)
+
+ ** Note: The serial.o driver must be loaded before loading this driver
+
+ ** Known Limitations:
+ ** Only supports mice on COM port 1
+
+*/
+
+#include <internal/mmhal.h>
+#include <internal/hal/io.h>
+#include <internal/hal/ddk.h>
+#include <funcs.h>
+
+#define MOUSE_IRQ_COM1  4
+#define MOUSE_IRQ_COM2  3
+
+#define COM1_PORT       0x3f8
+#define COM2_PORT       0x2f8
+
+#define max_screen_x    79
+#define max_screen_y    24
+
+static unsigned int MOUSE_IRQ=MOUSE_IRQ_COM1;
+static unsigned int MOUSE_COM=COM1_PORT;
+
+static unsigned int     bytepos=0, coordinate;
+static unsigned char    mpacket[3];
+static signed int       mouse_x=40, mouse_y=12;
+static unsigned char    mouse_button1, mouse_button2;
+static signed int       horiz_sensitivity, vert_sensitivity;
+
+BOOLEAN microsoft_mouse_handler(PKINTERRUPT Interrupt, PVOID ServiceContext)
+{
+        unsigned int mbyte=inb(MOUSE_COM);
+
+        // Synchronize
+        if((mbyte&64)==64) { bytepos=0; };
+
+        mpacket[bytepos]=mbyte;
+        bytepos++;
+
+        // Process packet
+        if(bytepos==3) {
+                // Retrieve change in x and y from packet
+                int change_x=((mpacket[0] & 3) << 6) + mpacket[1];
+                int change_y=((mpacket[0] & 12) << 4) + mpacket[2];
+
+                // Some mice need this
+                if(coordinate==1) {
+                  change_x-=128;
+                  change_y-=128;
+                };
+
+                // Change to signed
+                if(change_x>=128) { change_x=change_x-256; };
+                if(change_y>=128) { change_y=change_y-256; };
+
+                // Adjust mouse position according to sensitivity
+                mouse_x+=change_x/horiz_sensitivity;
+                mouse_y+=change_y/vert_sensitivity;
+
+                // Check that mouse is still in screen
+                if(mouse_x<0) { mouse_x=0; };
+                if(mouse_x>max_screen_x) { mouse_x=max_screen_x; };
+                if(mouse_y<0) { mouse_y=0; };
+                if(mouse_y>max_screen_y) { mouse_y=max_screen_y; };
+
+                // Retrieve mouse button status from packet
+                mouse_button1=mpacket[0] & 32;
+                mouse_button2=mpacket[0] & 16;
+
+                bytepos=0;
+        };
+
+};
+
+void InitializeMouseHardware(unsigned int mtype)
+{
+        char clear_error_bits;
+
+        outb_p(MOUSE_COM+3, 0x80); // set DLAB on
+        outb_p(MOUSE_COM, 0x60); // speed LO byte
+        outb_p(MOUSE_COM+1, 0); // speed HI byte
+        outb_p(MOUSE_COM+3, mtype); // 2=MS Mouse; 3=Mouse systems mouse
+        outb_p(MOUSE_COM+1, 0); // set comm and DLAB to 0
+        outb_p(MOUSE_COM+4, 1); // DR int enable
+        clear_error_bits=inb_p(MOUSE_COM+5); // clear error bits
+};
+
+int DetMicrosoft(void)
+{
+        char tmp, ind;
+        int buttons=0, i;
+
+        outb_p(MOUSE_COM+4, 0x0b);
+        tmp=inb_p(MOUSE_COM);
+
+        // Check the first for bytes for signs that this is an MS mouse
+        for(i=0; i<4; i++) {
+                while((inb_p(MOUSE_COM+5) & 1)==0) ;
+                ind=inb_p(MOUSE_COM);
+                if(ind==0x33) buttons=3;
+                if(ind==0x4d) buttons=2;
+        };
+
+        return buttons;
+};
+
+int CheckMouseType(unsigned int mtype)
+{
+        unsigned int retval=0;
+
+        InitializeMouseHardware(mtype);
+        if(mtype==2) retval=DetMicrosoft();
+        if(mtype==3) {
+                outb_p(MOUSE_COM+4, 11);
+                retval=3;
+        };
+        outb_p(MOUSE_COM+1, 1);
+
+        return retval;
+};
+
+void ClearMouse(void)
+{
+        // Waits until the mouse calms down but also quits out after a while
+        // in case some destructive user wants to keep moving the mouse
+        // before we're done
+
+        unsigned int restarts=0, i;
+        for (i=0; i<60000; i++)
+        {
+          unsigned temp=inb(MOUSE_COM);
+          if(temp!=0) {
+            restarts++;
+            if(restarts<300000) {
+                    i=0;
+            } else
+            {
+                    i=60000;
+            };
+          };
+        };
+};
+
+void InitializeMouse(void)
+{
+        int mbuttons=0, gotmouse=0;
+        ULONG MappedIrq;
+        KIRQL Dirql;
+        KAFFINITY Affinity;
+        PKINTERRUPT IrqObject;
+
+        horiz_sensitivity=2;
+        vert_sensitivity=3;
+
+        // Check for Microsoft mouse (2 buttons)
+        if(CheckMouseType(2)!=0)
+        {
+                gotmouse=1;
+                DbgPrint("Microsoft Mouse Detected\n");
+                ClearMouse();
+                coordinate=0;
+        };
+
+        // Check for Microsoft Systems mouse (3 buttons)
+        if(gotmouse==0) {
+          if(CheckMouseType(3)!=0)
+          {
+                gotmouse=1;
+                DbgPrint("Microsoft Mouse Detected\n");
+                ClearMouse();
+                coordinate=1;
+          };
+        };
+
+        if(gotmouse==0) {
+                DbgPrint("No Mouse Detected!\n");
+        } else {
+                MappedIrq = HalGetInterruptVector(Internal, 0, 0, MOUSE_IRQ,
+                                                  &Dirql, &Affinity);
+
+                IoConnectInterrupt(&IrqObject, microsoft_mouse_handler, NULL,
+                                   NULL, MappedIrq, Dirql, Dirql, 0, FALSE,
+                                   Affinity, FALSE);
+        };
+};
+
+// For test purposes only
+unsigned char get_text_char(int x, int y)
+{
+        unsigned char getchar;
+        char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
+        getchar=*vidmem;
+        return getchar;
+};
+
+// For test purposes only
+unsigned char get_text_color(int x, int y)
+{
+        unsigned char getcolor;
+        char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
+        vidmem++;
+        getcolor=*vidmem;
+        return getcolor;
+};
+
+// For test purposes only
+void put_text_char(int x, int y, unsigned char putchar[2])
+{
+        char *vidmem=(char*)physical_to_linear((0xb8000+(y*160)+(x*2)));
+        *vidmem=putchar[0];
+        vidmem++;
+        *vidmem=putchar[1];
+};
+
+// For test purposes only
+void test_mouse(void)
+{
+  static int i=0, forcechange=0;
+  static int old_x=40, old_y=12;
+  static unsigned char old_cursor[2], new_cursor[2];
+
+  DbgPrint("Testing mouse...");
+
+  old_cursor[0]=' ';
+  old_cursor[1]=7;
+  new_cursor[0]='Û';
+  new_cursor[1]=15;
+
+  old_cursor[0]=get_text_char(mouse_x, mouse_y);
+  old_cursor[1]=get_text_color(mouse_x, mouse_y);
+  put_text_char(mouse_x, mouse_y, new_cursor);
+
+  while(i!=1)
+  {
+    if(mouse_button1!=0) { new_cursor[1]=10; mouse_button1=0; forcechange=1; };
+    if(mouse_button2!=0) { new_cursor[1]=12; mouse_button2=0; forcechange=1; };
+
+    if((mouse_x!=old_x) || (mouse_y!=old_y) || (forcechange==1)) {
+        forcechange=0;
+
+        put_text_char(old_x, old_y, old_cursor);
+        old_cursor[0]=get_text_char(mouse_x, mouse_y);
+        old_cursor[1]=get_text_color(mouse_x, mouse_y);
+        put_text_char(mouse_x, mouse_y, new_cursor);
+
+        old_x=mouse_x;
+        old_y=mouse_y;
+    };
+  };
+};
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+{
+        DbgPrint("Mouse Driver 0.0.3\n");
+        InitializeMouse();
+        test_mouse();
+
+        return(STATUS_SUCCESS);
+};
+
diff --git a/reactos/drivers/dd/null/makefile b/reactos/drivers/dd/null/makefile
new file mode 100644 (file)
index 0000000..6cc6c40
--- /dev/null
@@ -0,0 +1 @@
+all: null.o
diff --git a/reactos/drivers/dd/null/null.c b/reactos/drivers/dd/null/null.c
new file mode 100644 (file)
index 0000000..6f4af0e
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/null/null.c
+ * PURPOSE:          NULL device driver
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY:
+ *              13/08/98: Created
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include <ddk/ntddk.h>
+
+/* FUNCTIONS **************************************************************/
+
+NTSTATUS NullWrite(PIRP Irp, PIO_STACK_LOCATION stk)
+{
+   Irp->IoStatus.Information = stk->Parameters.Write.Length;
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS NullRead(PIRP Irp, PIO_STACK_LOCATION stk)
+{
+   Irp->IoStatus.Information = 0;
+   return(STATUS_END_OF_FILE);
+}
+
+NTSTATUS NullDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/*
+ * FUNCTION: Handles user mode requests
+ * ARGUMENTS:
+ *           DeviceObject = Device for request
+ *           Irp = I/O request packet describing request
+ * RETURNS: Success or failure
+ */
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   NTSTATUS status;
+   
+   switch (Stack->MajorFunction)
+     {
+      case IRP_MJ_CREATE:
+      case IRP_MJ_CLOSE:
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_WRITE:
+       status = NullWrite(Irp,Stack);
+        break;
+       
+      case IRP_MJ_READ:
+       status = NullRead(Irp,Stack);
+        break;
+       
+      default:
+        status = STATUS_NOT_IMPLEMENTED;
+     }
+
+   Irp->IoStatus.Status = status;
+   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+   return(status);
+}
+
+NTSTATUS NullUnload(PDRIVER_OBJECT DriverObject)
+{
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   PDEVICE_OBJECT DeviceObject;
+   NTSTATUS ret;
+   ANSI_STRING ansi_device_name;
+   UNICODE_STRING device_name;
+   
+   DbgPrint("Null Device Driver 0.0.1\n");
+   
+   RtlInitAnsiString(&ansi_device_name,"\\Device\\NUL");
+   RtlAnsiStringToUnicodeString(&device_name,&ansi_device_name,TRUE);
+   ret = IoCreateDevice(DriverObject,0,&device_name,
+                        FILE_DEVICE_NULL,0,FALSE,&DeviceObject);
+   if (ret!=STATUS_SUCCESS)
+     {
+       return(ret);
+     }
+
+   DeviceObject->Flags=0;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = NullDispatch;
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = NullDispatch;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = NullDispatch;
+   DriverObject->MajorFunction[IRP_MJ_READ] = NullDispatch;
+   DriverObject->DriverUnload = NullUnload;
+   
+   return(STATUS_SUCCESS);
+}
+
diff --git a/reactos/drivers/dd/parallel/makefile b/reactos/drivers/dd/parallel/makefile
new file mode 100644 (file)
index 0000000..3770f6e
--- /dev/null
@@ -0,0 +1 @@
+all: parallel.o
diff --git a/reactos/drivers/dd/parallel/parallel.c b/reactos/drivers/dd/parallel/parallel.c
new file mode 100644 (file)
index 0000000..7cdcc4d
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/parallel/parallel.c
+ * PURPOSE:          Parallel port driver
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ *              ??/??/??: Created
+ *              18/06/98: Made more NT like
+ */
+
+/* FUNCTIONS **************************************************************/
+
+#include <ddk/ntddk.h>
+
+#include "parallel.h"
+
+#define LP_B (0x378)
+#define LP_S (inb_p(LP_B+1))
+#define LP_C (LP_B+2)
+
+static void Parallel_Reset(void)
+/*
+ * FUNCTION: Resets the device attached to the parallel port
+ */
+     {
+       int i;
+       
+        outb_p(LP_C,0);
+       for (i=0;i<LP_DELAY;i++);
+        outb_p(LP_C,LP_PSELECP | LP_PINITP);
+     }
+
+static void Parallel_putchar(unsigned char ch)
+/*
+ * FUNCTION: Writes a character to the parallel port
+ * ARGUMENTS:
+ *          ch = character to write
+ */
+     {
+       
+       int count=0;
+       int status;
+       int wait=0;
+
+       do
+         {
+            status=LP_S;
+            count++;
+         }
+       while ( count < 500000 && !(status & LP_PBUSY) );
+         
+        if (count==500000)
+         {
+             printk("printer_putchar(): timed out\n");
+            return;
+         }
+       
+        outb_p(LP_B,ch);
+       while (wait != 10000) { wait++; }
+        outb_p(LP_C, (LP_PSELECP | LP_PINITP | LP_PSTROBE ));
+       while (wait) { wait--; }
+        outb_p(LP_C, LP_PSELECP | LP_PINITP);
+     }
+
+NTSTATUS Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/*
+ * FUNCTION: Handles user mode requests
+ * ARGUMENTS:
+ *           DeviceObject = Device for request
+ *           Irp = I/O request packet describing request
+ * RETURNS: Success or failure
+ */
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   NTSTATUS status;
+   int i;
+   
+   switch (Stack->MajorFunction)
+     {
+      case IRP_MJ_CREATE:
+        printk("(Parallel Port Driver) Creating\n");
+       Parallel_Reset();
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_CLOSE:
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_WRITE:
+        printk("(Parallel Port Driver) Writing %d bytes\n",
+               Stack->Parameters.Write.Length);
+       for (i=0;i<Stack->Parameters.Write.Length;i++)
+         {
+                Parallel_putchar(((char *)Irp->UserBuffer)[i]);             
+         }
+       status = STATUS_SUCCESS;
+       break;
+       
+      default:
+        status = STATUS_NOT_IMPLEMENTED;
+       break;
+     }
+   
+   Irp->IoStatus.Status = status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(status);
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   PDEVICE_OBJECT DeviceObject;
+   NTSTATUS ret;
+   
+   printk("Parallel Port Driver 0.0.1\n");
+          
+   
+   ret = IoCreateDevice(DriverObject,0,"\\Device\\Parallel",
+                        FILE_DEVICE_PARALLEL_PORT,0,FALSE,&DeviceObject);
+   if (ret!=STATUS_SUCCESS)
+     {
+       return(ret);
+     }
+
+   DeviceObject->Flags=0;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dispatch;
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = Dispatch;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch;
+   DriverObject->DriverUnload = NULL;
+   
+   return(STATUS_SUCCESS);
+}
+
diff --git a/reactos/drivers/dd/parallel/parallel.h b/reactos/drivers/dd/parallel/parallel.h
new file mode 100644 (file)
index 0000000..07f9c92
--- /dev/null
@@ -0,0 +1,137 @@
+#ifndef _LINUX_LP_H
+#define _LINUX_LP_H
+
+/*
+ * usr/include/linux/lp.h c.1991-1992 James Wiegand
+ * many modifications copyright (C) 1992 Michael K. Johnson
+ * Interrupt support added 1993 Nigel Gamble
+ */
+
+/*
+ * Per POSIX guidelines, this module reserves the LP and lp prefixes
+ * These are the lp_table[minor].flags flags...
+ */
+#define LP_EXIST 0x0001
+#define LP_SELEC 0x0002
+#define LP_BUSY         0x0004
+#define LP_OFFL         0x0008
+#define LP_NOPA  0x0010
+#define LP_ERR   0x0020
+#define LP_ABORT 0x0040
+#define LP_CAREFUL 0x0080
+#define LP_ABORTOPEN 0x0100
+
+/* timeout for each character.  This is relative to bus cycles -- it
+ * is the count in a busy loop.  THIS IS THE VALUE TO CHANGE if you
+ * have extremely slow printing, or if the machine seems to slow down
+ * a lot when you print.  If you have slow printing, increase this
+ * number and recompile, and if your system gets bogged down, decrease
+ * this number.  This can be changed with the tunelp(8) command as well.
+ */
+
+#define LP_INIT_CHAR 1000
+
+/* The parallel port specs apparently say that there needs to be
+ * a .5usec wait before and after the strobe.  Since there are wildly
+ * different computers running linux, I can't come up with a perfect
+ * value, but since it worked well on most printers before without,
+ * I'll initialize it to 0.
+ */
+
+#define LP_INIT_WAIT 0
+
+/* This is the amount of time that the driver waits for the printer to
+ * catch up when the printer's buffer appears to be filled.  If you
+ * want to tune this and have a fast printer (i.e. HPIIIP), decrease
+ * this number, and if you have a slow printer, increase this number.
+ * This is in hundredths of a second, the default 2 being .05 second.
+ * Or use the tunelp(8) command, which is especially nice if you want
+ * change back and forth between character and graphics printing, which
+ * are wildly different...
+ */
+
+#define LP_INIT_TIME 2
+
+/* IOCTL numbers */
+#define LPCHAR   0x0601  /* corresponds to LP_INIT_CHAR */
+#define LPTIME   0x0602  /* corresponds to LP_INIT_TIME */
+#define LPABORT  0x0604  /* call with TRUE arg to abort on error,
+                           FALSE to retry.  Default is retry.  */
+#define LPSETIRQ 0x0605  /* call with new IRQ number,
+                           or 0 for polling (no IRQ) */
+#define LPGETIRQ 0x0606  /* get the current IRQ number */
+#define LPWAIT   0x0608  /* corresponds to LP_INIT_WAIT */
+#define LPCAREFUL   0x0609  /* call with TRUE arg to require out-of-paper, off-
+                           line, and error indicators good on all writes,
+                           FALSE to ignore them.  Default is ignore. */
+#define LPABORTOPEN 0x060a  /* call with TRUE arg to abort open() on error,
+                           FALSE to ignore error.  Default is ignore.  */
+#define LPGETSTATUS 0x060b  /* return LP_S(minor) */
+#define LPRESET     0x060c  /* reset printer */
+
+/* timeout for printk'ing a timeout, in jiffies (100ths of a second).
+   This is also used for re-checking error conditions if LP_ABORT is
+   not set.  This is the default behavior. */
+
+#define LP_TIMEOUT_INTERRUPT   (60 * HZ)
+#define LP_TIMEOUT_POLLED      (10 * HZ)
+
+#if 0
+#define LP_B(minor)    lp_table[(minor)].base          /* IO address */
+#define LP_F(minor)    lp_table[(minor)].flags         /* flags for busy, etc. */
+#define LP_S(minor)    inb_p(LP_B((minor)) + 1)        /* status port */
+#define LP_C(minor)    (lp_table[(minor)].base + 2)    /* control port */
+#define LP_CHAR(minor) lp_table[(minor)].chars         /* busy timeout */
+#define LP_TIME(minor) lp_table[(minor)].time          /* wait time */
+#define LP_WAIT(minor) lp_table[(minor)].wait          /* strobe wait */
+#define LP_IRQ(minor)  lp_table[(minor)].irq           /* interrupt # */
+                                                       /* 0 means polled */
+#endif
+
+#define LP_BUFFER_SIZE 256
+
+
+/*
+ * The following constants describe the various signals of the printer port
+ * hardware.  Note that the hardware inverts some signals and that some
+ * signals are active low.  An example is LP_STROBE, which must be programmed
+ * with 1 for being active and 0 for being inactive, because the strobe signal
+ * gets inverted, but it is also active low.
+ */
+
+/* 
+ * bit defines for 8255 status port
+ * base + 1
+ * accessed with LP_S(minor), which gets the byte...
+ */
+#define LP_PBUSY       0x80  /* inverted input, active high */
+#define LP_PACK                0x40  /* unchanged input, active low */
+#define LP_POUTPA      0x20  /* unchanged input, active high */
+#define LP_PSELECD     0x10  /* unchanged input, active high */
+#define LP_PERRORP     0x08  /* unchanged input, active low */
+
+/* 
+ * defines for 8255 control port
+ * base + 2 
+ * accessed with LP_C(minor)
+ */
+#define LP_PINTEN      0x10
+#define LP_PSELECP     0x08  /* inverted output, active low */
+#define LP_PINITP      0x04  /* unchanged output, active low */
+#define LP_PAUTOLF     0x02  /* inverted output, active low */
+#define LP_PSTROBE     0x01  /* inverted output, active low */
+
+/* 
+ * the value written to ports to test existence. PC-style ports will 
+ * return the value written. AT-style ports will return 0. so why not
+ * make them the same ? 
+ */
+#define LP_DUMMY       0x00
+
+/*
+ * This is the port delay time.  Your mileage may vary.
+ * It is used only in the lp_init() routine.
+ */
+#define LP_DELAY       150000
+
+#endif
diff --git a/reactos/drivers/dd/sdisk/makefile b/reactos/drivers/dd/sdisk/makefile
new file mode 100644 (file)
index 0000000..2bffb37
--- /dev/null
@@ -0,0 +1,4 @@
+all: sdisk.o
+
+WIN32_LEAN_AND_MEAN = yes
+include ../../../rules.mak
diff --git a/reactos/drivers/dd/sdisk/sdisk.c b/reactos/drivers/dd/sdisk/sdisk.c
new file mode 100644 (file)
index 0000000..518b6c3
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/sdisk/sdisk.c
+ * PURPOSE:          Disk driver for Bochs
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/hal/io.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+/* FUNCTIONS **************************************************************/
+
+#define PORT      (0x3ec)
+
+static VOID SdWriteOffset(ULONG Offset)
+{
+   outl_p(PORT,Offset);
+}
+
+NTSTATUS Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/*
+ * FUNCTION: Handles user mode requests
+ * ARGUMENTS:
+ *           DeviceObject = Device for request
+ *           Irp = I/O request packet describing request
+ * RETURNS: Success or failure
+ */
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   NTSTATUS status;
+   int i;
+   PCH Buffer;
+   ULONG Length;
+   ULONG Information = 0;
+   
+   switch (Stack->MajorFunction)
+     {
+      case IRP_MJ_CREATE:
+        DPRINT("Creating\n",0);
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_CLOSE:
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_WRITE:
+        DPRINT("Writing %d bytes\n",
+               Stack->Parameters.Write.Length);
+       Length = Stack->Parameters.Write.Length;
+       if ((Length%512)>0)
+         {
+            Length = Length - (Length%512);
+         }
+       Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+       DPRINT("Buffer %x\n",Buffer);
+       #if 0
+       for (i=0;i<Length;i++)
+         {
+            if ((i%512)==0)
+              {
+                 DPRINT("Offset %x\n",
+                          Stack->Parameters.Write.ByteOffset.LowPart+i);
+                 SdWriteOffset(Stack->Parameters.Write.ByteOffset.LowPart+i);
+              }
+            outb_p(PORT,Buffer[i]);
+            DbgPrint("%c",Buffer[i]);
+         }
+       #endif
+       for (i=0;i<(Length/512);i++)
+         {
+            DPRINT("Offset %x\n",
+                   Stack->Parameters.Write.ByteOffset.LowPart+i);
+                 SdWriteOffset(Stack->Parameters.Write.ByteOffset.LowPart+i);    
+            outsb(PORT,Buffer,512);
+         }
+       status = STATUS_SUCCESS;
+       Information = Length;
+       break;
+      
+      case IRP_MJ_READ:
+        DPRINT("Reading %d bytes\n",
+               Stack->Parameters.Write.Length);
+       Length = Stack->Parameters.Write.Length;
+       if ((Length%512)>0)
+         {
+            Length = Length - (Length%512);
+         }
+       Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+       for (i=0;i<Length;i++)
+         {
+            if ((i%512)==0)
+              {
+                 DPRINT("Offset %d\n",
+                          Stack->Parameters.Write.ByteOffset.LowPart+i);
+                 SdWriteOffset(Stack->Parameters.Write.ByteOffset.LowPart+i);
+              }
+            Buffer[i]=inb_p(PORT);
+         }
+       status = STATUS_SUCCESS;
+       break;
+       
+      default:
+        status = STATUS_NOT_IMPLEMENTED;
+       break;
+     }
+   
+   Irp->IoStatus.Status = status;
+   Irp->IoStatus.Information = Information;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(status);
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   PDEVICE_OBJECT DeviceObject;
+   NTSTATUS ret;
+   ANSI_STRING astr;
+   UNICODE_STRING ustr;
+   ANSI_STRING asymlink;
+   UNICODE_STRING usymlink;
+   
+   DbgPrint("Simple Disk Driver 0.0.1\n");
+          
+   RtlInitAnsiString(&astr,"\\Device\\SDisk");
+   RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
+   ret = IoCreateDevice(DriverObject,0,&ustr,
+                        FILE_DEVICE_DISK,0,FALSE,&DeviceObject);
+   if (ret!=STATUS_SUCCESS)
+     {
+       return(ret);
+     }
+   
+   RtlInitAnsiString(&asymlink,"\\??\\C:");
+   RtlAnsiStringToUnicodeString(&usymlink,&asymlink,TRUE);
+   IoCreateSymbolicLink(&usymlink,&ustr);
+   
+   DeviceObject->Flags=DO_DIRECT_IO;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dispatch;
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = Dispatch;
+   DriverObject->MajorFunction[IRP_MJ_READ] = Dispatch;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch;
+   DriverObject->DriverUnload = NULL;
+   
+   return(STATUS_SUCCESS);
+}
+
diff --git a/reactos/drivers/dd/serial/makefile b/reactos/drivers/dd/serial/makefile
new file mode 100644 (file)
index 0000000..fa05b0f
--- /dev/null
@@ -0,0 +1 @@
+all: serial.o
diff --git a/reactos/drivers/dd/serial/serial.c b/reactos/drivers/dd/serial/serial.c
new file mode 100644 (file)
index 0000000..8241c7c
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+
+ ** Serial driver
+ ** Written by Jason Filby (jasonfilby@yahoo.com)
+ ** For ReactOS (www.sid-dis.com/reactos)
+
+*/
+
+#include <internal/mmhal.h>
+#include <internal/hal/io.h>
+
+#define COM1    0x3F8
+#define COM2    0x2F8
+#define COM3    0x3E8
+#define COM4    0x2E8
+
+#define UART_BAUDRATE   96      // 1200 BPS
+#define UART_LCRVAL     0x1b    // 0x1b for 8e1
+#define UARY_FCRVAL     0x7
+
+int uart_detect(unsigned base)
+{
+        // Returns 0 if no UART detected
+
+        int olddata=inb_p(base+4);
+        outb_p(base+4, 0x10);
+        if ((inb_p(base+6) & 0xf0)) return 0;
+        return 1;
+};
+
+int irq_setup(unsigned base)
+{
+        // Returns -1 if not found -- otherwise returns interrupt level
+
+        char ier, mcr, imrm, imrs, maskm, masks, irqm, irqs;
+
+        __asm("cli");          // disable all CPU interrupts
+        ier = inb_p(base+1);   // read IER
+        outb_p(base+1,0);      // disable all UART ints
+        while (!(inb_p(base+5)&0x20));  // wait for the THR to be empty
+        mcr = inb_p(base+4);   // read MCR
+        outb_p(base+4,0x0F);   // connect UART to irq line
+        imrm = inb_p(0x21);    // read contents of master ICU mask register
+        imrs = inb_p(0xA1);    // read contents of slave ICU mask register
+        outb_p(0xA0,0x0A);     // next read access to 0xA0 reads out IRR
+        outb_p(0x20,0x0A);     // next read access to 0x20 reads out IRR
+        outb_p(base+1,2);      // let's generate interrupts...
+        maskm = inb_p(0x20);   // this clears all bits except for the one
+        masks = inb_p(0xA0);   // that corresponds to the int
+        outb_p(base+1,0);      // drop the int line
+        maskm &= ~inb_p(0x20); // this clears all bits except for the one
+        masks &= ~inb_p(0xA0); // that corresponds to the int
+        outb_p(base+1,2);      // and raise it again just to be sure...
+        maskm &= inb_p(0x20);  // this clears all bits except for the one
+        masks &= inb_p(0xA0);  // that corresponds to the int
+        outb_p(0xA1,~masks);   // now let us unmask this interrupt only
+        outb_p(0x21,~maskm);
+        outb_p(0xA0,0x0C);     // enter polled mode
+        outb_p(0x20,0x0C);     // that order is important with Pentium/PCI systems
+        irqs = inb_p(0xA0);    // and accept the interrupt
+        irqm = inb_p(0x20);
+        inb_p(base+2);         // reset transmitter interrupt in UART
+        outb_p(base+4,mcr);    // restore old value of MCR
+        outb_p(base+1,ier);    // restore old value of IER
+        if (masks) outb_p(0xA0,0x20);  // send an EOI to slave
+        if (maskm) outb_p(0x20,0x20);  // send an EOI to master
+        outb_p(0x21,imrm);     // restore old mask register contents
+        outb_p(0xA1,imrs);
+        __asm("sti");
+        if (irqs&0x80)       // slave interrupt occured
+          return (irqs&0x07)+8;
+        if (irqm&0x80)       // master interrupt occured
+          return irqm&0x07;
+        return -1;
+};
+
+void uart_init(unsigned uart_base)
+{
+        // Initialize the UART
+        outb_p(uart_base+3, 0x80);
+        outw_p(uart_base, UART_BAUDRATE);
+        outb_p(uart_base+3, UART_LCRVAL);
+        outb_p(uart_base+4, 0);
+};
+
+unsigned uart_getchar(unsigned uart_base)
+{
+        unsigned x;
+
+        x=(inb_p(uart_base+5) & 0x9f) << 8;
+        if(x & 0x100) x|=((unsigned)inb_p(uart_base)) & 0xff;
+        return x;
+};
+
+void InitializeSerial(void)
+{
+        unsigned comports[4] = { COM1, COM2, COM3, COM4 };
+        char *comname[4] = { "COM1", "COM2", "COM3", "COM4" };
+        int i, irq_level;
+
+        for (i=0; i<4; i++)
+        {
+                if(uart_detect(comports[i])==0)
+                {
+                          printk("%s not detected\n", comname[i]);
+                } else {
+                          uart_init(comports[i]);
+                          irq_level=irq_setup(comports[i]);
+                          if(irq_level==-1)
+                          {
+                                    printk("Warning: IRQ not detected!\n");
+                          } else {
+                                    printk("%s hooked to interrupt level %d\n", comname[i], irq_level);
+                          };
+                };
+        };
+};
+
+// For testing purposes
+void testserial()
+{
+        int i=0;
+        char testc;
+
+        union {
+          unsigned val;
+          char character;
+        } x;
+
+        printk("Testing serial input...\n");
+
+        while(i==0) {
+          x.val=uart_getchar(COM1);
+//    if(!x.val) continue;
+//    if(x.val & 0x100)
+
+                testc=inb_p(COM1);
+
+//    printk("(%x-%c)  %c\n", x.val, x.character, testc);
+        };
+};
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+{
+        printk("Serial Driver 0.0.2\n");
+        InitializeSerial();
+//        testserial();
+        return(STATUS_SUCCESS);
+};
+
diff --git a/reactos/drivers/dd/sound/dsp.c b/reactos/drivers/dd/sound/dsp.c
new file mode 100644 (file)
index 0000000..e318a59
--- /dev/null
@@ -0,0 +1,61 @@
+/************************************
+ * unsigned char read_dsp(void)
+ *
+ * Reads the DSP chip
+ * Arguments: none
+ * Returns: Byte read
+ ************************************/
+unsigned char read_dsp(unsigned short base)
+{
+       while((inb(base+0x0e)&0x80)==0);        //Wait until there is something to read
+       return  inb(base+0x0a);
+}
+
+/************************************'
+ * sb_status detect_dsp(void);
+ *
+ * Detects if a SB16 is installed
+ * Arguments: None
+ * Returns: Success or failure
+ ************************************/
+sb_status detect_dsp(SB16* sb16)
+{
+       for(base=0x200;base<0x280;base+=0x10)   //Tries to reset all DSP addresses there is
+               if(reset_dsp(base)==SB_TRUE)
+               {
+                       sb16->base=base;
+                       return SB_TRUE;
+               }
+       return SB_FALSE;
+}
+
+/**************************************
+ * sb_status reset_dsp(unsigned short base_address);
+ *
+ * Tries to reset a DSP chip
+ * Arguments: base address
+ * Returns: Success of failure
+ **************************************/
+sb_status reset_dsp(unsigned short base_address)
+{
+       int delay;
+
+       outb(base_address+DSP_RESET_PORT,1);
+       for(delay=0;delay<0xffff;delay++);
+
+       outb(base_address+DSP_RESET_PORT,0);
+       for(delay=0;delay<0xffff;delay++);
+
+       if((inb(base_address+DSP_READ_STATUS_PORT)&0x80)==0) return SB_FALSE;
+
+       if(inb(base_address+DSP_READ_DATA_PORT)!=0xAA) return SB_FALSE;
+
+       return SB_TRUE;
+}
+       
+void write_dsp(unsigned short base,unsigned char data)
+{
+  while ((inb(base+DSP_WRITE_PORT) & 0x80) != 0);
+  outb(base+DSP_WRITE_PORT, data);
+}
+  
\ No newline at end of file
diff --git a/reactos/drivers/dd/sound/dsp.h b/reactos/drivers/dd/sound/dsp.h
new file mode 100644 (file)
index 0000000..543cf44
--- /dev/null
@@ -0,0 +1,17 @@
+#define SB_TRUE                0
+#define SB_FALSE       1
+
+#define DSP_MIXER_ADDRESS_PORT 0x04
+#define DSP_MIXER_DATA_PORT            0x05
+#define DSP_RESET_PORT                                 0x06
+#define DSP_READ_DATA_PORT             0x0A
+#define DSP_WRITE_PORT                                 0x0C            //Same port used for reading status and writing data
+#define DSP_READ_STATUS_PORT   0x0E
+
+typedef unsigned char sb_status;
+unsigned short base;
+unsigned char irq,dma8,dma16;
+unsigned char read_dsp(unsigned short base);
+void write_dsp(unsigned short base,unsigned char data);
+sb_status detect_dsp(SB16* sb16);
+sb_status reset_dsp(unsigned short base_address);
diff --git a/reactos/drivers/dd/sound/makefile b/reactos/drivers/dd/sound/makefile
new file mode 100644 (file)
index 0000000..6819bcb
--- /dev/null
@@ -0,0 +1,2 @@
+sound.o: sound.c dsp.c mixer.c wave.h wave.c
+all: sound.o
diff --git a/reactos/drivers/dd/sound/mixer.c b/reactos/drivers/dd/sound/mixer.c
new file mode 100644 (file)
index 0000000..0be3de4
--- /dev/null
@@ -0,0 +1,32 @@
+unsigned char read_mixer(unsigned short base,unsigned char reg)
+{
+
+       outb(base+0x04,reg);
+       return inb(base+0x05);
+}
+
+unsigned char get_irq(SB16* sb16)
+{
+       unsigned char irq;
+       irq=(read_mixer(sb16->base,MIXER_INTERRUPT_SETUP_REGISTER)&0x0f);
+
+       if(irq==1) sb16->irq=2;
+       if(irq==2) sb16->irq=5;
+       if(irq==4) sb16->irq=7;
+       if(irq==8) sb16->irq=10;
+       return 0;
+}
+
+void get_dma(SB16* sb16)
+{
+       unsigned char hi,lo,result=read_mixer(sb16->base,MIXER_DMA_SETUP_REGISTER);
+  hi=result&0xE0;
+  lo=result&0x0B;
+  if(hi==0x80) sb16->dma16=7;
+  if(hi==0x40) sb16->dma16=6;
+  if(hi==0x20) sb16->dma16=5;
+  
+  if(lo==0x08) sb16->dma8=3;
+  if(lo==0x02) sb16->dma8=1;
+  if(lo==0x01) sb16->dma8=0;
+}
\ No newline at end of file
diff --git a/reactos/drivers/dd/sound/mixer.h b/reactos/drivers/dd/sound/mixer.h
new file mode 100644 (file)
index 0000000..564ae35
--- /dev/null
@@ -0,0 +1,8 @@
+#define MIXER_INTERRUPT_SETUP_REGISTER 0x80
+#define MIXER_DMA_SETUP_REGISTER                               0x81
+#define MIXER_INTERRUP_STATUS_REGISTEER        0x82
+
+void get_dma(SB16* sb16);
+unsigned char read_mixer(unsigned short base,unsigned char reg);
+unsigned char get_irq(SB16* sb16);
+
diff --git a/reactos/drivers/dd/sound/sb16.h b/reactos/drivers/dd/sound/sb16.h
new file mode 100644 (file)
index 0000000..cbe6704
--- /dev/null
@@ -0,0 +1,9 @@
+typedef struct
+{
+       unsigned short base;
+       unsigned char irq;
+       unsigned char dma8;
+       unsigned char dma16;
+       unsigned char* buffer;
+}SB16;
+       
\ No newline at end of file
diff --git a/reactos/drivers/dd/sound/sb_waveout.c b/reactos/drivers/dd/sound/sb_waveout.c
new file mode 100644 (file)
index 0000000..eeb523d
--- /dev/null
@@ -0,0 +1,3 @@
+void write_wave()
+{
+}
\ No newline at end of file
diff --git a/reactos/drivers/dd/sound/sound.c b/reactos/drivers/dd/sound/sound.c
new file mode 100644 (file)
index 0000000..9fcca25
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             mkernel/modules/sound/sound.c
+ * PURPOSE:          SoundBlaster 16 Driver
+ * PROGRAMMER:       Snatched from David Welch (welch@mcmail.com)
+ *                                                                      Modified for Soundblaster by Robert Bergkvist (fragdance@hotmail.com)
+ * UPDATE HISTORY: 
+ *              ??/??/??: Created
+ *              
+ */
+
+/* FUNCTIONS **************************************************************/
+
+#include <internal/hal/io.h>
+#include <ddk/ntddk.h>
+#include <internal/hal/ddk.h>
+#include <internal/dma.h>
+#include <internal/mm.h>
+#include <internal/string.h>
+#include <devices.h>
+#include "sb16.h"
+#include "dsp.h"
+#include "mixer.h"
+#include "in.h"
+#include "wave.h"
+
+
+SB16 sb16;
+sb_status sb16_getenvironment(void);
+
+NTSTATUS Dispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/*
+ * FUNCTION: Handles user mode requests
+ * ARGUMENTS:
+ *           DeviceObject = Device for request
+ *           Irp = I/O request packet describing request
+ * RETURNS: Success or failure
+ */
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   NTSTATUS status;
+   
+   switch (Stack->MajorFunction)
+     {
+      case IRP_MJ_CREATE:
+       printk("(SoundBlaster 16 Driver WaveOut) Creating\n");
+       reset_dsp(sb16.base);
+               status = STATUS_SUCCESS;
+       break;
+       
+     case IRP_MJ_CLOSE:
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_WRITE:
+        printk("(SoundBlaster 16 Driver) Writing %d bytes\n",Stack->Parameters.Write.Length);
+        sb16_play((WAVE_HDR*)Irp->UserBuffer);
+       status = STATUS_SUCCESS;
+       break;
+       
+      default:
+        status = STATUS_NOT_IMPLEMENTED;
+       break;
+       }
+   
+   Irp->IoStatus.Status = status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(status);
+}
+
+NTSTATUS ModuleEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+       PDEVICE_OBJECT DeviceObject;
+       NTSTATUS ret;
+   
+       printk("SoundBlaster 16 Driver 0.0.1\n");
+       if(sb16_getenvironment()!=SB_TRUE)
+       {
+               printk("Soundblaster 16 not found\n");
+               return 0;
+       }
+       ret = IoCreateDevice(DriverObject,0,"\\Device\\WaveOut",FILE_DEVICE_WAVE_OUT,0,FALSE,&DeviceObject);
+       if (ret!=STATUS_SUCCESS)
+               return(ret);
+               
+       DeviceObject->Flags=0;
+       DriverObject->MajorFunction[IRP_MJ_CLOSE] = Dispatch;
+       DriverObject->MajorFunction[IRP_MJ_CREATE] =Dispatch;
+       DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch;
+       DriverObject->MajorFunction[IRP_MJ_WRITE] = Dispatch;
+       DriverObject->DriverUnload = NULL;
+   
+       return(STATUS_SUCCESS);
+}
+
+sb_status sb16_getenvironment(void)
+{
+       if(detect_dsp(&sb16)!=SB_TRUE)
+       {
+               printk("Detect DSP failed!!!\n");
+               return SB_FALSE;
+       }
+       printk("DSP base address 0x%x\n",sb16.base);
+       get_irq(&sb16);
+       printk("IRQ: %d\n",sb16.irq);
+       get_dma(&sb16);
+       printk("DMA8: 0x%x DMA16: 0x%x\n",sb16.dma8,sb16.dma16);
+       return SB_TRUE;
+}
+
+#include "dsp.c"
+#include "mixer.c"
+#include "wave.c"
diff --git a/reactos/drivers/dd/sound/wave.h b/reactos/drivers/dd/sound/wave.h
new file mode 100644 (file)
index 0000000..7b1ca7a
--- /dev/null
@@ -0,0 +1,24 @@
+KIRQL irql;
+KAFFINITY affinity;
+
+typedef struct
+{      
+       unsigned char           rID[4]  __attribute__((packed));                                        //4     0
+       unsigned int            rLen    __attribute__((packed));                                                //4     4
+       unsigned char   wID[4] __attribute__((packed));                                         //4     8
+       unsigned char   fID[4] __attribute__((packed));                                         //4     12
+       unsigned int            fLen __attribute__((packed));                                                   //4     16
+       unsigned short          wFormatTag __attribute__((packed));                             //2     18
+       unsigned short  nChannels __attribute__((packed));                              //2     20
+       unsigned int            nSamplesPerSec __attribute__((packed));         //2 22
+       unsigned int            nAvgBytesPerSec __attribute__((packed));        //2     24
+       unsigned short  nBlockAlign __attribute__((packed));                    //2     26
+       unsigned short  FormatSpecific __attribute__((packed));         //2     28
+       unsigned char   dID[4] __attribute__((packed));                                         //4     30
+       unsigned int            dLen __attribute__((packed));
+       unsigned char*  data;
+}WAVE_HDR;
+
+void sb16_play(WAVE_HDR* wave);
+void dump_wav(WAVE_HDR* wave);
+BOOLEAN playRoutine(PKINTERRUPT Interrupt,PVOID ServiceContext);
\ No newline at end of file
diff --git a/reactos/drivers/dd/test/makefile b/reactos/drivers/dd/test/makefile
new file mode 100644 (file)
index 0000000..20523be
--- /dev/null
@@ -0,0 +1 @@
+all: test.o
diff --git a/reactos/drivers/dd/test/test.c b/reactos/drivers/dd/test/test.c
new file mode 100644 (file)
index 0000000..5eda215
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/test/test.c
+ * PURPOSE:          Testing driver
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ *              ??/??/??: Created
+ *              18/06/98: Made more NT like
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include <ddk/ntddk.h>
+
+/* FUNCTIONS **************************************************************/
+
+NTSTATUS TestWrite(PIRP Irp, PIO_STACK_LOCATION Stk)
+{
+   PVOID Address;
+   
+   Address = MmGetSystemAddressForMdl(Irp->MdlAddress);
+   printk("Asked to write '%s'\n",(PCH)Address);
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS TestDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+/*
+ * FUNCTION: Handles user mode requests
+ * ARGUMENTS:
+ *           DeviceObject = Device for request
+ *           Irp = I/O request packet describing request
+ * RETURNS: Success or failure
+ */
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   NTSTATUS status;
+   int i;
+   
+   switch (Stack->MajorFunction)
+     {
+      case IRP_MJ_CREATE:
+        printk("(Test Driver) Creating\n");
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_CLOSE:
+       status = STATUS_SUCCESS;
+       break;
+       
+      case IRP_MJ_WRITE:
+        printk("(Test Driver) Writing\n");
+       status = TestWrite(Irp,Stack);
+       break;
+       
+      default:
+        status = STATUS_NOT_IMPLEMENTED;
+       break;
+     }
+   
+   Irp->IoStatus.Status = status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(status);
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   PDEVICE_OBJECT DeviceObject;
+   NTSTATUS ret;
+   ANSI_STRING astr;
+   UNICODE_STRING ustr;
+   
+   printk("Test Driver 0.0.1\n");
+          
+   RtlInitAnsiString(&astr,"\\Device\\Test");
+   RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
+   ret = IoCreateDevice(DriverObject,0,&ustr,
+                        FILE_DEVICE_PARALLEL_PORT,0,FALSE,&DeviceObject);
+   if (ret!=STATUS_SUCCESS)
+     {
+       return(ret);
+     }
+
+   DeviceObject->Flags=DO_DIRECT_IO;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = TestDispatch;
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = TestDispatch;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = TestDispatch;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = TestDispatch;
+   DriverObject->DriverUnload = NULL;
+   
+   return(STATUS_SUCCESS);
+}
+
diff --git a/reactos/drivers/dd/test1/makefile b/reactos/drivers/dd/test1/makefile
new file mode 100644 (file)
index 0000000..20523be
--- /dev/null
@@ -0,0 +1 @@
+all: test.o
diff --git a/reactos/drivers/dd/test1/test.c b/reactos/drivers/dd/test1/test.c
new file mode 100644 (file)
index 0000000..b74037a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/test1/test.c
+ * PURPOSE:          Bug demonstration
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ *              ??/??/??: Created
+ *              18/06/98: Made more NT like
+ */
+
+/* FUNCTIONS **************************************************************/
+
+#include <windows.h>
+#include <internal/kernel.h>
+#include <internal/hal/io.h>
+#include <ddk/ntddk.h>
+#include <string.h>
+#include <internal/debug.h>
+
+#define IDE_NT_ROOTDIR_NAME "\\Device\\"
+#define IDE_NT_DEVICE_NAME "\\HardDrive"
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   char DeviceDirName[255];
+   UNICODE_STRING UnicodeDeviceDirName;
+   ANSI_STRING AnsiDeviceDirName;
+   OBJECT_ATTRIBUTES DeviceDirAttributes;
+   HANDLE Handle;
+   NTSTATUS RC;
+   ULONG HarddiskIdx = 0;
+   
+   strcpy(DeviceDirName,IDE_NT_ROOTDIR_NAME);
+   strcat(DeviceDirName,IDE_NT_DEVICE_NAME);
+   DeviceDirName[strlen(DeviceDirName)+1]='\0';
+   DeviceDirName[strlen(DeviceDirName)]= '0' + HarddiskIdx;
+   printk("DeviceDirName %s\n",DeviceDirName);
+   RtlInitAnsiString(&AnsiDeviceDirName,DeviceDirName);
+   RC = RtlAnsiStringToUnicodeString(&UnicodeDeviceDirName,
+                                    &AnsiDeviceDirName,
+                                    TRUE);
+   if (!NT_SUCCESS(RC))
+     {
+       DPRINT("Could not convert ansi to unicode for device dir\n",0);
+       return(STATUS_UNSUCCESSFUL);
+     }
+   InitializeObjectAttributes(&DeviceDirAttributes,&UnicodeDeviceDirName,
+                             0,NULL,NULL);
+   RC = ZwCreateDirectoryObject(&Handle,0,&DeviceDirAttributes);
+   if (!NT_SUCCESS(RC))
+     {
+       DPRINT("Could not create device dir\n",0);
+       return(STATUS_UNSUCCESSFUL);       
+     }
+   RtlFreeUnicodeString(&UnicodeDeviceDirName);
+}
+
diff --git a/reactos/drivers/fs/minix/block.c b/reactos/drivers/fs/minix/block.c
new file mode 100644 (file)
index 0000000..ba3670c
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/minix/minix.c
+ * PURPOSE:          Minix FSD
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+#include <wstring.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "minix.h"
+
+/* FUNCTIONS ****************************************************************/
+
+static unsigned int MinixGetBlock(PMINIX_DEVICE_EXTENSION DeviceExt,
+                                 struct minix_inode* inode, 
+                                 int blk)
+{
+   int block;
+   PCCB Ccb;
+   
+   DPRINT("MinixGetBlock(inode %x, blk %d)\n",inode,blk);
+   
+   if (blk < 7)
+     {
+       block = inode->i_zone[blk];
+       return(block);
+     }
+   blk = blk - 7;
+   
+   if (blk < 512)
+     {
+       block = inode->i_zone[7];
+       Ccb = CbAcquireForRead(&DeviceExt->Dccb,block);
+       block = ((PUSHORT)Ccb->Buffer)[blk];
+       CbReleaseFromRead(&DeviceExt->Dccb,Ccb);
+       return(block);
+     }
+   blk = blk - 512;
+   block = inode->i_zone[8];
+   
+   Ccb = CbAcquireForRead(&DeviceExt->Dccb,block);
+   block = ((PUSHORT)Ccb->Buffer)[(blk>>9)&511];
+   CbReleaseFromRead(&DeviceExt->Dccb,Ccb);
+   
+   Ccb = CbAcquireForRead(&DeviceExt->Dccb,block);
+   block = ((PUSHORT)Ccb->Buffer)[blk&512];
+   CbReleaseFromRead(&DeviceExt->Dccb,Ccb);
+   
+   return(block);
+}
+
+NTSTATUS MinixReadBlock(PMINIX_DEVICE_EXTENSION DeviceExt,
+                       struct minix_inode* inode, 
+                       int blk,
+                       PCCB* Ccb)
+{
+   unsigned int block;
+   
+   DPRINT("DeviceExt %x\n",DeviceExt);
+   DPRINT("inode %x\n",inode);
+   DPRINT("blk %d\n",blk);
+   DPRINT("Ccb %x\n",Ccb);
+   DPRINT("MinixReadBlock(DeviceExt %x, inode %x, blk %d, Ccb %x)\n",
+         DeviceExt,inode,blk,Ccb);
+   
+   block = MinixGetBlock(DeviceExt,inode,blk);
+   (*Ccb) = CbAcquireForRead(&DeviceExt->Dccb,block);
+   return(STATUS_SUCCESS);
+}
diff --git a/reactos/drivers/fs/minix/dir.c b/reactos/drivers/fs/minix/dir.c
new file mode 100644 (file)
index 0000000..2555560
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/minix/minix.c
+ * PURPOSE:          Minix FSD
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+#include <wstring.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "minix.h"
+
+/* FUNCTIONS ****************************************************************/
+
+BOOLEAN MinixCompareUnicodeStringToAnsi(PCH AnsiStr, PWCHAR UnicodeStr,
+                                       ULONG MaxLen)
+{
+   unsigned int i = 0;
+   
+   while (i<MaxLen)
+     {
+       if ((*AnsiStr)!=(*UnicodeStr))
+         {
+            return(FALSE);
+         }
+       if ((*AnsiStr)==0 && (*UnicodeStr)==0)
+         {
+            return(TRUE);
+         }
+       AnsiStr++;
+       UnicodeStr++;
+       i++;
+     }
+   return(TRUE);
+}
+
+#define ENTRIES_PER_BLOCK (BLOCKSIZE / MINIX_DIR_ENTRY_SIZE)
+
+ULONG MinixDirLookup(PMINIX_DEVICE_EXTENSION DeviceExt,
+                    struct minix_inode* dir,
+                    PWCHAR Name)
+{
+   struct minix_dir_entry* current_entry = NULL;
+   unsigned int offset;
+   unsigned int i;
+   unsigned int inode;
+   PCCB Ccb = NULL;
+   
+   DPRINT("MinixDirLookup(DeviceExt %x, dir %x, Name %w)\n",DeviceExt,dir,
+         Name);
+   
+   for (i=0;i<(dir->i_size/MINIX_DIR_ENTRY_SIZE);i++)
+     {
+       CHECKPOINT;
+       offset = i*MINIX_DIR_ENTRY_SIZE;
+       if ((offset%BLOCKSIZE)==0)
+         {
+            CHECKPOINT;
+            if (Ccb != NULL)
+              {
+                 CHECKPOINT;
+                 CbReleaseFromRead(&DeviceExt->Dccb,Ccb);
+              }
+            CHECKPOINT;
+            MinixReadBlock(DeviceExt,
+                           dir,
+                           offset/BLOCKSIZE,
+                           &Ccb);
+         }
+       current_entry = (struct minix_dir_entry *)
+         (Ccb->Buffer+offset%BLOCKSIZE);
+       DPRINT("Inode %x Name %.30s\n",current_entry->inode,
+              current_entry->name);
+        if (MinixCompareUnicodeStringToAnsi(current_entry->name,
+                                           Name,30))
+         {
+            inode = current_entry->inode;
+            CbReleaseFromRead(&DeviceExt->Dccb,Ccb);
+            DPRINT("MinixDirLookup() = %d\n",inode);
+            return(inode);
+         }
+     }
+   CHECKPOINT;
+   if (Ccb != NULL)
+     {
+       CbReleaseFromRead(&DeviceExt->Dccb,Ccb);
+     }
+   DPRINT("MinixDirLookup() = %d\n",0);
+   return(0);
+}
+
+NTSTATUS MinixOpen(PDEVICE_OBJECT DeviceObject,
+                  MINIX_DEVICE_EXTENSION* DeviceExt,
+                  PWSTR DeviceName,
+                  struct minix_inode* result,
+                  PULONG Information)
+{
+   PWSTR current;
+   PWSTR next;
+   PWSTR string = DeviceName;
+   struct minix_inode current_dir;
+   unsigned int current_ino;
+   
+   DbgPrint("MinixOpen(DeviceObject %x, DeviceName %w, result %x)\n",
+         DeviceObject,DeviceName,result);
+   DPRINT("DeviceName %x\n",DeviceName);
+   
+   next = &string[0];
+   current = next+1;
+   
+   current_ino = MINIX_ROOT_INO;
+   
+   while (next!=NULL && current_ino!=0)
+     { 
+       MinixReadInode(DeviceObject,DeviceExt,current_ino,&current_dir);
+
+       DPRINT("current %w next %x\n",current,next);
+       
+       *next = '\\';
+       current = next+1;
+       next = wcschr(next+1,'\\');
+       if (next!=NULL)
+         {
+            *next=0;
+         }
+       
+        current_ino = MinixDirLookup(DeviceExt,&current_dir,current);
+     }
+   if (next==NULL && current_ino!=0)
+     {
+       MinixReadInode(DeviceObject,DeviceExt,current_ino,&current_dir);       
+     }
+   else
+     {
+       (*Information) = FILE_DOES_NOT_EXIST;
+       return(STATUS_UNSUCCESSFUL);
+     }
+   memcpy(result,&current_dir,sizeof(struct minix_inode));
+   DPRINT("MinxOpen() = STATUS_SUCCESS\n",0);
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS MinixClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+
+   DPRINT("MinixClose(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+   
+   ExFreePool(FileObject->FsContext);
+
+   Irp->IoStatus.Status = STATUS_SUCCESS;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS MinixCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   NTSTATUS Status;
+   struct minix_inode* result;
+   MINIX_DEVICE_EXTENSION* DeviceExt;
+   
+   DPRINT("MinixCreate(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
+   DPRINT("Opening file %x %w\n",FileObject->FileName.Buffer,
+           FileObject->FileName.Buffer);
+   DPRINT("FileObject->FileName.Buffer %x\n",
+           FileObject->FileName.Buffer);
+   
+   DeviceExt = (MINIX_DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
+   result = ExAllocatePool(NonPagedPool,sizeof(struct minix_inode));
+   DPRINT("result %x\n",result);
+   Status = MinixOpen(DeviceExt->AttachedDevice,DeviceExt,
+                     FileObject->FileName.Buffer,result,
+                     &Irp->IoStatus.Information);
+   
+   if (Status==STATUS_SUCCESS)
+     {
+       FileObject->FsContext=result;
+     }
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
diff --git a/reactos/drivers/fs/minix/inode.c b/reactos/drivers/fs/minix/inode.c
new file mode 100644 (file)
index 0000000..11560e2
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/minix/minix.c
+ * PURPOSE:          Minix FSD
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+#include <internal/bitops.h>
+#include <ddk/ntifs.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "minix.h"
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS MinixDeleteInode(PDEVICE_OBJECT Volume,
+                         MINIX_DEVICE_EXTENSION* DeviceExt,
+                         ULONG ino)
+{
+   PULONG Buffer;
+   ULONG off;
+   
+   Buffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
+   MinixReadSector(Volume, (ino / 8192)+2, (PVOID)Buffer);
+   off = ino % 8192;
+   clear_bit(off%32,&Buffer[off/32]);
+   MinixWriteSector(Volume, (ino / 8192)+2, (PVOID)Buffer);
+   return(STATUS_SUCCESS);
+}
+
+static ULONG MinixAllocateInode(PDEVICE_OBJECT Volume,
+                               MINIX_DEVICE_EXTENSION* DeviceExt)
+{
+   ULONG i;
+   PULONG Buffer;
+   ULONG ino;
+   
+   Buffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
+   for (i=0; i<DeviceExt->sb->s_imap_blocks; i++)
+     {
+       MinixReadSector(Volume,i + 2,Buffer);
+       ino = find_first_zero_bit(Buffer,8192);
+       if (ino < 8192)
+         {
+            set_bit(ino%32,&Buffer[32]);
+            MinixWriteSector(Volume,i + 2,Buffer);
+            ExFreePool(Buffer);
+            return(ino + (i*8192));
+         }
+     }
+   ExFreePool(Buffer);
+   return(0);
+}
+
+ULONG MinixNewInode(PDEVICE_OBJECT Volume,
+                   MINIX_DEVICE_EXTENSION* DeviceExt,
+                   struct minix_inode* new_inode)
+{
+   ULONG ino;
+   
+   ino = MinixAllocateInode(Volume,DeviceExt);
+   if (ino == 0)
+     {
+       return(0);
+     }
+   MinixWriteInode(Volume,DeviceExt,ino,new_inode);
+   return(ino);
+}
+
+NTSTATUS MinixWriteInode(PDEVICE_OBJECT Volume,
+                        MINIX_DEVICE_EXTENSION* DeviceExt,
+                        ULONG ino, 
+                        struct minix_inode* result)
+{
+   int block;
+   char* buffer;
+   struct minix_inode* inodes;
+   
+   DPRINT("MinixWriteInode(ino %x, result %x)\n",ino,result);
+   
+   buffer = ExAllocatePool(NonPagedPool,1024);
+   inodes = (struct minix_inode *)buffer;
+   
+   block = 2 + DeviceExt->sb->s_imap_blocks + DeviceExt->sb->s_zmap_blocks 
+           + ((ino-1) / MINIX_INODES_PER_BLOCK);
+   MinixReadSector(Volume,block,buffer);
+   memcpy(&inodes[(ino-1)%MINIX_INODES_PER_BLOCK],result,
+         sizeof(struct minix_inode));
+   MinixWriteSector(Volume,block,buffer);
+   
+   ExFreePool(buffer);
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS MinixReadInode(PDEVICE_OBJECT DeviceObject,
+                       MINIX_DEVICE_EXTENSION* DeviceExt,
+                       ULONG ino, 
+                       struct minix_inode* result)
+{
+   PCCB Ccb;
+   int block;
+   struct minix_inode* inodes;
+   
+   DPRINT("MinixReadInode(ino %x, result %x)\n",ino,result);
+   
+   block = 2 + DeviceExt->sb->s_imap_blocks + DeviceExt->sb->s_zmap_blocks 
+           + ((ino-1) / MINIX_INODES_PER_BLOCK);
+   DPRINT("Reading block %x offset %x\n",block,block*BLOCKSIZE);
+   DPRINT("Index %x\n",(ino-1)%MINIX_INODES_PER_BLOCK);
+   
+   Ccb = CbAcquireForRead(&DeviceExt->Dccb,
+                         block);
+   inodes = (struct minix_inode *)Ccb->Buffer;
+     
+   memcpy(result,&inodes[(ino-1)%MINIX_INODES_PER_BLOCK],
+         sizeof(struct minix_inode));
+   DPRINT("result->i_uid %x\n",result->i_uid);
+   DPRINT("result->i_size %x\n",result->i_size);
+
+   CbReleaseFromRead(&DeviceExt->Dccb,Ccb);
+   
+   return(STATUS_SUCCESS);
+}
diff --git a/reactos/drivers/fs/minix/minix.h b/reactos/drivers/fs/minix/minix.h
new file mode 100644 (file)
index 0000000..2234cf8
--- /dev/null
@@ -0,0 +1,122 @@
+#include <ddk/ntddk.h>
+#include <ddk/ntifs.h>
+
+#define MINIX_ROOT_INO 1
+
+/* Not the same as the bogus LINK_MAX in <linux/limits.h>. Oh well. */
+#define MINIX_LINK_MAX 250
+
+#define MINIX_I_MAP_SLOTS      8
+#define MINIX_Z_MAP_SLOTS      64
+#define MINIX_SUPER_MAGIC      0x137F          /* original minix fs */
+#define MINIX_SUPER_MAGIC2     0x138F          /* minix fs, 30 char names */
+#define MINIX2_SUPER_MAGIC     0x2468          /* minix V2 fs */
+#define MINIX2_SUPER_MAGIC2    0x2478          /* minix V2 fs, 30 char names */
+#define MINIX_VALID_FS         0x0001          /* Clean fs. */
+#define MINIX_ERROR_FS         0x0002          /* fs has errors. */
+
+#define MINIX_INODES_PER_BLOCK ((BLOCKSIZE)/(sizeof (struct minix_inode)))
+#define MINIX2_INODES_PER_BLOCK ((BLOCKSIZE)/(sizeof (struct minix2_inode)))
+
+#define MINIX_V1               0x0001          /* original minix fs */
+#define MINIX_V2               0x0002          /* minix V2 fs */
+
+
+/*
+ * This is the original minix inode layout on disk.
+ * Note the 8-bit gid and atime and ctime.
+ */
+struct minix_inode {
+       unsigned short int i_mode;
+       unsigned short int i_uid;
+       unsigned long i_size;
+       unsigned long i_time;
+       unsigned char  i_gid;
+       unsigned char  i_nlinks;
+       unsigned short int i_zone[9];
+};
+
+/*
+ * The new minix inode has all the time entries, as well as
+ * long block numbers and a third indirect block (7+1+1+1
+ * instead of 7+1+1). Also, some previously 8-bit values are
+ * now 16-bit. The inode is now 64 bytes instead of 32.
+ */
+struct minix2_inode {
+       unsigned short int i_mode;
+       unsigned short int i_nlinks;
+       unsigned short int i_uid;
+       unsigned short int i_gid;
+       unsigned long i_size;
+       unsigned long i_atime;
+       unsigned long i_mtime;
+       unsigned long i_ctime;
+       unsigned long i_zone[10];
+};
+
+/*
+ * minix super-block data on disk
+ */
+struct minix_super_block {
+       unsigned short int s_ninodes;
+       unsigned short int s_nzones;
+       unsigned short int s_imap_blocks;
+       unsigned short int s_zmap_blocks;
+       unsigned short int s_firstdatazone;
+       unsigned short int s_log_zone_size;
+       unsigned long s_max_size;
+       unsigned short int s_magic;
+       unsigned short int s_state;
+       unsigned long s_zones;
+};
+
+struct minix_dir_entry {
+       unsigned short int inode;
+       char name[0];
+};
+#define MINIX_DIR_ENTRY_SIZE (sizeof(struct minix_dir_entry)+30)
+
+BOOLEAN MinixReadSector(IN PDEVICE_OBJECT pDeviceObject,
+                       IN ULONG        DiskSector,
+                       IN UCHAR*       Buffer);
+BOOLEAN MinixWriteSector(IN PDEVICE_OBJECT pDeviceObject,
+                       IN ULONG        DiskSector,
+                       IN UCHAR*       Buffer);
+
+#define BLOCKSIZE (1024)
+
+//extern PDRIVER_OBJECT DriverObject;
+
+typedef struct
+{
+   PDEVICE_OBJECT AttachedDevice;
+   struct minix_inode root_inode;
+   char superblock_buf[BLOCKSIZE];
+   struct minix_super_block* sb;
+   DCCB Dccb;
+} MINIX_DEVICE_EXTENSION, *PMINIX_DEVICE_EXTENSION;
+
+NTSTATUS MinixCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+NTSTATUS MinixClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+NTSTATUS MinixWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+NTSTATUS MinixRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
+ULONG MinixNewInode(PDEVICE_OBJECT Volume,
+                   MINIX_DEVICE_EXTENSION* DeviceExt,
+                   struct minix_inode* new_inode);
+NTSTATUS MinixWriteInode(PDEVICE_OBJECT Volume,
+                        MINIX_DEVICE_EXTENSION* DeviceExt,
+                        ULONG ino, 
+                        struct minix_inode* result);
+NTSTATUS MinixReadInode(PDEVICE_OBJECT DeviceObject,
+                       MINIX_DEVICE_EXTENSION* DeviceExt,
+                       ULONG ino, 
+                       struct minix_inode* result);
+NTSTATUS MinixDeleteInode(PDEVICE_OBJECT Volume,
+                         MINIX_DEVICE_EXTENSION* DeviceExt,
+                         ULONG ino);
+
+NTSTATUS MinixReadBlock(PMINIX_DEVICE_EXTENSION DeviceExt,
+                       struct minix_inode* inode, 
+                       int blk,
+                       PCCB* Ccb);
diff --git a/reactos/drivers/fs/minix/minix.sym b/reactos/drivers/fs/minix/minix.sym
new file mode 100644 (file)
index 0000000..3a8acf7
--- /dev/null
@@ -0,0 +1,156 @@
+         U _CbAcquireForRead
+         U _CbInitDccb
+         U _CbReleaseFromRead
+         U _DbgPrint
+         U _ExAllocatePool
+         U _ExFreePool
+         U _IoAttachDeviceToDeviceStack
+         U _IoBuildSynchronousFsdRequest
+         U _IoCallDriver
+         U _IoCompleteRequest
+         U _IoCreateDevice
+         U _IoGetCurrentIrpStackLocation
+         U _IoRegisterFileSystem
+         U _KeInitializeEvent
+         U _KeWaitForSingleObject
+         U _MmGetSystemAddressForMdl
+         U _RtlAnsiStringToUnicodeString
+         U _RtlCopyMemory
+         U _RtlInitAnsiString
+         U _wcschr
+00000000 t .text
+00000000 t LC0
+00000000 t ___gnu_compiled_c
+00000000 t gcc2_compiled.
+00000008 t LC1
+00000011 t LC2
+00000022 T _MinixCheckPoint
+0000004b t LC3
+0000006c t _MinixGetBlock
+000000b0 t L147
+0000010a t L148
+00000124 t L151
+0000012b t L150
+00000135 t LC4
+00000143 t LC5
+0000014d t LC6
+00000155 t LC7
+0000015d t LC8
+00000196 T _MinixReadBlock
+0000029c t .text
+0000029c t LC0
+0000029c t ___gnu_compiled_c
+0000029c t gcc2_compiled.
+000002a1 t LC1
+000002aa t LC2
+000002ce T _MinixWrite
+00000319 t LC3
+0000033d t LC4
+0000035c t LC5
+00000363 t LC6
+00000388 t LC7
+00000393 t LC8
+000003ba T _MinixRead
+00000492 t L151
+000004a2 t L152
+00000508 t L181
+0000059e t L191
+000005d1 t L153
+000005d6 t L199
+00000635 t L257
+000006a1 t L228
+000006bb t L256
+000006c4 t .text
+000006c4 T _MinixDeleteInode
+000006c4 t ___gnu_compiled_c
+000006c4 t gcc2_compiled.
+0000071a t _MinixAllocateInode
+00000778 t L167
+000007c2 t L166
+000007de t L165
+000007e6 t L173
+000007ee T _MinixNewInode
+0000081a t L175
+0000081c t L176
+00000824 T _MinixWriteInode
+000008a2 T _MinixReadInode
+0000090c t .text
+0000090c T _MinixCompareUnicodeStringToAnsi
+0000090c t ___gnu_compiled_c
+0000090c t gcc2_compiled.
+00000920 t L140
+00000936 t L141
+0000093f t L142
+0000094b t L139
+00000950 t L144
+00000958 t LC0
+0000095e t LC1
+00000967 t LC2
+00000996 t LC3
+0000099d t LC4
+000009b2 t LC5
+000009ca T _MinixDirLookup
+00000a26 t L153
+00000aa3 t L163
+00000ad8 t L158
+00000b68 t L152
+00000b80 t L151
+00000bb6 t L186
+00000bde t L191
+00000be6 t LC6
+00000c1c t LC7
+00000c2b t LC8
+00000c3f t LC9
+00000c5c T _MinixOpen
+00000cc0 t L206
+00000d26 t L205
+00000d3d t L198
+00000d43 t L237
+00000d5c t L207
+00000d6c t L208
+00000da7 t L236
+00000daf t LC10
+00000dd4 T _MinixClose
+00000e40 t LC11
+00000e66 t LC12
+00000e7a t LC13
+00000e9a t LC14
+00000ea6 T _MinixCreate
+00000fa7 t L260
+00000fc8 t .text
+00000fc8 T _MinixMount
+00000fc8 t ___gnu_compiled_c
+00000fc8 t gcc2_compiled.
+0000103b t LC0
+0000106c T _MinixFileSystemControl
+000010bc t L139
+000010c1 t L140
+000010e2 t LC1
+000010f3 t LC2
+00001102 T _DriverEntry
+000011b1 t L142
+000011b8 t .text
+000011b8 T _MinixReadSector
+000011b8 t ___gnu_compiled_c
+000011b8 t gcc2_compiled.
+00001232 t L140
+00001252 t L141
+00001258 t L143
+0000125a t L142
+00001262 T _MinixWriteSector
+000012c3 t L145
+000012ce t L146
+000012d0 t L147
+00002000 b .bss
+00002000 b .bss
+00002000 b .bss
+00002000 b .bss
+00002000 b .bss
+00002000 d .data
+00002000 d .data
+00002000 d .data
+00002000 d .data
+00002000 d .data
+00002000 d .data
+00002000 b _DriverObject
+00002004 b .bss
diff --git a/reactos/drivers/fs/minix/mount.c b/reactos/drivers/fs/minix/mount.c
new file mode 100644 (file)
index 0000000..64f9e5f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/minix/minix.c
+ * PURPOSE:          Minix FSD
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <ddk/ntifs.h>
+#include <internal/string.h>
+#include <wstring.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "minix.h"
+
+/* GLOBALS *******************************************************************/
+
+static PDRIVER_OBJECT DriverObject;
+
+/* FUNCTIONS ****************************************************************/
+
+VOID MinixMount(PDEVICE_OBJECT DeviceToMount)
+{
+   PDEVICE_OBJECT DeviceObject;
+   MINIX_DEVICE_EXTENSION* DeviceExt;
+   
+   IoCreateDevice(DriverObject,
+                 sizeof(MINIX_DEVICE_EXTENSION),
+                 NULL,
+                 FILE_DEVICE_FILE_SYSTEM,
+                 0,
+                 FALSE,
+                 &DeviceObject);
+   DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
+   DeviceExt = DeviceObject->DeviceExtension;
+   
+   MinixReadSector(DeviceToMount,1,DeviceExt->superblock_buf);
+   DeviceExt->sb = (struct minix_super_block *)(DeviceExt->superblock_buf);
+   
+   DeviceExt->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject,
+                                                          DeviceToMount);
+   CbInitDccb(&DeviceExt->Dccb,DeviceExt->AttachedDevice,
+             BLOCKSIZE,2880,10);
+}
+
+NTSTATUS MinixFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PVPB        vpb = Stack->Parameters.Mount.Vpb;
+   PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
+   NTSTATUS Status;
+   char* superblock_buf;
+   struct minix_super_block* sb;
+   
+   DbgPrint("MinixFileSystemControl(DeviceObject %x, Irp %x)\n",DeviceObject,
+         Irp);
+   DPRINT("DeviceToMount %x\n",DeviceToMount);
+
+   superblock_buf = ExAllocatePool(NonPagedPool,BLOCKSIZE);
+   
+   DPRINT("MinixReadSector %x\n",MinixReadSector);
+   MinixReadSector(DeviceToMount,1,superblock_buf);
+   sb = (struct minix_super_block *)superblock_buf;
+   DPRINT("Magic %x\n",sb->s_magic);
+   DPRINT("Imap blocks %x\n",sb->s_imap_blocks);
+   DPRINT("Zmap blocks %x\n",sb->s_zmap_blocks);
+   if (sb->s_magic==MINIX_SUPER_MAGIC2)
+     {
+       DPRINT("%s() = STATUS_SUCCESS\n",__FUNCTION__);
+       MinixMount(DeviceToMount);
+       Status = STATUS_SUCCESS;
+     }
+   else
+     {
+       DPRINT("%s() = STATUS_UNRECOGNIZED_VOLUME\n",__FUNCTION__);
+       Status = STATUS_UNRECOGNIZED_VOLUME;
+     }
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject, 
+                    PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   PDEVICE_OBJECT DeviceObject;
+   NTSTATUS ret;
+   UNICODE_STRING ustr;
+   ANSI_STRING astr;
+
+   DbgPrint("Minix FSD 0.0.1\n");
+          
+   DriverObject = _DriverObject;
+   
+   RtlInitAnsiString(&astr,"\\Device\\Minix");
+   RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
+   ret = IoCreateDevice(DriverObject,0,&ustr,
+                        FILE_DEVICE_PARALLEL_PORT,0,FALSE,&DeviceObject);
+   if (ret!=STATUS_SUCCESS)
+     {
+       return(ret);
+     }
+
+   DeviceObject->Flags=0;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = MinixClose;
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = MinixCreate;
+   DriverObject->MajorFunction[IRP_MJ_READ] = MinixRead;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = MinixWrite;
+   DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = 
+                      MinixFileSystemControl;
+   DriverObject->DriverUnload = NULL;
+
+   IoRegisterFileSystem(DeviceObject);
+   
+   return(STATUS_SUCCESS);
+}
+
diff --git a/reactos/drivers/fs/minix/rw.c b/reactos/drivers/fs/minix/rw.c
new file mode 100644 (file)
index 0000000..c476d06
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/minix/rw.c
+ * PURPOSE:          Minix FSD
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+#include <wstring.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "minix.h"
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS MinixWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   DPRINT("MinixWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+   
+   Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+   Irp->IoStatus.Information = 0;
+   return(STATUS_UNSUCCESSFUL);
+}
+
+NTSTATUS MinixRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   ULONG Length;
+   PVOID Buffer;
+   ULONG Offset;
+   ULONG CurrentOffset;
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   MINIX_DEVICE_EXTENSION* DeviceExt = DeviceObject->DeviceExtension;
+   struct minix_inode* inode = (struct minix_inode *)FileObject->FsContext;
+   unsigned int i;
+   PCCB Ccb = NULL;
+   
+   DPRINT("MinixRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
+   
+   Length = Stack->Parameters.Read.Length;
+   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+   Offset = Stack->Parameters.Read.ByteOffset.LowPart;
+   
+   DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset);
+   
+   CurrentOffset=Offset;
+   
+   DPRINT("inode->i_size %d\n",inode->i_size);
+   
+   if (Offset > inode->i_size)
+     {
+       Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+       Irp->IoStatus.Information = 0;
+       IoCompleteRequest(Irp,IO_NO_INCREMENT);
+       return(STATUS_UNSUCCESSFUL);
+     }
+   if ((Offset+Length) > inode->i_size)
+     {
+       Length = inode->i_size - Offset;
+     }
+   
+   if ((Offset%BLOCKSIZE)!=0)
+     {
+       CHECKPOINT;
+       
+       CurrentOffset = Offset - (Offset%BLOCKSIZE);
+       
+       MinixReadBlock(DeviceExt,inode,
+                      CurrentOffset/BLOCKSIZE,
+                      &Ccb);
+       memcpy(Buffer,Ccb->Buffer+(Offset%BLOCKSIZE),
+                 min(BLOCKSIZE - (Offset%BLOCKSIZE),Length));
+       DPRINT("(BLOCKSIZE - (Offset%BLOCKSIZE)) %d\n",
+              (BLOCKSIZE - (Offset%BLOCKSIZE)));
+       DPRINT("Length %d\n",Length);
+       CurrentOffset = CurrentOffset + BLOCKSIZE;
+       Buffer = Buffer + BLOCKSIZE - (Offset%BLOCKSIZE);
+       Length = Length - min(BLOCKSIZE - (Offset%BLOCKSIZE),Length);
+       DPRINT("CurrentOffset %d Buffer %x Length %d\n",CurrentOffset,Buffer,
+              Length);
+     }
+   for (i=0;i<(Length/BLOCKSIZE);i++)
+     {
+       CHECKPOINT;
+       
+       DPRINT("Length %d\n",Length);
+       
+       MinixReadBlock(DeviceExt,inode,
+                      CurrentOffset/BLOCKSIZE,&Ccb);
+       memcpy(Buffer,Ccb->Buffer,BLOCKSIZE);
+       CurrentOffset = CurrentOffset + BLOCKSIZE;
+       Buffer = Buffer + BLOCKSIZE;
+     }
+   if ((Length%BLOCKSIZE) > 0)
+     {
+       CHECKPOINT;
+       
+       DPRINT("Length %x Buffer %x\n",(Length%BLOCKSIZE),Buffer);
+       
+       MinixReadBlock(DeviceExt,inode,
+                      CurrentOffset/BLOCKSIZE,
+                      &Ccb);   
+       memcpy(Buffer,Ccb->Buffer,(Length%BLOCKSIZE));
+     }
+   
+   Irp->IoStatus.Status = STATUS_SUCCESS;
+   Irp->IoStatus.Information = Length;
+   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+   return(STATUS_SUCCESS);
+}
diff --git a/reactos/drivers/fs/template/makefile b/reactos/drivers/fs/template/makefile
new file mode 100644 (file)
index 0000000..64648bf
--- /dev/null
@@ -0,0 +1,2 @@
+all: template.o
+       $(LD) -r template.o -o tfsd.o
diff --git a/reactos/drivers/fs/template/template.c b/reactos/drivers/fs/template/template.c
new file mode 100644 (file)
index 0000000..9ba91ca
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/template/template.c
+ * PURPOSE:          Bare filesystem template
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+#include <wstring.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+typedef struct
+{
+   PDEVICE_OBJECT StorageDevice;
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+/* GLOBALS *****************************************************************/
+
+static PDRIVER_OBJECT DriverObject;
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
+/*
+ * FUNCTION: Closes a file
+ */
+{
+}
+
+NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, 
+                    PWSTR FileName)
+/*
+ * FUNCTION: Opens a file
+ */
+{
+}
+
+BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount)
+/*
+ * FUNCTION: Tests if the device contains a filesystem that can be mounted 
+ * by this fsd
+ */
+{
+}
+
+NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt, 
+                       PDEVICE_OBJECT DeviceToMount)
+/*
+ * FUNCTION: Mounts the device
+ */
+{
+}
+
+
+NTSTATUS FsdReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
+                    PVOID Buffer, ULONG Length, ULONG Offset)
+/*
+ * FUNCTION: Reads data from a file
+ */
+{
+}
+
+
+NTSTATUS FsdClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+   NTSTATUS Status;
+   
+   Status = FsdCloseFile(DeviceExtension,FileObject);
+
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
+NTSTATUS FsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   NTSTATUS Status;
+   PDEVICE_EXTENSION DeviceExt;
+   
+   DeviceExt = DeviceObject->DeviceExtension;
+   Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
+
+NTSTATUS FsdWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+   
+   Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+   Irp->IoStatus.Information = 0;
+   return(STATUS_UNSUCCESSFUL);
+}
+
+NTSTATUS FsdRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   ULONG Length;
+   PVOID Buffer;
+   ULONG Offset;
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
+   NTSTATUS Status;
+   
+   DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
+   
+   Length = Stack->Parameters.Read.Length;
+   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+   Offset = Stack->Parameters.Read.ByteOffset.LowPart;
+   
+   Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset);
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = Length;
+   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+   return(Status);
+}
+
+
+NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
+{
+   PDEVICE_OBJECT DeviceObject;
+   PDEVICE_EXTENSION DeviceExt;
+      
+   IoCreateDevice(DriverObject,
+                 sizeof(DEVICE_EXTENSION),
+                 NULL,
+                 FILE_DEVICE_FILE_SYSTEM,
+                 0,
+                 FALSE,
+                 &DeviceObject);
+   DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
+   DeviceExt = (PVOID)DeviceObject->DeviceExtension;
+   
+   FsdMountDevice(DeviceExt,DeviceToMount);
+   
+   DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
+                                                         DeviceToMount);
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PVPB        vpb = Stack->Parameters.Mount.Vpb;
+   PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
+   NTSTATUS Status;
+   
+   if (FsdHasFileSystem(DeviceToMount))
+     {
+       Status = FsdMount(DeviceToMount);
+     }
+   else
+     {
+       Status = STATUS_UNRECOGNIZED_VOLUME;
+     }
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject,
+                    PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   PDEVICE_OBJECT DeviceObject;
+   NTSTATUS ret;
+   UNICODE_STRING ustr;
+   ANSI_STRING astr;
+   
+   DbgPrint("Bare FSD Template 0.0.1\n");
+          
+   DriverObject = _DriverObject;
+   
+   RtlInitAnsiString(&astr,"\\Device\\BareFsd");
+   RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
+   ret = IoCreateDevice(DriverObject,0,&ustr,
+                        FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject);
+   if (ret!=STATUS_SUCCESS)
+     {
+       return(ret);
+     }
+
+   DeviceObject->Flags=0;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose;
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate;
+   DriverObject->MajorFunction[IRP_MJ_READ] = FsdRead;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite;
+   DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
+                      FsdFileSystemControl;
+   DriverObject->DriverUnload = NULL;
+   
+   IoRegisterFileSystem(DeviceObject);
+   
+   return(STATUS_SUCCESS);
+}
+
diff --git a/reactos/drivers/fs/vfat/blockdev.c b/reactos/drivers/fs/vfat/blockdev.c
new file mode 100644 (file)
index 0000000..8190ec8
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/blockdev.c
+ * PURPOSE:          Temporary sector reading support
+ * PROGRAMMER:       David Welch (welch@mcmail.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+/* FUNCTIONS ***************************************************************/
+
+BOOLEAN VFATReadSector(IN PDEVICE_OBJECT pDeviceObject,
+                       IN ULONG        DiskSector,
+                       IN UCHAR*       Buffer)
+{
+    LARGE_INTEGER   sectorNumber;
+    PIRP            irp;
+    IO_STATUS_BLOCK ioStatus;
+    KEVENT          event;
+    NTSTATUS        status;
+    ULONG           sectorSize;
+    PULONG          mbr;
+    int j;
+   
+   DPRINT("VFATReadSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
+           pDeviceObject,DiskSector,Buffer);
+
+    sectorNumber.HighPart = 0;
+    sectorNumber.LowPart = DiskSector * BLOCKSIZE;
+
+    KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+    sectorSize = BLOCKSIZE;
+
+    mbr = ExAllocatePool(NonPagedPool, sectorSize);
+
+    if (!mbr) {
+        return FALSE;
+    }
+
+
+    irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
+                                       pDeviceObject,
+                                       mbr,
+                                       sectorSize,
+                                       &sectorNumber,
+                                       &event,
+                                       &ioStatus );
+
+    if (!irp) {
+        DbgPrint("READ failed!!!\n");
+        ExFreePool(mbr);
+        return FALSE;
+    }
+
+    status = IoCallDriver(pDeviceObject,
+                          irp);
+
+    if (status == STATUS_PENDING) {
+        KeWaitForSingleObject(&event,
+                              Suspended,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+        status = ioStatus.Status;
+    }
+
+    if (!NT_SUCCESS(status)) {
+        DbgPrint("IO failed!!! Error code: %d\n", status);
+        ExFreePool(mbr);
+        return FALSE;
+    }
+
+   RtlCopyMemory(Buffer,mbr,sectorSize);
+
+    ExFreePool(mbr);
+    DPRINT("Block request succeeded\n");
+    return TRUE;
+}
diff --git a/reactos/drivers/fs/vfat/iface.c b/reactos/drivers/fs/vfat/iface.c
new file mode 100644 (file)
index 0000000..f6bc181
--- /dev/null
@@ -0,0 +1,743 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/iface.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+ * UPDATE HISTORY: 
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <internal/string.h>
+#include <wstring.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+#define FAT16 (1)
+#define FAT12 (2)
+
+typedef struct
+{
+   PDEVICE_OBJECT StorageDevice;
+   BootSector *Boot;
+   int rootDirectorySectors, FATStart, rootStart, dataStart;
+   int FATEntriesPerSector, FATUnit;
+   ULONG BytesPerCluster;
+   ULONG FatType;
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+typedef struct
+{
+   FATDirEntry entry;
+} FCB, *PFCB;
+
+#define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
+
+/* GLOBALS *****************************************************************/
+
+static PDRIVER_OBJECT DriverObject;
+
+/* FUNCTIONS ****************************************************************/
+
+ULONG Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
+{
+   ULONG FATsector;
+   ULONG FATeis;
+   PUSHORT Block;
+
+   Block = ExAllocatePool(NonPagedPool,1024);
+   
+   FATsector=CurrentCluster/(512/sizeof(USHORT));
+   FATeis=CurrentCluster-(FATsector*256);
+   
+   DPRINT("FATsector %d FATeis %d\n",FATsector,FATeis);
+   DPRINT("DeviceExt->FATStart %d\n",DeviceExt->FATStart);
+   
+   VFATReadSector(DeviceExt->StorageDevice,DeviceExt->FATStart+FATsector,
+                 Block);
+
+   DPRINT("offset %x\n",(&Block[FATeis])-Block);
+   
+   CurrentCluster = Block[FATeis];
+   
+   DPRINT("CurrentCluster %x\n",CurrentCluster);
+                                
+   if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
+     {
+       CurrentCluster = 0;
+     }  
+   
+   ExFreePool(Block);
+
+   DPRINT("Returning %x\n",CurrentCluster);
+   
+   return(CurrentCluster);
+}
+
+ULONG Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
+{
+   unsigned char* CBlock;
+   ULONG FATsector;
+   ULONG FATOffset;
+   ULONG Entry;
+
+   CBlock = ExAllocatePool(NonPagedPool,1024);
+   
+   FATsector = (CurrentCluster * 12) / (512 * 8);
+       
+   VFATReadSector(DeviceExt->StorageDevice,DeviceExt->FATStart
+                 +FATsector,CBlock);
+   
+   FATOffset = (CurrentCluster * 12) % (512 * 8);
+   
+//   DPRINT("FATSector %d FATOffset %d\n",FATsector,FATOffset);
+   
+   if ((CurrentCluster % 2) == 0)
+     {
+       Entry = CBlock[((FATOffset / 24)*3)];
+       Entry |= (CBlock[((FATOffset / 24)*3) + 1] & 0xf);
+     }
+   else
+     {
+       Entry = (CBlock[((FATOffset / 24)*3) + 1] >> 4);
+       Entry |= (CBlock[((FATOffset / 24)*3) + 2] << 4);
+     }
+       
+//   DPRINT("Entry %x\n",Entry);
+   
+   if (Entry >= 0xff8 && Entry <= 0xfff)
+     {
+       Entry = 0;
+     }
+   
+   CurrentCluster = Entry;
+   
+   ExFreePool(CBlock);
+
+   DPRINT("Returning %x\n",CurrentCluster);
+   
+   return(CurrentCluster);
+}
+
+ULONG GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
+{
+   
+   DPRINT("GetNextCluster(DeviceExt %x, CurrentCluster %d)\n",
+           DeviceExt,CurrentCluster);
+   if (DeviceExt->FatType == FAT16)
+     {
+       return(Fat16GetNextCluster(DeviceExt, CurrentCluster));
+     }
+   else
+     { 
+       return(Fat12GetNextCluster(DeviceExt, CurrentCluster));
+     }
+}
+
+unsigned long ClusterToSector(PDEVICE_EXTENSION DeviceExt, 
+                             unsigned long Cluster)
+{
+  return DeviceExt->dataStart+((Cluster-2)*DeviceExt->Boot->SectorsPerCluster);
+}
+
+void RtlAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length)
+{
+   int i;
+   
+   for (i=0; (i<Length && Source[i] != ' '); i++)
+     {
+       Dest[i] = Source[i];
+     }
+   Dest[i]=0;
+}
+
+void RtlCatAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length)
+{
+   ULONG i;
+   
+   while((*Dest)!=0)
+     {
+       Dest++;
+     }
+   for (i=0; (i<Length && Source[i] != ' '); i++)
+     {
+       Dest[i] = Source[i];
+     }
+   Dest[i]=0;
+}
+
+wchar_t * wcsncat(wchar_t * dest,const wchar_t * src,size_t count)
+{
+   int i,j;
+   
+   for (j=0;dest[j]!=0;j++);
+   for (i=0;i<count;i++)
+     {
+       dest[j+i] = src[i];
+       if (src[i] == ' ' || src[i] == 0)
+         {
+            return(dest);
+         }
+     }
+   dest[j+i]=0;
+   return(dest);
+}
+
+wchar_t * _wcsncpy(wchar_t * dest,const wchar_t *src,size_t count)
+{
+   int i;
+   
+   for (i=0;i<count;i++)
+     {
+       dest[i] = src[i];
+       if (src[i] == ' ' || src[i] == 0)
+         {
+            return(dest);
+         }
+     }
+   dest[i]=0;
+   return(dest);
+}
+
+
+BOOLEAN IsLastEntry(PVOID Block, ULONG Offset)
+{
+   return(((FATDirEntry *)Block)[Offset].Filename[0] == 0);
+}
+
+BOOLEAN IsDeletedEntry(PVOID Block, ULONG Offset)
+{
+   return(((FATDirEntry *)Block)[Offset].Filename[0] == 0xe5);
+}
+
+BOOLEAN GetEntryName(PVOID Block, PULONG _Offset, PWSTR Name)
+{
+   FATDirEntry* test;
+   slot* test2;
+   ULONG Offset = *_Offset;
+   
+   test = (FATDirEntry *)Block;
+   test2 = (slot *)Block;
+   
+   *Name = 0;
+
+   if (IsDeletedEntry(Block,Offset))
+     {
+       return(FALSE);
+     }
+   
+   DPRINT("Offset %d test2[Offset].attr %x\n",Offset,test2[Offset].attr);
+   if(test2[Offset].attr == 0x0f) 
+     {
+       DPRINT("Parsing long name record\n");
+       wcsncpy(Name,test2[Offset].name0_4,5);
+       DPRINT("Name %w\n",Name);
+       wcsncat(Name,test2[Offset].name5_10,6);
+       DPRINT("Name %w\n",Name);
+       wcsncat(Name,test2[Offset].name11_12,2);
+       DPRINT("Name %w\n",Name);
+       
+       while((test2[Offset].id!=0x41) && (test2[Offset].id!=0x01) &&
+             (test2[Offset].attr>0)) 
+         {
+            Offset++;
+            
+            DPRINT("Reading next long name record\n");
+            
+            wcsncat(Name,test2[Offset].name0_4,5);
+            wcsncat(Name,test2[Offset].name5_10,6);
+            wcsncat(Name,test2[Offset].name11_12,2);        
+         }
+       
+       if (IsDeletedEntry(Block,Offset+1))
+         {
+            Offset++;
+            *_Offset = Offset;
+            return(FALSE);
+         }
+       
+       *_Offset = Offset;
+       
+       return(TRUE);
+     }   
+      
+   RtlAnsiToUnicode(Name,test[Offset].Filename,8);
+   if (test[Offset].Ext[0]!=' ')
+     {
+       RtlCatAnsiToUnicode(Name,".",1);
+     }
+   RtlCatAnsiToUnicode(Name,test[Offset].Ext,3);
+      
+   *_Offset = Offset;
+   
+   return(TRUE);
+}
+
+BOOLEAN wstrcmpi(PWSTR s1, PWSTR s2)
+{
+   DPRINT("s1 '%w' s2 '%w'\n",s1,s2);
+   while (wtolower(*s1)==wtolower(*s2))
+     {
+       if ((*s1)==0 && (*s2)==0)
+         {
+            return(TRUE);
+         }
+       
+       s1++;
+       s2++;   
+     }
+   return(FALSE);
+}
+
+NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PFCB Fcb,
+                 PFCB Parent, PWSTR FileToFind)
+{
+   ULONG i, j, k;
+   ULONG Size;
+   char* block;
+   WCHAR name[255];
+   ULONG StartingSector;
+   ULONG NextCluster;
+   
+   DPRINT("FileFile(Parent %x, FileToFind %w)\n",Parent,FileToFind);
+   
+   if (Parent == NULL)
+     {
+       Size = DeviceExt->rootDirectorySectors;
+       StartingSector = DeviceExt->rootStart;
+     }
+   else
+     {
+       DPRINT("Parent->entry.FileSize %x\n",Parent->entry.FileSize);
+       
+       Size = ULONG_MAX;
+       StartingSector = ClusterToSector(DeviceExt, Parent->entry.FirstCluster);
+       NextCluster = Parent->entry.FirstCluster;
+     }
+   
+   block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
+   
+   for (j=0; j<Size; j++)
+     {
+       VFATReadSector(DeviceExt->StorageDevice,StartingSector,block);
+
+       
+       DPRINT("%u\n", StartingSector+j);
+
+       for (i=0; i<ENTRIES_PER_SECTOR; i++)
+         {
+            if (IsLastEntry((PVOID)block,i))
+              {
+                 ExFreePool(block);
+                 return(STATUS_SUCCESS);
+              }
+            if (GetEntryName((PVOID)block,&i,name))
+              {
+                 DPRINT("Scanning %w\n",name);
+                 
+                 DPRINT("Comparing %w %w\n",name,FileToFind);
+                 if (wstrcmpi(name,FileToFind))
+                   {
+                      DPRINT("Found match\n");
+                      memcpy(&Fcb->entry,&((FATDirEntry *)block)[i],
+                             sizeof(FATDirEntry));
+                      return(STATUS_SUCCESS);
+                   }
+              }
+            
+         }
+       if (Parent == NULL)
+         {
+            StartingSector++;
+         }
+       else
+         {
+            NextCluster = GetNextCluster(DeviceExt,NextCluster);
+            if (NextCluster == 0)
+              {
+                 return(STATUS_UNSUCCESSFUL);
+              }
+            StartingSector = ClusterToSector(DeviceExt,NextCluster);
+         }                  
+     }
+   ExFreePool(block);
+   return(STATUS_UNSUCCESSFUL);
+}
+
+
+NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
+/*
+ * FUNCTION: Closes a file
+ */
+{
+   /* NOP */
+}
+
+NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, 
+                    PWSTR FileName)
+/*
+ * FUNCTION: Opens a file
+ */
+{
+   PWSTR current;
+   PWSTR next;
+   PWSTR string = FileName;
+   PFCB ParentFcb = NULL;
+   PFCB Fcb = ExAllocatePool(NonPagedPool,sizeof(FCB));
+   PFCB Temp;
+   NTSTATUS Status;
+   
+   next = &string[0];
+   current = next+1;
+   
+   while (next!=NULL)
+     { 
+       DPRINT("current %w next %x\n",current,next);
+       
+       *next = '\\';
+       current = next+1;
+       next = wcschr(next+1,'\\');
+       if (next!=NULL)
+         {
+            *next=0;
+         }
+       
+        Status = FindFile(DeviceExt,Fcb,ParentFcb,current);
+       if (Status != STATUS_SUCCESS)
+         {          
+            return(Status);
+         }
+       Temp = Fcb;
+       if (ParentFcb == NULL)
+         {
+            Fcb = ExAllocatePool(NonPagedPool,sizeof(FCB));
+            ParentFcb = Temp;
+         }
+       else
+         {
+            Fcb = ParentFcb;
+            ParentFcb = Temp;
+         }
+     }
+   FileObject->FsContext = ParentFcb;
+   DPRINT("ParentFcb->entry.FileSize %d\n",ParentFcb->entry.FileSize);
+   return(STATUS_SUCCESS);
+}
+
+BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount)
+/*
+ * FUNCTION: Tests if the device contains a filesystem that can be mounted 
+ * by this fsd
+ */
+{
+   BootSector* Boot;
+   
+   Boot = ExAllocatePool(NonPagedPool,512);
+   VFATReadSector(DeviceToMount, 0, (UCHAR *)Boot);
+   
+   if (strncmp(Boot->SysType,"FAT12",5)==0 ||
+       strncmp(Boot->SysType,"FAT16",5)==0)
+     {
+       ExFreePool(Boot);
+       return(TRUE);
+     }
+   ExFreePool(Boot);
+   return(FALSE);
+}
+
+NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt, 
+                       PDEVICE_OBJECT DeviceToMount)
+/*
+ * FUNCTION: Mounts the device
+ */
+{
+   DPRINT("<VFAT> Mounting device...");
+   DPRINT("DeviceExt %x\n",DeviceExt);
+   
+   DeviceExt->Boot = ExAllocatePool(NonPagedPool,512);
+   
+   VFATReadSector(DeviceToMount, 0, (UCHAR *)DeviceExt->Boot);
+   
+   DPRINT("DeviceExt->Boot->BytesPerSector %x\n",
+         DeviceExt->Boot->BytesPerSector);
+   
+   DeviceExt->FATStart=DeviceExt->Boot->ReservedSectors;
+   DeviceExt->rootDirectorySectors=
+     (DeviceExt->Boot->RootEntries*32)/DeviceExt->Boot->BytesPerSector;
+   DeviceExt->rootStart=
+     DeviceExt->FATStart+DeviceExt->Boot->FATCount*DeviceExt->Boot->FATSectors;
+   DeviceExt->dataStart=DeviceExt->rootStart+DeviceExt->rootDirectorySectors;
+   DeviceExt->FATEntriesPerSector=DeviceExt->Boot->BytesPerSector/32;
+   DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
+                                DeviceExt->Boot->BytesPerSector;
+   
+   if (strncmp(DeviceExt->Boot->SysType,"FAT12",5)==0)
+     {
+       DeviceExt->FatType = FAT12;
+     }
+   else
+     {
+       DeviceExt->FatType = FAT16;
+     }
+}
+
+void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
+{
+   ULONG Sector;
+   ULONG i;
+   
+//   DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
+//       DeviceExt,Buffer,Cluster);
+   
+   Sector = ClusterToSector(DeviceExt, Cluster);
+   
+   for (i=0; i<DeviceExt->Boot->SectorsPerCluster; i++)
+     {
+       VFATReadSector(DeviceExt->StorageDevice,
+                      Sector+i,
+                      Buffer+(i*DeviceExt->Boot->BytesPerSector));
+     }
+}
+
+NTSTATUS FsdReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
+                    PVOID Buffer, ULONG Length, ULONG ReadOffset)
+/*
+ * FUNCTION: Reads data from a file
+ */
+{
+   ULONG CurrentCluster;
+   ULONG FileOffset;
+   ULONG i;
+   ULONG FirstCluster;
+   PFCB Fcb;
+   PVOID Temp;
+   ULONG TempLength;
+   
+   DPRINT("FsdReadFile(DeviceExt %x, FileObject %x, Buffer %x, "
+           "Length %d, ReadOffset %d)\n",DeviceExt,FileObject,Buffer,
+           Length,ReadOffset);
+   
+   FirstCluster = ReadOffset / DeviceExt->BytesPerCluster;
+   Fcb = FileObject->FsContext;
+   CurrentCluster = Fcb->entry.FirstCluster;
+   
+   DPRINT("DeviceExt->BytesPerCluster %x\n",DeviceExt->BytesPerCluster);
+   DPRINT("FirstCluster %d\n",FirstCluster);
+   DPRINT("CurrentCluster %d\n",CurrentCluster);
+   
+   Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster);
+   
+   for (FileOffset=0; FileOffset < FirstCluster; FileOffset++)
+     {
+       CurrentCluster = GetNextCluster(DeviceExt,CurrentCluster);
+        if (CurrentCluster == 0)
+        {
+                ExFreePool(Temp);
+                return(STATUS_UNSUCCESSFUL);
+        }
+     }
+   CHECKPOINT;
+   if ((ReadOffset % DeviceExt->BytesPerCluster)!=0)
+     {
+       VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
+       CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
+       
+       TempLength = min(Length,DeviceExt->BytesPerCluster -
+                        (ReadOffset % DeviceExt->BytesPerCluster));
+       
+       memcpy(Buffer, Temp + ReadOffset % DeviceExt->BytesPerCluster,
+              TempLength);
+       
+       Length = Length - TempLength;
+       Buffer = Buffer + TempLength;        
+     }
+   CHECKPOINT;
+   while (Length > DeviceExt->BytesPerCluster)
+     {
+       VFATLoadCluster(DeviceExt, Buffer, CurrentCluster);
+       CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
+       
+       if (CurrentCluster == 0)
+         {
+            return(STATUS_SUCCESS);
+         }
+       
+       Buffer = Buffer + DeviceExt->BytesPerCluster;
+       Length = Length - DeviceExt->BytesPerCluster;
+     }
+   CHECKPOINT;
+   if (Length > 0)
+     {
+       VFATLoadCluster(DeviceExt, Temp, CurrentCluster);
+       memcpy(Buffer, Temp, Length);
+     }
+   ExFreePool(Temp);
+   return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS FsdClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+   NTSTATUS Status;
+   
+   Status = FsdCloseFile(DeviceExtension,FileObject);
+
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
+NTSTATUS FsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   NTSTATUS Status;
+   PDEVICE_EXTENSION DeviceExt;
+
+   DPRINT("<VFAT> FsdCreate...\n");
+
+   DeviceExt = DeviceObject->DeviceExtension;
+   Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+   
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
+
+NTSTATUS FsdWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+   
+   Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+   Irp->IoStatus.Information = 0;
+   return(STATUS_UNSUCCESSFUL);
+}
+
+NTSTATUS FsdRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   ULONG Length;
+   PVOID Buffer;
+   ULONG Offset;
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PFILE_OBJECT FileObject = Stack->FileObject;
+   PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
+   NTSTATUS Status;
+   
+   DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
+   
+   Length = Stack->Parameters.Read.Length;
+   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+   Offset = Stack->Parameters.Read.ByteOffset.LowPart;
+   
+   Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset);
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = Length;
+   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+   return(Status);
+}
+
+
+NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
+{
+   PDEVICE_OBJECT DeviceObject;
+   PDEVICE_EXTENSION DeviceExt;
+      
+   IoCreateDevice(DriverObject,
+                 sizeof(DEVICE_EXTENSION),
+                 NULL,
+                 FILE_DEVICE_FILE_SYSTEM,
+                 0,
+                 FALSE,
+                 &DeviceObject);
+   DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
+   DeviceExt = (PVOID)DeviceObject->DeviceExtension;
+   
+   FsdMountDevice(DeviceExt,DeviceToMount);
+   
+   DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
+                                                         DeviceToMount);
+   return(STATUS_SUCCESS);
+}
+
+NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+   PVPB        vpb = Stack->Parameters.Mount.Vpb;
+   PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
+   NTSTATUS Status;
+   
+   DPRINT("<VFAT> FSC\n");
+
+   if (FsdHasFileSystem(DeviceToMount))
+     {
+       Status = FsdMount(DeviceToMount);
+     }
+   else
+     {
+        DPRINT("<VFAT> Unrecognized Volume\n");
+       Status = STATUS_UNRECOGNIZED_VOLUME;
+     }
+   
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = 0;
+
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   return(Status);
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject,
+                    PUNICODE_STRING RegistryPath)
+/*
+ * FUNCTION: Called by the system to initalize the driver
+ * ARGUMENTS:
+ *           DriverObject = object describing this driver
+ *           RegistryPath = path to our configuration entries
+ * RETURNS: Success or failure
+ */
+{
+   PDEVICE_OBJECT DeviceObject;
+   NTSTATUS ret;
+   UNICODE_STRING ustr;
+   ANSI_STRING astr;
+   
+   DbgPrint("VFAT 0.0.1\n");
+          
+   DriverObject = _DriverObject;
+   
+   RtlInitAnsiString(&astr,"\\Device\\VFAT");
+   RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
+   ret = IoCreateDevice(DriverObject,0,&ustr,
+                        FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject);
+   if (ret!=STATUS_SUCCESS)
+     {
+       return(ret);
+     }
+
+   DeviceObject->Flags=0;
+   DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose;
+   DriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate;
+   DriverObject->MajorFunction[IRP_MJ_READ] = FsdRead;
+   DriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite;
+   DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
+                      FsdFileSystemControl;
+   DriverObject->DriverUnload = NULL;
+   
+   IoRegisterFileSystem(DeviceObject);
+
+   return(STATUS_SUCCESS);
+}
+
diff --git a/reactos/drivers/fs/vfat/makefile b/reactos/drivers/fs/vfat/makefile
new file mode 100644 (file)
index 0000000..3735eb1
--- /dev/null
@@ -0,0 +1,9 @@
+%.o: %.cc
+       $(CC) $(CFLAGS) -c $< -o $@
+%.o: %.asm
+       $(NASM) $(NFLAGS) $< -o $@
+
+all: blockdev.o iface.o
+       $(LD) iface.o blockdev.o -r -o vfatfsd.o 
+
+include ../../../rules.mak
diff --git a/reactos/drivers/fs/vfat/vfat.h b/reactos/drivers/fs/vfat/vfat.h
new file mode 100644 (file)
index 0000000..2d92e61
--- /dev/null
@@ -0,0 +1,47 @@
+BOOLEAN VFATReadSector(IN PDEVICE_OBJECT pDeviceObject,
+                       IN ULONG        DiskSector,
+                       IN UCHAR*       Buffer);
+
+struct _BootSector { 
+  unsigned char  magic0, res0, magic1;
+  unsigned char  OEMName[8];
+  unsigned short BytesPerSector;
+  unsigned char  SectorsPerCluster;
+  unsigned short ReservedSectors;
+  unsigned char  FATCount;
+  unsigned short RootEntries, Sectors;
+  unsigned char  Media;
+  unsigned short FATSectors, SectorsPerTrack, Heads;
+  unsigned long  HiddenSectors, SectorsHuge;
+  unsigned char  Drive, Res1, Sig;
+  unsigned long  VolumeID;
+  unsigned char  VolumeLabel[11], SysType[8];
+  unsigned char  Res2[450];
+} __attribute__((packed));
+
+typedef struct _BootSector BootSector;
+
+struct _FATDirEntry {
+  unsigned char  Filename[8], Ext[3], Attrib, Res[14];
+  unsigned short FirstCluster;
+  unsigned long  FileSize;
+} __attribute__((packed));
+
+typedef struct _FATDirEntry FATDirEntry;
+
+struct _slot
+{
+  unsigned char id;               // sequence number for slot
+  WCHAR  name0_4[5];      // first 5 characters in name
+  unsigned char attr;             // attribute byte
+  unsigned char reserved;         // always 0
+  unsigned char alias_checksum;   // checksum for 8.3 alias
+  WCHAR  name5_10[6];     // 6 more characters in name
+  unsigned char start[2];         // starting cluster number
+  WCHAR  name11_12[2];     // last 2 characters in name
+} __attribute__((packed));
+
+
+typedef struct _slot slot;
+
+#define BLOCKSIZE 512
diff --git a/reactos/iface/native/genntdll b/reactos/iface/native/genntdll
new file mode 100644 (file)
index 0000000..c7ba01e
Binary files /dev/null and b/reactos/iface/native/genntdll differ
diff --git a/reactos/iface/native/genntdll.c b/reactos/iface/native/genntdll.c
new file mode 100644 (file)
index 0000000..e00823f
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * COPYRIGHT:             See COPYING in the top level directory
+ * PROJECT:               ReactOS version of ntdll
+ * FILE:                  lib/ntdll/genntdll.c
+ * PURPOSE:               Generates the system call stubs in ntdll
+ */
+
+/* INCLUDE ******************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define TRUE  1
+#define FALSE 0
+
+/* FUNCTIONS ****************************************************************/
+
+int process(FILE* in, FILE* out, FILE *out2)
+{
+   char line[255];
+   char* s;
+   char* name;
+   char* name2;
+   int value;
+   char* nr_args;
+
+   unsigned char first1 = TRUE;
+   
+   fprintf(out,"; Machine generated, don't edit\n");
+   fprintf(out,"\n\n");
+   fprintf(out,"SECTION .text\n\n");
+   
+   fprintf(out2,"// Machine generated, don't edit\n");
+   fprintf(out2,"\n\n");
+   //fprintf(out2,"#include <ntddk.h>");
+   fprintf(out2,"\n\n\n");
+   fprintf(out2,"SERVICE_TABLE _SystemServiceTable[256] = {\n");
+
+   value = 0;
+   while (!feof(in) && fgets(line,255,in) != NULL)
+     {
+//     fgets(line,255,in);
+       if ((s=(char *)strchr(line,'\n'))!=NULL)
+         {
+            *s=0;
+         }
+       s=&line[0];
+       if ((*s)!='#')
+         {
+            name = (char *)strtok(s," \t");
+            name2 = (char *)strtok(NULL," \t");
+//          value = strtok(NULL," \t");
+            nr_args = (char *)strtok(NULL," \t");
+            
+//          printf("name %s value %d\n",name,value);
+            fprintf(out,"GLOBAL _%s\n",name);
+            fprintf(out,"GLOBAL _%s\n",name2);
+            fprintf(out,"_%s:\n",name);
+            fprintf(out,"_%s:\n",name2);
+            fprintf(out,"\tmov\teax,%d\n",value);
+            fprintf(out,"\tlea\tedx,[esp+4]\n");
+            fprintf(out,"\tint\t2Eh\n");
+            fprintf(out,"\tret\t%s\n\n",nr_args);
+                
+
+            value++;
+            
+            if ( first1 == TRUE ) 
+                       first1 = FALSE;
+            else
+                       fprintf(out2,",\n");
+
+            fprintf(out2,"\t\t{ %s, (ULONG)%s }",nr_args,name);
+                
+         }
+     }
+
+     fprintf(out2,"\n};\n");
+        
+   return(0);
+}
+
+void usage(void)
+{
+   printf("Usage: genntdll sysfuncs.lst outfile.asm outfile.h\n");
+}
+
+int main(int argc, char* argv[])
+{
+   FILE* in;
+   FILE* out;
+   FILE *out2;
+   int ret;
+   
+   if (argc!=4)
+     {
+       usage();
+       return(1);
+     }
+   
+   in = fopen(argv[1],"rb");
+   if (in==NULL)
+     {
+       perror("Failed to open input file");
+       return(1);
+     }
+   
+   out = fopen(argv[2],"wb");
+   if (out==NULL)
+     {
+       perror("Failed to open output file");
+       return(1);
+     }
+   out2 = fopen(argv[3],"wb");
+   if (out2==NULL)
+     {
+       perror("Failed to open output file");
+       return(1);
+     }
+   
+   ret = process(in,out,out2);
+   
+   fclose(in);
+   fclose(out);
+   fclose(out2);
+   
+   return(ret);
+}
diff --git a/reactos/iface/native/makefile b/reactos/iface/native/makefile
new file mode 100644 (file)
index 0000000..0088750
--- /dev/null
@@ -0,0 +1,19 @@
+all: genntdll$(EXE_POSTFIX) ../../lib/ntdll/napi.asm
+
+../../lib/ntdll/napi.asm: sysfuncs.lst genntdll$(EXE_POSTFIX) ../../include/ntdll/napi.h
+       genntdll$(EXE_POSTFIX) sysfuncs.lst ../../lib/ntdll/napi.asm ../../include/ntdll/napi.h
+
+../../include/ntdll/napi.h: dummy
+
+genntdll$(EXE_POSTFIX): genntdll.c
+       $(NATIVE_CC) -g genntdll.c -o genntdll$(EXE_POSTFIX)    
+
+sysfuncs.lst: dummy
+
+clean: dummy
+       $(RM) ../../lib/ntdll/sysfuncs.lst
+       $(RM) ../../include/ntdll/napi.h
+       
+dummy:
+
+include ../../rules.mak
diff --git a/reactos/iface/native/sysfuncs.lst b/reactos/iface/native/sysfuncs.lst
new file mode 100644 (file)
index 0000000..2b90351
--- /dev/null
@@ -0,0 +1,210 @@
+NtAcceptConnectPort            ZwAcceptConnectPort               24         
+NtAccessCheck                  ZwAccessCheck                     32         
+NtAccessCheckAndAuditAlarm     ZwAccessCheckAndAuditAlarm        44         
+NtAddAtom                      ZwAddAtom                         8          
+NtAdjustGroupsToken            ZwAdjustGroupsToken               24         
+NtAdjustPrivilegesToken                ZwAdjustPrivilegesToken           24         
+NtAlertResumeThread            ZwAlertResumeThread               8          
+NtAlertThread                  ZwAlertThread                     4          
+NtAllocateLocallyUniqueId      ZwAllocateLocallyUniqueId         4          
+NtAllocateUuids                        ZwAllocateUuids                   12         
+NtAllocateVirtualMemory                ZwAllocateVirtualMemory           24         
+NtCallbackReturn               ZwCallbackReturn                  12         
+NtCancelIoFile                 ZwCancelIoFile                    8          
+NtCancelTimer                  ZwCancelTimer                     8          
+NtClearEvent                   ZwClearEvent                      4          
+NtClose                                ZwClose                           4          
+NtCloseObjectAuditAlarm                ZwCloseObjectAuditAlarm           12         
+NtCompleteConnectPort          ZwCompleteConnectPort             4          
+NtConnectPort                  ZwConnectPort                     32         
+NtContinue                     ZwContinue                        8          
+NtCreateDirectoryObject                ZwCreateDirectoryObject           12         
+NtCreateEvent                  ZwCreateEvent                     20         
+NtCreateEventPair              ZwCreateEventPair                 12         
+NtCreateFile                   ZwCreateFile                      44         
+NtCreateIoCompletion           ZwCreateIoCompletion              16         
+NtCreateKey                    ZwCreateKey                       28         
+NtCreateMailslotFile           ZwCreateMailslotFile              32         
+NtCreateMutant                 ZwCreateMutant                    16         
+NtCreateNamedPipeFile          ZwCreateNamedPipeFile             56         
+NtCreatePagingFile             ZwCreatePagingFile                16         
+NtCreatePort                   ZwCreatePort                      20         
+NtCreateProcess                        ZwCreateProcess                   32         
+NtCreateProfile                        ZwCreateProfile                   36         
+NtCreateSection                        ZwCreateSection                   28         
+NtCreateSemaphore              ZwCreateSemaphore                 20         
+NtCreateSymbolicLinkObject     ZwCreateSymbolicLinkObject        16         
+NtCreateThread                 ZwCreateThread                    32         
+NtCreateTimer                  ZwCreateTimer                     16         
+NtCreateToken                  ZwCreateToken                     52         
+NtDelayExecution               ZwDelayExecution                  8          
+NtDeleteAtom                   ZwDeleteAtom                      4          
+NtDeleteFile                   ZwDeleteFile                      4          
+NtDeleteKey                    ZwDeleteKey                       4          
+NtDeleteObjectAuditAlarm       ZwDeleteObjectAuditAlarm          12         
+NtDeleteValueKey               ZwDeleteValueKey                  8          
+NtDeviceIoControlFile          ZwDeviceIoControlFile             40         
+NtDisplayString                        ZwDisplayString                   4          
+NtDuplicateObject              ZwDuplicateObject                 28         
+NtDuplicateToken               ZwDuplicateToken                  24         
+NtEnumerateKey                 ZwEnumerateKey                    24         
+NtEnumerateValueKey            ZwEnumerateValueKey               24         
+NtExtendSection                        ZwExtendSection                   8          
+NtFindAtom                     ZwFindAtom                        8          
+NtFlushBuffersFile             ZwFlushBuffersFile                8          
+NtFlushInstructionCache                ZwFlushInstructionCache           12         
+NtFlushKey                     ZwFlushKey                        4          
+NtFlushVirtualMemory           ZwFlushVirtualMemory              16         
+NtFlushWriteBuffer             ZwFlushWriteBuffer                0          
+NtFreeVirtualMemory            ZwFreeVirtualMemory               16         
+NtFsControlFile                        ZwFsControlFile                   40         
+NtGetContextThread             ZwGetContextThread                8          
+NtGetPlugPlayEvent             ZwGetPlugPlayEvent                16         
+NtGetTickCount                 ZwGetTickCount                    0          
+NtImpersonateClientOfPort      ZwImpersonateClientOfPort         8          
+NtImpersonateThread            ZwImpersonateThread               12         
+NtInitializeRegistry           ZwInitializeRegistry              4          
+NtListenPort                   ZwListenPort                      8          
+NtLoadDriver                   ZwLoadDriver                      4          
+NtLoadKey                      ZwLoadKey                         8          
+NtLoadKey2                     ZwLoadKey2                        12         
+NtLockFile                     ZwLockFile                        40          
+NtLockVirtualMemory            ZwLockVirtualMemory               16          
+NtMakeTemporaryObject          ZwMakeTemporaryObject             4           
+NtMapViewOfSection             ZwMapViewOfSection                40          
+NtNotifyChangeDirectoryFile    ZwNotifyChangeDirectoryFile       36          
+NtNotifyChangeKey              ZwNotifyChangeKey                 40          
+NtOpenDirectoryObject          ZwOpenDirectoryObject             12          
+NtOpenEvent                    ZwOpenEvent                       12          
+NtOpenEventPair                        ZwOpenEventPair                   12          
+NtOpenFile                     ZwOpenFile                        24          
+NtOpenIoCompletion             ZwOpenIoCompletion                12          
+NtOpenKey                      ZwOpenKey                         12          
+NtOpenMutant                   ZwOpenMutant                      12          
+NtOpenObjectAuditAlarm         ZwOpenObjectAuditAlarm            48          
+NtOpenProcess                  ZwOpenProcess                     16          
+NtOpenProcessToken             ZwOpenProcessToken                12          
+NtOpenSection                  ZwOpenSection                     12          
+NtOpenSemaphore                        ZwOpenSemaphore                   12          
+NtOpenSymbolicLinkObject       ZwOpenSymbolicLinkObject          12          
+NtOpenThread                   ZwOpenThread                      16          
+NtOpenThreadToken              ZwOpenThreadToken                 16          
+NtOpenTimer                    ZwOpenTimer                       12          
+NtPlugPlayControl              ZwPlugPlayControl                 16          
+NtPrivilegeCheck               ZwPrivilegeCheck                  12          
+NtPrivilegedServiceAuditAlarm  ZwPrivilegedServiceAuditAlarm     20          
+NtPrivilegeObjectAuditAlarm    ZwPrivilegeObjectAuditAlarm       24          
+NtProtectVirtualMemory         ZwProtectVirtualMemory            20          
+NtPulseEvent                   ZwPulseEvent                      8           
+NtQueryInformationAtom         ZwQueryInformationAtom            20          
+NtQueryAttributesFile          ZwQueryAttributesFile             8           
+NtQueryDefaultLocale           ZwQueryDefaultLocale              8           
+NtQueryDirectoryFile           ZwQueryDirectoryFile              44          
+NtQueryDirectoryObject         ZwQueryDirectoryObject            28          
+NtQueryEaFile                  ZwQueryEaFile                     36          
+NtQueryEvent                   ZwQueryEvent                      20          
+NtQueryFullAttributesFile      ZwQueryFullAttributesFile         8           
+NtQueryInformationFile         ZwQueryInformationFile            20          
+NtQueryIoCompletion            ZwQueryIoCompletion               20          
+NtQueryInformationPort         ZwQueryInformationPort            20          
+NtQueryInformationProcess      ZwQueryInformationProcess         20          
+NtQueryInformationThread       ZwQueryInformationThread          20          
+NtQueryInformationToken                ZwQueryInformationToken           20          
+NtQueryIntervalProfile         ZwQueryIntervalProfile            8           
+NtQueryKey                     ZwQueryKey                        20          
+NtQueryMultipleValueKey                ZwQueryMultipleValueKey           24          
+NtQueryMutant                  ZwQueryMutant                     20          
+NtQueryObject                  ZwQueryObject                     20          
+NtQueryOleDirectoryFile                ZwQueryOleDirectoryFile           44          
+NtQueryPerformanceCounter      ZwQueryPerformanceCounter         8           
+NtQuerySection                 ZwQuerySection                    20          
+NtQuerySecurityObject          ZwQuerySecurityObject             20          
+NtQuerySemaphore               ZwQuerySemaphore                  20          
+NtQuerySymbolicLinkObject      ZwQuerySymbolicLinkObject         12          
+NtQuerySystemEnvironmentValue  ZwQuerySystemEnvironmentValue     16          
+NtQuerySystemInformation       ZwQuerySystemInformation          16          
+NtQuerySystemTime              ZwQuerySystemTime                 4           
+NtQueryTimer                   ZwQueryTimer                      20          
+NtQueryTimerResolution         ZwQueryTimerResolution            12          
+NtQueryValueKey                        ZwQueryValueKey                   24          
+NtQueryVirtualMemory           ZwQueryVirtualMemory              24          
+NtQueryVolumeInformationFile   ZwQueryVolumeInformationFile      20          
+NtQueueApcThread               ZwQueueApcThread                  20          
+NtRaiseException               ZwRaiseException                  12          
+NtRaiseHardError               ZwRaiseHardError                  24          
+NtReadFile                     ZwReadFile                        36          
+NtReadFileScatter              ZwReadFileScatter                 36          
+NtReadRequestData              ZwReadRequestData                 24          
+NtReadVirtualMemory            ZwReadVirtualMemory               20          
+NtRegisterThreadTerminatePort  ZwRegisterThreadTerminatePort     4           
+NtReleaseMutant                        ZwReleaseMutant                   8           
+NtReleaseSemaphore             ZwReleaseSemaphore                12          
+NtRemoveIoCompletion           ZwRemoveIoCompletion              20          
+NtReplaceKey                   ZwReplaceKey                      12          
+NtReplyPort                    ZwReplyPort                       8           
+NtReplyWaitReceivePort         ZwReplyWaitReceivePort            16          
+NtReplyWaitReplyPort           ZwReplyWaitReplyPort              8           
+NtRequestPort                  ZwRequestPort                     8           
+NtRequestWaitReplyPort         ZwRequestWaitReplyPort            12          
+NtResetEvent                   ZwResetEvent                      8           
+NtRestoreKey                   ZwRestoreKey                      12          
+NtResumeThread                 ZwResumeThread                    8           
+NtSaveKey                      ZwSaveKey                         8           
+NtSetIoCompletion              ZwSetIoCompletion                 20          
+NtSetContextThread             ZwSetContextThread                8           
+NtSetDefaultHardErrorPort      ZwSetDefaultHardErrorPort         4           
+NtSetDefaultLocale             ZwSetDefaultLocale                8           
+NtSetEaFile                    ZwSetEaFile                       16          
+NtSetEvent                     ZwSetEvent                        8           
+NtSetHighEventPair             ZwSetHighEventPair                4           
+NtSetHighWaitLowEventPair      ZwSetHighWaitLowEventPair         4           
+NtSetInformationFile           ZwSetInformationFile              20          
+NtSetInformationKey            ZwSetInformationKey               16          
+NtSetInformationObject         ZwSetInformationObject            16          
+NtSetInformationProcess                ZwSetInformationProcess           16          
+NtSetInformationThread         ZwSetInformationThread            16          
+NtSetInformationToken          ZwSetInformationToken             16          
+NtSetIntervalProfile           ZwSetIntervalProfile              8           
+NtSetLdtEntries                        ZwSetLdtEntries                   24          
+NtSetLowEventPair              ZwSetLowEventPair                 4           
+NtSetLowWaitHighEventPair      ZwSetLowWaitHighEventPair         4           
+NtSetSecurityObject            ZwSetSecurityObject               12          
+NtSetSystemEnvironmentValue    ZwSetSystemEnvironmentValue       8           
+NtSetSystemInformation         ZwSetSystemInformation            12          
+NtSetSystemPowerState          ZwSetSystemPowerState             12          
+NtSetSystemTime                        ZwSetSystemTime                   8           
+NtSetTimer                     ZwSetTimer                        28          
+NtSetTimerResolution           ZwSetTimerResolution              12          
+NtSetValueKey                  ZwSetValueKey                     24          
+NtSetVolumeInformationFile     ZwSetVolumeInformationFile        20          
+NtShutdownSystem               ZwShutdownSystem                  4           
+NtSignalAndWaitForSingleObject ZwSignalAndWaitForSingleObject    16          
+NtStartProfile                 ZwStartProfile                    4           
+NtStopProfile                  ZwStopProfile                     4           
+NtSuspendThread                        ZwSuspendThread                   8           
+NtSystemDebugControl           ZwSystemDebugControl              24          
+NtTerminateProcess             ZwTerminateProcess                8           
+NtTerminateThread              ZwTerminateThread                 8           
+NtTestAlert                    ZwTestAlert                       0           
+NtUnloadDriver                 ZwUnloadDriver                    4           
+NtUnloadKey                    ZwUnloadKey                       4           
+NtUnlockFile                   ZwUnlockFile                      20          
+NtUnlockVirtualMemory          ZwUnlockVirtualMemory             16          
+NtUnmapViewOfSection           ZwUnmapViewOfSection              8           
+NtVdmControl                   ZwVdmControl                      8           
+NtWaitForMultipleObjects       ZwWaitForMultipleObjects          20          
+NtWaitForSingleObject          ZwWaitForSingleObject             12          
+NtWaitHighEventPair            ZwWaitHighEventPair               4           
+NtWaitLowEventPair             ZwWaitLowEventPair                4           
+NtWriteFile                    ZwWriteFile                       36          
+NtWriteFileGather              ZwWriteFileGather                 36          
+NtWriteRequestData             ZwWriteRequestData                24          
+NtWriteVirtualMemory       &