Update of /cvsroot/opengtoolkit/portIO/c_source In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12704/c_source Added Files: MAKEFILE SOURCES ogportio.c ogportio.dsp ogportio.dsw ogportio.h ogportio.rc ogportiodll.c ogportiodll.h ogportiodll.rc Log Message: First release version of Port IO VI library with according Windows NT device driver. --- NEW FILE: MAKEFILE --- # # 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 --- NEW FILE: SOURCES --- # The sources for the OpenG Generic Port I/O device driver: TARGETNAME=ogportio TARGETPATH=obj TARGETTYPE=DRIVER INCLUDES=..\ SOURCES=ogportio.c ogportio.rc --- NEW FILE: ogportio.c --- #include <ntddk.h> #include <ogportio.h> #define IOPM_SIZE 0x2000 typedef UCHAR IOPM[IOPM_SIZE]; NTKERNELAPI void Ke386SetIoAccessMap(int, IOPM *); NTKERNELAPI void Ke386QueryIoAccessMap(int, IOPM *); NTKERNELAPI void Ke386IoSetAccessProcess(PEPROCESS, int); NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess); //NTKERNELAPI BOOLEAN MmIsAddressValid(IN PVOID ); //NTKERNELAPI PVOID MmMapIoSpace(PHYSICAL_ADDRESS, SIZE_T, BOOLEAN); //NTKERNELAPI VOID MmUnmapIoSpace(PVOID, SIZE_T); NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath); NTSTATUS OGPortIOReturn(IN PDEVICE_OBJECT deviceObject, IN PIRP irp); NTSTATUS OGPortIODispatch(IN PDEVICE_OBJECT deviceObject, IN PIRP irp); VOID OGPortIOUnload(IN PDRIVER_OBJECT driverObject); #ifdef MAP_ADDRESS #define BusAddress(busType, bus, physAddr, memType, mapAddr) \ HalTranslateBusAddress(Isa, 0, physAddr, &memType, &mapAddr) #else #define BusAddress(busType, bus, physAddr, memType, mapAddr) \ (mapAddr.LowPart = physAddr.LowPart, mapAddr.HighPart = physAddr.HighPart, TRUE) #endif #ifdef ALLOC_PRAGMA #pragma alloc_text (INIT, DriverEntry) #pragma alloc_text (PAGE, OGPortIOReturn) #pragma alloc_text (PAGE, OGPortIODispatch) #pragma alloc_text (PAGE, OGPortIOUnload) #endif /****************************************************************************** * * Driver entry point * *****************************************************************************/ NTSTATUS DriverEntry(IN PDRIVER_OBJECT driverObject, IN PUNICODE_STRING registryPath) { PDEVICE_OBJECT pDevObj; NTSTATUS status; WCHAR nameBuffer[] = L"\\Device\\OGPortIO"; WCHAR dosBuffer[] = L"\\DosDevices\\OGPortIO"; UNICODE_STRING uniNameString, uniDOSString; UNREFERENCED_PARAMETER (registryPath); KdPrint(("OpenG PORTIO: OGPortIO V1.0 08/18/2003 has loaded")); RtlInitUnicodeString(&uniNameString, nameBuffer); RtlInitUnicodeString(&uniDOSString, dosBuffer); status = IoCreateDevice(driverObject, sizeof(IOPM), &uniNameString, OGPORTIO_TYPE, 0, FALSE, &pDevObj); if (NT_SUCCESS(status)) { RtlFillMemory(pDevObj->DeviceExtension, sizeof(IOPM), 0xFF); status = IoCreateSymbolicLink (&uniDOSString, &uniNameString); if (NT_SUCCESS(status)) { driverObject->MajorFunction[IRP_MJ_CREATE] = OGPortIOReturn; driverObject->MajorFunction[IRP_MJ_CLOSE] = OGPortIOReturn; driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OGPortIODispatch; driverObject->DriverUnload = OGPortIOUnload; } else { KdPrint(("IoCreateSymbolicLink failed in DriverEntry\n")); IoDeleteDevice(driverObject->DeviceObject); } } else { KdPrint(("IoCreateDevice failed in DriverEntry\n")); } return status; } NTSTATUS OGPortIOReturn(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } static NTSTATUS OGPortIOProcess(ULONG processID, BOOLEAN install) { PEPROCESS process; if (processID) { KdPrint(("OpenG PORTIO: ProcessID received is %d\n", processID)); PsLookupProcessByProcessId(processID, &process); } else { process = IoGetCurrentProcess(); } KdPrint(("OpenG PORTIO: Pointer to process is 0x%X\n", process)); Ke386IoSetAccessProcess(process, install); return STATUS_SUCCESS; } NTSTATUS OGPortIODispatch(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { NTSTATUS ntStatus = STATUS_SUCCESS; PUCHAR pIOBuffer = (PUCHAR)pIrp->AssociatedIrp.SystemBuffer; PPORTMAP portmap = pIrp->AssociatedIrp.SystemBuffer; PPORTREG portreg = pIrp->AssociatedIrp.SystemBuffer; PMEMMAP memmap = pIrp->AssociatedIrp.SystemBuffer; PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(pIrp); ULONG inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; ULONG outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; switch (irpSp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_GET_VERSION: KdPrint(("OpenG PORTIO: IOCTL_GET_VERSION\n")); if (outBufLength >= sizeof(ULONG)) { *(PULONG)pIOBuffer = OGPORTIO_VERSION << 16; pIrp->IoStatus.Information = sizeof(ULONG); /* output buffer size */ } else { ntStatus = STATUS_BUFFER_TOO_SMALL; pIrp->IoStatus.Information = 0; /* output buffer size */ } break; case IOCTL_GET_IOPM: KdPrint(("OpenG PORTIO: IOCTL_GET_IOPM\n")); ntStatus = OGPortIOProcess(inBufLength >= 4 ? portmap->processID : 0, TRUE); if (ntStatus == STATUS_SUCCESS) { Ke386QueryIoAccessMap(1, pDevObj->DeviceExtension); if (outBufLength > 0) { PUCHAR buf = (PUCHAR)(pDevObj->DeviceExtension); if (inBufLength >= 8) { if (outBufLength > (portmap->offset + IOPM_SIZE)) outBufLength = IOPM_SIZE - portmap->offset; buf += portmap->offset; } else { if (outBufLength > IOPM_SIZE) outBufLength = IOPM_SIZE; } RtlMoveMemory(pIOBuffer, buf, outBufLength); } } pIrp->IoStatus.Information = outBufLength; /* output buffer size */ break; case IOCTL_SET_IOPM: KdPrint(("OpenG PORTIO: IOCTL_SET_IOPM\n")); ntStatus = OGPortIOProcess(inBufLength >= 4 ? portmap->processID : 0, TRUE); if (ntStatus == STATUS_SUCCESS) { if (inBufLength > 8 && portmap->offset < IOPM_SIZE) { PUCHAR buf = (PUCHAR)(pDevObj->DeviceExtension) + portmap->offset; inBufLength -= 8; if (portmap->offset + inBufLength > IOPM_SIZE) inBufLength = IOPM_SIZE - portmap->offset; RtlMoveMemory(buf, portmap->iopm, inBufLength); } Ke386SetIoAccessMap(1, pDevObj->DeviceExtension); } pIrp->IoStatus.Information = 0; /* output buffer size */ break; case IOCTL_RESET_IOPM: KdPrint(("OpenG PORTIO: IOCTL_RESET_IOPM\n")); ntStatus = OGPortIOProcess(inBufLength >= 4 ? portmap->processID : 0, FALSE); pIrp->IoStatus.Information = 0; /* output buffer size */ break; case IOCTL_READ_PORT: if ((inBufLength >= 8) && (outBufLength >= portreg->size)) { PHYSICAL_ADDRESS physAddr; PHYSICAL_ADDRESS mappedAddr; PVOID logicAddr; ULONG memType = 1; KdPrint(("OpenG PORTIO: IOCTL_READ_PORT 0x%X, size %d\n", portreg->address, portreg->size)); physAddr.LowPart = portreg->address; physAddr.HighPart = 0; if (BusAddress(Isa, 0, physAddr, memType, mappedAddr) == FALSE) { KdPrint(("HalTranslateBusAddress failed in IOCTL_READ_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } else if (memType == 0) { logicAddr = MmMapIoSpace(mappedAddr, portreg->size, FALSE); if (logicAddr == 0) { KdPrint(("MmMapIoSpace failed in IOCTL_READ_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } } else { logicAddr = (PVOID)mappedAddr.LowPart; } if (ntStatus == STATUS_SUCCESS) { switch (portreg->size) { case 1: ((PUCHAR)pIOBuffer)[0] = READ_PORT_UCHAR(logicAddr); KdPrint(("OpenG PORTIO: Value read %X\n", ((PUCHAR)pIOBuffer)[0])); break; case 2: ((PUSHORT)pIOBuffer)[0] = READ_PORT_USHORT(logicAddr); KdPrint(("OpenG PORTIO: Value read %X\n", ((PUSHORT)pIOBuffer)[0])); break; case 4: ((PULONG)pIOBuffer)[0] = READ_PORT_ULONG(logicAddr); KdPrint(("OpenG PORTIO: Value read %X\n", ((PULONG)pIOBuffer)[0])); break; default: KdPrint(("OpenG PORTIO: Invalid port read size\n")); ntStatus = STATUS_INVALID_PARAMETER; break; } if (memType == 0) { MmUnmapIoSpace(logicAddr, portreg->size); } } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } if (ntStatus == STATUS_SUCCESS) pIrp->IoStatus.Information = portreg->size; /* output buffer size */ else pIrp->IoStatus.Information = 0; break; case IOCTL_WRITE_PORT: if (inBufLength >= portreg->size + 8) { PHYSICAL_ADDRESS physAddr; PHYSICAL_ADDRESS mappedAddr; PVOID logicAddr; ULONG memType = 1; KdPrint(("OpenG PORTIO: IOCTL_WRITE_PORT 0x%X, size %d\n", portreg->address, portreg->size)); physAddr.LowPart = portreg->address; physAddr.HighPart = 0; if (BusAddress(Isa, 0, physAddr, memType, mappedAddr) == FALSE) { KdPrint(("HalTranslateBusAddress failed in IOCTL_READ_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } else if (memType == 0) { logicAddr = MmMapIoSpace(mappedAddr, portreg->size, FALSE); if (logicAddr == 0) { KdPrint(("MmMapIoSpace failed in IOCTL_READ_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } } else { logicAddr = (PVOID)mappedAddr.LowPart; } if (ntStatus == STATUS_SUCCESS) { switch (portreg->size) { case 1: KdPrint(("OpenG PORTIO: Value write 0x%X\n", portreg->u.byte)); WRITE_PORT_UCHAR(logicAddr, portreg->u.byte); break; case 2: KdPrint(("OpenG PORTIO: Value write 0x%X\n", portreg->u.word)); WRITE_PORT_USHORT(logicAddr, portreg->u.word); break; case 4: KdPrint(("OpenG PORTIO: Value write 0x%X\n", portreg->u.dword)); WRITE_PORT_ULONG(logicAddr, portreg->u.dword); break; default: KdPrint(("OpenG PORTIO: Invalid port write size\n")); ntStatus = STATUS_INVALID_PARAMETER; break; } if (memType == 0) { MmUnmapIoSpace(logicAddr, portreg->size); } } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } pIrp->IoStatus.Information = 0; /* output buffer size */ break; case IOCTL_READ_PHYSMEM: if ((inBufLength >= sizeof(MEMMAP)) && (outBufLength >= memmap->size)) { PHYSICAL_ADDRESS physAddr; PHYSICAL_ADDRESS mappedAddr; PVOID logicAddr; ULONG memType = 0; KdPrint(("OpenG PORTIO: IOCTL_READ_PHYSMEM 0x%X, size %d\n", memmap->address, memmap->size)); physAddr.LowPart = memmap->address; physAddr.HighPart = 0; if (BusAddress(Isa, 0, physAddr, memType, mappedAddr) == FALSE) { KdPrint(("HalTranslateBusAddress failed in IOCTL_READ_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } else if (memType == 0) { logicAddr = MmMapIoSpace(mappedAddr, memmap->size, FALSE); if (logicAddr == 0) { KdPrint(("MmMapIoSpace failed in IOCTL_READ_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } } else { logicAddr = (PVOID)mappedAddr.LowPart; } if (ntStatus == STATUS_SUCCESS) { switch (memmap->unit) { case 1: KdPrint(("OpenG PORTIO: Read memory, unit 1, size %d\n", memmap->size)); READ_REGISTER_BUFFER_UCHAR(logicAddr, pIOBuffer, memmap->size); break; case 2: KdPrint(("OpenG PORTIO: Read memory, unit 2, size %d\n", memmap->size/2)); READ_REGISTER_BUFFER_USHORT(logicAddr, (PUSHORT)pIOBuffer, memmap->size/2); break; case 4: KdPrint(("OpenG PORTIO: Read memory, unit 4, size %d\n", memmap->size/4)); READ_REGISTER_BUFFER_ULONG(logicAddr, (PULONG)pIOBuffer, memmap->size/4); break; default: KdPrint(("OpenG PORTIO: Invalid memory read unit %d\n", memmap->unit)); ntStatus = STATUS_INVALID_PARAMETER; break; } if (memType == 0) { MmUnmapIoSpace(logicAddr, memmap->size); } } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } pIrp->IoStatus.Information = 0; /* output buffer size */ break; case IOCTL_WRITE_PHYSMEM: if (inBufLength >= sizeof(MEMMAP) + memmap->size) { PHYSICAL_ADDRESS physAddr; PHYSICAL_ADDRESS mappedAddr; PVOID logicAddr; ULONG memType = 0; KdPrint(("OpenG PORTIO: IOCTL_WRITE_PHYSMEM 0x%X, size %d\n", memmap->address, memmap->size)); physAddr.LowPart = memmap->address; physAddr.HighPart = 0; if (BusAddress(Isa, 0, physAddr, memType, mappedAddr) == FALSE) { KdPrint(("HalTranslateBusAddress failed in IOCTL_WRITE_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } else if (memType == 0) { logicAddr = MmMapIoSpace(mappedAddr, memmap->size, FALSE); if (logicAddr == 0) { KdPrint(("MmMapIoSpace failed in IOCTL_WRITE_PHYSMEM\n")); ntStatus = STATUS_UNSUCCESSFUL; } } else { logicAddr = (PVOID)mappedAddr.LowPart; } if (ntStatus == STATUS_SUCCESS) { switch (memmap->unit) { case 1: KdPrint(("OpenG PORTIO: Write memory, unit 1, size %d\n", memmap->size)); WRITE_REGISTER_BUFFER_UCHAR(logicAddr, memmap->buf, memmap->size); break; case 2: KdPrint(("OpenG PORTIO: Write memory, unit 2, size %d\n", memmap->size/2)); WRITE_REGISTER_BUFFER_USHORT(logicAddr, (PUSHORT)memmap->buf, memmap->size/2); break; case 4: KdPrint(("OpenG PORTIO: Write memory, unit 4, size %d\n", memmap->size/4)); WRITE_REGISTER_BUFFER_ULONG(logicAddr, (PULONG)memmap->buf, memmap->size/4); break; default: KdPrint(("OpenG PORTIO: Invalid memory write unit %d\n", memmap->unit)); ntStatus = STATUS_INVALID_PARAMETER; break; } if (memType == 0) { MmUnmapIoSpace(logicAddr, memmap->size); } } } else { ntStatus = STATUS_BUFFER_TOO_SMALL; } pIrp->IoStatus.Information = 0; /* output buffer size */ break; default: KdPrint(("OpenG PORTIO: Unsupported IOCTL Call\n")); ntStatus = STATUS_UNSUCCESSFUL; pIrp->IoStatus.Information = 0; break; } pIrp->IoStatus.Status = ntStatus; IoCompleteRequest(pIrp, IO_NO_INCREMENT ); return ntStatus; } VOID OGPortIOUnload(IN PDRIVER_OBJECT driverObject) { WCHAR dosBuffer[] = L"\\DosDevices\\OGPortIO"; UNICODE_STRING uniDOSString; KdPrint(("OpenG PORTIO: OGPortIO is Unloading\n")); RtlInitUnicodeString(&uniDOSString, dosBuffer); IoDeleteSymbolicLink (&uniDOSString); IoDeleteDevice(driverObject->DeviceObject); } --- NEW FILE: ogportio.dsp --- # Microsoft Developer Studio Project File - Name="ogportio" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=ogportio - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "ogportio.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "ogportio.mak" CFG="ogportio - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "ogportio - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "ogportio - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "ogportio - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OGPORTIO_EXPORTS" /Yu"stdafx.h" /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OGPORTIO_EXPORTS" /FD /c # SUBTRACT CPP /YX /Yc /Yu # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shlwapi.lib /nologo /dll /machine:I386 !ELSEIF "$(CFG)" == "ogportio - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OGPORTIO_EXPORTS" /Yu"stdafx.h" /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "OGPORTIO_EXPORTS" /FD /GZ /c # SUBTRACT CPP /YX /Yc /Yu # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib shell32.lib uuid.lib shlwapi.lib /nologo /dll /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "ogportio - Win32 Release" # Name "ogportio - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\ogportiodll.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\ogportio.h # End Source File # Begin Source File SOURCE=.\ogportiodll.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # Begin Source File SOURCE=.\ogportiodll.rc # End Source File # End Group # End Target # End Project --- NEW FILE: ogportio.dsw --- Microsoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "ogportio"=.\ogportio.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### --- NEW FILE: ogportio.h --- /* * Generic Port IO device driver header definitions * * Copyright (C) 2004 Rolf Kalbermatter, r.k...@hc... * * Please visit http://www.OpenG.org to learn about the * Open Source LabVIEW software movement. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define OGPORTIO_NAME "\\\\.\\OGPortIO" #define OGPORTIO_VERSION 0x0101 #define OGPORTIO_TYPE 43210 /* 32768-65535 are reserved for customers */ // The IOCTL function codes from 0x800 to 0xFFF are for customer use. typedef struct { ULONG processID; ULONG offset; UCHAR iopm[0]; } PORTMAP, *PPORTMAP; #define IOCTL_GET_VERSION \ CTL_CODE(OGPORTIO_TYPE, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_GET_IOPM \ CTL_CODE(OGPORTIO_TYPE, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_SET_IOPM \ CTL_CODE(OGPORTIO_TYPE, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_RESET_IOPM \ CTL_CODE(OGPORTIO_TYPE, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS) typedef struct { ULONG address; ULONG size; union { UCHAR byte; USHORT word; ULONG dword; } u; } PORTREG, *PPORTREG; #define IOCTL_READ_PORT \ CTL_CODE(OGPORTIO_TYPE, 0x810, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_WRITE_PORT \ CTL_CODE(OGPORTIO_TYPE, 0x811, METHOD_BUFFERED, FILE_READ_ACCESS) typedef struct { ULONG address; ULONG size; ULONG unit; UCHAR buf[0]; } MEMMAP, *PMEMMAP; #define IOCTL_READ_PHYSMEM \ CTL_CODE(OGPORTIO_TYPE, 0x812, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_WRITE_PHYSMEM \ CTL_CODE(OGPORTIO_TYPE, 0x813, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_MAP_PHYSMEM \ CTL_CODE(OGPORTIO_TYPE, 0x814, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_UNMAP_PHYSMEM \ CTL_CODE(OGPORTIO_TYPE, 0x815, METHOD_BUFFERED, FILE_READ_ACCESS) --- NEW FILE: ogportio.rc --- #include <windows.h> #include <ntverp.h> #define VER_FILETYPE VFT_DRV #define VER_FILESUBTYPE VFT2_DRV_SYSTEM #define VER_FILEDESCRIPTION_STR "OpenG Generic Port I/O Device Driver" #define VER_INTERNALNAME_STR "OGPortIO.sys" #define VER_ORIGINALFILENAME_STR "OGPortIO.sys" #define VER_LEGALCOPYRIGHT_YEARS "\2512004" #define VER_LEGALCOPYRIGHT_STR VER_LEGALCOPYRIGHT_YEARS " Rolf Kalbermatter" #define VER_COMPANYNAME_STR "OpenG, http://www.openg.org" #define VER_PRODUCTNAME_STR "OpenG Generic Port I/O Driver" #define VER_FILEVERSION 1,0,1,0 #define VER_FILEVERSION_STR "Version 1.0.1" #define VER_PRODUCTVERSION 1,0,1 #define VER_PRODUCTVERSION_STR "OpenG Generic Port I/O Driver Version 1.0.1" #include "common.ver" --- NEW FILE: ogportiodll.c --- /* * Generic Port IO user space device driver shared library * * Copyright (C) 2004 Rolf Kalbermatter, r.k...@hc... * * Please visit http://www.OpenG.org to learn about the * Open Source LabVIEW software movement. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <windows.h> #include <shlwapi.h> #include <conio.h> #include "ogportio.h" #include "ogportiodll.h" #ifdef _DEBUG #define DebugBreaking() {__asm int 3} #else #define DebugBreaking() #endif static DWORD InstallPortIODriver(SC_HANDLE hSCManager); static HANDLE gModule; static HANDLE hDevice = INVALID_HANDLE_VALUE; static BOOL gWinNT = FALSE; BOOL APIENTRY DllMain(HANDLE hModule, DWORD uReason, LPVOID lpReserved) { switch (uReason) { case DLL_PROCESS_ATTACH: gModule = hModule; gWinNT = GetVersion() < 0x80000000; break; case DLL_PROCESS_DETACH: PortIOClose(); break; } return TRUE; } DWORD LibAPI StartPortIODriver(void) { SC_HANDLE hSCManager; SC_HANDLE hService; BOOL ret; DWORD err = ERROR_SUCCESS; if (gWinNT) { /* Open Handle to Service Control Manager */ hSCManager = OpenSCManager (NULL, /* machine (NULL == local) */ NULL, /* database (NULL == default) */ SC_MANAGER_ALL_ACCESS); /* access required */ if (hSCManager == NULL) { return GetLastError(); } do { /* Open a Handle to the Port IO Service Database */ hService = OpenService(hSCManager, /* handle to service control manager database */ "OGPortIO", /* pointer to name of service to start */ SERVICE_ALL_ACCESS); /* type of access to service */ if (hService == NULL) { switch (err = GetLastError()) { case ERROR_ACCESS_DENIED: /* You do not have rights to the OGPortIO service database\n */ case ERROR_INVALID_NAME: /* The specified service name is invalid */ return err; case ERROR_SERVICE_DOES_NOT_EXIST: err = InstallPortIODriver(hSCManager); if (err) return err; } } } while (hService == NULL); /* Start the PortIO driver. Errors will occur here if OGPortIO.sys file doesn't exist */ ret = StartService (hService, /* service identifier */ 0, /* number of arguments */ NULL); /* pointer to arguments */ if (!ret) { err = GetLastError(); if (err == ERROR_SERVICE_ALREADY_RUNNING) /* Driver already exists. No action taken. */ err = ERROR_SUCCESS; } /* Close handle to Service Control Manager */ CloseServiceHandle(hService); CloseServiceHandle(hSCManager); } return err; } static DWORD InstallPortIODriver(SC_HANDLE hSCManager) { SC_HANDLE hService; DWORD err = ERROR_SUCCESS; CHAR systemFileName[MAX_PATH]; CHAR driverFileName[MAX_PATH]; static CHAR filename[] = "OGPortIO.sys"; /* GetSystemDirectory. Assumes OGPortIO.sys driver is in this directory. Doesn't detect if file exists, nor if file is on removable media - if this is the case then when windows next boots, the driver will fail to load and a error entry is made in the event viewer to reflect this. */ if (!GetSystemDirectory(systemFileName, MAX_PATH - 22)) { return GetLastError(); } /* Append our driver name */ PathAppend(systemFileName, "drivers"); PathAppend(systemFileName, filename); if (!GetModuleFileName(gModule, driverFileName, MAX_PATH)) { return GetLastError(); } PathRemoveFileSpec(driverFileName); PathAppend(driverFileName, filename); /* Copy Driver to System32/drivers directory. This fails if the file doesn't exist. */ if (!CopyFile(driverFileName, systemFileName, FALSE)) { return GetLastError(); } /* Create Service/Driver - This adds the appropriate registry keys in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services - It doesn't care if the driver exists, or if the path is correct. */ hService = CreateService(hSCManager, /* SCManager database */ "OGPortIO", /* name of service */ "Open-G PortIO Driver", /* name to display */ SERVICE_ALL_ACCESS, /* desired access */ SERVICE_KERNEL_DRIVER, /* service type */ SERVICE_DEMAND_START, /* start type */ SERVICE_ERROR_NORMAL, /* error control type */ "System32\\Drivers\\OGPortIO.sys", /* service's binary */ NULL, /* no load ordering group */ NULL, /* no tag identifier */ NULL, /* no dependencies */ NULL, /* LocalSystem account */ NULL /* no password */ ); if (hService == NULL) { err = GetLastError(); if (err == ERROR_SERVICE_EXISTS) /* Driver already exists. No action taken. */ err = ERROR_SUCCESS; } /* Close Handle to Service Control Manager */ CloseServiceHandle(hService); return err; } DWORD LibAPI RemovePortIO(void) { SC_HANDLE hSCManager; SC_HANDLE hService; BOOL ret; DWORD err = ERROR_SUCCESS; SERVICE_STATUS serviceStatus; PortIOClose(); if (gWinNT) { /* Open Handle to Service Control Manager */ hSCManager = OpenSCManager (NULL, // machine (NULL == local) NULL, // database (NULL == default) SC_MANAGER_ALL_ACCESS); // access required /* Open Handle to PortTalk Service Database */ hService = OpenService (hSCManager, "OGPortIO", SERVICE_ALL_ACCESS); if (hService == NULL) { /* Seems not installed at all */ return ERROR_SERVICE_DOES_NOT_EXIST; } /* Stop Service */ ret = ControlService (hService, SERVICE_CONTROL_STOP, &serviceStatus); if (!ret) err = GetLastError(); /* Delete Service */ ret = DeleteService (hService); if (!ret) err = GetLastError(); /* Close Handle to Service Control Manager */ CloseServiceHandle (hService); CloseServiceHandle(hSCManager); } return err; } DWORD LibAPI PortIOOpen(void) { DWORD err = ERROR_SUCCESS; DebugBreaking(); /* if Windows NT, open device driver and if not present install it */ if (gWinNT) { hDevice = CreateFile(OGPORTIO_NAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice == INVALID_HANDLE_VALUE) { /* Start or install the Driver */ err = StartPortIODriver(); if (!err) { /* Then try to open once more, before failing */ hDevice = CreateFile(OGPORTIO_NAME, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice == INVALID_HANDLE_VALUE) { err = ERROR_DEV_NOT_EXIST; } } } } return err; } DWORD LibAPI PortIOClose(void) { if (gWinNT && hDevice != INVALID_HANDLE_VALUE) { return CloseHandle(hDevice); } return ERROR_SUCCESS; } DWORD LibAPI PortIOGetVersion(unsigned long *version) { DWORD BytesReturned, err = ERROR_SUCCESS; if (!version) return ERROR_INVALID_PARAMETER; DebugBreaking(); if (gWinNT) { if (hDevice == INVALID_HANDLE_VALUE) { err = PortIOOpen(); if (err) return err; } if (!DeviceIoControl(hDevice, IOCTL_GET_VERSION, NULL, 0, version, sizeof(*version), &BytesReturned, NULL)) { err = GetLastError(); } } *version |= OGPORTIO_VERSION; return err; } DWORD LibAPI PortIOEnablePort(unsigned long processID, unsigned short start, unsigned short size) { DWORD BytesReturned, i, j, err = ERROR_SUCCESS; DebugBreaking(); if (gWinNT) { int len = ((start + size + 7) >> 3) - (start >> 3); PPORTMAP param = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + sizeof(PORTMAP)); if (!param) return ERROR_OUTOFMEMORY; if (hDevice == INVALID_HANDLE_VALUE) { err = PortIOOpen(); if (err) return err; } param->processID = processID; param->offset = start >> 3; if (!DeviceIoControl(hDevice, IOCTL_GET_IOPM, param, sizeof(PORTMAP), param->iopm, len, &BytesReturned, NULL)) { err = GetLastError(); } else { for (i = (start % 8), j = 0; j < size; j++, i++) { param->iopm[i >> 3] &= ~(1 << (i % 8)); } if (!DeviceIoControl(hDevice, IOCTL_SET_IOPM, param, len + sizeof(PORTMAP), NULL, 0, &BytesReturned, NULL)) { err = GetLastError(); } } HeapFree(GetProcessHeap(), 0, param); } return err; } DWORD LibAPI PortIOReleasePort(unsigned long processID, unsigned short start, unsigned short size) { DWORD BytesReturned, i, j, err = ERROR_SUCCESS; if (gWinNT) { int len = ((start + size + 7) >> 3) - (start >> 3); PPORTMAP param = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + sizeof(PORTMAP)); if (!param) return ERROR_OUTOFMEMORY; if (hDevice == INVALID_HANDLE_VALUE) { err = PortIOOpen(); if (err) return err; } param->processID = processID; param->offset = start >> 3; if (!DeviceIoControl(hDevice, IOCTL_GET_IOPM, param, sizeof(PORTMAP), param->iopm, len, &BytesReturned, NULL)) { err = GetLastError(); } else { for (i = (start % 8), j = 0; j < size; j++, i++) { param->iopm[i >> 3] |= (1 << (i % 8)); } if (!DeviceIoControl(hDevice, IOCTL_SET_IOPM, param, len + sizeof(PORTMAP), NULL, 0, &BytesReturned, NULL)) { err = GetLastError(); } } HeapFree(GetProcessHeap(), 0, param); } return err; } DWORD LibAPI PortIOReadDirect(unsigned short address, unsigned long size, void *value) { switch (size) { case 1: *(char *)value = (char)_inp(address); break; case 2: *(short *)value = (short)_inpw(address); break; case 4: *(long *)value = (long)_inpd(address); break; default: return ERROR_INVALID_PARAMETER; } return ERROR_SUCCESS; } DWORD LibAPI PortIORead(unsigned short address, unsigned long size, void *value) { DWORD BytesReturned, err = ERROR_SUCCESS; PORTREG param; if (!gWinNT) return PortIOReadDirect(address, size, value); if (size < 1 || size > 4) return ERROR_INVALID_PARAMETER; if (hDevice == INVALID_HANDLE_VALUE) { err = PortIOOpen(); if (err) return err; } param.address = address; param.size = size; if (!DeviceIoControl(hDevice, IOCTL_READ_PORT, ¶m, sizeof(PORTREG), value, size, &BytesReturned, NULL)) { err = GetLastError(); } return err; } DWORD LibAPI PortIOWriteDirect(unsigned short address, unsigned long size, void *value) { switch (size) { case 1: _outp(address, *(char *)value); break; case 2: _outpw(address, *(short *)value); break; case 4: _outpd(address, *(long *)value); break; default: return ERROR_INVALID_PARAMETER; } return ERROR_SUCCESS; } DWORD LibAPI PortIOWrite(unsigned short address, unsigned long size, void *value) { DWORD BytesReturned, err = ERROR_SUCCESS; PORTREG param; if (!gWinNT) return PortIOWriteDirect(address, size, value); if (size < 1 || size > 4) return ERROR_INVALID_PARAMETER; if (hDevice == INVALID_HANDLE_VALUE) { err = PortIOOpen(); if (err) return err; } param.address = address; param.size = size; param.u.dword = *(DWORD *)value; if (!DeviceIoControl(hDevice, IOCTL_WRITE_PORT, ¶m, sizeof(PORTREG), NULL, 0, &BytesReturned, NULL)) { err = GetLastError(); } return err; } --- NEW FILE: ogportiodll.h --- /* * Generic Port IO user space device driver shared library * * Copyright (C) 2004 Rolf Kalbermatter, r.k...@hc... * * Please visit http://www.OpenG.org to learn about the * Open Source LabVIEW software movement. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #if defined(OGPORTIO_EXPORTS) #define LibAPI __declspec(dllexport) __cdecl #else #define LibAPI __declspec(dllimport) __cdecl #endif DWORD LibAPI StartPortIODriver(void); DWORD LibAPI RemovePortIO(void); DWORD LibAPI PortIOOpen(void); DWORD LibAPI PortIOClose(void); DWORD LibAPI PortIOGetVersion(unsigned long *version); DWORD LibAPI PortIOEnablePort(unsigned long processID, unsigned short start, unsigned short size); DWORD LibAPI PortIOReleasePort(unsigned long processID, unsigned short start, unsigned short size); DWORD LibAPI PortIOReadDirect(unsigned short address, unsigned long size, void *value); DWORD LibAPI PortIORead(unsigned short address, unsigned long size, void *value); DWORD LibAPI PortIOWriteDirect(unsigned short address, unsigned long size, void *value); DWORD LibAPI PortIOWrite(unsigned short address, unsigned long size, void *value); --- NEW FILE: ogportiodll.rc --- #include <windows.h> #include <ntverp.h> #define VER_FILETYPE VFT_DRV #define VER_FILESUBTYPE VFT2_DRV_SYSTEM #define VER_FILEDESCRIPTION_STR "OpenG Generic Port I/O User Space Library" #define VER_INTERNALNAME_STR "OGPortIO.dll" #define VER_ORIGINALFILENAME_STR "OGPortIO.dll" #define VER_LEGALCOPYRIGHT_YEARS "\2512004" #define VER_LEGALCOPYRIGHT_STR VER_LEGALCOPYRIGHT_YEARS " Rolf Kalbermatter" #define VER_COMPANYNAME_STR "OpenG, http://www.openg.org" #define VER_PRODUCTNAME_STR "OpenG Generic Port I/O Driver" #define VER_FILEVERSION 1,0,1,0 #define VER_FILEVERSION_STR "Version 1.0.1" #define VER_PRODUCTVERSION 1,0,1 #define VER_PRODUCTVERSION_STR "OpenG Generic Port I/O Driver Version 1.0.1" #include "common.ver" |