📄 ppw9xring0.c
字号:
break; if (tmo > 1000) return ret; } ring0_outb(LPTCTRL_PROGRAM | LPTCTRL_WRITE | LPTCTRL_ADDRSTB, pp_w9xring0_iobase + LPTREG_CONTROL); for (tmo = 0; ; tmo++) { if (!(ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & LPTSTAT_WAIT)) break; if (tmo > 1000) return ret; } ring0_outb(LPTCTRL_PROGRAM | LPTCTRL_WRITE, pp_w9xring0_iobase + LPTREG_CONTROL); ret++; } return ret;}unsigned parport_w9xring0_emul_epp_read_addr(void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; unsigned tmo; ring0_outb(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION, pp_w9xring0_iobase + LPTREG_CONTROL); for (; sz > 0; sz--, bp++) { for (tmo = 0; ; tmo++) { if (ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & LPTSTAT_WAIT) break; if (tmo > 1000) return ret; } ring0_outb(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION | LPTCTRL_ADDRSTB, pp_w9xring0_iobase + LPTREG_CONTROL); for (tmo = 0; ; tmo++) { if (!(ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & LPTSTAT_WAIT)) break; if (tmo > 1000) return ret; } *bp = ring0_inb(pp_w9xring0_iobase + LPTREG_DATA); ring0_outb(LPTCTRL_PROGRAM | LPTCTRL_DIRECTION, pp_w9xring0_iobase + LPTREG_CONTROL); ret++; } return ret;}/* ---------------------------------------------------------------------- */static int ecp_forward(void){ unsigned tmo = 0x10000; if (ring0_inb(pp_w9xring0_iobase + LPTREG_DSR) & 0x20) return 0; /* Event 47: Set nInit high */ ring0_outb(0x26, pp_w9xring0_iobase + LPTREG_DCR); /* Event 49: PError goes high */ while (!(ring0_inb(pp_w9xring0_iobase + LPTREG_DSR) & 0x20)) { if (!(--tmo)) return -1; } /* start driving the bus */ ring0_outb(0x04, pp_w9xring0_iobase + LPTREG_DCR); return 0;}static int ecp_reverse(void){ unsigned tmo = 0x10000; if (!(ring0_inb(pp_w9xring0_iobase + LPTREG_DSR) & 0x20)) return 0; ring0_outb(0x24, pp_w9xring0_iobase + LPTREG_DCR); /* Event 39: Set nInit low to initiate bus reversal */ ring0_outb(0x20, pp_w9xring0_iobase + LPTREG_DCR); while (ring0_inb(pp_w9xring0_iobase + LPTREG_DSR) & 0x20) { if (!(--tmo)) return -1; } return 0;}static unsigned emptyfifo(unsigned cnt){ unsigned fcnt = 0; ring0_outb(0xd0, pp_w9xring0_iobase + LPTREG_ECONTROL); /* FIFOtest mode */ while ((ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x01) && fcnt < 32 && fcnt < cnt) { ring0_inb(pp_w9xring0_iobase + LPTREG_TFIFO); fcnt++; } printf("emptyfifo: FIFO contained %d bytes\n", fcnt); ring0_outb(0x30, pp_w9xring0_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return cnt - fcnt;}unsigned parport_w9xring0_ecp_write_data(const void *buf, unsigned sz){ const unsigned char *bp = (const unsigned char *)buf; unsigned ret = 0; unsigned tmo = 0x10000; unsigned char stat; if (ecp_forward()) return 0; ring0_outb(0x70, pp_w9xring0_iobase + LPTREG_ECONTROL); /* ECP mode */ while (sz > 0) { while ((stat = ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL)) & 0x02) { if (!(--tmo)) return emptyfifo(ret); } if (stat & 0x01 && sz >= 8) { ring0_outsb(pp_w9xring0_iobase + LPTREG_DFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { ring0_outb(*bp++, pp_w9xring0_iobase + LPTREG_DFIFO); sz--; ret++; } tmo = 0x10000; } while (!(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x01) || !(ring0_inb(pp_w9xring0_iobase + LPTREG_DSR) & 0x80)) { if (!(--tmo)) return emptyfifo(ret); } ring0_outb(0x30, pp_w9xring0_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret;}unsigned parport_w9xring0_ecp_read_data(void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; unsigned tmo = 0x10000; unsigned char stat; if (ecp_reverse()) return 0; ring0_outb(0x70, pp_w9xring0_iobase + LPTREG_ECONTROL); /* ECP mode */ while (sz > 0) { while ((stat = ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL)) & 0x01) if (!(--tmo)) { ring0_outb(0xd0, pp_w9xring0_iobase + LPTREG_ECONTROL); /* FIFOTEST mode */ while (!(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x01) && sz > 0) { *bp++ = ring0_inb(pp_w9xring0_iobase + LPTREG_TFIFO); sz--; ret++; } ring0_outb(0x30, pp_w9xring0_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret; } if (stat & 0x02 && sz >= 8) { ring0_insb(pp_w9xring0_iobase + LPTREG_DFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { *bp++ = ring0_inb(pp_w9xring0_iobase + LPTREG_DFIFO); sz--; ret++; } tmo = 0x10000; } ring0_outb(0x30, pp_w9xring0_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret;}unsigned parport_w9xring0_ecp_write_addr(const void *buf, unsigned sz){ const unsigned char *bp = (const unsigned char *)buf; unsigned ret = 0; unsigned tmo = 0x10000; unsigned char stat; if (ecp_forward()) return 0; ring0_outb(0x70, pp_w9xring0_iobase + LPTREG_ECONTROL); /* ECP mode */ while (sz > 0) { while ((stat = ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL)) & 0x02) { if (!(--tmo)) return emptyfifo(ret); } if (stat & 0x01 && sz >= 8) { ring0_outsb(pp_w9xring0_iobase + LPTREG_AFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { ring0_outb(*bp++, pp_w9xring0_iobase + LPTREG_AFIFO); sz--; ret++; } tmo = 0x10000; } while (!(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x01) || !(ring0_inb(pp_w9xring0_iobase + LPTREG_DSR) & 0x80)) { if (!(--tmo)) return emptyfifo(ret); } ring0_outb(0x30, pp_w9xring0_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret;}/* ---------------------------------------------------------------------- */unsigned parport_w9xring0_emul_ecp_write_data(const void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret; unsigned char ctl; unsigned tmo; if (ecp_forward()) return 0; ctl = ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL) & ~PARPORT_CONTROL_AUTOFD; /* HostAck high (data, not command) */ ring0_outb(ctl, pp_w9xring0_iobase + LPTREG_CONTROL); for (ret = 0; ret < sz; ret++, bp++) { ring0_outb(*bp, pp_w9xring0_iobase + LPTREG_DATA); ring0_outb(ctl | PARPORT_CONTROL_STROBE, pp_w9xring0_iobase + LPTREG_CONTROL); for (tmo = 0; ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY; tmo++) if (tmo > 0x1000) return ret; ring0_outb(ctl, pp_w9xring0_iobase + LPTREG_CONTROL); for (tmo = 0; !(ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY); tmo++) if (tmo > 0x1000) return ret; } return ret;}unsigned parport_w9xring0_emul_ecp_write_addr(const void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret; unsigned char ctl; unsigned tmo; if (ecp_forward()) return 0; ctl = ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL) | PARPORT_CONTROL_AUTOFD; /* HostAck low (command, not data) */ ring0_outb(ctl, pp_w9xring0_iobase + LPTREG_CONTROL); for (ret = 0; ret < sz; ret++, bp++) { ring0_outb(*bp, pp_w9xring0_iobase + LPTREG_DATA); ring0_outb(ctl | PARPORT_CONTROL_STROBE, pp_w9xring0_iobase + LPTREG_CONTROL); for (tmo = 0; ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY; tmo++) if (tmo > 0x1000) return ret; ring0_outb(ctl, pp_w9xring0_iobase + LPTREG_CONTROL); for (tmo = 0; !(ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY); tmo++) if (tmo > 0x1000) return ret; } return ret;}unsigned parport_w9xring0_emul_ecp_read_data(void *buf, unsigned sz){ unsigned char *bp = (unsigned char *)buf; unsigned ret = 0; unsigned char ctl, stat; int command; unsigned tmo; if (ecp_reverse()) return 0; ctl = ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL); /* Set HostAck low to start accepting data. */ ring0_outb(ctl | PARPORT_CONTROL_AUTOFD, pp_w9xring0_iobase + LPTREG_CONTROL); while (ret < sz) { /* Event 43: Peripheral sets nAck low. It can take as long as it wants. */ tmo = 0; do { stat = ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS); if ((++tmo) > 0x10000) goto out; } while (stat & PARPORT_STATUS_ACK); /* Is this a command? */ command = stat & PARPORT_STATUS_BUSY; if (command) { //lprintf(3, "ECP: warning: emulation does not support RLE\n"); goto out; } /* Read the data. */ *bp = ring0_inb(pp_w9xring0_iobase + LPTREG_DATA); /* Event 44: Set HostAck high, acknowledging handshake. */ ring0_outb(ctl & ~PARPORT_CONTROL_AUTOFD, pp_w9xring0_iobase + LPTREG_CONTROL); /* Event 45: The peripheral has 35ms to set nAck high. */ tmo = 0; do { stat = ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS); if ((++tmo) > 0x10000) goto out; } while (!(stat & PARPORT_STATUS_ACK)); /* Event 46: Set HostAck low and accept the data. */ ring0_outb(ctl | PARPORT_CONTROL_AUTOFD, pp_w9xring0_iobase + LPTREG_CONTROL); /* Normal data byte. */ bp++; ret++; } out: return ret;} /* ---------------------------------------------------------------------- */#if 1unsigned parport_w9xring0_fpgaconfig_write(const void *buf, unsigned sz){ const unsigned char *bp = buf; unsigned u; for (u = 0; u < sz; u++, bp++) ring0_outb(*bp, pp_w9xring0_iobase + LPTREG_DATA); return sz;}#elseunsigned parport_w9xring0_fpgaconfig_write(const void *buf, unsigned sz){ const unsigned char *bp = buf; unsigned ret = 0; unsigned tmo = 0x10000; unsigned char stat; if (pp_w9xring0_modes & PARPORT_MODE_PCECR) { ring0_outb(0x50, pp_w9xring0_iobase + LPTREG_ECONTROL); /* COMPAT FIFO mode */ while (sz > 0) { while ((stat = ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL)) & 0x02) { if (!(--tmo)) return emptyfifo(ret); } if (stat & 0x01 && sz >= 8) { ring0_outsb(pp_w9xring0_iobase + LPTREG_DFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { ring0_outb(*bp++, pp_w9xring0_iobase + LPTREG_DFIFO); sz--; ret++; } tmo = 0x10000; } while (!(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x01) || !(ring0_inb(pp_w9xring0_iobase + LPTREG_DSR) & 0x80)) { if (!(--tmo)) return emptyfifo(ret); } ring0_outb(0x30, pp_w9xring0_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret; } for (ret = 0; ret < sz; ret++, bp++) ring0_outb(*bp, pp_w9xring0_iobase + LPTREG_DATA); return sz;}#endif/* ---------------------------------------------------------------------- */const struct parport_ops parport_w9xring0_ops = { parport_w9xring0_read_data, parport_w9xring0_write_data, parport_w9xring0_read_status, parport_w9xring0_read_control, parport_w9xring0_write_control, parport_w9xring0_frob_control, parport_w9xring0_epp_write_data, parport_w9xring0_epp_read_data, parport_w9xring0_epp_write_addr, parport_w9xring0_epp_read_addr, parport_w9xring0_ecp_write_data, parport_w9xring0_ecp_read_data, parport_w9xring0_ecp_write_addr, parport_w9xring0_fpgaconfig_write};const struct parport_ops parport_w9xring0_emul_ops = { parport_w9xring0_read_data, parport_w9xring0_write_data, parport_w9xring0_read_status, parport_w9xring0_read_control, parport_w9xring0_write_control, parport_w9xring0_frob_control, parport_w9xring0_emul_epp_write_data, parport_w9xring0_emul_epp_read_data, parport_w9xring0_emul_epp_write_addr, parport_w9xring0_emul_epp_read_addr, parport_w9xring0_emul_ecp_write_data, parport_w9xring0_emul_ecp_read_data, parport_w9xring0_emul_ecp_write_addr, parport_w9xring0_fpgaconfig_write};/* ---------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -