📄 parport_ip32.c
字号:
expire = jiffies + physport->cad->timeout; count = 0; while (1) { if (parport_ip32_fifo_wait_break(p, expire)) break; /* Check FIFO state. We do nothing when the FIFO is nor full, * nor empty. It appears that the FIFO full bit is not always * reliable, the FIFO state is sometimes wrongly reported, and * the chip gets confused if we give it another byte. */ ecr = parport_ip32_read_econtrol(p); if (ecr & ECR_F_EMPTY) { /* FIFO is empty, fill it up */ count = priv->fifo_depth; break; } /* Wait a moment... */ udelay(FIFO_POLLING_INTERVAL); } /* while (1) */ return count;}/** * parport_ip32_fwp_wait_interrupt - wait for FIFO to empty (interrupt-driven) * @p: pointer to &struct parport * * Returns the number of bytes that can safely be written in the FIFO. A * return value of zero means that the calling function should terminate as * fast as possible. */static unsigned int parport_ip32_fwp_wait_interrupt(struct parport *p){ static unsigned int lost_interrupt = 0; struct parport_ip32_private * const priv = p->physport->private_data; struct parport * const physport = p->physport; unsigned long nfault_timeout; unsigned long expire; unsigned int count; unsigned int ecr; nfault_timeout = min((unsigned long)physport->cad->timeout, msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); expire = jiffies + physport->cad->timeout; count = 0; while (1) { if (parport_ip32_fifo_wait_break(p, expire)) break; /* Initialize mutex used to take interrupts into account */ INIT_COMPLETION(priv->irq_complete); /* Enable serviceIntr */ parport_ip32_frob_econtrol(p, ECR_SERVINTR, 0); /* Enabling serviceIntr while the FIFO is empty does not * always generate an interrupt, so check for emptiness * now. */ ecr = parport_ip32_read_econtrol(p); if (!(ecr & ECR_F_EMPTY)) { /* FIFO is not empty: wait for an interrupt or a * timeout to occur */ wait_for_completion_interruptible_timeout( &priv->irq_complete, nfault_timeout); ecr = parport_ip32_read_econtrol(p); if ((ecr & ECR_F_EMPTY) && !(ecr & ECR_SERVINTR) && !lost_interrupt) { printk(KERN_WARNING PPIP32 "%s: lost interrupt in %s\n", p->name, __func__); lost_interrupt = 1; } } /* Disable serviceIntr */ parport_ip32_frob_econtrol(p, ECR_SERVINTR, ECR_SERVINTR); /* Check FIFO state */ if (ecr & ECR_F_EMPTY) { /* FIFO is empty, fill it up */ count = priv->fifo_depth; break; } else if (ecr & ECR_SERVINTR) { /* FIFO is not empty, but we know that can safely push * writeIntrThreshold bytes into it */ count = priv->writeIntrThreshold; break; } /* FIFO is not empty, and we did not get any interrupt. * Either it's time to check for nFault, or a signal is * pending. This is verified in * parport_ip32_fifo_wait_break(), so we continue the loop. */ } /* while (1) */ return count;}/** * parport_ip32_fifo_write_block_pio - write a block of data (PIO mode) * @p: pointer to &struct parport * @buf: buffer of data to write * @len: length of buffer @buf * * Uses PIO to write the contents of the buffer @buf into the parallel port * FIFO. Returns the number of bytes that were actually written. It can work * with or without the help of interrupts. The parallel port must be * correctly initialized before calling parport_ip32_fifo_write_block_pio(). */static size_t parport_ip32_fifo_write_block_pio(struct parport *p, const void *buf, size_t len){ struct parport_ip32_private * const priv = p->physport->private_data; const u8 *bufp = buf; size_t left = len; priv->irq_mode = PARPORT_IP32_IRQ_HERE; while (left > 0) { unsigned int count; count = (p->irq == PARPORT_IRQ_NONE) ? parport_ip32_fwp_wait_polling(p) : parport_ip32_fwp_wait_interrupt(p); if (count == 0) break; /* Transmission should be stopped */ if (count > left) count = left; if (count == 1) { writeb(*bufp, priv->regs.fifo); bufp++, left--; } else { writesb(priv->regs.fifo, bufp, count); bufp += count, left -= count; } } priv->irq_mode = PARPORT_IP32_IRQ_FWD; return len - left;}/** * parport_ip32_fifo_write_block_dma - write a block of data (DMA mode) * @p: pointer to &struct parport * @buf: buffer of data to write * @len: length of buffer @buf * * Uses DMA to write the contents of the buffer @buf into the parallel port * FIFO. Returns the number of bytes that were actually written. The * parallel port must be correctly initialized before calling * parport_ip32_fifo_write_block_dma(). */static size_t parport_ip32_fifo_write_block_dma(struct parport *p, const void *buf, size_t len){ struct parport_ip32_private * const priv = p->physport->private_data; struct parport * const physport = p->physport; unsigned long nfault_timeout; unsigned long expire; size_t written; unsigned int ecr; priv->irq_mode = PARPORT_IP32_IRQ_HERE; parport_ip32_dma_start(DMA_TO_DEVICE, (void *)buf, len); INIT_COMPLETION(priv->irq_complete); parport_ip32_frob_econtrol(p, ECR_DMAEN | ECR_SERVINTR, ECR_DMAEN); nfault_timeout = min((unsigned long)physport->cad->timeout, msecs_to_jiffies(FIFO_NFAULT_TIMEOUT)); expire = jiffies + physport->cad->timeout; while (1) { if (parport_ip32_fifo_wait_break(p, expire)) break; wait_for_completion_interruptible_timeout(&priv->irq_complete, nfault_timeout); ecr = parport_ip32_read_econtrol(p); if (ecr & ECR_SERVINTR) break; /* DMA transfer just finished */ } parport_ip32_dma_stop(); written = len - parport_ip32_dma_get_residue(); priv->irq_mode = PARPORT_IP32_IRQ_FWD; return written;}/** * parport_ip32_fifo_write_block - write a block of data * @p: pointer to &struct parport * @buf: buffer of data to write * @len: length of buffer @buf * * Uses PIO or DMA to write the contents of the buffer @buf into the parallel * p FIFO. Returns the number of bytes that were actually written. */static size_t parport_ip32_fifo_write_block(struct parport *p, const void *buf, size_t len){ size_t written = 0; if (len) /* FIXME - Maybe some threshold value should be set for @len * under which we revert to PIO mode? */ written = (p->modes & PARPORT_MODE_DMA) ? parport_ip32_fifo_write_block_dma(p, buf, len) : parport_ip32_fifo_write_block_pio(p, buf, len); return written;}/** * parport_ip32_drain_fifo - wait for FIFO to empty * @p: pointer to &struct parport * @timeout: timeout, in jiffies * * This function waits for FIFO to empty. It returns 1 when FIFO is empty, or * 0 if the timeout @timeout is reached before, or if a signal is pending. */static unsigned int parport_ip32_drain_fifo(struct parport *p, unsigned long timeout){ unsigned long expire = jiffies + timeout; unsigned int polling_interval; unsigned int counter; /* Busy wait for approx. 200us */ for (counter = 0; counter < 40; counter++) { if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) break; if (time_after(jiffies, expire)) break; if (signal_pending(current)) break; udelay(5); } /* Poll slowly. Polling interval starts with 1 millisecond, and is * increased exponentially until 128. */ polling_interval = 1; /* msecs */ while (!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY)) { if (time_after_eq(jiffies, expire)) break; msleep_interruptible(polling_interval); if (signal_pending(current)) break; if (polling_interval < 128) polling_interval *= 2; } return !!(parport_ip32_read_econtrol(p) & ECR_F_EMPTY);}/** * parport_ip32_get_fifo_residue - reset FIFO * @p: pointer to &struct parport * @mode: current operation mode (ECR_MODE_PPF or ECR_MODE_ECP) * * This function resets FIFO, and returns the number of bytes remaining in it. */static unsigned int parport_ip32_get_fifo_residue(struct parport *p, unsigned int mode){ struct parport_ip32_private * const priv = p->physport->private_data; unsigned int residue; unsigned int cnfga; /* FIXME - We are missing one byte if the printer is off-line. I * don't know how to detect this. It looks that the full bit is not * always reliable. For the moment, the problem is avoided in most * cases by testing for BUSY in parport_ip32_compat_write_data(). */ if (parport_ip32_read_econtrol(p) & ECR_F_EMPTY) residue = 0; else { pr_debug1(PPIP32 "%s: FIFO is stuck\n", p->name); /* Stop all transfers. * * Microsoft's document instructs to drive DCR_STROBE to 0, * but it doesn't work (at least in Compatibility mode, not * tested in ECP mode). Switching directly to Test mode (as * in parport_pc) is not an option: it does confuse the port, * ECP service interrupts are no more working after that. A * hard reset is then needed to revert to a sane state. * * Let's hope that the FIFO is really stuck and that the * peripheral doesn't wake up now. */ parport_ip32_frob_control(p, DCR_STROBE, 0); /* Fill up FIFO */ for (residue = priv->fifo_depth; residue > 0; residue--) { if (parport_ip32_read_econtrol(p) & ECR_F_FULL) break; writeb(0x00, priv->regs.fifo); } } if (residue) pr_debug1(PPIP32 "%s: %d PWord%s left in FIFO\n", p->name, residue, (residue == 1) ? " was" : "s were"); /* Now reset the FIFO */ parport_ip32_set_mode(p, ECR_MODE_PS2); /* Host recovery for ECP mode */ if (mode == ECR_MODE_ECP) { parport_ip32_data_reverse(p); parport_ip32_frob_control(p, DCR_nINIT, 0); if (parport_wait_peripheral(p, DSR_PERROR, 0)) pr_debug1(PPIP32 "%s: PEerror timeout 1 in %s\n", p->name, __func__); parport_ip32_frob_control(p, DCR_STROBE, DCR_STROBE); parport_ip32_frob_control(p, DCR_nINIT, DCR_nINIT); if (parport_wait_peripheral(p, DSR_PERROR, DSR_PERROR)) pr_debug1(PPIP32 "%s: PEerror timeout 2 in %s\n", p->name, __func__); } /* Adjust residue if needed */ parport_ip32_set_mode(p, ECR_MODE_CFG); cnfga = readb(priv->regs.cnfgA); if (!(cnfga & CNFGA_nBYTEINTRANS)) { pr_debug1(PPIP32 "%s: cnfgA contains 0x%02x\n", p->name, cnfga); pr_debug1(PPIP32 "%s: Accounting for extra byte\n", p->name); residue++; } /* Don't care about partial PWords since we do not support * PWord != 1 byte. */ /* Back to forward PS2 mode. */ parport_ip32_set_mode(p, ECR_MODE_PS2); parport_ip32_data_forward(p); return residue;}/** * parport_ip32_compat_write_data - write a block of data in SPP mode * @p: pointer to &struct parport * @buf: buffer of data to write * @len: length of buffer @buf * @flags: ignored */static size_t parport_ip32_compat_write_data(struct parport *p, const void *buf, size_t len, int flags){ static unsigned int ready_before = 1; struct parport_ip32_private * const priv = p->physport->private_data; struct parport * const physport = p->physport; size_t written = 0; /* Special case: a timeout of zero means we cannot call schedule(). * Also if O_NONBLOCK is set then use the default implementation. */ if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) return parport_ieee1284_write_compat(p, buf, len, flags); /* Reset FIFO, go in forward mode, and disable ackIntEn */ parport_ip32_set_mode(p, ECR_MODE_PS2); parport_ip32_write_control(p, DCR_SELECT | DCR_nINIT); parport_ip32_data_forward(p); parport_ip32_disable_irq(p); parport_ip32_set_mode(p, ECR_MODE_PPF); physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; /* Wait for peripheral to become ready */ if (parport_wait_peripheral(p, DSR_nBUSY | DSR_nFAULT, DSR_nBUSY | DSR_nFAULT)) { /* Avoid to flood the logs */ if (ready_before) printk(KERN_INFO PPIP32 "%s: not ready in %s\n", p->name, __func__); ready_before = 0; goto stop; } ready_before = 1; written = parport_ip32_fifo_write_block(p, buf, len); /* Wait FIFO to empty. Timeout is proportional to FIFO_depth. */ parport_ip32_drain_fifo(p, physport->cad->timeout * priv->fifo_depth); /* Check for a potential residue */ written -= parport_ip32_get_fifo_residue(p, ECR_MODE_PPF); /* Then, wait for BUSY to get low. */ if (parport_wait_peripheral(p, DSR_nBUSY, DSR_nBUSY)) printk(KERN_DEBUG PPIP32 "%s: BUSY timeout in %s\n", p->name, __func__);stop: /* Reset FIFO */ parport_ip32_set_mode(p, ECR_MODE_PS2); physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; return written;}/* * FIXME - Insert here parport_ip32_ecp_read_data(). *//** * parport_ip32_ecp_write_data - write a block of data in ECP mode * @p: pointer to &struct parport * @buf: buffer of data to write * @len: length of buffer @buf * @flags: ignored */static size_t parport_ip32_ecp_write_data(struct parport *p, const void *buf, size_t len, int flags){ static unsigned int ready_before = 1; struct parport_ip32_private * const priv = p->physport->private_data; struct parport * const physport = p->physport; size_t written = 0; /* Special case: a timeout of zero means we cannot call schedule(). * Also if O_NONBLOCK is set then use the default implementation. */ if (physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) return parport_ieee1284_ecp_write_data(p, buf, len, flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -