diff options
author | cliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a> | 2002-07-31 00:09:33 +0000 |
---|---|---|
committer | cliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a> | 2002-07-31 00:09:33 +0000 |
commit | e5fa3b60238db8bfe839d8bbffc4a638719f6e95 (patch) | |
tree | dd65b616d0f96163ea36951daa8087b0737087d4 | |
parent | 8864126e15e73ed3e09225fde414a265a6e520da (diff) | |
download | pyserial-git-e5fa3b60238db8bfe839d8bbffc4a638719f6e95.tar.gz |
added giveio sources and a readme
-rw-r--r-- | pyparallel/src/win32/README.txt | 20 | ||||
-rw-r--r-- | pyparallel/src/win32/giveio/GIVEIO.C | 168 | ||||
-rw-r--r-- | pyparallel/src/win32/giveio/MAKEFILE | 7 | ||||
-rw-r--r-- | pyparallel/src/win32/giveio/README.TXT | 92 | ||||
-rw-r--r-- | pyparallel/src/win32/giveio/SOURCES | 7 |
5 files changed, 294 insertions, 0 deletions
diff --git a/pyparallel/src/win32/README.txt b/pyparallel/src/win32/README.txt new file mode 100644 index 0000000..d0b3cc5 --- /dev/null +++ b/pyparallel/src/win32/README.txt @@ -0,0 +1,20 @@ +This extension is needed on Windows as there is no API to +manipulate the parallel port. This Python extension exposes +"inp()" and "outp()" that can be used to manipulate the printer +IOs directly. It could be basicaly used to access any IO port. + +On Windows NT/2k/XP direct access to IOs is not possible for +user applications (only kernel mode drivers). Because of that +a kernel driver is needed. The sources to GIVEIO.SYS are in +the respective directory. The loaddrv sources come from the +archive that is mentioned in the giveio readme. + +The extension tries to detect if its running on an NT based +system and activates the giveio driver to gain access to the +IO ports. + +Thanks go to + Dale Roberts for the giveio driver and to + Paula Tomlinson for the loaddrv sources + +chris <cliechti@gmx.net> diff --git a/pyparallel/src/win32/giveio/GIVEIO.C b/pyparallel/src/win32/giveio/GIVEIO.C new file mode 100644 index 0000000..f752a29 --- /dev/null +++ b/pyparallel/src/win32/giveio/GIVEIO.C @@ -0,0 +1,168 @@ +/********************************************************************* + +Author: Dale Roberts +Date: 8/30/95 +Program: GIVEIO.SYS +Compile: Use DDK BUILD facility + +Purpose: Give direct port I/O access to a user mode process. + +*********************************************************************/ +#include <ntddk.h> + +/* + * The name of our device driver. + */ +#define DEVICE_NAME_STRING L"giveio" + +/* + * This is the "structure" of the IOPM. It is just a simple + * character array of length 0x2000. + * + * This holds 8K * 8 bits -> 64K bits of the IOPM, which maps the + * entire 64K I/O space of the x86 processor. Any 0 bits will give + * access to the corresponding port for user mode processes. Any 1 + * bits will disallow I/O access to the corresponding port. + */ +#define IOPM_SIZE 0x2000 +typedef UCHAR IOPM[IOPM_SIZE]; + +/* + * This will hold simply an array of 0's which will be copied + * into our actual IOPM in the TSS by Ke386SetIoAccessMap(). + * The memory is allocated at driver load time. + */ +IOPM *IOPM_local = 0; + +/* + * These are the two undocumented calls that we will use to give + * the calling process I/O access. + * + * Ke386IoSetAccessMap() copies the passed map to the TSS. + * + * Ke386IoSetAccessProcess() adjusts the IOPM offset pointer so that + * the newly copied map is actually used. Otherwise, the IOPM offset + * points beyond the end of the TSS segment limit, causing any I/O + * access by the user mode process to generate an exception. + */ +void Ke386SetIoAccessMap(int, IOPM *); +void Ke386QueryIoAccessMap(int, IOPM *); +void Ke386IoSetAccessProcess(PEPROCESS, int); + +/********************************************************************* + Release any allocated objects. +*********************************************************************/ +VOID GiveioUnload(IN PDRIVER_OBJECT DriverObject) +{ + WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; + UNICODE_STRING uniDOSString; + + if(IOPM_local) + MmFreeNonCachedMemory(IOPM_local, sizeof(IOPM)); + + RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); + IoDeleteSymbolicLink (&uniDOSString); + IoDeleteDevice(DriverObject->DeviceObject); +} + +/********************************************************************* + Set the IOPM (I/O permission map) of the calling process so that it +is given full I/O access. Our IOPM_local[] array is all zeros, so +the IOPM will be all zeros. If OnFlag is 1, the process is given I/O +access. If it is 0, access is removed. +*********************************************************************/ +VOID SetIOPermissionMap(int OnFlag) +{ + Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag); + Ke386SetIoAccessMap(1, IOPM_local); +} + +void GiveIO(void) +{ + SetIOPermissionMap(1); +} + +/********************************************************************* + Service handler for a CreateFile() user mode call. + + This routine is entered in the driver object function call table by +the DriverEntry() routine. When the user mode application calls +CreateFile(), this routine gets called while still in the context of +the user mode application, but with the CPL (the processor's Current +Privelege Level) set to 0. This allows us to do kernel mode +operations. GiveIO() is called to give the calling process I/O +access. All the user mode application needs do to obtain I/O access +is open this device with CreateFile(). No other operations are +required. +*********************************************************************/ +NTSTATUS GiveioCreateDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) +{ + GiveIO(); // give the calling process I/O access + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +/********************************************************************* + Driver Entry routine. + + This routine is called only once after the driver is initially +loaded into memory. It allocates everything necessary for the +driver's operation. In our case, it allocates memory for our IOPM +array, and creates a device which user mode applications can open. +It also creates a symbolic link to the device driver. This allows +a user mode application to access our driver using the \\.\giveio +notation. +*********************************************************************/ +NTSTATUS DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath + ) +{ + PDEVICE_OBJECT deviceObject; + NTSTATUS status; + WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING; + WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING; + UNICODE_STRING uniNameString, uniDOSString; + + // + // Allocate a buffer for the local IOPM and zero it. + // + IOPM_local = MmAllocateNonCachedMemory(sizeof(IOPM)); + if(IOPM_local == 0) + return STATUS_INSUFFICIENT_RESOURCES; + RtlZeroMemory(IOPM_local, sizeof(IOPM)); + + // + // Set up device driver name and device object. + // + RtlInitUnicodeString(&uniNameString, NameBuffer); + RtlInitUnicodeString(&uniDOSString, DOSNameBuffer); + + status = IoCreateDevice(DriverObject, 0, + &uniNameString, + FILE_DEVICE_UNKNOWN, + 0, FALSE, &deviceObject); + + if(!NT_SUCCESS(status)) + return status; + + status = IoCreateSymbolicLink (&uniDOSString, &uniNameString); + + if (!NT_SUCCESS(status)) + return status; + + // + // Initialize the Driver Object with driver's entry points. + // All we require are the Create and Unload operations. + // + DriverObject->MajorFunction[IRP_MJ_CREATE] = GiveioCreateDispatch; + DriverObject->DriverUnload = GiveioUnload; + return STATUS_SUCCESS; +} + diff --git a/pyparallel/src/win32/giveio/MAKEFILE b/pyparallel/src/win32/giveio/MAKEFILE new file mode 100644 index 0000000..5818975 --- /dev/null +++ b/pyparallel/src/win32/giveio/MAKEFILE @@ -0,0 +1,7 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the driver components of the Windows NT DDK +# + +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/pyparallel/src/win32/giveio/README.TXT b/pyparallel/src/win32/giveio/README.TXT new file mode 100644 index 0000000..4a6ec36 --- /dev/null +++ b/pyparallel/src/win32/giveio/README.TXT @@ -0,0 +1,92 @@ +The entire archive was pulled from here: +Dr. Dobb's Journal, http://www.ddj.com/ftp/1996/1996.05/directio.zip +It contained some other snippets too, but as they are not useful here +I don't include them here. + +chris + +Following is the original readme of the archive: +----------------------------------------------------------------------------- + + +Author: Dale Roberts, Direct I/O and Windows NT + + +Here are two helpful hints to get you going with GIVEIO. The first +section below mentions the INSTDRV utility that is provided with the +Microsoft DDK. If you do not have access to the DDK, you can use Paula +Tomlinson's program LOADDRV instead. She describes it in her May 1995 +article in Windows/DOS Developer's Journal (now Windows Developer's +Journal). You can get the program from their FTP site at: + + ftp://ftp.mfi.com/pub/windev/1995/may95.zip. + + +------------------------------------------------------------------ +Device Driver Installation Made Easy + +The Microsoft NT Device Driver Kit documentation implies in several +places that there are several steps involved in installing a device driver +and making it accessible to a Win32 application. It explains that you +should edit the registry manually and then reboot the system. But +device drivers are dynamically loadable and unloadable in NT, and the +DDK comes with a very handy utility called INSTDRV that +demonstrates this facility in a very practical manner. + +INSTDRV is a console application that will register, load, and start a +kernel mode device driver. It does not require you to edit the registry +manually or reboot the computer. On the command line you simply +give the name of your device driver and the complete path to the .SYS +file (which does not need to be in the system's DRIVERS directory). +After this command is executed, you will find that the driver has been +registered with the system and appears in the Devices applet in the +control panel. If you give the word remove instead of the path, the +driver is removed from the system and taken out of the driver database. + +Once the driver is loaded and started, you can use the control panel's +Devices applet to start and stop it, or you can use the net start and net +stop commands (these are much faster) from a console window. When +a kernel mode device is stopped, it is in also unloaded from memory. +The next time you start the device, a fresh copy of the driver is read +from the hard drive, if it has been modified. This makes it very +convenient to develop device drivers, since you can go through the +modify, stop, start cycle repeatedly without ever needing to reboot. If +you need your driver to load at boot time, you can go into the Devices +applet and change its startup mode to boot. + +The other component that is needed to make the driver visible to user +mode applications, so they can use CreateFile() calls to access the +driver, is registering the name in the DOS Devices name space. This +can be done, as documented in the DDK, by editing the registry +manually and rebooting. Or, much more simply, the kernel mode +driver can call the IoCreateSymbolicLink() function to register the +name itself. The GIVEIO driver shown in Listing Four uses the later +technique. Once the name is registered, user mode applications can get +a file handle to the device driver by calling CreateFile() with the driver +name as the file parameter, but preceding the driver name with the +special cookie \\.\. The TESTIO application in Listing Five uses this +technique. + +------------------------------------------------------------------ +Quick Trick: Using DEBUG With Port I/O + +Sometimes you just need to do a quick I/O operation to a port. In DOS, +you could use the DEBUG program to accomplish this. In NT, once +you have the GIVEIO device driver up and running, you can once +again use DEBUG for port I/O. If you look at the source code for the +test application, you'll see that all it does is open and close the GIVEIO +device driver. It uses the special cookie \\.\ before the driver name in +order to access it. Without modifying DEBUG, you can have it open +this device driver by simply typing debug \\.\giveio in an NT console +window. You will get an error message complaining that the file +\\.\giveio is not found, but it will give DEBUG I/O access anyway. +Subsequent DOS applications that are run from this console window +will also have I/O access. + +WIN32 applications executed from this console window will still cause +exceptions. This is because DEBUG (and any other DOS application) +runs in the context of the VDM (Virtual DOS Machine) process of the +console box, whereas each WIN32 application gets its own process. +The VDM process stays active as long as the console window is open, +but each WIN32 application creates a brand new process with the +IOPM offset initialized to point beyond the end of the TSS. diff --git a/pyparallel/src/win32/giveio/SOURCES b/pyparallel/src/win32/giveio/SOURCES new file mode 100644 index 0000000..1f8abef --- /dev/null +++ b/pyparallel/src/win32/giveio/SOURCES @@ -0,0 +1,7 @@ +TARGETNAME=giveio +TARGETPATH=. +TARGETTYPE=DRIVER + +INCLUDES=c:\ddk\inc + +SOURCES=giveio.c |