我想读写一个ISA槽上的数据采集卡的数据,但是在Win2k系统下不能直接读写I/O端口,谁有读写I/O端口的动态连接库,多谢!!!

解决方案 »

  1.   

    用WINIO,去硬件系统版,那里可以找到方法
      

  2.   

    发信人: April (椰风海韵), 信区: VisualC 标  题: Re: 关于端口读写,help 发信站: BBS 水木清华站 (Tue Apr 17 13:12:56 2001)   NT下对I/O操作进行了保护的,不允许直接访问i/o端口,一般的解决方法是 编写驱动程序,这样可以在Kernel层访问I/O.在NT/2000DDK\src\general目录下有个 portio的例子,拿来就可以用了.还有更好的方法,利用DDK中几个未公开的API也可以 达到同样的目的. //portio.c #include <ntddk.h> /*  *  The name of our device driver.  */ #define DEVICE_NAME_STRING      L"portio" #define IOPM_SIZE       0x2000 typedef UCHAR IOPM[IOPM_SIZE]; IOPM *IOPM_local = 0;   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); }   VOID SetIOPermissionMap(int OnFlag) {         Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag);         Ke386SetIoAccessMap(1, IOPM_local); }   void GiveIO(void) {         SetIOPermissionMap(1); }   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; }   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; }   //在同一个目录下建造sources文件,内容: TARGETNAME=portio TARGETPATH=. TARGETTYPE=DRIVER INCLUDES=e:\ntddk\inc  ;//这儿填写DDK下inc目录的路径 SOURCES=portio.c   //在同一个目录下建造makefile文件,内容: !INCLUDE $(NTMAKEENV)\makefile.def   利用命令行:SetEnv e:\ntddk //设置DDK环境  在该目录下 build,然后会在该目录的I386中产生portio.sys文件,将文件 copy到WINNT\system32\drivers里面,在注册表中手工安装驱动程序(别告诉我你不会 ,到驱动程序版查查,最好设置为驱动程序自动启动,service的key为portio),重起机子。   编写用户态程序: HANDLE h; h = CreateFile("\\\\.\\portio", GENERIC_READ, 0, NULL,                                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NUULL);     if(h == INVALID_HANDLE_VALUE) {         printf("Couldn't access giveio device\n");         return -1;     }     CloseHandle(h); //然后以后用嵌入汇编或者_inp,_oup写端口即可.   【 在 qaq (qaq) 的大作中提到: 】 : 标  题: 关于端口读写,help : 发信站: BBS 水木清华站 (Tue Apr 17 11:04:26 2001) : : 各位大虾,dos下可以用inp(),outp()对端口操作。 : win95/98可以用-inp(),-outp(), : winnt 和 2000 呢,别告我不能对端口操作. : 3x : : -- : : ※ 来源:·BBS 水木清华站 smth.org·[FROM: 203.93.178.115]     --   
      

  3.   

    http://www.internals.com/utilities/winio.zip
      

  4.   

    1 才发现2000下不用谢驱动也可以,可以利用访问虚拟端口的方法实现(winio就是使用的这种方法)
    #include <conio.h>//注意必须包含着个
    读端口:
        switch (bSize)
        {
          case 1:        *pdwPortVal = _inp(wPortAddr);      break;      case 2:        *pdwPortVal = _inpw(wPortAddr);      break;      case 4:        *pdwPortVal = _inpd(wPortAddr);      break;
        }
    写端口:
        switch (bSize)
        {
          case 1:        _outp(wPortAddr, dwPortVal);      break;      case 2:        _outpw(wPortAddr, (WORD)dwPortVal);      break;      case 4:        _outpd(wPortAddr, dwPortVal);      break;
        }不过这种方法是访问的虚拟端口,虚拟端口被映射到物理端口,所以可能会有些限制,不过访问并口是绝对可以的2 写驱动程序,在里面使用汇编来完成或者使用DDK提供的访问端口函数,这样保险一些3 还可以使用winio,这是最简单的方法下面是我以前写的访问并口的程序,使用第二种方法,里面还包含winio
    http://vip.6to23.com/NowCan1/ctrl/portion.rar
      

  5.   

    关于端口的读写参看csdn里bhw98的专栏,你会有比较多收获!http://www.csdn.net/develop/author/netauthor/bhw98/实战DeviceIoControl 之六:访问物理端口 (原创)