📄 ppntddkgenportinit.c
字号:
if (i <= fifo_depth) lprintf(3, "ECP: readIntrThreshold is %d\n", i); else /* Number of bytes we can read if we get an interrupt. */ i = 0; readIntrThreshold = i; pp_ntddkgenport_outb(0x00, LPTREG_ECONTROL); /* Reset FIFO */ pp_ntddkgenport_outb(0xf4, LPTREG_ECONTROL); /* Configuration mode */ config = pp_ntddkgenport_inb(LPTREG_CONFIGA); pword = (config >> 4) & 0x7; switch (pword) { case 0: pword = 2; lprintf(0, "ECP: Unsupported pword size! (2)\n"); break; case 2: pword = 4; lprintf(0, "ECP: Unsupported pword size! (4)\n"); break; default: lprintf(0, "ECP: Unknown implementation ID (%d)\n", pword); /* Assume 1 */ case 1: pword = 1; } lprintf(3, "ECP: PWord is %d bits\n", 8 * pword); config = pp_ntddkgenport_inb(LPTREG_CONFIGB); lprintf(3, "ECP: Interrupts are ISA-%s\n", config & 0x80 ? "Level" : "Pulses"); if (!(config & 0x40)) lprintf(3, "ECP: IRQ conflict!\n"); /* Go back to mode 000 */ pp_ntddkgenport_outb(pp_ntddkgenport_inb(LPTREG_ECONTROL) & ~0xe0, LPTREG_ECONTROL); return PARPORT_MODE_PCECP;}/* EPP mode detection */static int parport_epp(void){ /* If EPP timeout bit clear then EPP available */ if (!pp_ntddkgenport_epp_clear_timeout()) return 0; /* No way to clear timeout */ /* * Theory: * Write two values to the EPP address register and * read them back. When the transfer times out, the state of * the EPP register is undefined in some cases (EPP 1.9?) but * in others (EPP 1.7, ECPEPP?) it is possible to read back * its value. */ pp_ntddkgenport_epp_clear_timeout(); usleep(30); /* Wait for possible EPP timeout */ pp_ntddkgenport_outb(0x55, LPTREG_EPPADDR); pp_ntddkgenport_epp_clear_timeout(); usleep(30); /* Wait for possible EPP timeout */ if (pp_ntddkgenport_inb(LPTREG_EPPADDR) == 0x55) { pp_ntddkgenport_outb(0xaa, LPTREG_EPPADDR); pp_ntddkgenport_epp_clear_timeout(); usleep(30); /* Wait for possible EPP timeout */ if (pp_ntddkgenport_inb(LPTREG_EPPADDR) == 0xaa) { pp_ntddkgenport_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. */ pp_ntddkgenport_outb(pp_ntddkgenport_inb(LPTREG_CONTROL) | 0x20, LPTREG_CONTROL); pp_ntddkgenport_outb(pp_ntddkgenport_inb(LPTREG_CONTROL) | 0x10, LPTREG_CONTROL); pp_ntddkgenport_epp_clear_timeout(); pp_ntddkgenport_inb(LPTREG_EPPDATA); usleep(30); /* Wait for possible EPP timeout */ if (pp_ntddkgenport_inb(LPTREG_STATUS) & 0x01) { pp_ntddkgenport_epp_clear_timeout(); return PARPORT_MODE_PCEPP; } return 0;}static int parport_ecpepp(void){ int mode; unsigned char oecr; oecr = pp_ntddkgenport_inb(LPTREG_ECONTROL); /* Search for SMC style EPP+ECP mode */ pp_ntddkgenport_outb(0x80, LPTREG_ECONTROL); mode = parport_epp(); pp_ntddkgenport_outb(oecr, LPTREG_ECONTROL); 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 = pp_ntddkgenport_inb(LPTREG_CONTROL); pp_ntddkgenport_epp_clear_timeout(); pp_ntddkgenport_outb(octr | 0x20, LPTREG_CONTROL); /* try to tri-state the buffer */ pp_ntddkgenport_outb(0x55, LPTREG_DATA); if (pp_ntddkgenport_inb(LPTREG_DATA) != 0x55) ok++; pp_ntddkgenport_outb(0xaa, LPTREG_DATA); if (pp_ntddkgenport_inb(LPTREG_DATA) != 0xaa) ok++; pp_ntddkgenport_outb(octr, 0); /* cancel input mode */ return ok ? PARPORT_MODE_PCPS2 : 0;}static int parport_ecpps2(void){ int mode; unsigned char oecr; oecr = pp_ntddkgenport_inb(LPTREG_ECONTROL); pp_ntddkgenport_outb(0x20, LPTREG_ECONTROL); mode = parport_ps2(); pp_ntddkgenport_outb(oecr, LPTREG_ECONTROL); return mode ? PARPORT_MODE_PCECPPS2 : 0;}/* ---------------------------------------------------------------------- */int parport_init_ntddkgenport(void){ if (pp_ntddkgenport_handle != INVALID_HANDLE_VALUE) CloseHandle(pp_ntddkgenport_handle); pp_ntddkgenport_handle = CreateFile(DEVNAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (pp_ntddkgenport_handle == INVALID_HANDLE_VALUE) { lprintf(0, "Cannot open genport.sys driver, error 0x%08lx\n", GetLastError()); return -1; } pp_ntddkgenport_flags = FLAGS_PCSPP; if (!parport_spp()) { lprintf(0, "No parport present\n"); goto err; } if (parport_ecr()) { pp_ntddkgenport_flags |= FLAGS_PCECR; pp_ntddkgenport_flags |= parport_ecp(); pp_ntddkgenport_flags |= parport_ecpps2(); pp_ntddkgenport_flags |= parport_ecpepp(); } else { pp_ntddkgenport_flags |= parport_ps2(); pp_ntddkgenport_flags |= parport_epp(); } lprintf(0, "Parport capabilities: SPP"); if (pp_ntddkgenport_flags & FLAGS_PCPS2) lprintf(0, ", PS2"); if (pp_ntddkgenport_flags & FLAGS_PCEPP) lprintf(0, ", EPP"); if (pp_ntddkgenport_flags & FLAGS_PCECR) lprintf(0, ", ECR"); if (pp_ntddkgenport_flags & FLAGS_PCECP) lprintf(0, ", ECP"); if (pp_ntddkgenport_flags & FLAGS_PCECPEPP) lprintf(0, ", ECPEPP"); if (pp_ntddkgenport_flags & FLAGS_PCECPPS2) lprintf(0, ", ECPPS2"); if (!(pp_ntddkgenport_flags & (FLAGS_PCPS2 | FLAGS_PCECPPS2))) { lprintf(0, "\nParport does not even support PS/2 mode, cannot use it\n"); goto err; } lprintf(0, "\nParport using NTDDK genport.sys hardware access"); if (pp_ntddkgenport_flags & FLAGS_PCECR) pp_ntddkgenport_outb(0x30, LPTREG_ECONTROL); /* PS/2 mode */ parport_ops = parport_ntddkgenport_ops; if (!(pp_ntddkgenport_flags & FLAGS_PCECP)) { parport_ops.parport_ecp_write_data = parport_ntddkgenport_emul_ops.parport_ecp_write_data; parport_ops.parport_ecp_read_data = parport_ntddkgenport_emul_ops.parport_ecp_read_data; parport_ops.parport_ecp_write_addr = parport_ntddkgenport_emul_ops.parport_ecp_write_addr; lprintf(0, ", emulating ECP"); } if (!(pp_ntddkgenport_flags & (FLAGS_PCEPP | FLAGS_PCECPEPP))) { parport_ops.parport_epp_write_data = parport_ntddkgenport_emul_ops.parport_epp_write_data; parport_ops.parport_epp_read_data = parport_ntddkgenport_emul_ops.parport_epp_read_data; parport_ops.parport_epp_write_addr = parport_ntddkgenport_emul_ops.parport_epp_write_addr; parport_ops.parport_epp_read_addr = parport_ntddkgenport_emul_ops.parport_epp_read_addr; lprintf(0, ", emulating EPP"); } lprintf(0, "\n"); return 0; err: CloseHandle(pp_ntddkgenport_handle); pp_ntddkgenport_handle = INVALID_HANDLE_VALUE; return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -