⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parport_ip32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -