📄 ppntddkgenport.c
字号:
/*****************************************************************************//* * ppntddkgenport.c -- Parport direct access with NTDDK genport.sys. * * Copyright (C) 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) * * 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. * * Please note that the GPL allows you to use the driver, NOT the radio. * In order to use the radio, you need a license from the communications * authority of your country. * *//*****************************************************************************/#include <windows.h>#include "parport.h"/* ---------------------------------------------------------------------- */#define DEVICE_TYPE DWORD#define CTL_CODE( DeviceType, Function, Method, Access ) ( \ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \)#define METHOD_BUFFERED 0#define METHOD_IN_DIRECT 1#define METHOD_OUT_DIRECT 2#define METHOD_NEITHER 3#define FILE_ANY_ACCESS 0#define FILE_READ_ACCESS (0x0001) #define FILE_WRITE_ACCESS (0x0002)#define GPD_TYPE 40000#define IOCTL_GPD_READ_PORT_UCHAR \ CTL_CODE( GPD_TYPE, 0x900, METHOD_BUFFERED, FILE_READ_ACCESS )#define IOCTL_GPD_READ_PORT_USHORT \ CTL_CODE( GPD_TYPE, 0x901, METHOD_BUFFERED, FILE_READ_ACCESS )#define IOCTL_GPD_READ_PORT_ULONG \ CTL_CODE( GPD_TYPE, 0x902, METHOD_BUFFERED, FILE_READ_ACCESS )#define IOCTL_GPD_WRITE_PORT_UCHAR \ CTL_CODE(GPD_TYPE, 0x910, METHOD_BUFFERED, FILE_WRITE_ACCESS)#define IOCTL_GPD_WRITE_PORT_USHORT \ CTL_CODE(GPD_TYPE, 0x911, METHOD_BUFFERED, FILE_WRITE_ACCESS)#define IOCTL_GPD_WRITE_PORT_ULONG \ CTL_CODE(GPD_TYPE, 0x912, METHOD_BUFFERED, FILE_WRITE_ACCESS)typedef struct _GENPORT_WRITE_INPUT { ULONG PortNumber; /* Port # to write to */ union { /* Data to be output to port */ ULONG LongData; USHORT ShortData; UCHAR CharData; };} GENPORT_WRITE_INPUT;/* ---------------------------------------------------------------------- *//* LPT registers *//* ECP specific registers */#define LPTREG_ECONTROL 0x402#define LPTREG_CONFIGB 0x401#define LPTREG_CONFIGA 0x400#define LPTREG_TFIFO 0x400#define LPTREG_DFIFO 0x400#define LPTREG_AFIFO 0x000#define LPTREG_DSR 0x001#define LPTREG_DCR 0x002/* EPP specific registers */#define LPTREG_EPPDATA 0x004#define LPTREG_EPPADDR 0x003/* standard registers */#define LPTREG_CONTROL 0x002#define LPTREG_STATUS 0x001#define LPTREG_DATA 0x000/* ECP config A */#define LPTCFGA_INTRISALEVEL 0x80#define LPTCFGA_IMPIDMASK 0x70#define LPTCFGA_IMPID16BIT 0x00#define LPTCFGA_IMPID8BIT 0x10#define LPTCFGA_IMPID32BIT 0x20#define LPTCFGA_NOPIPELINE 0x04#define LPTCFGA_PWORDCOUNT 0x03/* ECP config B */#define LPTCFGB_COMPRESS 0x80#define LPTCFGB_INTRVALUE 0x40#define LPTCFGB_IRQMASK 0x38#define LPTCFGB_IRQ5 0x38#define LPTCFGB_IRQ15 0x30#define LPTCFGB_IRQ14 0x28#define LPTCFGB_IRQ11 0x20#define LPTCFGB_IRQ10 0x18#define LPTCFGB_IRQ9 0x10#define LPTCFGB_IRQ7 0x08#define LPTCFGB_IRQJUMPER 0x00#define LPTCFGB_DMAMASK 0x07#define LPTCFGB_DMA7 0x07#define LPTCFGB_DMA6 0x06#define LPTCFGB_DMA5 0x05#define LPTCFGB_DMAJUMPER16 0x04#define LPTCFGB_DMA3 0x03#define LPTCFGB_DMA2 0x02#define LPTCFGB_DMA1 0x01#define LPTCFGB_DMAJUMPER8 0x00/* ECP ECR */#define LPTECR_MODEMASK 0xe0#define LPTECR_MODESPP 0x00#define LPTECR_MODEPS2 0x20#define LPTECR_MODESPPFIFO 0x40#define LPTECR_MODEECP 0x60#define LPTECR_MODEECPEPP 0x80#define LPTECR_MODETEST 0xc0#define LPTECR_MODECFG 0xe0#define LPTECR_NERRINTRDIS 0x10#define LPTECR_DMAEN 0x08#define LPTECR_SERVICEINTR 0x04#define LPTECR_FIFOFULL 0x02#define LPTECR_FIFOEMPTY 0x01/* ---------------------------------------------------------------------- */HANDLE pp_ntddkgenport_handle = INVALID_HANDLE_VALUE;unsigned int pp_ntddkgenport_flags = 0;#define FLAGS_PCSPP (1<<0)#define FLAGS_PCPS2 (1<<1)#define FLAGS_PCEPP (1<<2)#define FLAGS_PCECR (1<<3) /* ECR Register Exists */#define FLAGS_PCECP (1<<4)#define FLAGS_PCECPEPP (1<<5)#define FLAGS_PCECPPS2 (1<<6)/* ---------------------------------------------------------------------- */unsigned char pp_ntddkgenport_inb(unsigned int port){ ULONG p = port; UCHAR ch; BOOL res; DWORD retl; if (pp_ntddkgenport_handle == INVALID_HANDLE_VALUE) return 0xff; res = DeviceIoControl(pp_ntddkgenport_handle, IOCTL_GPD_READ_PORT_UCHAR, &p, sizeof(p), &ch, sizeof(ch), &retl, NULL); if (!res) { lprintf(0, "Parport: inb ioctl failed, error 0x%08lx\n", GetLastError()); return 0xff; } if (retl != sizeof(ch)) { lprintf(0, "Parport: inb ioctl returned invalid length, %lu\n", retl); return 0xff; } return ch;}void pp_ntddkgenport_outb(unsigned char val, unsigned int port){ GENPORT_WRITE_INPUT buf; BOOL res; DWORD retl; if (pp_ntddkgenport_handle == INVALID_HANDLE_VALUE) return; buf.PortNumber = port; buf.CharData = val; res = DeviceIoControl(pp_ntddkgenport_handle, IOCTL_GPD_WRITE_PORT_UCHAR, &buf, sizeof(buf), NULL, 0, &retl, NULL); if (!res) { lprintf(0, "Parport: outb ioctl failed, error 0x%08lx\n", GetLastError()); return; }}void pp_ntddkgenport_insb(unsigned int port, unsigned char *bp, unsigned int len){ for (; len > 0; len--, bp++) *bp = pp_ntddkgenport_inb(port);}void pp_ntddkgenport_outsb(unsigned int port, const unsigned char *bp, unsigned int len){ for (; len > 0; len--, bp++) pp_ntddkgenport_outb(*bp, port);}/* ---------------------------------------------------------------------- */extern inline void setecr(unsigned char ecr){ if (pp_ntddkgenport_flags & FLAGS_PCECR) pp_ntddkgenport_outb(ecr, LPTREG_ECONTROL);}int pp_ntddkgenport_epp_clear_timeout(void){ unsigned char r; if (!(pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_EPPTIMEOUT)) return 1; /* To clear timeout some chips require double read */ pp_ntddkgenport_inb(LPTREG_STATUS); r = pp_ntddkgenport_inb(LPTREG_STATUS); pp_ntddkgenport_outb(r | 0x01, LPTREG_STATUS); /* Some reset by writing 1 */ pp_ntddkgenport_outb(r & 0xfe, LPTREG_STATUS); /* Others by writing 0 */ r = pp_ntddkgenport_inb(LPTREG_STATUS); return !(r & 0x01);}/* ---------------------------------------------------------------------- */unsigned char parport_ntddkgenport_read_data(void){ return pp_ntddkgenport_inb(LPTREG_DATA);}void parport_ntddkgenport_write_data(unsigned char d){ pp_ntddkgenport_outb(d, LPTREG_DATA);}unsigned char parport_ntddkgenport_read_status(void){ return pp_ntddkgenport_inb(LPTREG_STATUS);}unsigned char parport_ntddkgenport_read_control(void){ return pp_ntddkgenport_inb(LPTREG_CONTROL);}void parport_ntddkgenport_write_control(unsigned char d){ pp_ntddkgenport_outb(d, LPTREG_CONTROL);}void parport_ntddkgenport_frob_control(unsigned char mask, unsigned char val){ unsigned char d = pp_ntddkgenport_inb(LPTREG_CONTROL); d = (d & (~mask)) ^ val; pp_ntddkgenport_outb(d, LPTREG_CONTROL);}/* ---------------------------------------------------------------------- */unsigned parport_ntddkgenport_epp_write_data(const void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; setecr(0x90); /* EPP mode */ for (; sz > 0; sz--, bp++) { pp_ntddkgenport_outb(*bp, LPTREG_EPPDATA); if (pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_EPPTIMEOUT) { pp_ntddkgenport_epp_clear_timeout(); goto rt; } ret++; } rt: setecr(0x30); /* PS/2 mode */ return ret;}unsigned parport_ntddkgenport_epp_read_data(void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; setecr(0x90); /* EPP mode */ for (; sz > 0; sz--, bp++) { *bp = pp_ntddkgenport_inb(LPTREG_EPPDATA); if (pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_EPPTIMEOUT) { pp_ntddkgenport_epp_clear_timeout(); goto rt; } ret++; } rt: setecr(0x30); /* PS/2 mode */ return ret;}unsigned parport_ntddkgenport_epp_write_addr(const void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; setecr(0x90); /* EPP mode */ for (; sz > 0; sz--, bp++) { pp_ntddkgenport_outb(*bp, LPTREG_EPPADDR); if (pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_EPPTIMEOUT) { pp_ntddkgenport_epp_clear_timeout(); goto rt; } ret++; } rt: setecr(0x30); /* PS/2 mode */ return ret;}unsigned parport_ntddkgenport_epp_read_addr(void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; setecr(0x90); /* EPP mode */ for (; sz > 0; sz--, bp++) { *bp = pp_ntddkgenport_inb(LPTREG_EPPADDR); if (pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_EPPTIMEOUT) { pp_ntddkgenport_epp_clear_timeout(); goto rt; } ret++; } rt: setecr(0x30); /* PS/2 mode */ return ret;}/* ---------------------------------------------------------------------- */unsigned parport_ntddkgenport_emul_epp_write_data(const void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; unsigned tmo; pp_ntddkgenport_outb(LPTCTRL_PROGRAM | LPTCTRL_WRITE, LPTREG_CONTROL); for (; sz > 0; sz--, bp++) { pp_ntddkgenport_outb(*bp, LPTREG_DATA); for (tmo = 0; ; tmo++) { if (pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_WAIT) break; if (tmo > 1000) return ret; } pp_ntddkgenport_outb(LPTCTRL_PROGRAM | LPTCTRL_WRITE | LPTCTRL_DATASTB, LPTREG_CONTROL); for (tmo = 0; ; tmo++) { if (!(pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_WAIT)) break; if (tmo > 1000) return ret; } pp_ntddkgenport_outb(LPTCTRL_PROGRAM | LPTCTRL_WRITE, LPTREG_CONTROL); ret++; } return ret;}unsigned parport_ntddkgenport_emul_epp_read_data(void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; unsigned tmo; pp_ntddkgenport_outb(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION, LPTREG_CONTROL); for (; sz > 0; sz--, bp++) { for (tmo = 0; ; tmo++) { if (pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_WAIT) break; if (tmo > 1000) return ret; } pp_ntddkgenport_outb(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION | LPTCTRL_DATASTB, LPTREG_CONTROL); for (tmo = 0; ; tmo++) { if (!(pp_ntddkgenport_inb(LPTREG_STATUS) & LPTSTAT_WAIT)) break; if (tmo > 1000) return ret; } *bp = pp_ntddkgenport_inb(LPTREG_DATA); pp_ntddkgenport_outb(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION, LPTREG_CONTROL); ret++; } return ret;}unsigned parport_ntddkgenport_emul_epp_write_addr(const void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -