📄 ppdirect.c
字号:
{ unsigned tmo = 0x10000; if (inb(pp_direct_iobase + LPTREG_DSR) & 0x20) return 0; /* Event 47: Set nInit high */ outb(0x26, pp_direct_iobase + LPTREG_DCR); /* Event 49: PError goes high */ while (!(inb(pp_direct_iobase + LPTREG_DSR) & 0x20)) { if (!(--tmo)) return -1; } /* start driving the bus */ outb(0x04, pp_direct_iobase + LPTREG_DCR); return 0;}static int ecp_reverse(void){ unsigned tmo = 0x10000; if (!(inb(pp_direct_iobase + LPTREG_DSR) & 0x20)) return 0; outb(0x24, pp_direct_iobase + LPTREG_DCR); /* Event 39: Set nInit low to initiate bus reversal */ outb(0x20, pp_direct_iobase + LPTREG_DCR); while (inb(pp_direct_iobase + LPTREG_DSR) & 0x20) { if (!(--tmo)) return -1; } return 0;}static unsigned emptyfifo(unsigned cnt){ unsigned fcnt = 0; outb(0xd0, pp_direct_iobase + LPTREG_ECONTROL); /* FIFOtest mode */ while ((inb(pp_direct_iobase + LPTREG_ECONTROL) & 0x01) && fcnt < 32 && fcnt < cnt) { inb(pp_direct_iobase + LPTREG_TFIFO); fcnt++; } printf("emptyfifo: FIFO contained %d bytes\n", fcnt); outb(0x30, pp_direct_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return cnt - fcnt;}unsigned parport_direct_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; outb(0x70, pp_direct_iobase + LPTREG_ECONTROL); /* ECP mode */ while (sz > 0) { while ((stat = inb(pp_direct_iobase + LPTREG_ECONTROL)) & 0x02) { if (!(--tmo)) return emptyfifo(ret); } if (stat & 0x01 && sz >= 8) { outsb(pp_direct_iobase + LPTREG_DFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { outb(*bp++, pp_direct_iobase + LPTREG_DFIFO); sz--; ret++; } tmo = 0x10000; } while (!(inb(pp_direct_iobase + LPTREG_ECONTROL) & 0x01) || !(inb(pp_direct_iobase + LPTREG_DSR) & 0x80)) { if (!(--tmo)) return emptyfifo(ret); } outb(0x30, pp_direct_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret;}unsigned parport_direct_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; outb(0x70, pp_direct_iobase + LPTREG_ECONTROL); /* ECP mode */ while (sz > 0) { while ((stat = inb(pp_direct_iobase + LPTREG_ECONTROL)) & 0x01) if (!(--tmo)) { outb(0xd0, pp_direct_iobase + LPTREG_ECONTROL); /* FIFOTEST mode */ while (!(inb(pp_direct_iobase + LPTREG_ECONTROL) & 0x01) && sz > 0) { *bp++ = inb(pp_direct_iobase + LPTREG_TFIFO); sz--; ret++; } outb(0x30, pp_direct_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret; } if (stat & 0x02 && sz >= 8) { insb(pp_direct_iobase + LPTREG_DFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { *bp++ = inb(pp_direct_iobase + LPTREG_DFIFO); sz--; ret++; } tmo = 0x10000; } outb(0x30, pp_direct_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret;}unsigned parport_direct_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; outb(0x70, pp_direct_iobase + LPTREG_ECONTROL); /* ECP mode */ while (sz > 0) { while ((stat = inb(pp_direct_iobase + LPTREG_ECONTROL)) & 0x02) { if (!(--tmo)) return emptyfifo(ret); } if (stat & 0x01 && sz >= 8) { outsb(pp_direct_iobase + LPTREG_AFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { outb(*bp++, pp_direct_iobase + LPTREG_AFIFO); sz--; ret++; } tmo = 0x10000; } while (!(inb(pp_direct_iobase + LPTREG_ECONTROL) & 0x01) || !(inb(pp_direct_iobase + LPTREG_DSR) & 0x80)) { if (!(--tmo)) return emptyfifo(ret); } outb(0x30, pp_direct_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret;}/* ---------------------------------------------------------------------- */unsigned parport_direct_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 = inb(pp_direct_iobase + LPTREG_CONTROL) & ~PARPORT_CONTROL_AUTOFD; /* HostAck high (data, not command) */ outb(ctl, pp_direct_iobase + LPTREG_CONTROL); for (ret = 0; ret < sz; ret++, bp++) { outb(*bp, pp_direct_iobase + LPTREG_DATA); outb(ctl | PARPORT_CONTROL_STROBE, pp_direct_iobase + LPTREG_CONTROL); for (tmo = 0; inb(pp_direct_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY; tmo++) if (tmo > 0x1000) return ret; outb(ctl, pp_direct_iobase + LPTREG_CONTROL); for (tmo = 0; !(inb(pp_direct_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY); tmo++) if (tmo > 0x1000) return ret; } return ret;}unsigned parport_direct_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 = inb(pp_direct_iobase + LPTREG_CONTROL) | PARPORT_CONTROL_AUTOFD; /* HostAck low (command, not data) */ outb(ctl, pp_direct_iobase + LPTREG_CONTROL); for (ret = 0; ret < sz; ret++, bp++) { outb(*bp, pp_direct_iobase + LPTREG_DATA); outb(ctl | PARPORT_CONTROL_STROBE, pp_direct_iobase + LPTREG_CONTROL); for (tmo = 0; inb(pp_direct_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY; tmo++) if (tmo > 0x1000) return ret; outb(ctl, pp_direct_iobase + LPTREG_CONTROL); for (tmo = 0; !(inb(pp_direct_iobase + LPTREG_STATUS) & PARPORT_STATUS_BUSY); tmo++) if (tmo > 0x1000) return ret; } return ret;}unsigned parport_direct_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 = inb(pp_direct_iobase + LPTREG_CONTROL); /* Set HostAck low to start accepting data. */ outb(ctl | PARPORT_CONTROL_AUTOFD, pp_direct_iobase + LPTREG_CONTROL); while (ret < sz) { /* Event 43: Peripheral sets nAck low. It can take as long as it wants. */ tmo = 0; do { stat = inb(pp_direct_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 = inb(pp_direct_iobase + LPTREG_DATA); /* Event 44: Set HostAck high, acknowledging handshake. */ outb(ctl & ~PARPORT_CONTROL_AUTOFD, pp_direct_iobase + LPTREG_CONTROL); /* Event 45: The peripheral has 35ms to set nAck high. */ tmo = 0; do { stat = inb(pp_direct_iobase + LPTREG_STATUS); if ((++tmo) > 0x10000) goto out; } while (!(stat & PARPORT_STATUS_ACK)); /* Event 46: Set HostAck low and accept the data. */ outb(ctl | PARPORT_CONTROL_AUTOFD, pp_direct_iobase + LPTREG_CONTROL); /* Normal data byte. */ bp++; ret++; } out: return ret;} /* ---------------------------------------------------------------------- */#if 1unsigned parport_direct_fpgaconfig_write(const void *buf, unsigned sz){ const unsigned char *bp = buf; unsigned u; for (u = 0; u < sz; u++, bp++) outb(*bp, pp_direct_iobase + LPTREG_DATA); return sz;}#elseunsigned parport_direct_fpgaconfig_write(const void *buf, unsigned sz){ const unsigned char *bp = buf; unsigned ret = 0; unsigned tmo = 0x10000; unsigned char stat; if (pp_direct_modes & PARPORT_MODE_PCECR) { outb(0x50, pp_direct_iobase + LPTREG_ECONTROL); /* COMPAT FIFO mode */ while (sz > 0) { while ((stat = inb(pp_direct_iobase + LPTREG_ECONTROL)) & 0x02) { if (!(--tmo)) return emptyfifo(ret); } if (stat & 0x01 && sz >= 8) { outsb(pp_direct_iobase + LPTREG_DFIFO, bp, 8); bp += 8; sz -= 8; ret += 8; } else { outb(*bp++, pp_direct_iobase + LPTREG_DFIFO); sz--; ret++; } tmo = 0x10000; } while (!(inb(pp_direct_iobase + LPTREG_ECONTROL) & 0x01) || !(inb(pp_direct_iobase + LPTREG_DSR) & 0x80)) { if (!(--tmo)) return emptyfifo(ret); } outb(0x30, pp_direct_iobase + LPTREG_ECONTROL); /* PS/2 mode */ return ret; } for (ret = 0; ret < sz; ret++, bp++) outb(*bp, pp_direct_iobase + LPTREG_DATA); return sz;}#endif/* ---------------------------------------------------------------------- */const struct parport_ops parport_direct_ops = { parport_direct_read_data, parport_direct_write_data, parport_direct_read_status, parport_direct_read_control, parport_direct_write_control, parport_direct_frob_control, parport_direct_epp_write_data, parport_direct_epp_read_data, parport_direct_epp_write_addr, parport_direct_epp_read_addr, parport_direct_ecp_write_data, parport_direct_ecp_read_data, parport_direct_ecp_write_addr, parport_direct_fpgaconfig_write};const struct parport_ops parport_direct_emul_ops = { parport_direct_read_data, parport_direct_write_data, parport_direct_read_status, parport_direct_read_control, parport_direct_write_control, parport_direct_frob_control, parport_direct_emul_epp_write_data, parport_direct_emul_epp_read_data, parport_direct_emul_epp_write_addr, parport_direct_emul_epp_read_addr, parport_direct_emul_ecp_write_data, parport_direct_emul_ecp_read_data, parport_direct_emul_ecp_write_addr, parport_direct_fpgaconfig_write};/* ---------------------------------------------------------------------- */struct parport_ops parport_ops = { parport_direct_read_data, parport_direct_write_data, parport_direct_read_status, parport_direct_read_control, parport_direct_write_control, parport_direct_frob_control, parport_direct_emul_epp_write_data, parport_direct_emul_epp_read_data, parport_direct_emul_epp_write_addr, parport_direct_emul_epp_read_addr, parport_direct_emul_ecp_write_data, parport_direct_emul_ecp_read_data, parport_direct_emul_ecp_write_addr, parport_direct_fpgaconfig_write};/* ---------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -