mirror of
https://github.com/reactos/reactos
synced 2025-10-07 08:52:45 +02:00
Compare commits
9 Commits
backups/mi
...
ReactOS-0.
Author | SHA1 | Date | |
---|---|---|---|
|
efb17a2783 | ||
|
5c1b8a026c | ||
|
02b00d9c04 | ||
|
935b7c2953 | ||
|
1b7327da76 | ||
|
f77c44657c | ||
|
df0328b7cc | ||
|
94c8483b04 | ||
|
fc7e59ce74 |
@@ -1,6 +0,0 @@
|
||||
8/12/98: Corrected bug in shell (Read two keypresses and assumed they
|
||||
where the key going up and down respectively)
|
||||
Corrected race in dpc handling
|
||||
Took out cleanup sections in ZwReadFile (now handled by the APC)
|
||||
Disabled broken code in kernel32
|
||||
|
14
reactos/NEWS
14
reactos/NEWS
@@ -1,14 +0,0 @@
|
||||
0.0.14 (so far):
|
||||
|
||||
0.0.13: Mostly bugfixes (I think)
|
||||
|
||||
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)
|
@@ -1,33 +0,0 @@
|
||||
#include <windows.h>
|
||||
|
||||
extern int main(int args, char* argv[], char* environ[]);
|
||||
|
||||
static unsigned int _argc = 0;
|
||||
static char** _argv = NULL;
|
||||
static char** _environ = NULL;
|
||||
|
||||
int mainCRTStartup(PWSTR args)
|
||||
{
|
||||
int nRet;
|
||||
|
||||
// SetUnhandledExceptionFilter(NULL);
|
||||
|
||||
// _fpreset();
|
||||
|
||||
// __GetMainArgs(&_argc, &_argv, &_environ, 0);
|
||||
|
||||
nRet = main(_argc, _argv, _environ);
|
||||
|
||||
// _cexit();
|
||||
|
||||
ExitProcess(nRet);
|
||||
}
|
||||
|
||||
int WinMainCRTStartup()
|
||||
{
|
||||
return mainCRTStartup(NULL);
|
||||
}
|
||||
|
||||
void __main(void)
|
||||
{
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
#include <internal/mmhal.h>
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
HANDLE OutputHandle;
|
||||
HANDLE InputHandle;
|
||||
|
||||
void debug_printf(char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[255];
|
||||
|
||||
va_start(args,fmt);
|
||||
vsprintf(buffer,fmt,args);
|
||||
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
void main(int argc, char* argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
AllocConsole();
|
||||
InputHandle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
for (i=0; i<argc; i++)
|
||||
{
|
||||
debug_printf("Args: '%s'\n",argv[i]);
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +0,0 @@
|
||||
all: args.exe
|
||||
|
||||
OBJECTS= ../common/crt0.o args.o
|
||||
LIBS= ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a
|
||||
|
||||
args.exe: $(OBJECTS) $(LIBS)
|
||||
$(CC) -specs=../../specs $(OBJECTS) $(LIBS) -lgcc -o args.exe
|
||||
$(NM) --numeric-sort args.exe > args.sym
|
||||
|
||||
include ../../rules.mak
|
@@ -1,7 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
printf("Hello world\n");
|
||||
return(0);
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
all: hello.exe
|
||||
|
||||
OBJECTS = hello.o
|
||||
|
||||
hello.exe: $(OBJECTS) $(LIBS)
|
||||
$(CC) $(OBJECTS) -o hello.exe
|
||||
|
||||
include ../../rules.mak
|
@@ -1,158 +0,0 @@
|
||||
#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;
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
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
|
@@ -1,10 +0,0 @@
|
||||
all: shell.exe
|
||||
|
||||
OBJECTS= ../common/crt0.o shell.o
|
||||
LIBS= ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a
|
||||
|
||||
shell.exe: $(OBJECTS) $(LIBS)
|
||||
$(CC) -specs=../../specs $(OBJECTS) $(LIBS) -lgcc -o shell.exe
|
||||
$(NM) --numeric-sort shell.exe > shell.sym
|
||||
|
||||
include ../../rules.mak
|
@@ -1,221 +0,0 @@
|
||||
#include <internal/mmhal.h>
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
HANDLE InputHandle, OutputHandle;
|
||||
|
||||
void debug_printf(char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char buffer[255];
|
||||
|
||||
va_start(args,fmt);
|
||||
vsprintf(buffer,fmt,args);
|
||||
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ExecuteCd(char* cmdline)
|
||||
{
|
||||
if (!SetCurrentDirectoryA(cmdline))
|
||||
{
|
||||
debug_printf("Invalid directory\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ExecuteDir(char* cmdline)
|
||||
{
|
||||
HANDLE shandle;
|
||||
WIN32_FIND_DATA FindData;
|
||||
int nFile=0,nRep=0;
|
||||
TIME_FIELDS fTime;
|
||||
|
||||
shandle = FindFirstFile("*",&FindData);
|
||||
|
||||
if (shandle==INVALID_HANDLE_VALUE)
|
||||
{
|
||||
debug_printf("Invalid directory\n");
|
||||
return;
|
||||
}
|
||||
do
|
||||
{
|
||||
debug_printf("%-15.15s",FindData.cAlternateFileName);
|
||||
if(FindData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
|
||||
debug_printf("<REP> "),nRep++;
|
||||
else
|
||||
debug_printf(" %10d ",FindData.nFileSizeLow),nFile++;
|
||||
// RtlTimeToTimeFields(&FindData.ftLastWriteTime ,&fTime);
|
||||
// debug_printf("%02d/%02d/%04d %02d:%02d:%02d "
|
||||
// ,fTime.Month,fTime.Day,fTime.Year
|
||||
// ,fTime.Hour,fTime.Minute,fTime.Second);
|
||||
debug_printf("%s\n",FindData.cFileName);
|
||||
} while(FindNextFile(shandle,&FindData));
|
||||
debug_printf("\n %d files\n %d directories\n\n",nFile,nRep);
|
||||
FindClose(shandle);
|
||||
}
|
||||
|
||||
void ExecuteType(char* cmdline)
|
||||
{
|
||||
HANDLE FileHandle;
|
||||
char c;
|
||||
DWORD Result;
|
||||
|
||||
FileHandle = CreateFile(cmdline,
|
||||
FILE_GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL);
|
||||
if (FileHandle == NULL)
|
||||
{
|
||||
debug_printf("Unknown file\n");
|
||||
return;
|
||||
}
|
||||
while (ReadFile(FileHandle,
|
||||
&c,
|
||||
1,
|
||||
&Result,
|
||||
NULL))
|
||||
{
|
||||
debug_printf("%c",c);
|
||||
c = 0;
|
||||
}
|
||||
CloseHandle(FileHandle);
|
||||
}
|
||||
|
||||
int ExecuteProcess(char* name, char* cmdline)
|
||||
{
|
||||
PROCESS_INFORMATION ProcessInformation;
|
||||
STARTUPINFO StartupInfo;
|
||||
char arguments;
|
||||
BOOL ret;
|
||||
|
||||
memset(&StartupInfo,0,sizeof(StartupInfo));
|
||||
StartupInfo.cb = sizeof(STARTUPINFO);
|
||||
StartupInfo.lpTitle = name;
|
||||
|
||||
ret = CreateProcessA(name,
|
||||
cmdline,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
CREATE_NEW_CONSOLE,
|
||||
NULL,
|
||||
NULL,
|
||||
&StartupInfo,
|
||||
&ProcessInformation);
|
||||
if (ret)
|
||||
{
|
||||
WaitForSingleObject(ProcessInformation.hProcess,INFINITE);
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void ExecuteCommand(char* line)
|
||||
{
|
||||
char* cmd;
|
||||
char* tail;
|
||||
|
||||
if (isalpha(line[0]) && line[1] == ':' && line[2] == 0)
|
||||
{
|
||||
line[2] = '\\';
|
||||
line[3] = 0;
|
||||
SetCurrentDirectoryA(line);
|
||||
return;
|
||||
}
|
||||
|
||||
tail = line;
|
||||
while ((*tail)!=' ' && (*tail)!=0)
|
||||
{
|
||||
tail++;
|
||||
}
|
||||
if ((*tail)==' ')
|
||||
{
|
||||
*tail = 0;
|
||||
tail++;
|
||||
}
|
||||
cmd = line;
|
||||
|
||||
|
||||
if (cmd==NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd,"cd")==0)
|
||||
{
|
||||
ExecuteCd(tail);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd,"dir")==0)
|
||||
{
|
||||
ExecuteDir(tail);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd,"type")==0)
|
||||
{
|
||||
ExecuteType(tail);
|
||||
return;
|
||||
}
|
||||
if (strcmp(cmd,"exit")==0)
|
||||
{
|
||||
ExitProcess(0);
|
||||
return;
|
||||
}
|
||||
if (ExecuteProcess(cmd,tail))
|
||||
{
|
||||
return;
|
||||
}
|
||||
debug_printf("Unknown command\n");
|
||||
}
|
||||
|
||||
void ReadLine(char* line)
|
||||
{
|
||||
KEY_EVENT_RECORD KeyEvent;
|
||||
DWORD Result;
|
||||
UCHAR CurrentDir[255];
|
||||
char ch;
|
||||
|
||||
GetCurrentDirectoryA(255,CurrentDir);
|
||||
debug_printf(CurrentDir);
|
||||
|
||||
do
|
||||
{
|
||||
if (!ReadConsoleA(InputHandle,
|
||||
&ch,
|
||||
1,
|
||||
&Result,
|
||||
NULL))
|
||||
{
|
||||
debug_printf("Failed to read from console\n");
|
||||
for(;;);
|
||||
}
|
||||
debug_printf("%c", ch);
|
||||
*line = ch;
|
||||
line++;
|
||||
} while (ch != '\n');
|
||||
line--;
|
||||
*line = 0;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
static char line[255];
|
||||
|
||||
AllocConsole();
|
||||
InputHandle = GetStdHandle(STD_INPUT_HANDLE);
|
||||
OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
debug_printf("Shell Starting...\n");
|
||||
|
||||
SetCurrentDirectoryA("C:\\");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
ReadLine(line);
|
||||
ExecuteCommand(line);
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1 @@
|
||||
loadros kimage.bin ide.o vfatfsd.o keyboard.o
|
||||
loaders\dos\loadros ntoskrnl\kimage.bin %1 %2 %3 %4
|
||||
|
@@ -1,40 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
:
|
||||
: copy files to HD...
|
||||
:
|
||||
COPY /Y BLUE.SYS C:\reactos\system\drivers\blue.SYS
|
||||
COPY /Y KEYBOARD.SYS C:\reactos\system\drivers\KEYBOARD.SYS
|
||||
COPY /Y NTDLL.DLL C:\reactos\system\NTDLL.DLL
|
||||
: COPY /Y CRTDLL.DLL C:\reactos\system\CRTDLL.DLL
|
||||
COPY /Y SHELL.EXE C:\reactos\system\SHELL.EXE
|
||||
|
||||
:
|
||||
: present a menu to the booter...
|
||||
:
|
||||
ECHO 1) Keyboard,IDE,VFatFSD
|
||||
ECHO 2) IDE,VFatFSD
|
||||
ECHO 3) No Drivers
|
||||
CHOICE /C:123 /T:2,3 "Select kernel boot config"
|
||||
IF ERRORLEVEL 3 GOTO :L3
|
||||
IF ERRORLEVEL 2 GOTO :L2
|
||||
|
||||
:L1
|
||||
CLS
|
||||
LOADROS NTOSKRNL.EXE KEYBOARD.O IDE.SYS VFATFSD.SYS
|
||||
GOTO :END
|
||||
|
||||
:L2
|
||||
CLS
|
||||
LOADROS NTOSKRNL.EXE IDE.SYS VFATFSD.SYS
|
||||
GOTO :END
|
||||
|
||||
:L3
|
||||
CLS
|
||||
LOADROS NTOSKRNL.EXE
|
||||
GOTO :END
|
||||
|
||||
:END
|
||||
EXIT
|
||||
|
||||
|
@@ -1,94 +0,0 @@
|
||||
This is the file "copying.dj". It does NOT apply to any sources or
|
||||
|
||||
binaries copyrighted by UCB Berkeley, the Free Software Foundation, or
|
||||
|
||||
any other agency besides DJ Delorie and others who have agreed to
|
||||
|
||||
allow their sources to be distributed under these terms.
|
||||
|
||||
|
||||
|
||||
Copyright Information for sources and executables that are marked
|
||||
|
||||
Copyright (C) DJ Delorie
|
||||
|
||||
7 Kim Lane
|
||||
|
||||
Rochester NH 03867-2954
|
||||
|
||||
|
||||
|
||||
This document is Copyright (C) DJ Delorie and may be distributed
|
||||
|
||||
verbatim, but changing it is not allowed.
|
||||
|
||||
|
||||
|
||||
Source code copyright DJ Delorie is distributed under the terms of the
|
||||
|
||||
GNU General Public Licence, with the following exceptions:
|
||||
|
||||
|
||||
|
||||
* Sources used to build crt0.o, gcrt0.o, libc.a, libdbg.a, and
|
||||
|
||||
libemu.a are distributed under the terms of the GNU Library General
|
||||
|
||||
Public License, rather than the GNU GPL.
|
||||
|
||||
|
||||
|
||||
* Any existing copyright or authorship information in any given source
|
||||
|
||||
file must remain intact. If you modify a source file, a notice to that
|
||||
|
||||
effect must be added to the authorship information in the source file.
|
||||
|
||||
|
||||
|
||||
* Runtime binaries, as provided by DJ in DJGPP, may be distributed
|
||||
|
||||
without sources ONLY if the recipient is given sufficient information
|
||||
|
||||
to obtain a copy of djgpp themselves. This primarily applies to
|
||||
|
||||
go32-v2.exe, emu387.dxe, and stubedit.exe.
|
||||
|
||||
|
||||
|
||||
* Runtime objects and libraries, as provided by DJ in DJGPP, when
|
||||
|
||||
linked into an application, may be distributed without sources ONLY
|
||||
|
||||
if the recipient is given sufficient information to obtain a copy of
|
||||
|
||||
djgpp themselves. This primarily applies to crt0.o and libc.a.
|
||||
|
||||
|
||||
|
||||
-----
|
||||
|
||||
|
||||
|
||||
Changes to source code copyright BSD or FSF by DJ Delorie fall under
|
||||
|
||||
the terms of the original copyright.
|
||||
|
||||
|
||||
|
||||
A copy of the files "COPYING" and "COPYING.LIB" are included with this
|
||||
|
||||
document. If you did not receive a copy of these files, you may
|
||||
|
||||
obtain one from whence this document was obtained, or by writing:
|
||||
|
||||
|
||||
|
||||
Free Software Foundation
|
||||
|
||||
675 Mass Ave
|
||||
|
||||
Cambridge, MA 02139
|
||||
|
||||
USA
|
||||
|
340
reactos/copying_rex
Normal file
340
reactos/copying_rex
Normal file
@@ -0,0 +1,340 @@
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@@ -1,22 +0,0 @@
|
||||
DIRECTORIES
|
||||
|
||||
system : compiled versions of the various system components and
|
||||
libraries
|
||||
ntoskrnl : kernel source
|
||||
ntoskrnl/hal : hardware abstraction layer source
|
||||
ntoskrnl/mm : memory managment subsystem source
|
||||
ntoskrnl/io : IO manager subsystem source
|
||||
ntoskrnl/ke : kernel 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/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)
|
||||
services/dd : device drivers
|
||||
services/fs : file systems
|
@@ -1,130 +0,0 @@
|
||||
* Introduction
|
||||
|
||||
Having successfully built ReactOS and been amazed by what it does, you're
|
||||
now desperate to fill in some of the omissions, this document shows you how.
|
||||
|
||||
* Prerequisites
|
||||
|
||||
A working knowledge of NT driver development is useful for understanding the
|
||||
kernel and some of its abstractions. The NT4 ddk is available for free
|
||||
download from http://www.microsoft.com/hwdev/. The Windows 98 and Windows
|
||||
2000 DDKs are also available but the NT4 one is the most useful. See
|
||||
Legal Stuff below however.
|
||||
|
||||
There are a number of books on NT driver development, I would recommend
|
||||
'Windows NT Device Driver Development' (http://www.osr.com/book/) since OSR
|
||||
seem to know their stuff. There is only one book on NT filesystem
|
||||
development 'Windows NT File System Internals'. Please don't buy any of
|
||||
these books unless you need to, and can afford it.
|
||||
|
||||
These mailing lists and newsgroups are useful for NT internals related
|
||||
questions,
|
||||
ntfsd@atria.com, ntdev@atria.com
|
||||
(subscribe by email to majordomo@atria.com)
|
||||
comp.os.????
|
||||
microsoft.public.????
|
||||
|
||||
* Style
|
||||
|
||||
There is no coding style used for ReactOS, however the following guidelines
|
||||
make things easier
|
||||
|
||||
Include information at the top of a module about its purpose, contact
|
||||
information for its programmer and any useful notes.
|
||||
|
||||
Include a comment by each non-trival function describing its arguments,
|
||||
purpose and any other notes.
|
||||
|
||||
Update the documentation in this directory
|
||||
|
||||
These guidelines are an ideal, no one manages to implement them all the
|
||||
time, straightforward working code is probably just as good.
|
||||
|
||||
* Debugging
|
||||
|
||||
Debugging kernel-mode code is tricky, these are some snippets
|
||||
|
||||
DbgPrint writes a message to the console using a printf style format
|
||||
string. The DPRINT macro (defined in internal/debug.h) expands to
|
||||
DbgPrint unless NDEBUG is defined, this is useful for having copious
|
||||
output from a module only when a problem is being debugging. DPRINT
|
||||
also prefixes the message with the file and line number to make it
|
||||
easier to see where output is coming from. DbgPrint can be used at any
|
||||
point including in interrupt handlers.
|
||||
|
||||
There are options in ntoskrnl/hal/x86/printk.c for copying DbgPrint
|
||||
output to a serial device (parallel support should also be added). This
|
||||
can be useful if a lot of output is being generated.
|
||||
|
||||
It should be possible to include support for debugging the kernel with
|
||||
gdb over a serial line. Bochs (a shareware CPU emulator) is also useful
|
||||
for debugging the kernel, I wrote some patches to allow capture of console
|
||||
output from within bochs to file and for debugging a kernel running
|
||||
under bochs with gdb. Contact me (welch@cwcom.net) if you're are
|
||||
interested.
|
||||
|
||||
If CPU reports an exception not handled by the kernel (any page fault
|
||||
not part of virtual memory support or any other exception) the kernel
|
||||
will display output like this and halt
|
||||
|
||||
General Protection Fault Exception: 13(0)
|
||||
CS:EIP xxxxxxxx:xxxxxxx
|
||||
DS xxxx ES xxxx FS xxxx GS xxxxx
|
||||
EAX: xxxx EBX: xxxx
|
||||
....
|
||||
EDI: xxxx EFLAGS: xxxx ESP: xxxx
|
||||
cr2: xxxx
|
||||
Stack: xxxx xxxx xxxx ...
|
||||
....
|
||||
Frames: xxxx xxxx xxxx ...
|
||||
....
|
||||
|
||||
The fault type will usually be either 'General Protection' or
|
||||
'Page Fault', see your Intel manual for the more exotic types. The
|
||||
'EIP' number is the address of the faulting instruction. If the 'CS'
|
||||
number is 0x20 then the exception occured in kernel mode, if it is 0x11
|
||||
then the exception occurred in user mode. 'cr2' is the address that the
|
||||
faulting instruction was trying to access, if the exception was a page
|
||||
fault. The number printed after 'Frames' are any addresses on the stack
|
||||
that look like function addresses.
|
||||
|
||||
|
||||
If the kernel detects a serious problem that it will bug check, displaying
|
||||
output like this
|
||||
|
||||
Bug detected (code x, param x x x x)
|
||||
Frames: xxx xxxx xxxx
|
||||
....
|
||||
|
||||
Again the numbers printed after 'Frames' are any addresses on the stack
|
||||
that look like function addresss. Usually the kernel will also print a
|
||||
message describing the problem in more detail, the bug check code isn't
|
||||
very useful at the moment.
|
||||
|
||||
* Contacts
|
||||
|
||||
There is a mailing list for kernel development,
|
||||
|
||||
ros-kernel@sid-dis.com
|
||||
|
||||
The main developers use a cvs account to coordinate changes, ask
|
||||
rex (rex@lvcablemodem.com) for an account if you are going to be adding
|
||||
a lot of code. Smaller patches can go to the mailing list or to the
|
||||
relevant developer (usually the comment at the top of a module will have
|
||||
an email address). Regular snapshots are made available for download,
|
||||
see the mailing list for announcements.
|
||||
|
||||
* Legal stuff
|
||||
|
||||
The ReactOS project is GPL'ed, please make sure any code submitted is
|
||||
compatible with this.
|
||||
|
||||
The NT4 ddk license agreement allows its usage for developing nt drivers
|
||||
only. Legally therefore it can not be used to develop ReactOS, neither the
|
||||
documentation or the sample code. I'm not a lawyer, but I doubt the
|
||||
effiacy of 'shrinkwrap licenses' particularly on freely downloadable
|
||||
software. The only precendent I know of, in a Scottish court, didn't
|
||||
upload this type of license.
|
||||
|
||||
Also the 'fair use' section of copyright law allows the 'quoting' of small
|
||||
sections from copyrighted documents, e.g. Windows API or DDK documentation
|
@@ -1,6 +0,0 @@
|
||||
HACKING: Some notes for adding code to ReactOS
|
||||
DIRS: Explanation of directory layout
|
||||
INTERNALS: Some notes on kernel internals
|
||||
TODO: Bugs and omissions, big and little things that need to be done
|
||||
NOTES: Unsorted material, some of it is redundant
|
||||
BUGLIST: Known bugs, please update when you find one
|
@@ -1,43 +0,0 @@
|
||||
A collection of articles on kernel internals, please add to this
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
IRQ level
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
IRQ level (IRQL) is a per-processor state in ReactOS used to coordinate
|
||||
execution between ISRs and between threads. There are several levels
|
||||
|
||||
PASSIVE_LEVEL, APC_LEVEL: The normal level for user mode and most
|
||||
kernel mode code. At the moment APC_LEVEL is unused.
|
||||
|
||||
DISPATCH_LEVEL: At this level all irqs are still allowed but thread
|
||||
rescheduling on the current processor is disabled. This is used by
|
||||
the spinlock synchronization primitive to implement its uniprocessor
|
||||
semantics (multiprocessor is more complex). It is also used for some
|
||||
other forms of synchronization, DPCs for example. Many APIs are
|
||||
unavailable at this IRQL, usually those that might have to wait. It
|
||||
is recommended that you don't spend too much time at this IRQL
|
||||
otherwise system responsiveness will be reduced.
|
||||
|
||||
> DISPATCH_LEVEL: Each irq is assigned a priority (which will be
|
||||
greater than DISPATCH_LEVEL). At an irq's priority level that irq,
|
||||
lower priority irqs and thread rescheduling are disabled. Higher
|
||||
priority irqs can still run. Very few APIs are available at IRQLs
|
||||
greater than DISPATCH_LEVEL.
|
||||
|
||||
HIGH_LEVEL: All irqs are disabled.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
DPCs
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
It is a design goal not to spend too much time in ISRs, for this reason
|
||||
ISRs should postpone most processing till it can run at a lower IRQL. The
|
||||
mechanism for this is a Delayed Procedure Call (DPC). When a DPC object is
|
||||
created, it is associated with a function. The DPC object can then be inserted
|
||||
in the DPC queue from an ISR. If the IRQL on return from the ISR is less than
|
||||
DISPATCH_LEVEL the DPC queue will be drained, otherwise this will happen when
|
||||
the IRQL level drops below DISPATCH_LEVEL or the processor becomes idle. When
|
||||
the DPC queue is drained each DPC object is removed and the associated
|
||||
function is called at DISPATCH_LEVEL. A DPC object can only be inserted once,
|
||||
further insertions before it is removed will have no effect.
|
140
reactos/doc/api.txt
Normal file
140
reactos/doc/api.txt
Normal file
@@ -0,0 +1,140 @@
|
||||
This file attempts to document the functions made publically available by
|
||||
the various subsystems.
|
||||
|
||||
* Formatted I/O operations *
|
||||
|
||||
NAME: int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
NAME: int sprintf(char* buf, const char* fmt, ...)
|
||||
WHERE: internal/kernel.h
|
||||
FUNCTION: The same as the standard c library versions
|
||||
|
||||
* PIO operations *
|
||||
|
||||
NAME: in[b/w/l](port)
|
||||
WHERE: internal/io.h
|
||||
FUNCTION: Read an IO port of the specified size (byte/word or long)
|
||||
RETURNS: The value read
|
||||
|
||||
NAME: out[b/w/l](port,val)
|
||||
WHERE: internal/io.h
|
||||
FUNCTION: Write an IO port of the specified size (byte/word or long)
|
||||
|
||||
NAME: in_p[b/w/l](port)
|
||||
WHERE: internal/io.h
|
||||
FUNCTION: Read an IO port of the specified size (byte/word or long) with
|
||||
a pause
|
||||
RETURNS: The value read
|
||||
|
||||
NAME: out_p[b/w/l](port,val)
|
||||
WHERE: internal/io.h
|
||||
FUNCTION: Write an IO port of the specified size (byte/word or long) with
|
||||
a pause
|
||||
|
||||
* Bit operations *
|
||||
|
||||
NAME: int set_bit(int nr, void* addr)
|
||||
NAME: int clear_bit(int nr, void* addr)
|
||||
NAME: int change_bit(int nr, void* addr)
|
||||
WHERE: internal/bitops.h>
|
||||
FUNCTION: Operate on a bit in the word pointed to by addr
|
||||
RETURN: 0 if the bit was cleared before the operations
|
||||
non-zero otherwise
|
||||
|
||||
* Debugging functions *
|
||||
|
||||
NAME: DPRINT(fmt,....)
|
||||
WHERE: internal/debug.h
|
||||
FUNCTION: Outputs a string to the console if NDEBUG isn't defined before
|
||||
including internal/debug.h, a NOP otherwise
|
||||
ARGUMENTS: The same as printf
|
||||
|
||||
NAME: printk
|
||||
WHERE: internal/kernel.h
|
||||
FUNCTION: Outputs a string to the console
|
||||
ARGUMENTS: The same as printf
|
||||
|
||||
* Memory managment functions *
|
||||
|
||||
NAME: unsigned int physical_to_linear(unsigned int paddr)
|
||||
WHERE: hal/page.h
|
||||
FUNCTION: Converts a physical address to a linear one
|
||||
RECEIVES:
|
||||
paddr = the physical address to convert
|
||||
RETURNS: A virtual address where the memory at that physical address can be
|
||||
accessed
|
||||
|
||||
NAME: void* ExAllocatePool(unsigned int size, unsigned int type = 0);
|
||||
WHERE: internal/pool.h
|
||||
FUNCTION: Allocates a block of memory
|
||||
RECEIVES:
|
||||
size = the size of the block to allocate
|
||||
type = will be whether to allocate pagable memory
|
||||
RETURNS: The address of the block
|
||||
NOTE: This isn't interrupt safe
|
||||
|
||||
NAME: void ExFreePool(void* block)
|
||||
WHERE: internal/pool.h
|
||||
FUNCTION: Frees a block of memory
|
||||
|
||||
NAME: void free_page(unsigned int physical_base, unsigned int nr = 1)
|
||||
WHERE: internal/mm.h
|
||||
FUNCTION: Adds a continuous range of physical memory to the free list
|
||||
|
||||
NAME: unsigned int get_free_page(void)
|
||||
WHERE: internal/mm.h
|
||||
FUNCTION: Gets a free page
|
||||
RETURNS: Its physical address
|
||||
|
||||
NAME: unsigned int get_page_physical_address(unsigned int vaddr)
|
||||
WHERE: internal/mm.h
|
||||
FUNCTION: Gets the physical address of a page
|
||||
|
||||
NAME: void mark_page_not_writable(unsigned int vaddr)
|
||||
WHERE: internal/mm.h
|
||||
FUNCTION: Prevent writing the page
|
||||
|
||||
* DMA functions *
|
||||
|
||||
NAME: unsigned int get_dma_page(unsigned int max_address)
|
||||
WHERE: internal/mm.h
|
||||
FUNCTION: Gets a page with a restricted physical address i.e. suitable for
|
||||
dma
|
||||
RETURNS: The physical address of the page
|
||||
|
||||
NAME: void disable_dma(unsigned int dmanr)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Disables the specified dma channel
|
||||
|
||||
NAME: void enable_dma(unsigned int dmanr)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Enables the specified dma channel
|
||||
|
||||
NAME: void clear_dma_ff(unsigned int dmanr)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Clear the dma flip-flop
|
||||
|
||||
NAME: void set_dma_mode(unsigned int dmanr, char mode)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Sets the type of dma transfer
|
||||
|
||||
NAME: void set_dma_page(unsigned int dmanr, char pagenr)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Set only the page register bits of the transfer address
|
||||
|
||||
NAME: void set_dma_addr(unsigned int dmanr, unsigned int a)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Set the transfer address for dma
|
||||
NOTE: Assumes flip-flop is clear
|
||||
|
||||
NAME: void set_dma_count(unsigned int dmanr, unsigned int count)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Sets the size of the transfer
|
||||
ARGUMENTS:
|
||||
count = the number of bytes to transfer
|
||||
NOTE: Count must be even for channels 5-7
|
||||
|
||||
NAME: int get_dma_residue(unsigned int dmanr)
|
||||
WHERE: internal/dma.h
|
||||
FUNCTION: Gets the residue remaining after a dma transfer on the channel
|
||||
|
||||
|
2
reactos/doc/buglist
Normal file
2
reactos/doc/buglist
Normal file
@@ -0,0 +1,2 @@
|
||||
* Kernel bugs not fixed
|
||||
|
27
reactos/doc/ddkfuncs.txt
Normal file
27
reactos/doc/ddkfuncs.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
This is a list of the functions documented in the ddk that have been
|
||||
implemented
|
||||
|
||||
IoAllocateController
|
||||
IoFreeController
|
||||
IoCreateController
|
||||
IoDeleteController
|
||||
IoStartNextPacket
|
||||
IoStartNextPacketByKey
|
||||
IoStartPacket
|
||||
IoSizeOfIrp
|
||||
IoMarkIrpPending
|
||||
IoFreeIrp
|
||||
IoConnectInterrupt
|
||||
IoDisconnectInterrupt
|
||||
IoGetCurrentIrpStackLocation
|
||||
IoGetNextIrpStackLocation
|
||||
IoRequestDpc
|
||||
IoInitializeDpc
|
||||
IoInitializeTimer
|
||||
IoStartTimer
|
||||
IoStopTimer
|
||||
|
||||
Partially implemented
|
||||
|
||||
IoCreateDevice
|
||||
IoCallDriver
|
19
reactos/doc/debug.txt
Normal file
19
reactos/doc/debug.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
Some notes on debugging the ReactOS kernel
|
||||
------------------------------------------
|
||||
|
||||
* Interpreting crashes
|
||||
|
||||
If the kernel causes a fatal cpu fault then it will print out a message and
|
||||
halt. This message contains important information for debugging the problem,
|
||||
look for these lines
|
||||
|
||||
Exception: xx(yy)
|
||||
CS:EIP 20:zzzzzzzzzzzz
|
||||
|
||||
Here xx is the type of error, usually either 14 or 13 and yy is the error
|
||||
code. Generally error codes 13 and 14 both mean the kernel tried to access
|
||||
some memory in an invalid way. zzzzzzzzz is the address of the erronous
|
||||
instruction.
|
||||
|
||||
* Debugging with bochs
|
||||
|
114
reactos/doc/faq.txt
Normal file
114
reactos/doc/faq.txt
Normal file
@@ -0,0 +1,114 @@
|
||||
Kernel Development FAQ (for v0.0.7)
|
||||
|
||||
This attempts to answer some of the common questions people developing for
|
||||
the kernel might want to ask (or at least what I think they should ask).
|
||||
Obviously I can only detail those parts which I have written so other
|
||||
developers please fill in the gaps.
|
||||
|
||||
Q: What is this, what are you people, what's going on
|
||||
A: This is the ReactOS, an operating system intended as a clone of windows
|
||||
NT. See the project website (http://www.sid-dis.com/reactos/) for more details.
|
||||
|
||||
Q: Why ReactOS
|
||||
A: To condemn Bill Gates to penury.
|
||||
|
||||
Q: What do I need to compile the kernel
|
||||
A: DJGPP, get it from http://www.delorie.com/djgpp
|
||||
|
||||
Q: How do I compile the kernel
|
||||
A: Unpack the zip. It is important not to install the kernel in the same
|
||||
directory as a previous version, this has caused a bit of confusion in the
|
||||
past. Edit the makefile in the top level directory, in particular select the
|
||||
correct host to build from. Then run make in the top directory
|
||||
|
||||
Q: What files are created when I make the kernel
|
||||
A: The following files are created in the kernel directory
|
||||
kimage = the kernel as a coff executable
|
||||
kimage.bin = the kernel as a raw binary image
|
||||
kernel.sym = a list of the kernel symbols
|
||||
|
||||
Q: How do I load the kernel
|
||||
A: Run the boot.bat batch file.
|
||||
|
||||
Q: Does it boot from disk
|
||||
A: Not at the moment.
|
||||
|
||||
Q: When I run the kernel it crashes
|
||||
A: The kernel (at the moment) can only be loaded from a clean system. That
|
||||
is one without EMM386 or any version of windows loaded. A quick way to
|
||||
ensure this (if you have windows 95) is to set the program to run in msdos
|
||||
mode and specify an empty config.sys and autoexec.bat. See the windows help
|
||||
for more information.
|
||||
|
||||
If you do that and the problem persists then contact the kernel team
|
||||
(ros-kernel@sid-dis.com) as it is probably a bug in the kernel
|
||||
|
||||
Q6: How do I load a module with the kernel
|
||||
A: Add the names of any modules to be loaded to the command line of boot.bat.
|
||||
|
||||
Q7: I want to add code to the kernel, how do I get it to be compiled
|
||||
A: You will need to edit the Makefile in kernel directory. There should be
|
||||
a statement like this
|
||||
|
||||
OBJECTS = hal/head.o hal/exp.o kernel/vsprintf.o \
|
||||
....
|
||||
kernel/irqhand.o hal/page.o mm/virtual.o kernel/error.o \
|
||||
kernel/exports.o kernel/module.o
|
||||
|
||||
Add the name of the object file (the file produced when your code is
|
||||
compiled) to the end of the statement (in this case after kernel/module.o).
|
||||
If you need to go onto a new line then add a slash to the end of the
|
||||
previous line. It is also very important to use an editor which preserves
|
||||
tabs.
|
||||
|
||||
Q8: I want to add code to the kernel, how do I make it official
|
||||
A: Contact the kernel mailing list ros-kernel@sid-dis.com or our coordinator
|
||||
dwinkley@whitworth.edu. If it is for a specific section then the kernel
|
||||
website (http://www.geocities.com/SiliconValley/Peaks/1957) has a list of
|
||||
those working on individual areas, you might what to contact one of them
|
||||
instead.
|
||||
|
||||
Q9: What header files should I use
|
||||
A: Don't include the usual DJGPP headers like stdio.h unless you are using
|
||||
something compiler based like stdargs.h. To use the DJGPP headers requires
|
||||
linking with libc which is useless in kernel mode.
|
||||
|
||||
All the header files are in the top-level include directory which is laid
|
||||
out like this
|
||||
include = general win32 api declarations
|
||||
include/internal = private kernel headers
|
||||
include/internal/hal = HAL headers
|
||||
include/ddk = header files with declarations for modules
|
||||
|
||||
There should be a file called api.txt which documents all of the functions
|
||||
(and which header files they need).
|
||||
|
||||
Q11: I want to export my function for modules to use, how do I do that
|
||||
A: Add the function to the list in kernel/exports.lst, then remake the
|
||||
kernel. Note the function must be declared as extern "C".
|
||||
|
||||
Q12: I want to make my functions part of the kernel interface to user mode,
|
||||
A: That section isn't finished yet, though it will probably mean adding a
|
||||
pointer to the function and the size of its parameters to a internal table
|
||||
somewhere.
|
||||
|
||||
Q14: I want to write a module, what are the guidelines
|
||||
A: See modules.txt in this directory
|
||||
|
||||
Q15: I want to write an ISR (interrupt service routine)
|
||||
A: See irq.txt in this directory
|
||||
|
||||
Q16: I want to use DMA
|
||||
A: Firstly this answer covers only DMA via the dma chips *not*
|
||||
busmaster DMA.
|
||||
|
||||
To program the dma chip use the functions in internal/dma.h (look in api.txt
|
||||
for details). PC DMA can only go to memory with a physical address below
|
||||
1mb (or 16mb on some systems), use the get_dma_page to allocate this kind
|
||||
of memory.
|
||||
|
||||
Q17: You haven't answered my question
|
||||
A: Send your questions to ros-kernel@sid-dis.com
|
||||
|
||||
|
||||
- David Welch (welch@mcmail.com)
|
10
reactos/doc/internal/mm.txt
Normal file
10
reactos/doc/internal/mm.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
This document describes the implementation of the memory managment
|
||||
|
||||
|
||||
* ReactOS memory map
|
||||
|
||||
0x00000000 - 0xc0000000 = User memory
|
||||
0xc0000000 - 0xd0000000 = Kernel memory
|
||||
0xd0000000 - 0xffffffff = Identify map of physical memory
|
||||
|
||||
*
|
1253
reactos/doc/internal/pe.txt
Normal file
1253
reactos/doc/internal/pe.txt
Normal file
File diff suppressed because it is too large
Load Diff
2
reactos/doc/internal/readme.txt
Normal file
2
reactos/doc/internal/readme.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
This contains documentation describing the internals of the various kernel
|
||||
subsystems and a few other useful bits of information.
|
135
reactos/doc/irq.txt
Normal file
135
reactos/doc/irq.txt
Normal file
@@ -0,0 +1,135 @@
|
||||
** Introduction
|
||||
|
||||
This attempts to document the ReactOS irq handling. As of v0.0.8 this has
|
||||
changed to be more nt like, I will attempt to summarize the new
|
||||
implementation for those unavailable with nt device driver writing. Note,
|
||||
ReactOS doesn't have an exact implementation but the omissions are, except
|
||||
where noted, not user visible.
|
||||
|
||||
** Steps in grabbing an irq vector
|
||||
|
||||
* Call HalConnectInterrupt
|
||||
|
||||
PROTOTYPE:
|
||||
|
||||
ULONG HalGetInterruptVector(INTERFACE_TYPE InterfaceType,
|
||||
ULONG BusNumber,
|
||||
ULONG BusInterruptLevel,
|
||||
ULONG BusInterruptVector,
|
||||
OUT PKIRQL Irql,
|
||||
OUT PKAFFINITY Affinity)
|
||||
|
||||
PURPOSE:
|
||||
|
||||
Translates a bus dependant interrupt vector to a system vector
|
||||
|
||||
ARGUMENTS:
|
||||
|
||||
InterfaceType = Type of bus to which the device to receive interrupts
|
||||
from is connected to. Currently only 'Internal' is
|
||||
recognized
|
||||
BusNumber = Number of the bus the device is connected to
|
||||
(currently ignored)
|
||||
BusInterruptLevel = Bus specific interrupt level (currently ignored)
|
||||
BusInterruptVector = Bus specific vector. Currently this is the same
|
||||
as the normal vector (09 is the keyboard vector
|
||||
for example)
|
||||
Irql = On return contains the DIRQL for the vector
|
||||
Affinity = On return contains the affinity mask for the vector
|
||||
(currently unimplemented)
|
||||
|
||||
RETURNS:
|
||||
The system mapped vector
|
||||
|
||||
* Call IoConnectInterrupt
|
||||
|
||||
PROTOTYPE:
|
||||
|
||||
NTSTATUS IoConnectInterrupt(OUT PKINTERRUPT* InterruptObject,
|
||||
PKSERVICE_ROUTINE ServiceRoutine,
|
||||
PVOID ServiceContext,
|
||||
PKSPIN_LOCK SpinLock,
|
||||
ULONG Vector,
|
||||
KIRQL Irql,
|
||||
KIRQL SynchronizeIrql,
|
||||
KINTERRUPT_MODE InterruptMode,
|
||||
BOOLEAN ShareVector,
|
||||
KAFFINITY ProcessorEnableMask,
|
||||
BOOLEAN FloatingSave)
|
||||
|
||||
PURPOSE:
|
||||
|
||||
Connect a service routine to an interrupt vector
|
||||
|
||||
ARGUMENTS:
|
||||
|
||||
InterruptObject = Points to an object describes the interrupt on
|
||||
return
|
||||
ServiceRoutine = Function to be called when the device interrupts
|
||||
ServiceContext = Parameters to be passed to the service routine
|
||||
SpinLock = Should be NULL
|
||||
Vector = System mapped vector returned from HalGetInterruptVector
|
||||
Irql = DIRQL returned from HalGetInterruptVector
|
||||
SynchronizeIrql = Should be the same as Irql
|
||||
InterruptMode = Device interrupt type (currently ignored)
|
||||
ShareVector = True if the interrupt vector can shared
|
||||
ProcessorEnableMask = Currently ignored
|
||||
FloatingSave = Should be false
|
||||
|
||||
RETURNS: Status
|
||||
|
||||
* Sample code for snarfing an interrupt vector
|
||||
|
||||
|
||||
void grab_my_irq()
|
||||
{
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
PKINTERRUPT IrqObject;
|
||||
|
||||
MappedIrq = HalGetInterruptVector(Internal,
|
||||
0,
|
||||
0,
|
||||
MY_VECTOR,
|
||||
&Dirql,
|
||||
&Affinity);
|
||||
IoConnectInterrupt(&IrqObject,
|
||||
my_irq_service_routine,
|
||||
my_context,
|
||||
NULL,
|
||||
MappedIrq,
|
||||
Dirql,
|
||||
Dirql,
|
||||
0,
|
||||
FALSE, // Not sharable
|
||||
Affinity,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
** Designing an interrupt service routine
|
||||
|
||||
An interrupt service routine should have the following prototype
|
||||
|
||||
BOOLEAN my_irq_service_routine(PKINTERRUPT Interrupt,
|
||||
PVOID ServiceContext);
|
||||
|
||||
ARGUMENTS:
|
||||
|
||||
Interrupt = The same as the object returned from the
|
||||
IoConnectInterrupt
|
||||
ServiceContext = A user defined parameters
|
||||
(passed to IoConnectInterrupt)
|
||||
|
||||
RETURNS:
|
||||
|
||||
True if it handled the interrupt, false if it should be passed onto
|
||||
other devices sharing the same vector
|
||||
|
||||
NOTES:
|
||||
|
||||
While an isr is executing all devices of a lower or equal priority
|
||||
can't interrupt. For this reason it is important that an isr
|
||||
should complete in a short an interval as possible. The set of
|
||||
routines an isr can call is also restricted.
|
||||
|
21
reactos/doc/irql.txt
Normal file
21
reactos/doc/irql.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
This document describes the state of a uniprocessor PC at each of the IRQ
|
||||
levels supported by the ReactOS kernel
|
||||
|
||||
PASSIVE_LEVEL: IF bit clear in the processor flags
|
||||
All irqs umasked at the PIC
|
||||
|
||||
APC_LEVEL: Unknown
|
||||
WAKE_LEVEL: Unknown
|
||||
|
||||
DISPATCH_LEVEL: IF bit clear in the processor flags
|
||||
All irqs umasked at the PIC
|
||||
Thread dispatching disabled
|
||||
|
||||
DIRQL (Device specific IRQ level):
|
||||
IF bit clear in the processor flags
|
||||
Device's irq and all lower priority irqs masked at the PIC
|
||||
Thread dispatching disabled
|
||||
|
||||
HIGH_LEVEL: IF bit set in the processor flags
|
||||
All irqs masked at the PIC
|
||||
Thread dispatching disabled
|
33
reactos/doc/modules.txt
Normal file
33
reactos/doc/modules.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
** Introduction
|
||||
|
||||
This is (an incomplete) guide to writing device drivers (and other kernel
|
||||
extensions) for ReactOS.
|
||||
|
||||
** Setting up the build environment
|
||||
|
||||
Create a new subdirectory in the modules directory and copy one of the
|
||||
existing module makefiles into it. Customize the makefile to compile the
|
||||
source files for the module. Note: generally it is not necessary to specify
|
||||
the compiler or compiler flags to use.
|
||||
|
||||
** Initializing a module
|
||||
|
||||
On loading the kernel will call the module function
|
||||
|
||||
PROTOTYPE:
|
||||
|
||||
NTSTATUS ModuleEntry(PDRIVER_OBJECT DriverObject,
|
||||
PUNICODE_STRING RegistryPath)
|
||||
|
||||
PURPOSE:
|
||||
|
||||
Initializing the module
|
||||
|
||||
ARGUMENTS:
|
||||
|
||||
DriverObject = Pointer to an object describing the driver
|
||||
RegistryPath = Currently NULL
|
||||
|
||||
RETURNS:
|
||||
|
||||
STATUS_SUCCESS = If the module initialized successfully
|
@@ -1,687 +0,0 @@
|
||||
*** This file contains messages I've culled off the net as well
|
||||
as previous discussions all of which have useful info on fixes
|
||||
that need to be added to ReactOS. messages are between five
|
||||
dashes on a line by themselves. If you implement the fix
|
||||
reffered to in a message, feel free to delete it from the file.
|
||||
Rex ***
|
||||
-----
|
||||
Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL because
|
||||
it needs to synchronize with KeInsertDpcQueue. Also the idle thread
|
||||
should run at DISPATCH_LEVEL and regularly drain the dpc queue, that
|
||||
way if an irq happens and the dpc can't be executed immediately it
|
||||
will be executed as soon as the processor is idle rather than
|
||||
waiting for the next timer tick
|
||||
-----
|
||||
About the console driver, I think it might be quite useful to have a simple
|
||||
way for apps to print to the screen for debugging. But when the kernel is more
|
||||
stable, console handling should be moved to user level because console printing
|
||||
needs to know about windows and so on which can only be done at user level.
|
||||
-----
|
||||
Subject: Re: IMSAMP-how to avoid rebooting?
|
||||
Date: 9 Nov 1998 00:40:32 -0000
|
||||
From: Charles Bryant <n51190709.ch@chch.demon.co.uk>
|
||||
Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
|
||||
References: 1, 2 , 3 , 4
|
||||
|
||||
In article <un264wzle.fsf@xxx.yyy.zzz>, David C. <qqqq@xxx.yyy.zzz> wrote:
|
||||
>The reason it won't unload when something is bound to it is the same
|
||||
>reason you can't unload any other driver that has an open client. If
|
||||
>you install any driver, and have a user program (or another driver) open
|
||||
>a handle to it, and then give the "net stop" command to unload it,
|
||||
>you'll find that the unload will be delayed until the user program
|
||||
>closes its handle.
|
||||
|
||||
When developing a driver I found this to be a considerable nuisance.
|
||||
Frequently a bug would leave an IRP stuck in the driver and I
|
||||
couldn't unload and reload a fixed version. While reading NTDDK.H I
|
||||
found a suspicious constant and discovered that the Flags field in
|
||||
the device (the one which you OR in DO_BUFFERED_IO or DO_DIRECT_IO)
|
||||
has a bit called DO_UNLOAD_PENDING. By experiment I confirmed that
|
||||
this bit is set when you do 'net stop', so a driver can check it
|
||||
periodically (e.g. from a timer DPC every ten seconds) and cancel all
|
||||
queued IRPs if it is found to be set.
|
||||
|
||||
Since this is not documented anywhere that I can find, it might be
|
||||
unwise to rely on it for production code, but it is very useful for
|
||||
debugging. Maybe someone with internals knowledge can comment on the
|
||||
reliability of it.
|
||||
-----
|
||||
Subject: Re: Kernel bugs
|
||||
Date: Fri, 23 Oct 1998 12:08:36 -0700
|
||||
From: rex <rex@lvcablemodem.com>
|
||||
To: Jason Filby <jasonfilby@yahoo.com>
|
||||
References: 1
|
||||
|
||||
Jason Filby wrote:
|
||||
|
||||
> Hi,
|
||||
>
|
||||
> Ok -- here's most of what I get when I press a key:
|
||||
>
|
||||
> Page fault detected at address 1fd4 with eip c042f794
|
||||
> Recursive page fault detected
|
||||
> Exception 14(2)
|
||||
> CS:EIP 20:c042f794
|
||||
>
|
||||
> Rex -- do you know of anyway to find out which function in what file
|
||||
> is causing the exception? I know that for problems in the kernel, you
|
||||
> just look in the ntoskrnl\kernel.sym file and find the EIP value which
|
||||
> matches the one given in the exception debug text. But what about
|
||||
> modules? How can we track exceptions that occur in functions in modules?
|
||||
>
|
||||
|
||||
I know this is a little belated, but I thought I'd take astab at answering
|
||||
this anyway. add an option to the
|
||||
makefile for the module to generate a listing file with
|
||||
symbol information. Then, on a boot test, note the
|
||||
address that the module is loaded at, and subtract
|
||||
this from the EIP value. add any offset used in the
|
||||
module link specification (I dont think there currently
|
||||
is one), and look for the last symbol with a lower
|
||||
address offset.
|
||||
|
||||
Brian, I have an idea on how to make this exception
|
||||
dump information a little more useful. We should
|
||||
have the load information for the load modules
|
||||
in memory somewhere. Perhaps the exception
|
||||
dump could check offending addresses to see if
|
||||
they lie in the kernel or in a module, and if they
|
||||
lie in a module the proper offset could be subtracted
|
||||
and this number could be displayed seperately. If
|
||||
I get a chance today, I'll make this change and send
|
||||
it to ya.
|
||||
|
||||
Rex.
|
||||
-----
|
||||
Subject: [ros-kernel] Pet peeve of the week
|
||||
Resent-Date: Sun, 25 Oct 1998 11:57:40 -0600
|
||||
Resent-From: ros-kernel@sid-dis.com
|
||||
Date: Sun, 25 Oct 1998 09:53:48 -0800
|
||||
From: rex <rex@lvcablemodem.com>
|
||||
Reply-To: <ros-kernel@sid-dis.com>
|
||||
To: ReactOS Kernel Forum <ros-kernel@sid-dis.com>
|
||||
|
||||
Hi all,
|
||||
|
||||
I guess it's about time to start another mailstorm
|
||||
on the list. :)
|
||||
|
||||
I have a suggestion for a change to the kernel.
|
||||
It not a very big change, and I hope everyone
|
||||
will agree that it makes sense.
|
||||
|
||||
There is a structure used in many places in the
|
||||
kernel called LARGE_INTEGER. the is also
|
||||
a version called ULARGE_INTEGER, but it
|
||||
is not used at all as far as I can tell. this structure
|
||||
is equivalent to a long long int. You can literally
|
||||
cast a pointer to a LARGE_INTEGER to a
|
||||
long long int and all manipulation will work
|
||||
seemlessly. My suggestion is that we replace the
|
||||
use of this structure with long long ints. Even
|
||||
microsoft, in their infinite wisdom, has made this
|
||||
suggestion in the DDK documentation. If you're
|
||||
wondering where, look at the RTL functions
|
||||
that manipulate LARGE_INTEGER structs.
|
||||
|
||||
Replacing LI's with long long ints will work
|
||||
because they are binary compatable. All software
|
||||
compiled to use LI's will manipulate long long ints
|
||||
correctly and vice versa. There is one problem
|
||||
with this suggestion: the LARGE_INTEGER type
|
||||
is a structure containing 2 members. Any code
|
||||
that accesses the structure by members will break.
|
||||
I think the kernel side impact is minimal, and is
|
||||
worth the change. However, the structure is used
|
||||
in several of the Win32 API functions, and needs
|
||||
to remain there. I think we build a conditionally
|
||||
compiled version of the LARGE_INTEGER type.
|
||||
In kernel mode code (the kernel proper and drivers)
|
||||
the LARGE INTEGER will be the following:
|
||||
|
||||
typedef long long int LARGE_INTEGER,
|
||||
*PLARGE_INTEGER;
|
||||
typedef unsigned long long int ULARGE_INTEGER,
|
||||
*PULARGE_INTEGER;
|
||||
|
||||
and in user mode code it will expand out to the
|
||||
current definition (which by the way, is not
|
||||
strictly correct, but can't be because it uses a
|
||||
MS compiler extension).
|
||||
|
||||
Brian, I would be willing to make the conversion
|
||||
to those kernel modules that needed it, and of
|
||||
course to the IDE driver if we want to go forward
|
||||
with the change.
|
||||
|
||||
Lastly, I'll mention what made me consider this.
|
||||
I was fixing the timer routines, and two of the
|
||||
three problems turned out to be related to LI
|
||||
conversion problems.
|
||||
|
||||
Rex.
|
||||
-----
|
||||
Subject: Re: [ros-kernel] Pet peeve of the week
|
||||
Date: Thu, 29 Oct 1998 19:10:37 +0100
|
||||
From: Boudewijn <ariadne@xs4all.nl>
|
||||
To: rex@lvcablemodem.com
|
||||
References: 1
|
||||
|
||||
Hai Rex
|
||||
|
||||
I think it is a good idea to wrap a makro around the member access
|
||||
to large integers.
|
||||
I haven't tested this, but do you think this is a good sugestion ?
|
||||
|
||||
#ifdef COMPILER_LARGE_INTEGERS
|
||||
#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( ( LargeInteger >>
|
||||
32) )
|
||||
#define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( (LargeInteger &
|
||||
0xFFFFFFFF) )
|
||||
#define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) (
|
||||
LargeInteger |= ( ((LARGE_INTEGER)Signed_Long) << 32 ) )
|
||||
#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
|
||||
LargeInteger |= Unsigned_Long )
|
||||
#else
|
||||
#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( (
|
||||
LargeInteger.HighPart) )
|
||||
#define GET_LARGE_INTEGER_LOW_PART(LargeInteger) (
|
||||
(LargeInteger.LowPart) )
|
||||
#define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) (
|
||||
LargeInteger.HighPart= Signed_Long )
|
||||
#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
|
||||
LargeInteger.LowPart = Unsigned_Long )
|
||||
#endif
|
||||
|
||||
Boudewijn
|
||||
-----
|
||||
Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O"
|
||||
Date: Mon, 16 Nov 1998 11:24:57 -0800
|
||||
From: "-Paul" <paulsan@microsoftSPAM.com>
|
||||
Organization: Microsoft Corp.
|
||||
Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-mode
|
||||
References: 1
|
||||
|
||||
Radu, I post the following information occassionally for questions such as
|
||||
yours. I hope it helps.
|
||||
|
||||
-Paul
|
||||
|
||||
Here is an explanation of buffers and DeviceIoControl.
|
||||
|
||||
First, here are the parameters,
|
||||
|
||||
BOOL DeviceIoControl(
|
||||
HANDLE hDevice, // handle to device of interest
|
||||
DWORD dwIoControlCode, // control code of operation to perform
|
||||
LPVOID lpInBuffer, // pointer to buffer to supply input data
|
||||
DWORD nInBufferSize, // size of input buffer
|
||||
LPVOID lpOutBuffer, // pointer to buffer to receive output data
|
||||
DWORD nOutBufferSize, // size of output buffer
|
||||
LPDWORD lpBytesReturned, // pointer to variable to receive output byte
|
||||
count
|
||||
LPOVERLAPPED lpOverlapped // pointer to overlapped structure for
|
||||
asynchronous operation
|
||||
);
|
||||
|
||||
METHOD_BUFFERED
|
||||
|
||||
user-mode perspective
|
||||
|
||||
lpInBuffer - optional, contains data that is written to the driver
|
||||
lpOutBuffer - optional, contains data that is read from the driver after
|
||||
the call has completed
|
||||
|
||||
lpInBuffer and lpOutBuffer can be two buffers or a single shared buffer.
|
||||
If a shared buffer, lpInBuffer is overwritten by lpOutBuffer.
|
||||
|
||||
|
||||
I/O Manager perspective
|
||||
|
||||
examines nInBufferSize and nOutBufferSize. Allocates memory from non-paged
|
||||
pool and puts the address of this pool in Irp->AssociatedIrp.SystemBuffer.
|
||||
The size of this buffer is equal to the size of the larger of the two
|
||||
bufferes. This buffer is accessible at any IRQL.
|
||||
|
||||
copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
|
||||
copies nOutBufferSize to
|
||||
irpSp->Parameters.DeviceIoControl.OutputBufferLength
|
||||
copies contents of lpInBuffer to SystemBuffer allocated above
|
||||
calls your driver
|
||||
|
||||
|
||||
|
||||
Device Driver perspective
|
||||
|
||||
you have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input data
|
||||
from this buffer and you write output data to the same buffer, overwriting
|
||||
the input data.
|
||||
|
||||
Before calling IoCompleteRequest, you must
|
||||
- set IoStatus.Status to an approriate NtStatus
|
||||
- if IoStatus.Status == STATUS_SUCCESS
|
||||
set IoStatus.Information to the
|
||||
number of bytes you want copied
|
||||
from the SystemBuffer back into
|
||||
lpOutBuffer.
|
||||
|
||||
|
||||
I/O Manager Completion Routine perspective
|
||||
|
||||
looks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies the
|
||||
number of bytes specified by IoStatus.Information from
|
||||
Irp->AssociatedIrp.SystemBuffer into lpOutBuffer
|
||||
completes the request
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
METHOD_IN_DIRECT
|
||||
|
||||
user-mode perspective
|
||||
|
||||
lpInBuffer - optional, contains data that is written to the driver. This
|
||||
buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
|
||||
confusion, mentally rename this buffer to lpControlBuffer. This is
|
||||
typically a small, optional buffer that might contain a control structure
|
||||
with useful information for the device driver. This buffer is smal and is
|
||||
double buffered.
|
||||
|
||||
lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read by
|
||||
the driver. To avoid confusion, mentally rename this buffer to
|
||||
lpDataTransferBuffer. This is physically the same buffer that the device
|
||||
driver will read from. There is no double buffering. Technically, this
|
||||
buffer is still optional, but since you are using this buffering method,
|
||||
what would be the point???
|
||||
|
||||
I/O Manager perspective
|
||||
|
||||
If lpInBuffer exists, allocates memory from non-paged pool and puts the
|
||||
address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
|
||||
accessible at any IRQL.
|
||||
|
||||
copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
|
||||
copies nOutBufferSize to
|
||||
irpSp->Parameters.DeviceIoControl.OutputBufferLength
|
||||
copies contents of lpInBuffer to SystemBuffer allocated above
|
||||
So far this is completely identical to METHOD_BUFFERED. Most likely
|
||||
lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
|
||||
|
||||
For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
|
||||
allocated. lpOutBuffer is probed and locked into memory. Then, the user
|
||||
buffer virtual addresses are checked to be sure they are readable in the
|
||||
caller's access mode.
|
||||
|
||||
The MDL is address is stored in Irp->MdlAddress.
|
||||
Your driver is called.
|
||||
|
||||
|
||||
Device Driver perspective
|
||||
|
||||
The device driver can read the copy of lpOutBuffer via
|
||||
Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
|
||||
this buffer is lost. The I/O Manager does not copy any data back to the
|
||||
user-mode buffers as it did in the completion routine for METHOD_BUFFERED.
|
||||
Art Baker's book is wrong in this respect (page 168, "data going from the
|
||||
driver back to the caller is passed through an intermediate system-space
|
||||
buffer" and page 177, "When the IOCTL IRP is completed, the contents of the
|
||||
system buffer will be copied back into the callers original output buffer".
|
||||
|
||||
The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
|
||||
The driver uses whatever Mdl API's to read the buffer. Usually, this
|
||||
buffer is to be written to some mass storage media or some similar
|
||||
operation. Since this is a large data transfer, assume a completion
|
||||
routine is required.
|
||||
|
||||
mark the Irp pending
|
||||
queue it
|
||||
return status pending
|
||||
|
||||
|
||||
|
||||
|
||||
Device Driver Completion Routine perspective
|
||||
|
||||
standard completion routine operations
|
||||
set IoStatus.Status to an approriate NtStatus
|
||||
IoStatus.Information is not needed
|
||||
completete the request
|
||||
|
||||
|
||||
|
||||
|
||||
I/O Manager Completion Routine perspective
|
||||
|
||||
standard I/O Manager completion routine operations
|
||||
unmap the pages
|
||||
deallocate the Mdl
|
||||
complete the request
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
METHOD_OUT_DIRECT
|
||||
|
||||
user-mode perspective
|
||||
|
||||
lpInBuffer - optional, contains data that is written to the driver. This
|
||||
buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
|
||||
confusion, mentally rename this buffer to lpControlBuffer. This is
|
||||
typically a small, optional buffer that might contain a control structure
|
||||
with useful information for the device driver. This buffer is smal and is
|
||||
double buffered.
|
||||
|
||||
lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is written
|
||||
by the driver and read by the wer-mode application when the request is
|
||||
completed. To avoid confusion, mentally rename this buffer to
|
||||
lpDataTransferBuffer. This is physically the same buffer that the device
|
||||
driver will write to. There is no double buffering. Technically, this
|
||||
buffer is still optional, but since you are using this buffering method,
|
||||
what would be the point???
|
||||
|
||||
I/O Manager perspective
|
||||
|
||||
If lpInBuffer exists, allocates memory from non-paged pool and puts the
|
||||
address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
|
||||
accessible at any IRQL.
|
||||
|
||||
copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
|
||||
copies nOutBufferSize to
|
||||
irpSp->Parameters.DeviceIoControl.OutputBufferLength
|
||||
copies contents of lpInBuffer to SystemBuffer allocated above
|
||||
So far this is completely identical to METHOD_BUFFERED. Most likely
|
||||
lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
|
||||
|
||||
For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
|
||||
allocated. lpOutBuffer is probed and locked into memory. Then the user
|
||||
buffer's addresses are checked to make sure the caller could write to them
|
||||
in the caller's access mode.
|
||||
|
||||
The MDL is address is stored in Irp->MdlAddress.
|
||||
Your driver is called.
|
||||
|
||||
|
||||
Device Driver perspective
|
||||
|
||||
The device driver can read the copy of lpOutBuffer via
|
||||
Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
|
||||
this buffer is lost.
|
||||
|
||||
The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
|
||||
The driver uses whatever Mdl API's to write data to the buffer. Usually,
|
||||
this buffer is to be read from some mass storage media or some similar
|
||||
operation. Since this is a large data transfer, assume a completion
|
||||
routine is required.
|
||||
|
||||
mark the Irp pending
|
||||
queue it
|
||||
return status pending
|
||||
|
||||
|
||||
|
||||
|
||||
Device Driver Completion Routine perspective
|
||||
|
||||
standard completion routine operations
|
||||
set IoStatus.Status to an approriate NtStatus
|
||||
IoStatus.Information is not needed
|
||||
completete the request
|
||||
|
||||
|
||||
|
||||
|
||||
I/O Manager Completion Routine perspective
|
||||
|
||||
standard I/O Manager completion routine operations
|
||||
unmap the pages
|
||||
deallocate the Mdl
|
||||
complete the request
|
||||
|
||||
|
||||
|
||||
|
||||
METHOD_NEITHER
|
||||
|
||||
I/O Manager perspective
|
||||
|
||||
Irp->UserBuffer = lpOutputBuffer;
|
||||
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer;
|
||||
|
||||
No comments here. Don't use METHOD_DIRECT unless you know what you are
|
||||
doing. Simple rule.
|
||||
|
||||
If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is the
|
||||
fastest path through the I/O Manager that involves an Irp.
|
||||
|
||||
|
||||
|
||||
|
||||
Final Comment
|
||||
|
||||
Don't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Two
|
||||
major problems can occur. 1 - page fault at high IRQL, or 2 - you write
|
||||
something to Irp->UserBuffer and the I/O Manager overwrites you in its
|
||||
completion routine. File systems access Irp->UserBuffer, but FSD writers
|
||||
know all of the above and know when it is safe to touch Irp->UserBuffer.
|
||||
|
||||
|
||||
|
||||
Radu Woinaroski wrote in message <364F8F6E.2434B010@scitec.com.au>...
|
||||
>Hello,
|
||||
>
|
||||
>I have a kernel-mode device driver that accepts a number of IoControl
|
||||
>commands that use buffered data transfer (METHOD_BUFFERED).
|
||||
>
|
||||
>A user mode API provides a higher level access then the DeviceIoControl
|
||||
>function.
|
||||
>
|
||||
>The function is implemented like that
|
||||
>
|
||||
>BOOL
|
||||
Something(
|
||||
> HANDLE hDevice ,
|
||||
> int param1,
|
||||
> int param2,
|
||||
> DWORD * pReturn,
|
||||
> LPOVERLAPPED pOverlapped)
|
||||
>{
|
||||
> // here a data buffer on the stack sent to asynchronous DeviceIoControl
|
||||
>call
|
||||
> int aDataIn[2];
|
||||
> aDataIn[0] = param1;
|
||||
> aDataIn[1] = param2;
|
||||
>
|
||||
> return DeviceIoControl(
|
||||
> hDevice,
|
||||
> DO_SOMETHING_IO,
|
||||
> aDataIn,
|
||||
> sizeof(int)*2,
|
||||
> pReturn,
|
||||
> sizeof(DWORD),
|
||||
> pOverlapped);
|
||||
>}
|
||||
>
|
||||
>The aDataIn buffer will not exist after DeviceIoControl returns (and
|
||||
>when the I/O operation terminates). I know that for buffered IO the
|
||||
>input data buffer is copyed by de IOManager to a nonpaged-pool area
|
||||
>before passing the request to driver dispatch routine (DeviceControl).
|
||||
>At the point of calling the dispatch routine (DeviceControl) the driver
|
||||
>runs in the context of the calling thread so DeviceIoControl hasn't
|
||||
>returned yet (?? or so I think) so aDataI
|
||||
n will still be valid at the
|
||||
>time IOManager copyes it to its buffer. So, this apears to work ok (at
|
||||
>least in my opinion).
|
||||
>
|
||||
>Does I/O Manager use the Input buffer from the call to the Win32
|
||||
>DeviceIoControl any where else after the first copy ?
|
||||
>
|
||||
>Is there any reason why this approach (passing a buffer on the stack to
|
||||
>a asynchronous DeviceIoControl that uses buffered I/O) wouldn't work ?
|
||||
>
|
||||
>Allocating buffers from heap and deleting them on IO completion while
|
||||
>managing asynchronous IO seems too much work ;-) .
|
||||
>
|
||||
>Thanks in advance for your opinions
|
||||
>Radu W.
|
||||
>
|
||||
>--
|
||||
>Radu Woinaroski
|
||||
>Scitec
|
||||
>Sydney, Australia
|
||||
>Radu.Woinaroski@scitec.com.au
|
||||
-----
|
||||
Subject: Re: PCI ISR problem
|
||||
Date: Fri, 20 Nov 1998 18:04:48 GMT
|
||||
From: jeh@cmkrnl.com (Jamie Hanrahan)
|
||||
Organization: Kernel Mode Systems, San Diego, CA
|
||||
Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
|
||||
References: 1
|
||||
|
||||
On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner
|
||||
<eric.gardiner@natinst.com> wrote:
|
||||
|
||||
>I'm having problems with NT4 not hooking the interrupt line indicated by
|
||||
>a PCI device. Here's what I'm doing:
|
||||
>
|
||||
>1) Enumerating the PCI buses on the system (using HalGetBusData) until
|
||||
>I find my device.
|
||||
>2) Once my device is found, I read the "Interrupt Line Register" in the
|
||||
>device's PCI config space to determine what interrupt level to pass to
|
||||
>HalGetInterruptVector.
|
||||
|
||||
Whups! No. Call HalAssignSlotResources and look at the returned
|
||||
CM_RESOURCE_LIST to find the vector, level, port addresses, etc., for
|
||||
your device. (Then pass the returned CM_RESOURCE_LIST to ExFreePool.)
|
||||
|
||||
|
||||
See Knowledge Base article Q152044.
|
||||
|
||||
--- Jamie Hanrahan, Kernel Mode Systems, San Diego CA (jeh@cmkrnl.com)
|
||||
Drivers, internals, networks, applications, and training for VMS and Windows NT
|
||||
NT kernel driver FAQ, links, and other information: http://www.cmkrnl.com/
|
||||
|
||||
Please post replies, followups, questions, etc., in news, not via e-mail.
|
||||
-----
|
||||
Subject: Re: IRP canceling
|
||||
Date: Mon, 23 Nov 1998 09:05:47 -0500
|
||||
From: Walter Oney <waltoney@oneysoft.com>
|
||||
Organization: Walter Oney Software
|
||||
Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
|
||||
References: 1
|
||||
|
||||
Seol,Keun Seok wrote:
|
||||
> But, if the IRP was the CurrentIrp of the Device Object,
|
||||
> the Driver's Start I/O routine will try to process the IRP.
|
||||
> In the DDK help, the Start I/O routine MUST check the current IRP's
|
||||
> Cancel bit.
|
||||
> If set, Start I/O routine must just return.
|
||||
>
|
||||
> But I think that the IRP already completed should not be accessed.
|
||||
|
||||
You're absolutely right. I recommend the following code in a standard
|
||||
StartIo routine to avoid the problem you point out:
|
||||
|
||||
VOID StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
KIRQL oldirql;
|
||||
IoAcquireCancelSpinLock(&oldirql);
|
||||
if (Irp != DeviceObject->CurrentIrp || Irp->Cancel)
|
||||
{
|
||||
IoReleaseCancelSpinLock(oldirql);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
IoSetCancelRoutine(Irp, NULL);
|
||||
IoReleaseCancelSpinLock(oldirql);
|
||||
}
|
||||
. . .
|
||||
}
|
||||
|
||||
This dovetails with a standard cancel routine:
|
||||
|
||||
VOID CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
if (DeviceObject->CurrentIrp == Irp)
|
||||
{
|
||||
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||
IoStartNextPacket(DeviceObject, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
|
||||
&Irp->Tail.Overlay.DeviceQueueEntry);
|
||||
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||
}
|
||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
You need to remember that the C language specification requires that
|
||||
evaluation of boolean operators short circuit when the result is known.
|
||||
So, if StartIo discovers that the Irp it got as an argument is not the
|
||||
same as CurrentIrp, it will not attempt to evaulate Irp->Cancel.
|
||||
|
||||
Now, as to why this works: StartIo gets called either by IoStartPacket
|
||||
or IoStartNextPacket. Each of them will grab the cancel spin lock and
|
||||
set CurrentIrp, then release the spin lock and call StartIo. If someone
|
||||
should sneak in on another CPU and cancel this very same IRP, your
|
||||
cancel routine will immediately release the spin lock and call
|
||||
IoStartNextPacket. One of two things will then happen. IoStartNextPacket
|
||||
may succeed in getting the cancel spin lock, whereupon it will nullify
|
||||
the CurrentIrp pointer. If another IRP is on the queue, it will remove
|
||||
it from the queue, set CurrentIrp to point to this *new* IRP, release
|
||||
the spin lock, and call StartIo. [You now have two instances of StartIo
|
||||
running on two different CPUs for two different IRPs, but it's not a
|
||||
problem because they won't be able to interfere with each other.]
|
||||
Meanwhile, your original instance of StartIo gets the cancel spin lock
|
||||
and sees that CurrentIrp is not equal to the IRP pointer it got as an
|
||||
argument, so it gives up.
|
||||
|
||||
The second way this could play out is that StartIo gets the cancel lock
|
||||
before IoStartNextPacket does. In this case, CurrentIrp is still
|
||||
pointing to the IRP that's in the process of being cancelled and that
|
||||
StartIo got as an argument. But this IRP hasn't been completed yet (the
|
||||
CPU that's running your cancel routine is spinning inside
|
||||
IoStartNextPacket and therefore hasn't gotten to calling
|
||||
IoCompleteRequest yet), so no-one will have been able to call IoFreeIrp
|
||||
to make your pointer invalid.
|
||||
|
||||
People may tell you that you should be using your own queues for IRPs so
|
||||
you can avoid bottlenecking the system on the global cancel spin lock.
|
||||
That's true enough, but doing it correctly with Plug and Play and Power
|
||||
management things in the way is gigantically complicated. There's a
|
||||
sample in the NT 5 beta-2 DDK called CANCEL that shows how to manage
|
||||
your own queue if you don't worry about PNP and POWER. I hear tell of an
|
||||
upcoming MSJ article by a Microsoft developer that may solve the
|
||||
complete problem.
|
||||
-----
|
||||
Subject: ANNOUNCE: ALINK v1.5
|
||||
Date: 16 Nov 1998 16:36:05 GMT
|
||||
From: anthony_w@my-dejanews.com
|
||||
Organization: Deja News - The Leader in Internet Discussion
|
||||
Newsgroups: comp.os.ms-windows.programmer.win32, comp.lang.asm.x86, comp.os.msdos.programmer
|
||||
|
||||
ALINK is a freeware linker, creating MSDOS COM and EXE files and Win32 PE EXE
|
||||
and DLL files from OMF format OBJ and LIB files, win32-COFF format OBJ files,
|
||||
and win32 RES files.
|
||||
|
||||
NEW for version 1.5:
|
||||
|
||||
Win32 COFF object file support.
|
||||
|
||||
Download it now from my home page.
|
||||
|
||||
Anthony
|
||||
--
|
||||
anthony_w@geocities.com
|
||||
http://www.geocities.com/SiliconValley/Network/4311/index.html
|
||||
|
||||
-----------== Posted via Deja News, The Discussion Network ==----------
|
||||
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
|
||||
-----
|
||||
|
@@ -1,51 +1,31 @@
|
||||
* Function groups totally or partially unimplemented
|
||||
* Kernel things implemented [exceptions in brackets]
|
||||
|
||||
Dma functions (see hal/x86/dma.c)
|
||||
PCI interface functions (see hal/x86/bios32.c, hal/x86/pci.c)
|
||||
HalExamineMbr
|
||||
Locale support (see ex/locale.c)
|
||||
Shutdown support (see ex/power.c)
|
||||
Zw(Set/Get)SystemInformation (see ex/sysinfo.c)
|
||||
Adapter functions (see io/adapter.c)
|
||||
Io cancelation support (see io/cancel, et al)
|
||||
Directory change notification (see io/dir.c)
|
||||
Error logging (see io/errlog.c)
|
||||
Buffer flushing (see io/flush.c)
|
||||
Io completion ports (see io/iocomp.c)
|
||||
DeviceIoControl support (see io/ioctrl.c)
|
||||
File locking (see io/lock.c)
|
||||
Mailslots (see io/mailslot.c)
|
||||
Named pipes (see io/npipe.c)
|
||||
Hardware resource management (see io/resource.c)
|
||||
File access checking (see io/share.c)
|
||||
APCs to user-mode (see ke/apc.c, ke/apchelp.asm)
|
||||
Exception support (see ke/catch.c)
|
||||
Mutex support (see ke/mutex.c)
|
||||
Semaphore support (see ke/sem.c)
|
||||
Timer support (see ke/timer.c)
|
||||
Properly calibrate delay loop (see ke/timer.c)
|
||||
Waiting for multiple objects (see ke/wait.c)
|
||||
Single linked lists (see rtl/slist.c)
|
||||
Sequenced lists (see rtl/seqlist.c)
|
||||
|
||||
* Verify implementation
|
||||
Spinlocks [Uniprocessor only]
|
||||
IRQ levels [Not APC_LEVEL or WAKE_LEVEL, uniprocessor only]
|
||||
ISRs [Partial, uniprocessor only]
|
||||
Timers [Untested]
|
||||
DPCs [Untested]
|
||||
Objects [Partial]
|
||||
Namespace [Partial]
|
||||
Handle tables [One process only]
|
||||
Threads [Some initial work]
|
||||
RTL list functions [All except sequenced lists]
|
||||
Zones [Untested]
|
||||
Memory pool [Working but semantics partially incompatiable]
|
||||
Device objects [Some but no support for layering]
|
||||
IRP [Partial]
|
||||
Memory sections [Partial, no file mappings]
|
||||
PCI interface [Probes but no support]
|
||||
CreateFile API [Device only]
|
||||
ReadFile/WriteFile API [Device only]
|
||||
MDL functions [Untested]
|
||||
|
||||
Fast mutexes (see ex/fmutex.c)
|
||||
|
||||
* Major areas
|
||||
* Kernel things unimplemented (partial)
|
||||
|
||||
Security support (see se/*.c)
|
||||
Registry support (see cm/*.c)
|
||||
Paging support
|
||||
File system cache support
|
||||
SCSI miniport driver
|
||||
Network support
|
||||
Video drivers
|
||||
USER and GDI modules
|
||||
|
||||
* Drivers
|
||||
NTFS, EXT2 filesystems
|
||||
Many others (use oem's where possible)
|
||||
|
||||
* For the future
|
||||
DOS, Win16, POSIX subsystems
|
||||
Add support for source level debugging to Bochs
|
||||
Support for remote debugging
|
||||
Process managment
|
||||
Dispatcher objects (Mutex, Semaphore etc)
|
||||
Investigate user and kernel mode APCs
|
||||
Asynchronous I/O
|
||||
Optimization
|
||||
|
16
reactos/doc/wstring.txt
Normal file
16
reactos/doc/wstring.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
subject wstring.zip
|
||||
author Boudewijn Dekker
|
||||
date 06-06-98
|
||||
|
||||
|
||||
I wrote some inline wide character string functions. It are modified version
|
||||
of the ones in string.h. I added four more function nl stricmp, strnicmp,
|
||||
wcsicmp, and wcsnicmp. These are the case insensitive variants of
|
||||
strcmp, strncmp and wcscmp, wcsncmp. I tested all the functions but I
|
||||
would urge anyone to tested again. I removed an extern specifier
|
||||
__wcstok and strtok cause I it caused an compilation error when
|
||||
using strtok or wcstok. Please could someone see if this correct.
|
||||
I also used these string functions in lstring api functions.
|
||||
|
||||
|
||||
Boudewijn Dekker
|
@@ -1,4 +0,0 @@
|
||||
base.tmp
|
||||
junk.tmp
|
||||
temp.exp
|
||||
|
@@ -1,155 +0,0 @@
|
||||
|
||||
#include <internal/mmhal.h>
|
||||
#include <internal/halio.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <string.h>
|
||||
#include <internal/string.h>
|
||||
#include <defines.h>
|
||||
|
||||
//#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
|
||||
|
||||
#define FSCTL_GET_CONSOLE_SCREEN_BUFFER_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 254, DO_DIRECT_IO, FILE_READ_ACCESS|FILE_WRITE_ACCESS)
|
||||
#define FSCTL_SET_CONSOLE_SCREEN_BUFFER_INFO CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 255, DO_DIRECT_IO, FILE_READ_ACCESS|FILE_WRITE_ACCESS)
|
||||
|
||||
|
||||
|
||||
CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
|
||||
|
||||
|
||||
VOID ScrStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS ScrDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG ControlCode;
|
||||
NTSTATUS Status;
|
||||
char *UserBuf = Irp->UserBuffer;
|
||||
int i;
|
||||
|
||||
switch (stk->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_CREATE:
|
||||
case IRP_MJ_CLOSE:
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
for(i=0;i<stk->Parameters.Write.Length;i++)
|
||||
__putchar(UserBuf[i]);
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
ControlCode = stk->Parameters.DeviceIoControl.IoControlCode;
|
||||
if ( ControlCode == FSCTL_GET_CONSOLE_SCREEN_BUFFER_INFO ) {
|
||||
// printk("get console screen buffer info\n");
|
||||
ConsoleScreenBufferInfo.dwCursorPosition.X=__wherex();
|
||||
ConsoleScreenBufferInfo.dwCursorPosition.Y=__wherey();
|
||||
|
||||
__getscreensize(&ConsoleScreenBufferInfo.dwSize.X, &ConsoleScreenBufferInfo.dwSize.Y );
|
||||
|
||||
memcpy(UserBuf,&ConsoleScreenBufferInfo,sizeof(CONSOLE_SCREEN_BUFFER_INFO));
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else if ( ControlCode == FSCTL_SET_CONSOLE_SCREEN_BUFFER_INFO ) {
|
||||
// printk("set console screen buffer info\n");
|
||||
memcpy(&ConsoleScreenBufferInfo,UserBuf,sizeof(CONSOLE_SCREEN_BUFFER_INFO));
|
||||
__goxy(ConsoleScreenBufferInfo.dwCursorPosition.X,ConsoleScreenBufferInfo.dwCursorPosition.Y);
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
IoCompleteRequest(Irp, Status);
|
||||
// DPRINT("Status %d\n",Status);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Module entry point
|
||||
*/
|
||||
STDCALL NTSTATUS
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
ANSI_STRING adevice_name;
|
||||
UNICODE_STRING device_name;
|
||||
ANSI_STRING asymlink_name;
|
||||
UNICODE_STRING symlink_name;
|
||||
|
||||
DbgPrint("Screen Driver 0.0.4\n");
|
||||
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrDispatch;
|
||||
DriverObject->DriverStartIo = ScrStartIo;
|
||||
|
||||
//ScrSwitchToBlueScreen();
|
||||
|
||||
|
||||
RtlInitAnsiString(&adevice_name,"\\Device\\BlueScreen");
|
||||
RtlAnsiStringToUnicodeString(&device_name,&adevice_name,TRUE);
|
||||
IoCreateDevice(DriverObject,0,&device_name,FILE_DEVICE_SCREEN,0,
|
||||
TRUE,&DeviceObject);
|
||||
|
||||
|
||||
RtlInitAnsiString(&asymlink_name,"\\??\\BlueScreen");
|
||||
RtlAnsiStringToUnicodeString(&symlink_name,&asymlink_name,TRUE);
|
||||
IoCreateSymbolicLink(&symlink_name,&device_name);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
|
||||
void ScrSwitchToBlueScreen(void)
|
||||
/*
|
||||
* FUNCTION: Switches the monitor to text mode and writes a blue background
|
||||
* NOTE: This function is entirely self contained and can be used from any
|
||||
* graphics mode.
|
||||
*/
|
||||
{
|
||||
|
||||
/*
|
||||
* Reset the cursor position
|
||||
*/
|
||||
ConsoleScreenBufferInfo.dwCursorPosition.X=__wherex();
|
||||
ConsoleScreenBufferInfo.dwCursorPosition.Y=__wherey();
|
||||
|
||||
__getscreensize(&ConsoleScreenBufferInfo.dwSize.X, &ConsoleScreenBufferInfo.dwSize.Y );
|
||||
|
||||
|
||||
/*
|
||||
* This code section is taken from the sample routines by
|
||||
* Jeff Morgan (kinfira@hotmail.com)
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -1,23 +0,0 @@
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
all: blue.sys
|
||||
|
||||
.phony: all
|
||||
|
||||
OBJECTS = blue.o ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
blue.sys: $(OBJECTS)
|
||||
$(CC) -specs=../../svc_specs -mdll -o junk.tmp -Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ -Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp $(OBJECTS)
|
||||
- $(RM) junk.tmp
|
||||
$(DLLTOOL) --dllname blue.sys --base-file base.tmp \
|
||||
--output-exp temp.exp
|
||||
- $(RM) base.tmp
|
||||
$(CC) --verbose -Wl,--image-base,0x10000 -Wl,-e,_DriverEntry@8 \
|
||||
-specs=../../svc_specs -mdll -o blue.sys $(OBJECTS) -Wl,temp.exp
|
||||
- $(RM) temp.exp
|
||||
|
||||
|
@@ -1,2 +0,0 @@
|
||||
DIRS=exe \
|
||||
sys
|
@@ -1,168 +0,0 @@
|
||||
/*++
|
||||
|
||||
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
|
@@ -1,7 +0,0 @@
|
||||
#
|
||||
# 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
|
@@ -1,10 +0,0 @@
|
||||
TARGETNAME=event
|
||||
TARGETPATH=$(BASEDIR)\lib
|
||||
TARGETTYPE=PROGRAM
|
||||
|
||||
INCLUDES=..\sys
|
||||
|
||||
SOURCES=eventtest.c
|
||||
|
||||
UMTYPE=console
|
||||
UMBASE=0x100000
|
@@ -1,50 +0,0 @@
|
||||
|
||||
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
|
@@ -1,447 +0,0 @@
|
||||
/*++
|
||||
|
||||
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
|
||||
);
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
@@ -1,43 +0,0 @@
|
||||
/*++
|
||||
|
||||
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__
|
@@ -1,7 +0,0 @@
|
||||
; 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
|
@@ -1,11 +0,0 @@
|
||||
#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"
|
||||
|
@@ -1,7 +0,0 @@
|
||||
#
|
||||
# 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
|
@@ -1,6 +0,0 @@
|
||||
TARGETNAME=event
|
||||
TARGETPATH=$(BASEDIR)\lib
|
||||
TARGETTYPE=DRIVER
|
||||
|
||||
SOURCES=event.c \
|
||||
event.rc
|
@@ -1,444 +0,0 @@
|
||||
//
|
||||
// FLOPPY.C - NEC-765/8272A floppy device driver
|
||||
// written by Rex Jolliff
|
||||
// with help from various other sources, including but not limited to:
|
||||
// Art Baker's NT Device Driver Book, Linux Source, and the internet.
|
||||
//
|
||||
// Modification History:
|
||||
// 08/19/98 RJJ Created.
|
||||
//
|
||||
// To do:
|
||||
// FIXME: get it working
|
||||
// FIXME: add support for DMA hardware
|
||||
// FIXME: should add support for floppy tape/zip devices
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#include "floppy.h"
|
||||
|
||||
#define VERSION "V0.0.1"
|
||||
|
||||
// --------------------------------------------------- File Statics
|
||||
|
||||
typedef struct _FLOPPY_CONTROLLER_PARAMETERS
|
||||
{
|
||||
int PortBase;
|
||||
int Vector;
|
||||
int IrqL;
|
||||
int SynchronizeIrqL;
|
||||
KINTERRUPT_MODE InterruptMode;
|
||||
KAFFINITY Affinity;
|
||||
} FLOPPY_CONTROLLER_PARAMETERS, *PFLOPPY_CONTROLLER_PARAMETERS;
|
||||
|
||||
#define FLOPPY_MAX_CONTROLLERS 2
|
||||
FLOPPY_CONTROLLER_PARAMETERS ControllerParameters[FLOPPY_MAX_CONTROLLERS] =
|
||||
{
|
||||
{0x03f0, 6, 6, 6, LevelSensitive, 0xffff},
|
||||
{0x0370, 6, 6, 6, LevelSensitive, 0xffff},
|
||||
};
|
||||
|
||||
FLOPPY_DEVICE_PARAMETERS DeviceTypes[] =
|
||||
{
|
||||
/* Unknown */
|
||||
{0, 500, 16, 16, 8000, 1000, 3000, 0, 20, 5, 80, 3000, 20, {3,1,2,0,2}, 0, 0, { 7, 4, 8, 2, 1, 5, 3,10}, 1500, 0, "unknown"},
|
||||
/* 5 1/4 360 KB PC*/
|
||||
{1, 300, 16, 16, 8000, 1000, 3000, 0, 20, 5, 40, 3000, 17, {3,1,2,0,2}, 0, 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 1500, 1, "360K PC"},
|
||||
/* 5 1/4 HD AT*/
|
||||
{2, 500, 16, 16, 6000, 400, 3000, 14, 20, 6, 83, 3000, 17, {3,1,2,0,2}, 0, 0, { 2, 5, 6,23,10,20,11, 0}, 1500, 2, "1.2M"},
|
||||
/* 3 1/2 DD*/
|
||||
{3, 250, 16, 16, 3000, 1000, 3000, 0, 20, 5, 83, 3000, 20, {3,1,2,0,2}, 0, 0, { 4,22,21,30, 3, 0, 0, 0}, 1500, 4, "720k"},
|
||||
/* 3 1/2 HD*/
|
||||
{4, 500, 16, 16, 4000, 400, 3000, 10, 20, 5, 83, 3000, 20, {3,1,2,0,2}, 0, 0, { 7, 4,25,22,31,21,29,11}, 1500, 7, "1.44M"},
|
||||
/* 3 1/2 ED*/
|
||||
{5, 1000, 15, 8, 3000, 400, 3000, 10, 20, 5, 83, 3000, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 1500, 8, "2.88M AMI BIOS"},
|
||||
/* 3 1/2 ED*/
|
||||
{6, 1000, 15, 8, 3000, 400, 3000, 10, 20, 5, 83, 3000, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 1500, 8, "2.88M"}
|
||||
};
|
||||
|
||||
static BOOLEAN FloppyInitialized = FALSE;
|
||||
|
||||
// ------------------------------------------------------ Functions
|
||||
|
||||
// ModuleEntry
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
NTSTATUS RC;
|
||||
PFLOPPY_DEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
// Export other driver entry points...
|
||||
DriverObject->DriverStartIo = FloppyStartIo;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyDispatchOpenClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyDispatchOpenClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = FloppyDispatchReadWrite;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = FloppyDispatchReadWrite;
|
||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FloppyDispatchDeviceControl;
|
||||
|
||||
// Try to detect controller and abort if it fails
|
||||
if (!FloppyCreateController(DriverObject,
|
||||
&ControllerParameters[0],
|
||||
0))
|
||||
{
|
||||
DPRINT("Could not find floppy controller");
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
FloppyCreateController(PDRIVER_OBJECT DriverObject,
|
||||
PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
|
||||
int Index)
|
||||
{
|
||||
PFLOPPY_CONTROLLER_TYPE ControllerType;
|
||||
PCONTROLLER_OBJECT ControllerObject;
|
||||
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension;
|
||||
|
||||
/* Detect controller and determine type */
|
||||
if (!FloppyGetControllerVersion(ControllerParameters, &ControllerType))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FIXME: Register port ranges and interrupts with HAL
|
||||
|
||||
/* Create controller object for FDC */
|
||||
ControllerObject = IoCreateController(sizeof(FLOPPY_CONTROLLER_EXTENSION));
|
||||
if (ControllerObject == NULL)
|
||||
{
|
||||
DPRINT("Could not create controller object for controller %d\n",
|
||||
Index);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FIXME: fill out controller data
|
||||
ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)
|
||||
ControllerObject->ControllerExtension;
|
||||
ControllerExtension->Number = Index;
|
||||
ControllerExtension->PortBase = ControllerParameters->PortBase;
|
||||
ControllerExtension->Vector = ControllerParameters->Vector;
|
||||
ControllerExtension->FDCType = ControllerType;
|
||||
|
||||
/* Initialize the spin lock in the controller extension */
|
||||
KeInitializeSpinLock(&ControllerExtension->SpinLock);
|
||||
|
||||
/* Register an interrupt handler for this controller */
|
||||
RC = IoConnectInterrupt(&ControllerExtension->Interrupt,
|
||||
FloppyIsr,
|
||||
ControllerExtension,
|
||||
&ControllerExtension->SpinLock,
|
||||
ControllerExtension->Vector,
|
||||
ControllerParameters->IrqL,
|
||||
ControllerParameters->SynchronizeIrqL,
|
||||
ControllerParameters->InterruptMode,
|
||||
FALSE,
|
||||
ControllerParameters->Affinity,
|
||||
FALSE);
|
||||
if (!NT_SUCCESS(RC))
|
||||
{
|
||||
DPRINT("Could not Connect Interrupt %d\n", ControllerExtension->Vector);
|
||||
IoDeleteController(ControllerObject);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// FIXME: setup DMA stuff for controller
|
||||
|
||||
// Check for each possible drive and create devices for them
|
||||
for (DriveIdx = 0; DriveIdx < FLOPPY_MAX_DRIVES; DriveIdx++)
|
||||
{
|
||||
// FIXME: try to identify the drive
|
||||
// FIXME: create a device if it's there
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// FloppyGetControllerVersion
|
||||
//
|
||||
// DESCRIPTION
|
||||
// Get the type/version of the floppy controller
|
||||
//
|
||||
// RUN LEVEL:
|
||||
// PASSIVE_LEVEL
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// IN OUT PFLOPPY_DEVICE_EXTENSION DeviceExtension
|
||||
//
|
||||
// RETURNS:
|
||||
// BOOL success or failure
|
||||
//
|
||||
// COMMENTS:
|
||||
// This routine (get_fdc_version) was originally written by David C. Niemi
|
||||
//
|
||||
static BOOLEAN
|
||||
FloppyGetControllerVersion(IN PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
|
||||
OUT PFLOPPY_CONTROLLER_TYPE ControllerType)
|
||||
{
|
||||
BYTE ResultReturned
|
||||
BYTE Result[FLOPPY_MAX_REPLIES];
|
||||
int ResultLength;
|
||||
|
||||
/* 82072 and better know DUMPREGS */
|
||||
if (!FloppyWriteCommandByte(ControllerParameters->PortBase,
|
||||
FLOPPY_CMD_DUMP_FDC))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
ResultLength = FloppyReadResultCode(PortBase, &Result));
|
||||
if (ResultLength < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 8272a/765 don't know DUMPREGS */
|
||||
if ((ResultLength == 1) && (Result[0] == 0x80))
|
||||
{
|
||||
DPRINT("FDC %d is an 8272A\n", PortBase);
|
||||
*ControllerType = FDC_8272A;
|
||||
return TRUE;
|
||||
}
|
||||
if (r != 10)
|
||||
{
|
||||
DPRINT("FDC %d init: DUMP_FDC: unexpected return of %d bytes.\n",
|
||||
PortBase,
|
||||
ResultLength);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!FloppyConfigure(PortBase, FALSE, 0x0a))
|
||||
{
|
||||
DPRINT("FDC %d is an 82072\n", PortBase);
|
||||
*ControllerType = FDC_82072;
|
||||
return TRUE;
|
||||
}
|
||||
FloppyWriteCommandByte(PortBase, FLOPPY_CMD_PPND_RW);
|
||||
if (FloppyNeedsMoreOutput(PortBase, Result) == FLOPPY_NEEDS_OUTPUT)
|
||||
{
|
||||
FloppyWriteCommandByte(PortBase, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("FDC %d is an 82072A\n", PortBase);
|
||||
*ControllerType = FDC_82072A;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Pre-1991 82077, doesn't know LOCK/UNLOCK */
|
||||
FloppyWriteCommandByte(PortBase, FLOPPY_CMD_UNLK_FIFO);
|
||||
ResultLength = FloppyReadResultCode(PortBase, &Result));
|
||||
if ((ResultLength == 1) && (Result[0] == 0x80))
|
||||
{
|
||||
DPRINT("FDC %d is a pre-1991 82077\n", PortBase);
|
||||
*ControllerType = FDC_82077_ORIG;
|
||||
return TRUE;
|
||||
}
|
||||
if ((ResultLength != 1) || (Result[0] != 0x00))
|
||||
{
|
||||
DPRINT("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
|
||||
PortBase,
|
||||
ResultLength);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Revised 82077AA passes all the tests */
|
||||
FloppyWriteCommandByte(PortBase, FLOPPY_CMD_PARTID);
|
||||
ResultLength = FloppyReadResultCode(PortBase, &Result));
|
||||
if (ResultLength != 1)
|
||||
{
|
||||
DPRINT("FDC %d init: PARTID: unexpected return of %d bytes.\n",
|
||||
PortBase,
|
||||
ResultLength);
|
||||
return FALSE;
|
||||
}
|
||||
if (Result[0] == 0x80)
|
||||
{
|
||||
DPRINT("FDC %d is a post-1991 82077\n", PortBase);
|
||||
*ControllerType = FDC_82077;
|
||||
return TRUE;
|
||||
}
|
||||
switch (Result[0] >> 5)
|
||||
{
|
||||
case 0x0:
|
||||
/* Either a 82078-1 or a 82078SL running at 5Volt */
|
||||
DPRINT("FDC %d is an 82078.\n", PortBase);
|
||||
*ControllerType = FDC_82078;
|
||||
return TRUE;
|
||||
|
||||
case 0x1:
|
||||
DPRINT("FDC %d is a 44pin 82078\n", PortBase);
|
||||
*ControllerType = FDC_82078;
|
||||
return TRUE;
|
||||
|
||||
case 0x2:
|
||||
DPRINT("FDC %d is a S82078B\n", PortBase);
|
||||
*ControllerType = FDC_S82078B;
|
||||
return TRUE;
|
||||
|
||||
case 0x3:
|
||||
DPRINT("FDC %d is a National Semiconductor PC87306\n", PortBase);
|
||||
*ControllerType = FDC_87306;
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
DPRINT("FDC %d init: 82078 variant with unknown PARTID=%d.\n",
|
||||
PortBase,
|
||||
Result[0] >> 5);
|
||||
*ControllerType = FDC_82078_UNKN;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* sends a command byte to the fdc */
|
||||
static BOOLEAN
|
||||
FloppyWriteCommandByte(WORD PortBase, BYTE Byte)
|
||||
{
|
||||
int Status;
|
||||
|
||||
if ((Status = FloppyWaitUntilReady()) < 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((Status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY)
|
||||
{
|
||||
FloppyWriteData(PortBase, Byte);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FloppyInitialized)
|
||||
{
|
||||
DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
|
||||
Byte,
|
||||
PortBase,
|
||||
Status);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* gets the response from the fdc */
|
||||
static int
|
||||
FloppyReadResultCode(WORD PortBase, PBYTE Result)
|
||||
{
|
||||
int Replies;
|
||||
int Status;
|
||||
|
||||
for (Replies = 0; Replies < FLOPPY_MAX_REPLIES; Replies++)
|
||||
{
|
||||
if ((Status = FloppyWaitUntilReady(PortBase)) < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
|
||||
if ((Status & ~STATUS_BUSY) == STATUS_READY)
|
||||
{
|
||||
return Replies;
|
||||
}
|
||||
if (Status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
|
||||
{
|
||||
Result[Replies] = fd_inb(FD_DATA);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FloppyInitialized)
|
||||
{
|
||||
DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
|
||||
PortBase,
|
||||
Status,
|
||||
Replies);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* waits until the fdc becomes ready */
|
||||
static int
|
||||
FloppyWaitUntilReady(WORD PortBase)
|
||||
{
|
||||
int Retries;
|
||||
int Status;
|
||||
|
||||
for (Retries = 0; Retries < FLOPPY_MAX_STAT_RETRIES; Retries++)
|
||||
{
|
||||
status = FloppyReadSTAT(PortBase);
|
||||
if (Status & STATUS_READY)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (FloppyInitialized)
|
||||
{
|
||||
DPRINT("Getstatus times out (%x) on fdc %d\n",
|
||||
Status,
|
||||
PortBase);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#define MORE_OUTPUT -2
|
||||
/* does the fdc need more output? */
|
||||
static int
|
||||
FloppyNeedsMoreOutput(WORD PortBase, PBYTE Result)
|
||||
{
|
||||
int Status;
|
||||
|
||||
if ((Status = FloppyWaitUntilReady(PortBase)) < 0)
|
||||
return -1;
|
||||
if ((Status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
|
||||
{
|
||||
return FLOPPY_NEEDS_OUTPUT;
|
||||
}
|
||||
|
||||
return FloppyReadResultCode(PortBase, Result);
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
FloppyConfigure(WORD PortBase, BOOLEAN DisableFIFO, BYTE FIFODepth)
|
||||
{
|
||||
BYTE Result[FLOPPY_MAX_REPLIES];
|
||||
|
||||
/* Turn on FIFO */
|
||||
FloppyWriteCommandByte(FLOPPY_CMD_CFG_FIFO);
|
||||
if (FloppyNeedsOutput(PortBase, Result) != FLOPPY_NEEDS_OUTPUT)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
FloppyWriteCommandByte(PortBase, 0);
|
||||
FloppyWriteCommandByte(PortBase,
|
||||
0x10 |
|
||||
(DisableFIFO ? 0x20 : 0x00) |
|
||||
(FIFODepth & 0x0f));
|
||||
/* pre-compensation from track 0 upwards */
|
||||
FloppyWriteCommandByte(PortBase, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@@ -1,158 +0,0 @@
|
||||
|
||||
#define FLOPPY_MAX_STAT_RETRIES 10000
|
||||
|
||||
#define FLOPPY_NEEDS_OUTPUT -2
|
||||
//
|
||||
// Floppy register definitions
|
||||
//
|
||||
|
||||
#define FLOPPY_REG_DOR 0x0002
|
||||
#define FLOPPY_REG_MSTAT 0x0004
|
||||
#define FLOPPY_MS_DRV0BUSY 0x01
|
||||
#define FLOPPY_MS_DRV1BUSY 0x02
|
||||
#define FLOPPY_MS_DRV2BUSY 0x04
|
||||
#define FLOPPY_MS_DRV3BUSY 0x08
|
||||
#define FLOPPY_MS_FDCBUSY 0x10
|
||||
#define FLOPPY_MS_DMAMODE 0x20
|
||||
#define FLOPPY_MS_DATADIR 0x40
|
||||
#define FLOPPY_MS_DATARDY 0x80
|
||||
#define FLOPPY_REG_DATA 0x0005
|
||||
#define FLOPPY_REG_DIR 0x0007 /* READ ONLY */
|
||||
#define FLOPPY_DI_DSKCHNG 0x80
|
||||
#define FLOPPY_REG_CCNTL 0x0007 /* WRITE ONLY */
|
||||
|
||||
#define FLOPPY_CMD_RD_TRK 0x02
|
||||
#define FLOPPY_CMD_SPEC_CHARS 0x03
|
||||
#define FLOPPY_CSC_SRT_SHIFT 4
|
||||
#define FLOPPY_CSC_HUT_MASK 0x0f
|
||||
#define FLOPPY_CSC_HLT_SHIFT 1
|
||||
#define FLOPPY_CSC_NON_DMA 0x01
|
||||
#define FLOPPY_CMD_SNS_DRV 0x04
|
||||
#define FLOPPY_CMD_WRT_DATA 0x05
|
||||
#define FLOPPY_CMD_RD_DATA 0x06
|
||||
#define FLOPPY_CMD_RECAL 0x07
|
||||
#define FLOPPY_CMD_SNS_INTR 0x08
|
||||
#define FLOPPY_CSI_IC_MASK 0xe0
|
||||
#define FLOPPY_CSI_IC_RDYCH 0x60
|
||||
#define FLOPPY_CSI_IC_SEEKGD 0x80
|
||||
#define FLOPPY_CSI_IC_SEEKBD 0xc0
|
||||
#define FLOPPY_CMD_WRT_DEL 0x09
|
||||
#define FLOPPY_CMD_RD_ID 0x0a
|
||||
#define FLOPPY_CMD_RD_DEL 0x0c
|
||||
#define FLOPPY_CMD_FMT_TRK 0x0d
|
||||
#define FLOPPY_CMD_DUMP_FDC 0x0e
|
||||
#define FLOPPY_CMD_SEEK 0x0f
|
||||
#define FLOPPY_CMD_VERSION 0x10
|
||||
#define FLOPPY_CMD_SCN_EQ 0x11
|
||||
#define FLOPPY_CMD_PPND_RW 0x12
|
||||
#define FLOPPY_CMD_CFG_FIFO 0x13
|
||||
#define FLOPPY_CMD_LCK_FIFO 0x14
|
||||
#define FLOPPY_CMD_PARTID 0x18
|
||||
#define FLOPPY_CMD_SCN_LE 0x19
|
||||
#define FLOPPY_CMD_SCN_GE 0x1d
|
||||
#define FLOPPY_CMD_CFG_PWR 0x27
|
||||
#define FLOPPY_CMD_SAVE_FDC 0x2e
|
||||
#define FLOPPY_CMD_FMT_ISO 0x33
|
||||
#define FLOPPY_CMD_DMA_READ 0x46
|
||||
#define FLOPPY_CMD_DMA_WRT 0x4a
|
||||
#define FLOPPY_CMD_REST_FDC 0x4e
|
||||
#define FLOPPY_CMD_DRV_SPEC 0x8e
|
||||
#define FLOPPY_CMD_RSEEK_OUT 0x8f
|
||||
#define FLOPPY_CMD_ULK_FIFO 0x94
|
||||
#define FLOPPY_CMD_RSEEK_IN 0xcf
|
||||
#define FLOPPY_CMD_FMT_WRT 0xef
|
||||
|
||||
// Command Code modifiers
|
||||
#define FLOPPY_C0M_SK 0x20
|
||||
#define FLOPPY_C0M_MFM 0x40
|
||||
#define FLOPPY_C0M_MT 0x80
|
||||
#define FLOPPY_C1M_DRVMASK 0x03
|
||||
#define FLOPPY_C1M_HEAD1 0x04
|
||||
|
||||
// Status code values and masks
|
||||
#define FLOPPY_ST0_INVALID 0x80
|
||||
|
||||
// useful command defines
|
||||
#define FLOPPY_CMD_READ (FLOPPY_CMD_RD_DATA | FLOPPY_C0M_SK | FLOPPY_C0M_MFM | FLOPPY_C0M_MT)
|
||||
#define FLOPPY_CMD_WRITE (FLOPPY_CMD_WRT_DATA | FLOPPY_C0M_MFM | FLOPPY_C0M_MT)
|
||||
#define FLOPPY_CMD_FORMAT (FLOPPY_CMD_FMT_TRK | FLOPPY_C0M_MFM)
|
||||
|
||||
//
|
||||
// HAL floppy register access commands
|
||||
//
|
||||
#define FloppyWriteDOR(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DOR, (V)))
|
||||
#define FloppyReadMSTAT(A) (READ_BYTE((A) + FLOPPY_REG_MSTAT))
|
||||
#define FloppyReadDATA(A) (READ_BYTE((A) + FLOPPY_REG_DATA))
|
||||
#define FloppyWriteDATA(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DATA, (V)))
|
||||
#define FloppyReadDIR(A) (READ_BYTE((A) + FLOPPY_REG_DIR))
|
||||
#define FloppyWriteCCNTL(A, V) (WRITE_BYTE((A) + FLOPPY_REG_CCNTL, (V)))
|
||||
|
||||
//
|
||||
// Known Floppy controller types
|
||||
//
|
||||
typedef enum _FLOPPY_CONTROLLER_TYPE
|
||||
{
|
||||
FDC_NONE,
|
||||
FDC_UNKNOWN,
|
||||
FDC_8272A, /* Intel 8272a, NEC 765 */
|
||||
FDC_765ED, /* Non-Intel 1MB-compatible FDC, can't detect */
|
||||
FDC_82072, /* Intel 82072; 8272a + FIFO + DUMPREGS */
|
||||
FDC_82072A, /* 82072A (on Sparcs) */
|
||||
FDC_82077_ORIG, /* Original version of 82077AA, sans LOCK */
|
||||
FDC_82077, /* 82077AA-1 */
|
||||
FDC_82078_UNKN, /* Unknown 82078 variant */
|
||||
FDC_82078, /* 44pin 82078 or 64pin 82078SL */
|
||||
FDC_82078_1, /* 82078-1 (2Mbps fdc) */
|
||||
FDC_S82078B, /* S82078B (first seen on Adaptec AVA-2825 VLB SCSI/EIDE/Floppy controller) */
|
||||
FDC_87306 /* National Semiconductor PC 87306 */
|
||||
} FLOPPY_CONTROLLER_TYPE, *PFLOPPY_CONTROLLER_TYPE;
|
||||
|
||||
typedef struct _FLOPPY_ERROR_THRESHOLDS
|
||||
{
|
||||
/* number of errors to be reached before aborting */
|
||||
unsigned int Abort;
|
||||
/* maximal number of errors permitted to read an entire track at once */
|
||||
unsigned int ReadTrack;
|
||||
/* maximal number of errors before a reset is tried */
|
||||
unsigned int Reset;
|
||||
/* maximal number of errors before a recalibrate is tried */
|
||||
unsigned int Recal;
|
||||
/*
|
||||
* Threshold for reporting FDC errors to the console.
|
||||
* Setting this to zero may flood your screen when using
|
||||
* ultra cheap floppies ;-)
|
||||
*/
|
||||
unsigned int Reporting;
|
||||
} FLOPPY_ERROR_THRESHOLDS;
|
||||
|
||||
#define FDP_DEBUG 0x02
|
||||
#define FDP_SILENT_DCL_CLEAR 0x04
|
||||
#define FDP_MSG 0x10
|
||||
#define FDP_BROKEN_DCL 0x20
|
||||
#define FDP_INVERTED_DCL 0x80
|
||||
|
||||
typedef struct _FLOPPY_DEVICE_PARAMETERS
|
||||
{
|
||||
char CMOSType;
|
||||
unsigned long MaxDTR; /* Step rate, usec */
|
||||
unsigned long HLT; /* Head load/settle time, msec */
|
||||
unsigned long HUT; /* Head unload time (remnant of 8" drives) */
|
||||
unsigned long SRT; /* Step rate, usec */
|
||||
unsigned long Spinup; /* time needed for spinup */
|
||||
unsigned long Spindown; /* timeout needed for spindown */
|
||||
unsigned char SpindownOffset; /* decides in which position the disk will stop */
|
||||
unsigned char SelectDelay; /* delay to wait after select */
|
||||
unsigned char RPS; /* rotations per second */
|
||||
unsigned char Tracks; /* maximum number of tracks */
|
||||
unsigned long Timeout; /* timeout for interrupt requests */
|
||||
unsigned char InterleaveSect; /* if there are more sectors, use interleave */
|
||||
FLOPPY_ERROR_THRESHOLDS MaxErrors;
|
||||
char Flags; /* various flags, including ftd_msg */
|
||||
BOOLEAN ReadTrack; /* use readtrack during probing? */
|
||||
short Autodetect[8]; /* autodetected formats */
|
||||
int CheckFreq; /* how often should the drive be checked for disk changes */
|
||||
int NativeFormat; /* native format of this drive */
|
||||
char *DriveName; /* name of the drive for reporting */
|
||||
} FLOPPY_DEVICE_PARAMETERS, *PFLOPPY_DEVICE_PARAMETERS;
|
||||
|
||||
|
@@ -1,3 +0,0 @@
|
||||
base.tmp
|
||||
junk.tmp
|
||||
temp.exp
|
File diff suppressed because it is too large
Load Diff
@@ -1,232 +0,0 @@
|
||||
//
|
||||
// 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_POLL_RETRIES 100000
|
||||
#define IDE_MAX_WRITE_RETRIES 1000
|
||||
#define IDE_MAX_BUSY_RETRIES 100
|
||||
#define IDE_MAX_DRQ_RETRIES 10000
|
||||
#define IDE_MAX_CMD_RETRIES 1
|
||||
#define IDE_CMD_TIMEOUT 5
|
||||
#define IDE_RESET_BUSY_TIMEOUT 31
|
||||
#define IDE_RESET_DRDY_TIMEOUT 120
|
||||
|
||||
// Control Block offsets and masks
|
||||
#define IDE_REG_ALT_STATUS 0x0000
|
||||
#define IDE_REG_DEV_CNTRL 0x0000 /* 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 0x0001
|
||||
|
||||
// Command Block offsets and masks
|
||||
#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)))
|
||||
|
||||
//
|
||||
// Data block read and write commands
|
||||
//
|
||||
#define IDEReadBlock(Address, Buffer, Count) \
|
||||
(insw((Address) + IDE_REG_DATA_PORT, (Buffer), (Count) / 2))
|
||||
#define IDEWriteBlock(Address, Buffer, Count) \
|
||||
(outsw((Address) + IDE_REG_DATA_PORT, (Buffer), (Count) / 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,
|
||||
IDETimerCmdWait,
|
||||
IDETimerResetWaitForBusyNegate,
|
||||
IDETimerResetWaitForDrdyAssert
|
||||
} 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;
|
||||
int Retries;
|
||||
|
||||
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 Reserved48; /*48*/
|
||||
WORD Capabilities; /*49*/
|
||||
#define IDE_DRID_STBY_SUPPORTED 0x2000
|
||||
#define IDE_DRID_IORDY_SUPPORTED 0x0800
|
||||
#define IDE_DRID_IORDY_DISABLE 0x0400
|
||||
#define IDE_DRID_LBA_SUPPORTED 0x0200
|
||||
#define IDE_DRID_DMA_SUPPORTED 0x0100
|
||||
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 */
|
||||
|
||||
|
@@ -1,20 +0,0 @@
|
||||
|
||||
|
||||
#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)
|
||||
|
@@ -1,15 +0,0 @@
|
||||
all: ide.sys
|
||||
|
||||
OBJECTS = ide.o ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
ide.sys: $(OBJECTS)
|
||||
$(CC) -specs=../../svc_specs -mdll -o junk.tmp -Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ -Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp $(OBJECTS)
|
||||
- $(RM) junk.tmp
|
||||
$(DLLTOOL) --dllname ide.sys --base-file base.tmp \
|
||||
--output-exp temp.exp
|
||||
- $(RM) base.tmp
|
||||
$(CC) --verbose -Wl,--image-base,0x10000 -Wl,-e,_DriverEntry@8 \
|
||||
-specs=../../svc_specs -mdll -o ide.sys $(OBJECTS) -Wl,temp.exp
|
||||
- $(RM) temp.exp
|
@@ -1,93 +0,0 @@
|
||||
/**
|
||||
*** 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)
|
||||
|
||||
/* taken from linux fdisk src */
|
||||
typedef enum PartitionTypes {
|
||||
PTEmpty = 0,
|
||||
PTDOS3xPrimary, /* 1 */
|
||||
PTXENIXRoot, /* 2 */
|
||||
PTXENIXUsr, /* 3 */
|
||||
PTOLDDOS16Bit, /* 4 */
|
||||
PTDosExtended, /* 5 */
|
||||
PTDos5xPrimary, /* 6 */
|
||||
PTOS2HPFS, /* 7 */
|
||||
PTAIX, /* 8 */
|
||||
PTAIXBootable, /* 9 */
|
||||
PTOS2BootMgr, /* 10 */
|
||||
PTWin95FAT32,
|
||||
PTWin95FAT32LBA,
|
||||
PTWin95FAT16LBA,
|
||||
PTWin95ExtendedLBA,
|
||||
PTVenix286 = 0x40,
|
||||
PTNovell = 0x51,
|
||||
PTMicroport = 0x52,
|
||||
PTGnuHurd = 0x63,
|
||||
PTNetware286 = 0x64,
|
||||
PTNetware386 = 0x65,
|
||||
PTPCIX = 0x75,
|
||||
PTOldMinix = 0x80,
|
||||
PTMinix = 0x81,
|
||||
PTLinuxSwap = 0x82,
|
||||
PTLinuxExt2 = 0x83,
|
||||
PTAmoeba = 0x93,
|
||||
PTAmoebaBBT = 0x94,
|
||||
PTBSD = 0xa5,
|
||||
PTBSDIFS = 0xb7,
|
||||
PTBSDISwap = 0xb8,
|
||||
PTSyrinx = 0xc7,
|
||||
PTCPM = 0xdb,
|
||||
PTDOSAccess = 0xe1,
|
||||
PTDOSRO = 0xe3,
|
||||
PTDOSSecondary = 0xf2,
|
||||
PTBBT = 0xff
|
||||
} PARTITIONTYPES;
|
||||
|
||||
#define PartitionIsSupported(P) \
|
||||
((P)->PartitionType == PTDOS3xPrimary || \
|
||||
(P)->PartitionType == PTOLDDOS16Bit || \
|
||||
(P)->PartitionType == PTDos5xPrimary || \
|
||||
(P)->PartitionType == PTWin95FAT32 || \
|
||||
(P)->PartitionType == PTWin95FAT32LBA || \
|
||||
(P)->PartitionType == PTWin95FAT16LBA || \
|
||||
(P)->PartitionType == PTLinuxExt2)
|
||||
|
||||
#define PartitionIsExtended(P) \
|
||||
((P)->PartitionType == PTDosExtended)
|
||||
|
||||
typedef struct Partition {
|
||||
unsigned char BootFlags;
|
||||
unsigned char StartingHead;
|
||||
unsigned char StartingSector;
|
||||
unsigned char StartingCylinder;
|
||||
unsigned char PartitionType;
|
||||
unsigned char EndingHead;
|
||||
unsigned char EndingSector;
|
||||
unsigned char EndingCylinder;
|
||||
unsigned int StartingBlock;
|
||||
unsigned int SectorCount;
|
||||
|
||||
} PARTITION;
|
||||
|
||||
#endif // PARTITION_H
|
||||
|
||||
|
@@ -1,4 +0,0 @@
|
||||
base.tmp
|
||||
junk.tmp
|
||||
temp.exp
|
||||
|
@@ -1,722 +0,0 @@
|
||||
/*
|
||||
** 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
|
||||
**
|
||||
*/
|
||||
|
||||
#include <internal/mmhal.h>
|
||||
#include <internal/halio.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <string.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 '\n';
|
||||
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);
|
||||
|
||||
// DbgPrint("Key: %c\n",VirtualToAscii(ScanToVirtual(thisKey),isDown));
|
||||
// DbgPrint("Key: %x\n",ScanToVirtual(thisKey));
|
||||
if (ScanToVirtual(thisKey)==0x2a)
|
||||
{
|
||||
KeBugCheck(0);
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
STDCALL NTSTATUS
|
||||
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
ANSI_STRING adevice_name;
|
||||
UNICODE_STRING device_name;
|
||||
ANSI_STRING asymlink_name;
|
||||
UNICODE_STRING symlink_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;
|
||||
|
||||
RtlInitAnsiString(&asymlink_name,"\\??\\Keyboard");
|
||||
RtlAnsiStringToUnicodeString(&symlink_name,&asymlink_name,TRUE);
|
||||
IoCreateSymbolicLink(&symlink_name,&device_name);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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
|
@@ -1,15 +0,0 @@
|
||||
all: keyboard.sys
|
||||
|
||||
OBJECTS = keyboard.o ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
keyboard.sys: $(OBJECTS)
|
||||
$(CC) -specs=../../svc_specs -mdll -o junk.tmp -Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ -Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp $(OBJECTS)
|
||||
- $(RM) junk.tmp
|
||||
$(DLLTOOL) --dllname keyboard.sys --base-file base.tmp \
|
||||
--output-exp temp.exp
|
||||
- $(RM) base.tmp
|
||||
$(CC) --verbose -Wl,--image-base,0x10000 -Wl,-e,_DriverEntry@8 \
|
||||
-specs=../../svc_specs -mdll -o keyboard.sys $(OBJECTS) -Wl,temp.exp
|
||||
- $(RM) temp.exp
|
@@ -1 +0,0 @@
|
||||
all: mouse.o
|
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
|
||||
** 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/halio.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]='<EFBFBD>';
|
||||
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);
|
||||
};
|
||||
|
@@ -1 +0,0 @@
|
||||
all: null.o
|
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
@@ -1 +0,0 @@
|
||||
all: parallel.o
|
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
@@ -1,137 +0,0 @@
|
||||
#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
|
@@ -1,4 +0,0 @@
|
||||
all: sdisk.o
|
||||
|
||||
WIN32_LEAN_AND_MEAN = yes
|
||||
include ../../../rules.mak
|
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* 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/halio.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",
|
||||
GET_LARGE_INTEGER_LOW_PART(Stack->Parameters.Write.ByteOffset)+i);
|
||||
SdWriteOffset(GET_LARGE_INTEGER_LOW_PART(Stack->Parameters.Write.ByteOffset)+i);
|
||||
}
|
||||
outb_p(PORT,Buffer[i]);
|
||||
DbgPrint("%c",Buffer[i]);
|
||||
}
|
||||
#endif
|
||||
for (i=0;i<(Length/512);i++)
|
||||
{
|
||||
DPRINT("Offset %x\n",
|
||||
GET_LARGE_INTEGER_LOW_PART(Stack->Parameters.Write.ByteOffset)+i);
|
||||
SdWriteOffset(GET_LARGE_INTEGER_LOW_PART(Stack->Parameters.Write.ByteOffset)+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",
|
||||
GET_LARGE_INTEGER_LOW_PART(Stack->Parameters.Write.ByteOffset)+i);
|
||||
SdWriteOffset(GET_LARGE_INTEGER_LOW_PART(Stack->Parameters.Write.ByteOffset)+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);
|
||||
}
|
||||
|
@@ -1 +0,0 @@
|
||||
all: serial.o
|
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
|
||||
** Serial driver
|
||||
** Written by Jason Filby (jasonfilby@yahoo.com)
|
||||
** For ReactOS (www.sid-dis.com/reactos)
|
||||
|
||||
*/
|
||||
|
||||
#include <internal/mmhal.h>
|
||||
#include <internal/halio.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);
|
||||
};
|
||||
|
@@ -1,61 +0,0 @@
|
||||
/************************************
|
||||
* 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);
|
||||
}
|
||||
|
@@ -1,17 +0,0 @@
|
||||
#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);
|
@@ -1,2 +0,0 @@
|
||||
sound.o: sound.c dsp.c mixer.c wave.h wave.c
|
||||
all: sound.o
|
@@ -1,32 +0,0 @@
|
||||
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;
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
#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);
|
||||
|
@@ -1,9 +0,0 @@
|
||||
typedef struct
|
||||
{
|
||||
unsigned short base;
|
||||
unsigned char irq;
|
||||
unsigned char dma8;
|
||||
unsigned char dma16;
|
||||
unsigned char* buffer;
|
||||
}SB16;
|
||||
|
@@ -1,3 +0,0 @@
|
||||
void write_wave()
|
||||
{
|
||||
}
|
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* 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/halio.h>
|
||||
#include <ddk/ntddk.h>
|
||||
#include <internal/hal/ddk.h>
|
||||
#include <internal/dma.h>
|
||||
#include <internal/mm.h>
|
||||
#include <string.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"
|
@@ -1,126 +0,0 @@
|
||||
ULONG OldIRQ;
|
||||
PKINTERRUPT IrqObject;
|
||||
BOOLEAN DMAOutputISR(PKINTERRUPT Interrupt, PVOID ServiceContext)
|
||||
{
|
||||
printk("interrupt\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void sb16_play(WAVE_HDR* wave)
|
||||
{
|
||||
unsigned int eflags;
|
||||
ULONG MappedIrq;
|
||||
KIRQL Dirql;
|
||||
KAFFINITY Affinity;
|
||||
PKINTERRUPT IrqObject;
|
||||
unsigned int mask,newmask;
|
||||
|
||||
unsigned int i;
|
||||
unsigned int tmp[255];
|
||||
i=0;
|
||||
dump_wav(wave);
|
||||
do
|
||||
{
|
||||
tmp[i++]=get_dma_page(0x0fffff+IDMAP_BASE);
|
||||
printk("0x%x ",tmp[i-1]);
|
||||
}
|
||||
while((tmp[i-1]&0xffff)!=0);
|
||||
free_page((tmp[0])-IDMAP_BASE,i-1);
|
||||
sb16.buffer=((unsigned char*)tmp[i-1]);
|
||||
|
||||
/*
|
||||
* Because this is used by alomost every subsystem including irqs it
|
||||
* must be atomic. The following code sequence disables interrupts after
|
||||
* saving the previous state of the interrupt flag
|
||||
*/
|
||||
|
||||
__asm__("pushf\n\tpop %0\n\tcli\n\t"
|
||||
: "=m" (eflags)
|
||||
: );
|
||||
|
||||
memcpy(sb16.buffer,(&wave->data),wave->dLen);
|
||||
|
||||
|
||||
MappedIrq = HalGetInterruptVector(Internal,0,0,8+sb16.irq,&Dirql,&Affinity);
|
||||
|
||||
|
||||
|
||||
IoConnectInterrupt(&IrqObject,DMAOutputISR,0,NULL,MappedIrq,Dirql,Dirql,0,FALSE,Affinity,FALSE);
|
||||
|
||||
mask=inb(0x21);
|
||||
newmask=((int)1<<sb16.irq);
|
||||
outb(0x21,(mask&~newmask));
|
||||
|
||||
// Restore the interrupt flag
|
||||
__asm__("push %0\n\tpopf\n\t"
|
||||
:
|
||||
: "m" (eflags));
|
||||
|
||||
|
||||
|
||||
disable_dma(sb16.dma8);
|
||||
//outb(0x0a,5);
|
||||
clear_dma_ff(1);
|
||||
//outb(0xc,0);
|
||||
set_dma_count(1,wave->dLen);
|
||||
set_dma_mode(1,DMA_MODE_WRITE);
|
||||
//outb(0xb,0x49);
|
||||
//outb(0x3,(wave->dLen)&0xff);
|
||||
//outb(0x3,((unsigned int)(wave->dLen)>>8)&0xff);
|
||||
set_dma_addr(sb16.dma8,(unsigned int)sb16.buffer-IDMAP_BASE);
|
||||
//outb(0x83,(((unsigned int)(sb16.buffer-IDMAP_BASE)>>16))&0xf);
|
||||
//outb(0x2,((unsigned int)sb16.buffer&0xff));
|
||||
//outb(0x2,(((unsigned int)(sb16.buffer-IDMAP_BASE)>>8))&0xff);
|
||||
enable_dma(sb16.dma8);
|
||||
//outb(0xa,1);
|
||||
|
||||
write_dsp(sb16.base,0x00D1);
|
||||
|
||||
write_dsp(sb16.base,0x40);
|
||||
write_dsp(sb16.base,((unsigned char)256-(1000000/wave->nSamplesPerSec)));
|
||||
|
||||
outb(sb16.base + 4, (int) 0xa);
|
||||
outb(sb16.base + 5, (int) 0x00);
|
||||
|
||||
outb(sb16.base + 4, (int) 4);
|
||||
outb(sb16.base + 5, (int) 0xFF);
|
||||
|
||||
outb(sb16.base + 4, (int) 0x22);
|
||||
outb(sb16.base + 5, (int) 0xFF);
|
||||
|
||||
write_dsp(sb16.base,0x14);
|
||||
write_dsp(sb16.base,(wave->dLen&0x00ff));
|
||||
write_dsp(sb16.base,((wave->dLen)&0xff00)>>8);
|
||||
|
||||
// write_dsp(sb16.base,0xc0);
|
||||
// write_dsp(sb16.base,0x0);
|
||||
// OldIRQ=HalGetInterruptVector(Internal,0,0,irq+8,&irql,&affinity);
|
||||
// printk("OldIRQ: 0x%x\n",OldIRQ);
|
||||
|
||||
// status=IoConnectInterrupt(&IrqObject,playRoutine,0,NULL,OldIRQ,irql,irql,0,FALSE,affinity,FALSE);
|
||||
// if(status!=STATUS_SUCCESS) printk("Couldn't set irq\n");
|
||||
// else printk("IRQ set\n");
|
||||
|
||||
}
|
||||
|
||||
void dump_wav(WAVE_HDR* wave)
|
||||
{
|
||||
printk("wave.rID: %c%c%c%c\n",wave->rID[0],wave->rID[1],wave->rID[2],wave->rID[3]);
|
||||
printk("wave.rLen: 0x%x\n",wave->rLen);
|
||||
printk("wave.wID: %c%c%c%c\n",wave->wID[0],wave->wID[1],wave->wID[2],wave->wID[3]);
|
||||
printk("wave.fID: %c%c%c%c\n",wave->fID[0],wave->fID[1],wave->fID[2],wave->fID[3]);
|
||||
printk("wave.fLen: 0x%x\n",wave->fLen);
|
||||
printk("wave.wFormatTag: 0x%x\n",wave->wFormatTag);
|
||||
printk("wave.nChannels: 0x%x\n",wave->nChannels);
|
||||
printk("wave.nSamplesPerSec: 0x%x\n",wave->nSamplesPerSec);
|
||||
printk("wave.nAvgBytesPerSec: 0x%x\n",wave->nAvgBytesPerSec);
|
||||
printk("wave.nBlockAlign: 0x%x\n",wave->nBlockAlign);
|
||||
printk("wave.FormatSpecific: 0x%x\n",wave->FormatSpecific);
|
||||
printk("wave.dID: %c%c%c%c\n",wave->dID[0],wave->dID[1],wave->dID[2],wave->dID[3]);
|
||||
printk("wave.dLen: 0x%x\n",wave->dLen);
|
||||
}
|
||||
|
||||
BOOLEAN playRoutine(PKINTERRUPT Interrupt,PVOID ServiceContext)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
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);
|
@@ -1,4 +0,0 @@
|
||||
base.tmp
|
||||
junk.tmp
|
||||
temp.exp
|
||||
|
@@ -1,16 +0,0 @@
|
||||
all: test.sys
|
||||
|
||||
OBJECTS = test.o ../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
# --def test.def --def test.def
|
||||
test.sys: test.o
|
||||
$(DLLTOOL) --dllname test.sys --output-lib test.a
|
||||
$(CC) -specs=$(KM_SPECS) -mdll -o junk.tmp -Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ -Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp $(OBJECTS)
|
||||
- $(RM) junk.tmp
|
||||
$(DLLTOOL) --dllname test.sys --base-file base.tmp \
|
||||
--output-exp temp.exp
|
||||
- $(RM) base.tmp
|
||||
$(CC) --verbose -Wl,--image-base,0x10000 -Wl,-e,_DriverEntry -specs=$(KM_SPECS) -mdll -o test.sys $(OBJECTS) -Wl,temp.exp
|
||||
- $(RM) temp.exp
|
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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 **************************************************************/
|
||||
|
||||
#if 0
|
||||
|
||||
NTSTATUS TestWrite(PIRP Irp, PIO_STACK_LOCATION Stk)
|
||||
{
|
||||
PVOID Address;
|
||||
|
||||
Address = MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||
DbgPrint("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:
|
||||
DbgPrint("(Test Driver) Creating\n");
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLOSE:
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
DbgPrint("(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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
DbgPrint("Test Driver 0.0.1\n");
|
||||
|
||||
#if 0
|
||||
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;
|
||||
#endif
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#include <internal/string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
BOOLEAN Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
|
||||
IN ULONG DiskSector,
|
||||
IN ULONG SectorCount,
|
||||
IN PVOID Buffer)
|
||||
{
|
||||
LARGE_INTEGER sectorNumber;
|
||||
PIRP irp;
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
KEVENT event;
|
||||
NTSTATUS status;
|
||||
ULONG sectorSize;
|
||||
int j;
|
||||
|
||||
DPRINT("VFATReadSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||
pDeviceObject,DiskSector,Buffer);
|
||||
|
||||
SET_LARGE_INTEGER_HIGH_PART(sectorNumber, 0);
|
||||
SET_LARGE_INTEGER_LOW_PART(sectorNumber, DiskSector * BLOCKSIZE);
|
||||
|
||||
DPRINT("DiskSector:%ld BLKSZ:%ld sectorNumber:%ld:%ld\n",
|
||||
(unsigned long) DiskSector,
|
||||
(unsigned long) BLOCKSIZE,
|
||||
(unsigned long) GET_LARGE_INTEGER_HIGH_PART(sectorNumber),
|
||||
(unsigned long) GET_LARGE_INTEGER_LOW_PART(sectorNumber));
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
sectorSize = BLOCKSIZE*SectorCount;
|
||||
|
||||
|
||||
DPRINT("Building synchronous FSD Request...\n");
|
||||
irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
|
||||
pDeviceObject,
|
||||
Buffer,
|
||||
sectorSize,
|
||||
§orNumber,
|
||||
&event,
|
||||
&ioStatus );
|
||||
|
||||
if (!irp) {
|
||||
DbgPrint("READ failed!!!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("Calling IO Driver...\n");
|
||||
status = IoCallDriver(pDeviceObject,
|
||||
irp);
|
||||
|
||||
DPRINT("Waiting for IO Operation...\n");
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
DPRINT("Getting IO Status...\n");
|
||||
status = ioStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN VFATWriteSectors(IN PDEVICE_OBJECT pDeviceObject,
|
||||
IN ULONG DiskSector,
|
||||
IN ULONG SectorCount,
|
||||
IN UCHAR* Buffer)
|
||||
{
|
||||
LARGE_INTEGER sectorNumber;
|
||||
PIRP irp;
|
||||
IO_STATUS_BLOCK ioStatus;
|
||||
KEVENT event;
|
||||
NTSTATUS status;
|
||||
ULONG sectorSize;
|
||||
PULONG mbr;
|
||||
int j;
|
||||
|
||||
DPRINT("VFATWriteSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||
pDeviceObject,DiskSector,Buffer);
|
||||
|
||||
SET_LARGE_INTEGER_HIGH_PART(sectorNumber, 0);
|
||||
SET_LARGE_INTEGER_LOW_PART(sectorNumber, DiskSector * BLOCKSIZE);
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
sectorSize = BLOCKSIZE*SectorCount;
|
||||
|
||||
|
||||
DPRINT("Building synchronous FSD Request...\n");
|
||||
irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
|
||||
pDeviceObject,
|
||||
Buffer,
|
||||
sectorSize,
|
||||
§orNumber,
|
||||
&event,
|
||||
&ioStatus );
|
||||
|
||||
if (!irp) {
|
||||
DbgPrint("WRITE failed!!!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DPRINT("Calling IO Driver...\n");
|
||||
status = IoCallDriver(pDeviceObject,
|
||||
irp);
|
||||
|
||||
DPRINT("Waiting for IO Operation...\n");
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
DPRINT("Getting IO Status...\n");
|
||||
status = ioStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DbgPrint("IO failed!!! Error code: %d(%x)\n", status, status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
ExFreePool(mbr);
|
||||
DPRINT("Block request succeeded\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@@ -1,326 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/dir.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <wchar.h>
|
||||
#include <internal/string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID Ext2ConvertName(PWSTR Out, PCH In, ULONG Len)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i=0; i<Len; i++)
|
||||
{
|
||||
*Out = *In;
|
||||
Out++;
|
||||
In++;
|
||||
}
|
||||
*Out = 0;
|
||||
}
|
||||
|
||||
PVOID Ext2ProcessDirEntry(PDEVICE_EXTENSION DeviceExt,
|
||||
struct ext2_dir_entry* dir_entry,
|
||||
PIO_STACK_LOCATION IoStack,
|
||||
PVOID Buffer,
|
||||
ULONG FileIndex)
|
||||
{
|
||||
PFILE_DIRECTORY_INFORMATION FDI;
|
||||
PFILE_NAMES_INFORMATION FNI;
|
||||
PFILE_BOTH_DIRECTORY_INFORMATION FBI;
|
||||
ULONG i;
|
||||
PWSTR FileName;
|
||||
struct ext2_inode inode;
|
||||
|
||||
DPRINT("FileIndex %d\n",FileIndex);
|
||||
DPRINT("Buffer %x\n",Buffer);
|
||||
|
||||
Ext2ReadInode(DeviceExt,
|
||||
dir_entry->inode,
|
||||
&inode);
|
||||
|
||||
switch (IoStack->Parameters.QueryDirectory.FileInformationClass)
|
||||
{
|
||||
case FileNamesInformation:
|
||||
FNI = (PFILE_NAMES_INFORMATION)Buffer;
|
||||
FNI->NextEntryOffset = sizeof(FileDirectoryInformation) +
|
||||
dir_entry->name_len + 1;
|
||||
FNI->FileNameLength = dir_entry->name_len;
|
||||
Ext2ConvertName(FNI->FileName, dir_entry->name, dir_entry->name_len);
|
||||
Buffer = Buffer + FNI->NextEntryOffset;
|
||||
break;
|
||||
|
||||
case FileDirectoryInformation:
|
||||
FDI = (PFILE_DIRECTORY_INFORMATION)Buffer;
|
||||
FDI->NextEntryOffset = sizeof(FileDirectoryInformation) +
|
||||
dir_entry->name_len + 1;
|
||||
FDI->FileIndex = FileIndex;
|
||||
// FDI->CreationTime = 0;
|
||||
// FDI->LastAccessTime = 0;
|
||||
// FDI->LastWriteTime = 0;
|
||||
// FDI->ChangeTime = 0;
|
||||
FDI->AllocationSize = FDI->EndOfFile = inode.i_size;
|
||||
FDI->FileAttributes = 0;
|
||||
FDI->FileNameLength = dir_entry->name_len;
|
||||
Ext2ConvertName(FDI->FileName, dir_entry->name, dir_entry->name_len);
|
||||
Buffer = Buffer + FDI->NextEntryOffset;
|
||||
break;
|
||||
|
||||
case FileBothDirectoryInformation:
|
||||
FBI = (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer;
|
||||
FBI->NextEntryOffset = sizeof(FileBothDirectoryInformation) +
|
||||
dir_entry->name_len + 1;
|
||||
FBI->FileIndex = FileIndex;
|
||||
FBI->AllocationSize = FBI->EndOfFile = inode.i_size;
|
||||
FBI->FileAttributes = 0;
|
||||
FBI->FileNameLength = dir_entry->name_len;
|
||||
Ext2ConvertName(FBI->FileName, dir_entry->name, dir_entry->name_len);
|
||||
memset(FBI->ShortName, 0, sizeof(FBI->ShortName));
|
||||
Buffer = Buffer + FBI->NextEntryOffset;
|
||||
break;
|
||||
|
||||
default:
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
return(Buffer);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS Ext2QueryDirectory(PDEVICE_EXTENSION DeviceExt,
|
||||
PEXT2_FCB Fcb,
|
||||
PIRP Irp,
|
||||
PIO_STACK_LOCATION IoStack)
|
||||
{
|
||||
ULONG Max;
|
||||
ULONG i;
|
||||
ULONG StartIndex;
|
||||
PVOID Buffer;
|
||||
struct ext2_dir_entry dir_entry;
|
||||
ULONG CurrentIndex;
|
||||
|
||||
DPRINT("Buffer %x\n",Buffer);
|
||||
|
||||
Buffer = Irp->UserBuffer;
|
||||
DPRINT("IoStack->Flags %x\n",IoStack->Flags);
|
||||
|
||||
if (IoStack->Flags & SL_RETURN_SINGLE_ENTRY)
|
||||
{
|
||||
Max = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
DPRINT("Buffer->FileIndex %d\n",
|
||||
((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex);
|
||||
if (IoStack->Flags & SL_INDEX_SPECIFIED)
|
||||
{
|
||||
StartIndex = ((PFILE_DIRECTORY_INFORMATION)Buffer)->FileIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
StartIndex = 0;
|
||||
}
|
||||
|
||||
if (IoStack->Flags & SL_RESTART_SCAN)
|
||||
{
|
||||
StartIndex = 0;
|
||||
}
|
||||
|
||||
DPRINT("StartIndex %d\n",StartIndex);
|
||||
|
||||
for (i=0; i<Max ;i++)
|
||||
{
|
||||
if (!Ext2ScanDir(DeviceExt,&Fcb->inode,"*",&dir_entry,&StartIndex))
|
||||
{
|
||||
((PFILE_DIRECTORY_INFORMATION)Buffer)->NextEntryOffset = 0;
|
||||
return(STATUS_NO_MORE_FILES);
|
||||
}
|
||||
Buffer = Ext2ProcessDirEntry(DeviceExt,
|
||||
&dir_entry,
|
||||
IoStack,
|
||||
Buffer,
|
||||
StartIndex);
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = Stack->FileObject;
|
||||
PEXT2_FCB Fcb = (PVOID)FileObject->FsContext;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
|
||||
DPRINT("Ext2DirectoryControl(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
|
||||
|
||||
DeviceExt = DeviceObject->DeviceExtension;
|
||||
|
||||
switch (Stack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_QUERY_DIRECTORY:
|
||||
Status = Ext2QueryDirectory(DeviceExt, Fcb, Irp, Stack);
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
BOOL Ext2ScanDir(PDEVICE_EXTENSION DeviceExt,
|
||||
struct ext2_inode* dir,
|
||||
PCH filename,
|
||||
struct ext2_dir_entry* ret,
|
||||
PULONG StartIndex)
|
||||
{
|
||||
ULONG i;
|
||||
char* buffer;
|
||||
ULONG offset;
|
||||
char name[255];
|
||||
struct ext2_dir_entry* current;
|
||||
ULONG block;
|
||||
|
||||
DPRINT("Ext2ScanDir(dir %x, filename %s, ret %x)\n",dir,filename,ret);
|
||||
|
||||
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
|
||||
for (i=0; i<((*StartIndex)/BLOCKSIZE); i++);
|
||||
for (; (block = Ext2BlockMap(DeviceExt, dir, i)) != 0; i++)
|
||||
{
|
||||
DPRINT("block %d\n",block);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
buffer);
|
||||
|
||||
offset = (*StartIndex)%BLOCKSIZE;
|
||||
while (offset < BLOCKSIZE)
|
||||
{
|
||||
current = &buffer[offset];
|
||||
|
||||
strncpy(name,current->name,current->name_len);
|
||||
name[current->name_len]=0;
|
||||
|
||||
DPRINT("Scanning offset %d inode %d name %s\n",
|
||||
offset,current->inode,name);
|
||||
|
||||
DPRINT("Comparing %s %s\n",name,filename);
|
||||
if (strcmp(name,filename)==0 || strcmp(filename,"*")==0)
|
||||
{
|
||||
DPRINT("Match found\n");
|
||||
*StartIndex = (i*BLOCKSIZE) + offset + current->rec_len;
|
||||
memcpy(ret,current,sizeof(struct ext2_dir_entry));
|
||||
ExFreePool(buffer);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
offset = offset + current->rec_len;
|
||||
assert(current->rec_len != 0);
|
||||
DPRINT("offset %d\n",offset);
|
||||
}
|
||||
DPRINT("Onto next block\n");
|
||||
}
|
||||
DPRINT("No match\n");
|
||||
ExFreePool(buffer);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
void unicode_to_ansi(PCH StringA, PWSTR StringW)
|
||||
{
|
||||
while((*StringW)!=0)
|
||||
{
|
||||
*StringA = *StringW;
|
||||
StringA++;
|
||||
StringW++;
|
||||
}
|
||||
*StringA = 0;
|
||||
}
|
||||
|
||||
NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||
PWSTR FileName)
|
||||
/*
|
||||
* FUNCTION: Opens a file
|
||||
*/
|
||||
{
|
||||
struct ext2_inode parent_inode;
|
||||
struct ext2_dir_entry entry;
|
||||
char name[255];
|
||||
ULONG current_inode = 2;
|
||||
char* current_segment;
|
||||
PEXT2_FCB Fcb;
|
||||
ULONG StartIndex = 0;
|
||||
|
||||
DPRINT("Ext2OpenFile(DeviceExt %x, FileObject %x, FileName %w)\n",
|
||||
DeviceExt,FileObject,FileName);
|
||||
|
||||
Fcb = ExAllocatePool(NonPagedPool, sizeof(EXT2_FCB));
|
||||
|
||||
unicode_to_ansi(name,FileName);
|
||||
DPRINT("name %s\n",name);
|
||||
|
||||
current_segment = strtok(name,"\\");
|
||||
while (current_segment!=NULL)
|
||||
{
|
||||
Ext2ReadInode(DeviceExt,
|
||||
current_inode,
|
||||
&parent_inode);
|
||||
if (!Ext2ScanDir(DeviceExt,&parent_inode,current_segment,&entry,
|
||||
&StartIndex))
|
||||
{
|
||||
ExFreePool(Fcb);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
current_inode = entry.inode;
|
||||
current_segment = strtok(NULL,"\\");
|
||||
StartIndex = 0;
|
||||
}
|
||||
DPRINT("Found file\n");
|
||||
|
||||
Ext2ReadInode(DeviceExt,
|
||||
current_inode,
|
||||
&Fcb->inode);
|
||||
FileObject->FsContext = Fcb;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = Stack->FileObject;
|
||||
NTSTATUS Status;
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
|
||||
DPRINT("Ext2Create(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
|
||||
|
||||
DeviceExt = DeviceObject->DeviceExtension;
|
||||
Status = Ext2OpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(Status);
|
||||
}
|
@@ -1,242 +0,0 @@
|
||||
BOOLEAN Ext2ReadSectors(IN PDEVICE_OBJECT pDeviceObject,
|
||||
IN ULONG DiskSector,
|
||||
IN ULONG SectorCount,
|
||||
IN PVOID Buffer);
|
||||
|
||||
#define BLOCKSIZE (1024)
|
||||
|
||||
struct ext2_super_block {
|
||||
ULONG s_inodes_count; /* Inodes count */
|
||||
ULONG s_blocks_count; /* Blocks count */
|
||||
ULONG s_r_blocks_count; /* Reserved blocks count */
|
||||
ULONG s_free_blocks_count; /* Free blocks count */
|
||||
ULONG s_free_inodes_count; /* Free inodes count */
|
||||
ULONG s_first_data_block; /* First Data Block */
|
||||
ULONG s_log_block_size; /* Block size */
|
||||
LONG s_log_frag_size; /* Fragment size */
|
||||
ULONG s_blocks_per_group; /* # Blocks per group */
|
||||
ULONG s_frags_per_group; /* # Fragments per group */
|
||||
ULONG s_inodes_per_group; /* # Inodes per group */
|
||||
ULONG s_mtime; /* Mount time */
|
||||
ULONG s_wtime; /* Write time */
|
||||
USHORT s_mnt_count; /* Mount count */
|
||||
SHORT s_max_mnt_count; /* Maximal mount count */
|
||||
USHORT s_magic; /* Magic signature */
|
||||
USHORT s_state; /* File system state */
|
||||
USHORT s_errors; /* Behaviour when detecting errors */
|
||||
USHORT s_minor_rev_level; /* minor revision level */
|
||||
ULONG s_lastcheck; /* time of last check */
|
||||
ULONG s_checkinterval; /* max. time between checks */
|
||||
ULONG s_creator_os; /* OS */
|
||||
ULONG s_rev_level; /* Revision level */
|
||||
USHORT s_def_resuid; /* Default uid for reserved blocks */
|
||||
USHORT s_def_resgid; /* Default gid for reserved blocks */
|
||||
/*
|
||||
* These fields are for EXT2_DYNAMIC_REV superblocks only.
|
||||
*
|
||||
* Note: the difference between the compatible feature set and
|
||||
* the incompatible feature set is that if there is a bit set
|
||||
* in the incompatible feature set that the kernel doesn't
|
||||
* know about, it should refuse to mount the filesystem.
|
||||
*
|
||||
* e2fsck's requirements are more strict; if it doesn't know
|
||||
* about a feature in either the compatible or incompatible
|
||||
* feature set, it must abort and not try to meddle with
|
||||
* things it doesn't understand...
|
||||
*/
|
||||
ULONG s_first_ino; /* First non-reserved inode */
|
||||
USHORT s_inode_size; /* size of inode structure */
|
||||
USHORT s_block_group_nr; /* block group # of this superblock */
|
||||
ULONG s_feature_compat; /* compatible feature set */
|
||||
ULONG s_feature_incompat; /* incompatible feature set */
|
||||
ULONG s_feature_ro_compat; /* readonly-compatible feature set */
|
||||
ULONG s_reserved[230]; /* Padding to the end of the block */
|
||||
};
|
||||
|
||||
/*
|
||||
* Codes for operating systems
|
||||
*/
|
||||
#define EXT2_OS_LINUX 0
|
||||
#define EXT2_OS_HURD 1
|
||||
#define EXT2_OS_MASIX 2
|
||||
#define EXT2_OS_FREEBSD 3
|
||||
#define EXT2_OS_LITES 4
|
||||
|
||||
/*
|
||||
* Revision levels
|
||||
*/
|
||||
#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */
|
||||
#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */
|
||||
|
||||
#define EXT2_CURRENT_REV EXT2_GOOD_OLD_REV
|
||||
#define EXT2_MAX_SUPP_REV EXT2_DYNAMIC_REV
|
||||
|
||||
/*
|
||||
* The second extended file system magic number
|
||||
*/
|
||||
#define EXT2_SUPER_MAGIC 0xEF53
|
||||
|
||||
/*
|
||||
* Constants relative to the data blocks
|
||||
*/
|
||||
#define EXT2_NDIR_BLOCKS 12
|
||||
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
|
||||
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
|
||||
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
|
||||
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
|
||||
|
||||
|
||||
/*
|
||||
* Structure of an inode on the disk
|
||||
*/
|
||||
struct ext2_inode {
|
||||
USHORT i_mode; /* File mode */
|
||||
USHORT i_uid; /* Owner Uid */
|
||||
ULONG i_size; /* Size in bytes */
|
||||
ULONG i_atime; /* Access time */
|
||||
ULONG i_ctime; /* Creation time */
|
||||
ULONG i_mtime; /* Modification time */
|
||||
ULONG i_dtime; /* Deletion Time */
|
||||
USHORT i_gid; /* Group Id */
|
||||
USHORT i_links_count; /* Links count */
|
||||
ULONG i_blocks; /* Blocks count */
|
||||
ULONG i_flags; /* File flags */
|
||||
union {
|
||||
struct {
|
||||
ULONG l_i_reserved1;
|
||||
} linux1;
|
||||
struct {
|
||||
ULONG h_i_translator;
|
||||
} hurd1;
|
||||
struct {
|
||||
ULONG m_i_reserved1;
|
||||
} masix1;
|
||||
} osd1; /* OS dependent 1 */
|
||||
ULONG i_block[EXT2_N_BLOCKS];/* Pointers to blocks */
|
||||
ULONG i_version; /* File version (for NFS) */
|
||||
ULONG i_file_acl; /* File ACL */
|
||||
ULONG i_dir_acl; /* Directory ACL */
|
||||
ULONG i_faddr; /* Fragment address */
|
||||
union {
|
||||
struct {
|
||||
UCHAR l_i_frag; /* Fragment number */
|
||||
UCHAR l_i_fsize; /* Fragment size */
|
||||
USHORT i_pad1;
|
||||
ULONG l_i_reserved2[2];
|
||||
} linux2;
|
||||
struct {
|
||||
UCHAR h_i_frag; /* Fragment number */
|
||||
UCHAR h_i_fsize; /* Fragment size */
|
||||
USHORT h_i_mode_high;
|
||||
USHORT h_i_uid_high;
|
||||
USHORT h_i_gid_high;
|
||||
ULONG h_i_author;
|
||||
} hurd2;
|
||||
struct {
|
||||
UCHAR m_i_frag; /* Fragment number */
|
||||
UCHAR m_i_fsize; /* Fragment size */
|
||||
USHORT m_pad1;
|
||||
ULONG m_i_reserved2[2];
|
||||
} masix2;
|
||||
} osd2; /* OS dependent 2 */
|
||||
};
|
||||
|
||||
#if defined(__KERNEL__) || defined(__linux__)
|
||||
#define i_reserved1 osd1.linux1.l_i_reserved1
|
||||
#define i_frag osd2.linux2.l_i_frag
|
||||
#define i_fsize osd2.linux2.l_i_fsize
|
||||
#define i_reserved2 osd2.linux2.l_i_reserved2
|
||||
#endif
|
||||
|
||||
#ifdef __hurd__
|
||||
#define i_translator osd1.hurd1.h_i_translator
|
||||
#define i_frag osd2.hurd2.h_i_frag;
|
||||
#define i_fsize osd2.hurd2.h_i_fsize;
|
||||
#define i_uid_high osd2.hurd2.h_i_uid_high
|
||||
#define i_gid_high osd2.hurd2.h_i_gid_high
|
||||
#define i_author osd2.hurd2.h_i_author
|
||||
#endif
|
||||
|
||||
#ifdef __masix__
|
||||
#define i_reserved1 osd1.masix1.m_i_reserved1
|
||||
#define i_frag osd2.masix2.m_i_frag
|
||||
#define i_fsize osd2.masix2.m_i_fsize
|
||||
#define i_reserved2 osd2.masix2.m_i_reserved2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Constants relative to the data blocks
|
||||
*/
|
||||
#define EXT2_NDIR_BLOCKS 12
|
||||
#define EXT2_IND_BLOCK EXT2_NDIR_BLOCKS
|
||||
#define EXT2_DIND_BLOCK (EXT2_IND_BLOCK + 1)
|
||||
#define EXT2_TIND_BLOCK (EXT2_DIND_BLOCK + 1)
|
||||
#define EXT2_N_BLOCKS (EXT2_TIND_BLOCK + 1)
|
||||
|
||||
/*
|
||||
* Inode flags
|
||||
*/
|
||||
#define EXT2_SECRM_FL 0x00000001 /* Secure deletion */
|
||||
#define EXT2_UNRM_FL 0x00000002 /* Undelete */
|
||||
#define EXT2_COMPR_FL 0x00000004 /* Compress file */
|
||||
#define EXT2_SYNC_FL 0x00000008 /* Synchronous updates */
|
||||
#define EXT2_IMMUTABLE_FL 0x00000010 /* Immutable file */
|
||||
#define EXT2_APPEND_FL 0x00000020 /* writes to file may only append */
|
||||
#define EXT2_NODUMP_FL 0x00000040 /* do not dump file */
|
||||
#define EXT2_RESERVED_FL 0x80000000 /* reserved for ext2 lib */
|
||||
|
||||
|
||||
/*
|
||||
* Structure of a blocks group descriptor
|
||||
*/
|
||||
struct ext2_group_desc
|
||||
{
|
||||
ULONG bg_block_bitmap; /* Blocks bitmap block */
|
||||
ULONG bg_inode_bitmap; /* Inodes bitmap block */
|
||||
ULONG bg_inode_table; /* Inodes table block */
|
||||
USHORT bg_free_blocks_count; /* Free blocks count */
|
||||
USHORT bg_free_inodes_count; /* Free inodes count */
|
||||
USHORT bg_used_dirs_count; /* Directories count */
|
||||
USHORT bg_pad;
|
||||
ULONG bg_reserved[3];
|
||||
};
|
||||
|
||||
#define EXT2_NAME_LEN 255
|
||||
|
||||
struct ext2_dir_entry {
|
||||
ULONG inode; /* Inode number */
|
||||
USHORT rec_len; /* Directory entry length */
|
||||
USHORT name_len; /* Name length */
|
||||
char name[EXT2_NAME_LEN]; /* File name */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PDEVICE_OBJECT StorageDevice;
|
||||
struct ext2_super_block* superblock;
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
||||
|
||||
VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG ino,
|
||||
struct ext2_inode* inode);
|
||||
struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG block_group);
|
||||
|
||||
typedef struct _EXT2_FCB
|
||||
{
|
||||
struct ext2_inode inode;
|
||||
} EXT2_FCB, *PEXT2_FCB;
|
||||
|
||||
ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt,
|
||||
struct ext2_inode* inode,
|
||||
ULONG offset);
|
||||
NTSTATUS Ext2OpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
|
||||
PWSTR FileName);
|
||||
NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT FileObject,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
LARGE_INTEGER Offset);
|
||||
NTSTATUS Ext2Create(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
NTSTATUS Ext2DirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/super.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
#define addr_per_block (BLOCKSIZE / sizeof(ULONG))
|
||||
|
||||
ULONG Ext2BlockMap(PDEVICE_EXTENSION DeviceExt,
|
||||
struct ext2_inode* inode,
|
||||
ULONG offset)
|
||||
{
|
||||
ULONG block;
|
||||
PULONG TempBuffer;
|
||||
|
||||
DPRINT("Ext2BlockMap(DeviceExt %x, inode %x, offset %d)\n",
|
||||
DeviceExt,inode,offset);
|
||||
if (offset < EXT2_NDIR_BLOCKS)
|
||||
{
|
||||
block = inode->i_block[offset];
|
||||
DPRINT("block %d\n",block);
|
||||
return(block);
|
||||
}
|
||||
offset = offset - EXT2_NDIR_BLOCKS;
|
||||
if (offset < addr_per_block)
|
||||
{
|
||||
block = inode->i_block[EXT2_IND_BLOCK];
|
||||
TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
TempBuffer);
|
||||
block = TempBuffer[offset];
|
||||
ExFreePool(TempBuffer);
|
||||
return(block);
|
||||
}
|
||||
DbgPrint("Failed at %s:%d\n",__FILE__,__LINE__);
|
||||
for(;;);
|
||||
}
|
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/inode.c
|
||||
* PURPOSE: Manipulating inodes
|
||||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* UPDATE HISTORY:
|
||||
* 26/12/98: Created
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
struct ext2_group_desc* Ext2LoadGroupDesc(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG block_group)
|
||||
{
|
||||
struct ext2_group_desc* buffer;
|
||||
ULONG block;
|
||||
struct ext2_group_desc* gdp;
|
||||
|
||||
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
|
||||
block = block_group / (BLOCKSIZE / sizeof(struct ext2_group_desc));
|
||||
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
2 + block,
|
||||
1,
|
||||
buffer);
|
||||
|
||||
gdp = &buffer[block_group % (BLOCKSIZE / sizeof(struct ext2_group_desc))];
|
||||
|
||||
DPRINT("gdp->bg_free_blocks_count %d\n",gdp->bg_free_blocks_count);
|
||||
DPRINT("gdp->bg_inode_table %d\n",gdp->bg_inode_table);
|
||||
|
||||
return(gdp);
|
||||
|
||||
}
|
||||
|
||||
#define INODES_PER_BLOCK (BLOCKSIZE / sizeof(struct ext2_inode))
|
||||
|
||||
VOID Ext2ReadInode(PDEVICE_EXTENSION DeviceExt,
|
||||
ULONG ino,
|
||||
struct ext2_inode* inode)
|
||||
{
|
||||
ULONG block_group;
|
||||
struct ext2_group_desc* gdp;
|
||||
ULONG offset;
|
||||
struct ext2_inode* buffer;
|
||||
|
||||
DPRINT("Ext2ReadInode(DeviceExt %x, ino %d, inode %x)\n",
|
||||
DeviceExt,ino,inode);
|
||||
|
||||
block_group = (ino - 1) / DeviceExt->superblock->s_inodes_per_group;
|
||||
|
||||
gdp = Ext2LoadGroupDesc(DeviceExt, block_group);
|
||||
|
||||
|
||||
|
||||
offset = (ino - 1) % DeviceExt->superblock->s_inodes_per_group;
|
||||
|
||||
buffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
gdp->bg_inode_table + (offset / INODES_PER_BLOCK),
|
||||
1,
|
||||
buffer);
|
||||
memcpy(inode,&buffer[offset % INODES_PER_BLOCK],sizeof(struct ext2_inode));
|
||||
|
||||
DPRINT("inode->i_uid %d\n",inode->i_uid);
|
||||
DPRINT("inode->i_links_count %d\n",inode->i_links_count);
|
||||
DPRINT("inode->i_blocks %d\n",inode->i_blocks);
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
all: ext2fs.sys
|
||||
|
||||
OBJECTS = super.o blockdev.o inode.o file.o dir.o rw.o \
|
||||
../../../ntoskrnl/ntoskrnl.a
|
||||
|
||||
ext2fs.sys: $(OBJECTS)
|
||||
$(CC) -specs=$(KM_SPECS) -mdll -o junk.tmp -Wl,--defsym,_end=end \
|
||||
-Wl,--defsym,_edata=__data_end__ -Wl,--defsym,_etext=etext \
|
||||
-Wl,--base-file,base.tmp $(OBJECTS)
|
||||
$(RM) junk.tmp
|
||||
$(DLLTOOL) --dllname ext2fs.sys --base-file base.tmp \
|
||||
--output-exp temp.exp
|
||||
$(RM) base.tmp
|
||||
$(CC) --verbose -Wl,--image-base,0x10000 -Wl,-e,_DriverEntry \
|
||||
-specs=$(KM_SPECS) -mdll -o ext2fs.sys $(OBJECTS) -Wl,temp.exp
|
||||
$(RM) temp.exp
|
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/super.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS Ext2ReadFile(PDEVICE_EXTENSION DeviceExt,
|
||||
PFILE_OBJECT FileObject,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
LARGE_INTEGER OffsetL)
|
||||
/*
|
||||
* FUNCTION: Reads data from a file
|
||||
*/
|
||||
{
|
||||
PEXT2_FCB Fcb;
|
||||
PVOID TempBuffer;
|
||||
ULONG Offset = OffsetL;
|
||||
ULONG block;
|
||||
ULONG Delta;
|
||||
ULONG i;
|
||||
|
||||
DPRINT("Ext2ReadFile(DeviceExt %x, FileObject %x, Buffer %x, Length %d, \n"
|
||||
"OffsetL %d)\n",DeviceExt,FileObject,Buffer,Length,(ULONG)OffsetL);
|
||||
|
||||
Fcb = (PEXT2_FCB)FileObject->FsContext;
|
||||
TempBuffer = ExAllocatePool(NonPagedPool, BLOCKSIZE);
|
||||
|
||||
if (Offset >= Fcb->inode.i_size)
|
||||
{
|
||||
ExFreePool(TempBuffer);
|
||||
return(STATUS_END_OF_FILE);
|
||||
}
|
||||
if ((Offset + Length) > Fcb->inode.i_size)
|
||||
{
|
||||
Length = Fcb->inode.i_size - Offset;
|
||||
}
|
||||
|
||||
CHECKPOINT;
|
||||
if ((Offset % BLOCKSIZE) != 0)
|
||||
{
|
||||
block = Ext2BlockMap(DeviceExt, &Fcb->inode, Offset / BLOCKSIZE);
|
||||
Delta = min(BLOCKSIZE - (Offset % BLOCKSIZE),Length);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
TempBuffer);
|
||||
memcpy(Buffer, TempBuffer + (Offset % BLOCKSIZE), Delta);
|
||||
Length = Length - Delta;
|
||||
Offset = Offset + Delta;
|
||||
Buffer = Buffer + Delta;
|
||||
}
|
||||
CHECKPOINT;
|
||||
for (i=0; i<(Length/BLOCKSIZE); i++)
|
||||
{
|
||||
block = Ext2BlockMap(DeviceExt, &Fcb->inode,
|
||||
(Offset / BLOCKSIZE)+i);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
Buffer);
|
||||
Length = Length - BLOCKSIZE;
|
||||
Offset = Offset + BLOCKSIZE;
|
||||
Buffer = Buffer + BLOCKSIZE;
|
||||
}
|
||||
CHECKPOINT;
|
||||
if ((Length % BLOCKSIZE) != 0)
|
||||
{
|
||||
block = Ext2BlockMap(DeviceExt, &Fcb->inode, Offset / BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceExt->StorageDevice,
|
||||
block,
|
||||
1,
|
||||
TempBuffer);
|
||||
memcpy(Buffer,TempBuffer,Length);
|
||||
}
|
||||
|
||||
ExFreePool(TempBuffer);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
@@ -1,192 +0,0 @@
|
||||
/*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: services/fs/ext2/super.c
|
||||
* PURPOSE: ext2 filesystem
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* UPDATE HISTORY:
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <wchar.h>
|
||||
#include <internal/string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "ext2fs.h"
|
||||
|
||||
/* GLOBALS *****************************************************************/
|
||||
|
||||
static PDRIVER_OBJECT DriverObject;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS Ext2Close(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack;
|
||||
PFILE_OBJECT FileObject;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("Ext2Close(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
FileObject = Stack->FileObject;
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2Write(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 Ext2Read(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;
|
||||
|
||||
Status = Ext2ReadFile(DeviceExt,FileObject,Buffer,Length,Offset);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = Length;
|
||||
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS Ext2Mount(PDEVICE_OBJECT DeviceToMount)
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_EXTENSION DeviceExt;
|
||||
PVOID BlockBuffer;
|
||||
struct ext2_super_block* superblock;
|
||||
|
||||
DPRINT("Ext2Mount(DeviceToMount %x)\n",DeviceToMount);
|
||||
|
||||
BlockBuffer = ExAllocatePool(NonPagedPool,BLOCKSIZE);
|
||||
Ext2ReadSectors(DeviceToMount,
|
||||
1,
|
||||
1,
|
||||
BlockBuffer);
|
||||
superblock = BlockBuffer;
|
||||
|
||||
if (superblock->s_magic != EXT2_SUPER_MAGIC)
|
||||
{
|
||||
ExFreePool(BlockBuffer);
|
||||
return(STATUS_UNRECOGNIZED_VOLUME);
|
||||
}
|
||||
DPRINT("Volume recognized\n");
|
||||
DPRINT("s_inodes_count %d\n",superblock->s_inodes_count);
|
||||
DPRINT("s_blocks_count %d\n",superblock->s_blocks_count);
|
||||
|
||||
IoCreateDevice(DriverObject,
|
||||
sizeof(DEVICE_EXTENSION),
|
||||
NULL,
|
||||
FILE_DEVICE_FILE_SYSTEM,
|
||||
0,
|
||||
FALSE,
|
||||
&DeviceObject);
|
||||
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
|
||||
DeviceExt = (PVOID)DeviceObject->DeviceExtension;
|
||||
|
||||
DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
|
||||
DeviceToMount);
|
||||
DeviceExt->superblock = superblock;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
NTSTATUS Ext2FileSystemControl(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;
|
||||
|
||||
Status = Ext2Mount(DeviceToMount);
|
||||
|
||||
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 DeviceNameU;
|
||||
ANSI_STRING DeviceNameA;
|
||||
|
||||
DbgPrint("Ext2 FSD 0.0.1\n");
|
||||
|
||||
DriverObject = _DriverObject;
|
||||
|
||||
RtlInitAnsiString(&DeviceNameA,"\\Device\\Ext2Fsd");
|
||||
RtlAnsiStringToUnicodeString(&DeviceNameU,&DeviceNameA,TRUE);
|
||||
ret = IoCreateDevice(DriverObject,
|
||||
0,
|
||||
&DeviceNameU,
|
||||
FILE_DEVICE_FILE_SYSTEM,
|
||||
0,
|
||||
FALSE,
|
||||
&DeviceObject);
|
||||
if (ret!=STATUS_SUCCESS)
|
||||
{
|
||||
return(ret);
|
||||
}
|
||||
|
||||
DeviceObject->Flags=0;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = Ext2Close;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = Ext2Create;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = Ext2Read;
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = Ext2Write;
|
||||
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
|
||||
Ext2FileSystemControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL]=
|
||||
Ext2DirectoryControl;
|
||||
DriverObject->DriverUnload = NULL;
|
||||
|
||||
DPRINT("DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] %x\n",
|
||||
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL]);
|
||||
DPRINT("IRP_MJ_DIRECTORY_CONTROL %d\n",IRP_MJ_DIRECTORY_CONTROL);
|
||||
|
||||
IoRegisterFileSystem(DeviceObject);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#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);
|
||||
}
|
@@ -10,13 +10,12 @@
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
#include <string.h>
|
||||
#include <internal/string.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
#include "minix.h"
|
||||
#include "minix_fs.h"
|
||||
|
||||
/* FUNCTIONS ***************************************************************/
|
||||
|
||||
@@ -35,8 +34,7 @@ BOOLEAN MinixReadSector(IN PDEVICE_OBJECT pDeviceObject,
|
||||
DPRINT("MinixReadSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||
pDeviceObject,DiskSector,Buffer);
|
||||
|
||||
SET_LARGE_INTEGER_HIGH_PART(sectorNumber, 0);
|
||||
SET_LARGE_INTEGER_LOW_PART(sectorNumber, DiskSector * BLOCKSIZE);
|
||||
sectorNumber.LowPart = DiskSector * BLOCKSIZE;
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
@@ -84,52 +82,3 @@ BOOLEAN MinixReadSector(IN PDEVICE_OBJECT pDeviceObject,
|
||||
ExFreePool(mbr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN MinixWriteSector(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;
|
||||
|
||||
DPRINT("MinixWriteSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
|
||||
pDeviceObject,DiskSector,Buffer);
|
||||
|
||||
SET_LARGE_INTEGER_HIGH_PART(sectorNumber, 0);
|
||||
SET_LARGE_INTEGER_LOW_PART(sectorNumber, DiskSector * BLOCKSIZE);
|
||||
|
||||
KeInitializeEvent(&event, NotificationEvent, FALSE);
|
||||
|
||||
sectorSize = BLOCKSIZE;
|
||||
|
||||
irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
|
||||
pDeviceObject,
|
||||
Buffer,
|
||||
sectorSize,
|
||||
§orNumber,
|
||||
&event,
|
||||
&ioStatus );
|
||||
|
||||
|
||||
status = IoCallDriver(pDeviceObject,
|
||||
irp);
|
||||
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(&event,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
status = ioStatus.Status;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#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,¤t_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,¤t_dir,current);
|
||||
}
|
||||
if (next==NULL && current_ino!=0)
|
||||
{
|
||||
MinixReadInode(DeviceObject,DeviceExt,current_ino,¤t_dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*Information) = FILE_DOES_NOT_EXIST;
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
memcpy(result,¤t_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 MinixDirectoryControl(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = Stack->FileObject;
|
||||
|
||||
if (Stack->MinorFunction != IRP_MN_QUERY_DIRECTORY)
|
||||
{
|
||||
return(STATUS_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* 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 <string.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);
|
||||
}
|
@@ -1,9 +1,2 @@
|
||||
OBJECTS = block.o rw.o inode.o dir.o mount.o blockdev.o
|
||||
|
||||
all: minix.o
|
||||
|
||||
minix.o: $(OBJECTS)
|
||||
$(LD) -r $(OBJECTS) -o minix.o
|
||||
|
||||
WIN32_LEAN_AND_MEAN = yes
|
||||
include ../../../rules.mak
|
||||
all: minix.o blockdev.o
|
||||
$(LD) -r minix.o blockdev.o -o minixfsd.o
|
||||
|
@@ -445,8 +445,6 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject,
|
||||
DriverObject->MajorFunction[IRP_MJ_WRITE] = MinixWrite;
|
||||
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
|
||||
MinixFileSystemControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
|
||||
MinixDirectoryControl;
|
||||
DriverObject->DriverUnload = NULL;
|
||||
|
||||
IoRegisterFileSystem(DeviceObject);
|
||||
|
@@ -1,122 +0,0 @@
|
||||
#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);
|
@@ -1,156 +0,0 @@
|
||||
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
|
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user