📄 ppwininit.c
字号:
usleep(30); /* Wait for possible EPP timeout */ parport_win_write_eppaddr(0x55); pp_win_epp_clear_timeout(); usleep(30); /* Wait for possible EPP timeout */ if (parport_win_read_eppaddr() == 0x55) { parport_win_write_eppaddr(0xaa); pp_win_epp_clear_timeout(); usleep(30); /* Wait for possible EPP timeout */ if (parport_win_read_eppaddr() == 0xaa) { pp_win_epp_clear_timeout(); return PARPORT_MODE_PCEPP; } } /* * Theory: * Bit 0 of STR is the EPP timeout bit, this bit is 0 * when EPP is possible and is set high when an EPP timeout * occurs (EPP uses the HALT line to stop the CPU while it does * the byte transfer, an EPP timeout occurs if the attached * device fails to respond after 10 micro seconds). * * This bit is cleared by either reading it (National Semi) * or writing a 1 to the bit (SMC, UMC, WinBond), others ??? * This bit is always high in non EPP modes. */ parport_win_frob_control(0x20, 0x20); parport_win_frob_control(0x10, 0x10); pp_win_epp_clear_timeout(); parport_win_read_eppdata(); usleep(30); /* Wait for possible EPP timeout */ if (parport_win_read_status() & 0x01) { pp_win_epp_clear_timeout(); return PARPORT_MODE_PCEPP; } return 0;}static int parport_ecpepp(void){ int mode; unsigned char oecr; oecr = parport_win_read_econtrol(); /* Search for SMC style EPP+ECP mode */ parport_win_write_econtrol(0x80); mode = parport_epp(); parport_win_write_econtrol(oecr); return mode ? PARPORT_MODE_PCECPEPP : 0;}/* Detect PS/2 support. * * Bit 5 (0x20) sets the PS/2 data direction; setting this high * allows us to read data from the data lines. In theory we would get back * 0xff but any peripheral attached to the port may drag some or all of the * lines down to zero. So if we get back anything that isn't the contents * of the data register we deem PS/2 support to be present. * * Some SPP ports have "half PS/2" ability - you can't turn off the line * drivers, but an external peripheral with sufficiently beefy drivers of * its own can overpower them and assert its own levels onto the bus, from * where they can then be read back as normal. Ports with this property * and the right type of device attached are likely to fail the SPP test, * (as they will appear to have stuck bits) and so the fact that they might * be misdetected here is rather academic. */static int parport_ps2(void){ int ok = 0; unsigned char octr = parport_win_read_control(); pp_win_epp_clear_timeout(); parport_win_write_control(octr | 0x20); /* try to tri-state the buffer */ parport_win_write_data(0x55); if (parport_win_read_data() != 0x55) ok++; parport_win_write_data(0xaa); if (parport_win_read_data() != 0xaa) ok++; parport_win_write_control(octr); /* cancel input mode */ return ok ? PARPORT_MODE_PCPS2 : 0;}static int parport_ecpps2(void){ int mode; unsigned char oecr; oecr = parport_win_read_econtrol(); parport_win_write_econtrol(0x20); mode = parport_ps2(); parport_win_write_econtrol(oecr); return mode ? PARPORT_MODE_PCECPPS2 : 0;}/* ---------------------------------------------------------------------- */#define SERVICENAME "eppflex"#define SERVICEDISPLAYNAME "Baycom EPPFLEX"//#define SERVICEBINARY "\"\\??\\g:\\nteppflex\\eppflex.sys\""#define SERVICEBINARY "System32\\drivers\\eppflex.sys"static int start_service(void){ int ret = -1; SC_HANDLE hscm, hserv; hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (!hscm) { lprintf(5, "Cannot open SC manager, error 0x%08lx\n", GetLastError()); return -1; } hserv = CreateService(hscm, SERVICENAME, SERVICEDISPLAYNAME, SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, SERVICEBINARY, NULL, NULL, NULL, NULL, NULL); if (!hserv) { lprintf(5, "Cannot create service, error 0x%08lx\n", GetLastError()); hserv = OpenService(hscm, SERVICENAME, SERVICE_ALL_ACCESS); if (!hserv) { lprintf(5, "Cannot open service, error 0x%08lx\n", GetLastError()); goto closescm; } } if (!StartService(hserv, 0, NULL)) { lprintf(5, "Cannot start service, error 0x%08lx\n", GetLastError()); goto closeserv; } lprintf(1, "Service %s started successfully\n", SERVICENAME); ret = 0; closeserv: if (!CloseServiceHandle(hserv)) lprintf(5, "Cannot close service handle, error 0x%08lx\n", GetLastError()); closescm: if (!CloseServiceHandle(hscm)) lprintf(5, "Cannot close service manager handle, error 0x%08lx\n", GetLastError()); return ret;}static int stop_service(void){ int ret = -1; SC_HANDLE hscm, hserv; SERVICE_STATUS sstat; hscm = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (!hscm) { lprintf(5, "Cannot open SC manager, error 0x%08lx\n", GetLastError()); return -1; } hserv = OpenService(hscm, SERVICENAME, SERVICE_ALL_ACCESS); if (!hserv) { lprintf(5, "Cannot open service, error 0x%08lx\n", GetLastError()); goto closescm; } ret = 0; if (!ControlService(hserv, SERVICE_CONTROL_STOP, &sstat)) { lprintf(5, "Cannot delete service, error 0x%08lx\n", GetLastError()); ret = -1; } if (!DeleteService(hserv)) { lprintf(5, "Cannot delete service, error 0x%08lx\n", GetLastError()); ret = -1; } if (!ret) lprintf(1, "Service %s stopped successfully\n", SERVICENAME); if (!CloseServiceHandle(hserv)) lprintf(5, "Cannot close service handle, error 0x%08lx\n", GetLastError()); closescm: if (!CloseServiceHandle(hscm)) lprintf(5, "Cannot close service manager handle, error 0x%08lx\n", GetLastError()); return ret;}/* ---------------------------------------------------------------------- */extern inline int isnt(){ OSVERSIONINFO info; info.dwOSVersionInfoSize = sizeof(info); if (GetVersionEx(&info) && info.dwPlatformId == VER_PLATFORM_WIN32_NT) return 1; return 0;}/* ---------------------------------------------------------------------- */void parport_stop_win(void){ DWORD bytesret; int nt = isnt(); if (pp_win_handle != INVALID_HANDLE_VALUE) { if (!nt) DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_RELEASEPORT, NULL, 0, NULL, 0, &bytesret, NULL); CloseHandle(pp_win_handle); } pp_win_handle = INVALID_HANDLE_VALUE; if (nt) stop_service();}/* ---------------------------------------------------------------------- */int parport_init_win_flags(unsigned int portnr, unsigned int flags){ char buf[32]; DWORD bytesret; if (pp_win_handle != INVALID_HANDLE_VALUE) CloseHandle(pp_win_handle); if (isnt()) { start_service(); snprintf(buf, sizeof(buf), "\\\\.\\eppflex\\%u", portnr); pp_win_handle = CreateFile(buf, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (pp_win_handle == INVALID_HANDLE_VALUE) { lprintf(0, "Cannot open eppflex.sys driver, error 0x%08lx\n", GetLastError()); goto err; } } else { pp_win_handle = CreateFile("\\\\.\\EPPFLEX.VXD", 0, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); if (pp_win_handle == INVALID_HANDLE_VALUE) { lprintf(0, "Cannot open eppflex.vxd driver, error 0x%08lx\n", GetLastError()); goto err; } if (!DeviceIoControl(pp_win_handle, IOCTL_EPPFLEX_ACQUIREPORT, &portnr, sizeof(portnr), NULL, 0, &bytesret, NULL)) { CloseHandle(pp_win_handle); pp_win_handle = INVALID_HANDLE_VALUE; lprintf(0, "Cannot open acquire port LPT%u, error 0x%08lx\n", portnr+1, GetLastError()); goto err; } } pp_win_flags = FLAGS_PCSPP; if (!parport_spp()) { lprintf(0, "No parport present\n"); goto err; } if (parport_ecr()) { pp_win_flags |= FLAGS_PCECR; pp_win_flags |= parport_ecp(); pp_win_flags |= parport_ecpps2(); pp_win_flags |= parport_ecpepp(); if ((flags & PPFLAG_FORCEHWEPP) && (pp_win_flags & (FLAGS_PCPS2|FLAGS_PCECPPS2)) && !(pp_win_flags & (FLAGS_PCEPP|FLAGS_PCECPEPP))) pp_win_flags |= FLAGS_PCECPEPP; else flags &= ~PPFLAG_FORCEHWEPP; } else { pp_win_flags |= parport_ps2(); pp_win_flags |= parport_epp(); if ((flags & PPFLAG_FORCEHWEPP) && (pp_win_flags & (FLAGS_PCPS2|FLAGS_PCECPPS2)) && !(pp_win_flags & (FLAGS_PCEPP|FLAGS_PCECPEPP))) pp_win_flags |= FLAGS_PCEPP; else flags &= ~PPFLAG_FORCEHWEPP; } lprintf(0, "Parport capabilities: SPP%s%s%s%s%s%s\n", (pp_win_flags & FLAGS_PCPS2) ? ", PS2" : "", (pp_win_flags & FLAGS_PCEPP) ? ((flags & PPFLAG_FORCEHWEPP) ? ", EPP (forced)" : ", EPP") : "", (pp_win_flags & FLAGS_PCECR) ? ", ECR" : "", (pp_win_flags & FLAGS_PCECP) ? ", ECP" : "", (pp_win_flags & FLAGS_PCECPEPP) ? ((flags & PPFLAG_FORCEHWEPP) ? ", ECPEPP (forced)" : ", ECPEPP") : "", (pp_win_flags & FLAGS_PCECPPS2) ? ", ECPPS2" : ""); if (!(pp_win_flags & (FLAGS_PCPS2 | FLAGS_PCECPPS2))) { lprintf(0, "Parport does not even support PS/2 mode, cannot use it\n"); goto err; } lprintf(0, "Parport using eppflex.sys/vxd hardware access"); if (pp_win_flags & FLAGS_PCECR) parport_win_write_econtrol(0x30); /* PS/2 mode */ parport_ops = parport_win_ops; if ((flags & PPFLAG_SWEMULECP) || !(pp_win_flags & FLAGS_PCECP)) { parport_ops.parport_ecp_write_data = parport_win_emul_ops.parport_ecp_write_data; parport_ops.parport_ecp_read_data = parport_win_emul_ops.parport_ecp_read_data; parport_ops.parport_ecp_write_addr = parport_win_emul_ops.parport_ecp_write_addr; lprintf(0, ", emulating ECP"); } if ((flags & PPFLAG_SWEMULEPP) || !(pp_win_flags & (FLAGS_PCEPP | FLAGS_PCECPEPP))) { parport_ops.parport_epp_write_data = parport_win_emul_ops.parport_epp_write_data; parport_ops.parport_epp_read_data = parport_win_emul_ops.parport_epp_read_data; parport_ops.parport_epp_write_addr = parport_win_emul_ops.parport_epp_write_addr; parport_ops.parport_epp_read_addr = parport_win_emul_ops.parport_epp_read_addr; lprintf(0, ", emulating EPP"); } lprintf(0, "\n"); return 0; err: parport_stop_win(); return -1;}int parport_init_win(unsigned int portnr){ return parport_init_win_flags(portnr, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -